def __mul__(self, other): if other.isZero(): return other elif self.isZero(): return self elif isinstance(other, Constant): const = Constant(self.calculate() * other.calculate()) return const elif isinstance(other, Variable): variable = Variable() variable.coefficient = self.calculate() * other.coefficient variable.value.extend(other.value) variable.power.extend(other.power) self = variable return variable elif isinstance(other, Expression): if other.power == 1: other.tokens[0] = self * other.tokens[0] for i, var in enumerate(other.tokens): if other.tokens[i-1].value == '+' or other.tokens[i-1].value == '-': other.tokens[i] = self * var else: if isinstance(other.power, Constant) or isinstance(other.power, int) or isinstance(other.power, float): self = self ** (-1 * other.power) for i, var in enumerate(other.tokens): if other.tokens[i - 1].value == '+' or other.tokens[i - 1].value == '-': other.tokens[i] = self * var else: other.coefficient = self * other.coefficient else: other.coefficient = self.calculate() * other.coefficient return other
def __sub__(self, other): if isinstance(other, Constant): self = self + Constant(-1, 1, 1) * other return self elif isinstance(other, Variable): if self.value == 0: other.coefficient *= -1 return other expression = Expression() expression.tokens = [self] expression.tokens.extend([Minus(), other]) elif isinstance(other, Expression): expression = Expression() expression.tokens = [self] if other.power == 1: coeff = other.coefficient for i, token in enumerate(other.tokens): print(expression, " ", type(token), other.tokens[i-1]) if isinstance(token, Constant): if other.tokens[i-1].value == '+' or i == 0: expression.tokens[0] = Constant(self.calculate() - token.calculate()*coeff) elif other.tokens[i-1].value == '-': expression.tokens[0] = Constant(self.calculate() + token.calculate()*coeff) elif isinstance(token, Variable): if other.tokens[i-1].value == '+' or i == 0: expression.tokens.extend([Minus(), Variable(token)]) elif other.tokens[i-1].value == '-': expression.tokens.extend([Plus(), Variable(token)]) else: expression.tokens.extend([Minus(), other]) self = expression return expression
def integrateTokens(funclist, wrtVar): """Integrates given tokens wrt given variable Arguments: funclist {list} -- list of function 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 isfunctionOf intFunc.append(func) else: newfunc = [] commentsNew[0] += r"$" + r"\int \ " + r"( " + func.__str__( ) + ")" + r" d" + wrtVar + r"$" funcCopy = copy.deepcopy(func) if wrtVar in funcCopy.functionOf(): if isinstance(funcCopy, Variable): log = False funcCopy, log = funcCopy.integrate(wrtVar) if log: commentsNew[0] += r"$" + r"= " + funcCopy[0].__str__( ) + r"*" + funcCopy[2].__str__() + r"\ ;\ " + r"$" newfunc.extend(funcCopy) else: commentsNew[0] += r"$" + r"= " + funcCopy.__str__( ) + r"\ ;\ " + r"$" newfunc.append(funcCopy) elif isinstance(funcCopy, Trigonometric): funcCopy = funcCopy.integrate(wrtVar) newfunc.append(funcCopy) commentsNew[0] += r"$" + r"= " + funcCopy.__str__( ) + r"\ ;\ " + r"$" 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"$" + r"= " + funcCopy.__str__( ) + r"\ ;\ " + r"$" intFunc.extend(newfunc) animNew.extend(intFunc) return intFunc, animNew, commentsNew
def division_constantVariable(constant, variable, coeff): variable1 = Variable() variable1.coefficient = (evaluateConstant( constant) / variable.coefficient) * coeff variable1.value = [] variable1.power = [] for i, var in enumerate(variable): variable1.value.append(var) variable1.power.append(-variable.power[i]) return variable1
def factorizeTokens(tokens): coeffs, var = getPolyCoeffs(tokens) gcf, roots, polynomial = factor(coeffs) if roots != []: tokens = [] comment = "The real roots of the above polynomial are " for root in roots: comment += r"$" + str(root) + "\ ,\ " + r"$" if gcf != 1: tokens.append(Constant(float(gcf))) tokens.append(Multiply()) for root in roots: expression = Expression() expression.tokens.append(Variable(1, var, 1)) if root > 0: expression.tokens.append(Minus()) expression.tokens.append(Constant(float(root))) elif root < 0: expression.tokens.append(Plus()) expression.tokens.append(Constant(float(-root))) tokens.append(expression) tokens.append(Multiply()) if polynomial != [1]: expression = Expression() degree = len(polynomial) - 1 for i, coeff in enumerate(polynomial): if i == degree: if coeff > 0: expression.tokens.append(Plus()) expression.tokens.append(Constant(float(coeff))) elif coeff < 0: expression.tokens.append(Minus()) expression.tokens.append(Constant(float(-coeff))) elif coeff > 0: expression.tokens.append(Plus()) expression.tokens.append(Variable(coeff, var, degree - i)) elif coeff < 0: expression.tokens.append(Minus()) expression.tokens.append(Variable(-coeff, var, degree - i)) if isinstance(expression.tokens[0], Plus): expression.tokens.pop(0) tokens.append(expression) else: tokens.pop() else: comment = None animation = [tokens] comments = [comment] return tokens, animation, comments
def multiplyVariables(variable1, variable2, coeff): variable = Variable() variable.value = [] variable.value.extend(variable1.value) variable.power = [] variable.power.extend(variable1.power) if isNumber(variable1.coefficient): variable.coefficient = float(variable1.coefficient) elif isinstance(variable1.coefficient, Function): variable.coefficient = evaluateConstant(variable1.coefficient) else: variable.coefficient = variable1.coefficient for j, var in enumerate(variable.value): found = False for k, var2 in enumerate(variable2.value): if var == var2: if isNumber(variable.power[j]) and isNumber(variable2.power[k]): variable.power[j] += variable2.power[k] found = True break if not found: variable.value.append(variable2.value[j]) variable.power.append(variable2.power[j]) variable.coefficient *= variable2.coefficient variable.coefficient *= coeff # removeScopes.append(tokens[i].scope) # removeScopes.append(tokens[i+1].scope) return variable
def test_Variable(): variable1 = Variable(2, 'x', 3) assert variable1.__str__() == "2{x}^{3}" variable1.integrate('x') assert variable1.__str__() == "0.5{x}^{4}" # FIXME: Optimize integrate """
def multiplyVariableConstant(constant, variable, coeff): variable1 = Variable() variable1.value = [] variable1.value.extend(variable.value) variable1.power = [] variable1.power.extend(variable.power) if isNumber(variable.coefficient): variable1.coefficient = float(variable.coefficient) elif isinstance(variable.coefficient, Function): variable1.coefficient = evaluateConstant(variable.coefficient) else: variable.coefficient = variable1.coefficient variable1.coefficient *= evaluateConstant(constant) variable1.coefficient *= coeff # removeScopes.append(tokens[i].scope) # removeScopes.append(tokens[i-1].scope) return variable1
def expressionDivision(variables, tokens): removeScopes = [] comments = [] for i, token in enumerate(tokens): if isinstance(token, Binary): if token.value in ['/']: prev = False nxt = False if i != 0: if tokens[i - 1].__class__ in [Variable, Constant]: prev = True if i + 1 < len(tokens): if tokens[i + 1].__class__ in [Variable, Constant]: nxt = True if nxt and prev: if isinstance(tokens[i + 1], Constant) and isinstance(tokens[i - 1], Constant): comments.append("Dividing " + r"$" + tokens[i - 1].__str__() + r"$" + " by " + r"$" + tokens[i + 1].__str__() + r"$") no_1 = False no_2 = False if isNumber(tokens[i - 1].value): no_1 = True if isNumber(tokens[i + 1].value): no_2 = True if no_1 and no_2: tokens[i + 1].value = evaluateConstant( tokens[i - 1]) / evaluateConstant(tokens[i + 1]) tokens[i + 1].power = 1 removeScopes.append(tokens[i].scope) removeScopes.append(tokens[i - 1].scope) elif no_1 and not no_2: value = tokens[i - 1].value power = tokens[i - 1].power tokens[i - 1].value = [value] tokens[i - 1].power = [power] for val in tokens[i + 1].value: tokens[i - 1].value.append(val) for pows in tokens[i + 1].power: tokens[i - 1].power.append(-pows) removeScopes.append(tokens[i].scope) removeScopes.append(tokens[i + 1].scope) elif not no_1 and no_2: tokens[i - 1].value.append(tokens[i + 1].value) tokens[i - 1].power.append(-tokens[i + 1].power) removeScopes.append(tokens[i].scope) removeScopes.append(tokens[i + 1].scope) elif not no_1 and not no_2: for vals in tokens[i + 1].value: tokens[i - 1].value.append(vals) for pows in tokens[i + 1].power: tokens[i - 1].power.append(pows) removeScopes.append(tokens[i].scope) removeScopes.append(tokens[i + 1].scope) return variables, tokens, removeScopes, comments elif isinstance(tokens[i + 1], Variable) and isinstance(tokens[i - 1], Variable): comments.append("Dividing " + r"$" + tokens[i - 1].__str__() + r"$" + " by " + r"$" + tokens[i + 1].__str__() + r"$") for j, var in enumerate(tokens[i + 1].value): found = False for k, var2 in enumerate(tokens[i - 1].value): tokens[i-1].coefficient /= tokens[i+1].coefficient if var == var2: if isNumber(tokens[i + 1].power[j]) and isNumber(tokens[i - 1].power[k]): tokens[i - 1].power[k] -= tokens[i + 1].power[j] if tokens[i - 1].power[k] == 0: del tokens[i - 1].power[k] del tokens[i - 1].value[k] found = True break if not found: tokens[i - 1].value.append(tokens[i + 1].value[j]) tokens[i - 1].power.append(-tokens[i + 1].power[j]) if len(tokens[i - 1].value) == 0: constant = Constant() constant.scope = tokens[i - 1].scope constant.power = 1 constant.value = tokens[i - 1].coefficient tokens[i - 1] = constant removeScopes.append(tokens[i].scope) removeScopes.append(tokens[i + 1].scope) return variables, tokens, removeScopes, comments elif (isinstance(tokens[i + 1], Variable) and isinstance(tokens[i - 1], Constant)): comments.append("Dividing " + r"$" + tokens[i - 1].__str__() + r"$" + " by " + r"$" + tokens[i + 1].__str__() + r"$") val = evaluateConstant(tokens[i - 1]) scope = tokens[i - 1].scope tokens[i - 1] = Variable() tokens[i - 1].value = tokens[i + 1].value tokens[i - 1].coefficient = val / \ tokens[i + 1].coefficient tokens[i - 1].power = [] tokens[i - 1].scope = scope for pows in tokens[i + 1].power: tokens[i - 1].power.append(-pows) removeScopes.append(tokens[i].scope) removeScopes.append(tokens[i + 1].scope) return variables, tokens, removeScopes, comments elif (isinstance(tokens[i - 1], Variable) and isinstance(tokens[i + 1], Constant)): comments.append("Dividing " + r"$" + tokens[i - 1].__str__() + r"$" + " by " + r"$" + tokens[i + 1].__str__() + r"$") tokens[i - 1].coefficient /= evaluateConstant(tokens[i + 1]) removeScopes.append(tokens[i].scope) removeScopes.append(tokens[i + 1].scope) return variables, tokens, removeScopes, comments return variables, tokens, removeScopes, comments
def test_Variable(): variable1 = Variable(2, 'x', 3) assert variable1.__str__() == "2{x}^{3}" variable1, _ = variable1.integrate('x') assert variable1.__str__() == "0.5{x}^{4}" constant = Constant(3) variable = Variable(2, 'x', 3) add = variable + constant assert add.__str__() == "{(2{x}^{3}+{3})}" variable1 = Variable(2, 'x', 3) variable2 = Variable(4, 'x', 3) add1 = variable1 + variable2 assert add1.__str__() == "6{x}^{3}" variable1 = Variable(2, 'x', 3) constant = Constant(3) exp1 = Expression([variable1, Plus(), constant]) variable2 = Variable(4, 'x', 3) add2 = variable2 + exp1 assert add2.__str__() == "{(6{x}^{3}+{3})}" variable1 = Variable(2, 'x', 3) constant = Constant(3) exp1 = variable1 + constant variable2 = Variable(4, 'x', 3) add2 = variable2 - exp1 assert add2.__str__() == "{(2{x}^{3}-{3})}" variable1 = Variable(2, 'x', 3) constant = Constant(3) exp1 = Expression([variable1, Plus(), constant]) variable2 = Variable(4, 'x', 3) add2 = exp1 - variable2 assert add2.__str__() == "{(-2{x}^{3}+{3})}" constant = Constant(3) variable = Variable(2, 'x', 3) add = variable - constant assert add.__str__() == "{(2{x}^{3}-{3})}" variable1 = Variable(2, 'x', 3) variable2 = Variable(4, 'x', 3) variable3 = Variable(2, 'x', 4) variable4 = Variable(2, 'x', 3) add1 = variable1 - variable2 add2 = variable3 - variable4 assert add1.__str__() == "-2{x}^{3}" assert add2.__str__() == "{(2{x}^{4}-2{x}^{3})}" constant = Constant(3) variable = Variable(2, 'x', 3) add = variable * constant assert add.__str__() == "6{x}^{3}" variable1 = Variable(2, 'x', 3) variable2 = Variable(4, 'x', 3) add2 = variable1 * variable2 assert add2.__str__() == "8{x}^{6}" variable1 = Variable(2, 'x', 3) variable2 = Variable(4, 'y', 3) add2 = variable1 * variable2 assert add2.__str__() == "8{x}^{3}{y}^{3}" variable1 = Variable(2, 'x', 3) variable2 = Variable(4, 'y', 4) add1 = variable1 / variable2 assert add1.__str__() == "0.5{x}^{3}{y}^{-4}" variable1 = Variable(2, 'x', 3) constant = Constant(3) exp1 = variable1 - constant variable2 = Variable(4, 'x', 3) add2 = variable2 / exp1 assert add2.__str__() == "{(4.0{x}^{3}*{(2{x}^{3}-{3})}^{-1})}" variable1 = Variable(2, 'x', 3) constant = Constant(3) exp1 = variable1 - constant variable2 = Variable(4, 'x', 3) add2 = variable2 * exp1 assert add2.__str__() == "{(8{x}^{6}-12{x}^{3})}" variable1 = Variable(2, 'x', 3) constant1 = Constant(3) exp1 = variable1 - constant1 variable2 = Variable(4, 'x', 3) constant2 = Constant(4) exp2 = variable2 - constant2 add2 = exp1 * exp2 assert add2.__str__() == "{({(8{x}^{6}-8{x}^{3})}-{(12{x}^{3}-{12})})}" variable2 = Variable(3, 'x', -1) variable2, _ = variable2.integrate('x') assert tokensToString(variable2) == '3 * log(x)'
def test_Constant(): # Tests for Calculus operations for Constant Class. constant1 = Constant(10) assert constant1.__str__() == "{10}" constant1.differentiate() assert constant1.value == 0 constant2 = Constant(5, 2) constant2.integrate('x') assert isinstance(constant2, Variable) assert constant2.__str__() == "25{x}" # Tests for Add/Sub operations (using Overloading) for Constant Class. constant4 = Constant(2, 2) constant5 = Constant(7) constant3 = constant4 - constant5 assert constant3.__str__() == "{-3}" constant4 = Constant(7, 2) constant0 = Constant(5) constant6 = constant4 - constant3 - constant5 + constant0 assert constant6.__str__() == "{50}" constant0 = Constant(5, 2, 2) constant2 = constant0 variable0 = Variable(5, 'X', 3) summation0 = constant0 - variable0 + constant2 assert summation0.__str__() == "{({100}-5{X}^{3})}" constant0 = Constant(5, 2, 2) constant2 = constant0 variable0 = Variable(5, 'X', 3) summation0 = constant0 + variable0 + constant2 assert summation0.__str__() == "{({100}+5{X}^{3})}" var1 = Variable(3, 'x', 3) const1 = Constant(5) expr1 = Expression([var1, Minus(), const1]) constant2 = Constant(2, 2) sub1 = constant2 - expr1 assert sub1.__str__() == "{({9}-3{x}^{3})}" constant1 = Constant(2) constant2 = Constant(7) constant3 = constant1 + constant2 assert constant3.__str__() == "{9}" constant1 = Constant(2) constant2 = Constant(7) constant3 = constant1 - constant2 assert constant3.__str__() == "{-5}" constant1 = Constant(5) variable1 = Variable(5, 'x', 3) summation = constant1 + variable1 assert summation.__str__() == "{({5}+5{x}^{3})}" constant1 = Constant(5) variable1 = Variable(5, 'x', 3) summation = constant1 - variable1 assert summation.__str__() == "{({5}-5{x}^{3})}" # Tests for Add/Sub operations (using Overloading) for Constant Class. constant0 = Constant(0, 2) constant1 = Constant(5) mul1 = constant0 * constant1 assert mul1.calculate() == 0 mul1 = constant1 * constant0 assert mul1.calculate() == 0 mul1 = constant1 * constant1 + constant0 * constant1 + constant0 * constant1 assert mul1.calculate() == 25 constant1 = Constant(5, 2) constant2 = Constant(4, 2) variable0 = Variable(3, 'X', 3) mul3 = constant1 * (constant2 + variable0) assert mul3.__str__() == "{({400}+75{X}^{3})}" constant1 = Constant(5, 2) constant2 = Constant(4, 2) variable0 = Variable(3, 'X', 3) mul3 = constant1 / (constant2 + variable0) assert mul3.__str__() == "{25}*{({16}+3{X}^{3})}^{-1}" constant1 = Constant(5) constant2 = Constant(4) div1 = constant1 / constant2 assert div1.__str__() == "{1.25}" constant1 = Constant(3, 2) constant2 = Constant(4, 2) variable0 = Variable(3, 'X', 3) mul3 = constant1 - constant1 / (constant2 / variable0 + constant1) assert mul3.__str__( ) == "{({9}-{9}*{(5.333333333333333{X}^{-3}+{9})}^{-1})}" constant1 = Constant(2, 2) constant2 = Constant(2, 2) mul3 = constant1**constant2 assert mul3.__str__() == "{256}" constant1 = Constant(5) constant2 = Constant(5) summation = constant1 * constant2 assert summation.__str__() == "{25}" constant1 = Constant(5) variable1 = Variable(5, 'x', 3) exp1 = Expression([constant1, Plus(), variable1]) constant2 = Constant(10) summation = constant2 + exp1 assert summation.__str__() == "{({15}+5{x}^{3})}" constant1 = Constant(5) variable1 = Variable(5, 'x', 3) exp1 = Expression([constant1, Plus(), variable1]) constant2 = Constant(10) summation = constant2 - exp1 assert summation.__str__() == "{({5}-5{x}^{3})}" constant1 = Constant(5) variable1 = Variable(5, 'x', 3) exp1 = Expression([constant1, Plus(), variable1]) constant2 = Constant(10) summation = exp1 - constant2 assert summation.__str__() == "{({-5}+5{x}^{3})}" constant1 = Constant(5) variable1 = Variable(5, 'x', 3) summation = constant1 * variable1 assert summation.__str__() == "25{x}^{3}" constant1 = Constant(5) variable1 = Variable(5, 'x', 3) exp1 = Expression([constant1, Plus(), variable1]) constant2 = Constant(10) summation = constant2 * exp1 assert summation.__str__() == "{({50}+50{x}^{3})}" constant1 = Constant(5) constant2 = Constant(5) summation = constant1 / constant2 assert summation.__str__() == "{1.0}" constant1 = Constant(5) variable1 = Variable(5, 'x', 3) summation = constant1 / variable1 assert summation.__str__() == "{x}^{-3}" constant1 = Constant(5) variable1 = Variable(5, 'x', 3) exp1 = Expression([constant1, Plus(), variable1]) constant2 = Constant(10) summation = constant2 / exp1 assert summation.__str__() == "{10}*{({5}+5{x}^{3})}^{-1}" constant1 = Constant(5) variable1 = Variable(5, 'x', 3) exp1 = Expression([constant1, Plus(), variable1]) constant2 = Constant(10) summation = exp1 / constant2 assert summation.__str__() == "{({0.5}+0.5{x}^{3})}"
def getLevelVariables(tokens): """Returns tokens of Function class from a list of function tokens Arguments: tokens {list} -- list of function tokens Returns: variables {list} -- list of tokens of Function class(Variable/Constant) """ variables = [] for i, term in enumerate(tokens): if isinstance(term, Variable): skip = False for var in variables: if var.value == term.value and var.power[0] == term.power: var.power.append(term.power) var.scope.append(term.scope) var.coefficient.append(term.coefficient) if i != 0 and isinstance(tokens[i - 1], Binary): var.before.append(tokens[i - 1].value) var.beforeScope.append(tokens[i - 1].scope) else: var.before.append('') var.beforeScope.append('') if i + 1 < len(tokens) and isinstance(tokens[i + 1], Binary): var.after.append(tokens[i + 1].value) var.afterScope.append(tokens[i + 1].scope) else: var.after.append('') var.afterScope.append('') skip = True break if not skip: variable = Variable() variable.value = term.value variable.scope = [term.scope] variable.power = [] variable.coefficient = [] variable.before = [] variable.beforeScope = [] variable.after = [] variable.afterScope = [] variable.power.append(term.power) variable.coefficient.append(term.coefficient) if i != 0 and isinstance(tokens[i - 1], Binary): variable.before.append(tokens[i - 1].value) variable.beforeScope.append(tokens[i - 1].scope) else: variable.before.append('') variable.beforeScope.append('') if i + 1 < len(tokens) and isinstance(tokens[i + 1], Binary): variable.after.append(tokens[i + 1].value) variable.afterScope.append(tokens[i + 1].scope) else: variable.after.append('') variable.afterScope.append('') variables.append(variable) elif isinstance(term, Constant): skip = False for var in variables: if isinstance(var.value, list) and isNumber(var.value[0]): if var.power[0] == term.power: var.value.append(term.value) var.power.append(term.power) var.scope.append(term.scope) if i != 0 and isinstance(tokens[i - 1], Binary): var.before.append(tokens[i - 1].value) var.beforeScope.append(tokens[i - 1].scope) else: var.before.append('') var.beforeScope.append('') if i + 1 < len(tokens) and isinstance(tokens[i + 1], Binary): var.after.append(tokens[i + 1].value) var.afterScope.append(tokens[i + 1].scope) else: var.after.append('') var.afterScope.append('') skip = True break if not skip: variable = Constant() variable.power = [] if isinstance(term.value, list): variable.value = [evaluateConstant(term)] variable.power.append(1) else: variable.value = [term.value] variable.power.append(term.power) variable.scope = [term.scope] variable.before = [] variable.beforeScope = [] variable.after = [] variable.afterScope = [] if i != 0 and isinstance(tokens[i - 1], Binary): variable.before.append(tokens[i - 1].value) variable.beforeScope.append(tokens[i - 1].scope) else: variable.before.append('') variable.beforeScope.append('') if i + 1 < len(tokens) and isinstance(tokens[i + 1], Binary): variable.after.append(tokens[i + 1].value) variable.afterScope.append(tokens[i + 1].scope) else: variable.after.append('') variable.afterScope.append('') variables.append(variable) elif isinstance(term, Expression): var = getLevelVariables(term.tokens) retType, val = extractExpression(var) if retType == "expression": variable = Expression() variable.value = val variable.tokens = term.tokens variables.append(variable) elif retType == "constant": skip = False for var in variables: if isinstance(var.value, list) and isNumber(var.value[0]): if var.power == val.power: var.value.append(val.value) var.power.append(val.power) var.scope.append(val.scope) var.before.append(val.before) var.beforeScope.append(val.beforeScope) var.after.append(val.after) var.afterScope.append(val.afterScope) skip = True break if not skip: var = Constant() var.value = [val.value] var.power = [val.power] var.scope = [val.scope] var.before = [val.before] var.beforeScope = [val.beforeScope] var.after = [] var.afterScope = [''] variables.append(var) elif retType == "variable": skip = False for var in variables: if var.value == val.value: var.power.append(val.power) var.before.append('') var.beforeScope.append('') var.after.append('') var.afterScope.append('') var.coefficient.append(val.coefficient) var.scope.append(val.scope) skip = True break if not skip: var = Constant() var.coefficient = [val.coefficient] var.value = val.value var.power = [val.power] var.scope = [val.scope] var.before = [''] var.beforeScope = [''] var.after = [''] var.afterScope = [''] variables.append(var) elif retType == "mixed": for v in val: if isinstance(v, Variable): skip = False for var in variables: if var.value == v.value: var.power.extend(v.power) var.before.extend(v.before) var.beforeScope.extend(v.beforeScope) var.after.extend(v.after) var.afterScope.extend(v.afterScope) var.coefficient.extend(v.coefficient) var.scope.extend(v.scope) skip = True break if not skip: var = Constant() var.coefficient = [v.coefficient] var.value = v.value var.power = [v.power] var.scope = [v.scope] var.before = [v.before] var.beforeScope = [v.beforeScope] var.after = [v.after] var.afterScope = [v.afterScope] variables.append(var) elif isinstance(v, Constant): for var in variables: if isinstance(var.value, list) and isNumber(var.value[0]): if var.power == v.power: var.value.extend(v.value) var.power.extend(v.power) var.before.extend(v.before) var.beforeScope.extend( v.beforeScope) var.after.extend(v.after) var.afterScope.extend(v.afterScope) var.coefficient.extend(v.coefficient) var.scope.extend(v.scope) skip = True break if not skip: var = Constant() var.coefficient = [v.coefficient] var.value = [v.value] var.power = [v.power] var.scope = [v.scope] var.before = [v.before] var.beforeScope = [v.beforeScope] var.after = [v.after] var.afterScope = [v.afterScope] variables.append(var) elif isinstance(v, Expression): variables.append(v) return variables
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 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