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]
Beispiel #2
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
Beispiel #3
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
Beispiel #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]
Beispiel #5
0
    def _print_Mul(self, expr):

        if _coeff_isneg(expr):
            x = self.dom.createElement('apply')
            x.appendChild(self.dom.createElement('minus'))
            x.appendChild(self._print_Mul(-expr))
            return x

        from sympy.simplify import fraction
        numer, denom = fraction(expr)

        if denom is not S.One:
            x = self.dom.createElement('apply')
            x.appendChild(self.dom.createElement('divide'))
            x.appendChild(self._print(numer))
            x.appendChild(self._print(denom))
            return x

        coeff, terms = expr.as_coeff_mul()
        if coeff is S.One and len(terms) == 1:
            # XXX since the negative coefficient has been handled, I don't
            # think a coeff of 1 can remain
            return self._print(terms[0])

        if self.order != 'old':
            terms = Mul._from_args(terms).as_ordered_factors()

        x = self.dom.createElement('apply')
        x.appendChild(self.dom.createElement('times'))
        if(coeff != 1):
            x.appendChild(self._print(coeff))
        for term in terms:
            x.appendChild(self._print(term))
        return x
Beispiel #6
0
    def _eval_expand_expectation(self, **hints):
        A = self.args[0]
        if isinstance(A, Add):
            # <A + B> = <A> + <B>
            return Add(*(Expectation(a, self.is_normal_order).expand(
                expectation=True) for a in A.args))

        if isinstance(A, Mul):
            # <c A> = c<A> where c is a commutative term
            A = A.expand()
            cA, ncA = A.args_cnc()
            return Mul(
                Mul(*cA),
                Expectation(Mul._from_args(ncA),
                            self.is_normal_order).expand())

        if isinstance(A, Integral):
            # <∫adx> ->  ∫<a>dx
            func, lims = A.function, A.limits
            new_args = [Expectation(func, self.is_normal_order).expand()]
            for lim in lims:
                new_args.append(lim)
            return Integral(*new_args)

        return self
Beispiel #7
0
        def multiply(expr, mrow):
            from sympy.simplify import fraction
            numer, denom = fraction(expr)

            if denom is not S.One:
                frac = self.dom.createElement('mfrac')
                xnum = self._print(numer)
                xden = self._print(denom)
                frac.appendChild(xnum)
                frac.appendChild(xden)
                return frac

            coeff, terms = expr.as_coeff_mul()
            if coeff is S.One and len(terms) == 1:
                return self._print(terms[0])

            if self.order != 'old':
                terms = Mul._from_args(terms).as_ordered_factors()

            if(coeff != 1):
                x = self._print(coeff)
                y = self.dom.createElement('mo')
                y.appendChild(self.dom.createTextNode(self.mathml_tag(expr)))
                mrow.appendChild(x)
                mrow.appendChild(y)
            for term in terms:
                x = self._print(term)
                mrow.appendChild(x)
                if not term == terms[-1]:
                    y = self.dom.createElement('mo')
                    y.appendChild(self.dom.createTextNode(self.mathml_tag(expr)))
                    mrow.appendChild(y)
            return mrow
Beispiel #8
0
        def multiply(expr, mrow):
            from sympy.simplify import fraction
            numer, denom = fraction(expr)
            if denom is not S.One:
                frac = self.dom.createElement('mfrac')
                if self._settings["fold_short_frac"] and len(str(expr)) < 7:
                    frac.setAttribute('bevelled', 'true')
                xnum = self._print(numer)
                xden = self._print(denom)
                frac.appendChild(xnum)
                frac.appendChild(xden)
                mrow.appendChild(frac)
                return mrow

            coeff, terms = expr.as_coeff_mul()
            if coeff is S.One and len(terms) == 1:
                mrow.appendChild(self._print(terms[0]))
                return mrow
            if self.order != 'old':
                terms = Mul._from_args(terms).as_ordered_factors()

            if coeff != 1:
                x = self._print(coeff)
                y = self.dom.createElement('mo')
                y.appendChild(self.dom.createTextNode(self.mathml_tag(expr)))
                mrow.appendChild(x)
                mrow.appendChild(y)
            for term in terms:
                x = self._print(term)
                mrow.appendChild(x)
                if not term == terms[-1]:
                    y = self.dom.createElement('mo')
                    y.appendChild(self.dom.createTextNode(self.mathml_tag(expr)))
                    mrow.appendChild(y)
            return mrow
Beispiel #9
0
    def eval(cls, a, b):
        if not (a and b): return S.Zero
        if a == b: return Integer(2)*a**2
        if a.is_commutative or b.is_commutative:
            return Integer(2)*a*b

        # [xA,yB]  ->  xy*[A,B]
        # from sympy.physics.qmul import QMul
        ca, nca = a.args_cnc()
        cb, ncb = b.args_cnc()
        c_part = ca + cb
        if c_part:
            return Mul(Mul(*c_part), cls(Mul._from_args(nca), Mul._from_args(ncb)))

        # Canonical ordering of arguments
        #The Commutator [A,B] is on canonical form if A < B.
        if a.compare(b) == 1:
            return cls(b,a)
Beispiel #10
0
 def flatten(cls, args):
     # TODO: disallow nested TensorProducts.
     c_part = []
     nc_parts = []
     for arg in args:
         cp, ncp = arg.args_cnc()
         c_part.extend(list(cp))
         nc_parts.append(Mul._from_args(ncp))
     return c_part, nc_parts
Beispiel #11
0
 def flatten(cls, args):
     # TODO: disallow nested TensorProducts.
     c_part = []
     nc_parts = []
     for arg in args:
         cp, ncp = arg.args_cnc()
         c_part.extend(list(cp))
         nc_parts.append(Mul._from_args(ncp))
     return c_part, nc_parts
Beispiel #12
0
    def eval(cls, a, b):
        if not (a and b):
            return S.Zero
        if a == b:
            return S.Zero
        if a.is_commutative or b.is_commutative:
            return S.Zero

        # [xA,yB]  ->  xy*[A,B]
        ca, nca = a.args_cnc()
        cb, ncb = b.args_cnc()
        c_part = ca + cb
        if c_part:
            return Mul(Mul(*c_part), cls(Mul._from_args(nca), Mul._from_args(ncb)))

        # Canonical ordering of arguments
        # The Commutator [A, B] is in canonical form if A < B.
        if a.compare(b) == 1:
            return S.NegativeOne*cls(b, a)
Beispiel #13
0
    def eval(cls, a, b):
        """The Commutator [A,B] is on canonical form if A < B.
        """
        if not (a and b): return S.Zero
        if a == b: return S.Zero
        if a.is_commutative or b.is_commutative:
            return S.Zero

        # [xA,yB]  ->  xy*[A,B]
        # from sympy.physics.qmul import QMul
        ca, nca = a.args_cnc()
        cb, ncb = b.args_cnc()
        c_part = list(ca) + list(cb)
        if c_part:
            return Mul(Mul(*c_part), cls(Mul._from_args(nca), Mul._from_args(ncb)))

        # Canonical ordering of arguments
        if a.compare(b) == 1:
            return S.NegativeOne*cls(b,a)
Beispiel #14
0
    def eval(cls, a, b):
        """The Commutator [A,B] is on canonical form if A < B.
        """
        if not (a and b): return S.Zero
        if a == b: return S.Zero
        if a.is_commutative or b.is_commutative:
            return S.Zero

        # [xA,yB]  ->  xy*[A,B]
        # from sympy.physics.qmul import QMul
        ca, nca = a.args_cnc()
        cb, ncb = b.args_cnc()
        c_part = list(ca) + list(cb)
        if c_part:
            return Mul(Mul(*c_part),
                       cls(Mul._from_args(nca), Mul._from_args(ncb)))

        # Canonical ordering of arguments
        if a.compare(b) == 1:
            return S.NegativeOne * cls(b, a)
Beispiel #15
0
    def _eval_expand_covariance(self, **hints):
        A, B = self.args[0], self.args[1]
        # <A + B, C> = <A, C> + <B, C>
        if isinstance(A, Add):
            return Add(*(Covariance(a, B, self.is_normal_order).expand()
                         for a in A.args))

        # <A, B + C> = <A, B> + <A, C>
        if isinstance(B, Add):
            return Add(*(Covariance(A, b, self.is_normal_order).expand()
                         for b in B.args))

        if isinstance(A, Mul):
            A = A.expand()
            cA, ncA = A.args_cnc()
            return Mul(
                Mul(*cA),
                Covariance(Mul._from_args(ncA), B,
                           self.is_normal_order).expand())
        if isinstance(B, Mul):
            B = B.expand()
            cB, ncB = B.args_cnc()
            return Mul(
                Mul(*cB),
                Covariance(A, Mul._from_args(ncB),
                           self.is_normal_order).expand())
        if isinstance(A, Integral):
            # <∫adx, B> ->  ∫<a, B>dx
            func, lims = A.function, A.limits
            new_args = [Covariance(func, B, self.is_normal_order).expand()]
            for lim in lims:
                new_args.append(lim)
            return Integral(*new_args)
        if isinstance(B, Integral):
            # <A, ∫bdx> ->  ∫<A, b>dx
            func, lims = B.function, B.limits
            new_args = [Covariance(A, func, self.is_normal_order).expand()]
            for lim in lims:
                new_args.append(lim)
            return Integral(*new_args)
        return self
