reverse

Crates.io Documentation License

Reverse mode automatic differentiation in Rust.

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

rust [dependencies] reverse = "0.1"

Examples

```rust use reverse::*;

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

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

The main type is Var<'a>, so you can define functions that take this in and the function will be differentiable. For example:

```rust use reverse::*;

fn main() { let graph = Graph::new(); let params = graph.addvars(&[5., 2., 0., 1.]); let result = difffn(&params); let gradients = result.grad(); println!("{:?}", gradients.wrt(&params)); }

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

Differentiable Functions

There is an optional diff feature that activates a convenience macro to transform certain functions so that they are differentiable. That is, functions that act on f64s can be used without change on Vars, and without needing to specify the type.

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

rust reverse = { version = "0.1", features = ["diff"] }

Functions must have the type Fn(&[f64], &[&[f64]]) -> f64, where the first argument contains the differentiable parameters and the second argument contains arbitrary arrays of data.

Example

Here is an example of what the feature allows you to do:

```rust use reverse::*;

fn main() { let graph = Graph::new(); let a = graph.addvar(5.); let b = graph.addvar(2.);

// you can track gradients through the function as usual!
let res = addmul(&[a, b], &[&[4.]]);
let grad = res.grad();

assert_eq!(grad.wrt(&a), 1.);
assert_eq!(grad.wrt(&b), 4.);

}

// function must have these argument types but can be arbitrarily complex // apply computations to params and data as if they were f64s

[differentiable]

fn addmul(params: &[f64], data: &[&[f64]]) -> f64 { params[0] + data[0][0] * params[1] } ```