예제 #1
0
    def test_converting_hubbard_ham(self, Lx, Ly):
        '''Evaluate energy of spinless Hubbard model
        on a random state, using 'qubit numbers' and 
        qubit coordinates to specify target sites. 
        Check energies are equal.
        '''
        psi_trial = qnets.QubitEncodeVector.rand(Lx, Ly, bond_dim=2)
        psi_trial.setup_bmps_contraction_()
        norm, bra, ket = psi_trial.make_norm(return_all=True)
        norm ^= all

        # encoded Fermi-Hubbard with default parameters
        HubbardHam = hams.SpinlessSimHam(Lx, Ly)

        # terms specify qubit coos rather than qubit nums
        CooHam = HubbardHam.convert_to_coordinate_ham(
            qubit_to_coo_map=psi_trial.qubit_to_coo_map)

        # energy computed with HubbardHam
        E1 = 0
        for where, gate in HubbardHam.gen_ham_terms():
            E1 += (bra | ket.apply_gate(
                gate, where, keys='qnumbers', contract=True)) ^ all

        # energy computed with CooHam
        E2 = 0
        for coos, gate in CooHam.gen_ham_terms():
            E2 += (bra | ket.apply_gate(
                gate, where=coos, keys='coos', contract=True)) ^ all

        E1 = E1 / norm
        E2 = E2 / norm

        assert np.allclose(E1, E2)
예제 #2
0
    def test_compute_local_expectation_vs_dense(self, Lx, Ly, normalized):

        # (2Lx-1) * (2Ly-1) lattice ePEPSvector
        epeps = qnets.QubitEncodeVector.rand(Lx, Ly)\
            .convert_to_ePEPS_vector()

        # qubits + dummies
        n_sites = (2 * Lx - 1) * (2 * Ly - 1)
        # vertices + occupied faces in 'original' Lx*Ly lattice
        n_qubits = (Lx * Ly) + int((Lx - 1) * (Ly - 1) / 2)

        # 'qubit' Fermi-Hubbard with random parameters
        t, V, mu = np.random.rand(3)
        H = hams.SpinlessSimHam(Lx, Ly, t, V, mu)

        # separate indices of qubits from 'aux' tensors
        qubit_inds = tuple(
            starmap(epeps.site_ind,
                    (epeps.qubit_to_coo_map[q] for q in range(n_qubits))))
        non_qubit_inds = set(epeps.site_inds) - set(qubit_inds)

        # 'densify' into vector with qubit dimensions first
        psi_dense = epeps.to_dense((*qubit_inds, *non_qubit_inds))
        if normalized:
            qu.normalize(psi_dense)

        dense_terms = [
            qu.pkron(term, dims=[2] * n_sites, inds=where)
            for where, term in H.gen_ham_terms()
        ]

        exact = sum((qu.expec(h, psi_dense) for h in dense_terms))

        # now compute energy with `ePEPSvector.compute_local_expectation`
        q2coo = lambda q: epeps.qubit_to_coo_map[q]
        CooHam = H.convert_to_coordinate_ham(q2coo)
        terms = CooHam._coo_ham_terms

        envs, plaqmap = epeps.calc_plaquette_envs_and_map(terms)
        opts = dict(cutoff=2e-3, max_bond=9, contract_optimize='random-greedy')

        e = epeps.compute_local_expectation(terms,
                                            normalized=normalized,
                                            autogroup=False,
                                            plaquette_envs=envs,
                                            plaquette_map=plaqmap,
                                            **opts)

        assert e == pytest.approx(exact, rel=1e-2)
예제 #3
0
    def test_epeps_absorb_3body_tensor(self, Lx, Ly, method):
        '''Currently only tests 3-body ops!

        contract_methods = {0: False,  1: 'triangle_absorb'}
        '''

        # opts for splitting 'blob' in `triangle_absorb` method
        compress_opts = {'method': method}

        epeps = qnets.QubitEncodeVector.rand(Lx,
                                             Ly).convert_to_ePEPS(dummy_size=1)
        bra = epeps.H

        # compile (vertex, vertex, face) 'target' qubits
        LatticeCooHam = hams.SpinlessSimHam(Lx, Ly).\
            convert_to_coordinate_ham(lambda q: epeps.qubit_to_coo_map[q])

        for coos, _ in LatticeCooHam.gen_ham_terms():

            # SKIP 2-body interactions
            if len(coos) == 2:
                continue

            rand_gate = qu.rand_matrix(8)  #use a random 3-body gate

            G_ket_0 = epeps.gate(G=rand_gate, coos=coos, contract=False)
            G_ket_1 = epeps.gate(G=rand_gate,
                                 coos=coos,
                                 contract='triangle_absorb',
                                 **compress_opts)

            expec_0 = (bra & G_ket_0) ^ all  # `contract=False` reference
            expec_1 = (bra & G_ket_1) ^ all  # `triangle_absorb` reference

            assert expec_1 == pytest.approx(expec_0, rel=1e-2)

            coos = (coos[1], coos[0], coos[2]
                    )  # now try w/ vertex qubits swapped

            G_ket_0 = epeps.gate(G=rand_gate, coos=coos, contract=False)
            G_ket_2 = epeps.gate(G=rand_gate,
                                 coos=coos,
                                 contract='triangle_absorb',
                                 **compress_opts)

            expec_0 = (bra & G_ket_0) ^ all
            expec_2 = (bra & G_ket_2) ^ all
            assert expec_2 == pytest.approx(expec_0, rel=1e-2)
