2个不稳定版本
| 0.2.0 | 2020年5月18日 |
|---|---|
| 0.1.0 | 2020年4月29日 |
#486 in 数学
46KB
1K SLoC
Fwd:AD是一个前向自动微分的crate
此crate允许您轻松编写对双数的操作,并执行前向自动微分。它使用户能够用最小的分配编写自动微分代码。
主要卖点
- 默认无克隆。Fwd:AD在其函数中永远不会克隆内存(除了
to_owning()和std::ops实现之外)并利用Rust的所有权系统确保内存正确性,并将何时进行克隆的决定权留给用户。 - 按需自动克隆。如果传递了
implicit-clone功能,Fwd:AD将在需要时隐式克隆Dual。是否克隆完全由类型系统决定,因此是在编译时完成的。 - 内存位置泛型:Fwd:AD的结构对容器类型进行泛型化,允许它们支持您选择的任何容器:使用堆的
Vec,如果你更喜欢栈,则使用数组,或其它。例如,它可以与&mut [f64]一起使用,以允许一个不需要在边界处复制内存的FFI API。
示例
详细示例可在examples/目录中找到,但以下是一些片段。
Rosenbrock函数最小化
extern crate fwd_ad;
use fwd_ad::*;
// The factor by which we will descend along the gradient.
// Rosenbrock function is pretty steep so its quite small.
const ALPHA : f64 = 1e-3;
fn main() {
// Create two duals with two derivatives each, as well as
// closures getdx and getdy to get their corresponding derivative
generate_duals!{
x = 0.; @ getdx
y = 0.; @ getdy
}
for _ in 0..10000 {
let xval : f64 = x.val();
let yval : f64 = y.val();
let res = (x.clone() - 1.).powf(2.) + 100.*(y-x.powf(2.)).powf(2.);
println!("At x={}, y={}, the rosenbrock function is {}",xval, yval, res.val());
generate_duals!{
newx = xval - ALPHA*getdx(res.view());
newy = yval - ALPHA*getdy(res.view());
}
x = newx;
y = newy;
}
}
简短教程
Fwd:AD的主要类型是Dual<Container, OM, F>结构。此结构由三种类型参数化,分别是
Container类型指示用于存储结构内容的“容器”。典型示例包括Vec<F>、[F; n]、&mut [F]或&[F]。OM是“拥有模式”,有两种可能性之一:表示“读写”的RW,表示 Dual 的内容可写,因此可以在计算期间重复使用,以及表示只读的RO。F是标量类型,通常是f32或f64,但你可以选择使用不同的类型。
Dual 包装其容器,该容器必须是“可读为 [F] 的切片”。该标量切片的第一个元素是 dual 的实际值,接下来的是关于连续变量的导数。
为了减轻编写长类型名称的负担,在 instanciations 模块中定义了规范的对拥有/查看 dual。
Fwd:AD Traits
Fwd:AD 依赖于几个特质以足够通用。用户可能需要实现的特质位于 traits 模块中。
ROAble(或RWAble)是应该由能够读取(或写入)其内容的容器实现的特质。所有容器类型都必须实现ROAble。这些特质类似于AsRef/AsMut来自core,并提供了一个泛型实现。ToView和ToOwning是用于定义规范“拥有”(可以是RW)和“查看”(只有RO容量)容器对应关系的特质。Scalar是代表标量数字的特质,它是num_traits的各种特质的超特质,因此这是你应该寻求实现的内容。
注意事项:由于你不能在外部类型上实现外部特质,你可能会发现自己在使用不常见的容器或标量类型时受到限制。如果是这样,请与该crate的维护者联系。
与其他(正向)AD Rust 库的比较
最后更新列表示检查相应crate的最后时间。自那时以来,crate可能已发生变化。
| crate | 版本 | 多元 | 高阶 | 最后更新 |
|---|---|---|---|---|
| Fwd:AD | 0.1.0 | ✔️ | ❌ | 2020-04-29 |
| ad | 0.1.0 | ❌ | ❌ | 2020-01-01 |
| autodiff | 0.1.9 | ❌ | ❌ | 2019-11-07 |
| descent¹ | 0.3 | ✔️ | (2nd order?) | 2018-12-10 |
| dual | 0.2.0 | ❌ | ❌ | 2015-12-25 |
| dual_num | 0.2.7 | ❌ | ❌ | 2019-04-03 |
| hyperdual² | 0.3.4 | ✔️ | ❌ | 2020-02-08 |
| peroxide | 0.21.7 | ❌ | (2nd order) | 2020-04-21 |
descent自动微分似乎很有前途,但文档不多,并且与 IP-OPT 接口混合。hyperdual与 Fwd:AD 有类似特性,但所有操作都会在 Fwd:AD 尝试重用现有内存时进行分配。
依赖关系
~0.1–11MB
~96K SLoC