Skip to content

Commit

Permalink
Finalize
Browse files Browse the repository at this point in the history
  • Loading branch information
gdalle committed Apr 14, 2024
1 parent fe11e33 commit 35b57fa
Show file tree
Hide file tree
Showing 7 changed files with 61 additions and 46 deletions.
8 changes: 4 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,10 @@ If a given package is missing, feel free to open an issue or pull request.
A natural approach is to use a keyword argument with e.g. `Bool` or `Symbol` values.
Let's see a few examples to understand why this is not enough:

- `autodiff = true`: ambiguous, we don't know which AD package should be used
- `autodiff = :forward`: ambiguous, there are several AD packages implementing both forward and reverse mode (and there are other modes beyond that)
- `autodiff = :Enzyme`: ambiguous, some AD packages can work both in forward and reverse mode
- `autodiff = (:Enzyme, :forward)`: not too bad, but many AD packages require additional configuration (number of chunks, tape compilation, etc.)
- `autodiff = true`: ambiguous, we don't know which AD package should be used
- `autodiff = :forward`: ambiguous, there are several AD packages implementing both forward and reverse mode (and there are other modes beyond that)
- `autodiff = :Enzyme`: ambiguous, some AD packages can work both in forward and reverse mode
- `autodiff = (:Enzyme, :forward)`: not too bad, but many AD packages require additional configuration (number of chunks, tape compilation, etc.)

A more involved struct is thus required, with package-specific parameters.
If every AD user develops their own version of said struct, it will ruin interoperability.
Expand Down
2 changes: 1 addition & 1 deletion src/ADTypes.jl
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
"""
ADTypes.jl
[ADTypes.jl](https://github.com/SciML/ADTypes.jl) is a common system for implementing multi-valued logic for choosing which automatic differentiation library to use.
[ADTypes.jl](https://github.com/SciML/ADTypes.jl) is a multi-valued logic system to choose an automatic differentiation (AD) package and specify its parameters.
"""
module ADTypes

