Simplex Curve Fitting Algorithm in C
sources-request at panda.UUCP
sources-request at panda.UUCP
Sun Feb 23 11:57:44 AEST 1986
Mod.sources: Volume 4, Issue 2
Submitted by: panda!genrad!decvax!ihnp4!chinet!blm
This program originally appeared in the May 1984 issue of Byte Magazine. It
was originally written in Pascal by Marco Caceci and William Caceris at Florida
State University. I have translated it to 'C'.
This program is based upon the Simplex curve fitting algorithm. For a detailed
descripstion of this program and it's workings see the above mentioned article.
I acknowledge the work of Marco Caceci and William Caceris for writing the
original Pascal program from which this is derived. The original authors
explicitly stated ''no copy-right''.
I've had some problems with accuracy. I've checked and rechecked my source
code and I can't find anything that would account for it. I could very well be
overlooking something, though. I suppose it could have to do with differences
in the precision of the floating-point libraries of the authors Pascal compiler
(Pascal/Z Version 4.0 CP/M) and my C compiler (Xenix 3.0). I welcome E-mail
on this subject. Nevertheless, the differences in values returned between
the original and mine are comparatively small.
I hope this helps someone in Netland.
-----
The preceding announcement was conceived in my own mind and is not
necessarily the opinion of whom ever I happen to work for at the time.
Name : Brad L. McKinley --- (503) 889-4321
USMail: M D R Professional Software, Inc., 915 SW 3rd Avenue, Ontario, OR 97914
Usenet: ihnp4!chinet!blm OR ihnp4!chinet!mdr!blm
CIS : 70015,1205
Source: BDY171
"God created Arrakis to test the faithful." -- Maud'dib
--- cut here ------ cut here ------ cut here ------ cut here ---
: This is a shar archive. Extract with sh, not csh.
: The rest of this file will extract:
: Makefile
: data sample data file
: enter.c
: f.c a typical function
: first.c
: main.c
: new_vertex.c
: order.c
: report.c
: sum_residual.c
:
echo extracting -- Makefile
sed 's/^X//' > Makefile << E_O_F
XBINARY = simplex
X
XSOURCES = main.c f.c sum_residual.c enter.c first.c new_vertex.c order.c report.c
X
XOBJECTS = main.o f.o sum_residual.o enter.o first.o new_vertex.o order.o report.o
X
XLIBRARIES = -lm -lc
X
XCFLAGS = -O
XLDFLAGS = -n -s -x
XLINTFLAGS =
X
X$(BINARY): $(OBJECTS)
X @echo " loading $(BINARY)"
X @ld -o $@ $(LDFLAGS) /lib/crt0.o $(OBJECTS) $(LIBRARIES)
X
Xlint:
X lint $(LINTFLAGS) $(SOURCES)
X
X$(OBJECTS): simplex.h
E_O_F
echo extracting -- data
sed 's/^X//' > data << E_O_F
X100
X0.2 3
X0.1 1
X1e-6 1e-6 1e-6
X1.68 0.172
X3.33 0.250
X5.00 0.286
X6.67 0.303
X10.0 0.334
X20.0 0.384
E_O_F
echo extracting -- simplex.h
sed 's/^X//' > simplex.h << E_O_F
X#include <math.h>
X#include <stdio.h>
X
X#define M 2
X#define NVPP 2
X#define N M+1
X#define MNP 200
X#define ALPHA 1.0
X#define BETA 0.5
X#define GAMMA 2.0
X#define LW 5
X#define ROOT2 1.414214
X
Xtypedef double vector[N];
Xtypedef double datarow[NVPP];
X
Xextern int h[N], l[N];
Xextern int np, maxiter, niter;
Xextern vector next, mean, error, maxerr, step, simp[N];
Xextern datarow data[MNP];
Xextern FILE *fpdata;
X
Xextern double f();
E_O_F
echo extracting -- enter.c
sed 's/^X//' > enter.c << E_O_F
X#include "simplex.h"
X
Xenter(fname)
Xchar *fname;
X{
X register int i, j;
X
X printf("SIMPLEX Optimization --- 'C' Version\n\n");
X printf("Accessing file: %s\n\n", fname);
X
X fscanf(fpdata, "%d", &maxiter);
X printf("maximum number of iterations = %d\n\n", maxiter);
X
X printf("Start Coordinates: ");
X for (i=0 ; i<M ; i++) {
X fscanf(fpdata, "%F", &simp[0][i]);
X if ((i+1) % LW == 0)
X printf("\n");
X printf(" %e", simp[0][i]);
X }
X printf("\n\n");
X
X printf("Start Steps: ");
X for (i=0 ; i<M ; i++) {
X fscanf(fpdata, "%F", &step[i]);
X if ((i+1) % LW == 0)
X printf("\n");
X printf(" %e", step[i]);
X }
X printf("\n\n");
X
X printf("Maximum Error: ");
X for (i=0 ; i<N ; i++) {
X fscanf(fpdata, "%F", &maxerr[i]);
X if ((i+1) % LW == 0)
X printf("\n");
X printf(" %e", maxerr[i]);
X }
X printf("\n\n");
X
X printf("DATA\n");
X printf(" X Y\n");
X np = 0;
X while (!feof(fpdata)) {
X for (j=0 ; j<NVPP ; j++) {
X if (fscanf(fpdata, "%F", &data[np][j]) == EOF)
X break;
X printf(" %e", data[np][j]);
X }
X np++;
X printf("\n");
X }
X np--;
X
X}
E_O_F
echo extracting -- f.c
sed 's/^X//' > f.c << E_O_F
X#include "simplex.h"
X
Xdouble f(x, d)
Xvector x;
Xdatarow d;
X{
X return (x[0]*d[0]/(x[1]+d[0]));
X}
E_O_F
echo extracting -- first.c
sed 's/^X//' > first.c << E_O_F
X#include "simplex.h"
X
Xfirst()
X{
X register int i, j;
X
X printf("Starting Simplex\n");
X for (j=0 ; j<N ; j++) {
X printf(" simp[%d]", j+1);
X for (i=0 ; i<N ; i++) {
X if ((i+1) % LW == 0)
X printf("\n");
X printf(" %e", simp[j][i]);
X }
X printf("\n");
X }
X printf("\n");
X}
E_O_F
echo extracting -- main.c
sed 's/^X//' > main.c << E_O_F
X#include "simplex.h"
X
X#define until(x) while (!(x))
X
Xint h[N], l[N];
Xint np, maxiter, niter;
Xvector next, mean, error, maxerr, step, simp[N];
Xdatarow data[MNP];
XFILE *fpdata;
X
Xmain(argc, argv)
Xint argc;
Xchar *argv[];
X{
X register int i, j, done;
X vector center, p, q;
X
X if (argc != 2) {
X fprintf(stderr, "usage: simplex file_name\n", argv[1]);
X exit(1);
X }
X
X if ((fpdata = fopen(argv[1], "r")) == NULL) {
X fprintf(stderr, "simplex: can't open %s\n", argv[1]);
X exit(1);
X }
X
X enter(argv[1]);
X
X /* First Vertex */
X sum_residual(simp[0]);
X
X /* Compute offset of Vertices */
X for (i=0 ; i<M ; i++) {
X p[i] = step[i] * (sqrt((double) N) + M - 1) / (M * ROOT2);
X q[i] = step[i] * (sqrt((double) N) - 1) / (M * ROOT2);
X }
X
X /* All Vertices of the Starting Simplex */
X for (i=1 ; i<N ; i++) {
X for (j=0 ; j<M ; j++)
X simp[i][j] = simp[0][j] + q[j];
X simp[i][i-1] = simp[0][i-1] + p[i-1];
X sum_residual(simp[i]);
X }
X
X /* Preset */
X for (i=0 ; i<N ; i++) {
X l[i] = 1;
X h[i] = 1;
X }
X order();
X
X first();
X
X niter = 0;
X
X /* Iterate */
X do {
X /* Wish it were True */
X done = 1;
X niter++;
X
X /* Compute Centroid...Excluding the Worst */
X for (i=0 ; i<N ; i++)
X center[i] = 0.0;
X for (i=0 ; i<N ; i++)
X if (i != h[N-1])
X for (j=0 ; j<M ; j++)
X center[j] += simp[i][j];
X
X /* First Attempt to Reflect */
X for (i=0 ; i<N ; i++) {
X center[i] /= M;
X next[i] = (1.0+ALPHA) * center[i] - ALPHA * simp[h[N-1]][i];
X }
X sum_residuals(next);
X
X if (next[N-1] <= simp[l[N-1]][N-1]) {
X new_vertex();
X for (i=0 ; i<M ; i++)
X next[i] = GAMMA * simp[h[N-1]][i] + (1.0-GAMMA) * center[i];
X sum_residual(next);
X if (next[N-1] <= simp[l[N-1]][N-1])
X new_vertex();
X }
X else {
X if (next[N-1] <= simp[h[N-1]][N-1])
X new_vertex();
X else {
X for (i=0 ; i<M ; i++)
X next[i] = BETA * simp[h[N-1]][i] + (1.0-BETA) * center[i];
X sum_residual(next);
X if (next[N-1] <= simp[h[N-1]][N-1])
X new_vertex();
X else {
X for (i=0 ; i<N ; i++) {
X for (j=0 ; j<M ; j++)
X simp[i][j] = BETA * (simp[i][j] + simp[l[N-1]][j]);
X sum_residual(simp[i]);
X }
X }
X }
X }
X
X order();
X
X /* Check For Convergence */
X for (j=0 ; j<N ; j++) {
X error[j] = (simp[h[j]][j] - simp[l[j]][j]) / simp[h[j]][j];
X if (done)
X if (error[j] > maxerr[j])
X done = 0;
X }
X
X } until(done || (niter == maxiter));
X
X /* Average Each Parameter */
X for (i=0 ; i<N ; i++) {
X mean[i] = 0.0;
X for (j=0 ; j<N ; j++)
X mean[i] += simp[j][i];
X mean[i] /= N;
X }
X
X report();
X}
E_O_F
echo extracting -- new_vertex.c
sed 's/^X//' > new_vertex.c << E_O_F
X#include "simplex.h"
X
Xnew_vertex()
X{
X register int i;
X
X printf(" --- %4d", niter);
X for (i=0 ; i<N ; i++) {
X simp[h[N-1]][i] = next[i];
X printf(" %e", next[i]);
X }
X printf("\n");
X}
E_O_F
echo extracting -- order.c
sed 's/^X//' > order.c << E_O_F
X#include "simplex.h"
X
Xorder()
X{
X register int i, j;
X
X for (j=0 ; j<N ; j++)
X for (i=0 ; i<N ; i++) {
X if (simp[i][j] < simp[l[j]][j])
X l[j] = i;
X if (simp[i][j] > simp[h[j]][j])
X h[j] = i;
X }
X}
E_O_F
echo extracting -- report.c
sed 's/^X//' > report.c << E_O_F
X#include "simplex.h"
X
Xreport()
X{
X register int i, j;
X double y, dy, sigma;
X
X printf("\nProgram exited after %d iterations.\n\n", niter);
X
X printf("The final simplex is:\n");
X for (j=0 ; j<N ; j++) {
X for (i=0 ; i<N ; i++) {
X if ((i+1) % LW == 0)
X printf("\n");
X printf(" %e", simp[j][i]);
X }
X printf("\n");
X }
X printf("\n\n");
X
X printf("The mean is:");
X for (i=0 ; i<N ; i++) {
X if ((i+1) % LW == 0)
X printf("\n");
X printf(" %e", mean[i]);
X }
X printf("\n\n");
X
X printf("The estimated fractional error is:");
X for (i=0 ; i<N ; i++) {
X if ((i+1) % LW == 0)
X printf("\n");
X printf(" %e", error[i]);
X }
X printf("\n\n");
X
X printf(" # X Y Y'' DY\n");
X sigma = 0.0;
X for (i=0 ; i<np ; i++) {
X y = f(mean, data[i]);
X dy = data[i][1] - y;
X sigma += (dy*dy);
X printf("%4d ", i);
X printf("%13e %13e ", data[i][0], data[i][1]);
X printf("%13e %13e\n", y, dy);
X }
X printf("\n");
X sigma = sqrt(sigma);
X printf("The standard deviation is %e\n\n", sigma);
X sigma /= sqrt((double) (np-M));
X printf("The estimated error of the function is %e\n\n", sigma);
X}
E_O_F
echo extracting -- sum_residual.c
sed 's/^X//' > sum_residual.c << E_O_F
X#include "simplex.h"
X
X#define sqr(x) ((x) * (x))
X
Xsum_residual(x)
Xvector x;
X{
X register int i;
X
X x[N-1] = 0.0;
X
X for (i=0 ; i<np ; i++)
X x[N-1] += sqr(f(x, data[i]) - data[i][1]);
X}
E_O_F
exit
---
Name : Brad L. McKinley --- (503) 889-4321
Usenet: ihnp4!chinet!blm US Mail: M D R Professional Software, Inc.
CIS : 70015,1205 915 SW 3rd Avenue
Source: BDY171 Ontario, Oregon 97914
"God created Arrakis to test the faithful."
More information about the Mod.sources
mailing list