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
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
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]
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)]
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
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
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
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
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
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
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
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
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
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
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
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) ]
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)]
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]
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) ]
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)]))
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)]))