From c8c61bf1a85e3df6743bd36344894f29cbcb330e Mon Sep 17 00:00:00 2001 From: Avik Pal Date: Mon, 30 Oct 2023 11:52:29 -0400 Subject: [PATCH 1/5] Run formatter --- ext/SparseDiffToolsSymbolicsExt.jl | 2 +- ext/SparseDiffToolsZygoteExt.jl | 4 +- src/coloring/acyclic_coloring.jl | 16 +++---- src/coloring/backtracking_coloring.jl | 10 ++--- src/coloring/high_level.jl | 4 +- src/coloring/matrix2graph.jl | 2 +- src/differentiation/compute_hessian_ad.jl | 36 ++++++++-------- src/differentiation/compute_jacobian_ad.jl | 50 +++++++++++----------- src/differentiation/jaches_products.jl | 44 +++++++++---------- src/differentiation/vecjac_products.jl | 8 ++-- src/highlevel/coloring.jl | 4 +- src/highlevel/common.jl | 10 ++--- src/highlevel/finite_diff.jl | 8 ++-- src/highlevel/forward_mode.jl | 8 ++-- src/highlevel/reverse_mode.jl | 8 ++-- 15 files changed, 107 insertions(+), 107 deletions(-) diff --git a/ext/SparseDiffToolsSymbolicsExt.jl b/ext/SparseDiffToolsSymbolicsExt.jl index b49c58b1..fa9e058e 100644 --- a/ext/SparseDiffToolsSymbolicsExt.jl +++ b/ext/SparseDiffToolsSymbolicsExt.jl @@ -4,7 +4,7 @@ using SparseDiffTools, Symbolics import SparseDiffTools: AbstractSparseADType function (alg::SymbolicsSparsityDetection)(ad::AbstractSparseADType, f, x; fx = nothing, - kwargs...) + kwargs...) fx = fx === nothing ? similar(f(x)) : dx f!(y, x) = (y .= f(x)) J = Symbolics.jacobian_sparsity(f!, fx, x) diff --git a/ext/SparseDiffToolsZygoteExt.jl b/ext/SparseDiffToolsZygoteExt.jl index c491afae..fd31dcea 100644 --- a/ext/SparseDiffToolsZygoteExt.jl +++ b/ext/SparseDiffToolsZygoteExt.jl @@ -75,7 +75,7 @@ end end function autoback_hesvec!(dy, f, x, v, cache1 = _default_autoback_hesvec_cache(x, v), - cache2 = _default_autoback_hesvec_cache(x, v)) + cache2 = _default_autoback_hesvec_cache(x, v)) g = let f = f (dx, x) -> dx .= first(Zygote.gradient(f, x)) end @@ -140,7 +140,7 @@ end # prefer non in-place method function (L::AutoDiffVJP{<:AutoZygote, IIP, true})(dv, v, p, t; - VJP_input = nothing) where {IIP} + VJP_input = nothing) where {IIP} # ignore VJP_input as pullback was computed in update_coefficients!(...) _dv = L(v, p, t; VJP_input = VJP_input) diff --git a/src/coloring/acyclic_coloring.jl b/src/coloring/acyclic_coloring.jl index 65313d4c..55ab983c 100644 --- a/src/coloring/acyclic_coloring.jl +++ b/src/coloring/acyclic_coloring.jl @@ -73,9 +73,9 @@ the induced 2-colored subgraphs/trees where the id of set is an integer representing an edge of graph 'g' """ function prevent_cycle!(first_visit_to_tree::AbstractVector{<:Tuple{Integer, Integer}}, - forbidden_colors::AbstractVector{<:Integer}, v::Integer, w::Integer, x::Integer, - g::Graphs.AbstractGraph, two_colored_forest::DisjointSets{<:Integer}, - color::AbstractVector{<:Integer}) + forbidden_colors::AbstractVector{<:Integer}, v::Integer, w::Integer, x::Integer, + g::Graphs.AbstractGraph, two_colored_forest::DisjointSets{<:Integer}, + color::AbstractVector{<:Integer}) e = find(w, x, g, two_colored_forest) p, q = first_visit_to_tree[e] @@ -97,8 +97,8 @@ Disjoint set is used to store stars in sets, which are identified through key edges present in g. """ function grow_star!(two_colored_forest::DisjointSets{<:Integer}, - first_neighbor::AbstractVector{<:Tuple{Integer, Integer}}, v::Integer, w::Integer, - g::Graphs.AbstractGraph, color::AbstractVector{<:Integer}) + first_neighbor::AbstractVector{<:Tuple{Integer, Integer}}, v::Integer, w::Integer, + g::Graphs.AbstractGraph, color::AbstractVector{<:Integer}) insert_new_tree!(two_colored_forest, v, w, g) p, q = first_neighbor[color[w]] @@ -119,7 +119,7 @@ Subroutine to merge trees present in the disjoint set which have a common edge. """ function merge_trees!(two_colored_forest::DisjointSets{<:Integer}, v::Integer, w::Integer, - x::Integer, g::Graphs.AbstractGraph) + x::Integer, g::Graphs.AbstractGraph) e1 = find(v, w, g, two_colored_forest) e2 = find(w, x, g, two_colored_forest) if e1 != e2 @@ -135,7 +135,7 @@ creates a new singleton set in the disjoint set 'two_colored_forest' consisting of the edge connecting v and w in the graph g """ function insert_new_tree!(two_colored_forest::DisjointSets{<:Integer}, v::Integer, - w::Integer, g::Graphs.AbstractGraph) + w::Integer, g::Graphs.AbstractGraph) edge_index = find_edge_index(v, w, g) push!(two_colored_forest, edge_index) end @@ -157,7 +157,7 @@ Returns the root of the disjoint set to which the edge connecting vertices w and in the graph g belongs to """ function find(w::Integer, x::Integer, g::Graphs.AbstractGraph, - two_colored_forest::DisjointSets{<:Integer}) + two_colored_forest::DisjointSets{<:Integer}) edge_index = find_edge_index(w, x, g) return find_root!(two_colored_forest, edge_index) end diff --git a/src/coloring/backtracking_coloring.jl b/src/coloring/backtracking_coloring.jl index a4abafa4..ae10ad73 100644 --- a/src/coloring/backtracking_coloring.jl +++ b/src/coloring/backtracking_coloring.jl @@ -115,7 +115,7 @@ Returns an uncolored vertex from the partially colored graph which has the highest degree """ function uncolored_vertex_of_maximal_degree(A::AbstractVector{<:Integer}, - F::AbstractVector{<:Integer}) + F::AbstractVector{<:Integer}) for v in A if F[v] == 0 return v @@ -145,8 +145,8 @@ g: Graph to be colored opt: Current optimal number of colors to be used in the coloring of graph g """ function free_colors(x::Integer, A::AbstractVector{<:Integer}, - colors::AbstractVector{<:Integer}, F::Vector{Integer}, g::Graphs.AbstractGraph, - opt::Integer) + colors::AbstractVector{<:Integer}, F::Vector{Integer}, g::Graphs.AbstractGraph, + opt::Integer) index = -1 freecolors = zeros(Int, 0) @@ -187,7 +187,7 @@ Returns least index i such that color of vertex A[i] is equal to `opt` (optimal chromatic number) """ function least_index(F::AbstractVector{<:Integer}, A::AbstractVector{<:Integer}, - opt::Integer) + opt::Integer) for i in eachindex(A) if F[A[i]] == opt return i @@ -202,7 +202,7 @@ Uncolors all vertices A[i] where i is greater than or equal to start """ function uncolor_all!(F::AbstractVector{<:Integer}, A::AbstractVector{<:Integer}, - start::Integer) + start::Integer) for i in start:length(A) F[A[i]] = 0 end diff --git a/src/coloring/high_level.jl b/src/coloring/high_level.jl index 6f0a9745..a9cd4d94 100644 --- a/src/coloring/high_level.jl +++ b/src/coloring/high_level.jl @@ -21,8 +21,8 @@ If `ArrayInterface.fast_matrix_colors(A)` is true, then uses `ArrayInterface.matrix_colors(A)` to compute the matrix colors. """ function ArrayInterface.matrix_colors(A::AbstractMatrix, - alg::SparseDiffToolsColoringAlgorithm = GreedyD1Color(); - partition_by_rows::Bool = false) + alg::SparseDiffToolsColoringAlgorithm = GreedyD1Color(); + partition_by_rows::Bool = false) # If fast algorithm for matrix coloring exists use that if !partition_by_rows diff --git a/src/coloring/matrix2graph.jl b/src/coloring/matrix2graph.jl index fcf4050b..85f79ee7 100644 --- a/src/coloring/matrix2graph.jl +++ b/src/coloring/matrix2graph.jl @@ -33,7 +33,7 @@ Note that the sparsity pattern is defined by structural nonzeroes, ie includes e stored zeros. """ function matrix2graph(sparse_matrix::AbstractSparseMatrix{<:Number}, - partition_by_rows::Bool = true) + partition_by_rows::Bool = true) (rows_index, cols_index, _) = findnz(sparse_matrix) ncols = size(sparse_matrix, 2) diff --git a/src/differentiation/compute_hessian_ad.jl b/src/differentiation/compute_hessian_ad.jl index 048dcf16..796e94fc 100644 --- a/src/differentiation/compute_hessian_ad.jl +++ b/src/differentiation/compute_hessian_ad.jl @@ -20,9 +20,9 @@ function make_hessian_buffers(colorvec, x) end function ForwardColorHesCache(f, x::AbstractVector{<:Number}, - colorvec::AbstractVector{<:Integer} = eachindex(x), - sparsity::Union{AbstractMatrix, Nothing} = nothing, - g! = (G, x, grad_config) -> ForwardDiff.gradient!(G, f, x, grad_config)) + colorvec::AbstractVector{<:Integer} = eachindex(x), + sparsity::Union{AbstractMatrix, Nothing} = nothing, + g! = (G, x, grad_config) -> ForwardDiff.gradient!(G, f, x, grad_config)) ncolors, D, buffer, G, G2 = make_hessian_buffers(colorvec, x) grad_config = ForwardDiff.GradientConfig(f, x) @@ -46,7 +46,7 @@ function ForwardColorHesCache(f, x::AbstractVector{<:Number}, end function numauto_color_hessian!(H::AbstractMatrix{<:Number}, f, x::AbstractArray{<:Number}, - hes_cache::ForwardColorHesCache; safe = true) + hes_cache::ForwardColorHesCache; safe = true) ϵ = cbrt(eps(eltype(x))) for j in 1:(hes_cache.ncolors) x .+= ϵ .* @view hes_cache.D[:, j] @@ -67,23 +67,23 @@ function numauto_color_hessian!(H::AbstractMatrix{<:Number}, f, x::AbstractArray end function numauto_color_hessian!(H::AbstractMatrix{<:Number}, f, x::AbstractArray{<:Number}, - colorvec::AbstractVector{<:Integer} = eachindex(x), - sparsity::Union{AbstractMatrix, Nothing} = nothing) + colorvec::AbstractVector{<:Integer} = eachindex(x), + sparsity::Union{AbstractMatrix, Nothing} = nothing) hes_cache = ForwardColorHesCache(f, x, colorvec, sparsity) numauto_color_hessian!(H, f, x, hes_cache) return H end function numauto_color_hessian(f, x::AbstractArray{<:Number}, - hes_cache::ForwardColorHesCache) + hes_cache::ForwardColorHesCache) H = convert.(eltype(x), hes_cache.sparsity) numauto_color_hessian!(H, f, x, hes_cache) return H end function numauto_color_hessian(f, x::AbstractArray{<:Number}, - colorvec::AbstractVector{<:Integer} = eachindex(x), - sparsity::Union{AbstractMatrix, Nothing} = nothing) + colorvec::AbstractVector{<:Integer} = eachindex(x), + sparsity::Union{AbstractMatrix, Nothing} = nothing) hes_cache = ForwardColorHesCache(f, x, colorvec, sparsity) H = convert.(eltype(x), hes_cache.sparsity) numauto_color_hessian!(H, f, x, hes_cache) @@ -102,9 +102,9 @@ end struct AutoAutoTag end function ForwardAutoColorHesCache(f, x::AbstractVector{V}, - colorvec::AbstractVector{<:Integer} = eachindex(x), - sparsity::Union{AbstractMatrix, Nothing} = nothing, - tag::ForwardDiff.Tag = ForwardDiff.Tag(AutoAutoTag(), V)) where {V} + colorvec::AbstractVector{<:Integer} = eachindex(x), + sparsity::Union{AbstractMatrix, Nothing} = nothing, + tag::ForwardDiff.Tag = ForwardDiff.Tag(AutoAutoTag(), V)) where {V} if sparsity === nothing sparsity = sparse(ones(length(x), length(x))) end @@ -124,28 +124,28 @@ function ForwardAutoColorHesCache(f, x::AbstractVector{V}, end function autoauto_color_hessian!(H::AbstractMatrix{<:Number}, f, x::AbstractArray{<:Number}, - hes_cache::ForwardAutoColorHesCache) + hes_cache::ForwardAutoColorHesCache) forwarddiff_color_jacobian!(H, hes_cache.grad!, x, hes_cache.jac_cache) end function autoauto_color_hessian!(H::AbstractMatrix{<:Number}, f, x::AbstractArray{<:Number}, - colorvec::AbstractVector{<:Integer} = eachindex(x), - sparsity::Union{AbstractMatrix, Nothing} = nothing) + colorvec::AbstractVector{<:Integer} = eachindex(x), + sparsity::Union{AbstractMatrix, Nothing} = nothing) hes_cache = ForwardAutoColorHesCache(f, x, colorvec, sparsity) autoauto_color_hessian!(H, f, x, hes_cache) return H end function autoauto_color_hessian(f, x::AbstractArray{<:Number}, - hes_cache::ForwardAutoColorHesCache) + hes_cache::ForwardAutoColorHesCache) H = convert.(eltype(x), hes_cache.sparsity) autoauto_color_hessian!(H, f, x, hes_cache) return H end function autoauto_color_hessian(f, x::AbstractArray{<:Number}, - colorvec::AbstractVector{<:Integer} = eachindex(x), - sparsity::Union{AbstractMatrix, Nothing} = nothing) + colorvec::AbstractVector{<:Integer} = eachindex(x), + sparsity::Union{AbstractMatrix, Nothing} = nothing) hes_cache = ForwardAutoColorHesCache(f, x, colorvec, sparsity) H = convert.(eltype(x), hes_cache.sparsity) autoauto_color_hessian!(H, f, x, hes_cache) diff --git a/src/differentiation/compute_jacobian_ad.jl b/src/differentiation/compute_jacobian_ad.jl index c8696650..7a9d9bad 100644 --- a/src/differentiation/compute_jacobian_ad.jl +++ b/src/differentiation/compute_jacobian_ad.jl @@ -20,7 +20,7 @@ const default_chunk_size = ForwardDiff.pickchunksize const SMALLTAG = typeof(ForwardDiff.Tag(missing, Float64)) function ForwardColorJacCache(f::F, x, _chunksize = nothing; dx = nothing, tag = nothing, - colorvec = 1:length(x), sparsity::Union{AbstractArray, Nothing} = nothing) where {F} + colorvec = 1:length(x), sparsity::Union{AbstractArray, Nothing} = nothing) where {F} if _chunksize isa Nothing chunksize = ForwardDiff.pickchunksize(maximum(colorvec)) else @@ -105,13 +105,13 @@ end end function forwarddiff_color_jacobian(f::F, - x::AbstractArray{<:Number}; - colorvec = 1:length(x), - sparsity = nothing, - jac_prototype = nothing, - chunksize = nothing, - dx = sparsity === nothing && jac_prototype === nothing ? - nothing : copy(x)) where {F} #if dx is nothing, we will estimate dx at the cost of a function call + x::AbstractArray{<:Number}; + colorvec = 1:length(x), + sparsity = nothing, + jac_prototype = nothing, + chunksize = nothing, + dx = sparsity === nothing && jac_prototype === nothing ? + nothing : copy(x)) where {F} #if dx is nothing, we will estimate dx at the cost of a function call if sparsity === nothing && jac_prototype === nothing cfg = if chunksize === nothing if typeof(x) <: StaticArrays.StaticArray @@ -136,12 +136,12 @@ function forwarddiff_color_jacobian(f::F, end function forwarddiff_color_jacobian(J::AbstractArray{<:Number}, f::F, - x::AbstractArray{<:Number}; - colorvec = 1:length(x), - sparsity = nothing, - jac_prototype = nothing, - chunksize = nothing, - dx = similar(x, size(J, 1))) where {F} #dx kwarg can be used to avoid re-allocating dx every time + x::AbstractArray{<:Number}; + colorvec = 1:length(x), + sparsity = nothing, + jac_prototype = nothing, + chunksize = nothing, + dx = similar(x, size(J, 1))) where {F} #dx kwarg can be used to avoid re-allocating dx every time if sparsity === nothing && jac_prototype === nothing cfg = chunksize === nothing ? ForwardDiff.JacobianConfig(f, x) : ForwardDiff.JacobianConfig(f, x, ForwardDiff.Chunk(getsize(chunksize))) @@ -154,8 +154,8 @@ function forwarddiff_color_jacobian(J::AbstractArray{<:Number}, f::F, end function forwarddiff_color_jacobian(f::F, x::AbstractArray{<:Number}, - jac_cache::ForwardColorJacCache, - jac_prototype = nothing) where {F} + jac_cache::ForwardColorJacCache, + jac_prototype = nothing) where {F} if jac_prototype isa Nothing ? ArrayInterface.ismutable(x) : ArrayInterface.ismutable(jac_prototype) # Whenever J is mutable, we mutate it to avoid allocations @@ -174,8 +174,8 @@ end # When J is mutable, this version of forwarddiff_color_jacobian will mutate J to avoid allocations function forwarddiff_color_jacobian(J::AbstractMatrix{<:Number}, f::F, - x::AbstractArray{<:Number}, - jac_cache::ForwardColorJacCache) where {F} + x::AbstractArray{<:Number}, + jac_cache::ForwardColorJacCache) where {F} t = jac_cache.t dx = jac_cache.dx p = jac_cache.p @@ -248,8 +248,8 @@ end # When J is immutable, this version of forwarddiff_color_jacobian will avoid mutating J function forwarddiff_color_jacobian_immutable(f, x::AbstractArray{<:Number}, - jac_cache::ForwardColorJacCache, - jac_prototype = nothing) + jac_cache::ForwardColorJacCache, + jac_prototype = nothing) t = jac_cache.t dx = jac_cache.dx p = jac_cache.p @@ -313,15 +313,15 @@ function forwarddiff_color_jacobian_immutable(f, x::AbstractArray{<:Number}, end function forwarddiff_color_jacobian!(J::AbstractMatrix{<:Number}, f, - x::AbstractArray{<:Number}; dx = similar(x, size(J, 1)), colorvec = 1:length(x), - sparsity = ArrayInterface.has_sparsestruct(J) ? J : nothing) + x::AbstractArray{<:Number}; dx = similar(x, size(J, 1)), colorvec = 1:length(x), + sparsity = ArrayInterface.has_sparsestruct(J) ? J : nothing) forwarddiff_color_jacobian!(J, f, x, ForwardColorJacCache(f, x; dx, colorvec, sparsity)) end function forwarddiff_color_jacobian!(J::AbstractMatrix{<:Number}, - f, - x::AbstractArray{<:Number}, - jac_cache::ForwardColorJacCache) + f, + x::AbstractArray{<:Number}, + jac_cache::ForwardColorJacCache) t = jac_cache.t fx = jac_cache.fx dx = jac_cache.dx diff --git a/src/differentiation/jaches_products.jl b/src/differentiation/jaches_products.jl index 264f22da..7c9d8d4b 100644 --- a/src/differentiation/jaches_products.jl +++ b/src/differentiation/jaches_products.jl @@ -5,10 +5,10 @@ get_tag(::Dual{T, V, N}) where {T, V, N} = T # J(f(x))*v function auto_jacvec!(dy, f, x, v, - cache1 = Dual{typeof(ForwardDiff.Tag(DeivVecTag(), eltype(x))), - eltype(x), 1, - }.(x, ForwardDiff.Partials.(tuple.(reshape(v, size(x))))), - cache2 = similar(cache1)) + cache1 = Dual{typeof(ForwardDiff.Tag(DeivVecTag(), eltype(x))), + eltype(x), 1, + }.(x, ForwardDiff.Partials.(tuple.(reshape(v, size(x))))), + cache2 = similar(cache1)) cache1 .= Dual{ get_tag(cache1), eltype(x), @@ -33,7 +33,7 @@ function auto_jacvec(f, x, v) end function num_jacvec!(dy, f, x, v, cache1 = similar(v), cache2 = similar(v); - compute_f0 = true) + compute_f0 = true) vv = reshape(v, axes(x)) compute_f0 && (f(cache1, x)) T = eltype(x) @@ -58,7 +58,7 @@ function num_jacvec(f, x, v, f0 = nothing) end function num_hesvec!(dy, f, x, v, cache1 = similar(v), cache2 = similar(v), - cache3 = similar(v)) + cache3 = similar(v)) cache = FiniteDiff.GradientCache(v[1], cache1, Val{:central}) g = let f = f, cache = cache (dx, x) -> FiniteDiff.finite_difference_gradient!(dx, f, x, cache) @@ -87,7 +87,7 @@ function num_hesvec(f, x, v) end function numauto_hesvec!(dy, f, x, v, cache = ForwardDiff.GradientConfig(f, v), - cache1 = similar(v), cache2 = similar(v)) + cache1 = similar(v), cache2 = similar(v)) g = let f = f, x = x, cache = cache g = (dx, x) -> ForwardDiff.gradient!(dx, f, x, cache) end @@ -115,12 +115,12 @@ function numauto_hesvec(f, x, v) end function autonum_hesvec!(dy, f, x, v, - cache1 = Dual{typeof(ForwardDiff.Tag(DeivVecTag(), eltype(x))), - eltype(x), 1, - }.(x, ForwardDiff.Partials.(tuple.(reshape(v, size(x))))), - cache2 = Dual{typeof(ForwardDiff.Tag(DeivVecTag(), eltype(x))), - eltype(x), 1, - }.(x, ForwardDiff.Partials.(tuple.(reshape(v, size(x)))))) + cache1 = Dual{typeof(ForwardDiff.Tag(DeivVecTag(), eltype(x))), + eltype(x), 1, + }.(x, ForwardDiff.Partials.(tuple.(reshape(v, size(x))))), + cache2 = Dual{typeof(ForwardDiff.Tag(DeivVecTag(), eltype(x))), + eltype(x), 1, + }.(x, ForwardDiff.Partials.(tuple.(reshape(v, size(x)))))) cache = FiniteDiff.GradientCache(v[1], cache1, Val{:central}) g = (dx, x) -> FiniteDiff.finite_difference_gradient!(dx, f, x, cache) cache1 .= Dual{ @@ -161,12 +161,12 @@ function num_hesvecgrad(g, x, v) end function auto_hesvecgrad!(dy, g, x, v, - cache2 = Dual{typeof(ForwardDiff.Tag(DeivVecTag(), eltype(x))), - eltype(x), 1, - }.(x, ForwardDiff.Partials.(tuple.(reshape(v, size(x))))), - cache3 = Dual{typeof(ForwardDiff.Tag(DeivVecTag(), eltype(x))), - eltype(x), 1, - }.(x, ForwardDiff.Partials.(tuple.(reshape(v, size(x)))))) + cache2 = Dual{typeof(ForwardDiff.Tag(DeivVecTag(), eltype(x))), + eltype(x), 1, + }.(x, ForwardDiff.Partials.(tuple.(reshape(v, size(x))))), + cache3 = Dual{typeof(ForwardDiff.Tag(DeivVecTag(), eltype(x))), + eltype(x), 1, + }.(x, ForwardDiff.Partials.(tuple.(reshape(v, size(x)))))) cache2 .= Dual{ get_tag(cache2), eltype(x), @@ -224,7 +224,7 @@ function Base.resize!(L::FwdModeAutoDiffVecProd, n::Integer) end function JacVec(f, u::AbstractArray, p = nothing, t = nothing; - autodiff = AutoForwardDiff(), tag = DeivVecTag(), kwargs...) + autodiff = AutoForwardDiff(), tag = DeivVecTag(), kwargs...) cache, vecprod, vecprod! = if autodiff isa AutoFiniteDiff cache1 = similar(u) cache2 = similar(u) @@ -256,7 +256,7 @@ function JacVec(f, u::AbstractArray, p = nothing, t = nothing; end function HesVec(f, u::AbstractArray, p = nothing, t = nothing; - autodiff = AutoForwardDiff(), tag = DeivVecTag(), kwargs...) + autodiff = AutoForwardDiff(), tag = DeivVecTag(), kwargs...) cache, vecprod, vecprod! = if autodiff isa AutoFiniteDiff cache1 = similar(u) cache2 = similar(u) @@ -296,7 +296,7 @@ function HesVec(f, u::AbstractArray, p = nothing, t = nothing; end function HesVecGrad(f, u::AbstractArray, p = nothing, t = nothing; - autodiff = AutoForwardDiff(), tag = DeivVecTag(), kwargs...) + autodiff = AutoForwardDiff(), tag = DeivVecTag(), kwargs...) cache, vecprod, vecprod! = if autodiff isa AutoFiniteDiff cache1 = similar(u) cache2 = similar(u) diff --git a/src/differentiation/vecjac_products.jl b/src/differentiation/vecjac_products.jl index 44842d55..87162012 100644 --- a/src/differentiation/vecjac_products.jl +++ b/src/differentiation/vecjac_products.jl @@ -1,5 +1,5 @@ function num_vecjac!(du, f, x, v, cache1 = similar(v), cache2 = similar(v); - compute_f0 = true) + compute_f0 = true) compute_f0 && (f(cache1, x)) T = eltype(x) # Should it be min? max? mean? @@ -49,7 +49,7 @@ L(x, v, p, t; VJP_input = w) # = df/dw * v ``` """ function VecJac(f, u::AbstractArray, p = nothing, t = nothing; - autodiff = AutoFiniteDiff(), kwargs...) + autodiff = AutoFiniteDiff(), kwargs...) L = _vecjac(f, u, autodiff) IIP, OOP = get_iip_oop(L) @@ -113,7 +113,7 @@ function get_iip_oop(::AutoDiffVJP{AD, IIP, OOP}) where {AD, IIP, OOP} end function update_coefficients(L::AutoDiffVJP{AD}, u, p, t; - VJP_input = nothing) where {AD <: AutoFiniteDiff} + VJP_input = nothing) where {AD <: AutoFiniteDiff} if !isnothing(VJP_input) @set! L.u = VJP_input end @@ -122,7 +122,7 @@ function update_coefficients(L::AutoDiffVJP{AD}, u, p, t; end function update_coefficients!(L::AutoDiffVJP{AD}, u, p, t; - VJP_input = nothing) where {AD <: AutoFiniteDiff} + VJP_input = nothing) where {AD <: AutoFiniteDiff} if !isnothing(VJP_input) copy!(L.u, VJP_input) end diff --git a/src/highlevel/coloring.jl b/src/highlevel/coloring.jl index 0ad7863f..3e57cf7a 100644 --- a/src/highlevel/coloring.jl +++ b/src/highlevel/coloring.jl @@ -33,7 +33,7 @@ end # Approximate Jacobian Sparsity Detection ## Right now we hardcode it to use `ForwardDiff` function (alg::ApproximateJacobianSparsity)(ad::AbstractSparseADType, f::F, x; fx = nothing, - kwargs...) where {F} + kwargs...) where {F} @unpack ntrials, rng = alg fx = fx === nothing ? f(x) : fx J = fill!(similar(fx, length(fx), length(x)), 0) @@ -48,7 +48,7 @@ function (alg::ApproximateJacobianSparsity)(ad::AbstractSparseADType, f::F, x; f end function (alg::ApproximateJacobianSparsity)(ad::AbstractSparseADType, f!::F, fx, x; - kwargs...) where {F} + kwargs...) where {F} @unpack ntrials, rng = alg cfg = ForwardDiff.JacobianConfig(f!, fx, x) J = fill!(similar(fx, length(fx), length(x)), 0) diff --git a/src/highlevel/common.jl b/src/highlevel/common.jl index 933c7b71..133eed58 100644 --- a/src/highlevel/common.jl +++ b/src/highlevel/common.jl @@ -86,7 +86,7 @@ on whether a reverse mode or forward mode or finite differences is used, the cor See Also: [SymbolicsSparsityDetection](@ref), [JacPrototypeSparsityDetection](@ref) """ function PrecomputedJacobianColorvec(; jac_prototype, partition_by_rows::Bool = false, - colorvec = missing, row_colorvec = missing, col_colorvec = missing) + colorvec = missing, row_colorvec = missing, col_colorvec = missing) if colorvec === missing @assert row_colorvec !== missing||col_colorvec !== missing "Either `colorvec` or `row_colorvec` and `col_colorvec` must be specified!" row_colorvec = row_colorvec === missing ? nothing : row_colorvec @@ -133,7 +133,7 @@ struct ApproximateJacobianSparsity{R <: AbstractRNG, end function ApproximateJacobianSparsity(; ntrials::Int = 3, - rng::AbstractRNG = Random.default_rng(), alg = GreedyD1Color()) + rng::AbstractRNG = Random.default_rng(), alg = GreedyD1Color()) return ApproximateJacobianSparsity(ntrials, rng, alg) end @@ -183,7 +183,7 @@ cases, use `sparse_jacobian_cache` once to generate the cache and use `sparse_ja with the same cache to compute the jacobian. """ function sparse_jacobian(ad::AbstractADType, sd::AbstractMaybeSparsityDetection, args...; - kwargs...) + kwargs...) cache = sparse_jacobian_cache(ad, sd, args...; kwargs...) J = init_jacobian(cache) return sparse_jacobian!(J, ad, cache, args...) @@ -197,7 +197,7 @@ Use the sparsity detection `cache` for computing the sparse Jacobian. This alloc Jacobian at every function call """ function sparse_jacobian(ad::AbstractADType, cache::AbstractMaybeSparseJacobianCache, - args...) + args...) J = init_jacobian(cache) return sparse_jacobian!(J, ad, cache, args...) end @@ -214,7 +214,7 @@ cases, use `sparse_jacobian_cache` once to generate the cache and use `sparse_ja with the same cache to compute the jacobian. """ function sparse_jacobian!(J::AbstractMatrix, ad::AbstractADType, - sd::AbstractMaybeSparsityDetection, args...; kwargs...) + sd::AbstractMaybeSparsityDetection, args...; kwargs...) cache = sparse_jacobian_cache(ad, sd, args...; kwargs...) return sparse_jacobian!(J, ad, cache, args...) end diff --git a/src/highlevel/finite_diff.jl b/src/highlevel/finite_diff.jl index b70fa56b..b9c955d7 100644 --- a/src/highlevel/finite_diff.jl +++ b/src/highlevel/finite_diff.jl @@ -7,7 +7,7 @@ struct FiniteDiffJacobianCache{CO, CA, J, FX, X} <: AbstractMaybeSparseJacobianC end function sparse_jacobian_cache(fd::Union{AutoSparseFiniteDiff, AutoFiniteDiff}, - sd::AbstractMaybeSparsityDetection, f::F, x; fx = nothing) where {F} + sd::AbstractMaybeSparsityDetection, f::F, x; fx = nothing) where {F} coloring_result = sd(fd, f, x) fx = fx === nothing ? similar(f(x)) : fx if coloring_result isa NoMatrixColoring @@ -22,7 +22,7 @@ function sparse_jacobian_cache(fd::Union{AutoSparseFiniteDiff, AutoFiniteDiff}, end function sparse_jacobian_cache(fd::Union{AutoSparseFiniteDiff, AutoFiniteDiff}, - sd::AbstractMaybeSparsityDetection, f!::F, fx, x) where {F} + sd::AbstractMaybeSparsityDetection, f!::F, fx, x) where {F} coloring_result = sd(fd, f!, fx, x) if coloring_result isa NoMatrixColoring cache = FiniteDiff.JacobianCache(x, fx) @@ -36,13 +36,13 @@ function sparse_jacobian_cache(fd::Union{AutoSparseFiniteDiff, AutoFiniteDiff}, end function sparse_jacobian!(J::AbstractMatrix, fd, cache::FiniteDiffJacobianCache, f::F, - x) where {F} + x) where {F} f!(y, x) = (y .= f(x)) return sparse_jacobian!(J, fd, cache, f!, cache.fx, x) end function sparse_jacobian!(J::AbstractMatrix, _, cache::FiniteDiffJacobianCache, f!::F, _, - x) where {F} + x) where {F} FiniteDiff.finite_difference_jacobian!(J, f!, x, cache.cache) return J end diff --git a/src/highlevel/forward_mode.jl b/src/highlevel/forward_mode.jl index 84c9ec12..f1dc6e2b 100644 --- a/src/highlevel/forward_mode.jl +++ b/src/highlevel/forward_mode.jl @@ -9,7 +9,7 @@ end struct SparseDiffToolsTag end function sparse_jacobian_cache(ad::Union{AutoSparseForwardDiff, AutoForwardDiff}, - sd::AbstractMaybeSparsityDetection, f::F, x; fx = nothing) where {F} + sd::AbstractMaybeSparsityDetection, f::F, x; fx = nothing) where {F} coloring_result = sd(ad, f, x) fx = fx === nothing ? similar(f(x)) : fx if coloring_result isa NoMatrixColoring @@ -25,7 +25,7 @@ function sparse_jacobian_cache(ad::Union{AutoSparseForwardDiff, AutoForwardDiff} end function sparse_jacobian_cache(ad::Union{AutoSparseForwardDiff, AutoForwardDiff}, - sd::AbstractMaybeSparsityDetection, f!::F, fx, x) where {F} + sd::AbstractMaybeSparsityDetection, f!::F, fx, x) where {F} coloring_result = sd(ad, f!, fx, x) if coloring_result isa NoMatrixColoring cache = ForwardDiff.JacobianConfig(f!, fx, x, __chunksize(ad, x), @@ -40,7 +40,7 @@ function sparse_jacobian_cache(ad::Union{AutoSparseForwardDiff, AutoForwardDiff} end function sparse_jacobian!(J::AbstractMatrix, _, cache::ForwardDiffJacobianCache, f::F, - x) where {F} + x) where {F} if cache.cache isa ForwardColorJacCache forwarddiff_color_jacobian(J, f, x, cache.cache) # Use Sparse ForwardDiff else @@ -50,7 +50,7 @@ function sparse_jacobian!(J::AbstractMatrix, _, cache::ForwardDiffJacobianCache, end function sparse_jacobian!(J::AbstractMatrix, _, cache::ForwardDiffJacobianCache, f!::F, fx, - x) where {F} + x) where {F} if cache.cache isa ForwardColorJacCache forwarddiff_color_jacobian!(J, f!, x, cache.cache) # Use Sparse ForwardDiff else diff --git a/src/highlevel/reverse_mode.jl b/src/highlevel/reverse_mode.jl index beb8f186..815a879c 100644 --- a/src/highlevel/reverse_mode.jl +++ b/src/highlevel/reverse_mode.jl @@ -8,7 +8,7 @@ struct ReverseModeJacobianCache{CO, CA, J, FX, X, I} <: AbstractMaybeSparseJacob end function sparse_jacobian_cache(ad::Union{AutoEnzyme, AbstractReverseMode}, - sd::AbstractMaybeSparsityDetection, f::F, x; fx = nothing) where {F} + sd::AbstractMaybeSparsityDetection, f::F, x; fx = nothing) where {F} fx = fx === nothing ? similar(f(x)) : fx coloring_result = sd(ad, f, x) jac_prototype = __getfield(coloring_result, Val(:jacobian_sparsity)) @@ -17,7 +17,7 @@ function sparse_jacobian_cache(ad::Union{AutoEnzyme, AbstractReverseMode}, end function sparse_jacobian_cache(ad::Union{AutoEnzyme, AbstractReverseMode}, - sd::AbstractMaybeSparsityDetection, f!::F, fx, x) where {F} + sd::AbstractMaybeSparsityDetection, f!::F, fx, x) where {F} coloring_result = sd(ad, f!, fx, x) jac_prototype = __getfield(coloring_result, Val(:jacobian_sparsity)) return ReverseModeJacobianCache(coloring_result, nothing, jac_prototype, fx, x, @@ -34,12 +34,12 @@ function sparse_jacobian!(J::AbstractMatrix, ad, cache::ReverseModeJacobianCache end function __sparse_jacobian_reverse_impl!(J::AbstractMatrix, ad, idx_vec, - cache::MatrixColoringResult, f::F, x) where {F} + cache::MatrixColoringResult, f::F, x) where {F} return __sparse_jacobian_reverse_impl!(J, ad, idx_vec, cache, f, nothing, x) end function __sparse_jacobian_reverse_impl!(J::AbstractMatrix, ad, idx_vec, - cache::MatrixColoringResult, f::F, fx, x) where {F} + cache::MatrixColoringResult, f::F, fx, x) where {F} # If `fx` is `nothing` then assume `f` is not in-place x_ = __maybe_copy_x(ad, x) fx_ = __maybe_copy_x(ad, fx) From 63fc8001768b6da76ebd3291c4a89d5d28351753 Mon Sep 17 00:00:00 2001 From: Avik Pal Date: Mon, 30 Oct 2023 12:18:49 -0400 Subject: [PATCH 2/5] Make things kind-of type stable when chunksize is not specified --- src/highlevel/common.jl | 9 ++++++--- src/highlevel/finite_diff.jl | 2 ++ src/highlevel/forward_mode.jl | 15 +++++++++++---- src/highlevel/reverse_mode.jl | 2 ++ 4 files changed, 21 insertions(+), 7 deletions(-) diff --git a/src/highlevel/common.jl b/src/highlevel/common.jl index 133eed58..8c8e3e51 100644 --- a/src/highlevel/common.jl +++ b/src/highlevel/common.jl @@ -186,7 +186,8 @@ function sparse_jacobian(ad::AbstractADType, sd::AbstractMaybeSparsityDetection, kwargs...) cache = sparse_jacobian_cache(ad, sd, args...; kwargs...) J = init_jacobian(cache) - return sparse_jacobian!(J, ad, cache, args...) + sparse_jacobian!(J, ad, cache, args...) + return J end """ @@ -199,7 +200,8 @@ Jacobian at every function call function sparse_jacobian(ad::AbstractADType, cache::AbstractMaybeSparseJacobianCache, args...) J = init_jacobian(cache) - return sparse_jacobian!(J, ad, cache, args...) + sparse_jacobian!(J, ad, cache, args...) + return J end """ @@ -216,7 +218,8 @@ with the same cache to compute the jacobian. function sparse_jacobian!(J::AbstractMatrix, ad::AbstractADType, sd::AbstractMaybeSparsityDetection, args...; kwargs...) cache = sparse_jacobian_cache(ad, sd, args...; kwargs...) - return sparse_jacobian!(J, ad, cache, args...) + sparse_jacobian!(J, ad, cache, args...) + return J end ## Internal diff --git a/src/highlevel/finite_diff.jl b/src/highlevel/finite_diff.jl index b9c955d7..31114ae0 100644 --- a/src/highlevel/finite_diff.jl +++ b/src/highlevel/finite_diff.jl @@ -6,6 +6,8 @@ struct FiniteDiffJacobianCache{CO, CA, J, FX, X} <: AbstractMaybeSparseJacobianC x::X end +__getfield(c::FiniteDiffJacobianCache, ::Val{:jac_prototype}) = c.jac_prototype + function sparse_jacobian_cache(fd::Union{AutoSparseFiniteDiff, AutoFiniteDiff}, sd::AbstractMaybeSparsityDetection, f::F, x; fx = nothing) where {F} coloring_result = sd(fd, f, x) diff --git a/src/highlevel/forward_mode.jl b/src/highlevel/forward_mode.jl index f1dc6e2b..47bafd77 100644 --- a/src/highlevel/forward_mode.jl +++ b/src/highlevel/forward_mode.jl @@ -6,15 +6,20 @@ struct ForwardDiffJacobianCache{CO, CA, J, FX, X} <: AbstractMaybeSparseJacobian x::X end +__getfield(c::ForwardDiffJacobianCache, ::Val{:jac_prototype}) = c.jac_prototype + struct SparseDiffToolsTag end +__standard_tag(::Nothing, x) = ForwardDiff.Tag(SparseDiffToolsTag(), eltype(x)) +__standard_tag(tag, _) = tag + function sparse_jacobian_cache(ad::Union{AutoSparseForwardDiff, AutoForwardDiff}, sd::AbstractMaybeSparsityDetection, f::F, x; fx = nothing) where {F} coloring_result = sd(ad, f, x) fx = fx === nothing ? similar(f(x)) : fx if coloring_result isa NoMatrixColoring cache = ForwardDiff.JacobianConfig(f, x, __chunksize(ad, x), - ifelse(ad.tag === nothing, SparseDiffToolsTag(), ad.tag)) + __standard_tag(ad.tag, x)) jac_prototype = nothing else cache = ForwardColorJacCache(f, x, __chunksize(ad); coloring_result.colorvec, @@ -29,7 +34,7 @@ function sparse_jacobian_cache(ad::Union{AutoSparseForwardDiff, AutoForwardDiff} coloring_result = sd(ad, f!, fx, x) if coloring_result isa NoMatrixColoring cache = ForwardDiff.JacobianConfig(f!, fx, x, __chunksize(ad, x), - ifelse(ad.tag === nothing, SparseDiffToolsTag(), ad.tag)) + __standard_tag(ad.tag, x)) jac_prototype = nothing else cache = ForwardColorJacCache(f!, x, __chunksize(ad); coloring_result.colorvec, @@ -44,7 +49,8 @@ function sparse_jacobian!(J::AbstractMatrix, _, cache::ForwardDiffJacobianCache, if cache.cache isa ForwardColorJacCache forwarddiff_color_jacobian(J, f, x, cache.cache) # Use Sparse ForwardDiff else - ForwardDiff.jacobian!(J, f, x, cache.cache) # Don't try to exploit sparsity + # Disable tag checking since we set the tag to our custom tag + ForwardDiff.jacobian!(J, f, x, cache.cache, Val(false)) # Don't try to exploit sparsity end return J end @@ -54,7 +60,8 @@ function sparse_jacobian!(J::AbstractMatrix, _, cache::ForwardDiffJacobianCache, if cache.cache isa ForwardColorJacCache forwarddiff_color_jacobian!(J, f!, x, cache.cache) # Use Sparse ForwardDiff else - ForwardDiff.jacobian!(J, f!, fx, x, cache.cache) # Don't try to exploit sparsity + # Disable tag checking since we set the tag to our custom tag + ForwardDiff.jacobian!(J, f!, fx, x, cache.cache, Val(false)) # Don't try to exploit sparsity end return J end diff --git a/src/highlevel/reverse_mode.jl b/src/highlevel/reverse_mode.jl index 815a879c..b24c42dc 100644 --- a/src/highlevel/reverse_mode.jl +++ b/src/highlevel/reverse_mode.jl @@ -7,6 +7,8 @@ struct ReverseModeJacobianCache{CO, CA, J, FX, X, I} <: AbstractMaybeSparseJacob idx_vec::I end +__getfield(c::ReverseModeJacobianCache, ::Val{:jac_prototype}) = c.jac_prototype + function sparse_jacobian_cache(ad::Union{AutoEnzyme, AbstractReverseMode}, sd::AbstractMaybeSparsityDetection, f::F, x; fx = nothing) where {F} fx = fx === nothing ? similar(f(x)) : fx From a7666fa8b676d29c13e46418f77f30a5148ce64c Mon Sep 17 00:00:00 2001 From: Avik Pal Date: Mon, 30 Oct 2023 13:19:13 -0400 Subject: [PATCH 3/5] Bump version --- Project.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Project.toml b/Project.toml index f3f4752a..123b98a2 100644 --- a/Project.toml +++ b/Project.toml @@ -1,7 +1,7 @@ name = "SparseDiffTools" uuid = "47a9eef4-7e08-11e9-0b38-333d64bd3804" authors = ["Pankaj Mishra ", "Chris Rackauckas "] -version = "2.9.1" +version = "2.9.2" [deps] ADTypes = "47edcb42-4c32-4615-8424-f2b9edc5f35b" From d6fae4e8da2a22e6c549c0eb81fda4c58c4c2af8 Mon Sep 17 00:00:00 2001 From: Avik Pal Date: Tue, 31 Oct 2023 10:28:46 -0400 Subject: [PATCH 4/5] Enable tag checking --- src/highlevel/forward_mode.jl | 27 ++++++++++++++++----------- 1 file changed, 16 insertions(+), 11 deletions(-) diff --git a/src/highlevel/forward_mode.jl b/src/highlevel/forward_mode.jl index 47bafd77..a319839f 100644 --- a/src/highlevel/forward_mode.jl +++ b/src/highlevel/forward_mode.jl @@ -10,20 +10,26 @@ __getfield(c::ForwardDiffJacobianCache, ::Val{:jac_prototype}) = c.jac_prototype struct SparseDiffToolsTag end +function ForwardDiff.checktag(::Type{<:ForwardDiff.Tag{<:SparseDiffToolsTag, <:T}}, f::F, + x::AbstractArray{T}) where {T, F} + return true +end + __standard_tag(::Nothing, x) = ForwardDiff.Tag(SparseDiffToolsTag(), eltype(x)) -__standard_tag(tag, _) = tag +__standard_tag(tag, x) = ForwardDiff.Tag(tag, eltype(x)) function sparse_jacobian_cache(ad::Union{AutoSparseForwardDiff, AutoForwardDiff}, sd::AbstractMaybeSparsityDetection, f::F, x; fx = nothing) where {F} coloring_result = sd(ad, f, x) fx = fx === nothing ? similar(f(x)) : fx + tag = __standard_tag(ad.tag, x) if coloring_result isa NoMatrixColoring - cache = ForwardDiff.JacobianConfig(f, x, __chunksize(ad, x), - __standard_tag(ad.tag, x)) + cache = ForwardDiff.JacobianConfig(f, x, __chunksize(ad, x), tag) jac_prototype = nothing else + # Colored ForwardDiff passes `tag` directly into Dual so we need the `typeof` cache = ForwardColorJacCache(f, x, __chunksize(ad); coloring_result.colorvec, - dx = fx, sparsity = coloring_result.jacobian_sparsity, ad.tag) + dx = fx, sparsity = coloring_result.jacobian_sparsity, tag = typeof(tag)) jac_prototype = coloring_result.jacobian_sparsity end return ForwardDiffJacobianCache(coloring_result, cache, jac_prototype, fx, x) @@ -32,13 +38,14 @@ end function sparse_jacobian_cache(ad::Union{AutoSparseForwardDiff, AutoForwardDiff}, sd::AbstractMaybeSparsityDetection, f!::F, fx, x) where {F} coloring_result = sd(ad, f!, fx, x) + tag = __standard_tag(ad.tag, x) if coloring_result isa NoMatrixColoring - cache = ForwardDiff.JacobianConfig(f!, fx, x, __chunksize(ad, x), - __standard_tag(ad.tag, x)) + cache = ForwardDiff.JacobianConfig(f!, fx, x, __chunksize(ad, x), tag) jac_prototype = nothing else + # Colored ForwardDiff passes `tag` directly into Dual so we need the `typeof` cache = ForwardColorJacCache(f!, x, __chunksize(ad); coloring_result.colorvec, - dx = fx, sparsity = coloring_result.jacobian_sparsity, ad.tag) + dx = fx, sparsity = coloring_result.jacobian_sparsity, tag = typeof(tag)) jac_prototype = coloring_result.jacobian_sparsity end return ForwardDiffJacobianCache(coloring_result, cache, jac_prototype, fx, x) @@ -49,8 +56,7 @@ function sparse_jacobian!(J::AbstractMatrix, _, cache::ForwardDiffJacobianCache, if cache.cache isa ForwardColorJacCache forwarddiff_color_jacobian(J, f, x, cache.cache) # Use Sparse ForwardDiff else - # Disable tag checking since we set the tag to our custom tag - ForwardDiff.jacobian!(J, f, x, cache.cache, Val(false)) # Don't try to exploit sparsity + ForwardDiff.jacobian!(J, f, x, cache.cache) # Don't try to exploit sparsity end return J end @@ -60,8 +66,7 @@ function sparse_jacobian!(J::AbstractMatrix, _, cache::ForwardDiffJacobianCache, if cache.cache isa ForwardColorJacCache forwarddiff_color_jacobian!(J, f!, x, cache.cache) # Use Sparse ForwardDiff else - # Disable tag checking since we set the tag to our custom tag - ForwardDiff.jacobian!(J, f!, fx, x, cache.cache, Val(false)) # Don't try to exploit sparsity + ForwardDiff.jacobian!(J, f!, fx, x, cache.cache) # Don't try to exploit sparsity end return J end From 41033f4af619e67ac186a88aa05a8f02a277c449 Mon Sep 17 00:00:00 2001 From: Avik Pal Date: Wed, 1 Nov 2023 10:53:24 -0400 Subject: [PATCH 5/5] don't rewrap a forwarddiff tag --- src/highlevel/forward_mode.jl | 1 + 1 file changed, 1 insertion(+) diff --git a/src/highlevel/forward_mode.jl b/src/highlevel/forward_mode.jl index a319839f..2ae378d6 100644 --- a/src/highlevel/forward_mode.jl +++ b/src/highlevel/forward_mode.jl @@ -16,6 +16,7 @@ function ForwardDiff.checktag(::Type{<:ForwardDiff.Tag{<:SparseDiffToolsTag, <:T end __standard_tag(::Nothing, x) = ForwardDiff.Tag(SparseDiffToolsTag(), eltype(x)) +__standard_tag(tag::ForwardDiff.Tag, _) = tag __standard_tag(tag, x) = ForwardDiff.Tag(tag, eltype(x)) function sparse_jacobian_cache(ad::Union{AutoSparseForwardDiff, AutoForwardDiff},