0% found this document useful (0 votes)
23 views20 pages

Neha AI

Uploaded by

deepakneeta22545
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)
23 views20 pages

Neha AI

Uploaded by

deepakneeta22545
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/ 20

T.Y.BSc.

IT Artificial Intelligence and Application I22044


PRACTICAL NO. 1

a) Implement depth first search algorithm.

Input:

graph1 = {
'A': ['B', 'C'],
'B': ['D', 'E'],
'C': ['F'],
'D': [],
'E': ['F'],
'F':[]
}
visited=set()
def dfs(graph, node, visited):
if node not in visited:
visited.append(node)
for n in graph[node]:
dfs(graph,n, visited)
return visited

visited = dfs(graph1,'A', [ ])
print(visited)

Output:

b) Implement breadth first search algorithm.

Input:

graph = {
'5' : ['3','7'],
'3' : ['2', '4'],
'7' : ['8'],
'2' : [],
'4' : ['8'],
'8' : []
}

visited = [] # List for visited nodes.


queue = [] #Initialize a queue

def bfs(visited, graph, node):


visited.append(node)
queue.append(node)

while queue:
m = queue.pop(0)
for neighbour in graph[m]:
T.Y.BSc.IT Artificial Intelligence and Application I22044
if neighbour not in visited:
visited.append(neighbour)
queue.append(neighbour)

bfs(visited, graph, '5')


print(visited)

Output:
T.Y.BSc.IT Artificial Intelligence and Application I22044
PRACTICAL NO.2

a) Solve tower of hanoi problem.

Input:

def TowerOfHanoi(n , src, dest, aux):


if n==1:
print ("Move disk 1 from source",src,"to destination",dest)
return
TowerOfHanoi(n-1, src, aux, dest)
print ("Move disk",n,"from source",src,"to destination",dest)
TowerOfHanoi(n-1, aux, dest, src)

disks = int(input('Enter the number of disks: '))


TowerOfHanoi(disks, 'A', 'B', 'C') # Calling the function

Output:

b) Simulate 4-Queen / N-Queen problem.

Input:
#Number of queens
print ("Enter the number of queens")
N = int(input())

#chessboard
#NxN matrix with all elements 0
board = [[0]*N for _ in range(N)]

def is_attack(i, j):


#checking if there is a queen in row or column
for k in range(0,N):
if board[i][k]==1 or board[k][j]==1:
return True
#checking diagonals
for k in range(0,N):
for l in range(0,N):
if (k+l==i+j) or (k-l==i-j):
if board[k][l]==1:
return True
return False

def N_queen(n):
if n==0:
return True
for i in range(0,N):
T.Y.BSc.IT Artificial Intelligence and Application I22044
for j in range(0,N):
'''checking if we can place a queen here or not
queen will not be placed if the place is being attacked
or already occupied'''
if (not(is_attack(i,j))) and (board[i][j]!=1):
board[i][j] = 1
#recursion
#wether we can put the next queen with this arrangment or not
if N_queen(n-1)==True:
return True
board[i][j] = 0
return False
N_queen(N)
for i in board:
print (i)
Output:
T.Y.BSc.IT Artificial Intelligence and Application I22044
PRACTICAL NO.5

a) Shuffle deck of cards.

Input:

import itertools, random


deck = list(itertools.product(range(1,14),['Spade','Heart','Diamond','Club']))
random.shuffle(deck)
# draw five cards
print("You got:")
for i in range(5):
print(deck[i][0], "of", deck[i][1])

Output:
T.Y.BSc.IT Artificial Intelligence and Application I22044
PRACTICAL NO.3

a) Implement alpha beta search.

Input:
import math

# Function to perform alpha-beta pruning


def alpha_beta_search(depth, node_index, maximizing_player, values, alpha, beta):
# Base case: if we have reached a leaf node
if depth == 3:
return values[node_index]

