#ifndef __de_inl__ #define __de_inl__ #include #include #if !(defined(__de_h__)) # error "de.inl should only be included by de.h" #endif template const double DE::Engine::DEFAULTSCALE = 0.85; template const double DE::Engine::DEFAULTCROSSOVER = 1.0; template const double DE::Engine::DEFAULTRANGE= 0.1; template const double DE::Engine::BIGDOUBLE = 1.79e308; // close to max double template inline DE::Engine::Engine() { // set defaults scale = DEFAULTSCALE; crossover = DEFAULTCROSSOVER; for ( unsigned int i=0;imean[i] = 0.0; this->variance[i] = DEFAULTRANGE; } // create an initial population Reset(); return; } template inline DE::Engine::~Engine() { return; } template inline void DE::Engine::Reset() { // reset our best bestfitness = BIGDOUBLE; for ( unsigned int i=0;i inline void DE::Engine::SetRange(double minimum, double maximum) { for (unsigned int i=0;i inline void DE::Engine::SetRange(unsigned int i, double minimum, double maximum) { if (imean[i] = (maximum+minimum)/2.0; this->variance[i] = (maximum-minimum)/2.0; } return; } template inline void DE::Engine::SetRange(const Vector& minimum, const Vector& maximum) { for (unsigned int i=0;i inline const double* DE::Engine::GetBest() const { return best; } template inline void DE::Engine::Select( unsigned int candidate, unsigned int *r1, unsigned int *r2, unsigned int *r3, unsigned int *r4, unsigned int *r5 ) { if ( r1 ) { do { *r1 = prng.RandU32(0,POPSIZE-1); } while ( *r1 == candidate ); } if ( r2 ) { do { *r2 = prng.RandU32(0,POPSIZE-1); } while ( (*r2 == candidate) || (*r2 == *r1) ); } if ( r3 ) { do { *r3 = prng.RandU32(0,POPSIZE-1); } while ( (*r3 == candidate) || (*r3 == *r2) || (*r3 == *r1) ); } if ( r4 ) { do { *r4 = prng.RandU32(0,POPSIZE-1); } while ( (*r4 == candidate) || (*r4 == *r3) || (*r4 == *r2) || (*r4 == *r1) ); } if ( r5 ) { do { *r5 = prng.RandU32(0,POPSIZE-1); } while ( (*r5 == candidate) || (*r5 == *r4) || (*r5 == *r3) || (*r5 == *r2) || (*r5 == *r1) ); } return; } template inline bool DE::Engine::Solve(unsigned int maxgenerations) { // spawn a new generation Reset(); // run generations until max or success while(!success && generation bool DE::Engine::RunOneGeneration() { printf("====== GENERATION %07d =============================================\n\n",++generation); // attempt to improve each individual in the population for (int candidate=0;candidate trial; MakeTrial_randtobest1exp(candidate,trial); // determine fitness of trial individual double trialfitness = TestFitness(trial,success); // see if the trial improved current candidate in population if ( trialfitness < fitness[candidate] ) { // it did improve, save it fitness[candidate] = trialfitness; population[candidate] = trial; // see if it also improved upon our current best if ( trialfitness < bestfitness ) { // it's better than the best, save it bestfitness = trialfitness; best = trial; // output new best Dump(bestfitness,best); } } } return success; } template inline void DE::Engine::Dump(const double& fitness, DE::Vector& individual) const { printf(" fitness = %24.16f\n",fitness); for (unsigned int i=0;i inline void DE::Engine::MakeTrial_best1exp(unsigned int candidate, DE::Vector& trial) { unsigned int r1, r2; unsigned int n; Select(candidate, &r1, &r2); n = prng.RandU32(0,DIM-1); trial = population[candidate]; for (unsigned int i=0; (prng.RandDouble(0.0,1.0) < crossover) && (i < DIM); i++) { trial[n] = best[n] + scale * (population[r1][n] - population[r2][n]); n = (n + 1) % DIM; } return; } template inline void DE::Engine::MakeTrial_rand1exp(unsigned int candidate, DE::Vector& trial) { unsigned int r1, r2, r3; unsigned int n; Select(candidate, &r1, &r2, &r3); n = prng.RandU32(0,DIM-1); trial = population[candidate]; for (unsigned int i=0; (prng.RandDouble(0.0,1.0) <= crossover) && (i < DIM); i++) { trial[n] = population[r1][n] + scale * (population[r2][n] - population[r3][n]); n = (n + 1) % DIM; } return; } template inline void DE::Engine::MakeTrial_randtobest1exp(unsigned int candidate, DE::Vector& trial) { unsigned int r1, r2; unsigned int n; Select(candidate, &r1, &r2); n = prng.RandU32(0,DIM-1); trial = population[candidate]; for (unsigned int i=0; (prng.RandDouble(0.0,1.0) <= crossover) && (i < DIM); i++) { trial[n] += scale * (best[n] - trial[n]) + scale * (population[r1][n] - population[r2][n]); n = (n + 1) % DIM; } return; } template inline void DE::Engine::MakeTrial_best2exp(unsigned int candidate, DE::Vector& trial) { unsigned int r1, r2, r3, r4; unsigned int n; Select(candidate, &r1, &r2, &r3, &r4); n = prng.RandU32(0,DIM-1); trial = population[candidate]; for (unsigned int i=0; (prng.RandDouble(0.0,1.0) <= crossover) && (i < DIM); i++) { trial[n] = best[n] + scale * (population[r1][n] + population[r2][n] - population[r3][n] - population[r4][n]); n = (n + 1) % DIM; } return; } template inline void DE::Engine::MakeTrial_rand2exp(unsigned int candidate, DE::Vector& trial) { unsigned int r1, r2, r3, r4, r5; unsigned int n; Select(candidate, &r1, &r2, &r3 ,&r4, &r5); n = prng.RandU32(0,DIM-1); trial = population[candidate]; for (unsigned int i=0; (prng.RandDouble(0.0,1.0) <= crossover) && (i < DIM); i++) { trial[n] = population[r1][n] + scale * (population[r2][n] + population[r3][n] - population[r4][n] - population[r5][n]); n = (n + 1) % DIM; } return; } template inline void DE::Engine::MakeTrial_best1bin(unsigned int candidate, DE::Vector& trial) { unsigned int r1, r2; unsigned int n; Select(candidate, &r1, &r2); n = prng.RandU32(0,DIM-1); trial = population[candidate]; for (unsigned int i=0; i < DIM; i++) { if ( (prng.RandDouble(0.0,1.0) <= crossover) || (i == (DIM - 1)) ) { trial[n] = best[n] + scale * (population[r1][n] - population[r2][n]); } n = (n + 1) % DIM; } return; } template inline void DE::Engine::MakeTrial_rand1bin(unsigned int candidate, DE::Vector& trial) { unsigned int r1, r2, r3; unsigned int n; Select(candidate, &r1, &r2, &r3); n = prng.RandU32(0,DIM-1); trial = population[candidate]; for (unsigned int i=0; i < DIM; i++) { if ( (prng.RandDouble(0.0,1.0) <= crossover) || (i == (DIM - 1)) ) { trial[n] = population[r1][n] + scale * (population[r2][n] - population[r3][n]); } n = (n + 1) % DIM; } return; } template inline void DE::Engine::MakeTrial_randtobest1bin(unsigned int candidate, DE::Vector& trial) { unsigned int r1, r2; unsigned int n; Select(candidate, &r1, &r2); n = prng.RandU32(0,DIM-1); trial = population[candidate]; for (unsigned int i=0; i < DIM; i++) { if ( (prng.RandDouble(0.0,1.0) <= crossover) || (i == (DIM - 1)) ) { trial[n] += scale * (best[n] - trial[n]) + scale * (population[r1][n] - population[r2][n]); } n = (n + 1) % DIM; } return; } template inline void DE::Engine::MakeTrial_best2bin(unsigned int candidate, DE::Vector& trial) { unsigned int r1, r2, r3, r4; unsigned int n; Select(candidate, &r1, &r2, &r3, &r4); n = prng.RandU32(0,DIM-1); trial = population[candidate]; for (unsigned int i=0; i < DIM; i++) { if ( (prng.RandDouble(0.0,1.0) <= crossover) || (i == (DIM - 1)) ) { trial[n] = best[n] + scale * (population[r1][n] + population[r2][n] - population[r3][n] - population[r4][n]); } n = (n + 1) % DIM; } return; } template inline void DE::Engine::MakeTrial_rand2bin(unsigned int candidate, DE::Vector& trial) { unsigned int r1, r2, r3, r4, r5; unsigned int n; Select(candidate, &r1, &r2, &r3, &r4, &r5); n = prng.RandU32(0,DIM-1); trial = population[candidate]; for (unsigned int i=0; i < DIM; i++) { if ( (prng.RandDouble(0.0,1.0) <= crossover) || (i == (DIM - 1)) ) { trial[n] = population[r1][n] + scale * (population[r2][n] + population[r3][n] - population[r4][n] - population[r5][n]); } n = (n + 1) % DIM; } return; } template inline DE::Engine::ErrorAccumulator::ErrorAccumulator() { Clear(); } template inline DE::Engine::ErrorAccumulator::~ErrorAccumulator() { // empty } template inline void DE::Engine::ErrorAccumulator::Clear() { num_tests = 0; sum_error_squared = 0.0; error_rmse = 0.0; // initial error == zero } template inline void DE::Engine::ErrorAccumulator::AddTestCase(double expected, double actual) { double e = expected - actual; // compute error sum_error_squared += e * e; // add to sum of error^2 num_tests += 1; // increment total test count error_rmse = -1.0; // mark as dirty } template inline double DE::Engine::ErrorAccumulator::GetRMSE() { if ( error_rmse < 0.0 ) // recalculate if set to "dirty" CalculateError(); return error_rmse; } template inline void DE::Engine::ErrorAccumulator::CalculateError() { // convert squared error to root mean squared error error_rmse = ::sqrt(sum_error_squared / (double)num_tests); } #endif // __de_inl__