Skip to content
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

Update Fminbox to better API #584

Merged
merged 6 commits into from
Apr 13, 2018
Merged

Update Fminbox to better API #584

merged 6 commits into from
Apr 13, 2018

Conversation

pkofod
Copy link
Member

@pkofod pkofod commented Apr 10, 2018

I guess ref #583 (I can take the tests here if you just close that PR, or you can PR your tests against this branch)

also ref #542

The idea here is to have Fminbox accept the method instance

Fminbox(ConjugateGradient())

or

Fminbox(BFGS(); mu0 = ..., mufactor = ..., precondprep = ...)

(I know this current version has a keyword, but that'll go)

I also moved the weird way of specifying the options into Options, so the API is now like the rest of the package.

I also plan to have

optimize(f, [g, h], x, lb, ub, method, ...)

where method might be BFGS() or similar dispatch to

optimize(f, [g, h], x, lb, ub, Fminbox(method), ...)

that is if bounds are given, it will default to Fminbox (the only possibility we have right now, but other methods could be implemented).

edit: don't mind the weird first commit...

@anriseth
Copy link
Contributor

I guess ref #583 (I can take the tests here if you just close that PR, or you can PR your tests against this branch)

I'll close the PR. It is probably easier to keep it all within one PR, as there are several WIP PRs to deal with already.

Copy link
Contributor

@anriseth anriseth left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I just looked through the code, and it looks much nicer :)

May I propose that we default to LBFGS rather than BFGS? It is the default when we call unconstrained optimize I believe?

src/types.jl Outdated
successive_f_tol::Int = 0,
iterations::Integer = 1_000,
outer_iterations = 1000,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

outer_iterations::Int ?
(And should we change iterations::Integer to ::Int as well?)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If it is a single number, I am not sure it is worth supporting all sizes of integers, unless there is an application with more iterations than 9,223,372,036,854,775,807.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It really doesn't matter... "worth" is without meaning when it's free, but I can change it to keep consistence.

@@ -179,10 +198,14 @@ function optimize(
warn("Initial position cannot be on the boundary of the box. Moving elements to the interior.\nElement indices affected: $boundaryidx")
end
df.df(gfunc, x)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's update this to gradient!(df, x) ; gfunc .= gradient(df)? (Or however is best to use the NLSolversBase interface here)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good point

Fminbox() = Fminbox{ConjugateGradient}() # default optimizer
struct Fminbox{T} <: AbstractOptimizer
inner_optimizer::T
mu0
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Type unstable?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes, this is WIP :)

# Increment the number of steps we've had to perform
iteration += 1

copy!(xold, x)
# Optimize with current setting of mu
funcc = (g, x) -> barrier_combined(gfunc, gbarrier, g, x, fb, mu)
funcc = (g, x) -> barrier_combined(gfunc, gbarrier, g, x, fb, mu[1])
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

May also trigger the closure bug.

@@ -179,10 +198,14 @@ function optimize(
warn("Initial position cannot be on the boundary of the box. Moving elements to the interior.\nElement indices affected: $boundaryidx")
end
df.df(gfunc, x)
mu = isnan(mu0) ? initial_mu(gfunc, gbarrier; mu0factor=mufactor) : mu0
mu = isnan(mu0) ? [initial_mu(gfunc, gbarrier; mu0factor=mufactor)] : [mu0]
Copy link
Contributor

@mohamed82008 mohamed82008 Apr 11, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why is mu an array? I only see one place where it is modified inside of optimize, so passing it around as a number will probably be better.

Copy link
Member Author

@pkofod pkofod Apr 11, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If you look at the changes you'll realize it is to avoid redefining pcp and thus _optimizer on every iteration. I think it's significantly simpler to do it like this compared to defining a type and call overloading it. However, if the closure bug (which seriously is the biggest gripe in Julia to me) has bite here, then it might be worth it to do the complicated thing.

edit: but will it really trigger the closure bug in funcc? I'm closing over mu[1] there... Anyway, the call overloading may still be worth it.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm, I see. A Base.RefValue would probably work better then which is created using Ref(mu0) for example. I am not 100% sure the closure bug will bite, but I have become somewhat closure-phobic over the last few months.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A red could work, and I think I’ve used that elsewhere, so maybe for consistency I should do that. I really think it’s annoying that the closure bug is still around. We got the first perf regression issue here at optim just after v0.5.0 hit , and I really hoped it would be fixed in v0.5.1, but...

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ya, it's annoying but since it's a bug fix, I think it may be done in the 1.0 cycle.

@codecov
Copy link

codecov bot commented Apr 12, 2018

Codecov Report

Merging #584 into master will increase coverage by 0.24%.
The diff coverage is 92.3%.

Impacted file tree graph

@@            Coverage Diff             @@
##           master     #584      +/-   ##
==========================================
+ Coverage   88.51%   88.75%   +0.24%     
==========================================
  Files          36       36              
  Lines        1942     1957      +15     
==========================================
+ Hits         1719     1737      +18     
+ Misses        223      220       -3
Impacted Files Coverage Δ
src/multivariate/optimize/interface.jl 79.22% <ø> (ø) ⬆️
src/multivariate/solvers/constrained/samin.jl 73.04% <ø> (ø) ⬆️
src/types.jl 81.35% <100%> (ø) ⬆️
src/multivariate/solvers/constrained/fminbox.jl 85.18% <92.1%> (+2.75%) ⬆️
src/utilities/perform_linesearch.jl 90% <0%> (-6.67%) ⬇️
...ultivariate/solvers/zeroth_order/particle_swarm.jl 98.09% <0%> (-0.2%) ⬇️

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 11e031c...326e80b. Read the comment docs.

@pkofod pkofod merged commit 22f8429 into master Apr 13, 2018
@pkofod pkofod deleted the PS branch April 13, 2018 11:07
@anriseth
Copy link
Contributor

anriseth commented May 8, 2018

Is there a way to add the inplace and autodiff keywords to this new interface? (Just wondering whether there will be too many ambiguities for dispatch)

EDIT: Ah, you're of course miles ahead of me @pkofod ( #589 )

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants