-
Notifications
You must be signed in to change notification settings - Fork 6
Expand file tree
/
Copy pathsymbdiff.py
More file actions
101 lines (89 loc) · 2.78 KB
/
symbdiff.py
File metadata and controls
101 lines (89 loc) · 2.78 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
"""
A basic demo of symbolic differentiation.
Just one variable, for simplicity.
"""
class Formula(object):
def __neg__(self): return Constant(-1) * self
def __add__(self, other): return add(self, promote(other))
def __sub__(self, other): return add(self, -promote(other))
def __mul__(self, other): return mul(self, promote(other))
def __div__(self, other): return div_(self, promote(other))
def __radd__(self, other): return Constant(other) + self
def __rsub__(self, other): return Constant(other) - self
def __rmul__(self, other): return Constant(other) * self
def __rdiv__(self, other): return Constant(other) / self
class Constant(Formula):
def __init__(self, value):
self.value = value
def __repr__(self):
return repr(self.value)
def eval(self, x):
return self.value
def d_dx(self):
return Constant(0)
class Variable(Formula):
"Just the one variable, x."
def __repr__(self):
return 'x'
def eval(self, x):
return x
def d_dx(self):
return Constant(1)
def add(e1, e2):
if isinstance(e1, Constant) and isinstance(e2, Constant):
return Constant(e1.value + e2.value)
else:
return Add(e1, e2)
def mul(e1, e2):
if isinstance(e1, Constant) and isinstance(e2, Constant):
return Constant(e1.value * e2.value)
elif isinstance(e2, Constant):
return mul(e2, e1)
elif isinstance(e1, Constant) and e1.value == 1:
return e2
else:
return Mul(e1, e2)
def div_(e1, e2):
return Div(e1, e2) # Yeah, I'm getting tired of this.
class Add(Formula):
def __init__(self, e1, e2):
self.e1 = e1
self.e2 = e2
def __repr__(self):
return '(%r + %r)' % (self.e1, self.e2)
def eval(self, x):
return self.e1.eval(x) + self.e2.eval(x)
def d_dx(self):
return self.e1.d_dx() + self.e2.d_dx()
class Mul(Formula):
def __init__(self, e1, e2):
self.e1 = e1
self.e2 = e2
def __repr__(self):
return '(%r * %r)' % (self.e1, self.e2)
def eval(self, x):
return self.e1.eval(x) * self.e2.eval(x)
def d_dx(self):
return self.e1.d_dx() * self.e2 + self.e1 * self.e2.d_dx()
class Div(Formula):
def __init__(self, e1, e2):
self.e1 = e1
self.e2 = e2
def __repr__(self):
return '(%r / %r)' % (self.e1, self.e2)
def eval(self, x):
return self.e1.eval(x) / self.e2.eval(x)
def d_dx(self):
return (self.e1.d_dx() * self.e2 - self.e1 * self.e2.d_dx()) / (self.e2 * self.e2)
def promote(value):
return value if isinstance(value, Formula) else Constant(value)
x = Variable()
x3 = x * x * x
## x3
#. ((x * x) * x)
## x3.eval(2)
#. 8
## x3.d_dx()
#. (((x + x) * x) + (x * x))
## x3.d_dx().eval(2)
#. 12