You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: docs/src/faq.md
+7-22Lines changed: 7 additions & 22 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -18,22 +18,22 @@ You can override the default with the `conditions_x_backend` and `conditions_y_b
18
18
19
19
### Arrays
20
20
21
-
Functions that eat or spit out arbitrary arrays are supported, as long as the forward mapping _and_ conditions return arrays of the same size.
21
+
Functions that eat or spit out arbitrary vectors are supported, as long as the forward mapping _and_ conditions return vectors of the same size.
22
22
23
-
If you deal with small arrays (say, less than 100 elements), consider using [StaticArrays.jl](https://github.com/JuliaArrays/StaticArrays.jl) for increased performance.
23
+
If you deal with small vectors (say, less than 100 elements), consider using [StaticArrays.jl](https://github.com/JuliaArrays/StaticArrays.jl) for increased performance.
24
24
25
25
### Scalars
26
26
27
27
Functions that eat or spit out a single number are not supported.
28
-
The forward mapping _and_ conditions need arrays: instead of returning `val` you should return `[val]` (a 1-element `Vector`).
28
+
The forward mapping _and_ conditions need vectors: instead of returning `val` you should return `[val]` (a 1-element `Vector`).
29
29
Or better yet, wrap it in a static vector: `SVector(val)`.
30
30
31
-
### Sparse arrays
31
+
### Sparse vectors
32
32
33
33
!!! danger "Danger"
34
-
Sparse arrays are not supported and might give incorrect values or `NaN`s!
34
+
Sparse vectors are not supported and might give incorrect values or `NaN`s!
35
35
36
-
With ForwardDiff.jl, differentiation of sparse arrays will often give wrong results due to [sparsity pattern cancellation](https://github.com/JuliaDiff/ForwardDiff.jl/issues/658).
36
+
With ForwardDiff.jl, differentiation of sparse vectors will often give wrong results due to [sparsity pattern cancellation](https://github.com/JuliaDiff/ForwardDiff.jl/issues/658).
37
37
That is why we do not test behavior for sparse inputs.
38
38
39
39
## Number of inputs and outputs
@@ -51,7 +51,7 @@ We now detail each of these options.
51
51
52
52
### Multiple inputs or outputs | Derivatives needed
53
53
54
-
Say your forward mapping takes multiple input arrays and returns multiple output arrays, such that you want derivatives for all of them.
54
+
Say your forward mapping takes multiple inputs and returns multiple outputs, such that you want derivatives for all of them.
55
55
56
56
The trick is to leverage [ComponentArrays.jl](https://github.com/jonniedie/ComponentArrays.jl) to wrap all the inputs inside a single a `ComponentVector`, and do the same for all the outputs.
57
57
See the examples for a demonstration.
@@ -92,21 +92,6 @@ This is mainly useful when the solution procedure creates objects such as Jacobi
92
92
In that case, you may want to write the conditions differentiation rules yourself.
93
93
A more advanced application is given by [DifferentiableFrankWolfe.jl](https://github.com/gdalle/DifferentiableFrankWolfe.jl).
94
94
95
-
## Linear system
96
-
97
-
### Lazy or dense
98
-
99
-
Usually, dense Jacobians are more efficient in small dimension, while lazy operators become necessary in high dimension.
100
-
This choice is made via the `lazy` type parameter of [`ImplicitFunction`](@ref), with `lazy = true` being the default.
101
-
102
-
### Picking a solver
103
-
104
-
The right linear solver to use depends on the Jacobian representation.
105
-
You can usually stick to the default settings:
106
-
107
-
- the direct solver `\` for dense Jacobians
108
-
- an iterative solver from [Krylov.jl](https://github.com/JuliaSmoothOptimizers/Krylov.jl) for lazy operators
Copy file name to clipboardExpand all lines: src/implicit_function.jl
+81-35Lines changed: 81 additions & 35 deletions
Original file line number
Diff line number
Diff line change
@@ -1,11 +1,31 @@
1
-
struct DefaultLinearSolver end
1
+
"""
2
+
KrylovLinearSolver
3
+
4
+
Callable object that can solve linear systems `As = b` and `AS = b` in the same way that `\`.
5
+
Uses an iterative solver from [Krylov.jl](https://github.com/JuliaSmoothOptimizers/Krylov.jl) under the hood.
6
+
7
+
# Note
2
8
3
-
function (::DefaultLinearSolver)(A, b::AbstractVector)
9
+
This name is not exported, and thus not part of the public API, but it is used in the [`ImplicitFunction`](@ref) constructors.
10
+
"""
11
+
struct KrylovLinearSolver end
12
+
13
+
"""
14
+
(::KylovLinearSolver)(A, b::AbstractVector)
15
+
16
+
Solve a linear system with a single right-hand side.
17
+
"""
18
+
function (::KrylovLinearSolver)(A, b::AbstractVector)
4
19
x, stats =gmres(A, b)
5
20
return x
6
21
end
7
22
8
-
function (::DefaultLinearSolver)(A, B::AbstractMatrix)
23
+
"""
24
+
(::KrylovLinearSolver)(A, B::AbstractMatrix)
25
+
26
+
Solve a linear system with multiple right-hand sides.
27
+
"""
28
+
function (::KrylovLinearSolver)(A, B::AbstractMatrix)
9
29
# X, stats = block_gmres(A, B) # https://github.com/JuliaSmoothOptimizers/Krylov.jl/issues/854
10
30
X =mapreduce(hcat, eachcol(B)) do b
11
31
first(gmres(A, b))
@@ -25,44 +45,28 @@ When a derivative is queried, the Jacobian of `y` is computed using the implicit
25
45
26
46
This requires solving a linear system `A * J = -B` where `A = ∂c/∂y`, `B = ∂c/∂x` and `J = ∂y/∂x`.
27
47
48
+
# Type parameters
49
+
50
+
- `lazy::Bool`: whether to represent `A` and `B` with a `LinearOperator` from [LinearOperators.jl](https://github.com/JuliaSmoothOptimizers/LinearOperators.jl) (`lazy = true`) or a dense Jacobian matrix (`lazy = false`)
51
+
52
+
Usually, dense Jacobians are more efficient in small dimension, while lazy operators become necessary in high dimension.
53
+
The value of `lazy` must be chosen together with the `linear_solver`, see below.
54
+
28
55
# Fields
29
56
30
57
- `forward`: a callable computing `y(x)`, does not need to be compatible with automatic differentiation
31
58
- `conditions`: a callable computing `c(x, y)`, must be compatible with automatic differentiation
32
-
- `linear_solver`: a callable to solve the linear system `A * J = -B`
59
+
- `linear_solver`: a callable to solve the linear system
33
60
- `conditions_x_backend`: defines how the conditions will be differentiated with respect to the first argument `x`
34
61
- `conditions_y_backend`: defines how the conditions will be differentiated with respect to the second argument `y`
35
62
36
-
# Type parameters
37
-
38
-
- `lazy`: whether to use a `LinearOperator` from [LinearOperators.jl](https://github.com/JuliaSmoothOptimizers/LinearOperators.jl) (`lazy = true`) or a dense Jacobian matrix (`lazy = false`) for `A` and `B`
- `linear_solver`: the direct solver `\` for dense Jacobians, or an iterative solver from [Krylov.jl](https://github.com/JuliaSmoothOptimizers/Krylov.jl) for lazy operators
56
-
- `conditions_x_backend = nothing`
57
-
- `conditions_y_backend = nothing`
58
-
59
63
# Function signatures
60
64
61
65
There are two possible signatures for `forward` and `conditions`, which must be consistent with one another:
Constructor for an [`ImplicitFunction`](@ref) which picks the `lazy` parameter automatically based on the `linear_solver`, using the following heuristic:
0 commit comments