예제 #4
0
    def test_qev_triangle_absorb_method(self, Lx, Ly, method):
        '''Test 'triangle_absorb' method, which works for 
        `QubitEncodeVector`-type geometry without rotating the 
        face tensors (i.e. non-rectangular lattice geometry).
        '''
        # opts for splitting 'blob' in `triangle_absorb` method
        compress_opts = {'method': method}

        # without rotating face tensors!
        psi = qnets.QubitEncodeVector.rand(Lx, Ly, bond_dim=2)
        bra = psi.H
        # norm = (bra & psi) ^ all

        # compile all 3-tuples (vertex, vertex, face) qubits to act on
        LatticeHam = hams.SpinlessSimHam(Lx, Ly)
        for where, _ in LatticeHam.gen_ham_terms():

            # skip 2-body terms
            if len(where) == 2:
                continue

            rand_gate = qu.rand_matrix(8)

            # apply gate both 0) without contracting, and 1) with 'triangle-absorb'
            G_ket_0 = psi.apply_gate(G=rand_gate, where=where, contract=False)
            G_ket_1 = psi.apply_gate(G=rand_gate,
                                     where=where,
                                     contract='triangle_absorb',
                                     **compress_opts)

            expec_0 = (bra & G_ket_0) ^ all
            expec_1 = (bra & G_ket_1) ^ all
            assert expec_1 == pytest.approx(expec_0, rel=1e-2)

            ## also try with vertex qubits switched!
            where = (where[1], where[0], where[2])
            G_ket_0 = psi.apply_gate(G=rand_gate, where=where, contract=False)
            G_ket_2 = psi.apply_gate(G=rand_gate,
                                     where=where,
                                     contract='triangle_absorb',
                                     **compress_opts)

            expec_0 = (bra & G_ket_0) ^ all
            expec_2 = (bra & G_ket_2) ^ all
            assert expec_2 == pytest.approx(expec_0, rel=1e-2)
예제 #5
0
    def test_epeps_absorb_3body_gate(self, Lx, Ly, method):
        '''Test absorbing a 3-body dense, random gate into the tn.
        '''

        # opts for splitting 'blob' in `triangle_absorb` method
        compress_opts = {'method': method}

        epeps = qnets.QubitEncodeVector.rand(Lx,
                                             Ly).convert_to_ePEPS(dummy_size=1)
        bra = epeps.H
        # norm = (bra & epeps) ^ all

        # use Ham to get (vertex, vertex, face) 'target' qubits
        LatticeCooHam = hams.SpinlessSimHam(Lx, Ly).\
            convert_to_coordinate_ham(lambda q: epeps.qubit_to_coo_map[q])

        for coos, _ in LatticeCooHam.gen_ham_terms():

            # skip 2-body interactions
            if len(coos) == 2:
                continue

            rand_gate = qu.rand_matrix(8)  #use a random 3-body gate

            G_ket_0 = epeps.gate(G=rand_gate, coos=coos, contract=False)
            G_ket_1 = epeps.absorb_three_body_gate(G=rand_gate,
                                                   coos=coos,
                                                   **compress_opts)

            expec_0 = (bra & G_ket_0) ^ all  # `contract=False` reference
            expec_1 = (bra & G_ket_1) ^ all  # `triangle_absorb` reference

            assert expec_1 == pytest.approx(expec_0, rel=1e-2)

            # now try with the vertex qubits swapped
            coos = (coos[1], coos[0], coos[2])
            G_ket_0 = epeps.gate(G=rand_gate, coos=coos, contract=False)
            G_ket_2 = epeps.absorb_three_body_gate(G=rand_gate,
                                                   coos=coos,
                                                   **compress_opts)

            expec_0 = (bra & G_ket_0) ^ all
            expec_2 = (bra & G_ket_2) ^ all
            assert expec_2 == pytest.approx(expec_0, rel=1e-2)
