0% found this document useful (0 votes)
51 views

AI Lab Manual

The document describes a Python program for solving the 8-puzzle problem using A* search algorithm. It defines classes for puzzle state, node, frontier and queue frontier. The puzzle class initializes the start and goal states, and defines methods for getting neighbors and printing solution. The program uses a queue frontier and explores neighbors by moving the empty tile up, down, left or right until it finds the goal state.

Uploaded by

rishit.kantariya
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
51 views

AI Lab Manual

The document describes a Python program for solving the 8-puzzle problem using A* search algorithm. It defines classes for puzzle state, node, frontier and queue frontier. The puzzle class initializes the start and goal states, and defines methods for getting neighbors and printing solution. The program uses a queue frontier and explores neighbors by moving the empty tile up, down, left or right until it finds the goal state.

Uploaded by

rishit.kantariya
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 22

Solution –Practical 1

# Tic-Tac-Toe Program using


# random number in Python

# importing all necessary libraries


importnumpy as np
import random
from time import sleep

# Creates an empty board


defcreate_board():
return(np.array([[0, 0, 0],
[0, 0, 0],
[0, 0, 0]]))

# Check for empty places on board


def possibilities(board):
l = []

for i in range(len(board)):
for j in range(len(board)):

if board[i][j] == 0:
l.append((i, j))
return(l)

# Select a random place for the player


defrandom_place(board, player):
selection = possibilities(board)
current_loc = random.choice(selection)
board[current_loc] = player
return(board)

# Checks whether the player has three


# of their marks in a horizontal row
defrow_win(board, player):
for x in range(len(board)):
win = True

for y in range(len(board)):
if board[x, y] != player:
win = False
continue

if win == True:
return(win)

Prepared By: Prof. RishitKantariya AI 3170716


return(win)

# Checks whether the player has three


# of their marks in a vertical row
defcol_win(board, player):
for x in range(len(board)):
win = True

for y in range(len(board)):
if board[y][x] != player:
win = False
continue

if win == True:
return(win)
return(win)

# Checks whether the player has three


# of their marks in a diagonal row
defdiag_win(board, player):
win = True
y=0
for x in range(len(board)):
if board[x, x] != player:
win = False
if win:
return win
win = True
if win:
for x in range(len(board)):
y = len(board) - 1 - x
if board[x, y] != player:
win = False
return win

# Evaluates whether there is


# a winner or a tie
def evaluate(board):
winner = 0

for player in [1, 2]:


if (row_win(board, player) or
col_win(board,player) or
diag_win(board,player)):

winner = player

ifnp.all(board != 0) and winner == 0:

Prepared By: Prof. RishitKantariya AI 3170716


winner = -1
return winner

# Main function to start the game


defplay_game():
board, winner, counter = create_board(), 0, 1
print(board)
sleep(2)

while winner == 0:
for player in [1, 2]:
board = random_place(board, player)
print("Board after " + str(counter) + " move")
print(board)
sleep(2)
counter += 1
winner = evaluate(board)
if winner != 0:
break
return(winner)

# Driver Code
print("Winner is: " + str(play_game()))

Output Screenshot:

Prepared By: Prof. RishitKantariya AI 3170716


Prepared By: Prof. RishitKantariya AI 3170716
Solution –Practical 2

from collections import deque

def BFS(a, b, target):

# Map is used to store the states, every


# state is hashed to binary value to
# indicate either that state is visited
# before or not
m = {}
isSolvable = False
path = []

# Queue to maintain states


q = deque()

# Initialing with initial state


q.append((0, 0))

while (len(q) > 0):

# Current state
u = q.popleft()

# q.pop() #pop off used state

# If this state is already visited


if ((u[0], u[1]) in m):
continue

# Doesn't met jug constraints


if ((u[0] > a or u[1] > b or
u[0] < 0 or u[1] < 0)):
continue

# Filling the vector for constructing


# the solution path
path.append([u[0], u[1]])

# Marking current state as visited


m[(u[0], u[1])] = 1

# If we reach solution state, put ans=1


if (u[0] == target or u[1] == target):
isSolvable = True

Prepared By: Prof. RishitKantariya AI 3170716


