This plugin provides reverse-mode automatic differentiation: autodiff.ad f yields the augmented function f' = λ args. (f args, f*) that returns the result together with its pullback. The actual differentiation is performed by the mim::plug::autodiff::Eval phase.
The tangent type of a type T (currently the identity).
Computes the augmented type of a function type: (T → U) => (T → U × (U → T)).
Yields the augmented term of a closed term (function, operator, higher-order argument, registered axiom, etc.). The augmented term f' returns the result together with the pullback: autodiff f = f' = λ args. (f args, f*)
Represents universal zero such that (zero T) +_T t = t.
A universal addition that consumes zeros and defaults to normal addition for scalar types. It lifts addition over structured types and special-cases types that do not allow addition.
Performs autodiff.add over a list of terms.
Replaces autodiff.zero T with the zero element of T, where one exists.
The heart of AD: replaces an autodiff.ad call with the differentiated function (mim::plug::autodiff::phase::Eval).
In this section, we define translations for axioms of other plugins. This would best be done using a register mechanism in a third plugin or at least in a separate file.
The general concept is that a call to an axiom is replaced with a call to the augmented axiom. The augmented axiom needs a wrapper for meta arguments (a higher-order function). Appropriate cps2ds wrappers are introduced to handle that the augmented axioms are in CPS whereas the original axioms are in direct style. Example:
The types (with Int for (Int w)) are:
The pullback has to be in cps for compliance.
The pullback is the derivative with respect to the input (weighted with the output tangent). For arithmetic operations, s is simply multiplied onto each input tangent: ∂_i f(x1,...,xn) * s It follows that the applied partial pullback needs to be: sum x_i*(∂_i f(x1,...,xn) * s) = sum x_i*(•) with • as the formula from above. This is a direct result of the chain-rule composition with the partial pullback of a tuple. The tuple pullback transports the partial pullbacks of the operands and handles the sums. By its nature the pullback of a tuple needs to be a sum.
The derivative of the axiom plugin.tag.sub is the annex autodiff.diff.plugin_tag_sub, i.e. the axiom's name with all .s replaced by _s; this is how mim::plug::autodiff::phase::Eval looks a derivative up. Being annexes, they are roots of the World and hence survive until mim::plug::autodiff::phase::Eval has consumed them. But - unlike externals - they are invisible to the backends and a compile.unload "autodiff" nukes them along with all the other annexes of this plugin.
The derivative of core.icmp.xYgLE (eq).
The comparison pullback exists formally but is not used.
The derivative of core.wrap.add:
s ↦ (s, s)
The derivative of core.wrap.mul:
s ↦ (s*b, s*a)