eqSolvemt#
Purpose#
Solves a system of nonlinear equations.
Format#
- out = eqSolvemt(&fct, par, ..., c)#
- Parameters:
&fct (scalar function pointer) – pointer to a procedure that computes the function to be minimized. This procedure must have an instance of a
PV
structure containing the parameters as the first input. Extra data needed by this function may be passed in after thePV
structure, but before the control structure. This procedure must have one output argument, a column vector containing the result of each equation.par (an instance of a
PV
structure) – The par instance is passed to the user-provided procedure pointed to by &fct. par is constructed using thepvPack()
functions..... – Optional extra arguments. These arguments are passed untouched to the user-provided objective function, by
eqSolveMT()
.c (an instance of an
eqSolvemtControl
structure.) –Optional. Normally an instance is initialized by calling
eqSolvemtControlCreate()
and members of this instance can be set to other values by the user. For an instance named c, the members are:c.jacobianProc
pointer to a procedure which computes the analytical Jacobian. By default,
eqSolvemt()
will compute the Jacobian numerically.c.maxIters
scalar, the maximum number of iterations. Default = 100.
c.stepTolerance
scalar, the step tolerance. Default = \(macheps^{2/3}\)
c.typicalF
Kx1 vector of the typical
fct(x)
values at a point not near a root, used for scaling. This becomes important when the magnitudes of the components offct(x)
are expected to be very different. By default, function values are not scaled.c.typicalX
Kx1 vector of the typical magnitude of x, used for scaling. This becomes important when the magnitudes of the components of x are expected to be very different. By default, variable values are not scaled.
c.printIters
scalar, if nonzero, iteration information is printed. Default = 0.
c.tolerance
scalar, the tolerance of the scalar function \(f = 0.5*||fct(X)||2\) required to terminate the algorithm. That is, the condition that \(|f(x)| <= c.tolerance\) must be met before that algorithm can terminate successfully. Default = 1e-5.
c.altNames
Kx1 string array of alternate names to be used by the printed output. By default, the names
X1,X2,X3...
will be used.c.title
string, printed as a title in output.
c.output
scalar. If non-zero, final results are printed.
- Returns:
out (struct) –
instance of
eqSolvemtOut
struct. For an instance named out, the members are:out.par
an instance of a
PV
structure containing the parameter estimates.out.fct
scalar, function evaluated at x
out.retcode
scalar, return code:
- -1:
Jacobian is singular.
- 1:
Norm of the scaled function value is less than c.tolerance. x given is an approximate root of
fct(x)
(unless c.tolerance is too large).- 2:
The scaled distance between the last two steps is less than the step-tolerance (c.stepTolerance). x may be an approximate root of
fct(x)
, but it is also possible that the algorithm is making very slow progress and is not near a root, or the step-tolerance is too large.- 3:
The last global step failed to decrease
norm2(fct(x))
sufficiently; either x is close to a root offct(x)
and no more accuracy is possible, or an incorrectly coded analytic Jacobian is being used, or the secant approximation to the Jacobian is inaccurate, or the step-tolerance is too large.- 4:
Iteration limit exceeded.
- 5:
Five consecutive steps of maximum step length have been taken; either
norm2(fct(x))
asymptotes from above to a finite value in some direction or the maximum step length is too small.- 6:
x seems to be an approximate local minimizer of
norm2(fct(x))
that is not a root offct(x)
. To find a root offct(x)
, restarteqSolvemt()
from a different region.
Examples#
Basic usage#
For example, consider a two-equation system given by:
new;
// Declare 'par' to be an instance of a PV vector
struct PV par;
/*
** Create default PV struct and add a parameter
** named 'x1' with a starting value of 1
*/
par = pvPack(pvCreate(), 1, "x1");
/*
** Add a parameter named 'x2' to 'par'
** with a starting value of 1
*/
par = pvPack(par, 1, "x2");
/*
** Solve the system of equations
** and print the output to the screen
*/
call eqSolvemt(&fct, par);
// The definition of the function to be minimized
proc fct(struct PV p);
local x1, x2, z;
x1 = pvUnpack(p, "x1");
x2 = pvUnpack(p, "x2");
z = (x1^2 + x2^2 - 5) | (exp(x1 - 1) + x2^3 - 5);
retp(z);
endp;
After the code above, a short report will be printed to the Command window. Part of the output is displayed below:
--------------------------------------------------------------------
VARIABLE START ROOTS F(ROOTS)
--------------------------------------------------------------------
X1 1.00000 1.7146639625 0.0000000001
X2 1.00000 1.4352447511 0.0000000002
--------------------------------------------------------------------
Using control and output structures#
Again, consider a two-equation system given by:
new;
// Declare control structure and fill with defaults
struct eqSolvemtControl c;
c = eqSolvemtControlCreate();
// Turn on printing of iteration information
c.printIters = 1;
// Assign variable names printed output
c.altNames = "alpha" $| "beta";
// Declare 'par' to be an instance of a PV vector
struct PV par;
/*
** Create default PV struct and add a parameter
** named 'x1' with a starting value of 1
*/
par = pvPack(pvCreate(),1, "x1");
/*
** Add a parameter named 'x2' to 'par'
** with a starting value of 1
*/
par = pvPack(par, 1, "x2");
// Declare output structure to hold results
struct eqSolvemtOut out;
// Solve the system of equations
out = eqSolvemt(&fct, par, c);
// The definition of the function to be minimized
proc fct(struct PV p);
local x1, x2, z;
x1 = pvUnpack(p, "x1");
x2 = pvUnpack(p, "x2");
z = (x1^2 + x2^2 - 5) | (exp(x1 - 1) + x2^3 - 5);
retp(z);
endp;
The code above will print out a report similar to the previous example. Notice that the variable names in the report are what we assigned to the altNames member of the control structure.
--------------------------------------------------------------------------------
VARIABLE START ROOTS F(ROOTS)
--------------------------------------------------------------------------------
alpha 1.00000 1.7146639625 0.0000000001
beta 1.00000 1.4352447511 0.0000000002
--------------------------------------------------------------------------------
The parameter values returned by eqSolveMT()
are located in the par member of the eqsolveMTOut
struct. They can be accessed with pvGetParVector()
or pvUnpack()
like this:
// Return the values of 'x1' and 'x2' as a 2x1 vector
x_all = pvGetParVector(out.par);
// Return the value of 'x1'
x1 = pvUnpack(out.par, "x1");
// Return the value of 'x2'
x2 = pvUnpack(out.par, "x2");
Remarks#
The equation procedure should return a column vector containing the result for each equation. For example, consider a two-equation system given by:
proc (1) = f(struct PV p);
local x1, x2, eqns;
// Set x1
x1 = pvUnpack(p, "x1");
// Set x2
x2 = pvUnpack(p, "x2");
// Preallocate output vector
eqns = { 0, 0 };
// Equation 1
eqns[1] = x1^2 + x2^2 - 2;
// Equation 2
eqns[2] = exp(x1-1) + x2^3 - 2;
retp(eqns);
endp;
Note that the first equation in the system is contained in the first row of eqns
and the second equation is contained in the second row of eqns
.
Source#
eqsolvemt.src
See also
Functions eqSolvemtControlCreate()
, eqSolvemtOutCreate()