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 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
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 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
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
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
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
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
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
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
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