def splitCuts(lp, integerIndices = None, sense = '>=', sol = None, max_coeff = 1): A = lp.coefMatrix b = CyLPArray(lp.constraintsUpper) if integerIndices is None: integerIndices = range(lp.nVariables) if sol is None: sol = lp.primalVariableSolution['x'] s = A*sol - b best = lp.getCoinInfinity() best_theta = None for theta in [0.1, 0.2, 0.3, 0.4, 0.5]: sp = CyLPModel() u = sp.addVariable('u', lp.nConstraints, isInt = False) v = sp.addVariable('v', lp.nConstraints, isInt = False) pi = sp.addVariable('pi', lp.nVariables, isInt = True) pi0 = sp.addVariable('pi0', 1, isInt = True) sp += pi + A.transpose()*u - A.transpose()*v == 0 sp += pi0 + b*u - b*v == theta - 1 if sense == '<=': sp += u >= 0 sp += v >= 0 else: #TODO this direction is not debugged # Is this all we need? sp += u <= 0 sp += v <= 0 sp.objective = (theta-1)*s*u - theta*s*v for i in xrange(lp.nVariables): if i in integerIndices: sp += -max_coeff <= pi[i] <= max_coeff else: sp[i] += pi[i] == 0 cbcModel = CyClpSimplex(sp).getCbcModel() cbcModel.logLevel = 0 #cbcModel.maximumSeconds = 5 cbcModel.solve() if debug_print: print theta, cbcModel.objectiveValue print cbcModel.primalVariableSolution['pi'], print cbcModel.primalVariableSolution['pi0'] if cbcModel.objectiveValue < best: best = cbcModel.objectiveValue multu = cbcModel.primalVariableSolution['u'] disjunction = cbcModel.primalVariableSolution['pi'] rhs = cbcModel.primalVariableSolution['pi0'] best_theta = theta if best_theta is not None: alpha = A.transpose()*multu + best_theta*disjunction if sense == '<=': beta = np.dot(lp.constraintsUpper, multu) + best_theta*rhs else: beta = np.dot(lp.constraintsLower, multu) + best_theta*rhs if (abs(alpha) > 1e-6).any(): return [(alpha, beta)] return []
if __name__ == '__main__': 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()
def disjunctionToCut(lp, pi, pi0, integerIndices = None, sense = '>=', sol = None, debug_print = False, use_cylp = True): me = "cglp_cuts: " if sol is None: sol = lp.primalVariableSolution['x'] infinity = lp.getCoinInfinity() if debug_print: print(me, "constraints sense = ", sense) print(me, "con lower bounds = ", lp.constraintsLower) print(me, "con upper bounds = ", lp.constraintsUpper) print(me, "con matrix = ", lp.coefMatrix.toarray()) print(me, "vars lower bounds = ", lp.variablesLower) print(me, "vars upper bounds = ", lp.variablesUpper) print(me, "Assuming objective is to minimize") print(me, "objective = ", lp.objective) print(me, "infinity = ", infinity) print(me, "current point = ", sol) print(me, "pi = ", pi) print(me, "pi0 = ", pi0) A = lp.coefMatrix.toarray() #c = lp.objective ## Convert to >= if the problem is in <= form. if sense == '<=': b = deepcopy(lp.constraintsUpper) b = -1.0*b A = -1.0*A else: b = deepcopy(lp.constraintsLower) #Add bounds on variables as explicit constraints for i in range(lp.nCols): e = np.zeros((1, lp.nCols)) if lp.variablesUpper[i] < infinity: b.resize(b.size+1, refcheck = False) e[0, i] = -1.0 b[-1] = -1.0*lp.variablesUpper[i] A = np.vstack((A, e)) if lp.variablesLower[i] > -infinity: b.resize(b.size+1, refcheck = False) e[0, i] = 1.0 b[-1] = lp.variablesLower[i] A = np.vstack((A, e)) A = csc_matrixPlus(A) ############################################################################ ## There are two given LPs: ## s.t. Ax >= b s.t. Ax >= b ## -pi.x >= -pi_0 pi.x >= pi_0+1 ## A, b, c, pi, pi_0 are given ## ## CGLP: alpha.x >= beta should be valid for both LPs above ## ## min alpha.x* - beta ## uA - u0.pi = alpha ## vA + v0.pi = alpha ## ub - u0.pi_0 >= beta ## vb + v0.(pi_0 + 1) >= beta ## u0 + v0 = 1 ## u, v, u0, v0 >= 0 ## if min value comes out < 0, then (alpha.x >= beta) is a cut. ############################################################################ b = CyLPArray(b) pi = CyLPArray(pi) Atran = A.transpose() if use_cylp: sp = CyLPModel() u = sp.addVariable('u', A.shape[0], isInt = False) v = sp.addVariable('v', A.shape[0], isInt = False) u0 = sp.addVariable('u0', 1, isInt = False) v0 = sp.addVariable('v0', 1, isInt = False) alpha = sp.addVariable('alpha', lp.nVariables, isInt = False) beta = sp.addVariable('beta', 1, isInt = False) for i in range(A.shape[1]): sp += alpha[i] - sum(Atran[i,j]*u[j] for j in range(A.shape[0])) + pi[i]*u0 == 0 for i in range(A.shape[1]): sp += alpha[i] - sum(Atran[i,j]*v[j] for j in range(A.shape[0])) - pi[i]*v0 == 0 sp += beta - b*u + pi0*u0 <= 0 sp += beta - b*v - (pi0 + 1)*v0 <= 0 sp += u0 + v0 == 1 if sense == '<=': sp += u >= 0 sp += v >= 0 sp += u0 >= 0 sp += v0 >= 0 else: #TODO this direction is not debugged # Is this all we need? sp += u <= 0 sp += v <= 0 sp += u0 <= 0 sp += v0 <= 0 sp.objective = sum(sol[i]*alpha[i] for i in range(A.shape[1])) - beta cbcModel = CyClpSimplex(sp).getCbcModel() cbcModel.logLevel = 0 #cbcModel.maximumSeconds = 5 cbcModel.solve() beta = cbcModel.primalVariableSolution['beta'][0] alpha = cbcModel.primalVariableSolution['alpha'] u = cbcModel.primalVariableSolution['u'] v = cbcModel.primalVariableSolution['v'] u0 = cbcModel.primalVariableSolution['u0'][0] v0 = cbcModel.primalVariableSolution['v0'][0] if debug_print: print('Objective Value: ', cbcModel.objectiveValue) print('alpha: ', alpha, 'alpha*sol: ', np.dot(alpha, sol)) print('beta: ', beta) print('Violation of cut: ', np.dot(alpha, sol) - beta) else: CG = AbstractModel() CG.u = Var(list(range(A.shape[0])), domain=NonNegativeReals, bounds = (0.0, None)) CG.v = Var(list(range(A.shape[0])), domain=NonNegativeReals, bounds = (0.0, None)) CG.u0 = Var(domain=NonNegativeReals, bounds = (0.0, None)) CG.v0 = Var(domain=NonNegativeReals, bounds = (0.0, None)) CG.alpha = Var(list(range(A.shape[0])), domain=Reals, bounds = (None, None)) CG.beta = Var(domain=Reals, bounds = (None, None)) ## Constraints def pi_rule_left(CG, i): x = float(pi[i]) return(sum(Atran[i, j]*CG.u[j] for j in range(A.shape[0])) - x*CG.u0 - CG.alpha[i] == 0.0) CG.pi_rule_left = Constraint(list(range(A.shape[1])), rule=pi_rule_left) def pi_rule_right(CG, i): x = float(pi[i]) return(sum(Atran[i, j]*CG.v[j] for j in range(A.shape[0])) + x*CG.v0 - CG.alpha[i] == 0.0) CG.pi_rule_right = Constraint(list(range(A.shape[1])), rule=pi_rule_right) def pi0_rule_left(CG): return(sum(b[j]*CG.u[j] for j in range(A.shape[0])) - pi0*CG.u0 - CG.beta >= 0.0) CG.pi0_rule_left = Constraint(rule=pi0_rule_left) def pi0_rule_right(CG): return(sum(b[j]*CG.v[j] for j in range(A.shape[0])) + (pi0 + 1)*CG.v0 - CG.beta >= 0.0) CG.pi0_rule_right = Constraint(rule=pi0_rule_right) def normalization_rule(CG): return(CG.u0 + CG.v0 == 1.0) CG.normalization_rule = Constraint(rule=normalization_rule) def objective_rule(CG): return(sum(sol[i]*CG.alpha[i] for i in range(A.shape[1])) - CG.beta) CG.objective = Objective(sense=minimize, rule=objective_rule) opt = SolverFactory("cbc") instance = CG.create_instance() #instance.pprint() #instance.write("foo.nl", format = "nl") #opt.options['bonmin.bb_log_level'] = 5 #opt.options['bonmin.bb_log_interval'] = 1 results = opt.solve(instance, tee=False) #results = opt.solve(instance) instance.solutions.load_from(results) beta = instance.beta.value alpha = np.array([instance.alpha[i].value for i in range(lp.nVariables)]) violation = beta - np.dot(alpha, sol) if debug_print: print(me, 'Beta: ', beta) print(me, 'alpha: ', alpha) print(me, 'Violation of cut: ', violation) if violation > 0.001: if (sense == ">="): return [(alpha, beta)] else: return [(-alpha, -beta)] return []
if __name__ == '__main__': 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(cylpDir, 'cylp', '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()
def disjunctionToCut(m, pi, pi0, debug_print=False, use_cylp=True, eps=EPS): '''Generate the most violated valid inequality from a given disjunction''' me = "cglp_cuts: " lp = m.lp sol = lp.primalVariableSolution['x'] if debug_print: print(me, "constraints sense = ", m.sense) print(me, "matrix = ") print(m.A) print(me, "rhs = ", m.b) print(me, "vars lower bounds = ", lp.variablesLower) print(me, "vars upper bounds = ", lp.variablesUpper) print(me, "objective = ", lp.objective) print(me, "current solution = ", sol) print(me, "pi = ", pi) print(me, "pi0 = ", pi0) ############################################################################ ## There are two given LPs: ## s.t. Ax >= b s.t. Ax >= b ## -pi.x >= -pi_0 pi.x >= pi_0+1 ## A, b, c, pi, pi_0 are given ## ## CGLP: alpha.x >= beta should be valid for both LPs above ## ## min alpha.x* - beta ## uA - u0.pi = alpha ## vA + v0.pi = alpha ## ub - u0.pi_0 >= beta ## vb + v0.(pi_0 + 1) >= beta ## u0 + v0 = 1 ## u, v, u0, v0 >= 0 ## if min value comes out < 0, then (alpha.x >= beta) is a cut. ############################################################################ pi = CyLPArray(pi) Atran = m.A.transpose() b = CyLPArray(m.b) numRows, numCols = m.A.shape if use_cylp: sp = CyLPModel() u = sp.addVariable('u', numRows, isInt=False) v = sp.addVariable('v', numRows, isInt=False) u0 = sp.addVariable('u0', 1, isInt=False) v0 = sp.addVariable('v0', 1, isInt=False) alpha = sp.addVariable('alpha', lp.nVariables, isInt=False) beta = sp.addVariable('beta', 1, isInt=False) #This should be as simple as this, but it doesn't work. #Maybe a bug in CyLP? #sp += alpha - Atran*u - pi*u0 == 0 #sp += alpha - Atran*v + pi*v0 == 0 for i in range(numCols): sp += alpha[i] - sum(Atran[i, j] * u[j] for j in range(numRows)) - pi[i] * u0 == 0 for i in range(numCols): sp += alpha[i] - sum(Atran[i, j] * v[j] for j in range(numRows)) + pi[i] * v0 == 0 if m.sense == '<=': sp += beta - b * u - pi0 * u0 >= 0 sp += beta - b * v + (pi0 + 1) * v0 >= 0 else: sp += beta - b * u - pi0 * u0 <= 0 sp += beta - b * v + (pi0 + 1) * v0 <= 0 sp += u0 + v0 == 1 sp += u >= 0 sp += v >= 0 sp += u0 >= 0 sp += v0 >= 0 if m.sense == '<=': sp.objective = sum(-sol[i] * alpha[i] for i in range(numCols)) + beta else: #This direction is not debugged sp.objective = sum(sol[i] * alpha[i] for i in range(numCols)) - beta cglp = CyClpSimplex(sp) # If we want to solve it as an MILP # cglp = CyClpSimplex(sp).getCbcModel() #cglp.writeLp('lp.lp') cglp.logLevel = 0 cglp.primal(startFinishOptions='x') # Solve as MILP # cglp.solve() beta = cglp.primalVariableSolution['beta'][0] alpha = cglp.primalVariableSolution['alpha'] u = cglp.primalVariableSolution['u'] v = cglp.primalVariableSolution['v'] u0 = cglp.primalVariableSolution['u0'][0] v0 = cglp.primalVariableSolution['v0'][0] if debug_print: print(me, 'Objective Value: ', cglp.objectiveValue) if debug_print: print(me, 'u: ', u) print(me, 'v: ', v) print(me, 'u0: ', u0) print(me, 'v0: ', v0) else: CG = AbstractModel() CG.u = Var(list(range(numRows)), domain=NonNegativeReals, bounds=(0.0, None)) CG.v = Var(list(range(numRows)), domain=NonNegativeReals, bounds=(0.0, None)) CG.u0 = Var(domain=NonNegativeReals, bounds=(0.0, None)) CG.v0 = Var(domain=NonNegativeReals, bounds=(0.0, None)) CG.alpha = Var(list(range(numRows)), domain=Reals, bounds=(None, None)) CG.beta = Var(domain=Reals, bounds=(None, None)) ## Constraints def pi_rule_left(CG, i): x = float(pi[i]) return (sum(Atran[i, j] * CG.u[j] for j in range(numRows)) - x * CG.u0 - CG.alpha[i] == 0.0) CG.pi_rule_left = Constraint(list(range(numCols)), rule=pi_rule_left) def pi_rule_right(CG, i): x = float(pi[i]) return (sum(Atran[i, j] * CG.v[j] for j in range(numRows)) + x * CG.v0 - CG.alpha[i] == 0.0) CG.pi_rule_right = Constraint(list(range(numCols)), rule=pi_rule_right) if m.sense == '<=': def pi0_rule_left(CG): return (sum(b[j] * CG.u[j] for j in range(numRows)) - pi0 * CG.u0 - CG.beta <= 0.0) CG.pi0_rule_left = Constraint(rule=pi0_rule_left) def pi0_rule_right(CG): return (sum(b[j] * CG.v[j] for j in range(numRows)) + (pi0 + 1) * CG.v0 - CG.beta <= 0.0) CG.pi0_rule_right = Constraint(rule=pi0_rule_right) else: def pi0_rule_left(CG): return (sum(b[j] * CG.u[j] for j in range(numRows)) - pi0 * CG.u0 - CG.beta >= 0.0) CG.pi0_rule_left = Constraint(rule=pi0_rule_left) def pi0_rule_right(CG): return (sum(b[j] * CG.v[j] for j in range(numRows)) + (pi0 + 1) * CG.v0 - CG.beta >= 0.0) CG.pi0_rule_right = Constraint(rule=pi0_rule_right) def normalization_rule(CG): return (CG.u0 + CG.v0 == 1.0) CG.normalization_rule = Constraint(rule=normalization_rule) def objective_rule(CG): return (sum(sol[i] * CG.alpha[i] for i in range(numCols)) - CG.beta) if m.sense == '<=': CG.objective = Objective(sense=maximize, rule=objective_rule) else: CG.objective = Objective(sense=minimize, rule=objective_rule) opt = SolverFactory("cbc") instance = CG.create_instance() #instance.pprint() #instance.write("foo.nl", format = "nl") #opt.options['bonmin.bb_log_level'] = 5 #opt.options['bonmin.bb_log_interval'] = 1 results = opt.solve(instance, tee=False) #results = opt.solve(instance) instance.solutions.load_from(results) beta = instance.beta.value alpha = np.array( [instance.alpha[i].value for i in range(lp.nVariables)]) violation = beta - np.dot(alpha, sol) if debug_print: print(me, 'Beta: ', beta) print(me, 'alpha: ', alpha) print(me, 'Violation of cut: ', violation) if np.abs(violation) > 10**(-eps): return [(alpha, beta)] print('No violated cuts found solving CGLP', violation) return []
def maxViolationSplitCuts(lp, integerIndices = None, sense = '>=', sol = None, max_coeff = 1): #Warning: At the moment, you must put bound constraints in explicitly for split cuts A = lp.coefMatrix if sense == '<=': b = CyLPArray(lp.constraintsUpper) else: b = CyLPArray(lp.constraintsLower) if integerIndices is None: integerIndices = range(lp.nVariables) if sol is None: sol = lp.primalVariableSolution['x'] s = A*sol - b best = lp.getCoinInfinity() best_theta = None for theta in [0.01, 0.02, 0.03, 0.04, 0.05, 0.1, 0.15, 0.2, 0.25, 0.3, 0.35, 0.4, 0.45, 0.46, 0.47, 0.48, 0.49, 0.5]: sp = CyLPModel() u = sp.addVariable('u', lp.nConstraints, isInt = False) v = sp.addVariable('v', lp.nConstraints, isInt = False) pi = sp.addVariable('pi', lp.nVariables, isInt = True) pi0 = sp.addVariable('pi0', 1, isInt = True) sp += pi + A.transpose()*u - A.transpose()*v == 0 sp += pi0 + b*u - b*v == theta - 1 if sense == '<=': sp += u >= 0 sp += v >= 0 else: #TODO this direction is not debugged # Is this all we need? sp += u <= 0 sp += v <= 0 sp.objective = (theta-1)*s*u - theta*s*v for i in xrange(lp.nVariables): if i in integerIndices: sp += -max_coeff <= pi[i] <= max_coeff else: sp[i] += pi[i] == 0 cbcModel = CyClpSimplex(sp).getCbcModel() cbcModel.logLevel = 0 #cbcModel.maximumSeconds = 5 cbcModel.solve() if debug_print: #print 'Theta: ', theta, #print 'Objective Value: ', cbcModel.objectiveValue - theta*(1-theta) #print 'pi: ', cbcModel.primalVariableSolution['pi'] #print 'pi0: ', cbcModel.primalVariableSolution['pi0'] multu = cbcModel.primalVariableSolution['u'] disjunction = cbcModel.primalVariableSolution['pi'] rhs = cbcModel.primalVariableSolution['pi0'] alpha = A.transpose()*multu + theta*disjunction beta = np.dot(b, multu) + theta*rhs #print 'alpha: ', alpha, 'alpha*sol: ', np.dot(alpha, sol) #print 'beta: ', beta #print 'Violation of cut: ', np.dot(alpha, sol) - beta if cbcModel.objectiveValue - theta*(1-theta) < best: best = cbcModel.objectiveValue - theta*(1-theta) best_multu = cbcModel.primalVariableSolution['u'] best_multv = cbcModel.primalVariableSolution['v'] best_disjunction = cbcModel.primalVariableSolution['pi'] best_rhs = cbcModel.primalVariableSolution['pi0'] best_theta = theta if best_theta is not None: alpha = A.transpose()*best_multu + best_theta*best_disjunction beta = np.dot(b, best_multu) + best_theta*best_rhs if debug_print: print 'Violation of cut: ', np.dot(alpha, sol) - beta print 'pi: ', best_disjunction print 'pi0: ', best_rhs print 'theta: ', best_theta if (abs(alpha) > 1e-6).any(): return [(alpha, beta)] return []
def disjunctionToCut(lp, pi, pi0, integerIndices=None, sense='>=', sol=None, debug_print=False, use_cylp=True): me = "cglp_cuts: " if sol is None: sol = lp.primalVariableSolution['x'] infinity = lp.getCoinInfinity() if debug_print: print(me, "constraints sense = ", sense) print(me, "con lower bounds = ", lp.constraintsLower) print(me, "con upper bounds = ", lp.constraintsUpper) print(me, "con matrix = ", lp.coefMatrix.toarray()) print(me, "vars lower bounds = ", lp.variablesLower) print(me, "vars upper bounds = ", lp.variablesUpper) print(me, "Assuming objective is to minimize") print(me, "objective = ", lp.objective) print(me, "infinity = ", infinity) print(me, "current point = ", sol) print(me, "pi = ", pi) print(me, "pi0 = ", pi0) A = lp.coefMatrix.toarray() #c = lp.objective ## Convert to >= if the problem is in <= form. if sense == '<=': b = deepcopy(lp.constraintsUpper) b = -1.0 * b A = -1.0 * A else: b = deepcopy(lp.constraintsLower) #Add bounds on variables as explicit constraints for i in range(lp.nCols): e = np.zeros((1, lp.nCols)) if lp.variablesUpper[i] < infinity: b.resize(b.size + 1, refcheck=False) e[0, i] = -1.0 b[-1] = -1.0 * lp.variablesUpper[i] A = np.vstack((A, e)) if lp.variablesLower[i] > -infinity: b.resize(b.size + 1, refcheck=False) e[0, i] = 1.0 b[-1] = lp.variablesLower[i] A = np.vstack((A, e)) A = csc_matrixPlus(A) ############################################################################ ## There are two given LPs: ## s.t. Ax >= b s.t. Ax >= b ## -pi.x >= -pi_0 pi.x >= pi_0+1 ## A, b, c, pi, pi_0 are given ## ## CGLP: alpha.x >= beta should be valid for both LPs above ## ## min alpha.x* - beta ## uA - u0.pi = alpha ## vA + v0.pi = alpha ## ub - u0.pi_0 >= beta ## vb + v0.(pi_0 + 1) >= beta ## u0 + v0 = 1 ## u, v, u0, v0 >= 0 ## if min value comes out < 0, then (alpha.x >= beta) is a cut. ############################################################################ b = CyLPArray(b) pi = CyLPArray(pi) Atran = A.transpose() if use_cylp: sp = CyLPModel() u = sp.addVariable('u', A.shape[0], isInt=False) v = sp.addVariable('v', A.shape[0], isInt=False) u0 = sp.addVariable('u0', 1, isInt=False) v0 = sp.addVariable('v0', 1, isInt=False) alpha = sp.addVariable('alpha', lp.nVariables, isInt=False) beta = sp.addVariable('beta', 1, isInt=False) for i in range(A.shape[1]): sp += alpha[i] - sum(Atran[i, j] * u[j] for j in range(A.shape[0])) + pi[i] * u0 == 0 for i in range(A.shape[1]): sp += alpha[i] - sum(Atran[i, j] * v[j] for j in range(A.shape[0])) - pi[i] * v0 == 0 sp += beta - b * u + pi0 * u0 <= 0 sp += beta - b * v - (pi0 + 1) * v0 <= 0 sp += u0 + v0 == 1 if sense == '<=': sp += u >= 0 sp += v >= 0 sp += u0 >= 0 sp += v0 >= 0 else: #TODO this direction is not debugged # Is this all we need? sp += u <= 0 sp += v <= 0 sp += u0 <= 0 sp += v0 <= 0 sp.objective = sum(sol[i] * alpha[i] for i in range(A.shape[1])) - beta cbcModel = CyClpSimplex(sp).getCbcModel() cbcModel.logLevel = 0 #cbcModel.maximumSeconds = 5 cbcModel.solve() beta = cbcModel.primalVariableSolution['beta'][0] alpha = cbcModel.primalVariableSolution['alpha'] u = cbcModel.primalVariableSolution['u'] v = cbcModel.primalVariableSolution['v'] u0 = cbcModel.primalVariableSolution['u0'][0] v0 = cbcModel.primalVariableSolution['v0'][0] if debug_print: print('Objective Value: ', cbcModel.objectiveValue) print('alpha: ', alpha, 'alpha*sol: ', np.dot(alpha, sol)) print('beta: ', beta) print('Violation of cut: ', np.dot(alpha, sol) - beta) else: CG = AbstractModel() CG.u = Var(list(range(A.shape[0])), domain=NonNegativeReals, bounds=(0.0, None)) CG.v = Var(list(range(A.shape[0])), domain=NonNegativeReals, bounds=(0.0, None)) CG.u0 = Var(domain=NonNegativeReals, bounds=(0.0, None)) CG.v0 = Var(domain=NonNegativeReals, bounds=(0.0, None)) CG.alpha = Var(list(range(A.shape[0])), domain=Reals, bounds=(None, None)) CG.beta = Var(domain=Reals, bounds=(None, None)) ## Constraints def pi_rule_left(CG, i): x = float(pi[i]) return (sum(Atran[i, j] * CG.u[j] for j in range(A.shape[0])) - x * CG.u0 - CG.alpha[i] == 0.0) CG.pi_rule_left = Constraint(list(range(A.shape[1])), rule=pi_rule_left) def pi_rule_right(CG, i): x = float(pi[i]) return (sum(Atran[i, j] * CG.v[j] for j in range(A.shape[0])) + x * CG.v0 - CG.alpha[i] == 0.0) CG.pi_rule_right = Constraint(list(range(A.shape[1])), rule=pi_rule_right) def pi0_rule_left(CG): return (sum(b[j] * CG.u[j] for j in range(A.shape[0])) - pi0 * CG.u0 - CG.beta >= 0.0) CG.pi0_rule_left = Constraint(rule=pi0_rule_left) def pi0_rule_right(CG): return (sum(b[j] * CG.v[j] for j in range(A.shape[0])) + (pi0 + 1) * CG.v0 - CG.beta >= 0.0) CG.pi0_rule_right = Constraint(rule=pi0_rule_right) def normalization_rule(CG): return (CG.u0 + CG.v0 == 1.0) CG.normalization_rule = Constraint(rule=normalization_rule) def objective_rule(CG): return (sum(sol[i] * CG.alpha[i] for i in range(A.shape[1])) - CG.beta) CG.objective = Objective(sense=minimize, rule=objective_rule) opt = SolverFactory("cbc") instance = CG.create_instance() #instance.pprint() #instance.write("foo.nl", format = "nl") #opt.options['bonmin.bb_log_level'] = 5 #opt.options['bonmin.bb_log_interval'] = 1 results = opt.solve(instance, tee=False) #results = opt.solve(instance) instance.solutions.load_from(results) beta = instance.beta.value alpha = np.array( [instance.alpha[i].value for i in range(lp.nVariables)]) violation = beta - np.dot(alpha, sol) if debug_print: print(me, 'Beta: ', beta) print(me, 'alpha: ', alpha) print(me, 'Violation of cut: ', violation) if violation > 0.001: if (sense == ">="): return [(alpha, beta)] else: return [(-alpha, -beta)] return []