13 releases

0.2.2 Aug 7, 2021
0.2.1 Aug 3, 2021
0.1.9 Aug 3, 2021
0.0.1 Aug 1, 2021

#456 in Science

Download history 45/week @ 2024-07-22 23/week @ 2024-07-29 35/week @ 2024-08-05 34/week @ 2024-08-12 57/week @ 2024-08-19 22/week @ 2024-08-26 7/week @ 2024-09-09 1/week @ 2024-09-16 46/week @ 2024-09-23 16/week @ 2024-09-30 39/week @ 2024-10-07 49/week @ 2024-10-14 34/week @ 2024-10-21 13/week @ 2024-10-28 45/week @ 2024-11-04

144 downloads per month
Used in 3 crates (2 directly)

MIT/Apache

28KB
737 lines

reverse

Crates.io Documentation License

Zero-dependency crate for reverse mode automatic differentiation in Rust.

To use this in your crate, add the following to Cargo.toml:

[dependencies]
reverse = "0.2"

Examples

use reverse::*;

fn main() {
  let tape = Tape::new();
  let a = tape.add_var(2.5);
  let b = tape.add_var(14.);
  let c = (a.sin().powi(2) + b.ln() * 3.) - 5.;
  let gradients = c.grad();

  assert_eq!(gradients.wrt(&a), (2. * 2.5).sin());
  assert_eq!(gradients.wrt(&b), 3. / 14.);
}

The main type is Var<'a>, so you can define functions that take this as an input (possibly along with other f64 arguments) and also returns this as an output, and the function will be differentiable. For example:

use reverse::*;

fn main() {
    let tape = Tape::new();
    let params = tape.add_vars(&[5., 2., 0.]);
    let data = [1., 2.];
    let result = diff_fn(&params, &data);
    let gradients = result.grad();
    println!("{:?}", gradients.wrt(&params));
}

fn diff_fn<'a>(params: &[Var<'a>], data: &[f64]) -> Var<'a> {
    params[0].powf(params[1]) + data[0].sin() - params[2].asinh() / data[1]
}

No runtime deps