coin-or / CyLP

A Python interface to CLP, CBC, and CGL to solve LPs and MIPs.
Other
182 stars 69 forks source link

Cylp model for lower bound to be numpy matrix in the constraint #111

Open abdxyz opened 3 years ago

abdxyz commented 3 years ago

It seems that Cylp model doesn't support both the upper bound and lower bound to be numpy array. Do you plan to add this feature?

import numpy as np
from cylp.cy import CyClpSimplex
from cylp.py.modeling.CyLPModel import CyLPArray

A = [[50, 31], [-3, 2, ]]
b_l = [-10000, -10000]
b_u = [250, 4]
c = [-1, -0.64]
l = [1, 0]
u = [10000, 10000]

model = CyClpSimplex()
x = model.addVariable('x', len(c))
A = np.matrix(A)
b_l = np.matrix(b_l)
# b_l = -1000
b_u = np.matrix(b_u)
l = CyLPArray(l)
u = CyLPArray(u)
c = CyLPArray(c)
model += (b_l <= A * x <= b_u)
model += l <= x <= u
model.objective = c * x

model.primal()
# print(model.getBasisStatus())
print(model.primalConstraintSolution)  # row value
print(model.primalVariableSolutionAll)  # row slack

print(model.dualConstraintSolution)  # dual variable
print(model.dualVariableSolution)  # dual slack

If I run this code, it will get the following error.

Traceback (most recent call last):
  File "/media/dxy/mathu-solver/cylp_tesp.py", line 21, in <module>
    model += (b_l <= A * x <= b_u)
ValueError: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all()
KeithWM commented 2 years ago

I think the problem is that the pythonic a <= b <= c isn't being interpreted correctly. I'm also not sure if that syntax works for plain numpy arrays outside of CyLP. A workaround is to specify the upper and lower bounds separately:

import numpy as np
from cylp.cy import CyClpSimplex
from cylp.py.modeling.CyLPModel import CyLPArray

A = [[50, 31], [-3, 2, ]]
b_l = [-10000, -10000]
b_u = [250, 4]
c = [-1, -0.64]
l = [1, 0]
u = [10000, 10000]

model = CyClpSimplex()
x = model.addVariable('x', len(c))
A = np.matrix(A)
b_l = np.matrix(b_l, dtype=float)
# b_l = -1000
b_u = np.matrix(b_u, dtype=float)
l = CyLPArray(l)
u = CyLPArray(u)
c = CyLPArray(c)
model += A * x <= b_u
model += A * x >= b_l
model += l <= x <= u
model.objective = c * x

model.primal()
# print(model.getBasisStatus())
print(model.primalConstraintSolution)  # row value
print(model.primalVariableSolutionAll)  # row slack

print(model.dualConstraintSolution)  # dual variable
print(model.dualVariableSolution)  # dual slack

Note that for both the upper and lower bounds the expression A*x is on the left-hand side, otherwise it fails. I also had to specify the types to b_l and b_u for it to work. Don't ask me why.

Just realized how old the post was, hope this is useful nevertheless.