From b656b251c4ae507faee5228314b4fada72656460 Mon Sep 17 00:00:00 2001 From: swaits Date: Thu, 30 Sep 2010 21:36:37 +0000 Subject: [PATCH] add saboteur optimization problem. minor compile fixes. --- de.inl | 3 +- saboteur.cpp | 158 +++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 160 insertions(+), 1 deletion(-) create mode 100644 saboteur.cpp diff --git a/de.inl b/de.inl index 8ddbab2..c8221d1 100644 --- a/de.inl +++ b/de.inl @@ -3,6 +3,7 @@ #include +#include #if !(defined(__de_h__)) @@ -493,7 +494,7 @@ template inline void DE::Engine::ErrorAccumulator::CalculateError() { // convert squared error to root mean squared error - error_rmse = sqrt(sum_error_squared / (double)num_tests); + error_rmse = ::sqrt(sum_error_squared / (double)num_tests); } diff --git a/saboteur.cpp b/saboteur.cpp new file mode 100644 index 0000000..1bf44a7 --- /dev/null +++ b/saboteur.cpp @@ -0,0 +1,158 @@ +#include +#include +#include + +#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 deck; + for (int i=0;i 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; +}