0% found this document useful (0 votes)
7 views

AI_Lab_Manual[1]

Uploaded by

Shoy Singh
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)
7 views

AI_Lab_Manual[1]

Uploaded by

Shoy Singh
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/ 28

1. Study of PROLOG and Python programming language.

Prolog (Programming in Logic) is a logic programming language used for tasks involving
symbolic reasoning and non-numerical computation. It is particularly suited for artificial
intelligence applications such as expert systems, natural language processing, and rule-based
reasoning.

Facts in Prolog

Definition:
Facts are simple statements that describe relationships between entities or properties of
an entity. Facts are always true.

parent(john, mary).
parent(mary, susan).
parent(mary, tom).
parent(jane, mary).
Meaning:
parent(john, mary): John is a parent of Mary.
parent(mary, susan): Mary is a parent of Susan.
parent(mary, tom): Mary is a parent of Tom.
parent(jane, mary): Jane is a parent of Mary.

Rules in Prolog
Definition:
Rules define new relationships or properties based on existing facts and other rules.
Rules typically have the form:

head :- body.

This means "the head is true if the body is true." The body can consist of multiple
conditions connected by logical operators like , (and).

Rule 1: Grandparent
grandparent(X, Y) :- parent(X, Z), parent(Z, Y).

This rule defines a grandparent relationship:


 X is a grandparent of Y if:
o X is a parent of Z, and
o Z is a parent of Y.
Example Query:
?- grandparent(john, susan).
Execution:

Prolog tries to prove grandparent(john, susan) using the rule:


Check if john is a parent of some Z. (Find Z = mary.)
Check if mary is a parent of susan. (True.)
Output:

Rule 2: Sibling

sibling(X, Y) :- parent(Z, X), parent(Z, Y), X \= Y.

This rule defines a sibling relationship:


X and Y are siblings if:
They share the same parent Z, and
X is not equal to Y.
Example Query:

?- sibling(susan, tom).

Execution:

Prolog checks:
Does susan and tom have a common parent? (Find Z = mary.)
Are susan and tom different? (True.)
Output:

true.

Rule 3: Ancestor

ancestor(X, Y) :- parent(X, Y).


ancestor(X, Y) :- parent(X, Z), ancestor(Z, Y).
This recursive rule defines the ancestor relationship:
Case 1: X is an ancestor of Y if X is a parent of Y.
Case 2: X is an ancestor of Y if X is a parent of some Z, and Z is an ancestor of Y.
Example Query:

?- ancestor(john, tom).

Execution:

Prolog checks:
Case 1: Is john a parent of tom? (No.)
Case 2: Is john a parent of Z and Z an ancestor of tom?
Find Z = mary.
Check if mary is an ancestor of tom. (True: mary is a parent of tom.)
Output:
true.

Queries in Prolog

Queries are questions asked to the Prolog system. Prolog attempts to resolve these
queries by matching them with facts or deducing answers using rules.

Example Queries:
Who are Mary’s children?

?- parent(mary, X).

Prolog searches for all X such that parent(mary, X) is true.


Result: X = susan and X = tom.
Find all ancestors of Tom.

?- ancestor(X, tom).

Prolog uses the recursive ancestor rule to find all X:

X = mary (direct parent of Tom).


X = john (parent of Mary, hence ancestor of Tom).
X = jane (parent of Mary, hence ancestor of Tom).
How Prolog Works
Matching (Unification):

Prolog resolves queries by matching them with facts or the head of rules.
If the head matches, Prolog checks if the body of the rule holds true.
Backtracking:

When a query fails, Prolog backtracks to try alternative solutions. This ensures all
possible answers are explored.

Logical Deduction:

Prolog combines facts and rules to deduce new facts or relationships.

Advantages of Prolog

Declarative Nature: Focuses on what to solve, not how to solve it.


Powerful Inference Engine: Handles logical deductions effectively.
Ideal for AI Applications: Solves problems like natural language processing, expert
systems, and symbolic reasoning.

2. Write simple facts for the statements using PROLOG.


likes(amit, chocolate).
girl(sneha).
likes(rahul, neha).
color(sky, blue).
owns(alok, car).

Who does Amit like?


?- likes(amit, What).
Output:
What = chocolate.

Who likes Neha?


?- likes(Who, neha).
Output:
Who = rahul.

What is the color of the sky?


?- color(sky, What).
Output:
What = blue.

Who owns a car?


?- owns(Who, What).
Output:
Who = alok,
What = car.

3. Write predicates One converts centigrade temperatures to Fahrenheit, the other checks
if a temperature is below freezing.

% Predicate to convert Centigrade to Fahrenheit


centigrade_to_fahrenheit(C, F) :-
F is (C * 9 / 5) + 32.

% Predicate to check if a temperature is below freezing in Centigrade


below_freezing(C) :-

Convert 25∘ C to Fahrenheit:


C < 0.

?- centigrade_to_fahrenheit(25, F).
Output:
F = 77.0.
Check if −5∘C is below freezing:
?- below_freezing(-5).
Output:
true.
Check if 10∘C is below freezing:
?- below_freezing(10).
Output:
false.
Find the Fahrenheit equivalent of −10∘C:
?- centigrade_to_fahrenheit(-10, F).
Output:
F = 14.0.

4. Write a program to solve the Water Jug problem.


from collections import deque

def water_jug_solver(jug1_capacity, jug2_capacity, target):


# Check if the target is achievable
if target > max(jug1_capacity, jug2_capacity):
return "Target is not achievable!"
if target % gcd(jug1_capacity, jug2_capacity) != 0:
return "Target is not achievable!"

# Helper function to find the greatest common divisor


def gcd(a, b):
while b:
a, b = b, a % b
return a

# Initialize BFS
visited = set()
queue = deque([(0, 0)]) # Starting with both jugs empty
path = [ ] # To store the steps taken

while queue:
# Get the current state
jug1, jug2 = queue.popleft()

# If already visited, skip


if (jug1, jug2) in visited:
continue

# Mark as visited
visited.add((jug1, jug2))
path.append((jug1, jug2))

# Check if the target is achieved


if jug1 == target or jug2 == target:
path.append((jug1, jug2))
return path

# Possible operations
next_states = [
(jug1_capacity, jug2), # Fill jug1
(jug1, jug2_capacity), # Fill jug2
(0, jug2), # Empty jug1
(jug1, 0), # Empty jug2
(min(jug1 + jug2, jug1_capacity), max(0, jug2 - (jug1_capacity - jug1))), # Pour
jug2 -> jug1
(max(0, jug1 - (jug2_capacity - jug2)), min(jug1 + jug2, jug2_capacity)) # Pour
jug1 -> jug2
]

# Add valid states to the queue


for state in next_states:
if state not in visited:
queue.append(state)

return "No solution found!"

# Example usage
jug1_capacity = 4
jug2_capacity = 3
target = 2

solution = water_jug_solver(jug1_capacity, jug2_capacity, target)


print("Steps to reach the target:")
print(solution)
Output
Input:
Jug1 capacity: 4
Jug2 capacity: 3
Target: 2
Output:
Steps to reach the target:
[(0, 0), (4, 0), (1, 3), (1, 0), (0, 1), (4, 1), (2, 3)]
5. Write a program to solve the Monkey Banana problem.
class MonkeyBananaProblem:
def __init__(self):
self.state = {
'monkey': 'ground', # The monkey's position
'box': 'ground', # The box's position
'bananas': 'hanging' # The bananas' position
}
def is_goal_state(self):
return self.state['monkey'] == 'above_bananas'

def move_monkey(self):
if self.state['monkey'] == 'ground':
print("Monkey moves to the box.")
self.state['monkey'] = 'box'
elif self.state['monkey'] == 'box':
print("Monkey climbs up to reach the bananas.")
self.state['monkey'] = 'above_bananas'

def move_box(self):
if self.state['box'] == 'ground':
print("Monkey pushes the box under the bananas.")
self.state['box'] = 'under_bananas'

def solve(self):
print("Initial State:", self.state)

