0% found this document useful (0 votes)
6 views23 pages

AI Lab

The document contains implementations of various algorithms and problems in Python, including Breadth-First Search (BFS), Depth-First Search (DFS), the Traveling Salesman Problem, Simulated Annealing, the Wumpus Problem, and the 8-puzzle problem. Each section provides a class structure and methods to execute the respective algorithms, demonstrating their functionality through driver code. These implementations serve as examples for understanding graph traversal, optimization techniques, and problem-solving in artificial intelligence.

Uploaded by

s.dineshwar1231
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)
6 views23 pages

AI Lab

The document contains implementations of various algorithms and problems in Python, including Breadth-First Search (BFS), Depth-First Search (DFS), the Traveling Salesman Problem, Simulated Annealing, the Wumpus Problem, and the 8-puzzle problem. Each section provides a class structure and methods to execute the respective algorithms, demonstrating their functionality through driver code. These implementations serve as examples for understanding graph traversal, optimization techniques, and problem-solving in artificial intelligence.

Uploaded by

s.dineshwar1231
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/ 23

1.

BFS
from collections import defaultdict

# This class represents a directed graph


# using adjacency list representation
class Graph:

# Constructor
def __init__(self):

# Default dictionary to store graph


self.graph = defaultdict(list)

# Function to add an edge to graph


def addEdge(self, u, v):
self.graph[u].append(v)

# Function to print a BFS of graph


def BFS(self, s):

# Mark all the vertices as not visited


visited = [False] * (max(self.graph) + 1)

# Create a queue for BFS


queue = []

# Mark the source node as


# visited and enqueue it
queue.append(s)
visited[s] = True

while queue:
# Dequeue a vertex from
# queue and print it
s = queue.pop(0)
print(s, end=" ")

# Get all adjacent vertices of the


# dequeued vertex s.
# If an adjacent has not been visited,
# then mark it visited and enqueue it
for i in self.graph[s]:
if not visited[i]:
queue.append(i)
visited[i] = True

# Driver code
if __name__ == '__main__':

# Create a graph given in


# the above diagram
g = Graph()
g.addEdge(0, 1)
g.addEdge(0, 2)
g.addEdge(1, 2)
g.addEdge(2, 0)
g.addEdge(2, 3)
g.addEdge(3, 3)

print("Following is Breadth First Traversal"


" (starting from vertex 2)")
g.BFS(2)
Output:

2. DFS
# Python3 program to print DFS traversal
# from a given graph
from collections import defaultdict

# This class represents a directed graph using


# adjacency list representation
class Graph:

# Constructor
def __init__(self):

# Default dictionary to store graph


self.graph = defaultdict(list)

# Function to add an edge to graph


def addEdge(self, u, v):
self.graph[u].append(v)

# A function used by DFS


def DFSUtil(self, v, visited):

# Mark the current node as visited


# and print it
visited.add(v)
print(v, end=' ')

# Recur for all the vertices


# adjacent to this vertex
for neighbour in self.graph[v]:
if neighbour not in visited:
self.DFSUtil(neighbour, visited)

# The function to do DFS traversal. It uses


# recursive DFSUtil()
def DFS(self, v):

# Create a set to store visited vertices


visited = set()

# Call the recursive helper function


# to print DFS traversal
self.DFSUtil(v, visited)

# Driver's code
if __name__ == "__main__":
g = Graph()
g.addEdge(0, 1)
g.addEdge(0, 2)
g.addEdge(1, 2)
g.addEdge(2, 0)
g.addEdge(2, 3)
g.addEdge(3, 3)

print("Following is Depth First Traversal (starting from vertex 2)")


# Function call
g.DFS(2)

Output:

3. Travelling Salesperson Problem

# Python3 program to implement traveling salesman


# problem using naive approach.
from sys import maxsize
from itertools import permutations
V=4

# implementation of traveling Salesman Problem


def travellingSalesmanProblem(graph, s):

# store all vertex apart from source vertex


vertex = []
for i in range(V):
if i != s:
vertex.append(i)

# store minimum weight Hamiltonian Cycle


min_path = maxsize
next_permutation=permutations(vertex)
for i in next_permutation:

# store current Path weight(cost)


current_pathweight = 0

# compute current path weight


k=s
for j in i:
current_pathweight += graph[k][j]
k=j
current_pathweight += graph[k][s]

# update minimum
min_path = min(min_path, current_pathweight)

return min_path
# Driver Code
if __name__ == "__main__":

# matrix representation of graph


