fwd_ad 0.1.0

Forward auto-differentiation, allowing its user to manage memory location and minimize copying.
Documentation

Fwd:AD a crate for Forward Auto-Differentiation

This crate allows you to easily write operations on dual numbers and do forward automatic differentiation. It empowers its user to write auto-differentiation code with minimal allocations.

Key selling-points

  1. Clone-free by default. Fwd:AD will never clone memory in its functions (except to_owning()) and std::ops implementations, leveraging Rust's ownership system to ensure correctness memory-wise, and leaving it up to the user to be explicit as to when cloning should happen.
  2. Automatic cloning on demand. If passed the implicit-clone feature, Fwd:AD will implicitly clone Duals when needed. Deciding whether to clone or not is entirely done via the type-system, and hence at compile time.
  3. Generic in memory location: Fwd:AD's structs are generic over a container type, allowing them to be backed by any container of your choice: Vec to rely on the heap, arrays if you're more of a stack-person, or other. For example, it can be used with &mut [f64] to allow an FFI API that won't need to copy memory at its frontier.

Examples

Detailled examples are available in the examples/ directory, but some snippets are reproduced below.

Rosenbrock function minimization

extern crate fwd_ad;
use fwd_ad::*;

// The factor by which we will descend along the gradient.
// Rosenbrock function is pretty steep so its quite small.
const ALPHA : f64 = 1e-3;

fn main() {
    // Create two duals with two derivatives each, as well as
    // closures getdx and getdy to get their corresponding derivative
    generate_duals!{
        x = 0.; @ getdx
        y = 0.; @ getdy
    }
    for _ in 0..10000 {
        let xval : f64 = x.val();
        let yval : f64 = y.val();

        let res = (x.clone() - 1.).powf(2.) + 100.*(y-x.powf(2.)).powf(2.);
        println!("At x={}, y={}, the rosenbrock function is {}",xval, yval, res.val());

        generate_duals!{
            newx = xval - ALPHA*getdx(res.view());
            newy = yval - ALPHA*getdy(res.view());
        }
        x = newx;
        y = newy;
    }
}

Comparision with other (forward) AD rust libraries

The last-update column represent the last time the corresponding crate was checked. Crates may have evolved since.

crate version multi-variate higher-order last update
Fwd:AD 0.1.0 ✔️ 2020-04-29
ad 0.1.0 2020-01-01
autodiff 0.1.9 2019-11-07
descent¹ 0.3 ✔️ (2nd order?) 2018-12-10
dual 0.2.0 2015-12-25
dual_num 0.2.7 2019-04-03
hyperdual² 0.3.4 ✔️ 2020-02-08
peroxide 0.21.7 (2nd order) 2020-04-21
  1. descent Automatic differentiation seems promising but isn't very documented and is mixed-up with the IP-OPT interface
  2. hyperdual has similar properties to Fwd:AD, except that all operations will allocate when Fwd:AD tries to reuse existing memory