Projet du cours MPRI 2.24.2 "Résolution de problèmes d'optimisation avec heuristiques de recherche" : https://wikimpri.dptinfo.ens-cachan.fr/doku.php?id=cours:c-2-24-2
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

scripts.h 20KB

  1. #ifndef SCRIPTS_H_INCLUDED
  2. #define SCRIPTS_H_INCLUDED
  3. #include <vector>
  4. #include "analysis.h"
  5. #include "ParameterOptimizer.h"
  6. using namespace std;
  7. class ProbaOptimizer : public ParameterOptimizer {
  8. public:
  9. ProbaOptimizer(int initial_n, std::default_random_engine& randomizer) : ParameterOptimizer(randomizer), m_initial_n{initial_n} {};
  10. SearchHeuristic* get_context(unsigned int i, double parameter, std::default_random_engine& randomizer) {
  11. EA* algo = new EA(1, 1, PLUS, parameter, randomizer);
  12. MasterMind* mm = new MasterMind(m_initial_n+i, m_initial_n+i, randomizer);
  13. algo->set_problem(mm);
  14. return algo;
  15. }
  16. virtual std::string display_context(unsigned int context) {
  17. std::stringstream ss;
  18. ss << "n=" << context+m_initial_n;
  19. return ss.str();
  20. }
  21. std::string get_context_for_csvfile(unsigned int num_context) {
  22. return std::to_string(m_initial_n+num_context);
  23. }
  24. private:
  25. int m_initial_n;
  26. };
  27. void optimal_proba_vmath3(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, vector<int> nb_tests_by_depth={}, vector<double> stq_by_depth={}) {
  28. ProbaOptimizer po(n_initial, randomizer);
  29. po.set_nb_contexts(n_final-n_initial);
  30. po.set_study_interval(p_init, p_final, p_step);
  31. for(int depth=0; depth<nb_tests_by_depth.size(); depth++)
  32. po.add_test_wave(nb_tests_by_depth[depth], stq_by_depth[depth], depth);
  33. po.run();
  34. }
  35. void script_optimal_proba(std::default_random_engine& randomizer) {
  36. std::string namefile = "optimal-proba.csv";
  37. {
  38. int n_init=3, n_final=16;
  39. double p_init=0.05, p_final=0.5, p_step=0.01;
  40. ProbaOptimizer po(n_init, randomizer);
  41. po.set_nb_contexts(n_final-n_init);
  42. po.set_study_interval(p_init, p_final, p_step);
  43. po.add_test_wave(20, 2.3362421597, 0);
  44. po.add_test_wave(200, 2.3451370823, 1);
  45. po.add_test_wave(2000, 2.2953981367, 2);
  46. po.save_run(namefile);
  47. po.run();
  48. }
  49. {
  50. int n_init=16, n_final=28;
  51. double p_init=0.03, p_final=0.2, p_step=0.01;
  52. ProbaOptimizer po(n_init, randomizer);
  53. po.set_nb_contexts(n_final-n_init);
  54. po.set_study_interval(p_init, p_final, p_step);
  55. po.add_test_wave(20, 2.6742086844, 0);
  56. po.add_test_wave(100, 2.4755765532, 1);
  57. po.add_test_wave(1000, 2.4365960683, 2);
  58. po.save_run(namefile);
  59. po.run();
  60. }
  61. {
  62. int n_init=28, n_final=46;
  63. double p_init=0.01, p_final=0.1, p_step=0.005;
  64. ProbaOptimizer po(n_init, randomizer);
  65. po.set_nb_contexts(n_final-n_init);
  66. po.set_study_interval(p_init, p_final, p_step);
  67. po.add_test_wave(20, 2.6742086844, 0);
  68. po.add_test_wave(100, 2.4755765532, 1);
  69. po.add_test_wave(1000, 2.4365960683, 2);
  70. po.save_run(namefile);
  71. po.run();
  72. }
  73. }
  74. vector<ConfidenceInterval> optimal_proba_vmath2(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, int nb_tests=10, double student_law_quartile=-1, bool displaying=true) {
  75. int nb_diff_proba = floor((p_final-p_init)/p_step);
  76. // Initialize result file
  77. ofstream probafile("probas-vmath.csv");
  78. probafile << "n;";
  79. for(int i=0; i<nb_diff_proba; i++)
  80. probafile << p_init+i*p_step << ";";
  81. probafile << endl;
  82. vector<ConfidenceInterval> res;
  83. for(int n=n_initial; n<n_final; n++) {
  84. auto start_n = start_chrono();
  85. Statistic stats[nb_diff_proba];
  86. double thresold = 0;
  87. // Realize the experiences
  88. for(int ind=0; ind<nb_diff_proba; ind++) {
  89. double p = p_init+ind*p_step;
  90. EA algo(1, 1, PLUS, p, randomizer);
  91. MasterMind mm(n, n, randomizer);
  92. algo.set_problem(&mm);
  93. stats[ind] = avg_calls(&algo, nb_tests, -1, student_law_quartile);
  94. double potential_thresold = stats[ind].average + stats[ind].alea;
  95. if(ind == 0 || thresold > potential_thresold)
  96. thresold = potential_thresold;
  97. auto stop_loop = stop_chrono();
  98. int elapsed_milliseconds_loop = interval_chrono(start_n, stop_loop);
  99. if(displaying) cout << '\r' << "n=" << n << ", p=" << p << "... executed in " << elapsed_milliseconds_loop/1000. << " s";
  100. }
  101. // Calculate the confidence interval of 95%
  102. if(displaying) cout << '\r' << "n=" << n << ". Thresold=" << thresold << ". Keep best... ";
  103. int min_possible = -1;
  104. int max_possible = -1;
  105. for(int i=0; i<nb_diff_proba; i++) {
  106. double min_bound = stats[i].average - stats[i].alea;
  107. if(min_possible < 0 && min_bound < thresold)
  108. min_possible = i;
  109. if(min_bound < thresold)
  110. max_possible = i;
  111. }
  112. double pmin = p_init+min_possible*p_step;
  113. double pmax = p_init+max_possible*p_step;
  114. // Store the results in a file
  115. probafile << n << ";";
  116. for(int i=0; i<nb_diff_proba; i++) {
  117. probafile << "("<<pmin<<","<<pmax<<")" << ";";
  118. }
  119. probafile << endl;
  120. auto stop_n = stop_chrono();
  121. int elapsed_milliseconds_n = interval_chrono(start_n, stop_n);
  122. if(displaying) cout << "Interval=[" << pmin << ", " << pmax << "]" << endl;
  123. if(displaying) cout << "... executed in " << elapsed_milliseconds_n/1000. << " seconds ";
  124. if(displaying) cout << "with " << nb_tests*nb_diff_proba << " resolutions" << endl;
  125. ConfidenceInterval ci(pmin, -1, pmax);
  126. res.push_back(ci);
  127. }
  128. return res;
  129. }
  130. vector<ConfidenceInterval> optimal_proba_vmath2_rec(int n_initial, int n_final, std::default_random_engine& randomizer, double base_p_init=0.05, double base_p_final=0.5, double p_step=0.01, vector<int> nb_tests_by_depth={}, vector<double> stq_by_depth={}) {
  131. vector<ConfidenceInterval> res;
  132. for(int n=n_initial; n<n_final; n++) {
  133. cout << "STUDY N=" << n << ":" << endl;
  134. vector<ConfidenceInterval> cis;
  135. int nb_tests = 0;
  136. for(unsigned int depth=0; depth<nb_tests_by_depth.size(); depth++) {
  137. double p_init = (depth == 0) ? base_p_init : cis[0].down-p_step/pow(2, depth-1);
  138. double p_final = (depth == 0) ? base_p_final : cis[0].up+p_step/depth;
  139. cout << " - depth=" << depth+1 << ": ";
  140. cis = optimal_proba_vmath2(n, n+1, randomizer, p_init, p_final, p_step/pow(2, depth), nb_tests_by_depth[depth], stq_by_depth[depth], false);
  141. nb_tests += nb_tests_by_depth[depth];
  142. cout << "["<< cis[0].down <<","<< cis[0].up <<"]" << endl;
  143. }
  144. res.push_back(cis[0]);
  145. ofstream probafile("probas-vmath-rec.csv", ios::app);
  146. probafile << n << ";" << cis[0].down << ";" << cis[0].up << ";" << 1./cis[0].up << ";" << 1./cis[0].down << ";" << nb_tests << endl;
  147. }
  148. return res;
  149. }
  150. double calculate_up_bound(double x, int nb) {
  151. return (x + 2./nb + sqrt(4./nb * (x - pow(x, 2) + 1./nb))) / (1. + 4./nb);
  152. }
  153. double calculate_down_bound(double x, int nb) {
  154. return (x + 2./nb - sqrt(4./nb * (x - pow(x, 2) + 1./nb))) / (1. + 4./nb);
  155. }
  156. void optimal_proba_vmath(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, int nb_loops=1000) {
  157. int nb_diff_proba = floor((p_final-p_init)/p_step);
  158. int nb_tests = 10;
  159. // Initialize result file
  160. ofstream probafile("probas-vmath.csv");
  161. probafile << "n;";
  162. for(int i=0; i<nb_diff_proba; i++)
  163. probafile << p_init+i*p_step << ";";
  164. probafile << endl;
  165. for(int n=n_initial; n<n_final; n++) {
  166. auto start_n = start_chrono();
  167. int nb_best[nb_diff_proba] = {0};
  168. int nb_solved_problems = 0;
  169. // Realize the experiences
  170. int old_min_ind = 0;
  171. int max_min_ind = 0;
  172. for(int num_loop=1; num_loop<nb_loops; num_loop++) {
  173. double min_avg = -1;
  174. int min_ind;
  175. // Realize the experience once
  176. for(int ind2=-1; ind2<nb_diff_proba; ind2++) {
  177. if(ind2 == old_min_ind) continue;
  178. int ind = (ind2 >= 0) ? ind2 : old_min_ind;
  179. double p = p_init+ind*p_step;
  180. EA algo(1, 1, PLUS, p, randomizer);
  181. MasterMind mm(n, n, randomizer);
  182. algo.set_problem(&mm);
  183. Statistic stat = avg_calls(&algo, nb_tests, min_avg+1);
  184. nb_solved_problems += stat.nb;
  185. double avg_nb_calls = stat.average;
  186. if(min_avg < 0 || min_avg > avg_nb_calls) {
  187. min_avg = avg_nb_calls;
  188. min_ind = ind;
  189. }
  190. }
  191. // Store the result of the experience
  192. nb_best[min_ind]++;
  193. if(nb_best[min_ind] > nb_best[max_min_ind])
  194. max_min_ind = min_ind;
  195. old_min_ind = min_ind;
  196. // Display temporary results
  197. auto stop_loop = stop_chrono();
  198. int elapsed_milliseconds_loop = interval_chrono(start_n, stop_loop);
  199. cout << "\r";
  200. cout << "n=" << n << ", num_loop=" << num_loop << ": ";
  201. cout << p_init+max_min_ind*p_step << " (" << nb_best[max_min_ind] << "), ";
  202. cout << "executed in " <<elapsed_milliseconds_loop/1000. << " seconds [" << nb_solved_problems << "]";
  203. cout << " ";
  204. }
  205. // Display the global distribution
  206. cout << '\r' << "===== Graph ==== " << endl;
  207. for(int j=9; j>=0; j--) {
  208. for(int i=0; i<nb_diff_proba; i++) {
  209. double pourcent = (double) nb_best[i]/nb_best[max_min_ind];
  210. cout << ((pourcent >= j/10.) ? '#' : ' ');
  211. }
  212. cout << endl;
  213. }
  214. cout << endl;
  215. // Calculate the confidence interval of 95%
  216. double pbest = p_init+max_min_ind*p_step;
  217. double x = (double) nb_best[max_min_ind]/nb_loops;
  218. cout << "x=" << x << ',' << nb_loops << ',' << nb_best[max_min_ind] << endl;
  219. double up_bound = calculate_up_bound(x, nb_loops);
  220. double down_bound = calculate_down_bound(x, nb_loops);
  221. cout << "\\mu_{p_best} \\in [" << down_bound << ", " << up_bound << "]" << endl;
  222. cout << "Keep best..." << endl;
  223. int min_possible = -1;
  224. int max_possible = -1;
  225. for(int i=0; i<nb_diff_proba; i++) {
  226. double measured = (double) nb_best[i]/nb_loops;
  227. double max_bound = calculate_up_bound(measured, nb_loops);
  228. if(min_possible < 0 && max_bound >= down_bound)
  229. min_possible = i;
  230. if(max_bound >= down_bound)
  231. max_possible = i;
  232. }
  233. double pmin = p_init+min_possible*p_step;
  234. double pmax = p_init+max_possible*p_step;
  235. // Store the results in a file
  236. probafile << n << ";";
  237. for(int i=0; i<nb_diff_proba; i++) {
  238. probafile << "("<<pmin<<","<<pbest<<","<<pmax<<")" << ";";
  239. }
  240. probafile << endl;
  241. auto stop_n = stop_chrono();
  242. int elapsed_milliseconds_n = interval_chrono(start_n, stop_n);
  243. cout << "n=" << n << ": We are sure at 95% that it is in [" << pmin << ", " << pmax << "], with p_best=" << pbest << "." << endl;
  244. cout << "... executed in " << elapsed_milliseconds_n/1000. << " seconds ";
  245. cout << "with " << nb_solved_problems << " resolutions";
  246. for(int u=0; u<3; u++)
  247. Beep(1568, 200);
  248. //delete[] nb_best;
  249. }
  250. }
  251. /// Bellow, it is just some tests of algorithm...
  252. struct Weight {
  253. Weight() : Weight(0) {};
  254. Weight(double w) {
  255. weight = w;
  256. nb_executed = 0;
  257. nb_best = 0;
  258. }
  259. double weight;
  260. int nb_executed;
  261. int nb_best;
  262. };
  263. void optimal_proba_v2(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, int depth_initial=8) {
  264. int nb_diff_proba = floor((p_final-p_init)/p_step);
  265. double initial_value = 50;
  266. int nb_test = 20;
  267. double zero_limit = 2/3.;
  268. double pa = -1./(pow(zero_limit, 2)-2*zero_limit+1);
  269. double pb = -2*pa;
  270. double pc = 1+pa;
  271. ofstream probafile("probas.csv");
  272. for(int i=0; i<nb_diff_proba; i++)
  273. probafile << p_init+i*p_step << ";";
  274. probafile << endl;
  275. for(int n=n_initial; n<n_final; n++) {
  276. auto start_n = start_chrono();
  277. Weight* tab = new Weight[nb_diff_proba];
  278. for(int i=0; i<nb_diff_proba; i++)
  279. tab[i].weight = initial_value;
  280. double max_weight = initial_value;
  281. int max_weight_ind_proba = 0;
  282. double second_weight = initial_value;
  283. int second_weight_ind_proba = 1;
  284. int nb_solved_problems = 0;
  285. for(int depth=depth_initial; depth>0; depth/=2) {
  286. double start_with_weight = max_weight;
  287. for(int num_loop=1; second_weight + 2*initial_value > max_weight && max_weight < 20*initial_value+start_with_weight; num_loop++) {
  288. int nb_new_problems = 0;
  289. for(int k=0; k<20; k++) {
  290. double min_avg = -1;
  291. double min_proba;
  292. for(int ind2=-2; ind2<nb_diff_proba; ind2++) {
  293. if(ind2 == max_weight_ind_proba || ind2 == second_weight_ind_proba) continue;
  294. int ind = (ind2 >= 0) ? ind2 : ((ind2 == -2) ? max_weight_ind_proba: second_weight_ind_proba);
  295. if(ind % depth != 0) continue;
  296. double p = p_init+ind*p_step;
  297. double weight = tab[ind].weight;
  298. double execution_proba = weight/max_weight;
  299. if(ind-depth >= 0 && ind+depth < nb_diff_proba)
  300. execution_proba = ((tab[ind-depth].weight+weight+tab[ind+depth].weight)/3)/max_weight;
  301. else if(ind-depth >= 0)
  302. execution_proba = ((tab[ind-depth].weight + weight)/2)/max_weight;
  303. else if(ind+depth < nb_diff_proba)
  304. execution_proba = ((weight + tab[ind+depth].weight)/2)/max_weight;
  305. execution_proba = (2*execution_proba > 1) ? pa*pow(execution_proba, 2)+pb*execution_proba+pc : 0;
  306. std::bernoulli_distribution distribution(execution_proba);
  307. if(distribution(randomizer)) {
  308. tab[ind].nb_executed++;
  309. EA algo(1, 1, PLUS, p, randomizer);
  310. MasterMind mm(n, n, randomizer);
  311. algo.set_problem(&mm);
  312. Statistic stat = avg_calls(&algo, nb_test, min_avg+1);
  313. double avg = stat.average;
  314. if(min_avg < 0 || min_avg > avg) {
  315. min_avg = avg;
  316. min_proba = p;
  317. }
  318. nb_new_problems += stat.nb;
  319. }
  320. }
  321. int ind_p = round((min_proba - p_init)/p_step);
  322. tab[ind_p].weight++;
  323. if(tab[ind_p].weight > max_weight) {
  324. max_weight = tab[ind_p].weight;
  325. max_weight_ind_proba = ind_p;
  326. }
  327. tab[max_weight_ind_proba].nb_best++;
  328. }
  329. auto stop_loop = stop_chrono();
  330. int elapsed_milliseconds_loop = interval_chrono(start_n, stop_loop);
  331. second_weight = -1;
  332. for(int i=0; i<nb_diff_proba; i++)
  333. if(i != max_weight_ind_proba)
  334. if(second_weight < 0 || second_weight < tab[i].weight) {
  335. second_weight = tab[i].weight;
  336. second_weight_ind_proba = i;
  337. }
  338. nb_solved_problems += nb_new_problems;
  339. cout << "\r";
  340. cout << "n=" << n << ", depth=" << depth << ", num_loop=" << num_loop << ": ";
  341. cout << p_init+max_weight_ind_proba*p_step << " (" << max_weight << "), ";
  342. cout << p_init+second_weight_ind_proba*p_step << " (" << second_weight << "), ";
  343. cout << "executed in " <<elapsed_milliseconds_loop/1000. << " seconds [.+" << nb_new_problems << "=" << nb_solved_problems << "]";
  344. cout << " ";
  345. }
  346. int fdepth = depth / 2;
  347. if(fdepth) {
  348. for(int ind=0; ind<nb_diff_proba; ind++) {
  349. if(ind%depth != 0 && ind%fdepth == 0) {
  350. if(ind+fdepth<nb_diff_proba)
  351. tab[ind].weight = max(tab[ind-fdepth].weight, tab[ind+fdepth].weight);
  352. else
  353. tab[ind].weight = tab[ind-fdepth].weight;
  354. }
  355. }
  356. second_weight = max_weight;
  357. }
  358. }
  359. double p_best = p_init+max_weight_ind_proba*p_step;
  360. double mean = 0;
  361. for(int i=0; i<nb_diff_proba; i++)
  362. mean += tab[i].nb_executed ? ((double) tab[i].nb_best/tab[i].nb_executed) * (p_init+i*p_step) : 0;
  363. double stddev = 0;
  364. for(int i=0; i<nb_diff_proba; i++)
  365. stddev += tab[i].nb_executed ? ((double) tab[i].nb_best/tab[i].nb_executed) * pow(p_init+i*p_step, 2) : 0;
  366. stddev -= pow(mean, 2);
  367. cout << '%' << mean << "," << stddev << endl;
  368. stddev = sqrt(stddev);
  369. for(int i=0; i<nb_diff_proba; i++)
  370. probafile << (tab[i].nb_executed ? ((double) tab[i].nb_best/tab[i].nb_executed) * pow(p_init+i*p_step, 2) : 0) << ";";
  371. probafile << endl;
  372. auto stop_n = stop_chrono();
  373. int elapsed_milliseconds_n = interval_chrono(start_n, stop_n);
  374. cout << '\r' << "n=" << n << ", p_best=" << p_best << " (" << stddev << "), ";
  375. cout << "executed in " << elapsed_milliseconds_n/1000. << " seconds ";
  376. cout << "with " << nb_solved_problems << " resolutions";
  377. cout << " " << endl;
  378. // for(int u=0; u<3; u++)
  379. // Beep(1568, 200);
  380. delete[] tab;
  381. }
  382. }
  383. 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) {
  384. for(int n=n_initial; n<n_final; n++) {
  385. vector<double> avg_list;
  386. vector<double> probas;
  387. auto start = start_chrono();
  388. for(double p=p_init; p<p_final; p+=p_step) {
  389. EA algo(1, 1, PLUS, p, randomizer);
  390. MasterMind mm(n, n, randomizer);
  391. algo.set_problem(&mm);
  392. Statistic stat = avg_calls(&algo);
  393. double avg = stat.average;
  394. avg_list.push_back(avg);
  395. probas.push_back(p);
  396. }
  397. auto stop = stop_chrono();
  398. int elapsed_milliseconds = interval_chrono(start, stop);
  399. int min_ind = 0;
  400. for(unsigned int i=1; i<avg_list.size(); i++)
  401. if(avg_list[min_ind] > avg_list[i])
  402. min_ind = i;
  403. double p_best = probas[min_ind];
  404. cout << "n=" << n << ": " << p_best << " in " << elapsed_milliseconds/1000. << " seconds " << "(" << 100*floor((p_final-p_init)/p_step) << " problems)" << endl;
  405. }
  406. }
  407. #endif // SCRIPTS_H_INCLUDED