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 differentiateTokens(funclist, wrtVar): """Differentiates given tokens wrt given variable Arguments: funclist {list} -- list of function tokens wrtVar {string} -- with respect to variable Returns: diffFunc {list} -- list of differentiated tokens animNew {list} -- equation tokens for step-by-step commentsNew {list} -- comments for step-by-step """ diffFunc = [] animNew = [] commentsNew = ["Differentiating with respect to " + r"$" + wrtVar + r"$" + "\n"] for func in funclist: if isinstance(func, Operator): diffFunc.append(func) else: newfunc = [] while(isinstance(func, Function)): commentsNew[0] += r"$" + "\\frac{d}{d" + wrtVar + "} ( " + func.__str__() + ")" + r"$" funcCopy = copy.deepcopy(func) if wrtVar in funcCopy.functionOf(): if not isinstance(funcCopy, Constant): for i, var in enumerate(funcCopy.value): if var == wrtVar: funcCopy.coefficient *= funcCopy.power[i] funcCopy.power[i] -= 1 if(funcCopy.power[i] == 0): del funcCopy.power[i] del funcCopy.value[i] if funcCopy.value == []: funcCopy.__class__ = Constant funcCopy.value = funcCopy.coefficient funcCopy.coefficient = 1 funcCopy.power = 1 commentsNew[0] += r"$" + r"= " + funcCopy.__str__() + r"\ ;\ " + r"$" newfunc.append(funcCopy) func.differentiate() if not(isinstance(func, Constant) and func.value == 1): newfunc.append(func) else: funcCopy = (Zero()) newfunc.append(funcCopy) commentsNew[0] += r"$" + r"= " + funcCopy.__str__() + r"\ ;\ " + r"$" if func.operand is None: break else: func = func.operand if isinstance(func, Constant): diffFunc = Zero() break diffFunc.extend(newfunc) animNew.extend(diffFunc) return diffFunc, animNew, commentsNew
def differentiateTokens(funclist, wrtVar): """Differentiates given tokens wrt given variable Arguments: funclist {list} -- list of function tokens wrtVar {string} -- with respect to variable Returns: diffFunc {list} -- list of differentiated tokens animNew {list} -- equation tokens for step-by-step commentsNew {list} -- comments for step-by-step """ diffFunc = [] animNew = [] commentsNew = ["Differentiating with respect to " + r"$" + wrtVar + r"$" + "\n"] for func in funclist: if isinstance(func, Operator): diffFunc.append(func) else: newExpression = Expression() newfunc = [] while(isinstance(func, Function)): commentsNew[0] += r"$" + "\\frac{d}{d" + wrtVar + "} ( " + func.__str__() + ")" + r"$" funcCopy = copy.deepcopy(func) if wrtVar in funcCopy.functionOf(): if isinstance(funcCopy, Trigonometric) or isinstance(funcCopy, Logarithm) or isinstance(funcCopy, Variable) or isinstance(funcCopy, Exponential): funcCopy = funcCopy.differentiate(wrtVar) newfunc.append(funcCopy) commentsNew[0] += r"$" + r"= " + funcCopy.__str__() + r"\ ;\ " + r"$" else: funcCopy = Zero() newfunc.append(funcCopy) commentsNew[0] += r"$" + r"= " + funcCopy.__str__() + r"\ ;\ " + r"$" newfunc.append(Multiply()) if func.operand is None: break else: func = func.operand if isinstance(func, Constant): diffFunc = Zero() break newfunc.pop() newExpression.tokens = newfunc diffFunc.extend([newExpression]) animNew.extend(diffFunc) return diffFunc, animNew, commentsNew
def determinant(self, mat=None): """Calculates square matrices' determinant Returns: list of tokens forming the determinant """ from visma.simplify.simplify import simplify if mat is None: self.dimension() mat = np.array(self.value) if (mat.shape[0] > 2): ans = [] for i in range(mat.shape[0]): mat1 = SquareMat() mat1.value = np.concatenate((mat[1:, :i], mat[1:, i + 1:]), axis=1).tolist() a, _, _, _, _ = simplify(mat1.determinant()) if (a[0].value != 0 and a != []): a, _, _, _, _ = simplify(a + [Multiply()] + mat[0][i].tolist()) if (i % 2 == 0): if (ans != []): ans, _, _, _, _ = simplify(ans + [Plus()] + a) else: ans = a else: ans, _, _, _, _ = simplify(ans + [Minus()] + a) elif (mat.shape[0] == 2): a = Multiply() b = Minus() mat = mat.tolist() a1, _, _, _, _ = simplify(mat[0][0] + [a] + mat[1][1]) a2, _, _, _, _ = simplify(mat[0][1] + [a] + mat[1][0]) ans, _, _, _, _ = simplify([a1[0], b, a2[0]]) if (isinstance(ans[0], Minus) or isinstance( ans[0], Plus)) and ans[0].value not in ['+', '-']: ans[0] = Constant(ans[0].value) else: ans, _, _, _, _ = simplify(mat[0][0]) if not ans: ans = Zero() return ans
def differentiate(self, wrtVar): from visma.functions.constant import Constant, Zero result = copy.deepcopy(self) if wrtVar in result.functionOf(): for i, var in enumerate(result.value): if var == wrtVar: result.coefficient *= result.power[i] result.power[i] -= 1 if (result.power[i] == 0): del result.power[i] del result.value[i] if result.value == []: result.__class__ = Constant result.value = result.coefficient result.coefficient = 1 result.power = 1 else: result = Zero() return result
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 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 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
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 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 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