Reputation: 848
I'm trying to solve the following linear program using cplex:
def generate_linear_program(self):
problem = cplex.Cplex()
problem.objective.set_sense(problem.objective.sense.minimize)
for index, track in enumerate(self.tracks):
tokens = track['track'].split('_')
problem.variables.add(names = ['c' + str(tokens[1])], ub = [1.0], types = ['C'])
problem.variables.add(names = ['e' + str(index) for index, param in enumerate(self.params)],
types = ['C'] * len(self.params),
ub = [param['c'] - param['u'] * param['r'] for param in self.params],
lb = [param['c'] - param['u'] * param['r'] - param['c'] * sum(param['tracks'][track] for track in param['tracks']) for param in self.params])
problem.variables.add(names = ['l' + str(index) for index, param in enumerate(self.params)],
#obj = [1.0] * len(self.params),
types = ['C'] * len(self.params))
problem.objective.set_quadratic([0.0] * len(self.tracks) + [1.0] * len(self.params) + [0.0] * len(self.params))
# add some linear constraints here
problem.solve()
When I call solve()
Cplex complains with the error message CPLEX Error 1017: Not available for mixed-integer problems
. If I remove the quadratic objective above and instead add a linear objective by uncommenting the commented line of code above (obj = [1.0] * len(self.params),
), it works without a problem.
Stack trace:
File "/share/src/python/kmer/programming.py", line 373, in solve
problem.solve()
File "/home/user/local/cplex/lib/python/cplex/__init__.py", line 998, in solve
_proc.qpopt(self._env._e, self._lp)
File "/home/user/local/cplex/lib/python/cplex/_internal/_procedural.py", line 499, in qpopt
check_status(env, status)
File "/home/user/local/cplex/lib/python/cplex/_internal/_procedural.py", line 171, in __call__
raise CplexSolverError(error_string, env, status)
cplex.exceptions.errors.CplexSolverError: CPLEX Error 1017: Not available for mixed-integer problems.
To get a better idea of what is happening here, when the objective is quadratic I'm trying to minimize the sum of the squares of some error terms. When the objective becomes linear, I'm minimizing the sum of the absolute values of those terms. The variables whose names start with e
are the error terms and the l
s will become their absolute value through these constraints:
for index, params in enumerate(self.params):
problem.linear_constraints.add(
lin_expr = [cplex.SparsePair(
ind = [len(self.tracks) + len(self.params) + index, len(self.tracks) + index],
val = [1.0, 1.0],
)],
rhs = [0],
senses = ['G']
)
problem.linear_constraints.add(
lin_expr = [cplex.SparsePair(
ind = [len(self.tracks) + len(self.params) + index, len(self.tracks) + index],
val = [1.0, -1.0],
)],
rhs = [0],
senses = ['G']
)
The l<index>
variables are actually useless in presence of the quadratic objective.
There are other linear constraints which I can't include here yet they are definitely not the cause of the problem because of the two following reasons:
What am I missing here?
Upvotes: 1
Views: 1029
Reputation: 4465
It's easy to miss the following note in the documentation for Cplex.variables.add:
If types is specified, the problem type will be a MIP, even if all variables are specified to be continuous.
If you remove the optional types
argument from your calls to Cplex.variables.add
, the problem should go away. For example, instead of:
problem.variables.add(names = ['c' + str(tokens[1])], ub = [1.0], types = ['C'])
use:
problem.variables.add(names = ['c' + str(tokens[1])], ub = [1.0])
The reason it works when you have a linear objective is that it's being passed into CPXmipopt
, as a convenience, after failing CPXlpopt
with a CPXERR_NOT_FOR_MIP
(error 1017). Whereas, when we call CPXqpopt
, this logic is not applied.
Upvotes: 1