def _substitute_raw_with_central(self, central_moments_exprs,
                                     central_from_raw_exprs, n_counter,
                                     k_counter):
        r"""
        Takes the expressions for central moments, and substitute the symbols representing raw moments,
        by equivalent expressions in terms of central moment

        :param central_moments_exprs: a matrix of expressions for central moments.
        :param central_from_raw_exprs: central moment expressed in terms of 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 k_counter: a list of :class:`~means.core.descriptors.Moment`\s representing raw moments
        :type k_counter: list[:class:`~means.core.descriptors.Moment`]

        :return: expressions for central moments without raw moment
        """
        positiv_raw_moms_symbs = [
            raw.symbol for raw in k_counter if raw.order > 1
        ]
        # The symbols for the corresponding central moment
        central_symbols = [
            central.symbol for central in n_counter if central.order > 1
        ]
        # Now we state (central_symbols == central_from_raw_exprs)
        eq_to_solve = [
            cfr - cs
            for (cs, cfr) in zip(central_symbols, central_from_raw_exprs)
        ]

        # And we solve this for the symbol of the corresponding raw moment. This gives an expression
        # of the symbol for raw moment in terms of central moments and lower order raw moment
        solved_xs = sp.Matrix([
            quick_solve(eq, raw)
            for (eq, raw) in zip(eq_to_solve, positiv_raw_moms_symbs)
        ])

        # now we want to express raw moments only in terms od central moments and means
        # for instance if we have: :math:`x_1 = 1; x_2 = 2 +x_1 and  x_3 = x_2*x_1`, we should give:
        # :math:`x_1 = 1; x_2 = 2+1 and  x_3 = 1*(2+1)`
        # To achieve this, we recursively apply substitution as many times as the highest order (minus one)
        max_order = max([p.order for p in k_counter])

        for i in range(max_order - 1):
            substitution_pairs = zip(positiv_raw_moms_symbs, solved_xs)
            solved_xs = substitute_all(solved_xs, substitution_pairs)

        # we finally build substitution pairs to replace all raw moments
        substitution_pairs = zip(positiv_raw_moms_symbs, solved_xs)

        # apply this substitution to all elements of the central moment expressions matrix
        out_exprs = substitute_all(central_moments_exprs, substitution_pairs)

        return out_exprs
示例#2
0
    def close(self, mfk, central_from_raw_exprs, n_counter, k_counter):

        """
        In MFK, replaces symbol for high order (order == max_order+1) by parametric expressions.
        That is expressions depending on lower order moments such as means, variances, covariances and so on.

        :param mfk: the right hand side equations containing symbols for high order central moments
        :param central_from_raw_exprs: expressions of central moments in terms of 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 k_counter: a list of :class:`~means.core.descriptors.Moment`\s representing raw moments
        :type k_counter: list[:class:`~means.core.descriptors.Moment`]
        :return: the modified MFK
        :rtype: `sympy.Matrix`
        """

        # we obtain expressions for central moments in terms of variances/covariances
        closed_central_moments = self._compute_closed_central_moments(central_from_raw_exprs, n_counter, k_counter)
        # set mixed central moment to zero iff univariate
        closed_central_moments = self._set_mixed_moments_to_zero(closed_central_moments, n_counter)

        # retrieve central moments from problem moment. Typically, :math: `[yx2, yx3, ...,yxN]`.

        # now we want to replace the new mfk (i.e. without highest order moment) any
        # symbol for highest order central moment by the corresponding expression (computed above)

        positive_n_counter = [n for n in n_counter if n.order > 0]
        substitutions_pairs = [(n.symbol, ccm) for n,ccm in
                               zip(positive_n_counter, closed_central_moments) if n.order > self.max_order]
        new_mfk = substitute_all(mfk, substitutions_pairs)

        return new_mfk
示例#3
0
    def test_substitute_all_on_expression(self):

        to_substitute = sympy.sympify("a*b + c*d + d*e + e*f")
        pairs = zip(to_sympy_matrix(["a","d","e","c","b"]),
                    to_sympy_matrix(["z","w","v","x","y"]))
        expected = sympy.sympify("z*y + x*w + w*v + v*f")
        answer = substitute_all(to_substitute, pairs)
        self.assertEqual(answer, expected)