Beispiel #16
0
    def _eval_expand_covariance(self, **hints):        
        A, B = self.args[0], self.args[1]
        # <A + B, C> = <A, C> + <B, C>
        if isinstance(A, Add):
            return Add(*(Covariance(a, B, self.is_normal_order).expand()
                         for a in A.args))

        # <A, B + C> = <A, B> + <A, C>
        if isinstance(B, Add):
            return Add(*(Covariance(A, b, self.is_normal_order).expand()
                         for b in B.args))
        
        if isinstance(A, Mul):
            A = A.expand()            
            cA, ncA = A.args_cnc()
            return Mul(Mul(*cA), Covariance(Mul._from_args(ncA), B, 
                                            self.is_normal_order).expand())
        if isinstance(B, Mul):
            B = B.expand()            
            cB, ncB = B.args_cnc()
            return Mul(Mul(*cB), Covariance(A, Mul._from_args(ncB),
                                             self.is_normal_order).expand())        
        if isinstance(A, Integral):
            # <∫adx, B> ->  ∫<a, B>dx
            func, lims = A.function, A.limits
            new_args = [Covariance(func, B, self.is_normal_order).expand()]
            for lim in lims:
                new_args.append(lim)
            return Integral(*new_args)
        if isinstance(B, Integral):
            # <A, ∫bdx> ->  ∫<A, b>dx
            func, lims = B.function, B.limits
            new_args = [Covariance(A, func, self.is_normal_order).expand()]
            for lim in lims:
                new_args.append(lim)
            return Integral(*new_args)
        return self
Beispiel #17
0
def linear_expand(expr):
    """
    linear_expand takes an expression that is the sum of a scalar
    expression and a linear combination of noncommutative terms with
    scalar coefficients and generates lists of coefficients and
    noncommutative symbols the coefficients multiply.  The list of
    noncommutatives symbols contains the scalar 1 if there is a scalar
    term in the sum and also does not contain any repeated noncommutative
    symbols.
    """
    if not isinstance(expr, Expr):
        raise TypeError('{!r} is not a SymPy Expr'.format(expr))

    expr = expand(expr)

    if expr == 0:
        coefs = [expr]
        bases = [S(1)]
        return (coefs, bases)

    if isinstance(expr, Add):
        args = expr.args
    else:
        if expr.is_commutative:
            return ([expr], [S(1)])
        else:
            args = [expr]
    coefs = []
    bases = []
    for term in args:
        if term.is_commutative:
            if S(1) in bases:
                coefs[bases.index(S(1))] += term
            else:
                bases.append(S(1))
                coefs.append(term)
        else:
            c, nc = term.args_cnc()
            base = nc[0]
            coef = Mul._from_args(c)
            if base in bases:
                coefs[bases.index(base)] += coef
            else:
                bases.append(base)
                coefs.append(coef)
    return (coefs, bases)
Beispiel #18
0
    def _eval_expand_expectation(self, **hints):
        A = self.args[0]
        if isinstance(A, Add):
            # <A + B> = <A> + <B>
            return Add(*(Expectation(a, self.is_normal_order).expand(expectation=True) for a in A.args))

        if isinstance(A, Mul):
            # <c A> = c<A> where c is a commutative term
            A = A.expand()
            cA, ncA = A.args_cnc()
            return Mul(Mul(*cA), Expectation(Mul._from_args(ncA), self.is_normal_order).expand())
        
        if isinstance(A, Integral):
            # <∫adx> ->  ∫<a>dx
            func, lims = A.function, A.limits
            new_args = [Expectation(func, self.is_normal_order).expand()]
            for lim in lims:
                new_args.append(lim)
            return Integral(*new_args)
        
        return self
Beispiel #19
0
def linear_expand(expr, mode=True):

    if isinstance(expr, Expr):
        expr = expand(expr)
    if expr == 0:
        coefs = [expr]
        bases = [S(1)]
        return (coefs, bases)

    if isinstance(expr, Add):
        args = expr.args
    else:
        if expr.is_commutative:
            return ([expr], [S(1)])
        else:
            args = [expr]
    coefs = []
    bases = []
    for term in args:
        if term.is_commutative:
            if S(1) in bases:
                coefs[bases.index(S(1))] += term
            else:
                bases.append(S(1))
                coefs.append(term)
        else:
            c, nc = term.args_cnc()
            base = nc[0]
            coef = Mul._from_args(c)
            if base in bases:
                coefs[bases.index(base)] += coef
            else:
                bases.append(base)
                coefs.append(coef)
    if mode:
        return (coefs, bases)
    else:
        return list(zip(coefs, bases))
