-
Notifications
You must be signed in to change notification settings - Fork 24
Enhancing DifferentiateWith
Interface
#806
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Comments
DifferentiateWith
DifferentiateWith
constraints
DifferentiateWith
constraintsDifferentiateWith
Interface
Thanks for the write up! Just to clarify, multiple active arguments are not supported by DI, nor will they be supported in the foreseeable future (#683). I agree with the need for contexts though, already suggested in #675. As for the API you suggest, passing the signature isn't enough because DifferentiateWith(f, backend, (Constant, Constant, Cache)) might suffice, where the third positional argument is the ordered tuple of wrappers that will be applied to each context. The default would be the empty tuple |
It is a design choice. Not all backends support callable objects closing over active data. Also, for implementation simplicity and thorough testing purposes, it might be better to pass the type signature instead. The tradeoff is that the type signature approach would forbid callable objects with active data when using By the way, have you encountered any examples where callable objects with active data could be critical? |
It's not just active data, it's any data. If we stick to the type signature, we can't differentiate any closure at all |
Do we need to differentiate closure? Users can always do |
Yes we do. I don't quite understand your suggestion but even there you're passing a function object, not a function type |
It should be |
Regardless, you can't compute derivatives of closures if you only give type information. Consider the following closure: julia> f = let a = 2
x -> a * x
end
#3 (generic function with 1 method)
julia> typeof(f)
var"#3#4"{Int64}
julia> dump(f)
#3 (function of type var"#3#4"{Int64})
a: Int64 2 Its type does not tell us that it performs multiplication by 2, we need the actual object for that. |
Uh oh!
There was an error while loading. Please reload this page.
Current Interface
The existing
DifferentiateWith(f, backend)
interface inDifferentiationInterface.jl
presents a significant limitation: it inherently supports only single-argument functions. This design makes it cumbersome to:Proposed Interface
To address these limitations, we propose a more expressive interface for
DifferentiateWith
:Where
Tfunc_sig
represents the function signature. The first element is the functionf
itself (or its type), and subsequent elementsT_arg1, T_arg2, ..., T_argN
represent the types of arguments tof
.Argument Type Wrappers:
To provide more context to the backend about how each argument should be treated, we can introduce wrapper types:
Constant{T}
: Indicates that an argument of typeT
is a constant and should not be differentiated.Cache{T}
: Signals that an argument of typeT
is a pre-allocated cache that the backend can utilise.Example Usage:
Consider a function
f(x, y, z, c)
wherex
andy
are active arguments,z
is a constant, andc
is a cache. Thefunc_sig
would be constructed as:Internal Handling:
With this richer
Tfunc_sig
,DifferentiateWith
can internally manage functions with multiple arguments. For backends that fundamentally operate on single-argument functions (e.g., by packing arguments into a tuple),DifferentiateWith
can perform this packing/unpacking automatically before invoking the backend's pushforward or pullback implementations. This keeps the backend APIs simpler while providing a user-friendly multi-argument interface.The text was updated successfully, but these errors were encountered: