tape-based automatic differentiation
fn[A] Tape::new() -> Self[A]fn[A] constant(x : A) -> Loc[A]fn[A] Tape::variable(Self[A], A) -> Loc[A]fn[A : Number] AllPrims::on(@tape.Tape[A]) -> Self[A]fn[A] Tape::op1(Self[A], String, (A) -> A, (A) -> A) -> (Loc[A]) -> Loc[A]
fn[A] Tape::op2(Self[A], String, (A, A) -> A, (A, A) -> A, (A, A) -> A) -> (Loc[A], Loc[A]) -> Loc[A]fn[A] Tape::eval(Self[A]) -> Array[A]fn[A : Diffable] Tape::diff_forward(Self[A], Array[A], wrt~ : Int = ..) -> Array[A]
fn[A : Diffable] Tape::diff_backward(Self[A], Array[A], wrt~ : Int = ..) -> Array[A]pub(open) trait Diffable : Add + Sub {
zero() -> Self
one() -> Self
}fn[A : Show] Tape::dump(Self[A], pad_1~ : Int = .., pad_2~ : Int = ..) -> Stringlet tape : Tape[Double] = Tape::new()
let { neg, add, mul, .. } = AllPrims::on(tape)
let x0 = tape.variable(2.0)
let x1 = tape.variable(5.0)
let res = add(neg(x0), mul(x0, x1))
// Evaluation
let mem = tape.eval()
inspect(mem, content="[2, 5, -2, 10, 8]")
// Dump
inspect(
tape.dump(pad_1=2, pad_2=3),
content=
#|x0= 2
#|x1= 5
#|x2= - x0
#|x3= * x0 x1
#|x4= + x2 x3
#|
,
)
// Forward differentiation with respect to x1
let diff_forward_mem_1 = tape.diff_forward(mem, wrt=1)
inspect(diff_forward_mem_1, content="[0, 1, 0, 2, 2]")
// Backward differentiation
let diff_backward_mem = tape.diff_backward(mem)
inspect(diff_backward_mem, content="[4, 2, 1, 1, 1]")tape-based automatic differentiation