Advertisement
skb50bd

8-Queen_Genetic

Mar 6th, 2019
276
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 4.09 KB | None | 0 0
  1. #!/usr/bin/env python
  2.  
  3. import random
  4. import string
  5.  
  6.  
  7. def random_individual(size):
  8.     return [random.randint(1, size) for _ in range(size)]
  9.  
  10.  
  11. maxFitness = 28
  12.  
  13.  
  14. def calculate_fitness(individual):
  15.     horizontal_collisions = sum([individual.count(queen) - 1 for queen in individual]) / 2
  16.     diagonal_collisions = 0
  17.  
  18.     n = len(individual)
  19.     left_diagonal = [0] * 2 * n
  20.     right_diagonal = [0] * 2 * n
  21.     for i in range(n):
  22.         left_diagonal[i + individual[i] - 1] += 1
  23.         right_diagonal[len(individual) - i + individual[i] - 2] += 1
  24.  
  25.     diagonal_collisions = 0
  26.     for i in range(2 * n - 1):
  27.         counter = 0
  28.         if left_diagonal[i] > 1:
  29.             counter += left_diagonal[i] - 1
  30.         if right_diagonal[i] > 1:
  31.             counter += right_diagonal[i] - 1
  32.         diagonal_collisions += counter / (n - abs(i - n + 1))
  33.  
  34.     return int(maxFitness - (horizontal_collisions + diagonal_collisions))
  35.  
  36.  
  37. def calculate_probability(individual):
  38.     return calculate_fitness(individual) / maxFitness
  39.  
  40.  
  41. def random_pick(population, probabilities):
  42.     population_with_probability = zip(population, probabilities)
  43.     total = sum(w for c, w in population_with_probability)
  44.     r = random.uniform(0, total)
  45.     up_to = 0
  46.     for c, w in zip(population, probabilities):
  47.         if up_to + w >= r:
  48.             return c
  49.         up_to += w
  50.     assert False, "Shouldn't get here"
  51.  
  52.  
  53. def cross_over(x, y):
  54.     n = len(x)
  55.     c = random.randint(0, n - 1)
  56.     return x[0:c] + y[c:n]
  57.  
  58.  
  59. def mutate(x):
  60.     n = len(x)
  61.     c = random.randint(0, n - 1)
  62.     m = random.randint(1, n)
  63.     x[c] = m
  64.     return x
  65.  
  66.  
  67. def genetic_queen(population):
  68.     mutation_probability = 0.03
  69.     new_population = []
  70.     probabilities = [calculate_probability(n) for n in population]
  71.     for i in range(len(population)):
  72.         x = random_pick(population, probabilities)
  73.         y = random_pick(population, probabilities)
  74.         child = cross_over(x, y)
  75.         if random.random() < mutation_probability:
  76.             child = mutate(child)
  77.         print_individual(child)
  78.         new_population.append(child)
  79.         if calculate_fitness(child) == 28: break
  80.     return new_population
  81.  
  82.  
  83. def genetic_queen_with_best_probabilities(population):
  84.     population.sort(key=lambda t: calculate_probability(t),
  85.                     reverse=True)
  86.  
  87.     fittest_population = population[0: (len(population) // 2)]
  88.     new_population = []
  89.     for individual in fittest_population:
  90.         random_position = random.randint(0, len(fittest_population) - 1)
  91.         other1 = fittest_population[random_position]
  92.         random_position = random.randint(0, len(fittest_population) - 1)
  93.         other2 = fittest_population[random_position]
  94.  
  95.         child1 = cross_over(individual, other1)
  96.         if calculate_fitness(child1) <= calculate_fitness(individual):
  97.             child1 = mutate(child1)
  98.  
  99.         child2 = cross_over(individual, other2)
  100.         if calculate_fitness(child2) <= calculate_fitness(individual):
  101.             child2 = mutate(child2)
  102.  
  103.         new_population.append(child1)
  104.         new_population.append(child2)
  105.         if calculate_fitness(child1) == 28: break
  106.         if calculate_fitness(child2) == 28: break
  107.     for i in new_population:
  108.         print_individual(i)
  109.  
  110.     return new_population
  111.  
  112.  
  113. def print_individual(x):
  114.     print("{},  fitness = {}, probability = {:.6f}"
  115.           .format(str(x), calculate_fitness(x), calculate_probability(x)))
  116.  
  117.  
  118. if __name__ == "__main__":
  119.     population = [random_individual(8) for _ in range(100)]
  120.     generation = 1
  121.  
  122.     # genetic_queen_with_best_probabilities(population)
  123.  
  124.     while 28 not in [calculate_fitness(x) for x in population]:
  125.         print("=== Generation {} ===".format(generation))
  126.         population = genetic_queen_with_best_probabilities(population)
  127.         print("Maximum fitness = {}".format(max([calculate_fitness(n) for n in population])))
  128.         generation += 1
  129.  
  130.     print("Solved in Generation {}!".format(generation - 1))
  131.     for x in population:
  132.         if calculate_fitness(x) == 28:
  133.             print_individual(x)
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement