📄 lmder.c
字号:
/* minpack/lmder.f -- translated by f2c (version 20050501).
You must link the resulting object file with libf2c:
on Microsoft Windows system, link with libf2c.lib;
on Linux or Unix systems, link with .../path/to/libf2c.a -lm
or, if you install libf2c.a in a standard place, with -lf2c -lm
-- in that order, at the end of the command line, as in
cc *.o -lf2c -lm
Source for libf2c is in /netlib/f2c/libf2c.zip, e.g.,
http://www.netlib.org/f2c/libf2c.zip
*/
#ifdef __cplusplus
extern "C" {
#endif
#include "v3p_netlib.h"
/* Table of constant values */
static integer c__1 = 1;
static logical c_true = TRUE_;
/*< >*/
/* Subroutine */ int lmder_(
void (*fcn)(v3p_netlib_integer*,
v3p_netlib_integer*,
v3p_netlib_doublereal*,
v3p_netlib_doublereal*,
v3p_netlib_doublereal*,
v3p_netlib_integer*,
v3p_netlib_integer*,
void*),
integer *m, integer *n, doublereal *x,
doublereal *fvec, doublereal *fjac, integer *ldfjac, doublereal *ftol,
doublereal *xtol, doublereal *gtol, integer *maxfev, doublereal *
diag, integer *mode, doublereal *factor, integer *nprint, integer *
info, integer *nfev, integer *njev, integer *ipvt, doublereal *qtf,
doublereal *wa1, doublereal *wa2, doublereal *wa3, doublereal *wa4,
void* userdata)
{
/* Initialized data */
static doublereal one = 1.; /* constant */
static doublereal p1 = .1; /* constant */
static doublereal p5 = .5; /* constant */
static doublereal p25 = .25; /* constant */
static doublereal p75 = .75; /* constant */
static doublereal p0001 = 1e-4; /* constant */
static doublereal zero = 0.; /* constant */
/* System generated locals */
integer fjac_dim1, fjac_offset, i__1, i__2;
doublereal d__1, d__2, d__3;
/* Builtin functions */
double sqrt(doublereal);
/* Local variables */
integer i__, j, l;
doublereal par, sum;
integer iter;
doublereal temp=0, temp1, temp2;
integer iflag;
doublereal delta;
extern /* Subroutine */ int qrfac_(integer *, integer *, doublereal *,
integer *, logical *, integer *, integer *, doublereal *,
doublereal *, doublereal *), lmpar_(integer *, doublereal *,
integer *, integer *, doublereal *, doublereal *, doublereal *,
doublereal *, doublereal *, doublereal *, doublereal *,
doublereal *);
doublereal ratio;
extern doublereal enorm_(integer *, doublereal *);
doublereal fnorm, gnorm, pnorm, xnorm=0, fnorm1, actred, dirder, epsmch,
prered;
extern doublereal dpmpar_(integer *);
/*< integer m,n,ldfjac,maxfev,mode,nprint,info,nfev,njev >*/
/*< integer ipvt(n) >*/
/*< double precision ftol,xtol,gtol,factor >*/
/*< >*/
/* ********** */
/* subroutine lmder */
/* the purpose of lmder is to minimize the sum of the squares of */
/* m nonlinear functions in n variables by a modification of */
/* the levenberg-marquardt algorithm. the user must provide a */
/* subroutine which calculates the functions and the jacobian. */
/* the subroutine statement is */
/* subroutine lmder(fcn,m,n,x,fvec,fjac,ldfjac,ftol,xtol,gtol, */
/* maxfev,diag,mode,factor,nprint,info,nfev, */
/* njev,ipvt,qtf,wa1,wa2,wa3,wa4) */
/* where */
/* fcn is the name of the user-supplied subroutine which */
/* calculates the functions and the jacobian. fcn must */
/* be declared in an external statement in the user */
/* calling program, and should be written as follows. */
/* subroutine fcn(m,n,x,fvec,fjac,ldfjac,iflag) */
/* integer m,n,ldfjac,iflag */
/* double precision x(n),fvec(m),fjac(ldfjac,n) */
/* ---------- */
/* if iflag = 1 calculate the functions at x and */
/* return this vector in fvec. do not alter fjac. */
/* if iflag = 2 calculate the jacobian at x and */
/* return this matrix in fjac. do not alter fvec. */
/* ---------- */
/* return */
/* end */
/* the value of iflag should not be changed by fcn unless */
/* the user wants to terminate execution of lmder. */
/* in this case set iflag to a negative integer. */
/* m is a positive integer input variable set to the number */
/* of functions. */
/* n is a positive integer input variable set to the number */
/* of variables. n must not exceed m. */
/* x is an array of length n. on input x must contain */
/* an initial estimate of the solution vector. on output x */
/* contains the final estimate of the solution vector. */
/* fvec is an output array of length m which contains */
/* the functions evaluated at the output x. */
/* fjac is an output m by n array. the upper n by n submatrix */
/* of fjac contains an upper triangular matrix r with */
/* diagonal elements of nonincreasing magnitude such that */
/* t t t */
/* p *(jac *jac)*p = r *r, */
/* where p is a permutation matrix and jac is the final */
/* calculated jacobian. column j of p is column ipvt(j) */
/* (see below) of the identity matrix. the lower trapezoidal */
/* part of fjac contains information generated during */
/* the computation of r. */
/* ldfjac is a positive integer input variable not less than m */
/* which specifies the leading dimension of the array fjac. */
/* ftol is a nonnegative input variable. termination */
/* occurs when both the actual and predicted relative */
/* reductions in the sum of squares are at most ftol. */
/* therefore, ftol measures the relative error desired */
/* in the sum of squares. */
/* xtol is a nonnegative input variable. termination */
/* occurs when the relative error between two consecutive */
/* iterates is at most xtol. therefore, xtol measures the */
/* relative error desired in the approximate solution. */
/* gtol is a nonnegative input variable. termination */
/* occurs when the cosine of the angle between fvec and */
/* any column of the jacobian is at most gtol in absolute */
/* value. therefore, gtol measures the orthogonality */
/* desired between the function vector and the columns */
/* of the jacobian. */
/* maxfev is a positive integer input variable. termination */
/* occurs when the number of calls to fcn with iflag = 1 */
/* has reached maxfev. */
/* diag is an array of length n. if mode = 1 (see */
/* below), diag is internally set. if mode = 2, diag */
/* must contain positive entries that serve as */
/* multiplicative scale factors for the variables. */
/* mode is an integer input variable. if mode = 1, the */
/* variables will be scaled internally. if mode = 2, */
/* the scaling is specified by the input diag. other */
/* values of mode are equivalent to mode = 1. */
/* factor is a positive input variable used in determining the */
/* initial step bound. this bound is set to the product of */
/* factor and the euclidean norm of diag*x if nonzero, or else */
/* to factor itself. in most cases factor should lie in the */
/* interval (.1,100.).100. is a generally recommended value. */
/* nprint is an integer input variable that enables controlled */
/* printing of iterates if it is positive. in this case, */
/* fcn is called with iflag = 0 at the beginning of the first */
/* iteration and every nprint iterations thereafter and */
/* immediately prior to return, with x, fvec, and fjac */
/* available for printing. fvec and fjac should not be */
/* altered. if nprint is not positive, no special calls */
/* of fcn with iflag = 0 are made. */
/* info is an integer output variable. if the user has */
/* terminated execution, info is set to the (negative) */
/* value of iflag. see description of fcn. otherwise, */
/* info is set as follows. */
/* info = 0 improper input parameters. */
/* info = 1 both actual and predicted relative reductions */
/* in the sum of squares are at most ftol. */
/* info = 2 relative error between two consecutive iterates */
/* is at most xtol. */
/* info = 3 conditions for info = 1 and info = 2 both hold. */
/* info = 4 the cosine of the angle between fvec and any */
/* column of the jacobian is at most gtol in */
/* absolute value. */
/* info = 5 number of calls to fcn with iflag = 1 has */
/* reached maxfev. */
/* info = 6 ftol is too small. no further reduction in */
/* the sum of squares is possible. */
/* info = 7 xtol is too small. no further improvement in */
/* the approximate solution x is possible. */
/* info = 8 gtol is too small. fvec is orthogonal to the */
/* columns of the jacobian to machine precision. */
/* nfev is an integer output variable set to the number of */
/* calls to fcn with iflag = 1. */
/* njev is an integer output variable set to the number of */
/* calls to fcn with iflag = 2. */
/* ipvt is an integer output array of length n. ipvt */
/* defines a permutation matrix p such that jac*p = q*r, */
/* where jac is the final calculated jacobian, q is */
/* orthogonal (not stored), and r is upper triangular */
/* with diagonal elements of nonincreasing magnitude. */
/* column j of p is column ipvt(j) of the identity matrix. */
/* qtf is an output array of length n which contains */
/* the first n elements of the vector (q transpose)*fvec. */
/* wa1, wa2, and wa3 are work arrays of length n. */
/* wa4 is a work array of length m. */
/* subprograms called */
/* user-supplied ...... fcn */
/* minpack-supplied ... dpmpar,enorm,lmpar,qrfac */
/* fortran-supplied ... dabs,dmax1,dmin1,dsqrt,mod */
/* argonne national laboratory. minpack project. march 1980. */
/* burton s. garbow, kenneth e. hillstrom, jorge j. more */
/* ********** */
/*< integer i,iflag,iter,j,l >*/
/*< >*/
/*< double precision dpmpar,enorm >*/
/*< >*/
/* Parameter adjustments */
--wa4;
--fvec;
--wa3;
--wa2;
--wa1;
--qtf;
--ipvt;
--diag;
--x;
fjac_dim1 = *ldfjac;
fjac_offset = 1 + fjac_dim1;
fjac -= fjac_offset;
/* Function Body */
/* epsmch is the machine precision. */
/*< epsmch = dpmpar(1) >*/
epsmch = dpmpar_(&c__1);
/*< info = 0 >*/
*info = 0;
/*< iflag = 0 >*/
iflag = 0;
/*< nfev = 0 >*/
*nfev = 0;
/*< njev = 0 >*/
*njev = 0;
/* check the input parameters for errors. */
/*< >*/
if (*n <= 0 || *m < *n || *ldfjac < *m || *ftol < zero || *xtol < zero ||
*gtol < zero || *maxfev <= 0 || *factor <= zero) {
goto L300;
}
/*< if (mode .ne. 2) go to 20 >*/
if (*mode != 2) {
goto L20;
}
/*< do 10 j = 1, n >*/
i__1 = *n;
for (j = 1; j <= i__1; ++j) {
/*< if (diag(j) .le. zero) go to 300 >*/
if (diag[j] <= zero) {
goto L300;
}
/*< 10 continue >*/
/* L10: */
}
/*< 20 continue >*/
L20:
/* evaluate the function at the starting point */
/* and calculate its norm. */
/*< iflag = 1 >*/
iflag = 1;
/*< call fcn(m,n,x,fvec,fjac,ldfjac,iflag) >*/
(*fcn)(m, n, &x[1], &fvec[1], &fjac[fjac_offset], ldfjac, &iflag,
userdata);
/*< nfev = 1 >*/
*nfev = 1;
/*< if (iflag .lt. 0) go to 300 >*/
if (iflag < 0) {
goto L300;
}
/*< fnorm = enorm(m,fvec) >*/
fnorm = enorm_(m, &fvec[1]);
/* initialize levenberg-marquardt parameter and iteration counter. */
/*< par = zero >*/
par = zero;
/*< iter = 1 >*/
iter = 1;
/* beginning of the outer loop. */
/*< 30 continue >*/
L30:
/* calculate the jacobian matrix. */
/*< iflag = 2 >*/
iflag = 2;
/*< call fcn(m,n,x,fvec,fjac,ldfjac,iflag) >*/
(*fcn)(m, n, &x[1], &fvec[1], &fjac[fjac_offset], ldfjac, &iflag,
userdata);
/*< njev = njev + 1 >*/
++(*njev);
/*< if (iflag .lt. 0) go to 300 >*/
if (iflag < 0) {
goto L300;
}
/* if requested, call fcn to enable printing of iterates. */
/*< if (nprint .le. 0) go to 40 >*/
if (*nprint <= 0) {
goto L40;
}
/*< iflag = 0 >*/
iflag = 0;
/*< >*/
if ((iter - 1) % *nprint == 0) {
(*fcn)(m, n, &x[1], &fvec[1], &fjac[fjac_offset], ldfjac, &iflag,
userdata);
}
/*< if (iflag .lt. 0) go to 300 >*/
if (iflag < 0) {
goto L300;
}
/*< 40 continue >*/
L40:
/* compute the qr factorization of the jacobian. */
/*< call qrfac(m,n,fjac,ldfjac,.true.,ipvt,n,wa1,wa2,wa3) >*/
qrfac_(m, n, &fjac[fjac_offset], ldfjac, &c_true, &ipvt[1], n, &wa1[1], &
wa2[1], &wa3[1]);
/* on the first iteration and if mode is 1, scale according */
/* to the norms of the columns of the initial jacobian. */
/*< if (iter .ne. 1) go to 80 >*/
if (iter != 1) {
goto L80;
}
/*< if (mode .eq. 2) go to 60 >*/
if (*mode == 2) {
goto L60;
}
/*< do 50 j = 1, n >*/
i__1 = *n;
for (j = 1; j <= i__1; ++j) {
/*< diag(j) = wa2(j) >*/
diag[j] = wa2[j];
/*< if (wa2(j) .eq. zero) diag(j) = one >*/
if (wa2[j] == zero) {
diag[j] = one;
}
/*< 50 continue >*/
/* L50: */
}
/*< 60 continue >*/
L60:
/* on the first iteration, calculate the norm of the scaled x */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -