void mrqmin(double *x, double *y, double *sig, int ndata, double *a, int *ia, int ma, double **covar, double **alpha, double *chisq, double *alamda, void (*funcs)(double *, double *, double *, double **, int, int, int, double *, double **, double *, double *, int *, void *), int Nlin_coeff, double **Design_Matrix, double *lin_coeffs, int *varylin_coeffs, #ifdef PARALLEL int mfit, double *ochisq, double *atry, double *beta, double *da, double **oneda, #endif void *userparams) { /*This function is taken from Press et al., 1992 - Levenberg-Marquardt method, attempting to reduce the value of chi^2 of a fit between a set of data points x[0....ndata-1], y[0.....ndata-1] with individual standard deviations sig[0.....ndata-1], and a nonlinear function dependent on ma coefficients a[0...ma-1]. The input array ia[0....ma-1] indicates by nonzero entries those components of a that should be fitted for, and by zero entries, those components that should be held fixed at their input values. The program returns current best-fit values for the parameters a[0...ma-1], and chi^2. The arrays covar[0...ma-1][0...ma-1], alpha[0....ma-1][0....ma-1] are used as working space during most iterations. Supply a routine funcs(x,a,yfit,dyda,ma) that evaluates the fitting fuction yfit, and its derivatives dyda[0....ma-1] with respect to the fitting parameters a at x. On the first call provide an initial guess for the parameters a, and set alamda<0 for initialization (which then sets alamda=0.001). If a step succeeds chisq becomes smaller and alamda decreases by a factor of 10. If a step fails alamda grows by a factor of 10. You must call this routine repeatedly until convergence is achieved. Then make one final call with alamda=0, so that covar[0....ma-1][0....ma-1] returns the covariance matrix, and alpha the curvature matrix. (Parameters help fixed will return zero covariances). */ void covsrt(double **covar, int ma, int *ia, int mfit); int gaussj(double **a, int n, double **b, int m); void mrqcof(double *x, double *y, double *sig, int ndata, double *a, int *ia, int ma, double **alpha, double *beta, double *chisq, void (*funcs)(double *, double *, double *, double **, int, int, int, double *, double **, double *, double *, int *, void *), int, double **, double *, int *, void *); int j, k, l; #ifndef PARALLEL static int mfit; static double ochisq[1], *atry, *beta, *da, **oneda; #endif if(*alamda < 0.0) { #ifndef PARALLEL if((atry = (double *) malloc(ma * sizeof(double))) == NULL || (beta = (double *) malloc(ma * sizeof(double))) == NULL || (da = (double *) malloc(ma * sizeof(double))) == NULL) error(ERR_MEMALLOC); for(mfit=0,j=0;j<ma;j++) if(ia[j]) mfit++; if((oneda = (double **) malloc(mfit * sizeof(double *))) == NULL) error(ERR_MEMALLOC); for(j=0;j<mfit;j++) if((oneda[j] = (double *) malloc(sizeof(double))) == NULL) error(ERR_MEMALLOC); #endif *alamda = 0.001; mrqcof(x,y,sig,ndata,a,ia,ma,alpha,beta,chisq,funcs, Nlin_coeff, Design_Matrix, lin_coeffs, varylin_coeffs, userparams); ochisq[0]=(*chisq); for(j=0;j<ma;j++) atry[j] = a[j]; } for(j=0;j<mfit;j++) { for(k=0;k<mfit;k++) covar[j][k] = alpha[j][k]; covar[j][j]=alpha[j][j]*(1.0+(*alamda)); oneda[j][0] = beta[j]; } if(gaussj(covar,mfit,oneda,1)) { *alamda = 0; } for(j=0;j<mfit;j++) da[j] = oneda[j][0]; if (*alamda == 0.0) { covsrt(covar,ma,ia,mfit); covsrt(alpha,ma,ia,mfit); #ifndef PARALLEL for(j=0;j<mfit;j++) free(oneda[j]); free(oneda); free(da); free(beta); free(atry); #endif return; } for(j=0,l=0;l<ma;l++) if(ia[l]) atry[l]=a[l]+da[j++]; mrqcof(x,y,sig,ndata,atry,ia,ma,covar,da,chisq,funcs,Nlin_coeff,Design_Matrix,lin_coeffs,varylin_coeffs, userparams); if (*chisq < ochisq[0]) { *alamda *= 0.1; ochisq[0] = (*chisq); for (j=0;j<mfit;j++) { for(k=0;k<mfit;k++) alpha[j][k] = covar[j][k]; beta[j] = da[j]; } for(l=0;l<ma;l++) a[l]=atry[l]; } else { *alamda *= 10.0; *chisq=ochisq[0]; } }
//----------------------------------------------------------------------- void TLMFit::mrqmin() { static vector < double> atry, beta, da; int j, k, l; static int mfit; static double ochisq; static vector< vector < double> > oneda; if (alamda < 0.0) { atry.resize(nparam); beta.resize(nparam); da.resize(nparam); for (mfit = 0, j = 0; j < nparam; j++) if (ia[j]) mfit++; oneda.resize(mfit); for (unsigned int i = 0; i < oneda.size(); i++) oneda[i].resize(1); alamda = 0.001; mrqcof(a, alpha, beta); ochisq = (chisq); for (j = 0; j < nparam; j++) atry[j] =(a[j]); } for (j = 0; j < mfit; j++) { for (k = 0; k < mfit; k++) covar[j][k] = alpha[j][k]; covar[j][j] = alpha[j][j]*(1.0 + (alamda)); oneda[j][0] = beta[j]; } try {gaussj(covar, mfit, oneda, 1);} catch (ESingularMatrix &E) { throw; } for (j = 0; j < mfit; j++) { da[j] = oneda[j][0]; } if (alamda == 0.0) { covsrt(mfit); return; } for (j = 0, l = 0; l < nparam; l++) if (ia[l]) atry[l] = a[l] + da[j++]; mrqcof(atry, covar, da); if (chisq < ochisq) { alamda *= 0.1; ochisq = (chisq); for (j = 0; j < mfit; j++) { for (k = 0; k < mfit; k++) alpha[j][k] = covar[j][k]; beta[j] = da[j]; } for (j = 0; j < nparam; j++) // Achtung!! in aelteren Versionen war hier ein Fehler a[j] = atry[j]; } else { alamda *= 10.0; chisq = ochisq; } }
gmx_bool mrqmin(real x[], real y[], real sig[], int ndata, real a[], int ma, int lista[], int mfit, real **covar, real **alpha, real *chisq, void (*funcs)(real, real *, real *, real *), real *alamda) { int k, kk, j, ihit; static real *da, *atry, **oneda, *beta, ochisq; if (*alamda < 0.0) { oneda = matrix1(1, mfit, 1, 1); atry = rvector(1, ma); da = rvector(1, ma); beta = rvector(1, ma); kk = mfit+1; for (j = 1; j <= ma; j++) { ihit = 0; for (k = 1; k <= mfit; k++) { if (lista[k] == j) { ihit++; } } if (ihit == 0) { lista[kk++] = j; } else if (ihit > 1) { nrerror("Bad LISTA permutation in MRQMIN-1", FALSE); return FALSE; } } if (kk != ma+1) { nrerror("Bad LISTA permutation in MRQMIN-2", FALSE); return FALSE; } *alamda = 0.001; mrqcof(x, y, sig, ndata, a, ma, lista, mfit, alpha, beta, chisq, funcs); ochisq = (*chisq); } for (j = 1; j <= mfit; j++) { for (k = 1; k <= mfit; k++) { covar[j][k] = alpha[j][k]; } covar[j][j] = alpha[j][j]*(1.0+(*alamda)); oneda[j][1] = beta[j]; } if (!gaussj(covar, mfit, oneda, 1)) { return FALSE; } for (j = 1; j <= mfit; j++) { da[j] = oneda[j][1]; } if (*alamda == 0.0) { covsrt(covar, ma, lista, mfit); free_vector(beta, 1); free_vector(da, 1); free_vector(atry, 1); free_matrix(oneda, 1, mfit, 1); return TRUE; } for (j = 1; j <= ma; j++) { atry[j] = a[j]; } for (j = 1; j <= mfit; j++) { atry[lista[j]] = a[lista[j]]+da[j]; } mrqcof(x, y, sig, ndata, atry, ma, lista, mfit, covar, da, chisq, funcs); if (*chisq < ochisq) { *alamda *= 0.1; ochisq = (*chisq); for (j = 1; j <= mfit; j++) { for (k = 1; k <= mfit; k++) { alpha[j][k] = covar[j][k]; } beta[j] = da[j]; a[lista[j]] = atry[lista[j]]; } } else { *alamda *= 10.0; *chisq = ochisq; } return TRUE; }
void mrqmin(float x[], float y[], float sig[], int ndata, float a[], int ia[], int ma, float **covar, float **alpha, float *chisq, void (*funcs)(float, float [], float *, float [], int), float *alamda) { void covsrt(float **covar, int ma, int ia[], int mfit); void gaussj(float **a, int n, float **b, int m); void mrqcof(float x[], float y[], float sig[], int ndata, float a[], int ia[], int ma, float **alpha, float beta[], float *chisq, void (*funcs)(float, float [], float *, float [], int)); int j,k,l,m; static int mfit; static float ochisq,*atry,*beta,*da,**oneda; if (*alamda < 0.0) { atry=vector(1,ma); beta=vector(1,ma); da=vector(1,ma); for (mfit=0,j=1;j<=ma;j++) if (ia[j]) mfit++; oneda=matrix(1,mfit,1,1); *alamda=0.001; mrqcof(x,y,sig,ndata,a,ia,ma,alpha,beta,chisq,funcs); ochisq=(*chisq); for (j=1;j<=ma;j++) atry[j]=a[j]; } for (j=0,l=1;l<=ma;l++) { if (ia[l]) { for (j++,k=0,m=1;m<=ma;m++) { if (ia[m]) { k++; covar[j][k]=alpha[j][k]; } } covar[j][j]=alpha[j][j]*(1.0+(*alamda)); oneda[j][1]=beta[j]; } } gaussj(covar,mfit,oneda,1); for (j=1;j<=mfit;j++) da[j]=oneda[j][1]; if (*alamda == 0.0) { covsrt(covar,ma,ia,mfit); free_matrix(oneda,1,mfit,1,1); free_vector(da,1,ma); free_vector(beta,1,ma); free_vector(atry,1,ma); return; } for (j=0,l=1;l<=ma;l++) if (ia[l]) atry[l]=a[l]+da[++j]; mrqcof(x,y,sig,ndata,atry,ia,ma,covar,da,chisq,funcs); if (*chisq < ochisq) { *alamda *= 0.1; ochisq=(*chisq); for (j=0,l=1;l<=ma;l++) { if (ia[l]) { for (j++,k=0,m=1;m<=ma;m++) { if (ia[m]) { k++; alpha[j][k]=covar[j][k]; } } beta[j]=da[j]; a[l]=atry[l]; } } } else { *alamda *= 10.0; *chisq=ochisq; } }
int mrqmin(float **y, float **sig, struct image *psf, int ma, double **covar, double **alpha, double *chisq, void (*funcs)(int, int, float *, float [], int [], int, struct fitpars *), float *alamda, struct fitpars *fpar, struct cons *constr, struct convpars *cpar, double *sigma) { void errcalc (double *sigma, double **alpha, int ma, int *ia, int mfit); int j,k,l; static int mfit; static double *da,**oneda,*beta,ochisq; static float *atry, *aorig; float *a; int *ia; /* Kludge -- copy from fpar->a to a */ a = vector (1, ma); ia = ivector (1, ma); copy_pars (a, ia, fpar, FROM); if (*alamda < 0.0) { aorig=vector(1,ma); copy_pars (aorig, ia, fpar, FROM); atry=vector(1,ma); beta=dvector(1,ma); da=dvector(1,ma); for (mfit=0,j=1;j<=ma;j++) if (ia[j]==1) mfit++; oneda=dmatrix(1,mfit,1,1); *alamda=0.01; mrqcof(y,sig,psf,a,ia,ma,alpha,beta,chisq,funcs,fpar,cpar); ochisq=(*chisq); for (j=1;j<=ma;j++) atry[j]=a[j]; } for (j=1;j<=mfit;j++) { for (k=1;k<=mfit;k++) covar[j][k]=alpha[j][k]; covar[j][j]=alpha[j][j]*(1.0+(*alamda)); oneda[j][1]=beta[j]; } gaussj(covar,mfit,oneda,1); for (j=1;j<=mfit;j++) da[j]=oneda[j][1]; if (*alamda == 0.0) { /* Convergence! */ errcalc (sigma, alpha, ma, ia, mfit); /* calculate uncert. */ covsrt(covar,ma,ia,mfit); covsrt(alpha,ma,ia,mfit); free_dmatrix(oneda,1,mfit,1,1); free_dvector(da,1,ma); free_dvector(beta,1,ma); free_vector(atry,1,ma); free_vector (a, 1, ma); free_ivector (ia, 1, ma); return; } par_monitor (ma, a, ia, atry, da, fpar); constraints (ma, mfit, atry, a, ia, constr, da, aorig); copy_pars (atry, ia, fpar, TO); mrqcof(y,sig,psf,atry,ia,ma,covar,da,chisq,funcs,fpar,cpar); if (*chisq < ochisq) { *alamda *= 0.1; ochisq=(*chisq); for (j=1;j<=mfit;j++) { for (k=1;k<=mfit;k++) alpha[j][k]=covar[j][k]; beta[j]=da[j]; } for (l=1;l<=ma;l++) a[l]=atry[l]; } else { *alamda *= 10.0; *chisq=ochisq; } copy_pars (a, ia, fpar, TO); free_vector (a, 1, ma); free_ivector (ia, 1, ma); return (0); }