Example #1
0
    def _add_switches(self, reactions):
        logger.info("Adding switches.")
        y_vars = list()
        switches = list()
        self._exchanges = list()
        for reaction in reactions:
            if reaction.id.startswith('DM_'):
                # demand reactions don't need integer switches
                self._exchanges.append(reaction)
                continue

            y = self.model.solver.interface.Variable('y_' + reaction.id, lb=0, ub=1, type='binary')
            y_vars.append(y)
            # The following is a complicated but efficient way to write the following constraints

            # switch_lb = self.model.solver.interface.Constraint(y * reaction.lower_bound - reaction.flux_expression,
            #                                                    name='switch_lb_' + reaction.id, ub=0)
            # switch_ub = self.model.solver.interface.Constraint(y * reaction.upper_bound - reaction.flux_expression,
            #                                                    name='switch_ub_' + reaction.id, lb=0)
            forward_var_term = Mul._from_args((RealNumber(-1), reaction.forward_variable))
            reverse_var_term = Mul._from_args((RealNumber(-1), reaction.reverse_variable))
            switch_lb_y_term = Mul._from_args((RealNumber(reaction.lower_bound), y))
            switch_ub_y_term = Mul._from_args((RealNumber(reaction.upper_bound), y))
            switch_lb = self.model.solver.interface.Constraint(
                Add._from_args((switch_lb_y_term, forward_var_term, reverse_var_term)), name='switch_lb_' + reaction.id,
                ub=0, sloppy=True)
            switch_ub = self.model.solver.interface.Constraint(
                Add._from_args((switch_ub_y_term, forward_var_term, reverse_var_term)), name='switch_ub_' + reaction.id,
                lb=0, sloppy=True)
            switches.extend([switch_lb, switch_ub])
        self.model.solver.add(y_vars)
        self.model.solver.add(switches, sloppy=True)
        logger.info("Setting minimization of switch variables as objective.")
        self.model.objective = self.model.solver.interface.Objective(Add(*y_vars), direction='min')
        self._y_vars_ids = [var.name for var in y_vars]
Example #2
0
 def _add_reaction_dual_constraint(self, reaction, coefficient, maximization, prefix):
     """Add a dual constraint corresponding to the reaction's objective coefficient"""
     stoichiometry = {self.solver.variables["lambda_" + m.id]: c for m, c in six.iteritems(reaction.metabolites)}
     if maximization:
         constraint = self.solver.interface.Constraint(
             Add._from_args(tuple(c * v for v, c in six.iteritems(stoichiometry))),
             name="r_%s_%s" % (reaction.id, prefix),
             lb=coefficient)
     else:
         constraint = self._dual_solver.interface.Constraint(
             Add._from_args(tuple(c * v for v, c in six.iteritems(stoichiometry))),
             name="r_%s_%s" % (reaction.id, prefix),
             ub=coefficient)
     self.solver._add_constraint(constraint)
Example #3
0
 def _add_reaction_dual_constraint(self, reaction, coefficient, maximization, prefix):
     """Add a dual constraint corresponding to the reaction's objective coefficient"""
     stoichiometry = {self.solver.variables["lambda_" + m.id]: c for m, c in six.iteritems(reaction.metabolites)}
     if maximization:
         constraint = self.solver.interface.Constraint(
             Add._from_args(tuple(c * v for v, c in six.iteritems(stoichiometry))),
             name="r_%s_%s" % (reaction.id, prefix),
             lb=coefficient)
     else:
         constraint = self._dual_solver.interface.Constraint(
             Add._from_args(tuple(c * v for v, c in six.iteritems(stoichiometry))),
             name="r_%s_%s" % (reaction.id, prefix),
             ub=coefficient)
     self.solver._add_constraint(constraint)
Example #4
0
    def _add_switches(self, reactions):
        logger.info("Adding switches.")
        y_vars = list()
        switches = list()
        self._exchanges = list()
        for reaction in reactions:
            if reaction.id.startswith('DM_'):
                # demand reactions don't need integer switches
                self._exchanges.append(reaction)
                continue

            y = self.model.solver.interface.Variable('y_' + reaction.id,
                                                     lb=0,
                                                     ub=1,
                                                     type='binary')
            y_vars.append(y)
            # The following is a complicated but efficient way to write the following constraints

            # switch_lb = self.model.solver.interface.Constraint(y * reaction.lower_bound - reaction.flux_expression,
            #                                                    name='switch_lb_' + reaction.id, ub=0)
            # switch_ub = self.model.solver.interface.Constraint(y * reaction.upper_bound - reaction.flux_expression,
            #                                                    name='switch_ub_' + reaction.id, lb=0)
            forward_var_term = Mul._from_args(
                (RealNumber(-1), reaction.forward_variable))
            reverse_var_term = Mul._from_args(
                (RealNumber(-1), reaction.reverse_variable))
            switch_lb_y_term = Mul._from_args(
                (RealNumber(reaction.lower_bound), y))
            switch_ub_y_term = Mul._from_args(
                (RealNumber(reaction.upper_bound), y))
            switch_lb = self.model.solver.interface.Constraint(
                Add._from_args(
                    (switch_lb_y_term, forward_var_term, reverse_var_term)),
                name='switch_lb_' + reaction.id,
                ub=0,
                sloppy=True)
            switch_ub = self.model.solver.interface.Constraint(
                Add._from_args(
                    (switch_ub_y_term, forward_var_term, reverse_var_term)),
                name='switch_ub_' + reaction.id,
                lb=0,
                sloppy=True)
            switches.extend([switch_lb, switch_ub])
        self.model.solver.add(y_vars)
        self.model.solver.add(switches, sloppy=True)
        logger.info("Setting minimization of switch variables as objective.")
        self.model.objective = self.model.solver.interface.Objective(
            Add(*y_vars), direction='min')
        self._y_vars_ids = [var.name for var in y_vars]
Example #5
0
def remove_infeasible_cycles(model, fluxes, fix=()):
    """Remove thermodynamically infeasible cycles from a flux distribution.

    Parameters
    ---------
    model : cobra.Model
        The model that generated the flux distribution.
    fluxes : dict
        The flux distribution containing infeasible loops.

    Returns
    -------
    dict
        A cycle free flux distribution.

    References
    ----------
    .. [1]	A. A. Desouki, F. Jarre, G. Gelius-Dietrich, and M. J. Lercher, “CycleFreeFlux: efficient removal of
            thermodynamically infeasible loops from flux distributions.”
    """
    with model:
        # make sure the original object is restored
        exchange_reactions = model.boundary
        exchange_ids = [exchange.id for exchange in exchange_reactions]
        internal_reactions = [reaction for reaction in model.reactions if reaction.id not in exchange_ids]
        for exchange in exchange_reactions:
            exchange_flux = fluxes[exchange.id]
            exchange.bounds = (exchange_flux, exchange_flux)
        cycle_free_objective_list = []
        for internal_reaction in internal_reactions:
            internal_flux = fluxes[internal_reaction.id]
            if internal_flux >= 0:
                cycle_free_objective_list.append(Mul._from_args((FloatOne, internal_reaction.forward_variable)))
                internal_reaction.bounds = (0, internal_flux)
            else:  # internal_flux < 0:
                cycle_free_objective_list.append(Mul._from_args((FloatOne, internal_reaction.reverse_variable)))
                internal_reaction.bounds = (internal_flux, 0)
        cycle_free_objective = model.solver.interface.Objective(
            Add._from_args(cycle_free_objective_list), direction="min", sloppy=True
        )
        model.objective = cycle_free_objective

        for reaction_id in fix:
            reaction_to_fix = model.reactions.get_by_id(reaction_id)
            reaction_to_fix.bounds = (fluxes[reaction_id], fluxes[reaction_id])
        try:
            solution = model.optimize(raise_error=True)
        except OptimizationError as e:
            logger.warning("Couldn't remove cycles from reference flux distribution.")
            raise e
        result = solution.fluxes
        return result
