def gen_heisen(d, Jx=0.5, Jz=0.5):
    """Generate Heisenberg Hamiltonian and Mx operator"""
    sx = [[0, 1], [1, 0]]
    sx = np.array(sx, dtype=np.float)
    sz = [[1, 0], [0, -1]]
    sz = np.array(sz, dtype=np.float)
    sz = 0.5 * sz
    sp = [[0, 1], [0, 0]]
    sp = np.array(sp, dtype=np.float)
    sm = sp.T
    e = np.eye(2)
    sx = tt.matrix(sx, 1e-12)
    sz = tt.matrix(sz, 1e-12)
    sp = tt.matrix(sp, 1e-12)
    sm = tt.matrix(sm, 1e-12)
    e = tt.matrix(e, 1e-12)
    # Generate ssx, ssz
    ssp = [gen_1d(sp, e, i, d) for i in range(d)]
    ssz = [gen_1d(sz, e, i, d) for i in range(d)]
    ssm = [gen_1d(sm, e, i, d) for i in range(d)]
    ssx = [gen_1d(sx, e, i, d) for i in range(d)]
    A = None
    Mx = None
    for i in range(d - 1):
        A = A + 0.5 * Jx * (ssp[i] * ssm[i + 1] +
                            ssm[i] * ssp[i + 1]) + Jz * (ssz[i] * ssz[i + 1])
        A = A.round(1e-8)
        Mx = Mx + 0.5 * ssx[i]
        Mx = Mx.round(1e-8)
    A = A + 0.5 * Jx * (ssp[d - 1] * ssm[0] +
                        ssm[d - 1] * ssp[0]) + Jz * (ssz[d - 1] * ssz[0])
    A = A.round(1e-8)
    Mx = Mx + 0.5 * ssx[d - 1]
    Mx = Mx.round(1e-8)
    return A, Mx
Example #2
0
def gen_heisen(d):
    sx = [[0, 1], [1, 0]]
    sx = np.array(sx, dtype=np.float)
    sz = [[1, 0], [0, -1]]
    sz = np.array(sz, dtype=np.float)
    sz = 0.5 * sz
    sp = [[0, 1], [0, 0]]
    sp = np.array(sp, dtype=np.float)
    sm = sp.T
    e = np.eye(2)
    sx = tt.matrix(sx, 1e-12)
    sz = tt.matrix(sz, 1e-12)
    sp = tt.matrix(sp, 1e-12)
    sm = tt.matrix(sm, 1e-12)
    e = tt.matrix(e, 1e-12)
    #Generate ssx, ssz
    ssp = [gen_1d(sp, e, i, d) for i in xrange(d)]
    ssz = [gen_1d(sz, e, i, d) for i in xrange(d)]
    ssm = [gen_1d(sm, e, i, d) for i in xrange(d)]
    A = None
    for i in xrange(d - 1):
        A = A + 0.5 * (ssp[i] * ssm[i + 1] + ssm[i] * ssp[i + 1]) + (
            ssz[i] * ssz[i + 1])
        A = A.round(1e-8)
    return A
Example #3
0
    def CME_tt(self, fs, C, nu):

        d = len(self.size)

        A1 = []
        A2 = []

        for i in range(d):

            core = np.zeros((self.size[i], self.size[i]))
            for k in range(self.size[i]):
                core[k, k] = fs[i](
                    k) if k + nu[i] >= 0 and k + nu[i] < self.size[i] else 0.0
            A1.append(core.reshape([1, self.size[i], self.size[i], 1]))
            # print(core[-10:,-10:])

            core = np.zeros((self.size[i], self.size[i]))
            for k in range(self.size[i]):
                if k + nu[i] >= 0 and k + nu[i] < self.size[i]:
                    core[k + nu[i], k] = fs[i](k)
            A2.append(core.reshape([1, self.size[i], self.size[i], 1]))
            # print(core[-10:,-10:])

        Att = C * (tt.matrix().from_list(A2) - tt.matrix().from_list(A1))

        Att = Att.round(1e-18, 64)

        return Att
def gen_heisenberg_hamiltonian(dimension, Jx=0.5, Jz=0.5, periodic=True):
    """
    Generate 1D Heisenberg hamiltonian
    Parameters:
    -----------
    dimension: int
           Numner of sites
    Jx: float
           Sx coupling strength
    Jz: float
           Sz coupling strength
    periodic: bool
           If the Hamiltonian will be made periodic
    """
    # Create operators
    sx = [[0, 1], [1, 0]]
    sx = np.array(sx, dtype=np.float)
    sz = [[1, 0], [0, -1]]
    sz = np.array(sz, dtype=np.float)
    sz = 0.5 * sz
    sp = [[0, 1], [0, 0]]
    sp = np.array(sp, dtype=np.float)
    sm = sp.T
    e = np.eye(2)
    sx = tt.matrix(sx, 1e-12)
    sz = tt.matrix(sz, 1e-12)
    sp = tt.matrix(sp, 1e-12)
    sm = tt.matrix(sm, 1e-12)
    e = tt.matrix(e, 1e-12)
    # Generate arrays of 1 site operators
    ssp = [
        gen_1site_1d_operator(sp, e, i, dimension) for i in range(dimension)
    ]
    ssz = [
        gen_1site_1d_operator(sz, e, i, dimension) for i in range(dimension)
    ]
    ssm = [
        gen_1site_1d_operator(sm, e, i, dimension) for i in range(dimension)
    ]
    ssx = [
        gen_1site_1d_operator(sx, e, i, dimension) for i in range(dimension)
    ]
    Ham = None
    for i in range(dimension - 1):
        Ham = Ham + 0.5 * Jx * (ssp[i] * ssm[i + 1] + ssm[i] *
                                ssp[i + 1]) + Jz * (ssz[i] * ssz[i + 1])
        # compress
        Ham = Ham.round(1e-8)
    # Add periodic conditions in the Hamiltonian
    if periodic:
        Ham = Ham + 0.5 * Jx * (ssp[dimension - 1] * ssm[0] +
                                ssm[dimension - 1] * ssp[0]) + Jz * (
                                    ssz[dimension - 1] * ssz[0])
    Ham = Ham.round(1e-8)
    return Ham
Example #5
0
 def conv2mode(self, mode=None, tau=None):
     if mode is not None:
         self.mode = mode
     if tau is not None:
         self.tau = tau
     if self.x is None:
         return
     elif isinstance(self.x, np.ndarray):
         if len(self.x.shape) != 2 or self.x.shape[0] != self.x.shape[1]:
             raise ValueError('Incorrect shape.')
         self.d = _n2d(self.x.shape[0])
         if self.mode == MODE_TT:
             self.x = tt.matrix(self.x.reshape([2] * (2 * self.d),
                                               order='F'),
                                eps=self.tau)
         if self.mode == MODE_SP:
             raise NotImplementedError()
     elif isinstance(self.x, tt.matrix):
         self.d = self.x.tt.d
         if self.mode == MODE_NP:
             self.x = self.x.full()
         if self.mode == MODE_SP:
             raise NotImplementedError()
     elif isinstance(self.x, csr_matrix):
         if self.mode == MODE_NP or self.mode == MODE_TT:
             self.x = self.x.toarray()
             self.conv2mode()
         else:
             if len(self.x.shape
                    ) != 2 or self.x.shape[0] != self.x.shape[1]:
                 raise ValueError('Incorrect shape.')
             self.d = _n2d(self.x.shape[0])
     else:
         raise ValueError('Incorrect matrix.')
def gen_ksite_magnetization(dimension, used_sites=None, scale_sites=None):
    """
    Generate the magnetization operator Mx

    Parameters:
    -----------
    dimension: int
           Number of sites
    used_sited: np.array, default None
           Logical array indicating which sites to measure
           By default a central site is used for odd
           dimension and a central pair of sites for even dimension
    scale_sites: np.array, default None
           Array for setting weight of every site. Default 0.
           Should have the same size as dimension
    """
    # Decide which sites to use
    if used_sites is None:
        used_sites = np.zeros(dimension)
        if dimension % 2 == 0:
            used_sites[dimension // 2] = 1
            used_sites[dimension // 2 - 1] = 1
        else:
            used_sites[dimension // 2] = 1

    if scale_sites is not None:
        assert (len(scale_sites) == dimension)
    else:
        scale_sites = np.ones(dimension)

    # Create operators
    sx = [[0, 1], [1, 0]]
    sx = np.array(sx, dtype=np.float)
    e = np.eye(2)
    sx = tt.matrix(sx, 1e-12)
    e = tt.matrix(e, 1e-12)
    # Generate arrays of 1 site operators
    ssx = [
        gen_1site_1d_operator(sx, e, i, dimension) for i in range(dimension)
    ]

    Mx = None
    for i in range(dimension):
        if bool(used_sites[i]) is True:
            Mx = Mx + 0.5 * ssx[i] * scale_sites[i]
            Mx = Mx.round(1e-8)
    return Mx
Example #7
0
def gen_heisen(d):
    sx = [[0,1],[1,0]]
    sx = np.array(sx,dtype=np.float)
    sz = [[1,0],[0,-1]]
    sz = np.array(sz,dtype=np.float)
    sz = 0.5 * sz
    sp = [[0,1],[0,0]]; sp =  np.array(sp,dtype=np.float)
    sm = sp.T
    e = np.eye(2)
    sx = tt.matrix(sx,1e-12)
    sz = tt.matrix(sz,1e-12)
    sp = tt.matrix(sp,1e-12)
    sm = tt.matrix(sm,1e-12)
    e = tt.matrix(e,1e-12)
    #Generate ssx, ssz
    ssp = [gen_1d(sp,e,i,d) for i in xrange(d)]
    ssz = [gen_1d(sz,e,i,d) for i in xrange(d)]
    ssm = [gen_1d(sm,e,i,d) for i in xrange(d)]
    A = None
    for i in xrange(d-1):
        A = A + 0.5 * (ssp[i] * ssm[i+1] + ssm[i] * ssp[i+1]) +  (ssz[i] * ssz[i+1])
        A = A.round(1e-8)
    return A
    Identity_bd_qtt=np.reshape(identity_bd,qtt_matrix)
    

    #------------------converting to TT-format------------------

    # #converting rightside to TT-format
    # #problem 1
    f1_qtt = tt.tensor(f1_qtt)
    g1_qtt = tt.tensor(g1_qtt )
    
    # #problem 1
    f2_qtt = tt.tensor(f2_qtt)
    g2_qtt = tt.tensor(g2_qtt)
    
    # #convert Identity matrix to TT-format
    Identity_qtt = tt.matrix(Identity_qtt) 
    Identity_bd_qtt=tt.matrix(Identity_bd_qtt)
    
    # #convert laplacian matrix to TT-format
    L_qtt = tt.matrix(L_qtt)
    Lbd_qtt = tt.matrix(Lbd_qtt)
    Lf_qtt = tt.matrix(Lf_qtt)
    

    
    
    #------------------building 3d Lbd_tt matrixmatrix in TT-format with TT-kronecker product------------------
    
    Lbd_qtt= tt.kron(tt.kron(Lbd_qtt,Identity_bd_qtt),Identity_bd_qtt)+tt.kron(tt.kron(Identity_bd_qtt,Lbd_qtt),Identity_bd_qtt)+tt.kron(tt.kron(Identity_bd_qtt,Identity_bd_qtt),Lbd_qtt)
        
    
Example #9
0
lm = 0.111803 #The magic constant
#lm = 0 #The magic constant
#lm = 1e-2
#lm = 
N = 15 # The size of the spectral discretization

x, ws = quadgauss.cdgqf(N,6,0,0.5) #Generation of hermite quadrature
#Generate Laplacian
lp = np.zeros((N,N))
for i in xrange(N):
    for j in xrange(N):
        if i is not j:
            lp[i,j] = (-1)**(i - j)*(2*(x[i] - x[j])**(-2) - 0.5)
        else:
            lp[i,j] = 1.0/6*(4*N - 1 - 2 * x[i]**2)
lp = tt.matrix(lp)
e = tt.eye([N])

lp2 = None
eps = 1e-8
for i in xrange(f):
    w = lp
    for j in xrange(i):
        w = tt.kron(e,w)
    for j in xrange(i+1,f):
        w = tt.kron(w,e)
    lp2 = lp2 + w
    lp2 = lp2.round(eps)


#Now we will compute Henon-Heiles stuff
Example #10
0
#L[0,:] = 0
#L[-1,:] = 0
#L[0,0] = 1
#L[-1,-1] = 1

#creating Identity matrix for kronecker product
Identity = np.identity(n + 1)

#------------------converting to TT-format------------------

#convert right-hand side b to TT-format
b1_tt = tt.vector(b1)
b2_tt = tt.vector(b2)

#convert Identity matrix to TT-format
Identity_tt = tt.matrix(Identity)

#convert laplacian matrix to TT-format
L_tt = tt.matrix(L)

#------------------building 3d laplacian matrix in TT-format with TT-kronecker product------------------

L_tt1 = tt.kron(tt.kron(L_tt, Identity_tt), Identity_tt)
L_tt2 = tt.kron(tt.kron(Identity_tt, L_tt), Identity_tt)
L_tt3 = tt.kron(tt.kron(Identity_tt, Identity_tt), L_tt)
L_tt = L_tt1 + L_tt2 + L_tt3

#------------------solving higher order linear system in TT-format------------------

#defining initial guess vector
x = tt.ones(11, d)
Example #11
0
    def solve(self,
              initial_tt,
              T,
              intervals=None,
              return_all=False,
              nswp=40,
              qtt=False,
              verb=False,
              rounding=True):

        if intervals == None:
            pass
        else:
            x_tt = initial_tt
            dT = T / intervals
            Nt = self.N_max

            S, P, ev, basis = self.get_SP(dT, Nt)

            if qtt:
                nqtt = int(np.log2(Nt))
                S = ttm2qttm(tt.matrix(S))
                P = ttm2qttm(tt.matrix(P))
                I_tt = tt.eye(self.A_tt.n)
                B_tt = tt.kron(I_tt, tt.matrix(S)) - tt.kron(
                    I_tt, P) @ tt.kron(self.A_tt, ttm2qttm(tt.eye([Nt])))

            else:
                nqtt = 1
                I_tt = tt.eye(self.A_tt.n)
                B_tt = tt.kron(I_tt, tt.matrix(S)) - tt.kron(
                    I_tt, tt.matrix(P)) @ tt.kron(self.A_tt,
                                                  tt.matrix(np.eye(Nt)))

            # print(dT,T,intervals)
            returns = []
            for i in range(intervals):
                # print(i)
                if qtt:
                    f_tt = tt.kron(x_tt, tt2qtt(tt.tensor(ev)))
                else:
                    f_tt = tt.kron(x_tt, tt.tensor(ev))
                # print(B_tt.n,f_tt.n)
                try:
                    # xs_tt = xs_tt.round(1e-10,5)
                    # tme = datetime.datetime.now()
                    xs_tt = tt.amen.amen_solve(B_tt,
                                               f_tt,
                                               self.xs_tt,
                                               self.epsilon,
                                               verb=1 if verb else 0,
                                               nswp=nswp,
                                               kickrank=8,
                                               max_full_size=50,
                                               local_prec='n')

                    # tme = datetime.datetime.now() - tme
                    # print(tme)

                    self.xs_tt = xs_tt
                except:
                    # tme = datetime.datetime.now()
                    xs_tt = tt.amen.amen_solve(B_tt,
                                               f_tt,
                                               f_tt,
                                               self.epsilon,
                                               verb=1 if verb else 0,
                                               nswp=nswp,
                                               kickrank=8,
                                               max_full_size=50,
                                               local_prec='n')
                    # tme = datetime.datetime.now() - tme
                    # print(tme)

                    self.xs_tt = xs_tt
                # print('SIZE',tt_size(xs_tt)/1e6)
                # print('PLMMM',tt.sum(xs_tt),xs_tt.r)
                if basis == None:
                    if return_all: returns.append(xs_tt)
                    x_tt = xs_tt[tuple([slice(None, None, None)] *
                                       len(self.A_tt.n) + [-1] * nqtt)]
                    x_tt = x_tt.round(self.epsilon / 10)
                else:

                    if return_all:
                        if qtt:
                            beval = basis(np.array([0])).flatten()
                            temp1 = xs_tt * tt.kron(tt.ones(self.A_tt.n),
                                                    tt2qtt(tt.tensor(beval)))
                            for l in range(nqtt):
                                temp1 = tt.sum(temp1, len(temp1.n) - 1)
                            beval = basis(np.array([dT])).flatten()
                            temp2 = xs_tt * tt.kron(tt.ones(self.A_tt.n),
                                                    tt2qtt(tt.tensor(beval)))
                            for l in range(nqtt):
                                temp2 = tt.sum(temp2, len(temp2.n) - 1)
                            returns.append(
                                tt.kron(temp1, tt.tensor(np.array([1, 0]))) +
                                tt.kron(temp2, tt.tensor(np.array([0, 1]))))
                        else:
                            beval = basis(np.array([0])).flatten()
                            temp1 = xs_tt * tt.kron(tt.ones(self.A_tt.n),
                                                    tt.tensor(beval))
                            temp1 = tt.sum(temp1, len(temp1.n) - 1)
                            beval = basis(np.array([dT])).flatten()
                            temp2 = xs_tt * tt.kron(tt.ones(self.A_tt.n),
                                                    tt.tensor(beval))
                            temp2 = tt.sum(temp2, len(temp2.n) - 1)
                            returns.append(
                                tt.kron(temp1, tt.tensor(np.array([1, 0]))) +
                                tt.kron(temp2, tt.tensor(np.array([0, 1]))))

                    beval = basis(np.array([dT])).flatten()
                    if qtt:
                        x_tt = xs_tt * tt.kron(tt.ones(self.A_tt.n),
                                               tt2qtt(tt.tensor(beval)))
                        for l in range(nqtt):
                            x_tt = tt.sum(x_tt, len(x_tt.n) - 1)
                        if rounding: x_tt = x_tt.round(self.epsilon / 10)
                    else:
                        x_tt = tt.sum(
                            xs_tt *
                            tt.kron(tt.ones(self.A_tt.n), tt.tensor(beval)),
                            len(xs_tt.n) - 1)
                        if rounding: x_tt = x_tt.round(self.epsilon / 10)
                # print('SIZE 2 ',tt_size(x_tt)/1e6)
            if not return_all: returns = x_tt
            return returns
Example #12
0
import timeit
import numpy as np
import pickle
import argparse
import tt
from tt.riemannian import riemannian

parser = argparse.ArgumentParser(description='Measure execution time of various t3f operations.')
parser.add_argument('--file_path', help='Path to the file to save logs.')
args = parser.parse_args()

matrix = tt.matrix(tt.rand(100, 10, 10))
vec = tt.matrix(tt.rand(10, 10, 10), n=[10] * 10, m=[1] * 10)
vec_100 = tt.matrix(tt.rand(10, 10, 100), n=[10] * 10, m=[1] * 10)
tens = np.random.randn(10, 10, 10, 10)
globals = {'matrix': matrix, 'vec': vec, 'vec_100': vec_100, 'tens': tens,
           'tt': tt, 'riemannian': riemannian}

logs = {'lib': 'ttpy'}

# Warmup
timeit.timeit("matrix * vec", globals=globals, number=10)

matvec_time = timeit.timeit("matrix * vec", globals=globals, number=1000) / 1000
print('Multiplying a matrix by a vector takes %f seconds.' % matvec_time)
logs['matvec_time'] = matvec_time

matmul_time = timeit.timeit("matrix * matrix", globals=globals, number=100) / 100
print('Multiplying a matrix by a matrix takes %f seconds.' % matmul_time)
logs['matmul_time'] = matmul_time
def gen_scaled_heisenberg_hamiltonian(dimension,
                                      cluster_size,
                                      Jx=0.5,
                                      Jz=0.5,
                                      periodic=True):
    """
    Generate 1D Heisenberg hamiltonian
    Parameters:
    -----------
    dimension: int
           Number of sites
    cluster_size: int
           Size of the cluster which is simulated exactly
           The cluster will be placed in the center of the chain
    Jx: float
           Sx coupling strength
    Jz: float
           Sz coupling strength
    periodic: bool
           If the Hamiltonian will be made periodic
    """
    # import pdb
    # pdb.set_trace()
    assert (dimension >= cluster_size)

    # Create operators
    sx = [[0, 1], [1, 0]]
    sx = np.array(sx, dtype=np.float)
    sz = [[1, 0], [0, -1]]
    sz = np.array(sz, dtype=np.float)
    sz = 0.5 * sz
    sp = [[0, 1], [0, 0]]
    sp = np.array(sp, dtype=np.float)
    sm = sp.T
    e = np.eye(2)
    sx = tt.matrix(sx, 1e-12)
    sz = tt.matrix(sz, 1e-12)
    sp = tt.matrix(sp, 1e-12)
    sm = tt.matrix(sm, 1e-12)
    e = tt.matrix(e, 1e-12)
    # Generate arrays of 1 site operators
    ssp = [
        gen_1site_1d_operator(sp, e, i, dimension) for i in range(dimension)
    ]
    ssz = [
        gen_1site_1d_operator(sz, e, i, dimension) for i in range(dimension)
    ]
    ssm = [
        gen_1site_1d_operator(sm, e, i, dimension) for i in range(dimension)
    ]
    ssx = [
        gen_1site_1d_operator(sx, e, i, dimension) for i in range(dimension)
    ]
    Ham = None

    space_size = 2**(cluster_size // 2)
    half_no_cluster = (dimension - cluster_size) // 2
    cluster_start = half_no_cluster - 1 if half_no_cluster > 0 else 0

    # classical subsystem
    for i in range(cluster_start):
        Ham = Ham + 0.5 * Jx * (ssp[i] * ssm[i + 1] + ssm[i] *
                                ssp[i + 1]) + Jz * (ssz[i] * ssz[i + 1])

    for i in range(dimension - half_no_cluster, dimension - 1):
        Ham = Ham + 0.5 * Jx * (ssp[i] * ssm[i + 1] + ssm[i] *
                                ssp[i + 1]) + Jz * (ssz[i] * ssz[i + 1])
    # quantum cluster
    center_of_cluster = cluster_start + cluster_size // 2 - 1
    cluster_end = cluster_start + cluster_size - 1
    if half_no_cluster > 0:
        cluster_end += 2
        center_of_cluster += 1

    jj = 0
    # if the cluster coincides with the system correct
    # the indices and the exponent counter
    if half_no_cluster == 0:
        jj += 1

    for i in range(cluster_start, cluster_end):
        scaling_factor = 1 / np.sqrt(space_size / 2**jj + 1)
        Ham = Ham + 0.5 * Jx * scaling_factor * (
            ssp[i] * ssm[i + 1] +
            ssm[i] * ssp[i + 1]) + Jz * scaling_factor * (ssz[i] * ssz[i + 1])
        if i < center_of_cluster:
            jj += 1
        else:
            jj -= 1
        # compress
        Ham = Ham.round(1e-8)

    # Add periodic conditions in the Hamiltonian
    if periodic:
        # the cluster coincides with the system size. Maximal
        # scaling factor across the edge
        if half_no_cluster == 0:
            scaling_factor = 1 / np.sqrt(space_size + 1)
            Ham = Ham + 0.5 * Jx * scaling_factor * (
                ssp[dimension - 1] * ssm[0] + ssm[dimension - 1] *
                ssp[0]) + Jz * (ssz[dimension - 1] * ssz[0])
        else:
            Ham = Ham + 0.5 * Jx * (ssp[dimension - 1] * ssm[0] +
                                    ssm[dimension - 1] * ssp[0]) + Jz * (
                                        ssz[dimension - 1] * ssz[0])
    Ham = Ham.round(1e-8)
    return Ham
Example #14
0
#   test_common.py
#   See LICENSE for details
"""Test common matrix operation with QTT-toolbox like matmat-operation and matvec-operation.
"""

from __future__ import print_function, absolute_import, division
import numpy as np
import sys

sys.path.append('../')

import tt

x = tt.xfun(2, 3)
e = tt.ones(2, 2)
X = tt.matrix(x, n=[2] * 3, m=[1] * 3)  # [0, 1, 2, 3, 4, 5, 6, 7]^T
E = tt.matrix(e, n=[1] * 2, m=[2] * 2)  # [1, 1, 1, 1]
#[[ 0.  0.  0.  0.]
# [ 1.  1.  1.  1.]
# [ 2.  2.  2.  2.]
# [ 3.  3.  3.  3.]
# [ 4.  4.  4.  4.]
# [ 5.  5.  5.  5.]
# [ 6.  6.  6.  6.]
# [ 7.  7.  7.  7.]]
print((X * E).full())
assert np.all((X * E) * np.arange(4) == np.arange(8) * 6.)

A = tt.matrix(tt.xfun(2, 3), n=[1] * 3, m=[2] * 3)
u = np.arange(8)
assert A * u == 140.
Example #15
0
#   See LICENSE for details
"""Test common matrix operation with QTT-toolbox like matmat-operation and matvec-operation.
"""

from __future__ import print_function, absolute_import, division
import numpy as np
import sys

sys.path.append('../')

import tt


x = tt.xfun(2, 3)
e = tt.ones(2, 2)
X = tt.matrix(x, n=[2] * 3, m=[1] * 3) # [0, 1, 2, 3, 4, 5, 6, 7]^T
E = tt.matrix(e, n=[1] * 2, m=[2] * 2) # [1, 1, 1, 1]
#[[ 0.  0.  0.  0.]
# [ 1.  1.  1.  1.]
# [ 2.  2.  2.  2.]
# [ 3.  3.  3.  3.]
# [ 4.  4.  4.  4.]
# [ 5.  5.  5.  5.]
# [ 6.  6.  6.  6.]
# [ 7.  7.  7.  7.]]
print((X * E).full())
assert np.all((X * E) * np.arange(4) == np.arange(8) * 6.)

A = tt.matrix(tt.xfun(2, 3), n=[1] * 3, m=[2] * 3)
u = np.arange(8)
assert A * u == 140.
qtt = True

# Set up model
mdl = CME(N, Pre, Post, rates * 0 + 1, Props)
Atts = mdl.construct_generator_tt(as_list=True)

Nl = 64
mult = 4
param_range = [(0, r * 5) for r in rates[:-1]]
pts1, ws1 = points_weights(param_range[0][0], param_range[0][1], Nl)
pts2, ws2 = points_weights(param_range[1][0], param_range[1][1], Nl)
pts3, ws3 = points_weights(param_range[2][0], param_range[2][1], Nl)
pts4, ws4 = points_weights(param_range[3][0], param_range[3][1], Nl)
pts5, ws5 = points_weights(param_range[4][0], param_range[4][1], Nl)

A_tt = tt.kron(Atts[0] , tt.kron(tt.matrix(np.diag(pts1)),tt.eye([Nl]*4)) ) \
     + tt.kron(Atts[1] , tt.kron(tt.kron(tt.eye([Nl]),tt.matrix(np.diag(pts2))),tt.eye([Nl]*3)) ) \
     + tt.kron(Atts[2] , tt.kron(tt.kron(tt.eye([Nl]*2),tt.matrix(np.diag(pts3))),tt.eye([Nl]*2)) )  \
     + tt.kron(Atts[3] , tt.kron(tt.kron(tt.eye([Nl]*3),tt.matrix(np.diag(pts4))),tt.eye([Nl]*1)) ) \
     + tt.kron(Atts[4] , tt.kron(tt.eye([Nl]*4),tt.matrix(np.diag(pts5))) ) \
     + tt.kron(Atts[5], tt.eye([Nl]*5) )*rates[5]

A_tt = A_tt.round(1e-10, 20)

No = 64
# Nt = 64
dT = 0.2
Nbs = 8
time_observation = np.arange(No) * dT

#%% Get observation
 def getForD1(self):
     return tt.matrix(np.array([[0, 1], [0, 0]]))