EXPERIMENT NO.
-1
AIM:
Write a Program to Implement Water-Jug problem.
PROGRAM:
from collections import deque
# Function to find the minimum operations to obtain d liters in one jug
def min_steps(m, n, d):
if d > max(m, n):
return -1
# Queue for BFS: (jug1, jug2, steps)
q = deque([(0, 0, 0)])
# For tracking the visited states
visited = [[False] * (n + 1) for _ in range(m + 1)]
visited[0][0] = True
while q:
jug1, jug2, steps = q.popleft()
if jug1 == d or jug2 == d:
return steps
# 1: Fill jug1
if not visited[m][jug2]:
visited[m][jug2] = True
q.append((m, jug2, steps + 1))
# 2: Fill jug2
if not visited[jug1][n]:
visited[jug1][n] = True
q.append((jug1, n, steps + 1))
# 3: Empty jug1
if not visited[0][jug2]:
visited[0][jug2] = True
q.append((0, jug2, steps + 1))
1
# 4: Empty jug2
if not visited[jug1][0]:
visited[jug1][0] = True
q.append((jug1, 0, steps + 1))
# 5: Pour jug1 into jug2
pour1to2 = min(jug1, n - jug2)
if not visited[jug1 - pour1to2][jug2 + pour1to2]:
visited[jug1 - pour1to2][jug2 + pour1to2] = True
q.append((jug1 - pour1to2, jug2 + pour1to2, steps + 1))
# 6: Pour jug2 into jug1
pour2to1 = min(jug2, m - jug1)
if not visited[jug1 + pour2to1][jug2 - pour2to1]:
visited[jug1 + pour2to1][jug2 - pour2to1] = True
q.append((jug1 + pour2to1, jug2 - pour2to1, steps + 1))
return -1
if __name__ == "__main__":
vol1 = int(input("Enter Volume of first jug: "))
vol2 = int(input("Enter Volume of second jug: "))
reqVol = int(input("Enter the required Volume in a jug: "))
result = min_steps(vol1, vol2, reqVol)
print()
if (result == -1):
print("This operation cannot be performed")
else:
print("Minimum operations to obtain", reqVol, "liters in one jug:", result)
OUTPUT:
2
EXPERIMENT NO.-2
AIM:
Write a Program to Implement Tower of Hanoi.
PROGRAM:
# Recursive Python function to solve tower of hanoi
def TowerOfHanoi(n, from_rod, to_rod, aux_rod):
if n == 0:
return
TowerOfHanoi(n-1, from_rod, aux_rod, to_rod)
print("Move disk", n, "from rod", from_rod, "to rod", to_rod)
TowerOfHanoi(n-1, aux_rod, to_rod, from_rod)
# Driver code
N=3
# A, B, C are the name of rods
TowerOfHanoi(N, 'A', 'C', 'B')
OUTPUT:
3
EXPERIMENT NO.-3
AIM:
Write a Program to Implement 8-Puzzle problem.
PROGRAM:
import copy
from heapq import heappush, heappop
n=3
row = [ 1, 0, -1, 0 ]
col = [ 0, -1, 0, 1 ]
class priorityQueue:
def __init__(self):
self.heap = []
def push(self, k):
heappush(self.heap, k)
def pop(self):
return heappop(self.heap)
def empty(self):
if not self.heap:
return True
else:
return False
class node:
def __init__(self, parent, mat, empty_tile_pos, cost, level):
self.parent = parent
self.mat = mat
self.empty_tile_pos = empty_tile_pos
self.cost = cost
self.level = level
def __lt__(self, nxt):
return self.cost < nxt.cost
4
def calculateCost(mat, final) -> int:
count = 0
for i in range(n):
for j in range(n):
if ((mat[i][j]) and
(mat[i][j] != final[i][j])):
count += 1
return count
def newNode(mat, empty_tile_pos, new_empty_tile_pos, level, parent, final) -> node:
new_mat = copy.deepcopy(mat)
x1 = empty_tile_pos[0]
y1 = empty_tile_pos[1]
x2 = new_empty_tile_pos[0]
y2 = new_empty_tile_pos[1]
new_mat[x1][y1], new_mat[x2][y2] = new_mat[x2][y2], new_mat[x1][y1]
cost = calculateCost(new_mat, final)
new_node = node(parent, new_mat, new_empty_tile_pos, cost, level)
return new_node
def printMatrix(mat):
for i in range(n):
for j in range(n):
print("%d " % (mat[i][j]), end = " ")
print()
def isSafe(x, y):
return x >= 0 and x < n and y >= 0 and y < n
def printPath(root):
if root == None:
return
printPath(root.parent)
printMatrix(root.mat)
5
print()
def solve(initial, empty_tile_pos, final):
pq = priorityQueue()
cost = calculateCost(initial, final)
root = node(None, initial, empty_tile_pos, cost, 0)
pq.push(root)
while not pq.empty():
minimum = pq.pop()
if minimum.cost == 0:
printPath(minimum)
return
for i in range(4):
new_tile_pos = [
minimum.empty_tile_pos[0] + row[i],
minimum.empty_tile_pos[1] + col[i], ]
if isSafe(new_tile_pos[0], new_tile_pos[1]):
child = newNode(minimum.mat, minimum.empty_tile_pos, new_tile_pos,
minimum.level + 1, minimum, final,)
pq.push(child)
initial = [ [ 1, 2, 3 ],
[ 8, 6, 0 ],
[ 7, 5, 4 ] ]
final = [ [ 1, 2, 3 ],
[ 8, 0, 4 ],
[ 7, 6, 5 ] ]
empty_tile_pos = [ 1, 2 ]
solve(initial, empty_tile_pos, final)
6
OUTPUT:
7
EXPERIMENT NO.-4
AIM:
Write a Program to Implement Breadth First Search.
PROGRAM:
from collections import deque
def bfs(adj, s, visited):
q = deque()
visited[s] = True
q.append(s)
while q:
curr = q.popleft()
print(curr, end=" ")
for x in adj[curr]:
if not visited[x]:
visited[x] = True
q.append(x)
def add_edge(adj, u, v):
adj[u].append(v)
adj[v].append(u) # Undirected graph
# Perform BFS for the entire graph
def bfs_disconnected(adj):
visited = [False] * len(adj)
for i in range(len(adj)):
if not visited[i]:
bfs(adj, i, visited)
V=5
adj = [[] for _ in range(V)]
8
# Add edges to the graph
add_edge(adj, 0, 1)
add_edge(adj, 0, 4)
add_edge(adj, 1, 2)
add_edge(adj, 1, 4)
add_edge(adj, 2, 3)
add_edge(adj, 2, 4)
add_edge(adj, 3, 4)
# Perform BFS traversal for the entire graph
print("BFS Traversal of given graph:")
bfs_disconnected(adj)
OUTPUT:
9
EXPERIMENT NO.-5
AIM:
Write a Program to Implement Depth First Search.
PROGRAM:
class Graph:
def __init__(self, vertices):
self.adj = [[] for _ in range(vertices)]
def add_edge(self, s, t):
self.adj[s].append(t)
self.adj[t].append(s)
def dfs_rec(self, visited, s):
visited[s] = True
print(s, end=" ")
for i in self.adj[s]:
if not visited[i]:
self.dfs_rec(visited, i)
def dfs(self):
visited = [False] * len(self.adj)
# Loop through all vertices to handle disconnected graph
for i in range(len(self.adj)):
if not visited[i]:
self.dfs_rec(visited, i)
if __name__ == "__main__":
# Number of vertices
V=5
graph = Graph(V)
# Define the edges of the graph
edges = [(0, 1), (0, 4), (1, 2), (1, 4), (2, 3), (2, 4), (3, 4)]
10
# Populate the adjacency list with edges
for edge in edges:
graph.add_edge(edge[0], edge[1])
# Perform DFS
print("DFS Traversal of given graph:")
graph.dfs()
OUTPUT:
11
EXPERIMENT NO.-6
AIM:
Write a Program to Implement A* algorithm.
PROGRAM:
import math
import heapq
class Cell:
def __init__(self):
self.parent_i = 0
self.parent_j = 0
# Total cost of the cell (g + h)
self.f = float('inf')
# Cost from start to this cell
self.g = float('inf')
# Heuristic cost from this cell to destination
self.h = 0
# Define the size of the grid
ROW = 4
COL = 8
def is_valid(row, col):
return (row >= 0) and (row < ROW) and (col >= 0) and (col < COL)
def is_unblocked(grid, row, col):
return grid[row][col] == 1
def is_destination(row, col, dest):
return row == dest[0] and col == dest[1]
def calculate_h_value(row, col, dest):
return ((row - dest[0]) ** 2 + (col - dest[1]) ** 2) ** 0.5
def trace_path(cell_details, dest):
print("The Path is ")
path = []
12
row = dest[0]
col = dest[1]
# Trace the path from destination to source using parent cells
while not (cell_details[row][col].parent_i == row and cell_details[row][col].parent_j == col):
path.append((row, col))
temp_row = cell_details[row][col].parent_i
temp_col = cell_details[row][col].parent_j
row = temp_row
col = temp_col
# Add the source cell to the path
path.append((row, col))
# Reverse the path to get the path from source to destination
path.reverse()
# Print the path
for i in path:
print("->", i, end=" ")
print()
def a_star_search(grid, src, dest):
# Check if the source and destination are valid
if not is_valid(src[0], src[1]) or not is_valid(dest[0], dest[1]):
print("Source or destination is invalid")
return
# Check if the source and destination are unblocked
if not is_unblocked(grid, src[0], src[1]) or not is_unblocked(grid, dest[0], dest[1]):
print("Source or the destination is blocked")
return
# Check if we are already at the destination
if is_destination(src[0], src[1], dest):
print("We are already at the destination")
return
# Initialize the closed list (visited cells)
closed_list = [[False for _ in range(COL)] for _ in range(ROW)]
13
# Initialize the details of each cell
cell_details = [[Cell() for _ in range(COL)] for _ in range(ROW)]
# Initialize the start cell details
i = src[0]
j = src[1]
cell_details[i][j].f = 0
cell_details[i][j].g = 0
cell_details[i][j].h = 0
cell_details[i][j].parent_i = i
cell_details[i][j].parent_j = j
# Initialize the open list (cells to be visited) with the start cell
open_list = []
heapq.heappush(open_list, (0.0, i, j))
# Initialize the flag for whether destination is found
found_dest = False
# Main loop of A* search algorithm
while len(open_list) > 0:
# Pop the cell with the smallest f value from the open list
p = heapq.heappop(open_list)
# Mark the cell as visited
i = p[1]
j = p[2]
closed_list[i][j] = True
# For each direction, check the successors
directions = [(0, 1), (0, -1), (1, 0), (-1, 0),
(1, 1), (1, -1), (-1, 1), (-1, -1)]
for dir in directions:
new_i = i + dir[0]
new_j = j + dir[1]
# If the successor is valid, unblocked, and not visited
if is_valid(new_i, new_j) and is_unblocked(grid, new_i, new_j) and not
closed_list[new_i][new_j]:
# If the successor is the destination
14
if is_destination(new_i, new_j, dest):
# Set the parent of the destination cell
cell_details[new_i][new_j].parent_i = i
cell_details[new_i][new_j].parent_j = j
print("The destination cell is found")
# Trace and print the path from source to destination
trace_path(cell_details, dest)
found_dest = True
return
else:
# Calculate the new f, g, and h values
g_new = cell_details[i][j].g + 1.0
h_new = calculate_h_value(new_i, new_j, dest)
f_new = g_new + h_new
# If the cell is not in the open list or the new f value is smaller
if cell_details[new_i][new_j].f == float('inf') or cell_details[new_i][new_j].f >
f_new:
# Add the cell to the open list
heapq.heappush(open_list, (f_new, new_i, new_j))
# Update the cell details
cell_details[new_i][new_j].f = f_new
cell_details[new_i][new_j].g = g_new
cell_details[new_i][new_j].h = h_new
cell_details[new_i][new_j].parent_i = i
cell_details[new_i][new_j].parent_j = j
# If the destination is not found after visiting all cells
if not found_dest:
print("Failed to find the destination cell")
def main():
# Define the grid (1 for unblocked, 0 for blocked)
grid = [
[1, 1, 1, 1, 0, 0, 0, 0],
[1, 1, 1, 1, 1, 0, 0, 0],
[0, 0, 1, 0, 0, 1, 1, 1],
[0, 1, 1, 1, 1, 1, 1, 1]
]
15
# Define the source and destination
src = [0, 0]
dest = [3, 7]
# Run the A* search algorithm
a_star_search(grid, src, dest)
if __name__ == "__main__":
main()
OUTPUT:
16
EXPERIMENT NO.-7
AIM:
Write a program to demonstrate the working of the decision tree based ID3. Use an
appropriate data set for building the decision tree and apply this knowledge to
classify a new sample.
PROGRAM:
import numpy as np
import math
import csv
def read_data(filename):
with open(filename, 'r') as csvfile:
datareader = csv.reader(csvfile, delimiter=',')
headers = next(datareader)
metadata = []
traindata = []
for name in headers:
metadata.append(name)
for row in datareader:
traindata.append(row)
return (metadata, traindata)
class Node:
def __init__(self, attribute):
self.attribute = attribute
self.children = []
self.answer = ""
def __str__(self):
return self.attribute
def subtables(data, col, delete):
dict = {}
items = np.unique(data[:, col])
count = np.zeros((items.shape[0], 1), dtype=np.int32)
17
for x in range(items.shape[0]):
for y in range(data.shape[0]):
if data[y, col] == items[x]:
count[x] += 1
for x in range(items.shape[0]):
dict[items[x]] = np.empty((int(count[x]), data.shape[1]), dtype="|S32")
pos = 0
for y in range(data.shape[0]):
if data[y, col] == items[x]:
dict[items[x]][pos] = data[y]
pos += 1
if delete:
dict[items[x]] = np.delete(dict[items[x]], col, 1)
return items, dict
def entropy(S):
items = np.unique(S)
if items.size == 1:
return 0
counts = np.zeros((items.shape[0], 1))
sums = 0
for x in range(items.shape[0]):
counts[x] = sum(S == items[x]) / (S.size * 1.0)
for count in counts:
sums += -1 * count * math.log(count, 2)
return sums
def gain_ratio(data, col):
items, dict = subtables(data, col, delete=False)
total_size = data.shape[0]
entropies = np.zeros((items.shape[0], 1))
intrinsic = np.zeros((items.shape[0], 1))
18
for x in range(items.shape[0]):
ratio = dict[items[x]].shape[0]/(total_size * 1.0)
entropies[x] = ratio * entropy(dict[items[x]][:, -1])
intrinsic[x] = ratio * math.log(ratio, 2)
total_entropy = entropy(data[:, -1])
iv = -1 * sum(intrinsic)
for x in range(entropies.shape[0]):
total_entropy -= entropies[x]
return total_entropy / iv
def create_node(data, metadata):
if (np.unique(data[:, -1])).shape[0] == 1:
node = Node("")
node.answer = np.unique(data[:, -1])[0]
return node
gains = np.zeros((data.shape[1] - 1, 1))
for col in range(data.shape[1] - 1):
gains[col] = gain_ratio(data, col)
split = np.argmax(gains)
node = Node(metadata[split])
metadata = np.delete(metadata, split, 0)
items, dict = subtables(data, split, delete=True)
for x in range(items.shape[0]):
child = create_node(dict[items[x]], metadata)
node.children.append((items[x], child))
return node
def empty(size):
s = ""
for x in range(size):
19
s += " "
return s
def print_tree(node, level):
if node.answer != "":
print(empty(level), node.answer)
return
print(empty(level), node.attribute)
for value, n in node.children:
print(empty(level + 1), value)
print_tree(n, level + 2)
metadata, traindata = read_data("data.csv")
data = np.array(traindata)
node = create_node(data, metadata)
print_tree(node, 0)
OUTPUT:
20
EXPERIMENT NO.-8
AIM:
Write a program to implement the naïve Bayesian classifier algorithm.
PROGRAM:
import pandas as pd
from sklearn import tree
from sklearn.preprocessing import LabelEncoder
from sklearn.naive_bayes import GaussianNB
# load data from CSV
data = pd.read_csv('data.csv')
print("The first 5 values of data is :\n",data.head())
# obtain Train data and Train output
X = data.iloc[:,:-1]
print("\nThe First 5 values of train data is\n",X.head())
y = data.iloc[:,-1]
print("\nThe first 5 values of Train output is\n",y.head())
# Convert them in numbers
le_outlook = LabelEncoder()
X.Outlook = le_outlook.fit_transform(X.Outlook)
le_Temperature = LabelEncoder()
X.Temperature = le_Temperature.fit_transform(X.Temperature)
le_Humidity = LabelEncoder()
X.Humidity = le_Humidity.fit_transform(X.Humidity)
le_Windy = LabelEncoder()
X.Windy = le_Windy.fit_transform(X.Windy)
print("\nNow the Train data is :\n",X.head())
le_PlayTennis = LabelEncoder()
y = le_PlayTennis.fit_transform(y)
print("\nNow the Train output is\n",y)
from sklearn.model_selection import train_test_split
X_train, X_test, y_train, y_test = train_test_split(X,y, test_size=0.20)
21
classifier = GaussianNB()
classifier.fit(X_train,y_train)
from sklearn.metrics import accuracy_score
print("Accuracy is:",accuracy_score(classifier.predict(X_test),y_test))
OUTPUT:
22
EXPERIMENT NO.-9
AIM:
Write a program to implement k-Nearest Neighbour algorithm.
PROGRAM:
from sklearn.datasets import load_iris
from sklearn.neighbors import KNeighborsClassifier
from sklearn.model_selection import train_test_split
import numpy as np
dataset=load_iris()
X_train,X_test,y_train,y_test=train_test_split(dataset["data"],dataset["target"],random_state=0)
kn=KNeighborsClassifier(n_neighbors=1)
kn.fit(X_train,y_train)
for i in range(len(X_test)):
x=X_test[i]
x_new=np.array([x])
prediction=kn.predict(x_new)
print("TARGET=",y_test[i],dataset["target_names"][y_test[i]],"PREDICTED=",prediction,datas
et["target_names"][prediction])
print(kn.score(X_test,y_test))
23
OUTPUT:
24
EXPERIMENT NO.-10
AIM:
Build an Artificial Neural Network by implementing the Backpropagation
algorithm and test the same using appropriate data sets.
PROGRAM:
import numpy as np
X = np.array(([2, 9], [1, 5], [3, 6]), dtype=float) # X = (hours sleeping, hours studying)
y = np.array(([92], [86], [89]), dtype=float) # y = score on test
# scale units
X = X/np.amax(X, axis=0) # maximum of X array
y = y/100 # max test score is 100
class Neural_Network(object):
def __init__(self):
# Parameters
self.inputSize = 2
self.outputSize = 1
self.hiddenSize = 3
# Weights
self.W1 = np.random.randn(self.inputSize, self.hiddenSize) # (3x2) weight matrix from
input to hidden layer
self.W2 = np.random.randn(self.hiddenSize, self.outputSize) # (3x1) weight matrix from
hidden to output layer
def forward(self, X):
#forward propagation through our network
self.z = np.dot(X, self.W1) # dot product of X (input) and first set of 3x2 weights
self.z2 = self.sigmoid(self.z) # activation function
self.z3 = np.dot(self.z2, self.W2) # dot product of hidden layer (z2) and second set of
3x1 weights
o = self.sigmoid(self.z3) # final activation function
return o
def sigmoid(self, s):
return 1/(1+np.exp(-s)) # activation function
25
def sigmoidPrime(self, s):
return s * (1 - s) # derivative of sigmoid
def backward(self, X, y, o):
# backward propgate through the network
self.o_error = y - o # error in output
self.o_delta = self.o_error*self.sigmoidPrime(o) # applying derivative of sigmoid to
self.z2_error = self.o_delta.dot(self.W2.T) # z2 error: how much our hidden layer weights
contributed to output error
self.z2_delta = self.z2_error*self.sigmoidPrime(self.z2) # applying derivative of sigmoid to
z2 error
self.W1 += X.T.dot(self.z2_delta) # adjusting first set (input --> hidden) weights
self.W2 += self.z2.T.dot(self.o_delta) # adjusting second set (hidden --> output) weights
def train (self, X, y):
o = self.forward(X)
self.backward(X, y, o)
NN = Neural_Network()
print ("\nInput: \n" + str(X))
print ("\nActual Output: \n" + str(y))
print ("\nPredicted Output: \n" + str(NN.forward(X)))
print ("\nLoss: \n" + str(np.mean(np.square(y - NN.forward(X))))) # mean sum squared loss)
NN.train(X, y)
OUTPUT:
26