graph = [[0, 10, 15, 20], [10, 0, 35, 25],
[15, 35, 0, 30], [20, 25, 30, 0]]
s=0
print(travellingSalesmanProblem(graph, s))

4. Implementation of Simulated Annealing


import math
import random

# Objective function: Rastrigin function


def objective_function(x):
return 10 * len(x) + sum([(xi**2 - 10 * math.cos(2 * math.pi * xi)) for xi
in x])

# Neighbor function: small random change


def get_neighbor(x, step_size=0.1):
neighbor = x[:]
index = random.randint(0, len(x) - 1)
neighbor[index] += random.uniform(-step_size, step_size)
return neighbor

# Simulated Annealing function


def simulated_annealing(objective, bounds, n_iterations, step_size, temp):
# Initial solution
best = [random.uniform(bound[0], bound[1]) for bound in bounds]
best_eval = objective(best)
current, current_eval = best, best_eval
scores = [best_eval]

for i in range(n_iterations):
# Decrease temperature
t = temp / float(i + 1)
# Generate candidate solution
candidate = get_neighbor(current, step_size)
candidate_eval = objective(candidate)
# Check if we should keep the new solution
if candidate_eval < best_eval or random.random() <
math.exp((current_eval - candidate_eval) / t):
current, current_eval = candidate, candidate_eval
if candidate_eval < best_eval:
best, best_eval = candidate, candidate_eval
scores.append(best_eval)

# Optional: print progress


