autodiff/
lib.rs

1//! Automatic differentiation for Rust.
2//!
3//! **Part of the [postbox workspace](../index.html)**
4//!
5//! This crate provides tools for computing derivatives automatically:
6//!
7//! - **Forward-mode AD**: Using dual numbers ([`Dual`]) for
8//!   single-variable functions
9//! - **Multivariable gradients**: Using multi-component dual numbers
10//!   ([`MultiDual`])
11//! - **Reverse-mode AD**: Using tape-based backpropagation ([`Tape`])
12//!
13//! # Single-variable differentiation
14//!
15//! Use [`Dual`] for computing derivatives of functions f: ℝ → ℝ:
16//!
17//! ```
18//! use autodiff::Dual;
19//!
20//! // Define a function
21//! fn f(x: Dual<f64>) -> Dual<f64> {
22//!     x * x + Dual::constant(2.0) * x
23//! }
24//!
25//! // Compute f and f' at x=3
26//! let y = f(Dual::variable(3.0));
27//! assert_eq!(y.value, 15.0);   // f(3) = 15
28//! assert_eq!(y.deriv, 8.0);    // f'(3) = 8
29//! ```
30//!
31//! # Multivariable gradients
32//!
33//! Use [`MultiDual`] and [`gradient`] for computing gradients of functions f: ℝⁿ → ℝ
34//! in a single forward pass:
35//!
36//! ```
37//! use autodiff::{MultiDual, gradient};
38//!
39//! // f(x, y) = x² + 2xy + y²
40//! let f = |vars: [MultiDual<f64, 2>; 2]| {
41//!     let [x, y] = vars;
42//!     let two = MultiDual::constant(2.0);
43//!     x * x + two * x * y + y * y
44//! };
45//!
46//! // Compute f and ∇f at (3, 4)
47//! let (value, grad) = gradient(f, [3.0, 4.0]);
48//! assert_eq!(value, 49.0);    // f(3, 4) = 49
49//! assert_eq!(grad[0], 14.0);  // ∂f/∂x = 14
50//! assert_eq!(grad[1], 14.0);  // ∂f/∂y = 14
51//! ```
52//!
53//! # Reverse-mode AD
54//!
55//! Use [`reverse_diff`] for single-variable reverse-mode (backpropagation):
56//!
57//! ```
58//! use autodiff::{reverse_diff, Var};
59//!
60//! // Define a reusable function
61//! let f = |x: Var<f64>| (x.clone() + 1.0) * (x - 1.0);
62//!
63//! // Evaluate at different points
64//! let (val, deriv) = reverse_diff(f, 3.0);
65//! assert_eq!(val, 8.0);    // f(3) = 8
66//! assert_eq!(deriv, 6.0);  // f'(3) = 2x = 6
67//! ```
68//!
69//! Use [`reverse_gradient`] for multivariable functions:
70//!
71//! ```
72//! use autodiff::{reverse_gradient, Var};
73//!
74//! // f(x, y) = x² + x*y
75//! let f = |[x, y]: [Var<f64>; 2]| x.clone() * x.clone() + x * y;
76//!
77//! let (val, grad) = reverse_gradient(f, [3.0, 4.0]);
78//! assert_eq!(val, 21.0);       // f(3, 4) = 21
79//! assert_eq!(grad[0], 10.0);   // ∂f/∂x = 2x + y = 10
80//! assert_eq!(grad[1], 3.0);    // ∂f/∂y = x = 3
81//! ```
82//!
83//! Or use [`Tape`] directly for explicit tape management:
84//!
85//! ```
86//! use autodiff::Tape;
87//!
88//! let tape = Tape::new();
89//! let x = tape.var(3.0);
90//! let y = x.clone() * x.clone();  // y = x²
91//!
92//! let grads = y.backward();
93//! assert_eq!(y.value(), 9.0);
94//! assert_eq!(grads.get(&x), 6.0);  // dy/dx = 2x = 6
95//! ```
96
97pub mod dual;
98pub mod multidual;
99pub mod tape;
100
101pub use dual::Dual;
102pub use multidual::{gradient, MultiDual};
103pub use tape::{reverse_diff, reverse_gradient, Gradients, Tape, Var};