Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Matrix library implementation in Python #16

Open
wants to merge 31 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
76c449d
Implement subRows method in matrixlib.py
Zishan-Rahman Dec 29, 2024
2c86996
Implement subMatrix method in matrixlib.py
Zishan-Rahman Dec 29, 2024
94a9455
Implement matrixExcludingRowColumn method in matrixlib.py
Zishan-Rahman Jan 6, 2025
4a34406
Implement column method in matrixlib.py
Zishan-Rahman Jan 6, 2025
accb36b
Add type definitions to rowMult and matrixMultiplication declarations…
Zishan-Rahman Jan 6, 2025
4c4fa76
Add import to ocl library in matrixlib.py
Zishan-Rahman Jan 6, 2025
d6a03b2
Implement shape method in matrixlib.py
Zishan-Rahman Jan 6, 2025
1326454
Implement singleValueMatrix method in matrixlib.py
Zishan-Rahman Jan 7, 2025
fde3a6c
Start work on (currently commented out) fillMatrixForm method impleme…
Zishan-Rahman Jan 7, 2025
24ced47
Implement identityMatrix, flattenMatrix, sumMatrix and prdMatrix meth…
Zishan-Rahman Jan 7, 2025
b960f2a
Add print statement to end of matrixlib.py for testing identityMatrix…
Zishan-Rahman Jan 7, 2025
d5370b4
Add line to .gitignore excluding all __pycache__ folders in subfolders
Zishan-Rahman Jan 7, 2025
ef9f6af
Uncomment fillMatrixForm method code
Zishan-Rahman Jan 7, 2025
e00dc39
Add clarification to code comment in prdMatrix method in matrixlib.py
Zishan-Rahman Jan 7, 2025
7e136cf
Implement listSubrange method in ocl.py
Zishan-Rahman Jan 7, 2025
bfd79f7
Complete (and perfect) fillMatrixForm implementation in matrixlib.py
Zishan-Rahman Jan 7, 2025
a27f25e
Implement elementwiseApply, elementwiseMult, elementwiseAdd and eleme…
Zishan-Rahman Jan 7, 2025
30202d9
Add missing for-loop to elementwiseDivide implementation in matrixlib.py
Zishan-Rahman Jan 7, 2025
4b43268
Fix implementation mishaps in elementwiseApply, elementwiseMult, elem…
Zishan-Rahman Jan 8, 2025
908fb1c
Implement elementwiseLess, elementwiseGreater and elementwiseEqual me…
Zishan-Rahman Jan 8, 2025
e02efd8
Implement detaux method in matrixlib.py
Zishan-Rahman Jan 8, 2025
9ed468a
Implement determinant2, determinant3 and determinant methods in matri…
Zishan-Rahman Jan 8, 2025
e7590f7
Implement rowAddition, matrixAddition, rowSubtraction and matrixSubtr…
Zishan-Rahman Jan 8, 2025
82dcc50
Implement rowDotProduct, dotProduct, rowDotDivision and dotDivision m…
Zishan-Rahman Jan 8, 2025
6702f49
Implement rowLess, matrixLess, rowGreater and matrixGreater methods i…
Zishan-Rahman Jan 8, 2025
726f71f
Implement transpose method in matrixlib.py
Zishan-Rahman Jan 8, 2025
c9ba901
Modify type hint to m parameter in determinant3 method in matrixlib.py
Zishan-Rahman Jan 9, 2025
e00f2f8
Rewrite all elementwise functions' "else" return statements into list…
Zishan-Rahman Jan 9, 2025
e36f0cc
Rewrite identityMatrix function in matrixlib.py into list comprehension
Zishan-Rahman Jan 9, 2025
f987788
Fix typos in matrixEcludingRowColumn implementation in matrixlib.py
Zishan-Rahman Jan 9, 2025
f9fa27c
Move existing testing code in matrixlib.py into main function and onl…
Zishan-Rahman Jan 9, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
*/__pycache__/
antlr-*-complete.jar
Test.xml
Data.ser
262 changes: 258 additions & 4 deletions libraries/matrixlib.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import numpy as np

import ocl

class MatrixLib :

def rowMult(s, m) :
def rowMult(s: list, m: list) -> list:
result = []
for i in range(0, len(s)) :
sum = 0
Expand All @@ -12,11 +12,265 @@ def rowMult(s, m) :
result.append(sum)
return result

def matrixMultiplication(m1, m2) :
def matrixMultiplication(m1: list, m2: list) -> list:
m1array = np.array(m1)
m2array = np.array(m2)
res = np.matmul(m1array, m2array)
return res.tolist()

def subRows(m: list, s: list[int]) -> list:
result = []
for integer in s:
if 0 <= integer <= len(m) - 1: # OCL starts indexing at 1, Python starts indexing at 0
result.append(m[integer])
return result

def subMatrix(m: list[list], rows: list[int], cols: list[int]) -> list:
result = []
for row in rows:
if 0 <= row <= len(m) - 1: # OCL starts indexing at 1, Python starts indexing at 0
result.append(subRows(m[row], cols))
return result

def matrixExcludingRowColumn(m: list, row: int, col: int) -> list:
result = []

# Original note-for-note adaption (as much as possible) of OCL code
# for i in range(len(m)):
# if i != row:
# r: list = m[i]
# for i in range(len(r)):
# if j != col:
# subrow: list = r[j]
# res.append(subrow)

# Better, more "pythonic" approach
for r, i in enumerate(m):
# not doing an "if i != row and j != col" check prevents us from checking every single column in every single row
if i != row:
for subrow, j in enumerate(r):
if j != col:
result.append(subrow)

return result

def column(m: list, i: int) -> list:
return [m[i]] if isinstance(m[i], list) else m[i]

def shape(x) -> list:
result: list = [0]
if isinstance(x, list):
sq: list = list(x)
result = [len(x)]
if len(sq) > 0:
result = ocl.union(result, MatrixLib.shape(sq[0]))
return result

def singleValueMatrix(sh: list, x) -> list:
if len(sh) == 0:
return []
elif len(sh) == 1:
return [x for i in range(1, sh[0], 1)]
else:
return [MatrixLib.singleValueMatrix(ocl.tail(sh), x) for i in range(1, sh[0], 1)]

def fillMatrixForm(sq: list, sh: list) -> list:
if len(sh) == 0:
return []
elif len(sh) == 1:
return [sq[i] for i in range(sh[0])]
else:
result = []
prod: int = ocl.prd(ocl.tail(sh))
for i in range(sh[0]):
rowi: list = MatrixLib.fillMatrixForm(ocl.listSubrange(sq, prod * (i - 1), (prod * i) - 1), ocl.tail(sh))
result.append(rowi)
return result

def identityMatrix(n: int) -> list:
return [[1.0 if i == j else 0.0 for j in range(n)] for i in range(n)]

def flattenMatrix(m: list) -> list:
if len(m) == 0:
return []
elif isinstance(m[0], list):
sq: list = m[0]
return [ocl.union(MatrixLib.flattenMatrix(sq), MatrixLib.flattenMatrix(ocl.tail(m)))]
else:
return m

def sumMatrix(m: list) -> float:
if len(m) == 0:
return 0.0
elif isinstance(m[0], list):
sq: list = m[0]
return MatrixLib.sumMatrix(sq) + MatrixLib.sumMatrix(ocl.tail(m))
else:
dmat: list = ocl.union([0.0], m)
return sum(dmat) # Python has a built-in sum function ready to use on a list

def prdMatrix(m: list) -> float:
if len(m) == 0:
return 0.0
elif isinstance(m[0], list):
sq: list = m[0]
return MatrixLib.prdMatrix(sq) * MatrixLib.prdMatrix(ocl.tail(m))
else:
dmat: list = ocl.union([1.0], m)
return np.prod(dmat) # Faster solution (mainly for very large lists), see https://stackoverflow.com/a/55297341

def elementwiseApply(m: list, f: callable) -> list:
if len(m) == 0:
return []
elif isinstance(m[0], list):
return [MatrixLib.elementwiseApply(list(_r), f) for _r in m]
return [f(float(z)) for z in m]

def elementwiseMult(m: list, x: float) -> list:
if len(m) == 0:
return []
elif isinstance(m[0], list):
return [MatrixLib.elementwiseMult(list(_r), x) for _r in m]
return [float(z) * x for z in m]

def elementwiseAdd(m: list, x: float) -> list:
if len(m) == 0:
return []
elif isinstance(m[0], list):
return [MatrixLib.elementwiseAdd(list(_r), x) for _r in m]
return [float(z) + x for z in m]

def elementwiseDivide(m: list, x: float) -> list:
if len(m) == 0:
return []
elif isinstance(m[0], list):
return [MatrixLib.elementwiseDivide(list(_r), x) for _r in m]
return [float(z) / x for z in m]

def elementwiseLess(m: list, x: float) -> list:
if len(m) == 0:
return []
elif isinstance(m[0], list):
return [MatrixLib.elementwiseLess(list(_r), x) for _r in m]
return [float(z) < x for z in m]

def elementwiseGreater(m: list, x: float) -> list:
if len(m) == 0:
return []
elif isinstance(m[0], list):
return [MatrixLib.elementwiseGreater(list(_r), x) for _r in m]
return [float(z) > x for z in m]

def elementwiseEqual(m: list, x: float) -> list:
if len(m) == 0:
return []
elif isinstance(m[0], list):
return [MatrixLib.elementwiseEqual(list(_r), x) for _r in m]
return [float(z) == x for z in m]

def detaux(x1: float, x2: float, y1: float, y2: float) -> float:
return x1*y2 - x2*y1

def determinant2(m: list) -> float:
if len(m) == 2 and len(m[0]) == 2:
m1: list = list(m[0])
m2: list = list(m[1])

d11: float = float(m[0][1])
d12: float = float(m[0][1])
d21: float = float(m[1][0])
d22: float = float(m[1][1])

