API reference

Public

ImplicitDifferentiation.ImplicitFunctionType
ImplicitFunction{lazy}

Wrapper for an implicit function defined by a forward mapping y and a set of conditions c.

An ImplicitFunction object behaves like a function, and every call is differentiable with respect to the first argument x. When a derivative is queried, the Jacobian of y is computed using the implicit function theorem:

∂/∂y c(x, y(x)) * ∂/∂x y(x) = -∂/∂x c(x, y(x))

This requires solving a linear system A * J = -B where A = ∂c/∂y, B = ∂c/∂x and J = ∂y/∂x.

Type parameters

  • lazy::Bool: whether to represent A and B with a LinearOperator from LinearOperators.jl (lazy = true) or a dense Jacobian matrix (lazy = false)

Usually, dense Jacobians are more efficient in small dimension, while lazy operators become necessary in high dimension. The value of lazy must be chosen together with the linear_solver, see below.

Fields

  • forward: a callable computing y(x), does not need to be compatible with automatic differentiation
  • conditions: a callable computing c(x, y), must be compatible with automatic differentiation
  • linear_solver: a callable to solve the linear system
  • conditions_x_backend: defines how the conditions will be differentiated with respect to the first argument x
  • conditions_y_backend: defines how the conditions will be differentiated with respect to the second argument y

Function signatures

There are two possible signatures for forward and conditions, which must be consistent with one another:

standardbyproduct
forward(x, args...; kwargs...) = yconditions(x, y, args...; kwargs...) = c
forward(x, args...; kwargs...) = (y, z)conditions(x, y, z, args...; kwargs...) = c

In both cases, x, y and c must be AbstractVectors, with length(y) = length(c). In the second case, the byproduct z can be an arbitrary object generated by forward. The positional arguments args... and keyword arguments kwargs... must be the same for both forward and conditions.

The byproduct z and the other positional arguments args... beyond x are considered constant for differentiation purposes.

Linear solver

The provided linear_solver objects needs to be callable, with two methods:

  • (A, b::AbstractVector) -> s::AbstractVector such that A * s = b
  • (A, B::AbstractVector) -> S::AbstractMatrix such that A * S = B

It can be either a direct solver (like \) or an iterative one (like KrylovLinearSolver). Typically, direct solvers work best with dense Jacobians (lazy = false) while iterative solvers work best with operators (lazy = true).

Condition backends

The provided conditions_x_backend and conditions_y_backend can be either:

  • an object subtyping AbstractADType from ADTypes.jl;
  • nothing, in which case the outer backend (the one differentiating through the ImplicitFunction) is used.
source
ImplicitDifferentiation.ImplicitFunctionMethod
(implicit::ImplicitFunction)(x::AbstractVector, args...; kwargs...)

Return implicit.forward(x, args...; kwargs...), which can be either an AbstractVector y or a tuple (y, z).

This call makes y differentiable with respect to x.

source
ImplicitDifferentiation.ImplicitFunctionMethod
ImplicitFunction(
    forward, conditions;
    linear_solver=KrylovLinearSolver(),
    conditions_x_backend=nothing,
    conditions_x_backend=nothing,
)

Constructor for an ImplicitFunction which picks the lazy parameter automatically based on the linear_solver, using the following heuristic: lazy = linear_solver != \.

source
ImplicitDifferentiation.ImplicitFunctionMethod
ImplicitFunction{lazy}(
    forward, conditions;
    linear_solver=lazy ? KrylovLinearSolver() : \,
    conditions_x_backend=nothing,
    conditions_x_backend=nothing,
)

Constructor for an ImplicitFunction which picks the linear_solver automatically based on the lazy parameter.

source

Internals