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