Description
Summary
On /pyomo/solvers/plugins/solvers/CBCplugin.py
line 418, the command line for the CBC solver is created, with the following arguments:
cmd.extend(["-stat=1", "-solve", "-solu", self._soln_file])
This causes the command line to have the options above as the last ones in the CLI, in particular the option solve
.
Then there's the initialSolve
option which, as CBC cli reports, is used to solve the original problem just as a continuous problem.
Indeed, it is used by PuLP to implement its mip
option (see here)
However, passing initialSolve
as an option via pyomo puts it before solve
, listed in the previous list, causing it to be ignored.
Note: this may not be a big issue specifically for initialSolve
if one could easily compute the linear relaxation of a model in other ways. It could still be an issue if other CBC options get ignored because of CLI construction.
For linear relaxation, I found this thread on google groups where they mention TransformationFactory('core.relax_integer_vars')
as a pyomo-way of transforming a MILP model in a LP one, however, fyi, it does not appear to be documented elsewhere.
Steps to reproduce the issue
Consider
m = ConcreteModel()
m.x = Var([0,1,2,3], domain=Binary)
m.weight=Constraint(expr=sum(m.x[i] for i in list(range(4)))<= 3.5)
m.value=Objective(expr=sum(m.x[i] for i in range(4)), sense=maximize)
m.write("example.lp")
solver = SolverFactory("cbc")
solver.options={"initialSolve":""}
solver.solve(m, tee=True)
Its optimal solution is 3.5, but it is solved as a MIP and thus the solution is 3 .
Log
Welcome to the CBC MILP Solver
Version: 2.10.7
Build Date: Feb 14 2022
command line - /usr/bin/cbc -printingOptions all -import /tmp/tmpb1phpxks.pyomo.lp **-initialSolve -stat=1 -solve** -solu /tmp/tmpb1phpxks.pyomo.soln (default strategy 1)
Option for printingOptions changed from normal to all
CoinLpIO::readLp(): Maximization problem reformulated as minimization
Coin0009I Switching back to maximization to get correct duals etc
Presolve 0 (-2) rows, 0 (-5) columns and 0 (-5) elements
Empty problem - 0 rows, 0 columns and 0 elements
Optimal - objective value 3.5
After Postsolve, objective 3.5, infeasibilities - dual 0 (0), primal 0 (0)
Optimal objective 3.5 - 0 iterations time 0.002, Presolve 0.00
Presolve 1 (-1) rows, 4 (-1) columns and 4 (-1) elements
Statistics for presolved model
Original problem has 4 integers (4 of which binary)
Presolved problem has 4 integers (4 of which binary)
==== 0 zero objective 1 different
4 variables have objective of 1
==== absolute objective values 1 different
4 variables have objective of 1
==== for integers 0 zero objective 1 different
4 variables have objective of 1
==== for integers absolute objective values 1 different
4 variables have objective of 1
===== end objective counts
Problem has 1 rows, 4 columns (4 with objective) and 4 elements
There are 4 singletons with objective
Column breakdown:
0 of type 0.0->inf, 0 of type 0.0->up, 0 of type lo->inf,
0 of type lo->up, 0 of type free, 0 of type fixed,
0 of type -inf->0.0, 0 of type -inf->up, 4 of type 0.0->1.0
Row breakdown:
0 of type E 0.0, 0 of type E 1.0, 0 of type E -1.0,
0 of type E other, 0 of type G 0.0, 0 of type G 1.0,
0 of type G other, 0 of type L 0.0, 0 of type L 1.0,
1 of type L other, 0 of type Range 0.0->1.0, 0 of type Range other,
0 of type Free
Continuous objective value is 3.5 - 0.00 seconds
Cgl0004I processed model has 0 rows, 0 columns (0 integer (0 of which binary)) and 0 elements
Cbc3007W No integer variables - nothing to do
Cuts at root node changed objective from -3 to -1.79769e+308
Probing was tried 0 times and created 0 cuts of which 0 were active after adding rounds of cuts (0.000 seconds)
Gomory was tried 0 times and created 0 cuts of which 0 were active after adding rounds of cuts (0.000 seconds)
Knapsack was tried 0 times and created 0 cuts of which 0 were active after adding rounds of cuts (0.000 seconds)
Clique was tried 0 times and created 0 cuts of which 0 were active after adding rounds of cuts (0.000 seconds)
MixedIntegerRounding2 was tried 0 times and created 0 cuts of which 0 were active after adding rounds of cuts (0.000 seconds)
FlowCover was tried 0 times and created 0 cuts of which 0 were active after adding rounds of cuts (0.000 seconds)
TwoMirCuts was tried 0 times and created 0 cuts of which 0 were active after adding rounds of cuts (0.000 seconds)
ZeroHalf was tried 0 times and created 0 cuts of which 0 were active after adding rounds of cuts (0.000 seconds)
Result - Optimal solution found
Objective value: 3.00000000
Enumerated nodes: 0
Total iterations: 0
Time (CPU seconds): 0.00
Time (Wallclock seconds): 0.00
Total time (CPU seconds): 0.00 (Wallclock seconds): 0.00
Solving the example.lp
file with CBC CLI, specifying just "initialSolve" works as intended.
$ cbc example.lp -initialSolve
Welcome to the CBC MILP Solver
Version: 2.10.7
Build Date: Feb 14 2022
command line - cbc example.lp -initialSolve (default strategy 1)
CoinLpIO::readLp(): Maximization problem reformulated as minimization
Coin0009I Switching back to maximization to get correct duals etc
Presolve 0 (-2) rows, 0 (-5) columns and 0 (-5) elements
Empty problem - 0 rows, 0 columns and 0 elements
Optimal - objective value 3.5
After Postsolve, objective 3.5, infeasibilities - dual 0 (0), primal 0 (0)
Optimal objective 3.5 - 0 iterations time 0.002, Presolve 0.00
Total time (CPU seconds): 0.00 (Wallclock seconds): 0.00
while adding -solve
after it recreates the issue
$ cbc example.lp -initialSolve -solve
Welcome to the CBC MILP Solver
Version: 2.10.7
Build Date: Feb 14 2022
command line - cbc example.lp -initialSolve -solve (default strategy 1)
CoinLpIO::readLp(): Maximization problem reformulated as minimization
Coin0009I Switching back to maximization to get correct duals etc
Presolve 0 (-2) rows, 0 (-5) columns and 0 (-5) elements
Empty problem - 0 rows, 0 columns and 0 elements
Optimal - objective value 3.5
After Postsolve, objective 3.5, infeasibilities - dual 0 (0), primal 0 (0)
Optimal objective 3.5 - 0 iterations time 0.002, Presolve 0.00
Continuous objective value is 3.5 - 0.00 seconds
Cgl0004I processed model has 0 rows, 0 columns (0 integer (0 of which binary)) and 0 elements
Cbc3007W No integer variables - nothing to do
Cuts at root node changed objective from -3 to -1.79769e+308
Probing was tried 0 times and created 0 cuts of which 0 were active after adding rounds of cuts (0.000 seconds)
Gomory was tried 0 times and created 0 cuts of which 0 were active after adding rounds of cuts (0.000 seconds)
Knapsack was tried 0 times and created 0 cuts of which 0 were active after adding rounds of cuts (0.000 seconds)
Clique was tried 0 times and created 0 cuts of which 0 were active after adding rounds of cuts (0.000 seconds)
MixedIntegerRounding2 was tried 0 times and created 0 cuts of which 0 were active after adding rounds of cuts (0.000 seconds)
FlowCover was tried 0 times and created 0 cuts of which 0 were active after adding rounds of cuts (0.000 seconds)
TwoMirCuts was tried 0 times and created 0 cuts of which 0 were active after adding rounds of cuts (0.000 seconds)
ZeroHalf was tried 0 times and created 0 cuts of which 0 were active after adding rounds of cuts (0.000 seconds)
Result - Optimal solution found
Objective value: 3.00000000
Enumerated nodes: 0
Total iterations: 0
Time (CPU seconds): 0.00
Time (Wallclock seconds): 0.00
Total time (CPU seconds): 0.00 (Wallclock seconds): 0.00