0% found this document useful (0 votes)
20 views36 pages

Ad3311 Lab Manual

Uploaded by

sfstan.prince
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)
20 views36 pages

Ad3311 Lab Manual

Uploaded by

sfstan.prince
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/ 36

EX.No.

1 IMPLEMENT BASIC SEARCH STRATEGIES 8-PUZZLE PROBLEM


DATE:

AIM

To implement basic search strategies – 8-Puzzle Problem.

ALGORITHM

1. The code starts by creating a Solution class and then defining the method solve.
2. The function takes in a board as an argument, which is a list of tuples representing the
positions on the board.
3. It iterates through each position in the list and creates a dictionary with that position's value
set to 0.
4. Then it iterates through all possible moves for that position and returns their number of
occurrences in dict.
5. After this, it loops over all nodes on the board until it finds one where there are no more
moves left to make (i.e., when len(current_nodes) == 0).
6. This node will be returned as -1 if found or else its index will be stored into pos_0 so that we
can find out what move was made at that point later on.
7. The next step is finding out what move was made at every node by looping over all possible
moves for each node using self's find_next function, which takes in a single node as an
argument and returns any other nodes connected to it via path-finding algorithms like DFS or
BFS (see below).
8. For example, if pos_0 = 1 then self would call: moves = { 0: [1], 1:
9. The code will print the number of paths in a solution.

PROGRAM

class Solution:
def solve(self, board):
state_dict = {} # Better name than 'dict' (which shadows the built-in dict type)
flatten = []

# Flatten the board into a 1D list and convert to tuple for immutability
for i in range(len(board)):
flatten += board[i]
flatten = tuple(flatten)

# Initialize the dictionary with the starting state


state_dict[flatten] = 0

# Check if the board is already in the goal state


if flatten == (0, 1, 2, 3, 4, 5, 6, 7, 8):
return 0

# Start the BFS search


return self.get_paths(state_dict)

def get_paths(self, state_dict):


cnt = 0

while True:
# Get all the nodes at the current depth level (cnt)
current_nodes = [x for x in state_dict if state_dict[x] == cnt]

# If no nodes are left to process, we return -1 (no solution)


if len(current_nodes) == 0:
return -1

# Explore all possible moves from the current nodes


for node in current_nodes:
next_moves = self.find_next(node)

for move in next_moves:


if move not in state_dict:
# Mark this state as visited and assign the new depth level
state_dict[move] = cnt + 1

# If the move is the goal state, return the depth


if move == (0, 1, 2, 3, 4, 5, 6, 7, 8):
return cnt + 1

# Move to the next depth level


cnt += 1

def find_next(self, node):


# Define the possible moves for each index (where 0 represents the blank tile)
moves = {
0: [1, 3],
1: [0, 2, 4],
2: [1, 5],
3: [0, 4, 6],
4: [1, 3, 5, 7],
5: [2, 4, 8],
6: [3, 7],
7: [4, 6, 8],
8: [5, 7]
}

results = []
pos_0 = node.index(0) # Find the position of the blank (0)

# Generate possible next moves by swapping the blank with its valid neighbors
for move in moves[pos_0]:
new_node = list(node)
new_node[move], new_node[pos_0] = new_node[pos_0], new_node[move]
results.append(tuple(new_node)) # Convert back to tuple for immutability

return results
# Example usage:
ob = Solution()
matrix = [
[3, 1, 2],
[4, 7, 5],
[6, 8, 0]
]

# Output the number of moves required to solve the puzzle


print("NO OF MOVES==", ob.solve(matrix)

OUTPUT:

NO OF MOVES== 4

RESULT:

Thus the program to implement 8 puzzles search strategy is implemented and executed successfully
EX.No. 1.b Implement basic search strategies – 8-Queens Problem
DATE:

AIM

To implement basic search strategies – 8-Queens Problem.

ALGORITHM

1. The code starts by asking the user to enter a number.


2. It then creates an NxN matrix with all elements set to 0.
3. The code then defines two functions: attack and N_queens.
4. The function attack checks vertically and horizontally, while the function N_queens checks diagonally.
5. If either of these functions return true, it means that there is a queen in that position on the board.
6. The code is a function that will check if there are enough queens on the chessboard.
7. The code starts by defining a function, N_queens (n), which will return true if there are enough queens
and False otherwise.
8. The variable n is used to define how many queens need to be placed on the board for it to be considered
complete.

PROGRAM

def print_board(board):
"""Helper function to print the board."""
for row in board:
print(" ".join("Q" if col == 1 else "." for col in row))
print()

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


"""Check if placing a queen at (row, col) is safe."""
# Check vertical and horizontal
for k in range(N):
if board[row][k] == 1 or board[k][col] == 1:
return True

# Check diagonals
for k in range(N):
for l in range(N):
if (k + l == row + col) or (k - l == row - col):
if board[k][l] == 1:
return True
return False

def N_queens(board, n, N):


"""Try to place n queens on the board."""
if n == 0: # All queens are placed
return True
for i in range(N):
for j in range(N):
if not attack(board, i, j, N) and board[i][j] != 1:
board[i][j] = 1 # Place queen

# Recur to place the rest of the queens


if N_queens(board, n - 1, N):
return True

# Backtrack
board[i][j] = 0

return False

# Main function to set up the N-Queens problem


def main():
print("Enter the number of queens:")
N = int(input())

# Create a NxN chessboard initialized with 0s


board = [[0] * N for _ in range(N)]

if N_queens(board, N, N):
print_board(board)
else:
print("No solution exists.")

# Execute the main function


if name__ == " main ":
main()
OUTPUT:
Enter the number of
queens 8
[1, 0, 0, 0, 0, 0, 0, 0]
[0, 0, 0, 0, 1, 0, 0, 0]
[0, 0, 0, 0, 0, 0, 0, 1]
[0, 0, 0, 0, 0, 1, 0, 0]
[0, 0, 1, 0, 0, 0, 0, 0]
[0, 0, 0, 0, 0, 0, 1, 0]
[0, 1, 0, 0, 0, 0, 0, 0]
[0, 0, 0, 1, 0, 0, 0, 0]

RESULT

Thus the program to implement 8 queens search strategy is implemented and executed successfully.
EX.No.3 Implement basic search strategies – Crypt arithmetic

DATE:

AIM
To implement basic search strategies – Crypt arithmetic.

ALGORITHM

1. Initialization:The code initializes a variable to keep track of letter assignments


and sets up a loop to assign integer values to each character in the given words.
2. Validation: It checks if any of the first or last letters of the words are assigned
a value of zero, indicating an invalid assignment which leads to an early termination
of the function.
3. Backtracking: The algorithm uses a recursive approach to try all possible
assignments of digits to letters, ensuring that no letter is zero if it is the starting letter
of a word.
4. Solution Check:It verifies if the current assignments satisfy the equation
`word1 + word2 = result` and collects all valid solutions.
5. Output:Finally, the code prints the solutions to the puzzle or indicates if no
valid solution is found, displaying a message like "0 Solutions”.
PROGRAM

def find_value(word, assigned):


"""Converts the letters of a word into the corresponding number using the assigned dictionary."""
num = 0
for char in word:
num = num * 10 + assigned[char]
return num

def is_valid_assignment(word1, word2, result, assigned):


"""Checks if the current assignment is valid."""
# First letter of any word cannot be zero
if assigned[word1[0]] == 0 or assigned[word2[0]] == 0 or assigned[result[0]] == 0:
return False
return True

def _solve(word1, word2, result, letters, assigned, solutions):


"""Recursively tries to solve the puzzle using backtracking."""
if not letters:
# All letters have been assigned
if is_valid_assignment(word1, word2, result, assigned):
num1 = find_value(word1, assigned)
num2 = find_value(word2, assigned)
num_result = find_value(result, assigned)
if num1 + num2 == num_result:
# Solution found
solutions.append((f'{num1} + {num2} = {num_result}', assigned.copy()))
return

# Get the next letter to assign


cur_letter = letters.pop()
for num in range(10):
if num not in assigned.values(): # Avoid reusing digits
assigned[cur_letter] = num
_solve(word1, word2, result, letters, assigned, solutions)
assigned.pop(cur_letter) # Backtrack
letters.append(cur_letter) # Restore the letter to the list

def solve(word1, word2, result):


"""Main function to solve the cryptarithmetic puzzle."""
# Extract all unique letters from word1, word2, and result
letters = sorted(set(word1) | set(word2) | set(result))

# If there are more than 10 unique letters, it's not possible to assign digits
if len(letters) > 10:
print('0 Solutions!')
return

solutions = []
_solve(word1, word2, result, letters, {}, solutions)

if solutions:
print('\nSolutions:')
for soln in solutions:
print(f'{soln[0]}\t{soln[1]}')
else:
print('0 Solutions!')

if __name__ == '__main__':
print('CRYPTARITHMETIC PUZZLE SOLVER')
print('WORD1 + WORD2 = RESULT')
word1 = input('Enter WORD1: ').upper()
word2 = input('Enter WORD2: ').upper()
result = input('Enter RESULT: ').upper()

# Ensure all inputs are valid alphabets


if not word1.isalpha() or not word2.isalpha() or not result.isalpha():
raise ValueError('Inputs should only consist of alphabets.')

solve(word1, word2, result)


OUTPUT

CRYPTARITHMETIC PUZZLE SOLVER


WORD1 + WORD2 = RESULT
Enter WORD1: SEND
Enter WORD2: MORE
Enter RESULT: MONEY
Solutions:
9567 + 1085 = 10652 {'Y': 2, 'S': 9, 'R': 8, 'O': 0, 'N': 6, 'M': 1, 'E':
5, 'D': 7}

RESULT

Thus the program to implement crypt arithmetic search strategy is implemented and executed successfully
EX.No. 2 Implement A* Algorithm
DATE:

AIM

To Implement A* Algorithm.

ALGORITHM

1. Class Initialization: The `A_Star_Solver` class is initialized with a starting


point, a goal, and a priority queue, setting up the state with values and parent
references.
2. Solve Method: The `Solve` method processes nodes from a priority queue,
exploring paths and checking if the current node matches the goal or if it’s the last
node.
3. Distance Calculation: Each state calculates its distance from the goal using
the `GetDistance` method to guide the search for the optimal path.
4. Node Exploration: The `Analyze` method adds new nodes to the queue, avoids
revisiting nodes, and generates children states using `CreateChildren` to further
explore potential paths.
5. Path Finding: The algorithm continues visiting nodes and their children until it
either finds the goal or exhausts all possibilities, eventually tracing back to the start
if no solution is found.

PROGRAM

from queue import PriorityQueue

# Base Class
class State(object):
def __init (self, value, parent, start=0, goal=0):
self.children = []
self.parent = parent
self.value = value
self.dist = 0
if parent:
self.start = parent.start
self.goal = parent.goal
self.path = parent.path[:] # Copy the parent's path
self.path.append(value) # Add the current value to the path
else:
self.path = [value]
self.start = start
self.goal = goal

def GetDistance(self):
pass
def CreateChildren(self):
pass

# Subclass for handling strings


class State_String(State):
def __init (self, value, parent, start=0, goal=0):
super(State_String, self). init__(value, parent, start, goal)
self.dist = self.GetDistance() # Calculate distance based on current state

def GetDistance(self):
if self.value == self.goal:
return 0
dist = 0
for i in range(len(self.goal)):
letter = self.goal[i]
if letter in self.value:
dist += abs(i - self.value.index(letter))
else:
dist += len(self.goal) # If letter is not found, add maximum possible distance
return dist

def CreateChildren(self):
if not self.children:
for i in range(len(self.goal) - 1):
val = self.value
# Swap adjacent letters
val = val[:i] + val[i+1] + val[i] + val[i+2:]
child = State_String(val, self) # Create new child state
self.children.append(child)

# A* Solver Class
class A_Star_Solver:
def __init (self, start, goal):
self.path = []
self.visitedQueue = []
self.priorityQueue = PriorityQueue()
self.start = start
self.goal = goal

def Solve(self):
startState = State_String(self.start, None, self.start, self.goal)
count = 0
self.priorityQueue.put((0, count, startState)) # Start state with priority 0

while not self.path and self.priorityQueue.qsize():


closestChild = self.priorityQueue.get()[2]
closestChild.CreateChildren() # Generate possible child states
self.visitedQueue.append(closestChild.value)

for child in closestChild.children:


if child.value not in self.visitedQueue:
count += 1
if child.dist == 0: # If the child distance is 0, we have found the goal
self.path = child.path
break
self.priorityQueue.put((child.dist, count, child))

if not self.path:
print("Goal is not possible: " + self.goal)
else:
print("Goal found! Path to solution:")
for i in range(len(self.path)):
print("{0}) {1}".format(i, self.path[i]))

# Main block to test the solver


if name__ == " main ":
start1 = "secure"
goal1 = "rescue"
print("Starting A* Solver")
a = A_Star_Solver(start1, goal1)
a.Solve()
OUTPUT

Starting....
0)secure
1)secrue
2)sercue
3)srecue
4)rsecue
5)rescue

RESULT

Thus the program to implement A* algorithm is implemented and executed successful


EX.No. 3 Implement Mini-Max algorithm for game playing (Alpha-Beta pruning)
DATE:

AIM

To Implement Mini-max algorithm for game playing.

ALGORITHM

1. The code first creates an array of five values.


2. These values represent the possible outcomes of a mini-max calculation.
3. Next, the code calls the minimax () function to find the optimal value for the current player.
4. This function takes three arguments: depth, nodeIndex, and maximizingPlayer.
5. The first two arguments specify how deep into the tree the minimax calculation should occur, and nodeIndex
specifies which child node in that depth should be used as the starting point for this calculation.
6. The third argument is a Boolean flag that tells minimax () whether or notmaximizingPlayer should be used during
this calculation.
7. The code then sets up some variables to track which value in values represents best for each of MIN and MAX.
8. These variables are alpha and beta.
9. Alpha tracks which value in values is currently being optimized (MIN or MAX), while beta tracks which value
is currently being minimized (MIN or MAX).
10. The code then loops through all of values' children nodes, calling minimax () on each one with different
combinations of True and False as its arguments.
11. It keeps track of these results using best and val variables respectively.
12. If any of these calculations results in a better overall value than either MIN or MAX, then that new best value
becomes the new minimum
13. The code will return the optimal value for the current player, which is 5
PROGRAM

MAX, MIN = 1000, -1000

# Returns optimal value for the current player (Initially called for root and maximizing player)
def minimax(depth, nodeIndex, maximizingPlayer, values, alpha, beta):
# Terminating condition. i.e, leaf node is reached
if depth == 3:
return values[nodeIndex]

if maximizingPlayer:
best = MIN
# Recur for left and right children (Maximizing player)
for i in range(2):
val = minimax(depth + 1, nodeIndex * 2 + i, False, values, alpha, beta)
best = max(best, val)
alpha = max(alpha, best)

# Alpha-Beta Pruning
if beta <= alpha:
break

return best
else:
best = MAX
# Recur for left and right children (Minimizing player)
for i in range(2):
val = minimax(depth + 1, nodeIndex * 2 + i, True, values, alpha, beta)
best = min(best, val)
beta = min(beta, best)

# Alpha-Beta Pruning
if beta <= alpha:
break

return best

# Driver Code
if name__ == " main ":
values = [3, 5, 6, 9, 1, 2, 0, -1] # Leaf node values
print("The optimal value is:", minimax(0, 0, True, values, MIN, MAX))
OUTPUT
The optimal value is : 5

RESULT

Thus the program to implement Minimax algorithm for game playing is implemented and executed
successfully
EX.No.4 Solve constraint satisfaction problems
DATE:

AIM

To solve constraint satisfaction problems.

ALGORITHM

1. The code starts by defining some variables.


2. The first variable, assignment, is a list of strings.
3. The second variable, VARIABLES, is a list of five strings.
4. Next, the code defines some constraints.
5. The first constraint is that the two lists have the same length (len(assignment) == len(VARIABLES)).
6. The next constraint is that each string in VARIABLES must be in one of the three domains (Monday, Tuesday,
and Wednesday).
7. Finally, the last constraint is that each string in DOMAIN must be associated with at least one variable in
VARIABLES.
8. The code then starts to search for an assignment that meets all the constraints.
9. First it checks if assignment is complete (if len (assignment) == len (VARIABLES)) and then it selects a
variable from VARIABLES based on its domain and value.
10. If there are no more variables to select, then the code returns none.
11. Otherwise it backtracks through the assignment looking for a consistent combination of values for each
selected variable.
12. If successful, it assigns those values to corresponding variables in result and returns this as solution.
13. The code first looks for a variable not yet assigned in the VARIABLES list.
14. If no variable is found, it returns none.
15. If an assignment is found, the code checks to see if the variables are consistent with each other.
16. If they are not, the code backtracks and tries again with a different variable.
17. If all variables are consistent with each other, then the code assigns the value of day to var3 and returns False.
PROGRAM
VARIABLES = ["csc", "maths", "phy", "che", "tam", "eng", "bio"]
DOMAIN = ["Monday", "Tuesday", "Wednesday"]
CONSTRAINTS = [
("csc", "maths"),
("csc", "phy"),
("maths", "phy"),
("maths", "che"),
("maths", "tam"),
("phy", "tam"),
("phy", "eng"),
("che", "eng"),
("tam", "eng"),
("tam", "bio"),
("eng", "bio")
]

def backtrack(assignment):
# Check if assignment is complete
if len(assignment) == len(VARIABLES):
return assignment

var = select_unassigned_variable(assignment) # Choose the next unassigned variable


for value in DOMAIN:
if consistent(var, value, assignment):
assignment[var] = value
result = backtrack(assignment)
if result is not None:
return result
# Undo the assignment (Backtrack)
del assignment[var]
return None

def select_unassigned_variable(assignment):
# Select the next unassigned variable (can be optimized with MRV)
for var in VARIABLES:
if var not in assignment:
return var
return None

def consistent(var, value, assignment):


# Check if the assignment of 'value' to 'var' is consistent with the constraints
for var1, var2 in CONSTRAINTS:
if var == var1 or var == var2:
# Check if either of the two variables is already assigned and has a conflict
other_var = var2 if var == var1 else var1
if other_var in assignment and assignment[other_var] == value:
return False
return True

# Initialize the assignment dictionary and start the backtracking search


assignment = {}
solution = backtrack(assignment)

print("Solution:")
print(solution)

OUTPUT
{'csc': 'Monday', 'maths': 'Tuesday', 'phy': 'Tuesday', 'che': 'Monday', 'tam': 'MoMonday', 'eng': 'Wednesday',
'bio': 'Tuesday'}

RESULT

Thus the program to solve constraint satisfaction problem is implemented and executed successfully.
EX.No. 5 Propositional Model Checking Algorithms
DATE:

AIM

To Implement Propositional Model checking Algorithm.

ALGORITHM

1. Class Literal, it has attributes name and sign to denote whether the literal is positive or negative in use.
2. The neg function returns a new literal with the same name but the opposite sign of its parent literal.
3. The repr function returns the string of the literal name,( or the string with a negative sign) each time the
instance of the literal is called.
4. The CNFConvert function converts the KiB from a list of sets to a list of list for easier computing
5. The VariableSet function finds all the used literals in the KB, and in order to assist with running the DPLL.
6. The Negativeofx function is for holding the negative form of the literal, for use in the DPLL algorithm
7. The pickX function picks a literal from the variable set and works with it as a node in the tree.
8. Now define the functions splitfalseliterals() and splitTrueLiteral().
9. Create the function dpll() that performs the dpll algorithm recursively.
10. Finally call the function to execute the code.

PROGRAM

import re

class Literal:
def __init (self, name, sign=True):
self.name = str(name)
self.sign = sign

def __neg (self):


return Literal(self.name, not self.sign)

def __str (self):


return str(self.name)

def __repr (self):


return f'{str(self.name) if self.sign else "-" + str(self.name)}'

def CNFconvert(KB):
# Converts the KB from a list of sets to a list of lists for easier computing
storage = []
for i in KB:
i = list(i)
i = [str(j) if isinstance(j, str) else j for j in i] # Ensure literals are properly handled
storage.append(i)
return storage
def VariableSet(KB):
# Finds all the used literals in the KB
KB = CNFconvert(KB)
storage = []
for obj in KB:
for item in obj:
if item[0] == '-' and item[1:] not in storage:
storage.append(str(item[1:]))
elif item not in storage and item[0] != '-':
storage.append(str(item))
return storage

def Negativeofx(x):
# Holds the negative form of the literal
return str(x[1:]) if x[0] == '-' else '-' + str(x)

def pickX(literals, varList):


# Picks a literal from the variable set
for x in varList:
if x not in literals:
return x
return None

def splitFalseLiterals(cnf, x):


holder = []
for item in cnf:
if x in item:
item.remove(x)
holder.append(item)
return holder

def splitTrueLiteral(cnf, x):


holder = []
for item in cnf:
if x not in item:
holder.append(item)
return holder

def unitResolution(clauses):
literalholder = {}
i=0
while i < len(clauses):
newClauses = []
clause = clauses[i]
if len(clause) == 1:
literal = str(clause[0])
pattern = re.match("-", literal)
if pattern:
nx = literal[1:]
literalholder[nx] = False
else:
nx = "-" + literal
literalholder[literal] = True
for item in clauses:
if item != clauses[i]:
if nx in item:
item.remove(nx)
newClauses.append(item)
i=0
clauses = newClauses
return literalholder, clauses

def dpll(clauses, varList):


literals, cnf = unitResolution(clauses)
if cnf == []:
return literals
elif [] in cnf:
return "notsatisfiable"
else:
while True:
x = pickX(literals, varList)
if x is None:
break
nx = Negativeofx(x)
ncnf = splitTrueLiteral(cnf, x)
ncnf = splitFalseLiterals(ncnf, nx)
if ncnf == cnf:
varList.remove(x)
else:
break
case1 = dpll(ncnf, varList)
if case1 != "notsatisfiable":
copy = case1.copy()
copy.update(literals)
copy.update({x: True})
return copy
case2 = dpll(ncnf, varList)
if case2 != "notsatisfiable":
copy = case2.copy()
copy.update(literals)
copy.update({x: False})
return copy
else:
return "notsatisfiable"

def DPLL(KB):
KB = CNFconvert(KB)
varList = VariableSet(KB)
result = dpll(KB, varList)
if result == 'notsatisfiable':
return [False, {}]
else:
for i in varList:
if i in result and result[i] == True:
result[i] = 'true'
elif i in result and result[i] == False:
result[i] = 'false'
else:
result[i] = 'free'
return [True, result]

# Example usage
A = Literal('A')
B = Literal('B')
C = Literal('C')
D = Literal('D')
KB = [{A, B}, {A, -C}, {-A, B, D}]
print(DPLL(KB))

OUTPUT

[True, {'B': 'true', 'A': True, 'C': 'free', 'D': 'free'}]

RESULT

Thus the program to implement Propositional Model checking Algorithm is implemented and executed
successfully.
EX.No. 6 Implement Forward Chaining Algorithm

DATE:

AIM

To Implement Forward Chaining Algorithm.

ALGORITHM

1. The code starts by declaring a variable called "x".


