Пример #1
0
    def test_ode_rhs_as_function_cache_does_not_persist_between_instances(self):
        """
        Given two ODEProblems, the cache should not persist between these objects.
        :return:
        """

        p1_lhs = [Moment(np.ones(4), i) for i in sympy.Matrix(['y_1', 'y_2', 'y_3', 'y_4'])]
        p1_rhs = to_sympy_matrix(['y_1+y_2+c_2', 'y_2+y_3+c_3', 'y_3+c_1', 'y_1*2'])

        p2_lhs = [Moment(np.ones(3), i) for i in sympy.Matrix(['y_1', 'y_2', 'y_3'])]
        p2_rhs = to_sympy_matrix(['y_1', 'c_1', 'y_2+y_3'])

        p1 = ODEProblem('MEA', p1_lhs, p1_rhs, parameters=sympy.symbols(['c_1', 'c_2', 'c_3']))
        p1_rhs_as_function = p1.right_hand_side_as_function

        p2 = ODEProblem('MEA', p2_lhs, p2_rhs, parameters=sympy.symbols(['c_1', 'c_2', 'c_3']))
        p2_rhs_as_function = p2.right_hand_side_as_function

        constants = [1, 2, 3]
        values_p1 = [4, 5, 6, 5]  # y_1, y_2, y_3, y_4 in that order
        values_p2 = [4, 5, 6]  # y_1, y_2, y_3  in that order

        p1_expected_ans = np.array([11, 14, 7, 8])
        p2_expected_ans = np.array([4, 1, 6+5])
        p1_actual_ans = np.array(p1_rhs_as_function(values_p1, constants))
        p2_actual_ans = np.array(p2_rhs_as_function(values_p2, constants))

        # This checks if by any means p2 is able to "override" the p1 result
        p1_ans_after_p2 = np.array(p1_rhs_as_function(values_p1, constants))

        assert_array_equal(p1_actual_ans, p1_expected_ans)
        assert_array_equal(p2_actual_ans, p2_expected_ans)
        assert_array_equal(p1_ans_after_p2, p1_expected_ans)
Пример #2
0
 def test_ode_moment_getting_n_vector_from_dict_and_key(self):
     """
     Given a list of descriptor and a list of symbols used to create Moment,
     Then problem descriptor_for_symbol function should return the correct
     descriptor for each corresponding symbol
     :return:
     """
     symbs = to_sympy_matrix(['y_1', 'y_2', 'y_3'])
     desc = [[0, 0, 1], [1, 0, 432], [21, 43, 34]]
     lhs = [Moment(d, s) for d, s in zip(desc, symbs)]
     rhs = to_sympy_matrix(['y_1+y_2+c_2', 'y_2+y_3+c_3', 'y_3+c_1'])
     p = ODEProblem('MEA', lhs, rhs, parameters=sympy.symbols(['c_1', 'c_2', 'c_3']))
     for i, l in enumerate(lhs):
         self.assertEqual(p.descriptor_for_symbol(l.symbol), l)
Пример #3
0
def _generate_ode_problem():
    # Create an ODEProblem from dimer instance
    c_0 = Symbol('c_0')
    c_1 = Symbol('c_1')
    c_2 = Symbol('c_2')

    constants = [c_0, c_1, c_2]

    y_0 = Symbol('y_0')

    yx1 = Symbol('yx1')

    right_hand_side = MutableDenseMatrix(
        [[
            -2 * c_0 * y_0 * (y_0 - 1) - 2 * c_0 * yx1 + 2 * c_1 *
            (Float('0.5', prec=15) * c_2 - Float('0.5', prec=15) * y_0)
        ],
         [
             Float('4.0', prec=15) * c_0 * y_0**2 -
             Float('4.0', prec=15) * c_0 * y_0 +
             Float('2.0', prec=15) * c_1 * c_2 -
             Float('2.0', prec=15) * c_1 * y_0 - yx1 *
             (Float('8.0', prec=15) * c_0 * y_0 - Float('8.0', prec=15) * c_0 +
              Float('2.0', prec=15) * c_1)
         ]])

    ode_lhs_terms = [
        Moment(np.array([1]), symbol=y_0),
        Moment(np.array([2]), symbol=yx1)
    ]

    dimer_problem = ODEProblem('MEA', ode_lhs_terms, right_hand_side,
                               constants)

    return dimer_problem
Пример #4
0
def _get_rhs_as_function(args):
    lhs, rhs = args

    p = ODEProblem('MEA', lhs, rhs, parameters=sympy.symbols(['c_1', 'c_2', 'c_3']))
    # access right_hand_side_as_function
    rhs_as_function = p.right_hand_side_as_function

    return p
Пример #5
0
    def test_ode_moment_no_description_from_variance_terms(self):
        """
        Given  Variance terms as left hand side terms, the generated descriptions
        dict should have nones
        for each of the symbols
        """
        lhs = [VarianceTerm(pos, term) for term, pos in [('V34', (3, 4)), ('V32', (3, 2)), ('V11', (1, 1))]]
        rhs = to_sympy_matrix(['y_1+y_2+c_2', 'y_2+y_3+c_3', 'y_3+c_1'])
        p = ODEProblem('LNA', lhs, rhs, parameters=sympy.symbols(['c_1', 'c_2', 'c_3']))

        for i,l in enumerate(lhs):
            self.assertIsNone(p._descriptions_dict[l.symbol].descriptor)
Пример #6
0
    def test_ode_rhs_as_function(self):
        """
        Given an ODEProblem with well specified LHS, RHS expressions as well as list of constants,
        the value of rhs_as_function given the appropriate params should be the same as the value of
        rhs evaluated for these params. The returned answer should also be an one-dimensional numpy array.
        :return:
        """
        lhs = [Moment(np.ones(3),i) for i in sympy.Matrix(['y_1', 'y_2', 'y_3'])]
        rhs = to_sympy_matrix(['y_1+y_2+c_2', 'y_2+y_3+c_3', 'y_3+c_1'])

        p = ODEProblem('MEA', lhs, rhs, parameters=sympy.symbols(['c_1', 'c_2', 'c_3']))

        rhs_as_function = p.right_hand_side_as_function

        values = [4, 5, 6]  # y_1, y_2, y_3 in that order
        expected_ans = np.array([11, 14, 7])
        actual_ans = np.array(rhs_as_function(values, [1, 2, 3]))
        self.assertEqual(actual_ans.ndim, 1)  # Returned answer must be an one-dimensional array,
                                              # otherwise ExplicitEuler solver would fail.
        assert_array_equal(actual_ans, expected_ans)
Пример #7
0
    def run(self):
        r"""
        Overrides the default run() method.
        Performs the complete analysis on the model specified during initialisation.

        :return: an ODE problem which can be further used in inference and simulation.
        :rtype: :class:`~means.core.problems.ODEProblem`
        """
        max_order = self.__max_order
        stoichiometry_matrix = self.model.stoichiometry_matrix
        propensities = self.model.propensities
        species = self.model.species
        # compute n_counter and k_counter; the "n" and "k" vectors in equations, respectively.
        n_counter, k_counter = generate_n_and_k_counters(max_order, species)
        # dmu_over_dt has row per species and one col per element of n_counter (eq. 6)
        dmu_over_dt = generate_dmu_over_dt(species, propensities, n_counter,
                                           stoichiometry_matrix)
        # Calculate expressions to use in central moments equations (eq. 9)
        central_moments_exprs = eq_central_moments(n_counter, k_counter,
                                                   dmu_over_dt, species,
                                                   propensities,
                                                   stoichiometry_matrix,
                                                   max_order)
        # Expresses central moments in terms of raw moments (and central moments) (eq. 8)
        central_from_raw_exprs = raw_to_central(n_counter, species, k_counter)
        # Substitute raw moment, in central_moments, with expressions depending only on central moments
        central_moments_exprs = self._substitute_raw_with_central(
            central_moments_exprs, central_from_raw_exprs, n_counter,
            k_counter)
        # Get final right hand side expressions for each moment in a vector
        mfk = self._generate_mass_fluctuation_kinetics(central_moments_exprs,
                                                       dmu_over_dt, n_counter)
        # Applies moment expansion closure, that is replaces last order central moments by parametric expressions
        mfk = self.closure.close(mfk, central_from_raw_exprs, n_counter,
                                 k_counter)
        # These are the left hand sign symbols referring to the mfk
        prob_lhs = self._generate_problem_left_hand_side(n_counter, k_counter)
        # Finally, we build the problem
        out_problem = ODEProblem("MEA", prob_lhs, mfk,
                                 sp.Matrix(self.model.parameters))
        return out_problem
