def __mul__(self, other): """Multiplies two matrices Arguments: self {visma.matrix.structure.Matrix} -- matrix token other {visma.matrix.structure.Matrix} -- matrix token Returns: matPro {visma.matrix.structure.Matrix} -- product matrix token Note: Make mulitplyCheck before calling multiplyMatrix Not commutative """ matPro = Matrix() matPro.empty([self.dim[0], other.dim[1]]) for i in range(self.dim[0]): for j in range(other.dim[1]): for k in range(self.dim[1]): if matPro.value[i][j] != []: matPro.value[i][j].append(Binary('+')) if len(self.value[i][k]) != 1: matPro.value[i][j].append(Expression(self.value[i][k])) else: matPro.value[i][j].extend(self.value[i][k]) matPro.value[i][j].append(Binary('*')) if len(other.value[k][j]) != 1: matPro.value[i][j].append(Expression( other.value[k][j])) else: matPro.value[i][j].extend(other.value[k][j]) from visma.matrix.operations import simplifyMatrix matPro = simplifyMatrix(matPro) return matPro
def multiplyMatrix(matA, matB): """Multiplies two matrices Arguments: matA {visma.matrix.structure.Matrix} -- matrix token matB {visma.matrix.structure.Matrix} -- matrix token Returns: matPro {visma.matrix.structure.Matrix} -- product matrix token Note: Make mulitplyCheck before calling multiplyMatrix Not commutative """ matPro = Matrix() matPro.empty([matA.dim[0], matB.dim[1]]) for i in range(matA.dim[0]): for j in range(matB.dim[1]): for k in range(matA.dim[1]): if matPro.value[i][j] != []: matPro.value[i][j].append(Binary('+')) if len(matA.value[i][k]) != 1: matPro.value[i][j].append(Expression(matA.value[i][k])) else: matPro.value[i][j].extend(matA.value[i][k]) matPro.value[i][j].append(Binary('*')) if len(matB.value[k][j]) != 1: matPro.value[i][j].append(Expression(matB.value[k][j])) else: matPro.value[i][j].extend(matB.value[k][j]) matPro = simplifyMatrix(matPro) return matPro
def gauss_elim(mat): """ Returns calculated values of unknown variables Arguments: mat {visma.matrix.structure.Matrix} -- matrix token Returns: result {visma.matrix.structure.Matrix} -- result matrix token Note: result is a Nx1 matrix """ echelon = Matrix() echelon = row_echelon(mat) result = Matrix() result.empty([mat.dim[0], 1]) N = mat.dim[0] M = mat.dim[1] index = N - 1 for i in range(N - 1, -1, -1): sum_ = [] temp = [] if echelon.value[i][i][ 0].value == 0.0: # no unique solution for this case return -1 for j in range(i + 1, M - 1): temp = [] temp.extend(echelon.value[i][j]) temp.append(Binary('*')) temp.extend(result.value[j][0]) temp, _, _, _, _ = simplify(temp) sum_.extend(temp) if j != M - 2: sum_.append(Binary('+')) sum_, _, _, _, _ = simplify(sum_) result.value[index][0].extend(echelon.value[i][M - 1]) if sum_: if sum_[0].value < 0: result.value[index][0].append( Binary('-') ) # negative sign makes the negative sign in value positive else: result.value[index][0].append(Binary('-')) result.value[index][0].extend(sum_) result.value[index][0], _, _, _, _ = simplify(result.value[index][0]) result.value[index][0].append(Binary('/')) result.value[index][0].extend(echelon.value[i][i]) result.value[index][0], _, _, _, _ = simplify(result.value[index][0]) index -= 1 return result
def integrate(self, wrtVar=None): from visma.functions.constant import Constant result = copy.deepcopy(self) log = False for i, var in enumerate(result.value): if var == wrtVar: if (result.power[i] == -1): log = True funcLog = Logarithm() funcLog.operand = Variable() funcLog.operand.coefficient = 1 funcLog.operand.value.append(result.value[i]) funcLog.operand.power.append(1) del result.power[i] del result.value[i] if result.value == []: result.__class__ = Constant result.value = result.coefficient result.coefficient = 1 result.power = 1 result = [result] funcJoin = Binary() funcJoin.value = '*' result.append(funcJoin) result.append(funcLog) else: result.power[i] += 1 result.coefficient /= result.power[i] print(result) return result, log
def equationAnimationBuilder(lTokens, rTokens): """Given LHS & RHS tokens for an equation it builds the tokens of complete equation Arguments: lTokens {list} -- Tokens of LHS rTokens {list} -- Tokens of RHS Returns: animBulder {list} -- list of tokens of complete equation """ animBuilder = [] lToks = copy.deepcopy(lTokens) rToks = copy.deepcopy(rTokens) animBuilder = lToks lenToks = len(lToks) equalTo = Binary() equalTo.scope = [lenToks] equalTo.value = '=' animBuilder.append(equalTo) if len(rToks) == 0: zero = Zero() zero.scope = [lenToks + 1] animBuilder.append(zero) else: animBuilder.extend(rToks) return animBuilder
def scalarDiv(const, mat): """Divides constant terms with Matrix Arguments: const {string}--- constant value mat {visma.matrix.structure.Matrix} -- matrix token Returns: matRes {visma.matrix.structure.Matrix} -- result matrix token """ if const != 0: matRes = Matrix() matRes.empty([mat.dim[0], mat.dim[1]]) for i in range(mat.dim[0]): for j in range(mat.dim[1]): if len(mat.value[i][j]) != 1: matRes.value[i][j].append(Expression(mat.value[i][j])) else: matRes.value[i][j].extend(mat.value[i][j]) matRes.value[i][j].append(Binary('/')) matRes.value[i][j].append(Constant(int(const))) matRes = simplifyMatrix(matRes) return matRes else: logger.error("ZeroDivisionError: Cannot divide matrix by zero")
def scalarSub(const, mat): """ Subtracts constant terms with Matrix Arguments: const {string}--- constant value mat {visma.matrix.structure.Matrix} -- matrix token Returns: matRes {visma.matrix.structure.Matrix} -- subtracted matrix token Note: This scalar addition follows the following equation {mat} - {lambda}{identity mat} """ matRes = Matrix() matRes.empty([mat.dim[0], mat.dim[1]]) for i in range(mat.dim[0]): for j in range(mat.dim[1]): if i != j: matRes.value[i][j].extend(mat.value[i][j]) else: if len(mat.value[i][j]) != 1: matRes.value[i][j].append(Expression(mat.value[i][j])) else: matRes.value[i][j].extend(mat.value[i][j]) matRes.value[i][j].append(Binary('-')) matRes.value[i][j].append(Constant(int(const))) matRes = simplifyMatrix(matRes) return matRes
def row_echelon(mat): """ Returns the row echelon form of the given matrix Arguments: mat {visma.matrix.structure.Matrix} -- matrix token Returns: row_echelon {visma.matrix.structure.Matrix} -- result matrix token """ N = mat.dim[0] M = mat.dim[1] for k in range(0, N): if abs(mat.value[k][k][0].value) == 0.0: if k == N - 1: return simplifyMatrix(mat) else: for i in range(0, N): t = mat.value[k][i] mat.value[k][i] = mat.value[k + 1][i] mat.value[k + 1][i] = t else: for i in range(k + 1, N): temp = [] temp.extend(mat.value[i][k]) temp.append(Binary('/')) temp.extend(mat.value[k][k]) temp, _, _, _, _ = simplify(temp) for j in range(k + 1, M): temp2 = [] temp2.extend(mat.value[k][j]) temp2.append(Binary('*')) temp2.extend(temp) temp2, _, _, _, _ = simplify(temp2) mat.value[i][j].append(Binary('-')) mat.value[i][j].extend(temp2) mat.value[i][k].append(Binary('*')) mat.value[i][k].append(Constant(0)) mat = simplifyMatrix(mat) return simplifyMatrix(mat)
def moveRTokensToLTokens(lTokens, rTokens): """Moves tokens in RHS to LHS Arguments: ltokens {list} -- LHS tokens list rtokens {list} -- RHS tokens list Returns: ltokens {list} -- LHS tokens list rtokens {list} -- RHS tokens list """ if len(lTokens) == 0 and len(rTokens) > 0: return rTokens, lTokens elif isEquation(lTokens, rTokens): return lTokens, rTokens elif len(lTokens) != 0: for i, token in enumerate(rTokens): if i == 0 and not isinstance(token, Binary): binary = Binary() binary.value = '-' binary.scope = copy.copy(token.scope) binary.scope[-1] -= 1 lTokens.append(binary) if isinstance(token, Binary): if token.value in ['+', '-']: if token.value == '-': token.value = '+' else: token.value = '-' elif isinstance(token, Constant): if token.value < 0: if isinstance(lTokens[-1], Binary): if lTokens[-1].value == '-': token.value *= -1 lTokens[-1].value = '+' elif lTokens[-1].value == '+': token.value *= -1 lTokens[-1].value = '-' elif isinstance(token, Variable): if token.coefficient < 0: if isinstance(lTokens[-1], Binary): if lTokens[-1].value == '-': token.coefficient *= -1 lTokens[-1].value = '+' elif lTokens[-1].value == '+': token.coefficient *= -1 lTokens[-1].value = '-' lTokens.append(token) rTokens = [] return lTokens, rTokens
def traceMat(self): """Returns the trace of a square matrix (sum of diagonal elements) Arguments: mat {visma.matrix.structure.Matrix} -- matrix token Returns: trace {visma.matrix.structure.Matrix} -- string token """ from visma.simplify.simplify import simplify trace = [] for i in range(self.dim[0]): trace.extend(self.value[i][i]) trace.append(Binary('+')) trace.append(Constant(0)) trace, _, _, _, _ = simplify(trace) return trace
def __add__(self, other): """Adds two matrices Arguments: self {visma.matrix.structure.Matrix} -- matrix token other {visma.matrix.structure.Matrix} -- matrix token Returns: matSum {visma.matrix.structure.Matrix} -- sum matrix token Note: Make dimCheck before calling addMatrix """ matSum = Matrix() matSum.empty(self.dim) for i in range(self.dim[0]): for j in range(self.dim[1]): matSum.value[i][j].extend(self.value[i][j]) matSum.value[i][j].append(Binary('+')) matSum.value[i][j].extend(other.value[i][j]) from visma.matrix.operations import simplifyMatrix matSum = simplifyMatrix(matSum) return matSum
def __sub__(self, other): """Subtracts two matrices Arguments: self {visma.matrix.structure.Matrix} -- matrix token other {visma.matrix.structure.Matrix} -- matrix token Returns: matSub {visma.matrix.structure.Matrix} -- subtracted matrix token Note: Make dimCheck before calling subMatrix """ matSub = Matrix() matSub.empty(self.dim) for i in range(self.dim[0]): for j in range(self.dim[1]): matSub.value[i][j].extend(self.value[i][j]) matSub.value[i][j].append(Binary('-')) matSub.value[i][j].extend(other.value[i][j]) from visma.matrix.operations import simplifyMatrix matSub = simplifyMatrix(matSub) return matSub
def subMatrix(matA, matB): """Subtracts two matrices Arguments: matA {visma.matrix.structure.Matrix} -- matrix token matB {visma.matrix.structure.Matrix} -- matrix token Returns: matSub {visma.matrix.structure.Matrix} -- subtracted matrix token Note: Make dimCheck before calling subMatrix """ matSub = Matrix() matSub.empty(matA.dim) for i in range(matA.dim[0]): for j in range(matA.dim[1]): matSub.value[i][j].extend(matA.value[i][j]) matSub.value[i][j].append(Binary('-')) matSub.value[i][j].extend(matB.value[i][j]) matSub = simplifyMatrix(matSub) return matSub
def addMatrix(matA, matB): """Adds two matrices Arguments: matA {visma.matrix.structure.Matrix} -- matrix token matB {visma.matrix.structure.Matrix} -- matrix token Returns: matSum {visma.matrix.structure.Matrix} -- sum matrix token Note: Make dimCheck before calling addMatrix """ matSum = Matrix() matSum.empty(matA.dim) for i in range(matA.dim[0]): for j in range(matA.dim[1]): matSum.value[i][j].extend(matA.value[i][j]) matSum.value[i][j].append(Binary('+')) matSum.value[i][j].extend(matB.value[i][j]) matSum = simplifyMatrix(matSum) return matSum
def scalarMult(const, mat): """Multiplies constant terms with Matrix Arguments: const {string}--- constant value mat {visma.matrix.structure.Matrix} -- matrix token Returns: matRes {visma.matrix.structure.Matrix} -- product matrix token """ matRes = Matrix() matRes.empty([mat.dim[0], mat.dim[1]]) for i in range(mat.dim[0]): for j in range(mat.dim[1]): if len(mat.value[i][j]) != 1: matRes.value[i][j].append(Expression(mat.value[i][j])) else: matRes.value[i][j].extend(mat.value[i][j]) matRes.value[i][j].append(Binary('*')) matRes.value[i][j].append(Constant(int(const))) matRes = simplifyMatrix(matRes) return matRes
def multiplyExpressions(expression1, expression2): tokens = [] tokens1 = expression1.tokens tokens2 = expression2.tokens coeff = expression1.coefficient * expression2.coefficient for i, token1 in enumerate(tokens1): # print(token1.value) op = 1 if i != 0: if isinstance(tokens1[i - 1], Binary): if tokens1[i - 1].value == '+': op *= 1 elif tokens1[i - 1].value == '-': op *= -1 if isinstance(token1, Variable) or isinstance(token1, Constant): for j, token2 in enumerate(tokens2): # print(token2.value) op2 = op if isinstance(token2, Variable) or isinstance(token2, Constant): if j == 0 and i == 0: pass else: if j != 0: if isinstance(tokens2[j - 1], Binary): if tokens2[j - 1].value == '+': op2 *= 1 elif tokens2[j - 1].value == '-': op2 *= -1 binary = Binary() if op2 == -1: binary.value = '-' elif op2 == 1: binary.value = '+' tokens.append(binary) tokens.append(multiplySelect(token1, token2, coeff))
def quadraticRoots(lTokens, rTokens): '''Used to get quadratic roots of an equation Argument: lTokens {list} -- list of LHS tokens rTokens {list} -- list of RHS tokens Returns: lTokens {list} -- list of LHS tokens rTokens {list} -- list of RHS tokens {empty list} token_string {string} -- final result stored in a string animation {list} -- list of equation solving process comments {list} -- list of comments in equation solving process ''' from visma.solvers.polynomial.roots import getCoefficients animations = [] comments = [] lTokens, rTokens, _, token_string, animNew1, commentNew1 = simplifyEquation(lTokens, rTokens) animations.extend(animNew1) comments.extend(commentNew1) if len(rTokens) > 0: lTokens, rTokens = moveRTokensToLTokens(lTokens, rTokens) coeffs = getCoefficients(lTokens, rTokens, 2) var = getVariables(lTokens) roots, animNew2, commentNew2 = getRootsQuadratic(coeffs) animations.extend(animNew2) comments.extend(commentNew2) if len(roots) == 1: tokens = [] expression = Expression(coefficient=1, power=2) variable = Variable(1, var[0], 1) tokens.append(variable) binary = Binary() if roots[0] < 0: roots[0] *= -1 binary.value = '+' else: binary.value = '-' tokens.append(binary) constant = Constant(round(roots[0], ROUNDOFF), 1) tokens.append(constant) expression.tokens = tokens lTokens = [expression] elif len(roots) == 2: tokens = [] expression = Expression(coefficient=1, power=1) variable = Variable(1, var[0], 1) tokens.append(variable) binary = Binary() if roots[0] < 0: roots[0] *= -1 binary.value = '+' else: binary.value = '-' tokens.append(binary) constant = Constant(round(roots[0], ROUNDOFF), 1) tokens.append(constant) expression.tokens = tokens tokens2 = [] expression2 = Expression(coefficient=1, power=1) tokens2.append(variable) binary2 = Binary() if roots[1] < 0: roots[1] *= -1 binary2.value = '+' else: binary2.value = '-' tokens2.append(binary2) constant2 = Constant(round(roots[1], ROUNDOFF), 1) tokens2.append(constant2) expression2.tokens = tokens2 binary3 = Binary() binary3.value = '*' lTokens = [expression, binary3, expression2] elif len(roots) == 3: binary4 = Binary() if roots[0] < 0: roots[0] *= -1 binary4.value = '+' else: binary4.value = '-' constant3 = Constant(round(roots[0], ROUNDOFF), 1) binary5 = Binary() binary5.value = '*' constant2 = Constant(round(roots[2], ROUNDOFF), 1) tokens = [] expression = Expression(coefficient=1, power=1) variable = Variable(1, var[0], 1) tokens.extend([variable, binary4, constant3]) binary = Binary() binary.value = '+' tokens.extend([binary, constant2, binary5]) constant = Constant(round(roots[1], ROUNDOFF), 1) sqrt = Sqrt(Constant(2, 1), constant) tokens.append(sqrt) expression.tokens = tokens tokens2 = [] expression2 = Expression(coefficient=1, power=1) variable2 = Variable(1, var[0], 1) tokens2.extend([variable2, binary4, constant3]) binary2 = Binary() binary2.value = '-' tokens2.extend([binary2, constant2, binary5, sqrt]) expression2.tokens = tokens2 binary3 = Binary() binary3.value = '*' lTokens = [expression, binary3, expression2] zero = Zero() rTokens = [zero] comments.append([]) tokenToStringBuilder = copy.deepcopy(lTokens) tokLen = len(lTokens) equalTo = Binary() equalTo.scope = [tokLen] equalTo.value = '=' tokenToStringBuilder.append(equalTo) tokenToStringBuilder.extend(rTokens) animations.append(copy.deepcopy(tokenToStringBuilder)) token_string = tokensToString(tokenToStringBuilder) return lTokens, rTokens, [], token_string, animations, comments
def inverse(self): """Calculates the inverse of the matrix using Gauss-Jordan Elimination Arguments: matrix {visma.matrix.structure.Matrix} -- matrix token Returns: inv {visma.matrix.structure.Matrix} -- result matrix token """ from visma.simplify.simplify import simplify from visma.io.tokenize import tokenizer from visma.io.parser import tokensToString if tokensToString(self.determinant()) == "0": return -1 self.dim[0] = len(self.value) self.dim[1] = len(self.value[0]) n = self.dim[0] mat = Matrix() mat.empty([n, 2 * n]) for i in range(0, n): for j in range(0, 2 * n): if j < n: mat.value[i][j] = self.value[i][j] else: mat.value[i][j] = [] for i in range(0, n): for j in range(n, 2 * n): if j == (i + n): mat.value[i][j].extend(tokenizer('1')) else: mat.value[i][j].extend(tokenizer("0")) for i in range(n - 1, 0, -1): if mat.value[i - 1][0][0].value < mat.value[i][0][0].value: for j in range(0, 2 * n): temp = mat.value[i][j] mat.value[i][j] = mat.value[i - 1][j] mat.value[i - 1][j] = temp for i in range(0, n): for j in range(0, n): if j != i: temp = [] if len(mat.value[j][i]) != 1: temp.append(Expression(mat.value[j][i])) else: temp.extend(mat.value[j][i]) temp.append(Binary('/')) if len(mat.value[i][i]) != 1: temp.append(Expression(mat.value[i][i])) else: temp.extend(mat.value[i][i]) temp, _, _, _, _ = simplify(temp) for k in range(0, 2 * n): t = [] if mat.value[i][k][0].value != 0: if len(mat.value[i][k]) != 1: t.append(Expression(mat.value[i][k])) else: t.extend(mat.value[i][k]) t.append(Binary('*')) if len(temp) != 1: t.append(Expression(temp)) else: t.extend(temp) t, _, _, _, _ = simplify(t) mat.value[j][k].append(Binary('-')) if len(t) != 1: mat.value[j][k].append(Expression(t)) else: mat.value[j][k].extend(t) mat.value[j][k], _, _, _, _ = simplify( mat.value[j][k]) for i in range(0, n): temp = [] temp.extend(mat.value[i][i]) for j in range(0, 2 * n): if mat.value[i][j][0].value != 0: mat.value[i][j].append(Binary('/')) mat.value[i][j].extend(temp) mat.value[i][j], _, _, _, _ = simplify(mat.value[i][j]) inv = SquareMat() inv.empty([n, n]) for i in range(0, n): for j in range(n, 2 * n): inv.value[i][j - n] = mat.value[i][j] return inv
def expressionSimplification(tokens_now, scope, tokens1): '''Makes an input equation free from Expressions, i.e. solving each Expression recursively to convert them in other tokens. Arguments: tokens_now {list} -- list of original tokens as function gets called recursively scope {list} -- integers (bounds) indicating which Expression we are currently solving tokens1 {list} -- list of current tokens as function gets called recursively Returns: simToks {list} -- list of simplified tokens of each Expression availableOperations {list} -- list of operations which can be performed on a equation token token_string {string} -- final result stored in a string animation {list} -- list of equation solving process comments {list} -- list of comments in equation solving process ''' animation = [] comments = [] pfTokens = [] i = 0 while (i < len(tokens1)): if (i + 1 < len(tokens1)): if isinstance(tokens1[i], Binary) and tokens1[i].value == '^': if isinstance(tokens1[i - 1], Expression): tokens1[i - 1].tokens, _, _, _, _ = expressionSimplification( tokens_now, scope, tokens1[i - 1].tokens) if isinstance(tokens1[i + 1], Expression): tokens1[i + 1].tokens, _, _, _, _ = expressionSimplification( tokens_now, scope, tokens1[i + 1].tokens) if len(tokens1[i + 1].tokens) == 1 and isinstance( tokens1[i + 1].tokens[0], Constant): tokens1[i + 1] = Constant( tokens1[i + 1].tokens[0].calculate(), 1, 1) if (isinstance(tokens1[i], Binary) and tokens1[i].value == '^') and isinstance( tokens1[i + 1], Constant): if float(tokens1[i + 1].calculate()).is_integer(): rep = int(tokens1[i + 1].calculate()) for _ in range(rep - 1): pfTokens.extend([Binary('*'), tokens1[i - 1]]) i += 1 else: pfTokens.append(tokens1[i]) else: pfTokens.append(tokens1[i]) else: pfTokens.append(tokens1[i]) i += 1 tokens1 = copy.deepcopy(pfTokens) animation.append(pfTokens) comments.append(['Expanding the powers of expressions']) mulFlag = True expressionMultiplication = False # Check for the case: {Non-Expression} * {Expression} for _ in range(50): for i, _ in enumerate(tokens1): mulFlag = False if isinstance(tokens1[i], Expression): if (i > 1): if (tokens1[i - 1].value == '*'): scope.append(i) tokens1[ i].tokens, _, _, _, _ = expressionSimplification( tokens_now, scope, tokens1[i].tokens) if isinstance(tokens1[i - 2], Expression): scope.append(i - 2) tokens1[ i - 2].tokens, _, _, _, _ = expressionSimplification( tokens_now, scope, tokens1[i - 2].tokens) a = tokens1[i - 2] b = tokens1[i] c = a * b mulFlag = True expressionMultiplication = True if isinstance(c, Expression): scope.append(i) c.tokens, _, _, _, _ = expressionSimplification( tokens_now, scope, c.tokens) tokens1[i] = c del tokens1[i - 1] del tokens1[i - 2] break trigonometricError = False # Check for the case: {Expression} * {Non-Expression} if not trigonometricError: for _ in range(50): for i, _ in enumerate(tokens1): mulFlag = False if isinstance(tokens1[i], Expression): if i + 2 < len(tokens1): if (tokens1[i + 1].value == '*'): scope.append(i) tokens1[ i].tokens, _, _, _, _ = expressionSimplification( tokens_now, scope, tokens1[i].tokens) if isinstance(tokens1[i + 2], Expression): scope.append(i + 2) tokens1[ i + 2].tokens, _, _, _, _ = expressionSimplification( tokens_now, scope, tokens1[i + 2].tokens) a = tokens1[i + 2] b = tokens1[i] trigonometricError = False for ec in b.tokens: if isinstance(ec, Trigonometric): trigonometricError = True break if not trigonometricError: c = a * b mulFlag = True expressionMultiplication = True if isinstance(c, Expression): scope.append(i) c.tokens, _, _, _, _ = expressionSimplification( tokens_now, scope, c.tokens) tokens1[i] = c del tokens1[i + 1] del tokens1[i + 1] break if not mulFlag: break if expressionMultiplication: animation.append(tokens1) comments.append(['Multiplying expressions']) # TODO: Implement verbose multiplication steps. simToks = [] expressionPresent = False for i, _ in enumerate(tokens1): if isinstance(tokens1[i], Expression): expressionPresent = True scope.append(i) newToks, _, _, _, _ = expressionSimplification( tokens_now, scope, tokens1[i].tokens) if not simToks: simToks.extend(newToks) elif (simToks[len(simToks) - 1].value == '+'): if isinstance(newToks[0], Constant): if (newToks[0].value < 0): simToks.pop() simToks.extend(newToks) elif (simToks[len(simToks) - 1].value == '-'): for _, x in enumerate(newToks): if x.value == '+': x.value = '-' elif x.value == '-': x.value = '+' if (isinstance(newToks[0], Constant)): if (newToks[0].value < 0): simToks[-1].value = '+' newToks[0].value = abs(newToks[0].value) elif (isinstance(newToks[0], Variable)): if (newToks[0].coefficient < 0): simToks[-1].value = '+' newToks[0].coefficient = abs(newToks[0].coefficient) simToks.extend(newToks) else: simToks.extend([tokens1[i]]) simToks = tokenizer(tokensToString(simToks)) if expressionPresent: animation += [simToks] comments += [['Opening up all the brackets']] # TODO: Implement Trigonometric functions in the simplify module. trigonometricError = False for tk in simToks: if isinstance(tk, Trigonometric): trigonometricError = True break if not trigonometricError: if scope == []: simToks, availableOperations, token_string, animExtra, commentExtra = simplifification( simToks) animExtra.pop(0) animation += animExtra comments += commentExtra else: availableOperations = '' token_string = '' else: availableOperations = [] token_string = tokensToString(simToks) # TODO: Implement verbose steps in simplification of Expressions (steps shown can be varied depending on length of expression) if scope != []: scope.pop() return simToks, availableOperations, token_string, animation, comments
def divisionEquation(lToks, rToks, direct=False): lTokens = copy.deepcopy(lToks) rTokens = copy.deepcopy(rToks) animation = [] comments = [] if direct: comments = [[]] animBuilder = lToks lenToks = len(lToks) equalTo = Binary() equalTo.scope = [lenToks] equalTo.value = '=' animBuilder.append(equalTo) if len(rToks) == 0: zero = Zero() zero.scope = [lenToks + 1] animBuilder.append(zero) else: animBuilder.extend(rToks) animation.append(copy.deepcopy(animBuilder)) lVariables = [] lVariables.extend(getLevelVariables(lTokens)) rVariables = [] rVariables.extend(getLevelVariables(rTokens)) availableOperations = getOperationsExpression(lVariables, lTokens) while '/' in availableOperations: _, tok, rem, com = expressionDivision(lVariables, lTokens) lTokens = removeToken(tok, rem) comments.append(com) animBuilder = copy.deepcopy(lTokens) lenToks = len(lTokens) equalTo = Binary() equalTo.scope = [lenToks] equalTo.value = '=' animBuilder.append(equalTo) if len(rTokens) == 0: zero = Zero() zero.scope = [lenToks + 1] animBuilder.append(zero) else: animBuilder.extend(rTokens) animation.append(copy.deepcopy(animBuilder)) lVariables = getLevelVariables(lTokens) availableOperations = getOperationsExpression(lVariables, lTokens) availableOperations = getOperationsExpression(rVariables, rTokens) while '/' in availableOperations: _, tok, rem, com = expressionDivision(rVariables, rTokens) rTokens = removeToken(tok, rem) comments.append(com) animBuilder = copy.deepcopy(lTokens) lenToks = len(lTokens) equalTo = Binary() equalTo.scope = [lenToks] equalTo.value = '=' animBuilder.append(equalTo) if len(rTokens) == 0: zero = Zero() zero.scope = [lenToks + 1] animBuilder.append(zero) else: animBuilder.extend(rTokens) animation.append(copy.deepcopy(animBuilder)) rVariables = getLevelVariables(rTokens) availableOperations = getOperationsExpression(rVariables, rTokens) tokenToStringBuilder = copy.deepcopy(lTokens) lenToks = len(lTokens) equalTo = Binary() equalTo.scope = [lenToks] equalTo.value = '=' tokenToStringBuilder.append(equalTo) if len(rTokens) == 0: zero = Zero() zero.scope = [lenToks + 1] tokenToStringBuilder.append(zero) else: tokenToStringBuilder.extend(rTokens) token_string = tokensToString(tokenToStringBuilder) lVariables = getLevelVariables(lTokens) rVariables = getLevelVariables(rTokens) availableOperations = getOperationsEquation( lVariables, lTokens, rVariables, rTokens) return lTokens, rTokens, availableOperations, token_string, animation, comments
def cubicRoots(lTokens, rTokens): '''Used to get roots of a cubic equation This functions also translates roots {list} into final result of solution Argument: lTokens {list} -- list of LHS tokens rTokens {list} -- list of RHS tokens Returns: lTokens {list} -- list of LHS tokens rTokens {list} -- list of RHS tokens {empty list} token_string {string} -- final result stored in a string animation {list} -- list of equation solving process comments {list} -- list of comments in equation solving process ''' from visma.solvers.polynomial.roots import getCoefficients animations = [] comments = [] lTokens, rTokens, _, token_string, animNew1, commentNew1 = simplifyEquation( lTokens, rTokens) animations.extend(animNew1) comments.extend(commentNew1) if len(rTokens) > 0: lTokens, rTokens = moveRTokensToLTokens(lTokens, rTokens) coeffs = getCoefficients(lTokens, rTokens, 3) var = getVariables(lTokens) roots, animNew2, commentNew2 = getRootsCubic(coeffs) animations.extend(animNew2) comments.extend(commentNew2) tokens1 = [] expression1 = Expression(coefficient=1, power=3) variable = Variable(1, var[0], 1) tokens1.append(variable) if roots[0][1] == 0: binary = Binary() if roots[0][0] < 0: roots[0][0] *= -1 binary.value = '+' else: binary.value = '-' tokens1.append(binary) constant = Constant(round(roots[0][0], ROUNDOFF), 1) tokens1.append(constant) expression1.tokens = tokens1 lTokens = [expression1, Binary('*')] if len(roots) > 1: expression1.power = 1 for _, root in enumerate(roots[1:]): tokens2 = [] expression2 = Expression(coefficient=1, power=1) variable = Variable(1, var[0], 1) tokens2.append(variable) binary = Binary() if root[1] == 0: if root[0] < 0: root[0] *= -1 binary.value = '+' else: binary.value = '-' tokens2.append(binary) constant = Constant(round(root[0], ROUNDOFF), 1) tokens2.append(constant) else: binary.value = '-' tokens2.append(binary) expressionResult = Expression(coefficient=1, power=1) tokensResult = [] real = Constant(round(root[0], ROUNDOFF), 1) tokensResult.append(real) imaginary = Constant(round(root[1], ROUNDOFF), 1) if imaginary.value < 0: tokensResult.append(Minus()) imaginary.value = abs(imaginary.value) tokensResult.append(imaginary) else: tokensResult.extend([Plus(), imaginary]) sqrt = Sqrt(Constant(2, 1), Constant(-1, 1)) tokensResult.append(Binary('*')) tokensResult.append(sqrt) expressionResult.tokens = tokensResult tokens2.append(expressionResult) expression2.tokens = tokens2 lTokens.extend([expression2, Binary('*')]) lTokens.pop() rTokens = [Zero()] tokenToStringBuilder = copy.deepcopy(lTokens) tokLen = len(lTokens) equalTo = Binary() equalTo.scope = [tokLen] equalTo.value = '=' tokenToStringBuilder.append(equalTo) tokenToStringBuilder.extend(rTokens) token_string = tokensToString(tokenToStringBuilder) animations.append(copy.deepcopy(tokenToStringBuilder)) comments.append([]) return lTokens, rTokens, [], token_string, animations, comments
def simplifyEquation(lToks, rToks): """Simplifies given equation tokens Arguments: lToks {list} -- LHS tokens list rToks {list} -- RHS tokens list Returns: lTokens {list} -- LHS tokens list rTokens {list} -- RHS tokens list availableOperations {list} -- list of operations token_string {string} -- simplified result in string animation {list} -- list of equation simplification progress comments {list} -- list of solution steps """ lTokens = copy.deepcopy(lToks) rTokens = copy.deepcopy(rToks) animation = [] comments = [[]] lVariables = [] lVariables.extend(getLevelVariables(lTokens)) rVariables = [] rVariables.extend(getLevelVariables(rTokens)) animBuilder = lToks lenToks = len(lToks) equalTo = Binary() equalTo.scope = [lenToks] equalTo.value = '=' animBuilder.append(equalTo) if len(rToks) == 0: zero = Zero() zero.scope = [lenToks + 1] animBuilder.append(zero) else: animBuilder.extend(rToks) animation.append(copy.deepcopy(animBuilder)) availableOperations = getOperationsEquation(lVariables, lTokens, rVariables, rTokens) while len(availableOperations) > 0: if '/' in availableOperations: lTokens, rTokens, availableOperations, token_string, anim, com = divisionEquation( lTokens, rTokens) animation.pop(len(animation) - 1) animation.extend(anim) comments.extend(com) elif '*' in availableOperations: lTokens, rTokens, availableOperations, token_string, anim, com = multiplicationEquation( lTokens, rTokens) animation.pop(len(animation) - 1) animation.extend(anim) comments.extend(com) elif '+' in availableOperations: lTokens, rTokens, availableOperations, token_string, anim, com = additionEquation( lTokens, rTokens) animation.pop(len(animation) - 1) animation.extend(anim) comments.extend(com) elif '-' in availableOperations: lTokens, rTokens, availableOperations, token_string, anim, com = subtractionEquation( lTokens, rTokens) animation.pop(len(animation) - 1) animation.extend(anim) comments.extend(com) lVariables = getLevelVariables(lTokens) rVariables = getLevelVariables(rTokens) availableOperations = getOperationsEquation(lVariables, lTokens, rVariables, rTokens) moved = False if len(rTokens) > 0: moved = True lTokens, rTokens = moveRTokensToLTokens(lTokens, rTokens) tokenToStringBuilder = copy.deepcopy(lTokens) lenToks = len(lTokens) equalTo = Binary() equalTo.scope = [lenToks] equalTo.value = '=' tokenToStringBuilder.append(equalTo) if len(rTokens) == 0: zero = Zero() zero.scope = [lenToks + 1] tokenToStringBuilder.append(zero) else: tokenToStringBuilder.extend(rTokens) if moved: animation.append(copy.deepcopy(tokenToStringBuilder)) comments.append(['Moving the rest of variables/constants to LHS']) token_string = tokensToString(tokenToStringBuilder) return lTokens, rTokens, availableOperations, token_string, animation, comments
def divisionEquation(lToks, rToks, direct=False): """Function deals with division related operations FOR EQUATIONS (driver function in division module) Arguments: rtoks {list} -- list of right tokens ltoks {list} -- list of left tokens direct {bool} -- True when we are only concerned about multiplications terms in the input Returns: availableOperations {list} -- list of operations which can be performed on a equation token token_string {string} -- final result stored in a string animation {list} -- list of equation solving process comments {list} -- list of comments in equation solving process """ lTokens = copy.deepcopy(lToks) rTokens = copy.deepcopy(rToks) animation = [] comments = [] if direct: comments = [[]] animBuilder = lToks lenToks = len(lToks) equalTo = Binary() equalTo.scope = [lenToks] equalTo.value = '=' animBuilder.append(equalTo) if len(rToks) == 0: zero = Zero() zero.scope = [lenToks + 1] animBuilder.append(zero) else: animBuilder.extend(rToks) animation.append(copy.deepcopy(animBuilder)) lVariables = [] lVariables.extend(getLevelVariables(lTokens)) rVariables = [] rVariables.extend(getLevelVariables(rTokens)) availableOperations = getOperationsExpression(lVariables, lTokens) while '/' in availableOperations: _, tok, rem, com = expressionDivision(lVariables, lTokens) lTokens = removeToken(tok, rem) comments.append(com) animBuilder = copy.deepcopy(lTokens) lenToks = len(lTokens) equalTo = Binary() equalTo.scope = [lenToks] equalTo.value = '=' animBuilder.append(equalTo) if len(rTokens) == 0: zero = Zero() zero.scope = [lenToks + 1] animBuilder.append(zero) else: animBuilder.extend(rTokens) animation.append(copy.deepcopy(animBuilder)) lVariables = getLevelVariables(lTokens) availableOperations = getOperationsExpression(lVariables, lTokens) availableOperations = getOperationsExpression(rVariables, rTokens) while '/' in availableOperations: _, tok, rem, com = expressionDivision(rVariables, rTokens) rTokens = removeToken(tok, rem) comments.append(com) animBuilder = copy.deepcopy(lTokens) lenToks = len(lTokens) equalTo = Binary() equalTo.scope = [lenToks] equalTo.value = '=' animBuilder.append(equalTo) if len(rTokens) == 0: zero = Zero() zero.scope = [lenToks + 1] animBuilder.append(zero) else: animBuilder.extend(rTokens) animation.append(copy.deepcopy(animBuilder)) rVariables = getLevelVariables(rTokens) availableOperations = getOperationsExpression(rVariables, rTokens) tokenToStringBuilder = copy.deepcopy(lTokens) lenToks = len(lTokens) equalTo = Binary() equalTo.scope = [lenToks] equalTo.value = '=' tokenToStringBuilder.append(equalTo) if len(rTokens) == 0: zero = Zero() zero.scope = [lenToks + 1] tokenToStringBuilder.append(zero) else: tokenToStringBuilder.extend(rTokens) token_string = tokensToString(tokenToStringBuilder) lVariables = getLevelVariables(lTokens) rVariables = getLevelVariables(rTokens) availableOperations = getOperationsEquation(lVariables, lTokens, rVariables, rTokens) return lTokens, rTokens, availableOperations, token_string, animation, comments
def integrateTokens(funclist, wrtVar): """Integrates given tokens wrt given variable Arguments: funclist {list} -- list of funtion tokens wrtVar {string} -- with respect to variable Returns: intFunc {list} -- list of integrated tokens animNew {list} -- equation tokens for step-by-step commentsNew {list} -- comments for step-by-step """ intFunc = [] animNew = [] commentsNew = [ "Integrating with respect to " + r"$" + wrtVar + r"$" + "\n" ] for func in funclist: if isinstance(func, Operator): # add isFuntionOf intFunc.append(func) else: newfunc = [] while (isinstance(func, Function)): commentsNew[0] += r"$" + "\int \ " + "( " + func.__str__( ) + ")" + " d" + wrtVar + r"$" funcCopy = copy.deepcopy(func) if wrtVar in funcCopy.functionOf(): if not isinstance(funcCopy, Constant): for i, var in enumerate(funcCopy.value): log = False if var == wrtVar: if (funcCopy.power[i] == -1): log = True funcLog = Logarithm() funcLog.operand = Variable() funcLog.operand.coefficient = 1 funcLog.operand.value.append( funcCopy.value[i]) funcLog.operand.power.append(1) del funcCopy.power[i] del funcCopy.value[i] if funcCopy.value == []: funcCopy.__class__ = Constant funcCopy.value = funcCopy.coefficient funcCopy.coefficient = 1 funcCopy.power = 1 funcCopy = [funcCopy] funcJoin = Binary() funcJoin.value = '*' funcCopy.append(funcJoin) funcCopy.append(funcLog) else: funcCopy.power[i] += 1 funcCopy.coefficient /= funcCopy.power[i] if log: commentsNew[0] += r"$" + "= " + funcCopy[0].__str__( ) + "*" + funcCopy[2].__str__() + "\ ;\ " + r"$" newfunc.extend(funcCopy) else: commentsNew[0] += r"$" + "= " + funcCopy.__str__( ) + "\ ;\ " + r"$" newfunc.append(funcCopy) else: if isinstance(funcCopy, Variable): funcCopy.value.append(wrtVar) funcCopy.power.append(1) if isinstance(funcCopy, Constant): coeff = funcCopy.value funcCopy = Variable() funcCopy.coefficient = coeff funcCopy.value.append(wrtVar) funcCopy.power.append(1) newfunc.append(funcCopy) commentsNew[0] += r"$" + "= " + funcCopy.__str__( ) + "\ ;\ " + r"$" if func.operand is None: break else: func = func.operand if isinstance(func, Constant): intFunc = Zero() break intFunc.extend(newfunc) animNew.extend(intFunc) return intFunc, animNew, commentsNew