0% found this document useful (0 votes)
44 views20 pages

Final AI LAB FILE

Uploaded by

Anushka Mane
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
44 views20 pages

Final AI LAB FILE

Uploaded by

Anushka Mane
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
You are on page 1/ 20

CERTIFICATE

School of Computer Science


Faculty of Science

This is to certify that,


Mr./ Ms. ___________________________________________ of class
___________________ roll no. ________________ has completed all the
practical work in the subject ______________________________________
satisfactorily in the department of
_______________________________________________ as prescribed by the
MIT World Peace University in the academic year 20__ - 20__.

Date:

Faculty in charge: Dr. Sumegh Tharewal

Signature:
INDEX

1. TIC TAC TOE


2. Breadth first search
3. Depth first search
4. Depth limit search
5. Uniform cost search
6. Iterative deepening Depth first search
7. Bidirectional search
8. Greedy search (Best first search)
9. A* search
10. Hill climbing search

1. Tic tac toe


from itertools import count
board=[['-','-','-'],
['-','-','-'],
['-','-','-']]
def draw_board():
for i in range(3):
print()
for j in range(3):
print(board[i][j],end='')
if j<2:
print('l',end='')
print()
def take_input():
pos=input("Enter a number:")
pos=int(pos)-1
return pos
def place_player(pos,player):
row=pos//3
column=pos%3
board[row][column]=player
return 1
def check_row(i):
x=0
o=0
for j in range(3):
if board[i][j]=='X':
x+=1
if board[i][j]=='O':
o+=1
if x==3:
print("X won")
quit()
elif 0==3:
print("O won")
quit()
def check_column(j):
x=0
o=0
for i in range(3):
if board[i][j]=='X':
x+=1
if board[i][j]=='O':
o+=1
if x==3:
print("X won")
quit()
elif o==3:
print("O won")
quit()
def check_tie():
for i in range(3):
for j in range(3):
if board[i][j]=='-':
return
else:
continue
print("The game is tied!!")
quit()
if x==3:
print("X won")
quit()
if o==3:
print("O won")
quit()
def check_diagonals(a,b,c):
var=[a,b,c]
x=0
o=0
for i in var:
if i=='X':
x+=1
if i=='O':
o+=1
if i==3:
print("X won")
quit()
elif i==3:
print("O won")
quit()
def main():
global game_on
game_on=True
count=0
while game_on:
if count%2==0:
player='X'
else:
player='O'
draw_board()
pos=take_input()
count+=place_player(pos,player)
check_tie()

for j in range(3):
check_column(j)
check_row(j)
check_diagonals(board[0][0],board[1][1],board[2][2])
check_diagonals(board[0][2],board[1][1],board[2][0])
if __name__=='__main__':
main()

OUTPUT
-l-l-
-l-l-
-l-l-
Enter a number:0
-l-l-

-l-l-
-l-lX

Enter a number:2
-lOl-
-l-l-
-l-lX

Enter a number:3
-lOlX
-l-l-
-l-lX

Enter a number:5
-lOlX
-lOl-
-l-lX

Enter a number:6
X won
-lOlX
-lOlX
-l-lX

2. Breadth first search


# BFS
graph = {
'5' : ['3','7'],
'3' : ['2', '4'],
'7' : ['8'],
'2' : [],
'4' : ['8'],
'8' : []
}
visited = [] # List for visited nodes.
queue = [] #Initialize a queue
def bfs(visited, graph, node): #function for BFS
visited.append(node)
queue.append(node)
while queue: # Creating loop to visit each node
m = queue.pop(0)
print (m, end = " ")
for neighbour in graph[m]:
if neighbour not in visited:
visited.append(neighbour)
queue.append(neighbour)
# Driver Code
print("Following is the Breadth-First Search")
bfs(visited, graph, '5')

OUTPUT
Following is the Breadth-First Search
5 3 7 2 4 8

3. Depth first search


#DFS
# Using a Python dictionary to act as an adjacency list
graph = {
'5' : ['3','7'],
'3' : ['2', '4'],
'7' : ['8'],
'2' : [],
'4' : ['8'],
'8' : []
}
visited = set() # Set to keep track of visited nodes of graph.
def dfs(visited, graph, node): #function for dfs
if node not in visited:
print (node)
visited.add(node)
for neighbour in graph[node]:
dfs(visited, graph, neighbour)
# Driver Code
print("Following is the Depth-First Search")
dfs(visited, graph, '5')

OUTPUT
Following is the Depth-First Search
5
3
2
4
8
7

4. Depth Limited Search


#DLS
graph = {
'A' : ['B','C'],
'B' : ['D', 'E'],
'C' : ['F', 'G'],
'D' : [],
'E' : [],
'F' : [],
'G' : []
}
def DLS(start,goal,path,level,maxD):
print('nCurrent level-->',level)
path.append(start)
if start == goal:
print("Goal test successful")
return path
print('Goal node testing failed')
if level==maxD:
return False
print('nExpanding the current node',start)
for child in graph[start]:
if DLS(child,goal,path,level+1,maxD):
return path
path.pop()
return False
start = 'A'
goal = input('Enter the goal node:-')
maxD = int(input("Enter the maximum depth limit:-"))
print()
path = list()
res = DLS(start,goal,path,0,maxD)
if(res):
print("Path to goal node available")
print("Path",path)
else:
print("No path available for the goal node in given depth limit")

OUTPUT
nCurrent level--> 0
Goal node testing failed
nExpanding the current node A
nCurrent level--> 1
Goal node testing failed
nExpanding the current node B
nCurrent level--> 2
Goal node testing failed
nExpanding the current node D
nCurrent level--> 2
Goal node testing failed
nExpanding the current node E
nCurrent level--> 1
Goal node testing failed
nExpanding the current node C
nCurrent level--> 2
Goal node testing failed
nExpanding the current node F
nCurrent level--> 2
Goal node testing failed
nExpanding the current node G
No path available for the goal node in given depth limit
5. iterative deepening depth first search
graph = {
'A': ['B', 'C'],
'B': ['D','E'],
"C": ['G'],
'D': [],
'E': ['F'],
'G': [],
'F':[]
}
path = list()
def DFS(currentNode,destination,graph,maxDepth,curList):
print("Checking for destination",currentNode)
curList.append(currentNode)
if currentNode==destination:
return True
if maxDepth<=0:
path.append(curList)
return False
for node in graph[currentNode]:
if DFS(node,destination,graph,maxDepth-1,curList):
return True
else:
curList.pop()
return False
def iterativeDDFS(currentNode,destination,graph,maxDepth):
for i in range(maxDepth):
curList = list()
if DFS(currentNode,destination,graph,i,curList):
return True
return False
if not iterativeDDFS('A','E',graph,4):
print("Path is not available")
else:
print("A path exists")
print(path.pop())

OUTPUT
Checking for destination A
Checking for destination A
Checking for destination B
Checking for destination C
Checking for destination A
Checking for destination B
Checking for destination D
Checking for destination E
A path exists
['A', 'B', 'E']

6. Uniform Cost Search


# Uniform cost serach
# returns the minimum cost in a vector( if
# there are multiple goal states)
def uniform_cost_search(goal, start):
# minimum cost upto
# goal state from starting
global graph,cost
answer = []
# create a priority queue
queue = []
# set the answer vector to max value
for i in range(len(goal)):
answer.append(10**8)
# insert the starting index
queue.append([0, start])
# map to store visited node
visited = {}
# count
count = 0
# while the queue is not empty
while (len(queue) > 0):
# get the top element of the
queue = sorted(queue)
p = queue[-1]
# pop the element
del queue[-1]
# get the original value
p[0] *= -1
# check if the element is part of
# the goal list
if (p[1] in goal):
# get the position
index = goal.index(p[1])
# if a new goal is reached
if (answer[index] == 10**8):
count += 1
# if the cost is less
if (answer[index] > p[0]):
answer[index] = p[0]
# pop the element
del queue[-1]
queue = sorted(queue)
if (count == len(goal)):
return answer
# check for the non visited nodes
# which are adjacent to present node
if (p[1] not in visited):
for i in range(len(graph[p[1]])):
# value is multiplied by -1 so that
# least priority is at the top
queue.append( [(p[0] + cost[(p[1], graph[p[1]][i])])* -1,
graph[p[1]][i]])
# mark as visited
visited[p[1]] = 1
return answer
# main function
if __name__ == '__main__':
# create the graph
graph,cost = [[] for i in range(8)],{}
# add edge
graph[0].append(1)
graph[0].append(3)
graph[3].append(1)
graph[3].append(6)
graph[3].append(4)
graph[1].append(6)
graph[4].append(2)
graph[4].append(5)
graph[2].append(1)
graph[5].append(2)
graph[5].append(6)
graph[6].append(4)
# add the cost
cost[(0, 1)] = 2
cost[(0, 3)] = 5
cost[(1, 6)] = 1
cost[(3, 1)] = 5
cost[(3, 6)] = 6
cost[(3, 4)] = 2
cost[(2, 1)] = 4
cost[(4, 2)] = 4
cost[(4, 5)] = 3
cost[(5, 2)] = 6
cost[(5, 6)] = 3
cost[(6, 4)] = 7
# goal state
goal = []
# set the goal
# there can be multiple goal states
goal.append(6)
# get the answer
answer = uniform_cost_search(goal, 0)
# print the answer
print("Minimum cost from 0 to 6 is = ",answer[0])

OUTPUT
Minimum cost from 0 to 6 is = 3

7. Bidirectional Search
class adjacent_Node:
def __init__(self, v):
self.vertex = v
self.next = None
class bidirectional_Search:
def __init__(self, vertices):
self.vertices = vertices
self.graph = [None] * self.vertices
self.source_queue = list()
self.last_node_queue = list()
self.source_visited = [False] * self.vertices
self.last_node_visited = [False] * self.vertices
self.source_parent = [None] * self.vertices
self.last_node_parent = [None] * self.vertices
def AddEdge(self, source, last_node):
node = adjacent_Node(last_node)
node.next = self.graph[source]
self.graph[source] = node
node = adjacent_Node(source)
node.next = self.graph[last_node]
self.graph[last_node] = node
def breadth_fs(self, direction = 'forward'):
if direction == 'forward':
current = self.source_queue.pop(0)
connected_node = self.graph[current]
while connected_node:
vertex = connected_node.vertex
if not self.source_visited[vertex]:
self.source_queue.append(vertex)
self.source_visited[vertex] = True
self.source_parent[vertex] = current
connected_node = connected_node.next
else:
current = self.last_node_queue.pop(0)
connected_node = self.graph[current]
while connected_node:
vertex = connected_node.vertex
if not self.last_node_visited[vertex]:
self.last_node_queue.append(vertex)
self.last_node_visited[vertex] = True
self.last_node_parent[vertex] = current
connected_node = connected_node.next
def is_intersecting(self):
for i in range(self.vertices):
if (self.source_visited[i] and
self.last_node_visited[i]):
return i
return -1
def path_st(self, intersecting_node,
source, last_node):
path = list()
path.append(intersecting_node)
i = intersecting_node
while i != source:
path.append(self.source_parent[i])
i = self.source_parent[i]
path = path[::-1]
i = intersecting_node
while i != last_node:
path.append(self.last_node_parent[i])
i = self.last_node_parent[i]
print("*****Path*****")
path = list(map(str, path))
print(' '.join(path))
def bidirectional_search(self, source, last_node):
self.source_queue.append(source)
self.source_visited[source] = True
self.source_parent[source] = -1
self.last_node_queue.append(last_node)
self.last_node_visited[last_node] = True
self.last_node_parent[last_node] = -1
while self.source_queue and self.last_node_queue:
self.breadth_fs(direction = 'forward')
self.breadth_fs(direction = 'backward')
intersecting_node = self.is_intersecting()
if intersecting_node != -1:
print("Path exists between {} and {}".format(source,
last_node))
print("Intersection at : {}".format(intersecting_node))
self.path_st(intersecting_node, source, last_node)
exit(0)
return -1
if __name__ == '__main__':
n = 17
source = 1
last_node = 16
my_Graph = bidirectional_Search(n)
my_Graph.AddEdge(1, 4)
my_Graph.AddEdge(2, 4)
my_Graph.AddEdge(3, 6)
my_Graph.AddEdge(5, 6)
my_Graph.AddEdge(4, 8)
my_Graph.AddEdge(6, 8)
my_Graph.AddEdge(8, 9)
my_Graph.AddEdge(9, 10)
my_Graph.AddEdge(10, 11)
my_Graph.AddEdge(11, 13)
my_Graph.AddEdge(11, 14)
my_Graph.AddEdge(10, 12)
my_Graph.AddEdge(12, 15)
my_Graph.AddEdge(12, 16)
out = my_Graph.bidirectional_search(source, last_node)
if out == -1:
print("No path between {} and {}".format(source, last_node))

