Пример #1
0
    def setUp(self):
        """Construct a Toeplitz matrix for testing the routines in sle.py"""

        # set tolerance for the error
        self.tol = 1e-7

        # set order of the resulting TT operator
        self.order = 10

        # generate Toeplitz matrix
        self.operator_mat = sp.linalg.toeplitz(np.arange(1, 2**self.order + 1),
                                               np.arange(1, 2**self.order + 1))

        # decompose Toeplitz matrix into TT format
        self.operator_tt = TT(self.operator_mat.reshape([2] * 2 * self.order))

        # define right-hand side as vector of all ones (matrix case)
        self.rhs_mat = np.ones(self.operator_mat.shape[0])

        # define right-hand side as tensor train of all ones (tensor case)
        self.rhs_tt = tt.ones(self.operator_tt.row_dims,
                              [1] * self.operator_tt.order)

        # define initial tensor train for solving the system of linear equations
        self.initial_tt = tt.ones(self.operator_tt.row_dims,
                                  [1] * self.operator_tt.order,
                                  ranks=5).ortho_right()
Пример #2
0
    def test_errors(self):
        """test for error computations"""

        # compute numerical solution of the ODE
        operator = mdl.signaling_cascade(3).tt2qtt([[2] * 6] * 3,
                                                   [[2] * 6] * 3)
        initial_value = tt.unit(operator.row_dims, [0] * operator.order)
        initial_guess = tt.ones(operator.row_dims, [1] * operator.order,
                                ranks=self.rank).ortho_right()
        step_sizes = [0.1] * 10
        solution_ee = ode.explicit_euler(operator,
                                         initial_value,
                                         step_sizes,
                                         progress=False,
                                         max_rank=self.max_rank)
        solution_ie = ode.implicit_euler(operator,
                                         initial_value,
                                         initial_guess,
                                         step_sizes,
                                         progress=False)
        solution_tr = ode.trapezoidal_rule(operator,
                                           initial_value,
                                           initial_guess,
                                           step_sizes,
                                           progress=False)

        # compute errors
        errors_ee = ode.errors_expl_euler(operator, solution_ee, step_sizes)
        errors_ie = ode.errors_impl_euler(operator, solution_ie, step_sizes)
        errors_tr = ode.errors_trapezoidal(operator, solution_tr, step_sizes)

        # check if errors are smaller than tolerance
        self.assertLess(np.max(errors_ee), self.tol)
        self.assertLess(np.max(errors_ie), self.tol)
        self.assertLess(np.max(errors_tr), self.tol)
Пример #3
0
    def test_trapezoidal_rule(self):
        """test for trapezoidal rule"""

        # compute numerical solution of the ODE
        operator = mdl.two_step_destruction(1, 2, 1, 2)
        initial_value = tt.zeros([2 ** 2, 2 ** (2 + 1), 2 ** 2, 2 ** 2], [1] * 4)
        initial_value.cores[0][0, -1, 0, 0] = 1
        initial_value.cores[1][0, -2, 0, 0] = 1
        initial_value.cores[2][0, 0, 0, 0] = 1
        initial_value.cores[3][0, 0, 0, 0] = 1
        initial_guess = tt.ones(operator.row_dims, [1] * operator.order, ranks=self.rank).ortho_right()
        step_sizes = [0.001] * 100 + [0.1] * 9 + [1] * 19
        solution_als = ode.trapezoidal_rule(operator, initial_value, initial_guess, step_sizes, tt_solver='als',
                                            progress=False)
        solution_mals = ode.trapezoidal_rule(operator, initial_value, initial_guess, step_sizes, tt_solver='mals',
                                             max_rank=self.rank, progress=False)

        # compute norm of the derivatives at the final 10 time steps
        derivatives_als = []
        derivatives_mals = []
        for i in range(10):
            derivatives_als.append((operator.dot(solution_als[-i - 1])).norm())
            derivatives_mals.append((operator.dot(solution_mals[-i - 1])).norm())

        # check if trapezoidal rule converged to stationary distribution
        for i in range(10):
            self.assertLess(derivatives_als[i], self.tol)
            self.assertLess(derivatives_mals[i], self.tol)
Пример #4
0
    def setUp(self):
        """Consider the triple-well model for testing the routines in sle.py"""

        # set tolerance for the error of the eigenvalues
        self.tol_eigval = 1e-3

        # set tolerance for the error of the eigenvectors
        self.tol_eigvec = 5e-2

        # set number of eigenvalues to compute
        self.number_ev = 3

        # generate operator in TT format
        directory = os.path.dirname(os.path.dirname(
            os.path.realpath(__file__)))
        transitions = io.loadmat(
            directory + '/examples/data/TripleWell2D_500.mat')["indices"]
        self.operator_tt = pf.perron_frobenius_2d(transitions, [50, 50], 500)

        # matricize TT operator
        self.operator_mat = self.operator_tt.matricize()

        # define initial tensor train for solving the eigenvalue problem
        self.initial_tt = tt.ones(self.operator_tt.row_dims,
                                  [1] * self.operator_tt.order,
                                  ranks=11).ortho_right()
Пример #5
0
    def test_adaptive(self):
        """test for adaptive_step_size"""

        # compute numerical solution of the ODE
        operator = mdl.signaling_cascade(2).tt2qtt([[2] * 6] * 2,
                                                   [[2] * 6] * 2)
        initial_value = tt.unit(operator.row_dims, [0] * operator.order)
        initial_guess = tt.ones(operator.row_dims, [1] * operator.order,
                                ranks=self.rank).ortho_right()
        solution_ie, _ = ode.adaptive_step_size(operator,
                                                initial_value,
                                                initial_guess,
                                                300,
                                                step_size_first=1,
                                                second_method='two_step_Euler',
                                                progress=False)
        solution_tr, _ = ode.adaptive_step_size(
            operator,
            initial_value,
            initial_guess,
            300,
            step_size_first=1,
            second_method='trapezoidal_rule',
            progress=False)

        # compute norm of the derivatives at the final time step
        derivative_ie = (operator.dot(solution_ie[-1])).norm()
        derivative_tr = (operator.dot(solution_tr[-1])).norm()

        # check if converged to stationary distribution
        self.assertLess(derivative_ie, self.tol)
        self.assertLess(derivative_tr, self.tol)
Пример #6
0
    def setUpClass(cls):

        super(TestEVP, cls).setUpClass()

        # set tolerance for the error of the eigenvalues
        cls.tol_eigval = 5e-3

        # set tolerance for the error of the eigenvectors
        cls.tol_eigvec = 5e-2

        # set number of eigenvalues to compute
        cls.number_ev = 3

        # load data
        directory = os.path.dirname(os.path.dirname(
            os.path.realpath(__file__)))
        transitions = np.load(
            directory +
            '/examples/data/triple_well_transitions.npz')["transitions"]

        # coarse-grain data
        transitions = np.int64(np.ceil(np.true_divide(transitions, 2)))

        # generate operators in TT format
        cls.operator_tt = ulam.ulam_2d(transitions, [25, 25], 2000)
        cls.operator_gevp = tt.eye(cls.operator_tt.row_dims)

        # matricize TT operator
        cls.operator_mat = cls.operator_tt.matricize()

        # define initial tensor train for solving the eigenvalue problem
        cls.initial_tt = tt.ones(cls.operator_tt.row_dims,
                                 [1] * cls.operator_tt.order,
                                 ranks=15).ortho_right()
Пример #7
0
def two_cell_tof(t, reactant_states, reaction_rate):
    """Turn-over frequency of a reaction in a cyclic homogeneous nearest-neighbor interaction system

    Parameters
    ----------
    t: instance of TT class
        tensor train representing a probability distribution
    reactant_states: list of ints
        reactant states of the given reaction in the form of [reactant_state_1, reactant_state_2] where the list entries
        represent the reactant states on two neighboring cell
    reaction_rate: float
        reaction rate constant of the given reaction

    Returns
    -------
    turn_over_frequency: float
        turn-over frequency of the given reaction
    """

    tt_left = [None] * t.order
    tt_right = [None] * t.order
    for k in range(t.order):
        tt_left[k] = tt.ones([1] * t.order, t.row_dims)
        tt_right[k] = tt.ones([1] * t.order, t.row_dims)
        tt_left[k].cores[k] = np.zeros([1, 1, t.row_dims[k], 1])
        tt_left[k].cores[k][0, 0, reactant_states[0], 0] = 1
        tt_right[k].cores[k] = np.zeros([1, 1, t.row_dims[k], 1])
        tt_right[k].cores[k][0, 0, reactant_states[0], 0] = 1
        if k > 0:
            tt_left[k].cores[k - 1] = np.zeros([1, 1, t.row_dims[k - 1], 1])
            tt_left[k].cores[k - 1][0, 0, reactant_states[1], 0] = 1
        else:
            tt_left[k].cores[-1] = np.zeros([1, 1, t.row_dims[-1], 1])
            tt_left[k].cores[-1][0, 0, reactant_states[1], 0] = 1
        if k < t.order - 1:
            tt_right[k].cores[k + 1] = np.zeros([1, 1, t.row_dims[k + 1], 1])
            tt_right[k].cores[k + 1][0, 0, reactant_states[1], 0] = 1
        else:
            tt_right[k].cores[0] = np.zeros([1, 1, t.row_dims[0], 1])
            tt_right[k].cores[0][0, 0, reactant_states[1], 0] = 1
    turn_over_frequency = 0
    for k in range(t.order):
        turn_over_frequency = turn_over_frequency + (reaction_rate / t.order) * (tt_left[k] @ t) + \
                              (reaction_rate / t.order) * (tt_right[k] @ t)
    return turn_over_frequency
Пример #8
0
    def test_toll_station(self):
        """tests for toll station"""

        # construct operator
        op = mdl.toll_station(self.number_of_lanes, self.number_of_cars)

        # check if stochastic
        self.assertLess((tt.ones([1] * op.order, op.col_dims).dot(op)).norm(),
                        self.tol)
Пример #9
0
    def test_co_oxidation(self):
        """tests for CO oxidation"""

        # construct operator
        op = mdl.co_oxidation(self.order, self.k_ad_co, cyclic=True)

        # check if stochastic
        self.assertLess((tt.ones([1] * op.order, op.col_dims).dot(op)).norm(),
                        self.tol)
Пример #10
0
    def test_two_step(self):
        """tests for two-setp destruction"""

        # construct operator
        op = mdl.two_step_destruction(self.k_1, self.k_2, self.k_3, self.m)

        # check if stochastic
        self.assertLess((tt.ones([1] * op.order, op.col_dims).dot(op)).norm(),
                        self.tol)
Пример #11
0
    def test_signaling_cascade(self):
        """tests for signaling cascade"""

        # construct operator
        op = mdl.signaling_cascade(self.order)

        # check if stochastic
        self.assertLess((tt.ones([1] * op.order, op.col_dims).dot(op)).norm(),
                        self.tol)
Пример #12
0
    def test_ones(self):
        """test tensor train of all ones"""

        # construct tensor train of all ones, convert to full format, and flatten
        t_ones = tt.ones(self.row_dims, self.col_dims).full().flatten()

        # construct full array of all ones
        t_full = np.ones(np.int(np.prod(self.row_dims)) * np.int(np.prod(self.col_dims)))

        # compute relative error
        rel_err = np.linalg.norm(t_ones - t_full) / np.linalg.norm(t_full)

        # check if relative error is smaller than tolerance
        self.assertLess(rel_err, self.tol)
Пример #13
0
    def test_implicit_euler(self):
        """test for implicit Euler method"""

        # compute numerical solution of the ODE
        operator = mdl.signaling_cascade(2).tt2qtt([[2] * 6] * 2,
                                                   [[2] * 6] * 2)
        initial_value = tt.unit(operator.row_dims, [0] * operator.order)
        initial_guess = tt.ones(operator.row_dims, [1] * operator.order,
                                ranks=self.rank).ortho_right()
        step_sizes = [1] * 300
        solution_als = ode.implicit_euler(operator,
                                          initial_value,
                                          initial_guess,
                                          step_sizes,
                                          tt_solver='als',
                                          progress=False)
        solution_mals = ode.implicit_euler(operator,
                                           initial_value,
                                           initial_guess,
                                           step_sizes,
                                           tt_solver='mals',
                                           max_rank=self.rank,
                                           progress=False)

        # compute norm of the derivatives at the final 10 time steps
        derivatives_als = []
        derivatives_mals = []
        for i in range(10):
            derivatives_als.append((operator.dot(solution_als[-i - 1])).norm())
            derivatives_mals.append(
                (operator.dot(solution_mals[-i - 1])).norm())

        # check if implicit Euler method converged to stationary distribution
        for i in range(10):
            self.assertLess(derivatives_als[i], self.tol)
            self.assertLess(derivatives_mals[i], self.tol)
Пример #14
0
# compute solutions and print results
# -----------------------------------

print('----------------------------------------------------------')
print('p_CO in atm    Method    TT ranks    Closeness    CPU time')
print('----------------------------------------------------------')

# construct eigenvalue problems to find the stationary distributions
# ------------------------------------------------------------------

for i in range(8):
    # construct and solve eigenvalue problem for current CO pressure
    operator = mdl.co_oxidation(
        20, 10**(8 + p_CO_exp[i])).ortho_left().ortho_right()
    initial_guess = tt.ones(operator.row_dims, [1] * operator.order,
                            ranks=R[i]).ortho_left().ortho_right()
    with utl.timer() as time:
        eigenvalues, solution = evp.als(tt.eye(operator.row_dims) + operator,
                                        initial_guess,
                                        repeats=10,
                                        solver='eigs')
        solution = (1 / solution.norm(p=1)) * solution

    # compute turn-over frequency of CO2 desorption
    tof.append(utl.two_cell_tof(solution, [2, 1], 1.7e5))

    # print results
    string_p_CO = '10^' + (p_CO_exp[i] >= 0) * '+' + str("%.1f" % p_CO_exp[i])
    string_method = ' ' * 9 + 'EVP' + ' ' * 9
    string_rank = (R[i] < 10) * ' ' + str(R[i]) + ' ' * 8
    string_closeness = str("%.2e" % (operator @ solution).norm()) + ' ' * 6
Пример #15
0
# operator in TT format
# ---------------------

operator = mdl.signaling_cascade(order)

# initial distribution in TT format
# ---------------------------------

initial_distribution = tt.zeros(operator.col_dims, [1] * order)
for p in range(initial_distribution.order):
    initial_distribution.cores[p][0, 0, 0, 0] = 1

# initial guess in TT format
# --------------------------

initial_guess = tt.ones(operator.col_dims, [1] * order,
                        ranks=tt_rank).ortho_right()

# solve Markovian master equation in TT format
# --------------------------------------------

print('TT approach:\n')
solution = ode.trapezoidal_rule(operator, initial_distribution, initial_guess,
                                step_sizes)

# operator in QTT format
# ----------------------

operator = TT.tt2qtt(operator, qtt_modes, qtt_modes, threshold=threshold)

# initial distribution in QTT format
# ----------------------------------
Пример #16
0
utl.progress('Load data', 0, dots=39)
transitions = io.loadmat("data/TripleWell2D_500.mat")["indices"]
utl.progress('Load data', 100, dots=39)

# construct TT operator
# ---------------------

utl.progress('Construct operator', 0, dots=30)
operator = pf.perron_frobenius_2d(transitions, [n_states, n_states],
                                  simulations)
utl.progress('Construct operator', 100, dots=30)

# approximate leading eigenfunctions of the Perron-Frobenius and Koopman operator
# -------------------------------------------------------------------------------

initial = tt.ones(operator.row_dims, [1] * operator.order, ranks=11)
utl.progress('Approximate eigenfunctions in the TT format', 0, dots=5)
eigenvalues_pf, eigenfunctions_pf = evp.als(operator, initial, number_ev, 3)
utl.progress('Approximate eigenfunctions in the TT format', 50, dots=5)
eigenvalues_km, eigenfunctions_km = evp.als(operator.transpose(), initial,
                                            number_ev, 2)