예제 #6
0
    def test_epeps_2body_reduce_split(self, Lx, Ly, contract):

        epeps = qnets.QubitEncodeVector.rand(Lx,
                                             Ly).convert_to_ePEPS(dummy_size=1)
        bra = epeps.H

        # compile (vertex, vertex) 'target' qubit pairs
        LatticeCooHam = hams.SpinlessSimHam(Lx, Ly).\
            convert_to_coordinate_ham(lambda q: epeps.qubit_to_coo_map[q])

        for coos, _ in LatticeCooHam.gen_ham_terms():

            # skip 3-body terms here
            if len(coos) == 3:
                continue

            rand_gate = qu.rand_matrix(4)

            G_ket_0 = epeps.gate(G=rand_gate, coos=coos, contract=False)
            G_ket_1 = epeps.gate(G=rand_gate, coos=coos, contract=contract)

            assert (bra & G_ket_1) ^ all == pytest.approx(
                (bra & G_ket_0) ^ all, rel=1e-2)
예제 #7
0
    def test_compute_local_expectation(self, Lx, Ly, normalized):

        # 'qubit' Fermi-Hubbard with default parameters
        t, V, mu = np.random.rand(3)
        H = hams.SpinlessSimHam(Lx, Ly, t, V, mu)

        psi_qev = qnets.QubitEncodeVector.rand(Lx, Ly)\
            .setup_bmps_contraction_()
        norm, bra, ket = psi_qev.make_norm(return_all=True)
        norm ^= all

        Exact = sum(((bra | ket.apply_gate(gate, where)) ^ all
                     for where, gate in H.gen_ham_terms()))

        if normalized:
            Exact /= norm

        # Now compute with `ePEPSvector.compute_local_expectation`

        epeps = psi_qev.convert_to_ePEPS_vector()

        q2coo = lambda q: epeps.qubit_to_coo_map[q]
        CooHam = H.convert_to_coordinate_ham(q2coo)
        terms = CooHam._coo_ham_terms

        envs, plaqmap = epeps.calc_plaquette_envs_and_map(terms)
        opts = dict(cutoff=2e-3, max_bond=9, contract_optimize='random-greedy')

        e = epeps.compute_local_expectation(terms,
                                            normalized=normalized,
                                            autogroup=False,
                                            plaquette_envs=envs,
                                            plaquette_map=plaqmap,
                                            **opts)

        assert e == pytest.approx(Exact, rel=1e-2)
예제 #8
0
    def test_epeps_vs_qev_absorb_gate(self, Lx, Ly, method, tn_format):
        '''Test that we get same result (for 3-body interactions)
        whether we evaluate with a ``QubitEncodeVector`` or the 
        2D-regular-lattice version ``ePEPS``.

        Methods tested:
        ---------------
            QubitEncodeVector.apply_gate(..., contract='triangle_absorb)
            ePEPS.absorb_three_body_gate(...)
        '''
        # opts for splitting 'blob' in `triangle_absorb` method
        compress_opts = {'method': method}

        # without rotating face tensors!
        psi = qnets.QubitEncodeVector.rand(Lx, Ly, bond_dim=2)
        bra = psi.H

        # make into 'regular' 2D-square-lattice TN
        if tn_format == 'epeps':
            psi_2d = psi.convert_to_ePEPS(dummy_size=1)

        elif tn_format == 'epeps_vec':
            psi_2d = psi.convert_to_ePEPS_vector(dummy_size=1)

        bra_2d = psi_2d.H

        Ham = hams.SpinlessSimHam(Lx, Ly)

        # LatticeCooHam = Ham.convert_to_coordinate_ham().\
        #     convert_to_coordinate_ham(psi_2d.qubit_to_coo_map)

        for where, _ in Ham.gen_ham_terms():

            # skip 2-body interactions
            if len(where) == 2:
                continue

            coos = [psi_2d.qubit_to_coo_map[q] for q in where]

            rand_gate = qu.rand_matrix(8)  #use a random 3-body gate

            G_psi = psi.apply_gate(G=rand_gate,
                                   where=where,
                                   contract='triangle_absorb',
                                   **compress_opts)
            expec_QEV = (bra & G_psi) ^ all

            G_psi_2d = psi_2d.absorb_three_body_gate(G=rand_gate,
                                                     coos=coos,
                                                     **compress_opts)
            expec_ePEPS = (bra_2d & G_psi_2d) ^ all

            assert expec_ePEPS == pytest.approx(expec_QEV, rel=1e-2)

            # now try with vertex qubits swapped
            where = (where[1], where[0], where[2])
            coos = [psi_2d.qubit_to_coo_map[q] for q in where]

            # do the same test
            G_psi = psi.apply_gate(G=rand_gate,
                                   where=where,
                                   contract='triangle_absorb',
                                   **compress_opts)
            expec_QEV = (bra & G_psi) ^ all
            G_psi_2d = psi_2d.absorb_three_body_gate(G=rand_gate,
                                                     coos=coos,
                                                     **compress_opts)
            expec_ePEPS = (bra_2d & G_psi_2d) ^ all
            assert expec_ePEPS == pytest.approx(expec_QEV, rel=1e-2)