def test_cylp_packaging(self): # https://github.com/coin-or/CyLP#modeling-example s = CyClpSimplex() # Add variables x = s.addVariable('x', 3) y = s.addVariable('y', 2) # Create coefficients and bounds A = np.matrix([[1., 2., 0],[1., 0, 1.]]) B = np.matrix([[1., 0, 0], [0, 0, 1.]]) D = np.matrix([[1., 2.],[0, 1]]) a = CyLPArray([5, 2.5]) b = CyLPArray([4.2, 3]) x_u= CyLPArray([2., 3.5]) # Add constraints s += A * x <= a s += 2 <= B * x + D * y <= b s += y >= 0 s += 1.1 <= x[1:3] <= x_u # Set the objective function c = CyLPArray([1., -2., 3.]) s.objective = c * x + 2 * y.sum() # Solve using primal Simplex s.primal() print s.primalVariableSolution['x']
def setUp(self): 'Test remove constraint' model = CyLPModel() x = model.addVariable('x', 3) y = model.addVariable('y', 2) A = csc_matrixPlus(([1, 2, 1, 1], ([0, 0, 1, 1], [0, 1, 0, 2])), shape=(2, 3)) B = csc_matrixPlus(([1, 1], ([0, 1], [0, 2])), shape=(2, 3)) D = np.matrix([[1., 2.], [0, 1]]) a = CyLPArray([3, 2.5]) b = CyLPArray([4.2, 3]) x_u = CyLPArray([2., 3.5]) model.addConstraint(A * x <= a, 'res1') model.addConstraint(2 <= B * x + D * y <= b, 'res2') model.addConstraint(y >= 0) model.addConstraint(1.1 <= x[1:3] <= x_u) model.addConstraint(x[0] >= 0.1) c = CyLPArray([1., -2., 3.]) model.objective = c * x + 2 * y[0] + 2 * y[1] s = CyClpSimplex(model) self.s = s self.x = x self.y = y
def solve(filename, method): s = CyClpSimplex() s.readMps(filename) s.preSolve(feasibilityTolerance=10**-8) #s.useCustomPrimal(1) if method == 'd': pivot = DantzigPivot(s) elif method == 'l': pivot = LIFOPivot(s) elif method == 'm': pivot = MostFrequentPivot(s) elif method == 'p': pivot = PositiveEdgePivot(s) else: print('Unkown solution method.') sys.exit(1) s.setPivotMethod(pivot) #s.setPerturbation(50) start = clock() s.primal() print('Problem solved in %g seconds.' % (clock() - start)) return s.objectiveValue
def QPModel(self, addW=False): A = self.A c = self.c s = CyClpSimplex() x = s.addVariable('x', self.nCols) if addW: w = s.addVariable('w', self.nCols) s += A * x >= 1 n = self.nCols if not addW: s += 0 <= x <= 1 else: s += x + w == 1 s += 0 <= w <= 1 ## s += -1 <= x <= 1 s.objective = c * x if addW: G = sparse.lil_matrix((2 * n, 2 * n)) for i in range(n / 2, n): #xrange(n-1): G[i, i] = 1 G[2 * n - 1, 2 * n - 1] = 10**-10 else: G = sparse.lil_matrix((n, n)) for i in range(n / 2, n): #xrange(n-1): G[i, i] = 1 s.Hessian = G return s
def test_write(self): self.model = CyLPModel() model = self.model x = model.addVariable('x', 3, isInt=True) y = model.addVariable('y', 2) A = np.matrix([[1., 2., 0], [1., 0, 1.]]) B = np.matrix([[1., 0, 0], [0, 0, 1.]]) D = np.matrix([[1., 2.], [0, 1]]) a = CyLPArray([5, 2.5]) b = CyLPArray([4.2, 3]) x_u = CyLPArray([2., 3.5]) model.addConstraint(A * x <= a) model.addConstraint(2 <= B * x + D * y <= b) model.addConstraint(y >= 0) model.addConstraint(1.1 <= x[1:3] <= x_u) c = CyLPArray([1., -2., 3.]) model.objective = c * x + 2 * y.sum() self.s = CyClpSimplex(model) s = self.s s.writeMps("cylptest.mps") os.remove("cylptest.mps") s.writeMps("cylptest.lp") os.remove("cylptest.lp")
def test_variableBoundSubset(self): m = self.model x = self.x y = m.addVariable('y', 4) z = m.addVariable('z', 5) A = self.A b = self.b k = m.addVariable('k', 2) s = CyClpSimplex(m) s.setColumnLowerSubset(np.array([1, 2], np.int32), np.array([3, 5, 8], np.int32), np.array([3.2, 3.1, 2.2])) self.assertTrue(s.variablesLower[3] != 3.2) self.assertTrue(s.variablesLower[5] == 3.1) self.assertTrue(s.variablesLower[8] == 2.2) s.setColumnUpperSubset(np.array([0, 2], np.int32), np.array([0, 4, 10], np.int32), np.array([3.2, 3.1, 2.2])) self.assertTrue(s.variablesUpper[0] == 3.2) self.assertTrue(s.variablesUpper[4] != 3.1) self.assertTrue(s.variablesUpper[10] == 2.2)
def solve(A, rhs, ct=None, logLevel=0, extnd=False, basis=False, mps_file=None): s = CyClpSimplex() s.logLevel = logLevel lp_dim = A.shape[1] x = s.addVariable('x', lp_dim) A = np.matrix(A) rhs = CyLPArray(rhs) s += A * x >= rhs s += x[lp_dim - 1] >= 0 s.objective = x[lp_dim - 1] nnz = np.count_nonzero(A) if not mps_file is None: s.writeMps(mps_file) return None logging.debug(f"TASK SIZE XCOUNT: {lp_dim} GXCOUNT: {len(rhs)}") s.primal() k = list(s.primalConstraintSolution.keys())[0] k2 =list(s.dualConstraintSolution.keys())[0] q = s.dualConstraintSolution[k2] logging.debug(f"{s.getStatusString()} objective: {s.objectiveValue}") logging.debug(f"nonzeros rhs: {np.count_nonzero(s.primalConstraintSolution[k])}") logging.debug(f"nonzeros dual: {np.count_nonzero(s.dualConstraintSolution[k2])}") if extnd and not basis: return s.primalVariableSolution['x'],s.primalConstraintSolution[k],s.dualConstraintSolution[k2] elif not extnd and basis: basis = s.getBasisStatus() return s.primalVariableSolution['x'],*basis else: return s.primalVariableSolution['x']
def _base_branch(self: T, idx: int) -> Dict[str, T]: """ Creates two new copies of the node with new bounds placed on the variable with index <idx>, one with the variable's lower bound set to the ceiling of its current value and another with the variable's upper bound set to the floor of its current value. :param idx: index of variable to branch on :return: dict of Nodes with the new bounds keyed by direction they branched """ assert self.lp_feasible, 'must solve before branching' assert idx in self._integerIndices, 'must branch on integer index' b_val = self.solution[idx] assert self._is_fractional( b_val), "index branched on must be fractional" # get end basis to warm start the kiddos # appears to be tuple (variable statuses, slack statuses) basis = self._lp.getBasisStatus() # when branching down set floor as upper bound for given index u = self._lp.variablesUpper.copy() u[idx] = floor(b_val) down_lp = CyClpSimplex() down_lp.loadProblem(self._lp.matrix, self._lp.variablesLower, u, self._lp.objective, self._lp.constraintsLower, self._lp.constraintsUpper) down_lp.setBasisStatus(*basis) # warm start # when branching up set ceiling as lower bound for given index l = self._lp.variablesLower.copy() l[idx] = ceil(b_val) up_lp = CyClpSimplex() up_lp.loadProblem(self._lp.matrix, l, self._lp.variablesUpper, self._lp.objective, self._lp.constraintsLower, self._lp.constraintsUpper) up_lp.setBasisStatus(*basis) # warm start # return instances of the subclass that calls this function return { 'down': type(self)(down_lp, self._integerIndices, self.objective_value, idx, 'down', b_val, self.depth + 1), 'up': type(self)(up_lp, self._integerIndices, self.objective_value, idx, 'up', b_val, self.depth + 1) }
def main(): if len(sys.argv) != 2: print "Invalid number of arguments!\nUsage: \npython ", sys.argv[ 0], " <INPUT_FILE>\n" quit() infile = sys.argv[1] with open(infile) as f: m, n = [int(x) for x in next(f).split() ] # m = number of points in X, n = number of points in Y e = int(next(f)) # e = number of edges incidence_matrix = np.zeros((m, n)) edge_matrix = np.zeros((m + n, e)) weights = [] i = 1 for line in f: a, b, weight = [int(x) for x in line.split()] if a > m or b > n: print "Invalid vertex id. Aborting!" quit() incidence_matrix[a - 1][b - 1] = weight edge_matrix[a - 1][i - 1] = 1 edge_matrix[m + b - 1][i - 1] = 1 weights.append(weight) i += 1 print "Adjacency Matrix:" print incidence_matrix print "Edge Matrix:" print edge_matrix print "Weights:" print weights s = CyClpSimplex() # Add variables x = s.addVariable('x', e) # Create coefficients and bounds A = np.matrix( edge_matrix[0:m]) # vertices corresponding to the set X (Left) B = np.matrix( edge_matrix[m:]) # vertices corresponding to the set Y (Right) a = CyLPArray(np.ones(m)) b = CyLPArray(np.ones(n)) # Add constraints s += A * x <= a # all vertices in set X must be perfectly matched s += B * x <= b # matching should be valid s += 0 <= x <= 1 # Set the objective function s.objective = CyLPArray(np.array(weights) * -1) * x # Solve using primal Simplex s.primal() print s.primalVariableSolution['x'] for i in range(len(s.primalVariableSolution['x'])): if s.primalVariableSolution['x'][i] > 1e-3: print "Edge ", 1 + i, ": Weight ", weights[i]
def solve_cylp(self, verbose: bool = True, **kwargs): """ Inspired by the cvxpy cbc layer, ty :) """ from cylp.cy import CyClpSimplex from cylp.py.modeling.CyLPModel import CyLPModel, CyLPArray cons = self.combine_cons() n = int(self.next_var_idx - 1) # Number of variables. # Maximize c@x s.t. A@x <= b (variable bounds done by constraints) c = self.objective.rawdense().squeeze()[ 1:n + 1] # Objective coefficients, no constants. A = cons.raw()[:, 1:n + 1] # Constraint coefficients. b = cons[:, 0].rawdense().squeeze() * -1.0 # Constraint constants. model = CyLPModel() x = model.addVariable("x", n) # Variables model.objective = c # I hate this so much. Casting A to a matrix causes A.__mul__ to be # be called, which raises NotImplemented, so then x.__rmul__ is called # which gets the job done. Using np.matmul or np.dot doesn't # trigger x.__rmul__ # model.addConstraint(np.matrix(A) * x <= CyLPArray(b)) # Works model.addConstraint(x.__rmul__(A) <= CyLPArray(b)) model = CyClpSimplex(model) # Convert model model.logLevel = 0 if not verbose else model.logLevel is_integer_model = not np.isclose(self.int_vars.sum(), 0) if is_integer_model: model.setInteger(x[np.argwhere(self.int_vars)]) cbcModel = model.getCbcModel() cbcModel.solve() status = cbcModel.status solmodel = cbcModel else: status = model.initialSolve() solmodel = model sol_x = np.hstack( # Pad back to original shape ( [1.0], # Special constant 1.0 variable. solmodel.primalVariableSolution["x"], # Actual solution np.zeros(self.max_vars - n - 1), # Unused vars )) solution = { "status": status, "primal": sol_x, "value": solmodel.objectiveValue } return solution, solution["primal"]
def model(self): A = self.A c = self.c s = CyClpSimplex() x = s.addVariable('x', self.nCols) s += A * x >= 1 s += 0 <= x <= 1 s.objective = c * x return s
def test_1(self): """simplest QP test""" s = CyClpSimplex() s.readMps(join(currentFilePath, '../input/hs35.qps')) #self.assertTrue(abs(cbcModel.objectiveValue - 3089.0) < 10 ** -6) #print s.Hessian.todense() p = WolfePivot(s) s.setPivotMethod(p) s.primal() print s.primalVariableSolution print s.objectiveValue
def test_removeVar2(self): s = CyClpSimplex() fp = os.path.join(currentFilePath, '../../input/p0033.mps') s.extractCyLPModel(fp) y = s.addVariable('y', 3) s.primal() x = s.getVarByName('x') s.addConstraint(x[1] + y[1] >= 1.2) #s.primal() s.removeVariable('x') s.primal() s = s.primalVariableSolution self.assertTrue((s['y'] - np.array([0, 1.2, 0]) <= 10**-6).all())
def test_SetInt_CopyIn(self): self.model = CyLPModel() model = self.model x = model.addVariable('x', 3) y = model.addVariable('y', 2) A = np.matrix([[1., 2., 0],[1., 0, 1.]]) B = np.matrix([[1., 0, 0], [0, 0, 1.]]) D = np.matrix([[1., 2.],[0, 1]]) a = CyLPArray([5, 2.5]) b = CyLPArray([4.2, 3]) x_u= CyLPArray([2., 3.5]) model.addConstraint(A*x <= a) model.addConstraint(2 <= B * x + D * y <= b) model.addConstraint(y >= 0) model.addConstraint(1.1 <= x[1:3] <= x_u) c = CyLPArray([1., -2., 3.]) model.objective = c * x + 2 * y.sum() self.s = CyClpSimplex(model) s = self.s s.setInteger(x[1:3]) cbcModel = s.getCbcModel() cbcModel.branchAndBound() sol_x = cbcModel.primalVariableSolution['x'] self.assertTrue((abs(sol_x - np.array([0.5, 2, 2]) ) <= 10**-6).all()) sol_y = cbcModel.primalVariableSolution['y'] self.assertTrue((abs(sol_y - np.array([0, 0.75]) ) <= 10**-6).all()) s.copyInIntegerInformation(np.array( [True, False, False, False, True], np.uint8)) cbcModel = s.getCbcModel() cbcModel.branchAndBound() sol_x = cbcModel.primalVariableSolution['x'] self.assertTrue((abs(sol_x - np.array([0, 2, 1.1]) ) <= 10**-6).all()) sol_y = cbcModel.primalVariableSolution['y'] self.assertTrue((abs(sol_y - np.array([0, 1]) ) <= 10**-6).all())
def test_multiDim(self): from cylp.cy import CyClpSimplex from cylp.py.modeling.CyLPModel import CyLPArray s = CyClpSimplex() x = s.addVariable('x', (5, 3, 6)) s += 2 * x[2, :, 3].sum() + 3 * x[0, 1, :].sum() >= 5 s += 0 <= x <= 1 c = CyLPArray(list(range(18))) s.objective = c * x[2, :, :] + c * x[0, :, :] s.primal() sol = s.primalVariableSolution['x'] self.assertTrue(abs(sol[0, 1, 0] - 1) <= 10**-6) self.assertTrue(abs(sol[2, 0, 3] - 1) <= 10**-6)
def test_init_fails_asserts(self): lp = CyClpSimplex() bb = BranchAndBound(small_branch) queue = PriorityQueue() # model asserts self.assertRaisesRegex(AssertionError, 'model must be cuppy MILPInstance', BranchAndBound, lp) # Node asserts self.assertRaisesRegex(AssertionError, 'Node must be a class', BranchAndBound, small_branch, 'Node') for attribute in bb._node_attributes: class BadNode(BaseNode): def __init__(self, **kwargs): super().__init__(**kwargs) delattr(self, attribute) self.assertRaisesRegex(AssertionError, f'Node needs a {attribute}', BranchAndBound, small_branch, BadNode) for func in bb._node_funcs: class BadNode(BaseNode): def __init__(self, **kwargs): super().__init__(**kwargs) self.__dict__[func] = 5 self.assertRaisesRegex(AssertionError, f'Node needs a {func}', BranchAndBound, small_branch, BadNode) # node_queue asserts for func in reversed(bb._queue_funcs): queue.__dict__[func] = 5 self.assertRaisesRegex(AssertionError, f'node_queue needs a {func} function', BranchAndBound, small_branch, BaseNode, queue) # strong branch iters asserts self.assertRaisesRegex( AssertionError, 'strong branching iterations must be positive integer', BranchAndBound, small_branch, strong_branch_iters=-1)
def branch_and_bound(G, num_threads=4): N = len(G) model = CyLPModel() # Decision variables, one for each node x = model.addVariable('x', N, isInt=True) # Adjacency matrix (possibly weighted) W = nx.to_numpy_matrix(G) z_ind = dict() ind = 0 w = [] for i in range(N): j_range = range(N) if (not nx.is_directed(G)): # Reduced range for undirected graphs j_range = range(i, N) for j in j_range: if (W[i,j] == 0): continue if (i not in z_ind): z_ind[i] = dict() z_ind[i][j] = ind w.append(W[i,j]) ind += 1 # Aux variables, one for each edge z = model.addVariable('z', len(w), isInt=True) # Adding the box contraints model += 0 <= x <= 1 model += 0 <= z <= 1 # Adding the cutting constraints # If x_i == x_j then z_ij = 0 # If x_i != x_j then z_ij = 1 for i in z_ind: for j in z_ind[i]: model += z[z_ind[i][j]] - x[i] - x[j] <= 0 model += z[z_ind[i][j]] + x[i] + x[j] <= 2 # Adding the objective function model.objective = CyLPArray(w) * z lp = CyClpSimplex(model) lp.logLevel = 0 lp.optimizationDirection = 'max' mip = lp.getCbcModel() mip.logLevel = 0 # Setting number of threads mip.numberThreads = num_threads mip.solve() return mip.objectiveValue, [int(i) for i in mip.primalVariableSolution['x']]
def test_ArrayIndexing(self): from cylp.cy import CyClpSimplex from cylp.py.modeling.CyLPModel import CyLPArray s = CyClpSimplex() x = s.addVariable('x', (5, 3, 6)) s += 2 * x[2, :, 3].sum() + 3 * x[0, 1, :].sum() >= 5 s += x[1, 2, [0, 3, 5]] - x[2, 1, np.array([1, 2, 4])] == 1 s += 0 <= x <= 1 c = CyLPArray(range(18)) s.objective = c * x[2, :, :] + c * x[0, :, :] s.primal() sol = s.primalVariableSolution['x'] self.assertTrue(abs(sol[1, 2, 0] - 1) <= 10**-6) self.assertTrue(abs(sol[1, 2, 3] - 1) <= 10**-6) self.assertTrue(abs(sol[1, 2, 5] - 1) <= 10**-6)
def test_onlyBounds2(self): s = CyClpSimplex() x = s.addVariable('x', 3) y = s.addVariable('y', 2) s += y >= 1 s += 2 <= x <= 4 c = CyLPArray([1., -2., 3.]) s.objective = c * x + 2 * y[0] + 2 * y[1] s.primal() sol = np.concatenate( (s.primalVariableSolution['x'], s.primalVariableSolution['y'])) self.assertTrue((abs(sol - np.array([2, 4, 2, 1, 1])) <= 10**-6).all())
def test_removeConstraint(self): 'Test remove constraint' model = CyLPModel() x = model.addVariable('x', 3) y = model.addVariable('y', 2) A = csc_matrixPlus(([1, 2, 1, 1], ([0, 0, 1, 1], [0, 1, 0, 2])), shape=(2, 3)) B = csc_matrixPlus(([1, 1], ([0, 1], [0, 2])), shape=(2, 3)) D = np.matrix([[1., 2.], [0, 1]]) a = CyLPArray([3, 2.5]) b = CyLPArray([4.2, 3]) x_u = CyLPArray([2., 3.5]) model.addConstraint(A * x <= a, 'res1') model.addConstraint(2 <= B * x + D * y <= b, 'res2') model.addConstraint(y >= 0) model.addConstraint(1.1 <= x[1:3] <= x_u) model.addConstraint(x[0] >= 0.1) c = CyLPArray([1., -2., 3.]) model.objective = c * x + 2 * y[0] + 2 * y[1] s = CyClpSimplex(model) s.primal() sol = np.concatenate( (s.primalVariableSolution['x'], s.primalVariableSolution['y'])) self.assertTrue( (abs(sol - np.array([0.1, 1.45, 1.1, 0, 0.95])) <= 10**-6).all()) s.removeConstraint('res2') s.primal() sol = np.concatenate( (s.primalVariableSolution['x'], s.primalVariableSolution['y'])) self.assertTrue( (abs(sol - np.array([0.1, 1.45, 1.1, 0, 0])) <= 10**-6).all()) s.removeConstraint('res1') s.primal() sol = np.concatenate( (s.primalVariableSolution['x'], s.primalVariableSolution['y'])) self.assertTrue( (abs(sol - np.array([0.1, 2, 1.1, 0, 0])) <= 10**-6).all())
def test_multiDim_Cbc_solve(self): from cylp.cy import CyClpSimplex from cylp.py.modeling.CyLPModel import CyLPArray s = CyClpSimplex() x = s.addVariable('x', (5, 3, 6)) s += 2 * x[2, :, 3].sum() + 3 * x[0, 1, :].sum() >= 5.5 s += 0 <= x <= 2.2 c = CyLPArray(list(range(18))) s.objective = c * x[2, :, :] + c * x[0, :, :] s.setInteger(x) cbcModel = s.getCbcModel() cbcModel.solve() sol_x = cbcModel.primalVariableSolution['x'] self.assertTrue(abs(sol_x[0, 1, 0] - 1) <= 10**-6) self.assertTrue(abs(sol_x[2, 0, 3] - 2) <= 10**-6)
def __init__(self): super().__init__() self.status = LPStatus.UNKNOWN self.constraint_counter = 0 self.model = CyClpSimplex() # Maps a variable to a Clp variable self.var_to_clp_var = {} # Maps a HIPS constraint to a Clp constraint self.constr_to_clp_constr = {} # Maps a CLP constraint to a name self.clp_constr_to_name = {} # Maps vars to the number of constraints it is contained in self.var_to_nconstr = {} # Maps constr to variables self.constr_to_vars = {} # Map vars to lower/upper bound constraint self.var_to_lower = {} self.var_to_upper = {}
def test_init_fails_asserts(self): lp = CyClpSimplex() # model asserts self.assertRaisesRegex(AssertionError, 'model must be cuppy MILPInstance', Utils, lp, BaseNode, self._node_funcs, self._node_attributes) # Node asserts self.assertRaisesRegex(AssertionError, 'Node must be a class', Utils, small_branch, 'Node', self._node_funcs, self._node_attributes) for attribute in self._node_attributes: class BadNode(BaseNode): def __init__(self, **kwargs): super().__init__(**kwargs) delattr(self, attribute) self.assertRaisesRegex(AssertionError, f'Node needs a {attribute}', Utils, small_branch, BadNode, self._node_attributes, self._node_funcs) for func in self._node_funcs: class BadNode(BaseNode): def __init__(self, **kwargs): super().__init__(**kwargs) self.__dict__[func] = 5 self.assertRaisesRegex(AssertionError, f'Node needs a {func}', Utils, small_branch, BadNode, self._node_attributes, self._node_funcs) # kwarg asserts self.assertRaisesRegex(AssertionError, 'next_node_idx is reserved', Utils, small_branch, BaseNode, self._node_attributes, self._node_funcs, next_node_idx=1)
def generateQP(self): m = self.m n = self.n s = CyClpSimplex() iNonZero = set(random.randint(n, size=self.nnzPerCol)) iZero = [i for i in range(n) if i not in iNonZero] x_star = np.matrix(np.zeros((n, 1))) z_star = np.matrix(np.zeros((n, 1))) for i in iNonZero: x_star[i, 0] = 1 for i in iZero: z_star[i, 0] = 0 if random.randint(2) else random.random() G = getG(n) A = getA(m, n, self.nnzPerCol) y_star = np.matrix(random.random((m, 1))) c = -(G * x_star - A.T * y_star - z_star) obj = 0.5 * ((x_star.T * G) * x_star) + c.T * x_star print(obj) c = CyLPArray((c.T)[0]) b = CyLPArray(((A * x_star).T)[0]) b = np.squeeze(np.asarray(b)) x = s.addVariable('x', n) s += A * x == b s += x >= 0 c = CyLPArray(c) s.objective = c * x s.Hessian = G self.model = s return s
def test_removeConst(self): m = self.model x = self.x A = self.A b = self.b m.addConstraint(x >= 0) m.addConstraint(A * x == b) m.addConstraint(x[1:3].sum() >= 1, 'rr') m.objective = x.sum() s = CyClpSimplex(m) s.primal() self.assertAlmostEqual(s.primalVariableSolution['x'][1], 1, 7) s.removeConstraint('rr') s.primal() self.assertAlmostEqual(s.primalVariableSolution['x'][1], 0, 7)
def plpd2d(xs, zs, ys, x_0, z_0): x, z, y = xs, zs, ys dim_p = len(x) rhs_p = np.array([x_0, z_0, 1], dtype=np.double) dim_d = len(rhs_p) s = CyClpSimplex() u = s.addVariable('u', dim_p) l = s.addVariable('l', dim_d) A_p = np.vstack([y, x, z, np.ones(dim_p)]) A_p = np.matrix(A_p) b_p = CyLPArray([0, x_0, z_0, 1]) A_d = np.hstack( [x.reshape(-1, 1), z.reshape(-1, 1), np.ones(len(x)).reshape(-1, 1)]) A_d = np.matrix(A_d) b_d = CyLPArray(y) A_d1 = np.matrix(np.vstack([-rhs_p, np.zeros((3, 3))])) s += A_p * u + A_d1 * l == b_p s += A_d * l <= b_d for i in range(dim_p): s += u[i] >= 0 s.optimizationDirection = 'max' s.objective = u[0] s.primal() cond = s.primalVariableSolution['u'] y_res = np.dot(cond, y) return y_res
def test_NodeCompare(self): s = CyClpSimplex() s.readMps(join(currentFilePath, '../input/p0033.mps')) s.copyInIntegerInformation(np.array(s.nCols * [True], np.uint8)) print("Solving relaxation") cbcModel = s.getCbcModel() n = SimpleNodeCompare() cbcModel.setNodeCompare(n) gom = CyCglGomory(limit=150) #gom.limit = 150 cbcModel.addCutGenerator(gom, name="Gomory") #clq = CyCglClique() #cbcModel.addCutGenerator(clq, name="Clique") knap = CyCglKnapsackCover(maxInKnapsack=50) cbcModel.addCutGenerator(knap, name="Knapsack") cbcModel.branchAndBound() self.assertTrue(abs(cbcModel.objectiveValue - 3089.0) < 10**-6)
def test_isInt(self): self.model = CyLPModel() model = self.model x = model.addVariable('x', 3, isInt=True) y = model.addVariable('y', 2) A = np.matrix([[1., 2., 0],[1., 0, 1.]]) B = np.matrix([[1., 0, 0], [0, 0, 1.]]) D = np.matrix([[1., 2.],[0, 1]]) a = CyLPArray([5, 2.5]) b = CyLPArray([4.2, 3]) x_u= CyLPArray([2., 3.5]) model.addConstraint(A*x <= a) model.addConstraint(2 <= B * x + D * y <= b) model.addConstraint(y >= 0) model.addConstraint(1.1 <= x[1:3] <= x_u) c = CyLPArray([1., -2., 3.]) model.objective = c * x + 2 * y.sum() self.s = CyClpSimplex(model) s = self.s cbcModel = s.getCbcModel() cbcModel.branchAndBound() sol_x = cbcModel.primalVariableSolution['x'] self.assertTrue((abs(sol_x - np.array([0, 2, 2]) ) <= 10**-6).all()) sol_y = cbcModel.primalVariableSolution['y'] self.assertTrue((abs(sol_y - np.array([0, 1]) ) <= 10**-6).all())
def solve(self, objective, constraints, cached_data, warm_start, verbose, solver_opts): """Returns the result of the call to the solver. Parameters ---------- objective : LinOp The canonicalized objective. constraints : list The list of canonicalized cosntraints. cached_data : dict A map of solver name to cached problem data. warm_start : bool Not used. verbose : bool Should the solver print output? solver_opts : dict Additional arguments for the solver. Returns ------- tuple (status, optimal value, primal, equality dual, inequality dual) """ # Import basic modelling tools of cylp from cylp.cy import CyClpSimplex from cylp.py.modeling.CyLPModel import CyLPModel, CyLPArray # Get problem data data = self.get_problem_data(objective, constraints, cached_data) c = data[s.C] b = data[s.B] A = data[s.A] dims = data[s.DIMS] data[s.BOOL_IDX] = solver_opts[s.BOOL_IDX] data[s.INT_IDX] = solver_opts[s.INT_IDX] n = c.shape[0] # Problem model = CyLPModel() # Variables x = model.addVariable('x', n) # Constraints # eq model += A[0:dims[s.EQ_DIM], :] * x == CyLPArray(b[0:dims[s.EQ_DIM]]) # leq leq_start = dims[s.EQ_DIM] leq_end = dims[s.EQ_DIM] + dims[s.LEQ_DIM] model += A[leq_start:leq_end, :] * x <= CyLPArray(b[leq_start:leq_end]) # Objective model.objective = c # Convert model model = CyClpSimplex(model) # No boolean vars available in Cbc -> model as int + restrict to [0,1] if self.is_mip(data): # Mark integer- and binary-vars as "integer" model.setInteger(x[data[s.BOOL_IDX]]) model.setInteger(x[data[s.INT_IDX]]) # Restrict binary vars only idxs = data[s.BOOL_IDX] n_idxs = len(idxs) model.setColumnLowerSubset(np.arange(n_idxs, dtype=np.int32), np.array(idxs, np.int32), np.zeros(n_idxs)) model.setColumnUpperSubset(np.arange(n_idxs, dtype=np.int32), np.array(idxs, np.int32), np.ones(n_idxs)) # Verbosity Clp if not verbose: model.logLevel = 0 # Build model & solve status = None if self.is_mip(data): # Convert model cbcModel = model.getCbcModel() # Verbosity Cbc if not verbose: cbcModel.logLevel = 0 # cylp: /cylp/cy/CyCbcModel.pyx#L134 # Call CbcMain. Solve the problem using the same parameters used by # CbcSolver. Equivalent to solving the model from the command line # using cbc's binary. cbcModel.solve() status = cbcModel.status else: # cylp: /cylp/cy/CyClpSimplex.pyx # Run CLP's initialSolve. It does a presolve and uses primal or dual # Simplex to solve a problem. status = model.initialSolve() results_dict = {} results_dict["status"] = status if self.is_mip(data): results_dict["x"] = cbcModel.primalVariableSolution['x'] results_dict["obj_value"] = cbcModel.objectiveValue else: results_dict["x"] = model.primalVariableSolution['x'] results_dict["obj_value"] = model.objectiveValue return self.format_results(results_dict, data, cached_data)
m = CyLPModel() firstExample = False if (firstExample): x = m.addVariable('x', 2, isInt=True) A = np.matrix([[7., -2.], [0., 1], [2., -2]]) b = CyLPArray([14, 3, 3]) m += A * x <= b m += x >= 0 c = CyLPArray([-4, 1]) m.objective = c * x s = CyClpSimplex(m) else: s = CyClpSimplex() #cylpDir = os.environ['CYLP_SOURCE_DIR'] inputFile = os.path.join('..', '..', 'input', 'p0033.mps') m = s.extractCyLPModel(inputFile) x = m.getVarByName('x') s.setInteger(x) cbcModel = s.getCbcModel() gc = GomoryCutGenerator(m) #cbcModel.addPythonCutGenerator(gc, name='PyGomory') #cbcModel.branchAndBound() cbcModel.solve()