if maximizing_player:
max_eval = -math.inf
# Evaluate the children of the current node
for i in range(2): # assuming binary tree
eval = alpha_beta_search(depth + 1, node_index * 2 + i, False, values, alpha, beta)
max_eval = max(max_eval, eval)
alpha = max(alpha, eval)
if beta <= alpha:
break # Beta cut-off
return max_eval
else:
min_eval = math.inf
# Evaluate the children of the current node
for i in range(2): # assuming binary tree
eval = alpha_beta_search(depth + 1, node_index * 2 + i, True, values, alpha, beta)
min_eval = min(min_eval, eval)
beta = min(beta, eval)
if beta <= alpha:
break # Alpha cut-off
return min_eval

# Example values at the leaf nodes of the tree (depth = 3)


values = [3, 5, 6, 9, 1, 2, 0, -1]

# Initial values for alpha and beta


alpha = -math.inf
beta = math.inf

# Start alpha-beta pruning


result = alpha_beta_search(0, 0, True, values, alpha, beta)
print("The optimal value is:", result)

Output:
T.Y.BSc.IT Artificial Intelligence and Application I22044

b) Implement hill climbing problem.

Input:
import random

def objective_function(solution):
return sum(solution)

def generate_neighbor(current_solution):
neighbor = current_solution[:]
index = random.randint(0, len(neighbor) - 1)
neighbor[index] = 1 - neighbor[index] # Flip the value at the selected index
return neighbor

def hill_climbing():
# Initialization
current_solution = [random.randint(0, 1) for _ in range(10)] # Generate an initial solution
current_fitness = objective_function(current_solution)

# Iterative process
while True:
# Neighbor generation
neighbor = generate_neighbor(current_solution)
neighbor_fitness = objective_function(neighbor)

# Comparison
if neighbor_fitness >= current_fitness:
current_solution = neighbor
current_fitness = neighbor_fitness
else:
break # Terminate if no better solution is found

return current_solution, current_fitness

# Usage example
best_solution, best_fitness = hill_climbing()
print("Best Solution:", best_solution)
print("Best Fitness:", best_fitness)
Output:
T.Y.BSc.IT Artificial Intelligence and Application I22044
PRACTICAL NO.4

a) Implement A* algorithm.

Input:
import heapq

# Class for representing nodes in the search space


class Node:
def init (self, position, parent=None):
self.position = position
self.parent = parent
self.g = 0
self.h = 0
self.f = 0
def eq (self, other):
return self.position == other.position

def lt (self, other):


return self.f < other.f

# A* algorithm
def astar(start, end, grid):
# Initialize the start and end nodes
start_node = Node(start)
end_node = Node(end)

# Open list (priority queue) and closed list


open_list = []
closed_list = set()

# Add the start node to the open list


heapq.heappush(open_list, start_node)

# Loop until we find the goal or exhaust the search space


while open_list:
# Get the current node with the lowest f score
current_node = heapq.heappop(open_list)
closed_list.add(current_node.position)

# If we reach the goal, reconstruct the path


if current_node == end_node:
return reconstruct_path(current_node)

# Generate neighbors (up, down, left, right)


neighbors = get_neighbors(current_node, grid)

for neighbor_position in neighbors:


# Skip if the neighbor is in the closed list (already visited)
if neighbor_position in closed_list:
continue
T.Y.BSc.IT Artificial Intelligence and Application I22044
# Create a new node for the neighbor
neighbor_node = Node(neighbor_position, current_node)

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


neighbor_node.g = current_node.g + 1 # Assuming uniform cost of 1 for grid
neighbor_node.h = heuristic(neighbor_node.position, end_node.position)
neighbor_node.f = neighbor_node.g + neighbor_node.h

# If the neighbor is already in the open list with a lower f score, skip it
if add_to_open_list(open_list, neighbor_node):
heapq.heappush(open_list, neighbor_node)

return None # No path found

# Heuristic function (Manhattan distance for grid)


def heuristic(position, goal):
return abs(position[0] - goal[0]) + abs(position[1] - goal[1])

# Get neighbors for a node (up, down, left, right movements)


def get_neighbors(node, grid):
neighbors = []
row, col = node.position
# Define movement directions: up, down, left, right
directions = [(-1, 0), (1, 0), (0, -1), (0, 1)]

for direction in directions:


