0% found this document useful (0 votes)
54 views25 pages

AI - 5thsem - Manual Updated

Uploaded by

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

AI - 5thsem - Manual Updated

Uploaded by

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

DEPARTMENT OF COMPUTER SCIENCE & ENGINEERING

ARTIFICIAL INTELLIGENCE LAB MANUAL

2024-2025

ATRIA INSTITUTE OF TECHNOLOGY


Adjacent to Bangalore Baptist HospitalHebbal Bengaluru-560024
AI Lab Manual BCS515B
B

ARTIFICIAL INTELLIGENCE LAB Semester 3


Course Code BCS515B CIE Marks 50
Teaching Hours/Week (L:T:P: S) 3:0:2:0 SEE Marks 50
Total Hours of Pedagogy 40 hours Theory + 8-10 Total Marks 100
Lab slots
Credits 03 Exam Hours 3
Examination nature (SEE) Theory
Sl. No Experiments
1) Write a Program to Implement Breadth First Search using Python.
2) Write a Program to Implement Depth First Search using Python.
3) Write a Program to Implement 8-Puzzle problem using Python.
4) Write a program to implement best first search algorithm using Python.
5) Write a program to implement the A* search algorithm usingPython
6) Write a python program to Implement Propositional Model checking Algorithm.
7) Write a program for first order logic using Python.
8) Write a program to implement forward chaining algorithm using Python
9) Write a program to implement backward chaining algorithm using Python
10) Write a simple python program to create a chatbot

Dept. of CS&E, AIT Page|2


AI Lab Manual BCS515B
B
1. Write a Program to Implement Breadth First Search using Python.

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
def bfs(visited, graph, node):
visited.append(node)
queue.append(node)
while queue:
s = queue.pop(0)
print (s, end = " ")
for neighbour in graph[s]:
if neighbour not in visited:
visited.append(neighbour)
queue.append(neighbour)
# Driver Code
bfs(visited, graph, 'A')

Output:

Dept. of CS&E, AIT Page|3


AI Lab Manual BCS515B
B
2 . Write a Program to Implement Depth First Search using Python.

graph = {
'A' : ['B','C'],
'B' : ['D', 'E'],
'C' : ['F'],
'D' : [],
'E' : ['F'],
'F' : []
}
visited = set() # Set to keep track of visited nodes.
def dfs(visited, graph, node):
if node not in visited:
print (node)
visited.add(node)
for neighbour in graph[node]:
dfs(visited, graph, neighbour)
# Driver Code
dfs(visited, graph, 'A')

Output:

Dept. of CS&E, AIT Page|4


AI Lab Manual BCS515B
B
3.Write a Program to Implement an 8-Puzzle problem using Python.

class Solution:
def solve(self, board):
state_dict = {}
flatten = []

# Flatten the board into a tuple


for i in range(len(board)):
flatten += board[i]
flatten = tuple(flatten)

# Initialize the dictionary with the starting state


state_dict[flatten] = 0

# If the initial state is the goal state, return 0


if flatten == (0, 1, 2, 3, 4, 5, 6, 7, 8):
return 0

return self.get_paths(state_dict)

def get_paths(self, state_dict):


cnt = 0
while True:
# Find nodes at the current distance cnt
current_nodes = [x for x in state_dict if state_dict[x] == cnt]

if len(current_nodes) == 0:
return -1

for node in current_nodes:


next_moves = self.find_next(node)
for move in next_moves:
if move not in state_dict:
state_dict[move] = cnt + 1
if move == (0, 1, 2, 3, 4, 5, 6, 7, 8):
return cnt + 1
cnt += 1

def find_next(self, node):


moves = {
0: [1, 3],
1: [0, 2, 4],
Dept. of CS&E, AIT Page|5
AI Lab Manual BCS515B
B
2: [1, 5],
3: [0, 4, 6],
4: [1, 3, 5, 7],
5: [2, 4, 8],
6: [3, 7],
7: [4, 6, 8],
8: [5, 7],
}

results = []
pos_0 = node.index(0)
for move in moves[pos_0]:
new_node = list(node)
# Swap the 0 with the target position
new_node[move], new_node[pos_0] = new_node[pos_0], new_node[move]
results.append(tuple(new_node))

return results

# Test the solution with a sample matrix


ob = Solution()
matrix = [
[3, 1, 2],
[4, 7, 5],
[6, 8, 0]
]
print(ob.solve(matrix))

Output:-

4
.

W
r
i
t
e

Dept. of CS&E, AIT Page|6


AI Lab Manual BCS515B
B
4. Program to implement best first search algorithm using Python

import heapq

class Node:
def __init__(self, position, g=0, h=0):
self.position = position
self.g = g # Cost from start node
self.h = h # Heuristic cost to end node
self.f = g + h # Total cost (f = g + h)
self.parent = None

def __lt__(self, other):


return self.f < other.f

def a_star(maze, start, end):


# Define the movement options: Up, Down, Left, Right
directions = [(0, -1), (0, 1), (-1, 0), (1, 0)]

# Set up the start and end nodes


start_node = Node(start)
end_node = Node(end)

# Priority queue for open list and set for closed list
open_list = []
closed_set = set()

# Add the start node to the priority queue


heapq.heappush(open_list, start_node)

# Store all visited nodes to avoid duplicate processing


all_nodes = {}

while open_list:
# Get the node with the lowest f value
current_node = heapq.heappop(open_list)
closed_set.add(current_node.position)

# Check if we have reached the goal


if current_node.position == end_node.position:
path = []
while current_node:

Dept. of CS&E, AIT Page|7


AI Lab Manual BCS515B
B
path.append(current_node.position)
current_node = current_node.parent
return path[::-1] # Return reversed path

# Generate neighbors
for direction in directions:
neighbor_pos = (current_node.position[0] + direction[0], current_node.position[1] +
direction[1])

# Check bounds and if the position is walkable


if (0 <= neighbor_pos[0] < len(maze)) and (0 <= neighbor_pos[1] < len(maze[0])) and
maze[neighbor_pos[0]][neighbor_pos[1]] == 0:

# Skip if the neighbor is already in the closed set


if neighbor_pos in closed_set:
continue

# Calculate costs
g_cost = current_node.g + 1
h_cost = abs(neighbor_pos[0] - end_node.position[0]) + abs(neighbor_pos[1] -
end_node.position[1])
f_cost = g_cost + h_cost

# Check if we have already seen this node with a lower cost


if neighbor_pos in all_nodes and all_nodes[neighbor_pos].g <= g_cost:
continue

# Create or update the node


neighbor_node = Node(neighbor_pos, g_cost, h_cost)
neighbor_node.parent = current_node
all_nodes[neighbor_pos] = neighbor_node

# Add the node to the open list


heapq.heappush(open_list, neighbor_node)

return None # No path found

# Example usage
maze = [
[0, 1, 0, 0, 0, 0, 0],
[0, 1, 0, 1, 1, 1, 0],
[0, 1, 0, 1, 0, 0, 0],
[0, 0, 0, 1, 0, 1, 0],
Dept. of CS&E, AIT Page|8
AI Lab Manual BCS515B
B
[1, 1, 0, 1, 0, 1, 0],
[0, 0, 0, 0, 0, 0, 0]
]

start = (0, 0)
end = (5, 6)
path = a_star(maze, start, end)
print("Path found:", path)

Output:

5
.

W
r
i

Dept. of CS&E, AIT Page|9


AI Lab Manual BCS515B
B
5. Write a program to implement the A* search algorithm using Python

from queue import PriorityQueue


v = 14
graph = [[] for i in range(v)]

# Function For Implementing Best First Search


def best_first_search(actual_Src, target, n):
visited = [False] * n
pq = PriorityQueue()
pq.put((0, actual_Src))
visited[actual_Src] = True
while pq.empty() == False:
u = pq.get()[1]
# Displaying the path having lowest cost
print(u, end=" ")
if u == target:
break

for v, c in graph[u]:
if visited[v] == False:
visited[v] = True
pq.put((c, v))
print()
# Function for adding edges to graph
def addedge(x, y, cost):
graph[x].append((y, cost))
graph[y].append((x, cost))
# implemented using integers addedge(x,y,cost);
addedge(0, 1, 3)
addedge(0, 2, 6)
addedge(0, 3, 5)
addedge(1, 4, 9)
addedge(1, 5, 8)
addedge(2, 6, 12)
addedge(2, 7, 14)
addedge(3, 8, 7)
addedge(8, 9, 5)
addedge(8, 10, 6)
addedge(9, 11, 1)
addedge(9, 12, 10)
addedge(9, 13, 2)
source = 0
Dept. of CS&E, AIT P a g e | 10
AI Lab Manual BCS515B
B
target = 9
best_first_search(source, target, v)

Output:

Dept. of CS&E, AIT P a g e | 11


AI Lab Manual BCS515B
B
6. Write a python program to Implement Propositional Model checking Algorithm.

import re
class Literal:
# Class Literal, it has attributes name and sign to denote whether the literal is positive or negative in
use
def __init__(self, name, sign=True):
self.name = str(name)
self.sign = sign

def __neg__(self):
return Literal(self.name, False)

def __str__(self):
return str(self.name)

def __repr__(self):
# Returns the string of the literal name, or the string with a negative sign each time the instance
of the literal is called
if self.sign:
return '%r' % str(self.__str__())
else:
return '%r' % str("-" + self.__str__())

def CNFconvert(KB):
# This function converts the KB from a list of sets to a list of lists for easier computing
storage = []
for i in KB:
i = list(i)
for j in i:
j = str(j)
storage.append(i)
return storage

def VariableSet(KB):
# This function finds all the used literals in the KB, to assist with running the DPLL
KB = eval((CNFconvert(KB).__str__()))
storage = []
for obj in KB:
for item in obj:
if item[0] == '-' and item[1:] not in storage:

Dept. of CS&E, AIT P a g e | 12


AI Lab Manual BCS515B
B
storage.append(str(item[1:]))
elif item not in storage and item[0] != '-':
storage.append(str(item))
return storage

def Negativeofx(x):
# This function holds the negative form of the literal, for use in the DPLL algorithm
check = re.match("-", str(x))
if check:
return str(x[1:])
else:
return "-" + str(x)

def pickX(literals, varList):


# This function picks a literal from the variable set and works with it as a node in the tree
for x in varList:
if x not in literals:
break
return x

def splitFalseLiterals(cnf, x):


holder = []
for item in cnf:
if x in item:
item.remove(x)
holder.append(item)
return holder

def splitTrueLiteral(cnf, x):


holder = []
for item in cnf:
if x in item:
continue
else:
holder.append(item)
return holder

def unitResolution(clauses):
literalholder = {} # Dictionary for holding the literal holder and their boolean values
i=0
while i < len(clauses): # For each clause
newClauses = []
clause = clauses[i]
Dept. of CS&E, AIT P a g e | 13
AI Lab Manual BCS515B
B
# Picks a clause to work on
if len(clause) == 1:
literal = str(clause[0])
pattern = re.match("-", literal)
# Populates the dictionary
if pattern:
nx = literal[1:]
literalholder[nx] = False
else:
nx = "-" + literal
literalholder[literal] = True
# Checks for all other appearances of the literal or its opposite in the KB
for item in clauses:
if item != clauses[i]:
if nx in item:
item.remove(nx)
newClauses.append(item)
i=0
clauses = newClauses
# No unit clause
else:
i += 1
return literalholder, clauses

def dpll(clauses, varList):


# Recursively performs the DPLL algorithm
literals, cnf = unitResolution(clauses)
if cnf == []:
return literals
elif [] in cnf:
return "notsatisfiable"
else:
# Pick a literal which isn't set yet but has an impact on the KB, and then work on it recursively
while True:
x = pickX(literals, varList)
x = str(x)
nx = Negativeofx(x)
ncnf = splitTrueLiteral(cnf, x)
ncnf = splitFalseLiterals(ncnf, nx)
if ncnf == cnf:
varList.remove(x)
else:
break
Dept. of CS&E, AIT P a g e | 14
AI Lab Manual BCS515B
B
# Does the same DPLL recursively, but follows the true path for that variable
case1 = dpll(ncnf, varList)
if case1 != "notsatisfiable":
copy = case1.copy()
copy.update(literals)
copy.update({x: True})
return copy
# Does the DPLL recursively, but follows the false path for that variable
case1 = dpll(ncnf, varList)
if not case1:
copy = case1.copy()
copy.update(literals)
copy.update({x: False})
return copy
else:
return "notsatisfiable"