if (u[0] == target):
if (u[1] != 0):

# Fill final state


path.append([u[0], 0])
else:
if (u[0] != 0):

# Fill final state


path.append([0, u[1]])

# Print the solution path


sz = len(path)
for i in range(sz):
print("(", path[i][0], ",",
path[i][1], ")")
break

# If we have not reached final state


# then, start developing intermediate
# states to reach solution state
q.append([u[0], b]) # Fill Jug2
q.append([a, u[1]]) # Fill Jug1

forap in range(max(a, b) + 1):

# Pour amount ap from Jug2 to Jug1


c = u[0] + ap
d = u[1] - ap

# Check if this state is possible or not


if (c == a or (d == 0 and d >= 0)):
q.append([c, d])

# Pour amount ap from Jug 1 to Jug2


c = u[0] - ap
d = u[1] + ap

# Check if this state is possible or not


if ((c == 0 and c >= 0) or d == b):
q.append([c, d])

# Empty Jug2
q.append([a, 0])

# Empty Jug1
q.append([0, b])

Prepared By: Prof. RishitKantariya AI 3170716


# No, solution exists if ans=0
if (not isSolvable):
print("No solution")

# Driver code
if __name__ == '__main__':

Jug1, Jug2, target = 4, 3, 2


print("Path from initial state "
"to solution state ::")

BFS(Jug1, Jug2, target)

Output Screenshot:

Prepared By: Prof. RishitKantariya AI 3170716


Solution – Practical 3
import sys
import numpy as np

class Node:
def __init__(self, state, parent, action):
self.state = state
self.parent = parent
self.action = action

class StackFrontier:
def __init__(self):
self.frontier = []

def add(self, node):


self.frontier.append(node)

def contains_state(self, state):


return any((node.state[0] == state[0]).all() for node in self.frontier)

def empty(self):
return len(self.frontier) == 0

def remove(self):
if self.empty():
raise Exception("Empty Frontier")
else:
node = self.frontier[-1]
self.frontier = self.frontier[:-1]
return node

class QueueFrontier(StackFrontier):
def remove(self):
if self.empty():
raise Exception("Empty Frontier")
else:
node = self.frontier[0]
self.frontier = self.frontier[1:]
return node

class Puzzle:

Prepared By: Prof.Rishit Kantariya AI 31707016


def __init__(self, start, startIndex, goal, goalIndex):
self.start = [start, startIndex]
self.goal = [goal, goalIndex]
self.solution = None

def neighbors(self, state):


mat, (row, col) = state
results = []

if row > 0:
mat1 = np.copy(mat)
mat1[row][col] = mat1[row - 1][col]
mat1[row - 1][col] = 0
results.append(('up', [mat1, (row - 1, col)]))
if col > 0:
mat1 = np.copy(mat)
mat1[row][col] = mat1[row][col - 1]
mat1[row][col - 1] = 0
results.append(('left', [mat1, (row, col - 1)]))
if row < 2:
mat1 = np.copy(mat)
mat1[row][col] = mat1[row + 1][col]
mat1[row + 1][col] = 0
results.append(('down', [mat1, (row + 1, col)]))
if col < 2:
mat1 = np.copy(mat)
mat1[row][col] = mat1[row][col + 1]
mat1[row][col + 1] = 0
results.append(('right', [mat1, (row, col + 1)]))

return results

def print(self):
solution = self.solution if self.solution is not None else None
print("Start State:\n", self.start[0], "\n")
print("Goal State:\n", self.goal[0], "\n")
print("\nStates Explored: ", self.num_explored, "\n")
print("Solution:\n ")
for action, cell in zip(solution[0], solution[1]):
print("action: ", action, "\n", cell[0], "\n")
print("Goal Reached!!")

def does_not_contain_state(self, state):


for st in self.explored:
if (st[0] == state[0]).all():

Prepared By: Prof.Rishit Kantariya AI 31707016


return False
return True

def solve(self):
self.num_explored = 0

start = Node(state=self.start, parent=None, action=None)


frontier = QueueFrontier()
frontier.add(start)

self.explored = []

while True:
if frontier.empty():
raise Exception("No solution")

