Beispiel #1
0
def raw_to_central(n_counter, species, k_counter):
    """
    Expresses central moments in terms of raw moments (and other central moments).
    Based on equation 8 in the paper:

    .. math::
         \mathbf{M_{x^n}} = \sum_{k_1=0}^{n_1} ... \sum_{k_d=0}^{n_d} \mathbf{{n \choose k}} (-1)^{\mathbf{n-k}} \mu^{\mathbf{n-k}} \langle \mathbf{x^k} \\rangle


    The term :math:`\mu^{\mathbf{n-k}}`, so called alpha term is expressed with respect to `species` values that
    are equivalent to :math:`\mu_i` in the paper.

    The last term, the beta term, :math:`\langle \mathbf{x^n} \\rangle` is simply obtained
    from k_counter as it contains the symbols for raw moments.

    :param n_counter: a list of :class:`~means.core.descriptors.Moment`\s representing central moments
    :type n_counter: list[:class:`~means.core.descriptors.Moment`]

    :param species: the symbols for species means

    :param k_counter: a list of :class:`~means.core.descriptors.Moment`\s representing raw moments
    :type k_counter: list[:class:`~means.core.descriptors.Moment`]


    :return: a vector of central moments expressed in terms of raw moment
    """
    # create empty output
    central_in_terms_of_raw = []
    # This loop loops through the ::math::`[n_1, ..., n_d]` vectors of the sums in the beginning of the equation
    # i.e. :math:`\sum_{k1=0}^n_1 ... \sum_{kd=0}^n_d` part of the equation.
    # Note, this is not the sum over k's in that equation, or at least I think its not
    for n_iter in n_counter:  #loop through all n1,...,nd combinations
        # nothing to do for 0th order central moment
        if n_iter.order == 0:
            continue
        # n_vec is the vector ::math::`[n_1, ... n_d]` in equation 8
        n_vec = n_iter.n_vector
        # k_lower contains the elements of `k_counter` that are lower than or equal to the current n_vec
        # This generates the list of possible k values to satisfy ns in the equation.
        # `k_vec` iterators bellow are the vector ::math::`[k_1, ..., k_d]`
        k_lower = [k for k in k_counter if n_iter >= k]
        # (n k) binomial term in equation 9
        n_choose_k_vec = [make_k_chose_e(k_vec.n_vector, n_vec) for k_vec in k_lower]
        # (-1)^(n-k) term in equation 9
        minus_one_pow_n_min_k_vec = [_make_min_one_pow_n_minus_k(n_vec, k_vec.n_vector)  for k_vec in k_lower ]
        # alpha term in equation 9
        alpha_vec = [_make_alpha(n_vec, k_vec.n_vector, species) for k_vec in k_lower]
        # beta term in equation 9
        beta_vec = [k_vec.symbol for k_vec in k_lower]
        # let us multiply all terms
        product = [(n * m * a * b) for (n, m, a, b) in zip(n_choose_k_vec, minus_one_pow_n_min_k_vec, alpha_vec, beta_vec)]
        # and store the product
        central_in_terms_of_raw.append(sum(product))
    return sp.Matrix(central_in_terms_of_raw)