# Step 1: Move the box under the bananas


self.move_box()

# Step 2: Move the monkey to the box


self.move_monkey()

# Step 3: Move the monkey to reach the bananas


self.move_monkey()

print("Final State:", self.state)


if self.is_goal_state():
print("The monkey has successfully reached the bananas!")
else:
print("The monkey could not reach the bananas.")

# Create an instance of the problem and solve it


monkey_banana_problem = MonkeyBananaProblem()
monkey_banana_problem.solve()

6. Write a program to solve 8 queens problem

def print_solution(board):

"""Function to print the chessboard solution."""

for row in board:


print(" ".join(row))

print("\n")

def is_safe(board, row, col):

"""Check if a queen can be placed on board[row][col]."""

# Check this row on left side

for i in range(col):

if board[row][i] == 'Q':

return False

# Check upper diagonal on left side

for i, j in zip(range(row, -1, -1), range(col, -1, -1)):

if board[i][j] == 'Q':

return False

# Check lower diagonal on left side

for i, j in zip(range(row, len(board)), range(col, -1, -1)):

if board[i][j] == 'Q':

return False

return True

def solve_n_queens_util(board, col):

"""Utilize backtracking to solve the N-Queens problem."""

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

if col >= len(board):

print_solution(board)

return True

# Consider this column and try placing this queen in all rows one by one
for i in range(len(board)):

if is_safe(board, i, col):

# Place this queen on board[i][col]

board[i][col] = 'Q'

# Recur to place the rest of the queens

if solve_n_queens_util(board, col + 1):

return True

# If placing queen in board[i][col] doesn't lead to a solution,

# then remove queen from board[i][col]

board[i][col] = '.' # Backtrack

return False

def solve_n_queens(n):

"""Main function to solve the N-Queens problem."""

board = [['.' for _ in range(n)] for _ in range(n)] # Create an n x n chessboard

if not solve_n_queens_util(board, 0):

print("Solution does not exist")

return False

return True

# Solve the 8 Queens problem

solve_n_queens(8)

7. Write a program to solve depth first search problem.

class Graph:

def __init__(self):

self.graph = {} # Dictionary to store the graph


def add_edge(self, u, v):

"""Add an edge to the graph."""

if u not in self.graph:

8. Write a program to solve best first search problem.

import heapq

class Node:

def __init__(self, name, cost=0, heuristic=0):

self.name = name

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

self.heuristic = heuristic # Estimated cost to goal

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

def __lt__(self, other):

return self.total_cost < other.total_cost # For priority queue

class Graph:

def __init__(self):

self.edges = {} # Dictionary to store graph edges

def add_edge(self, u, v, cost):

"""Add an edge with a cost to the graph."""

if u not in self.edges:

self.edges[u] = []

self.edges[u].append((v, cost))
def best_first_search(self, start, goal, heuristic):

"""Perform Best First Search (A* algorithm)."""

open_set = [] # Priority queue for nodes to explore

closed_set = set() # Set of explored nodes

# Initialize the start node

start_node = Node(start, 0, heuristic[start])

heapq.heappush(open_set, start_node)

while open_set:

# Get the node with the lowest total cost

current_node = heapq.heappop(open_set)

# If we reached the goal, return the result

if current_node.name == goal:

print(f"Goal {goal} reached with cost: {current_node.cost}")

return

closed_set.add(current_node.name)

# Explore neighbors

for neighbor, cost in self.edges.get(current_node.name, []):

if neighbor in closed_set:

continue # Skip already explored nodes

# Calculate the cost and heuristic for the neighbor

total_cost = current_node.cost + cost


neighbor_node = Node(neighbor, total_cost, heuristic[neighbor])

# Add the neighbor to the open set

heapq.heappush(open_set, neighbor_node)

print("Goal not reachable.")

# Example usage

if __name__ == "__main__":

# Create a graph

graph = Graph()

graph.add_edge('A', 'B', 1)

graph.add_edge('A', 'C', 4)

graph.add_edge('B', 'D', 2)

graph.add_edge('C', 'D', 5)

