Exemplo n.º 1
0
def calc_K_l(Km1, Cm1, lm2, r, A, Am1, sanity_checks=False):
    """Calculates the K_left using the recursive definition.
    
    This is the "bra-vector" K_left, which means (K_left.dot(r)).trace() = <K_left|r>.
    In other words, K_left ~ <K_left| and K_left.conj().T ~ |K_left>.
    """
    D = A.shape[2]
    q = A.shape[0]
    qm1 = Am1.shape[0]
    
    K = sp.zeros((D, D), dtype=A.dtype)
    
    Hl = sp.zeros_like(K)

    for s in xrange(qm1):
        Am1sh = Am1[s].conj().T
        for t in xrange(q):
            Hl += A[t].conj().T.dot(Am1sh).dot(lm2.dot(Cm1[s, t]))
        
        K += A[s].conj().T.dot(Km1.dot(A[s]))
        
    op_expect = mm.adot_noconj(Hl, r)
        
    K += Hl
    
    return K, op_expect
Exemplo n.º 2
0
    def calc_K(self):
        """Generates the right K matrices used to calculate the B's
        
        K[n] contains 'column-vectors' such that <l[n]|K[n]> = trace(l[n].dot(K[n])).
        K_l[n] contains 'bra-vectors' such that <K_l[n]|r[n]> = trace(K_l[n].dot(r[n])).
        """
   
        self.h_expect = sp.zeros((self.N + 1), dtype=self.typ)
        
        self.uni_r.calc_AA()
        self.uni_r.calc_C()
        self.uni_r.calc_K()
        self.K[self.N + 1][:] = self.uni_r.K[0]

        self.uni_l.calc_AA()
        self.uni_l.calc_C()
        K_left, h_left_uni = self.uni_l.calc_K_l()
        
        self.K_l[0][:] = K_left[-1]

        for n in xrange(self.N, self.N_centre - 1, -1):
            self.K[n], he = tm.calc_K(self.K[n + 1], self.C[n], self.get_l(n - 1),
                                      self.r[n + 1], self.A[n], self.get_AA(n))
                
            self.h_expect[n] = he

        for n in xrange(1, self.N_centre + 1):
            self.K_l[n], he = tm.calc_K_l(self.K_l[n - 1], self.C[n - 1], self.get_l(n - 2),
                                          self.r[n], self.A[n], self.get_AA(n - 1))
                
            self.h_expect[n - 1] = he

        self.dH_expect = (mm.adot_noconj(self.K_l[self.N_centre], self.r[self.N_centre]) 
                          + mm.adot(self.l[self.N_centre - 1], self.K[self.N_centre]) 
                          - (self.N + 1) * self.uni_r.h_expect)
Exemplo n.º 3
0
def calc_K_3s_l(Km1, Cm2, lm3, r, A, Am2Am1A):
    K = eps_l_noop(Km1, A, A)

    Hl = eps_l_op_3s_AAA123_C456(lm3, Am2Am1A, Cm2)

    op_expect = mm.adot_noconj(Hl, r)

    K += Hl

    return K, op_expect
Exemplo n.º 4
0
def calc_K_l_tp(Km1, lm2, r, Am1, A, Cm1_tp):
    K = eps_l_noop(Km1, A, A)

    Hl = eps_l_op_2s_C34_tp(lm2, Am1, A, Cm1_tp)

    op_expect = mm.adot_noconj(Hl, r)

    K += Hl

    return K, op_expect
Exemplo n.º 5
0
def calc_K_3s_l(Km1, Cm2, lm3, r, A, Am2Am1A):
    K = eps_l_noop(Km1, A, A)
    
    Hl = eps_l_op_3s_AAA123_C456(lm3, Am2Am1A, Cm2)  
    
    op_expect = mm.adot_noconj(Hl, r)
        
    K += Hl
    
    return K, op_expect
Exemplo n.º 6
0
def calc_K_l_tp(Km1, lm2, r, Am1, A, Cm1_tp):
    K = eps_l_noop(Km1, A, A)
    
    Hl = eps_l_op_2s_C34_tp(lm2, Am1, A, Cm1_tp)

    op_expect = mm.adot_noconj(Hl, r)
        
    K += Hl
    
    return K, op_expect
Exemplo n.º 7
0
def calc_K_l(Km1, Cm1, lm2, r, A, Am1A):
    """Calculates the K_left using the recursive definition.
    
    This is the "bra-vector" K_left, which means (K_left.dot(r)).trace() = <K_left|r>.
    In other words, K_left ~ <K_left| and K_left.conj().T ~ |K_left>.
    """
    K = eps_l_noop(Km1, A, A)

    Hl = eps_l_op_2s_AA12_C34(lm2, Am1A, Cm1)

    op_expect = mm.adot_noconj(Hl, r)

    K += Hl

    return K, op_expect
Exemplo n.º 8
0
def calc_K_l(Km1, Cm1, lm2, r, A, Am1A):
    """Calculates the K_left using the recursive definition.
    
    This is the "bra-vector" K_left, which means (K_left.dot(r)).trace() = <K_left|r>.
    In other words, K_left ~ <K_left| and K_left.conj().T ~ |K_left>.
    """    
    K = eps_l_noop(Km1, A, A)
    
    Hl = eps_l_op_2s_AA12_C34(lm2, Am1A, Cm1)

    op_expect = mm.adot_noconj(Hl, r)
        
    K += Hl
    
    return K, op_expect
Exemplo n.º 9
0
    def calc_K(self):
        """Generates the right K matrices used to calculate the B's
        
        K[n] contains 'column-vectors' such that <l[n]|K[n]> = trace(l[n].dot(K[n])).
        K_l[n] contains 'bra-vectors' such that <K_l[n]|r[n]> = trace(K_l[n].dot(r[n])).
        """

        self.h_expect = sp.zeros((self.N + 1), dtype=self.typ)

        self.uni_r.calc_AA()
        self.uni_r.calc_C()
        self.uni_r.calc_K()
        self.K[self.N + 1][:] = self.uni_r.K

        self.uni_l.calc_AA()
        self.uni_l.calc_C()
        K_left, h_left_uni = self.uni_l.calc_K_l()
        self.K_l[0][:] = K_left

        for n in xrange(self.N, self.N_centre - 1, -1):
            self.K[n], he = tm.calc_K(self.K[n + 1],
                                      self.C[n],
                                      self.get_l(n - 1),
                                      self.r[n + 1],
                                      self.A[n],
                                      self.A[n + 1],
                                      sanity_checks=self.sanity_checks)

            self.h_expect[n] = he

        for n in xrange(1, self.N_centre + 1):
            self.K_l[n], he = tm.calc_K_l(self.K_l[n - 1],
                                          self.C[n - 1],
                                          self.get_l(n - 2),
                                          self.r[n],
                                          self.A[n],
                                          self.A[n - 1],
                                          sanity_checks=self.sanity_checks)

            self.h_expect[n - 1] = he

        self.dH_expect = (
            mm.adot_noconj(self.K_l[self.N_centre], self.r[self.N_centre]) +
            mm.adot(self.l[self.N_centre - 1], self.K[self.N_centre]) -
            (self.N + 1) * self.uni_r.h_expect)
Exemplo n.º 10
0
    def calc_B_centre(self):
        """Calculate the optimal B_centre given right gauge-fixing on n_centre+1..N and
        left gauge-fixing on 1..n_centre-1.
        
        We use the non-norm-preserving K's, since the norm-preservation
        is not needed elsewhere. It is cleaner to subtract the relevant
        norm-changing terms from the K's here than to generate all K's
        with norm-preservation.
        """
        Bc = sp.empty_like(self.A[self.N_centre])

        Nc = self.N_centre

        try:
            rc_i = self.r[Nc].inv()
        except AttributeError:
            rc_i = mm.invmh(self.r[Nc])

        try:
            lcm1_i = self.l[Nc - 1].inv()
        except AttributeError:
            lcm1_i = mm.invmh(self.l[Nc - 1])

        Acm1 = self.A[Nc - 1]
        Ac = self.A[Nc]
        Acp1 = self.A[Nc + 1]
        rc = self.r[Nc]
        rcp1 = self.r[Nc + 1]
        lcm1 = self.l[Nc - 1]
        lcm2 = self.l[Nc - 2]

        #Note: this is a 'bra-vector'
        K_l_cm1 = self.K_l[Nc - 1] - lcm1 * mm.adot_noconj(
            self.K_l[Nc - 1], self.r[Nc - 1])

        Kcp1 = self.K[Nc + 1] - rc * mm.adot(self.l[Nc], self.K[Nc + 1])

        Cc = self.C[Nc] - self.h_expect[Nc] * self.AAc
        Ccm1 = self.C[Nc - 1] - self.h_expect[Nc - 1] * self.AAcm1

        for s in xrange(self.q[1]):
            try:  #3
                Bc[s] = Ac[s].dot(rc_i.dot_left(Kcp1))
            except AttributeError:
                Bc[s] = Ac[s].dot(Kcp1.dot(rc_i))

            for t in xrange(self.q[2]):  #1
                try:
                    Bc[s] += Cc[s,
                                t].dot(rcp1.dot(rc_i.dot_left(mm.H(Acp1[t]))))
                except AttributeError:
                    Bc[s] += Cc[s, t].dot(rcp1.dot(mm.H(Acp1[t]).dot(rc_i)))

            Bcsbit = K_l_cm1.dot(Ac[s])  #4

            for t in xrange(self.q[0]):  #2
                Bcsbit += mm.H(Acm1[t]).dot(lcm2.dot(Ccm1[t, s]))

            Bc[s] += lcm1_i.dot(Bcsbit)

        rb = tm.eps_r_noop(rc, Bc, Bc)
        eta = sp.sqrt(mm.adot(lcm1, rb))

        return Bc, eta
Exemplo n.º 11
0
    def calc_B_centre(self):
        """Calculate the optimal B_centre given right gauge-fixing on n_centre+1..N and
        left gauge-fixing on 1..n_centre-1.
        
        We use the non-norm-preserving K's, since the norm-preservation
        is not needed elsewhere. It is cleaner to subtract the relevant
        norm-changing terms from the K's here than to generate all K's
        with norm-preservation.
        """
        Bc = sp.empty_like(self.A[self.N_centre])
        
        Nc = self.N_centre

        try:
            rc_i = self.r[Nc].inv()
        except AttributeError:
            rc_i = mm.invmh(self.r[Nc])
            
        try:
            lcm1_i = self.l[Nc - 1].inv()
        except AttributeError:
            lcm1_i = mm.invmh(self.l[Nc - 1])
        
        Acm1 = self.A[Nc - 1]
        Ac = self.A[Nc]
        Acp1 = self.A[Nc + 1]
        rc = self.r[Nc]
        rcp1 = self.r[Nc + 1]
        lcm1 = self.l[Nc - 1]
        lcm2 = self.l[Nc - 2]
        
        #Note: this is a 'bra-vector'
        K_l_cm1 = self.K_l[Nc - 1] - lcm1 * mm.adot_noconj(self.K_l[Nc - 1], self.r[Nc - 1])
        
        Kcp1 = self.K[Nc + 1] - rc * mm.adot(self.l[Nc], self.K[Nc + 1])
        
        Cc = self.C[Nc] - self.h_expect[Nc] * self.AAc
        Ccm1 = self.C[Nc - 1] - self.h_expect[Nc - 1] * self.AAcm1
        
        for s in xrange(self.q[1]):
            try: #3
                Bc[s] = Ac[s].dot(rc_i.dot_left(Kcp1))
            except AttributeError:
                Bc[s] = Ac[s].dot(Kcp1.dot(rc_i))
            
            for t in xrange(self.q[2]): #1
                try:
                    Bc[s] += Cc[s, t].dot(rcp1.dot(rc_i.dot_left(mm.H(Acp1[t]))))
                except AttributeError:
                    Bc[s] += Cc[s, t].dot(rcp1.dot(mm.H(Acp1[t]).dot(rc_i)))                    
                
            Bcsbit = K_l_cm1.dot(Ac[s]) #4
                            
            for t in xrange(self.q[0]): #2
                Bcsbit += mm.H(Acm1[t]).dot(lcm2.dot(Ccm1[t,s]))
                
            Bc[s] += lcm1_i.dot(Bcsbit)
           
        rb = tm.eps_r_noop(rc, Bc, Bc)
        eta = sp.sqrt(mm.adot(lcm1, rb))
                
        return Bc, eta