0% found this document useful (0 votes)
26 views19 pages

Ai Lab

Uploaded by

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

Ai Lab

Uploaded by

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

CORE PRACTICAL IV

Semester IV ARTIFICIAL INTELLIGENCE LAB

COURSE OBJECTIVES:

 To impart knowledge about the practical aspects in Artificial Intelligence


 related problems To program different AI methods using a programming language
 To know how the logical operations and reason based AI problems are used using
programming

1. Write a program to implement the Hill Climbing problem

2. Write a program to implement the Towers of Hanoi problem

3. Write a program to implement the Missionaries and Cannibals problem

4. Write a program to implement the 8 queens problem

5. Write a program to implement the A* Algorithm

6. Write a program to Implement the Breadth first algorithm

7. Write a program to implement the Depth first algorithm

8. Write a program to implement the predicate logic

COURSE OUTCOMES:

Upon successful completion of this course the students would be able:

• Solve various kinds of problems using AI techniques.

• Solve basic AI based problems using any programming language.

• Understand to implement the various kinds of AI based algorithms.

• Apply AI techniques to real-world problems to develop intelligent systems.

• To understand problems related to AI.


*****

1. Write a program to implement the Hill Climbing problem

import random

def objective_function(x):

return -(x**2 - 4*x + 4) # Example: f(x) = -(x^2 - 4x + 4)

def hill_climbing():

current_solution = random.uniform(-10, 10) # Random initial guess

current_value = objective_function(current_solution)

while True:

neighbors = [current_solution + 0.1, current_solution - 0.1] # Generate neighbors

next_solution = max(neighbors, key=lambda x: objective_function(x)) # Choose best


neighbor

next_value = objective_function(next_solution)

if next_value <= current_value: # If no improvement, stop

break

current_solution, current_value = next_solution, next_value

return current_solution, current_value

best_solution, best_value = hill_climbing()


print(f"Best Solution: {best_solution}, Value: {best_value}")

Output:

Best Solution: 1.9513126518605843, Value: -0.0023704578688485967

2. Write a program to implement the Towers of Hanoi problem

def towers_of_hanoi(n, source, auxiliary, destination):

# Base case: If only one disk, move it directly from source to destination

if n == 1:

print(f"Move disk 1 from {source} to {destination}")

return

# Move n-1 disks from source to auxiliary, so they are out of the way

towers_of_hanoi(n - 1, source, destination, auxiliary)

# Move the nth disk from source to destination

print(f"Move disk {n} from {source} to {destination}")

# Move the n-1 disks from auxiliary to destination

towers_of_hanoi(n - 1, auxiliary, source, destination)

# Number of disks

n = 3 # Change this value to solve for different numbers of disks


# Call the function with source peg 'A', auxiliary peg 'B', and destination peg 'C'

towers_of_hanoi(n, 'A', 'B', 'C')

Output:

Move disk 1 from A to C

Move disk 2 from A to B

Move disk 1 from C to B

Move disk 3 from A to C

Move disk 1 from B to A

Move disk 2 from B to C

Move disk 1 from A to C

3. Write a program to implement the Missionaries and Cannibals


problem

def is_valid(m_left, c_left, m_right, c_right):

# At no point, cannibals should outnumber missionaries on either side

if (m_left > 0 and m_left < c_left) or (m_right > 0 and m_right < c_right):

return False

if m_left < 0 or c_left < 0 or m_right < 0 or c_right < 0:

return False

if m_left > 3 or c_left > 3 or m_right > 3 or c_right > 3:


return False

return True

def print_state(m_left, c_left, m_right, c_right, boat):

print(f"Left side: {m_left} missionaries, {c_left} cannibals | Right side: {m_right} missionaries,
{c_right} cannibals | Boat: {boat}")

def move(m_left, c_left, m_right, c_right, boat, moves):

if m_left == 0 and c_left == 0:

# Base case: All missionaries and cannibals have been moved to the right side

print("\nSolution found!")

for move in moves:

print(move)

return True

if boat == 'left':

# Try all valid moves from the left side to the right side

for m in range(0, 3):

for c in range(0, 3):

if m + c >= 1 and m + c <= 2: # Boat can carry at most 2 people

new_m_left = m_left - m

new_c_left = c_left - c

new_m_right = m_right + m

new_c_right = c_right + c

if is_valid(new_m_left, new_c_left, new_m_right, new_c_right):

# Make the move

moves.append(f"Move {m} missionaries and {c} cannibals from left to right")

if move(new_m_left, new_c_left, new_m_right, new_c_right, 'right', moves):


return True

# Backtrack

moves.pop()

else:

# Try all valid moves from the right side to the left side

for m in range(0, 3):

for c in range(0, 3):

if m + c >= 1 and m + c <= 2: # Boat can carry at most 2 people

new_m_left = m_left + m

new_c_left = c_left + c

new_m_right = m_right - m

new_c_right = c_right - c

if is_valid(new_m_left, new_c_left, new_m_right, new_c_right):

# Make the move

moves.append(f"Move {m} missionaries and {c} cannibals from right to left")

if move(new_m_left, new_c_left, new_m_right, new_c_right, 'left', moves):

return True

# Backtrack

moves.pop()

return False

def missionaries_and_cannibals():

m_left, c_left = 3, 3 # 3 missionaries and 3 cannibals on the left side

m_right, c_right = 0, 0 # None on the right side

boat = 'left' # The boat starts on the left side


moves = [] # List to record the moves

# Start the recursive search for a solution

print_state(m_left, c_left, m_right, c_right, boat)

if not move(m_left, c_left, m_right, c_right, boat, moves):

print("No solution found")

# Run the problem

missionaries_and_cannibals()

Output:

Left side: 3 missionaries, 3 cannibals | Right side: 0 missionaries, 0 cannibals | Boat: left

Move 1 missionaries and 1 cannibals from left to right

Left side: 2 missionaries, 2 cannibals | Right side: 1 missionaries, 1 cannibals | Boat: right

Move 2 missionaries and 0 cannibals from right to left

Left side: 4 missionaries, 2 cannibals | Right side: 1 missionaries, 1 cannibals | Boat: left

Move and

4. Write a program to implement the 8 queens problem


# Function to check if the current position is safe for placing a queen

def is_safe(board, row, col, n):

# Check the column

for i in range(row):

if board[i] == col or \

board[i] - i == col - row or \

board[i] + i == col + row:

return False
return True

# Function to solve the 8 queens problem using backtracking

def solve_n_queens(board, row, n):

if row == n:

# All queens are placed successfully, print the board configuration

print_board(board, n)

return True

res = False

for col in range(n):

if is_safe(board, row, col, n):

# Place the queen on the board

board[row] = col

# Recur to place queens in the next rows

res = solve_n_queens(board, row + 1, n) or res

# Backtrack (not needed explicitly, as we overwrite the board[row])

return res

# Function to print the board

def print_board(board, n):

for i in range(n):

row = ['Q' if j == board[i] else '.' for j in range(n)]

print(' '.join(row))

print("\n")

# Main function to solve the 8 queens problem

def eight_queens(n=8):
# Initialize the board with -1 (meaning no queen is placed)

board = [-1] * n

if not solve_n_queens(board, 0, n):

print("No solution found.")

# Run the solution for 8 queens

eight_queens()

Output:

Q.......

....Q...

......Q.

.Q......

...Q....

.....Q..

..Q.....

.......Q

5. Write a program to implement the A* Algorithm

import heapq

# Define the 4 possible movements (up, down, left, right)

MOVES = [(-1, 0), (1, 0), (0, -1), (0, 1)] # Up, Down, Left, Right

class Node:

def __init__(self, position, g, h):

self.position = position # Position in the grid (x, y)


self.g = g # Cost from start to this node

self.h = h # Heuristic estimate of cost to goal

self.f = g + h # Total cost (f = g + h)

self.parent = None # Parent node (used for path reconstruction)

def __lt__(self, other):

return self.f < other.f # For comparison in the priority queue (min-heap)

# Heuristic function (Manhattan Distance)

def heuristic(a, b):

return abs(a[0] - b[0]) + abs(a[1] - b[1])

# A* algorithm to find the shortest path from start to goal

def astar(start, goal, grid):

open_list = [] # The priority queue (min-heap)

closed_list = set() # Set to track visited nodes

# Start node with g=0 and h as the heuristic from start to goal

start_node = Node(start, 0, heuristic(start, goal))

heapq.heappush(open_list, start_node) # Push the start node to the open list

while open_list:

# Get the node with the lowest f-value

current_node = heapq.heappop(open_list)

if current_node.position == goal:

# Goal reached, reconstruct the path

path = []

while current_node:

path.append(current_node.position)
current_node = current_node.parent

return path[::-1] # Return reversed path (start to goal)

closed_list.add(current_node.position) # Add current node to closed list

# Explore neighbors

for move in MOVES:

neighbor_pos = (current_node.position[0] + move[0], current_node.position[1] +


move[1])

# Skip out-of-bounds neighbors or blocked cells

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

if neighbor_pos in closed_list:

continue

# Calculate g, h, and f values for the neighbor

g = current_node.g + 1 # Assume cost between neighbors is always 1

h = heuristic(neighbor_pos, goal)

neighbor_node = Node(neighbor_pos, g, h)

# If the neighbor is not in the open list, or has a lower f-value, add it to the open
list

if not any(neighbor_node.position == node.position and neighbor_node.f >= node.f for


node in open_list):

neighbor_node.parent = current_node

heapq.heappush(open_list, neighbor_node)

return None # If no path is found

# Grid representation (0 = free space, 1 = blocked cell)


grid = [

[0, 0, 0, 0, 0, 0],

[0, 1, 0, 1, 0, 0],

[0, 1, 0, 1, 0, 0],

[0, 0, 0, 0, 1, 0],

[0, 1, 1, 1, 1, 0],

[0, 0, 0, 0, 0, 0]

# Define start and goal positions

start = (0, 0) # Start at top-left corner

goal = (5, 5) # Goal at bottom-right corner

# Run A* algorithm

path = astar(start, goal, grid)

if path:

print("Path found:")

print(path)

else:

print("No path found.")

Output:

Path found:
[(0, 0), (1, 0), (2, 0), (3, 0), (4, 0), (5, 0), (5, 1), (5, 2), (5, 3), (5, 4), (5, 5)]

6. Write a program to Implement the Breadth first algorithm

from collections import deque

# Function to perform BFS on a graph

def bfs(graph, start):

# Create a set to keep track of visited nodes

visited = set()

# Create a queue for BFS and enqueue the start node

queue = deque([start])

# Mark the start node as visited

visited.add(start)

# List to store the BFS traversal order

bfs_order = []

while queue:

# Dequeue a vertex from the queue

node = queue.popleft()

# Process the node (in this case, print it)

bfs_order.append(node)

# Get all the neighbors of the current node

for neighbor in graph[node]:

if neighbor not in visited:


# If the neighbor has not been visited, enqueue it and mark it as visited

queue.append(neighbor)

visited.add(neighbor)

return bfs_order

# Example graph represented as an adjacency list

graph = {

0: [1, 2],

1: [0, 3, 4],

2: [0, 4],

3: [1],

4: [1, 2]

# Starting node for BFS

start_node = 0

# Perform BFS and print the result

bfs_traversal = bfs(graph, start_node)

print("BFS Traversal Order:", bfs_traversal)

Output:

Graph:

0 -- 1 -- 3

| |

2 -- 4
Start node: 0

BFS Traversal Order: [0, 1, 2, 3, 4]

7. Write a program to implement the Depth first algorithm


# Iterative Depth First Search (DFS) using stack

def dfs_iterative(graph, start):

visited = set() # Set to keep track of visited nodes

stack = [start] # Stack to store nodes to be explored

# List to store the DFS traversal order

dfs_order = []

while stack:

node = stack.pop() # Pop a node from the stack

if node not in visited:

visited.add(node) # Mark the node as visited

dfs_order.append(node) # Process the node (in this case, append to dfs_order)

# Add all unvisited neighbors to the stack

for neighbor in graph[node]:

if neighbor not in visited:

stack.append(neighbor)

return dfs_order

# Example graph represented as an adjacency list

graph = {

0: [1, 2],
1: [0, 3, 4],

2: [0, 4],

3: [1],

4: [1, 2]

# Starting node for DFS

start_node = 0

# Perform DFS (iterative)

dfs_traversal = dfs_iterative(graph, start_node)

print("DFS Traversal (Iterative):", dfs_traversal)

# Recursive Depth First Search (DFS)

def dfs_recursive(graph, node, visited=None, dfs_order=None):

if visited is None:

visited = set() # Set to keep track of visited nodes

if dfs_order is None:

dfs_order = [] # List to store the DFS traversal order

# Mark the node as visited and process it

visited.add(node)

dfs_order.append(node)

# Recur for all the unvisited neighbors

for neighbor in graph[node]:

if neighbor not in visited:

dfs_recursive(graph, neighbor, visited, dfs_order)

return dfs_order
# Perform DFS (recursive)

dfs_traversal_recursive = dfs_recursive(graph, start_node)

print("DFS Traversal (Recursive):", dfs_traversal_recursive)

Output:

Graph:

0 -- 1 -- 3

| |

2 -- 4

Start node: 0

DFS Traversal (Iterative): [0, 2, 4, 1, 3]

DFS Traversal (Recursive): [0, 1, 3, 4, 2]

8. Write a program to implement the predicate logic

# Define some facts (base predicates)

def is_sibling(x, y):

"""Predicate: x and y are siblings"""

siblings = {

("Alice", "Bob"),

("Bob", "Alice"),

("Charlie", "David"),

("David", "Charlie")
}

return (x, y) in siblings or (y, x) in siblings

def is_parent(x, y):

"""Predicate: x is a parent of y"""

parents = {

("Alice", "Charlie"),

("Alice", "David"),

("Bob", "Charlie"),

("Bob", "David")

return (x, y) in parents

def is_grandparent(x, y):

"""Predicate: x is a grandparent of y (if x is a parent of some z, and z is a parent of y)"""

# Check if x is a parent of someone who is a parent of y

for z in ["Alice", "Bob"]:

if is_parent(x, z) and is_parent(z, y):

return True

return False

# Query predicates

def main():

print("Is Alice a sibling of Bob?", is_sibling("Alice", "Bob"))


print("Is Alice a parent of Charlie?", is_parent("Alice", "Charlie"))

print("Is Alice a grandparent of Charlie?", is_grandparent("Alice", "Charlie"))

print("Is Alice a grandparent of David?", is_grandparent("Alice", "David"))

if __name__ == "__main__":

main()

Output

Is Alice a sibling of Bob? True

Is Alice a parent of Charlie? True

Is Alice a grandparent of Charlie? False

Is Alice a grandparent of David? False

You might also like