Integer type:  int32  int64  nag_int  show int32  show int32  show int64  show int64  show nag_int  show nag_int

Chapter Contents
Chapter Introduction
NAG Toolbox

# NAG Toolbox: nag_opt_lsq_check_deriv (e04ya)

## Purpose

nag_opt_lsq_check_deriv (e04ya) checks that a user-supplied function for evaluating a vector of functions and the matrix of their first derivatives produces derivative values which are consistent with the function values calculated.

## Syntax

[fvec, fjac, user, ifail] = e04ya(m, lsqfun, x, 'n', n, 'user', user)
[fvec, fjac, user, ifail] = nag_opt_lsq_check_deriv(m, lsqfun, x, 'n', n, 'user', user)
Note: the interface to this routine has changed since earlier releases of the toolbox:
Mark 22: liw, lw have been removed from the interface
Mark 24: drop w and iw, introduce user in main routine and all call-backs
.

## Description

Routines for minimizing a sum of squares of m$m$ nonlinear functions (or ‘residuals’), fi(x1,x2,,xn)${f}_{\mathit{i}}\left({x}_{1},{x}_{2},\dots ,{x}_{n}\right)$, for i = 1,2,,m$\mathit{i}=1,2,\dots ,m$ and mn$m\ge n$, may require you to supply a function to evaluate the fi${f}_{i}$ and their first derivatives. nag_opt_lsq_check_deriv (e04ya) checks the derivatives calculated by such user-supplied functions, e.g., functions of the form required for nag_opt_lsq_uncon_quasi_deriv_comp (e04gb), nag_opt_lsq_uncon_mod_deriv_comp (e04gd) and nag_opt_lsq_uncon_mod_deriv2_comp (e04he). As well as the function to be checked (lsqfun), you must supply a point x = (x1,x2,,xn)T $x={\left({x}_{1},{x}_{2},\dots ,{x}_{n}\right)}^{\mathrm{T}}$ at which the check will be made. nag_opt_lsq_check_deriv (e04ya) is essentially identical to CHKLSJ in the NPL Algorithms Library.
nag_opt_lsq_check_deriv (e04ya) first calls lsqfun to evaluate the fi(x)${f}_{i}\left(x\right)$ and their first derivatives, and uses these to calculate the sum of squares F(x) = i = 1m[fi(x)]2$F\left(x\right)=\sum _{i=1}^{m}{\left[{f}_{i}\left(x\right)\right]}^{2}$, and its first derivatives gj = ( F )/( xj )|x ${g}_{j}={\frac{\partial F}{\partial {x}_{j}}|}_{x}$, for j = 1,2,,n$j=1,2,\dots ,n$. The components of g$g$ along two orthogonal directions (defined by unit vectors p1${p}_{1}$ and p2${p}_{2}$, say) are then calculated; these will be gTp1${g}^{\mathrm{T}}{p}_{1}$ and gTp2${g}^{\mathrm{T}}{p}_{2}$ respectively. The same components are also estimated by finite differences, giving quantities
 vk = (F(x + hpk) − F(x))/h,  k = 1,2 $vk=F(x+hpk)-F(x)h, k=1,2$
where h$h$ is a small positive scalar. If the relative difference between v1${v}_{1}$ and gTp1${g}^{\mathrm{T}}{p}_{1}$ or between v2${v}_{2}$ and gTp2${g}^{\mathrm{T}}{p}_{2}$ is judged too large, an error indicator is set.

None.

## Parameters

### Compulsory Input Parameters

1:     m – int64int32nag_int scalar
The number m$m$ of residuals, fi(x)${f}_{i}\left(x\right)$, and the number n$n$ of variables, xj${x}_{j}$.
Constraint: 1nm$1\le {\mathbf{n}}\le {\mathbf{m}}$.
2:     lsqfun – function handle or string containing name of m-file
lsqfun must calculate the vector of values fi(x)${f}_{i}\left(x\right)$ and their first derivatives (fi)/(xj) $\frac{\partial {f}_{i}}{\partial {x}_{j}}$ at any point x$x$. (The minimization functions mentioned in Section [Description] give you the option of resetting a parameter to terminate immediately. nag_opt_lsq_check_deriv (e04ya) will also terminate immediately, without finishing the checking process, if the parameter in question is reset.)
[iflag, fvec, fjac, user] = lsqfun(iflag, m, n, xc, ldfjac, user)

