home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
C/C++ Interactive Guide
/
c-cplusplus-interactive-guide.iso
/
c_ref
/
csource4
/
209_01
/
simplib0.c
< prev
next >
Wrap
C/C++ Source or Header
|
1990-03-05
|
19KB
|
865 lines
/* SIMPLIB0.C VERS:- 01.00 DATE:- 09/26/86 TIME:- 09:39:24 PM */
/*
Description:
functions for simplex fitting:
simplex fitting routine = simpfit()
quadratic fit for standard deviations = simpdev()
supporting functions
By J.A. Rupley, Tucson, Arizona
Coded for ECO C compiler, version 3.40
*/
#include <stdio.h>
#include <ctrlcnst.h>
#define NPARM 10
/* STRUCTURES */
struct pstruct {
double val ;
double parm[NPARM] ;
} ;
struct qstruct {
int parmndx[NPARM] ;
double q[NPARM] ;
double yplus[NPARM] ;
double yminus[NPARM] ;
double a[NPARM] ;
double bdiag[NPARM] ;
double inv_bdiag[NPARM] ;
double std_dev[NPARM] ;
} ;
/* page eject */
/* SIMPFIT
SIMPLEX MINIMIZATION BY USE OF NELDER-MEAD ALGORITHM,
FOR MODEL DEFINED IN <FUNC()> .
*/
/* defines for simpfit */
#define ILLEGAL 0
#define REFLECT 1
#define STARCONTRACT 2
#define HIGHCONTRACT 3
#define SHRINK 4
#define FAILREFLECT 5
#define STAREXPAND 6
int simpfit(fptr)
FILE *fptr ;
{
register int j, i ;
int opcode ;
int c ;
int test_break ;
int nlow, nhigh ;
struct pstruct *p_best, pbar, pstar, p2star ;
void bsort(), fprintf() ;
int getchar() ;
double sqrt() ;
int pvalcomp(), p_swap() ;
int centroid(), func(), ptrial() ;
void fpprint(), pcopy() ;
extern struct pstruct p[], pcent, *p_p[] ;
extern double exit_test, mean_func, rms_func, test, rms_data;
extern int iter, maxiter, nparm, nvert, ndata, nfree ;
/* expansion-contraction coefficients */
double alpha ;
double beta ;
double gamma ;
/* descriptions of expn-cntrctn operations */
static char *opname[] = {
"illegal",
"reflect",
"reflect & contract",
"contract",
"shrink on lowest vertex",
"reflect after fail to expand",
"reflect and expand"
} ;
nlow = 0 ;
nhigh = nvert - 1 ;
/* initialization:
coefficients
pointers */
alpha = 1 ;
beta = .5 ;
gamma = 2 ;
for (j = 0; j < nvert; j++)
p_p[j] = &p[j] ;
fprintf(fptr,
"\n\ntype ^X to exit loop, ^S to pause\n\n") ;
/* MAIN LOOP OF MINIMIZATION */
while (++iter) {
/* ascending sort of pointers p_p
to struct array p */
bsort(nvert, pvalcomp, p_swap) ;
/* form reduced simplex, pbar,
for (nvert - 1) vertices
ie without high vertex */
centroid(&pbar, p_p, (nvert - 1)) ;
/* form pstar, new reflection trial vertex */
ptrial(&pstar, &pbar, p_p[nhigh], (1 + alpha), -alpha) ;
func(&pstar) ;
/* NELDER-MEAD ALGORITHM = test trial vertex
vs old high and low vertices ;
construct new trial vertices as appropriate;
set pointer to best new vertex */
if (pstar.val < p_p[nlow]->val){
ptrial(&p2star, &pstar, &pbar, (1 + gamma), -gamma) ;
func(&p2star) ;
if (p2star.val < p_p[nlow]->val) {
p_best = &p2star ;
opcode = STAREXPAND ;
} else {
p_best = &pstar ;
opcode = FAILREFLECT ;
}
} else if (pstar.val <= p_p[nhigh-1]->val) {
p_best = &pstar ;
opcode = REFLECT ;
} else {
if (pstar.val <= p_p[nhigh]->val) {
pcopy(p_p[nhigh], &pstar) ;
opcode = STARCONTRACT ;
} else
opcode = HIGHCONTRACT ;
ptrial(&p2star, p_p[nhigh], &pbar, beta, (1-beta)) ;
func(&p2star) ;
if (p2star.val <= p_p[nhigh]->val)
p_best = &p2star ;
else
opcode = SHRINK ;
}
/* END OF NELDER-MEAD ALGORITHM */
/* possible exit from loop on operator kbhit
clear keyboard of any extra chars typed */
test_break = FALSE ;
if (KBHIT) {
c = getchar() ;
while (KBHIT) {
getchar() ;
}
if ((c == CTRLX) || (c == CTRLC))
test_break = TRUE ;
else if (c == CTRLS)
getchar() ;
}
/* print results */
fprintf(fptr, "\n%5d %20.14e %20.14e %s\n",
iter, p_p[nhigh]->val, p_best->val, opname[opcode]) ;
fpprint(fptr, p_p[nhigh]) ;
fpprint(fptr, p_best) ;
/* adjust simplex
either loop over all vertices > lowest = [0]
to shrink on lowest
else copy best movement into high vertex */
if (opcode == SHRINK)
for (j = 1; j < nvert; j++) {
for (i = 0; i < nparm; i++)
p_p[j]->parm[i] = (p_p[nlow]->parm[i]
+ p_p[j]->parm[i])/2 ;
func(p_p[j]) ;
}
else
pcopy(p_p[nhigh], p_best) ;
/* calculate and print new centroid */
centroid(&pcent, p_p, nvert) ;
fpprint(fptr, &pcent) ;
/* calculate and print
mean and rms of function values */
mean_func = 0 ;
for (j = 0; j < nvert; j++)
mean_func = mean_func + p[j].val ;
mean_func = mean_func/nvert ;
rms_func = 0 ;
for (j = 0; j < nvert; j++)
rms_func = rms_func
+ (p[j].val - mean_func) * (p[j].val - mean_func) ;
rms_func = sqrt(rms_func/nvert) ;
test = rms_func/mean_func ;
rms_data = sqrt(p_p[nlow]->val/(ndata - nfree));
fprintf(fptr, "mean=%20.14e rms=%20.14e test=%20.14e\n",
mean_func, rms_func, test) ;
fprintf(fptr,
"root mean square weighted error of best fit to data = %20.14e\n\n",
rms_data) ;
fspecial(fptr) ;
/* exit test
calculate centroid function value if exit */
if ((test_break == TRUE) || (iter == maxiter)) {
func(&pcent) ;
break ;
}
if (test < exit_test) {
func(&pcent) ;
if ((pcent.val - mean_func) < (2 * rms_func))
break ;
}
}
/* END OF MAIN LOOP OF MINIMIZATION */
return (OK) ;
} /* END OF SIMPFIT */
/* page eject */
/* SIMPDEV
QUADRATIC FIT TO FUNCTION SURFACE FOR ESTIMATION OF:
VARIANCE-COVARIANCE MATRIX
STANDARD DEVIATIONS OF PARAMETERS
*/
int simpdev(fptr)
FILE *fptr ;
{
register int i, j, k, l ;
int xfree, free_count ;
int c ;
int err_count ;
double dtemp ;
double yminusij, yplusij ;
double tmparray[NPARM] ;
struct pstruct ptemp ;
void fprintf() ;
int getchar() ;
double sqrt() ;
int func() ;
void fpprint(), pcopy() ;
void fqprint(), fmatprint() ;
void bsort();
int pvalcomp(), p_swap() ;
extern struct pstruct *p_p[], p[], pcent, pmin ;
extern struct qstruct q ;
extern double qmat[][NPARM] ;
extern double rms_data, yzero, ymin, ypmin, mse ;
extern int nparm, nvert, ndata, nfree ;
/* be sure that pcent.val is set */
if (func(&pcent) == ERROR)
return (ERROR) ;
/* ascending sort of pointers p_p
to struct array p */
bsort(nvert, pvalcomp, p_swap) ;
/* if lowest vertex < centroid, then
replace centroid by lowest vertex */
if (p_p[0]->val < pcent.val) {
pcopy(&pcent, p_p[0]);
fprintf(fptr, "\n\nlowest vertex replaces centroid");
}
/* set yzero */
yzero = pcent.val ;
fprintf(fptr,
"\n\nlowest function value = yzero = %20.14e\n\n", yzero) ;
fpprint(fptr, &pcent) ;
fprintf(fptr, "\n") ;
/* calculate
q value = avg devn of a free parameter
from the centroid value ;
store the q value in structure q :
q.q[free_cnt] = q value ;
also store map of free parm to parm array in
q.parmndx[free_cnt] = index of parm
in p[nvert].parm[nparm] ;
set nfree and nvert */
free_cnt = 0 ;
for (i = 0; i < nparm; i++) {
dtemp = 0 ;
for (j = 0; j < nvert; j++)
dtemp = dtemp + ABS(p[j].parm[i] - pcent.parm[i]) ;
dtemp = dtemp/nvert ;
if (ABS(dtemp/pcent.parm[i]) < 1.e-16) {
fprintf(fptr, "parameter %d is fixed\n", i) ;
continue ;
} else {
q.q[free_cnt] = dtemp ;
q.parmndx[free_cnt] = i ;
free_cnt++ ;
}
}
nfree = free_cnt ;
if (nvert != (nfree + 1)) {
fprintf(fptr, "\nerror in count of free parameters\n") ;
return (ERROR) ;
}
fprintf(fptr,
"\nq values for the %d free parameters out of %d total:\n",
nfree, nparm) ;
fqprint(fptr, q.q) ;
/* check and if necessary adjust q values
for each free parameter, to be sure that the
function values are OK for the
centroid parameter values (+ & -) q ;
store function value for