Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Increase code coverage #264

Merged
merged 3 commits into from
May 16, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Loading