Design and Analysis of Algorithms Lab Aman Dubey
Design and Analysis of Algorithms Lab Aman Dubey
Enrollment number:07419011922
Batch : B1 Ds
Analysis
Algorithm
1. Naive Multiplication (naive_multiply):
• Calculate each element of the output matrix by iterating through rows and
columns, computing the dot product.
2. Strassen's Multiplication (strassen_multiply):
• Recursively divide matrices into submatrices.
• Compute seven products (P1 to P7) recursively.
• Combine submatrices to form the result matrix.
3. Matrix Generation (generate_random_matrix):
• Generate random matrices of specified sizes.
4. Comparison (compare_methods):
• Measure time taken by both methods for different matrix sizes.
• Plot a comparison graph.
5. Plotting (matplotlib):
• Use matplotlib to visualize the comparison graphically.
Code
import numpy as np
import time
import matplotlib.pyplot as plt
if n <= 2:
return np.dot(A, B)
return C
for i in range(n):
for j in range(n):
for k in range(n):
C[i, j] += A[i, k] * B[k, j]
return C
for n in matrix_sizes:
A = np.random.randint(1, 11, (n, n))
B = np.random.randint(1, 11, (n, n))
start_time = time.time()
C_strassen = strassen(A, B)
strassen_time = time.time() - start_time
strassen_times.append(strassen_time)
start_time = time.time()
C_naive = naive_multiply(A, B)
naive_time = time.time() - start_time
naive_times.append(naive_time)
plt.show()
Output
Q2. Implement the multiplication of two N-bit numbers (using Divide and
Conquer Strategy) and naive multiplication method. Compare these
methods in terms of time taken using N-bit numbers where n=4, 8, 16, 32
and 64.
Analysis
1.Methods:
• Implement Divide and Conquer and naive multiplication for N-bit
numbers.
2.Comparison:
• Compare time for multiplying N-bit numbers (N = 4, 8, 16, 32, 64).
3.Conclusion:
• Evaluate efficiency and preferences.
Divide And Conquer Algorithm
Code
import time
n = max(len(str(x)), len(str(y)))
half = n // 2
a = x // 10 ** half
b = x % (10 ** half)
c = y // 10 ** half
d = y % (10 ** half)
ac = divide_and_conquer_multiply(a, c)
bd = divide_and_conquer_multiply(b, d)
ad_bc = divide_and_conquer_multiply(a + b, c + d) - ac - bd
if __name__ == "__main__":
bit_sizes = [4, 8, 16, 32, 64]
print("Bit Size\tDivide & Conquer (s)\tNaive Multiplication (s)")
for n in bit_sizes:
x = 2 ** n - 1 # Generate an N-bit number
y = 2 ** n - 1 # Generate an N-bit number
start_time = time.time()
divide_and_conquer_multiply(x, y)
dnc_time = time.time() - start_time
start_time = time.time()
naive_multiply(x, y)
naive_time = time.time() - start_time
print(f"{n}\t\t{dnc_time:.6f}\t\t\t{naive_time:.6f}")
Output
ac = divide_and_conquer_multiply(a, c)
bd = divide_and_conquer_multiply(b, d)
ad_bc = divide_and_conquer_multiply(a + b, c + d) - ac - bd
start_time = time.time()
divide_and_conquer_multiply(x, y)
dnc_time = time.time() - start_time
start_time = time.time()
naive_multiply(x, y)
naive_time = time.time() - start_time
print(f"{n}\t\t{dnc_time:.6f}\t\t\t{naive_time:.6f}")
return max_so_far
# Example usage:
arr1 = [-2, 11, -4, 13, -5, 2]
arr2 = [1, -3, 4, -2, -1, 6]
Q4. Implement the algorithm (Algo_1) presented below and discuss which
task this algorithm performs. Also, analyse the time complexity and space
complexity of the given algorithm. Further, implement the algorithm with
following modification: replace m = ⌈2n/3⌉ with m = ⌊2n/3⌋, and compare
the tasks performed by the given algorithm and modified algorithm.
In each recursive call, the algorithm divides the array into three
parts and recursively calls itself on two of these parts.
Summary: