autodj

Automatic Differentiation Library

crates.io docs build rust-clippy analyze

AUTOmatic Derivatives & Jacobians by djmaxus and you

Functionality

Single variables

use autodj::prelude::single::*;

let x : DualF64 = 2.0.into_variable();

// Arithmetic operations are required by trait bounds
let _f = x * x + 1.0.into();

// Arithmetic rules itself are defined in `Dual` trait
// on borrowed values for extendability
let f = (x*x).add_impl(&1.0.into());

// Dual can be decomposed into a value-derivative pair
assert_eq!(f.decompose(), (5.0, 4.0));

// fmt::Display resembles Taylor expansion
assert_eq!(format!("{f}"), "5+4∆");

Multiple variables

Multivariate differentiation is based on multiple dual components. Such an approach requires no repetitive and “backward” differentiations. Each partial derivative is tracked separately from the start, and no repetitive calculations are made.

For built-in multivariate specializations, independent variables can be created consistently using .into_variables() method.

Static number of variables

use autodj::prelude::array::*;

// consistent set of independent variables
let [x, y] : [DualNumber<f64,2>; 2] = [2.0, 3.0].into_variables();

let f = x * (y - 1.0.into());

assert_eq!(f.value()        , & 4.);
assert_eq!(f.dual().as_ref(), &[2., 2.]);
assert_eq!(format!("{f}")   , "4+[2.0, 2.0]∆");

Dynamic number of variables

use autodj::prelude::vector::*;
use std::ops::Add;

let x = vec![1., 2., 3., 4., 5.].into_variables();

let f : DualF64 = x.iter()
                   .map(|x : &DualF64| x.mul_impl(&2.0.into()))
                   .reduce(Add::add)
                   .unwrap();

assert_eq!(f.value(), &30.);

f.dual()
 .as_ref()
 .iter()
 .for_each(|deriv| assert_eq!(deriv, &2.0) );

Generic dual numbers

// A trait with all the behavior defined
use autodj::fluid::Dual;
// A generic data structure which implements Dual
use autodj::solid::DualNumber;

Motivation

I do both academic & business R&D in the area of computational mathematics. As well as many of us, I’ve written a whole bunch of sophisticated Jacobians by hand.

One day, I learned about automatic differentiation based on dual numbers. Almost the same day, I learned about Rust as well :crab:

Then, I decided to:

Project goals

Anticipated features

You are very welcome to introduce issues to promote most wanted features or to report a bug.

Comparison with autodiff

As far as I noticed, autodj currently has the following differences

Some differences are planned to be eliminated as noted in the roadmap.

Within this crate, you may study & launch test target /tests/autodiff.rs to follow some differences.

cargo test --test autodiff -- --show-output