# Incremental Solving not supported? #7

Closed
opened this issue Aug 21, 2019 · 16 comments

### drlagos commented Aug 21, 2019 • edited

 Hello, I've been trying to learn how to do boolean modelling in Mixed Integer Programming, and I would like to get all solutions to the problem. Here is a simple example model where blocks with ports need to be connected, with some symmetry breaking on the blocks and ports (should have 3 solutions): ```import mip mm = mip.Model(solver_name="cbc") mm.verbose = False # Blocks bus = mm.add_var("bus", 0, 1, var_type=mip.BINARY) battery_1 = mm.add_var("battery_1", 0, 1, var_type=mip.BINARY) battery_2 = mm.add_var("battery_2", 0, 1, var_type=mip.BINARY) # Ports bus_p1 = mm.add_var("bus_p1", 0, 1, var_type=mip.BINARY) bus_p2 = mm.add_var("bus_p2", 0, 1, var_type=mip.BINARY) battery_1_p = mm.add_var("battery_1_p", 0, 1, var_type=mip.BINARY) battery_2_p = mm.add_var("battery_2_p", 0, 1, var_type=mip.BINARY) # Constraints mm.add_constr(battery_1 + battery_2 >= 0) mm.add_constr(battery_1 + battery_2 <= 2) mm.add_constr(bus == 1) mm.add_constr(battery_1 >= battery_2) mm.add_constr(battery_1 == battery_1_p) mm.add_constr(battery_2 == battery_2_p) mm.add_constr(bus >= bus_p1) mm.add_constr(bus >= bus_p2) mm.add_constr(bus_p1 <= bus_p2) mm.add_constr(bus_p1 + bus_p2 == battery_1_p + battery_2_p) count = 0 for i in range(0, 10): status = mm.optimize() if status == status.FEASIBLE or status == status.OPTIMAL: print(f"{bus}: {bus.x}") print(f"{battery_1}: {battery_1.x}") print(f"{battery_2}: {battery_2.x}") else: print("INFEASIBLE") break count += 1 # or(a != a.x, b != b.x, c != by) flip = [1 - v if v.x else v for v in (bus, battery_1, battery_2)] mm.add_constr(mip.xsum(flip) >= 1) print(f"CBC (Python-MIP) found {count} solutions")``` However this code only gives me 1 solution, 10 times. If I do the same with google Or-Tools, it works as expected: ```from ortools.linear_solver import pywraplp as or_tools om = or_tools.Solver("cbc", problem_type=or_tools.Solver.CBC_MIXED_INTEGER_PROGRAMMING) # Instances bus = om.BoolVar("bus") battery_1 = om.BoolVar("battery_1") battery_2 = om.BoolVar("battery_2") # Ports bus_p1 = om.BoolVar("bus_p1") bus_p2 = om.BoolVar("bus_p2") battery_1_p = om.BoolVar("battery_1_p") battery_2_p = om.BoolVar("battery_2_p") # Constraints om.Add(battery_1 + battery_2 >= 0) om.Add(battery_1 + battery_2 <= 2) om.Add(bus == 1) om.Add(battery_1 >= battery_2) om.Add(battery_1 == battery_1_p) om.Add(battery_2 == battery_2_p) om.Add(bus >= bus_p1) om.Add(bus >= bus_p2) om.Add(bus_p1 <= bus_p2) om.Add(bus_p1 + bus_p2 == battery_1_p + battery_2_p) count = 0 # Limit number of solutions for i in range(0, 10): status = om.Solve() if status == om.FEASIBLE or status == om.OPTIMAL: print(f"{bus}: {bus.solution_value()}") print(f"{battery_1}: {battery_1.solution_value()}") print(f"{battery_2}: {battery_2.solution_value()}") else: print("INFEASIBLE") break count += 1 # or(a != a.x, b != b.x, c != by) flip = [1 - v if v.solution_value() else v for v in (bus, battery_1, battery_2)] om.Add(sum(flip) >= 1) print(f"CBC (Or-Tools) found {count} solutions")``` This gives the expected 3 solutions. Is there anything I'm missing, like a different way to restrict solutions, or is python-mip just not intended to be used like this?
Author

### drlagos commented Aug 21, 2019

 Just tested with PuLP, it also works correctly with 3 solutions (albeit very, very slow).
Contributor

### tuliotoffolo commented Aug 21, 2019

 Dear Cesar, I just tested using Gurobi, and three solutions are generated (as expected). We will check why this is happening when using CBC as the solver in Python-MIP, and contact you again soon. Best, Túlio Em 21 de ago de 2019 07:07 -0300, César Santos , escreveu: … Just tested with PuLP, it also works correctly with 3 solutions (albeit very, very slow). — You are receiving this because you are subscribed to this thread. Reply to this email directly, view it on GitHub, or mute the thread.
Author

### drlagos commented Aug 21, 2019

 Great, thanks! I'm quite interested in python-mip since it lets me tell CBC to aim for feasible solutions or aim for optimal solutions (the ability to do both is what I'm interested in, hence investigating MIP solvers, OptSMT is still quite new and there's only 1 solver that is both good at it and has a decent license).
Contributor

