1 unstable release
0.1.0 | Nov 12, 2023 |
---|
#1573 in Algorithms
22KB
651 lines
frechet
frechet
implements the simple dual number types dual32
and dual64
, thus
providing basic auto-differentiation capabilities.
Example
use frechet::*;
fn p(x: dual32) -> dual32 { x.powf(2.5).atanh() + 1.0 }
fn p_derivative(x: f32) -> f32 { -2.5 * x.powf(1.5)/(x.powi(5) - 1.0) }
// using the `derivative` function
let z1 = derivative(p, 2.0);
// manually
let z2 = p(2.0.as_dual_variable()).d;
// exact derivative
let z3 = p_derivative(2.0);
assert!((z1 - z3).abs() < f32::EPSILON);
assert!((z2 - z3).abs() < f32::EPSILON);
lib.rs
:
frechet
is a library providing simple dual number types with interfaces
similar to that of the standard floating point types. Additionally, provides
a small interface to abstract the computation of derivatives.
Refresher on dual numbers
A dual number $z$ is represented as the sum of a "real part" $x$ and an "imaginary part" $y$, and written $z = x + yj$, where $j$ is purely symbolic and follows the rule $j^2 = 0$. As an example, evaluating the polynomial $P(X)=3X^2-X+1$ at the dual number $X + j$ yields $$P(X+j)=3X^2-X+1 + (6X-1)j = P(X) + P^\prime(X)j.$$ This motivates the following extension of any (differentiable) real function $f$ to dual numbers: $$f(x+yj) = f(x) + yf^\prime(x)j.$$
Example
use frechet::*;
fn p(x: dual32) -> dual32 { x.powf(2.5).atanh() + 1.0 }
fn p_derivative(x: f32) -> f32 { -2.5 * x.powf(1.5)/(x.powi(5) - 1.0) }
// using the `derivative` function
let z1 = derivative(p, 2.0);
// manually
let z2 = p(2.0.as_dual_variable()).d;
// exact derivative
let z3 = p_derivative(2.0);
assert!((z1 - z3).abs() < f32::EPSILON);
assert!((z2 - z3).abs() < f32::EPSILON);