Пример #8
0
Файл: lna.py Проект: pihop/means
    def run(self):
        """
        Overrides the default _run() private method.
        Performs the complete analysis
        :return: A fully computed set of Ordinary Differential Equations that can be used for further simulation
        :rtype: :class:`~means.core.problems.ODEProblem`
        """

        S = self.model.stoichiometry_matrix
        amat = self.model.propensities
        ymat = self.model.species
        n_species = len(ymat)

        # dPdt is matrix of each species differentiated w.r.t. time
        # The code below literally multiplies the stoichiometry matrix to a column vector of propensities
        # from the right (::math::`\frac{dP}{dt} = \mathbf{Sa}`)
        dPdt = S * amat

        # A Is a matrix of each species (rows) and the derivatives of their stoichiometry matrix rows
        # against each other species
        # Code below computes the matrix A, that is of size `len(ymat) x len(ymat)`, for which each entry
        # ::math::`A_{ik} = \sum_j S_{ij} \frac{\partial a_j}{\partial y_k} = \mathfb{S_i} \frac{\partial \mathbf{a}}{\partial y_k}`
        A = sp.Matrix(len(ymat), len(ymat), lambda i, j: 0)
        for i in range(A.rows):
            for k in range(A.cols):
                A[i, k] = reduce(operator.add, [
                    S[i, j] * sp.diff(amat[j], ymat[k])
                    for j in range(len(amat))
                ])

        # `diagA` is a matrix that has values sqrt(a[i]) on the diagonal (0 elsewhere)
        diagA = sp.Matrix(
            len(amat), len(amat), lambda i, j: amat[i]**sp.Rational(1, 2)
            if i == j else 0)
        # E is stoichiometry matrix times diagA
        E = S * diagA

        variance_terms = []
        cov_matrix = []
        for i in range(len(ymat)):
            row = []
            for j in range(len(ymat)):
                if i <= j:
                    symbol = 'V_{0}_{1}'.format(i, j)
                    variance_terms.append(
                        VarianceTerm(position=(i, j), symbol=symbol))
                else:
                    # Since Vi,j = Vj,i, i.e. covariance are equal, we only record Vi,j but not Vj,i
                    symbol = 'V_{0}_{1}'.format(j, i)
                    variance_terms.append(
                        VarianceTerm(position=(j, i), symbol=symbol))
                row.append(symbol)
            cov_matrix.append(row)

        V = sp.Matrix(cov_matrix)

        # Matrix of variances (diagonal) and covariances of species i and j differentiated wrt time.
        # I.e. if i=j, V_ij is the variance, and if i!=j, V_ij is the covariance between species i and species j
        dVdt = A * V + V * (A.T) + E * (E.T)

        # build ODEProblem object
        rhs_redundant = sp.Matrix([i for i in dPdt] + [i for i in dVdt])

        #generate ODE terms
        n_vectors = [
            tuple([1 if i == j else 0 for i in range(n_species)])
            for j in range(n_species)
        ]
        moment_terms = [
            Moment(nvec, lhs) for (lhs, nvec) in zip(ymat, n_vectors)
        ]

        ode_description = moment_terms + variance_terms

        non_redundant_idx = []
        ode_terms = []
        # remove repetitive covariances, as Vij = Vji
        for i, cov in enumerate(ode_description):
            if cov in ode_terms:
                continue
            else:
                ode_terms.append(cov)
                non_redundant_idx.append(i)
        rhs = []
        for i in non_redundant_idx:
            rhs.append(rhs_redundant[i])

        out_problem = ODEProblem("LNA", ode_terms, rhs,
                                 sp.Matrix(self.model.parameters))

        return out_problem
Пример #9
0
def _sample_problem():
    lhs_terms = [
        Moment(np.array([1, 0, 0]), symbol='y_0'),
        Moment(np.array([0, 1, 0]), symbol='y_1'),
        Moment(np.array([0, 0, 1]), symbol='y_2'),
        Moment(np.array([0, 0, 2]), symbol='yx1'),
        Moment(np.array([0, 1, 1]), symbol='yx2'),
        Moment(np.array([0, 2, 0]), symbol='yx3'),
        Moment(np.array([1, 0, 1]), symbol='yx4'),
        Moment(np.array([1, 1, 0]), symbol='yx5'),
        Moment(np.array([2, 0, 0]), symbol='yx6')
    ]
    constants = ['c_0', 'c_1', 'c_2', 'c_3', 'c_4', 'c_5', 'c_6']

    c_0 = Symbol('c_0')
    c_1 = Symbol('c_1')
    y_0 = Symbol('y_0')
    c_2 = Symbol('c_2')
    y_2 = Symbol('y_2')
    c_6 = Symbol('c_6')
    yx4 = Symbol('yx4')
    yx6 = Symbol('yx6')
    c_3 = Symbol('c_3')
    c_4 = Symbol('c_4')
    y_1 = Symbol('y_1')
    c_5 = Symbol('c_5')
    yx2 = Symbol('yx2')
    yx1 = Symbol('yx1')
    yx3 = Symbol('yx3')
    yx5 = Symbol('yx5')
    rhs = MutableDenseMatrix([
        [
            c_0 - c_1 * y_0 - c_2 * y_0 * y_2 / (c_6 + y_0) + yx4 *
            (c_2 * y_0 / (c_6 + y_0)**2 - c_2 / (c_6 + y_0)) + yx6 *
            (-c_2 * y_0 * y_2 / (c_6 + y_0)**3 + c_2 * y_2 / (c_6 + y_0)**2)
        ], [c_3 * y_0 - c_4 * y_1], [c_4 * y_1 - c_5 * y_2],
        [
            2 * c_4 * y_1 * y_2 + c_4 * y_1 + 2 * c_4 * yx2 -
            2 * c_5 * y_2**2 + c_5 * y_2 - 2 * c_5 * yx1 - 2 * y_2 *
            (c_4 * y_1 - c_5 * y_2)
        ],
        [
            c_3 * y_0 * y_2 + c_3 * yx4 + c_4 * y_1**2 - c_4 * y_1 * y_2 -
            c_4 * y_1 + c_4 * yx3 - c_5 * y_1 * y_2 - y_1 *
            (c_4 * y_1 - c_5 * y_2) - y_2 * (c_3 * y_0 - c_4 * y_1) + yx2 *
            (-c_4 - c_5)
        ],
        [
            2 * c_3 * y_0 * y_1 + c_3 * y_0 + 2 * c_3 * yx5 -
            2 * c_4 * y_1**2 + c_4 * y_1 - 2 * c_4 * yx3 - 2 * y_1 *
            (c_3 * y_0 - c_4 * y_1)
        ],
        [
            c_0 * y_2 - c_1 * y_0 * y_2 - c_2 * y_0 * y_2**2 / (c_6 + y_0) -
            c_2 * y_0 * yx1 / (c_6 + y_0) + c_4 * y_0 * y_1 + c_4 * yx5 -
            c_5 * y_0 * y_2 - y_0 * (c_4 * y_1 - c_5 * y_2) - y_2 *
            (c_0 - c_1 * y_0 - c_2 * y_0 * y_2 / (c_6 + y_0)) + yx4 *
            (-c_1 + 2 * c_2 * y_0 * y_2 / (c_6 + y_0)**2 - 2 * c_2 * y_2 /
             (c_6 + y_0) - c_5 - y_2 * (c_2 * y_0 / (c_6 + y_0)**2 - c_2 /
                                        (c_6 + y_0))) + yx6 *
            (-c_2 * y_0 * y_2**2 / (c_6 + y_0)**3 + c_2 * y_2**2 /
             (c_6 + y_0)**2 - y_2 *
             (-c_2 * y_0 * y_2 / (c_6 + y_0)**3 + c_2 * y_2 / (c_6 + y_0)**2))
        ],
        [
            c_0 * y_1 - c_1 * y_0 * y_1 - c_2 * y_0 * y_1 * y_2 / (c_6 + y_0) -
            c_2 * y_0 * yx2 / (c_6 + y_0) + c_3 * y_0**2 - c_4 * y_0 * y_1 -
            y_0 * (c_3 * y_0 - c_4 * y_1) - y_1 *
            (c_0 - c_1 * y_0 - c_2 * y_0 * y_2 / (c_6 + y_0)) + yx4 *
            (c_2 * y_0 * y_1 / (c_6 + y_0)**2 - c_2 * y_1 / (c_6 + y_0) - y_1 *
             (c_2 * y_0 / (c_6 + y_0)**2 - c_2 / (c_6 + y_0))) + yx5 *
            (-c_1 + c_2 * y_0 * y_2 / (c_6 + y_0)**2 - c_2 * y_2 /
             (c_6 + y_0) - c_4) + yx6 *
            (-c_2 * y_0 * y_1 * y_2 / (c_6 + y_0)**3 + c_2 * y_1 * y_2 /
             (c_6 + y_0)**2 + c_3 - y_1 *
             (-c_2 * y_0 * y_2 / (c_6 + y_0)**3 + c_2 * y_2 / (c_6 + y_0)**2))
        ],
        [
            2 * c_0 * y_0 + c_0 - 2 * c_1 * y_0**2 + c_1 * y_0 -
            2 * c_2 * y_0**2 * y_2 / (c_6 + y_0) + c_2 * y_0 * y_2 /
            (c_6 + y_0) - 2 * y_0 * (c_0 - c_1 * y_0 - c_2 * y_0 * y_2 /
                                     (c_6 + y_0)) + yx4 *
            (2 * c_2 * y_0**2 / (c_6 + y_0)**2 - 4 * c_2 * y_0 /
             (c_6 + y_0) - c_2 * y_0 / (c_6 + y_0)**2 + c_2 /
             (c_6 + y_0) - 2 * y_0 * (c_2 * y_0 / (c_6 + y_0)**2 - c_2 /
                                      (c_6 + y_0))) + yx6 *
            (-2 * c_1 - 2 * c_2 * y_0**2 * y_2 /
             (c_6 + y_0)**3 + 4 * c_2 * y_0 * y_2 /
             (c_6 + y_0)**2 + c_2 * y_0 * y_2 /
             (c_6 + y_0)**3 - 2 * c_2 * y_2 / (c_6 + y_0) - c_2 * y_2 /
             (c_6 + y_0)**2 - 2 * y_0 *
             (-c_2 * y_0 * y_2 / (c_6 + y_0)**3 + c_2 * y_2 / (c_6 + y_0)**2))
        ]
    ])

    problem = ODEProblem(method='MEA',
                         left_hand_side_descriptors=lhs_terms,
                         right_hand_side=rhs,
                         parameters=constants)
    return problem
Пример #10
0
    def test_ode_problem_lna_serialisation_works(self):

        c_0 = Symbol('c_0')
        c_1 = Symbol('c_1')
        y_0 = Symbol('y_0')
        c_2 = Symbol('c_2')
        y_2 = Symbol('y_2')
        c_6 = Symbol('c_6')
        c_3 = Symbol('c_3')
        c_4 = Symbol('c_4')
        y_1 = Symbol('y_1')
        c_5 = Symbol('c_5')
        V_00 = Symbol('V_00')
        V_02 = Symbol('V_02')
        V_20 = Symbol('V_20')
        V_01 = Symbol('V_01')
        V_21 = Symbol('V_21')
        V_22 = Symbol('V_22')
        V_10 = Symbol('V_10')
        V_12 = Symbol('V_12')
        V_11 = Symbol('V_11')
        right_hand_side = MutableDenseMatrix(
            [[c_0 - c_1 * y_0 - c_2 * y_0 * y_2 / (c_6 + y_0)],
             [c_3 * y_0 - c_4 * y_1], [c_4 * y_1 - c_5 * y_2],
             [
                 2 * V_00 * (-c_1 + c_2 * y_0 * y_2 /
                             (c_6 + y_0)**2 - c_2 * y_2 /
                             (c_6 + y_0)) - V_02 * c_2 * y_0 / (c_6 + y_0) -
                 V_20 * c_2 * y_0 / (c_6 + y_0) + c_0**Float('1.0', prec=15) +
                 (c_1 * y_0)**Float('1.0', prec=15) +
                 (c_2 * y_0 * y_2 / (c_6 + y_0))**Float('1.0', prec=15)
             ],
             [
                 V_00 * c_3 - V_01 * c_4 + V_01 *
                 (-c_1 + c_2 * y_0 * y_2 / (c_6 + y_0)**2 - c_2 * y_2 /
                  (c_6 + y_0)) - V_21 * c_2 * y_0 / (c_6 + y_0)
             ],
             [
                 V_01 * c_4 - V_02 * c_5 + V_02 *
                 (-c_1 + c_2 * y_0 * y_2 / (c_6 + y_0)**2 - c_2 * y_2 /
                  (c_6 + y_0)) - V_22 * c_2 * y_0 / (c_6 + y_0)
             ],
             [
                 V_00 * c_3 - V_10 * c_4 + V_10 *
                 (-c_1 + c_2 * y_0 * y_2 / (c_6 + y_0)**2 - c_2 * y_2 /
                  (c_6 + y_0)) - V_12 * c_2 * y_0 / (c_6 + y_0)
             ],
             [
                 V_01 * c_3 + V_10 * c_3 - 2 * V_11 * c_4 +
                 (c_3 * y_0)**Float('1.0', prec=15) +
                 (c_4 * y_1)**Float('1.0', prec=15)
             ],
             [
                 V_02 * c_3 + V_11 * c_4 - V_12 * c_4 - V_12 * c_5 -
                 (c_4 * y_1)**Float('1.0', prec=15)
             ],
             [
                 V_10 * c_4 - V_20 * c_5 + V_20 *
                 (-c_1 + c_2 * y_0 * y_2 / (c_6 + y_0)**2 - c_2 * y_2 /
                  (c_6 + y_0)) - V_22 * c_2 * y_0 / (c_6 + y_0)
             ],
             [
                 V_11 * c_4 + V_20 * c_3 - V_21 * c_4 - V_21 * c_5 -
                 (c_4 * y_1)**Float('1.0', prec=15)
             ],
             [
                 V_12 * c_4 + V_21 * c_4 - 2 * V_22 * c_5 +
                 (c_4 * y_1)**Float('1.0', prec=15) +
                 (c_5 * y_2)**Float('1.0', prec=15)
             ]])

        ode_lhs_terms = [
            Moment(np.array([1, 0, 0]), symbol=y_0),
            Moment(np.array([0, 1, 0]), symbol=y_1),
            Moment(np.array([0, 0, 1]), symbol=y_2),
            VarianceTerm((0, 0), V_00),
            VarianceTerm((0, 1), V_01),
            VarianceTerm((0, 2), V_02),
            VarianceTerm((1, 0), V_10),
            VarianceTerm((1, 1), V_11),
            VarianceTerm((1, 2), V_12),
            VarianceTerm((2, 0), V_20),
            VarianceTerm((2, 1), V_21),
            VarianceTerm((2, 2), V_22)
        ]

        constants = ['c_0', 'c_1', 'c_2', 'c_3', 'c_4', 'c_5', 'c_6']

        problem = ODEProblem('LNA', ode_lhs_terms, right_hand_side, constants)
        self._roundtrip(problem)

        # Now make sure to access problem.right_hand_side_as_function as this sometimes breaks pickle
        f = problem.right_hand_side_as_function
        # Do roundtrip again
        self._roundtrip(problem)