Skip to content

documentation: clarify role of mutable arguments for operators like jacobian! #977

@manuelbb-upb

Description

@manuelbb-upb

Hi, thanks for the great package.
I have been wondering about the role of mutable arguments for inplace operators based on inplace functions and could not find decisive information in the documentation.
Currently, the documentation only notes that

The positional arguments between f/f! and backend are always mutated, regardless of the bang ! in the operator name. In particular, for in-place functions f!(y, x), every variant of every operator will mutate y.

In a call DI.jacobian!(f!, y, Dy, backend, x), should y be considered just a temporary array? Or does it generally also hold the primal result values (like with DI.value_and_jacobian!)?
This question has been raised as well by @adrhill in #6 but I could not find an answer skimming the superseding issues.
When testing with ForwardDiff the array y holds the result:

import ForwardDiff
import DifferentiationInterface as DI

## out-of-place test function, ℝ³ → ℝ²
f(x) = [ sum(x); sum(abs2, x) ]
## inplace test function, ℝ³ → ℝ²
f!(y, x) = begin
    y[1] = sum(x)
    y[2] = sum(abs2, x)
    return nothing 
end

## test point
x = [1.0, 2.0, 3.0]
## use `ForwardDiff` for testing
bcknd = DI.AutoForwardDiff()

## compute Jacobian inplace, from out-of-place function:
Dy_oop = similar(x, 2, 3)
DI.jacobian!(f, Dy_oop, bcknd, x)

## compute Jacobian inplace, from inplace function:
y_tmp = similar(x, 2)       # scratch?
Dy_ip = similar(x, 2, 3)
DI.jacobian!(f!, y_tmp, Dy_ip, bcknd, x)

## Jacobian result matrices are equal …
@assert Dy_ip == Dy_oop
## … but `y_tmp` also holds correct result
@assert y_tmp == f(x)

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions