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

Source Code for Module user_functions.minimisation

  1  ############################################################################### 
  2  #                                                                             # 
  3  # Copyright (C) 2003-2013 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 graphics import WIZARD_IMAGE_PATH 
 27  from pipe_control import minimise 
 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      none_elements = True 
 81  ) 
 82   
 83  uf.add_keyarg( 
 84      name = "constraints", 
 85      default = True, 
 86      py_type = "bool", 
 87      desc_short = "constraints flag", 
 88      desc = "A boolean flag specifying whether the parameters should be constrained.  The default is to turn constraints on (constraints=True)." 
 89  ) 
 90   
 91  uf.add_keyarg( 
 92      name = "verbosity", 
 93      default = 1, 
 94      py_type = "int", 
 95      desc_short = "verbosity level", 
 96      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." 
 97  ) 
 98  # Description. 
 99  uf.desc.append(Desc_container()) 
100  uf.desc[-1].add_paragraph("This will perform a grid search across the parameter space.") 
101  uf.backend = minimise.grid_search 
102  uf.menu_text = "&grid_search" 
103  uf.gui_icon = "relax.grid_search" 
104  uf.wizard_size = (800, 500) 
105   
106   
107  # The minimise user function. 
108  uf = uf_info.add_uf('minimise') 
109  uf.title = "Perform an optimisation." 
110  uf.title_short = "Minimisation." 
111  uf.display = True 
112  uf.add_keyarg( 
113      name = "min_algor", 
114      default = "newton", 
115      py_type = "str", 
116      desc_short = "minimisation algorithm", 
117      desc = "The optimisation algorithm to use.", 
118      wiz_element_type = 'combo', 
119      wiz_combo_choices = [ 
120          "Back-and-forth coordinate descent", 
121          "Steepest descent", 
122          "Quasi-Newton BFGS", 
123          "Newton", 
124          "Newton-CG", 
125          "Cauchy point", 
126          "Dogleg", 
127          "CG-Steihaug", 
128          "Exact trust region", 
129          "Fletcher-Reeves", 
130          "Polak-Ribiere", 
131          "Polak-Ribiere +", 
132          "Hestenes-Stiefel", 
133          "Simplex", 
134          "Levenberg-Marquardt", 
135          "Simulated Annealing" 
136      ], 
137      wiz_combo_data = [ 
138          "cd", 
139          "sd", 
140          "bfgs", 
141          "newton", 
142          "ncg", 
143          "cauchy", 
144          "dogleg", 
145          "steihaug", 
146          "exact", 
147          "fr", 
148          "pr", 
149          "pr+", 
150          "hs", 
151          "simplex", 
152          "lm", 
153          "sa" 
154      ], 
155      wiz_read_only = True 
156  ) 
157  uf.add_keyarg( 
158      name = "line_search", 
159      py_type = "str", 
160      desc_short = "line search algorithm", 
161      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.", 
162      wiz_element_type = 'combo', 
163      wiz_combo_choices = [ 
164          "Backtracking", 
165          "Nocedal and Wright interpolation", 
166          "Nocedal and Wright for the Wolfe conditions", 
167          "More and Thuente", 
168          "No line search" 
169      ], 
170      wiz_combo_data = [ 
171          "back", 
172          "nwi", 
173          "nww", 
174          "mt", 
175          "no line" 
176      ], 
177      wiz_read_only = True, 
178      can_be_none = True 
179  ) 
180  uf.add_keyarg( 
181      name = "hessian_mod", 
182      py_type = "str", 
183      desc_short = "hessian modification", 
184      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.", 
185      wiz_element_type = 'combo', 
186      wiz_combo_choices = [ 
187          "Unmodified Hessian", 
188          "Eigenvalue modification", 
189          "Cholesky with added multiple of the identity", 
190          "The Gill, Murray, and Wright modified Cholesky algorithm", 
191          "The Schnabel and Eskow 1999 algorithm" 
192      ], 
193      wiz_combo_data = [ 
194          "no hessian mod", 
195          "eigen", 
196          "chol", 
197          "gmw", 
198          "se99" 
199      ], 
200      wiz_read_only = True, 
201      can_be_none = True 
202  ) 
203  uf.add_keyarg( 
204      name = "hessian_type", 
205      py_type = "str", 
206      desc_short = "hessian type", 
207      desc = "The Hessian type.  This will only be used in a few trust region algorithms, and defaults to BFGS.", 
208      wiz_element_type = 'combo', 
209      wiz_combo_choices = [ 
210          "Quasi-Newton BFGS", 
211          "Newton" 
212      ], 
213      wiz_combo_data = [ 
214          "bfgs", 
215          "newton" 
216      ], 
217      wiz_read_only = True, 
218      can_be_none = True 
219  ) 
220  uf.add_keyarg( 
221      name = "func_tol", 
222      default = 1e-25, 
223      py_type = "num", 
224      desc_short = "function tolerance", 
225      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." 
226  ) 
227  uf.add_keyarg( 
228      name = "grad_tol", 
229      py_type = "num", 
230      desc_short = "gradient tolerance", 
231      desc = "The gradient tolerance.  Minimisation is terminated if the current gradient value is less than the tolerance.  The default value is None.", 
232      can_be_none = True 
233  ) 
234  uf.add_keyarg( 
235      name = "max_iter", 
236      default = 10000000, 
237      py_type = "int", 
238      min = 1, 
239      max = 1000000000, 
240      desc_short = "maximum number of iterations", 
241      desc = "The maximum number of iterations.  The default value is 1e7." 
242  ) 
243  uf.add_keyarg( 
244      name = "constraints", 
245      default = True, 
246      py_type = "bool", 
247      desc_short = "constraints flag", 
248      desc = "A boolean flag specifying whether the parameters should be constrained.  The default is to turn constraints on (constraints=True)." 
249  ) 
250  uf.add_keyarg( 
251      name = "scaling", 
252      default = True, 
253      py_type = "bool", 
254      desc_short = "diagonal scaling flag", 
255      desc = "The diagonal scaling boolean flag.  The default that scaling is on (scaling=True)." 
256  ) 
257  uf.add_keyarg( 
258      name = "verbosity", 
259      default = 1, 
260      py_type = "int", 
261      desc_short = "verbosity level", 
262      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." 
263  ) 
264  # Description. 
265  uf.desc.append(Desc_container()) 
266  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.") 
267  # Diagonal scaling. 
268  uf.desc.append(Desc_container("Diagonal scaling")) 
269  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.") 
270  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.") 
271  # Minimisation algorithms. 
272  uf.desc.append(Desc_container("Minimisation algorithms")) 
273  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.") 
274  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:") 
275  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'.") 
276  uf.desc[-1].add_item_list_element("'^'", "Match the start of the string.") 
277  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.") 
278  uf.desc[-1].add_paragraph("To select a minimisation algorithm, use a string which matches one of the following patterns given in the tables.") 
279  uf.desc[-1].add_paragraph("Unconstrained line search methods:") 
280  table = uf_tables.add_table(label="table: min - line search", caption="Minimisation algorithms -- unconstrained line search methods.") 
281  table.add_headings(["Minimisation algorithm", "Patterns"]) 
282  table.add_row(["Back-and-forth coordinate descent", "'^[Cc][Dd]$' or '^[Cc]oordinate[ _-][Dd]escent$'"]) 
283  table.add_row(["Steepest descent", "'^[Ss][Dd]$' or '^[Ss]teepest[ _-][Dd]escent$'"]) 
284  table.add_row(["Quasi-Newton BFGS", "'^[Bb][Ff][Gg][Ss]$'"]) 
285  table.add_row(["Newton", "'^[Nn]ewton$'"]) 
286  table.add_row(["Newton-CG", "'^[Nn]ewton[ _-][Cc][Gg]$' or '^[Nn][Cc][Gg]$'"]) 
287  uf.desc[-1].add_table(table.label) 
288  uf.desc[-1].add_paragraph("Unconstrained trust-region methods:") 
289  table = uf_tables.add_table(label="table: min - trust-region", caption="Minimisation algorithms -- unconstrained trust-region methods.") 
290  table.add_headings(["Minimisation algorithm", "Patterns"]) 
291  table.add_row(["Cauchy point", "'^[Cc]auchy'"]) 
292  table.add_row(["Dogleg", "'^[Dd]ogleg'"]) 
293  table.add_row(["CG-Steihaug", "'^[Cc][Gg][-_ ][Ss]teihaug' or '^[Ss]teihaug'"]) 
294  table.add_row(["Exact trust region", "'^[Ee]xact'"]) 
295  uf.desc[-1].add_table(table.label) 
296  uf.desc[-1].add_paragraph("Unconstrained conjugate gradient methods:") 
297  table = uf_tables.add_table(label="table: min - conjugate gradient", caption="Minimisation algorithms -- unconstrained conjugate gradient methods.") 
298  table.add_headings(["Minimisation algorithm", "Patterns"]) 
299  table.add_row(["Fletcher-Reeves", "'^[Ff][Rr]$' or '^[Ff]letcher[-_ ][Rr]eeves$'"]) 
300  table.add_row(["Polak-Ribiere", "'^[Pp][Rr]$' or '^[Pp]olak[-_ ][Rr]ibiere$'"]) 
301  table.add_row(["Polak-Ribiere +", "'^[Pp][Rr]\+$' or '^[Pp]olak[-_ ][Rr]ibiere\+$'"]) 
302  table.add_row(["Hestenes-Stiefel", "'^[Hh][Ss]$' or '^[Hh]estenes[-_ ][Ss]tiefel$'"]) 
303  uf.desc[-1].add_table(table.label) 
304  uf.desc[-1].add_paragraph("Miscellaneous unconstrained methods:") 
305  table = uf_tables.add_table(label="table: min - misc", caption="Minimisation algorithms -- miscellaneous unconstrained methods.") 
306  table.add_headings(["Minimisation algorithm", "Patterns"]) 
307  table.add_row(["Simplex", "'^[Ss]implex$'"]) 
308  table.add_row(["Levenberg-Marquardt", "'^[Ll][Mm]$' or '^[Ll]evenburg-[Mm]arquardt$'"]) 
309  uf.desc[-1].add_table(table.label) 
310  uf.desc[-1].add_paragraph("Global minimisation methods:") 
311  table = uf_tables.add_table(label="table: min - global", caption="Minimisation algorithms -- global minimisation methods.") 
312  table.add_headings(["Minimisation algorithm", "Patterns"]) 
313  table.add_row(["Simulated Annealing", "'^[Ss][Aa]$' or '^[Ss]imulated [Aa]nnealing$'"]) 
314  uf.desc[-1].add_table(table.label) 
315  # Minimisation options. 
316  uf.desc.append(Desc_container("Minimisation options")) 
317  uf.desc[-1].add_paragraph("The minimisation options can be given in any order.") 
318  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:") 
319  table = uf_tables.add_table(label="table: min sub-algor - line search", caption="Minimisation sub-algorithms -- line search algorithms.") 
320  table.add_headings(["Line search algorithm", "Patterns"]) 
321  table.add_row(["Backtracking line search", "'^[Bb]ack'"]) 
322  table.add_row(["Nocedal and Wright interpolation based line search", "'^[Nn][Ww][Ii]' or '^[Nn]ocedal[ _][Ww]right[ _][Ii]nt'"]) 
323  table.add_row(["Nocedal and Wright line search for the Wolfe conditions", "'^[Nn][Ww][Ww]' or '^[Nn]ocedal[ _][Ww]right[ _][Ww]olfe'"]) 
324  table.add_row(["More and Thuente line search", "'^[Mm][Tt]' or '^[Mm]ore[ _][Tt]huente$'"]) 
325  table.add_row(["No line search", "'^[Nn]o [Ll]ine [Ss]earch$'"]) 
326  uf.desc[-1].add_table(table.label) 
327  uf.desc[-1].add_paragraph("Hessian modifications.  These are used in the Newton, Dogleg, and Exact trust region algorithms:") 
328  table = uf_tables.add_table(label="table: min sub-algor - Hessian mod", caption="Minimisation sub-algorithms -- Hessian modifications.") 
329  table.add_headings(["Hessian modification", "Patterns"]) 
330  table.add_row(["Unmodified Hessian", "'^[Nn]o [Hh]essian [Mm]od'"]) 
331  table.add_row(["Eigenvalue modification", "'^[Ee]igen'"]) 
332  table.add_row(["Cholesky with added multiple of the identity", "'^[Cc]hol'"]) 
333  table.add_row(["The Gill, Murray, and Wright modified Cholesky algorithm", "'^[Gg][Mm][Ww]$'"]) 
334  table.add_row(["The Schnabel and Eskow 1999 algorithm", "'^[Ss][Ee]99'"]) 
335  uf.desc[-1].add_table(table.label) 
336  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:") 
337  table = uf_tables.add_table(label="table: min sub-algor - Hessian type", caption="Minimisation sub-algorithms -- Hessian type.") 
338  table.add_headings(["Hessian type", "Patterns"]) 
339  table.add_row(["Quasi-Newton BFGS", "'^[Bb][Ff][Gg][Ss]$'"]) 
340  table.add_row(["Newton", "'^[Nn]ewton$'"]) 
341  uf.desc[-1].add_table(table.label) 
342  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.") 
343  # Prompt examples. 
344  uf.desc.append(Desc_container("Prompt examples")) 
345  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:") 
346  uf.desc[-1].add_prompt("relax> minimise('newton')") 
347  uf.desc[-1].add_prompt("relax> minimise('Newton')") 
348  uf.desc[-1].add_prompt("relax> minimise('newton', 'gmw')") 
349  uf.desc[-1].add_prompt("relax> minimise('newton', 'mt')") 
350  uf.desc[-1].add_prompt("relax> minimise('newton', 'gmw', 'mt')") 
351  uf.desc[-1].add_prompt("relax> minimise('newton', 'mt', 'gmw')") 
352  uf.desc[-1].add_prompt("relax> minimise('newton', func_tol=1e-25)") 
353  uf.desc[-1].add_prompt("relax> minimise('newton', func_tol=1e-25, grad_tol=None)") 
354  uf.desc[-1].add_prompt("relax> minimise('newton', max_iter=1e7)") 
355  uf.desc[-1].add_prompt("relax> minimise('newton', constraints=True, max_iter=1e7)") 
356  uf.desc[-1].add_prompt("relax> minimise('newton', verbosity=1)") 
357  uf.desc[-1].add_paragraph("To use constrained Simplex minimisation with a maximum of 5000 iterations, type:") 
358  uf.desc[-1].add_prompt("relax> minimise('simplex', constraints=True, max_iter=5000)") 
359  uf.backend = minimise.minimise 
360  uf.menu_text = "&minimise" 
361  uf.gui_icon = "relax.minimise" 
362  uf.wizard_height_desc = 300 
363  uf.wizard_size = (1000, 750) 
364  uf.wizard_image = WIZARD_IMAGE_PATH + 'minimise.png' 
365