예제 #1
0
def vumps_loss(A_L, A_C):
    """
    Norm of MPS gradient: see Appendix 4.
    """
    A_L_mat = ct.fuse_left(A_L)
    A_L_dag = np.conj(A_L_mat.T)
    N_L = sp.linalg.null_space(A_L_dag)
    N_L_dag = np.conj(N_L.T)
    A_C_mat = ct.fuse_left(A_C)
    B = np.dot(N_L_dag, A_C_mat)
    Bnorm = np.linalg.norm(B)
    return Bnorm
예제 #2
0
def gauge_match_SVD(A_C, C, thresh=1E-13):
    """
    Return approximately gauge-matched A_L and A_R from A_C and C
    using an SVD. If 
    """
    Ashape = A_C.shape
    Cdag = np.conj(C.T)

    AC_mat_l = ct.fuse_left(A_C)  #A_C.reshape(d*chi, chi)
    ACl_Cd = np.dot(AC_mat_l, Cdag)
    Ul, Sl, Vld = np.linalg.svd(ACl_Cd, full_matrices=False)
    AL_mat = np.dot(Ul, Vld)
    A_L = ct.unfuse_left(AL_mat, Ashape)

    AC_mat_r = ct.fuse_right(A_C)
    d, chi, chi = Ashape
    AC_mat_r = A_C.reshape(chi, d * chi)
    Cd_ACr = np.dot(Cdag, AC_mat_r)
    Ur, Sr, Vrd = np.linalg.svd(Cd_ACr, full_matrices=False)
    AR_mat = np.dot(Ur, Vrd)
    A_R = ct.unfuse_right(AR_mat, Ashape)

    smallest = min(min(Sl), min(Sr))
    SVD_ok = smallest > thresh
    if not SVD_ok:
        print("Singular values fell beneath threshold.")
    return (A_L, A_R, SVD_ok)
예제 #3
0
def compute_eR(A_R, C, A_C):
    """
    Approximate right loss function
    eR = ||A_C - C . A_R||
    """
    eRmid = A_C - ct.leftmult(C, A_R)
    eR = np.linalg.norm(ct.fuse_left(eRmid))
    return eR
예제 #4
0
def compute_eL(A_L, C, A_C):
    """
    Approximate left loss function
    eL = ||A_C - A_L . C||.
    """
    eLmid = A_C - ct.rightmult(A_L, C)
    eL = np.linalg.norm(ct.fuse_left(eLmid))
    return eL
예제 #5
0
def qrpos(A):
    """
    QR decomp. of A, with phase convention such that R has only positive
    elements on the main diagonal. 

    If A is an MPS tensor (d, chiL, chiR), it is reshaped appropriately
    before the throughput begins. In that case, Q will be a tensor
    of the same size, while R will be a chiR x chiR matrix.
    """
    Ashp = A.shape
    if len(Ashp) == 2:
        return qrmat(A)
    elif len(Ashp) != 3:
        print("A had invalid dimensions, ", A.shape)

    A = ct.fuse_left(A)  #d*chiL, chiR
    Q, R = qrmat(A, mode="economic")
    Q = ct.unfuse_left(Q, Ashp)
    return (Q, R)
예제 #6
0
def gauge_match_polar(A_C, C):
    """
    Return approximately gauge-matched A_L and A_R from A_C and C
    using a polar decomposition.
    """
    Ashape = A_C.shape
    AC_mat_l = ct.fuse_left(A_C)
    AC_mat_r = ct.fuse_right(A_C)

    UAc_l, PAc_l = sp.linalg.polar(AC_mat_l, side="right")
    UAc_r, PAc_r = sp.linalg.polar(AC_mat_r, side="left")
    UC_l, PC_l = sp.linalg.polar(C, side="right")
    UC_r, PC_r = sp.linalg.polar(C, side="left")

    A_L = np.dot(UAc_l, np.conj(UC_l.T))
    A_L = ct.unfuse_left(A_L, Ashape)
    A_R = np.dot(np.conj(UC_r.T), UAc_r)
    A_R = ct.unfuse_right(A_R, Ashape)
    return (A_L, A_R)
예제 #7
0
def null_spaces(mpslist):
    """
    Return matrices spanning the null spaces of A_L and A_R, and
    the hermitian conjugates of these, reshaped into rank
    3 tensors.
    """
    AL, C, AR = mpslist
    d, chi, _ = AL.shape
    NLshp = (d, chi, (d-1)*chi)
    ALdag = ct.fuse_left(AL).T.conj()
    NLm = sp.linalg.null_space(ALdag)
    NL = NLm.reshape(NLshp)

    ARmat = ct.fuse_right(AR)
    NRm_dag = sp.linalg.null_space(ARmat)
    NRm = np.conj(NRm_dag)
    NR = NRm.reshape((d, chi, (d-1)*chi))
    NR = NR.transpose((0, 2, 1))
    return (NL, NR)