OUTPUT
Path exists between 1 and 16
Intersection at : 9
*****Path*****
1 4 8 9 10 12 16
Path exists between 1 and 16
Intersection at : 9
*****Path*****
1 4 8 9 10 12 16
Path exists between 1 and 16
Intersection at : 8
*****Path*****
1 4 8 9 10 12 16
Path exists between 1 and 16
Intersection at : 8
*****Path*****
1 4 8 9 10 12 16
Path exists between 1 and 16
Intersection at : 8
*****Path*****
1 4 8 9 10 12 16
Path exists between 1 and 16
Intersection at : 4
*****Path*****
1 4 8 9 10 12 16
Path exists between 1 and 16
Intersection at : 3
*****Path*****
1 4 8 6 3 6 8 9 10 12 16
Path exists between 1 and 16
Intersection at : 1
*****Path*****
1 4 8 9 10 12 16
Path exists between 1 and 16
Intersection at : 1
*****Path*****
1 4 8 9 10 12 16
Path exists between 1 and 16
Intersection at : 1
*****Path*****
1 4 8 9 10 12 16
Path exists between 1 and 16
Intersection at : 1
*****Path*****
1 4 8 9 10 12 16
Path exists between 1 and 16
Intersection at : 1
*****Path*****
1 4 8 9 10 12 16
No path between 1 and 16

8. Greedy BFS
#Greedy BFS
from queue import PriorityQueue
# Filling adjacency matrix with empty arrays
vertices = 14
graph = [[] for i in range(vertices)]
# Function for adding edges to graph
def add_edge(x, y, cost):
graph[x].append((y, cost))
graph[y].append((x, cost))
# Function For Implementing Best First Search
# Gives output path having the lowest cost
def best_first_search(source, target, vertices):
visited = [0] * vertices
pq = PriorityQueue()
pq.put((0, source))
print("Path: ")
while not pq.empty():
u = pq.get()[1]
# Displaying the path having the lowest cost
print(u, end=" ")
if u == target:
break
for v, c in graph[u]:
if not visited[v]:
visited[v] = True
pq.put((c, v))
print()
if __name__ == '__main__':
# The nodes shown in above example(by alphabets) are
# implemented using integers add_edge(x,y,cost);
add_edge(0, 1, 1)
add_edge(0, 2, 8)
add_edge(1, 2, 12)
add_edge(1, 4, 13)
add_edge(2, 3, 6)
add_edge(4, 3, 3)
source = 0
target = 2
best_first_search(source, target, vertices)

OUTPUT
Path:
0 1 0 2

