DOcplexException: Expecting sequence of constraints, got: True at position 0

1.6k Views Asked by At

I am using docplex in google collab with python

For the following LP, the some of the decision variables are predetermined, and the LP needs to be solved for that. It's a sequencing problem and the sequence is a set of given values. The other decision variables will be optimized based on this.

#Define the decision variables

x = cost.continuous_var_dict(P, name='x') # The landing time of plane i
alpha = cost.continuous_var_dict(P, name='alpha') # How much of deviation of landing before target 
landing time for plane i
beta = cost.continuous_var_dict(P, name='beta') # How much of deviation of landing after target 
landing time for plane i
delta = cost.binary_var_dict(plane_matrix,name="delta") # 1 if plane i lands before plane j; 0 o/w
z = cost.binary_var_dict(plane_matrix, name="z") # 1 if plane i and j land on same runway; 0 o/w
y = cost.binary_var_dict(plane_runway, name="y") # 1 if plane j lands on runway r; 0 o/w

So the given values are for the delta, there is a constraint to satisfy this which is as follows

# Constraint 2: either plane i lands before j or j lands before i
cost.add_constraints(delta[i,j] + delta[j,i] == 1 for i in P for j in P if j!=i)

However, I get an error as follows:

DOcplexException                          Traceback (most recent call last)
<ipython-input-23-441ca8cbb9d0> in <module>()
      3 
      4 # #Constraint 2: either i lands before j or j lands before i
----> 5 cost.add_constraints(delta[i,j] + delta[j,i] == 1 for i in P for j in P if j!=i)
      6 
      7 # #Constraint 3: Each plane can land on only one runway

 4 frames
 /usr/local/lib/python3.6/dist-packages/docplex/mp/model.py in add_constraints(self, cts, names)
 3514             return self._lfactory._new_constraint_block2(cts, names)
 3515         else:
 -> 3516             return self._lfactory._new_constraint_block1(cts)
 3517 
 3518 

/usr/local/lib/python3.6/dist-packages/docplex/mp/mfactory.py in _new_constraint_block1(self, cts)
891                     posted_cts.append(ct)
892         else:
--> 893             checker.typecheck_constraint_seq(ctseq, check_linear=True, accept_range=True)
894             for ct in ctseq:
895                 if filterfn(ct, ctname=None, check_for_trivial_ct=check_trivial, 
arg_checker=checker):

/usr/local/lib/python3.6/dist-packages/docplex/mp/tck.py in typecheck_constraint_seq(self, cts, 
check_linear, accept_range)
354         for i, ct in enumerate(checked_cts_list):
355             if not isinstance(ct, AbstractConstraint):
--> 356                 self.fatal("Expecting sequence of constraints, got: {0!r} at position {1}", 
ct, i)
357             if check_linear:
358                 if not ct.is_linear():

/usr/local/lib/python3.6/dist-packages/docplex/mp/tck.py in fatal(self, msg, *args)
229 
230     def fatal(self, msg, *args):
--> 231         self._logger.fatal(msg, args)
232 
233     def error(self, msg, *args):  # pragma: no cover

/usr/local/lib/python3.6/dist-packages/docplex/mp/error_handler.py in fatal(self, msg, args)
208         resolved_message = resolve_pattern(msg, args)
209         docplex_error_stop_here()
--> 210         raise DOcplexException(resolved_message)
211 
212     def fatal_limits_exceeded(self):

DOcplexException: Expecting sequence of constraints, got: True at position 0

Please Help. I really can't figure out why that is an issue. Thank you

2

There are 2 best solutions below

0
On

Are you sure that all your elements in delta are actually decision variables? This code works fine for me:

with Model() as m:
    P = range(10)
    delta = m.binary_var_dict((i,j) for i in P for j in P)
    m.add_constraints(delta[i,j] + delta[j,i] == 1 for i in P for j in P if j!=i)

However, I can provoke your error if I do something like this (I replace some elements in delta by plain numbers):

with Model() as m:
    P = range(10)
    delta = m.binary_var_dict((i,j) for i in P for j in P)
    delta[0,1] = 0.5
    delta[1,0] = 0.5
    m.add_constraints(delta[i,j] + delta[j,i] == 1 for i in P for j in P if j!=i)

In that case some of the instantiations of delta[i,j] + delta[j,i] == 1 do no longer contain any decision variables and thus the == operator does not create a constraint but is just evaluated in a boolean context and gives True.

Instead of replacing variables by numbers, you can just fix those variables to a value but setting lower and upper bound of the variable:

delta[0,1].set_lb(0.5)
delta[0,1].set_ub(0.5)
delta[1,0].set_lb(0.5)
delta[1,0].set_ub(0.5)

That way your statement will still create constraints. A constraint with only fixed variables will be removed in presolve.

0
On

To complement Daniel's answer: note that Model.add_constraints (final s) expects an iterable object with constraints, so it won't accept one single constraint. If you want to pass either an iterable or a single constraint, use 'Model.add()' which accepts both.