~swaits/differential-evolution

eedade5b63a2502c47173dca576c85004143e3ee — swaits 17 years ago 76f95a7
convert example.cpp into polyapprox.cpp - made it a bit more of a generic polynomial approximator program
tweaked default range in DE::Engine
3 files changed, 82 insertions(+), 45 deletions(-)

M de.inl
D example.cpp
A polyapprox.cpp
M de.inl => de.inl +1 -1
@@ 17,7 17,7 @@ template <unsigned int DIM, unsigned int POP>
const double DE::Engine<DIM,POP>::DEFAULTCROSSOVER = 1.0;

template <unsigned int DIM, unsigned int POP>
const double DE::Engine<DIM,POP>::DEFAULTRANGE= 1000000.0;
const double DE::Engine<DIM,POP>::DEFAULTRANGE= 10.0;

template <unsigned int DIM, unsigned int POP>
const double DE::Engine<DIM,POP>::BIGDOUBLE = 1.79e308; // close to max double

D example.cpp => example.cpp +0 -44
@@ 1,44 0,0 @@
#include <cstdio>

#include "de.h"

// just a helper function used in calculating the polynomails
double Polynomial(double x, double a, double b, double c, double d)
{
	return a*(x*x*x) + b*(x*x) + c*x + d;
}

// the function we're searching for
double TargetFunction(double input)
{
	return Polynomial(input,17.0,321.0,-2.0,324.0);
}

// our DE implementation
class PolySearch: public DE::Engine<4>
{
	public:
		double CalculateError(const double testcase[4], bool& stop)
		{
			double error = 0.0;
			for ( int i=-100;i<=100;i++ )
			{
				double test   = Polynomial((double)i,testcase[0],testcase[1],testcase[2],testcase[3]);
				double actual = TargetFunction((double)i);
				error += (test-actual)*(test-actual);
			}
			if ( error < 0.00000000000001 )
			{
				stop = true;
			}
			return error;
		}
};

// main program
int main()
{
	PolySearch de;
	de.Solve();
	return 0;
}

A polyapprox.cpp => polyapprox.cpp +81 -0
@@ 0,0 1,81 @@
#include <cstdio>
#include <cmath>

#include "de.h"

// the order of the polynomial (actually the number of coefficients, i.e. 1 = constant, 2 = line, etc.)
#define NUM_COEFFICIENTS 3

// the function we're searching for
double TargetFunction(double x)
{
	//return 1.0 / (1.0 + exp(-4.9*x));               // Ken Stanley's NEAT activation
	//return (1.0 / (1.0 + exp(-4.9*x)) - 0.5) * 2.0; // " " (signed version)
	//return (1.0 / (1.0 + exp(-x)) - 0.5) * 2.0;     // signed sigmoid
	//return exp(-x*x);                               // gaussian
	//return tanh(x);                                 // tanh
	//return (2.0/(1.0+exp(-x))-1.0);                 // tanh approximation
	return (x<0.0 ? -1.0 : 1.0) * sqrt(abs(x));     // signed root
}


// a helper function used in calculating the polynomials
double CalculatePolynomial(double x, int n_coeffs, const double coeffs[])
{
	double accum = 0.0;
	double xmul  = 1.0;
	for (int i = n_coeffs-1; i>=0; --i)
	{
		accum += xmul * coeffs[i];
		xmul *= x;
	}
	return accum;
}


// our DE implementation
class PolySearch: public DE::Engine<NUM_COEFFICIENTS>
{
	public:
		// this method is called by the DE::Engine::Solve() to test a single DE individual
		double CalculateError(const double testcase[NUM_COEFFICIENTS], bool& stop)
		{
			double       error      = 0.0;
			unsigned int test_count = 0;

			// accumulate squared error
			for ( double i=-1.5;i<=1.5;i+=0.01 )
			{
				// test
				double test   = CalculatePolynomial(i,NUM_COEFFICIENTS,testcase);
				double actual = TargetFunction(i);

				// accumulate error^2
				error += (test-actual)*(test-actual);

				// inc test count (divisor to get from SE to MSE)
				test_count++;
			}

			// convert SE to RMSE
			error = sqrt(error / (double)test_count);

			// set stop flag if the error is really low
			if ( error < 0.0000001 )
			{
				stop = true;
			}

			// done
			return error;
		}
};


// main program
int main()
{
	PolySearch de;
	de.Solve(1000);
	return 0;
}