示例#1
0
def halfint_correlation_clustering(similarity):
    """Wacky MIP-based half-int constrained correlation clustering."""
    lp = yaposib.Problem(yaposib.available_solvers()[0])                   # Define the linear program.
    items = len(similarity)                  # Get the number of items.
    lp.obj.maximize = True                   # Set as maximization.
    for i in range((items*(items-1))/2):
        lp.cols.add(yaposib.vec([]))         # Each item pair has a var.
    for j in xrange(items):
        for i in xrange(j):
            index = pair2index(i, j)         # Get the index for this pair.
            lp.cols[index].lowerbound = 0    # Each variable in range 0 to 1.
            lp.cols[index].upperbound = 2    # Each variable in range 0 to 1.
            lp.cols[index].integer = True    # This should be integral.
            lp.obj[index]=similarity[j][i]/2 # If 1, this much added to obj.
    for k in xrange(items):                  # For all triples of items, we
        for j in xrange(k):                  # want to add in constraints to
            jk = pair2index(j,k)             # enforce respect for the
            for i in xrange(j):              # triangle inequality.
                ij, ik = pair2index(i,j), pair2index(i,k)
                # We want Xij >= Xik + Xjk - 1.
                # That is, we want 1 >= Xik + Xjk - Xij.
                # Add constraints to enforce this!
                lp.rows.add(yaposib.vec([(ij, 1), (ik, 1), (jk,-1)]))
                lp.rows.add(yaposib.vec([(ij, 1), (ik,-1), (jk, 1)]))
                lp.rows.add(yaposib.vec([(ij,-1), (ik, 1), (jk, 1)]))
    for row in lp.rows:                      # For each row.
        row.upperbound = 2                   # Each row is <= 1.
    lp.solveMIP()                            # Find the basic solution.
    labels = [[lp.cols[pair2index(i,j)].solution/2 for i in xrange(j)]
              for j in xrange(items)]
    return lp.obj.value, labels
示例#2
0
def halfint_correlation_clustering(similarity):
    """Wacky MIP-based half-int constrained correlation clustering."""
    lp = yaposib.Problem(
        yaposib.available_solvers()[0])  # Define the linear program.
    items = len(similarity)  # Get the number of items.
    lp.obj.maximize = True  # Set as maximization.
    for i in range((items * (items - 1)) / 2):
        lp.cols.add(yaposib.vec([]))  # Each item pair has a var.
    for j in xrange(items):
        for i in xrange(j):
            index = pair2index(i, j)  # Get the index for this pair.
            lp.cols[index].lowerbound = 0  # Each variable in range 0 to 1.
            lp.cols[index].upperbound = 2  # Each variable in range 0 to 1.
            lp.cols[index].integer = True  # This should be integral.
            lp.obj[
                index] = similarity[j][i] / 2  # If 1, this much added to obj.
    for k in xrange(items):  # For all triples of items, we
        for j in xrange(k):  # want to add in constraints to
            jk = pair2index(j, k)  # enforce respect for the
            for i in xrange(j):  # triangle inequality.
                ij, ik = pair2index(i, j), pair2index(i, k)
                # We want Xij >= Xik + Xjk - 1.
                # That is, we want 1 >= Xik + Xjk - Xij.
                # Add constraints to enforce this!
                lp.rows.add(yaposib.vec([(ij, 1), (ik, 1), (jk, -1)]))
                lp.rows.add(yaposib.vec([(ij, 1), (ik, -1), (jk, 1)]))
                lp.rows.add(yaposib.vec([(ij, -1), (ik, 1), (jk, 1)]))
    for row in lp.rows:  # For each row.
        row.upperbound = 2  # Each row is <= 1.
    lp.solveMIP()  # Find the basic solution.
    labels = [[lp.cols[pair2index(i, j)].solution / 2 for i in xrange(j)]
              for j in xrange(items)]
    return lp.obj.value, labels
