In [1]:
expr = :(x + 1)
Out[1]:
In [2]:
typeof(expr)
Out[2]:
In [3]:
expr |> dump
In [4]:
@doc Expr
Out[4]:
In [5]:
expr2 = Expr(:call, :+, 1, 1)
Out[5]:
In [6]:
expr2 |> eval
Out[6]:
In [7]:
# Constant
differentiate(x::Number, target::Symbol) = 0
Out[7]:
In [8]:
differentiate(5, :x)
Out[8]:
In [9]:
# Just one symbol
function differentiate(s::Symbol, target::Symbol)
if s == target
return 1
else
return 0
end
end
Out[9]:
In [10]:
differentiate(:x, :x)
Out[10]:
In [11]:
differentiate(:y, :x)
Out[11]:
In [12]:
# Sum
function differentiate_sum(ex::Expr, target::Symbol)
#@printf "diff[+]: %s\n" ex
n = length(ex.args)
new_args = Array(Any, n)
new_args[1] = :+
for i in 2:n
# @printf "diff: %s\n" ex.args[i]
new_args[i] = differentiate(ex.args[i], target)
end
return Expr(:call, new_args...)
end
Out[12]:
In [13]:
differentiate_sum(:(x + y), :x)
Out[13]:
In [14]:
function differentiate_subtraction(ex::Expr, target::Symbol)
#@printf "diff[-]: %s\n" ex
n = length(ex.args)
new_args = Array(Any, n)
new_args[1] = :-
for i in 2:n
new_args[i] = differentiate(ex.args[i], target)
end
return Expr(:call, new_args...)
end
Out[14]:
In [15]:
differentiate_subtraction(:(x - y), :x)
Out[15]:
In [16]:
function differentiate_product(ex::Expr, target::Symbol)
#@printf "diff[*]: %s\n" ex
n = length(ex.args)
res_args = Array(Any, n)
res_args[1] = :+
for i in 2:n
new_args = Array(Any, n)
new_args[1] = :*
for j in 2:n
if j == i
new_args[j] = differentiate(ex.args[j], target)
else
new_args[j] = ex.args[j]
end
end
# @printf "*: %s" new_args
res_args[i] = Expr(:call, new_args...)
end
return Expr(:call, res_args...)
end
Out[16]:
In [17]:
differentiate_product(:(x * x), :x)
Out[17]:
In [18]:
function differentiate_quotient(ex::Expr, target::Symbol)
#@printf "diff[/]: %s\n" ex
return Expr(:call,
:/,
Expr(:call,
:-,
Expr(:call,
:*,
differentiate(ex.args[2], target),
ex.args[3]
),
Expr(:call,
:*,
ex.args[2],
differentiate(ex.args[3], target)
)
),
Expr(:call,
:^,
ex.args[3],
2
)
)
end
Out[18]:
In [19]:
differentiate_quotient(:(x / y), :y)
Out[19]:
In [20]:
differentiate_lookup = Dict(
:+ => differentiate_sum,
:- => differentiate_subtraction,
:* => differentiate_product,
:/ => differentiate_quotient
)
Out[20]:
In [21]:
function differentiate(ex::Expr, target::Symbol)
# @printf "differentiate(%s):\n" ex
# dump(ex)
if ex.head == :call
if haskey(differentiate_lookup, ex.args[1])
f = differentiate_lookup[ex.args[1]]
@printf "%s(%s, %s)\n" f ex target
ret = f(ex, target)
@printf "=> %s\n" ret
return ret
else
error("Don't know how to differentiate $(ex.args[1])")
end
else
error("ex.head != :call")
# return differentiate(ex.head)
end
end
Out[21]:
In [22]:
differentiate(:(x * x), :x)
Out[22]:
In [23]:
differentiate(:((x + x) * x), :x)
Out[23]:
In [24]:
differentiate(:(1 + x + x * x), :x)
Out[24]:
In [25]:
differentiate(:(1 + z + x * z + x * z * z), :z)
Out[25]:
In [26]:
differentiate(:(1 + x + 1 / x + x * x), :x)
Out[26]:
In [27]:
# Pkg.add("Calculus")
In [28]:
# import Calculus
In [29]:
repeat("_", 5)
Out[29]:
In [36]:
ex = Expr(:call)
Out[36]:
In [37]:
ex.args = [:+, 1, 1]
Out[37]:
In [38]:
ex.typ = Any
Out[38]:
In [39]:
ex |> dump
In [51]:
arr1 = [:+, differentiate(:(x + x), :x)]
arr2 = [:+, differentiate(:(x - x), :x)]
arr3 = [:+, differentiate(:(x * x), :x)]
arr4 = [:+, differentiate(:(x / x), :x)]
ex5 = Expr(:call, arr1..., Expr(:call, arr2..., Expr(:call, arr3..., Expr(:call, arr4..., 5))))
Out[51]:
In [52]:
differentiate(ex5, :x)
In [ ]: