Ejemplo n.º 1
0
/*
 * PROCEDURE    : lmder1
 *
 * ENTREE	:
 * fcn		Fonction qui calcule la fonction et le jacobien de la fonction.
 * m		Nombre de fonctions.
 * n		Nombre de variables (parametres). n <= m
 * x		Vecteur de taille "n" contenant en entree une estimation
 *		initiale de la solution.
 * ldfjac	Taille maximale de la matrice "fjac". ldfjac >= "m".
 * tol		Tolerance. La terminaison de la procedure survient quand
 *		l'algorithme estime que l'erreur relative dans la somme des
 *		carres est au moins egal a tol ou bien que l'erreur relative
 *		entre x et la solution est au moins egal atol.
 * wa		Vecteur de travail de taille "lwa".
 * lwa		Taille du vecteur "wa". wa >= 5 * n + m.
 *
 *
 * SORTIE	:
 * x		Vecteur de taille "n" contenant en sortie l'estimee finale
 *		de la solution.
 * fvec		Vecteur de taille "m" contenant les fonctions evaluee en "x".
 * fjac		Matrice de taille "m" x "n". La sous matrice superieure de
 *		taille "n" x "n" de fjac contient une matrice triangulaire
 *		superieure r dont les elements diagonaux, classe dans le sens
 *		decroissant de leur valeur, sont de la forme :
 *
 *      	                 T      T              T
 *				p * (jac * jac) * p = r * r
 *
 *		Ou p est une matrice de permutation et jac est le jacobien
 *		     final calcule.
 *		La colonne j de p est la colonne ipvt (j) (voir ci apres) de
 *		la matrice identite. La partie trapesoidale inferieure de fjac
 *		contient les informations genere durant le calcul de r.
 * info		Information de l'executionde la procedure. Lorsque la procedure
 *		a termine son execution, "info" est inialisee a la valeur
 *		(negative) de iflag. sinon elle prend les valeurs suivantes :
 *		info = 0 : parametres en entre non valides.
 *		info = 1 : estimation par l'algorithme que l'erreur relative
 *			   de la somme des carre est egal a tol.
 *		info = 2 : estimation par l'algorithme que l'erreur relative
 *			   entre x et la solution est egal a tol.
 *		info = 3 : conditions info = 1 et info = 2 tous deux requis.
 *		info = 4 : fvec est orthogonal aux colonnes du jacobien.
 *		info = 5 : nombre d'appels a fcn avec iflag = 1 a atteint
 *			   100 * (n + 1).
 *		info = 6 : tol est trop petit. Plus moyen de reduire de la
 *			   somme des carres.
 *		info = 7 : tol est trop petit. Plus d'amelioration possible
 *			   d' approximer la solution x.
 * ipvt		Vecteur de taille "n". Il definit une matrice de permutation p
 *		tel que jac * p = q * p, ou jac est le jacbien final calcule,
 *		q est orthogonal (non socke) et r est triangulaire superieur,
 *		avec les elements diagonaux classes en ordre decroissant de
 *		leur valeur. La colonne j de p est ipvt[j] de la matrice identite.
 *
 * DESCRIPTION  :
 * La procedure minimize la somme de carre de m equation non lineaire a n
 * variables par une modification de l'algorithme de Levenberg - Marquardt.
 * Cette procedure appele la procedure generale au moindre carre lmder.
 *
 * REMARQUE	:
 * L'utilisateur doit fournir une procedure "fcn" qui calcule la fonction et
 * le jacobien.
 * "fcn" doit etre declare dans une instruction externe a la procedure et doit
 * etre appele comme suit :
 * fcn (int m, int n, int ldfjac, double *x, double *fvec, double *fjac, int *iflag)
 *
 * si iflag = 1 calcul de la fonction en x et retour de ce vecteur dans fvec.
 *		fjac n'est pas modifie.
 * si iflag = 2 calcul du jacobien en x et retour de cette matrice dans fjac.
 *		fvec n'est pas modifie.
 *
 * RETOUR	:
 * En cas de succes, la valeur zero est retournee.
 * Sinon, la valeur -1.
 *
 */
