+f!(y, x, contexts...) # in place, returns `nothing`</code></pre><p>In this notation:</p><ul><li><code>f</code> (or <code>f!</code>) is the differentiated function</li><li><code>y</code> is the output</li><li><code>x</code> is the input, the only "active" argument, which always comes first</li><li><code>contexts</code> may contain additional, inactive arguments</li></ul><p>The quantities returned by the various <a href="../operators/#Operators">operators</a> always correspond to (partial) derivatives of <code>y</code> with respect to <code>x</code>.</p><h3 id="Assumptions"><a class="docs-heading-anchor" href="#Assumptions">Assumptions</a><a id="Assumptions-1"></a><a class="docs-heading-anchor-permalink" href="#Assumptions" title="Permalink"></a></h3><p>The package makes one central assumption on the behavior and implementation of <code>f</code> (or <code>f!</code>):</p><div class="admonition is-danger" id="Mutation-rule-dbc96e17017da004"><header class="admonition-header">Mutation rule<a class="admonition-anchor" href="#Mutation-rule-dbc96e17017da004" title="Permalink"></a></header><div class="admonition-body"><p>Either an argument's provided value matters, or it can be mutated during the function call, but never both.</p></div></div><p>This rule is declined as follows:</p><ul><li>The provided value of <code>x</code> matters because we evaluate and differentiate <code>f</code> at point <code>x</code>. Therefore, <code>x</code> cannot be mutated by the function.</li><li>For in-place functions <code>f!</code>, the output <code>y</code> is meant to be overwritten. Hence, its provided (initial) value cannot matter, and it must be entirely overwritten.</li></ul><div class="admonition is-warning" id="Warning-f4cb7f914517bcb6"><header class="admonition-header">Warning<a class="admonition-anchor" href="#Warning-f4cb7f914517bcb6" title="Permalink"></a></header><div class="admonition-body"><p>Whether or not the function object itself can be mutated is a tricky question, and support for this varies between backends. When in doubt, try to avoid mutating functions and pass contexts instead. In any case, DifferentiationInterface will assume that the recursive components (fields, subfields, etc.) of <code>f</code> or <code>f!</code> individually satisfy the same mutation rule: whenever the initial value matters, no mutation is allowed.</p></div></div><h2 id="Contexts"><a class="docs-heading-anchor" href="#Contexts">Contexts</a><a id="Contexts-1"></a><a class="docs-heading-anchor-permalink" href="#Contexts" title="Permalink"></a></h2><h3 id="Motivation"><a class="docs-heading-anchor" href="#Motivation">Motivation</a><a id="Motivation-1"></a><a class="docs-heading-anchor-permalink" href="#Motivation" title="Permalink"></a></h3><p>As stated, there can be only one active argument, which we call <code>x</code>. However, version 0.6 of the package introduced the possibility of additional "context" arguments, whose derivatives we don't need to compute. Contexts can be useful if you have a function <code>y = f(x, a, b, c, ...)</code> or <code>f!(y, x, a, b, c, ...)</code> and you only want the derivative of <code>y</code> with respect to <code>x</code>. Another option would be creating a closure, but that is sometimes undesirable for performance reasons.</p><p>Every context argument must be wrapped in a subtype of <a href="../../api/#DifferentiationInterface.Context"><code>Context</code></a> and come after the active argument <code>x</code>.</p><h3 id="Context-types"><a class="docs-heading-anchor" href="#Context-types">Context types</a><a id="Context-types-1"></a><a class="docs-heading-anchor-permalink" href="#Context-types" title="Permalink"></a></h3><p>There are three kinds of context: <a href="../../api/#DifferentiationInterface.Constant"><code>Constant</code></a>, <a href="../../api/#DifferentiationInterface.Cache"><code>Cache</code></a> and the hybrid <a href="../../api/#DifferentiationInterface.ConstantOrCache"><code>ConstantOrCache</code></a>. Those are also classified based on the mutation rule:</p><ul><li><a href="../../api/#DifferentiationInterface.Constant"><code>Constant</code></a> contexts wrap data that influences the output of the function. Hence they cannot be mutated.</li><li><a href="../../api/#DifferentiationInterface.Cache"><code>Cache</code></a> contexts correspond to scratch spaces that can be mutated at will. Hence their provided value is arbitrary.</li><li><a href="../../api/#DifferentiationInterface.ConstantOrCache"><code>ConstantOrCache</code></a> is a hybrid, whose recursive components (fields, subfields, etc.) must individually satisfy the assumptions of either <code>Constant</code> or <code>Cache</code>.</li></ul><p>Semantically, both of these calls compute the partial gradient of <code>f(x, c)</code> with respect to <code>x</code>, but they consider <code>c</code> differently:</p><pre><code class="language-julia hljs">gradient(f, backend, x, Constant(c))
0 commit comments