You are on page 1of 8

ASSSIGNMENT #02

NAME: M HASSAM KHAN (11141)

GENETIC ALGORITHM

CODE:
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
localhost:8888/nbconvert/html/Untitled2.ipynb?download=false 1/5
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)

localhost:8888/nbconvert/html/Untitled2.ipynb?download=false 2/5
localhost:8888/nbconvert/html/Untitled2.ipynb?download=false 3/5
HILL CLIMBING

localhost:8888/nbconvert/html/Untitled2.ipynb?download=false 4/5
In [2]: import random
import math
import numpy as np

board = None # to store chess board


N = -1 # to store size of the board

# function to generate board


def generate():
global board
board = np.zeros([N, N], dtype=int)
rows = [*range(N)]
# initialising queens in all different columns
for i in range(N):
board[random.choice(tuple(rows))][i] = 1

# initialising queens randomly


# for i in range(N):
# cols = [*range(N)]
# board[random.choice(tuple(rows))][random.choice(tuple(cols)] = 1

# function to arrange queens in all different columns


def arrangeBoard():
# forward fixing
for i in range(N):
check = False
for j in range(N):
if board[j][i] == 1 and check and i != N - 1:
board[j][i] = 0
for k in range(N):
if board[k][i + 1] == 0:
board[k][i + 1] = 1
break
if board[j][i] == 1 and not check:
check = True

# backward fixing
for i in reversed(range(N)):
check = False
for j in range(N):
if board[j][i] == 1 and check and i != 0:
board[j][i] = 0
for k in range(N):
if board[k][i - 1] == 0:
board[k][i - 1] = 1
break
if board[j][i] == 1 and not check:
check = True

# function to calculate objective i.e. how many queens are attacking each othe
r
def objectiveFunc(temp_board):
count = 0

localhost:8888/nbconvert/html/Untitled2.ipynb?download=false 5/5
for i in range(N):
for j in range(N):
if temp_board[i][j] == 1:
# checking other queens in the same row
col = 0
while col != N:
if col != j and temp_board[i][col] == 1:
count += 1
col += 1

# checking queens in the same column


row = 0
while row != N:
if row != i and temp_board[row][j] == 1:
count += 1
row += 1

# checking queens in the area above main diagonal


row = i - 1
col = j - 1
while row != -1 and col != -1:
if temp_board[row][col] == 1:
count += 1
row -= 1
col -= 1

# checking queens in the area below main diagonal


row = i + 1
col = j + 1
while row != N and col != N:
if temp_board[row][col] == 1:
count += 1
row += 1
col += 1

# checking queens in the area above reverse diagonal


row = i - 1
col = j + 1
while row != -1 and col != N:
if temp_board[row][col] == 1:
count += 1
row -= 1
col += 1

# checking queens in the area below reverse diagonal


row = i + 1
col = j - 1
while row != N and col != -1:
if temp_board[row][col] == 1:
count += 1
row += 1
col -= 1
return count // 2

# function to check neighbour when applying hill climbing and move


# if there's a better neighbour otherwise stay at the same position

localhost:8888/nbconvert/html/Untitled2.ipynb?download=false 6/5
def checkNeighboursHC(row, col):
global board
temp_board = np.copy(board)

# if queen is in the first row who's neighbours are being checked


if row == 0:
temp_board[row][col] = 0
temp_board[row + 1][col] = 1
if objectiveFunc(temp_board) <= objectiveFunc(board):
board = np.copy(temp_board)

# if queen is in the last row who's neighbours are being checked


elif row == N - 1:
temp_board[row][col] = 0
temp_board[row - 1][col] = 1
if objectiveFunc(temp_board) <= objectiveFunc(board):
board = np.copy(temp_board)

# if in between first and last row


else:
temp_board1 = np.copy(board)
temp_board[row][col] = 0
temp_board[row - 1][col] = 1
temp_board1[row][col] = 0
temp_board1[row + 1][col] = 1

# randomly choose if the objective function of neighbours are same


if (objectiveFunc(temp_board) == objectiveFunc(temp_board1)) \
and (objectiveFunc(temp_board) <= objectiveFunc(board)):
check = random.randrange(0, 2)
if check == 0:
board = np.copy(temp_board)
elif check == 1:
board = np.copy(temp_board1)

# choose the neighbour who has less objective value


elif (objectiveFunc(temp_board) < objectiveFunc(temp_board1)) \
and (objectiveFunc(temp_board) < objectiveFunc(board)):
board = np.copy(temp_board)

# choose the neighbour who has less objective value


elif (objectiveFunc(temp_board1) < objectiveFunc(temp_board)) \
and (objectiveFunc(temp_board1) < objectiveFunc(board)):
board = np.copy(temp_board1)
return objectiveFunc(board) # return objective function of updated board

# hill climbing algorithm


def hillClimbing():
count = objectiveFunc(board)
while count != 0: # loop until the solution is found i.e. no queen is att
acking any other queen
check = np.copy(board)
# traversing through the board
for i in range(N):
if count == 0:
return not None

localhost:8888/nbconvert/html/Untitled2.ipynb?download=false 7/5
for j in range(N):
if count == 0:
return not None
if board[i][j] == 1:
count = checkNeighboursHC(i, j)
if np.array_equal(check, board): # if no better neighbours were found
then return
return None

if name == " main ":


N = int(input("Enter N: "))
generate()
arrangeBoard() # use this function to arrange queens in all different c
olumns if generated randomly before
print("Initial Board:\n", board)
board_cpy = np.copy(board)

if hillClimbing() is None:
print("\nNo solution found using Hill Climbing.\n")
else:
print("\nFinal board using Hill Climbing:\n", board)
Enter N: 8
Initial Board:
[[0 0 1 0 0 0 0 0]
[1 0 0 0 0 0 0 0]
[0 0 0 0 0 0 1 1]
[0 1 0 0 0 1 0 0]
[0 0 0 1 1 0 0 0]
[0 0 0 0 0 0 0 0]
[0 0 0 0 0 0 0 0]
[0 0 0 0 0 0 0 0]]

No solution found using Hill Climbing.

In [ ]:

localhost:8888/nbconvert/html/Untitled2.ipynb?download=false 8/5

You might also like