@@ -0,0 +1,239 @@ | |||
#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; | |||
} |
@@ -0,0 +1,141 @@ | |||
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') |
@@ -0,0 +1,33 @@ | |||
#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 |
@@ -0,0 +1,40 @@ | |||
#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 |
@@ -0,0 +1,18 @@ | |||
#ifndef RLS_H | |||
#define RLS_H | |||
#include <iostream> | |||
#include "SearchHeuristic.h" | |||
class RLS : public SearchHeuristic | |||
{ | |||
public: | |||
Result run(); | |||
protected: | |||
private: | |||
}; | |||
#endif // RLS_H |
@@ -0,0 +1,48 @@ | |||
#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 |
@@ -0,0 +1,57 @@ | |||
#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 |
@@ -0,0 +1,35 @@ | |||
#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 |
@@ -0,0 +1,173 @@ | |||
#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; | |||
} |
@@ -0,0 +1,57 @@ | |||
<?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> |
@@ -0,0 +1,61 @@ | |||
# 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" | |||
@@ -0,0 +1,60 @@ | |||
<?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> |
@@ -0,0 +1 @@ | |||
,DESKTOP-PGFQGB5/Thibauld Feneuil,DESKTOP-PGFQGB5,09.01.2020 14:26,file:///C:/Users/tfeneuil/AppData/Roaming/OpenOffice/4; |
@@ -0,0 +1,73 @@ | |||
#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; | |||
} | |||
} |
@@ -0,0 +1,87 @@ | |||
#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; | |||
} |
@@ -0,0 +1,45 @@ | |||
#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; | |||
} |
@@ -0,0 +1,15 @@ | |||
#include "SearchHeuristic.h" | |||
SearchHeuristic::SearchHeuristic() | |||
{ | |||
//ctor | |||
} | |||
void SearchHeuristic::set_problem(MasterMind* problem) { | |||
m_problem = problem; | |||
} | |||
SearchHeuristic::~SearchHeuristic() | |||
{ | |||
//dtor | |||
} |