def hinge_bf_to_factor(bf, bf_var):
     knot = bf.get_knot()
     if bf.get_reverse():
         factor = Max(0, RealNumber(knot) - bf_var)
     else:
         factor = Max(0, bf_var - RealNumber(knot))
     return factor
 def smoothed_hinge_bf_to_factor(bf, bf_var):
     knot = RealNumber(bf.get_knot())
     knot_minus = RealNumber(bf.get_knot_minus())
     knot_plus = RealNumber(bf.get_knot_plus())
     r = RealNumber(bf.get_r())
     p = RealNumber(bf.get_p())
     if bf.get_reverse():
         lower_p = (-(bf_var - knot)), (bf_var <= knot_minus)
         upper_p = (0, bf_var >= knot_plus)
         left_exp = Mul(p, Pow((bf_var - knot_plus), 2))
         right_exp = Mul(r, Pow((bf_var - knot_plus), 3))
         middle_b = And(knot_minus < bf_var, bf_var < knot_plus)
         middle_exp = (Add(left_exp, right_exp), middle_b)
         piecewise = Piecewise(lower_p, upper_p, middle_exp)
         factor = piecewise
     else:
         lower_p = (0, bf_var <= knot_minus)
         upper_p = (bf_var - knot, bf_var >= knot_plus)
         left_exp = Mul(p, Pow((bf_var - knot_minus), 2))
         right_exp = Mul(r, Pow((bf_var - knot_minus), 3))
         middle_b = And(knot_minus < bf_var, bf_var < knot_plus)
         middle_exp = (Add(left_exp, right_exp), middle_b)
         piecewise = Piecewise(lower_p, upper_p, middle_exp)
         factor = piecewise
     return factor
Beispiel #3
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 #4
0
 def _print_Piecewise(self, expr):
     from sympy import RealNumber
     # this fix is to prevent sympy from printing constructs like
     # merge(x,0,condition) which are illegal in Fortran
     newargs = ((RealNumber(x) if x.is_Integer else x \
         for x in y) for y in expr.args)
     return super(F90CodePrinter,
                  self)._print_Piecewise(Piecewise(*newargs))
Beispiel #5
0
def symbolic_exp(init_state, operator, t, var_vals, rel_epsilon=1e-5):
    """
    exp(-1j * t * operator) init_state =
        sum( (-1j * dt)^k / k! * operator^k init_state, k=0..n)

    :param init_state:
    :param operator:
    :param n:
    :return:
    """

    minus_jt = -1j * RealNumber(t)

    current_term = init_state

    result = lambdify(init_state.free_symbols, init_state, "numpy")(
        **{str(key): var_vals[str(key)]
           for key in init_state.free_symbols})

    # make sure the result is a numpy array
    result = np.array(result, copy=False)

    delta = np.array([np.inf])

    # counter
    k = Integer(0)

    # loop till convergence
    while np.linalg.norm(delta.reshape(-1), np.inf) / np.linalg.norm(
            result.reshape(-1), np.inf) > rel_epsilon:

        current_term = operator(current_term)
        k += 1
        current_term *= minus_jt / k
        current_term = simplify(current_term)

        delta = lambdify(current_term.free_symbols, current_term, "numpy")(**{
            str(key): var_vals[str(key)]
            for key in current_term.free_symbols
        })

        if k == 1:
            result = result + delta
        else:
            result += delta

        print(k)
        print(np.linalg.norm(delta.reshape(-1), np.inf))

    return result
 def constant_bf_to_factor(bf, bf_var):
     return RealNumber(1)