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')