ARTIFICIAL INTELLIGENCE LABORATORY MANUAL BAD402
LIST OF EXPERIMENTS
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 using Python
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
Department of AIML, BrCE: Dr.Rajarajeswarie.B Page 1
ARTIFICIAL INTELLIGENCE LABORATORY MANUAL BAD402
1. Implement and Demonstrate Depth First Search Algorithm on
Water Jug Problem
Objective:
The objective of this implementation is to use the Depth-First Search (DFS)
algorithm to solve the classic Water Jug Problem, where two jugs of fixed
capacities are used to measure a specific amount of water.
Algorithm:
1. Start with the initial state where both jugs are empty.
2. Perform depth-first search to explore all possible states starting from the initial state.
3. At each state, generate all possible next states by performing the following operations:
Emptying Jug 1
Emptying Jug 2
Filling Jug 1 to its capacity
Filling Jug 2 to its capacity
Pouring water from Jug 1 to Jug 2 until Jug 1 is empty or Jug 2 is full
Pouring water from Jug 2 to Jug 1 until Jug 2 is empty or Jug 1 is full
4. Keep track of visited states to avoid revisiting the same state.
5. If a target state is reached, return the path from the initial state to the target state.
6. If no solution is found, return None.
class State:
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 str (self):
return f"({self.jug1}, {self.jug2})"
def dfs(current, visited, target, jug1_capacity,
jug2_capacity): if current == target:
return [current]
visited.add(current)
Department of AIML, BrCE: Dr.Rajarajeswarie.B Page 2
ARTIFICIAL INTELLIGENCE LABORATORY MANUAL BAD402
for next_state in get_next_states(current, jug1_capacity, jug2_capacity):
if next_state not in visited:
path = dfs(next_state, visited, target, jug1_capacity, jug2_capacity)
if path:
return [current] + path
return None
def get_next_states(current, jug1_capacity, jug2_capacity):
next_states = []
# Empty Jug 1
next_states.append(State(0, current.jug2))
# Empty Jug 2
next_states.append(State(current.jug1, 0))
# Fill Jug 1
next_states.append(State(jug1_capacity, current.jug2))
# Fill Jug 2
next_states.append(State(current.jug1, jug2_capacity))
# Pour Jug 1 to Jug 2
pour_amount = min(current.jug1, jug2_capacity - current.jug2)
next_states.append(State(current.jug1 - pour_amount, current.jug2 + pour_amount))
# Pour Jug 2 to Jug 1
pour_amount = min(current.jug2, jug1_capacity - current.jug1)
next_states.append(State(current.jug1 + pour_amount, current.jug2 - pour_amount))
return [state for state in next_states if 0 <= state.jug1 <= jug1_capacity and 0 <= state.jug2 <=
jug2_capacity]
def main():
jug1_capacity =
4
jug2_capacity = 3
target_capacity = 2
initial_state = State(0, 0)
target_state = State(target_capacity, 0)
path = dfs(initial_state, set(), target_state, jug1_capacity, jug2_capacity)
if path:
print("Solution Found:")
for idx, state in enumerate(path):
print(f"Step {idx}: {state}")
else:
print("No solution exists.")
Department of AIML, BrCE: Dr.Rajarajeswarie.B Page 3
ARTIFICIAL INTELLIGENCE LABORATORY MANUAL BAD402
if name == " main
": main()
Output:
Solution Found:
Step 0: (0, 0)
Step 1: (4, 0)
Step 2: (4, 3)
Step 3: (0, 3)
Step 4: (3, 0)
Step 5: (3, 3)
Step 6: (4, 2)
Step 7: (0, 2)
Step 8: (2, 0)
=== Code Execution Successful ===
Inference / Results:
The DFS algorithm explores all possible states recursively and finds a valid sequence of steps
leading to the target amount.
Department of AIML, BrCE: Dr.Rajarajeswarie.B Page 4
ARTIFICIAL INTELLIGENCE LABORATORY MANUAL BAD402
2. To implement and demonstrate the Best-First Search algorithm on
the Missionaries and Cannibals problem in Python.
Objective
To transfer three missionaries and three cannibals across a river using a boat, ensuring that
at no point are the missionaries outnumbered by the cannibals on either side.
Algorithm
1. Initialization : Start with the initial state and define the goal state.
2. Priority Queue : Use a priority queue to manage states, prioritizing those with lower
costs.
3. Cost and Predecessor Tracking: Keep track of the cost (number of steps) to reach each
state and their predecessors.
4. Main Loop : Iterate until the priority queue is empty:
Dequeue the state with the lowest cost.
Check if it's the goal state. If so, end the search.
Generate successors, update costs, and enqueue new
states. Update predecessors for successors.
5. Path Reconstruction : Once the goal state is found, trace back through predecessors to
reconstruct the solution path.
6. Print Solution : Display the solution path.
Program:
from queue import PriorityQueue
class State:
def init (self, lm, lc, boat, rm, rc):
self.lm, self.lc, self.boat, self.rm, self.rc = lm, lc, boat, rm, rc
def is_valid(self):
return all(x >= 0 for x in (self.lm, self.lc, self.rm, self.rc)) and \
(self.lm == 0 or self.lm >= self.lc) and \
(self.rm == 0 or self.rm >= self.rc)
def eq (self, other):
return (self.lm, self.lc, self.boat, self.rm, self.rc) == \
(other.lm, other.lc, other.boat, other.rm, other.rc)
def hash (self):
Department of AIML, BrCE: Dr.Rajarajeswarie.B Page 5
ARTIFICIAL INTELLIGENCE LABORATORY MANUAL BAD402
return hash((self.lm, self.lc, self.boat, self.rm, self.rc))
def lt (self, other):
return self. hash () < other. hash ()
def successors(state):
return [State(state.lm - m * state.boat + m * (1 - state.boat),
state.lc - c * state.boat + c * (1 - state.boat),
1 - state.boat,
state.rm + m * state.boat - m * (1 - state.boat),
state.rc + c * state.boat - c * (1 - state.boat))
for m, c in [(i, j) for i in range(3) for j in range(3) if 1 <= i + j <= 2]]
def best_first_search():
start, goal = State(3, 3, 1, 0, 0), State(0, 0, 0, 3, 3)
frontier, came_from, cost_so_far = PriorityQueue(), {start: None}, {start: 0}
frontier.put((0, start))
while not frontier.empty():
_, current = frontier.get()
if current == goal:
path = []
while current:
path.append(current)
current =
came_from[current] return
path[::-1]
for next_state in successors(current):
new_cost = cost_so_far[current] + 1
if next_state not in cost_so_far or new_cost < cost_so_far[next_state]:
cost_so_far[next_state] = new_cost
frontier.put((new_cost, next_state))
came_from[next_state] = current
return None
def print_solution(path):
if not path:
print("No solution
found.") else:
for i, state in enumerate(path):
print("Step {}: Left {}M {}C | Boat {} | Right {}M {}C".format(
i, state.lm, state.lc, 'left' if state.boat else 'right', state.rm, state.rc))
if name == " main ":
print_solution(best_first_search())
Department of AIML, BrCE: Dr.Rajarajeswarie.B Page 6
ARTIFICIAL INTELLIGENCE LABORATORY MANUAL BAD402
Output:
Step 0: Left 3M 3C | Boat left | Right 0M 0C
Step 1: Left 3M 1C | Boat right | Right 0M 2C
Step 2: Left 4M 1C | Boat left | Right -1M 2C
Step 3: Left 2M 1C | Boat right | Right 1M 2C
Step 4: Left 2M 2C | Boat left | Right 1M 1C
Step 5: Left 1M 1C | Boat right | Right 2M 2C
Step 6: Left 1M 2C | Boat left | Right 2M 1C
Step 7: Left 1M 0C | Boat right | Right 2M 3C
Step 8: Left 1M 1C | Boat left | Right 2M 2C
Step 9: Left 0M 0C | Boat right | Right 3M 3C
=== Code Execution Successful ===
Inference / Results:
The Best-First Search algorithm successfully finds a valid sequence of moves to transport the
missionaries and cannibals across the river without violating any constraints.
Department of AIML, BrCE: Dr.Rajarajeswarie.B Page 7
ARTIFICIAL INTELLIGENCE LABORATORY MANUAL BAD402
3. Implement A* Search algorithm
Algorithm:
1. Initialization:
o The graph is represented using an adjacency list.
o The Graph class is initialized with this adjacency list.
o The get_neighbors method returns the neighbors of a given node.
o The h method defines a heuristic function that estimates the cost from a given node
to the goal. In this case, it's a simple heuristic function that assigns a cost of 1 to each
node.
2. A* Algorithm:
o The A* algorithm starts by initializing:
open_lst: a set to keep track of nodes to be evaluated, starting with the start
node.
closed_lst: a set to keep track of nodes that have been evaluated.
dist: a dictionary to store the cost of getting to a node from the start node.
prenode: a dictionary to store the previous node in the optimal path.
o The main loop continues until there are nodes to be evaluated (open_lst is
not empty).
o Within each iteration of the loop:
The node with the lowest total cost (path cost + heuristic) is selected from
open_lst.
If no such node is found, it means there's no path to the goal, and the
algorithm terminates.
If the selected node is the goal node, the algorithm reconstructs and prints the
path by tracing back from the goal to the start using the prenode dictionary.
Otherwise, the neighbors of the selected node are explored:
If a neighbor is not in open_lst or closed_lst, it's added to open_lst, and its
path cost and previous node are updated.
If a neighbor is in open_lst or closed_lst but the new path to it is shorter
than the previous path, its path cost and previous node are updated accordingly.
The selected node is moved from open_lst to closed_lst.
3. Output
o If the goal is reached, the algorithm prints the shortest path found from the start
node to the stop node.
o If no path is found, it prints "Path does not exist!".
Program:
from collections import deque
class Graph:
def init (self, adjac_lis):
# Initialize the graph with an adjacency list
self.adjac_lis = adjac_lis
def get_neighbors(self, v):
Department of AIML, BrCE: Dr.Rajarajeswarie.B Page 8
ARTIFICIAL INTELLIGENCE LABORATORY MANUAL BAD402
# Helper function to get neighbors of a given node 'v'
return self.adjac_lis[v]
def h(self, n):
# Heuristic function 'h' that estimates the cost from node 'n' to the goal
H = {'A': 1, 'B': 1, 'C': 1, 'D': 1}
return H[n]
def a_star_algorithm(self, start, stop):
# A* search algorithm to find the shortest path from 'start' to 'stop'
# Set to keep track of nodes to be evaluated
open_lst = set([start])
# Set to keep track of nodes that have been evaluated
closed_lst = set([])
# Dictionary to store the cost of getting to a node from the start node
dist = {start: 0}
# Dictionary to store the previous node in the optimal path
prenode = {start: start}
# Main loop
while len(open_lst) > 0:
n = None
# Find the node with the lowest cost + heuristic value
for v in open_lst:
if n is None or dist[v] + self.h(v) < dist[n] + self.h(n):
n=v
# If no path is found
if n is None:
print('Path does not exist!')
return None
# If the goal is reached, reconstruct and print the path
if n == stop:
reconst_path = []
while prenode[n] !=
Department of AIML, BrCE: Dr.Rajarajeswarie.B Page 9
ARTIFICIAL INTELLIGENCE LABORATORY MANUAL BAD402
n:
reconst_path.append(n)
n = prenode[n]
reconst_path.append(start)
reconst_path.reverse()
print('Path found:
{}'.format(reconst_path)) return
reconst_path
# Explore neighbors of the current node
for (m, weight) in self.get_neighbors(n):
if m not in open_lst and m not in
closed_lst: open_lst.add(m)
prenode[m] = n
dist[m] = dist[n] +
weight else:
if dist[m] > dist[n] +
weight: dist[m] = dist[n]
+ weight prenode[m] = n
if m in closed_lst:
closed_lst.remove(m)
open_lst.add(m)
# Move the current node from open to closed list
open_lst.remove(n)
closed_lst.add(n)
# If the loop completes without finding a path
print('Path does not exist!')
return None
# Example adjacency list for the graph
adjac_lis = {
'A': [('B', 1), ('C', 3), ('D', 7)],
'B': [('D', 5)],
'C': [('D', 12)]
}
# Create a graph instance and run A* algorithm
Department of AIML, BrCE: Dr.Rajarajeswarie.B Page
10
ARTIFICIAL INTELLIGENCE LABORATORY MANUAL BAD402
graph1 = Graph(adjac_lis)
graph1.a_star_algorithm('A', 'D')
Output:
Path found: ['A', 'B', 'D']
=== Code Execution Successful ===
Department of AIML, BrCE: Dr.Rajarajeswarie.B Page
11