return MatrixLib.detaux(d11, d12, d21, d22)

def determinant3(m: list[list]) -> float:
if len(m) == 3 and len(m[0]) == 3:
subm1: list = MatrixLib.subMatrix(m, [2, 3], [2, 3])
subm2: list = MatrixLib.subMatrix(m, [2, 3], [1, 3])
subm3: list = MatrixLib.subMatrix(m, [2, 3], [1, 2])

m1: list = list(m[0])

return (float(m1[0]) * MatrixLib.determinant2(subm1)) + \
(float(m1[1]) * MatrixLib.determinant2(subm2)) + \
(float(m1[2]) * MatrixLib.determinant2(subm3))

def determinant(m: list) -> float:
n = len(m)
if n == 1:
return float(m[0])
elif n == 2:
return MatrixLib.determinant2(m)
elif n == 3:
return MatrixLib.determinant3(m)
else:
result: float = 0.0
row: list = list(m[0])
factor: int = 1
for i in range(n):
submat: list = MatrixLib.matrixExcludingRowColumn(m, 1, i)
det: float = MatrixLib.determinant(submat)
rowi: float = float(row[i])
result += factor * rowi * det
factor = -factor
return result

def rowAddition(m1: list, m2: list) -> list:
if isinstance(m1[0], list):
return [MatrixLib.rowAddition(sq1, sq2) for sq1, sq2 in zip(m1, m2)]
return [float(m1j) + float(m2j) for m1j, m2j in zip(m1, m2)]

def matrixAddition(m1: list, m2: list) -> list:
return [MatrixLib.rowAddition(sq1, sq2) for sq1, sq2 in zip(m1, m2)]

def rowSubtraction(m1: list, m2: list) -> list:
if isinstance(m1[0], list):
return [MatrixLib.rowSubtraction(sq1, sq2) for sq1, sq2 in zip(m1, m2)]
return [float(m1j) - float(m2j) for m1j, m2j in zip(m1, m2)]

def matrixSubtraction(m1: list, m2: list) -> list:
return [MatrixLib.rowSubtraction(sq1, sq2) for sq1, sq2 in zip(m1, m2)]

def rowDotProduct(m1: list, m2: list) -> list:
if isinstance(m1[0], list):
return [MatrixLib.rowDotProduct(sq1, sq2) for sq1, sq2 in zip(m1, m2)]
return [float(m1j) * float(m2j) for m1j, m2j in zip(m1, m2)]

def dotProduct(m1: list, m2: list) -> list:
return [MatrixLib.dotProduct(sq1, sq2) for sq1, sq2 in zip(m1, m2)]

def rowDotDivision(m1: list, m2: list) -> list:
if isinstance(m1[0], list):
return [MatrixLib.rowDotDivision(m1i, m2i) for m1i, m2i in zip(m1, m2)]
return [float(m1j) / float(m2j) for m1j, m2j in zip(m1, m2)]

def dotDivision(m1: list, m2: list) -> list:
return [MatrixLib.rowDotDivision(sq1, sq2) for sq1, sq2 in zip(m1, m2)]

def rowLess(m1: list, m2: list) -> list:
if isinstance(m1[0], list):
return [MatrixLib.rowLess(m1i, m2i) for m1i, m2i in zip(m1, m2)]
return [m1j < m2j for m1j, m2j in zip(m1, m2)]

def matrixLess(m1: list, m2: list) -> list:
return [MatrixLib.rowLess(m1i, m2i) for m1i, m2i in zip(m1, m2)]

def rowGreater(m1: list, m2: list) -> list:
if isinstance(m1[0], list):
return [MatrixLib.rowGreater(m1i, m2i) for m1i, m2i in zip(m1, m2)]
return [m1j > m2j for m1j, m2j in zip(m1, m2)]

def matrixGreater(m1: list, m2: list) -> list:
return [MatrixLib.rowGreater(r1, r2) for r1, r2 in zip(m1, m2)]

def transpose(m: list) -> list:
if not isinstance(m[0], list):
return m
return [MatrixLib.column(m, i) for i, _ in enumerate(m)]

def main():
print(MatrixLib.matrixMultiplication([[1,2], [3,4]], [[5,6], [7,8]]))
print(MatrixLib.identityMatrix(5))

print(MatrixLib.matrixMultiplication([[1,2], [3,4]], [[5,6], [7,8]]))
if __name__=="__main__":
main()
11 changes: 11 additions & 0 deletions libraries/ocl.py
Original file line number Diff line number Diff line change
Expand Up @@ -527,6 +527,17 @@ def setSubrange(x,i,j,v) :
x1 = x[0:i-1] + str(v) + x[j:]
return x1

def listSubrange(l: list, i: int, j: int) -> list:
# For lists
result = []
if i < 0:
i = (len(l) - 1) + i
if j < 0:
j = (len(l) - 1) + j
for k in range(i, j+1):
result.append(l[k])
return result

def insertAt(x,i,s) :
# i must be > 0
if i <= 0 :
Expand Down