200 lines
4.2 KiB
C
200 lines
4.2 KiB
C
/* Code to test the conjgrad minimiser */
|
|
/*
|
|
* Copyright 1999, 2018 Graeme W. Gill
|
|
* All rights reserved.
|
|
*
|
|
* This material is licenced under the GNU AFFERO GENERAL PUBLIC LICENSE Version 3 :-
|
|
* see the License.txt file for licencing details.
|
|
*/
|
|
|
|
#include <stdio.h>
|
|
#include "numlib.h"
|
|
|
|
/* Final approximate solution: */
|
|
|
|
double expect[9] = {
|
|
-0.5706545E+00,
|
|
-0.6816283E+00,
|
|
-0.7017325E+00,
|
|
-0.7042129E+00,
|
|
-0.7013690E+00,
|
|
-0.6918656E+00,
|
|
-0.6657920E+00,
|
|
-0.5960342E+00,
|
|
-0.4164121E+00 };
|
|
|
|
double fcn( /* Return function value */
|
|
void *fdata, /* Opaque data pointer */
|
|
double tp[] /* Multivriate input value */
|
|
);
|
|
|
|
static double dfcn(
|
|
void *fdata,
|
|
double dp[],
|
|
double tp[]
|
|
);
|
|
|
|
#define N 9
|
|
|
|
static void progress(void *pdata, int perc) {
|
|
printf("%c% 3d%%",cr_char,perc);
|
|
if (perc == 100)
|
|
printf("\n");
|
|
fflush(stdout);
|
|
}
|
|
|
|
int main(void)
|
|
{
|
|
double cp[N]; /* Function input values */
|
|
double s[N]; /* Search area */
|
|
double err;
|
|
int j;
|
|
int nprint = 0; /* Itteration debugging print = off */
|
|
int rc;
|
|
|
|
error_program = "tconjgrad"; /* Set global error reporting string */
|
|
check_if_not_interactive();
|
|
|
|
/* ====== test with partial derivative ====== */
|
|
/* The following starting values provide a rough solution. */
|
|
for (j = 0; j < N; j++) {
|
|
cp[j] = -1.f;
|
|
s[j] = 0.9;
|
|
}
|
|
|
|
nprint = 0;
|
|
|
|
/* Set tol to the square root of the machine precision. */
|
|
/* Unless high precision solutions are required, */
|
|
/* this is the recommended setting. */
|
|
|
|
rc = conjgrad(
|
|
&err,
|
|
N, /* Dimentionality */
|
|
cp, /* Initial starting point */
|
|
s, /* Size of initial search area */
|
|
0.00000001, /* Tollerance of error change to stop on */
|
|
1000, /* Maximum iterations allowed */
|
|
fcn, /* Error function to evaluate */
|
|
dfcn, /* Partial derivative function */
|
|
NULL, /* Opaque data needed by function */
|
|
progress, /* Progress callback */
|
|
NULL /* Context for callback */
|
|
);
|
|
|
|
|
|
fprintf(stdout,"Using partial derivative:\n");
|
|
fprintf(stdout,"Status = %d, final approximate solution err = %f:\n",rc,err);
|
|
for (j = 0; j < N; j++) {
|
|
fprintf(stdout,"cp[%d] = %e, expect %e\n",j,cp[j],expect[j]);
|
|
}
|
|
|
|
/* ====== test without partial derivative ====== */
|
|
/* The following starting values provide a rough solution. */
|
|
for (j = 0; j < N; j++) {
|
|
cp[j] = -1.f;
|
|
s[j] = 0.9;
|
|
}
|
|
|
|
nprint = 0;
|
|
|
|
/* Set tol to the square root of the machine precision. */
|
|
/* Unless high precision solutions are required, */
|
|
/* this is the recommended setting. */
|
|
|
|
rc = conjgrad(
|
|
&err,
|
|
N, /* Dimentionality */
|
|
cp, /* Initial starting point */
|
|
s, /* Size of initial search area */
|
|
0.00000001, /* Tollerance of error change to stop on */
|
|
1000, /* Maximum iterations allowed */
|
|
fcn, /* Error function to evaluate */
|
|
NULL, /* No partial derivative function */
|
|
NULL, /* Opaque data needed by function */
|
|
progress, /* Progress callback */
|
|
NULL /* Context for callback */
|
|
);
|
|
|
|
|
|
fprintf(stdout,"\nNot using partial derivative:\n");
|
|
fprintf(stdout,"Status = %d, final approximate solution err = %f:\n",rc,err);
|
|
for (j = 0; j < N; j++) {
|
|
fprintf(stdout,"cp[%d] = %e, expect %e\n",j,cp[j],expect[j]);
|
|
}
|
|
|
|
return 0;
|
|
} /* main() */
|
|
|
|
/* Function being minimized */
|
|
double fcn( /* Return function value */
|
|
void *fdata, /* Opaque data pointer */
|
|
double tp[] /* Multivriate input value */
|
|
) {
|
|
double err, tt;
|
|
double temp, temp1, temp2;
|
|
int k;
|
|
|
|
/* Function Body */
|
|
err = 0.0;
|
|
for (k = 0; k < N; ++k) {
|
|
temp = (3.0 - 2.0 * tp[k]) * tp[k];
|
|
temp1 = 0.0;
|
|
if (k != 0) {
|
|
temp1 = tp[k-1];
|
|
}
|
|
temp2 = 0.0;
|
|
if (k != ((N)-1))
|
|
temp2 = tp[k+1];
|
|
tt = temp - temp1 - 2.0 * temp2 + 1.0;
|
|
err += tt * tt;
|
|
}
|
|
err = sqrt(err);
|
|
//printf("Returning %16.14f\n",err);
|
|
return err;
|
|
}
|
|
|
|
|
|
/* Compute aprox. forward difference */
|
|
|
|
#define JEPS 1.0e-8 /* Aprox. sqrt of machine precision */
|
|
|
|
static double dfcn(
|
|
void *fdata,
|
|
double dp[],
|
|
double tp[]
|
|
) {
|
|
int i;
|
|
double d, h, temp;
|
|
|
|
d = fcn(fdata, tp);
|
|
|
|
for (i = 0; i < N; i++) {
|
|
temp = tp[i];
|
|
|
|
h = JEPS * fabs(temp);
|
|
if (h == 0.0)
|
|
h = JEPS;
|
|
tp[i] = temp + h; /* Add delta */
|
|
h = tp[i] - temp; /* Actual delta with fp precision limits */
|
|
|
|
dp[i] = (fcn(fdata, tp) - d)/h;
|
|
|
|
tp[i] = temp; /* Restore value */
|
|
}
|
|
|
|
// return DFUNC_NRV;
|
|
return d;
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|