I am newbie in the field of programming, but I have tried to make relatively "huge" project. My "app" would derivate a mathematical expression, after that simplify the output expression.
How could I improve the expression simplify
function to further simplify the output expression?
I know about simpy, I want to implement the simplifier myself using python.
from abc import ABC, abstractmethod
import numpy as np
import math
class derivateSymb(ABC):
@abstractmethod
def df(self, var): pass
@abstractmethod
def compute(self): pass
class Const(derivateSymb):
def __init__(self, value): self.value = value
def df(self, var): return Const(0)
def compute(self): return self.value
def __repr__(self): return str(self.value)
class Var(derivateSymb):
def __init__(self, name, value=None): self.name, self.value = name, value
def df(self, var): return Const(1) if self == var else Const(0)
def compute(self):
if self.value is None:
raise ValueError('unassigned variable')
return self.value
def __repr__(self): return f'{self.name}'
class Add(derivateSymb):
def __init__(self, x, y): self.x, self.y = x, y
def df(self, var): return Add(self.x.df(var), self.y.df(var))
def compute(self): return self.x.compute() + self.y.compute()
def __repr__(self): return f'({self.x} + {self.y})'
class Sub(derivateSymb):
def __init__(self, x, y): self.x, self.y = x, y
def df(self, var): return Sub(self.x.df(var), self.y.df(var))
def compute(self): return self.x.compute() - self.y.compute()
def __repr__(self): return f'({self.x} - {self.y})'
class Mult(derivateSymb):
def __init__(self, x, y): self.x, self.y = x, y
def df(self, var): return Add( Mult(self.x.df(var), self.y), Mult(self.x, self.y.df(var)) )
def compute(self): return self.x.compute() * self.y.compute()
def __repr__(self): return f'({self.x} * {self.y})'
class Div(derivateSymb):
def __init__(self, x, y): self.x, self.y = x, y
def df(self, var): return Div( Sub( Mult(self.x.df(var), self.y), Mult(self.x, self.y.df(var)) ), Mult(self.y, self.y) )
def compute(self): return self.x.compute() / self.y.compute()
def __repr__(self): return f'({self.x} / {self.y})'
class Pow(derivateSymb):
def __init__(self, base, power): self.base, self.power = base, power
def df(self, var): return Mult( Mult( Const(self.power), Pow(self.base, self.power-1) ), self.base.df(var) )
def compute(self): return math.pow(self.base.compute(), self.power)
def __repr__(self): return f'({self.base}^{self.power})'
class Sin(derivateSymb):
def __init__(self, x): self.x = x
def df(self, var): return Mult( Cos(self.x), self.x.df(var) )
def compute(self): return math.sin(self.x.compute())
def __repr__(self): return f'(sin{self.x})'
class Cos(derivateSymb):
def __init__(self, x): self.x = x
def df(self, var): return Mult( Const(-1), Mult( Cos(self.x), self.x.df(var) ) )
def compute(self): return math.cos(self.x.compute())
def __repr__(self): return f'(cos{self.x})'
class Nodes:
@staticmethod
def _to_symbolic(x):
if not isinstance(x, derivateSymb): return Const(x)
else: return x
def __add__(self, other): return ErgonomicAdd(self, self._to_symbolic(other))
def __sub__(self, other): return ErgonomicSub(self, self._to_symbolic(other))
def __mul__(self, other): return ErgonomicMul(self, self._to_symbolic(other))
def __truediv__(self, other): return ErgonomicDiv(self, self._to_symbolic(other))
def __neg__(self): return ErgonomicMul(Const(-1), self)
class ErgonomicVar(Var, Nodes): pass
class ErgonomicAdd(Add, Nodes): pass
class ErgonomicSub(Sub, Nodes): pass
class ErgonomicMul(Mult, Nodes): pass
class ErgonomicDiv(Div, Nodes): pass
def simplify(node):
if isinstance(node, Add): return simplifyAdd(node)
elif isinstance(node, Sub): return simplifySub(node)
elif isinstance(node, Mult): return simplifyMult(node)
else: return node
def simplifyAdd(node):
x, y = simplify(node.x), simplify(node.y)
x_const, y_const = isinstance(x, Const), isinstance(y, Const)
if x_const and y_const: return Const(x.value + y.value)
elif x_const and x.value == 0: return y
elif y_const and y.value == 0: return x
else: return Add(x, y)
def simplifySub(node):
x, y = simplify(node.x), simplify(node.y)
x_const, y_const = isinstance(x, Const), isinstance(y, Const)
if x_const and y_const: return Const(x.value - y.value)
elif x_const and x.value == 0: return y
elif y_const and y.value == 0: return x
else: return Sub(x, y)
def simplifyMult(node):
x, y = simplify(node.x), simplify(node.y)
x_const, y_const = isinstance(x, Const), isinstance(y, Const)
if x_const and y_const: return Const(x.value * y.value)
elif x_const and x.value == 0: return Const(0)
elif x_const and x.value == 1: return y
elif y_const and y.value == 0: return Const(0)
elif y_const and y.value == 1: return x
else: return Mult(x, y)
x = ErgonomicVar('x', 3)
y = ErgonomicVar('y', 3)
z = Pow(x*3+y*y*y, 3)
#z = Sin(x*3+y*y)
print(z)
print(z.compute())
print(simplify(z.df(x)))
print(z.df(x).compute())
ABC
supposed to be? And do you have anyimport
statements that are not included in this code sample? \$\endgroup\$