| @@ -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 | |||
| } | |||