Implicit Backward Guide
This guide explains the package gradient path through equilibrium solves, what
implicit_adjoint_solve computes, and the scope of the public engine.
The backward construction follows the implicit-function treatment in the Deep
Implicit Layers tutorial [3] and
the adjoint formulation used for deep equilibrium models
[4].
Forward Equation
Every DEQ-style layer solves
The damped solver actually iterates
At convergence, \(T_\alpha(z^\star)=z^\star\), so the fixed point is unchanged by damping.
Differentiating The Fixed Point
Let a loss \(L(z^\star)\) depend on the equilibrium. The implicit function theorem gives
For reverse mode, solve the adjoint system
Then
For the damped transition \(T_\alpha\), the adjoint matrix becomes
Three Gradient Modes
SolverConfig.backward_mode selects the gradient estimator independently of
the forward solver:
| Mode | Forward graph | Backward calculation |
|---|---|---|
"unrolled" |
retains differentiable finite solver operations | ordinary reverse differentiation through the retained trajectory |
"implicit" |
solves under no_grad |
custom backward solves \((I-J_{T_\alpha}^\top)u=g\) and applies the adjoint to tracked parameters and inputs |
"phantom" |
solves under no_grad |
differentiates through phantom_steps damped transitions from the detached numerical state |
The exact implicit path is active in solve_equilibrium; it is not only a
diagnostic helper. Package layers pass their trainable parameters through
params and differentiable non-state inputs through tensors, then the custom
backward returns the corresponding sensitivities.
from silva_networks import SolverConfig
config = SolverConfig(
solver="anderson",
max_iter=30,
tol=1e-5,
backward_mode="implicit",
backward_solver="gmres",
backward_max_iter=40,
backward_tol=1e-7,
)
After loss.backward(), the solver result records backward_solver,
backward_iterations, backward_residual, and backward_converged in
result.info. Those values describe the linear adjoint solve and should be
reported separately from the forward fixed-point residual.
When To Use implicit_adjoint_solve
Use implicit_adjoint_solve when you need the adjoint vector
for diagnostics or a manual implicit-gradient experiment.
import torch
from silva_networks import implicit_adjoint_solve
z_star = torch.randn(4)
grad_output = torch.ones_like(z_star)
def transition(z):
return torch.tanh(0.4 * z)
adjoint = implicit_adjoint_solve(
transition,
z_star,
grad_output,
alpha=0.7,
max_iter=30,
tol=1e-6,
)
print(adjoint.x, adjoint.residuals)
The helper uses VJP-backed GMRES [13] and does not materialize the full Jacobian.
What Implicit Mode Executes
The custom backward follows these steps:
| Step | Responsibility |
|---|---|
| Forward | Solve \(z^\star=f_\theta(z^\star,x)\) without storing the whole trajectory |
| Backward | Recompute \(f_\theta(z^\star,x)\) under grad tracking |
| Linear solve | Solve \((I-J_f^\top)u=g\) with GMRES, Anderson, or Broyden |
| Parameter grads | Call torch.autograd.grad(f_theta, parameters, grad_outputs=u) |
| Input grads | Call torch.autograd.grad(f_theta, x, grad_outputs=u) |
The implementation uses the damped transition Jacobian, so the gradient passed to transition parameters carries the corresponding factor \(\alpha\). The state can be a tensor or a packed tuple/list; packed multi-state systems are treated as one coupled vector during both solves.
Practical Guidance
| Use case | Recommended path |
|---|---|
| Small, shallow validation where trajectory memory is acceptable | Use backward_mode="unrolled" |
| Equilibrium training with a matrix-free exact adjoint | Use backward_mode="implicit" and inspect backward residuals |
| Short approximate gradient from the solved state | Use backward_mode="phantom" and report steps/tau |
| Comparing solver residuals | Use return_result=True and inspect SolverResult |
| Checking implicit-gradient conditioning | Use implicit_adjoint_solve and GMRES residuals |
| Proving stability | Use stability_report and spectral radius diagnostics |
Tensor Contract and Sources
The forward transition, its state input, and its output must have identical shape, dtype, and device. The adjoint right-hand side \(g\), solution \(u\), and Jacobian-vector products use that same state contract.
See Solvers for every configuration field and Equilibrium and Implicit Layers for the implicit-function and DEQ sources. GMRES is listed under Solvers and Linear Algebra.
Where to Go Next
| Question | Page |
|---|---|
| Where is implicit differentiation derived? | Mathematical Foundations |
| Which solver options control the backward system? | Solvers API |
| Can I run a minimal implicit-gradient notebook? | Implicit Autodiff Notebook |