1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24 """The minimisation user function definitions."""
25
26
27 from string import split
28
29
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
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
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
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
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
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
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
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
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
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
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