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