Beispiel #20
0
def linear_expand(expr, mode=True):

    if isinstance(expr, Expr):
        expr = expand(expr)
    if expr == 0:
        coefs = [expr]
        bases = [S(1)]
        return (coefs, bases)

    if isinstance(expr, Add):
        args = expr.args
    else:
        if expr.is_commutative:
            return ([expr], [S(1)])
        else:
            args = [expr]
    coefs = []
    bases = []
    for term in args:
        if term.is_commutative:
            if S(1) in bases:
                coefs[bases.index(S(1))] += term
            else:
                bases.append(S(1))
                coefs.append(term)
        else:
            c, nc = term.args_cnc()
            base = nc[0]
            coef = Mul._from_args(c)
            if base in bases:
                coefs[bases.index(base)] += coef
            else:
                bases.append(base)
                coefs.append(coef)
    if mode:
        return (coefs, bases)
    else:
        return zip(coefs, bases)
Beispiel #21
0
def linear_expand(expr):
    if not isinstance(expr, Expr):
        raise TypeError('{!r} is not a SymPy Expr'.format(expr))

    expr = expand(expr)

    if expr == 0:
        coefs = [expr]
        bases = [S(1)]
        return (coefs, bases)

    if isinstance(expr, Add):
        args = expr.args
    else:
        if expr.is_commutative:
            return ([expr], [S(1)])
        else:
            args = [expr]
    coefs = []
    bases = []
    for term in args:
        if term.is_commutative:
            if S(1) in bases:
                coefs[bases.index(S(1))] += term
            else:
                bases.append(S(1))
                coefs.append(term)
        else:
            c, nc = term.args_cnc()
            base = nc[0]
            coef = Mul._from_args(c)
            if base in bases:
                coefs[bases.index(base)] += coef
            else:
                bases.append(base)
                coefs.append(coef)
    return (coefs, bases)
Beispiel #22
0
    def _print_Mul(self, expr):
        if _coeff_isneg(expr):
            x = _mathml_comp.RowComponent()
            x.append_object(
                _mathml_comp.OperatorComponent(_mathml_comp.OPERATOR_MINUS))
            x.append_object(self._print_Mul(-expr))
            return x

        PREC = precedence(expr)

        from sympy.simplify import fraction
        numer, denom = fraction(expr)

        if denom is not S.One:
            return _mathml_comp.FractionComponent(self._print(numer),
                                                  self._print(denom))

        coeff, terms = expr.as_coeff_mul()
        if coeff is S.One and len(terms) == 1:
            #  Since the negative coefficient has been handled, I don't
            #  thing a coeff of 1 can remain
            if precedence(terms[0]) < PREC:
                #  Return the argument with parentheses around.
                tmp_node = _mathml_comp.RowComponent()
                tmp_node.append_object(
                    _mathml_comp.OperatorComponent(
                        _mathml_comp.OPERATOR_LEFT_PARENTHESIS))
                tmp_node.append_object(self._print(terms[0]))
                tmp_node.append_object(
                    _mathml_comp.OperatorComponent(
                        _mathml_comp.OPERATOR_RIGHT_PARENTHESIS))

                return tmp_node
            else:
                #  Return the argument only.
                return self._print(terms[0])

        if self.order != 'old':
            # noinspection PyProtectedMember
            terms = Mul._from_args(terms).as_ordered_factors()

        #  Build result row element(node).
        x = _mathml_comp.RowComponent()

        if coeff != 1:
            if precedence(coeff) < PREC:
                #  Insert the coefficient number with parentheses around.
                x.append_object(
                    _mathml_comp.OperatorComponent(
                        _mathml_comp.OPERATOR_LEFT_PARENTHESIS))
                x.append_object(self._print(coeff))
                x.append_object(
                    _mathml_comp.OperatorComponent(
                        _mathml_comp.OPERATOR_RIGHT_PARENTHESIS))
            else:
                #  Insert the coefficient number only.
                x.append_object(self._print(coeff))

            #  Insert a multiply operator.
            if not terms[0].is_Symbol:
                x.append_object(
                    _mathml_comp.OperatorComponent(
                        _mathml_comp.OPERATOR_MULTIPLY))

        terms_len = len(terms)
        for term_id in range(0, terms_len):
            cur_term = terms[term_id]
            if precedence(cur_term) < PREC:
                x.append_object(
                    _mathml_comp.OperatorComponent(
                        _mathml_comp.OPERATOR_LEFT_PARENTHESIS))
                x.append_object(self._print(cur_term))
                x.append_object(
                    _mathml_comp.OperatorComponent(
                        _mathml_comp.OPERATOR_RIGHT_PARENTHESIS))
            else:
                x.append_object(self._print(cur_term))
            if term_id + 1 != terms_len and not cur_term.is_Symbol:
                x.append_object(
                    _mathml_comp.OperatorComponent(
                        _mathml_comp.OPERATOR_MULTIPLY))
        return x
Beispiel #23
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
Beispiel #24
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