Skip to content

Instantly share code, notes, and snippets.

@Joseph-Bake
Created July 15, 2018 13:24
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Joseph-Bake/ab0059c563018113ae8aaed5c9efab08 to your computer and use it in GitHub Desktop.
Save Joseph-Bake/ab0059c563018113ae8aaed5c9efab08 to your computer and use it in GitHub Desktop.
二重数の自動微分
import math
from numbers import Number
class Dual:
def __init__(self,z):
(self.x,self.y) = z
def __str__(self):
if self.y >= 0 :
return "{} + {}ε".format(self.x,self.y)
elif self.y < 0 :
return "{} - {}ε".format(self.x,math.abs(self.y))
def re(self):
x = self.x
return x
def du(self):
y = self.y
return y
def __add__(self,other):
if isinstance(other,Number):
other = Dual.r2d(other)
x = self.x + other.x
y = self.y + other.y
return Dual((x,y))
def __radd__(self,other):
other = Dual.r2d(other)
x = self.x + other.x
y = self.y + other.y
return Dual((x,y))
def __sub__(self,other):
if isinstance(other,Number):
other = Dual.r2d(other)
x = self.x - other.x
y = self.y - other.y
return Dual((x,y))
def __rsub__(self,other):
other = Dual.r2d(other)
x = self.x - other.x
y = self.y - other.y
return Dual((x,y))
def __mul__(self,other):
if isinstance(other,Number):
other = Dual.r2d(other)
x = self.x * other.x
y = self.x * other.y + self.y * other.x
return Dual((x,y))
def __rmul__(self,other):
other = Dual.r2d(other)
x = self.x * other.x
y = self.x * other.y + self.y * other.x
return Dual((x,y))
def __truediv__(self,other):
if isinstance(other,Number):
other = Dual.r2d(other)
try:
x = self.x/other.x
y = (self.y*other.x - self.x*other.y)/(other.x*other.x)
except ZeroDivisionError:
return Dual((math.nan,math.nan))
except TypeError:
print("type error")
else:
return Dual((x,y))
finally:
pass
def __rtruediv__(self,other):
other = Dual.r2d(other)
try:
x = other.x/self.x
y = (self.x*other.y - self.y*other.x)/(self.x*self.x)
except ZeroDivisionError:
return Dual((math.nan,math.nan))
except TypeError:
print("type error")
else:
return Dual((x,y))
finally:
pass
def __pow__(self,n):
x = self.x**n
y = n*self.x**(n-1)*self.y
return Dual((x,y))
def sin(self):
x = math.sin(self.x)
y = math.cos(self.x)*self.y
return Dual((x,y))
def cos(self):
x = math.cos(self.x)
y = -math.sin(self.x)*self.y
return Dual((x,y))
def tan(self):
return Dual.sin(self)/Dual.cos(self)
def exp(self):
x = math.exp(self.x)
y = math.exp(self.x)*self.y
return Dual((x,y))
def log(self):
x = math.log(self.x)
y = self.y/self.x
return Dual((x,y))
def sinh(self):
x = (math.exp(self.x) - math.exp(-self.x))*0.5
y = (math.exp(self.x)*self.y + math.exp(-self.x)*self.y)*0.5
return Dual((x,y))
def cosh(self):
x = (math.exp(self.x) + math.exp(-self.x))*0.5
y = (math.exp(self.x)*self.y - math.exp(-self.x)*self.y)*0.5
return Dual((x,y))
def tanh(self):
return Dual.sinh(self)/Dual.cosh(self)
def r2d(self):
return Dual((self,0.))
def r2d1(self):
return Dual((self,1.))
from dual import Dual
x = 1
xx = Dual.r2d1(x)
fy = xx**(0.5)
y = Dual.re(fy)
dy = Dual.du(fy)
print(y,dy)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment