0% found this document useful (0 votes)
143 views

Assignment 2

The document contains code for solving the maximum subarray problem using different algorithms like brute force, recursive, and iterative. It also contains code for matrix multiplication using the standard and Strassen's algorithm. The code defines functions for finding the maximum subarray, matrix addition, subtraction, and multiplication. It then tests the maximum subarray algorithms on sample data and compares the results of standard and Strassen's matrix multiplication on some sample matrices.

Uploaded by

Utsav Dusad
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
143 views

Assignment 2

The document contains code for solving the maximum subarray problem using different algorithms like brute force, recursive, and iterative. It also contains code for matrix multiplication using the standard and Strassen's algorithm. The code defines functions for finding the maximum subarray, matrix addition, subtraction, and multiplication. It then tests the maximum subarray algorithms on sample data and compares the results of standard and Strassen's matrix multiplication on some sample matrices.

Uploaded by

Utsav Dusad
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 9

# -*- coding: utf-8 -*-

import sys
from numpy import asarray
import numpy as np

# STOCK_PRICES = [100,113,110,85,105,102,86,63,81,101,94,106,101,79,94,90,97]

STOCK_PRICE_CHANGES = [13, -3, -25, 20, -3, -16,


-23, 18, 20, -7, 12, -5, -22, 15, -4, 7]
MOB = [-2, -3, 4, -1, -2, 1, 5, -3]
NEG = [-4, -6, -2, -9, -7]
POS = [1, 2, 3, 4, 8, 2, 12, 1]
XYZ = [[1, 2], [3, 4]]
PQR = [[2, 3], [4, 5]]
EMPTY_MATRIX = []
ABC = [[1, 2, 3, 4], [3, 4, 2, 1], [1, 2, 3, 4], [3, 4, 2, 1]]
DEF = [[2, 3, 1, 4], [4, 5, 6, 7], [1, 2, 3, 4], [4, 5, 6, 7]]

# ==============================================================

# The brute force method to solve max subarray problem


def find_maximum_subarray_brute(A):

"""

Return a tuple (i,j) where A[i:j] is the maximum subarray.

time complexity = O(n^2)

"""

if len(A) == 0:
return None

max = -sys.maxsize
start_index = 0
last_index = 0

for idx, number in enumerate(A):


sum = 0
for j in range(idx, len(A)):

sum = sum + A[j]


if sum > max:
max = sum
start_index = idx
last_index = j

return (start_index, last_index)

# ==============================================================

# The maximum crossing subarray method for solving the max subarray problem
def find_maximum_crossing_subarray(A, low, mid, high):

"""

Find the maximum subarray that crosses mid


Return a tuple ((i, j), sum) where sum is the maximum subarray of A[i:j].

"""

sum = 0
right_array_sum = -sys.maxsize
rindex = high
index = mid+1
while index <= high:
sum = sum + A[index]
if sum > right_array_sum:
right_array_sum = sum
rindex = index

index = index + 1

sum = 0
left_array_sum = -sys.maxsize
lindex = mid
index = mid
while index >= low:
sum = sum + A[index]
if sum > left_array_sum:
left_array_sum = sum
lindex = index

index = index-1

total_sum_left_and_right = left_array_sum + right_array_sum

return [(lindex, rindex), total_sum_left_and_right]

# The recursive method to solve max subarray problem


def find_maximum_subarray_recursive_helper(A, low=0, high=-1):

"""

Return a tuple ((i, j), sum) where sum is the maximum subarray of A[i:j].

"""

if low == high:
return ((low, high), A[low])

mid = (low + high) / 2

mid = int(mid)

left_maximum_sum = find_maximum_subarray_recursive_helper(A, low, mid)


# print (left_maximum_sum)

right_maximum_sum = find_maximum_subarray_recursive_helper(A,
mid + 1, high)
# print (right_maximum_sum)
crossing_subarray = find_maximum_crossing_subarray(A, low, mid, high)

# ans =
# max(left_maximum_sum[1], right_maximum_sum[1], crossing_subarray[1])
items = [left_maximum_sum, right_maximum_sum, crossing_subarray]
max_item = max(items, key=lambda item: item[1])

return max_item

# The recursive method to solve max subarray problem


def find_maximum_subarray_recursive(A):

"""

Return a tuple (i,j) where A[i:j] is the maximum subarray.

"""
if len(A) == 0:
return None

return find_maximum_subarray_recursive_helper(A, 0, len(A) - 1)[0]

# ==============================================================

# The iterative method to solve max subarray problem


def find_maximum_subarray_iterative(A):
NEG
"""

Return a tuple (i,j) where A[i:j] is the maximum subarray.

"""
if len(A) == 0:
return None

global_max = A[0]
max_current = A[0]
start = 0
finish = 0
temp_index = 0
for index, obj in enumerate(A):

if obj > max_current + obj:


max_current = obj
temp_index = index

else:
max_current = max_current + obj

if global_max < max_current:


global_max = max_current
finish = index
start = temp_index

return (start, finish)

# =================================================================

def square_matrix_multiply(A, B):

"""
Return the product AB of matrix multiplication.

"""

A = asarray(A)

B = asarray(B)

if len(A) == 0 or len(B) == 0:
return None
assert A.shape == B.shape
assert A.shape == A.T.shape

result = np.zeros([A.shape[0], B.shape[1]], dtype=int)


for row_index in range(0, A.shape[0]):
for col_index in range(0, B.shape[1]):
for k in range(0, B.shape[0]):
result[row_index][col_index] = \
result[row_index][col_index] \
+ A[row_index][k] * B[k][col_index]

return result

def add(A, B):


n = len(A)
C = [[0 for j in range(0, n)] for i in range(0, n)]
for i in range(0, n):
for j in range(0, n):
C[i][j] = A[i][j] + B[i][j]
return C

def subtract(A, B):


n = len(A)
C = [[0 for j in range(0, n)] for i in range(0, n)]
for i in range(0, n):
for j in range(0, n):
C[i][j] = A[i][j] - B[i][j]
return C

# ==============================================================

def square_matrix_multiply_strassens(A, B):

"""

Return the product AB of matrix multiplication.

Assume len(A) is a power of 2

"""

A = asarray(A)
B = asarray(B)

if len(A) == 0 or len(B) == 0:
return None

assert A.shape == B.shape

assert A.shape == A.T.shape

assert (len(A) & (len(A) - 1)) == 0, "A is not a power of 2"

matrix_size = len(A)
if matrix_size == 1:
# return matrixProductfor2by2(A, B)
return [A[0] * B[0]]
else:
new_size = int(matrix_size/2)
# initializng 4 sub matrices for both a and b
a11 = np.zeros([new_size, new_size], dtype=int)
a12 = np.zeros([new_size, new_size], dtype=int)
a21 = np.zeros([new_size, new_size], dtype=int)
a22 = np.zeros([new_size, new_size], dtype=int)
aResult = np.zeros([new_size, new_size], dtype=int)

b11 = np.zeros([new_size, new_size], dtype=int)


b12 = np.zeros([new_size, new_size], dtype=int)
b21 = np.zeros([new_size, new_size], dtype=int)
b22 = np.zeros([new_size, new_size], dtype=int)
bResult = np.zeros([new_size, new_size], dtype=int)

for row in range(new_size):


for col in range(new_size):
a11[row][col] = A[row][col]
a12[row][col] = A[row][col + new_size]
a21[row][col] = A[row + new_size][col]
a22[row][col] = A[row + new_size][col + new_size]

b11[row][col] = B[row][col]
b12[row][col] = B[row][col + new_size]
b21[row][col] = B[row + new_size][col]
b22[row][col] = B[row + new_size][col + new_size]

# M1 = (a11+a22) * (b11+b22)
# M2 = (a21+a22) * (b11)
# M3 = (a11) * (b12 - b22)
# M4 = (a22) * (b21 - b11)
# M5 = (a11+a12) * (b22)
# M6 = (a21-a11) * (b11+b12)
# M7 = (a12-a22) * (b21+b22)

