Beispiel #1
0
def test_lattice():
    chinfo = npc.ChargeInfo([1, 3])
    leg = gen_random_legcharge(chinfo, 8)
    leg2 = gen_random_legcharge(chinfo, 2)
    op1 = npc.Array.from_func(np.random.random, [leg, leg.conj()],
                              shape_kw='size')
    op2 = npc.Array.from_func(np.random.random, [leg2, leg2.conj()],
                              shape_kw='size')
    site1 = lattice.Site(leg, [('up', 0), ('down', -1)], op1=op1)
    site2 = lattice.Site(leg2, [('down', 0), ('up', -1)], op2=op2)
    for order in ['default', 'Fstyle', 'snake', 'snakeFstyle']:
        print("order =", order)
        Ls = [5, 2]
        basis = [[1., 1.], [0., 1.]]
        pos = [[0.1, 0.], [0.2, 0.]]
        lat = lattice.Lattice(Ls, [site1, site2],
                              order=order,
                              basis=basis,
                              positions=pos,
                              bc='periodic',
                              bc_MPS='infinite')
        assert lat.dim == len(Ls)
        assert lat.N_sites == np.prod(Ls) * 2
        for i in range(lat.N_sites):
            assert lat.lat2mps_idx(lat.mps2lat_idx(i)) == i
        idx = [4, 1, 0]
        assert np.all(lat.mps2lat_idx(lat.lat2mps_idx(idx)) == idx)
        # index conversion should also work for arbitrary index arrays and indices outside bc_MPS
        # for bc_MPS=infinite
        i = np.arange(-3, lat.N_sites * 2 - 3).reshape((-1, 2))
        assert np.all(lat.lat2mps_idx(lat.mps2lat_idx(i)) == i)
        # test position
        npt.assert_equal([4.1, 5.], lat.position(idx))
        # test lat.mps2lat_values
        A = np.random.random([lat.N_sites, 2, lat.N_sites])
        print(A.shape)
        Ares = lat.mps2lat_values(A, axes=[-1, 0])
        Ares_ma = lat.mps2lat_values_masked(A, [-1, 0], [None] * 2, [None] * 2)
        for i in range(lat.N_sites):
            idx_i = lat.mps2lat_idx(i)
            for j in range(lat.N_sites):
                idx_j = lat.mps2lat_idx(j)
                for k in range(2):
                    idx = tuple(idx_i) + (k, ) + tuple(idx_j)
                    assert Ares[idx] == A[i, k, j]
                    assert Ares_ma[idx] == A[i, k, j]
        # and again for fixed `u` within the unit cell
        for u in range(len(lat.unit_cell)):
            mps_u = lat.mps_idx_fix_u(u)
            A_u = A[np.ix_(mps_u, np.arange(2), mps_u)]
            A_u_res = lat.mps2lat_values(A_u, axes=[-1, 0], u=u)
            A_u_res_masked = lat.mps2lat_values_masked(A_u,
                                                       axes=[-1, 0],
                                                       mps_inds=[mps_u] * 2,
                                                       include_u=[False] * 2)
            A_u_expected = Ares[:, :, u, :, :, :, u]
            npt.assert_equal(A_u_res, A_u_expected)
            npt.assert_equal(A_u_res_masked, A_u_expected)
Beispiel #2
0
def test_npc_Array_reshape():
    a = random_Array((20, 15, 10), chinfo, sort=False)
    aflat = a.to_ndarray()
    for comb_legs, transpose in [([[1]], [0, 1, 2]), ([[1], [2]], [0, 1, 2]),
                                 ([[0], [1], [2]], [0, 1, 2]), ([[2, 0]], [1, 2, 0]),
                                 ([[2, 0, 1]], [2, 0, 1])]:
        print('combine legs', comb_legs)
        with warnings.catch_warnings():
            warnings.simplefilter("ignore", FutureWarning)
            acomb = a.combine_legs(comb_legs)  # just sorts second leg
        print("=> labels: ", acomb.get_leg_labels())
        acomb.test_sanity()
        asplit = acomb.split_legs()
        asplit.test_sanity()
        npt.assert_equal(asplit.to_ndarray(), aflat.transpose(transpose))
    print("test squeeze")
    b = random_Array((10, 1, 5, 1), chinfo3, sort=True)
    bflat = b.to_ndarray()
    bs = b.squeeze()
    bs.test_sanity()
    npt.assert_equal(bs.to_ndarray(), np.squeeze(bflat))
    bs.test_sanity()
    if b.stored_blocks > 0:
        # find a index with non-zero entry
        idx = tuple([l.slices[qi] for l, qi in zip(b.legs, b._qdata[0])])
    else:
        idx = tuple([0] * b.rank)
    assert b[idx[0], :, idx[2], :].squeeze() == bflat[idx]
    print("test add_trivial_leg")
    be = bs.copy(deep=True).add_trivial_leg(1, 'tr1', +1).add_trivial_leg(3, 'tr2', -1)
    be.test_sanity()
    npt.assert_equal(be.to_ndarray(), bflat)
    print("test concatenate")
    # create array `c` to concatenate with b along axis 2
    legs = b.legs[:]
    legs[1] = gen_random_legcharge(b.chinfo, 5)
    c1 = npc.Array.from_func(np.random.random, legs, qtotal=b.qtotal, shape_kw='size')
    c1flat = c1.to_ndarray()
    legs[1] = gen_random_legcharge(b.chinfo, 3)
    c2 = npc.Array.from_func(np.random.random, legs, qtotal=b.qtotal, shape_kw='size')
    c2flat = c2.to_ndarray()
    bc1c2 = npc.concatenate([b, c1, c2], axis=1)
    bc1c2.test_sanity()
    npt.assert_equal(bc1c2.to_ndarray(), np.concatenate([bflat, c1flat, c2flat], axis=1))

    print("trivial charges")
    a = npc.Array.from_func(np.random.random, [lcTr, lcTr.conj()], shape_kw='size')
    aflat = a.to_ndarray()
    acomb = a.combine_legs([0, 1])
    acomb.test_sanity()
    asplit = acomb.split_legs([0])
    asplit.test_sanity()
    npt.assert_equal(asplit.to_ndarray(), aflat)
