Skip to content

Commit

Permalink
Integrated back-substitution into the calculator through the solve an…
Browse files Browse the repository at this point in the history
…d eval functions.
  • Loading branch information
nrubin29 committed Nov 25, 2017
1 parent b3f637c commit 0277f8a
Show file tree
Hide file tree
Showing 3 changed files with 42 additions and 15 deletions.
1 change: 1 addition & 0 deletions common.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ def _str(self, node, depth=0) -> str:
(r'trnsform', 'OPR'),
(r'rref', 'OPR'),
(r'solve', 'OPR'),
(r'eval', 'OPR'),
(r'[a-zA-Z_]+', 'IDT'),
(r'=', 'EQL'),
(r'\+', 'ADD'),
Expand Down
22 changes: 12 additions & 10 deletions matrix.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import copy
from collections import OrderedDict
from typing import List, Tuple


Expand All @@ -8,7 +9,7 @@ class DynamicVector:
"""
def __init__(self, size):
self.size = size
self.vectors = {'const': [0] * size}
self.vectors = OrderedDict({'const': [0] * size})

def add(self, row):
# Adds a new free variable
Expand All @@ -32,7 +33,7 @@ def const(self, row, val):
self.vectors['const'][row] = val

def __str__(self):
return str(self.vectors)
return (str(self.vectors['const']) + ' + ' + ' + '.join([str(val) + ' * x_' + str(key) for key, val in self.vectors.items() if key != 'const'])).rstrip(' + ')


MatrixTyping = List[List[float]]
Expand All @@ -43,12 +44,13 @@ class MatrixTransformer:
This class is in charge of calculating rref and transformation matrices for a given matrix.
"""

def __init__(self, matrix, answer=None):
def __init__(self, matrix):
self.matrix = matrix
self.transformation = self.identity
self.answer = answer or [0] * len(self.matrix)
self.answer = None

def rref(self) -> Tuple[MatrixTyping, MatrixTyping, DynamicVector]:
def rref(self, answer=None) -> Tuple[MatrixTyping, MatrixTyping, DynamicVector]:
self.answer = answer or [0] * len(self.matrix)
row = 0
col = 0

Expand Down Expand Up @@ -121,7 +123,7 @@ def rref(self) -> Tuple[MatrixTyping, MatrixTyping, DynamicVector]:

for nxt in range(num_zeroes + 1, len(self.matrix[row])):
if self.matrix[row][nxt] != 0:
dvec.set(row, nxt, -matrix[row][nxt])
dvec.set(row, nxt, -self.matrix[row][nxt])

dvec.add_missing(range(len(self.matrix)))

Expand Down Expand Up @@ -186,14 +188,14 @@ def multiply_matrices(a: MatrixTyping, b: MatrixTyping) -> MatrixTyping:

if __name__ == '__main__':
# matrix = [[1, 2, 3, 4], [4, 2, 3, 7], [1, 2, 3, 8], [9, 2, 3, 3]]
# matrix = [[1, 0, 0], [0, 1, 0], [0, 0, 1]]
matrix = [[1, 0, 0], [0, 1, 0], [0, 0, 1]]
# matrix = [[1, 0, 0], [0, 1, 2], [0, 0, 0]]
matrix = [[1, 0, -58/17], [0, 1, 29/19], [0, 0, 0]]
# matrix = [[1, 0, -58/17], [0, 1, 29/19], [0, 0, 0]]
# matrix = [[1, 0, 0], [0, 0, 0], [0, 0, 0]]
# matrix = [[1, 2, 0], [0, 0, 1], [0, 0, 0]]
ans = [1, 2, 3]
transformer = MatrixTransformer(copy.deepcopy(matrix), copy.deepcopy(ans))
rref, transformation, answer = transformer.rref()
transformer = MatrixTransformer(copy.deepcopy(matrix))
rref, transformation, answer = transformer.rref(copy.deepcopy(ans))
print(rref, '|', ans, '->', answer, '\n')
print(transformation)
print(multiply_matrices(transformation, matrix))
34 changes: 29 additions & 5 deletions vartypes.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
from typing import List

from common import EvaluationException
from matrix import MatrixTransformer
from matrix import MatrixTransformer, DynamicVector


class Value(metaclass=ABCMeta):
Expand Down Expand Up @@ -145,6 +145,8 @@ def __init__(self, data):
else:
self.value = data

self._rref_cache = None

def __str__(self):
return '[\n' + '\n'.join(['[' + ', '.join(map(lambda cell: str(round(cell, 5)), row)) + ']' for row in self.value]) + '\n]'

Expand Down Expand Up @@ -218,7 +220,10 @@ def inv(self):
return MatrixValue([[cell * multiplier for cell in row] for row in self.adj().value])

def _rref(self):
return MatrixTransformer(copy.deepcopy(self.value)).rref()
if not self._rref_cache:
self._rref_cache = MatrixTransformer(copy.deepcopy(self.value)).rref()

return self._rref_cache

def rref(self):
return MatrixValue(self._rref()[0])
Expand All @@ -227,7 +232,7 @@ def trnsform(self):
return MatrixValue(self._rref()[1])

def solve(self, other):
return NumberValue(2)
return DynamicVectorValue(MatrixTransformer(copy.deepcopy(self.value)).rref(other.value[0])[2])


class MatrixRowValue(Value):
Expand All @@ -242,7 +247,26 @@ def __init__(self, data):


class OperatorBodyValue(Value):
def __init__(self, args):
def __init__(self, args: List):
super().__init__()

self.value = args
self.value = args


class DynamicVectorValue(Value):
def __init__(self, dvec: DynamicVector):
super().__init__()

self.value = dvec

def eval(self, *args):
dvec = copy.deepcopy(self.value)
ans = dvec.vectors.pop('const')

i = 0
for _, free_var in dvec.vectors.items():
row = [x * int(args[i].value) for x in free_var]
ans = [ans[i] + row[i] for i in range(len(ans))]
i += 1

return MatrixValue([ans])

0 comments on commit 0277f8a

Please sign in to comment.