Example #1
0
def maximize_overlap(thatmpslist, chi, thatAC=None, tol=1E-13):
    """
    Generate MPS tensors AL, C, AR of bond dimension chi, such
    that the overlap with the tensors in thatmpslist is maximized
    up to tolerance tol.
    """
    thatmpslist, thosefpoints = regauge(thatmpslist, tol=tol)
    thatAL, thatC, thatAR = thatmpslist
    print(np.diag(thatC))
    if thatAC is None:
        thatAC = ct.rightmult(thatAL, thatC)
    d, _, _ = thatAL.shape
    #IF CHANGING TO FLOAT LOOK HERE
    AL = utils.random_complex((d, chi, chi))
    AR = utils.random_complex((d, chi, chi))
    C = utils.random_complex((chi, chi))
    lam, L = tmeigs(thatAL,
                    B=np.conj(AL),
                    tol=0.01,
                    which="LM",
                    direction="left")
    _, R = tmeigs(thatAR,
                  B=np.conj(AR),
                  tol=0.01,
                  which="LM",
                  direction="right")
    AC = ct.gauge_transform(L, thatAC, R.T)
    C = ct.gauge_transform(L, thatC, R.T)
    AL, AR = gauge_match_polar(AC, C)
    delta = np.linalg.norm((ct.rightmult(AL, C) - AC / lam).flatten())
    while delta >= tol:
        print(delta)
        lam, L = tmeigs(thatAL,
                        B=np.conj(AL),
                        tol=delta / 10,
                        which="LM",
                        direction="left")
        _, R = tmeigs(thatAR,
                      B=np.conj(AR),
                      tol=delta / 10,
                      which="LM",
                      direction="right")
        AC = ct.gauge_transform(L, thatAC, R.T)
        C = ct.gauge_transform(L, thatC, R.T)
        print(np.diag(C))
        AL, AR = gauge_match_polar(AC, C)
        delta = np.linalg.norm((ct.rightmult(AL, C) - AC / lam).flatten())
    thismpslist = [AL, C, AR]
    return thismpslist
Example #2
0
def B2_tensor(oldlist, newlist):
    NL, NR = null_spaces(oldlist)
    AL, C, AR = newlist
    AC = ct.rightmult(AL, C)
    L = ct.XopL(AC, B=np.conj(NL))
    R = ct.XopR(AR, B=np.conj(NR))
    return np.dot(L, R.T)
Example #3
0
def testHAc(chi, d=2):
    """
    Tests that the sparse and dense apply_HAc give the same answer on random
    input.
    """
    h = utils.random_complex((d, d, d, d))
    A = utils.random_complex((d, chi, chi))
    mpslist = vumps.mixed_canonical(A)
    A_L, C, A_R = mpslist
    A_C = ct.rightmult(A_L, C)

    hL = utils.random_complex((chi, chi))
    hR = utils.random_complex((chi, chi))
    hlist = [h, hL, hR]
    Acp_sparse = vumps.apply_HAc(A_C, A_L, A_R, hlist)
    #print("Sparse: ", Acp_sparse)
    Acp_dense = vumps.apply_HAc_dense(A_C, A_L, A_R, hlist)
    # print("Dense: ", Acp_dense)
    # print("*")
    norm = np.linalg.norm(Acp_sparse - Acp_dense) / chi**2
    print("Test HAc.")
    print("Norm resid: ", norm)
    if norm < 1E-13:
        print("Passed!")
    else:
        print("Failed!")
Example #4
0
def onesiteexpect(A_R, C, O, real=True, L=None, R=None):
    A_C = ct.rightmult(A_R, C)
    E = ct.chainwithops([A_C], ops=[(O, 0)], lvec=L, rvec=R)
    if real:
        if np.abs(E.imag) > 1E-14:
            print("Warning: EV had large imaginary part ", str(E.imag))
        E = E.real
    return E
Example #5
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
Example #6
0
def vumps_expand(thatmpslist, H, chi, delta, params, thatAC=None):
    mpslist = maximize_overlap(thatmpslist, chi, thatAC=thatAC, tol=delta / 10)
    A_C = ct.rightmult(mpslist[0], mpslist[1])
    TMtol = params["TM_tol"]
    if params["adaptive_tm_tol"]:
        TMtol *= delta
    fpoints = vumps_tm_eigs(mpslist, params, tol=TMtol)
    H_env = vumps_environment(mpslist, fpoints, H, delta, params)
    return [mpslist, A_C, fpoints, H_env]