Input Parameters

1:     iflag – int64int32nag_int scalar
To lsqfun, iflag will be set to 2$2$.
2:     m – int64int32nag_int scalar
The numbers m$m$ of residuals.
3:     n – int64int32nag_int scalar
The numbers n$n$ of variables.
4:     xc(n) – double array
x$x$, the point at which the values of the fi${f}_{i}$ and the (fi)/(xj) $\frac{\partial {f}_{i}}{\partial {x}_{j}}$ are required.
5:     ldfjac – int64int32nag_int scalar
The first dimension of the array fjac as declared in the (sub)program from which nag_opt_lsq_check_deriv (e04ya) is called.
6:     user – Any MATLAB object
lsqfun is called from nag_opt_lsq_check_deriv (e04ya) with the object supplied to nag_opt_lsq_check_deriv (e04ya).

Output Parameters

1:     iflag – int64int32nag_int scalar
If you reset iflag to some negative number in lsqfun and return control to nag_opt_lsq_check_deriv (e04ya), the function will terminate immediately with ifail set to your setting of iflag.
2:     fvec(m) – double array
Unless iflag is reset to a negative number, fvec(i)${\mathbf{fvec}}\left(\mathit{i}\right)$ must contain the value of fi${f}_{\mathit{i}}$ at the point x$x$, for i = 1,2,,m$\mathit{i}=1,2,\dots ,m$.
3:     fjac(ldfjac,n) – double array
ldfjacm$\mathit{ldfjac}\ge {\mathbf{m}}$.
Unless iflag is reset to a negative number, fjac(i,j)${\mathbf{fjac}}\left(\mathit{i},\mathit{j}\right)$ must contain the value of (fi)/(xj) $\frac{\partial {f}_{\mathit{i}}}{\partial {x}_{\mathit{j}}}$ at the point x$x$, for i = 1,2,,m$\mathit{i}=1,2,\dots ,m$ and j = 1,2,,n$\mathit{j}=1,2,\dots ,n$.
4:     user – Any MATLAB object
3:     x(n) – double array
n, the dimension of the array, must satisfy the constraint 1nm$1\le {\mathbf{n}}\le {\mathbf{m}}$.
x(j)${\mathbf{x}}\left(\mathit{j}\right)$, for j = 1,2,,n$\mathit{j}=1,2,\dots ,n$, must be set to the coordinates of a suitable point at which to check the derivatives calculated by lsqfun. ‘Obvious’ settings, such as 0$0$ or 1$1$, should not be used since, at such particular points, incorrect terms may take correct values (particularly zero), so that errors can go undetected. For a similar reason, it is preferable that no two elements of x should have the same value.

### Optional Input Parameters

1:     n – int64int32nag_int scalar
Default: For n, the dimension of the array x.
The number m$m$ of residuals, fi(x)${f}_{i}\left(x\right)$, and the number n$n$ of variables, xj${x}_{j}$.
Constraint: 1nm$1\le {\mathbf{n}}\le {\mathbf{m}}$.
2:     user – Any MATLAB object
user is not used by nag_opt_lsq_check_deriv (e04ya), but is passed to lsqfun. Note that for large objects it may be more efficient to use a global variable which is accessible from the m-files than to use user.

### Input Parameters Omitted from the MATLAB Interface

ldfjac iuser liw w lw

### Output Parameters

1:     fvec(m) – double array
Unless you set iflag negative in the first call of lsqfun, fvec(i)${\mathbf{fvec}}\left(\mathit{i}\right)$ contains the value of fi${f}_{\mathit{i}}$ at the point supplied by you in x, for i = 1,2,,m$\mathit{i}=1,2,\dots ,m$.
2:     fjac(ldfjac,n) – double array
ldfjacm$\mathit{ldfjac}\ge {\mathbf{m}}$.
Unless you set iflag negative in the first call of lsqfun, fjac(i,j)${\mathbf{fjac}}\left(\mathit{i},\mathit{j}\right)$ contains the value of the first derivative (fi)/(xj) $\frac{\partial {f}_{\mathit{i}}}{\partial {x}_{\mathit{j}}}$ at the point given in x, as calculated by lsqfun, for i = 1,2,,m$\mathit{i}=1,2,\dots ,m$ and j = 1,2,,n$\mathit{j}=1,2,\dots ,n$.
3:     user – Any MATLAB object
4:     ifail – int64int32nag_int scalar
${\mathrm{ifail}}={\mathbf{0}}$ unless the function detects an error (see [Error Indicators and Warnings]).

## Error Indicators and Warnings

Note: nag_opt_lsq_check_deriv (e04ya) may return useful information for one or more of the following detected errors or warnings.
Errors or warnings detected by the function:

Cases prefixed with W are classified as warnings and do not generate an error of type NAG:error_n. See nag_issue_warnings.

W ifail < 0${\mathbf{ifail}}<0$
A negative value of ifail indicates an exit from nag_opt_lsq_check_deriv (e04ya) because you have set iflag negative in lsqfun. The setting of ifail will be the same as your setting of iflag. The check on lsqfun will not have been completed.
ifail = 1${\mathbf{ifail}}=1$
 On entry, m < n${\mathbf{m}}<{\mathbf{n}}$, or n < 1${\mathbf{n}}<1$, or ldfjac < m$\mathit{ldfjac}<{\mathbf{m}}$, or liw < 1$\mathit{liw}<1$, or lw < 3 × n + m + m × n$\mathit{lw}<3×{\mathbf{n}}+{\mathbf{m}}+{\mathbf{m}}×{\mathbf{n}}$.
W ifail = 2${\mathbf{ifail}}=2$
You should check carefully the derivation and programming of expressions for the (fi)/(xj) $\frac{\partial {f}_{i}}{\partial {x}_{j}}$, because it is very unlikely that lsqfun is calculating them correctly.

## Accuracy

ifail is set to 2$2$ if
 (vk − gTpk)2 ≥ h × ((gTpk)2 + 1) $( vk - gT pk ) 2 ≥ h× ( ( gT pk ) 2 +1 )$
for k = 1​ or ​2$k=1\text{​ or ​}2$. (See Section [Description] for definitions of the quantities involved.) The scalar h$h$ is set equal to sqrt(ε)$\sqrt{\epsilon }$, where ε$\epsilon$ is the machine precision as given by nag_machine_precision (x02aj).

nag_opt_lsq_check_deriv (e04ya) calls lsqfun three times.
Before using nag_opt_lsq_check_deriv (e04ya) to check the calculation of the first derivatives, you should be confident that lsqfun is calculating the residuals correctly.
nag_opt_lsq_check_deriv (e04ya) only checks the derivatives calculated by a user-supplied function when iflag = 2${\mathbf{iflag}}=2$. So, if lsqfun is intended for use in conjunction with a minimization function which may set iflag to 1$1$, you must check that, for given settings of the xc(j)${\mathbf{xc}}\left(j\right)$, lsqfun produces the same values for the (fi)/(xj) $\frac{\partial {f}_{i}}{\partial {x}_{j}}$ when iflag is set to 1$1$ as when iflag is set to 2$2$.

## Example