def DPLL(KB):
# Finally restructures the output to fit the required output by the assignment description
KB = eval((CNFconvert(KB).__str__()))
varList = VariableSet(KB)
result = dpll(KB, varList)
if result == 'notsatisfiable':
return False
else:
for i in varList:
if i in result and result[i] == True:
result[i] = 'true'
elif i in result and result[i] == False:
result[i] = 'false'
else:
result[i] = 'free'
return [True, result]

A = Literal('A')
B = Literal('B')
C = Literal('C')
D = Literal('D')
KB = [{A, B}, {A, -C}, {-A, B, D}]
print(DPLL(KB))

Dept. of CS&E, AIT P a g e | 15


AI Lab Manual BCS515B
B
Output:

Dept. of CS&E, AIT P a g e | 16


AI Lab Manual BCS515B
B
7. Write a program for first order logic using Python.

class KnowledgeBase:
def __init__(self):
self.facts = []
self.rules = []

def tell(self, fact):


self.facts.append(fact)

def ask(self, query):


if query in self.facts:
return True
for rule in self.rules:
if rule.can_apply(query, self):
return True
return False

def add_rule(self, rule):


self.rules.append(rule)

class Predicate:
def __init__(self, name, *args):
self.name = name
self.args = args

def __eq__(self, other):


return self.name == other.name and self.args == other.args

def __hash__(self):
return hash((self.name, self.args))

def __repr__(self):
return f"{self.name}({', '.join(map(str, self.args))})"

class Rule:
def __init__(self, antecedent, consequent):
self.antecedent = antecedent # List of conditions
self.consequent = consequent

def can_apply(self, query, kb):


if query.name != self.consequent.name:
Dept. of CS&E, AIT P a g e | 17
AI Lab Manual BCS515B
B
return False
substitution = {}
for arg_query, arg_rule in zip(query.args, self.consequent.args):
if isinstance(arg_rule, str) and arg_rule.islower(): # Check for a variable
substitution[arg_rule] = arg_query
elif arg_query != arg_rule:
return False

substituted_antecedent = [
Predicate(cond.name, *[substitution.get(arg, arg) for arg in cond.args])
for cond in self.antecedent
]

for cond in substituted_antecedent:


if not kb.ask(cond):
return False

kb.tell(query)
return True

# Define individuals
Socrates = "Socrates"

# Define predicates
Human = lambda x: Predicate("Human", x)
Mortal = lambda x: Predicate("Mortal", x)

kb = KnowledgeBase()

kb.tell(Human(Socrates))

kb.add_rule(Rule([Human("x")], Mortal("x")))

# Query the knowledge base


query = Mortal(Socrates)
if kb.ask(query):
print(f"{query} is True")
else:
print(f"{query} is False")

Dept. of CS&E, AIT P a g e | 18


AI Lab Manual BCS515B
B
Output:

Dept. of CS&E, AIT P a g e | 19


AI Lab Manual BCS515B
B
8. Write a program to implement forward chaining algorithm using Python

class KnowledgeBase:
def __init__(self):
self.rules = []
self.facts = set()

def tell(self, fact):


self.facts.add(fact)

def add_rule(self, antecedent, consequent):


self.rules.append((antecedent, consequent))

def forward_chain(self):
new_inferences = True

while new_inferences:
new_inferences = False
for antecedent, consequent in self.rules:
# Check if all conditions in the antecedent are true
if all(self.fact_match(cond) for cond in antecedent):
if consequent not in self.facts:
self.tell(consequent)
new_inferences = True

def fact_match(self, fact):


for f in self.facts:
bindings = self.match(fact, f)
if bindings is not None:
return True
return False

def match(self, pattern, fact):


if pattern == fact:
return {}
if isinstance(pattern, str) and isinstance(fact, str):
if pattern[0].islower(): # Variable match
return {pattern: fact}
return None

def main():
kb = KnowledgeBase()

Dept. of CS&E, AIT P a g e | 20


AI Lab Manual BCS515B
B
# Add facts to the knowledge base
kb.tell("Enemy(Nono, America)")
kb.tell("Owns(Nono, M1)")
kb.tell("Missile(M1)")
kb.tell("American(West)")

# Add rules to the knowledge base


kb.add_rule(["Missile(x)"], "Weapon(x)")
kb.add_rule(["Missile(x)", "Owns(Nono, x)"], "Sells(West, x, Nono)")
kb.add_rule(["Enemy(x, America)"], "Hostile(x)")
kb.add_rule(["American(x)", "Weapon(y)", "Sells(x, y, z)", "Hostile(z)"], "Criminal(x)")

# Perform forward chaining


kb.forward_chain()

# Check the result for a specific query


query = "Criminal(West)"
if query in kb.facts:
print(f"{query} is True based on the knowledge base.")
else:
print(f"{query} cannot be proven with the current knowledge base.")

if __name__ == "__main__":
main()

Output:

Dept. of CS&E, AIT P a g e | 21


AI Lab Manual BCS515B
B
9. Write a program to implement backward chaining algorithm using Python

class KnowledgeBase:
def __init__(self):
self.rules = []
self.facts = set()

def tell(self, fact):


self.facts.add(fact)

def add_rule(self, antecedent, consequent):


self.rules.append((antecedent, consequent))

def backward_chain(self, query):


# If the query is already known to be true
if query in self.facts:
return True

# Check all rules to see if we can infer the query


for antecedent, consequent in self.rules:
bindings = self.match(consequent, query)
if bindings is not None:
substituted_antecedent = [self.substitute(cond, bindings) for cond in antecedent]
if all(self.backward_chain(cond) for cond in substituted_antecedent):
self.tell(query) # Cache the result
return True

return False

def match(self, pattern, fact):


if pattern == fact:
return {}
if isinstance(pattern, str) and isinstance(fact, str):
if pattern[0].islower(): # Variable match
return {pattern: fact}
return None

def substitute(self, expression, bindings):


if isinstance(expression, str) and expression[0].islower():
return bindings.get(expression, expression)
if isinstance(expression, (list, tuple)):
return type(expression)(self.substitute(e, bindings) for e in expression)

Dept. of CS&E, AIT P a g e | 22


AI Lab Manual BCS515B
B
return expression

def main():
kb = KnowledgeBase()

# Add facts to the knowledge base


kb.tell("Enemy(Nono, America)")
kb.tell("Owns(Nono, M1)")
kb.tell("Missile(M1)")
kb.tell("American(West)")

# Add rules to the knowledge base


kb.add_rule(["Missile(x)"], "Weapon(x)")
kb.add_rule(["Missile(x)", "Owns(Nono, x)"], "Sells(West, x, Nono)")
kb.add_rule(["Enemy(x, America)"], "Hostile(x)")
kb.add_rule(["American(x)", "Weapon(y)", "Sells(x, y, z)", "Hostile(z)"], "Criminal(x)")
query = "Criminal(West)"
result = kb.backward_chain(query)

if result:
print(f"{query} is True based on the knowledge base.")
else:
print(f"{query} cannot be proven with the current knowledge base.")

if __name__ == "__main__":
main()

Output:

Dept. of CS&E, AIT P a g e | 23


AI Lab Manual BCS515B
B
10. Write a simple python program to create a chatbot.

import re
class SimpleChatBot:
def __init__(self):
self.responses = {
"hello": "Hi there! How can I help you today?",
"hi": "Hello! What can I do for you?",
"how are you": "I'm just a program, but I'm here to help you!",
"what is your name": "I'm a simple chatbot created in Python. What's your name?",
"bye": "Goodbye! Have a great day!",
"default": "I'm sorry, I don't understand that. Could you please rephrase?"
}
def get_response(self, message):
message = message.lower()

# Check for exact matches first


if message in self.responses:
return self.responses[message]

# Check for matches based on keywords


for pattern in self.responses:
if re.search(pattern, message):
return self.responses[pattern]

# Default response if no match found


return self.responses["default"]

def main():
bot = SimpleChatBot()
print("Chatbot: Hello! I am a simple chatbot. Type 'bye' to exit.")

while True:
user_message = input("You: ")
if user_message.lower() == "bye":
print("Chatbot: " + bot.get_response(user_message))
break

response = bot.get_response(user_message)
print("Chatbot: " + response)

if __name__ == "__main__":
main()
Dept. of CS&E, AIT P a g e | 24
AI Lab Manual BCS515B
B
Output:

Dept. of CS&E, AIT P a g e | 25

You might also like