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

Vector of optimizers in Formulation #534

Merged
merged 13 commits into from
May 26, 2021
Merged

Vector of optimizers in Formulation #534

merged 13 commits into from
May 26, 2021

Conversation

guimarqu
Copy link
Contributor

@guimarqu guimarqu commented May 23, 2021

- needs Manifest because it uses master branch of BlockDecomposition

Design changes :

  • Formulation has a vector of optimizers (MoiOptimizer, PricingCallback or CustomOptimizer later)
  • run! methods of SolveIpForm, SolveLpForm, and PricingCallback receive a new optional argument optimizer_id which is the index of the optimizers attached to the Formulation. See Vector of optimizers in Formulation #534 (comment)
  • methods to synchronize formulation with MoiOptimizers receive the optimizer as argument

@guimarqu guimarqu requested review from laradicp and vitornesello and removed request for laradicp May 23, 2021 14:11
@rrsadykov
Copy link
Collaborator

I do not like having an optional argument in the run!() method. If we change the algorithm for another optimization algorithm without this argument in the run!() method, we would have en error. The purpose of algorithms to be interchangeable. If we cannot change an algorithm for another, it is not an algorithm anymore.

Why not put optimizer_id directly to the definition of SolveIpForm, SolveLpForm, and PricingCallback? This would simplify a lot of things, and with this we would avoid adding arguments to the run!() method.

Also, the purpose of DefaultPricing algorithm is not clear anymore. The purpose of this algorithm was to switch pricing algorithms in the runtime. As now the user needs to set optimizer_id, we do not need to switch algorithms in the runtime. Why not setting directly SolveIpForm or PricingCallback with right optimizer_id as pricing_prob_solve_alg of ColumnGeneration?

@guimarqu
Copy link
Contributor Author

guimarqu commented May 23, 2021

I do not like having an optional argument in the run!() method. If we change the algorithm for another optimization algorithm without this argument in the run!() method, we would have en error. The purpose of algorithms to be interchangeable. If we cannot change an algorithm for another, it is not an algorithm anymore.

Since the argument is optional, you'll not have an error but you always have to use the first optimizer which is for me a major drawback. I tried to follow what I said in the discussion in your PR and to be quite conservative before having discussion.

Why not put optimizer_id directly to the definition of SolveIpForm, SolveLpForm, and PricingCallback? This would simplify a lot of things, and with this we would avoid adding arguments to the run!() method.

Also, the purpose of DefaultPricing algorithm is not clear anymore. The purpose of this algorithm was to switch pricing algorithms in the runtime. As now the user needs to set optimizer_id, we do not need to switch algorithms in the runtime. Why not setting directly SolveIpForm or PricingCallback with right optimizer_id as pricing_prob_solve_alg of ColumnGeneration?