new_row = row + direction[0]
new_col = col + direction[1]
# Ensure the neighbor is within bounds and not an obstacle
if 0 <= new_row < len(grid) and 0 <= new_col < len(grid[0]) and grid[new_row][new_col] ==
0:
neighbors.append((new_row, new_col))

return neighbors

# Helper function to check if a node should be added to the open list


def add_to_open_list(open_list, neighbor_node):
for node in open_list:
if neighbor_node == node and neighbor_node.f >= node.f:
return False
return True

# Reconstruct the path by tracing back from the goal node


def reconstruct_path(node):
path = []
while node:
path.append(node.position)
node = node.parent
return path[::-1] # Return the path in reverse order (from start to goal)

# Test case: A simple 5x5 grid (0 = free, 1 = obstacle)


grid = [
T.Y.BSc.IT Artificial Intelligence and Application I22044
[0, 1, 0, 0, 0],
[0, 1, 0, 1, 0],
[0, 0, 0, 1, 0],
[0, 1, 0, 1, 0],
[0, 0, 0, 0, 0]
]

start = (0, 0) # Starting position (top-left)


end = (4, 4) # Goal position (bottom-right)

# Run the A* algorithm


path = astar(start, end, grid)

# Print the result


if path:
print(f"Path found: {path}")
else:
print("No path found.")

Output:
T.Y.BSc.IT Artificial Intelligence and Application I22044
b) Solve water jug problem.
Input:

from collections import defaultdict


jug1, jug2, aim = 5, 4, 3
visited = defaultdict(lambda: False)
def waterJugSolver(amt1, amt2):
if (amt1 == aim and amt2 == 0) or (amt2 == aim and amt1 == 0):
print(amt1, amt2)
return True
if visited[(amt1, amt2)] == False:
print(amt1, amt2)
visited[(amt1, amt2)] = True
return (waterJugSolver(0, amt2) or
waterJugSolver(amt1, 0) or
waterJugSolver(jug1, amt2) or
waterJugSolver(amt1, jug2) or
waterJugSolver(amt1 + min(amt2,(jug1-amt1)),
amt2=min(amt2,(jug1-amt1))) or
waterJugSolver(amt1 - min(amt1, (jug2-amt2)),amt2+min(amt1,(jug2-amt2))))
else:
return False

print("Steps: ")
waterJugSolver(0, 0)

Output:
T.Y.BSc.IT Artificial Intelligence and Application I22044

PRACTICAL NO.6

a) Derive the expressions based on Associative Law.


Input:
# Function to demonstrate associative law for addition
def associative_addition(a, b, c):
return (a + b) + c == a + (b + c)

# Function to demonstrate associative law for multiplication


def associative_multiplication(a, b, c):
return (a * b) * c == a * (b * c)

# Test cases
a, b, c = 5, 10, 3
print(f"Associative law for addition holds: {associative_addition(a, b, c)}")
print(f"Associative law for multiplication holds: {associative_multiplication(a, b, c)}")
Output:

b) Derive the expressions based on Distributive Law.


Input:
# Function to demonstrate the distributive law
def distributive_law(a, b, c):
left_side = a * (b + c)
right_side = (a * b) + (a * c)
return left_side == right_side
# Test case
a, b, c = 5, 10, 3
print(f"Distributive law holds: {distributive_law(a, b, c)}")
Output:
T.Y.BSc.IT Artificial Intelligence and Application I22044
PRACTICAL NO.7

a) Derive the predicate. (for e.g.: Sachin is batsman, batsman is cricketer)

- > Sachin is Cricketer


Input:
class Entity:
def init (self, name):
self.name = name
self.relations = {}
def add_relation(self, relation, entity):
if relation not in self.relations:
self.relations[relation] = []
self.relations[relation].append(entity)
def is_relation(self, relation, entity):
return entity in self.relations.get(relation, [])
# Define entities
sachin = Entity("Sachin")
batsman = Entity("Batsman")
cricketer = Entity("Cricketer")
# Define relationships
sachin.add_relation("is_a", batsman)
batsman.add_relation("is_a", cricketer)

# Function to derive predicates