# C11 = m1 + m4 - m5 + m7
# C12 = m3 + m5
# C21 = m2 + m4
# C22 = m1 + m3 - m2 + m6

# Find m1 to m7:
# M1 = (a11+a22) * (b11+b22)
# aResult = add(a11, a22)
a = np.matrix(a11)
b = np.matrix(a22)
aResult = a + b
# bResult = add(b11, b22)
a = np.matrix(b11)
b = np.matrix(b22)
bResult = a + b
m1 = square_matrix_multiply_strassens(aResult, bResult)

# M2 = (a21+a22) * (b11)
aResult = add(a21, a22)
a = np.matrix(a21)
b = np.matrix(a22)
aResult = a + b
m2 = square_matrix_multiply_strassens(aResult, b11)

# M3 = (a11) * (b12 - b22)


# bResult = subtract(b12, b22)
a = np.matrix(b12)
b = np.matrix(b22)
bResult = a - b
m3 = square_matrix_multiply_strassens(a11, bResult)

# M4 = (a22) * (b21 - b11)


# bResult = subtract(b21, b11)
a = np.matrix(b21)
b = np.matrix(b11)
bResult = a - b
m4 = square_matrix_multiply_strassens(a22, bResult)

# M5 = (a11+a12) * (b22)
aResult = add(a11, a12)

m5 = square_matrix_multiply_strassens(aResult, b22)

# M6 = (a21-a11) * (b11+b12)
aResult = subtract(a21, a11)
bResult = add(b11, b12)
m6 = square_matrix_multiply_strassens(aResult, bResult)

# M7 = (a12-a22) * (b21+b22)
aResult = subtract(a12, a22)
bResult = add(b21, b22)
m7 = square_matrix_multiply_strassens(aResult, bResult)
# calculating c21, c21, c11 e c22:
c12 = add(m3, m5) # c12 = m3 + m5
c21 = add(m2, m4) # c21 = m2 + m4

aResult = add(m1, m4) # m1 + m4


bResult = add(aResult, m7) # m1 + m4 + m7
c11 = subtract(bResult, m5) # c11 = m1 + m4 - m5 + m7

aResult = add(m1, m3) # m1 + m3


bResult = add(aResult, m6) # m1 + m3 + m6
c22 = subtract(bResult, m2) # c22 = m1 + m3 - m2 + m6

# Grouping the results obtained in a single matrix:


C = [[0 for j in range(0, matrix_size)] for i in range(0, matrix_size)]
for i in range(0, new_size):
for j in range(0, new_size):
C[i][j] = c11[i][j]
C[i][j + new_size] = c12[i][j]
C[i + new_size][j] = c21[i][j]
C[i + new_size][j + new_size] = c22[i][j]
return C

pass
# ==============================================================

def test():

a = find_maximum_subarray_brute(STOCK_PRICE_CHANGES)
print("brute")
print(a)
a = find_maximum_subarray_recursive(STOCK_PRICE_CHANGES)
print ("Recurisve")
print (a)
a = find_maximum_subarray_iterative(STOCK_PRICE_CHANGES)
print("Iterative")
print(a)

p = square_matrix_multiply(ABC, DEF)
print("Multiplication: " + str(p))
p = square_matrix_multiply_strassens(ABC, DEF)
print("Strassens Multiplication: " + str(p))
pass

if __name__ == '__main__':

test()

# ==============================================================

Output:
If you see the output carefully the output of matrix multiplication of
Strassens is a 2D array whereas the output for the normal
multiplication is matrix. This is because:
1) In Strassens the output 2D array is created using:
[[0 for j in range(0, matrix_size)] for i in
range(0, matrix_size)]
2) In first case of normal matrix
multiplication we are creating a matrix
using numpy i.e
np.zeros([A.shape[0], B.shape[1]],
dtype=int)
The above line creates matrix with rows
A.shape[0] and B.shape[1]

In Strassens Algorithm I have used addition


and subtraction methods. I have also used
numpy for addition and subtraction in few
cases just to check how it works.
Flake8 output:

You might also like