def disp_polyhedron(A=None,
                    b=None,
                    points=None,
                    rays=None,
                    c=None,
                    obj_val=None,
                    opt=None,
                    loc=None):
    if loc is None and opt is not None:
        loc = opt
    f = Figure()
    f.add_polyhedron(p, label='Polyhedron $P$', color='red')
    f.set_xlim([p.xlim[0], p.xlim[1] + 1])
    f.set_ylim([p.ylim[0], p.ylim[1] + 2])
    if c is not None and obj_val is not None:
        f.add_line(c,
                   obj_val,
                   p.xlim + [0.2, 0.8],
                   p.ylim + [0.2, 1.8],
                   linestyle='dashed',
                   color='black',
                   label="Objective Function")
    if opt is not None:
        f.add_point(opt, 0.04, 'red')
        f.add_text(loc, r'$x^* = %s$' % str(opt))
    f.show()
Esempio n. 2
0
def disp_relaxation(A, b, cuts=[], sol=None, disj=[]):
    #TODO: Check sense of inequalities by looking explicitly at
    #      lp.constraintsUpper and lp.constraintsLower
    p = Polyhedron2D(A=A, b=b)
    f = Figure()
    f.add_polyhedron(p, label='Polyhedron $P$')
    f.set_xlim(p.xlim)
    f.set_ylim(p.ylim)
    pI = p.make_integer_hull()
    f.add_polyhedron(pI,
                     show_int_points=True,
                     color='red',
                     linestyle='dashed',
                     label='Convex hull of integer points')
    for (coeff, r) in cuts:
        f.add_line(coeff, r, p.xlim, p.ylim, color='green', linestyle='dashed')
    for (coeff, r) in disj:
        f.add_line(coeff, r, p.xlim, p.ylim, color='red', linestyle='dashed')
        f.add_line(coeff,
                   r + 1,
                   p.xlim,
                   p.ylim,
                   color='red',
                   linestyle='dashed')
    if sol is not None:
        f.add_point(sol, radius=.05)
    f.show()
Esempio n. 3
0
 def __init__(self, origProb, x0, pi_init=None):
     if pi_init == None:
         pi_init = [(v.name, 0) for v in list(self.var.values())]
     self.prob = origProb
     self.iter = 1
     self.x0 = x0
     self.var = origProb.variablesDict()
     self.dim = len(self.var)
     self.currentXtremePoint = {}
     self.solver = None
     self.c = dict(list((v.name, c) for v, c in origProb.objective.items()))
     for v in self.var:
         if v in self.c:
             continue
         else:
             self.c[v] = 0.0
     self.generate_separation_problem()
     self.piCurrent = dict([(v.name, pi_init[v.name])
                            for v in list(self.var.values())])
     self.piPrevious = dict([(v.name, 0) for v in list(self.var.values())])
     self.extremePoints = []
     self.f = Figure()
Esempio n. 4
0
A1 = [[1, 1], [4, -10], [-2, -2], [-6, -2], [-1, 4]]
A2 = [[-7, 1], [0, -1], [1, -1], [4, 1], [0, 1], [-1, 5]]
b1 = [8, -3, -9, -19, 12]
b2 = [-13, -1, 3, 27, 5, 20]
sense = ('Min', '<=')
integerIndices = [0, 1]
c = [1, 0]
cuts = None
rhs = None
obj_val = 2

p1 = Polyhedron2D(A=A1, b=b1)
p2 = Polyhedron2D(A=A2, b=b2)
sR = p2.make_integer_hull()

f = Figure()
f.add_polyhedron(p1,
                 label='$\mathcal{P}^{\,\prime}$',
                 color='blue',
                 show_int_points=True)
f.add_polyhedron(p2,
                 label='$\mathcal{P}^{\,\prime\prime}$',
                 color='black',
                 show_int_points=True)
f.add_polyhedron(
    sR,
    label=
    '$\operatorname{conv}(\mathcal{P}^{\,\prime\prime} \cap \mathbb{Z}^{\,2})$',
    color='red',
    linestyle='dashed')
