def test_ED(): # just quickly check that it runs without errors for a small system xxz_pars = dict(L=4, Jxx=1., Jz=1., hz=0.0, bc_MPS='finite') M = XXZChain(xxz_pars) ED = ExactDiag(M) ED.build_full_H_from_mpo() H, ED.full_H = ED.full_H, None ED.build_full_H_from_bonds() H2 = ED.full_H assert (npc.norm(H - H2, np.inf) < 1.e-14) ED.full_diagonalization() psi = ED.groundstate() print("select charge_sector =", psi.qtotal) ED2 = ExactDiag(M, psi.qtotal) ED2.build_full_H_from_mpo() ED2.full_diagonalization() psi2 = ED2.groundstate() full_psi2 = psi.zeros_like() full_psi2[ED2._mask] = psi2 ov = npc.inner(psi, full_psi2, do_conj=True) print("overlab <psi | psi2> = 1. -", 1. - ov) assert (abs(abs(ov) - 1.) < 1.e-15) # starting from a random guess in the correct charge sector, # check if we can also do lanczos. np.random.seed(12345) psi3 = npc.Array.from_func(np.random.random, psi2.legs, qtotal=psi2.qtotal, shape_kw='size') E0, psi3, N = lanczos(ED2, psi3) print("Lanczos E0 =", E0) ov = npc.inner(psi3, psi2, do_conj=True) print("overlab <psi2 | psi3> = 1. -", 1. - ov) assert (abs(abs(ov) - 1.) < 1.e-15)
def example_exact_diagonalization(L, Jz): xxz_pars = dict(L=L, Jxx=1., Jz=Jz, hz=0.0, bc_MPS='finite') M = XXZChain(xxz_pars) product_state = ["up", "down"] * (xxz_pars['L'] // 2) # this selects a charge sector! psi_DMRG = MPS.from_product_state(M.lat.mps_sites(), product_state) charge_sector = psi_DMRG.get_total_charge(True) # ED charge sector should match ED = ExactDiag(M, charge_sector=charge_sector, max_size=2.e6) ED.build_full_H_from_mpo() # ED.build_full_H_from_bonds() # whatever you prefer print("start diagonalization") ED.full_diagonalization() # the expensive part for large L E0_ED, psi_ED = ED.groundstate() # return the ground state print("psi_ED =", psi_ED) print("run DMRG") dmrg.run(psi_DMRG, M, {'verbose': 0}) # modifies psi_DMRG in place! # first way to compare ED with DMRG: convert MPS to ED vector psi_DMRG_full = ED.mps_to_full(psi_DMRG) print("psi_DMRG_full =", psi_DMRG_full) ov = npc.inner(psi_ED, psi_DMRG_full, axes='range', do_conj=True) print("<psi_ED|psi_DMRG_full> =", ov) assert (abs(abs(ov) - 1.) < 1.e-13) # second way: convert ED vector to MPS psi_ED_mps = ED.full_to_mps(psi_ED) ov2 = psi_ED_mps.overlap(psi_DMRG) print("<psi_ED_mps|psi_DMRG> =", ov2) assert (abs(abs(ov2) - 1.) < 1.e-13) assert (abs(ov - ov2) < 1.e-13) # -> advantage: expectation_value etc. of MPS are available! print("<Sz> =", psi_ED_mps.expectation_value('Sz'))
def test_CouplingMPOModel_group(): m1 = MyMod(dict(x=0.5, L=5, bc_MPS='finite')) model_params = {'L': 6, 'hz': np.random.random([6]), 'bc_MPS': 'finite'} m2 = XXZChain(model_params) for m in [m1, m2]: print("model = ", m) assert m.H_MPO.max_range == 1 # test grouping sites ED = ExactDiag(m) # ED.build_full_H_from_mpo() ED.build_full_H_from_bonds() m.group_sites(n=2) assert m.H_MPO.max_range == 1 ED_gr = ExactDiag(m) ED_gr.build_full_H_from_mpo() H = ED.full_H.split_legs().to_ndarray() Hgr = ED_gr.full_H.split_legs() Hgr.idrop_labels() Hgr = Hgr.split_legs().to_ndarray() assert np.linalg.norm(H - Hgr) < 1.e-14 ED_gr.full_H = None ED_gr.build_full_H_from_bonds() Hgr = ED_gr.full_H.split_legs() Hgr.idrop_labels() Hgr = Hgr.split_legs().to_ndarray() assert np.linalg.norm(H - Hgr) < 1.e-14
def test_purification_TEBD(L=3): xxz_pars = dict(L=L, Jxx=1., Jz=3., hz=0., bc_MPS='finite') M = XXZChain(xxz_pars) for disent in [ None, 'backwards', 'min(None,last)-renyi', 'noise-norm', 'renyi-min(None,noise-renyi)' ]: psi = purification_mps.PurificationMPS.from_infiniteT( M.lat.mps_sites(), bc='finite') TEBD_params = { 'trunc_params': { 'chi_max': 16, 'svd_min': 1.e-8 }, 'disentangle': disent, 'dt': 0.1, 'verbose': 30, 'N_steps': 2 } eng = PurificationTEBD(psi, M, TEBD_params) eng.run() N = psi.expectation_value('Id') # check normalization : <1> =?= 1 npt.assert_array_almost_equal_nulp(N, np.ones([L]), 100) eng.run_imaginary(0.2) N = psi.expectation_value('Id') # check normalization : <1> =?= 1 npt.assert_array_almost_equal_nulp(N, np.ones([L]), 100) if disent == 'last-renyi': eng.run_imaginary(0.3) eng.disentangle_global()
def test_purification_MPO(L=6): xxz_pars = dict(L=L, Jxx=1., Jz=2., hz=0., bc_MPS='finite') M = XXZChain(xxz_pars) psi = purification_mps.PurificationMPS.from_infiniteT(M.lat.mps_sites(), bc='finite') options = {'trunc_params': {'chi_max': 50, 'svd_min': 1.e-8}} U = M.H_MPO.make_U_II(dt=0.1) PurificationApplyMPO(psi, U, options).run() N = psi.expectation_value('Id') # check normalization : <1> =?= 1 npt.assert_array_almost_equal_nulp(N, np.ones([L]), 100)
def test_model_H_conversion(L=6): bc = 'finite' model_params = {'L': L, 'hz': np.random.random([L]), 'bc_MPS': bc} m = XXZChain(model_params) # can we run the conversion? # conversion from bond to MPO in NearestNeighborModel H_MPO = m.calc_H_MPO_from_bond() # conversion from MPO to bond in MPOModel H_bond = m.calc_H_bond_from_MPO() # compare: did we get the correct result? ED = ExactDiag(m) ED.build_full_H_from_bonds() H0 = ED.full_H # this should be correct ED.full_H = None m.H_MPO = H_MPO ED.build_full_H_from_mpo() full_H_mpo = ED.full_H # the one generated by NearstNeighborModel.calc_H_MPO_from_bond() print("npc.norm(H0 - full_H_mpo) = ", npc.norm(H0 - full_H_mpo)) assert npc.norm(H0 - full_H_mpo) < 1.e-14 # round off errors on order of 1.e-15 m.H_bond = H_bond ED.full_H = None ED.build_full_H_from_bonds() full_H_bond = ED.full_H # the one generated by NearstNeighborModel.calc_H_MPO_from_bond() print("npc.norm(H0 - full_H_bond) = ", npc.norm(H0 - full_H_bond)) assert npc.norm( H0 - full_H_bond) < 1.e-14 # round off errors on order of 1.e-15
def test_XXZChain_general(tol=1.e-14): check_general_model(XXZChain, dict(L=4, Jxx=1., hz=0., bc_MPS='finite'), { 'Jz': [0., 1., 2.], 'hz': [0., 0.2] }) model_param = dict(L=3, Jxx=1., Jz=1.5, hz=0.25, bc_MPS='finite') m1 = XXZChain(model_param) m2 = XXZChain2(model_param) for Hb1, Hb2 in zip(m1.H_bond, m2.H_bond): if Hb1 is None: assert Hb2 is None continue assert npc.norm(Hb1 - Hb2) < tol
def test_MPSEnvironment(): xxz_pars = dict(L=4, Jxx=1., Jz=1.1, hz=0.1, bc_MPS='finite') L = xxz_pars['L'] M = XXZChain(xxz_pars) state = ([0, 1] * L)[:L] # Neel state psi = mps.MPS.from_product_state(M.lat.mps_sites(), state, bc='finite') env = mps.MPSEnvironment(psi, psi) env.get_LP(3, True) env.get_RP(0, True) env.test_sanity() for i in range(4): ov = env.full_contraction(i) # should be one print("total contraction on site", i, ": ov = 1. - ", ov - 1.) assert (abs(abs(ov) - 1.) < 1.e-14) env.expectation_value('Sz')
def test_MPOEnvironment(): xxz_pars = dict(L=4, Jxx=1., Jz=1.1, hz=0.1, bc_MPS='finite') L = xxz_pars['L'] M = XXZChain(xxz_pars) state = ([0, 1] * L)[:L] # Neel psi = mps.MPS.from_product_state(M.lat.mps_sites(), state, bc='finite') env = mpo.MPOEnvironment(psi, M.H_MPO, psi) env.get_LP(3, True) env.get_RP(0, True) env.test_sanity() E_exact = -0.825 for i in range(4): E = env.full_contraction(i) # should be one print("total energy for contraction at site ", i, ": E =", E) assert (abs(E - E_exact) < 1.e-14)
def test_renyi_disentangler(L=4, eps=1.e-15): xxz_pars = dict(L=L, Jxx=1., Jz=3., hz=0., bc_MPS='finite') M = XXZChain(xxz_pars) psi = purification_mps.PurificationMPS.from_infiniteT(M.lat.mps_sites(), bc='finite') eng = PurificationTEBD(psi, M, {'verbose': 30, 'disentangle': 'renyi'}) theta = eng.psi.get_theta(1, 2) print(theta[0, :, :, 0, :, :]) # find random unitary: SVD of random matix pleg = psi.sites[0].leg pipe = npc.LegPipe([pleg, pleg]) A = npc.Array.from_func_square(rmat.CUE, pipe).split_legs() A.iset_leg_labels(['p0', 'p1', 'p0*', 'p1*']) # Now we have unitary `A`, i.e. the optimal `U` should be `A^dagger`. theta = npc.tensordot(A, theta, axes=[['p0*', 'p1*'], ['p0', 'p1']]) U0 = npc.outer( npc.eye_like(theta, 'q0').iset_leg_labels(['q0', 'q0*']), npc.eye_like(theta, 'q1').iset_leg_labels(['q1', 'q1*'])) U = U0 Sold = np.inf for i in range(20): S, U = eng.used_disentangler.iter(theta, U) if i == 0: S_0 = S print("iteration {i:d}: S={S:.5f}, DS={DS:.4e} ".format(i=i, S=S, DS=Sold - S)) if abs(Sold - S) < eps: print("break: S converged down to {eps:.1e}".format(eps=eps)) break Sold, S = S, Sold else: print("maximum number of iterations reached") theta = npc.tensordot(U, theta, axes=[['q0*', 'q1*'], ['q0', 'q1']]) print("new theta = ") print(theta.itranspose(['vL', 'vR', 'p0', 'q0', 'p1', 'q1'])) print(theta[0, 0]) assert (S < S_0) # this should always be true... if S > 100 * eps: print("final S =", S) warnings.warn("test of purification failed to find the optimum.")
def test_canoncial_purification(L=6, charge_sector=0, eps=1.e-14): site = spin_half psi = purification_mps.PurificationMPS.from_infiniteT_canonical( [site] * L, [charge_sector]) psi.test_sanity() total_psi = psi.get_theta(0, L).take_slice(0, 'vL').take_slice(0, 'vR') total_psi.itranspose(['p' + str(i) for i in range(L)] + ['q' + str(i) for i in range(L)]) # note: don't `combine_legs`: it will permute the p legs differently than q due to charges total_psi_dense = total_psi.to_ndarray().reshape(2**L, 2**L) # now it should be diagonal diag = np.diag(total_psi_dense) assert np.all( np.abs(total_psi_dense - np.diag(diag) < eps)) # is it diagonal? # and the diagonal should be sqrt(L choose L//2) for states with fitting numbers pref = 1. / scipy.special.comb(L, L // 2 + charge_sector)**0.5 Q_p = site.leg.to_qflat()[:, 0] for i, entry in enumerate(diag): Q_i = sum([Q_p[int(b)] for b in format(i, 'b').zfill(L)]) if Q_i == charge_sector: assert abs(entry - pref) < eps else: assert abs(entry) < eps # and one quick test of TEBD xxz_pars = dict(L=L, Jxx=1., Jz=3., hz=0., bc_MPS='finite') M = XXZChain(xxz_pars) TEBD_params = { 'trunc_params': { 'chi_max': 16, 'svd_min': 1.e-8 }, 'disentangle': None, # 'renyi' should work as well, 'backwards' not. 'dt': 0.1, 'N_steps': 2 } eng = PurificationTEBD(psi, M, TEBD_params) eng.run_imaginary(0.2) eng.run() N = psi.expectation_value('Id') # check normalization : <1> =?= 1 npt.assert_array_almost_equal_nulp(N, np.ones([L]), 100)
def gen_disentangler_psi_singlet_test(site_P=spin_half, L=6, max_range=4): psi0, pairs_PQ = gen_disentangler_psi_singlets(site_P, L, max_range) psi0.test_sanity() print("pairs: P", pairs_PQ[0]) print("pairs: Q", pairs_PQ[1]) print("entanglement entropy: ", psi0.entanglement_entropy() / np.log(2.)) coords, mutinf_pq = psi0.mutinf_two_site(legs='pq') print("(i,j)=", [tuple(c) for c in coords]) print("PQ:", np.round(mutinf_pq / np.log(2), 3)) print("P: ", np.round(psi0.mutinf_two_site(legs='p')[1] / np.log(2), 3)) print("Q: ", np.round(psi0.mutinf_two_site(legs='q')[1] / np.log(2), 3)) M = XXZChain(dict(L=L)) tebd_pars = dict(trunc_params={'trunc_cut': 1.e-10}, disentangle='diag') eng = PurificationTEBD(psi0, M, tebd_pars) for i in range(L): eng.disentangle_global() print(psi0.entanglement_entropy() / np.log(2)) mutinf_Q = psi0.mutinf_two_site(legs='q')[1] print("P: ", np.round(psi0.mutinf_two_site(legs='p')[1] / np.log(2), 3)) print("Q: ", np.round(mutinf_Q / np.log(2), 3)) assert (np.all(mutinf_Q < 1.e-10))
def test_XXZChain(): pars = dict(L=4, Jxx=1., Jz=1., hz=0., bc_MPS='finite') chain = XXZChain(pars) chain.test_sanity() for Hb in chain.H_bond[1:]: # check bond eigenvalues Hb2 = Hb.combine_legs([['p0', 'p1'], ['p0*', 'p1*']], qconj=[+1, -1]) print(Hb2.to_ndarray()) W = npc.eigvalsh(Hb2) npt.assert_array_almost_equal_nulp(np.sort(W), np.sort([-0.75, 0.25, 0.25, 0.25]), 16**3) # now check with non-trivial onsite terms pars['hz'] = 0.2 print("hz =", pars['hz']) chain = XXZChain(pars) chain.test_sanity() Hb = chain.H_bond[2] # the only central bonds: boundaries have different hz. Hb2 = Hb.combine_legs([['p0', 'p1'], ['p0*', 'p1*']], qconj=[+1, -1]) print(Hb2.to_ndarray()) W = npc.eigvalsh(Hb2) print(W) npt.assert_array_almost_equal_nulp( np.sort(W), np.sort( [-0.75, 0.25 - 2 * 0.5 * 0.5 * pars['hz'], 0.25, 0.25 + 2. * 0.5 * 0.5 * pars['hz']]), 16**3) pars['bc_MPS'] = 'infinite' for L in [2, 3, 4, 5, 6]: print("L =", L) pars['L'] = L chain = XXZChain(pars) pprint.pprint(chain.coupling_terms) assert len(chain.H_bond) == L Hb0 = chain.H_bond[0] for Hb in chain.H_bond[1:]: assert (npc.norm(Hb - Hb0, np.inf) == 0.) # exactly equal pars['Jxx'] = 0. chain = XXZChain(pars) chain.test_sanity()
"""A simple example comparing DMRG output with full diagonalization (ED). Sorry that this is not well documented! ED is meant to be used for debugging only ;) """ # Copyright 2018 TeNPy Developers import tenpy.linalg.np_conserved as npc from tenpy.models.xxz_chain import XXZChain from tenpy.networks.mps import MPS from tenpy.algorithms.exact_diag import ExactDiag from tenpy.algorithms.dmrg import run as run_DMRG xxz_pars = dict(L=4, Jxx=1., Jz=1., hz=0.0, bc_MPS='finite') M = XXZChain(xxz_pars) ED = ExactDiag(M, [0]) ED.build_full_H_from_mpo() # ED.build_full_H_from_bonds() # whatever you prefer print("start diagonalization") ED.full_diagonalization() psi_ED = ED.groundstate() print("psi_ED =", psi_ED) print("start DMRG") product_state = [0, 1] * (xxz_pars['L'] // 2) # this selects a charge sector! psi_DMRG = MPS.from_product_state(M.lat.mps_sites(), product_state) res = run_DMRG(psi_DMRG, M, {'verbose': 0}) # first way to compare ED with DMRG: convert MPS to ED vector psi_DMRG_full = ED.mps_to_full(psi_DMRG)
# setup circuit-generated isoMPS psi = IsoMPS(preg, breg, pcircs, L=L) ## Example (resolve parameters => random values and print circuit) # pick some random parameter values param_vals = [4 * np.pi * np.random.rand() for j in range(len(param_names))] param_dict = dict(zip(param_names, param_vals)) psi.construct_circuit(param_dict, include_measurements=False) #psi.circ.draw('mpl') #%% ## Setup XXZ model in Tenpy ## from tenpy.models.xxz_chain import XXZChain h_param_dict = {'Jz': Delta, 'hz': 0} model = XXZChain(h_param_dict) H_mpo = model.calc_H_MPO() # function to calculate energy using MPO/MPS contraction in tenpy #def energy_tp(param_vals,*args): """ inputs: - param_vals = dict {parameter:value} - *args, args[0] should be psi: state as IsoMPS args[1] should be H_mpo: Hamiltonian as MPO (input made this way to be compatible w/ scipy.optimize) outputs: - float, <psi|H|psi> computed w/ tenpy """ # parse inputs