Search code examples
optimizationmathematical-optimizationpulpcoin-or-cbc

PuLP - COIN-CBC error: How to add constraint with double inequality and relaxation?


I want to add this set of constraints:

-M(1-X_(i,j,k,n) )≤S_(i,j,k,n)-ToD_(i,j,k,n)≤M(1-X_(i,j,k,n) ) ∀i,j,k,n

Where M is a big number, S is a integer variable that takes values between 0 and 1440. ToD is a 4-dimensional matrix that takes values from an Excel sheet. X i dual variable, it takes as values 0-1.

I try to implement in code as following:

for n in range(L):
    for k in range(M):
        for i in range(N):
            for j in range(N):
                if (i != START_POINT_S & i != END_POINT_T & j != START_POINT_S & j != END_POINT_T):
                    prob += (-BIG_NUMBER*(1-X[i][j][k][n])) <= (S[i][j][k][n] - ToD[i][j][k][n]), ""

and another constraint as follows:

for i in range(N):
    for j in range(N):
        for k in range(M):
            for n in range(L):
                if (i != START_POINT_S & i != END_POINT_T & j != START_POINT_S & j != END_POINT_T):
                    prob += S[i][j][k][n] - ToD[i][j][k][n] <= BIG_NUMBER*(1-X[i][j][k][n]), ""

According to my experience, in code, those two constraints are totally equivalent to what we want. The problem is that PuLP and CBC won't accept them. The produce the following errors:

PuLP:

Traceback (most recent call last):
  File "basic_JP.py", line 163, in <module>
    prob.solve()
  File "C:\Users\dimri\Desktop\Filesystem\Projects\deliverable_B4\lib\site-packa
ges\pulp\pulp.py", line 1643, in solve
    status = solver.actualSolve(self, **kwargs)
  File "C:\Users\dimri\Desktop\Filesystem\Projects\deliverable_B4\lib\site-packa
ges\pulp\solvers.py", line 1303, in actualSolve
    return self.solve_CBC(lp, **kwargs)
  File "C:\Users\dimri\Desktop\Filesystem\Projects\deliverable_B4\lib\site-packa
ges\pulp\solvers.py", line 1366, in solve_CBC
    raise PulpSolverError("Pulp: Error while executing "+self.path)
pulp.solvers.PulpSolverError: Pulp: Error while executing C:\Users\dimri\Desktop
\Filesystem\Projects\deliverable_B4\lib\site-packages\pulp\solverdir\cbc\win\64\
cbc.exe

and CBC:

Welcome to the CBC MILP Solver
Version: 2.9.0
Build Date: Feb 12 2015

command line - C:\Users\dimri\Desktop\Filesystem\Projects\deliverable_B4\lib\sit
e-packages\pulp\solverdir\cbc\win\64\cbc.exe 5284-pulp.mps branch printingOption
s all solution 5284-pulp.sol (default strategy 1)
At line 2 NAME          MODEL
At line 3 ROWS
At line 2055 COLUMNS
Duplicate row C0000019 at line 10707 <     X0001454  C0000019  -1.000000000000e+
00 >
Duplicate row C0002049 at line 10708 <     X0001454  C0002049  -1.000000000000e+
00 >
Duplicate row C0000009 at line 10709 <     X0001454  C0000009   1.000000000000e+
00 >
Duplicate row C0001005 at line 10710 <     X0001454  C0001005   1.000000000000e+
00 >
At line 14153 RHS
At line 16204 BOUNDS
Bad image at line 17659 <  UP BND       X0001454   1.440000000000e+03 >
At line 18231 ENDATA
Problem MODEL has 2050 rows, 2025 columns and 5968 elements
Coin0008I MODEL read with 5 errors
There were 5 errors on input
** Current model not valid
Option for printingOptions changed from normal to all
** Current model not valid
No match for 5284-pulp.sol - ? for list of commands
Total time (CPU seconds):       0.02   (Wallclock seconds):       0.02

I don't know what's the problem, any help? I am new to this, if information are not enough let me know what I should add.


Solution

  • Alright, I have searched for hours, but right after I posted this question I found the answer. These kinds of problems are mainly because of the names of the variables or the constraints. That is what caused something to duplicate. I am really not used to that kind of software that is why it took me so long to find and answer. Anyway, the problem for me was when I was defining the variables:

    # define X[i,j,k,n]
    lower_bound_X = 0 # lower bound for variable X
    upper_bound_X = 1 # upper bound for variable X
    X = LpVariable.dicts(name="X",
                         indexs=(range(N), range(N), range(M), range(L)),     
                         lowBound=lower_bound_X,
                         upBound=upper_bound_X,
                         cat=LpInteger)
    

    and

    # define S[i,j,k,n]
    lower_bound_S = 0       # lower bound for variable S
    upper_bound_S = 1440    # upper bound for variable S
    S = LpVariable.dicts(name="X", 
                         indexs=(range(N), 
                         range(N), range(M), range(L)), 
                         lowBound=lower_bound_S, 
                         upBound=upper_bound_S, 
                         cat=LpInteger)
    

    As you see in the definition of S I obviously forgot to change the name of the variable to S because I copy-pasted it. Anyway, the right way to define S is like this:

    # define S[i,j,k,n]
    lower_bound_S = 0       # lower bound for variable S
    upper_bound_S = 1440    # upper bound for variable S
    S = LpVariable.dicts(name="S", 
                         indexs=(range(N), range(N), range(M), range(L)), 
                         lowBound=lower_bound_S, 
                         upBound=upper_bound_S, 
                         cat=LpInteger)
    

    This is how I got my code running.