Beispiel #2
0
    def get(self, k_vec, e_counter):
        r"""
        Provides the terms needed for equation 11 (see Ale et al. 2013).
        This gives the expressions for :math:`\frac{d\beta}{dt}` in equation 9, these are the
        time dependencies of the mixed moments

        :param k_vec: :math:`k` in eq. 11
        :param e_counter: :math:`e` in eq. 11
        :return: :math:`\frac{d\beta}{dt}`
        """

        if len(e_counter) == 0:
            return sp.Matrix(1, len(self.__n_counter), lambda i, j: 0)

        # compute F(x) for EACH REACTION and EACH entry in the EKCOUNTER (eq. 12)
        f_of_x_vec = [
            self._make_f_of_x(k_vec, ek.n_vector, reac)
            for (reac, ek) in itertools.product(self.__propensities, e_counter)
        ]

        # compute <F> from f(x) (eq. 12). The result is a list in which each element is a
        # vector in which each element relates to an entry of counter
        f_expectation_vec = [self._make_f_expectation(f) for f in f_of_x_vec]

        # compute s^e for EACH REACTION and EACH entry in the EKCOUNTER . this is a list of scalars
        s_pow_e_vec = sp.Matrix([
            self._make_s_pow_e(reac_idx, ek.n_vector)
            for (reac_idx, ek) in itertools.product(
                range(len(self.__propensities)), e_counter)
        ])

        # compute (k choose e) for EACH REACTION and EACH entry in the EKCOUNTER . This is a list of scalars.
        # Note that this does not depend on the reaction, so we can just repeat the result for each reaction
        k_choose_e_vec = sp.Matrix(
            [make_k_chose_e(ek.n_vector, k_vec)
             for ek in e_counter] * len(self.__propensities))

        # compute the element-wise product of the three entities
        s_times_ke = s_pow_e_vec.multiply_elementwise(k_choose_e_vec)
        prod = [
            list(f * s_ke) for (f, s_ke) in zip(f_expectation_vec, s_times_ke)
        ]

        # we have a list of vectors and we want to obtain a list of sums of all nth element together.
        # To do that we put all the data into a matrix in which each row is a different vector
        to_sum = sp.Matrix(prod)

        # then we sum over the columns -> row vector
        mixed_moments = sum_of_cols(to_sum)

        return mixed_moments
Beispiel #3
0
    def get(self, k_vec, e_counter):
        r"""
        Provides the terms needed for equation 11 (see Ale et al. 2013).
        This gives the expressions for :math:`\frac{d\beta}{dt}` in equation 9, these are the
        time dependencies of the mixed moments

        :param k_vec: :math:`k` in eq. 11
        :param e_counter: :math:`e` in eq. 11
        :return: :math:`\frac{d\beta}{dt}`
        """

        if len(e_counter) == 0:
            return sp.Matrix(1, len(self.__n_counter), lambda i, j: 0)

        # compute F(x) for EACH REACTION and EACH entry in the EKCOUNTER (eq. 12)
        f_of_x_vec = [self._make_f_of_x(k_vec, ek.n_vector, reac) for (reac, ek)
                      in itertools.product(self.__propensities, e_counter)]

        # compute <F> from f(x) (eq. 12). The result is a list in which each element is a
        # vector in which each element relates to an entry of counter
        f_expectation_vec = [self._make_f_expectation(f) for f in f_of_x_vec]

        # compute s^e for EACH REACTION and EACH entry in the EKCOUNTER . this is a list of scalars
        s_pow_e_vec = sp.Matrix([self._make_s_pow_e(reac_idx, ek.n_vector) for (reac_idx, ek)
                                 in itertools.product(range(len(self.__propensities)), e_counter)])

        # compute (k choose e) for EACH REACTION and EACH entry in the EKCOUNTER . This is a list of scalars.
        # Note that this does not depend on the reaction, so we can just repeat the result for each reaction
        k_choose_e_vec = sp.Matrix(
                [make_k_chose_e(ek.n_vector, k_vec) for ek in e_counter] *
                len(self.__propensities)
                )

        # compute the element-wise product of the three entities
        s_times_ke = s_pow_e_vec.multiply_elementwise(k_choose_e_vec)
        prod = [list(f * s_ke) for (f, s_ke) in zip(f_expectation_vec, s_times_ke)]

        # we have a list of vectors and we want to obtain a list of sums of all nth element together.
        # To do that we put all the data into a matrix in which each row is a different vector
        to_sum = sp.Matrix(prod)

        # then we sum over the columns -> row vector
        mixed_moments = sum_of_cols(to_sum)

        return mixed_moments
Beispiel #4
0
def eq_central_moments(n_counter, k_counter, dmu_over_dt, species, propensities, stoichiometry_matrix, max_order):
    r"""
    Function used to calculate the terms required for use in equations giving the time dependence of central moments.

    The function returns the list Containing the sum of the following terms in in equation 9,
    for each of the :math:`[n_1, ..., n_d]` combinations in eq. 9 where ... is ... # FIXME

    .. math::
        \mathbf{ {n \choose k} } (-1)^{ \mathbf{n-k} }
        [ \alpha \frac{d\beta}{dt} + \beta \frac{d\alpha}{dt} ]


    :param n_counter: a list of :class:`~means.core.descriptors.Moment`\s representing central moments
    :type n_counter: list[:class:`~means.core.descriptors.Moment`]
    :param k_counter: a list of :class:`~means.core.descriptors.Moment`\s representing raw moments
    :type k_counter: list[:class:`~means.core.descriptors.Moment`]
    :param dmu_over_dt: du/dt in paper
    :param species: species matrix: y_0, y_1,..., y_d
    :param propensities: propensities matrix
    :param stoichiometry_matrix: stoichiometry matrix
    :return: central_moments matrix with `(len(n_counter)-1)` rows and one column per each :math:`[n_1, ... n_d]` combination
    """
    central_moments = []


    # Loops through required combinations of moments (n1,...,nd)
    # (does not include 0th order central moment as this is 1,
    # or 1st order central moment as this is 0

    # copy dmu_mat matrix as a list of rows vectors (1/species)
    dmu_mat = [sp.Matrix(l).T for l in dmu_over_dt.tolist()]

    d_beta_over_dt_calculator = DBetaOverDtCalculator(propensities,n_counter,stoichiometry_matrix, species)

    for n_iter in n_counter:
        # skip zeroth moment
        if n_iter.order == 0 or n_iter.order > max_order:
            continue

        n_vec = n_iter.n_vector

        # Find all moments in k_counter that are lower than the current n_iter
        k_lower = [k for k in k_counter if n_iter >= k]

        taylor_exp_mat = []

        for k_iter in k_lower:
            k_vec = k_iter.n_vector

            # (n k) binomial term in equation 9
            n_choose_k = make_k_chose_e(k_vec, n_vec)

            # (-1)^(n-k) term in equation 9
            minus_one_pow_n_minus_k = product([sp.Integer(-1) ** (n - m) for (n,m)
                                               in zip(n_vec, k_vec)])

            # Calculate alpha, dalpha_over_dt terms in equation 9
            alpha = product([s ** (n - k) for s, n, k in zip(species, n_vec, k_vec)])
            # eq 10 {(n - k) mu_i^(-1)} corresponds to {(n - k)/s}. s is symbol for mean of a species

            # multiplies by alpha an the ith row of dmu_mat and sum it to get dalpha_over_dt
            # eq 10 {(n - k) mu_i^(-1)} corresponds to {(n - k)/s}
            dalpha_over_dt = sympy_sum_list([((n - k) / s) * alpha * mu_row for s, n, k, mu_row
                                             in zip(species, n_vec, k_vec, dmu_mat)])

            # e_counter contains elements of k_counter lower than the current k_iter
            e_counter = [k for k in k_counter if k_iter >= k and k.order > 0]

            dbeta_over_dt = d_beta_over_dt_calculator.get(k_iter.n_vector, e_counter)

            # Calculate beta, dbeta_over_dt terms in equation 9
            if len(e_counter) == 0:
                beta = 1
            else:
                beta = k_iter.symbol

            taylor_exp_mat.append(n_choose_k * minus_one_pow_n_minus_k * (alpha * dbeta_over_dt + beta * dalpha_over_dt))

        # Taylorexp is a matrix which has an entry equal to
        # the `n_choose_k * minus_one_pow_n_minus_k * (AdB/dt + beta dA/dt)` term in equation 9  for each k1,..,kd
        # These are summed over to give the Taylor Expansion for each n1,..,nd combination in equation 9
        central_moments.append(sum_of_cols(sp.Matrix(taylor_exp_mat)))

    return sp.Matrix(central_moments)