node = frontier.remove()
self.num_explored += 1

if (node.state[0] == self.goal[0]).all():
actions = []
cells = []
while node.parent is not None:
actions.append(node.action)
cells.append(node.state)
node = node.parent
actions.reverse()
cells.reverse()
self.solution = (actions, cells)
return

self.explored.append(node.state)

for action, state in self.neighbors(node.state):


if not frontier.contains_state(state) and self.does_not_contain_state(state):
child = Node(state=state, parent=node, action=action)
frontier.add(child)

start = np.array([[1, 2, 3], [8, 0, 4], [7, 6, 5]])


goal = np.array([[2, 8, 1], [0, 4, 3], [7, 6, 5]])

startIndex = (1, 1)
goalIndex = (1, 0)

Prepared By: Prof.Rishit Kantariya AI 31707016


p = Puzzle(start, startIndex, goal, goalIndex)
p.solve()
p.print()

Screenshot

Prepared By: Prof.Rishit Kantariya AI 31707016


Solution-Practical 4
# Recursive Python function to solve the tower of hanoi

def TowerOfHanoi(n , source, destination, auxiliary):


if n==1:
print ("Move disk 1 from source",source,"to destination",destination)
return
TowerOfHanoi(n-1, source, auxiliary, destination)
print ("Move disk",n,"from source",source,"to destination",destination)
TowerOfHanoi(n-1, auxiliary, destination, source)

# Driver code
n=4
TowerOfHanoi(n,'A','B','C')
# A, C, B are the name of rods

Screenshot

Prepared By: Prof.Rishit Kantariya AI 31707016


Solution Practial -5
DOMAINS
queen = q(integer, integer)
queens = queen*
freelist = integer*
board = board(queens, freelist, freelist, freelist, freelist)

PREDICATES
nondeterm placeN(integer, board, board)
nondeterm place_a_queen(integer, board, board)
nondeterm nqueens(integer)
nondeterm makelist(integer, freelist)
nondeterm findandremove(integer, freelist, freelist)
nextrow(integer, freelist, freelist)

CLAUSES
nqueens(N):-
makelist(N,L),Diagonal=N*2-1,makelist(Diagonal,LL),
placeN(N,board([],L,L,LL,LL),Final), write(Final).

placeN(_,board(D,[],[],D1,D2),board(D,[],[],D1,D2)):-!.
placeN(N,Board1,Result):-
place_a_queen(N,Board1,Board2),
placeN(N,Board2,Result).

place_a_queen(N,board(Queens,Rows,Columns,Diag1,Diag2),
board([q(R,C)|Queens],NewR,NewC,NewD1,NewD2)):-
nextrow(R,Rows,NewR),
findandremove(C,Columns,NewC),
D1=N+C-R,findandremove(D1,Diag1,NewD1),
D2=R+C-1,findandremove(D2,Diag2,NewD2).
findandremove(X,[X|Rest],Rest).
findandremove(X,[Y|Rest],[Y|Tail]):-
findandremove(X,Rest,Tail).

makelist(1,[1]).
makelist(N,[N|Rest]) :-
N1=N-1,makelist(N1,Rest).
nextrow(Row,[Row|Rest],Rest).

Prepared By: Prof.Rishit Kantariya AI 31707016


Solution-Practical 6

n = 4 # there are four nodes in example graph (graph is 1-based)

# dist[i][j] represents shortest distance to go from i to j

# this matrix can be calculated for any given graph using

# all-pair shortest path algorithms

dist = [[0, 0, 0, 0, 0], [0, 0, 10, 15, 20], [

0, 10, 0, 25, 25], [0, 15, 25, 0, 30], [0, 20, 25, 30, 0]]

# memoization for top down recursion

memo = [[-1]*(1 << (n+1)) for _ in range(n+1)]

def fun(i, mask):

# base case

# if only ith bit and 1st bit is set in our mask,

# it implies we have visited all other nodes already

if mask == ((1 << i) | 3):

Prepared By: Prof.Rishit Kantariya AI 31707016


return dist[1][i]

# memoization

if memo[i][mask] != -1:

return memo[i][mask]

res = 10**9 # result of this sub-problem

