Esempio n. 1
0
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 []
Esempio n. 2
0
        cuts = []
        for rowInd in range(s.nConstraints):
            basicVarInd = bv[rowInd]
            if basicVarInd < clpModel.nVariables and intInds[
                    basicVarInd] and not rhsIsInt[rowInd]:
                coef, b = gomoryCut(clpModel, rowInd)
                if b is not None:
                    #print 'Adding cut: ', coef, '>=', b
                    expr = CyLPArray(coef) * x >= b
                    cuts.append(expr)
        return cuts


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)
Esempio n. 3
0
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 []
Esempio n. 4
0
        rhsIsInt = map(isInt, rhs)

        cuts = []
        for rowInd in xrange(s.nConstraints):
            basicVarInd = bv[rowInd]
            if basicVarInd < clpModel.nVariables and intInds[basicVarInd] and not rhsIsInt[rowInd]:
                coef, b = gomoryCut(clpModel, rowInd)
                if b is not None:
                    #print 'Adding cut: ', coef, '>=', b
                    expr = CyLPArray(coef) * x >= b
                    cuts.append(expr)
        return cuts


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)
Esempio n. 5
0
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 []
Esempio n. 6
0
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 []
Esempio n. 7
0
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 []