9. A* algoritm
# A* algorithm
def aStarAlgo(start_node, stop_node):
open_set = set(start_node)
closed_set = set()
g = {} #store distance from starting node
parents = {}# parents contains an adjacency map of all nodes
#ditance of starting node from itself is zero
g[start_node] = 0
#start_node is root node i.e it has no parent nodes
#so start_node is set to its own parent node
parents[start_node] = start_node
while len(open_set) > 0:
n = None
#node with lowest f() is found
for v in open_set:
if n == None or g[v] + heuristic(v) < g[n] + heuristic(n):
n = v
if n == stop_node or Graph_nodes[n] == None:
pass
else:
for (m, weight) in get_neighbors(n):
#nodes 'm' not in first and last set are added to first
#n is set its parent
if m not in open_set and m not in closed_set:
open_set.add(m)
parents[m] = n
g[m] = g[n] + weight
#for each node m,compare its distance from start i.e g(m) to
the
#from start through n node
else:
if g[m] > g[n] + weight:
#update g(m)
g[m] = g[n] + weight
#change parent of m to n
parents[m] = n
#if m in closed set,remove and add to open
if m in closed_set:
closed_set.remove(m)
open_set.add(m)
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:
path = []
while parents[n] != n:
path.append(n)
n = parents[n]
path.append(start_node)
path.reverse()
print('Path found: {}'.format(path))
return path
# remove n from the open_list, and add it to closed_list
# because all of his neighbors were inspected
open_set.remove(n)
closed_set.add(n)
print('Path does not exist!')
return None
#define fuction to return neighbor and its distance
#from the passed node
def get_neighbors(v):
if v in Graph_nodes:
return Graph_nodes[v]
else:
return None
#for simplicity we ll consider heuristic distances given
#and this function returns heuristic distance for all nodes
def heuristic(n):
H_dist = {
'A': 11,
'B': 6,
'C': 99,
'D': 1,
'E': 7,
'G': 0,

}
return H_dist[n]
#Describe your graph here
Graph_nodes = {
'A': [('B', 2), ('E', 3)],
'B': [('C', 1),('G', 9)],
'C': None,
'E': [('D', 6)],
'D': [('G', 1)],

}
aStarAlgo('A', 'G')

OUTPUT
Path found: ['A', 'E', 'D', 'G']
['A', 'E', 'D', 'G']

10. Hill Climb


#Hill Climb
import numpy as np
def find_neighbours(state, landscape):

neighbours = []
dim = landscape.shape
# left neighbour
if state[0] != 0:
neighbours.append((state[0] - 1, state[1]))
# right neighbour
if state[0] != dim[0] - 1:
neighbours.append((state[0] + 1, state[1]))
# top neighbour
if state[1] != 0:
neighbours.append((state[0], state[1] - 1))
# bottom neighbour
if state[1] != dim[1] - 1:
neighbours.append((state[0], state[1] + 1))
# top left
if state[0] != 0 and state[1] != 0:
neighbours.append((state[0] - 1, state[1] - 1))
# bottom left
if state[0] != 0 and state[1] != dim[1] - 1:
neighbours.append((state[0] - 1, state[1] + 1))
# top right
if state[0] != dim[0] - 1 and state[1] != 0:
neighbours.append((state[0] + 1, state[1] - 1))
# bottom right
if state[0] != dim[0] - 1 and state[1] != dim[1] - 1:
neighbours.append((state[0] + 1, state[1] + 1))
return neighbours
# Current optimization objective: local/global maximum
def hill_climb(curr_state, landscape):
neighbours = find_neighbours(curr_state, landscape)
bool
ascended = False
next_state = curr_state
for neighbour in neighbours: #Find the neighbour with the greatest value
if landscape[neighbour[0]][neighbour[1]] > landscape[next_state[0]]
[next_state[1]]:
next_state = neighbour
ascended = True
return ascended, next_state
def __main__():
landscape = np.random.randint(1, high=50, size=(10, 10))
print(landscape)
start_state = (3, 6) # matrix index coordinates
current_state = start_state
count = 1
ascending = True
while ascending:
print("\nStep #", count)
print("Current state coordinates: ", current_state)
print("Current state value: ", landscape[current_state[0]]
[current_state[1]])
count += 1
ascending, current_state = hill_climb(current_state, landscape)
print("\nStep #", count)
print("Optimization objective reached.")
print("Final state coordinates: ", current_state)
print("Final state value: ", landscape[current_state[0]][current_state[1]])
__main__()

OUTPUT
[[ 8 4 34 38 12 40 38 26 42 34]
[46 26 46 14 34 14 4 29 46 41]
[44 41 15 32 37 39 23 7 20 11]
[15 46 40 38 25 14 48 10 8 48]
[29 21 1 26 35 44 35 44 49 29]
[10 16 24 3 38 12 47 6 23 42]
[35 21 6 4 4 36 45 4 49 7]
[22 37 49 16 26 26 39 11 44 42]
[30 21 2 13 16 41 28 14 40 48]
[22 46 20 12 20 14 40 6 23 23]]

Step # 1
Current state coordinates: (3, 6)
Current state value: 48

Step # 2
Optimization objective reached.
Final state coordinates: (3, 6)
Final state value: 48

You might also like