```function nag_opt_lsq_check_deriv_example
m = int64(15);
x = [0.19; -1.34; 0.88];
y=[0.14,0.18,0.22,0.25,0.29,0.32,0.35,0.39,0.37,0.58,0.73,0.96,1.34,2.10,4.39];

t = [1.0, 15.0, 1.0;
2.0, 14.0, 2.0;
3.0, 13.0, 3.0;
4.0, 12.0, 4.0;
5.0, 11.0, 5.0;
6.0, 10.0, 6.0;
7.0, 9.0, 7.0;
8.0, 8.0, 8.0;
9.0, 7.0, 7.0;
10.0, 6.0, 6.0;
11.0, 5.0, 5.0;
12.0, 4.0, 4.0;
13.0, 3.0, 3.0;
14.0, 2.0, 2.0;
15.0, 1.0, 1.0];

user = {y; t};

[fvec, fjac, user, ifail] = nag_opt_lsq_check_deriv(m, @lsqfun, x, 'user', user)

function [iflag, fvecc, fjacc, user] = lsqfun(iflag, m, n, xc, ljc, user)
y = user{1};
t = user{2};

fvecc = zeros(m, 1);
fjacc = zeros(ljc, n);

for i = 1:double(m)
denom = xc(2)*t(i,2) + xc(3)*t(i,3);
if (iflag ~= 1)
fvecc(i) = xc(1) + t(i,1)/denom - y(i);
end
if (iflag ~= 0)
fjacc(i,1) = 1;
dummy = -1/(denom*denom);
fjacc(i,2) = t(i,1)*t(i,2)*dummy;
fjacc(i,3) = t(i,1)*t(i,3)*dummy;
end
end
```
```

fvec =

-0.0020
-0.1076
-0.2330
-0.3785
-0.5836
-0.8689
-1.3464
-2.3739
-2.9750
-4.0132
-5.3226
-7.2917
-10.5703
-17.1274
-36.8087

fjac =

1.0000   -0.0406   -0.0027
1.0000   -0.0969   -0.0138
1.0000   -0.1785   -0.0412
1.0000   -0.3043   -0.1014
1.0000   -0.5144   -0.2338
1.0000   -0.9100   -0.5460
1.0000   -1.8098   -1.4076
1.0000   -4.7259   -4.7259
1.0000   -6.0762   -6.0762
1.0000   -7.8765   -7.8765
1.0000  -10.3970  -10.3970
1.0000  -14.1777  -14.1777
1.0000  -20.4789  -20.4789
1.0000  -33.0813  -33.0813
1.0000  -70.8885  -70.8885

user =

[ 1x15 double]
[15x3  double]

ifail =

0

```
```function e04ya_example
m = int64(15);
x = [0.19; -1.34; 0.88];
y=[0.14,0.18,0.22,0.25,0.29,0.32,0.35,0.39,0.37,0.58,0.73,0.96,1.34,2.10,4.39];

t = [1.0, 15.0, 1.0;
2.0, 14.0, 2.0;
3.0, 13.0, 3.0;
4.0, 12.0, 4.0;
5.0, 11.0, 5.0;
6.0, 10.0, 6.0;
7.0, 9.0, 7.0;
8.0, 8.0, 8.0;
9.0, 7.0, 7.0;
10.0, 6.0, 6.0;
11.0, 5.0, 5.0;
12.0, 4.0, 4.0;
13.0, 3.0, 3.0;
14.0, 2.0, 2.0;
15.0, 1.0, 1.0];

user = {y; t};

[fvec, fjac, user, ifail] = e04ya(m, @lsqfun, x, 'user', user)

function [iflag, fvecc, fjacc, user] = lsqfun(iflag, m, n, xc, ljc, user)
y = user{1};
t = user{2};

fvecc = zeros(m, 1);
fjacc = zeros(ljc, n);

for i = 1:double(m)
denom = xc(2)*t(i,2) + xc(3)*t(i,3);
if (iflag ~= 1)
fvecc(i) = xc(1) + t(i,1)/denom - y(i);
end
if (iflag ~= 0)
fjacc(i,1) = 1;
dummy = -1/(denom*denom);
fjacc(i,2) = t(i,1)*t(i,2)*dummy;
fjacc(i,3) = t(i,1)*t(i,3)*dummy;
end
end
```
```

fvec =

-0.0020
-0.1076
-0.2330
-0.3785
-0.5836
-0.8689
-1.3464
-2.3739
-2.9750
-4.0132
-5.3226
-7.2917
-10.5703
-17.1274
-36.8087

fjac =

1.0000   -0.0406   -0.0027
1.0000   -0.0969   -0.0138
1.0000   -0.1785   -0.0412
1.0000   -0.3043   -0.1014
1.0000   -0.5144   -0.2338
1.0000   -0.9100   -0.5460
1.0000   -1.8098   -1.4076
1.0000   -4.7259   -4.7259
1.0000   -6.0762   -6.0762
1.0000   -7.8765   -7.8765
1.0000  -10.3970  -10.3970
1.0000  -14.1777  -14.1777
1.0000  -20.4789  -20.4789
1.0000  -33.0813  -33.0813
1.0000  -70.8885  -70.8885

user =

[ 1x15 double]
[15x3  double]

ifail =

0

```