示例#4
0
    def test_substitute_all_on_expression(self):

        to_substitute = sympy.sympify("a*b + c*d + d*e + e*f")
        pairs = zip(to_sympy_matrix(["a", "d", "e", "c", "b"]),
                    to_sympy_matrix(["z", "w", "v", "x", "y"]))
        expected = sympy.sympify("z*y + x*w + w*v + v*f")
        answer = substitute_all(to_substitute, pairs)
        self.assertEqual(answer, expected)
示例#5
0
    def test_substitute_all_on_matrix(self):

        to_substitute = to_sympy_matrix(["a*b","c*d","d*e","e*f"])
        pairs = zip(to_sympy_matrix(["a","d","e","c","b"]),
                    to_sympy_matrix(["z","w","v","x","y"]))

        expected = sympy.Matrix(["z*y","x*w","w*v","v*f"])
        answer = substitute_all(to_substitute, pairs)
        self.assertEqual(answer, expected)
示例#6
0
    def test_substitute_all_on_matrix(self):

        to_substitute = to_sympy_matrix(["a*b", "c*d", "d*e", "e*f"])
        pairs = zip(to_sympy_matrix(["a", "d", "e", "c", "b"]),
                    to_sympy_matrix(["z", "w", "v", "x", "y"]))

        expected = sympy.Matrix(["z*y", "x*w", "w*v", "v*f"])
        answer = substitute_all(to_substitute, pairs)
        self.assertEqual(answer, expected)
    def _substitute_raw_with_central(self, central_moments_exprs, central_from_raw_exprs, n_counter, k_counter):
        r"""
        Takes the expressions for central moments, and substitute the symbols representing raw moments,
        by equivalent expressions in terms of central moment

        :param central_moments_exprs: a matrix of expressions for central moments.
        :param central_from_raw_exprs: central moment expressed in terms of 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 k_counter: a list of :class:`~means.core.descriptors.Moment`\s representing raw moments
        :type k_counter: list[:class:`~means.core.descriptors.Moment`]

        :return: expressions for central moments without raw moment
        """
        positiv_raw_moms_symbs = [raw.symbol for raw in k_counter if raw.order > 1]
        # The symbols for the corresponding central moment
        central_symbols= [central.symbol for central in n_counter if central.order > 1]
        # Now we state (central_symbols == central_from_raw_exprs)
        eq_to_solve = [cfr - cs for (cs, cfr) in zip(central_symbols, central_from_raw_exprs)]

        # And we solve this for the symbol of the corresponding raw moment. This gives an expression
        # of the symbol for raw moment in terms of central moments and lower order raw moment
        solved_xs = sp.Matrix([quick_solve(eq,raw) for (eq, raw) in zip(eq_to_solve, positiv_raw_moms_symbs)])

        # now we want to express raw moments only in terms od central moments and means
        # for instance if we have: :math:`x_1 = 1; x_2 = 2 +x_1 and  x_3 = x_2*x_1`, we should give:
        # :math:`x_1 = 1; x_2 = 2+1 and  x_3 = 1*(2+1)`
        # To achieve this, we recursively apply substitution as many times as the highest order (minus one)
        max_order = max([p.order for p in k_counter])

        for i in range(max_order - 1):
            substitution_pairs = zip(positiv_raw_moms_symbs, solved_xs)
            solved_xs = substitute_all(solved_xs, substitution_pairs)

        # we finally build substitution pairs to replace all raw moments
        substitution_pairs = zip(positiv_raw_moms_symbs, solved_xs)

        # apply this substitution to all elements of the central moment expressions matrix
        out_exprs = substitute_all(central_moments_exprs, substitution_pairs)

        return out_exprs
示例#8
0
    def _compute_closed_central_moments(self, central_from_raw_exprs, n_counter, k_counter):
        r"""
        Computes parametric expressions (e.g. in terms of mean, variance, covariances) for all central moments
        up to max_order + 1 order.

        :param central_from_raw_exprs: the expression of central moments in terms of 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 k_counter: a list of :class:`~means.core.descriptors.Moment`\s representing raw moments
        :type k_counter: list[:class:`~means.core.descriptors.Moment`]
        :return: the central moments where raw moments have been replaced by parametric expressions
        :rtype: `sympy.Matrix`
        """

        closed_raw_moments = self._compute_raw_moments(n_counter, k_counter)
        assert(len(central_from_raw_exprs) == len(closed_raw_moments))
        # raw moment lef hand side symbol
        raw_symbols = [raw.symbol for raw in k_counter if raw.order > 1]

        # we want to replace raw moments symbols with closed raw moment expressions (in terms of variances/means)
        substitution_pairs = zip(raw_symbols, closed_raw_moments)
        # so we can obtain expression of central moments in terms of low order raw moments
        closed_central_moments = substitute_all(central_from_raw_exprs, substitution_pairs)
        return closed_central_moments
示例#9
0
    def simulate_system(self, parameters, initial_conditions, timepoints,
                        max_moment_order=1, number_of_processes=1):
        """
        Perform Gillespie SSA simulations and returns trajectories for of each species.
        Each trajectory is interpolated at the given time points.
        By default, the average amounts of species for all simulations is returned.

        :param parameters: list of the initial values for the constants in the model.
                                  Must be in the same order as in the model
        :param initial_conditions: List of the initial values for the equations in the problem.
                        Must be in the same order as these equations occur.

        :param timepoints: A list of time points to simulate the system for

        :param number_of_processes: the number of parallel process to be run
        :param max_moment_order: the highest moment order to calculate the trajectories to.
                                 if set to zero, the individual trajectories will be returned, instead of
                                 the averaged moments.
        E.g. a value of one will return means, a values of two, means, variances and covariance and so on.


        :return: a list of :class:`~means.simulation.Trajectory` one per species in the problem,
            or a list of lists of trajectories (one per simulation) if `return_average == False`.
        :rtype: list[:class:`~means.simulation.Trajectory`]
        """
        max_moment_order = int(max_moment_order)
        assert(max_moment_order >= 0)

        n_simulations = self.__n_simulations
        self._validate_parameters(parameters, initial_conditions)
        t_max= max(timepoints)

        substitution_pairs = dict(zip(self.__problem.parameters, parameters))
        propensities = substitute_all(self.__problem.propensities, substitution_pairs)
        # lambdify the propensities for fast evaluation
        propensities_as_function = self.__problem.propensities_as_function
        def f(*species_parameters):
            return propensities_as_function(*(np.concatenate((species_parameters, parameters))))

        population_rates_as_function = f

        if not self.__random_seed:
            seed_for_processes = [None] * n_simulations
        else:
            seed_for_processes = [i for i in range(self.__random_seed, n_simulations + self.__random_seed)]



        if number_of_processes ==1:
            ssa_generator = _SSAGenerator(population_rates_as_function,
                                        self.__problem.change, self.__problem.species,
                                        initial_conditions, t_max, seed=self.__random_seed)

            results = map(ssa_generator.generate_single_simulation, seed_for_processes)


        else:
            p = multiprocessing.Pool(number_of_processes,
                    initializer=multiprocessing_pool_initialiser,
                    initargs=[population_rates_as_function, self.__problem.change,
                              self.__problem.species,
                              initial_conditions, t_max, self.__random_seed])

            results = p.map(multiprocessing_apply_ssa, seed_for_processes)

            p.close()
            p.join()

        resampled_results = [[traj.resample(timepoints, extrapolate=True) for traj in res] for res in results]
        for i in resampled_results:
            idx = len(i[0].values) - 1

        if max_moment_order == 0:
            # Return a list of TrajectoryCollection objects
            return map(TrajectoryCollection, resampled_results)

        moments = self._compute_moments(resampled_results, max_moment_order)
        return TrajectoryCollection(moments)