### h-g-s commented Aug 21, 2019

 Hi, There are two bugs here: CBC storing updated bounds on variables after optimizing (we'll fix it) your code has also a dangerous operation: if v.x tests for zero. as computation in linear programming solvers use limited accuracy it is often the case that instead zero you got 0.000000000001 (which is also zero for practical purposes) it would be better to use here: abs(v.x) <= 1e-7
Author

### drlagos commented Aug 21, 2019

 I did not realize integer variables were actually handled as reals rather than integers. Thank you for the warning! You probably just saved me some frustrating nights debugging that issue.
Member

### tkralphs commented Aug 21, 2019

 @h-g-s Although integer variables are handled as reals inside the solver, the value of any variable that is intended to be an integer should be handed to the user as an integer. I believe Cbc itself should do this rounding before handing the user the solution, but if not Cbc, it seems your interface should do it. I don't think users should need to be aware of these details.
Contributor

### h-g-s commented Aug 21, 2019

 @tkralphs true, I'll check it in CBC
Contributor

### spoorendonk commented Aug 21, 2019

 @h-g-s I think that 1. (the storing of updated bounds) was also the problem I had in #3 and the reason why the pricing problem could not be re-optimized. Perhaps the cutting stock example should be reverted (except for the model bug) when this issue is fixed.
Contributor

### h-g-s commented Aug 22, 2019

 @spoorendonk I think that the CBC fix will not take too long...

### aopt commented Aug 26, 2019 • edited

 @h-g-s Although integer variables are handled as reals inside the solver, the value of any variable that is intended to be an integer should be handed to the user as an integer. I believe Cbc itself should do this rounding before handing the user the solution, but if not Cbc, it seems your interface should do it. I don't think users should need to be aware of these details. Rounding can lead to larger infeasibilities. I think this is why the solver would not do this automatically. Safer is to use a tighter integer feasibility tolerance (Cplex allows epint=0). Of course that can lead to longer solution times.
Member

### tkralphs commented Aug 26, 2019

 The infeasibility that the user probably cares most about is the one computed with the the rounded values for the integer variables. From a practical standpoint, it doesn't matter (to the user) that the infeasibility of the given continuous solution is within a tolerance (for the linear constraints) if rounding the values of the integer variables causes it to exceed that tolerance. For practical reasons, it's difficult to ensure that the rounded solution satisfy a given feasibility tolerance, but that shouldn't prevent the interface from handing the user a solution that is fully integer feasible. Whether you do the rounding on behalf of the user or not, there is some potential for confusion, but rounding seems to eliminate the most likely source.
Contributor

### h-g-s commented Sep 6, 2019

 1.4.0 released with (hopefully) a fix for the MIP reoptimization issue in CBC. Could you try it ???
Author

### drlagos commented Sep 7, 2019 • edited

 I have good news and bad news. The good news is that the bug is fixed! The bad news is that there is a new one, setting verbosity to 0 doesn't do anything and I get a spam of messages from CBC. Though maybe i'm just doing something wrong. my_model.verbosity = 0 Should be this right? max_solutions also appears to be ignored, I get this from CBC: No match for max_solutions - ? for list of commands
Contributor

### h-g-s commented Sep 7, 2019

 Ops, in the reorganization of the C interface some parameters were not being updated. Testing the fix now. On 9/7/19 10:08 PM, César Santos wrote: I have good news and bad news. The good news is that the bug is fixed! The bad news is that there is a new one, setting verbosity to 0 doesn't do anything and I get a spam of messages from CBC. Though maybe i'm just doing something wrong. my_model.verbosity = 0 Should be this right? — You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub <#7?email_source=notifications&email_token=AB4VZOXXMREC4O55ZDAVIJTQIQC4RA5CNFSM4IOEOPL2YY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LNMVXHJKTDN5WW2ZLOORPWSZGOD6FBK3I#issuecomment-529143149>, or mute the thread . -- ============================================================= Haroldo Gambini Santos Computing Department Universidade Federal de Ouro Preto - UFOP email: haroldo@ufop.edu.br home/research page: www.decom.ufop.br/haroldo It has long been an axiom of mine that the little things are infinitely the most important. -- Sir Arthur Conan Doyle, "A Case of Identity"
Contributor

### h-g-s commented Sep 7, 2019

 Released 1.4.1 with the fix for linux and windows (don't have a mac here, so this build will wait). … -- ============================================================= Haroldo Gambini Santos Computing Department Universidade Federal de Ouro Preto - UFOP email: haroldo@ufop.edu.br Haroldo.GambiniSantos@cs.kuleuven.be home/research page: www.decom.ufop.br/haroldo It has long been an axiom of mine that the little things are infinitely the most important. -- Sir Arthur Conan Doyle, "A Case of Identity" On Sat, 7 Sep 2019, César Santos wrote: I have good news and bad news. The good news is that the bug is fixed! The bad news is that there is a new one, setting verbosity to 0 doesn't do anything and I get a spam of messages from CBC. Though maybe i'm just doing something wrong. my_model.verbosity = 0 Should be this right? — You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub, or mute thethread.[AB4VZOW67RGEUSTZM2OOM73QIQC4RA5CNFSM4IOEOPL2YY3PNVWWK3TUL52HS4DFVREXG43VMVBW 63LNMVXHJKTDN5WW2ZLOORPWSZGOD6FBK3I.gif]
Author

### drlagos commented Sep 7, 2019

 Verbosity works now :) just max_solutions still missing. I will close the issue since not having max_solutions does not really affect me. Excellent work!