-
Notifications
You must be signed in to change notification settings - Fork 42
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
Added support to pricing phases for use of heuristic pricing #519
Conversation
I tested both CVRP and VRPTW applications with the branch testing_heuristic_pricing of ColunaBenchmarks and fast_testing_run of Camina. |
Codecov Report
@@ Coverage Diff @@
## release-0.4.0 #519 +/- ##
=================================================
+ Coverage 83.95% 84.00% +0.04%
=================================================
Files 47 47
Lines 4606 4619 +13
=================================================
+ Hits 3867 3880 +13
Misses 739 739
Continue to review full report at Codecov.
|
Dear Artur, Sorry if this was not clear, but the code architecture supposes that col.gen. phases should be implemented at the level of I suggest to replace I would also suggest to "extract" pricing callback from We may have a video call with you and Guillaume to discuss this. |
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.
See my previous comment
Also, the name |
@@ -60,12 +60,11 @@ end | |||
|
|||
function product_score(group::BranchingGroup, parent_optstate::OptimizationState) | |||
parent_inc = getincumbents(parent_optstate) | |||
# TO DO : we need to mesure the gap to the cut-off value |
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 this comment has been removed ?
function setphase!(opt::MoiOptimizer, ph::Int) | ||
return | ||
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.
function setphase!(opt::MoiOptimizer, ph::Int) | |
return | |
end | |
setphase!(opt::MoiOptimizer, ph::Int) = nothing |
function setphase!(opt::UserOptimizer, ph::Int) | ||
opt.phase = ph | ||
return | ||
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.
function setphase!(opt::UserOptimizer, ph::Int) | |
opt.phase = ph | |
return | |
end | |
setphase!(opt::UserOptimizer, ph::Int) = opt.phase = ph |
@@ -427,7 +427,7 @@ end | |||
|
|||
function getoptbuilder(prob::Problem, ann::BD.Annotation) | |||
if BD.getpricingoracle(ann) !== nothing | |||
return () -> UserOptimizer(BD.getpricingoracle(ann)) | |||
return () -> UserOptimizer(BD.getpricingoracle(ann), 0) # exact phase |
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.
It it's always 0
by default it should be in the constructor ?
This is indeed the way to go.
I couldn't extract the pricing callback from I think the best alternative is to rename
Since I did not make a lot of progress last two weeks, we can discuss this Thursday. The meeting is at 11am France which is very early in Brazil, we can do it later if you want. |
Is it possible to force solving the subproblem MIP even if the pricing callback is defined? If yes, that what we can do is to create two separate algorithms for solving MIP (current |
How column generation will know what algorithm it should run to optimize the subproblems ? |
There is the field |
It means that if the user decides to solve the subproblems with a pricing callback, he must change the solver through BlockDecomposition and he must also change the |
I agree that it is less convenient. However, this is more flexible. For example, the user can define the heuristic callback and use it together with MIP (for the exact phase). This is impossible for the moment. Inconvenience can be minimized by defining a shortcut |
I think we can split the pricing callback and the call to the MOI solver into two algorithms : This solution allow us more flexibility without inconvenience. |
Good for me. |
Hello, guys. It is nice to see that this branch motivated a lot of improvements on the structure of Coluna. However, I will would like to remark that heuristic pricing is already working in the way it is implemented and it is important to accelerate the executions needed to test other new features. So, I am afraid that delaying this PR with several changes in the structure might delay the whole project. How about opening an issue for that letting these changes for another branch? |
Dear Artur. The problem with this pull request that it adds a number of changes to |
@artalvpes The discussion went off topic. We won't wait for the split of
I'm ok with the changes done in |
Hi, Artur. Ok, can please add a test in this pull request, and then it will be accepted. |
Hi Ruslan and Guillaume. I started to check the changes suggested by Guillaume but I have some concerns that go in the direction of the previous discussion. I think that the name phases for ColumnGeneration is already used for the classical two phases of the Simplex algorithm. So, I think that creating several copies of ColumnGeneration, one for each pricing phase, will be misleading. Note that switching between two pricing phases may occur before or after switching between the two simplex phases. Because of that, I agree with Ruslan that the pricing phase should be somehow attached to PricingCallback instead of ColumnGeneration but I agree with Guillaume that having to configure this through both BlockDecomposition and an attribute of ColumnGeneration would not be convenient. Thus, I would like to ask Guillaume if he agrees with Ruslan to let it as is for now until we decide the best way to refactor it. Then I would only add a test and go the next task. |
Perhaps the problem is that we want Coluna to control something that is not its responsibility. Perhaps, the best way to implement this is letting the user switch to a more exhaustive pricing method when the current one fails in the same pricing call, just reporting to Coluna in some way that this change occurred (to reset the pseudo_dual_bound) and whether the obtained solutions give a valid dual bound or not. The user would also need to be able to save a pricing state (with the current pricing phase but Coluna does not need to know about it) to be recovered in the next callback of the same node. This is also more generic because it would allow for example a premature change in the pricing phase according to some criterion known only by the pricing solver. To allow solving the pricing subproblem by MIP in some phase, I think we could export a special function to be called inside the callback. What do you think? |
Dear Artur, We talked with Guillaume yesterday and we agreed that it is better not to merge changes which will be reverted after. This is a double work. Concerning the names, I propose to call change "phases" name for "stages". So we would have pricing stages (or more generally conquer stages) which may consist of several simplex phases.
I think this suggestion comes against the "design philosophy" of Coluna. The Coluna design suggests that every algorithm is independent from other algorithms. Algorithms communicate only through input and output and also through storage units. But in any case there should be no communication between algorithms except running one from another. If other type of communication is unavoidable, two communicating algorithms should be merged into one. For example, in your code, you have |
What we suggest with Gullaume is pretty simple to implement for me. We should define field The default parameterisation of
The default parameterisation of
If user wants that the exact pricing is solved by MIP, it would be
Of course, dispatch modes (1, 2, 3) should be named somehow. Parameterisation will later be simplified with an alias ( |
Ok for me.
From your previous message, I understand that we must be able to stop column generation from any point. Can we have an extra field in the pricing callback output to tell Column Generation that it should stop and let ConCutGenConquer run the next column generation algorithm ?
I think this one can be fixed by passing the stage as argument of the
I would add that such a mechanism is "out of bounds" for callbacks because the user can keep his data in the parent scope of the pricing callback method (even if it cannot know when the node changes at the moment). The goal of the pricing callback is to allow the user to quickly implement/test a pricing solver. However, we will have such a mechanism for the custom pricing solver because it will be attached to a model that may have a storage. So, we should keep this mechanism for the custom pricing solver.
It can be improved :) |
I can implement support of pricing stages. But I first need a test for this case. |
I do not think that stopping col.gen. prematurely should be decided by pricing. The column generation algorithm should decide itself when and why it should stop. It would be very much welcome to leave If you do not agree with this, I would like to know the concrete case when this behaviour is needed. |
I was not suggesting that the pricing could be able to stop col.gen.. I was suggesting that the pricing could be able to automatically switch to the next algorithm stage when solving the pricing subproblem. However, this has an impact in Coluna because, as the quality of the columns improve, the pseudo dual cost of the generated columns may get worse (the better the column, the worse its pseudo dual cost) preventing the stability center to be updated and worsening the convergence of col. gen. |
Ok. I agree with that but for me it is just a matter of using the "official" methods to send the same information (either algorithm inputs and outputs or the storage units).
In fact, I personally don't think that solving a pricing subproblem by MIP is efficient in practice. Specially, if one has a specific pricing algorithm in hand, being able to call it alternately with a MIP does not make much sense for me. So I tried to propose a way not to change the structure of Coluna only to allow for using this option. |
That's a good suggestion! If you want, I can leave this discussion making whatever you decide and concentrate in the algorithms themselves ;-) |
I added a test in "test/pricing_callback_tests.jl". It is using the current interface for the pricing phases. You need to update the test when the interface changes. |
… due to numerical precision
Reimplemented in pull request #525 |
No description provided.