Paghillect
Paghillect

Reputation: 848

CPLEX quadratic objective CPLEX Error 1017: Not available for mixed-integer problems

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 ls 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:

  1. The linear objective works without a problem in their presence
  2. I still get the same error when I comment them out using the quadratic objective.

What am I missing here?

Upvotes: 1

Views: 1029

Answers (1)

rkersh
rkersh

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

Related Questions