graph.add_edge('B', 'E', 3)

graph.add_edge('E', 'D', 1)

# Define heuristic values (estimated cost to reach the goal)

heuristic = {

'A': 7,

'B': 6,

'C': 2,

'D': 0,

'E': 1

}
# Perform Best First Search

graph.best_first_search('A', 'D', heuristic)

9. Write a program to solve 8-Puzzle problem.

import heapq

class PuzzleState:

def __init__(self, board, zero_position, moves=0):

self.board = board

self.zero_position = zero_position # (row, col) of the empty tile

self.moves = moves # Number of moves taken to reach this state

self.size = len(board)

self.goal = self.create_goal_state()

self.heuristic = self.calculate_heuristic()

def create_goal_state(self):

"""Create the goal state for the puzzle."""

goal = []

for i in range(self.size):

row = []

for j in range(self.size):

if i == self.size - 1 and j == self.size - 1:

row.append(0) # The empty tile

else:

row.append(i * self.size + j + 1)

goal.append(row)

return goal
def calculate_heuristic(self):

"""Calculate the Manhattan distance heuristic."""

distance = 0

for i in range(self.size):

for j in range(self.size):

if self.board[i][j] != 0: # Skip the empty tile

target = self.board[i][j] - 1

target_row = target // self.size

target_col = target % self.size

distance += abs(i - target_row) + abs(j - target_col)

return distance

def get_neighbors(self):

"""Generate all possible states from the current state."""

neighbors = []

row, col = self.zero_position

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

for dr, dc in directions:

new_row, new_col = row + dr, col + dc

if 0 <= new_row < self.size and 0 <= new_col < self.size:

# Create a new board configuration

new_board = [list(row) for row in self.board] # Deep copy

new_board[row][col], new_board[new_row][new_col] = new_board[new_row]


[new_col], new_board[row][col]

neighbors.append((new_board, (new_row, new_col)))

return neighbors
def __lt__(self, other):

"""For priority queue comparison."""

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

def a_star_search(initial_board):

"""Perform A* search to solve the 8-puzzle problem."""

initial_zero_position = next((i, j) for i in range(len(initial_board))

for j in range(len(initial_board)) if initial_board[i][j] == 0)

initial_state = PuzzleState(initial_board, initial_zero_position)

open_set = []

heapq.heappush(open_set, initial_state)

closed_set = set()

while open_set:

current_state = heapq.heappop(open_set)

# Check if we reached the goal

if current_state.board == current_state.goal:

print(f"Solution found in {current_state.moves} moves!")

return

closed_set.add(tuple(map(tuple, current_state.board))) # Add to closed set

for neighbor_board, new_zero_position in current_state.get_neighbors():

neighbor_state = PuzzleState(neighbor_board, new_zero_position, current_state.moves +


1)
if tuple(map(tuple, neighbor_board)) in closed_set:

continue # Skip already explored states

heapq.heappush(open_set, neighbor_state)

print("No solution found.")

# Example usage

if __name__ == "__main__":

initial_board = [

[1, 2, 3],

[4, 0, 5],

[7, 8, 6]

a_star_search(initial_board)

10. Write a Program to Implement Tic-Tac-Toe game.

class TicTacToe:

def __init__(self):

self.board = [' ' for _ in range(9)] # A list to hold the board state

self.current_player = 'X' # Starting player

def display_board(self):

"""Display the current state of the board."""

print(f"{self.board[0]} | {self.board[1]} | {self.board[2]}")

print("--+---+--")

print(f"{self.board[3]} | {self.board[4]} | {self.board[5]}")


print("--+---+--")

print(f"{self.board[6]} | {self.board[7]} | {self.board[8]}")

print()

def make_move(self, position):

"""Place the current player's mark on the board."""

if self.board[position] == ' ':

self.board[position] = self.current_player

return True

return False

def check_winner(self):

"""Check if there is a winner."""

win_conditions = [

[0, 1, 2], [3, 4, 5], [6, 7, 8], # Horizontal

[0, 3, 6], [1, 4, 7], [2, 5, 8], # Vertical

[0, 4, 8], [2, 4, 6] # Diagonal

for condition in win_conditions:

if self.board[condition[0]] == self.board[condition[1]] == self.board[condition[2]] != ' ':

return self.board[condition[0]]

return None

def is_draw(self):

"""Check if the game is a draw."""

return ' ' not in self.board


def switch_player(self):

"""Switch the current player."""

self.current_player = 'O' if self.current_player == 'X' else 'X'

def play_game(self):

"""Main game loop."""

while True:

self.display_board()

try:

move = int(input(f"Player {self.current_player}, enter your move (1-9): ")) - 1

if move < 0 or move > 8:

print("Invalid input. Please enter a number between 1 and 9.")

continue

if not self.make_move(move):

print("Invalid move. The position is already taken.")

continue

except ValueError:

print("Invalid input. Please enter a number between 1 and 9.")

continue

winner = self.check_winner()

if winner:

self.display_board()

print(f"Player {winner} wins!")

break

if self.is_draw():
self.display_board()

print("It's a draw!")

break

self.switch_player()

if __name__ == "__main__":

game = TicTacToe()

game.play_game()

11. Write a Program to find the solution for travelling salesman Problem.

import itertools

def calculate_distance(route, distance_matrix):

"""Calculate the total distance of the given route based on the distance matrix."""

total_distance = 0

for i in range(len(route)):

total_distance += distance_matrix[route[i]][route[(i + 1) % len(route)]]

return total_distance

def traveling_salesman(distance_matrix):

"""Find the shortest route for the Traveling Salesman Problem."""

n = len(distance_matrix)

cities = list(range(n)) # List of cities (0, 1, 2, ..., n-1)

min_distance = float('inf')

best_route = None
# Generate all possible routes (permutations of cities)

for route in itertools.permutations(cities):

current_distance = calculate_distance(route, distance_matrix)

if current_distance < min_distance:

min_distance = current_distance

best_route = route

return best_route, min_distance

if __name__ == "__main__":

# Example distance matrix (symmetric)

distance_matrix = [

[0, 10, 15, 20],

[10, 0, 35, 25],

[15, 35, 0, 30],

[20, 25, 30, 0]

best_route, min_distance = traveling_salesman(distance_matrix)

print("Best route:", best_route)

print("Minimum distance:", min_distance)

12. Write a program to implement Hill Climbing Algorithm.

import random

def function(x):

"""The function we want to maximize."""

return -x**2 + 4*x


def hill_climbing(start, step_size, max_iterations):

"""Hill Climbing Algorithm to find the maximum value of the function."""

current_position = start

current_value = function(current_position)

for _ in range(max_iterations):

# Generate neighboring positions

neighbors = [current_position + step_size, current_position - step_size]

# Evaluate the function at the neighbors

neighbor_values = [function(neighbor) for neighbor in neighbors if 0 <= neighbor <= 4]

# Find the best neighbor

if neighbor_values:

best_neighbor_value = max(neighbor_values)

best_neighbor_position = neighbors[neighbor_values.index(best_neighbor_value)]

# If the best neighbor is better than the current position, move to that neighbor

if best_neighbor_value > current_value:

current_position = best_neighbor_position

current_value = best_neighbor_value

else:

break # No better neighbors, stop climbing

else:

break # No valid neighbors, stop climbing


return current_position, current_value

if __name__ == "__main__":

start_position = random.uniform(0, 4) # Random starting position between 0 and 4

step_size = 0.1 # Step size for climbing

max_iterations = 100 # Maximum number of iterations

best_position, best_value = hill_climbing(start_position, step_size, max_iterations)

print(f"Best position: {best_position:.2f}, Best value: {best_value:.2f}")

13. Write a program to implement A* Algorithm.

import heapq

class Node:

def __init__(self, position, parent=None):

self.position = position # (x, y)

self.parent = parent # Parent Node

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

self.h = 0 # Heuristic cost to goal

self.f = 0 # Total cost

def __lt__(self, other):

return self.f < other.f # For priority queue

def heuristic(a, b):

"""Calculate the Manhattan distance heuristic."""

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


def a_star(grid, start, goal):

"""A* algorithm to find the shortest path from start to goal."""

open_list = []

closed_list = set()

start_node = Node(start)

goal_node = Node(goal)

heapq.heappush(open_list, start_node)

while open_list:

current_node = heapq.heappop(open_list)

closed_list.add(current_node.position)

# Check if we reached the goal

if current_node.position == goal_node.position:

path = []

while current_node:

path.append(current_node.position)

current_node = current_node.parent

return path[::-1] # Return reversed path

# Generate children (neighbors)

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

for new_position in neighbors:

node_position = (current_node.position[0] + new_position[0], current_node.position[1] +


new_position[1])
# Check if within bounds

if node_position[0] < 0 or node_position[0] >= len(grid) or node_position[1] < 0 or


node_position[1] >= len(grid[0]):

continue

# Check if walkable

if grid[node_position[0]][node_position[1]] != 0:

continue

# Create a new node

child_node = Node(node_position, current_node)

# Skip if already in closed list

if child_node.position in closed_list:

continue

# Calculate costs

child_node.g = current_node.g + 1

child_node.h = heuristic(child_node.position, goal_node.position)

child_node.f = child_node.g + child_node.h

# Check if child is already in open list

if any(open_node.position == child_node.position and open_node.g <= child_node.g for


open_node in open_list):

continue

# Add child to open list


heapq.heappush(open_list, child_node)

return None # No path found

if __name__ == "__main__":

# Define the grid (0 = walkable, 1 = obstacle)

grid = [

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

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

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

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

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

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

start = (0, 0) # Starting position

goal = (5, 5) # Goal position

path = a_star(grid, start, goal)

if path:

print("Path found:", path)

else:

print("No path found.")

14. Write a Program to Implement Tower of Hanoi.

def tower_of_hanoi(n, source, target, auxiliary):

"""Solve the Tower of Hanoi problem."""


if n == 1:

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

return

tower_of_hanoi(n - 1, source, auxiliary, target) # Move n-1 disks from source to auxiliary

print(f"Move disk {n} from {source} to {target}") # Move the nth disk from source to target

tower_of_hanoi(n - 1, auxiliary, target, source) # Move n-1 disks from auxiliary to target

if __name__ == "__main__":

num_disks = 3 # You can change this value to test with different numbers of disks

print(f"Solving Tower of Hanoi with {num_disks} disks:")

tower_of_hanoi(num_disks, 'A', 'C', 'B') # A, B, C are the names of the pegs

15. Write a Program to Implement N-Queens Problem.

def print_solution(board):

"""Helper function to print the chessboard solution."""

for row in board:

print(" ".join(row))

print()

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

"""Check if it's safe to place a queen at board[row][col]."""

# Check this row on the left side

for i in range(col):

if board[row][i] == 'Q':

return False

# Check upper diagonal on the left side

for i, j in zip(range(row, -1, -1), range(col, -1, -1)):


if board[i][j] == 'Q':

return False

# Check lower diagonal on the left side

for i, j in zip(range(row, N), range(col, -1, -1)):

if board[i][j] == 'Q':

return False

return True

def solve_n_queens_util(board, col, N):

"""Utilize backtracking to solve the N-Queens problem."""

# Base case: If all queens are placed

if col >= N:

print_solution(board)

return True

res = False

for i in range(N):

if is_safe(board, i, col, N):

board[i][col] = 'Q' # Place queen

# Recur to place the rest of the queens

res = solve_n_queens_util(board, col + 1, N) or res

# Backtrack: Remove queen

board[i][col] = '.' # Remove queen


return res

def solve_n_queens(N):

"""Main function to solve the N-Queens problem."""

board = [['.' for _ in range(N)] for _ in range(N)] # Create an N x N chessboard

if not solve_n_queens_util(board, 0, N):

print("No solution exists")

if __name__ == "__main__":

N = 4 # You can change this value to test with different sizes of the board

print(f"Solutions for {N}-Queens problem:")

solve_n_queens(N)

You might also like