The match command provides a unified interface to several optimizer. It can be used to match optics parameters (its main purpose), to fit data sets with parametric functions in the least-squares sense, or to find local or global minima of non-linear problems. Most local methods support bounds, equalities and inequalities constraints. The least-squares methods are custom variant of the Newton-Raphson and the Gauss-Newton algorithms implemented by the :ref:`LSopt <sec.match.lsopt>` module. The local and global non-linear methods are relying on the :ref:`NLopt <sec.match.lsopt>` module, which interfaces the embedded NLopt library that implements a dozen of well-known algorithms.
The match command format is summarized in :numref:`fig-match-synop`. including the default setup of the attributes.
status, fmin, ncall = match {
command = function or nil,
jacobian = function or nil,
variables = { variables-attributes,
{ variable-attributes },
..., more variable definitions, ...
{ variable-attributes } },
equalities = { constraints-attributes,
{ constraint-attributes },
..., more equality definitions, ...
{ constraint-attributes } },
inequalities = { constraints-attributes,
{ constraint-attributes },
..., more inequality definitions,...
{ constraint-attributes } },
weights = { weights-list },
objective = { objective-attributes },
maxcall=nil, -- call limit
maxtime=nil, -- time limit
info=nil, -- information level (output on terminal)
debug=nil, -- debug information level (output on terminal)
usrdef=nil, -- user defined data attached to the environment
}
The match command supports the following attributes:
- :ref:`command <sec.match.cmd>`
A callable
(e)that will be invoked during the optimization process at each iteration. (default: :const:`nil`).- jacobian
A callable
(cres, fgrd, cjac, e)that fills the objective gradient and/or the constraints Jacobian explicitly for the current command resultcres. When provided, it supersedes the finite-difference Jacobian builder. (default: :const:`nil`).Example: :expr:`jacobian = my_jacobian`.
- :ref:`variables <sec.match.var>`
An mappable of single :ref:`variable <sec.match.var>` specification that can be combined with a set of specifications for all variables. (no default, required).
- :ref:`equalities <sec.match.cst>`
An mappable of single equality specification that can be combined with a set of specifications for all equalities. (default:
{}).Example: :expr:`equalities = {{ expr=\\t -> t.q1-64.295, name='q1' }}`.
- :ref:`inequalities <sec.match.cst>`
An mappable of single inequality specification that can be combined with a set of specifications for all inequalities. (default:
{}).Example: :expr:`inequalities = {{ expr=\\t -> t.mq4.beta11-50 }}`.
- :ref:`weights <sec.match.cst>`
A mappable of weights specification that can be used in the
kindattribute of the constraints specifications. (default:{}).Example: :expr:`weights = { px=10 }`.
- :ref:`objective <sec.match.obj>`
A mappable of specifications for the objective to minimize. (default:
{}).Example: :expr:`objective = { method="LD_LMDIF", fmin=1e-10 }`.
- maxcall
A number specifying the maximum allowed calls of the
commandfunction or theobjectivefunction. (default: :const:`nil`).Example: :expr:`maxcall = 100`.
- maxtime
A number specifying the maximum allowed time in seconds. (default: :const:`nil`).
Example: :expr:`maxtime = 60`.
- info
A number specifying the information level to control the verbosity of the output on the :ref:`console <sec.match.conso>`. (default: :const:`nil`).
Example: :expr:`info = 3`.
- debug
A number specifying the debug level to perform extra assertions and to control the verbosity of the output on the :ref:`console <sec.match.conso>`. (default: :const:`nil`).
Example: :expr:`debug = 2`.
- usrdef
Any user defined data that will be attached to the matching environment, which is passed as extra argument to all user defined functions in the
matchcommand. (default: :const:`nil`).Example: :expr:`usrdef = { var=vector(15) }`.
The match command returns the following values in this order:
- status
- A string corresponding to the status of the command or the stopping reason of the method. See :numref:`tbl.match.status` for the list of supported status.
- fmin
- A number corresponding to the best minimum reached during the optimization.
- ncall
- The number of calls of the
commandfunction or theobjectivefunction.
| :var:`status` | Meaning |
|---|---|
| SUCCESS | Generic success (:ref:`NLopt <sec.match.nlopt>` only, unlikely). |
| FMIN | :var:`fmin` :ref:`criteria <sec.match.nlopt>` is fulfilled by the objective function. |
| FTOL | :var:`tol` or :var:`rtol` :ref:`criteria <sec.match.nlopt>` are fulfilled by the objective function. |
| XTOL | :var:`tol` or :var:`rtol` :ref:`criteria <sec.match.nlopt>` are fulfilled by the variables step. |
| MAXCALL | :var:`maxcall` :ref:`criteria <sec.match.nlopt>` is reached. |
| MAXTIME | :var:`maxtime` :ref:`criteria <sec.match.nlopt>` is reached. |
| ROUNDOFF | Round off limited iteration progress, results may still be useful. |
| STOPPED | Termination forced by user, i.e. :expr:`{env.stop = true}`. |
| Errors | |
| FAILURE | Generic failure (:ref:`NLopt <sec.match.nlopt>` only, unlikely). |
| INVALID_ARGS | Invalid argument (:ref:`NLopt <sec.match.nlopt>` only, unlikely). |
| OUT_OF_MEMORY | Ran out of memory (:ref:`NLopt <sec.match.nlopt>` only, unlikely). |
The match command creates a matching environment, which is passed as argument to user's functions invoked during an iteration. It contains some useful attributes that can be read or changed during the optimization process (with care):
- ncall
- The current number of calls of the
commandand/or theobjectivefunctions. - dtime
- A number reporting the current elapsed time.
- stop
- A logical stopping the
matchcommand immediately if set to :const:`true`. - info
- The current information level \geq 0.
- debug
- The current debugging level \geq 0.
- usrdef
- The
usrdefattribute of thematchcommand or :const:`nil`. - command
- The
commandattribute of thematchcommand or :const:`nil`. - variables
- The
variablesattribute of thematchcommand. - equalities
- The
equalitiesattribute of thematchcommand or{}. - inequalities
- The
inequalitiesattribute of thematchcommand or{}. - weights
- The
weightsattribute of thematchcommand or{}.
The attribute command (default: :const:`nil`) must be a callable (e) that will be invoked with the matching environment as first argument during the optimization, right after the update of the :ref:`variables <sec.match.var>` to their new values, and before the evaluation of the :ref:`constraints <par.match.cst>` and the :ref:`objective <sec.match.obj>` function. (default: :const:`nil`).
command = function or nil
The value returned by command is passed as the first argument to all constraints. If this return value is :const:`nil`, the match command considers the current iteration as invalid. Depending on the selected method, the optimizer can start a new iteration or stop.
A typical command definition for matching optics is a function that calls a :var:`twiss` command [1] :
command := mchklost( twiss { twiss-attributes } )
where the function mchklost surrounding the :var:`twiss` command checks if the returned mtable (i.e. the twiss table) has lost particles and returns :const:`nil`instead:
mchklost = \mt -> mt.lost == 0 and mt or nil
The function mchklost [2] is useful to avoid that all constraints do the check individually.
The attribute variables (no default, required) defines the variables that the command match will update while trying to minimize the objective function.
variables = { variables-attributes,
{ variable-attributes },
... ,more variable definitions, ...
{ variable-attributes } }
The variable-attributes is a set of attributes that specify a single variable:
- var
A string specifying the identifier (and indirection) needed to reach the variable from the user's scope where the
matchcommand is defined. (default: :const:`nil`).Example: :expr:`var = "lhcb1.mq_12l4_b1.k1"`.
- name
A string specifying the name of the variable to display when the :var:`info` level is positive. (default:
var).Example: :expr:`name = "MQ.12L4.B1->k1"`.
- min
A number specifying the lower bound for the variable. (default:
-inf).Example: :expr:`min = -4`.
- max
A number specifying the upper bound for the variable. (default:
+inf).Example: :expr:`max = 10`.
- sign
A logical enforcing the sign of the variable by moving :var:`min` or :var:`max` to zero depending on the sign of its initial value. (default: :const:`false`).
Example: :expr:`sign = true`.
- slope
A number enforcing (:ref:`LSopt <sec.match.lsopt>` methods only) with its sign the variation direction of the variable, i.e. positive will only increase and negative will only decrease. (default: :const:`0` ).
Example: :expr:`slope = -1`.
- rstp
A small positive number specifying the relative finite-difference scale used to approximate the derivatives with the :ref:`sec.match.der` method. If the value is not provided, the command will use its built-in heuristic. (default: :const:`nil`).
Example: :expr:`rstp = 1e-6`.
- tol
A number specifying the tolerance on the variable step. If an update is smaller than
tol, the command will return the status"XTOL". (default: :const:`0`).Example: :expr:`tol = 1e-8`.
- get
A callable
(e)returning the variable value as a number, optionally using the matching environment passed as first argument. This attribute is required if the variable is local or an upvalue to avoid a significant slowdown of the code. (default: :const:`nil`).Example: :expr:`get := lhcb1.mq_12l4_b1.k1`.
- set
A callable
(v, e)updating the variable value with the number passed as first argument, optionally using the matching environment passed as second argument.This attribute is required if the variable is local or an upvalue to avoid a significant slowdown of the code. (default: :const:`nil`).Example: :expr:`set = \\v,e => lhcb1.mqxa_1l5.k1 = v*e.usrdef.xon end`.
The variables-attributes is a set of attributes that specify all variables together, but with a lower precedence than the single variable specification of the same name unless otherwise specified:
- min
- Idem :ref:`variable-attributes <par.match.var>`, but for all variables with no local override.
- max
- Idem :ref:`variable-attributes <par.match.var>`, but for all variables with no local override.
- sign
- Idem :ref:`variable-attributes <par.match.var>`, but for all variables with no local override.
- slope
- Idem :ref:`variable-attributes <par.match.var>`, but for all variables with no local override.
- rstp
- Idem :ref:`variable-attributes <par.match.var>`, but for all variables with no local override.
- tol
- Idem :ref:`variable-attributes <par.match.var>`, but for all variables with no local override.
- rtol
A number specifying the relative tolerance on all variable steps. If an update is smaller than
rtolrelative to its variable value, the command will return the status"XTOL". (default: :const:`eps`).Example: :expr:`tol = 1e-8`.
- rmov
A number specifying the relative maximum move allowed on each variable during a single update. (default: :const:`inf`).
Example: :expr:`rmov = 0.2`.
- nvar
A number specifying the number of variables of the problem. It is useful when the problem is made abstract with functions and it is not possible to deduce this count from single variable definitions, or one needs to override it. (default: :const:`nil`).
Example: :expr:`nvar = 15`.
- get
A callable
(x, e)updating a vector passed as first argument with the values of all variables, optionally using the matching environment passed as second argument. This attribute supersedes all single variablegetand may be useful when it is better to read all the variables together, or when they are all locals or upvalues. (default: :const:`nil`).- set
A callable
(x, e)updating all the variables with the values passed as first argument in a vector, optionally using the matching environment passed as second argument. This attribute supersedes all single variablesetand may be useful when it is better to update all the variables together, or when they are all locals or upvalues.(default: :const:`nil`).- nowarn
A logical disabling a warning emitted when the definition of
getandsetare advised but not defined. It is safe to not definegetandsetin such case, but it will significantly slowdown the code. (default: :const:`nil`).Example: :expr:`nowarn = true`.
The attributes equalities (default: {}) and inequalities (default: {}) define the constraints that the command match will try to satisfy while minimizing the objective function. Equalities and inequalities are considered differently when calculating the :ref:`penalty function <sec.match.fun>`.
equalities = { constraints-attributes,
{ constraint-attributes } ,
... more equality definitions ...
{ constraint-attributes } },
inequalities = { constraints-attributes,
{ constraint-attributes } ,
... more inequality definitions ...
{ constraint-attributes } },
weights = { weights-list },
The constraint-attributes is a set of attributes that specify a single constraint, either an equality or an inequality:
- expr
A callable
(r, e)returning the constraint value as a number, optionally using the result ofcommandpassed as first argument, and the matching environment passed as second argument. (default: :const:`nil`)- name
A string specifying the name of the constraint to display when the
infolevel is positive. (default: :const:`nil`).Example: :expr:`name = "betx@IP8"`.
- kind
A string specifying the kind to refer to for the weight of the constraint, taken either in the user-defined or in the default :ref:`weights-list<par.match.wght>`. (default: :const:`nil`).
Example: :expr:`kind = "dq1"`.
- weight
A number used to override the weight of the constraint. (default: :const:`nil`).
Example: :expr:`weight = 100`.
- tol
A number specifying the tolerance to apply on the constraint when checking for its fulfillment. (default: :const:`1e-8` ).
Example: :expr:`tol = 1e-6`.
The constraints-attributes is a set of attributes that specify all equalities or inequalities constraints together, but with a lower precedence than the single constraint specification of the same name unless otherwise specified:
- tol
- Idem :ref:`constraint-attributes <par.match.cst>`, but for all constraints with no local override.
- nequ
A number specifying the number of equations (i.e. number of equalities or inequalities) of the problem. It is useful when the problem is made abstract with functions and it is not possible to deduce this count from single constraint definitions, or one needs to override it. (default: :const:`nil`).
Example: :expr:`nequ = 15`.
- exec
A callable
(x, c, cjac)updating a vector passed as second argument with the values of all constraints, and updating an optional matrix passed as third argument with the Jacobian of all constraints (if not :const:`nil`), using the variables values passed in a vector as first argument. This attribute supersedes all constraintsexprand may be useful when it is better to update all the constraints together. (default: :const:`nil`).Example: :expr:`exec = myinequ`, where (
nvar=2andnequ=2)
local function myinequ (x, c, cjac)
c:fill { 8*x[1]^3 - x[2] ; (1 - x[1])^3 - x[2] }
if cjac then -- fill [2x2] matrix if present
cjac:fill { 24*x[1]^2, - 1 ; - 3*(1 - x[1])^2, - 1 }
end
end
- disp
A logical disabling the display of the equalities in the summary if it is explicitly set to :const:`false`. This is useful for fitting data where equalities are used to compute the residuals. (default: :const:`nil`).
Example: :expr:`disp = false`.
The weights-list is a set of attributes that specify weights for kinds used by constraints. It allows to override the default weights of the supported kinds summarized in :numref:`tbl.match.wght`, or to extend this list with new kinds and weights. The default weight for any undefined kind is :const:`1`.
Example: :expr:`weights = { q1=100, q2=100, mykind=3 }`.
The attribute objective (default: {}) defines the objective that the command match will try to minimize.
objective = { objective-attributes },
The objective-attributes is a set of attributes that specify the objective to fulfill:
- method
A string specifying the algorithm to use for solving the problem, see :numref:`tbl.match.mthd`, :numref:`tbl.match.lmthd` and :numref:`tbl.match.gmthd`. (default:
"LN_COBYLA"ifobjective.execis defined,"LD_JACOBIAN"otherwise).Example: :expr:`method = "LD_LMDIF"`.
- submethod
A string specifying the algorithm from NLopt module to use for solving the problem locally when the method is an augmented algorithm, see :numref:`tbl.match.lmthd` and :numref:`tbl.match.gmthd` (default:
"LN_COBYLA").- fmin
A number corresponding to the minimum to reach during the optimization. For least squares problems, it corresponds to the tolerance on the :ref:`penalty function <sec.match.fun>`. If an iteration finds a value smaller than
fminand all the constraints are fulfilled, the command will return the status"FMIN". (default: :const:`nil`).Example: :expr:`fmin = 1e-12`.
- tol
A number specifying the tolerance on the objective function step. If an update is smaller than
tol, the command will return the status"FTOL". (default: :const:`0`).Example: :expr:`tol = 1e-10`.
- rtol
A number specifying the relative tolerance on the objective function step. If an update is smaller than
rtolrelative to its step value, the command will return the status"FTOL"(default: :const:`0`).Example: :expr:`tol = 1e-8`.
- bstra
A number specifying the strategy to select the best case of the :ref:`objective <sec.match.fun>` function. (default: :const:`nil`).
Example: :expr:`bstra = 0`. [3]
- broyden
A logical allowing the Jacobian approximation by finite difference to update its columns with a Broyden's rank one estimates when the step of the corresponding variable is almost collinear with the variables step vector. This option may save some expensive calls to
command, e.g. save Twiss calculations, when it does not degrade the rate of convergence of the selected method. (default: :const:`nil`).Example: :expr:`broyden = true`.
- reset
A logical specifying to the
matchcommand to restore the initial state of the variables before returning. This is useful to attempt an optimization without changing the state of the variables. Note that if any function amongstcommand, variablesgetandset, constraintsexprorexec, or objectiveexechave side effects on the environment, these will be persistent. (default: :const:`nil`).Example: :expr:`reset = true`.
- exec
A callable
(x, fgrd)returning the value of the objective function as a number, and updating a vector passed as second argument with its gradient, using the variables values passed in a vector as first argument. (default: :const:`nil`).Example: :expr:`exec = myfun`, where (
nvar=2)
local function myfun(x, fgrd)
if fgrd then -- fill [2x1] vector if present
fgrd:fill { 0, 0.5/sqrt(x[2]) }
end
return sqrt(x[2])
end
- grad
A logical enabling (:const:`true`) or disabling (:const:`false`) the approximation by finite difference of the gradient of the objective function or the Jacobian of the constraints. A :const:`nil` value will be converted to :const:`true` if no
execfunction is defined and the selectedmethodrequires derivatives (D), otherwise it will be converted to :const:`false`. (default: :const:`nil`).Example: :expr:`grad = false`.
- bisec
A number specifying (:ref:`LSopt <sec.match.lsopt>` methods only) the maximum number of attempt to minimize an increasing objective function by reducing the variables steps by half, i.e. that is a :ref:`line search <ref.algo.linesearch>` using \alpha=0.5^k where k=0..\text{bisec}. (default:
3if :attr:`objective.exec` is undefined, :const:`0` otherwise).Example: :expr:`bisec = 9`.
- rcond
A number specifying ( :ref:`LSopt <sec.match.lsopt>` methods only) how to determine the effective rank of the Jacobian while solving the least squares system (see
ssolvefrom the :doc:`Linear Algebra <mad_mod_linalg>` module). This attribute can be updated between iterations, e.g. throughenv.objective.rcond. (default:eps).Example: :expr:`rcond = 1e-14`.
- ncond
A number specifying (:ref:`LSopt <sec.match.lsopt>` methods only) how many singular values must be discarded while solving the least-squares system with
ssolve. A positive (resp. negative) integer discards the smallest (resp. largest) singular values. This attribute can be updated between iterations, e.g. throughenv.objective.ncond. (default: :const:`0`).Example: :expr:`ncond = 1`.
- jtol
A number specifying (:ref:`LSopt <sec.match.lsopt>` methods only) the tolerance on the norm of the Jacobian rows to reject useless constraints. This attribute can be updated between iterations, e.g. through
env.objective.jtol. (default:eps).Example: :expr:`tol = 1e-14`.
- jiter
A number specifying (:ref:`LSopt <sec.match.lsopt>` methods only) the maximum allowed attempts to solve the least squares system when variables are rejected, e.g. wrong slope or out-of-bound values. (default: :const:`10`).
Example: :expr:`jiter = 15`.
- jstra
A number specifying (:ref:`LSopt <sec.match.lsopt>` methods only) the strategy to use for reducing the variables of the least squares system. (default: :const:`1`).
Example: :expr:`jstra = 3`. [4]
| jstra | Strategy for reducing variables of least squares system. |
|---|---|
| 0 | no variables reduction, constraints reduction is still active. |
| 1 | reduce system variables for bad slopes and out-of-bound values. |
| 2 | idem 1, but bad slopes reinitialize variables to their original state. |
| 3 | idem 2, but strategy switches definitely to 0 if jiter is reached. |
The match command supports local and global optimization algorithms through the method attribute, as well as combinations of them with the submethod attribute (see :ref:`objective<sec.match.obj>`). The method should be selected according to the kind of problem that will add a prefix to the method name: local (L) or global (G), with (D) or without (N) derivatives, and least squares or nonlinear function minimization. When the method requires the derivatives (D) and no objective.exec function is defined or the attribute grad is set to :const:`false`, the match command will approximate the derivatives, i.e. gradient and Jacobian, by the finite difference method (see :ref:`derivatives <sec.match.der>`).
Most global optimization algorithms explore the variables domain with methods belonging to stochastic sampling, deterministic scanning, and splitting strategies, or a mix of them. Hence, all global methods require boundaries to define the searching region, which may or may not be internally scaled to a hypercube. Some global methods allow to specify with the submethod attribute, the local method to use for searching local minima. If this is not the case, it is wise to refine the global solution with a local method afterward, as global methods put more effort on finding global solutions than precise local minima. The global (G) optimization algorithms, with (D) or without (N) derivatives, are listed in :numref:`tbl.match.gmthd`.
Most local optimization algorithms with derivatives are variants of the Newton iterative method suitable for finding local minima of nonlinear vector-valued function \vec{f}(\vec{x}), i.e. searching for stationary points. The iteration steps \vec{h} are given by the minimization \vec{h}=-\alpha(\nabla^2\vec{f})^{-1}\nabla\vec{f}, coming from the local approximation of the function at the point \vec{x}+\vec{h} by its Taylor series truncated at second order \vec{f}(\vec{x}+\vec{h})\approx \vec{f}(\vec{x})+\vec{h}^T\nabla\vec{f}(\vec{x})+\frac{1}{2}\vec{h}^T\nabla^2\vec{f}(\vec{x})\vec{h},
and solved for \nabla_{\vec{h}}\vec{f}=0. The factor \alpha>0 is part of the line search strategy , which is sometimes replaced or combined with a trusted region strategy like in the Leverberg-Marquardt algorithm. The local (L) optimization algorithms, with (D) or without (N) derivatives, are listed in :numref:`tbl.match.mthd` for least squares methods and in :numref:`tbl.match.lmthd` for non-linear methods, and can be grouped by family of algorithms:
- Newton
- An iterative method to solve nonlinear systems that uses iteration step given by the minimization \vec{h}=-\alpha(\nabla^2\vec{f})^{-1}\nabla\vec{f}.
- Newton-Raphson
- An iterative method to solve nonlinear systems that uses iteration step given by the minimization \vec{h}=-\alpha(\nabla\vec{f})^{-1}\vec{f}.
- Gradient-Descent
- An iterative method to solve nonlinear systems that uses iteration step given by \vec{h}=-\alpha\nabla\vec{f}.
- Quasi-Newton
- A variant of the Newton method that uses BFGS approximation of the Hessian \nabla^2\vec{f} or its inverse (\nabla^2\vec{f})^{-1}, based on values from past iterations.
- Gauss-Newton
- A variant of the Newton method for least-squares problems that uses iteration step given by the minimization \vec{h}=-\alpha(\nabla\vec{f}^T\nabla\vec{f})^{-1}(\nabla\vec{f}^T\vec{f}), where the Hessian \nabla^2\vec{f} is approximated by \nabla\vec{f}^T\nabla\vec{f} with \nabla\vec{f} being the Jacobian of the residuals \vec{f}.
- Levenberg-Marquardt
- A hybrid G-N and G-D method for least-squares problems that uses iteration step given by the minimization \vec{h}=-\alpha(\nabla\vec{f}^T\nabla\vec{f}+\mu\vec{D})^{-1}(\nabla\vec{f}^T\vec{f}), where mu>0 is the damping term selecting the method G-N (small \mu) or G-D (large \mu), and \vec{D}=\mathrm{diag}(\nabla\vec{f}^T\nabla\vec{f}).
- Simplex
- A linear programming method (simplex method) working without using any derivatives.
- Nelder-Mead
- A nonlinear programming method (downhill simplex method) working without using any derivatives.
- Principal-Axis
- An adaptive coordinate descent method working without using any derivatives, selecting the descent direction from the Principal Component Analysis.
The match command will stop the iteration of the algorithm and return one of the following status if the corresponding criteria, checked in this order, is fulfilled (see also :numref:`tbl.match.status`):
STOPPED- Check
env.stop == true, i.e. termination forced by a user-defined function.FMIN- Check f\leq f_{\min} if c_{\text{fail}} = 0 or
bstra == 0, where f is the current value of the objective function, and c_{\text{fail}} is the number of failed constraints (i.e. feasible point).FTOL- Check |\Delta f| \leq f_{\text{tol}} or |\Delta f| \leq f_{\text{rtol}}\,|f| if c_{\text{fail}} = 0, where f and \Delta f are the current value and step of the objective function, and c_{\text{fail}} the number of failed constraints (i.e. feasible point).
XTOL- Check \max (|\Delta \vec{x}|-\vec{x}_{\text{tol}}) \leq 0 or \max (|\Delta \vec{x}|-\vec{x}_{\text{rtol}}\circ|\vec{x}|) \leq 0, where \vec{x} and \Delta\vec{x} are the current values and steps of the variables. Note that these criteria are checked even for non feasible points, i.e. c_{\text{fail}} > 0, as the algorithm can be trapped in a local minima that does not satisfy the constraints.
ROUNDOFF- Check \max (|\Delta \vec{x}|-\varepsilon\,|\vec{x}|) \leq 0 if \vec{x}_{\text{rtol}} < \varepsilon, where \vec{x} and \Delta\vec{x} are the current values and steps of the variables. The :ref:`LSopt <sec.match.lsopt>` module returns also this status if the Jacobian is full of zeros, which is
jtoldependent during itsjstrareductions.MAXCALL- Check
env.ncall >= maxcallifmaxcall > 0.MAXTIME- Check
env.dtime >= maxtimeifmaxtime > 0.
The objective function is the key point of the match command, specially when tolerances are applied to it or to the constraints, or the best case strategy is changed. It is evaluated as follows:
- Update user's
variableswith the vector \vec{x}. - Evaluate the callable
commandif defined and pass its value to the constraints. - Evaluate the callable
objective.execif defined and save its value f. - Evaluate the callable
equalities.execif defined, otherwise evaluate all the functionsequalities[].expr(cmd,env), and use the result to fill the vector \vec{c}^{=}. - Evaluate the callable
inequalities.execif defined, otherwise evaluate all the functionsinequalities[].expr(cmd,env)and use the result to fill the vector \vec{c}^{\leq}. - Count the number of invalid constraints c_{\text{fail}} = \text{card}\{ |\vec{c}^{=}| > \vec{c}^{=}_{\text{tol}}\} + \text{card}\{ \vec{c}^{\leq} > \vec{c}^{\leq}_{\text{tol}}\}.
- Calculate the penalty p = \|\vec{c}\|/\|\vec{w}\|, where \vec{c} = \vec{w}\circ \genfrac[]{0pt}{1}{\vec{c}^{=}}{\vec{c}^{\leq}} and \vec{w} is the weights vector of the constraints. Set f=p if the callable
objective.execis undefined. [5] - Save the current iteration state as the best state depending on the strategy
bstra. The defaultbstra=nilcorresponds to the last strategy
| bstra | Strategy for selecting the best case of the objective function. |
|---|---|
| 0 | f < f^{\text{best}}_{\text{min}} , no feasible point check. |
| 1 | c_{\text{fail}} \leq c^{\text{best}}_{\text{fail}} and f < f^{\text{best}}_{\text{min}} , improve both feasible point and objective. |
| - | c_{\text{fail}} < c^{\text{best}}_{\text{fail}} or c_{\text{fail}} = c^{\text{best}}_{\text{fail}} and f < f^{\text{best}}_{\text{min}}, improve feasible point or objective. |
The derivatives are approximated by the finite difference methods when the selected algorithm requires them (D) and the function objective.exec is undefined or the attribute grad=false. The difficulty of the finite difference methods is to choose the small step h for the difference. The match command uses the forward difference method with a step h = 10^{-4}\,\|\vec{h}\|, where \vec{h} is the last :ref:`iteration steps <ref.iteration.step>`, unless it is overridden by the user with the variable attribute rstp. In order to avoid zero step size, which would be problematic for the calculation of the Jacobian, the choice of h is a bit more subtle:
\frac{\partial f_j}{\partial x_i} \approx \frac{f_j(\vec{x}+h\vec{e_i}) - f_j(\vec{x})}{h}\quad ; \quad
h =
\begin{cases}
10^{-4}\,\|\vec{h}\| & \text{if } \|\vec{h}\| \not= 0 \\
10^{-8}\,\|\vec{x}\| & \text{if } \|\vec{h}\| = 0 \text{ and } \|\vec{x}\| \not= 0 \\
10^{-10} & \text{otherwise.}
\end{cases}
Hence the approximation of the Jacobian will need an extra evaluation of the objective function per variable. If this evaluation has an heavy cost, e.g. like a :var:`twiss` command, it is possible to approximate the Jacobian evolution by a Broyden's rank-1 update with the broyden attribute:
\vec{J}_{k+1} = \vec{J}_{k} + \frac{\vec{f}(\vec{x}_{k}+\vec{h}_k) - \vec{f}(\vec{x}_{k}) - \vec{J}_{k}\,\vec{h}_{k}}{\|\vec{h}_{k}\|^2}\,\vec{h}^T_k
The update of the i-th column of the Jacobian by the Broyden approximation makes sense if the angle between \vec{h} and \vec{e}_i is small, that is when |\vec{h}^T\vec{e}_i| \geq \gamma\,\|\vec{h}\|. The match command uses a rather pessimistic choice of \gamma = 0.8, which gives good performance. Nevertheless, it is advised to always check if Broyden's update saves evaluations of the objective function for your study.
The verbosity of the output of the match command on the console (e.g. terminal) is controlled by the info level, where the level info=0 means a completely silent command as usual. The first verbose level info=1 displays the final summary at the end of the matching, as shown in :numref:`code.match.info1` and the next level info=2 adds intermediate summary for each evaluation of the objective function, as shown in :numref:`code.match.info2`. The columns of these tables are self-explanatory, and the sign > on the right of the constraints marks those failing.
The bottom line of the intermediate summary displays in order:
- the number of evaluation of the objective function so far,
- the elapsed time in second (in square brackets) so far,
- the current objective function value,
- the current objective function step,
- the current number of constraint that failed c_{\text{fail}}.
The bottom line of the final summary displays the same information but for the best case found, as well as the final status returned by the match command. The number in square brackets right after fbst is the evaluation number of the best case.
The :ref:`LSopt <sec.match.lsopt>` module adds the sign # to mark the adjusted variables and the sign * to mark the rejected variables and constraints on the right of the intermediate summary tables to qualify the behavior of the constraints and the variables during the optimization process. If these signs appear in the final summary too, it means that they were always adjusted or rejected during the matching, which is useful to tune your study e.g. by removing the useless constraints.
Constraints Type Kind Weight Penalty Value
-----------------------------------------------------------------------------
1 IP8 equality beta 1 9.41469e-14
2 IP8 equality beta 1 3.19744e-14
3 IP8 equality alfa 10 0.00000e+00
4 IP8 equality alfa 10 1.22125e-14
5 IP8 equality dx 10 5.91628e-14
6 IP8 equality dpx 100 1.26076e-13
7 E.DS.R8.B1 equality beta 1 7.41881e-10
8 E.DS.R8.B1 equality beta 1 1.00158e-09
9 E.DS.R8.B1 equality alfa 10 4.40514e-12
10 E.DS.R8.B1 equality alfa 10 2.23532e-11
11 E.DS.R8.B1 equality dx 10 7.08333e-12
12 E.DS.R8.B1 equality dpx 100 2.12877e-13
13 E.DS.R8.B1 equality mu1 10 2.09610e-12
14 E.DS.R8.B1 equality mu2 10 1.71063e-12
Variables Final Value Init. Value Lower Limit Upper Limit
--------------------------------------------------------------------------------
1 kq4.l8b1 -3.35728e-03 -4.31524e-03 -8.56571e-03 0.00000e+00
2 kq5.l8b1 4.93618e-03 5.28621e-03 0.00000e+00 8.56571e-03
3 kq6.l8b1 -5.10313e-03 -5.10286e-03 -8.56571e-03 0.00000e+00
4 kq7.l8b1 8.05555e-03 8.25168e-03 0.00000e+00 8.56571e-03
5 kq8.l8b1 -7.51668e-03 -5.85528e-03 -8.56571e-03 0.00000e+00
6 kq9.l8b1 7.44662e-03 7.07113e-03 0.00000e+00 8.56571e-03
7 kq10.l8b1 -6.73001e-03 -6.39311e-03 -8.56571e-03 0.00000e+00
8 kqtl11.l8b1 6.85635e-04 7.07398e-04 0.00000e+00 5.56771e-03
9 kqt12.l8b1 -2.38722e-03 -3.08650e-03 -5.56771e-03 0.00000e+00
10 kqt13.l8b1 5.55969e-03 3.78543e-03 0.00000e+00 5.56771e-03
11 kq4.r8b1 4.23719e-03 4.39728e-03 0.00000e+00 8.56571e-03
12 kq5.r8b1 -5.02348e-03 -4.21383e-03 -8.56571e-03 0.00000e+00
13 kq6.r8b1 4.18341e-03 4.05914e-03 0.00000e+00 8.56571e-03
14 kq7.r8b1 -5.48774e-03 -6.65981e-03 -8.56571e-03 0.00000e+00
15 kq8.r8b1 5.88978e-03 6.92571e-03 0.00000e+00 8.56571e-03
16 kq9.r8b1 -3.95756e-03 -7.46154e-03 -8.56571e-03 0.00000e+00
17 kq10.r8b1 7.18012e-03 7.55573e-03 0.00000e+00 8.56571e-03
18 kqtl11.r8b1 -3.99902e-03 -4.78966e-03 -5.56771e-03 0.00000e+00
19 kqt12.r8b1 -1.95221e-05 -1.74210e-03 -5.56771e-03 0.00000e+00
20 kqt13.r8b1 -2.04425e-03 -3.61438e-03 -5.56771e-03 0.00000e+00
ncall=381 [4.1s], fbst[381]=8.80207e-12, fstp=-3.13047e-08, status=FMIN. Constraints Type Kind Weight Penalty Value
-----------------------------------------------------------------------------
1 IP8 equality beta 1 3.10118e+00 >
2 IP8 equality beta 1 1.85265e+00 >
3 IP8 equality alfa 10 9.77591e-01 >
4 IP8 equality alfa 10 8.71014e-01 >
5 IP8 equality dx 10 4.37803e-02 >
6 IP8 equality dpx 100 4.59590e-03 >
7 E.DS.R8.B1 equality beta 1 9.32093e+01 >
8 E.DS.R8.B1 equality beta 1 7.60213e+01 >
9 E.DS.R8.B1 equality alfa 10 2.98722e+00 >
10 E.DS.R8.B1 equality alfa 10 1.04758e+00 >
11 E.DS.R8.B1 equality dx 10 7.37813e-02 >
12 E.DS.R8.B1 equality dpx 100 6.67388e-03 >
13 E.DS.R8.B1 equality mu1 10 7.91579e-02 >
14 E.DS.R8.B1 equality mu2 10 6.61916e-02 >
Variables Curr. Value Curr. Step Lower Limit Upper Limit
--------------------------------------------------------------------------------
1 kq4.l8b1 -3.36997e-03 -4.81424e-04 -8.56571e-03 0.00000e+00 #
2 kq5.l8b1 4.44028e-03 5.87400e-04 0.00000e+00 8.56571e-03
3 kq6.l8b1 -4.60121e-03 -6.57316e-04 -8.56571e-03 0.00000e+00 #
4 kq7.l8b1 7.42273e-03 7.88826e-04 0.00000e+00 8.56571e-03
5 kq8.l8b1 -7.39347e-03 0.00000e+00 -8.56571e-03 0.00000e+00 *
6 kq9.l8b1 7.09770e-03 2.58912e-04 0.00000e+00 8.56571e-03
7 kq10.l8b1 -5.96101e-03 -8.51573e-04 -8.56571e-03 0.00000e+00 #
8 kqtl11.l8b1 6.15659e-04 8.79512e-05 0.00000e+00 5.56771e-03 #
9 kqt12.l8b1 -2.66538e-03 0.00000e+00 -5.56771e-03 0.00000e+00 *
10 kqt13.l8b1 4.68776e-03 0.00000e+00 0.00000e+00 5.56771e-03 *
11 kq4.r8b1 4.67515e-03 -5.55795e-04 0.00000e+00 8.56571e-03 #
12 kq5.r8b1 -4.71987e-03 5.49407e-04 -8.56571e-03 0.00000e+00 #
13 kq6.r8b1 4.68747e-03 -5.54035e-04 0.00000e+00 8.56571e-03 #
14 kq7.r8b1 -5.35315e-03 4.58938e-04 -8.56571e-03 0.00000e+00 #
15 kq8.r8b1 5.77068e-03 0.00000e+00 0.00000e+00 8.56571e-03 *
16 kq9.r8b1 -4.97761e-03 -7.11087e-04 -8.56571e-03 0.00000e+00 #
17 kq10.r8b1 6.90543e-03 4.33052e-04 0.00000e+00 8.56571e-03
18 kqtl11.r8b1 -4.16758e-03 -5.95369e-04 -5.56771e-03 0.00000e+00 #
19 kqt12.r8b1 -1.57183e-03 0.00000e+00 -5.56771e-03 0.00000e+00 *
20 kqt13.r8b1 -2.57565e-03 0.00000e+00 -5.56771e-03 0.00000e+00 *
ncall=211 [2.3s], fval=8.67502e-01, fstp=-2.79653e+00, ccnt=14.The match command can be extended easily with new optimizer either from external libraries or internal module, or both. The interface should be flexible and extensible enough to support new algorithms and new options with a minimal effort.
The LSopt (Least Squares optimization) module implements custom variant of the Newton-Raphson and the Levenberg-Marquardt algorithms to solve least squares problems. Both support the options rcond, bisec, jtol, jiter and jstra described in the section :ref:`objective <sec.match.obj>`, with the same default values. :numref:`tbl.match.mthd` lists the names of the algorithms for the attribute method. These algorithms cannot be used with the attribute submethod for the augmented algorithms of the :ref:`NLopt <sec.match.nlopt>` module, which would not make sense as these methods support both equalities and inequalities.
| Method | Equ | Iqu | Description |
|---|---|---|---|
| :var:`LD_JACOBIAN` | y | y | Modified Newton-Raphson algorithm. |
| :var:`LD_LMDIF` | y | y | Modified Levenberg-Marquardt algorithm. |
The NLopt (Non-Linear optimization) module provides a simple interface to the algorithms implemented in the embedded NLopt library. :numref:`tbl.match.lmthd` and :numref:`tbl.match.gmthd` list the names of the local and global algorithms respectively for the attribute method. The methods that do not support equalities (column Equ) or inequalities (column Iqu) can still be used with constraints by specifying them as the submethod of the AUGmented LAGrangian method. For details about these algorithms, please refer to the Algorithms section of its online documentation.
| Method | Equ | Iqu | Description |
|---|---|---|---|
| Local optimizers without derivative (:var:`LN_`) | |||
| :var:`LN_BOBYQA` | n | n | Bound-constrained Optimization BY Quadratic Approximations algorithm. |
| :var:`LN_COBYLA` | y | y | Bound Constrained Optimization BY Linear Approximations algorithm. |
| :var:`LN_NELDERMEAD` | n | n | Original Nelder-Mead algorithm. |
| :var:`LN_NEWUOA` | n | n | Older and less efficient :var:`LN_BOBYQA`. |
| :var:`LN_NEWUOA_BOUND` | n | n | Older and less efficient :var:`LN_BOBYQA` with bound constraints. |
| :var:`LN_PRAXIS` | n | n | PRincipal-AXIS algorithm. |
| :var:`LN_SBPLX` | n | n | Subplex algorithm, variant of Nelder-Mead. |
| Local optimizers with derivative (:var:`LD_`) | |||
| :var:`LD_CCSAQ` | n | y | Conservative Convex Separable Approximation with Quatratic penalty. |
| :var:`LD_LBFGS` | n | n | BFGS algorithm with low memory footprint. |
| :var:`LD_LBFGS_NOCEDAL` | n | n | Variant from J. Nocedal of :var:`LD_LBFGS`. |
| :var:`LD_MMA` | n | y | Method of Moving Asymptotes algorithm. |
| :var:`LD_SLSQP` | y | y | Sequential Least-Squares Quadratic Programming algorithm. |
| :var:`LD_TNEWTON` | n | n | Inexact Truncated Newton algorithm. |
| :var:`LD_TNEWTON_PRECOND` | n | n | Idem :var:`LD_TNEWTON` with preconditioning. |
| :var:`LD_TNEWTON_PRECOND_RESTART` | n | n | Idem :var:`LD_TNEWTON` with preconditioning and steepest-descent restarting. |
| :var:`LD_TNEWTON_RESTART` | n | n | Idem :var:`LD_TNEWTON` with steepest-descent restarting. |
| :var:`LD_VAR1` | n | n | Shifted limited-memory VARiable-metric rank-1 algorithm. |
| :var:`LD_VAR2` | n | n | Shifted limited-memory VARiable-metric rank-2 algorithm. |
| Method | Equ | Iqu | Description |
|---|---|---|---|
| Global optimizers without derivative (:var:`GN_`) | |||
| :var:`GN_CRS2_LM` | n | n | Variant of the Controlled Random Search algorithm with Local Mutation (mixed stochastic and genetic method). |
| :var:`GN_DIRECT` | n | n | DIviding RECTangles algorithm (deterministic method). |
| :var:`GN_DIRECT_L` | n | n | Idem :var:`GN_DIRECT` with locally biased optimization. |
| :var:`GN_DIRECT_L_RAND` | n | n | Idem :var:`GN_DIRECT_L` with some randomization in the selection of the dimension to reduce next. |
| :var:`GN_DIRECT*_NOSCAL` | n | n | Variants of above :var:`GN_DIRECT*` without scaling the problem to a unit hypercube to preserve dimension weights. |
| :var:`GN_ESCH` | n | n | Modified Evolutionary algorithm (genetic method). |
| :var:`GN_ISRES` | y | y | Improved Stochastic Ranking Evolution Strategy algorithm (mixed genetic and variational method). |
| :var:`GN_MLSL` | n | n | Multi-Level Single-Linkage algorithm (stochastic method). |
| :var:`GN_MLSL_LDS` | n | n | Idem :var:`GN_MLSL` with low-discrepancy scan sequence. |
| Global optimizers with derivative (:var:`GD_`) | |||
| :var:`GD_MLSL` | n | n | Multi-Level Single-Linkage algorithm (stochastic method). |
| :var:`GD_MLSL_LDS` | n | n | Idem :var:`GL_MLSL` with low-discrepancy scan sequence. |
| :var:`GD_STOGO` | n | n | Branch-and-bound algorithm (deterministic method). |
| :var:`GD_STOGO_RAND` | n | n | Variant of :var:`GD_STOGO` (deterministic and stochastic method). |
| :var:`AUGLAG` | y | y | Augmented Lagrangian algorithm, combines objective function and nonlinear constraints into a single "penalty" function. |
| :var:`AUGLAG_EQ` | y | n | Idem :var:`AUGLAG` but handles only equality constraints and pass inequality constraints to :var:`submethod`. |
| :var:`G_MLSL` | n | n | MLSL with user-specified local algorithm using :var:`submethod`. |
| :var:`G_MLSL_LDS` | n | n | Idem :var:`G_MLSL` with low-discrepancy scan sequence. |
The following example below shows how to match the betatron tunes of the LHC beam 1 to q_1=64.295 and q_2=59.301 using the quadrupoles strengths kqtf and kqtd, followed by the matching of the chromaticities to dq_1=15 and dq_2=15 using the main sextupole strengths ksf and ksd.
local lhcb1 in MADX
local twiss, match in MAD
local status, fmin, ncall = match {
command := twiss { sequence=lhcb1, cofind=true,
method=4, observe=1 },
variables = { rtol=1e-6, -- 1 ppm
{ var='MADX.kqtf_b1' },
{ var='MADX.kqtd_b1' }},
equalities = {{ expr=\t -> t.q1- 64.295, name='q1' },
{ expr=\t -> t.q2- 59.301, name='q2' }},
objective = { fmin=1e-10, broyden=true },
maxcall=100, info=2
}
local status, fmin, ncall = match {
command := twiss { sequence=lhcb1, cofind=true, chrom=true,
method=4, observe=1 },
variables = { rtol=1e-6, -- 1 ppm
{ var='MADX.ksf_b1' },
{ var='MADX.ksd_b1' }},
equalities = {{ expr= \t -> t.dq1-15, name='dq1' },
{ expr= \t -> t.dq2-15, name='dq2' }},
objective = { fmin=1e-8, broyden=true },
maxcall=100, info=2
}
The following example hereafter shows how to squeeze the beam 1 of the LHC to \beta^*=\mathrm{beta_ip8}\times0.6^2 at the IP8 while enforcing the required constraints at the interaction point and the final dispersion suppressor (i.e. at makers "IP8" and "E.DS.R8.B1") in two iterations, using the 20 quadrupoles strengths from kq4 to kqt13 on left and right sides of the IP. The boundary conditions are specified by the beta0 blocks bir8b1 for the initial conditions and eir8b1 for the final conditions. The final summary and an instance of the intermediate summary of this match example are shown in :numref:`code.match.info1` and :ref:`code.match.info2`.
local SS, ES = "S.DS.L8.B1", "E.DS.R8.B1"
lhcb1.range = SS.."/"..ES
for n=1,2 do
beta_ip8 = beta_ip8*0.6
local status, fmin, ncall = match {
command := twiss { sequence=lhcb1, X0=bir8b1, method=4, observe=1 },
variables = { sign=true, rtol=1e-8, -- 20 variables
{ var='MADX.kq4_l8b1', name='kq4.l8b1', min=-lim2, max=lim2 },
{ var='MADX.kq5_l8b1', name='kq5.l8b1', min=-lim2, max=lim2 },
{ var='MADX.kq6_l8b1', name='kq6.l8b1', min=-lim2, max=lim2 },
{ var='MADX.kq7_l8b1', name='kq7.l8b1', min=-lim2, max=lim2 },
{ var='MADX.kq8_l8b1', name='kq8.l8b1', min=-lim2, max=lim2 },
{ var='MADX.kq9_l8b1', name='kq9.l8b1', min=-lim2, max=lim2 },
{ var='MADX.kq10_l8b1', name='kq10.l8b1', min=-lim2, max=lim2 },
{ var='MADX.kqtl11_l8b1', name='kqtl11.l8b1', min=-lim3, max=lim3 },
{ var='MADX.kqt12_l8b1', name='kqt12.l8b1' , min=-lim3, max=lim3 },
{ var='MADX.kqt13_l8b1', name='kqt13.l8b1', min=-lim3, max=lim3 },
{ var='MADX.kq4_r8b1', name='kq4.r8b1', min=-lim2, max=lim2 },
{ var='MADX.kq5_r8b1', name='kq5.r8b1', min=-lim2, max=lim2 },
{ var='MADX.kq6_r8b1', name='kq6.r8b1', min=-lim2, max=lim2 },
{ var='MADX.kq7_r8b1', name='kq7.r8b1', min=-lim2, max=lim2 },
{ var='MADX.kq8_r8b1', name='kq8.r8b1', min=-lim2, max=lim2 },
{ var='MADX.kq9_r8b1', name='kq9.r8b1', min=-lim2, max=lim2 },
{ var='MADX.kq10_r8b1', name='kq10.r8b1', min=-lim2, max=lim2 },
{ var='MADX.kqtl11_r8b1', name='kqtl11.r8b1', min=-lim3, max=lim3 },
{ var='MADX.kqt12_r8b1', name='kqt12.r8b1', min=-lim3, max=lim3 },
{ var='MADX.kqt13_r8b1', name='kqt13.r8b1', min=-lim3, max=lim3 },
},
equalities = { -- 14 equalities
{ expr=\t -> t.IP8.beta11-beta_ip8, kind='beta', name='IP8' },
{ expr=\t -> t.IP8.beta22-beta_ip8, kind='beta', name='IP8' },
{ expr=\t -> t.IP8.alfa11, kind='alfa', name='IP8' },
{ expr=\t -> t.IP8.alfa22, kind='alfa', name='IP8' },
{ expr=\t -> t.IP8.dx, kind='dx', name='IP8' },
{ expr=\t -> t.IP8.dpx, kind='dpx', name='IP8' },
{ expr=\t -> t[ES].beta11-eir8b1.beta11, kind='beta', name=ES },
{ expr=\t -> t[ES].beta22-eir8b1.beta22, kind='beta', name=ES },
{ expr=\t -> t[ES].alfa11-eir8b1.alfa11, kind='alfa', name=ES },
{ expr=\t -> t[ES].alfa22-eir8b1.alfa22, kind='alfa', name=ES },
{ expr=\t -> t[ES].dx-eir8b1.dx, kind='dx', name=ES },
{ expr=\t -> t[ES].dpx-eir8b1.dpx, kind='dpx', name=ES },
{ expr=\t -> t[ES].mu1-muxip8, kind='mu1', name=ES },
{ expr=\t -> t[ES].mu2-muyip8, kind='mu2', name=ES },
},
objective = { fmin=1e-10, broyden=true },
maxcall=1000, info=2
}
MADX.n, MADX.tar = n, fmin
end
The following example shows how to fit data with a non-linear model using the least squares methods. The "measurements" are generated by the data function:
d(x) = a \sin(x f_1) \cos(x f_2), \quad \text{with} \quad a=5, f1=3, f2=7, \text{ and } x\in[0,\pi).
The least squares minimization is performed by the small code below starting from the arbitrary values a=1, f_1=1, and f_2=1. The 'LD_JACOBIAN'
methods finds the values a=5\pm 10^{-10}, f_1=3\pm 10^{-11}, and f_2=7\pm 10^{-11} in 2574 iterations and 0.1,s. The 'LD_LMDIF' method finds similar values in 2539 iterations. The data and the model are plotted in the :numref:`fig.match.fit`.
local n, k, a, f1, f2 = 1000, pi/1000, 5, 3, 7
local d = vector(n):seq():map \i -> a*sin(i*k*f1)*cos(i*k*f2) -- data
if noise then d=d:map \x -> x+randtn(noise) end -- add noise if any
local m, p = vector(n), { a=1, f1=1, f2=1 } -- model parameters
local status, fmin, ncall = match {
command := m:seq():map \i -> p.a*sin(i*k*p.f1)*cos(i*k*p.f2),
variables = { { var='p.a' },
{ var='p.f1' },
{ var='p.f2' }, min=1, max=10 },
equalities = { { expr=\m -> ((d-m):norm()) } },
objective = { fmin=1e-9, bisec=noise and 5 },
maxcall=3000, info=1
}
The same least squares minimization can be achieved on noisy data by adding a gaussian RNG truncated at 2\sigma to the data generator, i.e.:literal:noise=2, and by increasing the attribute bisec=5. Of course, the penalty tolerance fmin must be moved to variables tolerance tol or rtol.
The 'LD_JACOBIAN' methods finds the values a=4.98470, f_1=3.00369, and f_2=6.99932 in 704 iterations (404 for 'LD_LMDIF'). The data and the model are plotted in :numref:`fig.match.fitnoise`.
The following example shows how to fit data with a non-linear model and its derivatives using the least squares methods. The least squares minimization is performed by the small code below starting from the arbitrary values v=0.9 and k=0.2. The 'LD_JACOBIAN' methods finds the values v=0.362\pm 10^{-3} and k=0.556\pm 10^{-3} in 6 iterations. The 'LD_LMDIF' method finds similar values in 6 iterations too. The data (points) and the model (curve) are plotted in the :numref:`fig.match.fit2`, where the latter has been smoothed using cubic splines.
local x = vector{0.038, 0.194, 0.425, 0.626 , 1.253 , 2.500 , 3.740 }
local y = vector{0.050, 0.127, 0.094, 0.2122, 0.2729, 0.2665, 0.3317}
local p = { v=0.9, k=0.2 }
local n = #x
local function eqfun (_, r, jac)
local v, k in p
for i=1,n do
r[i] = y[i] - v*x[i]/(k+x[i])
jac[2*i-1] = -x[i]/(k+x[i])
jac[2*i] = v*x[i]/(k+x[i])^2
end
end
local status, fmin, ncall = match {
variables = { tol=5e-3, min=0.1, max=2,
{ var='p.v' },
{ var='p.k' } },
equalities = { nequ=n, exec=eqfun, disp=false },
maxcall=20
The following example [6] hereafter shows how to find the minimum of the function:
\min_{\vec{x}\in\mathbb{R}^2} \sqrt{x_2}, \quad \text{subject to the constraints} \quad
\begin{cases}
x_2 \geq 0, \\
x_2\geq (a_1 x_1 + b_1)^3, \\
x_2 \geq (a_2 x_1 + b_2)^3,
\end{cases}
for the parameters a_1=2, b_1=0, a_2=-1 and b_2=1. The minimum of the function is f_{\min} = \sqrt{\frac{8}{27}} at the point \vec{x} = (\frac{1}{3}, \frac{8}{27}), and found by the method LD_MMA in 11 evaluations for a relative tolerance of 10^{-4} on the variables, starting at the arbitrary point \vec{x}_0=(1.234, 5.678).
local function testFuncFn (x, grd)
if grd then x:fill{ 0, 0.5/sqrt(x[2]) } end
return sqrt(x[2])
end
local function testFuncLe (x, r, jac)
if jac then jac:fill{ 24*x[1]^2, -1, -3*(1-x[1])^2, -1 } end
r:fill{ 8*x[1]^3-x[2], (1-x[1])^3-x[2] }
end
local x = vector{1.234, 5.678} -- start point
local status, fmin, ncall = match {
variables = { rtol=1e-4,
{ var='x[1]', min=-inf },
{ var='x[2]', min=0 } },
inequalities = { exec=testFuncLe, nequ=2, tol=1e-8 },
objective = { exec=testFuncFn, method='LD_MMA' },
maxcall=100, info=2
}
This example can also be solved with least squares methods, where the LD_JACOBIAN method finds the minimum in 8 iterations with a precision of \pm 10^{-16}, and the LD_LMDIF method finds the minimum in 10 iterations with a precision of \pm 10^{-11}.
| [1] | Here, the function (i.e. the deferred expression) ignores the matching environment passed as first argument. |
| [2] | The function mchklost is provided by the :doc:`GPhys module. <mad_mod_gphys>` |
| [3] | MAD-X matching corresponds to bstra=0. |
| [4] | MAD-X JACOBIAN with strategy=3 corresponds to jstra=3. |
| [5] | The LSopt module sets the values of valid inequalities to zero, i.e. \vec{c}^{\leq} = 0 if \vec{c}^{\leq} \leq\vec{c}^{\leq}_{\text{tol}}. |
| [6] | This example is taken from the NLopt documentation. |


