0% found this document useful (0 votes)
38 views49 pages

Cse (Aiml) Artificial Intelligence Lab Manual 22 Scheme

The document is a laboratory manual for the Artificial Intelligence Laboratory course at AMC Engineering College, effective from the academic year 2023-2024. It outlines the vision and mission of the institution and department, program educational objectives, specific outcomes, and program outcomes related to Artificial Intelligence and Machine Learning. Additionally, it includes details on experiments, assessment criteria, suggested learning resources, and sample code for implementing algorithms.

Uploaded by

saranshdash207
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)
38 views49 pages

Cse (Aiml) Artificial Intelligence Lab Manual 22 Scheme

The document is a laboratory manual for the Artificial Intelligence Laboratory course at AMC Engineering College, effective from the academic year 2023-2024. It outlines the vision and mission of the institution and department, program educational objectives, specific outcomes, and program outcomes related to Artificial Intelligence and Machine Learning. Additionally, it includes details on experiments, assessment criteria, suggested learning resources, and sample code for implementing algorithms.

Uploaded by

saranshdash207
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/ 49

AMC ENGINEERING COLLEGE

(Affiliated to VTU, Belagavi, Karnataka)


18th K.M, Bannerghatta Main Road, Bengaluru-560083

DEPARTMENT OF COMPUTER SCIENCE AND ENGINEERING


(ARTIFICIAL INTELLIGENCE AND MACHINE LEARNING)

LABORATORY MANUAL
ARTIFICIAL INTELLIGENCE LABORATORY/ BAD402
(Effective from the academic year 2023 -2024)

Prepared by
Prof. Vinaya K, Prof. Ambili K, Prof. Kavya P
Assistant Professor’s
Department of CSE-AIML

Compiled by
Dr. Nandeeswar S B
Head of the Department
Department of CSE-AIML

VISVESVARAYA TECHNOLOGICAL UNIVERSITY


“Jnana Sangama”, BELAGAVI – 590 018
KARNATAKA

1
Vision and Mission of the
Institution
VISION

“To be leader in Impacting Value Based Technical Education and Research for
the benefit of Society”

MISSION

M1 To Provide state of the art infrastructure and facilities.

M2 To Implement modern pedagogical methods in delivering academic


programs with an experienced and committed faculty.

To Create a vibrant ambience that promotes Learning, Research,


M3
Invention and Innovations
To undertake skill development programmers for academic
M4
institution and industries.
To Enhance industry institue interaction through collaborative
M5
research and consultancy.
Generate and disseminate knowledge through startups, training
M6
programs, workshops, seminars, conferences and publications.

2
DEPARTMENT OF CSE(AI&ML) ENGINEERING

Vision of the Department


“Be a premier department in the field of Computer Science & Engineering - Artificial
Intelligence & Machine Learning (CSE - AIML) to meet the technological challenges of
the society”.

Mission of the Department

MD1: To facilitate state of the art infrastructure by providing exposure to the latest AI

tools used in a technically competent society.

MD2: To strive for academic excellence through research in Artificial Intelligence &

Machine Learning with creative teaching-learning pedagogy.

MD3: To establish Industry Institute Interaction and make students ready for the

Industrial environment.

MD4: To transform students into entrepreneurial, technically competent, socially

responsible, and ethical AI professional.

3
PROGRAM EDUCATIONAL OBJECTIVES (PEO)

PEO-1: Graduates possess advanced knowledge of Computer Science & Engineering – Artificial
Intelligence & Machine Learning and excel in leadership roles to serve the society.
PEO-2: Graduates of the program will apply Artificial Intelligence enabled Computer Engineering tools
in core technologies for improving knowledge in the Interdisciplinary Research and
Entrepreneurs.
PEO-3: Graduates adapt Value-Based Proficiency in solving Real Time problems.

PROGRAM SPECIFIC OUTCOMES (PSOs)

PSO-1: Professional Skills: Ability of applying the Artificial Intelligence & Machine Learning
knowledge, Computing Concepts, Data Structure, Computer Hardware, Computer Networks and
Suitable Algorithm.

PSO-2: Software Skills: Ability to build Artificial Intelligence enabled Software Engineering System with
Development Life Cycle by using analytical knowledge in Computer Science & Engineering and
applying modern methodologies.

4
PROGRAM OUTCOMES (POs)

PO-1: Engineering knowledge - Apply the knowledge of mathematics, science, engineering fundamentals,
and an engineering specialization to the solution of complex engineering problems.
PO-2: Problem analysis - Identify, formulate, review research literature, and analyze complex engineering
problems reaching substantiated conclusions using first principles of mathematics, natural sciences,
and engineering sciences.
PO-3: Design/development of solutions - Design solutions for complex engineering problems and design
system components or processes that meet the specified needs with appropriate consideration for the
public health and safety, and the cultural, societal, and environmental considerations.
PO-4: Conduct investigations of complex problems - Use research-based knowledge and research
methods including design of experiments, analysis and interpretation of data, and synthesis of the
information to provide valid conclusions.
PO-5: Modern tool usage - Create, select, and apply appropriate techniques, resources, and modern
engineering and IT tools including prediction and modeling to complex engineering activities with
an understanding of the limitations.
PO-6: The engineer and society - Apply reasoning informed by the contextual knowledge to assess societal,
health, safety, legal and cultural issues and the consequent responsibilities relevant to the
professional engineering practice.
PO-7: Environment and sustainability - Understand the impact of the professional engineering solutions in
societal and environmental contexts, and demonstrate the knowledge of, and need for sustainable
development
PO-8: Ethics: Apply ethical principles and commit to professional ethics and responsibilities and norms of
the engineering practice.
PO-9: Individual and team work: Function effectively as an individual, and as a member or leader in
diverse teams, and in multidisciplinary settings.
PO-10: Communication: Communicate effectively on complex engineering activities with the engineering
community and with society at large, such as, being able to comprehend and write effective reports
and design documentation, make effective presentations, and give and receive clear instructions.
PO-11: Project management and finance: Demonstrate knowledge and understanding of the engineering
and management principles and apply these to one’s own work, as a member and leader in a team, to
manage projects and in multidisciplinary environments.
PO-12: Life-long learning: Recognize the need for, and have the preparation and ability to engage in
independent and life-long learning in the broadest context of technological change.
5
lOMoARcPSD|27793530

Sl.NO
Experiments

1 Implement and Demonstrate Depth First Search Algorithm on Water Jug Problem

2 Implement and Demonstrate Best First Search Algorithm on Missionaries-Cannibals


Problems usingPython

3 Implement A* Search algorithm

4 Implement AO* Search algorithm


5 Solve 8-Queens Problem with suitable assumptions

6 Implementation of TSP using heuristic approach

7 Implementation of the problem solving strategies: either using Forward Chaining or


Backward Chaining

8 Implement resolution principle on FOPL related problems

9 Implement Tic-tac-toe game using Python

10 Build a bot which provides all the information related to text in search box

11 Implement any Game and demonstrate the Game playing strategies

Course outcomes (Course Skill Set):


At the end of the course, the student will be able to:

CO1: Apply knowledge of agent architecture, searching and reasoning techniques


for differentapplications.
CO 2. Compare various Searching and Inferencing Techniques.
CO 3. Develop knowledge base sentences using propositional logic and first
order logic
CO 4. Describe the concepts of quantifying uncertainty.
CO5: Use the concepts of Expert Systems to build applications.

Dept CSE AIML, AMCEC 2023-24


6
lOMoARcPSD|27793530

Assessment Details (both CIE and SEE)


The weightage of Continuous Internal Evaluation (CIE) is 50% and for Semester End Exam (SEE) is 50%. The
minimum passing mark for the CIE is 40% of the maximum marks (20 marks out of 50) and for the SEE
minimum passing mark is 35% of the maximum marks (18 out of 50 marks). A student shall be deemed to
have satisfied the academic requirements and earned the credits allotted to each subject/ course if the student
secures a minimum of 40% (40 marks out of 100) in the sum total of the CIE (Continuous Internal Evaluation)
and SEE (Semester End Examination) taken together.

CIE for the theory component of the IPCC (maximum marks 50)
● IPCC means practical portion integrated with the theory of the course.
● CIE marks for the theory component are 25 marks and that for the practical component is 25 marks.
● 25 marks for the theory component are split into 15 marks for two Internal Assessment Tests (Two Tests,
each of 15 Marks with 01-hour duration, are to be conducted) and 10 marks for other assessment methods
mentioned in 22OB4.2. The first test at the end of 40-50% coverage of the syllabus and the second test
after covering 85-90% of the syllabus.
● Scaled-down marks of the sum of two tests and other assessment methods will be CIE marks for the theory
component of IPCC (that is for 25 marks).
● The student has to secure 40% of 25 marks to qualify in the CIE of the theory component of IPCC.
CIE for the practical component of the IPCC

● 15 marks for the conduction of the experiment and preparation of laboratory record, and 10 marks for the
test to be conducted after the completion of all the laboratory sessions.
● On completion of every experiment/program in the laboratory, the students shall be evaluated including
viva-voce and marks shall be awarded on the same day.
● The CIE marks awarded in the case of the Practical component shall be based on the continuous evaluation
of the laboratory report. Each experiment report can be evaluated for 10 marks. Marks of all experiments’
write-ups are added and scaled down to 15 marks.
● The laboratory test (duration 02/03 hours) after completion of all the experiments shall be conducted for
50 marks and scaled down to 10 marks.
● Scaled-down marks of write-up evaluations and tests added will be CIE marks for the laboratory
component of IPCC for 25 marks.

Dept CSE AIML, AMCEC 2023-24


7
lOMoARcPSD|27793530

● The student has to secure 40% of 25 marks to qualify in the CIE of the practical component of the IPCC.
SEE for IPCC
Theory SEE will be conducted by University as per the scheduled timetable, with common question papers for
the course (duration 03 hours)
1. The question paper will have ten questions. Each question is set for 20 marks.
2. There will be 2 questions from each module. Each of the two questions under a module (with a maximum
of 3 sub-questions), should have a mix of topics under that module.
3. The students have to answer 5 full questions, selecting one full question from each module.
4. Marks scoredby the student shall be proportionally scaled down to 50 Marks
The theory portion of the IPCC shall be for both CIE and SEE, whereas the practical portion will have a
CIE component only. Questions mentioned in the SEE paper may include questions from the practical
component.
Suggested Learning Resources:
Text Books
1. Stuart J. Russell and Peter Norvig , Artificial Intelligence, 3rd Edition, Pearson,2015
2. Elaine Rich, Kevin Knight, Artificial Intelligence, 3rd edition,Tata McGraw Hill,2013

Reference:
1. George F Lugar, Artificial Intelligence Structure and strategies for complex, Pearson Education,
5th Edition, 2011
2. Nils J. Nilsson, Principles of Artificial Intelligence, Elsevier, 1980
3. Saroj Kaushik, Artificial Intelligence, Cengage learning, 2014
Web links and Video Lectures (e-Resources)
1. https://www.kdnuggets.com/2019/11/10-free-must-read-books-ai.html
2. https://www.udacity.com/course/knowledge-based-ai-cognitive-systems--ud409
3. https://nptel.ac.in/courses/106/105/106105077/

Activity Based Learning (Suggested Activities in Class)/ Practical Based learning


1. Group discussion on Real world examples
2. Project based learning
3. Simple strategies on gaming, reasoning and uncertainty etc

Dept CSE AIML, AMCEC 2023-24


8
lOMoARcPSD|27793530

1.Implement and Demonstrate Depth First Search Algorithm on Water Jug


Problem

class WaterJugState:
def __init__(self, jug1, jug2):
self.jug1 = jug1
self.jug2 = jug2

def __eq__(self, other):


return self.jug1 == other.jug1 and self.jug2 == other.jug2
def __hash__(self):
return hash((self.jug1, self.jug2))

def dfs(current_state, visited, jug1_capacity, jug2_capacity, target_volume):


if current_state.jug1 == target_volume or current_state.jug2 == target_volume:
if current_state.jug1 == target_volume :
print("Jug 1 now has", target_volume, "liters.")
else:
print("Jug 2 now has", target_volume, "liters.")
return True

visited.add(current_state)
# Define all possible operations: (action, from_jug, to_jug)
operations = [
('Fill Jug 1', jug1_capacity, current_state.jug2),
('Fill Jug 2', current_state.jug1, jug2_capacity),
('Empty Jug 1', 0, current_state.jug2),
('Empty Jug 2', current_state.jug1, 0),
('Pour Jug 1 to Jug 2',
max(0, current_state.jug1 + current_state.jug2 - jug2_capacity),
min(jug2_capacity, current_state.jug1 + current_state.jug2)),

('Pour Jug 2 to Jug 1',


min(jug1_capacity, current_state.jug1 + current_state.jug2),
max(0, current_state.jug1 + current_state.jug2 - jug1_capacity))
]
for operation in operations:
action, new_jug1, new_jug2 = operation
new_state = WaterJugState(new_jug1, new_jug2)

if new_state not in visited:


print(f"Trying: {action} => ({new_jug1}, {new_jug2})")
if dfs(new_state, visited, jug1_capacity, jug2_capacity, target_volume):
return True
# print(new_jug1, new_jug2)
return False
lOMoARcPSD|27793530

def solve_water_jug_problem(jug1_capacity, jug2_capacity, target_volume):


initial_state = WaterJugState(0, 0)
visited = set()
if dfs(initial_state, visited, jug1_capacity, jug2_capacity, target_volume):
print("Solution found!")
# print(jug1_capacity, jug2_capacity)
else:
print("Solution not possible.")

# Example usage:
jug1_capacity = int(input("Enter Jug 1 capacity : "))
jug2_capacity = int(input("Enter Jug 1 capacity : "))
target_volume = int(input("Enter Target Volume : "))
print(f"Solving Water Jug Problem with capacities ({jug1_capacity}, {jug2_capacity}) to measure
{target_volume} liters.")
solve_water_jug_problem(jug1_capacity, jug2_capacity, target_volume)

OUTPUT
$ p3 01_DFS_WJP.py
Enter Jug 1 capacity : 5
Enter Jug 1 capacity : 4
Enter Target Volume : 3
Solving Water Jug Problem with capacities (5, 4) to measure 3 liters.
Trying: Fill Jug 1 => (5, 0)
Trying: Fill Jug 2 => (5, 4)
Trying: Empty Jug 1 => (0, 4)
Trying: Pour Jug 2 to Jug 1 => (4, 0)
Trying: Fill Jug 2 => (4, 4)
Trying: Pour Jug 2 to Jug 1 => (5, 3)
Jug 2 now has 3 liters.
Solution found!

$ p3 01_DFS_WJP.py
Enter Jug 1 capacity : 2
Enter Jug 1 capacity : 2
Enter Target Volume : 6
Solving Water Jug Problem with capacities (2, 2) to measure 6 liters.
Trying: Fill Jug 1 => (2, 0)
Trying: Fill Jug 2 => (2, 2)
Trying: Empty Jug 1 => (0, 2)
Solution not possible.
lOMoARcPSD|27793530

VIVA QUESTIONS
1. What is the Water Jug Problem?
Answer:
The Water Jug Problem is a classic problem in Artificial Intelligence and Search Algorithms. Given two
jugs of different capacities and an unlimited water supply, the goal is to measure a specific amount of water
using only these jugs and the rules of filling, emptying, and transferring water between them.

2. What is Depth First Search (DFS)?


Answer:
DFS is a graph traversal algorithm that explores as deep as possible along each branch before backtracking.
It uses a stack (LIFO) for implementation, either explicitly or via recursion.

3. Why is DFS suitable for solving the Water Jug Problem?


Answer:
DFS is suitable because it systematically explores all possible ways of filling, emptying, and transferring
water in a depth-first manner until the goal state is reached.

4. What are the states in the Water Jug Problem?


Answer:
Each state is represented as a tuple (x, y) where:
 x is the amount of water in Jug1.
 y is the amount of water in Jug2.
For example, (0, 0) represents both jugs being empty.

5. What are the possible operations in the Water Jug Problem?


Answer:
The operations include:
1. Fill Jug1 to its maximum capacity.
2. Fill Jug2 to its maximum capacity.
3. Empty Jug1 completely.
4. Empty Jug2 completely.
5. Pour water from Jug1 to Jug2 until Jug2 is full or Jug1 is empty.
6. Pour water from Jug2 to Jug1 until Jug1 is full or Jug2 is empty.

6. How do you implement DFS for this problem?


Answer:
1. Represent the problem as a graph where each state (x, y) is a node.
lOMoARcPSD|27793530

2. Use DFS (recursion or a stack) to explore each state.


3. Maintain a visited set to avoid cycles.
4. Stop when the goal state is reached.

7. What data structure is used for DFS implementation?


Answer:
DFS can be implemented using:
 Recursion (Implicit stack).
 Explicit stack (Using a list or LIFO stack).

8. How does DFS handle cycles in the Water Jug Problem?


Answer:
To prevent cycles, we maintain a visited set of already explored states. Before expanding a new state, we
check if it has already been visited.

9. Can DFS guarantee the shortest solution in the Water Jug Problem?
Answer:
No, DFS does not guarantee the shortest solution because it explores deep paths first without considering
the shortest route. Breadth-First Search (BFS) is better for finding the shortest path.

10. What is the time complexity of DFS for the Water Jug Problem?
Answer:
The time complexity is O(2^n) in the worst case, where n is the number of possible states. However,
pruning using a visited set improves efficiency.
lOMoARcPSD|27793530

2.Implement and Demonstrate Best First Search Algorithm on Missionaries-Cannibals Problems

from queue import PriorityQueue#


#Define the state class for the Missionaries and Cannibals Problem
class State:
def __init__(self, left_m, left_c, boat, right_m, right_c):
self.left_m = left_m # Number of missionaries on the left bank
self.left_c = left_c # Number of cannibals on the left bank
self.boat = boat # 1 if boat is on the left bank, 0 if on the right bank
self.right_m = right_m # Number of missionaries on the right bank
self.right_c = right_c # Number of cannibals on the right bank

def is_valid(self):
# Check if the state is valid (no missionaries eaten on either bank)
if self.left_m < 0 or self.left_c < 0 or self.right_m < 0 or self.right_c < 0:
return False
if self.left_m > 0 and self.left_c > self.left_m:
return False
if self.right_m > 0 and self.right_c > self.right_m:
return False
return True

def is_goal(self):
# Check if the state is the goal state (all missionaries and cannibals on the right bank)
return self.left_m == 0 and self.left_c == 0
def __lt__(self, other):
# Define less-than operator for PriorityQueue comparison (used in Best-First Search)
return False
def __eq__(self, other):
# Define equality operator for comparing states
return self.left_m == other.left_m and self.left_c == other.left_c \
and self.boat == other.boat and self.right_m == other.right_m \
and self.right_c == other.right_c
def __hash__(self):
# Define hash function for storing states in a set
return hash((self.left_m, self.left_c, self.boat, self.right_m, self.right_c))
def successors(state):
# Generate all valid successor states from the current state
succ_states = [ ]
if state.boat == 1: # Boat is on the left bank
for m in range(3):
for c in range(3):
if 1 <= m + c <= 2: # Boat capacity is 2
new_state = State(state.left_m - m, state.left_c - c, 0,
state.right_m + m, state.right_c + c)
if new_state.is_valid( ):
succ_states.append(new_state)
else: # Boat is on the right bank

13
lOMoARcPSD|27793530

for m in range(3):
for c in range(3):
if 1 <= m + c <= 2: # Boat capacity is 2
new_state = State(state.left_m + m, state.left_c + c, 1, state.right_m - m, state.right_c - c)
if new_state.is_valid( ):
succ_states.append(new_state)
return succ_states

def best_first_search( ):
start_state = State(3, 3, 1, 0, 0)
goal_state = State(0, 0, 0, 3, 3)
frontier = PriorityQueue( )
frontier.put((0, start_state)) # Priority queue with (cost, state)
came_from = {}
cost_so_far = {}
came_from[start_state] = None
cost_so_far[start_state] = 0
while not frontier.empty( ):
current_cost, current_state = frontier.get()
if current_state == goal_state:
# Reconstruct the path from start_state to goal_state
path = [ ]
while current_state is not None:
path.append(current_state)
current_state = came_from[current_state]
path.reverse()
return path
for next_state in successors(current_state):
new_cost = cost_so_far[current_state] + 1 # Uniform cost of 1 for each move
if next_state not in cost_so_far or new_cost < cost_so_far[next_state]:
cost_so_far[next_state] = new_cost
priority = new_cost # Best-First Search uses cost as priority
frontier.put((priority, next_state))
came_from[next_state] = current_state
return None # No path found

def print_solution(path):
if path is None:
print("No solution found.")
else:
print("Solution found!")
for i, state in enumerate(path):
print(f"Step {i}:")
print(f"Left Bank: {state.left_m} missionaries, {state.left_c} cannibals")
print(f"Boat is {'on the left' if state.boat == 1 else 'on the right'} bank")
print(f"Right Bank: {state.right_m} missionaries, {state.right_c} cannibals")
print("------------")
# Main function to run the Best-First Search and print the solution
if __name__ == "__main__":
solution_path = best_first_search( )
print_solution(solution_path)

14
lOMoARcPSD|27793530

OUTPUT

Solution found!
Step 0:
Left bank: 3 missionaries, 3 cannibals
Boat is on the left bank
Right bank: 0 missionaries, 0 cannibals
------------
Step 1:
Left bank: 3 missionaries, 1 cannibals
Boat is on the right bank
Right bank: 0 missionaries, 2 cannibals
------------
Step 2:
Left bank: 3 missionaries, 2 cannibals
Boat is on the left bank
Right bank: 0 missionaries, 1 cannibals
Step 3:
Left bank: 3 missionaries, 0 cannibals
Boat is on the right bank
Right bank: 0 missionaries, 3 cannibals
------------
Step 4:
Left bank: 3 missionaries, 1 cannibals
Boat is on the left bank
Right bank: 0 missionaries, 2 cannibals
------------
Step 5:
Left bank: 1 missionaries, 1 cannibals
Boat is on the right bank
Right bank: 2 missionaries, 2 cannibals
------------

15
lOMoARcPSD|27793530

Step 6:
Left bank: 2 missionaries, 2 cannibals
Boat is on the left bank
Right bank: 1 missionaries, 1 cannibals

Step 7:
Left bank: 0 missionaries, 2 cannibals
Boat is on the right bank
Right bank: 3 missionaries, 1 cannibals
------------
Step 8:
Left bank: 0 missionaries, 3 cannibals
Boat is on the left bank
Right bank: 3 missionaries, 0 cannibals
------------
Step 9:
Left bank: 0 missionaries, 1 cannibals
Boat is on the right bank
Right bank: 3 missionaries, 2 cannibals
------------
Step 10:
Left bank: 0 missionaries, 2 cannibals
Boat is on the left bank
Right bank: 3 missionaries, 1 cannibals
------------
Step 11:
Left bank: 0 missionaries, 0 cannibals
Boat is on the right bank
Right bank: 3 missionaries, 3 cannibals

16
lOMoARcPSD|27793530

VIVA QUESTIONS

1. What is the Missionaries and Cannibals Problem?


Answer: It is a classic AI problem where 3 missionaries and 3 cannibals must cross a river using a boat that can carry a
maximum of 2 people, without ever allowing the cannibals to outnumber missionaries on either bank.

2. What is the Best First Search Algorithm?


Answer: Best First Search (BFS) is a heuristic-based search algorithm that selects the most promising node based
on a heuristic function and expands it first.

3. Why is Best First Search used for solving this problem?


Answer: BFS is efficient because it prioritizes nodes with a lower heuristic cost, reducing unnecessary searches and
finding a solution faster.

4. What data structure is used to implement Best First Search?


Answer: A priority queue (min-heap) is used to always expand the least-cost node first.

5. How does the heuristic function work in this problem?


Answer: The heuristic cost is the number of moves made so far. BFS selects the state with the least cost.

6. What are the constraints that make a state invalid?


Answer:
 The number of missionaries or cannibals cannot be negative or exceed 3.
 Cannibals cannot outnumber missionaries on either side.

7. How is the goal state defined?


Answer: The goal state is reached when (0, 0, 0), meaning all missionaries and cannibals have safely crossed the river.

8. How do we prevent revisiting the same states?


Answer: A visited set is maintained to store already explored states and avoid cycles.

9. What is the time complexity of Best First Search?


Answer: The worst-case time complexity is O(b^d), where b is the branching factor and d is the depth of the search tree.

10. How does Best First Search compare to A Search?*


Answer:
 Best First Search only considers heuristic cost (h(n)).
 A* Search considers both heuristic (h(n)) and path cost (g(n)) for optimal solutions

17
lOMoARcPSD|27793530

3.Implement A* Search algorithm

import heapq
class Node:
def __init__(self, state, parent=None, action=None, cost=0, heuristic=0):
self.state = state # Current state in the search space
self.parent = parent # Parent node
self.action = action # Action that led to this node from the parent node
self.cost = cost # Cost to reach this node from the start node
self.heuristic = heuristic # Heuristic estimate of the cost to reach the goal

def __lt__(self, other):


return (self.cost + self.heuristic) < (other.cost + other.heuristic)def parse_graph_input():
graph = {}
num_edges = int(input("Enter the number of edges: "))
for _ in range(num_edges):
u, v, cost = input("Enter an edge (format: u v cost): ").split()
cost = int(cost)
if u not in graph:
graph[u] = []
if v not in graph:
graph[v] = []
graph[u].append((v, cost))
graph[v].append((u, cost))
return graph

def astar_search(start_state, goal_test, successors, heuristic):


# Priority queue to store nodes ordered by f = g + h
frontier = [ ]
heapq.heappush(frontier, Node(start_state, None, None, 0, heuristic(start_state))) explored = set( )
while frontier:
current_node = heapq.heappop(frontier)
current_state = current_node.state
if goal_test(current_state):
# Reconstruct the path from the goal node to the start node
path = [ ]
while current_node.parent is not None:
path.append((current_node.action, current_node.state))
current_node = current_node.parent
path.reverse()
return path
explored.add(current_state)
# Generate successors for the current state using the `successors` function
for action, successor_state, step_cost in successors(current_state):
if successor_state not in explored:
new_cost = current_node.cost + step_cost
new_node = Node(successor_state, current_node, action, new_cost,
heuristic(successor_state))
heapq.heappush(frontier, new_node)
return None # No path found

18
lOMoARcPSD|27793530

if __name__ == "__main__":
# Get user input to define the graph
print("Define the graph:")
graph = parse_graph_input()
start_state = input("Enter the start state: ")
goal_state = input("Enter the goal state: ")
def goal_test(state):
return state == goal_state

def successors(state):
# Generate successor states from the current state based on the graph
successors_list = [ ]
for neighbor, cost in graph.get(state, [ ]):
action = f"Move to {neighbor}" # Default action (e.g., "Move to B") successor_state = neighbor
step_cost = cost
successors_list.append((action, successor_state, step_cost))
return successors_list

def heuristic(state):
# Define a simple heuristic function (e.g., straight-line distance)
heuristic_values = {key: abs(ord(key) - ord(goal_state)) for key in graph.keys()}
return heuristic_values.get(state, float('inf'))
# Default to infinity if state not found
# Perform A* search using custom successors function
path = astar_search(start_state, goal_test, successors, heuristic)
# Print the resulting path found by A* search
if path:
print("Path found:")
for action, state in path:
print(f"Action: {action}, State: {state}")
else:
print("No path found.")

OUTPUT
$ p3 03Astar_search.py
Define the graph:
Enter the number of edges: 7
Enter an edge (format: u v cost): A B 1
Enter an edge (format: u v cost): A C 3
Enter an edge (format: u v cost): B C 1
Enter an edge (format: u v cost): B D 2
Enter an edge (format: u v cost): C D 1
Enter an edge (format: u v cost): D E 4
Enter an edge (format: u v cost): E G 3
Enter the start state: A
Enter the goal state: G
Path found:
Action: Move to B, State: B
Action: Move to D, State: D
Action: Move to E, State: E
Action: Move to G, State: G

19
lOMoARcPSD|27793530

VIVA QUESTIONS
1. What is the A* Search Algorithm?
Answer: A* is a search algorithm that finds the shortest path from a start node to a goal node. It uses both:
 g(n) → The cost from the start node to the current node.
 h(n) → A heuristic estimate of the cost from the current node to the goal.
The total cost function is:
f(n)=g(n)+h(n)f(n) = g(n) + h(n)

2. Why is A* better than Best First Search?


Answer: Best First Search uses only the heuristic function h(n), which may lead to inefficient paths.
A* considers both g(n) (actual cost) and h(n) (estimated cost), ensuring an optimal path.

3. What is the heuristic function in A*?


Answer:A heuristic function h(n) estimates the cost to reach the goal from node n.
It should be admissible (never overestimates) and consistent (follows the triangle inequality).

4. What data structure is used in A* Search?


Answer:A* uses a priority queue (min-heap) to always expand the node with the lowest f(n) value first.

5. What are the necessary conditions for A* to guarantee an optimal solution?


Answer:
 The heuristic function must be admissible (never overestimates the true cost).
 The heuristic must be consistent (monotonicity property).
 The search space must be finite.

6. What is the worst-case time complexity of A*?


Answer:The worst-case time complexity is O(b^d), where:
 b is the branching factor (average number of children per node).
 d is the depth of the optimal solution.
However, if the heuristic is well-designed, A* performs much better than uninformed search algorithms.

7. How do we prevent cycles in A* Search?


Answer:A visited set (closed list) is maintained to avoid re-exploring already visited nodes.

8. Can A* work with a bad heuristic function?


Answer:Yes, but its performance degrades.

20
lOMoARcPSD|27793530

 If h(n) = 0, A* behaves like Dijkstra's Algorithm.


 If h(n) overestimates, it may produce suboptimal or incorrect solutions.

9. What are real-world applications of A* Search?


Answer: A* is widely used in:
 Pathfinding in games (e.g., Pac-Man, Google Maps, GPS systems)
 Robotics (e.g., autonomous navigation)
 Artificial intelligence (e.g., solving puzzles like the 8-puzzle problem)

10. How does A* differ from Dijkstra’s Algorithm?


Answer:
 Dijkstra’s Algorithm considers only the actual cost g(n) (uniform-cost search).
 A Search* uses both g(n) and h(n) for a more efficient pathfinding approach.

21
lOMoARcPSD|27793530

4. Implement AO* Search Algorithm


import heapq
class Node:
def __init__(self, state, parent=None, action=None, cost=0, heuristic=0):
self.state = state # Current state in the search space
self.parent = parent # Parent node
self.action = action # Action that led to this node from the parent node
self.cost = cost # Cost to reach this node from the start node
self.heuristic = heuristic # Heuristic estimate of the cost to reach the goal

def __lt__(self, other):


return (self.cost + self.heuristic) < (other.cost + other.heuristic)

def parse_graph_input():
graph = {}
num_edges = int(input("Enter the number of edges: "))
for _ in range(num_edges):
u, v, cost = input("Enter an edge (format: u v cost): ").split()
cost = float(cost)
if u not in graph:
graph[u] = [ ]
if v not in graph:
graph[v] = [ ]
graph[u].append((v, cost))
return graph

def ao_star_search(start_state, goal_state, graph):


frontier = [ ]
heapq.heappush(frontier, Node(start_state, None, None, 0, heuristic(start_state, goal_state)))
explored = {}
while frontier:
current_node = heapq.heappop(frontier)
current_state = current_node.state
if current_state == goal_state:
# Reconstruct the path from the goal node to the start node
path = [ ]
while current_node.parent is not None:
path.append((current_node.action, current_node.state))
current_node = current_node.parent
path.reverse()
return path
if current_state not in explored or current_node.cost < explored[current_state]:
explored[current_state] = current_node.cost
for neighbor, step_cost in graph.get(current_state, []):
new_cost = current_node.cost + step_cost
new_node = Node(neighbor, current_node,
f"Move to {neighbor}", new_cost, heuristic(neighbor, goal_state))
heapq.heappush(frontier, new_node)
return None # No path found
def heuristic(state, goal_state):

22
lOMoARcPSD|27793530

# Simple heuristic function (e.g., straight-line distance)


heuristic_values = {'A': 5, 'B': 3, 'C': 2, 'D': 1, 'E': 2, 'G': 0}
# Custom heuristic values based on problem domain
return heuristic_values.get(state, float('inf'))
# Default to infinity if state not found
if __name__ == "__main__":
# Get user input to define the graph
print("Define the graph:")
graph = parse_graph_input( )
start_state = input("Enter the start state: ")
goal_state = input("Enter the goal state: ")
# Perform AO* search using the defined graph, start state, and goal state
path = ao_star_search(start_state, goal_state, graph)
# Print the resulting path found by AO* search

if path:
print("Path found:")
for action, state in path:
print(f"Action: {action}, State: {state}")
else:
print("No path found.")

OUTPUT
$ p3 04AOstar_search.py
Define the graph:
Enter the number of edges: 8
Enter an edge (format: u v cost): S A 3
Enter an edge (format: u v cost): S B 2
Enter an edge (format: u v cost): A C 4
Enter an edge (format: u v cost): A D 2
Enter an edge (format: u v cost): B E 3
Enter an edge (format: u v cost): C G 2
Enter an edge (format: u v cost): D G 5
Enter an edge (format: u v cost): E G 4
Enter the start state: S
Enter the goal state: G
Path found:
Action: Move to B, State: B
Action: Move to E, State: E
Action: Move to G, State: G

23
lOMoARcPSD|27793530

VIVA QUESTIONS

1. What is the AO* Search Algorithm?


Answer:AO* is an informed search algorithm used for solving problems represented as an AND-OR graph,
where nodes may require multiple sub-goals to be solved together.

2. What is the difference between AO* and A* Search?


Answer:
 A* is used for single-goal problems (OR graphs).
 AO* handles problems with multiple sub-goals that must be solved together (AND-OR graphs).

3. What are AND and OR nodes in AO*Search?


Answer:
 OR nodes: A solution can be found by selecting one child node.
 AND nodes: A solution requires selecting all child nodes.

4. How does AO* evaluate a node’s cost?


Answer:AO* updates the cost of a node by considering:
f(n)=g(n)+h(n)f(n) = g(n) + h(n)
where g(n) is the actual cost, and h(n) is the estimated heuristic cost.

5. What data structure is used in AO* Search?


Answer:AO* uses a graph structure instead of a simple tree, allowing cycles and multiple paths.

6. How does AO* handle backtracking?


Answer:AO* propagates cost values backward, ensuring that the best path is selected dynamically as the search
progresses.

7. What are some applications of AO* Search?


Answer:AO* is used in:
 AI planning and decision-making
 Game playing (e.g., solving puzzles and multi-agent games)
 Expert systems for medical diagnosis

8. How does AO* ensure optimality?


Answer: AO* uses a heuristic function to guide search and backpropagation to adjust solutions dynamically,
ensuring an optimal or near-optimal solution.

24
lOMoARcPSD|27793530

9. What is the main advantage of AO* over traditional search algorithms?


Answer:AO* efficiently handles problems with sub-goals by pruning unnecessary paths and dynamically updating
best solution.

10. What is the worst-case time complexity of AO* Search?


Answer:The worst-case complexity is O(b^d), where b is the branching factor and d is the depth of the solution, similar
to A*.

25
lOMoARcPSD|27793530

5. Solve 8-Queens Problem with suitable assumptions

 Python code for first solution

def is_safe(board, row, col):


""" Check if it's safe to place a queen at board[row][col] """
# Check column
for i in range(row):
if board[i][col] == 1:
return False

# Check upper diagonal on left side


i, j = row, col
while i >= 0 and j >= 0:
if board[i][j] == 1:
return False
i -= 1
j -= 1

# Check upper diagonal on right side


i, j = row, col
while i >= 0 and j < len(board):
if board[i][j] == 1:
return False
i -= 1
j += 1

return True

def solve_queens(board, row):


""" Recursively solve the 8-Queens Problem using backtracking """
n = len(board)

# Base case: If all queens are placed, return True


if row >= n:
return True

for col in range(n):


if is_safe(board, row, col):
board[row][col] = 1 # Place the queen

# Recur to place the rest of the queens


if solve_queens(board, row + 1):
return True

# If placing queen at board[row][col] doesn't lead to a solution, backtrack


board[row][col] = 0 # Backtrack

return False

26
lOMoARcPSD|27793530

def print_board(board):
""" Print the board configuration """
n = len(board)
for i in range(n):
for j in range(n):
print(board[i][j], end=" ")
print()

def solve_8queens():
""" Solve the 8-Queens Problem and print the solution """
n = 8 # Size of the chessboard (8x8)
board = [[0] * n for _ in range(n)] # Initialize empty board

if solve_queens(board, 0):
print("Solution found:")
print_board(board)
else:
print("No solution exists.")

# Call the function to solve the 8-Queens Problem


solve_8queens()

OUTPUT

$ python 05NQueens.py Solution found:


10000000
00001000
00000001
00000100
00100000
00000010
01000000
00010000

27
lOMoARcPSD|27793530

 Python code for all solution

def is_safe(board, row, col):


""" Check if it's safe to place a queen at board[row][col] """
n = len(board)

# Check column
for i in range(row):
if board[i][col] == 1:
return False

# Check upper diagonal on left side


i, j = row, col
while i >= 0 and j >= 0:
if board[i][j] == 1:
return False
i -= 1
j -= 1

# Check upper diagonal on right side


i, j = row, col
while i >= 0 and j < n:
if board[i][j] == 1:
return False
i -= 1
j += 1

return True

def solve_queens(board, row, solutions):


""" Recursively solve the 8-Queens Problem using backtracking """
n = len(board)

# Base case: If all queens are placed, add the solution to the list
if row >= n:
solutions.append([row[:] for row in board])
return

for col in range(n):


if is_safe(board, row, col):
board[row][col] = 1 # Place the queen
solve_queens(board, row + 1, solutions)
board[row][col] = 0 # Backtrack

def print_board(board):
""" Print the board configuration """
n = len(board)
for i in range(n):
for j in range(n):
print(board[i][j], end=" ")
print()

28
lOMoARcPSD|27793530

print()

def print_all_solutions():
""" Solve the 8-Queens Problem and print all distinct solutions """
n = 8 # Size of the chessboard (8x8)
board = [[0] * n for _ in range(n)] # Initialize empty board
solutions = []

solve_queens(board, 0, solutions)

# Print all solutions found


num_solutions = len(solutions)
if num_solutions == 0:
print("No solutions found.")
else:
print(f"Total solutions found: {num_solutions}")
for idx, solution in enumerate(solutions, start=1):
print(f"Solution {idx}:")
print_board(solution)

# Call the function to print all solutions to the 8-Queens Problem


print_all_solutions()

29
lOMoARcPSD|27793530

VIVA QUESTIONS

1. What is the 8-Queens Problem?


Answer:
The 8-Queens Problem is a constraint satisfaction problem where 8 queens must be placed on an 8×8 chessboard so that no two
queens attack each other.

2. What are the constraints in the 8-Queens Problem?


Answer:
No two queens should be in the same row, same column, or the same diagonal.

3. What are some common algorithms to solve the 8-Queens Problem?


Answer:
 Backtracking
 Branch and Bound
 Hill Climbing
 Genetic Algorithms

4. How does the backtracking approach work for solving the 8-Queens Problem?
Answer:
Backtracking places queens one by one in each row and backtracks if a conflict is found, trying different placements.

5. What is the time complexity of the 8-Queens Problem using backtracking?


Answer:
The worst-case time complexity is O(N!), where N is the number of queens.

6. What is the heuristic function used in solving the 8-Queens Problem using Hill Climbing?
Answer:
The heuristic function counts the number of attacking pairs of queens and tries to minimize it.

7. Can we solve the N-Queens Problem for any value of N?


Answer:
Yes, the problem has solutions for N ≥ 4, except for N = 2 and N = 3, which have no solutions.

8. How many solutions exist for the 8-Queens Problem?


Answer:
There are 92 distinct solutions, but only 12 are unique (others are symmetric variations).

30
lOMoARcPSD|27793530

9. Why can’t we place all queens in one row?


Answer:
Because they will attack each other, violating the same-row constraint.

10. What are some real-world applications of the N-Queens Problem?


Answer:
 Parallel computing (task scheduling)
 Robotics (motion planning)
 Genetic algorithms (optimization problems)

31
lOMoARcPSD|27793530

6.Implementation of TSP using heuristic approach

import sys

def nearest_neighbor_tsp(distances):
num_cities = len(distances)

# Start from the first city (arbitrary choice)


tour = [0] # Store the tour as a list of city indices
visited = set([0]) # Track visited cities

current_city = 0
total_distance = 0

while len(visited) < num_cities:


nearest_city = None
min_distance = sys.maxsize

# Find the nearest unvisited city


for next_city in range(num_cities):
if next_city not in visited and distances[current_city][next_city] < min_distance:
nearest_city = next_city
min_distance = distances[current_city][next_city]

# Move to the nearest city


tour.append(nearest_city)
visited.add(nearest_city)
total_distance += min_distance
current_city = nearest_city

# Complete the tour by returning to the starting city


tour.append(0)
total_distance += distances[current_city][0]

return tour, total_distance

# Example usage:
if __name__ == "__main__":
# Example distance matrix (symmetric, square matrix)
# distances = [[0, 10, 15, 20], [10, 0, 35, 25], [15, 35, 0, 30], [20, 25, 30, 0]]
distances = [[ 0, 4, 8, 9, 12], [ 4, 0, 6, 8, 9], [ 8, 6, 0, 10, 11], [ 9, 8, 10, 0, 7], [12, 9, 11, 7, 0]]
# Run nearest neighbor TSP algorithm
tour, total_distance = nearest_neighbor_tsp(distances)

# Print the tour and total distance


print("Nearest Neighbor TSP Tour:", tour)
print("Total Distance:", total_distance)

32
lOMoARcPSD|27793530

OUTPUT

$ python 06_TSP_heuristics.py
Nearest Neighbor TSP Tour: [0, 1, 2, 3, 4, 0]
Total Distance: 39

VIVA QUESTIONS

1. What is the Traveling Salesman Problem (TSP)?


Answer:
TSP is an optimization problem where a salesman must visit N cities exactly once and return to the starting city with the
minimum travel cost.

2. What is a heuristic approach in TSP?


Answer:
A heuristic is an approximate method to find a good (but not necessarily optimal) solution quickly, often used when exact
algorithms are too slow.

3. What is the Nearest Neighbor Heuristic?


Answer:
The Nearest Neighbor Algorithm selects the closest unvisited city at each step until all cities are visited.

4. What is the time complexity of the Nearest Neighbor Algorithm?


Answer:
The time complexity is O(N²), where N is the number of cities.

5. Is the Nearest Neighbor Algorithm guaranteed to find the optimal solution?


Answer:
No, it often finds suboptimal solutions because it makes greedy local choices that may not be globally optimal.

6. What is the limitation of the Nearest Neighbor Heuristic?


Answer:
It may get stuck in a locally optimal path, missing better global solutions.

33
lOMoARcPSD|27793530

7. What are alternative heuristic approaches for TSP?


Answer:
 Genetic Algorithms
 Simulated Annealing
 Ant Colony Optimization
 2-opt and 3-opt methods

8. What is an adjacency matrix in TSP?


Answer:
An adjacency matrix is a 2D array where graph[i][j] represents the cost/distance from city i to city j.

9. What is a real-world application of TSP?


Answer:
 Logistics and delivery routing (Amazon, FedEx)
 Route planning for GPS navigation
 Manufacturing (circuit board drilling)

10. How does TSP relate to Graph Theory?


Answer:
TSP is a graph traversal problem where cities are nodes, and paths between them are edges with weights (distances).

34
lOMoARcPSD|27793530

7.Implementation of the problem solving strategies: either using Forward Chaining or


Backward Chaining

def forward_chaining(rules, facts, goal):


inferred_facts = set(facts)
new_facts = True

while new_facts:
new_facts = False

for rule in rules:


condition, result = rule

if all(cond in inferred_facts for cond in condition) and result not in inferred_facts:


inferred_facts.add(result)
new_facts = True

if result == goal:
return True
return False

def backward_chaining(rules, facts, goal):


def ask(query):
if query in facts:
return True

for rule in rules:


condition, result = rule
if result == query and all(ask(cond) for cond in condition):
return True
return False
return ask(goal)

# Define the rules and facts for the animal classification problem
rules = [
(['hair', 'live young'], 'mammal'),
(['feathers', 'fly'], 'bird')
]

facts = ['hair', 'live young']


goal = 'mammal'

# Use forward chaining to determine if a cat is classified as a mammal


is_mammal = forward_chaining(rules, facts, goal)
if is_mammal:
print("Using forward chaining the cat is classified as a mammal.")
else:
print("Using forward chaining the cat is not classified as a mammal.")
facts = ['feathers', 'fly']
goal = 'bird'

35
lOMoARcPSD|27793530

# Use backward chaining to determine if a pigeon is classified as a bird


is_bird = backward_chaining(rules, facts, goal)
if is_bird:
print("Using backward chaining the pigeon is classified as a bird.")
else:
print("Using backward chaining the pigeon is not classified as a bird.")

OUTPUT

$ python 07_Fwd_Bwd_chaining.py
Using forward chaining the cat is classified as a mammal.
Using backward chaining the pigeon is classified as a bird.

36
lOMoARcPSD|27793530

VIVA QUESTIONS

1. What is Forward Chaining?


Answer:
Forward Chaining is a data-driven reasoning approach where inference starts with known facts and applies rules to reach a goal
(conclusion).

2. What is Backward Chaining?


Answer:
Backward Chaining is a goal-driven reasoning approach where inference starts with a goal (hypothesis) and works backward to
find supporting facts.

3. What is the main difference between Forward and Backward Chaining?


Answer:
 Forward Chaining starts from facts and derives conclusions.
 Backward Chaining starts from a goal and looks for supporting facts.
Example:
 Forward Chaining: "If it’s raining, the road will be wet" → It’s raining → The road is wet.
 Backward Chaining: "Is the road wet? → Check if it's raining or a pipe is leaking."

4. Where are Forward and Backward Chaining used in AI?


Answer:
 Forward Chaining: Expert systems, rule-based AI, medical diagnosis (MYCIN system).
 Backward Chaining: Prolog programming, theorem proving, AI planning (goal-based agents).

5. Which is more efficient: Forward or Backward Chaining?


Answer:
 Forward Chaining is efficient when many facts are available and we need to derive multiple conclusions.
 Backward Chaining is efficient when few possible goals exist, as it only searches relevant facts.

37
lOMoARcPSD|27793530

8.Implement resolution principle on FOPL related problems

def negate_literal(literal):
""" Negate a literal by adding or removing the negation symbol '~' """
if literal.startswith('~'):
return literal[1:] # Remove negation
else:
return '~' + literal # Add negation

def resolve(clause1, clause2):


""" Resolve two clauses to derive a new clause """
new_clause = []
resolved = False

# Convert clauses to tuples for hashability


clause1_tuple = tuple(clause1)
clause2_tuple = tuple(clause2)

# Copy literals from both clauses


for literal in clause1_tuple:
if negate_literal(literal) in clause2_tuple:
resolved = True
else:
new_clause.append(literal)

for literal in clause2_tuple:


if negate_literal(literal) not in clause1_tuple:
new_clause.append(literal)

if resolved:
return new_clause
else:
return None # No resolution possible

def resolution(propositional_kb, query):


""" Use resolution to prove or disprove a query using propositional logic """
kb = propositional_kb[:]
kb.append(negate_literal(query)) # Add negated query to knowledge base

while True:
new_clauses = []
n = len(kb)
resolved_pairs = set() # Track resolved pairs to avoid redundant resolutions

for i in range(n):
for j in range(i + 1, n):
clause1 = kb[i]
clause2 = kb[j]

# Convert clauses to tuples for hashability


clause1_tuple = tuple(clause1)

38
lOMoARcPSD|27793530

clause2_tuple = tuple(clause2)

if (clause1_tuple, clause2_tuple) not in resolved_pairs:


resolved_pairs.add((clause1_tuple, clause2_tuple))
resolvent = resolve(clause1, clause2)

if resolvent is None:
continue # No resolution possible for these clauses

if len(resolvent) == 0:
return True # Empty clause (contradiction), query is proved

# Convert resolvent back to list before adding to new_clauses


resolvent_list = list(resolvent)
if resolvent_list not in new_clauses:
new_clauses.append(resolvent_list)

if all(clause in kb for clause in new_clauses):


return False # No new clauses added, query cannot be proven
kb.extend(new_clauses) # Add new clauses to the knowledge base

# Example usage:
if __name__ == "__main__":
# Example propositional knowledge base (list of clauses)
propositional_kb = [
['~P', 'Q'],
['P', '~Q', 'R'],
['~R', 'S']
]

# Example query to prove/disprove using resolution


query = 'S'

# Use resolution to determine if the query can be proven


result = resolution(propositional_kb, query)

if result:
print(f"The query '{query}' is PROVED.")
else:
print(f"The query '{query}' is DISPROVED.")

OUTPUT
$ python 08_fopl.py
The query 'S' is DISPROVED.

39
lOMoARcPSD|27793530

VIVA QUESTIONS
1. What is the Resolution Principle in First-Order Predicate Logic (FOPL)?
Answer:
The Resolution Principle is an inference rule used in automated theorem proving. It refutes a given statement by converting it
into clausal form and deriving contradictions using unification and resolution.

2. What are the steps involved in the resolution process?


Answer:
1. Convert the given statements into First-Order Predicate Logic (FOPL).
2. Convert FOPL statements into Clausal Form (CNF - Conjunctive Normal Form).
3. Apply Unification to resolve literals.
4. Apply Resolution to derive new clauses.
5. Continue until a contradiction (empty clause) is found, proving the theorem.

3. What is Unification in the Resolution Principle?


Answer:
Unification is the process of making two logical expressions identical by substituting variables with appropriate values. It helps
in resolving predicates.
Example:
 Given: P(x) and P(a)
 Unification: Substitute x = a, making both expressions identical.

4. What is Conjunctive Normal Form (CNF), and why is it important in Resolution?


Answer:
CNF (Conjunctive Normal Form) is a logical representation where a formula is expressed as a conjunction (AND) of
disjunctions (OR) of literals.
It is important because resolution works only on CNF expressions.
Example:
(A∨B)∧(¬B∨C)(A \lor B) \land (\neg B \lor C)(A∨B)∧(¬B∨C)

5. Where is the Resolution Principle used in AI?


Answer:
The Resolution Principle is used in:
 Automated Theorem Proving (Prolog, AI reasoning systems).
 Expert Systems (Medical diagnosis, rule-based AI).
 Natural Language Processing (NLP) (Semantic understanding).
 Knowledge Representation and Reasoning

40
lOMoARcPSD|27793530

9. Implement Tic-tac-toe game using Python

def print_board(board):
""" Print the current state of the Tic-Tac-Toe board """
for row in board:
print(" | ".join(row))
print("-" * 9)

def check_winner(board, player):


""" Check if the specified player has won the game """
for row in board:
if all(cell == player for cell in row):
return True
for col in range(3):
if all(board[row][col] == player for row in range(3)):
return True
if all(board[i][i] == player for i in range(3)):
return True
if all(board[i][2-i] == player for i in range(3)):
return True
return False

def is_full(board):
""" Check if the board is completely filled """
return all(cell != ' ' for row in board for cell in row)

def tic_tac_toe():
""" Main function to run the Tic-Tac-Toe game """
board = [[' ' for _ in range(3)] for _ in range(3)]
current_player = 'X'

while True:
print_board(board)
print(f"Player {current_player}'s turn.")
row = int(input("Enter row (1-3): "))
col = int(input("Enter column (1-3): "))
row -= 1
col -= 1

if board[row][col] == ' ':


board[row][col] = current_player
else:
print("Invalid move! Try again.")
continue

# Check if the current player has won


if check_winner(board, current_player):
print_board(board)
print(f"Player {current_player} wins!")
break

41
lOMoARcPSD|27793530

# Check if the board is full (tie game)


if is_full(board):
print_board(board)
print("It's a tie!")
break

# Switch to the other player


current_player = 'O' if current_player == 'X' else 'X'

if __name__ == "__main__":
tic_tac_toe()

OUTPUT
$ python 09_Tic_Tac_Toe.py
| |
---------
| |
---------
| |
Player X's turn.
Enter row (1-3): 2
Enter column (1-3): 2
| |
---------
| X |
---------
| |
Player O's turn.
Enter row (1-3): 1
Enter column (1-3): 1
O | |
---------
| X |
---------
| |
---------
Player X's turn.
Enter row (1-3): 1
Enter column (1-3): 2
O | X |
---------
| X |
| |
Player O's turn.
Enter row (1-3): 3
Enter column (1-3): 2
O | X |
---------
| X |
---------
| O |
---------
Player X's turn.
Enter row (1-3): 1
Enter column (1-3): 3
O | X | X

42
lOMoARcPSD|27793530

---------
| X |
---------
| O |
Player O's turn.
Enter row (1-3): 3
Enter column (1-3): 3

O | X | X
---------
| X |
---------
| O | O
Player X's turn.
Enter row (1-3): 3
Enter column (1-3): 1
O | X | X
---------
| X |
X | O | O
Player X wins!

43
lOMoARcPSD|27793530

VIVA QUESTIONS

1. What is the basic logic behind a Tic-Tac-Toe game?


Answer:
Tic-Tac-Toe is a turn-based two-player game where players take turns placing "X" or "O" on a 3×3 grid. The player who first
places three of their marks in a row, column, or diagonal wins.

2. How can you implement Tic-Tac-Toe in Python?


Answer:
Tic-Tac-Toe can be implemented using:
 A 2D list (matrix) to represent the board.
 A loop for alternating turns.
 A function to check for a win (rows, columns, diagonals).
 A function to check for a draw (if the board is full).

3. How do you check the winner in a Tic-Tac-Toe game?


Answer:
A function checks:
 Rows: If all elements in any row are the same (X or O).
 Columns: If all elements in any column are the same.
 Diagonals: If all elements in any diagonal are the same.
If any condition is met, the game ends with a winner.

4. How do you implement a basic AI for Tic-Tac-Toe?


Answer:
A simple AI can be implemented using:
 Random move selection (Beginner AI).
 Minimax algorithm (Optimal AI that never loses).
 Alpha-Beta Pruning (Optimized Minimax for better performance).

5. What are the possible outcomes of a Tic-Tac-Toe game?


Answer:
 Win: One player gets three marks in a row, column, or diagonal.
 Draw: The board is full, and no player has won.
 Ongoing: Some moves are still left, and no winner is decided yet.

44
lOMoARcPSD|27793530

10. Build a bot which provides all the information related to text in search box

Theory:

The bot performs a Google search based on the user's input and retrieves the search results. You can extend this
code further to include more advanced features such as processing the search results for specific types of
information, implementing natural language processing for understanding user queries better, and integrating
with other APIs for additional functionalities.

To see the results of the above program, you can simply run the script in your Python environment and follow
the instructions. Here's how you can do it:

 Copy the provided code into a Python file (e.g., search_bot.py).


 Save the file.
 Open a terminal or command prompt.
 Navigate to the directory where you saved the Python file.
 Run the Python script by typing python search_bot.py and pressing Enter.
 The program will prompt you to enter a search query. Type your query and press Enter.
 The program will then fetch the search results from Google and display them in the terminal.

45
lOMoARcPSD|27793530

Program:

Output:

46
lOMoARcPSD|27793530

11.Implement any Game and demonstrate the Game playing strategies

import random
class RockPaperScissors:
def init (self):
self.moves = ['rock', 'paper', 'scissors']
self.winning_moves = {'rock': 'scissors', 'paper': 'rock', 'scissors': 'paper'}
def play_round(self, player_move):
computer_move = random.choice(self.moves)
print(f"Computer chooses: {computer_move}")
if player_move == computer_move:
return "It's a tie!"
elif self.winning_moves[player_move] == computer_move:
return "You win!"
else:
return "Computer wins!"
class RandomPlayer:
def init (self):
pass
def get_move(self):
return random.choice(['rock', 'paper', 'scissors'])
class AIPlayer:
def init (self):
pass
def get_move(self, player_moves):
# Basic strategy: Counter the player's last move
last_move = player_moves[-1]
if last_move == 'rock':
lOMoARcPSD|27793530

return 'paper'
elif last_move == 'paper':
return 'scissors'
else:

return 'rock'
# Demonstration
if name == ' main ':
game = RockPaperScissors()
player1 = RandomPlayer()
player2 = AIPlayer()
player_moves = []
for _ in range(3):

# Random player's move


player_move = player1.get_move()
player_moves.append(player_move)
print(f"You chose: {player_move}")
# AI player's move
ai_move = player2.get_move(player_moves)
player_moves.append(ai_move)
print(f"AI chose: {ai_move}")

# Determine the winner of the round


result = game.play_round(player_move)
print(result)
print('---')
Output
You chose:
rockAI
chose:
paper
Computer chooses:
scissorsYou win!
---
You chose:
rockAI
chose:
paper
Computer chooses:
paperComputer
wins!
---
You chose:
scissorsAI
chose: rock
Computer chooses:
paperYou win!
---

Dept CSE (AIML) 2023-24


AMCEC
49

You might also like