f.set_xlim(p2.xlim + [0, 1])
Esempio n. 5
0
def solve(m,
          whichCuts=[],
          use_cglp=False,
          debug_print=False,
          eps=EPS,
          max_iter=100,
          max_cuts=10,
          display=False,
          filename=None):

    if not isinstance(m, MILPInstance):
        print("Invalid first parameter: Must be of type MILPInstance")
        exit

    if not DISPLAY_ENABLED:
        display = False
    else:
        f = Figure()

    if m.lp.nCols > 2 or m.A is None:
        display = False
    m.lp.logLevel = 0

    #Include bounds explicitly in the constraint matrix for display and for
    #use in cut generators.
    infinity = m.lp.getCoinInfinity()
    if m.sense == '<=':
        b = m.lp.constraintsUpper.copy()
        mult = -1.0
    else:
        b = m.lp.constraintsLower.copy()
        mult = 1.0
    if type(m.A) == csc_matrixPlus:
        A = m.A.toarray()
    else:
        A = m.A.copy()
    for i in range(m.lp.nCols):
        e = np.zeros((1, m.lp.nCols))
        if m.lp.variablesUpper[i] < infinity:
            b.resize(b.size + 1, refcheck=False)
            e[0, i] = -mult
            b[-1] = -mult * m.lp.variablesUpper[i]
            A = np.vstack((A, e))
        if m.lp.variablesLower[i] > -infinity:
            b.resize(b.size + 1, refcheck=False)
            e[0, i] = mult
            b[-1] = mult * m.lp.variablesLower[i]
            A = np.vstack((A, e))
    m.A = A
    m.b = b

    if display and filename is not None:
        disp_relaxation(f, m.A, m.b, filename=filename + '.png')
    elif display:
        disp_relaxation(f, m.A, m.b)

    disj = []
    prev_sol = np.zeros((1, m.lp.nCols))
    for i in range(max_iter):
        print('Iteration ', i)
        m.lp.primal(startFinishOptions='x')
        print('Current bound:', m.lp.objectiveValue)
        #Binv = np.zeros(shape = (lp.nConstraints, lp.nConstraints))
        #for i in range(lp.nVariables, lp.nVariables+lp.nConstraints):
        #    lp.getBInvACol(i, Binv[i-lp.nVariables,:])
        #rhs = lp.rhs
        if m.sense == '<=':
            rhs = np.dot(m.lp.basisInverse, m.lp.constraintsUpper)
        else:
            rhs = np.dot(m.lp.basisInverse, m.lp.constraintsLower)
        sol = m.lp.primalVariableSolution['x']
        if debug_print:
            print('Current basis inverse:')
            print(m.lp.basisInverse)
            print('Condition number of basis inverse',
                  np.around(np.linalg.cond(m.lp.basisInverse)))
            print('Current tableaux:')
            print(m.lp.tableau)
            print('Current right hand side:\n', rhs)
            #print('Dual solution:', m.lp.dualConstraintSolution)
            #print lp.rhs
        print('Current solution: ', sol)

        if (sol - prev_sol).any():
            prev_sol = sol
        else:
            print("Solution repeated, stalling detected")
            print("Exiting")
            break

        if isInt(sol[m.integerIndices], eps):
            print('Integer solution found!')
            break

        if np.around(np.linalg.cond(m.lp.basisInverse)) >= 10**32:
            print("Condition number of the basis matrix exceeds 10^32")
            print("Exiting")
            break

        cuts = []
        if disj == []:
            for (cg, args) in whichCuts:
                tmp_cuts, tmp_disj = cg(m, **args, eps=eps)
                cuts += tmp_cuts
                disj += tmp_disj
        cur_num_cuts = len(cuts)
        if use_cglp:
            if len(disj) > 0:
                for d in disj:
                    cuts += disjunctionToCut(m, d[0], d[1], eps=eps)
        if cuts == []:
            if disj == []:
                print('No cuts found and terminating!')
                break
            else:
                print('No cuts found but continuing!')
        if display and filename is not None:
            disp_relaxation(f,
                            m.A,
                            m.b,
                            cuts,
                            sol,
                            disj,
                            filename=filename + str(i) + '.png')
        elif display:
            disp_relaxation(f, m.A, m.b, cuts, sol, disj)
        if len(cuts) == cur_num_cuts:
            disj = []
        for (coeff, r) in cuts[:max_cuts]:
            #TODO sort cuts by degree of violation
            if m.sense == '<=':
                coeff = np.floor(coeff * (10**eps)) / (10**eps)
                r = np.ceil(r * (10**eps)) / (10**eps)
                print('Adding cut: ', coeff, '<=', r)
                m.lp += CyLPArray(coeff) * m.x <= r
            else:
                coeff = np.ceil(coeff * (10**eps)) / (10**eps)
                r = np.floor(r * (10**eps)) / (10**eps)
                print('Adding cut: ', coeff, '>=', r)
                m.lp += CyLPArray(coeff) * m.x >= r
            m.A = np.vstack((m.A, np.array(coeff)))
            m.b.resize(m.b.size + 1, refcheck=False)
            m.b[-1] = r

    if display:
        disp_relaxation(f, m.A, m.b)