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.

mastermind.py 3.9KB

  1. import random
  2. import numpy
  3. ## Configuration MasterMind
  4. nb_colors = 5
  5. nb_cases = 5
  6. ## Black-box
  7. class MasterMind:
  8. def __init__(self, nb_colors, nb_cases, solution=None):
  9. self.nb_colors = nb_colors
  10. self.nb_cases = nb_cases
  11. self._solution = solution if solution else self.random_candidate()
  12. def random_candidate(self):
  13. import random
  14. return [random.randrange(self.nb_colors) for _ in range(self.nb_cases)]
  15. def try_candidate(self, candidate):
  16. total = 0
  17. for i, x in enumerate(self._solution):
  18. if candidate[i] == x:
  19. total += 1
  20. return total
  21. def get_max_radius(self):
  22. return self.nb_cases
  23. def modify_with_radius(self, x, r):
  24. import random
  25. x = x[:]
  26. items = list(range(self.nb_cases))
  27. random.shuffle(items)
  28. for i in items[:r]:
  29. x[i] = random.randrange(self.nb_colors)
  30. return x
  31. def is_optimal(self, x, v_x=None):
  32. v_x = v_x if v_x else self.try_candidate(x)
  33. return (v_x == self.nb_cases)
  34. class SearchHeuristic:
  35. def set_problem(self, problem):
  36. self.problem = problem
  37. def run(self):
  38. raise Exception('Not implemented !')
  39. # Random Local Search
  40. class RLS(SearchHeuristic):
  41. def run(self):
  42. pb = self.problem
  43. x = pb.random_candidate()
  44. v_x = pb.try_candidate(x)
  45. nb_calls = 1
  46. while not pb.is_optimal(x, v_x):
  47. r = 1
  48. y = pb.modify_with_radius(x, r)
  49. v_y = pb.try_candidate(y)
  50. if v_y >= v_x:
  51. x = y
  52. v_x = v_y
  53. nb_calls += 1
  54. return (x, v_x, nb_calls)
  55. class EA(SearchHeuristic):
  56. def __init__(self, proba, lda, mu):
  57. self.proba = proba
  58. self.lda = lda
  59. self.mu = mu
  60. def run(self):
  61. pb = self.problem
  62. x_list = []
  63. for _ in range(self.mu):
  64. x = pb.random_candidate()
  65. vx = pb.try_candidate(x)
  66. x_list.append((x, vx))
  67. x_list = sorted(x_list, key=lambda x: x[1], reverse=True)
  68. x_best = x_list[0]
  69. nb_calls = 1
  70. while not pb.is_optimal(x_best[0], x_best[1]):
  71. y_list = []
  72. for _ in range(self.lda):
  73. r = numpy.random.binomial(pb.get_max_radius(), self.proba)
  74. y = pb.modify_with_radius(x_best[0], r)
  75. vy = pb.try_candidate(y)
  76. y_list.append((y, vy))
  77. #print(x_list, y_list)
  78. selection = x_list + y_list
  79. selection = sorted(selection, key=lambda x: x[1], reverse=True)
  80. x_list = selection[:self.mu]
  81. x_best = x_list[0]
  82. nb_calls += 1
  83. return (x_best[0], x_best[1], nb_calls)
  84. def avg_calls(algo, problem, nb=100):
  85. nb_calls_list = []
  86. for _ in range(100):
  87. algo.set_problem(problem)
  88. _, _, nb_calls = algo.run()
  89. nb_calls_list.append(nb_calls)
  90. return numpy.mean(nb_calls_list)
  91. ## Main
  92. avg = avg_calls(RLS(), MasterMind(nb_colors, nb_cases))
  93. print('Average RLS: %s' % avg)
  94. avg = avg_calls(EA(1./nb_cases, 1, 1), MasterMind(nb_colors, nb_cases))
  95. print('Average EA: %s' % avg)
  96. print('=================')
  97. probas = list(numpy.arange(0.05, 0.5, 0.01))
  98. p_best_list = []
  99. for n in range(5, 15):
  100. avg_list = []
  101. for p in probas:
  102. avg = avg_calls(EA(p, 1, 1), MasterMind(n, n))
  103. avg_list.append(avg)
  104. #print('{}%'.format(int(p*100)))
  105. p_best = probas[numpy.argmin(avg_list)]
  106. p_best *= n
  107. p_best_list.append(p_best)
  108. print('{}: {}'.format(n, p_best))
  109. from matplotlib import pyplot as plt
  110. x = list(range(5, 15))
  111. y = p_best_list
  112. plt.plot(x, y)
  113. plt.savefig('foo3.png')