Beispiel #3
0
def test_npc_grid_concat():
    # this is also a heavy test of Array.__getitem__
    ci = chinfo3
    legs = [gen_random_legcharge(ci, l) for l in [5, 4, 3]]
    A = npc.Array.from_func(np.random.random,
                            legs,
                            qtotal=[0],
                            shape_kw='size')
    print("orig legs")
    for l in legs:
        print(l)
    print('---')
    Aflat = A.to_ndarray()
    grid = [A[..., :2, :], A[:, 2:3, ...], A[:, 3:]]
    A_full = npc.grid_concat(grid, [1])
    npt.assert_equal(Aflat, A_full.to_ndarray())
    grid = [[A[:, :1, 2:3], A[:, :1, 0:2]],
            [A[:, 2:, 2:3], A[:, 2:, 0:2]]]  # yapf: disable
    A_part = npc.grid_concat(grid, [1, 2]).to_ndarray()
    A_part_exact = Aflat[:, [0, 2, 3], :][:, :, [2, 0, 1]]
    npt.assert_equal(A_part, A_part_exact)
    grid[1][0] = None
    A_part = npc.grid_concat(grid, [1, 2]).to_ndarray()
    A_part_exact[:, 1:, 0] = 0.
    npt.assert_equal(A_part, A_part_exact)
Beispiel #4
0
def test_npc_grid_outer():
    ci = chinfo3
    p_leg = gen_random_legcharge(ci, 4)
    legs_op = [p_leg, p_leg.conj()]
    op_0 = 1.j * npc.Array.from_func(np.random.random, legs_op, qtotal=[0], shape_kw='size')
    op_pl = npc.Array.from_func(np.random.random, legs_op, qtotal=[1], shape_kw='size')
    op_min = npc.Array.from_func(np.random.random, legs_op, qtotal=[-1], shape_kw='size')
    op_id = npc.eye_like(op_0)
    grid = [[op_id, op_pl, op_min, op_0, None],
            [None, None, None, None, op_min],
            [None, None, None, None, op_pl],
            [None, None, None, None, op_0],
            [None, None, None, None, op_id]]  # yapf: disable
    leg_WL = npc.LegCharge.from_qflat(ci, ci.make_valid([[0], [1], [-1], [0], [0]]))
    leg_WR = npc.LegCharge.from_qflat(ci, ci.make_valid([[0], [1], [-1], [0], [0]]), -1)
    leg_WR_calc = npc.detect_grid_outer_legcharge(grid, [leg_WL, None], qconj=-1)[1]
    leg_WR.test_equal(leg_WR_calc)

    W = npc.grid_outer(grid, [leg_WL, leg_WR])
    W.test_sanity()
    Wflat = np.zeros([5, 5, 4, 4], dtype=W.dtype)
    for idx, op in [[(0, 0), op_id], [(0, 1), op_pl], [(0, 2), op_min], [(0, 3), op_0],
                    [(1, 4), op_min], [(2, 4), op_pl], [(3, 4), op_0], [(4, 4), op_id]]:
        Wflat[idx] = op.to_ndarray()
    npt.assert_equal(W.to_ndarray(), Wflat)