Expand Down
54 changes: 31 additions & 23 deletions src/dense.jl
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
"""
AutoChainRules{RC}
Chooses any AD library based on [ChainRulesCore.jl](https://github.com/JuliaDiff/ChainRulesCore.jl).
Chooses any AD library based on [ChainRulesCore.jl](https://github.com/JuliaDiff/ChainRulesCore.jl) (see the list [here](https://juliadiff.org/ChainRulesCore.jl/stable/index.html#ChainRules-roll-out-status)).
# Fields
Expand All @@ -15,7 +15,7 @@ Base.@kwdef struct AutoChainRules{RC} <: AbstractADType
ruleconfig::RC
end

mode(::AutoChainRules) = ForwardOrReverseMode()
mode(::AutoChainRules) = ForwardOrReverseMode() # specialized in the extension

"""
AutoDiffractor
Expand All @@ -28,7 +28,7 @@ Chooses [Diffractor.jl](https://github.com/JuliaDiff/Diffractor.jl).
"""
struct AutoDiffractor <: AbstractADType end

mode(::AutoDiffractor) = ForwardMode()
mode(::AutoDiffractor) = ForwardOrReverseMode()

"""
AutoEnzyme{M}
Expand All @@ -37,19 +37,19 @@ Chooses [Enzyme.jl](https://github.com/EnzymeAD/Enzyme.jl).
# Fields
- `mode::M = nothing`: can be either
- `mode::M`: can be either
- an object subtyping `EnzymeCore.Mode` (like `EnzymeCore.Forward` or `EnzymeCore.Reverse`) if a specific mode is required
- the default value `nothing` to choose the best mode automatically
- `nothing` to choose the best mode automatically
# Constructors
AutoEnzyme(mode)
AutoEnzyme(; mode=nothing)
"""
Base.@kwdef struct AutoEnzyme{M} <: AbstractADType
mode::M = nothing
end

mode(::AutoEnzyme) = ForwardOrReverseMode()
mode(::AutoEnzyme) = ForwardOrReverseMode() # specialized in the extension

"""
AutoFastDifferentiation
Expand All @@ -71,13 +71,13 @@ Chooses [FiniteDiff.jl](https://github.com/JuliaDiff/FiniteDiff.jl).
# Fields
- `fdtype::T1 = Val(:forward)`: finite difference type
- `fdjtype::T2 = fdtype`: finite difference type for the Jacobian
- `fdhtype::T3 = Val(:hcentral)`: finite difference type for the Hessian
- `fdtype::T1`: finite difference type
- `fdjtype::T2`: finite difference type for the Jacobian
- `fdhtype::T3`: finite difference type for the Hessian
# Constructor
AutoFiniteDiff(; fdtype, fdjtype, fdhtype)
AutoFiniteDiff(; fdtype=Val(:forward), fdjtype=fdtype, fdhtype=Val(:hcentral))
"""
Base.@kwdef struct AutoFiniteDiff{T1, T2, T3} <: AbstractADType
fdtype::T1 = Val(:forward)
Expand All @@ -94,7 +94,7 @@ Chooses [FiniteDifferences.jl](https://github.com/JuliaDiff/FiniteDifferences.jl
# Fields
- `fdm::T`: should be a [`FiniteDifferenceMethod`](https://juliadiff.org/FiniteDifferences.jl/stable/pages/api/#FiniteDifferences.FiniteDifferenceMethod) constructed for instance with `FiniteDifferences.central_fdm`.
- `fdm::T`: a [`FiniteDifferenceMethod`](https://juliadiff.org/FiniteDifferences.jl/stable/pages/api/#FiniteDifferences.FiniteDifferenceMethod), constructed for instance with `FiniteDifferences.central_fdm`.
# Constructor
Expand All @@ -111,13 +111,17 @@ mode(::AutoFiniteDifferences) = FiniteDifferencesMode()
Chooses [ForwardDiff.jl](https://github.com/JuliaDiff/ForwardDiff.jl).
# Type parameters
- `chunksize`: the preferred [chunk size](https://juliadiff.org/ForwardDiff.jl/stable/user/advanced/#Configuring-Chunk-Size) to evaluate several derivatives at once
# Fields
- `tag::T`: a potential [custom tag](https://juliadiff.org/ForwardDiff.jl/release-0.10/user/advanced.html#Custom-tags-and-tag-checking-1)
- `tag::T`: a [custom tag](https://juliadiff.org/ForwardDiff.jl/release-0.10/user/advanced.html#Custom-tags-and-tag-checking-1) to handle nested differentiation calls (usually not necessary)
# Constructors
AutoForwardDiff(; chunksize = nothing, tag = nothing)
AutoForwardDiff(; chunksize=nothing, tag=nothing)
"""
struct AutoForwardDiff{chunksize, T} <: AbstractADType
tag::T
Expand All @@ -136,12 +140,12 @@ Chooses [ModelingToolkit.jl](https://github.com/SciML/ModelingToolkit.jl).
# Fields
- `obj_sparse::Bool = false`
- `cons_sparse::Bool = false`
- `obj_sparse::Bool`
- `cons_sparse::Bool`
# Constructor
AutoModelingToolkit(; obj_sparse, cons_sparse)
AutoModelingToolkit(; obj_sparse=false, cons_sparse=false)
"""
Base.@kwdef struct AutoModelingToolkit <: AbstractADType
obj_sparse::Bool = false
Expand All @@ -151,17 +155,21 @@ end
mode(::AutoModelingToolkit) = SymbolicMode()

"""
AutoPolyesterForwardDiff{chunksize}
AutoPolyesterForwardDiff{chunksize,T}
Chooses [PolyesterForwardDiff.jl](https://github.com/JuliaDiff/PolyesterForwardDiff.jl).
# Type parameters
- `chunksize`: the preferred [chunk size](https://juliadiff.org/ForwardDiff.jl/stable/user/advanced/#Configuring-Chunk-Size) to evaluate several derivatives at once
# Fields
- `tag::T`: a potential [custom tag](https://juliadiff.org/ForwardDiff.jl/release-0.10/user/advanced.html#Custom-tags-and-tag-checking-1)
- `tag::T`: a [custom tag](https://juliadiff.org/ForwardDiff.jl/release-0.10/user/advanced.html#Custom-tags-and-tag-checking-1) to handle nested differentiation calls (usually not necessary)
# Constructors
AutoPolyesterForwardDiff(; chunksize = nothing, tag = nothing)
AutoPolyesterForwardDiff(; chunksize=nothing, tag=nothing)
"""
struct AutoPolyesterForwardDiff{chunksize, T} <: AbstractADType
tag::T
Expand All @@ -180,11 +188,11 @@ Chooses [ReverseDiff.jl](https://github.com/JuliaDiff/ReverseDiff.jl).
# Fields
- `compile::Bool = false`
- `compile::Bool`: whether to [compile the tape](https://juliadiff.org/ReverseDiff.jl/api/#ReverseDiff.compile) prior to differentiation
# Constructor
AutoReverseDiff(compile)
AutoReverseDiff(; compile=false)
"""
Base.@kwdef struct AutoReverseDiff <: AbstractADType
compile::Bool = false
Expand All @@ -197,7 +205,7 @@ mode(::AutoReverseDiff) = ReverseMode()
Chooses [Tapir.jl](https://github.com/withbayes/Tapir.jl).
!! danger
!!! danger
This package is experimental, use at your own risk.
# Constructor
Expand Down
2 changes: 1 addition & 1 deletion src/mode.jl
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ struct ReverseMode <: AbstractMode end
Trait for AD choices that can rely on either [forward mode](https://en.wikipedia.org/wiki/Automatic_differentiation#Forward_accumulation) or [reverse mode](https://en.wikipedia.org/wiki/Automatic_differentiation#Reverse_accumulation) algorithmic differentiation, depending on their configuration.
!!! warning
This trait should probably never be used, because more precise dispatches should be defined.
This trait should rarely be used, because more precise dispatches to [`ForwardMode`](@ref) or [`ReverseMode`](@ref) should be defined.
"""
struct ForwardOrReverseMode <: AbstractMode end

Expand Down
8 changes: 4 additions & 4 deletions src/sparse.jl
Original file line number Diff line number Diff line change
Expand Up @@ -16,14 +16,14 @@ abstract type AbstractSparsityDetector end
jacobian_sparsity(f, x, sd::AbstractSparsityDetector)::AbstractMatrix{Bool}
jacobian_sparsity(f!, y, x, sd::AbstractSparsityDetector)::AbstractMatrix{Bool}
Use `sd` to construct a (typically sparse) matrix `S` describing the pattern of nonzeroes in the Jacobian of `f` (resp. `f!`) applied at `x` (resp. `(y, x)`).
Use detector `sd` to construct a (typically sparse) matrix `S` describing the pattern of nonzeroes in the Jacobian of `f` (resp. `f!`) applied at `x` (resp. `(y, x)`).
"""
function jacobian_sparsity end

"""
hessian_sparsity(f, x, sd::AbstractSparsityDetector)::AbstractMatrix{Bool}
Use `sd` to construct a (typically sparse) matrix `S` describing the pattern of nonzeroes in the Hessian of `f` applied at `x`.
Use detector `sd` to construct a (typically sparse) matrix `S` describing the pattern of nonzeroes in the Hessian of `f` applied at `x`.
"""
function hessian_sparsity end

Expand Down Expand Up @@ -59,14 +59,14 @@ abstract type AbstractColoringAlgorithm end
"""
column_coloring(M::AbstractMatrix, ca::ColoringAlgorithm)::AbstractVector{<:Integer}
Use `ca` to construct a coloring vector `c` of length `size(M, 2)` such that if two columns `j1` and `j2` satisfy `c[j1] = c[j2]`, they do not share any nonzero coefficients in `M`.
Use algorithm `ca` to construct a coloring vector `c` of length `size(M, 2)` such that if two columns `j1` and `j2` satisfy `c[j1] = c[j2]`, they do not share any nonzero coefficients in `M`.
"""
function column_coloring end

"""
row_coloring(M::AbstractMatrix, ca::ColoringAlgorithm)::AbstractVector{<:Integer}
Use `ca` to construct a coloring vector `c` of length `size(M, 1)` such that if two rows `i1` and `i2` satisfy `c[i1] = c[i2]`, they do not share any nonzero coefficients in `M`.
Use algorithm `ca` to construct a coloring vector `c` of length `size(M, 1)` such that if two rows `i1` and `i2` satisfy `c[i1] = c[i2]`, they do not share any nonzero coefficients in `M`.
"""
function row_coloring end

Expand Down
28 changes: 18 additions & 10 deletions test/dense.jl
Original file line number Diff line number Diff line change
Expand Up @@ -2,47 +2,47 @@
ad = AutoChainRules(; ruleconfig = ForwardOrReverseRuleConfig())
@test ad isa AbstractADType
@test ad isa AutoChainRules{ForwardOrReverseRuleConfig}
@test ad.ruleconfig == ForwardOrReverseRuleConfig()
@test mode(ad) isa ForwardOrReverseMode
@test ad.ruleconfig == ForwardOrReverseRuleConfig()

ad = AutoChainRules(; ruleconfig = ForwardRuleConfig())
@test ad isa AbstractADType
@test ad isa AutoChainRules{ForwardRuleConfig}
@test ad.ruleconfig == ForwardRuleConfig()
@test mode(ad) isa ForwardMode
@test ad.ruleconfig == ForwardRuleConfig()

ad = AutoChainRules(; ruleconfig = ReverseRuleConfig())
@test ad isa AbstractADType
@test ad isa AutoChainRules{ReverseRuleConfig}
@test ad.ruleconfig == ReverseRuleConfig()
@test mode(ad) isa ReverseMode
@test ad.ruleconfig == ReverseRuleConfig()
end

@testset "AutoDiffractor" begin
ad = AutoDiffractor()
@test ad isa AbstractADType
@test ad isa AutoDiffractor
@test mode(ad) isa ForwardMode
@test mode(ad) isa ForwardOrReverseMode
end

@testset "AutoEnzyme" begin
ad = AutoEnzyme()
@test ad isa AbstractADType
@test ad isa AutoEnzyme{Nothing}
@test ad.mode === nothing
@test mode(ad) isa ForwardOrReverseMode
@test ad.mode === nothing

ad = AutoEnzyme(; mode = EnzymeCore.Forward)
@test ad isa AbstractADType
@test ad isa AutoEnzyme{typeof(EnzymeCore.Forward)}
@test ad.mode == EnzymeCore.Forward
@test mode(ad) isa ForwardMode
@test ad.mode == EnzymeCore.Forward

ad = AutoEnzyme(; mode = EnzymeCore.Reverse)
@test ad isa AbstractADType
@test ad isa AutoEnzyme{typeof(EnzymeCore.Reverse)}
@test ad.mode == EnzymeCore.Reverse
@test mode(ad) isa ReverseMode
@test ad.mode == EnzymeCore.Reverse
end

@testset "AutoFastDifferentiation" begin
Expand All @@ -60,6 +60,14 @@ end
@test ad.fdtype === Val(:forward)
@test ad.fdjtype === Val(:forward)
@test ad.fdhtype === Val(:hcentral)

ad = AutoFiniteDiff(; fdtype = Val(:central), fdjtype = Val(:forward))
@test ad isa AbstractADType
@test ad isa AutoFiniteDiff
@test mode(ad) isa FiniteDifferencesMode
@test ad.fdtype === Val(:central)
@test ad.fdjtype === Val(:forward)
@test ad.fdhtype === Val(:hcentral)
end

@testset "AutoFiniteDifferences" begin
Expand All @@ -69,11 +77,11 @@ end
@test mode(ad) isa FiniteDifferencesMode
@test ad.fdm === nothing

ad = AutoFiniteDifferences(; fdm = Val(:forward))
ad = AutoFiniteDifferences(; fdm = Val(:forward_fdm))
@test ad isa AbstractADType
@test ad isa AutoFiniteDifferences{Val{:forward}}
@test ad isa AutoFiniteDifferences{Val{:forward_fdm}}
@test mode(ad) isa FiniteDifferencesMode
@test ad.fdm == Val(:forward)
@test ad.fdm == Val(:forward_fdm)
end

@testset "AutoForwardDiff" begin
Expand Down
5 changes: 2 additions & 3 deletions test/runtests.jl
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@ using ADTypes: dense_ad,
using ChainRulesCore: ChainRulesCore, RuleConfig,
HasForwardsMode, HasReverseMode,
NoForwardsMode, NoReverseMode

using EnzymeCore: EnzymeCore
using Test

Expand All @@ -32,12 +31,12 @@ struct ForwardOrReverseRuleConfig <: RuleConfig{Union{HasForwardsMode, HasRevers

function every_ad()
return [
AutoChainRules(:rc),
AutoChainRules(; ruleconfig = :rc),
AutoDiffractor(),
AutoEnzyme(),
AutoFastDifferentiation(),
AutoFiniteDiff(),
AutoFiniteDifferences(:fdm),
AutoFiniteDifferences(; fdm = :fdm),
AutoForwardDiff(),
AutoModelingToolkit(),
AutoPolyesterForwardDiff(),
Expand Down

0 comments on commit 35b57fa

Please sign in to comment.