Skip to content

Commit

Permalink
Merge pull request #16 from Zishan-Rahman/matrixlib
Browse files Browse the repository at this point in the history
Matrix library implementation in Python
  • Loading branch information
kevinlano authored Jan 22, 2025
2 parents 78b09e0 + 0ee646b commit 946a600
Show file tree
Hide file tree
Showing 3 changed files with 260 additions and 6 deletions.
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
264 changes: 259 additions & 5 deletions libraries/matrixlib.py
Original file line number Diff line number Diff line change
@@ -1,22 +1,276 @@
import numpy as np

import ocl

class MatrixLib :

def rowMult(s, m) :
result = []
def rowMult(s: list[float], m: list[list[float]]) -> list[float]:
result: list[float] = []
for i in range(0, len(s)) :
sum = 0
for k in range(0, len(m)) :
sum = sum + s[k]*(m[k][i])
result.append(sum)
return result

def matrixMultiplication(m1, m2) :
def matrixMultiplication(m1: list[list[float]], m2: list[list[float]]) -> list[list[float]]:
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: list = []
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: list = []
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: list = []

# 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[int]:
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()
1 change: 0 additions & 1 deletion libraries/ocl.py
Original file line number Diff line number Diff line change
Expand Up @@ -542,7 +542,6 @@ def sequenceSubrange(l, i, j) :
result.append(l[k])
return result


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

0 comments on commit 946a600

Please sign in to comment.