Skip to content

Commit

Permalink
add missing elementwise derivative propagation methods (#30)
Browse files Browse the repository at this point in the history
* add missing elementwise derivative propagation methods

* always checkout DiffBase master in tests, in order to grab the most recent test functions

* fix typo

* fix Jacobian tests for functions with general output dimension
  • Loading branch information
jrevels authored Dec 8, 2016
1 parent 689e789 commit f200520
Show file tree
Hide file tree
Showing 3 changed files with 71 additions and 36 deletions.
2 changes: 1 addition & 1 deletion .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ notifications:
email: false
script:
- if [[ -a .git/shallow ]]; then git fetch --unshallow; fi
- julia -e 'Pkg.clone(pwd()); Pkg.build("ReverseDiff"); Pkg.test("ReverseDiff"; coverage=true)'
- julia -e 'Pkg.clone(pwd()); Pkg.build("ReverseDiff"); Pkg.checkout("DiffBase"); Pkg.test("ReverseDiff"; coverage=true)'
after_success:
# push coverage results to Coveralls
- julia -e 'cd(Pkg.dir("ReverseDiff")); Pkg.add("Coverage"); using Coverage; Coveralls.submit(Coveralls.process_folder())'
52 changes: 43 additions & 9 deletions src/derivatives/elementwise.jl
Original file line number Diff line number Diff line change
Expand Up @@ -613,8 +613,10 @@ function broadcast_duals_increment!(input::TrackedReal, output, duals, p::Int)
return nothing
end

# broadcast_deriv_increment! #
#----------------------------#
# broadcast_deriv_increment!/broadcast_deriv_decrement! #
#-------------------------------------------------------#

#######

function broadcast_deriv_increment!(input::TrackedArray, output)
max_input_index = max_leftover_index(input, output)
Expand All @@ -625,6 +627,17 @@ function broadcast_deriv_increment!(input::TrackedArray, output)
return nothing
end

function broadcast_deriv_increment!(input::AbstractArray, output)
max_input_index = max_leftover_index(input, output)
output_deriv = deriv(output)
for i in CartesianRange(size(output))
increment_deriv!(input[min(max_input_index, i)], output_deriv[i])
end
return nothing
end

#######

function broadcast_deriv_decrement!(input::TrackedArray, output)
max_input_index = max_leftover_index(input, output)
input_deriv, output_deriv = deriv(input), deriv(output)
Expand All @@ -634,6 +647,17 @@ function broadcast_deriv_decrement!(input::TrackedArray, output)
return nothing
end

function broadcast_deriv_decrement!(input::AbstractArray, output)
max_input_index = max_leftover_index(input, output)
output_deriv = deriv(output)
for i in CartesianRange(size(output))
decrement_deriv!(input[min(max_input_index, i)], output_deriv[i])
end
return nothing
end

#######

function broadcast_deriv_increment!(input::TrackedArray, output, partials::AbstractArray)
max_input_index = max_leftover_index(input, output)
max_partials_index = max_leftover_index(partials, output)
Expand All @@ -644,15 +668,18 @@ function broadcast_deriv_increment!(input::TrackedArray, output, partials::Abstr
return nothing
end

function broadcast_deriv_increment!(input::AbstractArray, output, partials::Real)
max_input_index = max_leftover_index(input, output)
function broadcast_deriv_increment!(input::AbstractArray, output, partials::AbstractArray)
max_input_index = max_leftover_index(input, output)
max_partials_index = max_leftover_index(partials, output)
output_deriv = deriv(output)
for i in CartesianRange(size(output))
increment_deriv!(input[min(max_input_index, i)], output_deriv[i] * partials)
increment_deriv!(input[min(max_input_index, i)], output_deriv[i] * partials[min(max_partials_index, i)])
end
return nothing
end

#######

function broadcast_deriv_increment!(input::TrackedArray, output, partials::Real)
max_input_index = max_leftover_index(input, output)
input_deriv, output_deriv = deriv(input), deriv(output)
Expand All @@ -662,16 +689,17 @@ function broadcast_deriv_increment!(input::TrackedArray, output, partials::Real)
return nothing
end

function broadcast_deriv_increment!(input::AbstractArray, output, partials::AbstractArray)
max_input_index = max_leftover_index(input, output)
max_partials_index = max_leftover_index(partials, output)
function broadcast_deriv_increment!(input::AbstractArray, output, partials::Real)
max_input_index = max_leftover_index(input, output)
output_deriv = deriv(output)
for i in CartesianRange(size(output))
increment_deriv!(input[min(max_input_index, i)], output_deriv[i] * partials[min(max_partials_index, i)])
increment_deriv!(input[min(max_input_index, i)], output_deriv[i] * partials)
end
return nothing
end

#######

function broadcast_deriv_increment!(input::TrackedReal, output::TrackedArray, partials::AbstractArray)
output_deriv = deriv(output)
for i in eachindex(output_deriv)
Expand All @@ -680,6 +708,8 @@ function broadcast_deriv_increment!(input::TrackedReal, output::TrackedArray, pa
return nothing
end

#######

function broadcast_deriv_increment!(input::TrackedReal, output::TrackedArray, partials::Real)
output_deriv = deriv(output)
for i in eachindex(output_deriv)
Expand All @@ -688,6 +718,8 @@ function broadcast_deriv_increment!(input::TrackedReal, output::TrackedArray, pa
return nothing
end

#######

function broadcast_deriv_increment!(input::TrackedReal, output::TrackedArray)
output_deriv = deriv(output)
for i in eachindex(output_deriv)
Expand All @@ -696,6 +728,8 @@ function broadcast_deriv_increment!(input::TrackedReal, output::TrackedArray)
return nothing
end

#######

function broadcast_deriv_decrement!(input::TrackedReal, output::TrackedArray)
output_deriv = deriv(output)
for i in eachindex(output_deriv)
Expand Down
53 changes: 27 additions & 26 deletions test/api/JacobianTests.jl
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,8 @@ tic()
############################################################################################

function test_unary_jacobian(f, x)
test = ForwardDiff.jacobian!(DiffBase.JacobianResult(x), f, x, ForwardDiff.JacobianConfig(x))
test_val = f(x)
test = ForwardDiff.jacobian!(DiffBase.JacobianResult(test_val, x), f, x, ForwardDiff.JacobianConfig(x))

# without JacobianConfig

Expand All @@ -20,7 +21,7 @@ function test_unary_jacobian(f, x)
ReverseDiff.jacobian!(out, f, x)
@test_approx_eq_eps out DiffBase.jacobian(test) EPS

result = DiffBase.JacobianResult(x)
result = DiffBase.JacobianResult(test_val, x)
ReverseDiff.jacobian!(result, f, x)
@test_approx_eq_eps DiffBase.value(result) DiffBase.value(test) EPS
@test_approx_eq_eps DiffBase.jacobian(result) DiffBase.jacobian(test) EPS
Expand All @@ -35,7 +36,7 @@ function test_unary_jacobian(f, x)
ReverseDiff.jacobian!(out, f, x, cfg)
@test_approx_eq_eps out DiffBase.jacobian(test) EPS

result = DiffBase.JacobianResult(x)
result = DiffBase.JacobianResult(test_val, x)
ReverseDiff.jacobian!(result, f, x, cfg)
@test_approx_eq_eps DiffBase.value(result) DiffBase.value(test) EPS
@test_approx_eq_eps DiffBase.jacobian(result) DiffBase.jacobian(test) EPS
Expand All @@ -50,7 +51,7 @@ function test_unary_jacobian(f, x)
ReverseDiff.jacobian!(out, tp, x)
@test_approx_eq_eps out DiffBase.jacobian(test) EPS

result = DiffBase.JacobianResult(x)
result = DiffBase.JacobianResult(test_val, x)
ReverseDiff.jacobian!(result, tp, x)
@test_approx_eq_eps DiffBase.value(result) DiffBase.value(test) EPS
@test_approx_eq_eps DiffBase.jacobian(result) DiffBase.jacobian(test) EPS
Expand All @@ -71,12 +72,12 @@ function test_unary_jacobian(f, x)
Jf!(out, x)
@test_approx_eq_eps out DiffBase.jacobian(test) EPS

result = DiffBase.JacobianResult(x)
result = DiffBase.JacobianResult(test_val, x)
ReverseDiff.jacobian!(result, ctp, x)
@test_approx_eq_eps DiffBase.value(result) DiffBase.value(test) EPS
@test_approx_eq_eps DiffBase.jacobian(result) DiffBase.jacobian(test) EPS

result = DiffBase.JacobianResult(x)
result = DiffBase.JacobianResult(test_val, x)
Jf!(result, x)
@test_approx_eq_eps DiffBase.value(result) DiffBase.value(test) EPS
@test_approx_eq_eps DiffBase.jacobian(result) DiffBase.jacobian(test) EPS
Expand Down Expand Up @@ -186,14 +187,14 @@ function test_binary_jacobian(f, a, b)
@test_approx_eq_eps Ja test_a EPS
@test_approx_eq_eps Jb test_b EPS

Ja = similar(a, length(a), length(b))
Jb = copy(Ja)
Ja = similar(a, length(test_val), length(a))
Jb = similar(b, length(test_val), length(b))
ReverseDiff.jacobian!((Ja, Jb), f, (a, b))
@test_approx_eq_eps Ja test_a EPS
@test_approx_eq_eps Jb test_b EPS

Ja = DiffBase.JacobianResult(a, b)
Jb = copy(Ja)
Ja = DiffBase.JacobianResult(test_val, a)
Jb = DiffBase.JacobianResult(test_val, b)
ReverseDiff.jacobian!((Ja, Jb), f, (a, b))
@test_approx_eq_eps DiffBase.value(Ja) test_val EPS
@test_approx_eq_eps DiffBase.value(Jb) test_val EPS
Expand All @@ -208,14 +209,14 @@ function test_binary_jacobian(f, a, b)
@test_approx_eq_eps Ja test_a EPS
@test_approx_eq_eps Jb test_b EPS

Ja = similar(a, length(a), length(b))
Jb = copy(Ja)
Ja = similar(a, length(test_val), length(a))
Jb = similar(b, length(test_val), length(b))
ReverseDiff.jacobian!((Ja, Jb), f, (a, b), cfg)
@test_approx_eq_eps Ja test_a EPS
@test_approx_eq_eps Jb test_b EPS

Ja = DiffBase.JacobianResult(a, b)
Jb = copy(Ja)
Ja = DiffBase.JacobianResult(test_val, a)
Jb = DiffBase.JacobianResult(test_val, b)
ReverseDiff.jacobian!((Ja, Jb), f, (a, b), cfg)
@test_approx_eq_eps DiffBase.value(Ja) test_val EPS
@test_approx_eq_eps DiffBase.value(Jb) test_val EPS
Expand All @@ -230,14 +231,14 @@ function test_binary_jacobian(f, a, b)
@test_approx_eq_eps Ja test_a EPS
@test_approx_eq_eps Jb test_b EPS

Ja = similar(a, length(a), length(b))
Jb = copy(Ja)
Ja = similar(a, length(test_val), length(a))
Jb = similar(b, length(test_val), length(b))
ReverseDiff.jacobian!((Ja, Jb), tp, (a, b))
@test_approx_eq_eps Ja test_a EPS
@test_approx_eq_eps Jb test_b EPS

Ja = DiffBase.JacobianResult(a, b)
Jb = copy(Ja)
Ja = DiffBase.JacobianResult(test_val, a)
Jb = DiffBase.JacobianResult(test_val, b)
ReverseDiff.jacobian!((Ja, Jb), tp, (a, b))
@test_approx_eq_eps DiffBase.value(Ja) test_val EPS
@test_approx_eq_eps DiffBase.value(Jb) test_val EPS
Expand All @@ -254,28 +255,28 @@ function test_binary_jacobian(f, a, b)
@test_approx_eq_eps Ja test_a EPS
@test_approx_eq_eps Jb test_b EPS

Ja = similar(a, length(a), length(b))
Jb = copy(Ja)
Ja = similar(a, length(test_val), length(a))
Jb = similar(b, length(test_val), length(b))
ReverseDiff.jacobian!((Ja, Jb), ctp, (a, b))
@test_approx_eq_eps Ja test_a EPS
@test_approx_eq_eps Jb test_b EPS

Ja = similar(a, length(a), length(b))
Jb = copy(Ja)
Ja = similar(a, length(test_val), length(a))
Jb = similar(b, length(test_val), length(b))
Jf!((Ja, Jb), (a, b))
@test_approx_eq_eps Ja test_a EPS
@test_approx_eq_eps Jb test_b EPS

Ja = DiffBase.JacobianResult(a, b)
Jb = copy(Ja)
Ja = DiffBase.JacobianResult(test_val, a)
Jb = DiffBase.JacobianResult(test_val, b)
ReverseDiff.jacobian!((Ja, Jb), ctp, (a, b))
@test_approx_eq_eps DiffBase.value(Ja) test_val EPS
@test_approx_eq_eps DiffBase.value(Jb) test_val EPS
@test_approx_eq_eps DiffBase.gradient(Ja) test_a EPS
@test_approx_eq_eps DiffBase.gradient(Jb) test_b EPS

Ja = DiffBase.JacobianResult(a, b)
Jb = copy(Ja)
Ja = DiffBase.JacobianResult(test_val, a)
Jb = DiffBase.JacobianResult(test_val, b)
Jf!((Ja, Jb), (a, b))
@test_approx_eq_eps DiffBase.value(Ja) test_val EPS
@test_approx_eq_eps DiffBase.value(Jb) test_val EPS
Expand Down

0 comments on commit f200520

Please sign in to comment.