示例#10
0
    def _get_parameter_symbols(self, n_counter, k_counter):
        r"""
        Calculates parameters Y expressions and beta coefficients in
        :math:`X = {A(\beta_0,\beta_1\ldots \beta_n) \cdot Y}`

        :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`]
        :return: two column matrices Y expressions and beta multipliers
        """

        n_moment = self.max_order + 1

        expectation_symbols = sp.Matrix(
            [n.symbol for n in k_counter if n.order == 1])

        n_species = len(expectation_symbols)

        # Create auxiliary symbolic species Y_{ij}, for i,j = 0 ... (n-1) and mirror, so that Y_{ij}=Y_{ji}
        symbolic_species = sp.Matrix([[
            sp.Symbol(('Y_{0}'.format(str(j))) + '{0}'.format(str(i)))
            for i in range(n_species)
        ] for j in range(n_species)])
        for i in range(n_species):
            for j in range(i + 1, n_species):
                symbolic_species[j, i] = symbolic_species[i, j]

        # Obtain beta terms explaining how original variables are derived from auxiliary ones
        if self.is_multivariate:
            # :math: `X_i = \sum_j Y_{ij}`
            beta_in_matrix = sp.Matrix(
                [sum(symbolic_species[i, :]) for i in range(n_species)])
        else:
            # In univariate case, only the diagonal elements are needed
            beta_in_matrix = sp.Matrix(
                [symbolic_species[i, i] for i in range(n_species)])

        # Covariance symbols are read into a matrix. Variances are the diagonal elements
        covariance_matrix = sp.Matrix(
            n_species, n_species,
            lambda x, y: self._get_covariance_symbol(n_counter, x, y))
        variance_symbols = sp.Matrix(
            [covariance_matrix[i, i] for i in range(n_species)])

        # Compute :math:  `\beta_i = Var(X_i)/\mathbb{E}(X_i) \bar\alpha_i = \mathbb{E}(X_i)^2/Var(X_i)`
        beta_exprs = sp.Matrix(
            [v / e for e, v in zip(expectation_symbols, variance_symbols)])
        alpha_bar_exprs = sp.Matrix([
            (e**2) / v for e, v in zip(expectation_symbols, variance_symbols)
        ])

        if self.is_multivariate:
            # Calculate nondiagonal elements from covariances
            alpha_exprs = sp.Matrix(
                n_species, n_species, lambda i, j: covariance_matrix[i, j] /
                (beta_exprs[i] * beta_exprs[j]))
        else:
            # Covariances are zero in univariate case
            alpha_exprs = sp.Matrix(n_species, n_species, lambda i, j: 0)
        for sp_idx in range(n_species):
            # Compute diagonal elements as :math: `\alpha_{ii} = \bar\alpha_{i} - \sum(\alpha_{ij})` //equiv to \bar\alpha_{i} in univariate
            alpha_exprs[sp_idx, sp_idx] = 0
            alpha_exprs[sp_idx, sp_idx] = alpha_bar_exprs[sp_idx] - sum(
                alpha_exprs[sp_idx, :])

        # Each row in moment matrix contains the exponents of Xs for a given moment
        # Each row in Y_exprs and beta_multipliers has elements on the appropriate power
        # determined by the corresponding row in the moment matrix
        Y_exprs = []
        beta_multipliers = []

        positive_n_counter = [n for n in n_counter if n.order > 0]
        for mom in positive_n_counter:
            Y_exprs.append(
                product([(b**s).expand()
                         for b, s in zip(beta_in_matrix, mom.n_vector)]))
            beta_multipliers.append(
                product([(b**s).expand()
                         for b, s in zip(beta_exprs, mom.n_vector)]))

        Y_exprs = sp.Matrix(Y_exprs).applyfunc(sp.expand)
        beta_multipliers = sp.Matrix(beta_multipliers)

        # Substitute alpha expressions in place of symbolic species Ys
        # by going through all powers up to the moment order for closure
        subs_pairs = []
        for i, a in enumerate(alpha_exprs):
            Y_to_substitute = [
                symbolic_species[i]**n for n in range(2, n_moment + 1)
            ]

            # Obtain alpha term for higher order moments :math: `\mathbb{E}(Y_{ij}^n) \rightarrow (\alpha_{ij})_n`
            alpha_m = [
                self._gamma_factorial(a, n) for n in range(2, n_moment + 1)
            ]

            # Substitute alpha term for symbolic species
            subs_pairs += zip(Y_to_substitute, alpha_m)
            subs_pairs.append((symbolic_species[i],
                               a))  # Add first order expression to the end
        Y_exprs = substitute_all(Y_exprs, subs_pairs)

        return Y_exprs, beta_multipliers
示例#11
0
    def _get_parameter_symbols(self, n_counter, k_counter):
        r"""
        Calculates parameters Y expressions and beta coefficients in
        :math:`X = {A(\beta_0,\beta_1\ldots \beta_n) \cdot Y}`

        :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`]
        :return: two column matrices Y expressions and beta multipliers
        """

        n_moment = self.max_order + 1

        expectation_symbols = sp.Matrix([n.symbol for n in k_counter if n.order == 1])


        n_species = len(expectation_symbols)

        # Create auxiliary symbolic species Y_{ij}, for i,j = 0 ... (n-1) and mirror, so that Y_{ij}=Y_{ji}
        symbolic_species=sp.Matrix([[sp.Symbol(('Y_{0}'.format(str(j)))+'{0}'.format(str(i))) for i in range(n_species)]for j in range(n_species)])
        for i in range(n_species):
            for j in range(i+1,n_species):
                symbolic_species[j,i]=symbolic_species[i,j]


        # Obtain beta terms explaining how original variables are derived from auxiliary ones
        if self.is_multivariate:
            # :math: `X_i = \sum_j Y_{ij}`
            beta_in_matrix = sp.Matrix([sum(symbolic_species[i,:]) for i in range(n_species)])
        else :
            # In univariate case, only the diagonal elements are needed
            beta_in_matrix = sp.Matrix([symbolic_species[i,i] for i in range(n_species)])

        # Covariance symbols are read into a matrix. Variances are the diagonal elements
        covariance_matrix = sp.Matrix(n_species,n_species, lambda x,y: self._get_covariance_symbol(n_counter,x,y))
        variance_symbols = sp.Matrix([covariance_matrix[i,i] for i in range(n_species)])


        # Compute :math:  `\beta_i = Var(X_i)/\mathbb{E}(X_i) \bar\alpha_i = \mathbb{E}(X_i)^2/Var(X_i)`
        beta_exprs = sp.Matrix([v / e for e,v in zip(expectation_symbols,variance_symbols)])
        alpha_bar_exprs = sp.Matrix([(e ** 2) / v for e,v in zip(expectation_symbols,variance_symbols)])

        if self.is_multivariate:
            # Calculate nondiagonal elements from covariances
            alpha_exprs = sp.Matrix(n_species,n_species, lambda i,j: covariance_matrix[i,j]/(beta_exprs[i]*beta_exprs[j]))
        else:
            # Covariances are zero in univariate case
            alpha_exprs = sp.Matrix(n_species,n_species, lambda i,j: 0)
        for sp_idx in range(n_species):
            # Compute diagonal elements as :math: `\alpha_{ii} = \bar\alpha_{i} - \sum(\alpha_{ij})` //equiv to \bar\alpha_{i} in univariate
            alpha_exprs[sp_idx,sp_idx]=0
            alpha_exprs[sp_idx,sp_idx]=alpha_bar_exprs[sp_idx]-sum(alpha_exprs[sp_idx,:])


        # Each row in moment matrix contains the exponents of Xs for a given moment
        # Each row in Y_exprs and beta_multipliers has elements on the appropriate power
        # determined by the corresponding row in the moment matrix
        Y_exprs = []
        beta_multipliers = []

        positive_n_counter = [n for n in n_counter if n.order > 0]
        for mom in positive_n_counter:
            Y_exprs.append(product([(b ** s).expand() for b, s in zip(beta_in_matrix, mom.n_vector)]))
            beta_multipliers.append(product([(b ** s).expand() for b, s in zip(beta_exprs, mom.n_vector)]))

        Y_exprs = sp.Matrix(Y_exprs).applyfunc(sp.expand)
        beta_multipliers = sp.Matrix(beta_multipliers)

        # Substitute alpha expressions in place of symbolic species Ys
        # by going through all powers up to the moment order for closure
        subs_pairs = []
        for i,a in enumerate(alpha_exprs):
            Y_to_substitute = [symbolic_species[i]**n for n in range(2, n_moment+1)]

            # Obtain alpha term for higher order moments :math: `\mathbb{E}(Y_{ij}^n) \rightarrow (\alpha_{ij})_n`
            alpha_m = [self._gamma_factorial(a,n) for n in range(2, n_moment+1)]

            # Substitute alpha term for symbolic species
            subs_pairs += zip(Y_to_substitute, alpha_m)
            subs_pairs.append((symbolic_species[i], a)) # Add first order expression to the end
        Y_exprs = substitute_all(Y_exprs, subs_pairs)

        return Y_exprs, beta_multipliers