Пример #1
0
    def restore_RCF(self, use_QR=True, update_l=True, diag_l=True):
        """Use a gauge-transformation to restore right canonical form.
        
        Implements the conditions for right canonical form from sub-section
        3.1, theorem 1 of arXiv:quant-ph/0608197v2.
        
        It is possible to skip the diagonalization of the l's, such that
        only the right orthonormalization condition (r_n = eye) is met.
        
        By default, the l's are updated even if diag_l=False.
        
        Parameters
        ----------
        update_l : bool
            Whether to call calc_l() after completion (defaults to True)
        diag_l : bool
            Whether to put l in diagonal form (defaults to True)
        """   
        if use_QR:
            tm.restore_RCF_r_seq(self.A, self.r, sanity_checks=self.sanity_checks,
                                     sc_data="restore_RCF_r")
        else:
            G_n_i = sp.eye(self.D[self.N], dtype=self.typ) #This is actually just the number 1
            for n in xrange(self.N, 0, -1):
                self.r[n - 1], G_n, G_n_i = tm.restore_RCF_r(self.A[n], self.r[n], 
                                                             G_n_i, sc_data=('site', n),
                                                             zero_tol=self.zero_tol,
                                                             sanity_checks=self.sanity_checks)

        if self.sanity_checks:
            if not sp.allclose(self.r[0].A, 1, atol=1E-12, rtol=1E-12):
                log.warning("Sanity Fail in restore_RCF!: r_0 is bad / norm failure")
        
        if diag_l:
            tm.restore_RCF_l_seq(self.A, self.l, sanity_checks=self.sanity_checks,
                                                 sc_data="restore_RCF_l")

            if self.sanity_checks:
                if not sp.allclose(self.l[self.N].A, 1, atol=1E-12, rtol=1E-12):
                    log.warning("Sanity Fail in restore_RCF!: l_N is bad / norm failure")
                    log.warning("l_N = %s", self.l[self.N].squeeze().real)
                
                for n in xrange(1, self.N + 1):
                    r_nm1 = tm.eps_r_noop(self.r[n], self.A[n], self.A[n])
                    #r_nm1 = tm.eps_r_noop(m.eyemat(self.D[n], self.typ), self.A[n], self.A[n])
                    if not sp.allclose(r_nm1, self.r[n - 1], atol=1E-11, rtol=1E-11):
                        log.warning("Sanity Fail in restore_RCF!: r_%u is bad (off by %g)", n, la.norm(r_nm1 - self.r[n - 1]))
        elif update_l:
            self.calc_l()
Пример #2
0
    def _restore_CF_ONR(self):
        nc = self.N_centre

        #Want: r[n >= nc] = eye

        #First do uni_r
        uGs, uG_is = self.uni_r.restore_RCF(
            zero_tol=self.zero_tol, diag_l=False,
            ret_g=True)  #FIXME: Don't always to all!
        Gi = uGs[-1]  #Inverse is on the other side in the uniform code.
        self.r[self.N] = self.uni_r.r[-1]

        for n in xrange(self.N, nc, -1):
            self.r[n - 1], Gm1, Gm1_i = tm.restore_RCF_r(
                self.A[n],
                self.r[n],
                Gi,
                zero_tol=self.zero_tol,
                sanity_checks=self.sanity_checks)

            Gi = Gm1_i

        self.r[self.N + 1] = self.r[self.N]

        #G is now G_nc
        for s in xrange(self.q[nc]):
            self.A[nc][s] = self.A[nc][s].dot(Gi)

        #Now want: l[n < nc] = eye
        uGs, uG_is = self.uni_l.restore_LCF(zero_tol=self.zero_tol,
                                            diag_r=False,
                                            ret_g=True)
        Gm1 = uG_is[-1]
        self.l[0] = self.uni_l.l[-1]
        lm1 = self.l[0]
        for n in xrange(1, nc):
            self.l[n], G, Gi = tm.restore_LCF_l(
                self.A[n],
                lm1,
                Gm1,
                zero_tol=self.zero_tol,
                sanity_checks=self.sanity_checks)

            lm1 = self.l[n]
            Gm1 = G

        #Gm1 is now G_nc-1
        for s in xrange(self.q[nc]):
            self.A[nc][s] = Gm1.dot(self.A[nc][s])
Пример #3
0
    def restore_RCF(self, use_QR=True, update_l=True, diag_l=True):
        """Use a gauge-transformation to restore right canonical form.
        
        Implements the conditions for right canonical form from sub-section
        3.1, theorem 1 of arXiv:quant-ph/0608197v2.
        
        It is possible to skip the diagonalization of the l's, such that
        only the right orthonormalization condition (r_n = eye) is met.
        
        By default, the l's are updated even if diag_l=False.
        
        Parameters
        ----------
        update_l : bool
            Whether to call calc_l() after completion (defaults to True)
        diag_l : bool
            Whether to put l in diagonal form (defaults to True)
        """   
        if use_QR:
            tm.restore_RCF_r_seq(self.A, self.r, sanity_checks=self.sanity_checks,
                                     sc_data="restore_RCF_r")
        else:
            G_n_i = sp.eye(self.D[self.N], dtype=self.typ) #This is actually just the number 1
            for n in xrange(self.N, 0, -1):
                self.r[n - 1], G_n, G_n_i = tm.restore_RCF_r(self.A[n], self.r[n], 
                                                             G_n_i, sc_data=('site', n),
                                                             zero_tol=self.zero_tol,
                                                             sanity_checks=self.sanity_checks)

        if self.sanity_checks:
            if not sp.allclose(self.r[0].A, 1, atol=1E-12, rtol=1E-12):
                log.warning("Sanity Fail in restore_RCF!: r_0 is bad / norm failure")
        
        if diag_l:
            tm.restore_RCF_l_seq(self.A, self.l, sanity_checks=self.sanity_checks,
                                                 sc_data="restore_RCF_l")

            if self.sanity_checks:
                if not sp.allclose(self.l[self.N].A, 1, atol=1E-12, rtol=1E-12):
                    log.warning("Sanity Fail in restore_RCF!: l_N is bad / norm failure")
                    log.warning("l_N = %s", self.l[self.N].squeeze().real)
                
                for n in xrange(1, self.N + 1):
                    r_nm1 = tm.eps_r_noop(self.r[n], self.A[n], self.A[n])
                    #r_nm1 = tm.eps_r_noop(m.eyemat(self.D[n], self.typ), self.A[n], self.A[n])
                    if not sp.allclose(r_nm1, self.r[n - 1], atol=1E-11, rtol=1E-11):
                        log.warning("Sanity Fail in restore_RCF!: r_%u is bad (off by %g)", n, la.norm(r_nm1 - self.r[n - 1]))
        elif update_l:
            self.calc_l()
Пример #4
0
    def _restore_CF_ONR(self):
        nc = self.N_centre

        #Want: r[n >= nc] = eye

        #First do uni_r
        uGs, uG_is = self.uni_r.restore_RCF(zero_tol=self.zero_tol, diag_l=False, ret_g=True) #FIXME: Don't always to all!
        Gi = uGs[-1] #Inverse is on the other side in the uniform code.
        self.r[self.N] = self.uni_r.r[-1]
        
        for n in xrange(self.N, nc, -1):
            self.r[n - 1], Gm1, Gm1_i = tm.restore_RCF_r(self.A[n], self.r[n],
                                             Gi, zero_tol=self.zero_tol,
                                             sanity_checks=self.sanity_checks)

            Gi = Gm1_i

        self.r[self.N + 1] = self.r[self.N]

        #G is now G_nc
        for s in xrange(self.q[nc]):
            self.A[nc][s] = self.A[nc][s].dot(Gi)

        #Now want: l[n < nc] = eye
        uGs, uG_is = self.uni_l.restore_LCF(zero_tol=self.zero_tol, diag_r=False, ret_g=True)
        Gm1 = uG_is[-1]
        self.l[0] = self.uni_l.l[-1]
        lm1 = self.l[0]
        for n in xrange(1, nc):
            self.l[n], G, Gi = tm.restore_LCF_l(self.A[n], lm1, Gm1,
                                                zero_tol=self.zero_tol,
                                                sanity_checks=self.sanity_checks)

            lm1 = self.l[n]
            Gm1 = G

        #Gm1 is now G_nc-1
        for s in xrange(self.q[nc]):
            self.A[nc][s] = Gm1.dot(self.A[nc][s])
Пример #5
0
    def _restore_CF_ONR(self):
        nc = self.N_centre

        #Want: r[n >= nc] = eye
        Gi = None
        for n in xrange(self.N + 1, nc, -1):
            self.r[n - 1], Gm1, Gm1_i = tm.restore_RCF_r(self.A[n], self.r[n],
                                             Gi, zero_tol=self.zero_tol,
                                             sanity_checks=self.sanity_checks)

            if n == self.N + 1:
                self.uni_r.l = Gm1_i.conj().T.dot(self.uni_r.l.dot(Gm1_i))

            Gi = Gm1_i

        self.r[self.N + 1] = self.r[self.N]

        #G is now G_nc
        for s in xrange(self.q[nc]):
            self.A[nc][s] = self.A[nc][s].dot(Gi)

        #Now want: l[n < nc] = eye
        Gm1 = None
        lm1 = self.l[0]
        for n in xrange(nc):
            self.l[n], G, Gi = tm.restore_LCF_l(self.A[n], lm1, Gm1,
                                                zero_tol=self.zero_tol,
                                                sanity_checks=self.sanity_checks)

            if n == 0:
                self.uni_l.r = G.dot(self.uni_l.r.dot(G.conj().T))

            lm1 = self.l[n]
            Gm1 = G

        #Gm1 is now G_nc-1
        for s in xrange(self.q[nc]):
            self.A[nc][s] = Gm1.dot(self.A[nc][s])
Пример #6
0
    def restore_RCF(self, update_l=True, normalize=True, diag_l=True):
        """Use a gauge-transformation to restore right canonical form.
        
        Implements the conditions for right canonical form from sub-section
        3.1, theorem 1 of arXiv:quant-ph/0608197v2.
        
        This performs two 'almost' gauge transformations, where the 'almost'
        means we allow the norm to vary (if "normalize" = True).
        
        The last step (A[1]) is done diffently to the others since G[0],
        the gauge-transf. matrix, is just a number, which can be found more
        efficiently and accurately without using matrix methods.
        
        The last step (A[1]) is important because, if we have successfully made 
        r[1] = 1 in the previous steps, it fully determines the normalization 
        of the state via r[0] ( = l[N]).
        
        Optionally (normalize=False), the function will not attempt to make
        A[1] satisfy the orthonorm. condition, and will take G[0] = 1 = G[N],
        thus performing a pure gauge-transformation, but not ensuring complete
        canonical form.
        
        It is also possible to begin the process from a site n other than N,
        in case the sites > n are known to be in the desired form already.
        
        It is also possible to skip the diagonalization of the l's, such that
        only the right orthonormalization condition (r_n = eye) is met.
        
        By default, the l's are updated even if diag_l=False.
        
        Parameters
        ----------
        update_l : bool
            Whether to call calc_l() after completion (defaults to True)
        normalize : bool
            Whether to also attempt to normalize the state.
        diag_l : bool
            Whether to put l in diagonal form (defaults to True)
        """   
        start = self.N
        
        G_n_i = sp.eye(self.D[start], dtype=self.typ) #This is actually just the number 1
        for n in xrange(start, 1, -1):
            self.r[n - 1], G_n, G_n_i = tm.restore_RCF_r(self.A[n], self.r[n], 
                                                         G_n_i, sc_data=('site', n),
                                                         zero_tol=self.zero_tol,
                                                         sanity_checks=self.sanity_checks)
        
        #Now do A[1]...
        #Apply the remaining G[1]^-1 from the previous step.
        for s in xrange(self.q[1]):                
            self.A[1][s] = m.mmul(self.A[1][s], G_n_i)
                    
        #Now finish off
        tm.eps_r_noop_inplace(self.r[1], self.A[1], self.A[1], out=self.r[0])
        
        if normalize:
            G0 = 1. / sp.sqrt(self.r[0].squeeze().real)
            self.A[1] *= G0
            self.r[0][:] = 1
            
            if self.sanity_checks:
                r0 = tm.eps_r_noop(self.r[1], self.A[1], self.A[1])
                if not sp.allclose(r0, 1, atol=1E-12, rtol=1E-12):
                    log.warning("Sanity Fail in restore_RCF!: r_0 is bad / norm failure")

        if diag_l:
            G_nm1 = sp.eye(self.D[0], dtype=self.typ)
            for n in xrange(1, self.N):
                self.l[n], G_nm1, G_nm1_i = tm.restore_RCF_l(self.A[n],
                                                             self.l[n - 1],
                                                             G_nm1,
                                                             self.sanity_checks)

            #Apply remaining G_Nm1 to A[N]
            n = self.N
            for s in xrange(self.q[n]):
                self.A[n][s] = m.mmul(G_nm1, self.A[n][s])

            #Deal with final, scalar l[N]
            tm.eps_l_noop_inplace(self.l[n - 1], self.A[n], self.A[n], out=self.l[n])

            if self.sanity_checks:
                if not sp.allclose(self.l[self.N].real, 1, atol=1E-12, rtol=1E-12):
                    log.warning("Sanity Fail in restore_RCF!: l_N is bad / norm failure")
                    log.warning("l_N = %s", self.l[self.N].squeeze().real)
                
                for n in xrange(1, self.N + 1):
                    r_nm1 = tm.eps_r_noop(self.r[n], self.A[n], self.A[n])
                    #r_nm1 = tm.eps_r_noop(m.eyemat(self.D[n], self.typ), self.A[n], self.A[n])
                    if not sp.allclose(r_nm1, self.r[n - 1], atol=1E-11, rtol=1E-11):
                        log.warning("Sanity Fail in restore_RCF!: r_%u is bad (off by %g)", n, la.norm(r_nm1 - self.r[n - 1]))
        elif update_l:
            self.calc_l()
Пример #7
0
    def restore_RCF(self, update_l=True, normalize=True, diag_l=True):
        """Use a gauge-transformation to restore right canonical form.
        
        Implements the conditions for right canonical form from sub-section
        3.1, theorem 1 of arXiv:quant-ph/0608197v2.
        
        This performs two 'almost' gauge transformations, where the 'almost'
        means we allow the norm to vary (if "normalize" = True).
        
        The last step (A[1]) is done diffently to the others since G[0],
        the gauge-transf. matrix, is just a number, which can be found more
        efficiently and accurately without using matrix methods.
        
        The last step (A[1]) is important because, if we have successfully made 
        r[1] = 1 in the previous steps, it fully determines the normalization 
        of the state via r[0] ( = l[N]).
        
        Optionally (normalize=False), the function will not attempt to make
        A[1] satisfy the orthonorm. condition, and will take G[0] = 1 = G[N],
        thus performing a pure gauge-transformation, but not ensuring complete
        canonical form.
        
        It is also possible to begin the process from a site n other than N,
        in case the sites > n are known to be in the desired form already.
        
        It is also possible to skip the diagonalization of the l's, such that
        only the right orthonormalization condition (r_n = eye) is met.
        
        By default, the l's are updated even if diag_l=False.
        
        Parameters
        ----------
        update_l : bool
            Whether to call calc_l() after completion (defaults to True)
        normalize : bool
            Whether to also attempt to normalize the state.
        diag_l : bool
            Whether to put l in diagonal form (defaults to True)
        """
        start = self.N

        G_n_i = sp.eye(self.D[start],
                       dtype=self.typ)  #This is actually just the number 1
        for n in xrange(start, 1, -1):
            self.r[n - 1], G_n, G_n_i = tm.restore_RCF_r(
                self.A[n],
                self.r[n],
                G_n_i,
                sc_data=('site', n),
                zero_tol=self.zero_tol,
                sanity_checks=self.sanity_checks)

        #Now do A[1]...
        #Apply the remaining G[1]^-1 from the previous step.
        for s in xrange(self.q[1]):
            self.A[1][s] = m.mmul(self.A[1][s], G_n_i)

        #Now finish off
        tm.eps_r_noop_inplace(self.r[1], self.A[1], self.A[1], out=self.r[0])

        if normalize:
            G0 = 1. / sp.sqrt(self.r[0].squeeze().real)
            self.A[1] *= G0
            self.r[0][:] = 1

            if self.sanity_checks:
                r0 = tm.eps_r_noop(self.r[1], self.A[1], self.A[1])
                if not sp.allclose(r0, 1, atol=1E-12, rtol=1E-12):
                    log.warning(
                        "Sanity Fail in restore_RCF!: r_0 is bad / norm failure"
                    )

        if diag_l:
            G_nm1 = sp.eye(self.D[0], dtype=self.typ)
            for n in xrange(1, self.N):
                self.l[n], G_nm1, G_nm1_i = tm.restore_RCF_l(
                    self.A[n], self.l[n - 1], G_nm1, self.sanity_checks)

            #Apply remaining G_Nm1 to A[N]
            n = self.N
            for s in xrange(self.q[n]):
                self.A[n][s] = m.mmul(G_nm1, self.A[n][s])

            #Deal with final, scalar l[N]
            tm.eps_l_noop_inplace(self.l[n - 1],
                                  self.A[n],
                                  self.A[n],
                                  out=self.l[n])

            if self.sanity_checks:
                if not sp.allclose(
                        self.l[self.N].real, 1, atol=1E-12, rtol=1E-12):
                    log.warning(
                        "Sanity Fail in restore_RCF!: l_N is bad / norm failure"
                    )
                    log.warning("l_N = %s", self.l[self.N].squeeze().real)

                for n in xrange(1, self.N + 1):
                    r_nm1 = tm.eps_r_noop(self.r[n], self.A[n], self.A[n])
                    #r_nm1 = tm.eps_r_noop(m.eyemat(self.D[n], self.typ), self.A[n], self.A[n])
                    if not sp.allclose(
                            r_nm1, self.r[n - 1], atol=1E-11, rtol=1E-11):
                        log.warning(
                            "Sanity Fail in restore_RCF!: r_%u is bad (off by %g)",
                            n, la.norm(r_nm1 - self.r[n - 1]))
        elif update_l:
            self.calc_l()