utl.progress('Approximate eigenfunctions in the TT format', 100, dots=5)

# compute exact eigenvectors
# --------------------------

utl.progress('Compute exact eigenfunctions in matrix format', 0)
eigenvalues_pf_exact, eigenfunctions_pf_exact = splin.eigs(
    operator.matricize(), k=number_ev)
utl.progress('Compute exact eigenfunctions in matrix format', 100)
Пример #17
0
    def setUp(self):
        """Consider the Fermi-Pasta-Ulam problem and Kuramoto model for testing the routines in sle.py"""

        # set tolerance
        self.tol = 1e-5

        # number of oscillators
        self.fpu_d = 4
        self.kuramoto_d = 10

        # parameters for the Fermi-Pasta_ulam problem
        self.fpu_m = 2000
        self.fpu_psi = [
            lambda t: 1, lambda t: t, lambda t: t**2, lambda t: t**3
        ]

        # parameters for the Kuramoto model
        self.kuramoto_x_0 = 2 * np.pi * np.random.rand(self.kuramoto_d) - np.pi
        self.kuramoto_w = np.linspace(-5, 5, self.kuramoto_d)
        self.kuramoto_t = 100
        self.kuramoto_m = 1000
        self.kuramoto_psi = [lambda t: np.sin(t), lambda t: np.cos(t)]
        self.kuramoto_basis = [[tdt.constant_function()] +
                               [tdt.sin(i, 1) for i in range(self.kuramoto_d)],
                               [tdt.constant_function()] +
                               [tdt.cos(i, 1) for i in range(self.kuramoto_d)]]
        self.kuramoto_initial = tt.ones([11, 11], [1, 1], 11)

        # exact coefficient tensors
        self.fpu_xi_exact = mdl.fpu_coefficients(self.fpu_d)
        self.kuramoto_xi_exact = mdl.kuramoto_coefficients(
            self.kuramoto_d, self.kuramoto_w)

        # generate test data for FPU
        self.fpu_x = 0.2 * np.random.rand(self.fpu_d, self.fpu_m) - 0.1
        self.fpu_y = np.zeros((self.fpu_d, self.fpu_m))
        for j in range(self.fpu_m):
            self.fpu_y[0,
                       j] = self.fpu_x[1, j] - 2 * self.fpu_x[0, j] + 0.7 * (
                           (self.fpu_x[1, j] - self.fpu_x[0, j])**3 -
                           self.fpu_x[0, j]**3)
            for i in range(1, self.fpu_d - 1):
                self.fpu_y[i, j] = self.fpu_x[
                    i + 1,
                    j] - 2 * self.fpu_x[i, j] + self.fpu_x[i - 1, j] + 0.7 * (
                        (self.fpu_x[i + 1, j] - self.fpu_x[i, j])**3 -
                        (self.fpu_x[i, j] - self.fpu_x[i - 1, j])**3)
                self.fpu_y[-1, j] = -2 * self.fpu_x[-1, j] + self.fpu_x[
                    -2, j] + 0.7 * (-self.fpu_x[-1, j]**3 -
                                    (self.fpu_x[-1, j] - self.fpu_x[-2, j])**3)

        # generate test data for Kuramoto
        number_of_oscillators = len(self.kuramoto_x_0)

        def kuramoto_ode(_, theta):
            [theta_i, theta_j] = np.meshgrid(theta, theta)
            return self.kuramoto_w + 2 / number_of_oscillators * np.sin(
                theta_j - theta_i).sum(0) + 0.2 * np.sin(theta)

        sol = spint.solve_ivp(kuramoto_ode, [0, self.kuramoto_t],
                              self.kuramoto_x_0,
                              method='BDF',
                              t_eval=np.linspace(0, self.kuramoto_t,
                                                 self.kuramoto_m))
        self.kuramoto_x = sol.y
        self.kuramoto_y = np.zeros([number_of_oscillators, self.kuramoto_m])
        for i in range(self.kuramoto_m):
            self.kuramoto_y[:, i] = kuramoto_ode(0, self.kuramoto_x[:, i])