2. This is the number of items in the database.
3. The code then declares two variables, "database" and "knowbase".
4. The first one is an array that stores all the words in the database.
5. The second one is an array that stores all the colors of objects in our world.
6. Next, it prints out a message saying *-----Forward--Chaining ---- * to let us know what's going on.
7. Then it displays some text with instructions for how to use this program before displaying any output from it
(i.e., telling us what we're supposed to do).
8. It also tells us which input option will be valid if you enter 1 or 2 as your input value (in this case, frog0 and
green1).
9. If you enter 3 or 4 instead, then they'll tell you about canary1 and yellow3 respectively.
10. Else it prints invalid knowledge database

PROGRAM

database = ["Croaks", "Eat Flies", "Shrimps", "Sings"]


knowbase = ["Frog", "Canary", "Green", "Yellow"]
def display():
print("\n X is \n1..Croaks \n2.Eat Flies \n3.shrimps \n4.Sings ", end='')
print("\n Select One ", end='')

def main():
print("*-----Forward--Chaining ---- *", end='')
display()
x = int(input())
print(" \n", end='')
if x == 1 or x == 2:
print(" Chance Of Frog ", end='')
elif x == 3 or x == 4:
print(" Chance of Canary ", end='')
else:
print("\n-------In Valid Option Select ---------", end='')
if x >= 1 and x <= 4:
print("\n X is ", end='')
print(database[x-1], end='')
print("\n Color Is 1.Green 2.Yellow", end='')
print("\n Select Option ", end='')
k = int(input())
if k == 1 and (x == 1 or x == 2): # frog0 and green1
print(" yes it is ", end='')
print(knowbase[0], end='')
print(" And Color Is ", end='')
print(knowbase[2], end='')
elif k == 2 and (x == 3 or x == 4): # canary1 and yellow3
print(" yes it is ", end='')
print(knowbase[1], end='')
print(" And Color Is ", end='')
print(knowbase[3], end='')
else:
print("\n---InValid Knowledge Database", end='')

if name == " main ":


main()

OUTPUT

*-----Forward--Chaining ---- *
X is
1.Croaks
2.Eat Flies
3.shrimps
4.Sings
Select One 1
Chance Of Frog
X is Croaks
Color Is
1.Green
2.Yellow
Select Option 1
yes it is Frog And Color Is Green

RESULT

Thus the program to implement Forward Chaining Algorithm is implemented and executed successful
EX.No. 7 Implement backward Chaining Algorithm
DATE:

AIM

To implement backward chaining algorithm

ALGORITHM

1. The code starts with a function called display () which prints out the text "X is 1.frog 2.canary"
2. And then asks for input from the user, asking them to select one of two options: Chance of eating flies or
Chance of shrimping.
3. If they choose either option, it will print out what that option would be in green or yellow color respectively.
4. The next line is x = int (input ()) which takes the value entered by the user and assigns it to variable x.
5. The if statement checks whether x equals 1 or 2
6. So if they enter 1 as their answer, it will print out "Chance of eating flies"
7. Otherwise it will print "Chance of shrimping".

PROGRAM

# Databases and knowledge base


database = ["Croaks", "Eat Flies", "Shrimps", "Sings"]
knowbase = ["Frog", "Canary", "Green", "Yellow"]

def display():
"""Displays options for the user to choose from."""
print("\nX is:")
print("1. Croaks")
print("2. Eat Flies")
print("3. Shrimps")
print("4. Sings")
print("\nSelect One (1-4):", end=' ')

def main():
"""Main function to drive the forward chaining logic."""
print("*-----Forward-Chaining---- *")
display()

try:
x = int(input()) # User selects an option from the database

# Check if the user selected a valid option


if x < 1 or x > 4:
print("\n-------Invalid Option Selected ------- ")
return

# Print the chosen option from the database


print("\nX is", database[x - 1])

# Now ask for the color (Green or Yellow)


print("\nColor Is:")
print("1. Green")
print("2. Yellow")
print("\nSelect Option (1-2):", end=' ')
k = int(input()) # User selects a color option

# Forward chaining logic


if k == 1: # Green color
if x == 1 or x == 2: # Frog
print("Yes, it is", knowbase[0], "and Color Is", knowbase[2]) # Frog and Green
else:
print("\n---Invalid Knowledge Database---") # Invalid selection for Green
elif k == 2: # Yellow color
if x == 3 or x == 4: # Canary
print("Yes, it is", knowbase[1], "and Color Is", knowbase[3]) # Canary and Yellow
else:
print("\n---Invalid Knowledge Database---") # Invalid selection for Yellow
else:
print("\n---Invalid Option Selected for Color---") # If user selects an invalid color option

except ValueError:
print("\n---Invalid Input. Please enter a number (1-4 for X and 1-2 for Color).---")

if name__ == " main ":


main()
OUTPUT

*-----Backward--Chaining ---- *
X is
1.frog
2.canary
Select One 1
Chance Of eating flies
X is Frog
1.green
2.yellow
1
yes it is in Green colour and will Croak

RESULT

Thus the program to implement backward chaining algorithm is implemented and executed successfully.
EX.No. 8 Implement Naïve Bayes Models

DATE:

AIM

To implement Naïve Bayes Models.

ALGORITHM

1. The code starts by loading the iris dataset.


2. The data is then split into a training and test set of equal size.
3. Next, a Gaussian Naive Bayes classifier is trained using the training set.
4. Then predictions are made on the test set with accuracy scores calculated for each prediction.
5. Finally, a confusion matrix is created to show how well each prediction was classified as correct or incorrect
6. The code is used to train a Gaussian Naive Bayes classifier and then use it to make predictions.
7. The code prints the model's predictions, as well as the test set's output for comparison.

PROGRAM

# Import necessary libraries


from sklearn import datasets
from sklearn.metrics import confusion_matrix, accuracy_score
from sklearn.model_selection import train_test_split
from sklearn.naive_bayes import GaussianNB

# Load the iris dataset


iris = datasets.load_iris()
X = iris.data
Y = iris.target

# Split the dataset into training and testing sets (1/3 for testing)
X_train, X_test, Y_train, Y_test = train_test_split(X, Y, test_size=0.33)

# Training a Gaussian Naive Bayes classifier


model = GaussianNB()
model.fit(X_train, Y_train)

# Make predictions on the test set


model_predictions = model.predict(X_test)

# Print model predictions


print("\nPredicted Values:\n", model_predictions)

# Print actual test values


print("\nActual Values:\n", Y_test)

# Calculate accuracy of the model


accuracy_score_value = accuracy_score(Y_test, model_predictions)
print("\nAccuracy Score is:", accuracy_score_value)

# Generate a confusion matrix


cm = confusion_matrix(Y_test, model_predictions)
print("\nConfusion Matrix:\n", cm)

OUTPUT

Predicted Values:
[1 0 2 2 2 0 1 0 1 1 2 2 0 2 2 1 1 2 1 0 2 2 0 2 1 0 1 2 1 2 2 0 0 2 1 0 1
2 1 2 2 1 2 2 1 1 2 2 0 1]

Actual Values:
[1 0 2 2 2 0 1 0 1 1 2 2 0 2 2 1 1 2 1 0 2 2 0 2 2 0 1 1 1 1 2 0 0 2 1 0 1
2 1 2 2 1 2 2 2 1 2 2 0 1]

Accuracy Score is: 0.92

Confusion Matrix:
[[11 0 0]
[ 0 15 2]
[ 0 2 20]]

RESULT

Thus the program to implement Naïve Bayes Model is implemented and executed successf
EX.No. 9 Implement Bayesian Networks and perform inferences

DATE:

AIM:
To Implement Bayesian Networks and perform inferences.

ALGORITHM:

1. The code starts by importing the datasets module.


2. This is used to load the iris dataset from sklearn, which is then passed into a variable called data.
3. The target and data_tensor are then created with torch's numpy library.
4. The code continues by creating an instance of a sequential model that has three layers:
bnn.BayesLinear(prior_mu=0, prior_sigma=0.1, in_features=4), nn.ReLU(), and bnn.BayesLinear(prior_mu=0,
prior_sigma=0.1, in_features=100).
5. The cross entropy loss function is then created as well as an instance of it being assigned to the cross entropy
loss variable named crossEntropyLoss().
6. The code will create a model that takes in 100 features and outputs 3.
7. The code starts by importing the necessary libraries.
8. Then it creates a model that will be used to predict the target variable, which is the number of people who are
likely to buy a product in one month.
9. The code then calculates how much money it would cost for this prediction and compares it with what's
actually spent on advertising.
10. The code starts by creating an optimizer object that uses Adam as its learning algorithm and has a parameter
of 0.01 for its learning rate.
11. It then loops through 3000 steps, each step taking about 1 second, where models are created from data_tensor
using torch's max function and predicted is calculated using torch's max function on models' data tensor (which is
just another way of saying "the most recent value").
12. Cross entropy loss is calculated between predictions and targets using cross_entropy_loss
13. Finally, kloss , which stands for Kullback-Leibler divergence, is calculated with klloss .
14. This loss measures how different two probability distributions are from each other; in this case we're
measuring how different our predictions are from their actual values (i.e., whether they were correct).
15. Total cost is then calculated by adding cross entropy plus klweight*kl .
16. Finally, optim
17. The code is used to predict the output of a model given input data.
18. The code starts by initializing the variables that will be needed for later calculations.

36
19. Next, it calculates the cross entropy loss between target and predicted values.
20. Then, it calculates the cost function which is then minimized using Adam optimizer.
21. Finally, it prints out the predicted value and total cost after every iteration of optimization process.
22. The code starts by defining a function called draw_graph that takes in a predicted value.
23. The code then creates two subplots on the same figure, one for each of the predictions.
24. The first subplot is created with fig_1 and has an index of 1, which means it's the second plot in this figure.
25. This plot will have two axes: x-axis and y-axis.
26. The x-axis represents time, while the y-axis represents accuracy percentage (0% to 100%).
27. The second subplot is created with fig_2 and has an index of 2, which means it's the third plot in this figure.
28. This plot will also have two axes: x-axis and y-axis but they represent different values than those on fig_1 .
29. The code is a function that takes in an input of predicted and returns the accuracy, cross entropy, and KL
values.
30. The first line of code calculates the size of the tensor using target_tensor.size(0) which will be equal to 1
because it is a one-dimensional tensor.
31. Next, we have the function draw_graph which draws a graph with two subplots; one for accuracy and one for
cross entropy.
32. The last line prints out some statistics on how accurate this prediction was.

PROGRAM

# Install torchbnn if not already installed


!pip install torchbnn

# Install PyTorch if not installed


