-
Notifications
You must be signed in to change notification settings - Fork 28
/
Copy pathN-Queen_GeneticAlgo.py
114 lines (89 loc) · 3.5 KB
/
N-Queen_GeneticAlgo.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
import random
def random_chromosome(size): #making random chromosomes
return [ random.randint(1, nq) for _ in range(nq) ]
def fitness(chromosome):
horizontal_collisions = sum([chromosome.count(queen)-1 for queen in chromosome])/2
diagonal_collisions = 0
n = len(chromosome)
left_diagonal = [0] * 2*n
right_diagonal = [0] * 2*n
for i in range(n):
left_diagonal[i + chromosome[i] - 1] += 1
right_diagonal[len(chromosome) - i + chromosome[i] - 2] += 1
diagonal_collisions = 0
for i in range(2*n-1):
counter = 0
if left_diagonal[i] > 1:
counter += left_diagonal[i]-1
if right_diagonal[i] > 1:
counter += right_diagonal[i]-1
diagonal_collisions += counter / (n-abs(i-n+1))
return int(maxFitness - (horizontal_collisions + diagonal_collisions)) #28-(2+3)=23
def probability(chromosome, fitness):
return fitness(chromosome) / maxFitness
def random_pick(population, probabilities):
populationWithProbabilty = zip(population, probabilities)
total = sum(w for c, w in populationWithProbabilty)
r = random.uniform(0, total)
upto = 0
for c, w in zip(population, probabilities):
if upto + w >= r:
return c
upto += w
assert False, "Shouldn't get here"
def reproduce(x, y): #doing cross_over between two chromosomes
n = len(x)
c = random.randint(0, n - 1)
return x[0:c] + y[c:n]
def mutate(x): #randomly changing the value of a random index of a chromosome
n = len(x)
c = random.randint(0, n - 1)
m = random.randint(1, n)
x[c] = m
return x
def genetic_queen(population, fitness):
mutation_probability = 0.03
new_population = []
probabilities = [probability(n, fitness) for n in population]
for i in range(len(population)):
x = random_pick(population, probabilities) #best chromosome 1
y = random_pick(population, probabilities) #best chromosome 2
child = reproduce(x, y) #creating two new chromosomes from the best 2 chromosomes
if random.random() < mutation_probability:
child = mutate(child)
print_chromosome(child)
new_population.append(child)
if fitness(child) == maxFitness: break
return new_population
def print_chromosome(chrom):
print("Chromosome = {}, Fitness = {}"
.format(str(chrom), fitness(chrom)))
if __name__ == "__main__":
nq = int(input("Enter Number of Queens: ")) #say N = 8
maxFitness = (nq*(nq-1))/2 # 8*7/2 = 28
population = [random_chromosome(nq) for _ in range(100)]
generation = 1
while not maxFitness in [fitness(chrom) for chrom in population]:
print("=== Generation {} ===".format(generation))
population = genetic_queen(population, fitness)
print("")
print("Maximum Fitness = {}".format(max([fitness(n) for n in population])))
generation += 1
chrom_out = []
print("Solved in Generation {}!".format(generation-1))
for chrom in population:
if fitness(chrom) == maxFitness:
print("")
print("One of the solutions: ")
chrom_out = chrom
print_chromosome(chrom)
board = []
for x in range(nq):
board.append(["x"] * nq)
for i in range(nq):
board[nq-chrom_out[i]][i]="Q"
def print_board(board):
for row in board:
print (" ".join(row))
print()
print_board(board)