Skip to content

Commit

Permalink
CLEANUP: Remove bit-rotted automatic differentiation code.
Browse files Browse the repository at this point in the history
Closes #19. I may revisit this later if I need this functionality.
  • Loading branch information
epatters committed Nov 7, 2018
1 parent 18f3449 commit aa3a189
Show file tree
Hide file tree
Showing 2 changed files with 6 additions and 69 deletions.
46 changes: 2 additions & 44 deletions src/algebra/Network.jl
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,6 @@ import ...Diagram.TikZWiring: box, wires, rect, junction_circle
import ...Meta: concat_expr
import ...Syntax: show_latex, show_unicode

@optional_import using ReverseDiffSource

# Syntax
########

Expand Down Expand Up @@ -88,8 +86,8 @@ optimizations. Still, the code should be fast provided the original expression
is properly factored (there are no duplicated computations).
"""
function compile(f::Union{AlgebraicNet.Hom,Block};
return_constants::Bool=false, vector::Bool=false, kw...)
expr, consts = vector ? compile_expr_vector(f; kw...) : compile_expr(f; kw...)
return_constants::Bool=false, kw...)
expr, consts = compile_expr(f; kw...)
compiled = eval(expr)
return_constants ? (compiled, consts) : compiled
end
Expand Down Expand Up @@ -126,46 +124,6 @@ function compile_expr(block::Block; name::Symbol=Symbol())
(Expr(:function, call_expr, body_expr), block.constants)
end

""" Compile an algebraic network into a Julia function expression.
The function signature is:
- first argument = input vector
- second argument = constant (coefficients) vector
Unlike `compile_expr`, this method assumes the network has a single output, and
supports gradients, Hessians, and higher order derivatives (with respect to the
coefficients) via reverse-mode automatic differentiation.
"""
function compile_expr_vector(f::AlgebraicNet.Hom; name::Symbol=Symbol(),
inputs::Symbol=:x, constants::Symbol=:c, kw...)
block = compile_block(f; inputs=inputs, constants=constants)
compile_expr_vector(block; name=name, inputs=inputs, constants=constants, kw...)
end
function compile_expr_vector(block::Block; name::Symbol=Symbol(),
inputs::Symbol=:x, constants::Symbol=:c,
order::Int=0, allorders::Bool=true)
# Create call expression (function header).
call_expr = if name == Symbol() # Anonymous function
Expr(:tuple, inputs, constants)
else # Named function
Expr(:call, name, inputs, constants)
end

# Create function body.
@assert length(block.outputs) == 1
return_expr = Expr(:return, block.outputs[1])
body_expr = concat_expr(block.code, return_expr)

# Automatic differentiation with respect to coefficients.
if order > 0
vars = Dict(inputs => Vector{Float64}, constants => Vector{Float64})
body_expr = rdiff(body_expr; order=order, allorders=allorders,
ignore=[inputs], vars...)
end

(Expr(:function, call_expr, body_expr), block.constants)
end

""" Compile an algebraic network into a block of Julia code.
"""
function compile_block(f::AlgebraicNet.Hom;
Expand Down
29 changes: 4 additions & 25 deletions test/algebra/Network.jl
Original file line number Diff line number Diff line change
Expand Up @@ -137,39 +137,18 @@ f = linear(:c, R, R)
f_comp = compile(f)
@test f_comp(x,c=1) == x
@test f_comp(x,c=2) == 2x
f_comp, f_const = compile(f, return_constants=true, vector=true)
f_comp, f_const = compile(f, return_constants=true)
@test f_const == [:c]
@test f_comp([x],[2]) == 2x
@test f_comp(x,c=2) == 2x

f = compose(linear(:k,R,R), Hom(:sin,R,R), linear(:A,R,R))
f_comp = compile(f)
f_comp, f_const = compile(f, return_constants=true)
@test f_const == [:k,:A]
@test f_comp(x,k=1,A=2) == @. 2 * sin(x)
@test f_comp(x,k=2,A=1) == @. sin(2x)
f_comp, f_const = compile(f, return_constants=true, vector=true)
@test f_const == [:k,:A]
@test f_comp([x],[1,2]) == @. 2 * sin(x)
@test f_comp([x],[2,1]) == @. sin(2x)

f = compose(otimes(id(R),constant(:c,R)), mmerge(R))
f_comp = compile(f,name=:myfun3)
@test f_comp(x,c=2) @. x+2

# Automatic differentiation of symbolic coefficients
if haskey(Pkg.installed(), "ReverseDiffSource")
x0 = 2.0 # Vectorized evaluation not allowed.
f = compose(linear(:a,R,R), Hom(:sin,R,R))
f_comp = compile(f, vector=true, order=1)
@test f_comp([x0],[1]) == (sin(x0), [x0 * cos(x0)])
f_grad = compile(f, vector=true, order=1, allorders=false)
f_hess = compile(f, vector=true, order=2, allorders=false)
@test f_grad([x0],[1]) == [x0 * cos(x0)]
@test f_hess([x0],[1]) == reshape([-x0^2 * sin(x0)],(1,1))

f = compose(linear(:k,R,R), Hom(:sin,R,R), linear(:A,R,R))
f_grad = compile(f, vector=true, order=1, allorders=false)
f_hess = compile(f, vector=true, order=2, allorders=false)
@test f_grad([x0],[1,1]) == [x0 * cos(x0), sin(x0)]
@test f_hess([x0],[1,1]) == [-x0^2 * sin(x0) x0*cos(x0); x0*cos(x0) 0]
end

end

0 comments on commit aa3a189

Please sign in to comment.