autodiff tutorial
This tutorial is the fastest route through the repository: with the single
import Luna-Flow/autodiff you differentiate a function, write generic code
against the re-exported traits, and handle checked failures. Each section
links to the package tutorial that goes deeper.
Quick start
moon add Luna-Flow/autodiff@0.2.0
import {
"Luna-Flow/autodiff",
}
fn main {
let (value, slope) = @autodiff.value_and_diff(x => x * x.exp(), 1.0)
println("f(1) = \{value}")
println("f'(1) = \{slope}")
}
f(1) = 2.718281828459045
f'(1) = 5.43656365691809
has , so .
Everyday tasks
Differentiate a closure
fn main {
let slope = @autodiff.diff(x => x.sin() * x.cos(), 0.0)
println("d/dx sin x cos x at 0 = \{slope}")
}
d/dx sin x cos x at 0 = 1
Write generic code with the re-exported traits
All bounds come from the one import:
fn[T : @autodiff.Ring + @autodiff.Exponential + @autodiff.IntegralHomomorphism] softplus_like(
x : T,
) -> T {
let one : T = @autodiff.IntegralHomomorphism::from_integral(1)
one + @autodiff.Exponential::exp(x)
}
fn main {
println("value at 0: \{softplus_like(0.0)}")
println("slope at 0: \{@autodiff.diff(softplus_like, 0.0)}")
}
value at 0: 2
slope at 0: 1
Use mathematical constants
Constants gives , and as dual constants:
fn main {
let area_slope = @autodiff.diff(
r => {
let pi : @autodiff.Dual[Double] = @autodiff.Constants::pi()
pi * r * r
},
2.0,
)
println("d/dr pi r^2 at 2 = \{area_slope}")
}
d/dr pi r^2 at 2 = 12.566370614359172
Handle a checked failure
fn main {
let ctx = @autodiff.ArithmeticContext::new(53)
let x = @autodiff.Dual::variable(2.0)
match @autodiff.DivChecked::div_checked(x, x - x, ctx) {
Ok(_) => println("unexpected")
Err(e) => println("division by zero: \{e.is_division_by_zero()}")
}
}
division by zero: true
Going further
- Seeding by hand, directional derivatives and finite-difference comparisons: the dual tutorial.
- Higher derivatives and Newton’s method: the forward tutorial.
- Gradients and Jacobians: the linalg tutorial.
- Polynomial derivatives: the poly tutorial.
- Checked operations in depth: the checked tutorial.
Common pitfalls
- The root package has no gradients. Import
Luna-Flow/autodiff/linalgforgradientandjacobian. - Re-exported traits are the original traits. An instance you write for
@lg.Ringis the instance of@autodiff.Ring; do not implement both. - Literals need
Dual::constantorfrom_integralinside differentiated code.
Next steps
- The autodiff API lists every re-exported name.
- The autodiff design explains the facade.
- The overview maps all packages.