!pip install torch torchvision torchaudio
!pip install matplotlib

import numpy as np
import torch
import torch.nn as nn
import torch.optim as optim
import torchbnn as bnn
import matplotlib.pyplot as plt
from sklearn import datasets

# Load the Iris dataset


37
dataset = datasets.load_iris()
data = dataset.data
target = dataset.target

# Convert to tensors
data_tensor = torch.from_numpy(data).float()
target_tensor = torch.from_numpy(target).long()

# Define the Bayesian Neural Network model


model = nn.Sequential(
bnn.BayesLinear(prior_mu=0, prior_sigma=0.1, in_features=4, out_features=100),
nn.ReLU(),
bnn.BayesLinear(prior_mu=0, prior_sigma=0.1, in_features=100, out_features=3)
)

# Loss functions
cross_entropy_loss = nn.CrossEntropyLoss()
klloss = bnn.BKLLoss(reduction='mean', last_layer_only=False)

# Hyperparameters
klweight = 0.01
optimizer = optim.Adam(model.parameters(), lr=0.01)

# Training the model


for step in range(3000):
model.train() # Set the model to training mode

# Forward pass
models = model(data_tensor)

# Compute the cross-entropy loss


cross_entropy = cross_entropy_loss(models, target_tensor)

# Compute the Kullback-Leibler divergence loss


kl = klloss(model)

38
# Total loss
total_cost = cross_entropy + klweight * kl

# Zero the gradients, perform the backward pass, and update the weights
optimizer.zero_grad()
total_cost.backward()
optimizer.step()

# Print the accuracy and loss every 300 steps


if step % 300 == 0:
# Get predictions
_, predicted = torch.max(models.data, 1)

# Calculate accuracy
final = target_tensor.size(0)
correct = (predicted == target_tensor).sum().item()
accuracy = 100 * float(correct) / final

print(f'- Accuracy: {accuracy:.2f}%')


print(f'- CE : {cross_entropy.item():.2f}, KL : {kl.item():.2f}')

# Evaluate the model and plot the results


def draw_graph(predicted):
fig = plt.figure(figsize=(16, 8))

# Real data
fig_1 = fig.add_subplot(1, 2, 1)
z1_plot = fig_1.scatter(data[:, 0], data[:, 1], c=target, marker='v')
plt.colorbar(z1_plot, ax=fig_1)
fig_1.set_title("REAL")

# Predicted data
fig_2 = fig.add_subplot(1, 2, 2)
z2_plot = fig_2.scatter(data[:, 0], data[:, 1], c=predicted, marker='v')
plt.colorbar(z2_plot, ax=fig_2)
fig_2.set_title("PREDICT")
39
plt.show()

# Test the model


model.eval() # Set the model to evaluation mode
with torch.no_grad():
models = model(data_tensor)
_, predicted = torch.max(models.data, 1)

# Plot the results


draw_graph(predicted)

OUTPUT:

- Accuracy: 33.33%
- CE : 2.31, KL : 2.91
- Accuracy: 95.33%
- CE : 0.14, KL : 3.19
- Accuracy: 95.33%
- CE : 0.10, KL : 3.74
- Accuracy: 98.00%
- CE : 0.06, KL : 3.79
- Accuracy: 94.00%
- CE : 0.16, KL : 3.86
- Accuracy: 98.00%
- CE : 0.06, KL : 3.76
- Accuracy: 98.00%
- CE : 0.06, KL : 3.62
- Accuracy: 98.67%
- CE : 0.05, KL : 3.47
- Accuracy: 98.67%
- CE : 0.06, KL : 3.34
- Accuracy: 98.67%
- CE : 0.06, KL : 3.24

40
RESULT

Thus, the program to implement Bayesian Networks and perform inferences is implemented and executed
successfully.

41

You might also like