# we have to travel all nodes j in mask and end the path at ith node

# so for every node j in mask, recursively calculate cost of

# travelling all nodes in mask

# except i and then travel back from node j to node i taking

# the shortest path take the minimum of all possible j nodes

for j in range(1, n+1):

if (mask & (1 << j)) != 0 and j != i and j != 1:

res = min(res, fun(j, mask & (~(1 << i))) + dist[j][i])

memo[i][mask] = res # storing the minimum value

return res

# Driver program to test above logic

ans = 10**9

for i in range(1, n+1):

# try to go from node 1 visiting all nodes in between to i

Prepared By: Prof.Rishit Kantariya AI 31707016


# then return from i taking the shortest route to 1

ans = min(ans, fun(i, (1 << (n+1))-1) + dist[i][1])

print("The cost of most efficient tour = " + str(ans))

Screenshot:

Prepared By: Prof.Rishit Kantariya AI 31707016


Solution – Practical 7
from collections import deque

class Graph:
# example of adjacency list (or rather map)
# adjacency_list = {
# 'A': [('B', 1), ('C', 3), ('D', 7)],
# 'B': [('D', 5)],
# 'C': [('D', 12)]
#}

def __init__(self, adjacency_list):


self.adjacency_list = adjacency_list

def get_neighbors(self, v):


return self.adjacency_list[v]

# heuristic function with equal values for all nodes


def h(self, n):
H={
'A': 1,
'B': 1,
'C': 1,
'D': 1
}

return H[n]

def a_star_algorithm(self, start_node, stop_node):


# open_list is a list of nodes which have been visited, but who's neighbors
# haven't all been inspected, starts off with the start node
# closed_list is a list of nodes which have been visited
# and who's neighbors have been inspected
open_list = set([start_node])
closed_list = set([])

# g contains current distances from start_node to all other nodes


# the default value (if it's not found in the map) is +infinity
g = {}

g[start_node] = 0

# parents contains an adjacency map of all nodes


parents = {}
parents[start_node] = start_node

while len(open_list) > 0:


n = None

Prepared By: Prof.Rishit Kantariya AI 31707016


# find a node with the lowest value of f() - evaluation function
for v in open_list:
if n == None or g[v] + self.h(v) < g[n] + self.h(n):
n = v;

if n == None:
print('Path does not exist!')
return None

# if the current node is the stop_node


# then we begin reconstructin the path from it to the start_node
if n == stop_node:
reconst_path = []

while parents[n] != n:
reconst_path.append(n)
n = parents[n]

reconst_path.append(start_node)

reconst_path.reverse()

print('Path found: {}'.format(reconst_path))


return reconst_path

# for all neighbors of the current node do


for (m, weight) in self.get_neighbors(n):
# if the current node isn't in both open_list and closed_list
# add it to open_list and note n as it's parent
if m not in open_list and m not in closed_list:
open_list.add(m)
parents[m] = n
g[m] = g[n] + weight

# otherwise, check if it's quicker to first visit n, then m


# and if it is, update parent data and g data
# and if the node was in the closed_list, move it to open_list
else:
if g[m] > g[n] + weight:
g[m] = g[n] + weight
parents[m] = n

if m in closed_list:
closed_list.remove(m)
open_list.add(m)

# remove n from the open_list, and add it to closed_list

Prepared By: Prof.Rishit Kantariya AI 31707016


# because all of his neighbors were inspected
open_list.remove(n)
closed_list.add(n)

print('Path does not exist!')


return None

Let's look at an example with the following weighted graph:

We run the code as so:

adjacency_list = {
'A': [('B', 1), ('C', 3), ('D', 7)],
'B': [('D', 5)],
'C': [('D', 12)]
}
graph1 = Graph(adjacency_list)
graph1.a_star_algorithm('A', 'D')

Screenshot:

Prepared By: Prof.Rishit Kantariya AI 31707016


Solution-Practical 8

Prepared By: Prof.Rishit Kantariya AI 31707016


Solution-Practical 9

Prepared By: Prof.Rishit Kantariya AI 31707016


Prepared By: Prof.Rishit Kantariya AI 31707016

You might also like