⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 misc_core.c

📁 levenberg marquit算法的.C源码
💻 C
📖 第 1 页 / 共 2 页
字号:
/////////////////////////////////////////////////////////////////////////////////// //  Levenberg - Marquardt non-linear minimization algorithm//  Copyright (C) 2004-05  Manolis Lourakis (lourakis@ics.forth.gr)//  Institute of Computer Science, Foundation for Research & Technology - Hellas//  Heraklion, Crete, Greece.////  This program is free software; you can redistribute it and/or modify//  it under the terms of the GNU General Public License as published by//  the Free Software Foundation; either version 2 of the License, or//  (at your option) any later version.////  This program is distributed in the hope that it will be useful,//  but WITHOUT ANY WARRANTY; without even the implied warranty of//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the//  GNU General Public License for more details.///////////////////////////////////////////////////////////////////////////////////#ifndef LM_REAL // not included by misc.c#error This file should not be compiled directly!#endif/* precision-specific definitions */#define LEVMAR_CHKJAC LM_ADD_PREFIX(levmar_chkjac)#define FDIF_FORW_JAC_APPROX LM_ADD_PREFIX(fdif_forw_jac_approx)#define FDIF_CENT_JAC_APPROX LM_ADD_PREFIX(fdif_cent_jac_approx)#define TRANS_MAT_MAT_MULT LM_ADD_PREFIX(trans_mat_mat_mult)#define LEVMAR_COVAR LM_ADD_PREFIX(levmar_covar)#ifdef HAVE_LAPACK#define LEVMAR_PSEUDOINVERSE LM_ADD_PREFIX(levmar_pseudoinverse)static int LEVMAR_PSEUDOINVERSE(LM_REAL *A, LM_REAL *B, int m);/* BLAS matrix multiplication & LAPACK SVD routines */#define GEMM LM_CAT_(LM_BLAS_PREFIX, LM_ADD_PREFIX(gemm_))/* C := alpha*op( A )*op( B ) + beta*C */extern void GEMM(char *transa, char *transb, int *m, int *n, int *k,          LM_REAL *alpha, LM_REAL *a, int *lda, LM_REAL *b, int *ldb, LM_REAL *beta, LM_REAL *c, int *ldc);#define GESVD LM_ADD_PREFIX(gesvd_)#define GESDD LM_ADD_PREFIX(gesdd_)extern int GESVD(char *jobu, char *jobvt, int *m, int *n, LM_REAL *a, int *lda, LM_REAL *s, LM_REAL *u, int *ldu,                 LM_REAL *vt, int *ldvt, LM_REAL *work, int *lwork, int *info);/* lapack 3.0 new SVD routine, faster than xgesvd() */extern int GESDD(char *jobz, int *m, int *n, LM_REAL *a, int *lda, LM_REAL *s, LM_REAL *u, int *ldu, LM_REAL *vt, int *ldvt,                 LM_REAL *work, int *lwork, int *iwork, int *info);#else#define LEVMAR_LUINVERSE LM_ADD_PREFIX(levmar_LUinverse_noLapack)static int LEVMAR_LUINVERSE(LM_REAL *A, LM_REAL *B, int m);#endif /* HAVE_LAPACK *//* blocked multiplication of the transpose of the nxm matrix a with itself (i.e. a^T a) * using a block size of bsize. The product is returned in b. * Since a^T a is symmetric, its computation can be speeded up by computing only its * upper triangular part and copying it to the lower part. * * More details on blocking can be found at  * http://www-2.cs.cmu.edu/afs/cs/academic/class/15213-f02/www/R07/section_a/Recitation07-SectionA.pdf */void TRANS_MAT_MAT_MULT(LM_REAL *a, LM_REAL *b, int n, int m){#ifdef HAVE_LAPACK /* use BLAS matrix multiply */LM_REAL alpha=CNST(1.0), beta=CNST(0.0);  /* Fool BLAS to compute a^T*a avoiding transposing a: a is equivalent to a^T in column major,   * therefore BLAS computes a*a^T with a and a*a^T in column major, which is equivalent to   * computing a^T*a in row major!   */  GEMM("N", "T", &m, &m, &n, &alpha, a, &m, a, &m, &beta, b, &m);#else /* no LAPACK, use blocking-based multiply */register int i, j, k, jj, kk;register LM_REAL sum, *bim, *akm;const int bsize=__BLOCKSZ__;#define __MIN__(x, y) (((x)<=(y))? (x) : (y))#define __MAX__(x, y) (((x)>=(y))? (x) : (y))  /* compute upper triangular part using blocking */  for(jj=0; jj<m; jj+=bsize){    for(i=0; i<m; ++i){      bim=b+i*m;      for(j=__MAX__(jj, i); j<__MIN__(jj+bsize, m); ++j)        bim[j]=0.0; //b[i*m+j]=0.0;    }    for(kk=0; kk<n; kk+=bsize){      for(i=0; i<m; ++i){        bim=b+i*m;        for(j=__MAX__(jj, i); j<__MIN__(jj+bsize, m); ++j){          sum=0.0;          for(k=kk; k<__MIN__(kk+bsize, n); ++k){            akm=a+k*m;            sum+=akm[i]*akm[j]; //a[k*m+i]*a[k*m+j];          }          bim[j]+=sum; //b[i*m+j]+=sum;        }      }    }  }  /* copy upper triangular part to the lower one */  for(i=0; i<m; ++i)    for(j=0; j<i; ++j)      b[i*m+j]=b[j*m+i];#undef __MIN__#undef __MAX__#endif /* HAVE_LAPACK */}/* forward finite difference approximation to the jacobian of func */void FDIF_FORW_JAC_APPROX(    void (*func)(LM_REAL *p, LM_REAL *hx, int m, int n, void *adata),													   /* function to differentiate */    LM_REAL *p,              /* I: current parameter estimate, mx1 */    LM_REAL *hx,             /* I: func evaluated at p, i.e. hx=func(p), nx1 */    LM_REAL *hxx,            /* W/O: work array for evaluating func(p+delta), nx1 */    LM_REAL delta,           /* increment for computing the jacobian */    LM_REAL *jac,            /* O: array for storing approximated jacobian, nxm */    int m,    int n,    void *adata){register int i, j;LM_REAL tmp;register LM_REAL d;  for(j=0; j<m; ++j){    /* determine d=max(1E-04*|p[j]|, delta), see HZ */    d=CNST(1E-04)*p[j]; // force evaluation    d=FABS(d);    if(d<delta)      d=delta;    tmp=p[j];    p[j]+=d;    (*func)(p, hxx, m, n, adata);    p[j]=tmp; /* restore */    d=CNST(1.0)/d; /* invert so that divisions can be carried out faster as multiplications */    for(i=0; i<n; ++i){      jac[i*m+j]=(hxx[i]-hx[i])*d;    }  }}/* central finite difference approximation to the jacobian of func */void FDIF_CENT_JAC_APPROX(    void (*func)(LM_REAL *p, LM_REAL *hx, int m, int n, void *adata),													   /* function to differentiate */    LM_REAL *p,              /* I: current parameter estimate, mx1 */    LM_REAL *hxm,            /* W/O: work array for evaluating func(p-delta), nx1 */    LM_REAL *hxp,            /* W/O: work array for evaluating func(p+delta), nx1 */    LM_REAL delta,           /* increment for computing the jacobian */    LM_REAL *jac,            /* O: array for storing approximated jacobian, nxm */    int m,    int n,    void *adata){register int i, j;LM_REAL tmp;register LM_REAL d;  for(j=0; j<m; ++j){    /* determine d=max(1E-04*|p[j]|, delta), see HZ */    d=CNST(1E-04)*p[j]; // force evaluation    d=FABS(d);    if(d<delta)      d=delta;    tmp=p[j];    p[j]-=d;    (*func)(p, hxm, m, n, adata);    p[j]=tmp+d;    (*func)(p, hxp, m, n, adata);    p[j]=tmp; /* restore */    d=CNST(0.5)/d; /* invert so that divisions can be carried out faster as multiplications */    for(i=0; i<n; ++i){      jac[i*m+j]=(hxp[i]-hxm[i])*d;    }  }}/*  * Check the jacobian of a n-valued nonlinear function in m variables * evaluated at a point p, for consistency with the function itself. * * Based on fortran77 subroutine CHKDER by * Burton S. Garbow, Kenneth E. Hillstrom, Jorge J. More * Argonne National Laboratory. MINPACK project. March 1980. * * * func points to a function from R^m --> R^n: Given a p in R^m it yields hx in R^n * jacf points to a function implementing the jacobian of func, whose correctness *     is to be tested. Given a p in R^m, jacf computes into the nxm matrix j the *     jacobian of func at p. Note that row i of j corresponds to the gradient of *     the i-th component of func, evaluated at p. * p is an input array of length m containing the point of evaluation. * m is the number of variables * n is the number of functions * adata points to possible additional data and is passed uninterpreted *     to func, jacf. * err is an array of length n. On output, err contains measures *     of correctness of the respective gradients. if there is *     no severe loss of significance, then if err[i] is 1.0 the *     i-th gradient is correct, while if err[i] is 0.0 the i-th *     gradient is incorrect. For values of err between 0.0 and 1.0, *     the categorization is less certain. In general, a value of *     err[i] greater than 0.5 indicates that the i-th gradient is *     probably correct, while a value of err[i] less than 0.5 *     indicates that the i-th gradient is probably incorrect. * * * The function does not perform reliably if cancellation or * rounding errors cause a severe loss of significance in the * evaluation of a function. therefore, none of the components * of p should be unusually small (in particular, zero) or any * other value which may cause loss of significance. */void LEVMAR_CHKJAC(    void (*func)(LM_REAL *p, LM_REAL *hx, int m, int n, void *adata),    void (*jacf)(LM_REAL *p, LM_REAL *j, int m, int n, void *adata),    LM_REAL *p, int m, int n, void *adata, LM_REAL *err){LM_REAL factor=CNST(100.0);LM_REAL one=CNST(1.0);LM_REAL zero=CNST(0.0);LM_REAL *fvec, *fjac, *pp, *fvecp, *buf;register int i, j;LM_REAL eps, epsf, temp, epsmch;LM_REAL epslog;int fvec_sz=n, fjac_sz=n*m, pp_sz=m, fvecp_sz=n;  epsmch=LM_REAL_EPSILON;  eps=(LM_REAL)sqrt(epsmch);  buf=(LM_REAL *)malloc((fvec_sz + fjac_sz + pp_sz + fvecp_sz)*sizeof(LM_REAL));  if(!buf){    fprintf(stderr, LCAT(LEVMAR_CHKJAC, "(): memory allocation request failed\n"));    exit(1);  }  fvec=buf;  fjac=fvec+fvec_sz;  pp=fjac+fjac_sz;  fvecp=pp+pp_sz;  /* compute fvec=func(p) */  (*func)(p, fvec, m, n, adata);  /* compute the jacobian at p */  (*jacf)(p, fjac, m, n, adata);  /* compute pp */  for(j=0; j<m; ++j){    temp=eps*FABS(p[j]);    if(temp==zero) temp=eps;    pp[j]=p[j]+temp;  }  /* compute fvecp=func(pp) */  (*func)(pp, fvecp, m, n, adata);  epsf=factor*epsmch;  epslog=(LM_REAL)log10(eps);  for(i=0; i<n; ++i)    err[i]=zero;  for(j=0; j<m; ++j){    temp=FABS(p[j]);    if(temp==zero) temp=one;    for(i=0; i<n; ++i)      err[i]+=temp*fjac[i*m+j];  }  for(i=0; i<n; ++i){    temp=one;    if(fvec[i]!=zero && fvecp[i]!=zero && FABS(fvecp[i]-fvec[i])>=epsf*FABS(fvec[i]))

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -