create example dir
This commit is contained in:
1 parent
b656b251c4
commit
bcbb99be6f
3 files changed
No files matched your search
@@ -0,0 +1,82 @@
|
||||
#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 7
|
||||
|
||||
// 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
|
||||
//return sin(x); // sin
|
||||
}
|
||||
|
||||
|
||||
// a helper function used in calculating the polynomials
|
||||
double CalculatePiecewise(double x, int n_coeffs, const double coeffs[])
|
||||
{
|
||||
double abs_x = (x < 0.0 ? -x : x);
|
||||
const double* pcoeffs;
|
||||
if ( abs_x < coeffs[6] )
|
||||
pcoeffs = &coeffs[0];
|
||||
else
|
||||
pcoeffs = &coeffs[3];
|
||||
|
||||
return (pcoeffs[0] + pcoeffs[1]*abs_x + pcoeffs[2]*abs_x*abs_x) * (x < 0.0 ? -1.0 : 1.0);
|
||||
}
|
||||
|
||||
|
||||
// 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 TestFitness(const double testcase[NUM_COEFFICIENTS], bool& stop)
|
||||
{
|
||||
ErrorAccumulator e;
|
||||
|
||||
// accumulate squared error
|
||||
for ( double i=-2.5;i<=2.5;i+=0.01 )
|
||||
{
|
||||
// test
|
||||
double actual = CalculatePiecewise(i,NUM_COEFFICIENTS,testcase);
|
||||
double expected = TargetFunction(i);
|
||||
|
||||
// accumulate error
|
||||
e.AddTestCase(expected,actual);
|
||||
}
|
||||
|
||||
// set stop flag if the error is really low
|
||||
if ( e.GetRMSE() < 0.0000001 )
|
||||
{
|
||||
stop = true;
|
||||
}
|
||||
|
||||
// done
|
||||
return e.GetRMSE();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
// main program
|
||||
int main()
|
||||
{
|
||||
PolySearch de;
|
||||
|
||||
// setup, adjust from default range
|
||||
//de.SetRange(-0.1,0.1);
|
||||
|
||||
// reset, and run the DE
|
||||
de.Solve(1000);
|
||||
|
||||
// done
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,93 @@
|
||||
#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 8
|
||||
|
||||
// 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
|
||||
//return sin(x); // sin
|
||||
}
|
||||
|
||||
|
||||
// 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 TestFitness(const double testcase[NUM_COEFFICIENTS], bool& stop)
|
||||
{
|
||||
ErrorAccumulator e;
|
||||
|
||||
// accumulate squared error
|
||||
for ( double i=-1.25;i<=1.25;i+=0.001 )
|
||||
{
|
||||
// test
|
||||
double actual = CalculatePolynomial(i,NUM_COEFFICIENTS,testcase);
|
||||
double expected = TargetFunction(i);
|
||||
|
||||
// accumulate error
|
||||
e.AddTestCase(expected, actual);
|
||||
}
|
||||
|
||||
// set stop flag if the error is really low
|
||||
if ( e.GetRMSE() < 0.0000001 )
|
||||
{
|
||||
stop = true;
|
||||
}
|
||||
|
||||
// done
|
||||
return e.GetRMSE();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
// main program
|
||||
int main()
|
||||
{
|
||||
PolySearch de;
|
||||
|
||||
// setup, adjust from default range
|
||||
de.SetRange(-0.1,0.1);
|
||||
|
||||
// create new population with adjusted range
|
||||
de.Reset();
|
||||
|
||||
// run the DE
|
||||
de.Solve(1500);
|
||||
|
||||
// output winner in polynomial form
|
||||
printf("Best Polynomial Found\n=====================\ny =");
|
||||
for (int i=0;i<NUM_COEFFICIENTS-2;++i)
|
||||
{
|
||||
printf(" %0.16f*x^%d +",de.GetBest()[i],NUM_COEFFICIENTS-1-i);
|
||||
}
|
||||
printf(" %0.16f*x + %0.16f\n",de.GetBest()[NUM_COEFFICIENTS-2],de.GetBest()[NUM_COEFFICIENTS-1]);
|
||||
|
||||
// done
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,158 @@
|
||||
#include <cstdio>
|
||||
#include <vector>
|
||||
#include <algorithm>
|
||||
|
||||
#include "de.h"
|
||||
|
||||
#define MAX(a,b) ((a)>(b)?(a):(b))
|
||||
#define MIN(a,b) ((a)<(b)?(a):(b))
|
||||
#define CLAMP(min,max,x) (MAX(min,MIN(max,x)))
|
||||
|
||||
class Saboteur: public DE::Engine<16>
|
||||
{
|
||||
public:
|
||||
double TestCardMix(int players, int saboteur_cards, int digger_cards)
|
||||
{
|
||||
int total_games = 0;
|
||||
int total_saboteurs = 0;
|
||||
int total_diggers = 0;
|
||||
double saboteur_frequency = 0.0;
|
||||
|
||||
// make deck
|
||||
std::vector<int> deck;
|
||||
for (int i=0;i<saboteur_cards;++i)
|
||||
{
|
||||
deck.push_back(1);
|
||||
}
|
||||
for (int i=0;i<digger_cards;++i)
|
||||
{
|
||||
deck.push_back(0);
|
||||
}
|
||||
|
||||
const int NUM_ITER = 5000;
|
||||
for (int i=0;i<NUM_ITER;++i)
|
||||
{
|
||||
// shuffle deck
|
||||
std::random_shuffle(deck.begin(),deck.end());
|
||||
|
||||
// deal first N cards
|
||||
for (int j=0;j<players;++j)
|
||||
{
|
||||
if ( deck[j] == 1 )
|
||||
++total_saboteurs;
|
||||
}
|
||||
}
|
||||
|
||||
return ((double)total_saboteurs/(double)NUM_ITER) / (double)players;
|
||||
}
|
||||
|
||||
double TestIndividualFitness(int players, int saboteur_cards, int digger_cards, bool verbose=false)
|
||||
{
|
||||
double error_bonus = 0.0;
|
||||
if ( saboteur_cards < 1 || saboteur_cards > 4 )
|
||||
error_bonus += 1000.0;
|
||||
if ( digger_cards < 1 || digger_cards > 7 )
|
||||
error_bonus += 1000.0;
|
||||
if ( saboteur_cards >= players )
|
||||
error_bonus += 500.0;
|
||||
if ( (saboteur_cards+digger_cards) < (players+1) )
|
||||
error_bonus += 500.0;
|
||||
if ( (saboteur_cards+digger_cards) > (players+3) )
|
||||
error_bonus += 500.0;
|
||||
|
||||
if ( verbose )
|
||||
{
|
||||
printf("\n %2d players (%d, %d): ",players,saboteur_cards,digger_cards);
|
||||
}
|
||||
|
||||
if ( error_bonus > 0.0 )
|
||||
{
|
||||
if ( verbose )
|
||||
{
|
||||
printf(" ERROR! (%f)\n",error_bonus);
|
||||
}
|
||||
return error_bonus;
|
||||
}
|
||||
else
|
||||
{
|
||||
double actual = TestCardMix(players,saboteur_cards,digger_cards);
|
||||
if ( verbose )
|
||||
{
|
||||
printf(" %0.5f\n",actual);
|
||||
}
|
||||
return actual;
|
||||
}
|
||||
}
|
||||
|
||||
double TestFitness(const double testcase[16], bool& stop)
|
||||
{
|
||||
ErrorAccumulator e;
|
||||
|
||||
const int num_players[8] = { 3, 4, 5, 6, 7, 8, 9, 10 };
|
||||
const double expected = 0.363;
|
||||
//const double expected = 1.0/3.0; // saboteurs are 1:3
|
||||
|
||||
for (int i=0;i<8;++i)
|
||||
{
|
||||
int i_saboteur_cards = i * 2;
|
||||
int i_digger_cards = i_saboteur_cards + 1;
|
||||
int players = num_players[i];
|
||||
|
||||
int saboteur_cards = (int)testcase[i_saboteur_cards];
|
||||
int digger_cards = (int)testcase[i_digger_cards];
|
||||
|
||||
double actual = TestIndividualFitness(players,saboteur_cards,digger_cards);
|
||||
|
||||
e.AddTestCase(expected,actual);
|
||||
}
|
||||
|
||||
return e.GetRMSE();
|
||||
}
|
||||
};
|
||||
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
// init
|
||||
Saboteur s;
|
||||
for (int i=0;i<8;++i)
|
||||
{
|
||||
s.SetRange( i*2, 1.0, 4.0);
|
||||
s.SetRange(i*2+1, 1.0, 7.0);
|
||||
}
|
||||
s.Reset();
|
||||
|
||||
// print original
|
||||
const double original[16] = { 1,3,1,4,2,4,2,5,3,5,3,6,3,7,4,7 };
|
||||
for (int i=0;i<8;++i)
|
||||
{
|
||||
const int num_players[8] = { 3, 4, 5, 6, 7, 8, 9, 10 };
|
||||
int i_saboteur_cards = i * 2;
|
||||
int i_digger_cards = i_saboteur_cards + 1;
|
||||
int players = num_players[i];
|
||||
|
||||
int saboteur_cards = (int)original[i_saboteur_cards];
|
||||
int digger_cards = (int)original[i_digger_cards];
|
||||
|
||||
s.TestIndividualFitness(players,saboteur_cards,digger_cards,true);
|
||||
}
|
||||
|
||||
// run
|
||||
s.Solve(1000);
|
||||
|
||||
// output
|
||||
const double* best = s.GetBest();
|
||||
for (int i=0;i<8;++i)
|
||||
{
|
||||
const int num_players[8] = { 3, 4, 5, 6, 7, 8, 9, 10 };
|
||||
int i_saboteur_cards = i * 2;
|
||||
int i_digger_cards = i_saboteur_cards + 1;
|
||||
int players = num_players[i];
|
||||
|
||||
int saboteur_cards = (int)best[i_saboteur_cards];
|
||||
int digger_cards = (int)best[i_digger_cards];
|
||||
|
||||
s.TestIndividualFitness(players,saboteur_cards,digger_cards,true);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
Reference in new issue
Block a user