if i % 100 == 0:
print(f"Iteration {i}, Temperature {t:.3f}, Best Evaluation
{best_eval:.5f}")

return best, best_eval, scores

# Define problem domain


bounds = [(-5.0, 5.0) for _ in range(2)] # for a 2-dimensional Rastrigin
function
n_iterations = 1000
step_size = 0.1
temp = 10

# Perform the simulated annealing search


best, score, scores = simulated_annealing(objective_function, bounds,
n_iterations, step_size, temp)

print(f'Best Solution: {best}')


print(f'Best Score: {score}')

5. Wumpus Problem

class Agent:
def __init__(self):
self.__wumpusWorld = [
['','','P',''], # Rooms [1,1] to [4,1]
['','','',''], # Rooms [1,2] to [4,2]
['W','','',''], # Rooms [1,3] to [4,3]
['','','',''], # Rooms [1,4] to [4,4]
] # This is the wumpus world shown in the assignment question.
# A different instance of the wumpus world will be used for
evaluation.
self.__curLoc = [1,1]
self.__isAlive = True
self.__hasExited = False

def __FindIndicesForLocation(self,loc):
x,y = loc
i,j = y-1, x-1
return i,j

def __CheckForPitWumpus(self):
ww = self.__wumpusWorld
i,j = self.__FindIndicesForLocation(self.__curLoc)
if 'P' in ww[i][j] or 'W' in ww[i][j]:
print(ww[i][j])
self.__isAlive = False
print('Agent is DEAD.')
return self.__isAlive

def TakeAction(self,action): # The function takes an action and returns


whether the Agent is alive
# after taking the action.
validActions = ['Up','Down','Left','Right']
assert action in validActions, 'Invalid Action.'
if self.__isAlive == False:
print('Action cannot be performed. Agent is DEAD. Location:
{0}'.format(self.__curLoc))
return False
if self.__hasExited == True:
print('Action cannot be performed. Agent has exited the Wumpus
world.'.format(self.__curLoc))
return False

index = validActions.index(action)
validMoves = [[0,1],[0,-1],[-1,0],[1,0]]
move = validMoves[index]
newLoc = []
for v, inc in zip(self.__curLoc,move):
z = v + inc #increment location index
z = 4 if z>4 else 1 if z<1 else z #Ensure that index is between 1
and 4

newLoc.append(z)
self.__curLoc = newLoc
print('Action Taken: {0}, Current Location
{1}'.format(action,self.__curLoc))
if self.__curLoc[0]==4 and self.__curLoc[1]==4:
self.__hasExited=True
return self.__CheckForPitWumpus()

def __FindAdjacentRooms(self):
cLoc = self.__curLoc
validMoves = [[0,1],[0,-1],[-1,0],[1,0]]
adjRooms = []
for vM in validMoves:
room = []
valid = True
for v, inc in zip(cLoc,vM):
z = v + inc
if z<1 or z>4:
valid = False
break
else:
room.append(z)
if valid==True:
adjRooms.append(room)
return adjRooms

def PerceiveCurrentLocation(self): #This function perceives the current


location.
#It tells whether breeze and stench are present
in the current location.
breeze, stench = False, False
ww = self.__wumpusWorld
if self.__isAlive == False:
print('Agent cannot perceive. Agent is DEAD. Location:
{0}'.format(self.__curLoc))
return [None,None]
if self.__hasExited == True:
print('Agent cannot perceive. Agent has exited the Wumpus
World.'.format(self.__curLoc))
return [None,None]

adjRooms = self.__FindAdjacentRooms()
for room in adjRooms:
i,j = self.__FindIndicesForLocation(room)
if 'P' in ww[i][j]:
breeze = True
if 'W' in ww[i][j]:
stench = True
return [breeze,stench]

def FindCurrentLocation(self):
return self.__curLoc

def main():
ag = Agent()

print('curLoc',ag.FindCurrentLocation())
print('Percept [breeze, stench] :',ag.PerceiveCurrentLocation())
ag.TakeAction('Right')
print('Percept',ag.PerceiveCurrentLocation())
ag.TakeAction('Right')
print('Percept',ag.PerceiveCurrentLocation())
ag.TakeAction('Right')
print('Percept',ag.PerceiveCurrentLocation())
ag.TakeAction('Up')
print('Percept',ag.PerceiveCurrentLocation())
ag.TakeAction('Up')
print('Percept',ag.PerceiveCurrentLocation())
ag.TakeAction('Up')
print('Percept',ag.PerceiveCurrentLocation())

if __name__=='__main__':
main()

6. 8 puzzle Problem
# Python code to display the way from the root
# node to the final destination node for N*N-1 puzzle
# algorithm by the help of Branch and Bound technique
# The answer assumes that the instance of the
# puzzle can be solved

# Importing the 'copy' for deepcopy method


import copy

# Importing the heap methods from the python


# library for the Priority Queue
from heapq import heappush, heappop

# This particular var can be changed to transform


# the program from 8 puzzle(n=3) into 15
# puzzle(n=4) and so on ...
n=3

# bottom, left, top, right


rows = [ 1, 0, -1, 0 ]
cols = [ 0, -1, 0, 1 ]

# creating a class for the Priority Queue


class priorityQueue:

# Constructor for initializing a


# Priority Queue
def __init__(self):
self.heap = []

# Inserting a new key 'key'


def push(self, key):
heappush(self.heap, key)

# funct to remove the element that is minimum,


# from the Priority Queue
def pop(self):
return heappop(self.heap)

# funct to check if the Queue is empty or not


def empty(self):
if not self.heap:
return True
else:
return False

# structure of the node


class nodes:

def __init__(self, parent, mats, empty_tile_posi,


costs, levels):

# This will store the parent node to the


# current node And helps in tracing the
# path when the solution is visible
self.parent = parent

# Useful for Storing the matrix


self.mats = mats

# useful for Storing the position where the


# empty space tile is already existing in the matrix
self.empty_tile_posi = empty_tile_posi

# Store no. of misplaced tiles


self.costs = costs

# Store no. of moves so far


self.levels = levels

# This func is used in order to form the


# priority queue based on
# the costs var of objects
def __lt__(self, nxt):
return self.costs < nxt.costs

# method to calc. the no. of


# misplaced tiles, that is the no. of non-blank
# tiles not in their final posi
def calculateCosts(mats, final) -> int:

count = 0
for i in range(n):
for j in range(n):
if ((mats[i][j]) and
(mats[i][j] != final[i][j])):
count += 1

return count

def newNodes(mats, empty_tile_posi, new_empty_tile_posi,


levels, parent, final) -> nodes:

# Copying data from the parent matrixes to the present matrixes


new_mats = copy.deepcopy(mats)

# Moving the tile by 1 position


x1 = empty_tile_posi[0]
y1 = empty_tile_posi[1]
x2 = new_empty_tile_posi[0]
y2 = new_empty_tile_posi[1]
new_mats[x1][y1], new_mats[x2][y2] = new_mats[x2][y2],
new_mats[x1][y1]

# Setting the no. of misplaced tiles


costs = calculateCosts(new_mats, final)

new_nodes = nodes(parent, new_mats, new_empty_tile_posi,


costs, levels)
return new_nodes
# func to print the N by N matrix
def printMatsrix(mats):

for i in range(n):
for j in range(n):
print("%d " % (mats[i][j]), end = " ")

print()

# func to know if (x, y) is a valid or invalid


# matrix coordinates
def isSafe(x, y):

return x >= 0 and x < n and y >= 0 and y < n

# Printing the path from the root node to the final node
def printPath(root):

if root == None:
return

printPath(root.parent)
printMatsrix(root.mats)
print()

# method for solving N*N - 1 puzzle algo


# by utilizing the Branch and Bound technique. empty_tile_posi is
# the blank tile position initially.
def solve(initial, empty_tile_posi, final):

# Creating a priority queue for storing the live


# nodes of the search tree
pq = priorityQueue()

# Creating the root node


costs = calculateCosts(initial, final)
root = nodes(None, initial,
empty_tile_posi, costs, 0)

# Adding root to the list of live nodes


pq.push(root)

# Discovering a live node with min. costs,


# and adding its children to the list of live
# nodes and finally deleting it from
# the list.
while not pq.empty():

# Finding a live node with min. estimatsed


# costs and deleting it form the list of the
# live nodes
minimum = pq.pop()

# If the min. is ans node


if minimum.costs == 0:

# Printing the path from the root to


# destination;
printPath(minimum)
return

# Generating all feasible children


for i in range(n):
new_tile_posi = [
minimum.empty_tile_posi[0] + rows[i],
minimum.empty_tile_posi[1] + cols[i], ]

if isSafe(new_tile_posi[0], new_tile_posi[1]):

# Creating a child node


child = newNodes(minimum.mats,
minimum.empty_tile_posi,
new_tile_posi,
minimum.levels + 1,
minimum, final,)

# Adding the child to the list of live nodes


pq.push(child)

# Main Code

# Initial configuration
# Value 0 is taken here as an empty space
initial = [ [ 1, 2, 3 ],
[ 5, 6, 0 ],
[ 7, 8, 4 ] ]

# Final configuration that can be solved


# Value 0 is taken as an empty space
final = [ [ 1, 2, 3 ],
[ 5, 8, 6 ],
[ 0, 7, 4 ] ]

# Blank tile coordinates in the


# initial configuration
empty_tile_posi = [ 1, 2 ]

# Method call for solving the puzzle


solve(initial, empty_tile_posi, final)
7. Towers of Hanoi
def tower_of_hanoi(disks, source, auxiliary, target):
# Base case: If there's only one disk, move it directly from source to
target
if disks == 1:
print('Move disk 1 from rod {} to rod {}.'.format(source, target))
return
# Move the top (n-1) disks from source to auxiliary, using target as
auxiliary
tower_of_hanoi(disks - 1, source, target, auxiliary)
# Move the nth disk from source to target
print('Move disk {} from rod {} to rod {}.'.format(disks, source, target))
# Move the (n-1) disks from auxiliary to target, using source as auxiliary
tower_of_hanoi(disks - 1, auxiliary, source, target)

# Input number of disks


disks = int(input('Enter the number of disks: '))
# Calling the function: source=A, auxiliary=B, target=C
tower_of_hanoi(disks, 'A', 'B', 'C')
8. Implement A* algorithm
from queue import PriorityQueue

# Creating Base Class


class State(object):
def __init__(self, value, parent, start=0, goal=0):
self.children = []
self.parent = parent
self.value = value
self.dist = 0
if parent:
self.start = parent.start
self.goal = parent.goal
self.path = parent.path[:]
self.path.append(value)
else:
self.path = [value]
self.start = start
self.goal = goal

def GetDistance(self):
pass

def CreateChildren(self):
pass
# Creating subclass
class State_String(State):
def __init__(self, value, parent, start=0, goal=0):
super(State_String, self).__init__(value, parent, start, goal)
self.dist = self.GetDistance()

def GetDistance(self):
if self.value == self.goal:
return 0
dist = 0
for i in range(len(self.goal)):
letter = self.goal[i]
if letter in self.value:
dist += abs(i - self.value.index(letter))
else:
dist += len(self.goal) # Penalty if letter is not in the string
return dist

def CreateChildren(self):
if not self.children:
for i in range(len(self.value) - 1):
val = list(self.value)
# Swap adjacent letters
val[i], val[i + 1] = val[i + 1], val[i]
child = State_String("".join(val), self)
self.children.append(child)

# Creating a class that holds the final magic


class A_Star_Solver:
def __init__(self, start, goal):
self.path = []
self.visitedQueue = []
self.priorityQueue = PriorityQueue()
self.start = start
self.goal = goal

def Solve(self):
startState = State_String(self.start, None, self.start, self.goal)
count = 0
self.priorityQueue.put((0, count, startState))

while not self.path and not self.priorityQueue.empty():


closestChild = self.priorityQueue.get()[2]
closestChild.CreateChildren()
self.visitedQueue.append(closestChild.value)

for child in closestChild.children:


if child.value not in self.visitedQueue:
count += 1
if not child.dist:
self.path = child.path
break
self.priorityQueue.put((child.dist, count, child))

if not self.path:
print("Goal is not possible: " + self.goal)
return self.path

# Calling all the existing stuff


if __name__ == "__main__":
start1 = "path"
goal1 = "hpta"
print("Starting....")
a = A_Star_Solver(start1, goal1)
result_path = a.Solve()
for i in range(len(result_path)):
print("{0}) {1}".format(i, result_path[i]))

9. Hill Climbing Algorithm


import random

def randomSolution(tsp):
cities = list(range(len(tsp)))
solution = []
for i in range(len(tsp)):
randomCity = cities[random.randint(0, len(cities) - 1)]
solution.append(randomCity)
cities.remove(randomCity)
return solution

def routeLength(tsp, solution):


route_length = 0
for i in range(len(solution)):
route_length += tsp[solution[i - 1]][solution[i]]
return route_length

def getNeighbours(solution):
neighbours = []
for i in range(len(solution)):
for j in range(i + 1, len(solution)):
neighbour = solution.copy()
neighbour[i], neighbour[j] = neighbour[j], neighbour[i] # Swap two cities
neighbours.append(neighbour)
return neighbours

def getBestNeighbour(tsp, neighbours):


bestRouteLength = routeLength(tsp, neighbours[0])
bestNeighbour = neighbours[0]

for neighbour in neighbours:


currentRouteLength = routeLength(tsp, neighbour)
if currentRouteLength < bestRouteLength:
bestRouteLength = currentRouteLength
bestNeighbour = neighbour

return bestNeighbour, bestRouteLength

def hillClimbing(tsp):
currentSolution = randomSolution(tsp)
currentRouteLength = routeLength(tsp, currentSolution)

while True:
neighbours = getNeighbours(currentSolution)
bestNeighbour, bestNeighbourRouteLength = getBestNeighbour(tsp,
neighbours)

if bestNeighbourRouteLength < currentRouteLength:


currentSolution = bestNeighbour
currentRouteLength = bestNeighbourRouteLength
else:
break # Stop if no better neighbour is found

return currentSolution, currentRouteLength


def main():
tsp = [
[0, 400, 500, 300],
[400, 0, 300, 500],
[500, 300, 0, 400],
[300, 500, 400, 0]
]
solution, length = hillClimbing(tsp)
print("Best solution:", solution)
print("Route length:", length)

if __name__ == "__main__":
main()

10.
def greet(bot_name, birth_year):
print("Hello! My name is {0}.".format(bot_name))
print("I was created in {0}.".format(birth_year))

def remind_name():
print('Please, remind me your name.')
name = input()
print("What a great name you have, {0}!".format(name))

def provide_information():
while True:
print("What information would you like to know?")
print("1. Courses offered this semester")
print("2. Next campus event")
print("3. How to apply for financial aid")
print("4. College facilities")
print("5. Student organizations")

choice = int(input("Enter your choice (1-5): "))

if choice == 1:
print("This semester, we offer the following courses:")
print("- Mathematics 101")
print("- Introduction to Computer Science")
print("- English Literature")
print("- Biology 101")
print("- History of Art")
elif choice == 2:
print("The next campus event is the career fair on March 15th from 10
AM to 4 PM in the Student Center.")
elif choice == 3:
print("To apply for financial aid, visit the Financial Aid Office or check our
website for scholarship opportunities.")
elif choice == 4:
print("Our college has the following facilities:")
print("- Library")
print("- Gymnasium")
print("- Student Lounge")
print("- Computer Lab")
print("- Cafeteria")
elif choice == 5:
print("Here are some popular student organizations:")
print("- Coding Club")
print("- Art Society")
print("- Debate Team")
print("- Environmental Club")
else:
print("I’m sorry, I didn’t understand that.")

# Ask if they want more information or to exit


continue_choice = input("Would you like to ask another question? (yes/no):
").strip().lower()
if continue_choice != 'yes':
print("Exiting.")
break
def end():
print('Congratulations, have a nice day!')
input()

# Start of the program


greet('CollegeInfoBot', '2024') # Change as needed
remind_name()
provide_information()
end()

You might also like