def create_problem(cobra_model, **kwargs): """Solver-specific method for constructing a solver problem from a cobra.Model. This can be tuned for performance using kwargs """ metabolite_to_index = {r: i for i, r in enumerate(cobra_model.metabolites)} 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)) for r, the_metabolite in zip(lp.rows, cobra_model.metabolites): 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 else: raise ValueError("invalid constraint sense") objective_coefficients = [] linear_constraints = [] for c, the_reaction in zip(lp.cols, cobra_model.reactions): c.name = the_reaction.id 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)) for metabolite, coefficient in iteritems(the_reaction._metabolites): metabolite_index = metabolite_to_index[metabolite] linear_constraints.append((metabolite_index, c.index, coefficient)) #Add the new objective coefficients to the problem lp.obj[:] = objective_coefficients #Need to assign lp.matrix after constructing the whole list #linear_constraints.sort() # if we wanted to be 100% deterministic lp.matrix = linear_constraints # make sure the objective sense is set in create_problem objective_sense = kwargs.get("objective_sense", "maximize") set_parameter(lp, "objective_sense", objective_sense) return lp
def create_problem(cobra_model, **kwargs): """Solver-specific method for constructing a solver problem from a cobra.Model. This can be tuned for performance using kwargs """ metabolite_to_index = {r: i for i, r in enumerate(cobra_model.metabolites)} 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)) for r, the_metabolite in zip(lp.rows, cobra_model.metabolites): 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 else: raise ValueError("invalid constraint sense") objective_coefficients = [] linear_constraints = [] for c, the_reaction in zip(lp.cols, cobra_model.reactions): c.name = the_reaction.id 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)) for metabolite, coefficient in iteritems(the_reaction._metabolites): metabolite_index = metabolite_to_index[metabolite] linear_constraints.append((metabolite_index, c.index, coefficient)) #Add the new objective coefficients to the problem lp.obj[:] = objective_coefficients #Need to assign lp.matrix after constructing the whole list #linear_constraints.sort() # if we wanted to be 100% deterministic lp.matrix = linear_constraints # make sure the objective sense is set in create_problem objective_sense = kwargs.get("objective_sense", "maximize") set_parameter(lp, "objective_sense", objective_sense) return lp
def create_problem(cobra_model, objective_sense="maximize", lp=None): if lp is None: lp = LPX() # Create empty problem instance lp.name = cobra_model.id lp.rows.add(len(cobra_model.metabolites)) lp.cols.add(len(cobra_model.reactions)) if objective_sense == 'maximize': lp.obj.maximize = True elif objective_sense == 'minimize': lp.obj.maximize = False else: raise ValueError("objective_sense not 'maximize' or 'minimize'") # create metabolites/constraints as rows for i, r in enumerate(lp.rows): metabolite = cobra_model.metabolites[i] r.name = metabolite.id b = float(metabolite._bound) c = metabolite._constraint_sense # constraint sense is set by changing the bounds if c == 'E': r.bounds = (b, b) elif c == 'L': r.bounds = (None, b) elif c == 'G': r.bounds = (b, None) else: raise ValueError("%s is not a valid constraint_sense" % c) # create reactions/variables as columns for i, c in enumerate(lp.cols): reaction = cobra_model.reactions[i] c.name = reaction.id c.kind = variable_kind_dict[reaction.variable_kind] c.bounds = (reaction.lower_bound, reaction.upper_bound) lp.obj[i] = float(reaction.objective_coefficient) # create S matrix lp.matrix = [(int(i), int(j), c) \ for (i, j), c in cobra_model.to_array_based_model().S.todok().iteritems()] return lp
from glpk import LPX # set up to maximize the objective function lp = LPX() 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
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
from glpk import LPX # set up to maximize the objective function lp = LPX() 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
def testLpxName(self): lp = LPX() with self.assertRaises(ValueError) as cm: lp.name = 'a' * 256 self.assertIn('name may be at most 255 chars', str(cm.exception))
from glpk import LPX # set up to maximize the objective function lp = LPX() 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