Example #6
0
def remove_infeasible_cycles(model, fluxes, fix=()):
    """Remove thermodynamically infeasible cycles from a flux distribution.

    Arguments
    ---------
    model : cobra.Model
        The model that generated the flux distribution.
    fluxes : dict
        The flux distribution containing infeasible loops.

    Returns
    -------
    dict
        A cycle free flux distribution.

    References
    ----------
    .. [1]	A. A. Desouki, F. Jarre, G. Gelius-Dietrich, and M. J. Lercher, “CycleFreeFlux: efficient removal of
            thermodynamically infeasible loops from flux distributions.”
    """
    with model:
        # make sure the original object is restored
        exchange_reactions = model.boundary
        exchange_ids = [exchange.id for exchange in exchange_reactions]
        internal_reactions = [reaction for reaction in model.reactions if reaction.id not in exchange_ids]
        for exchange in exchange_reactions:
            exchange_flux = fluxes[exchange.id]
            exchange.bounds = (exchange_flux, exchange_flux)
        cycle_free_objective_list = []
        for internal_reaction in internal_reactions:
            internal_flux = fluxes[internal_reaction.id]
            if internal_flux >= 0:
                cycle_free_objective_list.append(Mul._from_args((FloatOne, internal_reaction.forward_variable)))
                internal_reaction.bounds = (0, internal_flux)
            else:  # internal_flux < 0:
                cycle_free_objective_list.append(Mul._from_args((FloatOne, internal_reaction.reverse_variable)))
                internal_reaction.bounds = (internal_flux, 0)
        cycle_free_objective = model.solver.interface.Objective(
            Add._from_args(cycle_free_objective_list), direction="min", sloppy=True
        )
        model.objective = cycle_free_objective

        for reaction_id in fix:
            reaction_to_fix = model.reactions.get_by_id(reaction_id)
            reaction_to_fix.bounds = (fluxes[reaction_id], fluxes[reaction_id])
        try:
            solution = model.optimize(raise_error=True)
        except OptimizationError as e:
            logger.warning("Couldn't remove cycles from reference flux distribution.")
            raise e
        result = solution.fluxes
        return result
Example #7
0
def remove_infeasible_cycles(model, fluxes, fix=()):
    """Remove thermodynamically infeasible cycles from a flux distribution.

    Arguments
    ---------
    model : SolverBasedModel
        The model that generated the flux distribution.
    fluxes : dict
        The flux distribution containing infeasible loops.

    Returns
    -------
    dict
        A cycle free flux distribution.

    References
    ----------
    .. [1]	A. A. Desouki, F. Jarre, G. Gelius-Dietrich, and M. J. Lercher, “CycleFreeFlux: efficient removal of
            thermodynamically infeasible loops from flux distributions.”
    """
    with TimeMachine() as tm:
        # make sure the original object is restored
        tm(do=int, undo=partial(setattr, model, 'objective', model.objective))
        exchange_reactions = model.exchanges
        exchange_ids = [exchange.id for exchange in exchange_reactions]
        internal_reactions = [
            reaction for reaction in model.reactions
            if reaction.id not in exchange_ids
        ]
        for exchange in exchange_reactions:
            exchange_flux = fluxes[exchange.id]
            tm(do=partial(setattr, exchange, 'lower_bound', exchange_flux),
               undo=partial(setattr, exchange, 'lower_bound',
                            exchange.lower_bound))
            tm(do=partial(setattr, exchange, 'upper_bound', exchange_flux),
               undo=partial(setattr, exchange, 'upper_bound',
                            exchange.upper_bound))
        cycle_free_objective_list = []
        for internal_reaction in internal_reactions:
            internal_flux = fluxes[internal_reaction.id]
            if internal_flux >= 0:
                cycle_free_objective_list.append(
                    Mul._from_args(
                        (FloatOne, internal_reaction.forward_variable)))
                tm(do=partial(setattr, internal_reaction, 'lower_bound', 0),
                   undo=partial(setattr, internal_reaction, 'lower_bound',
                                internal_reaction.lower_bound))
                tm(do=partial(setattr, internal_reaction, 'upper_bound',
                              internal_flux),
                   undo=partial(setattr, internal_reaction, 'upper_bound',
                                internal_reaction.upper_bound))
            else:  # internal_flux < 0:
                cycle_free_objective_list.append(
                    Mul._from_args(
                        (FloatOne, internal_reaction.reverse_variable)))
                tm(do=partial(setattr, internal_reaction, 'lower_bound',
                              internal_flux),
                   undo=partial(setattr, internal_reaction, 'lower_bound',
                                internal_reaction.lower_bound))
                tm(do=partial(setattr, internal_reaction, 'upper_bound', 0),
                   undo=partial(setattr, internal_reaction, 'upper_bound',
                                internal_reaction.upper_bound))

        cycle_free_objective = model.solver.interface.Objective(
            Add._from_args(cycle_free_objective_list),
            direction="min",
            sloppy=True)
        model.objective = cycle_free_objective

        for reaction_id in fix:
            reaction_to_fix = model.reactions.get_by_id(reaction_id)
            tm(do=partial(setattr, reaction_to_fix, 'lower_bound',
                          fluxes[reaction_id]),
               undo=partial(setattr, reaction_to_fix, 'lower_bound',
                            reaction_to_fix.lower_bound))
            tm(do=partial(setattr, reaction_to_fix, 'upper_bound',
                          fluxes[reaction_id]),
               undo=partial(setattr, reaction_to_fix, 'upper_bound',
                            reaction_to_fix.upper_bound))

        try:
            solution = model.solve()
        except SolveError as e:
            logger.warning(
                "Couldn't remove cycles from reference flux distribution.")
            raise e
        result = solution.x_dict

    return result
Example #8
0
def remove_infeasible_cycles(model, fluxes, fix=()):
    """Remove thermodynamically infeasible cycles from a flux distribution.

    Arguments
    ---------
    model : SolverBasedModel
        The model that generated the flux distribution.
    fluxes : dict
        The flux distribution containing infeasible loops.

    Returns
    -------
    dict
        A cycle free flux distribution.

    References
    ----------
    .. [1]	A. A. Desouki, F. Jarre, G. Gelius-Dietrich, and M. J. Lercher, “CycleFreeFlux: efficient removal of
            thermodynamically infeasible loops from flux distributions.”
    """
    with TimeMachine() as tm:
        # make sure the original object is restored
        tm(do=int, undo=partial(setattr, model, 'objective', model.objective))
        exchange_reactions = model.exchanges
        exchange_ids = [exchange.id for exchange in exchange_reactions]
        internal_reactions = [reaction for reaction in model.reactions if reaction.id not in exchange_ids]
        for exchange in exchange_reactions:
            exchange_flux = fluxes[exchange.id]
            tm(do=partial(setattr, exchange, 'lower_bound', exchange_flux),
               undo=partial(setattr, exchange, 'lower_bound', exchange.lower_bound))
            tm(do=partial(setattr, exchange, 'upper_bound', exchange_flux),
               undo=partial(setattr, exchange, 'upper_bound', exchange.upper_bound))
        cycle_free_objective_list = []
        for internal_reaction in internal_reactions:
            internal_flux = fluxes[internal_reaction.id]
            if internal_flux >= 0:
                cycle_free_objective_list.append(Mul._from_args((FloatOne, internal_reaction.forward_variable)))
                tm(do=partial(setattr, internal_reaction, 'lower_bound', 0),
                   undo=partial(setattr, internal_reaction, 'lower_bound', internal_reaction.lower_bound))
                tm(do=partial(setattr, internal_reaction, 'upper_bound', internal_flux),
                   undo=partial(setattr, internal_reaction, 'upper_bound', internal_reaction.upper_bound))
            else:  # internal_flux < 0:
                cycle_free_objective_list.append(Mul._from_args((FloatOne, internal_reaction.reverse_variable)))
                tm(do=partial(setattr, internal_reaction, 'lower_bound', internal_flux),
                   undo=partial(setattr, internal_reaction, 'lower_bound', internal_reaction.lower_bound))
                tm(do=partial(setattr, internal_reaction, 'upper_bound', 0),
                   undo=partial(setattr, internal_reaction, 'upper_bound', internal_reaction.upper_bound))

        cycle_free_objective = model.solver.interface.Objective(
            Add._from_args(cycle_free_objective_list), direction="min", sloppy=True
        )
        model.objective = cycle_free_objective

        for reaction_id in fix:
            reaction_to_fix = model.reactions.get_by_id(reaction_id)
            tm(do=partial(setattr, reaction_to_fix, 'lower_bound', fluxes[reaction_id]),
               undo=partial(setattr, reaction_to_fix, 'lower_bound', reaction_to_fix.lower_bound))
            tm(do=partial(setattr, reaction_to_fix, 'upper_bound', fluxes[reaction_id]),
               undo=partial(setattr, reaction_to_fix, 'upper_bound', reaction_to_fix.upper_bound))

        try:
            solution = model.solve()
        except SolveError as e:
            logger.warning("Couldn't remove cycles from reference flux distribution.")
            raise e
        result = solution.x_dict

    return result