These are the two options I saw this afternoon when working on this PR :

  • if we remove DefaultPricing, keep SolveIpForm SolveLpForm PricingCallback & put optimizer_id as parameter of these algorithms, then Coluna will throw an error when the user chooses SolveLpForm to call a UserOptimizer. I think we should avoid this by automatically detecting if the solver is a MoiOptimizer or a UserOptimizer (that's the job of DefaultPricing, it should be renamed by the way).
  • if we keep SolveIpForm SolveLpForm PricingCallback, put optimizer_id as parameter of these algorithms & letDefaultPricing do the dispatch depending on the type of the optimizer, then we have to make the types SolveIpForm, SolveLpForm,PricingCallback mutable to allow DefaultPricing to change their optimizer_id parameter before calling them. I don't know if it's ok to have mutable parameters for the algorithms.

What do you think ?

@rrsadykov
Copy link
Collaborator

rrsadykov commented May 24, 2021

Since the argument is optional, you'll not have an error but you always have to use the first optimizer which is for me a major drawback. I tried to follow what I said in the discussion in your PR and to be quite conservative before having discussion.

If you have an optional argument, you will use it at least once. In the call when this argument is used, you cannot use another algorithm which does not have this argument in the run!() function, you will get an error. Therefore, these two algorithms, one which calls and another which is called, are not independent anymore. Thus, you need to combine these algorithms together (or you should introduce another algorithm type, and add this argument to the input).

Coluna will throw an error when the user chooses SolveLpForm to call a UserOptimizer

I do not see a problem here. If parameterisation is inconsistent, there should be an error, it is normal for me. We cannot expect the user to always give a consistent parameterisation, especially if we mix paramerization in the algorithms and through BlockDecomposition.

I propose to put optimizer_id as a parameter in the algorithms with default value 1. We can leave DefaultPricing algorithm and rename it if you want. It will call the callback if the optimizer of formulation with id equal to optimizer_id of CallbackAlgorithm is of type UserOptimizer, otherwise it will call SolveIpForm. With this, the behaviour would be the same as before if the user gives only one solver for the subproblem. If no solver is set, then Coluna may automatically set the MOI default optimizer. However, if two or more solves are set, then user needs to use stages in column generation, and this requires a proper parameterisation, which may trigger errors if not properly set.

@rrsadykov
Copy link
Collaborator

  • I don't know if it's ok to have mutable parameters for the algorithms.

We should avoid that of course

@rrsadykov
Copy link
Collaborator

Ok, I like the current version better.

src/Algorithm/colgen.jl Outdated Show resolved Hide resolved
pricing_prob_solve_alg = ClA.DefaultPricing(
optimizer_id=2, pricing_callback = PricingCallback(stage=1)
pricing_prob_solve_alg = ClA.SolveIpForm(
optimizer_id=2, user_params = ClA.UserOptimize(stage=1)
Copy link
Collaborator

Choose a reason for hiding this comment

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

If user may define several solvers, he can define several callbacks (one heuristic and second exact). This way we can avoid stage parameter: user will just define optimizer_id=2 and optimizer_id=3. @guimarqu, what do you think about this?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I thought about that but forgot. So it's ok for me.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I open a new issue to adapt this

@guimarqu
Copy link
Contributor Author

guimarqu commented May 25, 2021

Ok, I like the current version better.

I was planning to write a comment to explain the changes after my break.

MoiOptimize and UserOptimize are not classic algorithm anymore although you can use them as algorithm. The user should rather use SolveIpForm that will dispatch depending on the type of the optimizer. It's kind of halfway between the implementation of SolveIpForm in master & what you did in the previous PR.

I'm going to fix your comments.

src/MathProg/optimizerwrappers.jl Outdated Show resolved Hide resolved
Comment on lines +86 to +90
opt = getoptimizer(form, algo.optimizer_id)
params = _optimizer_params(algo, opt)
if params !== nothing
return run!(params, env, form, input; optimizer_id = algo.optimizer_id)
end
Copy link
Collaborator

Choose a reason for hiding this comment

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

I think that there is some dispatch happening in runtime on lines 86, 87 and 89.
I think we should open an issue to investigate the impact later

@guimarqu guimarqu requested a review from rrsadykov May 25, 2021 19:49
@rrsadykov
Copy link
Collaborator

Ok for me, but I think the tests should pass before approving.

@guimarqu
Copy link
Contributor Author

Tests pass on my machine. These changes need BlockDecomposition#master & when I push the Manifest, it breaks the CI. I don't want to release a new version of BlockDecomposition before having custom model/solver.

@guimarqu guimarqu merged commit 69544da into release-0.4.0 May 26, 2021
@guimarqu guimarqu deleted the optimizer branch May 26, 2021 08:53
guimarqu added a commit that referenced this pull request Jun 14, 2021
* dev branch to prepare release of 0.4.0

* Move storage & records in ColunaBase (#507)

* Renaming in storage (#509)

* RecordContainer -> RecordWrapper

* state -> record

* rename lot of things, remove getters of Storage not used by Algorithms

* Storage -> StorageUnitWrapper

* Deletion of `AbstractData`  (#510)

* RecordContainer -> RecordWrapper

* state -> record

* rename lot of things, remove getters of Storage not used by Algorithms

* start removing AbstractData structs

* tests ok

* getunit -> getstorageunit;  StorageDict -> Storage

* fix docstring

* Bijection StorageUnit -> Record (#518)

* Bijection StorageUnit -> Record

* address Ruslan's comments

* Implementation of column generation stages  (#525)

* Implementation of column generation stages (for example, heuristic and exact stage)

* Update after conversation with Guillaume + stabilization correction

* Simplification for ColCutGenConquer

* Some more modifs due to Guillaume comments

* Counting the number of exact calls when testing the pricing stages (#530)

* Add bound callback tests (#532)

* add bound callback tests

* include bound callback in runtests

* fix test

* Apply suggestions from code review

Co-authored-by: Guillaume Marques <[email protected]>

* add comment

* Apply suggestions from code review

Co-authored-by: Guillaume Marques <[email protected]>

Co-authored-by: Guillaume Marques <[email protected]>

* Vector of optimizers in `Formulation` (#534)

* vector of optimizers in formulation

* solver_id -> optimizer_id

* add Manifest

* update Manifest

* remove Manifest because does not work

* changes

* rm files

* address Ruslan's comment

* Update src/MathProg/optimizerwrappers.jl

Co-authored-by: Vitor Nesello <[email protected]>

* add Manifest

* change ci

* remove ci change

* rm Manifest

Co-authored-by: Vitor Nesello <[email protected]>

* UnitsUsageDict -> UnitsUsage (#522)

* UnitsUsageDict -> UnitsAccess

* wip

* improve

* tests ok

* Custom data for variables and constraints (#495)

* draft for support of customer data

* custom data in solution

* custom data for cut callback

* computecoeff

* store custom data of solutions in manager

* add Manifest

* rm Manifest

* Support to custom cuts over custom data assigned to columns with new test

* tests ok

Co-authored-by: Artur Alves Pessoa <[email protected]>

* Prototyping custom model/optimizer (#535)

* Start example

* wip draft

* continue

* add map

* works with caching optimizer

* varids in Env

* wrong result

* multiply costs by -1

* fix scaling

* Apply suggestions from code review

* Update test/interfaces/model.jl

Co-authored-by: Lara Pontes <[email protected]>

* Follow up of "custom data" (#538)

* add AbstractCustomData and set/get inc_val

* fix bugs

* remove duplicate methods

* delete unnecessary prefixes and fix some bugs

* revert some changes and update docstring

* custom information for dw sp (#542)

* docstring for restricted master heuristic (#543)

* docstring for restricted master heuristic

* Update src/Algorithm/conquer.jl

* Refactoring `ObjValues` & `OptimizationState` (#544)

* clean + doc

* move doc from objvalues to optstate; tests of objvalues; update ci

* update

* update branching priorioty deprecated method

* tests ok

* tests ok

* tests ok

* delete duplicated tests

Co-authored-by: Ruslan Sadykov <[email protected]>
Co-authored-by: Artur Pessoa <[email protected]>
Co-authored-by: Lara di Cavalcanti Pontes <[email protected]>
Co-authored-by: Vitor Nesello <[email protected]>
Co-authored-by: Lara Pontes <[email protected]>
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