Beispiel #5
0
def test_LegPipe():
    shape = (20, 10, 8)
    legs = [gen_random_legcharge(ch_1, s) for s in shape]
    for sort, bunch in it.product([True, False], repeat=2):
        pipe = charges.LegPipe(legs, sort=sort, bunch=bunch)
        pipe.test_sanity()
        pipe_conj = pipe.conj()
        pipe.test_contractible(pipe.conj())
        pipe_equal = pipe.flip_charges_qconj()
        pipe_equal.test_equal(pipe)

        assert (pipe.ind_len == np.prod(shape))
        print(pipe.q_map)
        # test pipe._map_incoming_qind
        qind_inc = pipe.q_map[:, 3:].copy()  # all possible qindices
        np.random.shuffle(
            qind_inc)  # different order to make the test non-trivial
        qmap_ind = pipe._map_incoming_qind(qind_inc)
        for i in range(len(qind_inc)):
            npt.assert_equal(pipe.q_map[qmap_ind[i], 3:], qind_inc[i])
            size = np.prod([
                l.slices[j + 1] - l.slices[j]
                for l, j in zip(legs, qind_inc[i])
            ])
            assert size == pipe.q_map[qmap_ind[i], 1] - pipe.q_map[qmap_ind[i],
                                                                   0]
Beispiel #6
0
def test_site():
    chinfo = npc.ChargeInfo([1, 3])
    leg = gen_random_legcharge(chinfo, 8)
    op1 = npc.Array.from_func(np.random.random, [leg, leg.conj()], shape_kw='size')
    op2 = npc.Array.from_func(np.random.random, [leg, leg.conj()], shape_kw='size')
    labels = ['up'] + [None] * (leg.ind_len - 2) + ['down']
    s = site.Site(leg, labels, silly_op=op1)
    assert s.state_index('up') == 0
    assert s.state_index('down') == leg.ind_len - 1
    assert s.opnames == set(['silly_op', 'Id', 'JW'])
    assert s.silly_op is op1
    s.add_op('op2', op2)
    assert s.op2 is op2
    assert s.get_op('op2') is op2
    assert s.get_op('silly_op') is op1
    npt.assert_equal(
        s.get_op('silly_op op2').to_ndarray(),
        npc.tensordot(op1, op2, [1, 0]).to_ndarray())
    leg2 = npc.LegCharge.from_drop_charge(leg, 1)
    leg2 = npc.LegCharge.from_change_charge(leg2, 0, 2, 'changed')
    s2 = copy.deepcopy(s)
    s2.change_charge(leg2)
    perm_qind, leg2s = leg2.sort()
    perm_flat = leg2.perm_flat_from_perm_qind(perm_qind)
    s2s = copy.deepcopy(s2)
    s2s.change_charge(leg2s, perm_flat)
    for site_check in [s2, s2s]:
        print("site_check.leg = ", site_check.leg)
        for opn in site_check.opnames:
            op1 = s.get_op(opn).to_ndarray()
            op2 = site_check.get_op(opn).to_ndarray()
            perm = site_check.perm
            npt.assert_equal(op1[np.ix_(perm, perm)], op2)
Beispiel #7
0
def test_FlatHermitianOperator(n=30, k=5, tol=5.e-15):
    leg = gen_random_legcharge(ch, n)
    H = npc.Array.from_func_square(rmat.GUE, leg)
    H_flat = H.to_ndarray()
    E_flat, psi_flat = np.linalg.eigh(H_flat)
    E0_flat, psi0_flat = E_flat[0], psi_flat[:, 0]
    qtotal = npc.detect_qtotal(psi0_flat, [leg])

    H_sparse = sparse.FlatHermitianOperator.from_NpcArray(H,
                                                          charge_sector=qtotal)
    psi_init = npc.Array.from_func(np.random.random, [leg], qtotal=qtotal)
    psi_init /= npc.norm(psi_init)
    psi_init_flat = H_sparse.npc_to_flat(psi_init)

    # check diagonalization
    E, psi = scipy.sparse.linalg.eigsh(H_sparse,
                                       k,
                                       v0=psi_init_flat,
                                       which='SA')
    E0, psi0 = E[0], psi[:, 0]
    print("full spectrum:", E_flat)
    print("E0 = {E0:.14f} vs exact {E0_flat:.14f}".format(E0=E0,
                                                          E0_flat=E0_flat))
    print("|E0-E0_flat| / |E0_flat| =", abs((E0 - E0_flat) / E0_flat))
    assert (abs((E0 - E0_flat) / E0_flat) < tol)
    psi0_H_psi0 = np.inner(psi0.conj(), H_sparse.matvec(psi0)).item()
    print("<psi0|H|psi0> / E0 = 1. + ", psi0_H_psi0 / E0 - 1.)
    assert (abs(psi0_H_psi0 / E0 - 1.) < tol)
Beispiel #8
0
def test_lanczos(n=30, k=5, tol=5.e-15):
    # generate Hermitian test array
    leg = gen_random_legcharge(ch, n)
    H = npc.Array.from_func_square(rmat.GUE, leg)
    H_flat = H.to_ndarray()
    E_flat, psi_flat = np.linalg.eigh(H_flat)
    E0_flat, psi0_flat = E_flat[0], psi_flat[:, 0]
    qtotal = npc.detect_qtotal(psi0_flat, [leg])

    H_Op = H  # use `matvec` of the array
    psi_init = npc.Array.from_func(np.random.random, [leg], qtotal=qtotal)

    E0, psi0, N = lanczos.lanczos(H_Op, psi_init, {'verbose': 1})
    print("full spectrum:", E_flat)
    print("E0 = {E0:.14f} vs exact {E0_flat:.14f}".format(E0=E0,
                                                          E0_flat=E0_flat))
    print("|E0-E0_flat| / |E0_flat| =", abs((E0 - E0_flat) / E0_flat))
    psi0_H_psi0 = npc.inner(psi0,
                            npc.tensordot(H, psi0, axes=[1, 0]),
                            do_conj=True)
    print("<psi0|H|psi0> / E0 = 1. + ", psi0_H_psi0 / E0 - 1.)
    assert (abs(psi0_H_psi0 / E0 - 1.) < tol)
    print("<psi0_flat|H_flat|psi0_flat> / E0_flat = ", end=' ')
    print(np.inner(psi0_flat.conj(), np.dot(H_flat, psi0_flat)) / E0_flat)
    ov = np.inner(psi0.to_ndarray().conj(), psi0_flat)
    print("|<psi0|psi0_flat>|=", abs(ov))
    assert (abs(1. - abs(ov)) < tol)

    # now repeat, but keep orthogonal to original ground state
    # -> should give second eigenvector psi1 in the same charge sector
    for i in range(1, len(E_flat)):
        E1_flat, psi1_flat = E_flat[i], psi_flat[:, i]
        qtotal = npc.detect_qtotal(psi1_flat, psi0.legs)
        if np.all(qtotal == psi0.qtotal):
            break  # found psi1 in same charge sector
    else:
        print(
            "warning: test didn't find a second eigenvector in the same charge sector!"
        )
        return  # just ignore the rest....
    E1, psi1, N = lanczos.lanczos(H_Op,
                                  psi_init, {'verbose': 1},
                                  orthogonal_to=[psi0])
    print("E1 = {E1:.14f} vs exact {E1_flat:.14f}".format(E1=E1,
                                                          E1_flat=E1_flat))
    print("|E1-E1_flat| / |E1_flat| =", abs((E1 - E1_flat) / E1_flat))
    psi1_H_psi1 = npc.inner(psi1,
                            npc.tensordot(H, psi1, axes=[1, 0]),
                            do_conj=True)
    print("<psi1|H|psi1> / E1 = 1 + ", psi1_H_psi1 / E1 - 1.)
    assert (abs(psi1_H_psi1 / E1 - 1.) < tol)
    print("<psi1_flat|H_flat|psi1_flat> / E1_flat = ", end=' ')
    print(np.inner(psi1_flat.conj(), np.dot(H_flat, psi1_flat)) / E1_flat)
    ov = np.inner(psi1.to_ndarray().conj(), psi1_flat)
    print("|<psi1|psi1_flat>|=", abs(ov))
    assert (abs(1. - abs(ov)) < tol)
    # and finnally check also orthogonality to psi0
    ov = npc.inner(psi0, psi1, do_conj=True)
    print("|<psi0|psi1>| =", abs(ov))
    assert (abs(ov) < tol**0.5)
Beispiel #9
0
def test_eig():
    size = 10
    max_nulp = 10 * size**3
    ci = chinfo3
    l = gen_random_legcharge(ci, size)
    A = npc.Array.from_func(np.random.random, [l, l.conj()],
                            qtotal=None,
                            shape_kw='size')
    print("hermitian A")
    A += A.conj().itranspose()
    Aflat = A.to_ndarray()
    W, V = npc.eigh(A, sort='m>')
    V.test_sanity()
    V_W = V.scale_axis(W, axis=-1)
    recalc = npc.tensordot(V_W, V.conj(), axes=[1, 1])
    npt.assert_array_almost_equal_nulp(Aflat, recalc.to_ndarray(), max_nulp)
    Wflat, Vflat = np.linalg.eigh(Aflat)
    npt.assert_array_almost_equal_nulp(np.sort(W), Wflat, max_nulp)
    W2 = npc.eigvalsh(A, sort='m>')
    npt.assert_array_almost_equal_nulp(W, W2, max_nulp)

    print("check complex B")
    B = 1.j * npc.Array.from_func(np.random.random, [l, l.conj()],
                                  shape_kw='size')
    B += B.conj().itranspose()
    B = A + B
    Bflat = B.to_ndarray()
    W, V = npc.eigh(B, sort='m>')
    V.test_sanity()
    recalc = npc.tensordot(V.scale_axis(W, axis=-1), V.conj(), axes=[1, 1])
    npt.assert_array_almost_equal_nulp(Bflat, recalc.to_ndarray(), max_nulp)
    Wflat, Vflat = np.linalg.eigh(Bflat)
    npt.assert_array_almost_equal_nulp(np.sort(W), Wflat, max_nulp)

    print("calculate without 'hermitian' knownledge")
    W, V = npc.eig(B, sort='m>')
    assert (np.max(np.abs(W.imag)) < EPS * max_nulp)
    npt.assert_array_almost_equal_nulp(np.sort(W.real), Wflat, max_nulp)

    print("sparse speigs")
    qi = 1
    ch_sect = B.legs[0].get_charge(qi)
    k = min(3, B.legs[0].slices[qi + 1] - B.legs[0].slices[qi])
    Wsp, Vsp = npc.speigs(B, ch_sect, k=k, which='LM')
    for W_i, V_i in zip(Wsp, Vsp):
        V_i.test_sanity()
        diff = npc.tensordot(B, V_i, axes=1) - V_i * W_i
        assert (npc.norm(diff, np.inf) < EPS * max_nulp)

    print("for trivial charges")
    A = npc.Array.from_func(np.random.random, [lcTr, lcTr.conj()],
                            shape_kw='size')
    A = A + A.conj().itranspose()
    Aflat = A.to_ndarray()
    W, V = npc.eigh(A)
    recalc = npc.tensordot(V.scale_axis(W, axis=-1), V.conj(), axes=[1, 1])
    npt.assert_array_almost_equal_nulp(Aflat, recalc.to_ndarray(),
                                       10 * A.shape[0]**3)
Beispiel #10
0
def test_expm(size=10):
    ci = chinfo3
    l = gen_random_legcharge(ci, size)
    A = npc.Array.from_func(np.random.random, [l, l.conj()], qtotal=None, shape_kw='size')
    A_flat = A.to_ndarray()
    exp_A = npc.expm(A)
    exp_A.test_sanity()
    from scipy.linalg import expm
    npt.assert_array_almost_equal_nulp(expm(A_flat), exp_A.to_ndarray(), size * size)
Beispiel #11
0
def test_lattice():
    chinfo = npc.ChargeInfo([1, 3])
    leg = gen_random_legcharge(chinfo, 8)
    leg2 = gen_random_legcharge(chinfo, 2)
    op1 = npc.Array.from_func(np.random.random, [leg, leg.conj()],
                              shape_kw='size')
    op2 = npc.Array.from_func(np.random.random, [leg2, leg2.conj()],
                              shape_kw='size')
    site1 = lattice.Site(leg, [('up', 0), ('down', -1)], op1=op1)
    site2 = lattice.Site(leg2, [('down', 0), ('up', -1)], op2=op2)
    for order in ['default', 'Fstyle', 'snake', 'snakeFstyle']:
        print("order =", order)
        Ls = [5, 2]
        basis = [[1., 1.], [0., 1.]]
        pos = [[0.1, 0.], [0.2, 0.]]
        lat = lattice.Lattice(Ls, [site1, site2],
                              order=order,
                              basis=basis,
                              positions=pos)
        nst.eq_(lat.dim, len(Ls))
        nst.eq_(lat.N_sites, np.prod(Ls) * 2)
        for i in range(lat.N_sites):
            nst.eq_(lat.lat2mps_idx(lat.mps2lat_idx(i)), i)
        idx = (4, 1, 0)
        nst.eq_(lat.mps2lat_idx(lat.lat2mps_idx(idx)), idx)
        npt.assert_equal([4.1, 5.], lat.position(idx))
        # test lat.mps2lat_values
        A = np.random.random([lat.N_sites, 2, lat.N_sites])
        print(A.shape)
        Ares = lat.mps2lat_values(A, axes=[-1, 0])
        for i in range(lat.N_sites):
            idx_i = lat.mps2lat_idx(i)
            for j in range(lat.N_sites):
                idx_j = lat.mps2lat_idx(j)
                for k in range(2):
                    idx = idx_i + (k, ) + idx_j
                    nst.eq_(Ares[idx], A[i, k, j])
        # and again for fixed `u` within the unit cell
        for u in range(len(lat.unit_cell)):
            A_u = A[np.ix_(lat.mps_idx_fix_u(u), np.arange(2),
                           lat.mps_idx_fix_u(u))]
            A_u_res = lat.mps2lat_values(A_u, axes=[-1, 0], u=u)
            npt.assert_equal(A_u_res, Ares[:, :, u, :, :, :, u])
Beispiel #12
0
def test_trace():
    chinfo = chinfo3
    legs = [gen_random_legcharge(chinfo, s) for s in (7, 8, 9)]
    legs.append(legs[1].conj())
    A = npc.Array.from_func(np.random.random, legs, qtotal=[1], shape_kw='size')
    Aflat = A.to_ndarray()
    Atr = npc.trace(A, leg1=1, leg2=-1)
    Atr.test_sanity()
    Aflattr = np.trace(Aflat, axis1=1, axis2=-1)
    npt.assert_array_almost_equal_nulp(Atr.to_ndarray(), Aflattr, A.shape[1])
Beispiel #13
0
def test_gramschmidt(n=30, k=5, tol=1.e-15):
    leg = gen_random_legcharge(ch, n)
    vecs_old = [
        npc.Array.from_func(np.random.random, [leg], shape_kw='size')
        for i in range(k)
    ]
    vecs_new, _ = lanczos.gram_schmidt(vecs_old, rcond=0., verbose=1)
    assert all([v == w for v, w in zip(vecs_new, vecs_old)])
    vecs_new, _ = lanczos.gram_schmidt(vecs_old, rcond=tol, verbose=1)
    vecs = [v.to_ndarray() for v in vecs_new]
    ovs = np.zeros((k, k))
    for i, v in enumerate(vecs):
        for j, w in enumerate(vecs):
            ovs[i, j] = np.inner(v.conj(), w)
    print(ovs)
    assert (np.linalg.norm(ovs - np.eye(k)) < 2 * n * k * k * tol)
Beispiel #14
0
def test_arnoldi(n, which):
    tol = 5.e-14 if n <= 20 else 1.e-10
    # generate Hermitian test array
    leg = gen_random_legcharge(ch, n)
    # if looking for small/large real part, ensure hermitian H
    func = rmat.GUE if which[-1] == 'R' else rmat.standard_normal_complex
    H = npc.Array.from_func_square(func, leg)
    H_flat = H.to_ndarray()
    E_flat, psi_flat = np.linalg.eig(H_flat)
    if which == 'LM':
        i = np.argmax(np.abs(E_flat))
    elif which == 'LR':
        i = np.argmax(np.real(E_flat))
    elif which == 'SR':
        i = np.argmin(np.real(E_flat))
    E0_flat, psi0_flat = E_flat[i], psi_flat[:, i]
    qtotal = npc.detect_qtotal(psi0_flat, [leg])

    H_Op = H  # use `matvec` of the array
    psi_init = npc.Array.from_func(np.random.random, [leg], qtotal=qtotal)

    eng = lanczos.Arnoldi(H_Op, psi_init, {
        'which': which,
        'num_ev': 1,
        'N_max': 20
    })
    (E0, ), (psi0, ), N = eng.run()
    print("full spectrum:", E_flat)
    print("E0 = {E0:.14f} vs exact {E0_flat:.14f}".format(E0=E0,
                                                          E0_flat=E0_flat))
    print("|E0-E0_flat| / |E0_flat| =", abs((E0 - E0_flat) / E0_flat))
    assert abs((E0 - E0_flat) / E0_flat) < tol
    psi0_H_psi0 = npc.inner(psi0,
                            npc.tensordot(H, psi0, axes=[1, 0]),
                            'range',
                            do_conj=True)
    print("<psi0|H|psi0> / E0 = 1. + ", psi0_H_psi0 / E0 - 1.)
    assert (abs(psi0_H_psi0 / E0 - 1.) < tol)
    print("<psi0_flat|H_flat|psi0_flat> / E0_flat = ", end=' ')
    print(np.inner(psi0_flat.conj(), np.dot(H_flat, psi0_flat)) / E0_flat)
    ov = np.inner(psi0.to_ndarray().conj(), psi0_flat)
    print("|<psi0|psi0_flat>|=", abs(ov))
    assert (abs(1. - abs(ov)) < tol)
Beispiel #15
0
def test_lanczos_evolve(n, N_cache, tol=5.e-15):
    # generate Hermitian test array
    leg = gen_random_legcharge(ch, n)
    H = npc.Array.from_func_square(rmat.GUE, leg) - npc.diag(1., leg)
    H_flat = H.to_ndarray()
    H_Op = H  # use `matvec` of the array
    qtotal = leg.to_qflat()[0]
    psi_init = npc.Array.from_func(np.random.random, [leg], qtotal=qtotal)
    psi_init /= npc.norm(psi_init)
    psi_init_flat = psi_init.to_ndarray()
    lanc = lanczos.LanczosEvolution(H_Op, psi_init, {
        'verbose': 1,
        'N_cache': N_cache
    })
    for delta in [-0.1j, 0.1j, 1.j]:  #, 0.1, 1.]:
        psi_final_flat = expm(H_flat * delta).dot(psi_init_flat)
        psi_final, N = lanc.run(delta)
        ov = np.inner(psi_final.to_ndarray().conj(), psi_final_flat)
        ov /= np.linalg.norm(psi_final_flat)
        print("<psi1|psi1_flat>/norm=", ov)
        assert (abs(1. - abs(ov)) < tol)
Beispiel #16
0
def test_lanczos_evolve(n, N_cache, tol=5.e-14):
    # generate Hermitian test array
    leg = gen_random_legcharge(ch, n)
    H = npc.Array.from_func_square(rmat.GUE, leg) - npc.diag(1., leg)
    H_flat = H.to_ndarray()
    H_Op = H  # use `matvec` of the array
    qtotal = leg.to_qflat()[0]
    psi_init = npc.Array.from_func(np.random.random, [leg], qtotal=qtotal)
    #psi_init /= npc.norm(psi_init) # not necessary
    psi_init_flat = psi_init.to_ndarray()
    lanc = lanczos.LanczosEvolution(H_Op, psi_init, {'N_cache': N_cache})
    for delta in [-0.1j, 0.1j, 1.j, 0.1, 1.]:
        psi_final_flat = expm(H_flat * delta).dot(psi_init_flat)
        norm = np.linalg.norm(psi_final_flat)
        psi_final, N = lanc.run(delta, normalize=False)
        diff = np.linalg.norm(psi_final.to_ndarray() - psi_final_flat)
        print("norm(|psi_final> - |psi_final_flat>)/norm = ",
              diff / norm)  # should be 1.
        assert diff / norm < tol
        psi_final2, N = lanc.run(delta, normalize=True)
        assert npc.norm(psi_final / norm - psi_final2) < tol
Beispiel #17
0
def test_FlatHermitianOperator(n=30, k=5, tol=1.e-14):
    leg = gen_random_legcharge(ch, n // 2)
    leg2 = gen_random_legcharge(ch, 2)
    pipe = npc.LegPipe([leg, leg2], qconj=+1)
    H = npc.Array.from_func_square(rmat.GUE, pipe)
    H.iset_leg_labels(["(a.b)", "(a*.b*)"])
    H_flat = H.to_ndarray()
    E_flat, psi_flat = np.linalg.eigh(H_flat)
    E0_flat, psi0_flat = E_flat[0], psi_flat[:, 0]
    qtotal = npc.detect_qtotal(psi0_flat, [pipe])

    H_sparse = sparse.FlatHermitianOperator.from_NpcArray(H,
                                                          charge_sector=qtotal)
    psi_init = npc.Array.from_func(np.random.random, [pipe], qtotal=qtotal)
    psi_init /= npc.norm(psi_init)
    psi_init.iset_leg_labels(["(a.b)"])
    psi_init_flat = H_sparse.npc_to_flat(psi_init)

    # check diagonalization
    E, psi = scipy.sparse.linalg.eigsh(H_sparse,
                                       k,
                                       v0=psi_init_flat,
                                       which='SA')
    E0, psi0 = E[0], psi[:, 0]
    print("full spectrum:", E_flat)
    print("E0 = {E0:.14f} vs exact {E0_flat:.14f}".format(E0=E0,
                                                          E0_flat=E0_flat))
    print("|E0-E0_flat| / |E0_flat| =", abs((E0 - E0_flat) / E0_flat))
    assert (abs((E0 - E0_flat) / E0_flat) < tol)
    psi0_H_psi0 = np.inner(psi0.conj(), H_sparse.matvec(psi0)).item()
    print("<psi0|H|psi0> / E0 = 1. + ", psi0_H_psi0 / E0 - 1.)
    assert (abs(psi0_H_psi0 / E0 - 1.) < tol)

    # split H to check `FlatHermitianOperator.from_guess_with_pipe`.
    print("=========")
    print("split legs and define separate matvec")
    assert psi_init.legs[0] is pipe
    psi_init_split = psi_init.split_legs([0])
    H_split = H.split_legs()

    def H_split_matvec(vec):
        vec = npc.tensordot(H_split, vec, [["a*", "b*"], ["a", "b"]])
        # TODO as additional challenge, transpose the resulting vector
        return vec

    H_sparse_split, psi_init_split_flat = sparse.FlatLinearOperator.from_guess_with_pipe(
        H_split_matvec, psi_init_split, dtype=H_split.dtype)

    # diagonalize
    E, psi = scipy.sparse.linalg.eigsh(H_sparse_split,
                                       k,
                                       v0=psi_init_split_flat,
                                       which='SA')
    E0, psi0 = E[0], psi[:, 0]
    print("full spectrum:", E_flat)
    print("E0 = {E0:.14f} vs exact {E0_flat:.14f}".format(E0=E0,
                                                          E0_flat=E0_flat))
    print("|E0-E0_flat| / |E0_flat| =", abs((E0 - E0_flat) / E0_flat))
    assert (abs((E0 - E0_flat) / E0_flat) < tol)
    psi0_H_psi0 = np.inner(psi0.conj(), H_sparse.matvec(psi0)).item()
    print("<psi0|H|psi0> / E0 = 1. + ", psi0_H_psi0 / E0 - 1.)
    assert (abs(psi0_H_psi0 / E0 - 1.) < tol)
Beispiel #18
0
def test_lanczos_gs(n, N_cache, tol=5.e-14):
    # generate Hermitian test array
    leg = gen_random_legcharge(ch, n)
    H = npc.Array.from_func_square(rmat.GUE, leg)
    H_flat = H.to_ndarray()
    E_flat, psi_flat = np.linalg.eigh(H_flat)
    E0_flat, psi0_flat = E_flat[0], psi_flat[:, 0]
    qtotal = npc.detect_qtotal(psi0_flat, [leg])

    H_Op = H  # use `matvec` of the array
    psi_init = npc.Array.from_func(np.random.random, [leg], qtotal=qtotal)

    E0, psi0, N = lanczos.lanczos(H_Op, psi_init, {
        'verbose': 1,
        'N_cache': N_cache
    })
    print("full spectrum:", E_flat)
    print("E0 = {E0:.14f} vs exact {E0_flat:.14f}".format(E0=E0,
                                                          E0_flat=E0_flat))
    print("|E0-E0_flat| / |E0_flat| =", abs((E0 - E0_flat) / E0_flat))
    psi0_H_psi0 = npc.inner(psi0,
                            npc.tensordot(H, psi0, axes=[1, 0]),
                            'range',
                            do_conj=True)
    print("<psi0|H|psi0> / E0 = 1. + ", psi0_H_psi0 / E0 - 1.)
    assert (abs(psi0_H_psi0 / E0 - 1.) < tol)
    print("<psi0_flat|H_flat|psi0_flat> / E0_flat = ", end=' ')
    print(np.inner(psi0_flat.conj(), np.dot(H_flat, psi0_flat)) / E0_flat)
    ov = np.inner(psi0.to_ndarray().conj(), psi0_flat)
    print("|<psi0|psi0_flat>|=", abs(ov))
    assert (abs(1. - abs(ov)) < tol)

    print("version with arpack")
    E0a, psi0a = lanczos.lanczos_arpack(H_Op, psi_init, {'verbose': 1})
    print("E0a = {E0a:.14f} vs exact {E0_flat:.14f}".format(E0a=E0a,
                                                            E0_flat=E0_flat))
    print("|E0a-E0_flat| / |E0_flat| =", abs((E0a - E0_flat) / E0_flat))
    psi0a_H_psi0a = npc.inner(psi0a,
                              npc.tensordot(H, psi0a, axes=[1, 0]),
                              'range',
                              do_conj=True)
    print("<psi0a|H|psi0a> / E0a = 1. + ", psi0a_H_psi0a / E0a - 1.)
    assert (abs(psi0a_H_psi0a / E0a - 1.) < tol)
    ov = np.inner(psi0a.to_ndarray().conj(), psi0_flat)
    print("|<psi0a|psi0_flat>|=", abs(ov))
    assert (abs(1. - abs(ov)) < tol)

    # now repeat, but keep orthogonal to original ground state
    orthogonal_to = [psi0]
    # -> should give second eigenvector psi1 in the same charge sector
    for i in range(1, len(E_flat)):
        E1_flat, psi1_flat = E_flat[i], psi_flat[:, i]
        qtotal = npc.detect_qtotal(psi1_flat, psi0.legs, cutoff=1.e-10)
        if np.any(qtotal != psi0.qtotal):
            continue  # not in same charge sector
        print("--- excited state #", len(orthogonal_to))
        ortho_to = [psi.copy()
                    for psi in orthogonal_to]  # (gets modified inplace)
        lanczos_params = {'verbose': 1, 'reortho': True}
        if E1_flat > -0.01:
            lanczos_params['E_shift'] = -2. * E1_flat - 0.2
        E1, psi1, N = lanczos.lanczos(
            sparse.OrthogonalNpcLinearOperator(H_Op, ortho_to), psi_init,
            lanczos_params)
        print("E1 = {E1:.14f} vs exact {E1_flat:.14f}".format(E1=E1,
                                                              E1_flat=E1_flat))
        print("|E1-E1_flat| / |E1_flat| =", abs((E1 - E1_flat) / E1_flat))
        psi1_H_psi1 = npc.inner(psi1,
                                npc.tensordot(H, psi1, axes=[1, 0]),
                                'range',
                                do_conj=True)
        print("<psi1|H|psi1> / E1 = 1 + ", psi1_H_psi1 / E1 - 1.)
        assert (abs(psi1_H_psi1 / E1 - 1.) < tol)
        print("<psi1_flat|H_flat|psi1_flat> / E1_flat = ", end='')
        print(np.inner(psi1_flat.conj(), np.dot(H_flat, psi1_flat)) / E1_flat)
        ov = np.inner(psi1.to_ndarray().conj(), psi1_flat)
        print("|<psi1|psi1_flat>|=", abs(ov))
        assert (abs(1. - abs(ov)) < tol)
        # and finnally check also orthogonality to previous states
        for psi_prev in orthogonal_to:
            ov = npc.inner(psi_prev, psi1, 'range', do_conj=True)
            assert (abs(ov) < tol)
        orthogonal_to.append(psi1)
    if len(orthogonal_to) == 1:
        print(
            "warning: test didn't find a second eigenvector in the same charge sector!"
        )