Skip to content

Commit

Permalink
Increase code coverage (#264)
Browse files Browse the repository at this point in the history
* Increase code coverage

* Fix

* Move detector tests
  • Loading branch information
gdalle authored May 16, 2024
1 parent d5420a1 commit fe4ba4c
Show file tree
Hide file tree
Showing 19 changed files with 147 additions and 139 deletions.
2 changes: 1 addition & 1 deletion DifferentiationInterface/Project.toml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
name = "DifferentiationInterface"
uuid = "a0c0ee7d-e4b9-4e03-894e-1c5f64a51d63"
authors = ["Guillaume Dalle", "Adrian Hill"]
version = "0.4.0"
version = "0.4.1"

[deps]
ADTypes = "47edcb42-4c32-4615-8424-f2b9edc5f35b"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,26 +42,13 @@ function DI.derivative(
return finite_difference_derivative(f, x, fdtype(backend))
end

function DI.derivative!(
f, der, backend::AutoFiniteDiff, x, extras::FiniteDiffOneArgDerivativeExtras{Nothing}
)
return copyto!(der, DI.derivative(f, backend, x, extras))
end

function DI.value_and_derivative(
f, backend::AutoFiniteDiff, x, ::FiniteDiffOneArgDerivativeExtras{Nothing}
)
y = f(x)
return y, finite_difference_derivative(f, x, fdtype(backend), eltype(y), y)
end

function DI.value_and_derivative!(
f, der, backend::AutoFiniteDiff, x, extras::FiniteDiffOneArgDerivativeExtras{Nothing}
)
y, new_der = DI.value_and_derivative(f, backend, x, extras)
return y, copyto!(der, new_der)
end

### Scalar to array

function DI.derivative(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ end

## Pullback

DI.prepare_pullback(f, ::AutoFiniteDifferences, x) = NoPullbackExtras()
DI.prepare_pullback(f, ::AutoFiniteDifferences, x, dy) = NoPullbackExtras()

function DI.pullback(f, backend::AutoFiniteDifferences, x, dy, ::NoPullbackExtras)
return only(j′vp(backend.fdm, f, dy, x))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,10 @@ choose_chunk(::AutoForwardDiff{C}, x) where {C} = Chunk{C}()
tag_type(f, ::AutoForwardDiff{C,T}, x) where {C,T} = T
tag_type(f, ::AutoForwardDiff{C,Nothing}, x) where {C} = Tag{typeof(f),eltype(x)}

make_dual(::Type{T}, x::Number, dx) where {T} = Dual{T}(x, dx)
make_dual(::Type{T}, x, dx) where {T} = Dual{T}.(x, dx) # TODO: map causes Enzyme to fail

make_dual_similar(::Type{T}, x::Number) where {T} = Dual{T}(x, x)
make_dual_similar(::Type{T}, x) where {T} = similar(x, Dual{T,eltype(x),1})

make_dual(::Type{T}, x::Number, dx) where {T} = Dual{T}(x, dx)
make_dual!(::Type{T}, xdual, x, dx) where {T} = map!(Dual{T}, xdual, x, dx)

myvalue(::Type{T}, ydual::Number) where {T} = value(T, ydual)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -109,11 +109,7 @@ function DI.prepare_gradient(f, ::AutoSymbolics, x)
grad_var = gradient(f(x_var), vec(x_var))

res = build_function(grad_var, vec(x_var); expression=Val(false))
(grad_exe, grad_exe!) = if res isa Tuple
res
elseif res isa RuntimeGeneratedFunction
res, nothing
end
(grad_exe, grad_exe!) = res
return SymbolicsOneArgGradientExtras(grad_exe, grad_exe!)
end

Expand Down Expand Up @@ -156,11 +152,7 @@ function DI.prepare_jacobian(
end

res = build_function(jac_var, x_var; expression=Val(false))
(jac_exe, jac_exe!) = if res isa Tuple
res
elseif res isa RuntimeGeneratedFunction
res, nothing
end
(jac_exe, jac_exe!) = res
return SymbolicsOneArgJacobianExtras(jac_exe, jac_exe!)
end

Expand Down Expand Up @@ -220,11 +212,7 @@ function DI.prepare_hessian(f, backend::Union{AutoSymbolics,AutoSparse{<:AutoSym
end

res = build_function(hess_var, vec(x_var); expression=Val(false))
(hess_exe, hess_exe!) = if res isa Tuple
res
elseif res isa RuntimeGeneratedFunction
res, nothing
end
(hess_exe, hess_exe!) = res
return SymbolicsOneArgHessianExtras(hess_exe, hess_exe!)
end

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,11 +23,7 @@ function DI.prepare_pushforward(f!, y, ::AutoSymbolics, x, dx)
pf_var = substitute(step_der_var, Dict(t_var => zero(eltype(x))))

res = build_function(pf_var, vcat(myvec(x_var), myvec(dx_var)); expression=Val(false))
(pushforward_exe, pushforward_exe!) = if res isa Tuple
res
elseif res isa RuntimeGeneratedFunction
res, nothing
end
(pushforward_exe, pushforward_exe!) = res
return SymbolicsTwoArgPushforwardExtras(pushforward_exe, pushforward_exe!)
end

Expand Down Expand Up @@ -77,11 +73,7 @@ function DI.prepare_derivative(f!, y, ::AutoSymbolics, x)
der_var = derivative(y_var, x_var)

res = build_function(der_var, x_var; expression=Val(false))
(der_exe, der_exe!) = if res isa Tuple
res
elseif res isa RuntimeGeneratedFunction
res, nothing
end
(der_exe, der_exe!) = res
return SymbolicsTwoArgDerivativeExtras(der_exe, der_exe!)
end

Expand Down Expand Up @@ -132,11 +124,7 @@ function DI.prepare_jacobian(
end

res = build_function(jac_var, x_var; expression=Val(false))
(jac_exe, jac_exe!) = if res isa Tuple
res
elseif res isa RuntimeGeneratedFunction
res, nothing
end
(jac_exe, jac_exe!) = res
return SymbolicsTwoArgJacobianExtras(jac_exe, jac_exe!)
end

Expand Down
6 changes: 0 additions & 6 deletions DifferentiationInterface/src/sparse/coloring.jl
Original file line number Diff line number Diff line change
Expand Up @@ -130,12 +130,6 @@ function neighbors(g::AdjacencyGraph, j::Integer)
return filter(!isequal(j), nz_in_col(g.A_colmajor, j))
end

function colored_neighbors(g::AdjacencyGraph, j::Integer, colors::AbstractVector{<:Integer})
return filter(neighbors(g, j)) do i
!iszero(colors[i])
end
end

function star_coloring(g::AdjacencyGraph)
n = length(columns(g))
colors = zeros(Int, n)
Expand Down
1 change: 1 addition & 0 deletions DifferentiationInterface/src/utils/exceptions.jl
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
struct MissingBackendError <: Exception
backend::AbstractADType
end

function Base.showerror(io::IO, e::MissingBackendError)
println(io, "failed to use $(backend_str(e.backend)) backend.")
if !check_available(e.backend)
Expand Down
43 changes: 32 additions & 11 deletions DifferentiationInterface/test/Internals/coloring.jl
Original file line number Diff line number Diff line change
Expand Up @@ -3,20 +3,41 @@ import DifferentiationInterface as DI
import DifferentiationInterfaceTest as DIT
using LinearAlgebra: I, Symmetric
using SparseArrays: sprand
using Test

alg = DI.GreedyColoringAlgorithm()

A = sprand(Bool, 100, 200, 0.05)
@testset "Grouping" begin
colors = [1, 3, 1, 3, 1, 2]
@test DI.color_groups(colors) == [[1, 3, 5], [6], [2, 4]]
colors = [2, 3, 2, 3, 2, 1]
@test DI.color_groups(colors) == [[6], [1, 3, 5], [2, 4]]
colors = [2, 3, 2, 3, 2]
@test_throws AssertionError DI.color_groups(colors)
end

column_colors = ADTypes.column_coloring(A, alg)
@test DIT.check_structurally_orthogonal_columns(A, column_colors)
@test maximum(column_colors) < size(A, 2) ÷ 2
@testset "Column coloring" begin
for A in (sprand(Bool, 100, 200, 0.05), sprand(Bool, 200, 100, 0.05))
column_colors = ADTypes.column_coloring(A, alg)
@test DIT.check_structurally_orthogonal_columns(A, column_colors)
@test minimum(column_colors) == 1
@test maximum(column_colors) < size(A, 2) ÷ 2
end
end

row_colors = ADTypes.row_coloring(A, alg)
@test DIT.check_structurally_orthogonal_rows(A, row_colors)
@test maximum(row_colors) < size(A, 1) ÷ 2
@testset "Row coloring" begin
for A in (sprand(Bool, 100, 200, 0.05), sprand(Bool, 200, 100, 0.05))
row_colors = ADTypes.row_coloring(A, alg)
@test DIT.check_structurally_orthogonal_rows(A, row_colors)
@test minimum(row_colors) == 1
@test maximum(row_colors) < size(A, 1) ÷ 2
end
end

S = Symmetric(sprand(Bool, 100, 100, 0.05)) + I
symmetric_colors = ADTypes.symmetric_coloring(S, alg)
@test DIT.check_symmetrically_structurally_orthogonal(S, symmetric_colors)
@test maximum(symmetric_colors) < size(A, 2) ÷ 2
@testset "Symmetric coloring" begin
S = Symmetric(sprand(Bool, 100, 100, 0.05)) + I
symmetric_colors = ADTypes.symmetric_coloring(S, alg)
@test DIT.check_symmetrically_structurally_orthogonal(S, symmetric_colors)
@test minimum(symmetric_colors) == 1
@test maximum(symmetric_colors) < size(S, 2) ÷ 2
end
20 changes: 13 additions & 7 deletions DifferentiationInterface/test/Internals/exceptions.jl
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
using ADTypes: ADTypes, AbstractADType
using DifferentiationInterface
import DifferentiationInterface as DI
using Test

"""
AutoBrokenForward <: ADTypes.AbstractADType
Expand All @@ -19,16 +21,20 @@ Used to test error messages.
"""
struct AutoBrokenReverse <: AbstractADType end
ADTypes.mode(::AutoBrokenReverse) = ADTypes.ReverseMode()
DI.check_available(::AutoBrokenReverse) = true

## Test exceptions
@testset "MissingBackendError" begin
f(x::AbstractArray) = sum(abs2, x)
x = [1.0, 2.0, 3.0]
x = [1.0]
y = similar(x)
dx = similar(x)
dy = similar(y)

@test_throws DI.MissingBackendError gradient(f, AutoBrokenForward(), x)
@test_throws DI.MissingBackendError gradient(f, AutoBrokenReverse(), x)
@test_throws DI.MissingBackendError jacobian(copy, AutoBrokenForward(), x)
@test_throws DI.MissingBackendError jacobian(copy, AutoBrokenReverse(), x)

@test_throws DI.MissingBackendError hvp(f, AutoBrokenForward(), x, x)
@test_throws DI.MissingBackendError hvp(f, AutoBrokenReverse(), x, x)
@test_throws DI.MissingBackendError jacobian(copyto!, y, AutoBrokenForward(), x)
@test_throws DI.MissingBackendError jacobian(copyto!, y, AutoBrokenReverse(), x)

@test_throws DI.MissingBackendError hessian(sum, AutoBrokenForward(), x)
@test_throws DI.MissingBackendError hessian(sum, AutoBrokenReverse(), x)
end
7 changes: 7 additions & 0 deletions DifferentiationInterface/test/Internals/second_order.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
using ADTypes
using DifferentiationInterface
using Test

@test ADTypes.mode(SecondOrder(AutoForwardDiff(), AutoZygote())) isa ADTypes.ForwardMode

@test startswith(string(SecondOrder(AutoForwardDiff(), AutoZygote())), "SecondOrder")
9 changes: 8 additions & 1 deletion DifferentiationInterface/test/Single/ForwardDiff.jl
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,14 @@ for backend in [AutoForwardDiff(), AutoSparse(AutoForwardDiff())]
@test check_hessian(backend)
end

test_differentiation([AutoForwardDiff(), AutoSparse(AutoForwardDiff())]; logging=LOGGING);
test_differentiation(
[
AutoForwardDiff(),
AutoForwardDiff(; chunksize=2, tag=:hello),
AutoSparse(AutoForwardDiff()),
];
logging=LOGGING,
);

test_differentiation(
MyAutoSparse(AutoForwardDiff()), sparse_scenarios(); sparsity=true, logging=LOGGING
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ using DataFrames: DataFrame
output_type=Number,
second_order=false,
excluded=[PullbackScenario],
logging=get(ENV, "CI", "false") == "false",
logging=LOGGING,
)

# derivative and jacobian for f!(x, y)
Expand All @@ -28,7 +28,7 @@ using DataFrames: DataFrame
output_type=AbstractVector,
second_order=false,
excluded=[PullbackScenario],
logging=get(ENV, "CI", "false") == "false",
logging=LOGGING,
)

data = vcat(DataFrame(results1), DataFrame(results2))
Expand Down Expand Up @@ -58,7 +58,7 @@ end
outofplace=false,
onearg=false,
second_order=false,
logging=get(ENV, "CI", "false") == "false",
logging=LOGGING,
)

data = vcat(DataFrame(results1))
Expand Down
4 changes: 4 additions & 0 deletions DifferentiationInterface/test/Single/Symbolics.jl
Original file line number Diff line number Diff line change
Expand Up @@ -17,3 +17,7 @@ test_differentiation(
test_differentiation(
AutoSparse(AutoSymbolics()), sparse_scenarios(); sparsity=true, logging=LOGGING
);

if VERSION >= v"1.10"
include("Symbolics/detector.jl")
end
21 changes: 21 additions & 0 deletions DifferentiationInterface/test/Single/Symbolics/detector.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
using ADTypes: ADTypes
using DifferentiationInterface: SymbolicsSparsityDetector
using Symbolics
using Test

detector = SymbolicsSparsityDetector()
@test detector isa ADTypes.AbstractSparsityDetector

f(x) = reshape(vcat(x[1], diff(vec(x))), size(x))
f!(y, x) = copyto!(vec(y), vec(f(x)))

for x in (rand(4), rand(4, 5))
@test sum(ADTypes.jacobian_sparsity(f, x, detector)) == 2length(x) - 1
@test sum(ADTypes.jacobian_sparsity(f!, similar(x), x, detector)) == 2length(x) - 1
end

g(x) = sum(abs2, diff(vec(x)))

for x in (rand(4), rand(4, 5))
@test sum(ADTypes.hessian_sparsity(g, x, detector)) == 3length(x) - 2
end
Loading

0 comments on commit fe4ba4c

Please sign in to comment.