Skip to content

Commit 3b3bf9b

Browse files
committed
Use multiple forward diff trials to generate approximate Jacobian sparsity pattern
1 parent 1eb7252 commit 3b3bf9b

File tree

5 files changed

+56
-4
lines changed

5 files changed

+56
-4
lines changed

Project.toml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
name = "SparseDiffTools"
22
uuid = "47a9eef4-7e08-11e9-0b38-333d64bd3804"
33
authors = ["Pankaj Mishra <pankajmishra1511@gmail.com>", "Chris Rackauckas <contact@chrisrackauckas.com>"]
4-
version = "2.6.0"
4+
version = "2.7.0"
55

66
[deps]
77
ADTypes = "47edcb42-4c32-4615-8424-f2b9edc5f35b"
@@ -14,6 +14,7 @@ ForwardDiff = "f6369f11-7733-5829-9624-2563aa707210"
1414
Graphs = "86223c79-3864-5bf0-83f7-82e725a168b6"
1515
LinearAlgebra = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e"
1616
PackageExtensionCompat = "65ce6f38-6b18-4e1d-a461-8949797d7930"
17+
Random = "9a3f8284-a2c9-5f02-9a11-845980a1fd5c"
1718
Reexport = "189a3867-3050-52da-a836-e630ba90ab69"
1819
SciMLOperators = "c0aeaf25-5076-4817-a8d5-81caf7dfa961"
1920
Setfield = "efcf1570-3423-57d1-acb7-fd33fddbac46"

src/SparseDiffTools.jl

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ using ArrayInterface, SparseArrays
1717
import ArrayInterface: matrix_colors
1818
import StaticArrays
1919
# Others
20-
using SciMLOperators, LinearAlgebra
20+
using SciMLOperators, LinearAlgebra, Random
2121
import DataStructures: DisjointSets, find_root!, union!
2222
import SciMLOperators: update_coefficients, update_coefficients!
2323
import Setfield: @set!
@@ -89,7 +89,7 @@ export update_coefficients, update_coefficients!, value!
8989
export AutoSparseEnzyme
9090

9191
export NoSparsityDetection, SymbolicsSparsityDetection, JacPrototypeSparsityDetection,
92-
PrecomputedJacobianColorvec, AutoSparsityDetection
92+
PrecomputedJacobianColorvec, ApproximateJacobianSparsity, AutoSparsityDetection
9393
export sparse_jacobian, sparse_jacobian_cache, sparse_jacobian!
9494
export init_jacobian
9595

src/highlevel/coloring.jl

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,5 +30,31 @@ function (alg::PrecomputedJacobianColorvec)(ad::AbstractSparseADType, args...; k
3030
return MatrixColoringResult(colorvec, J, nz_rows, nz_cols)
3131
end
3232

33+
# Approximate Jacobian Sparsity Detection
34+
## Right now we hardcode it to use `ForwardDiff`
35+
function (alg::ApproximateJacobianSparsity)(ad::AbstractSparseADType, f, x; kwargs...)
36+
@unpack ntrials, rng = alg
37+
cfg = ForwardDiff.JacobianConfig(f, x)
38+
J = sum(1:ntrials) do _
39+
local x_ = similar(x)
40+
rand!(rng, x_)
41+
abs.(ForwardDiff.jacobian(f, x_, cfg))
42+
end
43+
return (JacPrototypeSparsityDetection(; jac_prototype = sparse(J), alg.alg))(ad, f, x;
44+
kwargs...)
45+
end
46+
47+
function (alg::ApproximateJacobianSparsity)(ad::AbstractSparseADType, f!, fx, x; kwargs...)
48+
@unpack ntrials, rng = alg
49+
cfg = ForwardDiff.JacobianConfig(f!, fx, x)
50+
J = sum(1:ntrials) do _
51+
local x_ = similar(x)
52+
rand!(rng, x_)
53+
abs.(ForwardDiff.jacobian(f!, fx, x_, cfg))
54+
end
55+
return (JacPrototypeSparsityDetection(; jac_prototype = sparse(J), alg.alg))(ad, f!, fx,
56+
x; kwargs...)
57+
end
58+
3359
# TODO: Heuristics to decide whether to use Sparse Differentiation or not
3460
# Simple Idea: Check min(max(colorvec_cols), max(colorvec_rows))

src/highlevel/common.jl

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,31 @@ function _get_colorvec(alg::PrecomputedJacobianColorvec, ::AbstractReverseMode)
112112
return cvec
113113
end
114114

115+
"""
116+
ApproximateJacobianSparsity(; ntrials = 5, rng = Random.default_rng(),
117+
alg = GreedyD1Color())
118+
119+
Use `ntrials` random vectors to compute the sparsity pattern of the Jacobian. This is an
120+
approximate method and the sparsity pattern may not be exact.
121+
122+
## Keyword Arguments
123+
124+
- `ntrials`: The number of random vectors to use for computing the sparsity pattern
125+
- `rng`: The random number generator used for generating the random vectors
126+
- `alg`: The algorithm used for computing the matrix colors
127+
"""
128+
struct ApproximateJacobianSparsity{R <: AbstractRNG,
129+
A <: ArrayInterface.ColoringAlgorithm} <: AbstractSparsityDetection
130+
ntrials::Int
131+
rng::R
132+
alg::A
133+
end
134+
135+
function ApproximateJacobianSparsity(; ntrials::Int = 3,
136+
rng::AbstractRNG = Random.default_rng(), alg = GreedyD1Color())
137+
return ApproximateJacobianSparsity(ntrials, rng, alg)
138+
end
139+
115140
# No one should be using this currently
116141
Base.@kwdef struct AutoSparsityDetection{A <: ArrayInterface.ColoringAlgorithm} <:
117142
AbstractSparsityDetection

test/test_sparse_jacobian.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ row_colorvec = SparseDiffTools.matrix_colors(J_sparsity; partition_by_rows = tru
3030
col_colorvec = SparseDiffTools.matrix_colors(J_sparsity; partition_by_rows = false)
3131

3232
SPARSITY_DETECTION_ALGS = [JacPrototypeSparsityDetection(; jac_prototype = J_sparsity),
33-
SymbolicsSparsityDetection(), NoSparsityDetection(),
33+
SymbolicsSparsityDetection(), NoSparsityDetection(), ApproximateJacobianSparsity(),
3434
PrecomputedJacobianColorvec(; jac_prototype = J_sparsity, row_colorvec, col_colorvec)]
3535

3636
@testset "High-Level API" begin

0 commit comments

Comments
 (0)