示例#3
0
def hamiltonian(edges):
    node2colnums = {} # Maps node to col indices of incident edges.
    for colnum, edge in enumerate(edges):
        n1, n2 = edge
        node2colnums.setdefault(n1, []).append(colnum)
        node2colnums.setdefault(n2, []).append(colnum)

    print node2colnums

    lp = yaposib.Problem(yaposib.available_solvers()[0])              # A new empty linear program
    for i in range(len(edges)):
        col = lp.cols.add(yaposib.vec([]))  # A struct var for each edge
        col.integer = True                  # Make integer, not continuous
        col.lowerbound = 0                  # Make binary, not continuous
        col.upperbound = 1                  # Make binary, not continuous

    # For each node, select at least 1 and at most 2 incident edges.
    for edge_column_nums in node2colnums.values():
        row = lp.rows.add(yaposib.vec([(cn, 1.0) for cn in edge_column_nums]))
        row.lowerbound = 1
        row.upperbound = 2

    # We should select exactly (number of nodes - 1) edges total
    row = lp.rows.add(yaposib.vec([(cn, 1.0) for cn in
        range(len(lp.cols))]))
    row.lowerbound = row.upperbound = len(node2colnums)-1

    lp.solve()
    if lp.status != 'optimal': return None  # If no relaxed sol., no exact sol.

    # Return the edges whose associated struct var has value 1.
    return [edge for edge, col in zip(edges, lp.cols) if col.solution > 0.99]
示例#4
0
文件: sat.py 项目: tkralphs/yaposib
def solve_sat(expression):
    if len(expression) == 0: return []  # Trivial case.  Otherwise count vars.
    numvars = max([max([abs(v) for v in clause]) for clause in expression])
    lp = yaposib.Problem(
        yaposib.available_solvers()[0])  # Construct an empty linear program.
    for i in range(2 * numvars):
        col = lp.cols.add(yaposib.vec(
            []))  # As many columns as there are literals.
        col.lowerbound = 0.0  # Literal must be between false and true.
        col.upperbound = 1.0

    def lit2col(lit):  # Function to compute column index.
        return [2 * (-lit) - 1, 2 * lit - 2][lit > 0]

    for i in xrange(1, numvars + 1):  # Ensure "oppositeness" of literals.
        row = lp.rows.add(yaposib.vec([(lit2col(i), 1.0), (lit2col(-i), 1.0)]))
        row.lowerbound = row.upperbound = 1.0  # Must sum to exactly 1.
    for clause in expression:  # Ensure "trueness" of each clause.
        row = lp.rows.add(yaposib.vec([(lit2col(lit), 1.0) for lit in clause]))
        row.lowerbound = 1.0  # At least one literal must be true.
    lp.solve()  # Try to solve the relaxed problem.
    if lp.status != 'optimal':
        return None  # If no relaxed solution, no exact sol.

    for col in lp.cols:
        col.integer = True
    lp.solveMIP()  # Try to solve this integer problem.
    if lp.status != 'optimal': return None
    return [lp.cols[i].solution > 0.99 for i in range(0, len(lp.cols), 2)]
示例#5
0
def unbounded(solver):
    """
    returns the following problem

    0  <= x <= 4
    -1 <= y <= 1
    0  <= z
    0  <= w

    maximize obj = x + 4*y + 9*z + w
    such that:
    c1: x+y <= 5
    c2: x+z >= 10
    c3: -y+z == 7
    c4: w >= 0
    """
    prob = yaposib.Problem(solver)
    obj = prob.obj
    obj.name = "unbounded"
    obj.maximize = True
    # names
    cols = prob.cols
    for i in range(4):
        cols.add(yaposib.vec([]))
    cols[0].name = "x"
    cols[1].name = "y"
    cols[2].name = "z"
    cols[3].name = "w"
    # lowerbounds
    for col in cols:
        col.lowerbound = 0
    cols[1].lowerbound = -1
    # upperbounds
    cols[0].upperbound = 4
    cols[1].upperbound = 1
    # constraints
    rows = prob.rows
    rows.add(yaposib.vec([(0, 1), (1, 1)]))
    rows.add(yaposib.vec([(0, 1), (2, 1)]))
    rows.add(yaposib.vec([(1, -1), (2, 1)]))
    rows.add(yaposib.vec([(3, 1)]))
    # constraints bounds
    rows[0].upperbound = 5
    rows[1].lowerbound = 10
    rows[2].lowerbound = 7
    rows[2].upperbound = 7
    rows[3].lowerbound = 0
    # constraints names
    rows[0].name = "c1"
    rows[1].name = "c2"
    rows[2].name = "c3"
    rows[3].name = "c4"
    # obj
    prob.obj[0] = 1
    prob.obj[1] = 4
    prob.obj[2] = 9
    prob.obj[3] = 1
    return prob
示例#6
0
def unbounded(solver):
    """
    returns the following problem

    0  <= x <= 4
    -1 <= y <= 1
    0  <= z
    0  <= w

    maximize obj = x + 4*y + 9*z + w
    such that:
    c1: x+y <= 5
    c2: x+z >= 10
    c3: -y+z == 7
    c4: w >= 0
    """
    prob = yaposib.Problem(solver)
    obj = prob.obj
    obj.name = "unbounded"
    obj.maximize = True
    # names
    cols = prob.cols
    for i in range(4):
        cols.add(yaposib.vec([]))
    cols[0].name = "x"
    cols[1].name = "y"
    cols[2].name = "z"
    cols[3].name = "w"
    # lowerbounds
    for col in cols:
        col.lowerbound = 0
    cols[1].lowerbound = -1
    # upperbounds
    cols[0].upperbound = 4
    cols[1].upperbound = 1
    # constraints
    rows = prob.rows
    rows.add(yaposib.vec([(0,1),(1,1)]))
    rows.add(yaposib.vec([(0,1),(2,1)]))
    rows.add(yaposib.vec([(1,-1),(2,1)]))
    rows.add(yaposib.vec([(3,1)]))
    # constraints bounds
    rows[0].upperbound = 5
    rows[1].lowerbound = 10
    rows[2].lowerbound = 7
    rows[2].upperbound = 7
    rows[3].lowerbound = 0
    # constraints names
    rows[0].name = "c1"
    rows[1].name = "c2"
    rows[2].name = "c3"
    rows[3].name = "c4"
    # obj
    prob.obj[0] = 1
    prob.obj[1] = 4
    prob.obj[2] = 9
    prob.obj[3] = 1
    return prob
示例#7
0
def mip(solver):
    """
    returns the following problem

    0  <= x <= 4
    -1 <= y <= 1
    0  <= z

    minimize obj = x + 4*y + 9*z
    such that:
    c1: x+y <= 5
    c2: x+z >= 10
    c3: -y+z == 7.5

    z integer
    """
    prob = yaposib.Problem(solver)
    obj = prob.obj
    obj.name = "mip"
    obj.maximize = False
    # names
    cols = prob.cols
    for i in range(3):
        cols.add(yaposib.vec([]))
    cols[0].name = "x"
    cols[1].name = "y"
    cols[2].name = "z"
    # lowerbounds
    for col in cols:
        col.lowerbound = 0
    cols[1].lowerbound = -1
    # upperbounds
    cols[0].upperbound = 4
    cols[1].upperbound = 1
    # integer variables
    cols[2].integer = True
    # constraints
    rows = prob.rows
    rows.add(yaposib.vec([(0,1),(1,1)]))
    rows.add(yaposib.vec([(0,1),(2,1)]))
    rows.add(yaposib.vec([(1,-1),(2,1)]))
    # constraints bounds
    rows[0].upperbound = 5
    rows[1].lowerbound = 10
    rows[2].lowerbound = 7.5
    rows[2].upperbound = 7.5
    # constraints names
    rows[0].name = "c1"
    rows[1].name = "c2"
    rows[2].name = "c3"
    # obj
    prob.obj[0] = 1
    prob.obj[1] = 4
    prob.obj[2] = 9
    return prob
示例#8
0
def mip(solver):
    """
    returns the following problem

    0  <= x <= 4
    -1 <= y <= 1
    0  <= z

    minimize obj = x + 4*y + 9*z
    such that:
    c1: x+y <= 5
    c2: x+z >= 10
    c3: -y+z == 7.5

    z integer
    """
    prob = yaposib.Problem(solver)
    obj = prob.obj
    obj.name = "mip"
    obj.maximize = False
    # names
    cols = prob.cols
    for i in range(3):
        cols.add(yaposib.vec([]))
    cols[0].name = "x"
    cols[1].name = "y"
    cols[2].name = "z"
    # lowerbounds
    for col in cols:
        col.lowerbound = 0
    cols[1].lowerbound = -1
    # upperbounds
    cols[0].upperbound = 4
    cols[1].upperbound = 1
    # integer variables
    cols[2].integer = True
    # constraints
    rows = prob.rows
    rows.add(yaposib.vec([(0, 1), (1, 1)]))
    rows.add(yaposib.vec([(0, 1), (2, 1)]))
    rows.add(yaposib.vec([(1, -1), (2, 1)]))
    # constraints bounds
    rows[0].upperbound = 5
    rows[1].lowerbound = 10
    rows[2].lowerbound = 7.5
    rows[2].upperbound = 7.5
    # constraints names
    rows[0].name = "c1"
    rows[1].name = "c2"
    rows[2].name = "c3"
    # obj
    prob.obj[0] = 1
    prob.obj[1] = 4
    prob.obj[2] = 9
    return prob
示例#9
0
def integer_infeasible(solver):
    """
    returns the following problem

    0  <= x <= 4
    -1 <= y <= 1
    0  <= z <= 10

    no objective
    constraints:
    c1: x+y <= 5.2
    c2: x+z >= 10.3
    c3: -y+z == 7.4

    x, y, z integer
    """
    prob = yaposib.Problem(solver)
    obj = prob.obj
    obj.name = "integer_infeasible"
    obj.maximize = False
    # names
    cols = prob.cols
    for i in range(3):
        cols.add(yaposib.vec([]))
    cols[0].name = "x"
    cols[1].name = "y"
    cols[2].name = "z"
    # integer variables
    for col in cols:
        col.integer = True
    # lowerbounds
    for col in cols:
        col.lowerbound = 0
    cols[1].lowerbound = -1
    # upperbounds
    cols[0].upperbound = 4
    cols[1].upperbound = 1
    cols[2].upperbound = 10
    # constraints
    rows = prob.rows
    rows.add(yaposib.vec([(0,1),(1,1)]))
    rows.add(yaposib.vec([(0,1),(2,1)]))
    rows.add(yaposib.vec([(1,-1),(2,1)]))
    # constraints bounds
    rows[0].upperbound = 5.2
    rows[1].lowerbound = 10.3
    rows[2].lowerbound = 7.4
    rows[2].upperbound = 7.4
    # constraints names
    rows[0].name = "c1"
    rows[1].name = "c2"
    rows[2].name = "c3"
    return prob
示例#10
0
def integer_infeasible(solver):
    """
    returns the following problem

    0  <= x <= 4
    -1 <= y <= 1
    0  <= z <= 10

    no objective
    constraints:
    c1: x+y <= 5.2
    c2: x+z >= 10.3
    c3: -y+z == 7.4

    x, y, z integer
    """
    prob = yaposib.Problem(solver)
    obj = prob.obj
    obj.name = "integer_infeasible"
    obj.maximize = False
    # names
    cols = prob.cols
    for i in range(3):
        cols.add(yaposib.vec([]))
    cols[0].name = "x"
    cols[1].name = "y"
    cols[2].name = "z"
    # integer variables
    for col in cols:
        col.integer = True
    # lowerbounds
    for col in cols:
        col.lowerbound = 0
    cols[1].lowerbound = -1
    # upperbounds
    cols[0].upperbound = 4
    cols[1].upperbound = 1
    cols[2].upperbound = 10
    # constraints
    rows = prob.rows
    rows.add(yaposib.vec([(0, 1), (1, 1)]))
    rows.add(yaposib.vec([(0, 1), (2, 1)]))
    rows.add(yaposib.vec([(1, -1), (2, 1)]))
    # constraints bounds
    rows[0].upperbound = 5.2
    rows[1].lowerbound = 10.3
    rows[2].lowerbound = 7.4
    rows[2].upperbound = 7.4
    # constraints names
    rows[0].name = "c1"
    rows[1].name = "c2"
    rows[2].name = "c3"
    return prob
