2 * $Id: levenmar.c,v 1.20 2004/01/23 18:11:02 lindahl Exp $
4 * This source code is part of
8 * GROningen MAchine for Chemical Simulations
11 * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
12 * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
13 * Copyright (c) 2001-2004, The GROMACS development team,
14 * check out http://www.gromacs.org for more information.
16 * This program is free software; you can redistribute it and/or
17 * modify it under the terms of the GNU General Public License
18 * as published by the Free Software Foundation; either version 2
19 * of the License, or (at your option) any later version.
21 * If you want to redistribute modifications, please consider that
22 * scientific software is very special. Version control is crucial -
23 * bugs must be traceable. We will be happy to consider code for
24 * inclusion in the official distribution, but derived work must not
25 * be called official GROMACS. Details are found in the README & COPYING
26 * files - if they are missing, get the official version at www.gromacs.org.
28 * To help us fund GROMACS development, we humbly ask that you cite
29 * the papers on the package - you can find them in the top README file.
31 * For more info, check our website at http://www.gromacs.org
34 * Green Red Orange Magenta Azure Cyan Skyblue
44 #include "types/simple.h"
46 static void nrerror(const char error_text
[], gmx_bool bExit
)
48 fprintf(stderr
,"Numerical Recipes run-time error...\n");
49 fprintf(stderr
,"%s\n",error_text
);
51 fprintf(stderr
,"...now exiting to system...\n");
56 /* dont use the keyword vector - it will clash with the
57 * altivec extensions used for powerpc processors.
60 static real
*rvector(int nl
,int nh
)
64 v
=(real
*)malloc((unsigned) (nh
-nl
+1)*sizeof(real
));
65 if (!v
) nrerror("allocation failure in rvector()", TRUE
);
69 static int *ivector(int nl
, int nh
)
73 v
=(int *)malloc((unsigned) (nh
-nl
+1)*sizeof(int));
74 if (!v
) nrerror("allocation failure in ivector()", TRUE
);
78 static double *dvector(int nl
, int nh
)
82 v
=(double *)malloc((unsigned) (nh
-nl
+1)*sizeof(double));
83 if (!v
) nrerror("allocation failure in dvector()", TRUE
);
89 static real
**matrix1(int nrl
, int nrh
, int ncl
, int nch
)
94 m
=(real
**) malloc((unsigned) (nrh
-nrl
+1)*sizeof(real
*));
95 if (!m
) nrerror("allocation failure 1 in matrix1()", TRUE
);
98 for(i
=nrl
;i
<=nrh
;i
++) {
99 m
[i
]=(real
*) malloc((unsigned) (nch
-ncl
+1)*sizeof(real
));
100 if (!m
[i
]) nrerror("allocation failure 2 in matrix1()", TRUE
);
106 static double **dmatrix(int nrl
, int nrh
, int ncl
, int nch
)
111 m
=(double **) malloc((unsigned) (nrh
-nrl
+1)*sizeof(double*));
112 if (!m
) nrerror("allocation failure 1 in dmatrix()", TRUE
);
115 for(i
=nrl
;i
<=nrh
;i
++) {
116 m
[i
]=(double *) malloc((unsigned) (nch
-ncl
+1)*sizeof(double));
117 if (!m
[i
]) nrerror("allocation failure 2 in dmatrix()", TRUE
);
123 static int **imatrix1(int nrl
, int nrh
, int ncl
, int nch
)
127 m
=(int **)malloc((unsigned) (nrh
-nrl
+1)*sizeof(int*));
128 if (!m
) nrerror("allocation failure 1 in imatrix1()", TRUE
);
131 for(i
=nrl
;i
<=nrh
;i
++) {
132 m
[i
]=(int *)malloc((unsigned) (nch
-ncl
+1)*sizeof(int));
133 if (!m
[i
]) nrerror("allocation failure 2 in imatrix1()", TRUE
);
141 static real
**submatrix(real
**a
, int oldrl
, int oldrh
, int oldcl
,
142 int newrl
, int newcl
)
147 m
=(real
**) malloc((unsigned) (oldrh
-oldrl
+1)*sizeof(real
*));
148 if (!m
) nrerror("allocation failure in submatrix()", TRUE
);
151 for(i
=oldrl
,j
=newrl
;i
<=oldrh
;i
++,j
++) m
[j
]=a
[i
]+oldcl
-newcl
;
158 static void free_vector(real
*v
, int nl
)
160 free((char*) (v
+nl
));
163 static void free_ivector(int *v
, int nl
)
165 free((char*) (v
+nl
));
168 static void free_dvector(int *v
, int nl
)
170 free((char*) (v
+nl
));
175 static void free_matrix(real
**m
, int nrl
, int nrh
, int ncl
)
179 for(i
=nrh
;i
>=nrl
;i
--) free((char*) (m
[i
]+ncl
));
180 free((char*) (m
+nrl
));
183 static void free_dmatrix(double **m
, int nrl
, int nrh
, int ncl
)
187 for(i
=nrh
;i
>=nrl
;i
--) free((char*) (m
[i
]+ncl
));
188 free((char*) (m
+nrl
));
191 static void free_imatrix(int **m
, int nrl
, int nrh
, int ncl
)
195 for(i
=nrh
;i
>=nrl
;i
--) free((char*) (m
[i
]+ncl
));
196 free((char*) (m
+nrl
));
201 static void free_submatrix(real
**b
, int nrl
)
203 free((char*) (b
+nrl
));
208 static real
**convert_matrix(real
*a
, int nrl
, int nrh
, int ncl
, int nch
)
215 m
= (real
**) malloc((unsigned) (nrow
)*sizeof(real
*));
216 if (!m
) nrerror("allocation failure in convert_matrix()", TRUE
);
218 for(i
=0,j
=nrl
;i
<=nrow
-1;i
++,j
++) m
[j
]=a
+ncol
*i
-ncl
;
224 static void free_convert_matrix(real
**b
, int nrl
)
226 free((char*) (b
+nrl
));
229 #define SWAP(a,b) {real temp=(a);(a)=(b);(b)=temp;}
231 static void dump_mat(int n
,real
**a
)
235 for(i
=1; (i
<=n
); i
++) {
236 for(j
=1; (j
<=n
); j
++)
237 fprintf(stderr
," %10.3f",a
[i
][j
]);
238 fprintf(stderr
,"\n");
242 gmx_bool
gaussj(real
**a
, int n
, real
**b
, int m
)
244 int *indxc
,*indxr
,*ipiv
;
245 int i
,icol
=0,irow
=0,j
,k
,l
,ll
;
251 for (j
=1;j
<=n
;j
++) ipiv
[j
]=0;
258 if (fabs(a
[j
][k
]) >= big
) {
263 } else if (ipiv
[k
] > 1) {
264 nrerror("GAUSSJ: Singular Matrix-1", FALSE
);
270 for (l
=1;l
<=n
;l
++) SWAP(a
[irow
][l
],a
[icol
][l
])
271 for (l
=1;l
<=m
;l
++) SWAP(b
[irow
][l
],b
[icol
][l
])
275 if (a
[icol
][icol
] == 0.0) {
276 fprintf(stderr
,"irow = %d, icol = %d\n",irow
,icol
);
278 nrerror("GAUSSJ: Singular Matrix-2", FALSE
);
281 pivinv
=1.0/a
[icol
][icol
];
283 for (l
=1;l
<=n
;l
++) a
[icol
][l
] *= pivinv
;
284 for (l
=1;l
<=m
;l
++) b
[icol
][l
] *= pivinv
;
285 for (ll
=1;ll
<=n
;ll
++)
289 for (l
=1;l
<=n
;l
++) a
[ll
][l
] -= a
[icol
][l
]*dum
;
290 for (l
=1;l
<=m
;l
++) b
[ll
][l
] -= b
[icol
][l
]*dum
;
294 if (indxr
[l
] != indxc
[l
])
296 SWAP(a
[k
][indxr
[l
]],a
[k
][indxc
[l
]]);
298 free_ivector(ipiv
,1);
299 free_ivector(indxr
,1);
300 free_ivector(indxc
,1);
308 static void covsrt(real
**covar
, int ma
, int lista
[], int mfit
)
314 for (i
=j
+1;i
<=ma
;i
++) covar
[i
][j
]=0.0;
316 for (j
=i
+1;j
<=mfit
;j
++) {
317 if (lista
[j
] > lista
[i
])
318 covar
[lista
[j
]][lista
[i
]]=covar
[i
][j
];
320 covar
[lista
[i
]][lista
[j
]]=covar
[i
][j
];
323 for (j
=1;j
<=ma
;j
++) {
324 covar
[1][j
]=covar
[j
][j
];
327 covar
[lista
[1]][lista
[1]]=swap
;
328 for (j
=2;j
<=mfit
;j
++) covar
[lista
[j
]][lista
[j
]]=covar
[1][j
];
330 for (i
=1;i
<=j
-1;i
++) covar
[i
][j
]=covar
[j
][i
];
333 #define SWAP(a,b) {swap=(a);(a)=(b);(b)=swap;}
335 static void covsrt_new(real
**covar
,int ma
, int ia
[], int mfit
)
336 /* Expand in storage the covariance matrix covar, so as to take
337 * into account parameters that are being held fixed. (For the
338 * latter, return zero covariances.)
343 for (i
=mfit
+1;i
<=ma
;i
++)
344 for (j
=1;j
<=i
;j
++) covar
[i
][j
]=covar
[j
][i
]=0.0;
346 for (j
=ma
;j
>=1;j
--) {
348 for (i
=1;i
<=ma
;i
++) SWAP(covar
[i
][k
],covar
[i
][j
])
349 for (i
=1;i
<=ma
;i
++) SWAP(covar
[k
][i
],covar
[j
][i
])
356 static void mrqcof(real x
[], real y
[], real sig
[], int ndata
, real a
[],
357 int ma
, int lista
[], int mfit
,
358 real
**alpha
, real beta
[], real
*chisq
,
359 void (*funcs
)(real
,real
*,real
*,real
*))
362 real ymod
,wt
,sig2i
,dy
,*dyda
;
365 for (j
=1;j
<=mfit
;j
++) {
366 for (k
=1;k
<=j
;k
++) alpha
[j
][k
]=0.0;
370 for (i
=1;i
<=ndata
;i
++) {
371 (*funcs
)(x
[i
],a
,&ymod
,dyda
);
372 sig2i
=1.0/(sig
[i
]*sig
[i
]);
374 for (j
=1;j
<=mfit
;j
++) {
375 wt
=dyda
[lista
[j
]]*sig2i
;
377 alpha
[j
][k
] += wt
*dyda
[lista
[k
]];
380 (*chisq
) += dy
*dy
*sig2i
;
382 for (j
=2;j
<=mfit
;j
++)
383 for (k
=1;k
<=j
-1;k
++) alpha
[k
][j
]=alpha
[j
][k
];
388 gmx_bool
mrqmin(real x
[], real y
[], real sig
[], int ndata
, real a
[],
389 int ma
, int lista
[], int mfit
,
390 real
**covar
, real
**alpha
, real
*chisq
,
391 void (*funcs
)(real
,real
*,real
*,real
*),
395 static real
*da
,*atry
,**oneda
,*beta
,ochisq
;
398 oneda
=matrix1(1,mfit
,1,1);
403 for (j
=1;j
<=ma
;j
++) {
405 for (k
=1;k
<=mfit
;k
++)
406 if (lista
[k
] == j
) ihit
++;
410 nrerror("Bad LISTA permutation in MRQMIN-1", FALSE
);
415 nrerror("Bad LISTA permutation in MRQMIN-2", FALSE
);
419 mrqcof(x
,y
,sig
,ndata
,a
,ma
,lista
,mfit
,alpha
,beta
,chisq
,funcs
);
422 for (j
=1;j
<=mfit
;j
++) {
423 for (k
=1;k
<=mfit
;k
++) covar
[j
][k
]=alpha
[j
][k
];
424 covar
[j
][j
]=alpha
[j
][j
]*(1.0+(*alamda
));
427 if (!gaussj(covar
,mfit
,oneda
,1))
429 for (j
=1;j
<=mfit
;j
++)
431 if (*alamda
== 0.0) {
432 covsrt(covar
,ma
,lista
,mfit
);
436 free_matrix(oneda
,1,mfit
,1);
439 for (j
=1;j
<=ma
;j
++) atry
[j
]=a
[j
];
440 for (j
=1;j
<=mfit
;j
++)
441 atry
[lista
[j
]] = a
[lista
[j
]]+da
[j
];
442 mrqcof(x
,y
,sig
,ndata
,atry
,ma
,lista
,mfit
,covar
,da
,chisq
,funcs
);
443 if (*chisq
< ochisq
) {
446 for (j
=1;j
<=mfit
;j
++) {
447 for (k
=1;k
<=mfit
;k
++) alpha
[j
][k
]=covar
[j
][k
];
449 a
[lista
[j
]]=atry
[lista
[j
]];
459 gmx_bool
mrqmin_new(real x
[],real y
[],real sig
[],int ndata
,real a
[],
460 int ia
[],int ma
,real
**covar
,real
**alpha
,real
*chisq
,
461 void (*funcs
)(real
, real
[], real
*, real
[]),
463 /* Levenberg-Marquardt method, attempting to reduce the value Chi^2
464 * of a fit between a set of data points x[1..ndata], y[1..ndata]
465 * with individual standard deviations sig[1..ndata], and a nonlinear
466 * function dependent on ma coefficients a[1..ma]. The input array
467 * ia[1..ma] indicates by nonzero entries those components of a that
468 * should be fitted for, and by zero entries those components that
469 * should be held fixed at their input values. The program returns
470 * current best-fit values for the parameters a[1..ma], and
471 * Chi^2 = chisq. The arrays covar[1..ma][1..ma], alpha[1..ma][1..ma]
472 * are used as working space during most iterations. Supply a routine
473 * funcs(x,a,yfit,dyda,ma) that evaluates the fitting function yfit,
474 * and its derivatives dyda[1..ma] with respect to the fitting
475 * parameters a at x. On the first call provide an initial guess for
476 * the parameters a, and set alamda < 0 for initialization (which then
477 * sets alamda=.001). If a step succeeds chisq becomes smaller and
478 * alamda de-creases by a factor of 10. If a step fails alamda grows by
479 * a factor of 10. You must call this routine repeatedly until
480 * convergence is achieved. Then, make one final call with alamda=0,
481 * so that covar[1..ma][1..ma] returns the covariance matrix, and alpha
482 * the curvature matrix.
483 * (Parameters held fixed will return zero covariances.)
486 void covsrt(real
**covar
, int ma
, int ia
[], int mfit
);
487 gmx_bool
gaussj(real
**a
, int n
, real
**b
,int m
);
488 void mrqcof_new(real x
[], real y
[], real sig
[], int ndata
, real a
[],
489 int ia
[], int ma
, real
**alpha
, real beta
[], real
*chisq
,
490 void (*funcs
)(real
, real
[], real
*, real
[]));
493 static real ochisq
,*atry
,*beta
,*da
,**oneda
;
495 if (*alamda
< 0.0) { /* Initialization. */
499 for (mfit
=0,j
=1;j
<=ma
;j
++)
501 oneda
=matrix1(1,mfit
,1,1);
503 mrqcof_new(x
,y
,sig
,ndata
,a
,ia
,ma
,alpha
,beta
,chisq
,funcs
);
508 for (j
=1;j
<=mfit
;j
++) { /* Alter linearized fitting matrix, by augmenting. */
509 for (k
=1;k
<=mfit
;k
++)
510 covar
[j
][k
]=alpha
[j
][k
]; /* diagonal elements. */
511 covar
[j
][j
]=alpha
[j
][j
]*(1.0+(*alamda
));
514 if (!gaussj(covar
,mfit
,oneda
,1)) /* Matrix solution. */
516 for (j
=1;j
<=mfit
;j
++)
518 if (*alamda
== 0.0) { /* Once converged, evaluate covariance matrix. */
519 covsrt_new(covar
,ma
,ia
,mfit
);
520 free_matrix(oneda
,1,mfit
,1);
526 for (j
=0,l
=1;l
<=ma
;l
++) /* Did the trial succeed? */
527 if (ia
[l
]) atry
[l
]=a
[l
]+da
[++j
];
528 mrqcof_new(x
,y
,sig
,ndata
,atry
,ia
,ma
,covar
,da
,chisq
,funcs
);
529 if (*chisq
< ochisq
) {
530 /* Success, accept the new solution. */
533 for (j
=1;j
<=mfit
;j
++) {
534 for (k
=1;k
<=mfit
;k
++) alpha
[j
][k
]=covar
[j
][k
];
537 for (l
=1;l
<=ma
;l
++) a
[l
]=atry
[l
];
538 } else { /* Failure, increase alamda and return. */
545 void mrqcof_new(real x
[], real y
[], real sig
[], int ndata
, real a
[],
546 int ia
[], int ma
, real
**alpha
, real beta
[], real
*chisq
,
547 void (*funcs
)(real
, real
[], real
*, real
[]))
548 /* Used by mrqmin to evaluate the linearized fitting matrix alpha, and
549 * vector beta as in (15.5.8), and calculate Chi^2.
552 int i
,j
,k
,l
,m
,mfit
=0;
553 real ymod
,wt
,sig2i
,dy
,*dyda
;
558 for (j
=1;j
<=mfit
;j
++) { /* Initialize (symmetric) alpha), beta. */
559 for (k
=1;k
<=j
;k
++) alpha
[j
][k
]=0.0;
563 for (i
=1;i
<=ndata
;i
++) { /* Summation loop over all data. */
564 (*funcs
)(x
[i
],a
,&ymod
,dyda
);
565 sig2i
=1.0/(sig
[i
]*sig
[i
]);
567 for (j
=0,l
=1;l
<=ma
;l
++) {
570 for (j
++,k
=0,m
=1;m
<=l
;m
++)
571 if (ia
[m
]) alpha
[j
][++k
] += wt
*dyda
[m
];
575 *chisq
+= dy
*dy
*sig2i
; /* And find Chi^2. */
577 for (j
=2;j
<=mfit
;j
++) /* Fill in the symmetric side. */
578 for (k
=1;k
<j
;k
++) alpha
[k
][j
]=alpha
[j
][k
];