Example #7
0
def gauge_match_QR(A_C, C):
    QAC, RAC = qrpos(A_C)
    QC, RC = qrpos(C)
    A_L = ct.rightmult(QAC, np.conj(RC.T))
    errL = np.linalg.norm(RAC-RC)
    QAC, LAC = rqpos(A_C)
    QC, LC = rqpos(C)
    A_R = ct.leftmult(QC.T, QAC)
    errR = np.linalg.norm(LAC-LC)
    err = max(errL, errR)
    return (A_L, A_R, err)
Example #8
0
def mixed_canonical_old(A, lam=None):
    # """
    # Bring a uniform MPS tensor into mixed canonical form.
    # """
    lam, gam = tm.canonicalized_gamma(A, lam=lam)
    A_L = ct.leftmult(lam, gam)
    A_R = ct.rightmult(gam, lam)
    chi = lam.size
    C = np.zeros(chi, dtype=A.dtype)
    C[:] = lam.real[:]
    C = np.diag(C)
    mpslist = [A_L, C, A_R]
    return mpslist
Example #9
0
def expand_tensors(oldlist, newlist, Dchi):
    NL, NR = null_spaces(oldlist)
    #AL, C, AR = newlist
    AL, C, AR = oldlist
    d, chi, _ = AL.shape
    B2 = B2_tensor(oldlist, newlist)
    #U, S, VH = sp.linalg.svd(B2)
    print("B2: ", B2.shape)
    try:
        U, s, V = np.linalg.svd(B2, full_matrices=False, compute_uv=True)
    except:
        print("Divide-and-conquer SVD failed. Trying gesvd...")
        U, s, V = sp.linalg.svd(B2,
                                full_matrices=False,
                                overwrite_a=False,
                                check_finite=True,
                                lapack_driver='gesvd')

    U = U[:, :Dchi]
    Vh = dag(V[:Dchi, :])
    newchi = chi + Dchi

    NLU = ct.rightmult(NL, U)
    newAL = np.zeros((d, newchi, newchi), dtype=oldlist[0].dtype)
    newAL[:, :chi, :chi] = AL[:, :, :]
    newAL[:, chi:, chi:] = NLU[:, :]

    newAL = ct.unfuse_left(newAL, (d, newchi, newchi))

    newC = np.zeros((newchi, newchi), dtype=oldlist[0].dtype)
    newC[:chi, :chi] = C[:, :]

    VhNR = ct.leftmult(Vh, NR)
    newAR = np.zeros((d, newchi, newchi), dtype=oldlist[0].dtype)
    newAR[:, :chi, :chi] = AR[:, :chi, :chi]
    newAR[:, chi:, chi:] = VhNR[:, :, :]
    newmpslist = [newAL, newC, newAR]
    newAC = ct.rightmult(newAL, newC)
    return (newmpslist, newAC)
Example #10
0
def apply_Hc(C, A_L, A_R, Hlist):
    """
    Compute C' via eq 16 of vumps paper (132 of tangent space methods).
    """
    H, LH, RH = Hlist
    A_Lstar = np.conj(A_L)
    A_C = ct.rightmult(A_L, C)
    to_contract = [A_C, A_Lstar, A_R, np.conj(A_R), H]
    idxs = [(4, 1, 3), (6, 1, -1), (5, 3, 2), (7, -2, 2), (6, 7, 4, 5)]
    term1 = scon(to_contract, idxs)
    term2 = np.dot(LH, C)
    term3 = np.dot(C, RH.T)
    C_prime = term1 + term2 + term3
    return C_prime
Example #11
0
def apply_HAc(A_C, A_L, A_R, Hlist):
    """
    Compute A'C via eq 11 of vumps paper (131 of tangent space methods).
    """
    H, LH, RH = Hlist
    to_contract_1 = [A_L, np.conj(A_L), A_C, H]
    idxs_1 = [(2, 1, 4), (3, 1, -2), (5, 4, -3), (3, -1, 2, 5)]
    term1 = scon(to_contract_1, idxs_1)

    to_contract_2 = [A_C, A_R, np.conj(A_R), H]
    idxs_2 = [(5, -2, 4), (2, 4, 1), (3, -3, 1), (-1, 3, 5, 2)]
    term2 = scon(to_contract_2, idxs_2)

    term3 = ct.leftmult(LH, A_C)
    term4 = ct.rightmult(A_C, RH.T)
    A_C_prime = term1 + term2 + term3 + term4
    return A_C_prime
Example #12
0
def vumps_initial_tensor(d, chi, params, dtype=np.complex128):
    """
    Generate a random uMPS in mixed canonical forms, along with the left
    dominant eV L of A_L and right dominant eV R of A_R.
    """
    Ainit = utils.random_complex((d, chi, chi))
    if dtype == np.float64 or dtype == np.float32:
        Ainit = Ainit.real
    mpslist = mixed_canonical(Ainit)
    A_L, C, A_R = mpslist

    Cd = np.conj(C.T)
    rL = np.dot(Cd, C)
    lR = np.dot(C, Cd)
    lR /= np.trace(lR)
    rL /= np.trace(rL)
    A_C = ct.rightmult(A_L, C)
    fpoints = [rL, lR]
    return (mpslist, A_C, fpoints)
Example #13
0
def vumps_truncate(mpslist, maxchi=None, writer=None, Niter=None):
    """
    Use an SVD to adjust the bond dimension of the MPS.
    """
    A_L, C, A_R = mpslist
    A_C = ct.leftmult(C, A_R)
    th = ct.twositecontract(A_L, A_C)
    gam_L, gam_R, lam, newchi, err = ct.svd(th, maxchi=maxchi)

    A_L = ct.leftmult(lam, gam_L)
    A_R = ct.rightmult(gam_R, lam)
    C = np.zeros((lam.size, lam.size), dtype=C.dtype)
    C += np.diag(lam)
    newmpslist = [A_L, C, A_R]
    if writer is not None:
        vumps_print(writer, "Adjusting bond dimension...")
        vumps_print(writer, "\tNew chi: ", str(newchi))
        vumps_print("\tTruncation error: ", str(err))
        truncarr = np.array([err])
        truncfile = "TruncationError.txt"
        writer.writearray(truncfile, truncarr, Niter, header="TruncationError")
    return (newmpslist, newchi, err)
Example #14
0
def RH_test(chi, d=2, tol=1E-11):
    """
    Tests that <L|R_H> = 0 where R_H is the renormalized effective 
    Hamiltonian of the right infinite block of a random uMPS with
    bond dimension chi. The Hamiltonian is randomized and Hermitian.
    """
    params = vumps.vumps_params()
    params["dom_ev_approx"] = False
    mpslist, rL, lR = vumps.vumps_initial_tensor(d, chi, params)
    A_L, C, A_R = mpslist
    # evl, evr, eVl, eVr = tm.tmeigs(A_R, nev=3, ncv=30, tol=1E-13,
    # which="both")

    #H = utils.random_hermitian(d*d).reshape((d,d,d,d))
    H = utils.H_ising(-1.0, -0.48).reshape((d, d, d, d))

    #RH = vumps.solve_for_RH(A_R, H, rL, params)
    RH = vumps.solve_for_RH(A_R, H, lR, params)
    proj = np.abs(vumps.proj(rL, RH))
    print("<L|RH>:", proj)
    if proj > tol:
        print("Failed!")
    else:
        print("Passed!")

    print("GAUGE MATCHING RANDOM AC AND C")
    mpslist, _, _ = vumps.vumps_initial_tensor(d, chi, params)
    A_C = utils.random_unitary(d * chi)[:, :chi].reshape((d, chi, chi))
    # A_C = utils.random_unitary(d*chi)[:, :chi].reshape(
    # (d, chi, chi))
    A_C = utils.random_complex((d, chi, chi))
    #C = np.diag(utils.random_rng(chi, 0.1, 1))
    C = utils.random_complex((chi, chi))
    A_L, A_R, _ = vumps.gauge_match_SVD(A_C, C, 1E-15)
    mpslist = [A_L, C, A_R]
    rL, lR = vumps.normalized_tm_eigs(mpslist, params)
    RH = vumps.solve_for_RH(A_R, H, rL, params)
    proj = np.abs(vumps.proj(rL, RH))
    print("<L|RH>:", proj)
    if proj > tol:
        print("Failed!")
    else:
        print("Passed!")

    print("GAUGE MATCHING CANONICAL AC AND C")
    mpslist, _, _ = vumps.vumps_initial_tensor(d, chi, params)
    A_L, C, A_R = mpslist
    A_C = ct.rightmult(A_L, C)
    A_L, A_R, _ = vumps.gauge_match_SVD(A_C, C, 1E-15)
    mpslist = [A_L, C, A_R]
    rL, lR = vumps.normalized_tm_eigs(mpslist, params)
    RH = vumps.solve_for_RH(A_R, H, rL, params)
    proj = np.abs(vumps.proj(rL, RH))
    print("<L|RH>:", proj)
    if proj > tol:
        print("Failed!")
    else:
        print("Passed!")

    print("TENSORS AFTER ONE VUMPS ITERATION")
    mpslist, rL, lR = vumps.vumps_initial_tensor(d, chi, params)
    A_L, C, A_R = mpslist
    A_C = ct.rightmult(A_L, C)
    vumps_state = [True, A_C, None, None]
    mpslist, delta, vumps_state = vumps.vumps_iteration(
        mpslist, H, params["delta_0"], params, vumps_state)
    A_L, C, A_R = mpslist
    rL, lR = vumps.normalized_tm_eigs(mpslist, params)

    RH = vumps.solve_for_RH(A_R, H, rL, params)
    proj = np.abs(vumps.proj(rL, RH))
    print("<L|RH>:", proj)
    if proj > tol:
        print("Failed!")
    else:
        print("Passed!")
Example #15
0
def LH_test(chi, d=2, tol=1E-13):
    """
    Tests that <LH|R> = 0 where LH is the renormalized effective 
    Hamiltonian of the left infinite block of a random uMPS with
    bond dimension chi. The Hamiltonian is randomized and Hermitian.
    """
    params = vumps.vumps_params()
    params["dom_ev_approx"] = False
    params["env_tol"] = 1E-12
    enviro_params = vumps.extract_enviro_params(params, params["delta_0"])
    H = utils.random_hermitian(d * d).reshape((d, d, d, d))

    print("MIXED CANONICAL")
    mpslist, rL, lR = vumps.vumps_initial_tensor(d, chi, params)

    A_L, C, A_R = mpslist
    #rL, lR = vumps.normalized_tm_eigs(mpslist, params)

    # print("rL - lR:", np.linalg.norm(rL-lR))
    # print("rL - rL.T:", np.linalg.norm(rL-rL.T))
    # print("rL - dag(rL):", np.linalg.norm(rL-np.conj(rL.T)))
    # print("E: ", vumps.twositeexpect(mpslist, H))
    # hL = vumps.compute_hL(A_L, H)
    # print("<hL|R>: ", vumps.proj(hL, lR))

    LH = vumps.solve_for_LH(A_L, H, lR, enviro_params)
    proj = np.abs(vumps.proj(LH, lR))
    print("<LH|R>:", proj)
    if proj > tol:
        print("Failed!")
    else:
        print("Passed!")

    print("GAUGE MATCHING RANDOM AC AND C")
    mpslist, rL, lR = vumps.vumps_initial_tensor(d, chi, params)
    A_C = utils.random_unitary(d * chi)[:, :chi].reshape((d, chi, chi))
    C = np.diag(utils.random_rng(chi, 0.1, 1))
    A_L, A_R = vumps.gauge_match_polar(A_C, C)
    mpslist = [A_L, C, A_R]
    print("E:", vumps.twositeexpect(mpslist, H))
    rL, lR = vumps.normalized_tm_eigs(mpslist, params)

    #hL = vumps.compute_hL(A_L, H)
    # print("E: ", vumps.twositeexpect(mpslist, H))
    # print("<hL|R>: ", vumps.proj(hL, lR))
    LH = vumps.solve_for_LH(A_L, H, lR, enviro_params)
    proj = np.abs(vumps.proj(LH, lR))
    print("<LH|R>:", proj)
    if proj > tol:
        print("Failed!")
    else:
        print("Passed!")

    print("TENSORS AFTER ONE VUMPS ITERATION")

    mpslist, rL, lR = vumps.vumps_initial_tensor(d, chi, params)
    A_L, C, A_R = mpslist
    A_C = ct.rightmult(A_L, C)

    environment_init = [rL, lR, None, None]
    environment = vumps.vumps_environment(mpslist, H, tol, params,
                                          environment_init)
    vumps_state = [False, A_C]

    mpslist, delta, vumps_state = vumps.vumps_gradient(mpslist, H, environment,
                                                       tol, params,
                                                       vumps_state)

    environment = vumps.vumps_environment(mpslist, H, tol, params, environment)

    A_L, C, A_R = mpslist
    rL, lR = vumps.normalized_tm_eigs(mpslist, params)

    LH = vumps.solve_for_LH(A_L, H, lR, params)
    proj = np.abs(vumps.proj(LH, lR))
    print("<LH|R>:", proj)
    if proj > tol:
        print("Failed!")
    else:
        print("Passed!")