echidna_optim/lib.rs
1//! Optimization solvers with automatic differentiation support, plus implicit
2//! differentiation tools for differentiating through fixed-point equations.
3//!
4//! This crate depends on [`echidna`] with the `bytecode` feature enabled,
5//! giving it access to bytecode tapes, forward-over-reverse Hessians, and
6//! sparse derivative machinery.
7//!
8//! # Solvers
9//!
10//! Three unconstrained optimizers, all operating on a bytecode-tape
11//! [`Objective`]:
12//!
13//! - **L-BFGS** ([`lbfgs`]) — two-loop recursion limited-memory quasi-Newton.
14//! Low per-iteration cost; the default choice for smooth, large-scale problems.
15//! - **Newton** ([`newton`]) — exact Hessian solved by LU with partial
16//! pivoting, falling back to steepest descent on indefinite Hessians.
17//! Quadratic convergence near the solution; practical when `n` is moderate.
18//! - **Trust-region** ([`trust_region`]) — Steihaug-Toint conjugate-gradient
19//! subproblem. Robust on indefinite or ill-conditioned Hessians.
20//!
21//! # Line search
22//!
23//! All solvers use **Armijo backtracking** ([`ArmijoParams`]) to enforce
24//! sufficient decrease along the search direction.
25//!
26//! # Implicit differentiation
27//!
28//! Differentiate through solutions of `F(z, x) = 0` via the Implicit Function
29//! Theorem without unrolling the solver:
30//!
31//! - [`implicit_tangent`] — tangent (forward) mode: `dz/dx · v`
32//! - [`implicit_adjoint`] — adjoint (reverse) mode: `(dz/dx)^T · w`
33//! - [`implicit_jacobian`] — full Jacobian `dz/dx`
34//! - [`implicit_hvp`] — Hessian-vector product of a loss composed with the
35//! implicit solution
36//! - [`implicit_hessian`] — full Hessian of a loss composed with the implicit
37//! solution
38//!
39//! # Piggyback differentiation
40//!
41//! Differentiate through fixed-point iterations `z = G(z, x)` by
42//! interleaving derivative accumulation with the primal iteration:
43//!
44//! - [`piggyback_tangent_solve`] — tangent mode (forward)
45//! - [`piggyback_adjoint_solve`] — adjoint mode (reverse)
46//! - [`piggyback_forward_adjoint_solve`] — interleaved forward-adjoint for
47//! second-order derivatives
48//! - [`piggyback_tangent_step`] / [`piggyback_tangent_step_with_buf`] —
49//! single-step building blocks for custom loops
50//!
51//! # Sparse implicit differentiation
52//!
53//! With the **`sparse-implicit`** feature, [`sparse_implicit`] exploits
54//! structural sparsity in `F_z` for efficient implicit differentiation via
55//! `faer` sparse LU factorization. See [`SparseImplicitContext`],
56//! [`implicit_tangent_sparse`], [`implicit_adjoint_sparse`], and
57//! [`implicit_jacobian_sparse`].
58
59mod convergence;
60pub mod implicit;
61mod linalg;
62pub mod line_search;
63pub mod objective;
64pub mod piggyback;
65pub mod result;
66pub mod solvers;
67
68#[cfg(feature = "sparse-implicit")]
69pub mod sparse_implicit;
70
71pub use convergence::ConvergenceParams;
72pub use implicit::{
73 implicit_adjoint, implicit_hessian, implicit_hvp, implicit_jacobian, implicit_tangent,
74 ImplicitError,
75};
76
77pub use line_search::ArmijoParams;
78pub use objective::{Objective, TapeObjective};
79pub use piggyback::{
80 piggyback_adjoint_solve, piggyback_forward_adjoint_solve, piggyback_tangent_solve,
81 piggyback_tangent_step, piggyback_tangent_step_with_buf, PiggybackError,
82};
83pub use result::{
84 LbfgsDiagnostics, NewtonDiagnostics, OptimResult, SolverDiagnostics, TerminationReason,
85 TrustRegionDiagnostics,
86};
87pub use solvers::lbfgs::{lbfgs, LbfgsConfig};
88pub use solvers::newton::{newton, NewtonConfig};
89pub use solvers::trust_region::{trust_region, TrustRegionConfig};
90#[cfg(feature = "sparse-implicit")]
91pub use sparse_implicit::{
92 implicit_adjoint_sparse, implicit_jacobian_sparse, implicit_tangent_sparse,
93 SparseImplicitContext, SparseImplicitError,
94};
95
96/// Compile and run the README examples as doctests.
97#[cfg(doctest)]
98#[doc = include_str!("../README.md")]
99struct ReadmeDoctests;