def solve_sat(self, expression=None, callback=None, return_processor=None, kwargs={}): """Runs a solve sat with a callback. This is similar to the other SAT solving procedures in this test suite, with some modifications to enable testing of the MIP callback functionality. expression is the expression argument, and defaults to the expression declared in the MIPCallbackTest. callback is the callback instance being tested. return_processor is a function called with the retval from the lp.integer call, and the lp, e.g., return_processor(retval, lp), prior to any further processing of the results. kwargs is a dictionary of other optional keyword arguments and their values which is passed to the lp.integer solution procedure.""" if expression is None: expression = self.expression if len(expression) == 0: return [] numvars = max(max(abs(v) for v in clause) for clause in expression) lp = LPX() lp.cols.add(2*numvars) for col in lp.cols: col.bounds = 0.0, 1.0 def lit2col(lit): if lit > 0: return 2*lit-2 return 2*(-lit)-1 for i in range(1, numvars+1): lp.cols[lit2col(i)].name = 'x_%d' % i lp.cols[lit2col(-i)].name = '!x_%d' % i lp.rows.add(1) lp.rows[-1].matrix = [(lit2col(i), 1.0), (lit2col(-i), 1.0)] lp.rows[-1].bounds = 1.0 for clause in expression: lp.rows.add(1) lp.rows[-1].matrix = [(lit2col(lit), 1.0) for lit in clause] lp.rows[-1].bounds = 1, None retval = lp.simplex() if retval is not None: return None if lp.status != 'opt': return None for col in lp.cols: col.kind = int retval = lp.integer(callback=callback, **kwargs) if return_processor: return_processor(retval, lp) if retval is not None: return None if lp.status != 'opt': return None return [col.value > 0.99 for col in lp.cols[::2]]
def testLpxRay(self): lp = LPX() self.assertTrue(lp.ray is None) lp.cols.add(2) x1, x2 = lp.cols[0:2] lp.obj[:] = [-1.0, 1.0] lp.rows.add(2) r1, r2 = lp.rows[0:2] r1.matrix = [1.0, -1.0] r1.bounds = (-3, None) r2.matrix = [-1.0, 2.0] r2.bounds = (-2.0, None) x1.bounds = None x2.bounds = None lp.simplex() self.assertEqual(lp.status, 'unbnd') self.assertTrue(lp.ray.iscol)
def solve_sat(self, expression): """Attempts to satisfy a formula of conjunction of disjunctions. If there are n variables in the expression, this will return a list of length n, all elements booleans. The truth of element i-1 corresponds to the truth of variable i. If no satisfying assignment could be found, None is returned.""" if len(expression) == 0: return [] numvars = max(max(abs(v) for v in clause) for clause in expression) lp = LPX() lp.cols.add(2*numvars) for col in lp.cols: col.bounds = 0.0, 1.0 def lit2col(lit): if lit > 0: return 2*lit-2 return 2*(-lit)-1 for i in range(1, numvars+1): lp.cols[lit2col(i)].name = 'x_%d' % i lp.cols[lit2col(-i)].name = '!x_%d' % i lp.rows.add(1) lp.rows[-1].matrix = [(lit2col(i), 1.0), (lit2col(-i), 1.0)] lp.rows[-1].bounds = 1.0 for clause in expression: lp.rows.add(1) lp.rows[-1].matrix = [(lit2col(lit), 1.0) for lit in clause] lp.rows[-1].bounds = 1, None retval = lp.simplex() if retval is not None: return None if lp.status != 'opt': return None for col in lp.cols: col.kind = int retval = lp.integer() if retval is not None: return None if lp.status != 'opt': return None return [col.value > 0.99 for col in lp.cols[::2]]
lp.name = 'example' lp.obj.maximize = True # append 3 rows, named p, q, r row_names = ["p", "q", "r"] lp.rows.add(len(row_names)) for r in lp.rows: r.name = row_names[r.index] lp.rows[0].bounds = None, 100.0 lp.rows[1].bounds = None, 600.0 lp.rows[2].bounds = None, 150.0 # append 3 cols, named x0, x1, x2 lp.cols.add(3) for c in lp.cols: c.name = 'x%d' % c.index c.bounds = 0.0, None # set the objective coefficients and # non-zero entries of the constraint matrix lp.obj[:] = [ 5.0, 3.0, 2.0 ] lp.matrix = [ 1.0, 1.0, 3.0, 10.0, 4.0, 5.0, 1.0, 1.0, 3.0 ] # report the objective function value and structural variables lp.simplex(msg_lev=LPX.MSG_ALL) print 'Z = %g;' % lp.obj.value, print '; '.join('%s = %g' % (c.name, c.primal) for c in lp.cols)
def _optimize_glpk( cobra_model, new_objective=None, objective_sense='maximize', min_norm=0, the_problem=None, tolerance_optimality=1e-6, tolerance_feasibility=1e-6, tolerance_integer=1e-9, error_reporting=None, print_solver_time=False, lp_method=1, quadratic_component=None, reuse_basis=True, #Not implemented tolerance_barrier=None, lp_parallel=None, copy_problem=None, relax_b=None, update_problem_reaction_bounds=True): """Uses the GLPK (www.gnu.org/software/glpk/) optimizer via pyglpk (http://www.tfinley.net/software/pyglpk/release.html) to perform an optimization on cobra_model for the objective_coefficients in cobra_model._objective_coefficients based on the objective sense. cobra_model: A cobra.Model object new_objective: Reaction, String, or Integer referring to a reaction in cobra_model.reactions to set as the objective. Currently, only supports single objective coeffients. Will expand to include mixed objectives. objective_sense: 'maximize' or 'minimize' min_norm: not implemented the_problem: None or a problem object for the specific solver that can be used to hot start the next solution. tolerance_optimality: Solver tolerance for optimality. tolerance_feasibility: Solver tolerance for feasibility. error_reporting: None or True to disable or enable printing errors encountered when trying to find the optimal solution. print_solver_time: False or True. Indicates if the time to calculate the solution should be displayed. quadratic_component: None. GLPK cannot solve quadratic programs at the moment. reuse_basis: Boolean. If True and the_problem is a model object for the solver, attempt to hot start the solution. Currently, only True is available for GLPK update_problem_reaction_bounds: Boolean. Set to True if you're providing the_problem and you've modified reaction bounds on your cobra_model since creating the_problem. Only necessary for CPLEX lp.simplex() with Salmonella model: cold start: 0.42 seconds hot start: 0.0013 seconds """ from numpy import zeros, array, nan #TODO: Speed up problem creation if hasattr(quadratic_component, 'todok'): raise Exception('GLPK cannot solve quadratic programs please '+\ 'try using the gurobi or cplex solvers') from glpk import LPX from cobra.flux_analysis.objective import update_objective from cobra.solvers.legacy import status_dict, variable_kind_dict status_dict = eval(status_dict['glpk']) variable_kind_dict = eval(variable_kind_dict['glpk']) if new_objective and new_objective != 'update problem': update_objective(cobra_model, new_objective) #Faster to use these dicts than index lists index_to_metabolite = dict( zip(range(len(cobra_model.metabolites)), cobra_model.metabolites)) index_to_reaction = dict( zip(range(len(cobra_model.reactions)), cobra_model.reactions)) reaction_to_index = dict( zip(index_to_reaction.values(), index_to_reaction.keys())) if the_problem == None or the_problem in ['return', 'setup'] or \ not isinstance(the_problem, LPX): lp = LPX() # Create empty problem instance lp.name = 'cobra' # Assign symbolic name to problem lp.rows.add(len(cobra_model.metabolites)) lp.cols.add(len(cobra_model.reactions)) linear_constraints = [] for r in lp.rows: the_metabolite = index_to_metabolite[r.index] r.name = the_metabolite.id b = float(the_metabolite._bound) c = the_metabolite._constraint_sense if c == 'E': r.bounds = b, b # Set metabolite to steady state levels elif c == 'L': r.bounds = None, b elif c == 'G': r.bounds = b, None #Add in the linear constraints for the_reaction in the_metabolite._reaction: reaction_index = reaction_to_index[the_reaction] the_coefficient = the_reaction._metabolites[the_metabolite] linear_constraints.append( (r.index, reaction_index, the_coefficient)) #Need to assign lp.matrix after constructing the whole list lp.matrix = linear_constraints objective_coefficients = [] for c in lp.cols: the_reaction = index_to_reaction[c.index] c.name = the_reaction.id the_reaction = index_to_reaction[c.index] c.kind = variable_kind_dict[the_reaction.variable_kind] c.bounds = the_reaction.lower_bound, the_reaction.upper_bound objective_coefficients.append( float(the_reaction.objective_coefficient)) #Add the new objective coefficients to the problem lp.obj[:] = objective_coefficients else: lp = the_problem #BUG with changing / unchanging the basis if new_objective is not None: objective_coefficients = [] for c in lp.cols: # Iterate over all rows the_reaction = index_to_reaction[c.index] c.name = the_reaction.id c.bounds = the_reaction.lower_bound, the_reaction.upper_bound objective_coefficients.append( float(the_reaction.objective_coefficient)) c.kind = variable_kind_dict[the_reaction.variable_kind] #Add the new objective coefficients to the problem lp.obj[:] = objective_coefficients else: for c in lp.cols: # Iterate over all rows the_reaction = index_to_reaction[c.index] c.name = the_reaction.id c.bounds = the_reaction.lower_bound, the_reaction.upper_bound c.kind = variable_kind_dict[the_reaction.variable_kind] if objective_sense.lower() == 'maximize': lp.obj.maximize = True # Set this as a maximization problem else: lp.obj.maximize = False if the_problem == 'setup': return lp if print_solver_time: start_time = time() the_methods = [1, 2, 3] if lp_method in the_methods: the_methods.remove(lp_method) else: lp_method = 1 if not isinstance(the_problem, LPX): if lp.kind == int: lp.simplex(tol_bnd=tolerance_optimality, tol_dj=tolerance_optimality, meth=lp_method) # we first have to solve the LP? lp.integer(tol_int=tolerance_integer) else: lp.simplex(tol_bnd=tolerance_optimality, tol_dj=tolerance_optimality, meth=lp_method) # Solve this LP or MIP with the simplex (depending on if integer variables exist). Takes about 0.35 s without hot start if lp.status in status_dict: status = status_dict[lp.status] else: status = 'failed' if status != 'optimal': for lp_method in the_methods: lp.simplex(tol_bnd=tolerance_optimality, tol_dj=tolerance_optimality, meth=lp_method) if lp.status == 'opt': if lp.kind == int: lp.integer(tol_int=tolerance_integer) break else: if lp.kind == int: lp.simplex(tol_bnd=tolerance_optimality, tol_dj=tolerance_optimality, meth=lp_method, tm_lim=100) # we first have to solve the LP? lp.integer(tol_int=tolerance_integer) else: lp.simplex(tol_bnd=tolerance_optimality, tol_dj=tolerance_optimality, meth=lp_method, tm_lim=100) #If the solver takes more than 0.1 s with a hot start it is likely stuck if lp.status in status_dict: status = status_dict[lp.status] else: status = 'failed' if status != 'optimal': if lp.kind == int: lp.simplex(tol_bnd=tolerance_optimality, tol_dj=tolerance_optimality, meth=lp_method) # we first have to solve the LP? lp.integer(tol_int=tolerance_integer) else: for lp_method in the_methods: lp.simplex(tol_bnd=tolerance_optimality, tol_dj=tolerance_optimality, meth=lp_method) if lp.status == 'opt': if lp.kind == int: lp.integer(tol_int=tolerance_integer) break if lp.status in status_dict: status = status_dict[lp.status] else: status = 'failed' if status != 'optimal': lp = optimize_glpk( cobra_model, new_objective=new_objective, objective_sense=objective_sense, min_norm=min_norm, the_problem=None, print_solver_time=print_solver_time, tolerance_optimality=tolerance_optimality, tolerance_feasibility=tolerance_feasibility)['the_problem'] if lp.status == 'opt': if lp.kind == int: lp.integer(tol_int=tolerance_integer) if lp.status in status_dict: status = status_dict[lp.status] else: status = 'failed' if status != 'optimal': lp.simplex(tol_bnd=tolerance_optimality, presolve=True, tm_lim=5000) if lp.kind == int: lp.integer(tol_int=tolerance_integer) if print_solver_time: print 'simplex time: %f' % (time() - start_time) x = [] y = [] x_dict = {} y_dict = {} if lp.status in status_dict: status = status_dict[lp.status] else: status = 'failed' if status == 'optimal': objective_value = lp.obj.value [(x.append(float(c.primal)), x_dict.update({c.name: c.primal})) for c in lp.cols] if lp.kind == float: #return the duals as well as the primals for LPs [(y.append(float(c.dual)), y_dict.update({c.name: c.dual})) for c in lp.rows] else: #MIPs don't have duals y = y_dict = None x = array(x) else: x = y = x_dict = y_dict = objective_value = None if error_reporting: print 'glpk failed: %s' % lp.status cobra_model.solution = the_solution = Solution(objective_value, x=x, x_dict=x_dict, y=y, y_dict=y_dict, status=status) solution = {'the_problem': lp, 'the_solution': the_solution} return solution
def _optimize_glpk(cobra_model, new_objective=None, objective_sense='maximize', min_norm=0, the_problem=None, tolerance_optimality=1e-6, tolerance_feasibility=1e-6, tolerance_integer=1e-9, error_reporting=None, print_solver_time=False, lp_method=1, quadratic_component=None, reuse_basis=True, #Not implemented tolerance_barrier=None, lp_parallel=None, copy_problem=None, relax_b=None,update_problem_reaction_bounds=True): """Uses the GLPK (www.gnu.org/software/glpk/) optimizer via pyglpk (http://www.tfinley.net/software/pyglpk/release.html) to perform an optimization on cobra_model for the objective_coefficients in cobra_model._objective_coefficients based on the objective sense. cobra_model: A cobra.Model object new_objective: Reaction, String, or Integer referring to a reaction in cobra_model.reactions to set as the objective. Currently, only supports single objective coeffients. Will expand to include mixed objectives. objective_sense: 'maximize' or 'minimize' min_norm: not implemented the_problem: None or a problem object for the specific solver that can be used to hot start the next solution. tolerance_optimality: Solver tolerance for optimality. tolerance_feasibility: Solver tolerance for feasibility. error_reporting: None or True to disable or enable printing errors encountered when trying to find the optimal solution. print_solver_time: False or True. Indicates if the time to calculate the solution should be displayed. quadratic_component: None. GLPK cannot solve quadratic programs at the moment. reuse_basis: Boolean. If True and the_problem is a model object for the solver, attempt to hot start the solution. Currently, only True is available for GLPK update_problem_reaction_bounds: Boolean. Set to True if you're providing the_problem and you've modified reaction bounds on your cobra_model since creating the_problem. Only necessary for CPLEX lp.simplex() with Salmonella model: cold start: 0.42 seconds hot start: 0.0013 seconds """ from numpy import zeros, array, nan #TODO: Speed up problem creation if hasattr(quadratic_component, 'todok'): raise Exception('GLPK cannot solve quadratic programs please '+\ 'try using the gurobi or cplex solvers') from glpk import LPX from cobra.flux_analysis.objective import update_objective from cobra.solvers.legacy import status_dict, variable_kind_dict status_dict = eval(status_dict['glpk']) variable_kind_dict = eval(variable_kind_dict['glpk']) if new_objective and new_objective != 'update problem': update_objective(cobra_model, new_objective) #Faster to use these dicts than index lists index_to_metabolite = dict(zip(range(len(cobra_model.metabolites)), cobra_model.metabolites)) index_to_reaction = dict(zip(range(len(cobra_model.reactions)), cobra_model.reactions)) reaction_to_index = dict(zip(index_to_reaction.values(), index_to_reaction.keys())) if the_problem == None or the_problem in ['return', 'setup'] or \ not isinstance(the_problem, LPX): lp = LPX() # Create empty problem instance lp.name = 'cobra' # Assign symbolic name to problem lp.rows.add(len(cobra_model.metabolites)) lp.cols.add(len(cobra_model.reactions)) linear_constraints = [] for r in lp.rows: the_metabolite = index_to_metabolite[r.index] r.name = the_metabolite.id b = float(the_metabolite._bound) c = the_metabolite._constraint_sense if c == 'E': r.bounds = b, b # Set metabolite to steady state levels elif c == 'L': r.bounds = None, b elif c == 'G': r.bounds = b, None #Add in the linear constraints for the_reaction in the_metabolite._reaction: reaction_index = reaction_to_index[the_reaction] the_coefficient = the_reaction._metabolites[the_metabolite] linear_constraints.append((r.index, reaction_index, the_coefficient)) #Need to assign lp.matrix after constructing the whole list lp.matrix = linear_constraints objective_coefficients = [] for c in lp.cols: the_reaction = index_to_reaction[c.index] c.name = the_reaction.id the_reaction = index_to_reaction[c.index] c.kind = variable_kind_dict[the_reaction.variable_kind] c.bounds = the_reaction.lower_bound, the_reaction.upper_bound objective_coefficients.append(float(the_reaction.objective_coefficient)) #Add the new objective coefficients to the problem lp.obj[:] = objective_coefficients else: lp = the_problem #BUG with changing / unchanging the basis if new_objective is not None: objective_coefficients = [] for c in lp.cols: # Iterate over all rows the_reaction = index_to_reaction[c.index] c.name = the_reaction.id c.bounds = the_reaction.lower_bound, the_reaction.upper_bound objective_coefficients.append(float(the_reaction.objective_coefficient)) c.kind = variable_kind_dict[the_reaction.variable_kind] #Add the new objective coefficients to the problem lp.obj[:] = objective_coefficients else: for c in lp.cols: # Iterate over all rows the_reaction = index_to_reaction[c.index] c.name = the_reaction.id c.bounds = the_reaction.lower_bound, the_reaction.upper_bound c.kind = variable_kind_dict[the_reaction.variable_kind] if objective_sense.lower() == 'maximize': lp.obj.maximize = True # Set this as a maximization problem else: lp.obj.maximize = False if the_problem == 'setup': return lp if print_solver_time: start_time = time() the_methods = [1, 2, 3] if lp_method in the_methods: the_methods.remove(lp_method) else: lp_method = 1 if not isinstance(the_problem, LPX): if lp.kind == int: lp.simplex(tol_bnd=tolerance_optimality, tol_dj=tolerance_optimality, meth=lp_method) # we first have to solve the LP? lp.integer(tol_int=tolerance_integer) else: lp.simplex(tol_bnd=tolerance_optimality, tol_dj=tolerance_optimality, meth=lp_method) # Solve this LP or MIP with the simplex (depending on if integer variables exist). Takes about 0.35 s without hot start if lp.status in status_dict: status = status_dict[lp.status] else: status = 'failed' if status != 'optimal': for lp_method in the_methods: lp.simplex(tol_bnd=tolerance_optimality, tol_dj=tolerance_optimality, meth=lp_method) if lp.status == 'opt': if lp.kind == int: lp.integer(tol_int=tolerance_integer) break else: if lp.kind == int: lp.simplex(tol_bnd=tolerance_optimality, tol_dj=tolerance_optimality, meth=lp_method, tm_lim=100) # we first have to solve the LP? lp.integer(tol_int=tolerance_integer) else: lp.simplex(tol_bnd=tolerance_optimality, tol_dj=tolerance_optimality, meth=lp_method, tm_lim=100) #If the solver takes more than 0.1 s with a hot start it is likely stuck if lp.status in status_dict: status = status_dict[lp.status] else: status = 'failed' if status != 'optimal': if lp.kind == int: lp.simplex(tol_bnd=tolerance_optimality, tol_dj=tolerance_optimality, meth=lp_method) # we first have to solve the LP? lp.integer(tol_int=tolerance_integer) else: for lp_method in the_methods: lp.simplex(tol_bnd=tolerance_optimality, tol_dj=tolerance_optimality, meth=lp_method) if lp.status == 'opt': if lp.kind == int: lp.integer(tol_int=tolerance_integer) break if lp.status in status_dict: status = status_dict[lp.status] else: status = 'failed' if status != 'optimal': lp = optimize_glpk(cobra_model, new_objective=new_objective, objective_sense=objective_sense, min_norm=min_norm, the_problem=None, print_solver_time=print_solver_time, tolerance_optimality=tolerance_optimality, tolerance_feasibility=tolerance_feasibility)['the_problem'] if lp.status == 'opt': if lp.kind == int: lp.integer(tol_int=tolerance_integer) if lp.status in status_dict: status = status_dict[lp.status] else: status = 'failed' if status != 'optimal': lp.simplex(tol_bnd=tolerance_optimality, presolve=True, tm_lim=5000) if lp.kind == int: lp.integer(tol_int=tolerance_integer) if print_solver_time: print 'simplex time: %f'%(time() - start_time) x = [] y = [] x_dict = {} y_dict = {} if lp.status in status_dict: status = status_dict[lp.status] else: status = 'failed' if status == 'optimal': objective_value = lp.obj.value [(x.append(float(c.primal)), x_dict.update({c.name:c.primal})) for c in lp.cols] if lp.kind == float: #return the duals as well as the primals for LPs [(y.append(float(c.dual)), y_dict.update({c.name:c.dual})) for c in lp.rows] else: #MIPs don't have duals y = y_dict = None x = array(x) else: x = y = x_dict = y_dict = objective_value = None if error_reporting: print 'glpk failed: %s'%lp.status the_solution = Solution(objective_value, x=x, x_dict=x_dict, y=y, y_dict=y_dict, status=status) solution = {'the_problem': lp, 'the_solution': the_solution} return solution
lp.name = 'foobartendr' lp.obj.maximize = True # append 3 rows row_names = ["ingrednt", "bartendr", "delivery"] lp.rows.add(len(row_names)) for r in lp.rows: r.name = row_names[r.index] lp.rows[0].bounds = None, 100.0 lp.rows[1].bounds = None, 600.0 lp.rows[2].bounds = None, 150.0 # append 3 cols, named x0, x1, x2 lp.cols.add(3) for c in lp.cols: c.name = 'x%d' % c.index c.bounds = 0.0, None # set the objective coefficients and # non-zero entries of the constraint matrix lp.obj[:] = [ 5.0, 3.0, 2.0 ] lp.matrix = [ 1.0, 1.0, 3.0, 10.0, 4.0, 5.0, 1.0, 1.0, 3.0 ] # report the objective function value and structural variables lp.simplex(msg_lev=LPX.MSG_ALL) print 'Z = %g;' % lp.obj.value, print '; '.join('%s = %g' % (c.name, c.primal) for c in lp.cols)