-
Notifications
You must be signed in to change notification settings - Fork 227
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
API for fg! #439
Comments
Would be nice to have an easier was of specifying that you're passing fg! In a lot of the different constructors. As you mention, almost all calls are fg calls, the exception is the case where the gradient isn't used in the method and also the linesearches. I don't think it's true that fg is always free compared to just f or just g, so I'm not in favor of totally removing the current setup, but we should make it easier to pass just fg. Nlsolve does it using helper functions. |
Alright, how about in addition to the existing constructors I add a
that adds the required methods based on the arguments it gets? (ie valid inputs are for instance passing f and g!, or passing fg). |
The only problem is that adding keywords with exclamation marks are kind of frowned upon. We recently removed it in the linesearch keyword because quite a few people got odd errors from writing |
That makes sense, but in this case I guess the error will be easy to see (g and g! have different signatures). Yes, there are many ways for the user to specify an objective function (mutating/non-mutating, f and g/f and fg/only fg), and it seems like the best way for the user to do that is through keyword arguments. |
The problem is errors like this
and even worse if it comes from a file... People will wonder why it says that |
@ChrisRackauckas you seem to be using https://github.com/JuliaDiffEq/DiffEqBase.jl/blob/911ec37739c0ea3e6026b7fafa016e377cf6a4b7/src/utils.jl#L13 to detect this automatically, right? Will this fail if people have a function |
Since this is sort of an advanced feature, would it be so bad to simply implement it as edit: |
My preference still goes to a fg! argument for simplicity and because the created bugs would not be the end of the world to debug (and we can add a line or two in the documentation to guide users), but I guess the nothing version is fine: it's slightly jarring with the rest of the constructors, but at least it doesn't require a workaround like the one currently described in the docs. |
Yeah, well.. Practical experience shows that people do make the mistake, and the error message is not good to put it mildly.
Hm, that workaround is mostly useless as we actually mostly use fg! as you already stated, and we now check if the |
Alternatively we can have an exported module called optimize(Objectives.fg!(myfg), x0, method, ...)
optimize(Objectives.fg(myfg), x0, method, ...) in there, where |
I think keyword arguments are fine here, just don't add the OnceDifferentiable(x0_seed::AbstractArray; f=nothing, g=nothing, fg=nothing)
OnceDifferentiable{inplace}(x0_seed::AbstractArray; f=nothing, g=nothing, fg=nothing) where
Well, maybe. For example, for ODEs it labels it inplace if there is any method with 3 or more arguments, ignoring the special forms for declaring Jacobians and the like. First of all, inplace is recommended and pretty much default, so that gets it right most of the time anyways. Out-of-place is more of a special case (solving equations with static arrays), so how many times will it show up that somebody experimented with adding more dispatches to |
An alternative could be
where defaults are then given by the comments in the last line. We could reintroduce the I think this could be a relatively good way of avoiding the regular user even knowing about For the performance demaning users who really want to keep the caches (that I want to experiment moving out anyway) because they're solving some problem over an over, can then create an (because you're not a participant yet: @anriseth how does this suggestions sound to you?) |
Did you mean to have I don't understand how Some notes, just in case they haven't been considered.
|
yes, edited
Yeah, actually it probably only makes sense for
Yes, it's not really my priority anyways, but... |
Anyway, I'll have PRs for NLSolversBase, Optim, and NLsolve as soon as I have fixed the lasts tests in NLsolve (basically just need to use the new syntax). Then we can discuss the specifics. |
So refactoring something like NDifferentiables makes you question certain past design choices. I think this design choice of making it easier to pass Seeing as we now have inter-procedural constant propagation, it would basically be free to have users provide function fg!(G, x, calc_grad)
if calc_grad
# do grad stuff in-place of course
end
# do f stuff
end This is now free because in value!(df, x) = value_gradient!(df, x, false) such that the branch would be completely compiled away for The only problem is that you objective function would need three positional arguments where two of them are not used in the case of NelderMead, SimulatedAnnealing, and ParticleSwarm... Additionally, I think that for many cases in NLSolve, it makes sense to evaluate the F(x) vector and Jacobian separately. |
That last choice is very similar to NLopt, except it just either gives an empty array for the grad output or not. |
Ah yes of course. We could just either do that or pass |
Yup, their derivative free methods just never pass a pre-allocated output for the gradient, so that branch is effectively ignored. I like the |
Two comments:
|
no but it certainly could, the original motivation for this PR was actually simply to be able to use
|
and given this is ready, you should not wait until there is agreement on different ways to construct |
I believe everything here is covered already |
It is often the case that computing the gradient yields the functional for the same cost. Right now, the objective functions require supplying f and g!, and there is an awful trick in http://julianlsolvers.github.io/Optim.jl/latest/user/tipsandtricks/ to avoid repeatings computations. The code itself mostly seems to use fg!. Is there a particular objection to implementing OnceDifferentiable(fg!, x_seed::AbstractArray) (that creates a wrapper for f and g!) and advising the users to use that instead?
The text was updated successfully, but these errors were encountered: