from six import iteritems
from ..manipulation.modify import convert_to_irreversible, revert_to_reversible
from ..solvers import solver_dict, get_solver_name
[docs]def optimize_minimal_flux(cobra_model, already_irreversible=False,
fraction_of_optimum=1.0, solver=None,
desired_objective_value=None, **optimize_kwargs):
"""Perform basic pFBA (parsimonius FBA) and minimize total flux.
The function attempts to act as a drop-in replacement for optimize. It
will make the reaction reversible and perform an optimization, then
force the objective value to remain the same and minimize the total
flux. Finally, it will convert the reaction back to the irreversible
form it was in before. See http://dx.doi.org/10.1038/msb.2010.47
cobra_model : :class:`~cobra.core.Model` object
already_irreversible : bool, optional
By default, the model is converted to an irreversible one.
However, if the model is already irreversible, this step can be
skipped
fraction_of_optimum : float, optional
Fraction of optimum which must be maintained. The original objective
reaction is constrained to be greater than maximal_value *
fraction_of_optimum. By default, this option is specified to be 1.0
desired_objective_value : float, optional
A desired objective value for the minimal solution that bypasses the
initial optimization result.
solver : string of solver name
If None is given, the default solver will be used.
Updates everything in-place, returns model to original state at end.
"""
if len(cobra_model.objective) > 1:
raise ValueError('optimize_minimal_flux only supports models with'
' a single objective function')
if 'objective_sense' in optimize_kwargs:
if optimize_kwargs['objective_sense'] == 'minimize':
raise ValueError(
'Minimization not supported in optimize_minimal_flux')
optimize_kwargs.pop('objective_sense', None)
# Convert to irreversible, so all reactions will have a positive flux
convert_to_irreversible(cobra_model)
solver = solver_dict[get_solver_name() if solver is None else solver]
lp = solver.create_problem(cobra_model, **optimize_kwargs)
if not desired_objective_value:
solver.solve_problem(lp, objective_sense='maximize')
status = solver.get_status(lp)
if status != "optimal":
raise ValueError(
"pFBA requires optimal solution status, not {}".format(status))
desired_objective_value = solver.get_objective_value(lp)
for i, reaction in enumerate(cobra_model.reactions):
if reaction.objective_coefficient != 0:
# Enforce a certain fraction of the original objective
target = (desired_objective_value * fraction_of_optimum /
reaction.objective_coefficient)
solver.change_variable_bounds(lp, i, target, reaction.upper_bound)
# Minimize all reaction fluxes (including objective?)
solver.change_variable_objective(lp, i, 1)
solver.solve_problem(lp, objective_sense='minimize', **optimize_kwargs)
solution = solver.format_solution(lp, cobra_model)
# Return the model to its original state
cobra_model.solution = solution
revert_to_reversible(cobra_model)
if solution.status == "optimal":
cobra_model.solution.f = sum([coeff * reaction.x for reaction, coeff in
iteritems(cobra_model.objective)])
return solution