def derive(entity, relation):
if entity.is_relation(relation, batsman):
if batsman.is_relation("is_a", cricketer):
return f"{entity.name} is a {cricketer.name}."
return f"No derivation found for {entity.name}."
# Derive predicate
result = derive(sachin, "is_a")
print(result) # Output: Sachin is a Cricketer.
Output:
T.Y.BSc.IT Artificial Intelligence and Application I22044
PRACTICAL NO.8

a) Write a program which contains three predicates: male, female, parent. Make rules for
following family relations: father, mother, grandfather, grandmother, brother, sister, uncle,
aunt, nephew and niece, cousin. Question: i. Draw Family Tree. ii. Define: Clauses, Facts,
Predicates and Rules with conjunction and disjunction.

Input:
class Person:
def init (self, name, gender):
self.name = name
self.gender = gender
self.parents = []
self.children = []

def add_parent(self, parent):


self.parents.append(parent)
parent.children.append(self)

# Predicate functions
def male(person):
return person.gender == 'male'

def female(person):
return person.gender == 'female'

def parent(person):
return person.children

# Family relationship functions


def father(child):
for parent in child.parents:
if male(parent):
return parent
return None

def mother(child):
for parent in child.parents:
if female(parent):
return parent
return None

def grandfather(grandchild):
for parent in grandchild.parents:
father_of_parent = father(parent)
if father_of_parent:
return father_of_parent
return None

def grandmother(grandchild):
for parent in grandchild.parents:
mother_of_parent = mother(parent)
T.Y.BSc.IT Artificial Intelligence and Application I22044
if mother_of_parent:
return mother_of_parent
return None

def brother(sibling1, sibling2):


return male(sibling1) and sibling1 != sibling2 and any(parent in sibling1.parents for parent in
sibling2.parents)

def sister(sibling1, sibling2):


return female(sibling1) and sibling1 != sibling2 and any(parent in sibling1.parents for parent in
sibling2.parents)

def uncle(niece_or_nephew):
for parent in niece_or_nephew.parents:
for sibling in parent.children:
if sibling != parent and male(sibling):
return sibling
return None

def aunt(niece_or_nephew):
for parent in niece_or_nephew.parents:
for sibling in parent.children:
if sibling != parent and female(sibling):
return sibling
return None

def nephew(niece_or_nephew):
for parent in niece_or_nephew.parents:
for sibling in parent.children:
if sibling != parent and male(sibling):
return sibling
return None

def niece(niece_or_nephew):
for parent in niece_or_nephew.parents:
for sibling in parent.children:
if sibling != parent and female(sibling):
return sibling
return None

def cousin(cousin1, cousin2):


return any(parent in cousin1.parents for parent in cousin2.parents) and cousin1 != cousin2

# Example family setup


john = Person("John", "male")
susan = Person("Susan", "female")
mike = Person("Mike", "male")
lisa = Person("Lisa", "female")
james = Person("James", "male")
mary = Person("Mary", "female")

# Define parent relationships


T.Y.BSc.IT Artificial Intelligence and Application I22044
john.add_parent(mike)
susan.add_parent(mike)
john.add_parent(lisa)
susan.add_parent(lisa)
mike.add_parent(james)
mike.add_parent(mary)

# Example queries
print("Father of John:", father(john).name)
print("Mother of John:", mother(john).name)
print("Grandfather of John:", grandfather(john).name)
print("Grandmother of John:", grandmother(john).name)
print("Is Mike John's brother?", brother(mike, john))
print("Is Lisa John's sister?", sister(lisa, john))
print("Uncle of John:", uncle(john).name)
print("Aunt of John:", aunt(john).name)

Output :
T.Y.BSc.IT Artificial Intelligence and Application I22044
PRACTICAL NO.9

a) Design an application to simulate number puzzle problem.


Input:
import random

class Puzzle:
def init (self):
self.size = 4
self.board = self.initialize_board()
self.empty_tile = (3, 3) # Coordinates of the empty tile (row, col)

def initialize_board(self):
"""Initialize the board with numbers 1-15 and an empty tile (0)"""
numbers = list(range(1, 16)) + [0] # 0 represents the empty tile
random.shuffle(numbers)
board = [numbers[i * self.size:(i + 1) * self.size] for i in range(self.size)]
return board

def display(self):
"""Display the current state of the board"""
for row in self.board:
print(" ".join(f"{num:2d}" if num != 0 else " . " for num in row))
print()

def find_empty_tile(self):
"""Find the current position of the empty tile"""
for i in range(self.size):
for j in range(self.size):
if self.board[i][j] == 0:
return (i, j)

def is_solvable(self):
"""Check if the current configuration is solvable"""
flat_list = [num for row in self.board for num in row if num != 0]
inversions = sum(
1 for i in range(len(flat_list)) for j in range(i + 1, len(flat_list)) if flat_list[i] > flat_list[j]
)
return inversions % 2 == 0

def slide(self, direction):


"""Slide a tile in the specified direction (up, down, left, right)"""
row, col = self.empty_tile
if direction == "up" and row < self.size - 1:
self.board[row][col], self.board[row + 1][col] = self.board[row + 1][col],
self.board[row][col]
self.empty_tile = (row + 1, col)
elif direction == "down" and row > 0:
self.board[row][col], self.board[row - 1][col] = self.board[row - 1][col],
self.board[row][col]
self.empty_tile = (row - 1, col)
elif direction == "left" and col < self.size - 1:
T.Y.BSc.IT Artificial Intelligence and Application I22044
self.board[row][col], self.board[row][col + 1] = self.board[row][col + 1],
self.board[row][col]
self.empty_tile = (row, col + 1)
elif direction == "right" and col > 0:
self.board[row][col], self.board[row][col - 1] = self.board[row][col - 1],
self.board[row][col]
self.empty_tile = (row, col - 1)

def is_solved(self):
"""Check if the board is in a solved state"""
count = 1
for row in range(self.size):
for col in range(self.size):
if (row, col) == (self.size - 1, self.size - 1):
return self.board[row][col] == 0 # Last tile should be 0
if self.board[row][col] != count:
return False
count += 1
return True

def play_game():
puzzle = Puzzle()

# Ensure the puzzle is solvable


while not puzzle.is_solvable():
puzzle = Puzzle()

print("Welcome to the 15-Puzzle Game!")


puzzle.display()

while not puzzle.is_solved():


move = input("Enter your move (up, down, left, right): ").lower()
if move in ["up", "down", "left", "right"]:
puzzle.slide(move)
puzzle.display()
else:
print("Invalid move! Please enter 'up', 'down', 'left', or 'right'.")

print("Congratulations! You've solved the puzzle!")

if name == " main ":


play_game()

Output:
T.Y.BSc.IT Artificial Intelligence and Application I22044
PRACTICAL NO.10

a) Solve constraint satisfaction problem.

Input:

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


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

# Check upper diagonal on left side


for i, j in zip(range(row, -1, -1), range(col, -1, -1)):
if j < 0:
break
if board[i][j] == 'Q':
return False

# Check upper diagonal on right side


for i, j in zip(range(row, -1, -1), range(col, n)):
if j >= n:
break
if board[i][j] == 'Q':
return False

return True

def solve_n_queens_util(board, row, n, solutions):


"""Utilize backtracking to solve the N-Queens problem."""
if row >= n:
# Found a solution, add it to the solutions list
solutions.append([''.join(row) for row in board])
return

for col in range(n):


if is_safe(board, row, col, n):
board[row][col] = 'Q' # Place queen
solve_n_queens_util(board, row + 1, n, solutions) # Recur to place rest of the queens
board[row][col] = '.' # Backtrack

def solve_n_queens(n):
"""Solve the N-Queens problem and return all solutions."""
board = [['.' for _ in range(n)] for _ in range(n)] # Initialize the board
solutions = []
solve_n_queens_util(board, 0, n, solutions)
return solutions

def print_solutions(solutions):
"""Print all the solutions in a human-readable format."""
for idx, solution in enumerate(solutions):
T.Y.BSc.IT Artificial Intelligence and Application I22044
print(f"Solution {idx + 1}:")
for row in solution:
print(row)
print()

if name == " main ":


n = 4 # Change this value to solve for a different N
solutions = solve_n_queens(n)
print_solutions(solutions)

Output:

You might also like