#include #include #include #include #include #include #include using namespace std; using namespace __gnu_cxx; int cost[13][3] = { { 2, 2, 0 }, { 6, 6, 0 }, { 3, 1, 0 }, { 6, 4, 0 }, { 20, 7, 2 }, { 40, 20, 0 }, { 10, 20, 10 }, { 10, 5, 2 }, { 0, 1, 0 }, { 50, 25, 15 }, { 0, 2, 1 }, { 60, 50, 15 }, { 5000, 4000, 1000 } }; int max_fleet_value_def = 1000; int max_fleet_value_att = 4000; int ind_per_gen = 50; int max_gen = 100; int mutation_rate = 25; int num_simus = 50; pthread_mutex_t p_mutex; class Indiv { public: Indiv(int *); ~Indiv(); double calc_fitness(); void build_ships(); void build_ships(bool); char *get_ships_str(); char *get_prop_str(); int fleet_value(); Indiv *dup(); void recombine(); void recombine(Indiv *); double fitness; int *prop; int *ships; char *ships_str; char *prop_str; }; class ThreadArg { public: list::iterator it, it2; }; Indiv *enemy; list population; Indiv::Indiv(int *prop) { this->prop = prop; ships = NULL; fitness = 0; ships_str = NULL; prop_str = NULL; } Indiv::~Indiv() { if (ships) delete[] ships; if (ships_str) delete[] ships_str; if (prop_str) delete[] prop_str; if (prop) delete[] prop; } Indiv *Indiv::dup() { Indiv *dup = new Indiv(prop); dup->fitness = fitness; int *old_prop = prop; int *new_prop = new int[13]; int i; for (i = 0; i <= 12; i++) new_prop[i] = old_prop[i]; dup->prop = new_prop; return dup; } void Indiv::build_ships() { build_ships(false); } void Indiv::build_ships (bool enemy) { int i; if (!ships) ships = new int[13]; for (i = 0; i <= 12; i++) ships[i] = (prop[i]*(enemy ? max_fleet_value_def : max_fleet_value_att)/100) / (cost[i][0] + cost[i][1] + cost[i][2]); } char *Indiv::get_ships_str() { if (!ships) return NULL; if (!ships_str) ships_str = new char[256]; bzero(ships_str, 256); int i; char tmp[16]; for (i = 0; i <= 12; i++) { sprintf(tmp, "%d ", ships[i]); strcat(ships_str, tmp); } return ships_str; } char *Indiv::get_prop_str() { if (!prop_str) prop_str = new char[256]; bzero(prop_str, 256); int i; char tmp[16]; for (i = 0; i <= 12; i++) { sprintf(tmp, "%d ", prop[i]); strcat(prop_str, tmp); } return prop_str; } int Indiv::fleet_value() { if (!ships) return 0; int i, value = 0; for (i = 0; i <= 12; i++) value += ships[i] * (cost[i][0] + cost[i][1] + cost[i][2]); return value; } double Indiv::calc_fitness() { FILE *fp; char exec[256]; char output[65536]; int readbytes = 0; Indiv *opponent = enemy->dup(); opponent->build_ships(true); sprintf(exec, "/home/target0/DEV/average_f.pl %s%s0 0 0 0 0 0 0 0 0 0 0 0 0 0 %d", get_ships_str(), opponent->get_ships_str(), num_simus); int att_value_before = fleet_value(); int def_value_before = opponent->fleet_value(); char *lastround; if ((fp = popen(exec, "r")) == NULL) { perror("popen"); delete opponent; return -2; } bzero(output, 65536); while (!feof(fp)) { readbytes = strlen(output); fgets(output+readbytes, (65536 - readbytes), fp); } pclose(fp); *(strchr(output, '\n')) = '\0'; lastround = output; unsigned int cutAt, i; std::vector v; std::string tempstr = (char *)lastround; while ((cutAt = tempstr.find_first_of(" ")) != tempstr.npos) { if (cutAt > 0) { v.push_back(tempstr.substr(0, cutAt)); } tempstr = tempstr.substr(cutAt + 1); } if (tempstr.length() > 0) { v.push_back(tempstr); } for (i = 0; i <= 12; i++) ships[i] = atoi(v[i].c_str()); for (i = 13; i <= 25; i++) opponent->ships[i-13] = atoi(v[i].c_str()); int att_value_after = fleet_value(); int def_value_after = opponent->fleet_value(); double att_loss = att_value_before - att_value_after; double def_loss = def_value_before - def_value_after; /* printf("\n==================\n"); printf("input is %s\n", exec); printf("lastround is %s\n", lastround); printf("att loss = %lf (%d - %d), def loss = %lf (%d - %d)\n", att_loss, att_value_before, att_value_after, def_loss, def_value_before, def_value_after); printf("=================\n");*/ if (att_value_before == 0) return (fitness = 0); if (att_loss == 0) return (fitness = -1); fitness = ((double)(def_loss / att_loss)); delete opponent; return fitness; } void Indiv::recombine() { int prop1, mutation, i; prop1 = random() % 12; mutation = random() % 100; if (prop[prop1] + mutation > 100) mutation = 100 - prop[prop1]; for (i = 0; i < 12; i++) { /* XXX enable/disable EN */ if (i != prop1 && (prop[i] - mutation) >= 0) { prop[prop1] += mutation; prop[i] -= mutation; if (prop[i] < 0) { printf("OMG NEGATIVE VALUE (%d)\n", prop[i]); exit(0); } break; } } } void Indiv::recombine(Indiv *ind) { int prop1, prop2, old_prop; prop1 = random() % 12; prop2 = random() % 12; old_prop = prop[prop1]; prop[prop1] = ind->prop[prop2]; ind->prop[prop2] = old_prop; } bool compare (Indiv *a, Indiv *b) { if (a->fitness > b->fitness) return true; /* tri par ordre décroissant */ return false; } void *mt_init_pop (void *) { int *new_prop, pavail, j; Indiv *ind; new_prop = new int[13]; pavail = 100; for (j = 0; j <= 12; j++) { new_prop[j] = random()%pavail; pavail -= new_prop[j]; } new_prop[12] = 0; //XXX enable/disable EN if (pavail < 0) { printf("pavail < 0\n"); exit(0); } ind = new Indiv(new_prop); ind->build_ships(); ind->calc_fitness(); pthread_mutex_lock(&p_mutex); population.push_back(ind); pthread_mutex_unlock(&p_mutex); return NULL; } void *mt_gen_off (void *arg) { ThreadArg *t_arg = (ThreadArg *)arg; Indiv *ind; list::iterator it, it2; it = t_arg->it; it2 = t_arg->it2; ind = *it2; delete ind; ind = (*it)->dup(); ind->recombine(); ind->build_ships(); ind->calc_fitness(); pthread_mutex_lock(&p_mutex); *it2 = ind; pthread_mutex_unlock(&p_mutex); delete t_arg; return NULL; } int main() { int *enemy_prop = new int[13]; enemy_prop[0] = 0; //8; enemy_prop[1] = 0; enemy_prop[2] = 0; //34; enemy_prop[3] = 0; //39; enemy_prop[4] = 0; //19; enemy_prop[5] = 0; enemy_prop[6] = 0; enemy_prop[7] = 0; enemy_prop[8] = 0; enemy_prop[9] = 0; enemy_prop[10] = 0; enemy_prop[11] = 100; //0; enemy_prop[12] = 0; enemy = new Indiv(enemy_prop); enemy->build_ships(true); srandom(time(NULL)); int i; Indiv *ind; pthread_t t[ind_per_gen]; printf("Generating initial population... "); fflush(stdout); for (i = 0; i < ind_per_gen; i++) { if ((pthread_create(&t[i], NULL, mt_init_pop, NULL)) != 0) { perror("pthread_create"); exit(0); } printf("%d ", i); fflush(stdout); } for (i = 0; i < ind_per_gen; i++) { if ((pthread_join(t[i], NULL)) != 0) { perror("pthread_join"); exit(0); } } printf("done.\n"); population.sort(compare); list::iterator it, it2; int gen; double last_best = 0; for (gen = 0; gen < max_gen; gen++) { printf("Generation %d : ", gen); for (i = 0, it = population.begin(); i < ind_per_gen; i++, it++) printf("%lf (%d) ", (*it)->fitness, i); printf("\n"); it2 = population.end(); it2--; printf("Generating offspring... "); fflush(stdout); pthread_t t2[mutation_rate]; for (i = 0, it = population.begin(); i < mutation_rate; i++, it++, it2--) { ThreadArg *t_arg = new ThreadArg; t_arg->it = it; t_arg->it2 = it2; if ((pthread_create(&t2[i], NULL, mt_gen_off, (void *)t_arg)) != 0) { perror("pthread_create"); exit(0); } printf("%d ", i); fflush(stdout); } for (i = 0; i < mutation_rate; i++) { if ((pthread_join(t2[i], NULL)) != 0) { perror("pthread_join"); exit(0); } } printf("done\n"); population.sort(compare); last_best = (*population.begin())->fitness; } it = population.begin(); ind = *it; printf("Best ranked individual with fitness %lf is : %s\n", ind->fitness, ind->get_prop_str()); delete enemy; return 0; }