#include <iostream> | |||||
#include <cstdlib> | |||||
#include <ctime> | |||||
#include <numeric> | |||||
#include <algorithm> | |||||
#include <vector> | |||||
#include <random> | |||||
using namespace std; | |||||
class MasterMind { | |||||
public: | |||||
MasterMind(int nb_colors, int nb_cases) { | |||||
m_nb_colors = nb_colors; | |||||
m_nb_cases = nb_cases; | |||||
m_solution = random_candidate(); | |||||
} | |||||
MasterMind(int nb_colors, int nb_cases, int* solution) { | |||||
m_nb_colors = nb_colors; | |||||
m_nb_cases = nb_cases; | |||||
m_solution = solution; | |||||
} | |||||
int* random_candidate() { | |||||
int* cand = new int[m_nb_cases]; | |||||
for(int i=0; i<m_nb_cases; i++) | |||||
cand[i] = (rand() % m_nb_colors); | |||||
return cand; | |||||
} | |||||
int try_candidate(int* candidate){ | |||||
int total = 0; | |||||
for(int i=0; i<m_nb_cases; i++) | |||||
if(candidate[i] == m_solution[i]) | |||||
total++; | |||||
return total; | |||||
} | |||||
int get_max_radius() { | |||||
return m_nb_cases; | |||||
} | |||||
int* modify_with_radius(int* x, int r, bool copy=false) { | |||||
vector<int> items(m_nb_cases); | |||||
iota(items.begin(), items.end(), 0); | |||||
mt19937 rng(std::random_device{}()); | |||||
shuffle(begin(items), end(items), rng); | |||||
int* x2 = x; | |||||
if(copy) { | |||||
x2 = new int[m_nb_cases]; | |||||
for(int i=0; i<m_nb_cases; i++) | |||||
x2[i] = x[i]; | |||||
} | |||||
for(int i=0; i<r; i++) | |||||
x2[items[i]] = rand() % m_nb_colors; | |||||
return x2; | |||||
} | |||||
bool is_optimal(int* x) { | |||||
int v_x = try_candidate(x); | |||||
return (v_x == m_nb_cases); | |||||
} | |||||
bool is_optimal(int* x, int v_x) { | |||||
return (v_x == m_nb_cases); | |||||
} | |||||
private: | |||||
int m_nb_colors; | |||||
int m_nb_cases; | |||||
int* m_solution; | |||||
}; | |||||
struct Result { | |||||
Result(int* s, int v, int c) { | |||||
solution = s; | |||||
v_solution = v; | |||||
nb_calls = c; | |||||
} | |||||
int* solution; | |||||
int v_solution; | |||||
int nb_calls; | |||||
}; | |||||
class SearchHeuristic { | |||||
public: | |||||
virtual Result run() = 0; | |||||
void set_problem(MasterMind* problem) { | |||||
m_problem = problem; | |||||
} | |||||
protected: | |||||
MasterMind* m_problem; | |||||
}; | |||||
struct Candidate { | |||||
Candidate(int* s, int v) { | |||||
sol = s; | |||||
value = v; | |||||
} | |||||
int* sol; | |||||
int value; | |||||
}; | |||||
class RLS : public SearchHeuristic { | |||||
public: | |||||
Result run() { | |||||
MasterMind* pb = m_problem; | |||||
int* x = pb->random_candidate(); | |||||
int v_x = pb->try_candidate(x); | |||||
int nb_calls = 1; | |||||
while(! pb->is_optimal(x, v_x)) { | |||||
int r = 1; | |||||
int* y = pb->modify_with_radius(x, r, true); | |||||
int v_y = pb->try_candidate(y); | |||||
if(v_y >= v_x) { | |||||
delete[] x; | |||||
x = y; | |||||
v_x = v_y; | |||||
} else { | |||||
delete[] y; | |||||
} | |||||
nb_calls++; | |||||
} | |||||
return Result(x, v_x, nb_calls); | |||||
} | |||||
}; | |||||
class EA : public SearchHeuristic { | |||||
public: | |||||
EA(double proba, int lda, int mu) { | |||||
m_proba = proba; | |||||
m_lambda = lda; | |||||
m_mu = mu; | |||||
} | |||||
Result run() { | |||||
MasterMind* pb = m_problem; | |||||
vector<Candidate> x_list; | |||||
for(int i=0; i<m_mu; i++) { | |||||
int* x = pb->random_candidate(); | |||||
int vx = pb->try_candidate(x); | |||||
x_list.push_back(Candidate(x, vx)); | |||||
} | |||||
struct { | |||||
bool operator()(Candidate a, Candidate b) const | |||||
{ | |||||
return a.value > b.value; | |||||
} | |||||
} customLess; | |||||
sort(x_list.begin(), x_list.end(), customLess); | |||||
Candidate x_best = x_list[0]; | |||||
int nb_calls = 1; | |||||
default_random_engine generator; | |||||
binomial_distribution<int> distribution(pb->get_max_radius(), m_proba); | |||||
while(! pb->is_optimal(x_best.sol, x_best.value)) { | |||||
for(int i=0; i<m_lambda; i++) { | |||||
int r = distribution(generator); | |||||
int* y = pb->modify_with_radius(x_best.sol, r, true); | |||||
int vy = pb->try_candidate(y); | |||||
x_list.push_back(Candidate(y, vy)); | |||||
} | |||||
sort(x_list.begin(), x_list.end(), customLess); | |||||
for(int i=0; i<x_list.size()-m_mu; i++) | |||||
x_list.pop_back(); | |||||
x_best = x_list[0]; | |||||
nb_calls++; | |||||
} | |||||
return Result(x_best.sol, x_best.value, nb_calls); | |||||
} | |||||
private: | |||||
double m_proba; | |||||
int m_lambda; | |||||
int m_mu; | |||||
}; | |||||
double avg_calls(SearchHeuristic& algo, MasterMind problem, int nb=100) { | |||||
int sum = 0; | |||||
for(int i=0; i<nb; i++) { | |||||
algo.set_problem(&problem); | |||||
Result res = algo.run(); | |||||
sum += res.nb_calls; | |||||
//cout << res.nb_calls << "; "; | |||||
} | |||||
return (double) sum / nb; | |||||
} | |||||
int main() { | |||||
int nb_colors = 5; | |||||
int nb_cases = 5; | |||||
srand(time(NULL)); | |||||
RLS algo1; | |||||
double avg = avg_calls(algo1, MasterMind(nb_colors, nb_cases)); | |||||
cout << "Average RLS: " << avg << endl; | |||||
EA algo2(1./nb_cases, 1, 1); | |||||
avg = avg_calls(algo2, MasterMind(nb_colors, nb_cases)); | |||||
cout << "Average EA: " << avg << endl; | |||||
cout << "=========================" << endl; | |||||
for(int n=5; n<15; n++) { | |||||
vector<double> avg_list; | |||||
vector<double> probas; | |||||
for(double p=0.05; p<0.5; p+=0.01) { | |||||
EA algo(p, 1, 1); | |||||
double avg = avg_calls(algo, MasterMind(n, n)); | |||||
avg_list.push_back(avg); | |||||
probas.push_back(p); | |||||
} | |||||
int min_ind = 0; | |||||
for(int i=1; i<avg_list.size(); i++) | |||||
if(avg_list[min_ind] > avg_list[i]) | |||||
min_ind = i; | |||||
double p_best = probas[min_ind]; | |||||
cout << n << ": " << p_best << endl; | |||||
} | |||||
return 0; | |||||
} |
import random | |||||
import numpy | |||||
## Configuration MasterMind | |||||
nb_colors = 5 | |||||
nb_cases = 5 | |||||
## Black-box | |||||
class MasterMind: | |||||
def __init__(self, nb_colors, nb_cases, solution=None): | |||||
self.nb_colors = nb_colors | |||||
self.nb_cases = nb_cases | |||||
self._solution = solution if solution else self.random_candidate() | |||||
def random_candidate(self): | |||||
import random | |||||
return [random.randrange(self.nb_colors) for _ in range(self.nb_cases)] | |||||
def try_candidate(self, candidate): | |||||
total = 0 | |||||
for i, x in enumerate(self._solution): | |||||
if candidate[i] == x: | |||||
total += 1 | |||||
return total | |||||
def get_max_radius(self): | |||||
return self.nb_cases | |||||
def modify_with_radius(self, x, r): | |||||
import random | |||||
x = x[:] | |||||
items = list(range(self.nb_cases)) | |||||
random.shuffle(items) | |||||
for i in items[:r]: | |||||
x[i] = random.randrange(self.nb_colors) | |||||
return x | |||||
def is_optimal(self, x, v_x=None): | |||||
v_x = v_x if v_x else self.try_candidate(x) | |||||
return (v_x == self.nb_cases) | |||||
class SearchHeuristic: | |||||
def set_problem(self, problem): | |||||
self.problem = problem | |||||
def run(self): | |||||
raise Exception('Not implemented !') | |||||
# Random Local Search | |||||
class RLS(SearchHeuristic): | |||||
def run(self): | |||||
pb = self.problem | |||||
x = pb.random_candidate() | |||||
v_x = pb.try_candidate(x) | |||||
nb_calls = 1 | |||||
while not pb.is_optimal(x, v_x): | |||||
r = 1 | |||||
y = pb.modify_with_radius(x, r) | |||||
v_y = pb.try_candidate(y) | |||||
if v_y >= v_x: | |||||
x = y | |||||
v_x = v_y | |||||
nb_calls += 1 | |||||
return (x, v_x, nb_calls) | |||||
class EA(SearchHeuristic): | |||||
def __init__(self, proba, lda, mu): | |||||
self.proba = proba | |||||
self.lda = lda | |||||
self.mu = mu | |||||
def run(self): | |||||
pb = self.problem | |||||
x_list = [] | |||||
for _ in range(self.mu): | |||||
x = pb.random_candidate() | |||||
vx = pb.try_candidate(x) | |||||
x_list.append((x, vx)) | |||||
x_list = sorted(x_list, key=lambda x: x[1], reverse=True) | |||||
x_best = x_list[0] | |||||
nb_calls = 1 | |||||
while not pb.is_optimal(x_best[0], x_best[1]): | |||||
y_list = [] | |||||
for _ in range(self.lda): | |||||
r = numpy.random.binomial(pb.get_max_radius(), self.proba) | |||||
y = pb.modify_with_radius(x_best[0], r) | |||||
vy = pb.try_candidate(y) | |||||
y_list.append((y, vy)) | |||||
#print(x_list, y_list) | |||||
selection = x_list + y_list | |||||
selection = sorted(selection, key=lambda x: x[1], reverse=True) | |||||
x_list = selection[:self.mu] | |||||
x_best = x_list[0] | |||||
nb_calls += 1 | |||||
return (x_best[0], x_best[1], nb_calls) | |||||
def avg_calls(algo, problem, nb=100): | |||||
nb_calls_list = [] | |||||
for _ in range(100): | |||||
algo.set_problem(problem) | |||||
_, _, nb_calls = algo.run() | |||||
nb_calls_list.append(nb_calls) | |||||
return numpy.mean(nb_calls_list) | |||||
## Main | |||||
avg = avg_calls(RLS(), MasterMind(nb_colors, nb_cases)) | |||||
print('Average RLS: %s' % avg) | |||||
avg = avg_calls(EA(1./nb_cases, 1, 1), MasterMind(nb_colors, nb_cases)) | |||||
print('Average EA: %s' % avg) | |||||
print('=================') | |||||
probas = list(numpy.arange(0.05, 0.5, 0.01)) | |||||
p_best_list = [] | |||||
for n in range(5, 15): | |||||
avg_list = [] | |||||
for p in probas: | |||||
avg = avg_calls(EA(p, 1, 1), MasterMind(n, n)) | |||||
avg_list.append(avg) | |||||
#print('{}%'.format(int(p*100))) | |||||
p_best = probas[numpy.argmin(avg_list)] | |||||
p_best *= n | |||||
p_best_list.append(p_best) | |||||
print('{}: {}'.format(n, p_best)) | |||||
from matplotlib import pyplot as plt | |||||
x = list(range(5, 15)) | |||||
y = p_best_list | |||||
plt.plot(x, y) | |||||
plt.savefig('foo3.png') |
#ifndef EA_H | |||||
#define EA_H | |||||
#include <iostream> | |||||
#include <vector> | |||||
#include <algorithm> | |||||
#include <random> | |||||
#include "SearchHeuristic.h" | |||||
class EA : public SearchHeuristic | |||||
{ | |||||
public: | |||||
EA(double proba, int lda, int mu, std::default_random_engine& randomizer); | |||||
void prepare_tab(); | |||||
Result run(); | |||||
virtual ~EA(); | |||||
protected: | |||||
double m_proba; | |||||
int m_lambda; | |||||
int m_mu; | |||||
std::default_random_engine m_randomizer; | |||||
std::binomial_distribution<int> m_binomial_dist; | |||||
bool m_is_prepared; | |||||
Candidate** x_tab; | |||||
private: | |||||
}; | |||||
#endif // EA_H |
#ifndef MASTERMIND_H | |||||
#define MASTERMIND_H | |||||
#include <iostream> | |||||
#include <ctime> | |||||
#include <random> | |||||
#include <vector> | |||||
#include <algorithm> | |||||
class MasterMind | |||||
{ | |||||
public: | |||||
MasterMind(int nb_colors, int nb_cases, std::default_random_engine& randomizer); | |||||
MasterMind(int nb_colors, int nb_cases, int* solution, std::default_random_engine& randomizer); | |||||
void set_new_random_solution(); | |||||
int* get_random_candidate(); | |||||
void display_candidate(int *x); | |||||
int try_candidate(int* candidate); | |||||
int get_max_radius(); | |||||
int* modify_with_radius(int* x, int r); | |||||
int* crossover(int* y, int** x, int nb); | |||||
void copy_candidate(int *x, int *y); | |||||
bool is_optimal(int* x); | |||||
bool is_optimal(int* x, int v_x); | |||||
virtual ~MasterMind(); | |||||
protected: | |||||
private: | |||||
int m_nb_colors; | |||||
int m_nb_cases; | |||||
int* m_solution; | |||||
bool m_random_solution; | |||||
std::vector<int> m_permutation; | |||||
std::default_random_engine m_randomizer; | |||||
}; | |||||
#endif // MASTERMIND_H |
#ifndef RLS_H | |||||
#define RLS_H | |||||
#include <iostream> | |||||
#include "SearchHeuristic.h" | |||||
class RLS : public SearchHeuristic | |||||
{ | |||||
public: | |||||
Result run(); | |||||
protected: | |||||
private: | |||||
}; | |||||
#endif // RLS_H |
#ifndef SEARCHHEURISTIC_H | |||||
#define SEARCHHEURISTIC_H | |||||
#include "MasterMind.h" | |||||
struct Candidate { | |||||
Candidate(int* s, int v) { | |||||
sol = s; | |||||
value = v; | |||||
} | |||||
int* sol; | |||||
int value; | |||||
}; | |||||
struct { | |||||
bool operator()(Candidate* a, Candidate* b) const { | |||||
return a->value > b->value; | |||||
} | |||||
} cmp_candidates; | |||||
struct Result { | |||||
Result(int* s, int v, int c) { | |||||
solution = s; | |||||
v_solution = v; | |||||
nb_calls = c; | |||||
} | |||||
int* solution; | |||||
int v_solution; | |||||
int nb_calls; | |||||
}; | |||||
class SearchHeuristic | |||||
{ | |||||
public: | |||||
SearchHeuristic(); | |||||
virtual Result run() = 0; | |||||
void set_problem(MasterMind* problem); | |||||
virtual ~SearchHeuristic(); | |||||
protected: | |||||
MasterMind* m_problem; | |||||
private: | |||||
}; | |||||
#endif // SEARCHHEURISTIC_H |
#ifndef ANALYSIS_H_INCLUDED | |||||
#define ANALYSIS_H_INCLUDED | |||||
#include <iostream> | |||||
#include <chrono> | |||||
#include <vector> | |||||
#include "SearchHeuristic.h" | |||||
std::chrono::time_point<std::chrono::system_clock> start_chrono() { | |||||
return std::chrono::system_clock::now(); | |||||
} | |||||
std::chrono::time_point<std::chrono::system_clock> stop_chrono() { | |||||
return std::chrono::system_clock::now(); | |||||
} | |||||
int interval_chrono(std::chrono::time_point<std::chrono::system_clock> start, std::chrono::time_point<std::chrono::system_clock> stop) { | |||||
return std::chrono::duration_cast<std::chrono::milliseconds>(stop-start).count(); | |||||
} | |||||
struct Statistic { | |||||
Statistic(double avg, double mini, double maxi, double med, double dev) : | |||||
average{avg}, minimal{mini}, maximal{maxi}, median{med}, deviation{dev} {}; | |||||
double average; | |||||
double minimal; | |||||
double maximal; | |||||
double median; | |||||
double deviation; | |||||
}; | |||||
Statistic avg_calls(SearchHeuristic& algo, MasterMind problem, int nb=100) { | |||||
std::vector<double> data; | |||||
Statistic stat(0,0,0,0,0); | |||||
for(int i=0; i<nb; i++) { | |||||
algo.set_problem(&problem); | |||||
Result res = algo.run(); | |||||
delete[] res.solution; | |||||
data.push_back(res.nb_calls); | |||||
stat.average += res.nb_calls; | |||||
if(i == 0) { | |||||
stat.minimal = res.nb_calls; | |||||
stat.maximal = res.nb_calls; | |||||
} | |||||
if(res.nb_calls > stat.maximal) | |||||
stat.maximal = res.nb_calls; | |||||
if(res.nb_calls < stat.minimal) | |||||
stat.minimal = res.nb_calls; | |||||
} | |||||
stat.average /= nb; | |||||
for(int i=0; i<nb; i++) | |||||
stat.deviation += pow(data[i] - stat.average, 2); | |||||
stat.deviation = sqrt(stat.deviation/nb); | |||||
return stat; | |||||
} | |||||
#endif // ANALYSIS_H_INCLUDED |
#ifndef SCRIPTS_H_INCLUDED | |||||
#define SCRIPTS_H_INCLUDED | |||||
#include <vector> | |||||
#include "analysis.h" | |||||
using namespace std; | |||||
void optimal_proba(int n_initial, int n_final, std::default_random_engine& randomizer, double p_init=0.05, double p_final=0.5, double p_step=0.01) { | |||||
for(int n=n_initial; n<n_final; n++) { | |||||
vector<double> avg_list; | |||||
vector<double> probas; | |||||
auto start = start_chrono(); | |||||
for(double p=p_init; p<p_final; p+=p_step) { | |||||
EA algo(p, 1, 1, randomizer); | |||||
Statistic stat = avg_calls(algo, MasterMind(n, n, randomizer)); | |||||
double avg = stat.average; | |||||
avg_list.push_back(avg); | |||||
probas.push_back(p); | |||||
} | |||||
auto stop = stop_chrono(); | |||||
int elapsed_milliseconds = interval_chrono(start, stop); | |||||
int min_ind = 0; | |||||
for(int i=1; i<avg_list.size(); i++) | |||||
if(avg_list[min_ind] > avg_list[i]) | |||||
min_ind = i; | |||||
double p_best = probas[min_ind]; | |||||
cout << "n=" << n << ": " << p_best << " in " << elapsed_milliseconds/1000. << " seconds " << "(" << 100*floor((p_final-p_init)/p_step) << " problems)" << endl; | |||||
} | |||||
} | |||||
#endif // SCRIPTS_H_INCLUDED |
#include <iostream> | |||||
#include <cstdlib> | |||||
#include <ctime> | |||||
#include <numeric> | |||||
#include <algorithm> | |||||
#include <vector> | |||||
#include <random> | |||||
#include <chrono> | |||||
#include <cmath> | |||||
#include <windows.h> | |||||
#include <limits> | |||||
#include "EA.h" | |||||
#include "RLS.h" | |||||
#include "analysis.h" | |||||
#include "scripts.h" | |||||
using namespace std; | |||||
int main() { | |||||
int nb_colors = 16; | |||||
int nb_cases = 16; | |||||
srand(time(NULL)); | |||||
std::default_random_engine randomizer{static_cast<long unsigned int>(time(0))}; | |||||
auto start2 = start_chrono(); | |||||
RLS algo1; | |||||
Statistic stat1 = avg_calls(algo1, MasterMind(nb_colors, nb_cases, randomizer), 4500); | |||||
cout << "Average RLS: " << stat1.average << endl; | |||||
EA algo2(1./nb_cases, 1, 1, randomizer); | |||||
Statistic stat2 = avg_calls(algo2, MasterMind(nb_colors, nb_cases, randomizer), 4500); | |||||
cout << "Average EA: " << stat2.average << endl; | |||||
auto stop2 = stop_chrono(); | |||||
int elapsed_milliseconds2 = interval_chrono(start2, stop2); | |||||
cout << " ... executed in " << elapsed_milliseconds2/1000. << " seconds" << endl; | |||||
for(int u=0; u<3; u++) | |||||
Beep(1568, 200); | |||||
cout << "=========================" << endl; | |||||
//optimal_proba(5,15, randomizer); | |||||
double p_init=0.05; | |||||
double p_final=0.5; | |||||
double p_step=0.01; | |||||
int nb_diff_proba = floor((p_final-p_init)/p_step); | |||||
int exploration_phase = 1000; | |||||
int exploitation_phase = 10000; | |||||
double initial_value = 50; | |||||
int nb_test = 20; | |||||
for(int n=2; n<15; n++) { | |||||
auto start_n = start_chrono(); | |||||
double* tab = new double[nb_diff_proba]; | |||||
for(int i=0; i<nb_diff_proba; i++) | |||||
tab[i] = initial_value; | |||||
double max_weight = initial_value; | |||||
int max_weight_ind_proba = 0; | |||||
double second_weight = initial_value; | |||||
double second_weight_ind_proba = 1; | |||||
for(int num_loop=1; second_weight + 2*initial_value > max_weight; num_loop++) { | |||||
auto start_loop = start_chrono(); | |||||
int nb_solved_problems = 0; | |||||
for(int k=0; k<20; k++) { | |||||
double min_avg = -1; | |||||
double min_proba; | |||||
for(double p=p_init; p<p_final; p+=p_step) { | |||||
int ind = round((p - p_init)/p_step); | |||||
double execution_proba = 0; | |||||
if(ind > 0 && ind < nb_diff_proba-1) | |||||
execution_proba = ((tab[ind-1]+tab[ind]+tab[ind+1])/3)/max_weight; | |||||
else if(ind > 0) | |||||
execution_proba = ((tab[ind-1] + tab[ind])/2)/max_weight; | |||||
else if(ind < nb_diff_proba-1) | |||||
execution_proba = ((tab[ind] + tab[ind+1])/2)/max_weight; | |||||
execution_proba = (2*execution_proba > 1) ? -4*pow(execution_proba, 2)+8*execution_proba-3 : 0; | |||||
std::bernoulli_distribution distribution(execution_proba); | |||||
if(distribution(randomizer)) { | |||||
EA algo(p, 1, 1, randomizer); | |||||
Statistic stat = avg_calls(algo, MasterMind(n, n, randomizer), nb_test); | |||||
double avg = stat.average; | |||||
if(min_avg < 0 || min_avg > avg) { | |||||
min_avg = avg; | |||||
min_proba = p; | |||||
} | |||||
nb_solved_problems += nb_test; | |||||
} | |||||
} | |||||
int ind_p = round((min_proba - p_init)/p_step); | |||||
tab[ind_p]++; | |||||
if(tab[ind_p] > max_weight) { | |||||
max_weight = tab[ind_p]; | |||||
max_weight_ind_proba = ind_p; | |||||
} | |||||
} | |||||
auto stop_loop = stop_chrono(); | |||||
int elapsed_milliseconds_loop = interval_chrono(start_n, stop_loop); | |||||
second_weight = -1; | |||||
for(int i=0; i<nb_diff_proba; i++) | |||||
if(i != max_weight_ind_proba) | |||||
if(second_weight < 0 || second_weight < tab[i]) { | |||||
second_weight = tab[i]; | |||||
second_weight_ind_proba = i; | |||||
} | |||||
cout << "\r"; | |||||
cout << "n=" << n << ", num_loop=" << num_loop << ": "; | |||||
cout << p_init+max_weight_ind_proba*p_step << " (" << max_weight << "), "; | |||||
cout << p_init+second_weight_ind_proba*p_step << " (" << second_weight << "), "; | |||||
cout << "executed in " <<elapsed_milliseconds_loop/1000. << " seconds [" << nb_solved_problems << "]"; | |||||
cout << " "; | |||||
} | |||||
//cout << endl; | |||||
//for(int i=0; i<nb_diff_proba; i++) | |||||
// cout << p_init+i*p_step << ": " << tab[i]-initial_value << endl; | |||||
auto stop_n = stop_chrono(); | |||||
int elapsed_milliseconds_n = interval_chrono(start_n, stop_n); | |||||
cout << '\r' << "n=" << n << ", p_best=" << p_init+max_weight_ind_proba*p_step << ", executed in " << elapsed_milliseconds_n/1000. << " seconds"; | |||||
cout << " " << endl; | |||||
for(int u=0; u<3; u++) | |||||
Beep(1568, 200); | |||||
} | |||||
cout << "FINISHED !" << endl; | |||||
std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n'); | |||||
std::cin.get(); | |||||
return 0; | |||||
cout << "=========================" << endl; | |||||
for(int n=5; n<6; n++) { | |||||
vector<double> avg_list; | |||||
vector<double> lambdas; | |||||
int lambda_init = 1; | |||||
int lambda_final = 20; | |||||
int nb_tests = 10000; | |||||
auto start = start_chrono(); | |||||
for(int lambda=lambda_init; lambda<lambda_final; lambda++) { | |||||
EA algo(1./n, lambda, 1, randomizer); | |||||
Statistic stat = avg_calls(algo, MasterMind(n, n, randomizer), nb_tests); | |||||
double avg = stat.average; | |||||
avg_list.push_back(avg); | |||||
lambdas.push_back(lambda); | |||||
cout << " -> lambda=" << lambda << ", nbcalls=" << avg << endl; | |||||
} | |||||
auto stop = stop_chrono(); | |||||
int elapsed_milliseconds = interval_chrono(start, stop); | |||||
int min_ind = 0; | |||||
for(int i=1; i<avg_list.size(); i++) | |||||
if(avg_list[min_ind] > avg_list[i]) | |||||
min_ind = i; | |||||
double lambda_best = lambdas[min_ind]; | |||||
cout << "n=" << n << ": " << lambda_best << " in " << elapsed_milliseconds/1000. << " seconds " << "(" << nb_tests*(lambda_final-lambda_init) << " problems)" << endl; | |||||
} | |||||
return 0; | |||||
} |
<?xml version="1.0" encoding="UTF-8" standalone="yes" ?> | |||||
<CodeBlocks_project_file> | |||||
<FileVersion major="1" minor="6" /> | |||||
<Project> | |||||
<Option title="mm-cpp" /> | |||||
<Option pch_mode="2" /> | |||||
<Option compiler="gcc" /> | |||||
<Build> | |||||
<Target title="Debug"> | |||||
<Option output="bin/Debug/mm-cpp" prefix_auto="1" extension_auto="1" /> | |||||
<Option object_output="obj/Debug/" /> | |||||
<Option type="1" /> | |||||
<Option compiler="gcc" /> | |||||
<Compiler> | |||||
<Add option="-std=c++11" /> | |||||
<Add option="-g" /> | |||||
<Add directory="include" /> | |||||
</Compiler> | |||||
</Target> | |||||
<Target title="Release"> | |||||
<Option output="bin/Release/mm-cpp" prefix_auto="1" extension_auto="1" /> | |||||
<Option object_output="obj/Release/" /> | |||||
<Option type="1" /> | |||||
<Option compiler="gcc" /> | |||||
<Compiler> | |||||
<Add option="-O2" /> | |||||
<Add option="-std=c++11" /> | |||||
<Add directory="include" /> | |||||
</Compiler> | |||||
<Linker> | |||||
<Add option="-s" /> | |||||
</Linker> | |||||
</Target> | |||||
</Build> | |||||
<Compiler> | |||||
<Add option="-Wall" /> | |||||
<Add option="-fexceptions" /> | |||||
</Compiler> | |||||
<Unit filename="include/EA.h" /> | |||||
<Unit filename="include/MasterMind.h" /> | |||||
<Unit filename="include/RLS.h" /> | |||||
<Unit filename="include/SearchHeuristic.h" /> | |||||
<Unit filename="include/analysis.h" /> | |||||
<Unit filename="include/scripts.h" /> | |||||
<Unit filename="main.cpp" /> | |||||
<Unit filename="src/EA.cpp" /> | |||||
<Unit filename="src/MasterMind.cpp" /> | |||||
<Unit filename="src/RLS.cpp" /> | |||||
<Unit filename="src/SearchHeuristic.cpp" /> | |||||
<Extensions> | |||||
<code_completion /> | |||||
<envvars /> | |||||
<debugger /> | |||||
<lib_finder disable_auto="1" /> | |||||
</Extensions> | |||||
</Project> | |||||
</CodeBlocks_project_file> |
# depslib dependency file v1.0 | |||||
1578514325 source:c:\users\tfeneuil\nextcloud\apprentissage\telecom paristech\mpri\heuristiques de recherche\mastermind\mm-cpp\src\rls.cpp | |||||
"RLS.h" | |||||
1578486688 c:\users\tfeneuil\nextcloud\apprentissage\telecom paristech\mpri\heuristiques de recherche\mastermind\mm-cpp\include\rls.h | |||||
<iostream> | |||||
"SearchHeuristic.h" | |||||
1578515541 c:\users\tfeneuil\nextcloud\apprentissage\telecom paristech\mpri\heuristiques de recherche\mastermind\mm-cpp\include\searchheuristic.h | |||||
"MasterMind.h" | |||||
1578518136 c:\users\tfeneuil\nextcloud\apprentissage\telecom paristech\mpri\heuristiques de recherche\mastermind\mm-cpp\include\mastermind.h | |||||
<iostream> | |||||
<ctime> | |||||
<random> | |||||
<vector> | |||||
<algorithm> | |||||
1578485606 source:c:\users\tfeneuil\nextcloud\apprentissage\telecom paristech\mpri\heuristiques de recherche\mastermind\mm-cpp\src\searchheuristic.cpp | |||||
"SearchHeuristic.h" | |||||
1578518197 source:c:\users\tfeneuil\nextcloud\apprentissage\telecom paristech\mpri\heuristiques de recherche\mastermind\mm-cpp\src\ea.cpp | |||||
"EA.h" | |||||
1578516723 c:\users\tfeneuil\nextcloud\apprentissage\telecom paristech\mpri\heuristiques de recherche\mastermind\mm-cpp\include\ea.h | |||||
<iostream> | |||||
<vector> | |||||
<algorithm> | |||||
<random> | |||||
"SearchHeuristic.h" | |||||
1578517787 source:c:\users\tfeneuil\nextcloud\apprentissage\telecom paristech\mpri\heuristiques de recherche\mastermind\mm-cpp\src\mastermind.cpp | |||||
"MasterMind.h" | |||||
1578576187 source:c:\users\tfeneuil\nextcloud\apprentissage\telecom paristech\mpri\heuristiques de recherche\mastermind\mm-cpp\main.cpp | |||||
<iostream> | |||||
<cstdlib> | |||||
<ctime> | |||||
<numeric> | |||||
<algorithm> | |||||
<vector> | |||||
<random> | |||||
<chrono> | |||||
<cmath> | |||||
<windows.h> | |||||
<limits> | |||||
"EA.h" | |||||
"RLS.h" | |||||
"analysis.h" | |||||
"scripts.h" | |||||
1578495657 c:\users\tfeneuil\nextcloud\apprentissage\telecom paristech\mpri\heuristiques de recherche\mastermind\mm-cpp\include\analysis.h | |||||
<iostream> | |||||
<chrono> | |||||
<vector> | |||||
"SearchHeuristic.h" | |||||
1578517311 c:\users\tfeneuil\nextcloud\apprentissage\telecom paristech\mpri\heuristiques de recherche\mastermind\mm-cpp\include\scripts.h | |||||
<vector> | |||||
"analysis.h" | |||||
<?xml version="1.0" encoding="UTF-8" standalone="yes" ?> | |||||
<CodeBlocks_layout_file> | |||||
<FileVersion major="1" minor="0" /> | |||||
<ActiveTarget name="Release" /> | |||||
<File name="src\SearchHeuristic.cpp" open="1" top="0" tabpos="10" split="0" active="1" splitpos="0" zoom_1="0" zoom_2="0"> | |||||
<Cursor> | |||||
<Cursor1 position="177" topLine="0" /> | |||||
</Cursor> | |||||
</File> | |||||
<File name="main.cpp" open="1" top="1" tabpos="1" split="0" active="1" splitpos="0" zoom_1="0" zoom_2="0"> | |||||
<Cursor> | |||||
<Cursor1 position="904" topLine="24" /> | |||||
</Cursor> | |||||
</File> | |||||
<File name="src\MasterMind.cpp" open="1" top="0" tabpos="7" split="0" active="1" splitpos="0" zoom_1="-2" zoom_2="0"> | |||||
<Cursor> | |||||
<Cursor1 position="1941" topLine="48" /> | |||||
</Cursor> | |||||
</File> | |||||
<File name="src\RLS.cpp" open="1" top="0" tabpos="4" split="0" active="1" splitpos="0" zoom_1="0" zoom_2="0"> | |||||
<Cursor> | |||||
<Cursor1 position="979" topLine="0" /> | |||||
</Cursor> | |||||
</File> | |||||
<File name="include\scripts.h" open="1" top="0" tabpos="11" split="0" active="1" splitpos="0" zoom_1="0" zoom_2="0"> | |||||
<Cursor> | |||||
<Cursor1 position="725" topLine="6" /> | |||||
</Cursor> | |||||
</File> | |||||
<File name="include\EA.h" open="1" top="0" tabpos="5" split="0" active="1" splitpos="0" zoom_1="0" zoom_2="0"> | |||||
<Cursor> | |||||
<Cursor1 position="579" topLine="15" /> | |||||
</Cursor> | |||||
</File> | |||||
<File name="include\MasterMind.h" open="1" top="0" tabpos="8" split="0" active="1" splitpos="0" zoom_1="0" zoom_2="0"> | |||||
<Cursor> | |||||
<Cursor1 position="670" topLine="10" /> | |||||
</Cursor> | |||||
</File> | |||||
<File name="src\EA.cpp" open="1" top="0" tabpos="6" split="0" active="1" splitpos="0" zoom_1="0" zoom_2="0"> | |||||
<Cursor> | |||||
<Cursor1 position="818" topLine="16" /> | |||||
</Cursor> | |||||
</File> | |||||
<File name="include\analysis.h" open="1" top="0" tabpos="2" split="0" active="1" splitpos="0" zoom_1="0" zoom_2="0"> | |||||
<Cursor> | |||||
<Cursor1 position="1719" topLine="40" /> | |||||
</Cursor> | |||||
</File> | |||||
<File name="include\RLS.h" open="1" top="0" tabpos="3" split="0" active="1" splitpos="0" zoom_1="0" zoom_2="0"> | |||||
<Cursor> | |||||
<Cursor1 position="85" topLine="1" /> | |||||
</Cursor> | |||||
</File> | |||||
<File name="include\SearchHeuristic.h" open="1" top="0" tabpos="9" split="0" active="1" splitpos="0" zoom_1="0" zoom_2="0"> | |||||
<Cursor> | |||||
<Cursor1 position="349" topLine="5" /> | |||||
</Cursor> | |||||
</File> | |||||
</CodeBlocks_layout_file> |
,DESKTOP-PGFQGB5/Thibauld Feneuil,DESKTOP-PGFQGB5,09.01.2020 14:26,file:///C:/Users/tfeneuil/AppData/Roaming/OpenOffice/4; |
#include "EA.h" | |||||
EA::EA(double proba, int lda, int mu, std::default_random_engine& randomizer) { | |||||
m_proba = proba; | |||||
m_lambda = lda; | |||||
m_mu = mu; | |||||
m_randomizer = randomizer; | |||||
m_is_prepared = false; | |||||
x_tab = nullptr; | |||||
} | |||||
void EA::prepare_tab() { | |||||
if(m_is_prepared) return; | |||||
x_tab = new Candidate*[m_mu+m_lambda]; | |||||
for(int i=0; i<m_mu+m_lambda; i++) { | |||||
int* x = m_problem->get_random_candidate(); | |||||
x_tab[i] = new Candidate(x, 0); | |||||
} | |||||
m_binomial_dist = std::binomial_distribution<int>(m_problem->get_max_radius(), m_proba); | |||||
m_is_prepared = true; | |||||
} | |||||
Result EA::run() { | |||||
MasterMind* pb = m_problem; | |||||
prepare_tab(); | |||||
// Initial parents | |||||
for(int i=0; i<m_mu; i++) { | |||||
int* x = pb->get_random_candidate(); | |||||
x_tab[i]->sol = x; | |||||
x_tab[i]->value = pb->try_candidate(x); | |||||
} | |||||
std::sort(x_tab, x_tab+m_mu, cmp_candidates); | |||||
Candidate* x_best = x_tab[0]; | |||||
int nb_calls = m_mu; | |||||
while(! pb->is_optimal(x_best->sol, x_best->value)) { | |||||
for(int i=0; i<m_lambda; i++) { | |||||
int r = m_binomial_dist(m_randomizer); | |||||
Candidate* y = x_tab[m_mu+i]; | |||||
if(m_mu == 1) { | |||||
pb->copy_candidate(x_tab[0]->sol, y->sol); | |||||
} else { | |||||
//pb->crossover(y->sol, x_tab, m_mu); | |||||
} | |||||
pb->modify_with_radius(y->sol, r); | |||||
y->value = pb->try_candidate(y->sol); | |||||
} | |||||
std::sort(x_tab, x_tab+(m_mu+m_lambda), cmp_candidates); | |||||
x_best = x_tab[0]; | |||||
nb_calls += m_lambda; | |||||
} | |||||
int* final_sol = pb->get_random_candidate(); | |||||
pb->copy_candidate(x_best->sol, final_sol); | |||||
return Result(final_sol, x_best->value, nb_calls); | |||||
} | |||||
EA::~EA() { | |||||
if(m_is_prepared) { | |||||
for(int i=0, s=m_mu+m_lambda; i<s; i++) { | |||||
Candidate* y = x_tab[i]; | |||||
delete[] y->sol; | |||||
delete y; | |||||
} | |||||
delete[] x_tab; | |||||
} | |||||
} |
#include "MasterMind.h" | |||||
MasterMind::MasterMind(int nb_colors, int nb_cases, std::default_random_engine& randomizer) : | |||||
MasterMind(nb_colors, nb_cases, nullptr, randomizer) { | |||||
m_solution = get_random_candidate(); | |||||
m_random_solution = true; | |||||
}; | |||||
MasterMind::MasterMind(int nb_colors, int nb_cases, int* solution, std::default_random_engine& randomizer) : | |||||
m_nb_colors{nb_colors}, m_nb_cases{nb_cases}, m_solution{solution}, m_random_solution{false}, | |||||
m_randomizer{randomizer}, m_permutation{std::vector<int>(nb_cases)} { | |||||
iota(m_permutation.begin(), m_permutation.end(), 0); | |||||
} | |||||
void MasterMind::set_new_random_solution() { | |||||
if(m_random_solution) | |||||
delete[] m_solution; | |||||
m_solution = get_random_candidate(); | |||||
m_random_solution = true; | |||||
} | |||||
int* MasterMind::get_random_candidate() { | |||||
int* cand = new int[m_nb_cases]; | |||||
for(int i=0; i<m_nb_cases; i++) | |||||
cand[i] = (rand() % m_nb_colors); | |||||
return cand; | |||||
} | |||||
void MasterMind::display_candidate(int* x) { | |||||
std::cout << "["; | |||||
for(int i=0; i<m_nb_cases; i++) { | |||||
if(i) std::cout << ", "; | |||||
std::cout << x[i]; | |||||
} | |||||
std::cout << "]"; | |||||
} | |||||
int MasterMind::try_candidate(int* candidate) { | |||||
int total = 0; | |||||
for(int i=0; i<m_nb_cases; i++) | |||||
if(candidate[i] == m_solution[i]) | |||||
total++; | |||||
return total; | |||||
} | |||||
int MasterMind::get_max_radius() { | |||||
return m_nb_cases; | |||||
} | |||||
int* MasterMind::modify_with_radius(int* x, int r) { | |||||
std::shuffle(begin(m_permutation), end(m_permutation), m_randomizer); | |||||
std::uniform_int_distribution<int> unif(0,(m_nb_colors-1)-1); | |||||
for(int i=0; i<r; i++) { | |||||
int new_color = unif(m_randomizer); | |||||
// to force the modification of color | |||||
if(new_color == x[m_permutation[i]]) | |||||
new_color = m_nb_colors-1; | |||||
x[m_permutation[i]] = new_color; | |||||
} | |||||
return x; | |||||
} | |||||
int* MasterMind::crossover(int* y, int** x, int nb) { | |||||
std::uniform_int_distribution<int> unif(0,nb-1); | |||||
for(int i=0; i<m_nb_cases; i++) | |||||
y[i] = x[unif(m_randomizer)][i]; | |||||
} | |||||
void MasterMind::copy_candidate(int *x, int *y) { | |||||
for(int i=0; i<m_nb_cases; i++) | |||||
y[i] = x[i]; | |||||
} | |||||
bool MasterMind::is_optimal(int* x) { | |||||
int v_x = try_candidate(x); | |||||
return (v_x == m_nb_cases); | |||||
} | |||||
bool MasterMind::is_optimal(int* x, int v_x) { | |||||
return (v_x == m_nb_cases); | |||||
} | |||||
MasterMind::~MasterMind() { | |||||
if(m_random_solution) | |||||
delete[] m_solution; | |||||
} |
#include "RLS.h" | |||||
Result RLS::run() { | |||||
MasterMind* pb = m_problem; | |||||
// Solution x : the parent | |||||
int* s_x = pb->get_random_candidate(); | |||||
int v_x = pb->try_candidate(s_x); | |||||
Candidate* x = new Candidate(s_x, v_x); | |||||
// Solution y : the child | |||||
int* s_y = pb->get_random_candidate(); | |||||
Candidate* y = new Candidate(s_y, 0); | |||||
int nb_calls = 1; | |||||
// std::cout << "BEFORE LOOP..." << std::endl; | |||||
while(! pb->is_optimal(x->sol, x->value)) { | |||||
// std::cout << "ITERATION: " << x->value << std::endl; | |||||
// pb->display_candidate(x->sol); | |||||
// std::cout << std::endl; | |||||
int r = 1; | |||||
pb->copy_candidate(x->sol, y->sol); | |||||
pb->modify_with_radius(y->sol, r); | |||||
y->value = pb->try_candidate(y->sol); | |||||
// pb->display_candidate(y->sol); | |||||
// std::cout << "(" << y->value << ")" << std::endl; | |||||
if(y->value >= x->value) { | |||||
// Swap x and y | |||||
Candidate* tmp = x; | |||||
x = y; | |||||
y = tmp; | |||||
} | |||||
nb_calls++; | |||||
} | |||||
Result res(x->sol, x->value, nb_calls); | |||||
// Cleaning | |||||
delete[] y->sol; | |||||
delete y; | |||||
delete x; | |||||
return res; | |||||
} |
#include "SearchHeuristic.h" | |||||
SearchHeuristic::SearchHeuristic() | |||||
{ | |||||
//ctor | |||||
} | |||||
void SearchHeuristic::set_problem(MasterMind* problem) { | |||||
m_problem = problem; | |||||
} | |||||
SearchHeuristic::~SearchHeuristic() | |||||
{ | |||||
//dtor | |||||
} |