SpineOpt.jl icon indicating copy to clipboard operation
SpineOpt.jl copied to clipboard

Use solution from previous Benders iteration to warm start solver

Open DillonJ opened this issue 1 year ago • 13 comments

The only thing that will change between Benders iterations are the investment variables... the subproblem solution from the previous benders iteration should at least provide a feasible starting point for the solver in the next iteration

DillonJ avatar Aug 13 '23 19:08 DillonJ

I did something on this in my experimental branch (https://github.com/spine-tools/SpineOpt.jl/commit/27c2ad9b8dc44acf3167c1db5e2927a958136bfa) and it's very effective!

DillonJ avatar Aug 17 '23 09:08 DillonJ

I think that what I have done is not perfect, because it also warm starts the investment variables that are fixed to the new Benders solution, but the solver seems smart enough to fix it

DillonJ avatar Aug 17 '23 09:08 DillonJ

@manuelma could you please look at this... I'm not sure if what I have done means we all have two copies of the saved solution... I think we might not be able to avoid this as we don't save everything in m.ext.values (or do we?).

Also, maybe there is a better way than this to more explicitly omit the investment variables, but maybe this is ok for now: https://github.com/spine-tools/SpineOpt.jl/commit/e5adeb7f4ef883bd0aaf04e184e6af1a37072e86

It works really well, so we should incorporate this into master at least.

Also, I wonder is there a better way at including custom constraints in our models like this without having to create our own branch... or maybe that's ok? The problem is that often, one would need, in addition to the new constraint, new pre-processing or post processing steps, so it could be difficult to find a way to include custom constraints in a more modular way

DillonJ avatar Aug 17 '23 15:08 DillonJ

Amazing stuff @DillonJ - as far as I can see, the amount of extra storage you introduced is optimal. We will have one copy of the solution for each window, plus the rolling copy we had previously. We can't do any better than this I don't think. The only minor optimisation I can see is to not save the solution for the investment variables since we are not warmstarting those. I will add some unit-tests and then make that only change soon.

manuelma avatar Aug 18 '23 09:08 manuelma

Thanks @manuelma The investment variables will be a tiny overhead, so not sure it's worth putting too much time into that

DillonJ avatar Aug 18 '23 09:08 DillonJ

It just takes a second and the memory usage of a simple SpineOpt run is pretty high already, so I think it's worth keeping it as tight as possible even if it's a tiny difference as you correctly say.

manuelma avatar Aug 18 '23 09:08 manuelma

Fair enough :-)

DillonJ avatar Aug 18 '23 10:08 DillonJ

Actually, what we need to do is use set_start_value() to set the start value of the investment variables to their fixed value. I am currently doing a run with slightly bigger sub problem windows and warm starting it isn't as effective as before. The solver says it has no solution from the MIP start and tries to repair it - but if it had a fully feasible starting solution, it may be a lot better. Perhaps you can investigate @manuelma

DillonJ avatar Aug 18 '23 19:08 DillonJ

@DillonJ I think the issue might be that occursin() is being called with the arguments in the wrong order, so it is not skipping the investment variables. As result, we are setting the start value for the invesment variables to the value of the previous iteration, and at the same time fixing them to the value of the current iteration?

manuelma avatar Aug 21 '23 11:08 manuelma

I might have fixed it in the latest min-res-gen branch.

manuelma avatar Aug 21 '23 12:08 manuelma

Nice... let's see how this works. I suspected something was wrong alright. The more complete soution would be to warmstart the investment variables to their fixed values. I will report back here when I see how it goes

DillonJ avatar Aug 21 '23 12:08 DillonJ

So I'm running with the latest version and get this:

Warning:  Non-integral bounds for integer variables rounded.
Warning:  No solution found from 1 MIP starts.
Retaining values of one MIP start for possible repair.
Warning:  Non-integral bounds for integer variables rounded.

I can't see why the solution from the previous Benders iteration for the same window wouldn't be a solution for the next iteration... maybe you can test on a small system @manuelma

Maybe the rounding issue is related? Maybe it's just small differences. I think the warm start still helps, but perhaps could be improved further

DillonJ avatar Aug 21 '23 16:08 DillonJ

@DillonJ Looks like you've made some progress on this - has it already been merged?

clizbe avatar Jan 22 '24 16:01 clizbe