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