Incremental Solving not supported?
See original GitHub issueIssue Description
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?
Issue Analytics
- State:
- Created 4 years ago
- Comments:16 (10 by maintainers)
Top Results From Across the Web
What are the benefits of incremental solving? - Stack Overflow
The incremental solver is usually (but not always) slower on non-incremental queries, but in turn can take advantage of incrementality.
Read more >Incremental Solving - Varisat Manual
Varisat supports two features that enable incremental solving. These are incremental clause additions and solving under assumptions.
Read more >A Comparative Study of Incremental Constraint Solving ... - KIT
Abstract. Constraint solving is a major source of cost in Symbolic Ex- ecution (SE). This paper presents a study to assess the importance...
Read more >How does incremental solving work with presolve
Hi, I added some constraints to a model and called model.solve(), which seems to trigger presolve. Optimize a model with 2241 rows,...
Read more >[2009.11111] Efficient Incremental Modelling and Solving - arXiv
... interaction between SAT solvers and the automated modelling system Savile Row to support efficient incremental modelling and solving.
Read more >
Top Related Medium Post
No results found
Top Related StackOverflow Question
No results found
Troubleshoot Live Code
Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free
Top Related Reddit Thread
No results found
Top Related Hackernoon Post
No results found
Top Related Tweet
No results found
Top Related Dev.to Post
No results found
Top Related Hashnode Post
No results found
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.
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!