示例#11
0
def feasability_only(solver):
    """
    returns the following problem

    0  <= x <= 4
    -1 <= y <= 1
    0  <= z

    no objective
    constraints:
    c1: x+y <= 5
    c2: x+z >= 10
    c3: -y+z == 7.5

    z integer
    """
    prob = yaposib.Problem(solver)
    obj = prob.obj
    obj.name = "feasability_only"
    obj.maximize = False
    # names
    cols = prob.cols
    for i in range(3):
        cols.add(yaposib.vec([]))
    cols[0].name = "x"
    cols[1].name = "y"
    cols[2].name = "z"
    # lowerbounds
    for col in cols:
        col.lowerbound = 0
    cols[1].lowerbound = -1
    # upperbounds
    cols[0].upperbound = 4
    cols[1].upperbound = 1
    # integer variables
    cols[2].integer = True
    # constraints
    rows = prob.rows
    rows.add(yaposib.vec([(0,1),(1,1)]))
    rows.add(yaposib.vec([(0,1),(2,1)]))
    rows.add(yaposib.vec([(1,-1),(2,1)]))
    # constraints bounds
    rows[0].upperbound = 5
    rows[1].lowerbound = 10
    rows[2].lowerbound = 7.5
    rows[2].upperbound = 7.5
    # constraints names
    rows[0].name = "c1"
    rows[1].name = "c2"
    rows[2].name = "c3"
    return prob
示例#12
0
def duals_and_slacks(solver):
    """
    returns the following problem

    0  <= x <= 5
    -1 <= y <= 1
    0  <= z

    Minimize obj = x + 4 y + 9 z
    constraints:
    c1: x+y <= 5
    c2: x+z >= 10
    c3: -y+z == 7
    """
    prob = yaposib.Problem(solver)
    obj = prob.obj
    obj.name = "duals_and_slacks"
    obj.maximize = False
    # names
    cols = prob.cols
    for i in range(3):
        cols.add(yaposib.vec([]))
    cols[0].name = "x"
    cols[1].name = "y"
    cols[2].name = "z"
    # lowerbounds
    for col in cols:
        col.lowerbound = 0
    cols[1].lowerbound = -1
    # upperbounds
    cols[0].upperbound = 5
    cols[1].upperbound = 1
    # constraints
    rows = prob.rows
    rows.add(yaposib.vec([(0,1),(1,1)]))
    rows.add(yaposib.vec([(0,1),(2,1)]))
    rows.add(yaposib.vec([(1,-1),(2,1)]))
    # constraints bounds
    rows[0].upperbound = 5
    rows[1].lowerbound = 10
    rows[2].lowerbound = 7
    rows[2].upperbound = 7
    # constraints names
    rows[0].name = "c1"
    rows[1].name = "c2"
    rows[2].name = "c3"
    # obj
    prob.obj[0] = 1
    prob.obj[1] = 4
    prob.obj[2] = 9
    return prob
示例#13
0
def duals_and_slacks(solver):
    """
    returns the following problem

    0  <= x <= 5
    -1 <= y <= 1
    0  <= z

    Minimize obj = x + 4 y + 9 z
    constraints:
    c1: x+y <= 5
    c2: x+z >= 10
    c3: -y+z == 7
    """
    prob = yaposib.Problem(solver)
    obj = prob.obj
    obj.name = "duals_and_slacks"
    obj.maximize = False
    # names
    cols = prob.cols
    for i in range(3):
        cols.add(yaposib.vec([]))
    cols[0].name = "x"
    cols[1].name = "y"
    cols[2].name = "z"
    # lowerbounds
    for col in cols:
        col.lowerbound = 0
    cols[1].lowerbound = -1
    # upperbounds
    cols[0].upperbound = 5
    cols[1].upperbound = 1
    # constraints
    rows = prob.rows
    rows.add(yaposib.vec([(0, 1), (1, 1)]))
    rows.add(yaposib.vec([(0, 1), (2, 1)]))
    rows.add(yaposib.vec([(1, -1), (2, 1)]))
    # constraints bounds
    rows[0].upperbound = 5
    rows[1].lowerbound = 10
    rows[2].lowerbound = 7
    rows[2].upperbound = 7
    # constraints names
    rows[0].name = "c1"
    rows[1].name = "c2"
    rows[2].name = "c3"
    # obj
    prob.obj[0] = 1
    prob.obj[1] = 4
    prob.obj[2] = 9
    return prob
