home *** CD-ROM | disk | FTP | other *** search
- Subject: Simplex Curve Fitting Algorithm in C
- Keywords: simplex C
- Newsgroups: mod.sources
- Approved: jpn@panda.UUCP
-
- 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."
-
-
-