Romil Patel
20204170
CSE-C
Genetic Algorithms Assignment 2
(a).Describe the approach to solving the N-queen problem using a genetic algorithm. Explain
the solution methodically, illustrating key steps with a practical example.
First of all N-Queen problem is the problem where we need to find an arrangement of N queens on the
chessboard, such that no queen can attack any other queens on the board. So in our 5-Queens problem
we need to placing 5 chess queens on a 5×5 chessboard so that no two queens attack each other. In
order to solve the 5-Queen problem the following steps are needed:
1) Chromosome design
2) Initialization
3) Fitness evaluation
4) Selection
5) Crossover
6) Mutation
7) Update generation
8) Go back to 3)
Chromosome Design
2) Initialization
In the initialization process, we need to arrange a random population of chromosomes (potential
solutions) are created. Here is the initial population, I took 4 chromosomes, each of which has a length
5. They are
[5 2 4 3 5]
[4 3 5 1 4]
[2 1 3 2 4]
[5 2 3 4 1]
3) Fitness evaluation
First of all, the fitness function is pairs of non-attacking queens. So, higher scores are better is better for
us. In order to solve the fitness function for the chromosome [5 2 4 3 5], I assigned each queen uniquely
as Q1, Q2, Q3, Q4 and Q5. And to find the fitness function value.
4) Selection
In the next step, we randomly choose the two pairs to reproduce based on probabilities which we
counted on the previous step. In other words, a certain number of chromosomes will survive into the
next generator using a selection operator. Here selected chromosomes to act as parents that are
combined using crossover operator to make children. In addition to this, we pick a crossover point per
pair.
5) Crossover
In the crossover, selected chromosomes act as parents that are combined using crossover operator to
make children. In other words, it combines the genetic information of two parents to generate new
offspring.
6) Mutation
The next step is mutation. In the mutation process, we alter one or more gene values in chromosomes
which we found after crossover. So it randomly changes a few gens and the mutation probability is low.
7) Update generation
In the next step, we need to update the generation. New chromosomes will update the population but
the population number will not change
(b). Provide a clear pseudo code for the algorithm
Step 1: A random chromosome is generated
Step 2: Fitness value of the chromosome is calculated
Step 3: If fitness is not equal to Fmax
Step 4: Reproduce (crossover) new chromosome from 2 randomly selected best chromosomes
Step 5: Mutation may take place
Step 6: New chromosome added to population
Repeat Step 2 to 6 until a chromosome (solution) with Fitness value = Fmax is found
c). Choose a programming language and implement the solution. Attach the code and
screenshots of the output.
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)