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