Artificial Intelligence Lab Manual R20
Artificial Intelligence Lab Manual R20
(R20)
AI -LAB MANUAL
1. Write a program to implement DFS and BFS
Breadth-first search (BFS) is an algorithm used for tree traversal on graphs or tree data
structures. BFS can be easily implemented using recursion and data structures like dictionaries
and lists.
The Algorithm
1. Pick any node, visit the adjacent unvisited vertex, mark it as visited, display it, and insert
it in a queue.
2. If there are no remaining adjacent vertices left, remove the first vertex from the queue.
3. Repeat step 1 and step 2 until the queue is empty or the desired node is found.
Implementation
Consider the below graph, which is to be implemented:
SOURCE CODE:
graph = {
'A' : ['B','C'],
'B' : ['D', 'E'],
'C' : ['F'],
'D' : [],
'E' : ['F'],
'F' : []
}
visited = [] # List to keep track of visited nodes.
queue = [] #Initialize a queue
while queue:
s = queue.pop(0)
print (s, end = " ")
Explanation
➢ Lines 3-10: The illustrated graph is represented using an adjacency list. An easy way
to do this in Python is to use a dictionary data structure, where each vertex has a
stored list of its adjacent nodes.
➢ Line 12: visited is a list that is used to keep track of visited nodes.
➢ Line 13: queue is a list that is used to keep track of nodes currently in the queue.
➢ Line 29: The arguments of the bfs function are the visited list, the graph in the form
of a dictionary, and the starting node A.
➢ Lines 15-26: bfs follows the algorithm described above:
1. It checks and appends the starting
node to the visited list and the queue.
2. Then, while the queue contains
elements, it keeps taking out nodes from the queue, appends the neighbors of that node to
the queue if they are unvisited, and marks them as visited.
3. This continues until the queue is
empty.
Time Complexity
Since all of the nodes and vertices are visited, the time complexity for BFS on a graph
is O(V + E)O(V+E); where VV is the number of vertices and EE is the number of edges.
Depth-first search (DFS), is an algorithm for tree traversal on graph or tree data structures. It
can be implemented easily using recursion and data structures like dictionaries and sets.
The Algorithm
1. Pick any node. If it is unvisited, mark it as visited and recur on all its adjacent nodes.
2. Repeat until all the nodes are visited, or the node to be searched is found.
Implementation
Consider the below graph, which is to be implemented:
SOURCE CODE:
# Using a Python dictionary to act as an adjacency list
graph = {
'A' : ['B','C'],
'B' : ['D', 'E'],
'C' : ['F'],
'D' : [],
'E' : ['F'],
'F' : []
}
visited = set() # Set to keep track of visited nodes.
Explanation
• Lines 2-9: The illustrated graph is represented using an adjacency list - an easy way to
do it in Python is to use a dictionary data structure. Each vertex has a list of its adjacent
nodes stored.
• Line 11: visited is a set that is used to keep track of visited nodes.
• Line 21: The dfs function is called and is passed the visited set, the graph in the form of a
dictionary, and A, which is the starting node.
• Lines 13-18: dfs follows the algorithm described above:
1. It first checks if the current node is unvisited - if yes, it is appended in
the visited set.
2. Then for each neighbor of the current node, the dfs function is invoked again.
3. The base case is invoked when all the nodes are visited. The function then returns.
Time Complexity
• Since all the nodes and vertices are visited, the average time complexity for DFS on a
graph is O(V + E)O(V+E), where VV is the number of vertices and EE is the number of
edges. In case of DFS on a tree, the time complexity is O(V)O(V), where VV is the
number of nodes.
Note: We say average time complexity because a set’s in operation has an average time
complexity of O(1)O(1). If we used a list, the complexity would be higher.
2. Write a Program to find the solution for travelling salesman Problem.
What is a Travelling Salesperson Problem?
➢ The travelling salesperson problem (TSP) is a classic optimization problem where the
goal is to determine the shortest tour of a collection of n “cities” (i.e. nodes), starting and
ending in the same city and visiting all of the other cities exactly once.
➢ In such a situation, a solution can be represented by a vector of n integers, each in the
range 0 to n-1, specifying the order in which the cities should be visited.
➢ TSP is an NP-hard problem, meaning that, for larger values of n, it is not feasible to
evaluate every possible problem solution within a reasonable period of time.
Consequently, TSPs are well suited to solving using randomized optimization algorithms.
Travelling Salesman Problem (TSP) : Given a set of cities and distances between every pair of
cities, the problem is to find the shortest possible route that visits every city exactly once and
returns to the starting point.
Note the difference between Hamiltonian Cycle and TSP. The Hamiltoninan cycle problem is to
find if there exist a tour that visits every city exactly once. Here we know that Hamiltonian Tour
exists (because the graph is complete) and in fact many such tours exist, the problem is to find a
minimum weight Hamiltonian Cycle.
Explanation
1. Consider city 1 as the starting and ending point. Since the route is cyclic, we can
consider any point as a starting point.
2. Generate all (n-1)! permutations of cities.
3. Calculate the cost of every permutation and keep track of the minimum cost
permutation.
4. Return the permutation with minimum cost.
SOURCE CODE
# 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
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))
OUTPUT
80
# objective function
def objective(x):
return x[0]**2.0
# define range for input
r_min, r_max = -5.0, 5.0
# sample input range uniformly at 0.1 increments
inputs = arange(r_min, r_max, 0.1)
# compute targets
results = [objective([x]) for x in inputs]
# create a line plot of input vs result
pyplot.plot(inputs, results)
# define optimal input value
x_optima = 0.0
# draw a vertical line at the optimal input
pyplot.axvline(x=x_optima, ls='--', color='red')
# show the plot
pyplot.show()
SOURCE CODE
# explore temperature vs algorithm iteration for simulated annealing
from matplotlib import pyplot
# total iterations of algorithm
iterations = 100
# initial temperature
initial_temp = 10
# array of iterations from 0 to iterations - 1
iterations = [i for i in range(iterations)]
# temperatures for each iterations
temperatures = [initial_temp/float(i + 1) for i in iterations]
# plot iterations vs temperatures
pyplot.plot(iterations, temperatures)
pyplot.xlabel('Iteration')
pyplot.ylabel('Temperature')
pyplot.show()
SOURCE CODE
dataset = pd.read_csv('potato_train_data.csv')
labels = pd.read_csv('potato_train_label.csv')
features = list(dataset.keys())
classes = np.array(['Corn', 'Potato', 'grass'])
for i in range(3):
labels.loc[labels['type']==classes[i], 'type'] = i
dataset = dataset.values
labels = labels['type'].values
visualize(dataset, labels, features, classes)
5. Write a program to implement 8 puzzle problem
SOURCE CODE
import copy
from heapq import heappush, heappop
n=3
row = [ 1, 0, -1, 0 ]
col = [ 0, -1, 0, 1 ]
class priorityQueue:
def init (self):
self.heap = []
def push(self, k):
heappush(self.heap, k)
def pop(self):
return heappop(self.heap)
def empty(self):
if not self.heap:
return True
else:
return False
class node:
def init (self, parent, mat, empty_tile_pos,
cost, level):
self.parent = parent
self.mat = mat
self.empty_tile_pos = empty_tile_pos
self.cost = cost
self.level = level
def lt (self, nxt):
return self.cost < nxt.cost
def calculateCost(mat, final) -> int:
count = 0
for i in range(n):
for j in range(n):
if ((mat[i][j]) and
(mat[i][j] != final[i][j])):
count += 1
return count
def newNode(mat, empty_tile_pos, new_empty_tile_pos,
level, parent, final) -> node:
new_mat = copy.deepcopy(mat)
x1 = empty_tile_pos[0]
y1 = empty_tile_pos[1]
x2 = new_empty_tile_pos[0]
y2 = new_empty_tile_pos[1]
new_mat[x1][y1], new_mat[x2][y2] = new_mat[x2][y2], new_mat[x1][y1]
cost = calculateCost(new_mat, final)
new_node = node(parent, new_mat, new_empty_tile_pos,
cost, level)
return new_node
def printMatrix(mat):
for i in range(n):
for j in range(n):
print("%d " % (mat[i][j]), end = " ")
print()
def isSafe(x, y):
return x >= 0 and x < n and y >= 0 and y < n
def printPath(root):
if root == None:
return
printPath(root.parent)
printMatrix(root.mat)
print()
def solve(initial, empty_tile_pos, final):
pq = priorityQueue()
cost = calculateCost(initial, final)
root = node(None, initial,
empty_tile_pos, cost, 0)
pq.push(root)
while not pq.empty():
minimum = pq.pop()
if minimum.cost == 0:
printPath(minimum)
return
for i in range(n):
new_tile_pos = [
minimum.empty_tile_pos[0] + row[i],
minimum.empty_tile_pos[1] + col[i], ]
if isSafe(new_tile_pos[0], new_tile_pos[1]):
child = newNode(minimum.mat,
minimum.empty_tile_pos,
new_tile_pos,
minimum.level + 1,
minimum, final,)
pq.push(child)
initial = [ [ 1, 2, 3 ],
[ 5, 6, 0 ],
[ 7, 8, 4 ] ]
final = [ [ 1, 2, 3 ],
[ 5, 8, 6 ],
[ 0, 7, 4 ] ]
empty_tile_pos = [ 1, 2 ]
solve(initial, empty_tile_pos, final)
OUTPUT:
1 2 3
5 6 0
7 8 4
1 2 3
5 0 6
7 8 4
1 2 3
5 8 6
7 0 4
1 2 3
5 8 6
0 7 4
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]
dist += abs(i - self.value.index(letter))
return dist
def CreateChildren(self):
if not self.children:
for i in range(len(self.goal)-1):
val = self.value
val = val[:i] + val[i+1] + val[i] + val[i+2:]
child = State_String(val, self)
self.children.append(child)
count = 0
self.priorityQueue.put((0,count, startState))
while(not self.path and self.priorityQueue.qsize()):
closesetChild = self.priorityQueue.get()[2]
closesetChild.CreateChildren()
self.vistedQueue.append(closesetChild.value)
for child in closesetChild.children:
if child.value not in self.vistedQueue:
count += 1
if not child.dist:
self.path = child.path
break
self.priorityQueue.put((child.dist,count,child))
if not self.path:
print("Goal Of is not possible !" + self.goal )
return self.path
# objective function
def objective(v):
x, y = v
return -20.0 * exp(-0.2 * sqrt(0.5 * (x**2 + y**2))) - exp(0.5 * (cos(2 * pi * x) + cos(2 *
pi * y))) + e + 20
10. Build a bot which provides all the information related to your college.
SOURCE CODE
SOURCE CODE
def send():
send = "You:"+ e.get()
text.insert(END,"\n" + send)
if(e.get()=='hi'):
text.insert(END, "\n" + "Bot: hello")
elif(e.get()=='hello'):
text.insert(END, "\n" + "Bot: hi")
elif (e.get() == 'how are you?'):
text.insert(END, "\n" + "Bot: i'm fine and you?")
elif (e.get() == "i'm fine too"):
text.insert(END, "\n" + "Bot: nice to hear that")
else:
text.insert(END, "\n" + "Bot: Sorry I didnt get it.")
text = Text(root,bg='light blue')
text.grid(row=0,column=0,columnspan=2)
e = Entry(root,width=80)
send = Button(root,text='Send',bg='blue',width=20,command=send).grid(row=1,column=1)
e.grid(row=1,column=0)
root = Tk()
root.title('IT SOURCCODE SIMPLE CHATBOT')
root.mainloop()
11. Build a virtual assistant for Wikipedia using Wolfram Alpha and Python.
SOURCE CODE
import wolframalpha
print(answer)
12. The following is a function that counts the number of times a string occurs in another
string:
# Count the number of times string s1 is found in string s2
def countsubstring(s1,s2):
count = 0
for i in range(0,len(s2)-len(s1)+1):
if s1 == s2[i:i+len(s1)]:
count += 1
return count
For instance, countsubstring(’ab’,’cabalaba’) returns 2.
Write a recursive version of the above function. To get the rest of a string (i.e. everything
but the first character).
SOURCE CODE
# Python3 program to count occurrences of pattern in a text.
def KMPSearch(pat, txt):
M = len(pat)
N = len(txt)
# Create lps[] that will hold the longest prefix suffix values for pattern
lps = [None] * M
j = 0 # index for pat[]
# When we find pattern first time,we iterate again to check if there exists more pattern
j = lps[j - 1]
res = res + 1
# We start i to check for more than once appearance of pattern, we will reset i to previous
start+1
if lps[j] != 0:
next_i = next_i + 1
i = next_i
j=0
return res
else: # if (len == 0)
lps[i] = len
i=i+1
# Driver code
if name == " main ":
print(ans)
13. Higher order functions. Write a higher-order function count that counts the number of
elements in a list that satisfy a given test. For instance: count(lambda x: x>2, [1,2,3,4,5])
should return 3, as there are three elements in the list larger than 2. Solve this task without
using any existing higher-order function.
SOURCE CODE
# return count
return j-i+1;
# if x is present in arr[] then return the index of FIRST occurrence of x in arr[0..n-1], otherwise
returns -1
def first(arr, low, high, x, n):
if high >= low:
# if x is present in arr[] then return the index of LAST occurrence of x in arr[0..n-1], otherwise
returns -1
def last(arr, low, high, x, n):
if high >= low:
14. Brute force solution to the Knapsack problem. Write a function that allows you to
generate random problem instances for the knapsack program. This function should
generate a list of items containing N items that each have a unique name, a random size in
the range 1 ....... 5 and a random value in the range 1 ...... 10.
Next, you should perform performance measurements to see how long the given knapsack
solver take to solve different problem sizes. You should peform atleast 10 runs with
different randomly generated problem instances for the problem sizes 10,12,14,16,18,20
and 22. Use a
backpack size of 2:5 x N for each value problem size N. Please note that the method used to
generate random numbers can also affect performance, since different distributions of
values can make the initial conditions of the problem slightly more or less demanding.
How much longer time does it take to run this program when we increase the number of
items? Does the backpack size affect the answer?
Try running the above tests again with a backpack size of 1 x N and with 4:0 x N.
SOURCE CODE
# Python3 program to solve fractional Knapsack Problem
class ItemValue:
# Greedy Approach
class FractionalKnapSack:
totalValue = 0
for i in iVal:
curWt = int(i.wt)
curVal = int(i.val)
if capacity - curWt >= 0:
capacity -= curWt
totalValue += curVal
else:
fraction = capacity / curWt
totalValue += curVal * fraction
capacity = int(capacity - (curWt * fraction))
break
return totalValue
# Driver Code
if name == " main ":
wt = [10, 40, 20, 30]
val = [60, 40, 100, 120]
capacity = 50
# Function call
maxValue = FractionalKnapSack.getMaxValue(wt, val, capacity)
print("Maximum value in Knapsack =", maxValue)
OUTPUT:-
Maximum value in Knapsack = 240.0
15. Assume that you are organising a party for N people and have been given a list L of
people who, for social reasons, should not sit at the same table. Furthermore, assume that
you have C tables (that are infinitly large).
Write a function layout(N,C,L) that can give a table placement (ie. a number from 0 : : :C -
1) for each guest such that there will be no social mishaps.
For simplicity we assume that you have a unique number 0 ...... N-1 for each guest and that
the list of restrictions is of the form [(X,Y), ... ] denoting guests X, Y that are not allowed to
sit together. Answer with a dictionary mapping each guest into a table assignment, if there
are no possible layouts of the guests you should answer False.
SOURCE CODE
# Python3 program to solve fractional Knapsack Problem
class ItemValue:
# Greedy Approach
class FractionalKnapSack:
totalValue = 0
for i in iVal:
curWt = int(i.wt)
curVal = int(i.val)
if capacity - curWt >= 0:
capacity -= curWt
totalValue += curVal
else:
fraction = capacity / curWt
totalValue += curVal * fraction
capacity = int(capacity - (curWt * fraction))
break
return totalValue
# Driver Code
if name == " main ":
wt = [10, 40, 20, 30]
val = [60, 40, 100, 120]
capacity = 50
# Function call
maxValue = FractionalKnapSack.getMaxValue(wt, val, capacity)
print("Maximum value in Knapsack =", maxValue)
OUTPUT:-
Maximum value in Knapsack = 240.0