示例#14
0
def feasability_only(solver):
    """
    returns the following problem

    0  <= x <= 4
    -1 <= y <= 1
    0  <= z

    no objective
    constraints:
    c1: x+y <= 5
    c2: x+z >= 10
    c3: -y+z == 7.5

    z integer
    """
    prob = yaposib.Problem(solver)
    obj = prob.obj
    obj.name = "feasability_only"
    obj.maximize = False
    # names
    cols = prob.cols
    for i in range(3):
        cols.add(yaposib.vec([]))
    cols[0].name = "x"
    cols[1].name = "y"
    cols[2].name = "z"
    # lowerbounds
    for col in cols:
        col.lowerbound = 0
    cols[1].lowerbound = -1
    # upperbounds
    cols[0].upperbound = 4
    cols[1].upperbound = 1
    # integer variables
    cols[2].integer = True
    # constraints
    rows = prob.rows
    rows.add(yaposib.vec([(0, 1), (1, 1)]))
    rows.add(yaposib.vec([(0, 1), (2, 1)]))
    rows.add(yaposib.vec([(1, -1), (2, 1)]))
    # constraints bounds
    rows[0].upperbound = 5
    rows[1].lowerbound = 10
    rows[2].lowerbound = 7.5
    rows[2].upperbound = 7.5
    # constraints names
    rows[0].name = "c1"
    rows[1].name = "c2"
    rows[2].name = "c3"
    return prob
示例#15
0
 def buildSolverModel(self, lp):
     """
     Takes the pulp lp model and translates it into a yaposib model
     """
     log.debug("create the yaposib model")
     lp.solverModel = yaposib.Problem(self.solverName)
     prob = lp.solverModel
     prob.name = lp.name
     log.debug("set the sense of the problem")
     if lp.sense == constants.LpMaximize:
         prob.obj.maximize = True
     log.debug("add the variables to the problem")
     for var in lp.variables():
         col = prob.cols.add(yaposib.vec([]))
         col.name = var.name
         if not var.lowBound is None:
             col.lowerbound = var.lowBound
         if not var.upBound is None:
             col.upperbound = var.upBound
         if var.cat == constants.LpInteger:
             col.integer = True
         prob.obj[col.index] = lp.objective.get(var, 0.0)
         var.solverVar = col
     log.debug("add the Constraints to the problem")
     for name, constraint in lp.constraints.items():
         row = prob.rows.add(
             yaposib.vec(
                 [
                     (var.solverVar.index, value)
                     for var, value in constraint.items()
                 ]
             )
         )
         if constraint.sense == constants.LpConstraintLE:
             row.upperbound = -constraint.constant
         elif constraint.sense == constants.LpConstraintGE:
             row.lowerbound = -constraint.constant
         elif constraint.sense == constants.LpConstraintEQ:
             row.upperbound = -constraint.constant
             row.lowerbound = -constraint.constant
         else:
             raise PulpSolverError("Detected an invalid constraint type")
         row.name = name
         constraint.solverConstraint = row
示例#16
0
def maxflow(capgraph, s, t):
    node2rnum = {}  # Map non-source/sink nodes to row num.
    for nfrom, nto, cap in capgraph:
        if nfrom != s and nfrom != t:
            node2rnum.setdefault(nfrom, len(node2rnum))
        if nto != s and nto != t:
            node2rnum.setdefault(nto, len(node2rnum))

    lp = yaposib.Problem(yaposib.available_solvers()[0])  # Empty LP instance.
    for i in range(len(capgraph)):
        lp.cols.add(yaposib.vec([]))  # As many columns cap-graph edges.

    mat = []  # Will hold constraint matrix entries.
    for colnum, (nfrom, nto, cap) in enumerate(capgraph):
        lp.cols[colnum].lowerbound = 0  # Flow along edge bounded by capacity.
        lp.cols[
            colnum].upperbound = cap  # Flow along edge bounded by capacity.

        if nfrom == s:
            lp.obj[colnum] = 1.0  # Flow from source increases flow value
        elif nto == s:
            lp.obj[colnum] = -1.0  # Flow to source decreases flow value

        if nfrom in node2rnum:  # Flow from node decreases its net flow
            mat.append((node2rnum[nfrom], colnum, -1.0))
        if nto in node2rnum:  # Flow to node increases its net flow
            mat.append((node2rnum[nto], colnum, 1.0))

    lp.obj.maximize = True  # Want source s max flow maximized.

    for row_nr in range(len(node2rnum)):
        to_add = [(j, coef) for i, j, coef in mat if i == row_nr]
        row = lp.rows.add(yaposib.vec(to_add))
        row.lowerbound = row.upperbound = 0  # Net flow for non-source/sink is 0.

    lp.solve()  # This should work unless capgraph bad.

    return [
        (nfrom, nto, col.solution)  # Return edges with assigned flow.
        for col, (nfrom, nto, cap) in zip(lp.cols, capgraph)
    ]
