def test_add_constraint(self, core_model): cache = ProblemCache(core_model) def add_var(model, var_id): return model.solver.interface.Variable(var_id, ub=0) def add_constraint(m, const_id, var): return m.solver.interface.Constraint(var, lb=-10, ub=10, name=const_id) def update_constraint(model, const, var): return setattr(const, "ub", 1000) for i in range(10): cache.add_variable("%i" % i, add_var, None) cache.add_constraint("c%i" % i, add_constraint, update_constraint, cache.variables["%i" % i]) for i in range(10): assert cache.constraints["c%i" % i] in core_model.solver.constraints assert cache.constraints["c%i" % i].ub == 10 assert cache.constraints["c%i" % i].lb == -10 assert core_model.solver.constraints["c%i" % i].ub == 10 assert core_model.solver.constraints["c%i" % i].lb == -10 for i in range(10): cache.add_constraint("c%i" % i, add_constraint, update_constraint, cache.variables["%i" % i]) assert core_model.solver.constraints["c%i" % i].ub == 1000 cache.reset() for i in range(10): with pytest.raises(KeyError): core_model.solver.variables.__getitem__("%i" % i) with pytest.raises(KeyError): core_model.solver.constraints.__getitem__("c%i" % i)
def test_add_variable(self, core_model): cache = ProblemCache(core_model) def add_var(model, var_id): return model.solver.interface.Variable(var_id, ub=0) def update_var(model, var): return setattr(var, "ub", 1000) for i in range(10): cache.add_variable("%i" % i, add_var, update_var) for i in range(10): assert cache.variables["%i" % i] in core_model.solver.variables assert cache.variables["%i" % i].ub == 0 assert core_model.solver.variables["%i" % i].ub == 0 for i in range(10): cache.add_variable("%i" % i, add_var, update_var) assert cache.variables["%i" % i].ub == 1000 assert core_model.solver.variables["%i" % i].ub == 1000 cache.reset() for i in range(10): with pytest.raises(KeyError): core_model.solver.variables.__getitem__("%i" % i)
def lmoma(model, reference=None, cache=None, reactions=None, *args, **kwargs): """Linear Minimization Of Metabolic Adjustment [1]. Parameters ---------- model: cobra.Model reference: FluxDistributionResult, dict cache: ProblemCache reactions: list Returns ------- FluxDistributionResult Contains the result of the solver. References ---------- .. [1] Becker, S. A., Feist, A. M., Mo, M. L., Hannum, G., Palsson, B. Ø., & Herrgard, M. J. (2007). Quantitative prediction of cellular metabolism with constraint-based models: the COBRA Toolbox. Nature Protocols, 2(3), 727–38. doi:10.1038/nprot.2007.99 """ volatile = False if cache is None: volatile = True cache = ProblemCache(model) cache.begin_transaction() if not isinstance(reference, (dict, pandas.Series, FluxDistributionResult)): raise TypeError("reference must be a flux distribution (dict or FluxDistributionResult") try: for rid, flux_value in six.iteritems(reference): reaction = model.reactions.get_by_id(rid) def create_variable(model, var_id, lb): var = model.solver.interface.Variable(var_id, lb=lb) return var pos_var_id = "u_%s_pos" % rid cache.add_variable(pos_var_id, create_variable, None, 0) neg_var_id = "u_%s_neg" % rid cache.add_variable(neg_var_id, create_variable, None, 0) # ui = vi - wt def update_upper_constraint(model, constraint, var, reaction, flux_value): if constraint.lb != flux_value: constraint.lb = flux_value def create_upper_constraint(model, constraint_id, var, reaction, flux_value): constraint = model.solver.interface.Constraint(reaction.flux_expression + var, lb=flux_value, sloppy=True, name=constraint_id) return constraint cache.add_constraint("lmoma_const_%s_ub" % rid, create_upper_constraint, update_upper_constraint, cache.variables[pos_var_id], reaction, flux_value) def update_lower_constraint(model, constraint, var, reaction, flux_value): if constraint.ub != flux_value: constraint.ub = flux_value def create_lower_constraint(model, constraint_id, var, reaction, flux_value): constraint = model.solver.interface.Constraint(reaction.flux_expression - var, ub=flux_value, sloppy=True, name=constraint_id) return constraint cache.add_constraint("lmoma_const_%s_lb" % rid, create_lower_constraint, update_lower_constraint, cache.variables[neg_var_id], reaction, flux_value) def create_objective(model, variables): return model.solver.interface.Objective(add([mul((One, var)) for var in variables]), direction="min", sloppy=False) cache.add_objective(create_objective, None, cache.variables.values()) solution = model.optimize(raise_error=True) if reactions is not None: result = FluxDistributionResult( {r: solution.get_primal_by_id(r) for r in reactions}, solution.objective_value) else: result = FluxDistributionResult.from_solution(solution) return result except Exception as e: cache.rollback() raise e finally: if volatile: cache.reset()
def room(model, reference=None, cache=None, delta=0.03, epsilon=0.001, reactions=None, *args, **kwargs): """Regulatory On/Off Minimization [1]. Parameters ---------- model: cobra.Model reference: FluxDistributionResult, dict delta: float epsilon: float cache: ProblemCache Returns ------- FluxDistributionResult Contains the result of the linear solver. References ---------- .. [1] Tomer Shlomi, Omer Berkman and Eytan Ruppin, "Regulatory on/off minimization of metabolic flux changes after genetic perturbations", PNAS 2005 102 (21) 7695-7700; doi:10.1073/pnas.0406346102 """ volatile = False if cache is None: volatile = True cache = ProblemCache(model) elif not isinstance(cache, ProblemCache): raise TypeError("Invalid cache object (must be a cameo.util.ProblemCache)") cache.begin_transaction() if not isinstance(reference, (dict, pandas.Series, FluxDistributionResult)): raise TypeError("reference must be a flux distribution (dict or FluxDistributionResult") try: for rid, flux_value in six.iteritems(reference): reaction = model.reactions.get_by_id(rid) def create_variable(model, var_id): return model.solver.interface.Variable(var_id, type="binary") cache.add_variable("y_%s" % rid, create_variable, None) def create_upper_constraint(model, constraint_id, reaction, variable, flux_value, epsilon): w_u = flux_value + delta * abs(flux_value) + epsilon return model.solver.interface.Constraint( reaction.flux_expression - variable * (reaction.upper_bound - w_u), ub=w_u, sloppy=True, name=constraint_id) def update_upper_constraint(model, constraint, reaction, variable, flux_value, epsilon): w_u = flux_value + delta * abs(flux_value) + epsilon constraint.set_linear_coefficients({variable: reaction.upper_bound - w_u}) constraint.ub = w_u cache.add_constraint("room_const_%s_upper" % rid, create_upper_constraint, update_upper_constraint, reaction, cache.variables["y_%s" % rid], flux_value, epsilon) def create_lower_constraint(model, constraint_id, reaction, variable, flux_value, epsilon): w_l = flux_value - delta * abs(flux_value) - epsilon return model.solver.interface.Constraint( reaction.flux_expression - variable * (reaction.lower_bound - w_l), lb=w_l, sloppy=True, name=constraint_id) def update_lower_constraint(model, constraint, reaction, variable, flux_value, epsilon): w_l = flux_value - delta * abs(flux_value) - epsilon constraint.set_linear_coefficients({variable: reaction.lower_bound - w_l}) constraint.lb = w_l cache.add_constraint("room_const_%s_lower" % rid, create_lower_constraint, update_lower_constraint, reaction, cache.variables["y_%s" % rid], flux_value, epsilon) model.objective = model.solver.interface.Objective(add([mul([One, var]) for var in cache.variables.values()]), direction='min') solution = model.optimize(raise_error=True) if reactions is not None: result = FluxDistributionResult( {r: solution.get_primal_by_id(r) for r in reactions}, solution.objective_value) else: result = FluxDistributionResult.from_solution(solution) return result except Exception as e: cache.rollback() raise e finally: if volatile: cache.reset()
def moma(model, reference=None, cache=None, reactions=None, *args, **kwargs): """ Minimization of Metabolic Adjustment[1] Parameters ---------- model: cobra.Model reference: FluxDistributionResult, dict cache: ProblemCache reactions: list Returns ------- FluxDistributionResult Contains the result of the solver. References ---------- .. [1] Segrè, D., Vitkup, D., & Church, G. M. (2002). Analysis of optimality in natural and perturbed metabolic networks. Proceedings of the National Academy of Sciences of the United States of America, 99(23), 15112–7. doi:10.1073/pnas.232349399 """ volatile = False if cache is None: volatile = True cache = ProblemCache(model) cache.begin_transaction() try: for rid, flux_value in six.iteritems(reference): def create_variable(model, variable_id): var = model.solver.interface.Variable(variable_id) return var var_id = "moma_aux_%s" % rid cache.add_variable(var_id, create_variable, None) def create_constraint(model, constraint_id, var, reaction, flux_value): constraint = model.solver.interface.Constraint(reaction.flux_expression - var, lb=flux_value, ub=flux_value, name=constraint_id) return constraint def update_constraint(model, constraint, var, reaction, flux_value): if constraint.lb != flux_value: constraint.lb = flux_value constraint.ub = flux_value constraint_id = "moma_const_%s" % rid reaction = model.reactions.get_by_id(rid) cache.add_constraint(constraint_id, create_constraint, update_constraint, cache.variables[var_id], reaction, flux_value) def create_objective(model, variables): return model.solver.interface.Objective(Add(*[FloatOne * var ** 2 for var in variables]), direction="min", sloppy=True) cache.add_objective(create_objective, None, cache.variables.values()) solution = model.optimize(raise_error=True) if reactions is not None: result = FluxDistributionResult( {r: solution.get_primal_by_id(r) for r in reactions}, solution.objective_value) else: result = FluxDistributionResult.from_solution(solution) return result except Exception as e: cache.rollback() raise e finally: if volatile: cache.reset()
def room(model, reference=None, cache=None, delta=0.03, epsilon=0.001, reactions=None, *args, **kwargs): """Regulatory On/Off Minimization [1]. Parameters ---------- model: cobra.Model reference: FluxDistributionResult, dict delta: float epsilon: float cache: ProblemCache Returns ------- FluxDistributionResult Contains the result of the linear solver. References ---------- .. [1] Tomer Shlomi, Omer Berkman and Eytan Ruppin, "Regulatory on/off minimization of metabolic flux changes after genetic perturbations", PNAS 2005 102 (21) 7695-7700; doi:10.1073/pnas.0406346102 """ volatile = False if cache is None: volatile = True cache = ProblemCache(model) elif not isinstance(cache, ProblemCache): raise TypeError("Invalid cache object (must be a cameo.util.ProblemCache)") cache.begin_transaction() if not isinstance(reference, (dict, pandas.Series, FluxDistributionResult)): raise TypeError("reference must be a flux distribution (dict or FluxDistributionResult") try: for rid, flux_value in six.iteritems(reference): reaction = model.reactions.get_by_id(rid) def create_variable(model, var_id): return model.solver.interface.Variable(var_id, type="binary") cache.add_variable("y_%s" % rid, create_variable, None) def create_upper_constraint(model, constraint_id, reaction, variable, flux_value, epsilon): w_u = flux_value + delta * abs(flux_value) + epsilon return model.solver.interface.Constraint( reaction.flux_expression - variable * (reaction.upper_bound - w_u), ub=w_u, sloppy=True, name=constraint_id) def update_upper_constraint(model, constraint, reaction, variable, flux_value, epsilon): w_u = flux_value + delta * abs(flux_value) + epsilon constraint.set_linear_coefficients({variable: reaction.upper_bound - w_u}) constraint.ub = w_u cache.add_constraint("room_const_%s_upper" % rid, create_upper_constraint, update_upper_constraint, reaction, cache.variables["y_%s" % rid], flux_value, epsilon) def create_lower_constraint(model, constraint_id, reaction, variable, flux_value, epsilon): w_l = flux_value - delta * abs(flux_value) - epsilon return model.solver.interface.Constraint( reaction.flux_expression - variable * (reaction.lower_bound - w_l), lb=w_l, sloppy=True, name=constraint_id) def update_lower_constraint(model, constraint, reaction, variable, flux_value, epsilon): w_l = flux_value - delta * abs(flux_value) - epsilon constraint.set_linear_coefficients({variable: reaction.lower_bound - w_l}) constraint.lb = w_l cache.add_constraint("room_const_%s_lower" % rid, create_lower_constraint, update_lower_constraint, reaction, cache.variables["y_%s" % rid], flux_value, epsilon) model.objective = model.solver.interface.Objective(add([mul([One, var]) for var in cache.variables.values()]), direction='min') solution = model.optimize(raise_error=True) if reactions is not None: result = FluxDistributionResult({r: solution.get_primal_by_id(r) for r in reactions}, solution.f) else: result = FluxDistributionResult.from_solution(solution) return result except Exception as e: cache.rollback() raise e finally: if volatile: cache.reset()
def lmoma(model, reference=None, cache=None, reactions=None, *args, **kwargs): """Linear Minimization Of Metabolic Adjustment [1]. Parameters ---------- model: cobra.Model reference: FluxDistributionResult, dict cache: ProblemCache reactions: list Returns ------- FluxDistributionResult Contains the result of the solver. References ---------- .. [1] Becker, S. A., Feist, A. M., Mo, M. L., Hannum, G., Palsson, B. Ø., & Herrgard, M. J. (2007). Quantitative prediction of cellular metabolism with constraint-based models: the COBRA Toolbox. Nature Protocols, 2(3), 727–38. doi:10.1038/nprot.2007.99 """ volatile = False if cache is None: volatile = True cache = ProblemCache(model) cache.begin_transaction() if not isinstance(reference, (dict, pandas.Series, FluxDistributionResult)): raise TypeError("reference must be a flux distribution (dict or FluxDistributionResult") try: for rid, flux_value in six.iteritems(reference): reaction = model.reactions.get_by_id(rid) def create_variable(model, var_id, lb): var = model.solver.interface.Variable(var_id, lb=lb) return var pos_var_id = "u_%s_pos" % rid cache.add_variable(pos_var_id, create_variable, None, 0) neg_var_id = "u_%s_neg" % rid cache.add_variable(neg_var_id, create_variable, None, 0) # ui = vi - wt def update_upper_constraint(model, constraint, var, reaction, flux_value): if constraint.lb != flux_value: constraint.lb = flux_value def create_upper_constraint(model, constraint_id, var, reaction, flux_value): constraint = model.solver.interface.Constraint(reaction.flux_expression + var, lb=flux_value, sloppy=True, name=constraint_id) return constraint cache.add_constraint("lmoma_const_%s_ub" % rid, create_upper_constraint, update_upper_constraint, cache.variables[pos_var_id], reaction, flux_value) def update_lower_constraint(model, constraint, var, reaction, flux_value): if constraint.ub != flux_value: constraint.ub = flux_value def create_lower_constraint(model, constraint_id, var, reaction, flux_value): constraint = model.solver.interface.Constraint(reaction.flux_expression - var, ub=flux_value, sloppy=True, name=constraint_id) return constraint cache.add_constraint("lmoma_const_%s_lb" % rid, create_lower_constraint, update_lower_constraint, cache.variables[neg_var_id], reaction, flux_value) def create_objective(model, variables): return model.solver.interface.Objective(add([mul((One, var)) for var in variables]), direction="min", sloppy=False) cache.add_objective(create_objective, None, cache.variables.values()) solution = model.optimize(raise_error=True) if reactions is not None: result = FluxDistributionResult({r: solution.get_primal_by_id(r) for r in reactions}, solution.f) else: result = FluxDistributionResult.from_solution(solution) return result except Exception as e: cache.rollback() raise e finally: if volatile: cache.reset()
def moma(model, reference=None, cache=None, reactions=None, *args, **kwargs): """ Minimization of Metabolic Adjustment[1] Parameters ---------- model: cobra.Model reference: FluxDistributionResult, dict cache: ProblemCache reactions: list Returns ------- FluxDistributionResult Contains the result of the solver. References ---------- .. [1] Segrè, D., Vitkup, D., & Church, G. M. (2002). Analysis of optimality in natural and perturbed metabolic networks. Proceedings of the National Academy of Sciences of the United States of America, 99(23), 15112–7. doi:10.1073/pnas.232349399 """ volatile = False if cache is None: volatile = True cache = ProblemCache(model) cache.begin_transaction() try: for rid, flux_value in six.iteritems(reference): def create_variable(model, variable_id): var = model.solver.interface.Variable(variable_id) return var var_id = "moma_aux_%s" % rid cache.add_variable(var_id, create_variable, None) def create_constraint(model, constraint_id, var, reaction, flux_value): constraint = model.solver.interface.Constraint(reaction.flux_expression - var, lb=flux_value, ub=flux_value, name=constraint_id) return constraint def update_constraint(model, constraint, var, reaction, flux_value): if constraint.lb != flux_value: constraint.lb = flux_value constraint.ub = flux_value constraint_id = "moma_const_%s" % rid reaction = model.reactions.get_by_id(rid) cache.add_constraint(constraint_id, create_constraint, update_constraint, cache.variables[var_id], reaction, flux_value) def create_objective(model, variables): return model.solver.interface.Objective(Add(*[FloatOne * var ** 2 for var in variables]), direction="min", sloppy=True) cache.add_objective(create_objective, None, cache.variables.values()) solution = model.optimize(raise_error=True) if reactions is not None: result = FluxDistributionResult({r: solution.get_primal_by_id(r) for r in reactions}, solution.f) else: result = FluxDistributionResult.from_solution(solution) return result except Exception as e: cache.rollback() raise e finally: if volatile: cache.reset()
def lmoma(model, reference=None, cache=None, *args, **kwargs): """Linear Minimization Of Metabolic Adjustment. Parameters ---------- model: SolverBasedModel reference: dict objective: str or reaction or optlang.Objective An objective to be minimized/maximized for volatile: boolean cache: dict Returns ------- FluxDistributionResult Contains the result of the linear solver. """ volatile = False if cache is None: volatile = True cache = ProblemCache(model) cache.begin_transaction() if not isinstance(reference, (dict, FluxDistributionResult)): raise TypeError("reference must be a flux distribution (dict or FluxDistributionResult") try: for rid, flux_value in six.iteritems(reference): reaction = model.reactions.get_by_id(rid) def create_variable(model, var_id, lb): var = model.solver.interface.Variable(var_id, lb=lb) return var pos_var_id = "u_%s_pos" % rid cache.add_variable(pos_var_id, create_variable, None, 0) neg_var_id = "u_%s_neg" % rid cache.add_variable(neg_var_id, create_variable, None, 0) # ui = vi - wt def update_upper_constraint(model, constraint, var, reaction, flux_value): constraint.lb = flux_value def create_upper_constraint(model, constraint_id, var, reaction, flux_value): constraint = model.solver.interface.Constraint(reaction.flux_expression + var, lb=flux_value, sloppy=True, name=constraint_id) return constraint cache.add_constraint("c_%s_ub" % rid, create_upper_constraint, update_upper_constraint, cache.variables[pos_var_id], reaction, flux_value) def update_lower_constraint(model, constraint, var, reaction, flux_value): constraint.ub = flux_value def create_lower_constraint(model, constraint_id, var, reaction, flux_value): constraint = model.solver.interface.Constraint(reaction.flux_expression - var, ub=flux_value, sloppy=True, name=constraint_id) return constraint cache.add_constraint("c_%s_lb" % rid, create_lower_constraint, update_lower_constraint, cache.variables[neg_var_id], reaction, flux_value) model.objective = model.solver.interface.Objective(add([mul([One, var]) for var in cache.variables.values()]), direction="min") try: return FluxDistributionResult(model.solve()) except SolveError as e: raise e except Exception as e: cache.rollback() raise e finally: if volatile: cache.reset()