0% found this document useful (0 votes)
19 views23 pages

DAA Lab Manual

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)
19 views23 pages

DAA Lab Manual

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/ 23

Ex no.

: 1 DIVIDE AND CONQURE – STRASSEN’S MATRIX MULTIPLICATION

Date:

AIM
To do Divide and Conquer - Strassen's Matrix Multiplication

ALGORITHM
Step 1: Start the program.
Step 2: create a matrix A and B
Step 3: Divide matrix A and matrix B into 4 sub-matrices of size N/2 x N/2 as shown in the above diagram. Step 4:
Calculate the 7 matrix multiplications recursively.
Step 5: Compute the submatrices of C.
Step 6: Combine these submatrices into our new matrix C Step 7: End
the program

PROGRAM

import numpy as np
def strassen_algorithm(x, y):
if x.size == 1 or y.size == 1: return x * y
n = x.shape[0] if n % 2
== 1:
x = np.pad(x, (0, 1), mode='constant')
y = np.pad(y, (0, 1), mode='constant') m =
int(np.ceil(n / 2))
a = x[: m, : m]
b = x[: m, m:]
c = x[m:, : m]
d = x[m:, m:]
e = y[: m, : m]
f = y[: m, m:]
g = y[m:, : m]
h = y[m:, m:]
p1 = strassen_algorithm(a, f - h) p2 =
strassen_algorithm(a + b, h) p3 =
strassen_algorithm(c + d, e) p4 =
strassen_algorithm(d, g - e)
p5 = strassen_algorithm(a + d, e + h)
p6 = strassen_algorithm(b - d, g + h)
p7 = strassen_algorithm(a - c, e + f)
result = np.zeros((2 * m, 2 * m), dtype=np.int32)
result[: m, : m] = p5 + p4 - p2 + p6
result[: m, m:] = p1 + p2
result[m:, : m] = p3 + p4
result[m:, m:] = p1 + p5 - p3 - p7
return result[: n, : n]
#input of two matrix
x = np.array([[1, 1, 1, 1], [2, 2, 2, 2], [3, 3, 3, 3], [2, 2, 2, 2]])
y = np.array([[1, 1, 1, 1], [2, 2, 2, 2], [3, 3, 3, 3], [2, 2, 2, 2]])
print('Matrix multiplication result: ')
print(strassen_algorithm(x, y))

OUTPUT

Matrix multiplication result:


[[ 8 8 8 8]
[16 16 16 16]
[24 24 24 24]
[16 16 16 16]]

RESULT
The above program has been executed successfully and the required output is displayed
Ex no.: 2 Date: DIVIDE AND CONQUER – TOPOLOGICAL SORTING

AIM
To implement Decrease and Conquer - Topological Sorting

ALGORITHM
Step 1: Create a stack to store the nodes.
Step 2: Initialize visited an array of size N to keep the record of visited nodes. Step 3: Run
a loop from 0 to N
Step 4: if the node is not marked True in the visited array
Step 5: Call the recursive function for topological sort and perform the following steps. Step 6:
Mark the current node as True in the visited array.
Step 7: Run a loop on all the nodes which have a directed edge to the current node Step 8: if
the node is not marked True in the visited array:
Recursively call the topological sort function on the node and Push the current node in the stack.
Step 9: Print all the elements in the stack.

PROGRAM

# Python program to print topological sorting of a DAG from


collections import defaultdict
# Class to represent a graph class
Graph:
def init (self, vertices):
self.graph = defaultdict(list) # dictionary containing adjacency List self.V =
vertices # No. of vertices
# function to add an edge to graph def
addEdge(self, u, v):
self.graph[u].append(v)
# A recursive function used by topologicalSort def
topologicalSortUtil(self, v, visited, stack):
# Mark the current node as visited. visited[v] =
True
# Recur for all the vertices adjacent to this vertex for i
in self.graph[v]:
if visited[i] == False: self.topologicalSortUtil(i,
visited, stack)
# Push current vertex to stack which stores result
stack.append(v)
# The function to do Topological Sort. It uses recursive #
topologicalSortUtil()
def topologicalSort(self):
# Mark all the vertices as not visited
visited = [False]*self.V
stack = []
# Call the recursive helper function to store Topological
# Sort starting from all vertices one by one
for i in range(self.V):
if visited[i] == False:
self.topologicalSortUtil(i, visited, stack)
# Print contents of the stack
print(stack[::-1]) # return list in reverse order
g = Graph(6)
g.addEdge(5, 2)
g.addEdge(5, 0)
g.addEdge(4, 0)
g.addEdge(4, 1)
g.addEdge(2, 3)
g.addEdge(3, 1)
print ("Topological Sort of the given graph")
g.topologicalSort()

OUTPUT

Topological Sort of the given graph


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

RESULT
The above program has been executed successfully and the required output is displayed
Ex no.: 3 Date: TEANSFORM AND CONQUER – HEAP SORT

AIM
To write a python program to Transform and Conquer - Heap Sort

ALGORITHM
Step 1: First convert the array into a heap data structure using heapify,
Step 2: one by one delete the root node of the Max-heap and replace it with the last node in the heap and then heapify the
root of the heap.
Step 3: Repeat this process until the size of the heap is greater than 1. Step 4: Build
a max heap from the input data.
Step 5: At this point, the maximum element is stored at the root of the heap. Step 6: Replace it with the last item of the
heap followed by reducing the size of the heap by 1.
Step 7: Finally, heapify the root of the tree.
Step 8: Repeat step 2 while the size of the heap is greater than 1.

PROGRAM

def heapify(arr, n, i):


largest = i
l=2*i+1r=2*i+
2
if l < n and arr[i] < arr[l]: largest = l
if r < n and arr[largest] < arr[r]: largest = r
if largest != i:
(arr[i], arr[largest]) = (arr[largest], arr[i]) # swap
heapify(arr, n, largest)
def heapSort(arr): n =
len(arr)
for i in range(n // 2 - 1, -1, -1): heapify(arr, n, i)
for i in range(n - 1, 0, -1):
(arr[i], arr[0]) = (arr[0], arr[i]) # swap heapify(arr, i, 0)
arr = [12, 11, 13, 5, 6, 7, ]
heapSort(arr) n =
len(arr)
print('Sorted array is')
for i in range(n):
print(arr[i])

OUTPUT

Sorted array is
5
6
7
11
12
13

RESULT
The above program has been executed successfully and the required output is displayed.
DYNAMIC PROGRAMMING – COIN CHANGING PROBLEM,
Ex no.: 4 Date:
WARSHALL’S AND FLOYD’S ALAGRITHMS, KNAPSACK
PROBLEM

AIM
To write a python program to implement Dynamic programming - Coin change Problem, Warshall's and Floyd's
algorithms, Knapsack Problem

ALGORITHM
Coinbase Problem
Step 1: Start the program.
Step 2: Create a 2-D vector to store the Overlapping Solutions
Step 3: Keep Track of the overlapping subproblems while Traversing the array of coins Step 4:
Recall them whenever needed
Step 5: End the program

Floyd's Warshall algorithm


Step 1: Start the program.
Step 2: Initialize the solution matrix the same as the input graph matrix as a first step.
Step 3: Then update the solution matrix by considering all vertices as an intermediate vertex.
Step 4: The idea is to one by one pick all vertices and updates all shortest paths which include the picked vertex as an
intermediate vertex in the shortest path.
Step 5: When we pick vertex number k as an intermediate vertex, we already have considered vertices {0, 1, 2, .. k-1} as
intermediate vertices.
Step 6: For every pair (i, j) of the source and destination vertices respectively, there are two possible cases.
Step 7: k is not an intermediate vertex in the shortest path from i to j. We keep the value of dist[i][j] as it is.
Step 8: k is an intermediate vertex in the shortest path from i to j. We update the value of dist[i][j] as dist[i][k] +
dist[k][j] if dist[i][j] > dist[i][k] + dist[k][j]
Step 9: End the program

Knapsack Problem
Step 1: Start the program. Step 2: Start
the program.
Step 3: The maximum value obtained from ‘N’ items is the max of the following two values.
Step 4: Maximum value obtained by N-1 items and W weight (excluding nth item)
Step 5: Value of nth item plus maximum value obtained by N-1 items and W minus the weight of the Nth
item (including Nth item)
Step 6: If the weight of the ‘Nth’ item is greater than ‘W’, then the Nth item cannot be included and Case 1 is
the only possibility.
Step 7: End the program

PROGRAM

Coin change Problem


def count(S, m, n):
table = [[0 for x in range(m)] for x in range(n+1)]
for i in range(m):
table[0][i] = 1
for i in range(1, n+1):
for j in range(m):
x = table[i - S[j]][j] if i-S[j] >= 0 else 0
y = table[i][j-1] if j >= 1 else 0
table[i][j] = x + y
return table[n][m-1]
arr = [1, 2, 3]
m = len(arr)
n=4
print(count(arr, m, n))

Warshall’s and Floyd‘s algorithms

nV = 4
INF = 999
def floyd(G):
dist = list(map(lambda p: list(map(lambda q: q, p)), G))
for r in range(nV):
for p in range(nV):
for q in range(nV):
dist[p][q] = min(dist[p][q], dist[p][r] + dist[r][q])
sol(dist)
def sol(dist):
for p in range(nV):
for q in range(nV):
if(dist[p][q] == INF):
print("INF", end=" ")
else:
print(dist[p][q], end=" ")
print(" ")
G = [[0, 5, INF, INF],
[50, 0, 15, 5],
[30, INF, 0, 15],
[15, INF, 5, 0]]
floyd(G)

Output
0 5 15 10
20 0 10 5
30 35 0 15
15 20 5 0

knapsack problem

def knapSack(W, wt, val, n):


K = [[0 for x in range(W + 1)] for x in range(n + 1)]
for i in range(n + 1):
for w in range(W + 1):
if i == 0 or w == 0:
K[i][w] = 0
elif wt[i-1] <= w:
K[i][w] = max(val[i-1]
+ K[i-1][w-wt[i-1]],
K[i-1][w])
else:
K[i][w] = K[i-1][w]

return K[n][W]
val = [60, 100, 120]
wt = [10, 20, 30]
W = 50
n = len(val)
print(knapSack(W, wt, val, n))

OUTPUT:
220
RESULT
The above program has been executed successfully and the required output is displayed.
Ex no.: 5 Date: GREEDY TECHNIQUE – DIJKSTRA’S ALGORITHM,
HUFFMAN TREES, AND CODES

AIM
To write a python program to implement Greedy Technique - Dijkstra's algorithm, Huffman Trees, and codes

ALGORITHM
Step 1: Create a set sptSet (shortest path tree set) that keeps track of vertices included in the
shortest path tree.

Step 2: Assign a distance value to all vertices in the input graph. Initialize all distance values
as INFINITE.

Step 3: Assign the distance value as 0 for the source vertex so that it is picked first. Step 4: While

sptSet doesn’t include all vertices:

Step 5: Pick a vertex u that is not there in sptSet and has a minimum distance value. Step 6: Include

u to sptSet7.

Step 7: Update the distance value of all adjacent vertices of u. To update the distance values,
iterate through all adjacent vertices. For every adjacent vertex v, if the sum of a distance value of
u (from source) and weight of edge u-v, is less than the distance value of v, then update the
distance value of v.

PROGRAM

Dijkstra’s algorithm

num_of_vertex = 7
def minimumDistance(distance, visited):
_min = 1e11 min_index = 1e11
for i in range(num_of_vertex):
if not visited[i] and distance[i] & lt; = _min:
_min = distance[i]
min_index = i
return min_index
def printParentNode(parent, i):
if parent[i] == -1:
return
printParentNode(parent, parent[i])
print("{} ".format(i + 1), end = "")
def dijkstra(graph, src):
distance = list()
visited = list()
parent = list()
for i in range(num_of_vertex):
parent.append(-1)
distance.append(1e11)
visited.append(False)
distance[src] = 0
for i in range(num_of_vertex - 1):
U = minimumDistance(distance, visited)
visited[U] = True
for j in range(num_of_vertex):
curr_distance = distance[U] + graph[U][j]
if not visited[j] and graph[U][j] and curr_distance & lt;
distance[j]: parent[j] = U
distance[j] = curr_distance
print("Vertex\t\tDistance\tPath")
for i in range(num_of_vertex):
print("{}->{}\t\t{}\t\t{}
".format(src + 1, i + 1, distance[i], src + 1), end = "")
printParentNode(parent, i)
print("")
graph = [

[0, 1, 7, 6, 0, 0, 0],
[1, 0, 9, 0, 0, 3, 0],
[7, 9, 0, 0, 0, 0, 1],
[6, 0, 0, 0, 2, 0, 0],
[0, 0, 0, 2, 0, 0, 0],
[0, 3, 0, 0, 0, 0, 3],
[0, 0, 0, 0, 5, 3, 0]
]
dijkstra(graph, 0)

Output:
Vertex Distance Path

1->1 0 1
1->2 1 1 2
1->3 7 1 3
1->4 6 1 4
1->5 8 1 4 5
1->6 4 1 2 6
1->7 7 1 2 6 7

Huffman Trees and codes


from collections import Counter
class NodeTree(object):
def init (self, left=None, right=None):
self.left = left
self.right = right
def children(self):
return self.left, self.right
def str (self):
return self.left, self.right
def huffman_code_tree(node, binString=''):
if type(node) is str:
return {node: binString}
(l, r) = node.children()
d = dict()
d.update(huffman_code_tree(l, binString + '0'))
d.update(huffman_code_tree(r, binString + '1'))
return d
def make_tree(nodes):

while len(nodes) > 1:


(key1, c1) = nodes[-1]
(key2, c2) = nodes[-2]
nodes = nodes[:-2]
node = NodeTree(key1, key2)
nodes.append((node, c1 + c2))
nodes = sorted(nodes, key=lambda x: x[1], reverse=True)
return nodes[0][0]
if name == ' main ':
string = 'BCAADDDCCACACAC'
freq = dict(Counter(string))
freq = sorted(freq.items(), key=lambda x: x[1], reverse=True)
node = make_tree(freq)
encoding = huffman_code_tree(node)
for i in encoding:
print(f'{i} : {encoding[i]}

RESULT
The above program has been executed successfully and the required output is displayed
Ex no.: 6 Date:
ITERATIVE IMPROVEMENT – SIMPLEX METHOD

AIM
To write a program to implement Iterative improvement - Simplex Method.

ALGORITHM
Step 1: Start with the initial basis associated with the identity matrix. Step 2:
Calculate the relative profits.

For MAX problem-


If all the relative profits are less than or equal to 0, then the current basis is the optimal one. STOP. Else continue
to 3.

For MIN problem


If all the relative profits are greater than or equal to 0, then the current basis is the optimal one. STOP. Else
continue to 3.

Step 3: Find the column corresponding to max relative profit. Say column k has the max Rel. profit. So
xk will enter the basis.

Step 4: Perform a min ratio test to determine which variable will leave the basis. min ratio test:
XBr/y_{rk} = min\{XB_i/y_{ik}\}
The index of the min element i.e 'r' will determine the leaving variable. The basic
variable at index r will leave the basis.

Step 5: It's evident that the entered variable will not form an identity matrix, so we will have to perform row operations to
make it identity again.
Step 6: Find the pivot element. The element at index (r, k) will be the pivot element and row r will be the pivot row.
Step 7:Divide the rth row by pivot to make it 1. And subtract c*(rth row) from other rows to make them 0, where c is the
coefficient required to make that row 0.
PROGRAM

import numpy as np
from fractions import Fraction # so that numbers are not displayed in decimal.

print("\n ****SiMplex Algorithm ****\n\n")


A = np.array([[1, 1, 0, 1], [2, 1, 1, 0]])
b = np.array([8, 10])
c = np.array([1, 1, 0, 0])
cb = np.array(c[3])
B = np.array([[3], [2]])
cb = np.vstack((cb, c[2]))
xb = np.transpose([b])
table = np.hstack((B, cb))
table = np.hstack((table, xb))
table = np.hstack((table, A))
table = np.array(table, dtype ='float')
MIN = 0
print("Table at itr = 0")
print("B \tCB \tXB \ty1 \ty2 \ty3 \ty4")
for row in table:
for el in row:
print(Fraction(str(el)).limit_denominator(100), end ='\t')
print()
print()
print("Simplex Working .... ")

reached = 0
itr = 1
unbounded = 0
alternate = 0

while reached == 0:

print("Iteration: ", end =' ')


print(itr)
print("B \tCB \tXB \ty1 \ty2 \ty3 \ty4")
for row in table:
for el in row:
print(Fraction(str(el)).limit_denominator(100), end ='\t')
print()
i=0
rel_prof = []
while i<len(A[0]):
rel_prof.append(c[i] - np.sum(table[:, 1]*table[:, 3 + i]))
i=i+1

print("rel profit: ", end =" ")


for profit in rel_prof:
print(Fraction(str(profit)).limit_denominator(100), end =", ")
print()
i=0

b_var = table[:, 0]
# checking for alternate solution
while i<len(A[0]):
j=0
present = 0
while j<len(b_var):
if int(b_var[j]) == i:
present = 1
break;
j+= 1
if present == 0:
if rel_prof[i] == 0:
alternate = 1
print("Case of Alternate found")
# print(i, end =" ")
i+= 1
print()
flag = 0
for profit in rel_prof:
if profit>0:
flag = 1
break
# if all relative profits <= 0
if flag == 0:
print("All profits are <= 0, optimality reached")
reached = 1
break

k = rel_prof.index(max(rel_prof))
min = 99999
i = 0;
r = -1
while i<len(table):
if (table[:, 2][i]>0 and table[:, 3 + k][i]>0):
val = table[:, 2][i]/table[:, 3 + k][i]
if val<min:
min = val
r = i # leaving variable
i+= 1
if r ==-1:
unbounded = 1
print("Case of Unbounded")
break

print("pivot element index:", end =' ')


print(np.array([r, 3 + k]))

pivot = table[r][3 + k]
print("pivot element: ", end =" ")
print(Fraction(pivot).limit_denominator(100))

table[r, 2:len(table[0])] = table[


r, 2:len(table[0])] / pivot

i=0
while i<len(table):
if i != r:
table[i, 2:len(table[0])] = table[i,
2:len(table[0])] - table[i][3 + k] *
table[r, 2:len(table[0])]
i += 1
table[r][0] = k
table[r][1] = c[k]

print()
print()
itr+= 1
print()

print("**************************************************")
if unbounded == 1:
print("UNBOUNDED LPP")
exit()
if alternate == 1:
print("ALTERNATE Solution")

print("optimal table:")
print("B \tCB \tXB \ty1 \ty2 \ty3 \ty4")
for row in table:
for el in row:
print(Fraction(str(el)).limit_denominator(100), end ='\t')
print()
print()
print("value of Z at optimality: ", end =" ")

basis = []
i=0
sum = 0
while i<len(table):
sum += c[int(table[i][0])]*table[i][2]
temp = "x"+str(int(table[i][0])+1)
basis.append(temp)
i+= 1
if MIN == 1:
print(-Fraction(str(sum)).limit_denominator(100))
else:
print(Fraction(str(sum)).limit_denominator(100))
print("Final Basis: ", end =" ")
print(basis)

print("Simplex Finished...")
print()

RESULT
The above program has been executed successfully and the required output is displayed.
Ex no.: 7 Date:
BACKTRACKING – N-QUEEN PROBLEM, SUBSET SUM PROBLEM

AIM
To write a program to implement Backtracking - N-Queen problem, Subset Sum Problem

ALGORITHM
Step 1: Make a board, and make a space to collect all solution states. Step 2: Start
in the topmost row.
Step 3: Make a recursive function that takes the state of the board and the current row number as its parameter.
Step 4: Fill a queen in a safe place and use this state of the board to advance to the next recursive call, add 1 to
the current row. Revert the state of the board after making the call.
a) Safe function checks the current column, left top diagonal, and right top diagonal.
b) If no queen is present then fill else return false and stop exploring that state and track
back to the next possible solution state
Step 5: Keep calling the function till the current row is out of bounds.
Step 6: If the current row reaches the number of rows in the board then the board is filled. Step 7: Store
the state and return.

PROGRAM

N-Queen problem

global N N = 4
def printSolution(board):
for i in range(N):
for j in range(N):
print (board[i][j],end=' ')
print()

def isSafe(board, row, col): for i in


range(col):
if board[row][i] == 1:
return False

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


if board[i][j] == 1:
return False

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


if board[i][j] == 1:
return False

return True

def solveNQUtil(board, col):

if col >= N:
return True

for i in range(N):

if isSafe(board, i, col):
board[i][col] = 1

if solveNQUtil(board, col + 1) == True:


return True

board[i][col] = 0

return False

def solveNQ():
board = [ [0, 0, 0, 0],
[0, 0, 0, 0],
[0, 0, 0, 0],
[0, 0, 0, 0]
]

if solveNQUtil(board, 0) == False:
print ("Solution does not exist")
return False

printSolution(board)
return True

solveNQ()

OUTPUT
0010
1000
0001
0100
Subset problem
def isSubsetSum(set, n, sum):

if (sum == 0):
return True
if (n == 0):
return False

if (set[n - 1] > sum):


return isSubsetSum(set, n - 1, sum)
return isSubsetSum(
set, n-1, sum) or isSubsetSum(
set, n-1, sum-set[n-1])
set = [3, 34, 4, 12, 5, 2]
sum = 9
n = len(set)
if (isSubsetSum(set, n, sum) == True):
print("Found a subset with given sum")
else:
print("No subset with given sum")

OUTPUT
Found a subset with given sum

RESULT
The above program has been executed successfully and the required output is displayed.
Ex no.: 8 BRANCH AND BOND – ASSIGNMENT PROBLEM, TRAVELING
SALESMAN PROBLEM
Date:02/06/22

AIM
To write a python program to implement Branch and Bound - Assignment problem, Traveling Salesman Problem
ALGORITHM
Step 1: In the Branch and Bound method, for the current node in the tree, we compute a bound on the best possible
solution that we can get if we down this node.
Step 2: If the bound on the best possible solution itself is worse than the current best (best computed so far) Step 3: Then
we ignore the subtree rooted with the node.
Step 4: Note that the cost through a node includes two costs.
Step 5: Cost of reaching the node from the root (When we reach a node, we have this cost computed) Step 6: Cost
of reaching an answer from the current node to a leaf (We compute a bound on this cost to decide whether to ignore
subtree with this node or not).

PROGRAM

from sys import maxsize


from itertools import permutations V = 4

def travellingSalesmanProblem(graph, s): vertex = []


for i in range(V):
if i != s:
vertex.append(i)

min_path = maxsize
next_permutation=permutations(vertex) for i in
next_permutation:
current_pathweight = 0 k = s
for j in i:
current_pathweight += graph[k][j] k = j
current_pathweight += graph[k][s]
min_path = min(min_path, current_pathweight) return

min_path
if name == " main ":
graph = [[0, 10, 15, 20], [10, 0, 35, 25],
[15, 35, 0, 30], [20, 25, 30, 0]]
s=0
print(travellingSalesmanProblem(graph, s))

OUTPUT

The minimum cost is: 80

RESULT
The above program has been executed successfully and the required output is displayed.

You might also like