示例#17
0
def maxflow(capgraph, s, t):
    node2rnum = {}                      # Map non-source/sink nodes to row num.
    for nfrom, nto, cap in capgraph:
        if nfrom!=s and nfrom!=t:
            node2rnum.setdefault(nfrom, len(node2rnum))
        if nto!=s and nto!=t:
            node2rnum.setdefault(nto, len(node2rnum))

    lp = yaposib.Problem(yaposib.available_solvers()[0])         # Empty LP instance.
    for i in range(len(capgraph)):
        lp.cols.add(yaposib.vec([])) # As many columns cap-graph edges.

    mat = []                            # Will hold constraint matrix entries.
    for colnum, (nfrom, nto, cap) in enumerate(capgraph):
        lp.cols[colnum].lowerbound = 0  # Flow along edge bounded by capacity.
        lp.cols[colnum].upperbound = cap # Flow along edge bounded by capacity.

        if nfrom == s:
            lp.obj[colnum] =  1.0       # Flow from source increases flow value
        elif nto == s:
            lp.obj[colnum] = -1.0       # Flow to source decreases flow value

        if nfrom in node2rnum:          # Flow from node decreases its net flow
            mat.append((node2rnum[nfrom], colnum, -1.0))
        if nto in node2rnum:            # Flow to node increases its net flow
            mat.append((node2rnum[nto], colnum, 1.0))

    lp.obj.maximize = True              # Want source s max flow maximized.

    for row_nr in range(len(node2rnum)):
        to_add = [(j, coef) for i, j, coef in mat if i == row_nr]
        row = lp.rows.add(yaposib.vec(to_add))
        row.lowerbound = row.upperbound = 0 # Net flow for non-source/sink is 0.

    lp.solve()                        # This should work unless capgraph bad.

    return [(nfrom, nto, col.solution)     # Return edges with assigned flow.
            for col, (nfrom, nto, cap) in zip(lp.cols, capgraph)]
示例#18
0
def tsp(edges):
    node2colnums = {} # Maps node to col indices of incident edges.
    for colnum, edge in enumerate(edges):
        n1, n2, cost = edge
        node2colnums.setdefault(n1, []).append(colnum)
        node2colnums.setdefault(n2, []).append(colnum)

    lp = yaposib.Problem(yaposib.available_solvers()[0])              # A new empty linear program
    for i in range(len(edges)):
        col = lp.cols.add(yaposib.vec([]))  # A struct var for each edge
        col.integer = True                  # Make binary, not continuous
        col.lowerbound = 0              # Either edge selected (1) or not (0)
        col.upperbound = 1              # Either edge selected (1) or not (0)

    lp.rows.add(len(node2colnums)+1)    # Constraint for each node

    lp.obj[:] = [e[-1] for e in edges]  # Try to minimize the total costs.
    lp.obj.maximize = False

    # For each node, select two edges, i.e.., an arrival and a departure.
    for edge_column_nums in node2colnums.values():
        row = lp.rows.add(yaposib.vec([(cn, 1.0) for cn in edge_column_nums]))
        row.lowerbound = row.upperbound = 2

    # We should select exactly (number of nodes) edges total
    row = lp.rows.add(yaposib.vec([(cn, 1.0) for cn in
        range(len(lp.cols))]))
    row.lowerbound = row.upperbound = len(node2colnums)

    lp.solve()
    if lp.status != 'optimal': return None  # If no relaxed sol., no exact sol.

    lp.solveMIP()
    if lp.status != 'optimal': return None  # Count not find integer solution!

    # Return the edges whose associated struct var has value 1.
    return [edge for edge, col in zip(edges, lp.cols) if col.value > 0.99]