int lmder1 (void (*ptr_fcn)(int m, int n, double *xc, double *fvecc,
			    double *jac, int ldfjac, int iflag),
	    int m, int n, double *x, double *fvec, double *fjac,
	    int ldfjac, double tol, int *info, int *ipvt, int lwa, double *wa)
{
  const double	factor = 100.0;
  int		maxfev, mode, nfev, njev, nprint;
  double		ftol, gtol, xtol;

  *info = 0;

  /* verification des parametres en entree qui causent des erreurs */


  if ((n <= 0) || (m < n) || (ldfjac < m) || (tol < 0.0) ||
      (lwa < (5 * n + m)) )
  {
    printf("%d %d %d %d  %d \n", (n <= 0) , (m < n), (ldfjac < m), (tol < 0.0) ,      (lwa < (5 * n + m))) ;
    return (-1);
  }

  /* appel a lmder	*/

  maxfev = 100 * (n + 1);
  ftol = tol;
  xtol = tol;
  gtol = 0.0;
  mode = 1;
  nprint = 0;

  lmder (ptr_fcn , m, n, x, fvec, fjac, ldfjac, ftol, xtol, gtol, maxfev, wa,
	 mode, factor, nprint, info, &nfev, &njev, ipvt, &wa[n], &wa[2 * n],
	 &wa[3 * n], &wa[4 * n], &wa[5 * n]);

  if (*info == 8)
    *info = 4;

  return (0);
}
Ejemplo n.º 2
0
/* Subroutine */ int lmder1(minpack_funcder_mn fcn, void *p, int m, int n, double *x, 
	double *fvec, double *fjac, int ldfjac, double tol, 
	int *ipvt, double *wa, int lwa)
{
    /* Initialized data */

    const double factor = 100.;

    /* System generated locals */
    int fjac_dim1, fjac_offset;

    /* Local variables */
    int mode, nfev, njev;
    double ftol, gtol, xtol;
    int maxfev, nprint;
    int info;

/*     ********** */

/*     subroutine lmder1 */

/*     the purpose of lmder1 is to minimize the sum of the squares of */
/*     m nonlinear functions in n variables by a modification of the */
/*     levenberg-marquardt algorithm. this is done by using the more */
/*     general least-squares solver lmder. the user must provide a */
/*     subroutine which calculates the functions and the jacobian. */

/*     the subroutine statement is */

/*       subroutine lmder1(fcn,m,n,x,fvec,fjac,ldfjac,tol,info, */
/*                         ipvt,wa,lwa) */

/*     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 lmder1. */
/*         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. */

/*       tol is a nonnegative input variable. termination occurs */
/*         when the algorithm estimates either that the relative */
/*         error in the sum of squares is at most tol or that */
/*         the relative error between x and the solution is at */
/*         most tol. */

/*       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  algorithm estimates that the relative error */
/*                   in the sum of squares is at most tol. */

/*         info = 2  algorithm estimates that the relative error */
/*                   between x and the solution is at most tol. */

/*         info = 3  conditions for info = 1 and info = 2 both hold. */

/*         info = 4  fvec is orthogonal to the columns of the */
/*                   jacobian to machine precision. */

/*         info = 5  number of calls to fcn with iflag = 1 has */
/*                   reached 100*(n+1). */

/*         info = 6  tol is too small. no further reduction in */
/*                   the sum of squares is possible. */

/*         info = 7  tol is too small. no further improvement in */
/*                   the approximate solution x is possible. */

/*       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. */

/*       wa is a work array of length lwa. */

/*       lwa is a positive integer input variable not less than 5*n+m. */

/*     subprograms called */

/*       user-supplied ...... fcn */

/*       minpack-supplied ... lmder */

/*     argonne national laboratory. minpack project. march 1980. */
/*     burton s. garbow, kenneth e. hillstrom, jorge j. more */

/*     ********** */
    /* Parameter adjustments */
    --fvec;
    --ipvt;
    --x;
    fjac_dim1 = ldfjac;
    fjac_offset = 1 + fjac_dim1 * 1;
    fjac -= fjac_offset;
    --wa;

    /* Function Body */
    info = 0;

/*     check the input parameters for errors. */

    if (n <= 0 || m < n || ldfjac < m || tol < 0. || lwa < n * 5 +
	    m) {
	/* goto L10; */
        return info;
    }

/*     call lmder. */

    maxfev = (n + 1) * 100;
    ftol = tol;
    xtol = tol;
    gtol = 0.;
    mode = 1;
    nprint = 0;
    info = lmder(fcn, p, m, n, &x[1], &fvec[1], &fjac[fjac_offset], ldfjac,
	    ftol, xtol, gtol, maxfev, &wa[1], mode, factor, nprint, 
	    &nfev, &njev, &ipvt[1], &wa[n + 1], &wa[(n << 1) + 1], &
	    wa[n * 3 + 1], &wa[(n << 2) + 1], &wa[n * 5 + 1]);
    if (info == 8) {
	info = 4;
    }
/* L10: */
    return info;

/*     last card of subroutine lmder1. */

} /* lmder1_ */