Description
Summary
Hello,
I was trying to use a warmstart with cbc but I had the error:
Colum1: Third column in mipstart file should be numeric, ignoring.
...
And finally:
Cbc0045I Warning: mipstart values could not be used to build a solution.
I know the warmstart was correct because it was ok with cplex. So I started to debug. It comes from the method _write_soln_file
in the CBCSHELL class (solvers > plugins > CBCplugin.py).
column_index = 0
with open(filename, 'w') as solnfile:
for var in instance.component_data_objects(Var):
# Cbc only expects integer variables with non-zero
# values for mipstart.
if (
var.value
and (var.is_integer() or var.is_binary())
and (id(var) in byObject)
):
name = byObject[id(var)]
solnfile.write('{} {} {}\n'.format(column_index, name, var.value))
# Cbc ignores column indexes, so the value does not matter.
column_index += 1
There are 2 problems:
- If the variable is a Real, it is not considered in the warmstart but the latest stable version of cbc (2.10.7) accepts it
- If the variable is Binary, and is set to True in the warmstart, pyomo writes "True" but cbc can only read numeric valid, so it should be 1
Steps to reproduce the issue
$ python pyomo_cbc_warmstart_bug.py
# pyomo_cbc_warmstart_bug.py
from pyomo.environ import (
ConcreteModel,
Var,
Integers,
Binary,
Reals,
Objective,
Constraint,
SolverFactory,
maximize
)
m = ConcreteModel()
# decision variables
m.x1 = Var(domain=Integers, name="x1", bounds=(0, 10))
m.x2 = Var(domain=Reals, name="x2", bounds=(0, 10))
m.x3 = Var(domain=Binary, name="x3")
# objective function
m.OBJ = Objective(expr=(3*m.x1 + 2*m.x2 + 4*m.x3), sense=maximize)
# constraints
m.C1 = Constraint(expr=m.x1 + m.x2 <= 9)
m.C2 = Constraint(expr=3*m.x1 + m.x2 <= 18)
m.C3 = Constraint(expr=m.x1 <= 7)
m.C4 = Constraint(expr=m.x2 <= 6)
# MIP start
m.x1 = 4
m.x2 = 4.5
m.x3 = True
# solving process
SolverFactory('cbc').solve(m, tee=True, warmstart=True).write()
Error Message
$ command line - /usr/bin/cbc -printingOptions all -import /tmp/tmpjeb6cedi.pyomo.lp -mipstart /tmp/tmpgkdx66mk.cbc.soln -stat=1 -solve -solu /tmp/tmpjeb6cedi.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
$ opening mipstart file /tmp/tmpgkdx66mk.cbc.soln.
$ Reading: /tmp/tmpgkdx66mk.cbc.soln, line 2 - Third column in mipstart file should be numeric, ignoring.
$ MIPStart values read for 1 variables.
...
The important part is that The third column should be numeric, (in this case, it is "True")
And only 1 variable was read, the Integer one, and neither the Real one nor the Binary one.
Information on your system
Pyomo version: 6.8.2
Python version: 3.10.12
Operating system: Ubuntu 22.04
How Pyomo was installed (PyPI, conda, source): pip
Solver (if applicable): cbc 2.10.7
Additional information
I can suggest a correction, maybe I should directly have done a PR, I'm not sure.
column_index = 0
with open(filename, 'w') as solnfile:
for var in instance.component_data_objects(Var):
# Cbc only expects variables with non-zero
# values for mipstart.
if (
var.value
and (var.is_integer() or var.is_binary() or var.is_continuous())
and (id(var) in byObject)
):
name = byObject[id(var)]
if var.is_binary():
var_value = 1
else:
var_value = var.value
solnfile.write('{} {} {}\n'.format(column_index, name, var_value))
# Cbc ignores column indexes, so the value does not matter.
column_index += 1