-
-
Notifications
You must be signed in to change notification settings - Fork 30
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
Fix AD for parameters #175
Conversation
Yes,
I would try to make the behaviour of the solutions as similar as possible to how this is handled for AD of
I'm not sure if I understand what aspect of the ellipse is being nudged here. Do you mean how the integral would change if one of the axes were to change in length a bit? If so, indeed we need better AD for handling the boundaries of the integration domain. Getting it working for the bounds of a box would already be a great improvement.
I would hold off on this until |
It's not ready. It doesn't cache. |
Agreed, that interface just needs to change. |
Yeah this is as discussed in #169. We should change the interface, just no one has gotten around to doing it.
It just needs a few overloads like https://github.com/SciML/SciMLBase.jl/blob/master/src/solutions/zygote.jl |
@@ -29,7 +29,8 @@ function Integrals.__solvebp(cache, alg, sensealg, lb, ub, | |||
dfdp = function (out, x, p) | |||
dualp = reinterpret(ForwardDiff.Dual{T, V, P}, p) | |||
if cache.batch > 0 | |||
dx = similar(dualp, cache.nout, size(x, 2)) | |||
dx = cache.nout == 1 ? similar(dualp, size(x, ndims(x))) : |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
won't the nout = 1 case not be able to use similar
because it could be scalar?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Since p
is an array (see function signature), so are rawp
(look below) and dualp
, so I think similar
will be defined.
# messy, there are 4 cases, some better in forward mode than reverse | ||
# 1: length(y) == 1 and length(p) == 1 | ||
# 2: length(y) > 1 and length(p) == 1 | ||
# 3: length(y) == 1 and length(p) > 1 | ||
# 4: length(y) > 1 and length(p) > 1 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not sure what this comment is here for? I mean, agreed these are the 4 cases and sometimes forward is better than reverse, but I don't understand why that's here 😅
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah sorry, I just left that as a note to myself and I can remove it. The lines of code below need all the if statements to handle these cases, so I found it helpful to list them
ext/IntegralsZygoteExt.jl
Outdated
# Zygote.@adjoint function Zygote.literal_getproperty(sol::SciMLBase.IntegralSolution, | ||
# ::Val{:u}) | ||
# sol.u, Δ -> (SciMLBase.build_solution(sol.prob, sol.alg, Δ, sol.resid),) | ||
# end |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why was this removed?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think I wanted to see if removing it broke any tests. It didn't, but I forgot to add it back. Is it used?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That just means a test didn't use sol.u
. This is necessary for if the user getfield's on u
. It should be added back for that case, preferably with a test since that seems to have been missed.
In general looks great, just a few comments. |
Sounds good
You're right about what I was suggesting, e.g. looking at the sensitivity of the integral to making the ellipse infinitesimally flatter/taller. This would require an interface change (e.g. #160) where we replace
I can add limit differentiation to this pr by the method of evaluating integrals on the faces of the hypercube. I'll explain below that this does not generalize to other types of domains. Do you think I should add to this pr or make another? To handle ellipses, manifolds, implicit domains (e.g. level sets) etc... we could relax the type assertion
|
Should we add these prototype containers to Integrals.jl or SciMLBase.jl? |
SciMLBase. |
This pr should fix #99 but in writing this I ran into a lot of internal inconsistencies in Integrals.jl as to how it handles the behavior of nout, batch, and inplace integration (as defined in the docs for
IntegralProblem
). Moreover, there are two ambiguities that mean I can't make autodiff type stable:This pr also creates breaking changes in IntegralsCubature.jl because a) it did not follow the interface in the docs (i.e. in places it used adjoints to turn vectors into matrices where it was not supposed to) and b) I changed the default choice regarding point 2. above to return a scalar when nout = 1.
In light of these points, I advocate for merging this pr, and also making the following changes in the next breaking release of Integrals.jl
nout
, andbatch
should be replaced by specialized integrand wrappers that allow the user to provide the output (and input) arrays of the correct Julia types, which can be arbitrary. (I believe this is the right abstraction and have implemented it in https://github.com/lxvm/AutoBZCore.jl)IntegralSolution
s are treated like arrays, so we should decide how to interpret the output of algorithms in terms of this so we can write type-stable pullbacks.sensealg
argument with different AD backends provided by AbstractDifferentiation.jl?Thanks in advance for your help.