2013-05-18 11:54:11 -06:00
|
|
|
#include <stdio.h>
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <math.h>
|
|
|
|
|
|
|
|
#define TINY 1.0e-10
|
|
|
|
#define NMAX 100000
|
|
|
|
#define SWAP(a,b) {(a)+=(b);(b)=(a)-(b);(a)-=(b);}
|
|
|
|
|
|
|
|
// Downhill Simplex Minimization
|
2022-08-06 22:23:15 -06:00
|
|
|
int
|
|
|
|
dsmin (double **p, double *y, int n, double ftol, double (*func) (double *))
|
2013-05-18 11:54:11 -06:00
|
|
|
{
|
2022-08-06 22:23:15 -06:00
|
|
|
int i, j, nfunk = 0;
|
|
|
|
int ihi, ilo, ise;
|
|
|
|
double *ptry, *pmid, *psum;
|
|
|
|
double tol, ytry, rtol, ysave;
|
|
|
|
double *vector_sum (double **, int);
|
|
|
|
double dsmod (double **, double *, double *, int, double (*func) (double *),
|
|
|
|
int, double);
|
2013-05-18 11:54:11 -06:00
|
|
|
|
|
|
|
// Allocate memory
|
2022-08-06 22:23:15 -06:00
|
|
|
psum = (double *) malloc (sizeof (double) * n);
|
2013-05-18 11:54:11 -06:00
|
|
|
|
|
|
|
// Get function values
|
2022-08-06 22:23:15 -06:00
|
|
|
for (i = 0; i <= n; i++)
|
|
|
|
y[i] = func (p[i]);
|
2013-05-18 11:54:11 -06:00
|
|
|
|
|
|
|
// Sum vectors
|
2022-08-06 22:23:15 -06:00
|
|
|
psum = vector_sum (p, n);
|
2013-05-18 11:54:11 -06:00
|
|
|
|
|
|
|
// Start forever loop
|
2022-08-06 22:23:15 -06:00
|
|
|
for (;;)
|
|
|
|
{
|
|
|
|
// Find high and low point
|
|
|
|
ilo = 0;
|
|
|
|
ihi = (y[0] > y[1]) ? (ise = 1, 0) : (ise = 0, 1);
|
|
|
|
for (i = 0; i <= n; i++)
|
|
|
|
{
|
|
|
|
if (y[i] <= y[ilo])
|
|
|
|
ilo = i;
|
|
|
|
if (y[i] > y[ihi])
|
|
|
|
{
|
|
|
|
ise = ihi;
|
|
|
|
ihi = i;
|
|
|
|
}
|
|
|
|
else if (y[i] > y[ise] && i != ihi)
|
|
|
|
ise = i;
|
|
|
|
}
|
2013-05-18 11:54:11 -06:00
|
|
|
|
2022-08-06 22:23:15 -06:00
|
|
|
// Compute fractional range from highest to lowest point
|
|
|
|
rtol =
|
|
|
|
2.0 * fabs (y[ihi] - y[ilo]) / (fabs (y[ihi]) + fabs (y[ilo]) + TINY);
|
2013-05-18 11:54:11 -06:00
|
|
|
|
2022-08-06 22:23:15 -06:00
|
|
|
// Return if fractional tolerance is acceptable
|
|
|
|
if (rtol < ftol)
|
|
|
|
break;
|
2013-05-18 11:54:11 -06:00
|
|
|
|
2022-08-06 22:23:15 -06:00
|
|
|
if (nfunk >= NMAX)
|
|
|
|
{
|
|
|
|
printf ("dsmin: NMAX exceeded!\n");
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
nfunk += 2;
|
|
|
|
|
|
|
|
// Reflect simplex
|
|
|
|
ytry = dsmod (p, y, psum, n, func, ihi, -1.0);
|
|
|
|
|
|
|
|
if (ytry <= y[ilo]) // Goes right direction, extrapolate by factor 2
|
|
|
|
ytry = dsmod (p, y, psum, n, func, ihi, 2.0);
|
|
|
|
else if (ytry >= y[ise])
|
|
|
|
{ // 1D contraction
|
|
|
|
ysave = y[ihi];
|
|
|
|
ytry = dsmod (p, y, psum, n, func, ihi, 0.5);
|
|
|
|
if (ytry >= ysave)
|
|
|
|
{
|
|
|
|
for (i = 0; i <= n; i++)
|
|
|
|
{
|
|
|
|
if (i != ilo)
|
|
|
|
{
|
|
|
|
for (j = 0; j < n; j++)
|
|
|
|
p[i][j] = psum[j] = 0.5 * (p[i][j] + p[ilo][j]);
|
|
|
|
y[i] = (*func) (psum);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
nfunk += n;
|
|
|
|
|
|
|
|
psum = vector_sum (p, n);
|
|
|
|
}
|
2013-05-18 11:54:11 -06:00
|
|
|
}
|
2022-08-06 22:23:15 -06:00
|
|
|
else
|
|
|
|
--nfunk;
|
|
|
|
}
|
|
|
|
free (psum);
|
2013-05-18 11:54:11 -06:00
|
|
|
|
|
|
|
return nfunk;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Sum vectors
|
2022-08-06 22:23:15 -06:00
|
|
|
double *
|
|
|
|
vector_sum (double **p, int n)
|
2013-05-18 11:54:11 -06:00
|
|
|
{
|
2022-08-06 22:23:15 -06:00
|
|
|
int i, j;
|
|
|
|
double sum, *psum;
|
2013-05-18 11:54:11 -06:00
|
|
|
|
2022-08-06 22:23:15 -06:00
|
|
|
psum = (double *) malloc (sizeof (double) * n);
|
2013-05-18 11:54:11 -06:00
|
|
|
|
2022-08-06 22:23:15 -06:00
|
|
|
for (i = 0; i < n; i++)
|
|
|
|
{
|
|
|
|
sum = 0.;
|
|
|
|
for (j = 0; j <= n; j++)
|
|
|
|
sum += p[j][i];
|
|
|
|
psum[i] = sum;
|
|
|
|
}
|
2013-05-18 11:54:11 -06:00
|
|
|
|
|
|
|
return psum;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Simplex modification
|
2022-08-06 22:23:15 -06:00
|
|
|
double
|
|
|
|
dsmod (double **p, double *y, double *psum, int n, double (*func) (double *),
|
|
|
|
int ihi, double fac)
|
2013-05-18 11:54:11 -06:00
|
|
|
{
|
|
|
|
int i;
|
2022-08-06 22:23:15 -06:00
|
|
|
double fac1, fac2, ytry, *ptry;
|
|
|
|
|
|
|
|
ptry = (double *) malloc (sizeof (double) * n);
|
|
|
|
fac1 = (1.0 - fac) / (double) n;
|
|
|
|
fac2 = fac1 - fac;
|
|
|
|
|
|
|
|
for (i = 0; i < n; i++)
|
|
|
|
ptry[i] = psum[i] * fac1 - p[ihi][i] * fac2;
|
|
|
|
ytry = (*func) (ptry);
|
|
|
|
if (ytry < y[ihi])
|
|
|
|
{
|
|
|
|
y[ihi] = ytry;
|
|
|
|
for (i = 0; i < n; i++)
|
|
|
|
{
|
|
|
|
psum[i] += ptry[i] - p[ihi][i];
|
|
|
|
p[ihi][i] = ptry[i];
|
|
|
|
}
|
2013-05-18 11:54:11 -06:00
|
|
|
}
|
|
|
|
|
2022-08-06 22:23:15 -06:00
|
|
|
free (ptry);
|
|
|
|
|
2013-05-18 11:54:11 -06:00
|
|
|
return ytry;
|
|
|
|
}
|