示例#19
0
def solve_sat(expression):
    if len(expression)==0: return [] # Trivial case.  Otherwise count vars.
    numvars = max([max([abs(v) for v in clause]) for clause in expression])
    lp = yaposib.Problem(yaposib.available_solvers()[0])           # Construct an empty linear program.
    for i in range(2*numvars):
        col = lp.cols.add(yaposib.vec([])) # As many columns as there are literals.
        col.lowerbound = 0.0         # Literal must be between false and true.
        col.upperbound = 1.0
    def lit2col(lit):                # Function to compute column index.
        return [2*(-lit)-1,2*lit-2][lit>0]
    for i in xrange(1, numvars+1):   # Ensure "oppositeness" of literals.
        row = lp.rows.add(yaposib.vec([(lit2col(i), 1.0), (lit2col(-i), 1.0)]))
        row.lowerbound = row.upperbound = 1.0 # Must sum to exactly 1.
    for clause in expression:        # Ensure "trueness" of each clause.
        row = lp.rows.add(yaposib.vec([(lit2col(lit), 1.0) for lit in clause]))
        row.lowerbound =  1.0        # At least one literal must be true.
    lp.solve()                       # Try to solve the relaxed problem.
    if lp.status!='optimal': return None # If no relaxed solution, no exact sol.

    for col in lp.cols:
        col.integer = True
    lp.solveMIP()          # Try to solve this integer problem.
    if lp.status != 'optimal': return None
    return [lp.cols[i].solution > 0.99 for i in range(0, len(lp.cols), 2) ]
示例#20
0
    0  <= w

    minimize obj = x + 4*y + 9*z
    such that:
    c1: x+y <= 5
    c2: x+z >= 10
    c3: -y+z == 7
    c4: w >= 0
    """
    prob = yaposib.Problem(yaposib.available_solvers()[0])

    prob.obj.name = "MyProblem"
    prob.obj.maximize = False
    # names
    for i in range(4):
        prob.cols.add(yaposib.vec([]))
    prob.cols[0].name = "x"
    prob.cols[1].name = "y"
    prob.cols[2].name = "z"
    prob.cols[3].name = "w"
    # lowerbounds
    for col in prob.cols:
        col.lowerbound = 0
    prob.cols[1].lowerbound = -1
    # upperbounds
    prob.cols[0].upperbound = 4
    prob.cols[1].upperbound = 1
    # constraints
    prob.rows.add(yaposib.vec([(0,1),(1,1)]))
    prob.rows.add(yaposib.vec([(0,1),(2,1)]))
    prob.rows.add(yaposib.vec([(1,-1),(2,1)]))
示例#21
0
    0  <= w

    minimize obj = x + 4*y + 9*z
    such that:
    c1: x+y <= 5
    c2: x+z >= 10
    c3: -y+z == 7
    c4: w >= 0
    """
    prob = yaposib.Problem(yaposib.available_solvers()[0])

    prob.obj.name = "MyProblem"
    prob.obj.maximize = False
    # names
    for i in range(4):
        prob.cols.add(yaposib.vec([]))
    prob.cols[0].name = "x"
    prob.cols[1].name = "y"
    prob.cols[2].name = "z"
    prob.cols[3].name = "w"
    # lowerbounds
    for col in prob.cols:
        col.lowerbound = 0
    prob.cols[1].lowerbound = -1
    # upperbounds
    prob.cols[0].upperbound = 4
    prob.cols[1].upperbound = 1
    # constraints
    prob.rows.add(yaposib.vec([(0, 1), (1, 1)]))
    prob.rows.add(yaposib.vec([(0, 1), (2, 1)]))
    prob.rows.add(yaposib.vec([(1, -1), (2, 1)]))