By Pablo Rodríguez-Sánchez
A derivative takes a function
and a position
as an argument, and returns a number representing the slope of that function at that point.
Where:
represents a function
represents its derivativeIs true for any algebraic function!
""" Structure representing a Dual number """
struct Dual
x::Real
dx::Real
end
function +(self::Dual, other::Dual)::Dual
return Dual(self.x + other.x, self.dx + other.dx)
end
function *(self::Dual, other::Dual)::Dual
y = self.x * other.x
dy = self.dx * other.x + self.x * other.dx
return Dual(y, dy)
end
function /(self::Dual, other::Dual)::Dual
y = self.x / other.x
dy = (self.dx * other.x - self.x * other.dx) / (other.x)^(2)
return Dual(y, dy)
end
+(z::Dual) = z
-(z::Dual) = Dual(-z.x, -z.dx)
>(self::Dual, other::Dual) = self.x > other.x
==(self::Dual, other::Dual) = (self.x == other.x) && (self.dx == other.dx)
poly = x -> x^(3) + x^(2) + x
z = Dual(3, 1)
poly(z)
> Dual(39, 34)
""" Equivalent to previous example. Just uglier """
function poly(x)
aux = 0 # Initialize auxiliary variable
for n in 1:3
aux = aux + x
end
end
poly(z)
> Dual(39, 34)
'''Enables one-liners like:
operator(z::Dual) = _factory(<fun>, <derivative>)(z)
'''
function _factory(f::Function, df::Function)::Function
return z -> Dual(f(z.x), df(z.x) * z.dx)
end
sin(x::Dual) = _factory(sin, cos)(x)
sin(x::Dual) = _factory(sin, cos)(x)
cos(x::Dual) = _factory(cos, x -> -sin(x))(x)
sin(x::Dual) = _factory(sin, cos)(x)
cos(x::Dual) = _factory(cos, x -> -sin(x))(x)
tan(x::Dual) = sin(x) / cos(x)
csc(x::Dual) = 1 / sin(x)
sec(x::Dual) = 1 / cos(x)
cot(x::Dual) = 1 / tan(x)
Found typo: the code above requires coercing Real
into Dual
at quotient definition.
See code here.
I hid this in the slides for the sake of simplicity.
Kudos for Suvayu Ali for noticing.
fun = x -> x + tan(cos(x)^(2) + sin(x)^(2))
z = Dual(0, 1)
fun(z)
> Dual(1.557407724654902, 1.0)