Package user_functions :: Module minimisation'
[hide private]
[frames] | no frames]

Source Code for Module user_functions.minimisation'

  1  ############################################################################### 
  2  #                                                                             # 
  3  # Copyright (C) 2003-2012 Edward d'Auvergne                                   # 
  4  #                                                                             # 
  5  # This file is part of the program relax (http://www.nmr-relax.com).          # 
  6  #                                                                             # 
  7  # This program is free software: you can redistribute it and/or modify        # 
  8  # it under the terms of the GNU General Public License as published by        # 
  9  # the Free Software Foundation, either version 3 of the License, or           # 
 10  # (at your option) any later version.                                         # 
 11  #                                                                             # 
 12  # This program is distributed in the hope that it will be useful,             # 
 13  # but WITHOUT ANY WARRANTY; without even the implied warranty of              # 
 14  # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the               # 
 15  # GNU General Public License for more details.                                # 
 16  #                                                                             # 
 17  # You should have received a copy of the GNU General Public License           # 
 18  # along with this program.  If not, see <http://www.gnu.org/licenses/>.       # 
 19  #                                                                             # 
 20  ############################################################################### 
 21   
 22  # Module docstring. 
 23  """The minimisation user function definitions.""" 
 24   
 25  # relax module imports. 
 26  from generic_fns import minimise 
 27  from graphics import WIZARD_IMAGE_PATH 
 28  from user_functions.data import Uf_info, Uf_tables; uf_info = Uf_info(); uf_tables = Uf_tables() 
 29  from user_functions.objects import Desc_container 
 30   
 31   
 32  # The calc user function. 
 33  uf = uf_info.add_uf('calc') 
 34  uf.title = "Calculate the function value." 
 35  uf.title_short = "Function value calculation." 
 36  uf.display = True 
 37  uf.add_keyarg( 
 38      name = "verbosity", 
 39      default = 1, 
 40      py_type = "int", 
 41      desc_short = "verbosity level", 
 42      desc = "The amount of information to print to screen.  Zero corresponds to minimal output while higher values increase the amount of output.  The default value is 1." 
 43  ) 
 44  # Description. 
 45  uf.desc.append(Desc_container()) 
 46  uf.desc[-1].add_paragraph("This will call the target function for the analysis type associated with the current data pipe using the current parameter values.  This can be used to find, for example, the chi-squared value for different parameter values.") 
 47  uf.backend = minimise.calc 
 48  uf.menu_text = "&calc" 
 49  uf.gui_icon = "relax.minimise" 
 50  uf.wizard_image = WIZARD_IMAGE_PATH + 'minimise.png' 
 51   
 52   
 53  # The grid_search user function. 
 54  uf = uf_info.add_uf('grid_search') 
 55  uf.title = "Perform a grid search." 
 56  uf.title_short = "Grid search." 
 57  uf.display = True 
 58  uf.add_keyarg( 
 59      name = "lower", 
 60      py_type = "num_list", 
 61      desc_short = "lower bounds", 
 62      desc = "An array of the lower bound parameter values for the grid search.  The length of the array should be equal to the number of parameters in the model.", 
 63      can_be_none = True 
 64  ) 
 65   
 66  uf.add_keyarg( 
 67      name = "upper", 
 68      py_type = "num_list", 
 69      desc_short = "upper bounds", 
 70      desc = "An array of the upper bound parameter values for the grid search.  The length of the array should be equal to the number of parameters in the model.", 
 71      can_be_none = True 
 72  ) 
 73   
 74  uf.add_keyarg( 
 75      name = "inc", 
 76      default = 21, 
 77      py_type = "int_or_int_list", 
 78      desc_short = "incrementation value", 
 79      desc = "The number of increments to search over.  If a single integer is given then the number of increments will be equal in all dimensions.  Different numbers of increments in each direction can be set if 'inc' is set to an array of integers of length equal to the number of parameters." 
 80  ) 
 81   
 82  uf.add_keyarg( 
 83      name = "constraints", 
 84      default = True, 
 85      py_type = "bool", 
 86      desc_short = "constraints flag", 
 87      desc = "A boolean flag specifying whether the parameters should be constrained.  The default is to turn constraints on (constraints=True)." 
 88  ) 
 89   
 90  uf.add_keyarg( 
 91      name = "verbosity", 
 92      default = 1, 
 93      py_type = "int", 
 94      desc_short = "verbosity level", 
 95      desc = "The amount of information to print to screen.  Zero corresponds to minimal output while higher values increase the amount of output.  The default value is 1." 
 96  ) 
 97  # Description. 
 98  uf.desc.append(Desc_container()) 
 99  uf.desc[-1].add_paragraph("This will perform a grid search across the parameter space.") 
100  uf.backend = minimise.grid_search 
101  uf.menu_text = "&grid_search" 
102  uf.gui_icon = "relax.grid_search" 
103  uf.wizard_size = (800, 500) 
104   
105   
106  # The minimise user function. 
107  uf = uf_info.add_uf('minimise') 
108  uf.title = "Perform an optimisation." 
109  uf.title_short = "Minimisation." 
110  uf.display = True 
111  uf.add_keyarg( 
112      name = "min_algor", 
113      default = "newton", 
114      py_type = "str", 
115      desc_short = "minimisation algorithm", 
116      desc = "The optimisation algorithm to use.", 
117      wiz_element_type = 'combo', 
118      wiz_combo_choices = [ 
119          "Back-and-forth coordinate descent", 
120          "Steepest descent", 
121          "Quasi-Newton BFGS", 
122          "Newton", 
123          "Newton-CG", 
124          "Cauchy point", 
125          "Dogleg", 
126          "CG-Steihaug", 
127          "Exact trust region", 
128          "Fletcher-Reeves", 
129          "Polak-Ribiere", 
130          "Polak-Ribiere +", 
131          "Hestenes-Stiefel", 
132          "Simplex", 
133          "Levenberg-Marquardt", 
134          "Simulated Annealing" 
135      ], 
136      wiz_combo_data = [ 
137          "cd", 
138          "sd", 
139          "bfgs", 
140          "newton", 
141          "ncg", 
142          "cauchy", 
143          "dogleg", 
144          "steihaug", 
145          "exact", 
146          "fr", 
147          "pr", 
148          "pr+", 
149          "hs", 
150          "simplex", 
151          "lm", 
152          "sa" 
153      ], 
154      wiz_read_only = True 
155  ) 
156  uf.add_keyarg( 
157      name = "line_search", 
158      py_type = "str", 
159      desc_short = "line search algorithm", 
160      desc = "The line search algorithm which will only be used in combination with the line search and conjugate gradient methods.  This will default to the More and Thuente line search.", 
161      wiz_element_type = 'combo', 
162      wiz_combo_choices = [ 
163          "Backtracking", 
164          "Nocedal and Wright interpolation", 
165          "Nocedal and Wright for the Wolfe conditions", 
166          "More and Thuente", 
167          "No line search" 
168      ], 
169      wiz_combo_data = [ 
170          "back", 
171          "nwi", 
172          "nww", 
173          "mt", 
174          "no line" 
175      ], 
176      wiz_read_only = True, 
177      can_be_none = True 
178  ) 
179  uf.add_keyarg( 
180      name = "hessian_mod", 
181      py_type = "str", 
182      desc_short = "hessian modification", 
183      desc = "The Hessian modification.  This will only be used in the algorithms which use the Hessian, and defaults to Gill, Murray, and Wright modified Cholesky algorithm.", 
184      wiz_element_type = 'combo', 
185      wiz_combo_choices = [ 
186          "Unmodified Hessian", 
187          "Eigenvalue modification", 
188          "Cholesky with added multiple of the identity", 
189          "The Gill, Murray, and Wright modified Cholesky algorithm", 
190          "The Schnabel and Eskow 1999 algorithm" 
191      ], 
192      wiz_combo_data = [ 
193          "no hessian mod", 
194          "eigen", 
195          "chol", 
196          "gmw", 
197          "se99" 
198      ], 
199      wiz_read_only = True, 
200      can_be_none = True 
201  ) 
202  uf.add_keyarg( 
203      name = "hessian_type", 
204      py_type = "str", 
205      desc_short = "hessian type", 
206      desc = "The Hessian type.  This will only be used in a few trust region algorithms, and defaults to BFGS.", 
207      wiz_element_type = 'combo', 
208      wiz_combo_choices = [ 
209          "Quasi-Newton BFGS", 
210          "Newton" 
211      ], 
212      wiz_combo_data = [ 
213          "bfgs", 
214          "newton" 
215      ], 
216      wiz_read_only = True, 
217      can_be_none = True 
218  ) 
219  uf.add_keyarg( 
220      name = "func_tol", 
221      default = 1e-25, 
222      py_type = "num", 
223      desc_short = "function tolerance", 
224      desc = "The function tolerance.  This is used to terminate minimisation once the function value between iterations is less than the tolerance.  The default value is 1e-25." 
225  ) 
226  uf.add_keyarg( 
227      name = "grad_tol", 
228      py_type = "num", 
229      desc_short = "gradient tolerance", 
230      desc = "The gradient tolerance.  Minimisation is terminated if the current gradient value is less than the tolerance.  The default value is None.", 
231      can_be_none = True 
232  ) 
233  uf.add_keyarg( 
234      name = "max_iter", 
235      default = 10000000, 
236      py_type = "int", 
237      min = 1, 
238      max = 1000000000, 
239      desc_short = "maximum number of iterations", 
240      desc = "The maximum number of iterations.  The default value is 1e7." 
241  ) 
242  uf.add_keyarg( 
243      name = "constraints", 
244      default = True, 
245      py_type = "bool", 
246      desc_short = "constraints flag", 
247      desc = "A boolean flag specifying whether the parameters should be constrained.  The default is to turn constraints on (constraints=True)." 
248  ) 
249  uf.add_keyarg( 
250      name = "scaling", 
251      default = True, 
252      py_type = "bool", 
253      desc_short = "diagonal scaling flag", 
254      desc = "The diagonal scaling boolean flag.  The default that scaling is on (scaling=True)." 
255  ) 
256  uf.add_keyarg( 
257      name = "verbosity", 
258      default = 1, 
259      py_type = "int", 
260      desc_short = "verbosity level", 
261      desc = "The amount of information to print to screen.  Zero corresponds to minimal output while higher values increase the amount of output.  The default value is 1." 
262  ) 
263  # Description. 
264  uf.desc.append(Desc_container()) 
265  uf.desc[-1].add_paragraph("This will perform an optimisation starting from the current parameter values.  This is only suitable for data pipe types which have target functions and hence support optimisation.") 
266  # Diagonal scaling. 
267  uf.desc.append(Desc_container("Diagonal scaling")) 
268  uf.desc[-1].add_paragraph("Diagonal scaling is the transformation of parameter values such that each value has a similar order of magnitude.  Certain minimisation techniques, for example the trust region methods, perform extremely poorly with badly scaled problems.  In addition, methods which are insensitive to scaling such as Newton minimisation may still benefit due to the minimisation of round off errors.") 
269  uf.desc[-1].add_paragraph("In Model-free analysis for example, if S2 = 0.5, te = 200 ps, and Rex = 15 1/s at 600 MHz, the unscaled parameter vector would be [0.5, 2.0e-10, 1.055e-18].  Rex is divided by (2 * pi * 600,000,000)**2 to make it field strength independent.  The scaling vector for this model may be something like [1.0, 1e-9, 1/(2 * pi * 6e8)**2].  By dividing the unscaled parameter vector by the scaling vector the scaled parameter vector is [0.5, 0.2, 15.0].  To revert to the original unscaled parameter vector, the scaled parameter vector and scaling vector are multiplied.") 
270  # Minimisation algorithms. 
271  uf.desc.append(Desc_container("Minimisation algorithms")) 
272  uf.desc[-1].add_paragraph("A minimisation function is selected if the minimisation algorithm matches a certain pattern.  Because the python regular expression 'match' statement is used, various strings can be supplied to select the same minimisation algorithm.  Below is a list of the minimisation algorithms available together with the corresponding patterns.") 
273  uf.desc[-1].add_paragraph("This is a short description of python regular expression, for more information, see the regular expression syntax section of the Python Library Reference.  Some of the regular expression syntax used in this function is:") 
274  uf.desc[-1].add_item_list_element("'[]'", "A sequence or set of characters to match to a single character.  For example, '[Nn]ewton' will match both 'Newton' and 'newton'.") 
275  uf.desc[-1].add_item_list_element("'^'", "Match the start of the string.") 
276  uf.desc[-1].add_item_list_element("'$'", "Match the end of the string.  For example, '^[Ll][Mm]$' will match 'lm' and 'LM' but will not match if characters are placed either before or after these strings.") 
277  uf.desc[-1].add_paragraph("To select a minimisation algorithm, use a string which matches one of the following patterns given in the tables.") 
278  uf.desc[-1].add_paragraph("Unconstrained line search methods:") 
279  table = uf_tables.add_table(label="table: min - line search", caption="Minimisation algorithms -- unconstrained line search methods.") 
280  table.add_headings(["Minimisation algorithm", "Patterns"]) 
281  table.add_row(["Back-and-forth coordinate descent", "'^[Cc][Dd]$' or '^[Cc]oordinate[ _-][Dd]escent$'"]) 
282  table.add_row(["Steepest descent", "'^[Ss][Dd]$' or '^[Ss]teepest[ _-][Dd]escent$'"]) 
283  table.add_row(["Quasi-Newton BFGS", "'^[Bb][Ff][Gg][Ss]$'"]) 
284  table.add_row(["Newton", "'^[Nn]ewton$'"]) 
285  table.add_row(["Newton-CG", "'^[Nn]ewton[ _-][Cc][Gg]$' or '^[Nn][Cc][Gg]$'"]) 
286  uf.desc[-1].add_table(table.label) 
287  uf.desc[-1].add_paragraph("Unconstrained trust-region methods:") 
288  table = uf_tables.add_table(label="table: min - trust-region", caption="Minimisation algorithms -- unconstrained trust-region methods.") 
289  table.add_headings(["Minimisation algorithm", "Patterns"]) 
290  table.add_row(["Cauchy point", "'^[Cc]auchy'"]) 
291  table.add_row(["Dogleg", "'^[Dd]ogleg'"]) 
292  table.add_row(["CG-Steihaug", "'^[Cc][Gg][-_ ][Ss]teihaug' or '^[Ss]teihaug'"]) 
293  table.add_row(["Exact trust region", "'^[Ee]xact'"]) 
294  uf.desc[-1].add_table(table.label) 
295  uf.desc[-1].add_paragraph("Unconstrained conjugate gradient methods:") 
296  table = uf_tables.add_table(label="table: min - conjugate gradient", caption="Minimisation algorithms -- unconstrained conjugate gradient methods.") 
297  table.add_headings(["Minimisation algorithm", "Patterns"]) 
298  table.add_row(["Fletcher-Reeves", "'^[Ff][Rr]$' or '^[Ff]letcher[-_ ][Rr]eeves$'"]) 
299  table.add_row(["Polak-Ribiere", "'^[Pp][Rr]$' or '^[Pp]olak[-_ ][Rr]ibiere$'"]) 
300  table.add_row(["Polak-Ribiere +", "'^[Pp][Rr]\+$' or '^[Pp]olak[-_ ][Rr]ibiere\+$'"]) 
301  table.add_row(["Hestenes-Stiefel", "'^[Hh][Ss]$' or '^[Hh]estenes[-_ ][Ss]tiefel$'"]) 
302  uf.desc[-1].add_table(table.label) 
303  uf.desc[-1].add_paragraph("Miscellaneous unconstrained methods:") 
304  table = uf_tables.add_table(label="table: min - misc", caption="Minimisation algorithms -- miscellaneous unconstrained methods.") 
305  table.add_headings(["Minimisation algorithm", "Patterns"]) 
306  table.add_row(["Simplex", "'^[Ss]implex$'"]) 
307  table.add_row(["Levenberg-Marquardt", "'^[Ll][Mm]$' or '^[Ll]evenburg-[Mm]arquardt$'"]) 
308  uf.desc[-1].add_table(table.label) 
309  uf.desc[-1].add_paragraph("Global minimisation methods:") 
310  table = uf_tables.add_table(label="table: min - global", caption="Minimisation algorithms -- global minimisation methods.") 
311  table.add_headings(["Minimisation algorithm", "Patterns"]) 
312  table.add_row(["Simulated Annealing", "'^[Ss][Aa]$' or '^[Ss]imulated [Aa]nnealing$'"]) 
313  uf.desc[-1].add_table(table.label) 
314  # Minimisation options. 
315  uf.desc.append(Desc_container("Minimisation options")) 
316  uf.desc[-1].add_paragraph("The minimisation options can be given in any order.") 
317  uf.desc[-1].add_paragraph("Line search algorithms.  These are used in the line search methods and the conjugate gradient methods.  The default is the Backtracking line search.  The algorithms are:") 
318  table = uf_tables.add_table(label="table: min sub-algor - line search", caption="Minimisation sub-algorithms -- line search algorithms.") 
319  table.add_headings(["Line search algorithm", "Patterns"]) 
320  table.add_row(["Backtracking line search", "'^[Bb]ack'"]) 
321  table.add_row(["Nocedal and Wright interpolation based line search", "'^[Nn][Ww][Ii]' or '^[Nn]ocedal[ _][Ww]right[ _][Ii]nt'"]) 
322  table.add_row(["Nocedal and Wright line search for the Wolfe conditions", "'^[Nn][Ww][Ww]' or '^[Nn]ocedal[ _][Ww]right[ _][Ww]olfe'"]) 
323  table.add_row(["More and Thuente line search", "'^[Mm][Tt]' or '^[Mm]ore[ _][Tt]huente$'"]) 
324  table.add_row(["No line search", "'^[Nn]o [Ll]ine [Ss]earch$'"]) 
325  uf.desc[-1].add_table(table.label) 
326  uf.desc[-1].add_paragraph("Hessian modifications.  These are used in the Newton, Dogleg, and Exact trust region algorithms:") 
327  table = uf_tables.add_table(label="table: min sub-algor - Hessian mod", caption="Minimisation sub-algorithms -- Hessian modifications.") 
328  table.add_headings(["Hessian modification", "Patterns"]) 
329  table.add_row(["Unmodified Hessian", "'^[Nn]o [Hh]essian [Mm]od'"]) 
330  table.add_row(["Eigenvalue modification", "'^[Ee]igen'"]) 
331  table.add_row(["Cholesky with added multiple of the identity", "'^[Cc]hol'"]) 
332  table.add_row(["The Gill, Murray, and Wright modified Cholesky algorithm", "'^[Gg][Mm][Ww]$'"]) 
333  table.add_row(["The Schnabel and Eskow 1999 algorithm", "'^[Ss][Ee]99'"]) 
334  uf.desc[-1].add_table(table.label) 
335  uf.desc[-1].add_paragraph("Hessian type, these are used in a few of the trust region methods including the Dogleg and Exact trust region algorithms.  In these cases, when the Hessian type is set to Newton, a Hessian modification can also be supplied as above.  The default Hessian type is Newton, and the default Hessian modification when Newton is selected is the GMW algorithm:") 
336  table = uf_tables.add_table(label="table: min sub-algor - Hessian type", caption="Minimisation sub-algorithms -- Hessian type.") 
337  table.add_headings(["Hessian type", "Patterns"]) 
338  table.add_row(["Quasi-Newton BFGS", "'^[Bb][Ff][Gg][Ss]$'"]) 
339  table.add_row(["Newton", "'^[Nn]ewton$'"]) 
340  uf.desc[-1].add_table(table.label) 
341  uf.desc[-1].add_paragraph("For Newton minimisation, the default line search algorithm is the More and Thuente line search, while the default Hessian modification is the GMW algorithm.") 
342  # Prompt examples. 
343  uf.desc.append(Desc_container("Prompt examples")) 
344  uf.desc[-1].add_paragraph("To apply Newton minimisation together with the GMW81 Hessian modification algorithm, the More and Thuente line search algorithm, a function tolerance of 1e-25, no gradient tolerance, a maximum of 10,000,000 iterations, constraints turned on to limit parameter values, and have normal printout, type any combination of:") 
345  uf.desc[-1].add_prompt("relax> minimise('newton')") 
346  uf.desc[-1].add_prompt("relax> minimise('Newton')") 
347  uf.desc[-1].add_prompt("relax> minimise('newton', 'gmw')") 
348  uf.desc[-1].add_prompt("relax> minimise('newton', 'mt')") 
349  uf.desc[-1].add_prompt("relax> minimise('newton', 'gmw', 'mt')") 
350  uf.desc[-1].add_prompt("relax> minimise('newton', 'mt', 'gmw')") 
351  uf.desc[-1].add_prompt("relax> minimise('newton', func_tol=1e-25)") 
352  uf.desc[-1].add_prompt("relax> minimise('newton', func_tol=1e-25, grad_tol=None)") 
353  uf.desc[-1].add_prompt("relax> minimise('newton', max_iter=1e7)") 
354  uf.desc[-1].add_prompt("relax> minimise('newton', constraints=True, max_iter=1e7)") 
355  uf.desc[-1].add_prompt("relax> minimise('newton', verbosity=1)") 
356  uf.desc[-1].add_paragraph("To use constrained Simplex minimisation with a maximum of 5000 iterations, type:") 
357  uf.desc[-1].add_prompt("relax> minimise('simplex', constraints=True, max_iter=5000)") 
358  uf.backend = minimise.minimise 
359  uf.menu_text = "&minimise" 
360  uf.gui_icon = "relax.minimise" 
361  uf.wizard_height_desc = 300 
362  uf.wizard_size = (1000, 750) 
363  uf.wizard_image = WIZARD_IMAGE_PATH + 'minimise.png' 
364