def calc_x_tp(Kp1, C_tp, Cm1_tp, rp1, lm2, Am1, A, Ap1, lm1_s, lm1_si, r_s, r_si, Vsh): D = A.shape[2] Dm1 = A.shape[1] q = A.shape[0] x = np.zeros((Dm1, q * D - Dm1), dtype=A.dtype) V = sp.transpose(Vsh, axes=(0, 2, 1)).conj().copy() Vri = V.copy() try: for Vris in Vri: Vris[:] = r_si.dot_left(Vris) except AttributeError: for Vris in Vri: Vris[:] = Vris.dot(r_si) if not C_tp is None: x += lm1_s.dot(eps_r_op_2s_C12_tp(rp1, C_tp, Vri, Ap1)) #1 if not Cm1_tp is None: for al in xrange(len(Cm1_tp)): x += lm1_si.dot(eps_l_noop(lm2, Am1, Cm1_tp[al][0]).dot(eps_r_noop(r_s, Cm1_tp[al][1], V))) #2 if not Kp1 is None: x += lm1_s.dot(eps_r_noop(Kp1, A, Vri)) return x
def restore_LCF_r(A, r, Gi, sanity_checks=False): if Gi is None: x = r else: x = Gi.dot(r.dot(Gi.conj().T)) M = eps_r_noop(x, A, A) ev, EV = la.eigh(M) #wraps lapack routines, which return eigenvalues in ascending order if sanity_checks: assert np.all(ev == np.sort(ev)), "unexpected eigenvalue ordering" rm1 = mm.simple_diag_matrix(ev, dtype=A.dtype) Gm1 = EV.conj().T if Gi is None: Gi = EV #for left uniform case r = rm1 #for sanity check for s in xrange(A.shape[0]): A[s] = Gm1.dot(A[s].dot(Gi)) if sanity_checks: rm1_ = eps_r_noop(r, A, A) if not sp.allclose(rm1_, rm1, atol=1E-12, rtol=1E-12): log.warning("Sanity Fail in restore_LCF_r!: r is bad!") log.warning(la.norm(rm1_ - rm1)) Gm1_i = EV return rm1, Gm1, Gm1_i
def calc_Vsh(A, r_s, sanity_checks=False): D = A.shape[2] Dm1 = A.shape[1] q = A.shape[0] if q * D - Dm1 <= 0: return None R = sp.zeros((D, q, Dm1), dtype=A.dtype, order='C') for s in xrange(q): R[:,s,:] = r_s.dot(A[s].conj().T) R = R.reshape((q * D, Dm1)) Vconj = ns.nullspace_qr(R.conj().T).T if sanity_checks: if not sp.allclose(mm.mmul(Vconj.conj(), R), 0): log.warning("Sanity Fail in calc_Vsh!: VR != 0") if not sp.allclose(mm.mmul(Vconj, Vconj.conj().T), sp.eye(Vconj.shape[0])): log.warning("Sanity Fail in calc_Vsh!: V H(V) != eye") Vconj = Vconj.reshape((q * D - Dm1, D, q)) Vsh = Vconj.T Vsh = sp.asarray(Vsh, order='C') if sanity_checks: Vs = sp.transpose(Vsh, axes=(0, 2, 1)).conj() M = eps_r_noop(r_s, Vs, A) if not sp.allclose(M, 0): log.warning("Sanity Fail in calc_Vsh!: Bad Vsh") return Vsh
def calc_Vsh(A, r_s, sanity_checks=False): D = A.shape[2] Dm1 = A.shape[1] q = A.shape[0] if q * D - Dm1 <= 0: return None R = sp.zeros((D, q, Dm1), dtype=A.dtype, order='C') for s in range(q): R[:, s, :] = r_s.dot(A[s].conj().T) R = R.reshape((q * D, Dm1)) Vconj = ns.nullspace_qr(R.conj().T).T if sanity_checks: if not sp.allclose(mm.mmul(Vconj.conj(), R), 0): log.warning("Sanity Fail in calc_Vsh!: VR != 0") if not sp.allclose(mm.mmul(Vconj, Vconj.conj().T), sp.eye(Vconj.shape[0])): log.warning("Sanity Fail in calc_Vsh!: V H(V) != eye") Vconj = Vconj.reshape((q * D - Dm1, D, q)) Vsh = Vconj.T Vsh = sp.asarray(Vsh, order='C') if sanity_checks: Vs = sp.transpose(Vsh, axes=(0, 2, 1)).conj() M = eps_r_noop(r_s, Vs, A) if not sp.allclose(M, 0): log.warning("Sanity Fail in calc_Vsh!: Bad Vsh") return Vsh
def calc_K_3s(Kp1, C, lm1, rp2, A, AAp1Ap2): K = eps_r_noop(Kp1, A, A) Hr = eps_r_op_3s_C123_AAA456(rp2, C, AAp1Ap2) op_expect = mm.adot(lm1, Hr) K += Hr return K, op_expect
def calc_K(Kp1, C, lm1, rp1, A, AAp1): K = eps_r_noop(Kp1, A, A) Hr = eps_r_op_2s_C12_AA34(rp1, C, AAp1) op_expect = mm.adot(lm1, Hr) K += Hr return K, op_expect
def calc_K_tp(Kp1, lm1, rp1, A, Ap1, C_tp): K = eps_r_noop(Kp1, A, A) Hr = eps_r_op_2s_C12_tp(rp1, C_tp, A, Ap1) op_expect = mm.adot(lm1, Hr) K += Hr return K, op_expect
def calc_BB_Y_2s(C, Vlh, Vrh_p1, l_s_m1, r_s_p1): Vr_p1 = sp.transpose(Vrh_p1, axes=(0, 2, 1)).conj() Y = sp.zeros((Vlh.shape[1], Vrh_p1.shape[2]), dtype=C.dtype) for s in xrange(Vlh.shape[0]): Y += Vlh[s].dot(l_s_m1.dot(eps_r_noop(r_s_p1, C[s], Vr_p1))) etaBB_sq = mm.adot(Y, Y) return Y, etaBB_sq
def calc_BB_Y_2s_tp(C_tp, Vlh, Vrh_p1, l_s_m1, r_s_p1): Vl = sp.transpose(Vlh, axes=(0, 2, 1)).conj().copy() Vr_p1 = sp.transpose(Vrh_p1, axes=(0, 2, 1)).conj().copy() Y = 0 for al in range(len(C_tp)): Y += eps_l_noop(l_s_m1, Vl, C_tp[al][0]).dot(eps_r_noop(r_s_p1, C_tp[al][1], Vr_p1)) etaBB_sq = mm.adot(Y, Y) return Y, etaBB_sq
def calc_BB_Y_2s_tp(C_tp, Vlh, Vrh_p1, l_s_m1, r_s_p1): Vl = sp.transpose(Vlh, axes=(0, 2, 1)).conj().copy() Vr_p1 = sp.transpose(Vrh_p1, axes=(0, 2, 1)).conj().copy() Y = 0 for al in xrange(len(C_tp)): Y += eps_l_noop(l_s_m1, Vl, C_tp[al][0]).dot(eps_r_noop(r_s_p1, C_tp[al][1], Vr_p1)) etaBB_sq = mm.adot(Y, Y) return Y, etaBB_sq
def restore_RCF_r_seq(A, r, GN=None, sanity_checks=False, sc_data=''): """Transforms a sequence of A[n]'s to obtain r[n - 1] = eye(D). Implements the condition for right-orthonormalization from sub-section 3.1, theorem 1 of arXiv:quant-ph/0608197v2. Uses a reduced QR decomposition to avoid inverting anything explicity. Parameters ---------- A : sequence of ndarray The parameter tensors for a sequence of sites [None, A1, A2,..., AN]. The first entry is ignored so that the indices match up with r. r : sequence of ndarray or objects with array interface The matrices [r0, r1, r2,..., rN], where rN will not be changed, but is used for sanity checks. GN : ndarray or scalar Initial right gauge transformation matrix for site N. Only needed when used as part of a larger transformation. sanity_checks : bool (False) Whether to perform additional sanity checks. sc_data : string A string to be appended to sanity check log messages. """ assert len(A) == len(r), 'A and r must have the same length!' if GN is None: Gh = mm.eyemat(A[-1].shape[2], dtype=A[-1].dtype) else: Gh = GN.conj().T for n in xrange(len(A) - 1, 0, -1): q, Dm1, D = A[n].shape AG = sp.array([Gh.dot(As.conj().T) for As in A[n]]).reshape( (q * D, Dm1)) Q, R = la.qr(AG, mode='economic') A[n] = sp.transpose(Q.conj().reshape((q, D, Dm1)), axes=(0, 2, 1)) Gh = R r[n - 1] = mm.eyemat(Dm1, dtype=A[n].dtype) if sanity_checks: r_nm1_ = eps_r_noop(r[n], A[n], A[n]) if not sp.allclose(r_nm1_, r[n - 1].A, atol=1E-13, rtol=1E-13): log.warning("Sanity Fail in restore_RCF_r!: r is bad! %s %s", la.norm(r_nm1_ - r[n - 1]), sc_data) return Gh.conj().T
def restore_RCF_r_seq(A, r, GN=None, sanity_checks=False, sc_data=''): """Transforms a sequence of A[n]'s to obtain r[n - 1] = eye(D). Implements the condition for right-orthonormalization from sub-section 3.1, theorem 1 of arXiv:quant-ph/0608197v2. Uses a reduced QR decomposition to avoid inverting anything explicity. Parameters ---------- A : sequence of ndarray The parameter tensors for a sequence of sites [None, A1, A2,..., AN]. The first entry is ignored so that the indices match up with r. r : sequence of ndarray or objects with array interface The matrices [r0, r1, r2,..., rN], where rN will not be changed, but is used for sanity checks. GN : ndarray or scalar Initial right gauge transformation matrix for site N. Only needed when used as part of a larger transformation. sanity_checks : bool (False) Whether to perform additional sanity checks. sc_data : string A string to be appended to sanity check log messages. """ assert len(A) == len(r), 'A and r must have the same length!' if GN is None: Gh = mm.eyemat(A[-1].shape[2], dtype=A[-1].dtype) else: Gh = GN.conj().T for n in xrange(len(A) - 1, 0, -1): q, Dm1, D = A[n].shape AG = sp.array([Gh.dot(As.conj().T) for As in A[n]]).reshape((q * D, Dm1)) Q, R = la.qr(AG, mode='economic') A[n] = sp.transpose(Q.conj().reshape((q, D, Dm1)), axes=(0, 2, 1)) Gh = R r[n - 1] = mm.eyemat(Dm1, dtype=A[n].dtype) if sanity_checks: r_nm1_ = eps_r_noop(r[n], A[n], A[n]) if not sp.allclose(r_nm1_, r[n - 1].A, atol=1E-13, rtol=1E-13): log.warning("Sanity Fail in restore_RCF_r!: r is bad! %s %s", la.norm(r_nm1_ - r[n - 1]), sc_data) return Gh.conj().T
def eps_r_op_3s_C123_AAA456(x, C123, AAA456): d = C123.shape[0] * C123.shape[1] * C123.shape[2] S1 = (d, C123.shape[3], C123.shape[4]) S2 = (d, AAA456.shape[3], AAA456.shape[4]) return eps_r_noop(x, C123.reshape(S1), AAA456.reshape(S2))
def eps_r_op_2s_AA12_C34(x, AA12, C34): d = C34.shape[0] * C34.shape[1] S1 = (d, AA12.shape[2], AA12.shape[3]) S2 = (d, C34.shape[2], C34.shape[3]) return eps_r_noop(x, AA12.reshape(S1), C34.reshape(S2))
def eps_r_op_2s_C12_tp(x, C12_tp, A1, A2): res = 0 for al in xrange(len(C12_tp)): res += eps_r_noop(eps_r_noop(x, C12_tp[al][1], A2), C12_tp[al][0], A1) return res
def restore_RCF_r(A, r, G_n_i, zero_tol=1E-15, sanity_checks=False, sc_data=''): """Transforms a single A[n] to obtain r[n - 1] = eye(D). Implements the condition for right-orthonormalization from sub-section 3.1, theorem 1 of arXiv:quant-ph/0608197v2. This function must be called for each n in turn, starting at N + 1, passing the gauge transformation matrix from the previous step as an argument. Finds a G[n-1] such that orthonormalization is fulfilled for n. If rank-deficiency is encountered, the result fulfills the orthonormality condition in the occupied subspace with the zeros at the top-left (for example r = diag([0, 0, 1, 1, 1, 1, 1])). Parameters ---------- A : ndarray The parameter tensor for the nth site A[n]. r : ndarray or object with array interface The matrix r[n]. G_n_i : ndarray The inverse gauge transform matrix for site n obtained in the previous step (for n + 1). sanity_checks : bool (False) Whether to perform additional sanity checks. zero_tol : float Tolerance for detecting zeros. Returns ------- r_nm1 : ndarray or simple_diag_matrix or eyemat The new matrix r[n - 1]. G_nm1 : ndarray The gauge transformation matrix for the site n - 1. G_n_m1_i : ndarray The inverse gauge transformation matrix for the site n - 1. """ if G_n_i is None: GGh_n_i = r else: GGh_n_i = G_n_i.dot(r.dot(G_n_i.conj().T)) M = eps_r_noop(GGh_n_i, A, A) X, Xi, new_D = herm_fac_with_inv(M, zero_tol=zero_tol, return_rank=True, sanity_checks=sanity_checks) G_nm1 = Xi.conj().T G_nm1_i = X.conj().T if G_n_i is None: G_n_i = G_nm1_i if sanity_checks: #GiG may not be equal to eye in the case of rank-deficiency, #but the rest should lie in the null space of A. GiG = G_nm1_i.dot(G_nm1) As = np.sum(A, axis=0) if not sp.allclose(GiG.dot(As).dot(G_n_i), As.dot(G_n_i), atol=1E-13, rtol=1E-13): log.warning("Sanity Fail in restore_RCF_r!: Bad GT! %s %s", la.norm(GiG.dot(As).dot(G_n_i) - As.dot(G_n_i)), sc_data) for s in xrange(A.shape[0]): A[s] = G_nm1.dot(A[s]).dot(G_n_i) if new_D == A.shape[1]: r_nm1 = mm.eyemat(A.shape[1], A.dtype) else: r_nm1 = sp.zeros((A.shape[1]), dtype=A.dtype) r_nm1[-new_D:] = 1 r_nm1 = mm.simple_diag_matrix(r_nm1, dtype=A.dtype) if sanity_checks: r_nm1_ = G_nm1.dot(M).dot(G_nm1.conj().T) if not sp.allclose(r_nm1_, r_nm1.A, atol=1E-13, rtol=1E-13): log.warning("Sanity Fail in restore_RCF_r!: r != g old_r gH! %s %s", la.norm(r_nm1_ - r_nm1), sc_data) r_nm1_ = eps_r_noop(r, A, A) if not sp.allclose(r_nm1_, r_nm1.A, atol=1E-13, rtol=1E-13): log.warning("Sanity Fail in restore_RCF_r!: r is bad! %s %s", la.norm(r_nm1_ - r_nm1), sc_data) return r_nm1, G_nm1, G_nm1_i
def restore_RCF_r(A, r, G_n_i, zero_tol=1E-15, sanity_checks=False, sc_data=''): """Transforms a single A[n] to obtain r[n - 1] = eye(D). Implements the condition for right-orthonormalization from sub-section 3.1, theorem 1 of arXiv:quant-ph/0608197v2. This function must be called for each n in turn, starting at N + 1, passing the gauge transformation matrix from the previous step as an argument. Finds a G[n-1] such that orthonormalization is fulfilled for n. If rank-deficiency is encountered, the result fulfills the orthonormality condition in the occupied subspace with the zeros at the top-left (for example r = diag([0, 0, 1, 1, 1, 1, 1])). Parameters ---------- A : ndarray The parameter tensor for the nth site A[n]. r : ndarray or object with array interface The matrix r[n]. G_n_i : ndarray The inverse gauge transform matrix for site n obtained in the previous step (for n + 1). sanity_checks : bool (False) Whether to perform additional sanity checks. zero_tol : float Tolerance for detecting zeros. Returns ------- r_nm1 : ndarray or simple_diag_matrix or eyemat The new matrix r[n - 1]. G_nm1 : ndarray The gauge transformation matrix for the site n - 1. G_n_m1_i : ndarray The inverse gauge transformation matrix for the site n - 1. """ if G_n_i is None: GGh_n_i = r else: GGh_n_i = G_n_i.dot(r.dot(G_n_i.conj().T)) M = eps_r_noop(GGh_n_i, A, A) X, Xi, new_D = herm_fac_with_inv(M, zero_tol=zero_tol, return_rank=True, sanity_checks=sanity_checks) G_nm1 = Xi.conj().T G_nm1_i = X.conj().T if G_n_i is None: G_n_i = G_nm1_i if sanity_checks: #GiG may not be equal to eye in the case of rank-deficiency, #but the rest should lie in the null space of A. GiG = G_nm1_i.dot(G_nm1) As = np.sum(A, axis=0) if not sp.allclose( GiG.dot(As).dot(G_n_i), As.dot(G_n_i), atol=1E-13, rtol=1E-13): log.warning("Sanity Fail in restore_RCF_r!: Bad GT! %s %s", la.norm(GiG.dot(As).dot(G_n_i) - As.dot(G_n_i)), sc_data) for s in xrange(A.shape[0]): A[s] = G_nm1.dot(A[s]).dot(G_n_i) if new_D == A.shape[1]: r_nm1 = mm.eyemat(A.shape[1], A.dtype) else: r_nm1 = sp.zeros((A.shape[1]), dtype=A.dtype) r_nm1[-new_D:] = 1 r_nm1 = mm.simple_diag_matrix(r_nm1, dtype=A.dtype) if sanity_checks: r_nm1_ = G_nm1.dot(M).dot(G_nm1.conj().T) if not sp.allclose(r_nm1_, r_nm1.A, atol=1E-13, rtol=1E-13): log.warning( "Sanity Fail in restore_RCF_r!: r != g old_r gH! %s %s", la.norm(r_nm1_ - r_nm1), sc_data) r_nm1_ = eps_r_noop(r, A, A) if not sp.allclose(r_nm1_, r_nm1.A, atol=1E-13, rtol=1E-13): log.warning("Sanity Fail in restore_RCF_r!: r is bad! %s %s", la.norm(r_nm1_ - r_nm1), sc_data) return r_nm1, G_nm1, G_nm1_i