import math
import numpy as np
class Exp:
def eval(self, ** env):
pass
def deriv(self, x):
pass
def __add__(self, other):
other = to_exp(other)
return Add(self, other)
def __radd__(self, other):
other = to_exp(other)
return Add(other, self)
def __sub__(self, other):
other = to_exp(other)
return Sub(self, other)
def __rsub__(self, other):
other = to_exp(other)
return Sub(other, self)
def __mul__(self, other):
other = to_exp(other)
if isinstance(other, Const) and other.value == 0:
return 0
return Mul(self, other)
def __rmul__(self, other):
other = to_exp(other)
if isinstance(other, Const) and other.value == 0:
return 0
return Mul(other, self)
def __truediv__(self, other):
other = to_exp(other)
return Truediv(self, other)
def __rtruediv__(self, other):
other = to_exp(other)
if isinstance(other, Const) and other.value == 0:
return 0
return Truediv(other, self)
def __pow__(self, power, modulo=None):
return Pow(self, to_exp(power))
def __rpow__(self, other):
return Pow(to_exp(other), self)
def __abs__(self):
return Abs(self)
def to_exp(value):
if isinstance(value, Exp):
return value
if type(value) == str:
return Variable(value)
if type(value) in (int, float):
return Const(value)
raise Exception('Can not convert %s to an Expression' % value)
class Abs(Exp):
def __init__(self, value):
self.value = value
def __repr__(self):
return '|%s|' % self.value
def eval(self, **env):
self.result = abs(self.value.eval(**env))
return self.result
def deriv(self, x):
return (1 if self.result > 0 else -1) * self.value.deriv(x)
def log(exp):
exp = to_exp(exp)
return Log(exp, e)
class Pow(Exp):
def __init__(self, left, right):
self.left = left
self.right = right
def eval(self, **env):
return self.left.eval(**env) ** self.right.eval(**env)
def deriv(self, x):
if isinstance(self.right, Const):
return self.right * self.left**(self.right-1) * self.left.deriv(x)
if isinstance(self.left, Const):
return self.right.deriv(x) * log(self.left) * self
result = self.right.deriv(x) * log(self.left) + self.right * self.left.deriv(x) / self.left
return result * self
def __repr__(self):
return '%s ** %s' % (self.left, self.right)
class Truediv(Exp):
def __init__(self, left, right):
self.left = left
self.right = right
def eval(self, **env):
div = self.left.eval(**env)
if div == 0:
return 0
der = self.right.eval(**env)
return div / der
def deriv(self, x):
return (self.left.deriv(x) * self.right - self.left * self.right.deriv(x)) / self.right ** 2
def __repr__(self):
return '(%s / %s)' % (self.left, self.right)
class Mul(Exp):
def __init__(self, left, right):
self.left = left
self.right = right
def eval(self, **env):
return self.left.eval(**env) * self.right.eval(**env)
def deriv(self, x):
return self.left.deriv(x) * self.right + self.left * self.right.deriv(x)
def __repr__(self):
return '(%s * %s)' % (self.left, self.right)
class Sub(Exp):
def __init__(self, left, right):
self.left = left
self.right = right
def eval(self, **env):
return self.left.eval(**env) - self.right.eval(**env)
def deriv(self, x):
return self.left.deriv(x) - self.right.deriv(x)
def __repr__(self):
return '(%s - %s)' % (self.left, self.right)
class Add(Exp):
def __init__(self, left, right):
self.left = left
self.right = right
def eval(self, **env):
return self.left.eval(**env) + self.right.eval(**env)
def deriv(self, x):
return self.left.deriv(x) + self.right.deriv(x)
def __repr__(self):
return '(%s + %s)' % (self.left, self.right)
class Const(Exp):
def __init__(self, value):
self.value = value
def eval(self, **env):
return self.value
def deriv(self, x):
return 0
def __repr__(self):
return str(self.value)
e = Const(math.e)
pi = Const(math.pi)
class Log(Exp):
def __init__(self, value, base=e):
self.value = value
self.base = base
def eval(self, **env):
return math.log(self.value.eval(**env), self.base.eval(**env))
def deriv(self, x):
if isinstance(self.base, Const):
return self.value.deriv(x) / self.value / log(self.base)
if isinstance(self.value, Const):
return - log(self.value) * self.base.deriv(x) / (self.base * log(self.base)**2)
result = self.value.deriv(x) / self.value * log(self.base)
result -= self.base.deriv(x) / self.base * log(self.value)
return result / (log(self.base) ** 2)
def __repr__(self):
return 'log(%s, %s)' % (self.value, self.base)
class Variable(Exp):
def __init__(self, name):
self.name = name
def eval(self, **env):
if self.name in env:
return env[self.name]
raise Exception('Variable %s not found' % self.name)
def deriv(self, x):
if isinstance(x, Variable):
x = x.name
return 1 if self.name == x else 0
def __repr__(self):
return self.name
def _test_deriv(y, x):
dy_dx = y.deriv('x')
print('-' * 200)
print(y)
print(dy_dx)
print(dy_dx.eval(x=x))
if __name__ == '__main__':
x = Variable('x')
print(x.eval(x=3.14))
y = x + 3
dy_dx = y.deriv(x)
print(y)
print(dy_dx)
print('-' * 200)
y = 4 * x + 3
dy_dx = y.deriv(x)
print(y)
print(dy_dx)
print('-' * 200)
y = 4 * x * x + 3 * x + 5
dy_dx = y.deriv(x)
print(y)
print(dy_dx)
print(dy_dx.eval(x=1))
print('-' * 200)
y = 1 / x
dy_dx = y.deriv(x)
print(y)
print(dy_dx)
print(dy_dx.eval(x=0.5))
_test_deriv(e ** (2*x), 0.5)
y = abs(x**3)
y.eval(x=0.5)
_test_deriv(y, 0.5)
D:\Anaconda\python.exe D:/AI20/06_codes/deeplearning_20/p15_deriv.py
3.14
(x + 3)
1
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
((4 * x) + 3)
((0 + (4 * 1)) + 0)
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
((((4 * x) * x) + (3 * x)) + 5)
(((((0 + (4 * 1)) * x) + ((4 * x) * 1)) + (0 + (3 * 1))) + 0)
11
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
(1 / x)
((0 - (1 * 1)) / x ** 2)
-4.0
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
2.718281828459045 ** (2 * x)
(((0 + (2 * 1)) * log(2.718281828459045, 2.718281828459045)) * 2.718281828459045 ** (2 * x))
5.43656365691809
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|x ** 3|
(1 * ((3 * x ** (3 - 1)) * 1))
0.75
Process finished with exit code 0