From 0e2be5a5656b94fbf2cf6e7dde742057594544e4 Mon Sep 17 00:00:00 2001 From: Kritika Date: Sat, 11 Mar 2017 11:37:10 +0530 Subject: [PATCH 1/6] Added value function to nqueens problem --- search.py | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/search.py b/search.py index 04d5b6c51..8f2eaec62 100644 --- a/search.py +++ b/search.py @@ -884,6 +884,16 @@ def goal_test(self, state): return not any(self.conflicted(state, state[col], col) for col in range(len(state))) + def value(self,state): + """Returns value corresponding to a state where value is defined as + the number of pairs of non-attacking queens""" + attacking_sum = 0 + for c1 in range(len(state)): + if not state[c1] == None : + for c2 in range(c1+1,len(state)): + if not state[c2] == None : + attacking_sum += self.conflict(state[c1],c1,state[c2],c2) + return (self.N*(self.N - 1))/2 - attacking_sum # ______________________________________________________________________________ # Inverse Boggle: Search for a high-scoring Boggle board. A good domain for # iterative-repair and related search techniques, as suggested by Justin Boyan. From b8ecc74dfe927705bb93908655d5e1445cdfdb7c Mon Sep 17 00:00:00 2001 From: Kritika Date: Sat, 11 Mar 2017 11:37:10 +0530 Subject: [PATCH 2/6] updated genetic search --- search.py | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/search.py b/search.py index 8f2eaec62..44010cc42 100644 --- a/search.py +++ b/search.py @@ -570,16 +570,20 @@ def LRTA_cost(self, s, a, s1, H): # Genetic Algorithm -def genetic_search(problem, fitness_fn, ngen=1000, pmut=0.1, n=20): +def genetic_search(problem, fitness_fn,ngen=1000, pmut=0.1, n=20,initial_population=None): """ Call genetic_algorithm on the appropriate parts of a problem. This requires the problem to have states that can mate and mutate, - plus a value method that scores states.""" - s = problem.initial_state - states = [problem.result(s, a) for a in problem.actions(s)] - random.shuffle(states) - return genetic_algorithm(states[:n], problem.value, ngen, pmut) - + plus a value method that scores states.These states are passed as initial + population to the search""" + if(initial_population == None) : + raise Exception("Initial population not given in genetic search") + else : + random.shuffle(initial_population) + newfitness_fn = lambda inidividual : fitness_fn(inidividual.genes) + population = [GAState(initial_population[i]) for i in range(len(initial_population))] + best_individual = genetic_algorithm(population[:n],newfitness_fn,gene_bound,optimal_value, ngen, pmut) + return best_individual.genes def genetic_algorithm(population, fitness_fn, ngen=1000, pmut=0.1): "[Figure 4.8]" From deefb6948965a0f83a3a3f507cc02a178baeb8f5 Mon Sep 17 00:00:00 2001 From: Kritika Date: Sat, 11 Mar 2017 11:51:33 +0530 Subject: [PATCH 3/6] implemented mutate function --- search.py | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/search.py b/search.py index 44010cc42..375cc7ec3 100644 --- a/search.py +++ b/search.py @@ -570,7 +570,7 @@ def LRTA_cost(self, s, a, s1, H): # Genetic Algorithm -def genetic_search(problem, fitness_fn,ngen=1000, pmut=0.1, n=20,initial_population=None): +def genetic_search(problem, fitness_fn,gene_bound,ngen=1000, pmut=0.1, n=20,initial_population=None): """ Call genetic_algorithm on the appropriate parts of a problem. This requires the problem to have states that can mate and mutate, @@ -582,10 +582,10 @@ def genetic_search(problem, fitness_fn,ngen=1000, pmut=0.1, n=20,initial_populat random.shuffle(initial_population) newfitness_fn = lambda inidividual : fitness_fn(inidividual.genes) population = [GAState(initial_population[i]) for i in range(len(initial_population))] - best_individual = genetic_algorithm(population[:n],newfitness_fn,gene_bound,optimal_value, ngen, pmut) + best_individual = genetic_algorithm(population[:n],newfitness_fn,gene_bound, ngen, pmut) return best_individual.genes -def genetic_algorithm(population, fitness_fn, ngen=1000, pmut=0.1): +def genetic_algorithm(population, fitness_fn, gene_bound, ngen=1000, pmut=0.1): "[Figure 4.8]" for i in range(ngen): new_population = [] @@ -594,7 +594,7 @@ def genetic_algorithm(population, fitness_fn, ngen=1000, pmut=0.1): p1, p2 = weighted_sample_with_replacement(population, fitnesses, 2) child = p1.mate(p2) if random.uniform(0, 1) < pmut: - child.mutate() + child.mutate(gene_bound) new_population.append(child) population = new_population return argmax(population, key=fitness_fn) @@ -612,9 +612,10 @@ def mate(self, other): c = random.randrange(len(self.genes)) return self.__class__(self.genes[:c] + other.genes[c:]) - def mutate(self): - "Change a few of my genes." - raise NotImplementedError + def mutate(self,gene_bound) : + "Change one of my genes." + index = random.choice(range(len(self.genes))) + self.genes[index] = random.choice(range(gene_bound[0],gene_bound[1])) # _____________________________________________________________________________ # The remainder of this file implements examples for the search algorithms. From 65501f1632becf21d6060570f4be80002f0c8c35 Mon Sep 17 00:00:00 2001 From: Kritika Date: Sat, 11 Mar 2017 11:53:04 +0530 Subject: [PATCH 4/6] fixed bug in genetic algorithm --- search.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/search.py b/search.py index 375cc7ec3..a79bd3f9a 100644 --- a/search.py +++ b/search.py @@ -589,7 +589,7 @@ def genetic_algorithm(population, fitness_fn, gene_bound, ngen=1000, pmut=0.1): "[Figure 4.8]" for i in range(ngen): new_population = [] - for i in range(len(population)): + for j in range(len(population)): fitnesses = map(fitness_fn, population) p1, p2 = weighted_sample_with_replacement(population, fitnesses, 2) child = p1.mate(p2) From 13f85829d521eb7f2b9c00d624c7c1775aad1a01 Mon Sep 17 00:00:00 2001 From: Kritika Date: Sat, 11 Mar 2017 12:10:07 +0530 Subject: [PATCH 5/6] update genetic algorithm --- search.py | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/search.py b/search.py index a79bd3f9a..dffd5c6a1 100644 --- a/search.py +++ b/search.py @@ -570,7 +570,7 @@ def LRTA_cost(self, s, a, s1, H): # Genetic Algorithm -def genetic_search(problem, fitness_fn,gene_bound,ngen=1000, pmut=0.1, n=20,initial_population=None): +def genetic_search(problem, fitness_fn,gene_bound,ngen=1000, optimal_value=10000000,pmut=0.1, n=20,initial_population=None): """ Call genetic_algorithm on the appropriate parts of a problem. This requires the problem to have states that can mate and mutate, @@ -582,12 +582,12 @@ def genetic_search(problem, fitness_fn,gene_bound,ngen=1000, pmut=0.1, n=20,init random.shuffle(initial_population) newfitness_fn = lambda inidividual : fitness_fn(inidividual.genes) population = [GAState(initial_population[i]) for i in range(len(initial_population))] - best_individual = genetic_algorithm(population[:n],newfitness_fn,gene_bound, ngen, pmut) + best_individual = genetic_algorithm(population[:n],newfitness_fn,gene_bound,optimal_value, ngen, pmut) return best_individual.genes -def genetic_algorithm(population, fitness_fn, gene_bound, ngen=1000, pmut=0.1): +def genetic_algorithm(population, fitness_fn, gene_bound,optimal_value=10000000, ngen=1000, pmut=0.1): "[Figure 4.8]" - for i in range(ngen): + for i in range(int(ngen)): new_population = [] for j in range(len(population)): fitnesses = map(fitness_fn, population) @@ -597,7 +597,10 @@ def genetic_algorithm(population, fitness_fn, gene_bound, ngen=1000, pmut=0.1): child.mutate(gene_bound) new_population.append(child) population = new_population - return argmax(population, key=fitness_fn) + current_bestindividual = argmax(population, key=fitness_fn) + if(fitness_fn(current_bestindividual) >= optimal_value) : + return current_bestindividual + return current_bestindividual class GAState: From 137bdc9dc6c49f079b70e3f3302d025c35d9833c Mon Sep 17 00:00:00 2001 From: Kritika Date: Sat, 11 Mar 2017 12:10:29 +0530 Subject: [PATCH 6/6] test for genetic algorithm --- tests/test_search.py | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/tests/test_search.py b/tests/test_search.py index 11d522e94..00c3d5c5b 100644 --- a/tests/test_search.py +++ b/tests/test_search.py @@ -86,6 +86,18 @@ def test_LRTAStarAgent(): my_agent = LRTAStarAgent(LRTA_problem) assert my_agent('State_5') is None +def test_genetic_search(): + N = 5 + nqueens_problem = NQueensProblem(N) + initial_population = [] + gene_bound = (0,N) + for i in range(N * 20) : + population = [random.choice(range(N)) for gene in range(N)] + initial_population.append(population) + result = genetic_search(nqueens_problem,nqueens_problem.value,gene_bound,(N*(N-1))/2,1000,0.1,N * 20,initial_population) + for col1 in range(len(result)) : + for col2 in range(col1+1,len(result)) : + assert nqueens_problem.conflict(result[col1],col1,result[col2],col2) == False # TODO: for .ipynb: """