Beispiel #1
0
def test_solver_via_rdms():
    molecule = build_lih_moleculardata()
    n_electrons = molecule.n_electrons
    sz = 0
    oei, tei = molecule.get_integrals()
    elec_hamil = fqe.restricted_hamiltonian.RestrictedHamiltonian(
        (oei, np.einsum("ijlk", -0.5 * tei)))
    soei, stei = spinorb_from_spatial(oei, tei)
    astei = np.einsum('ijkl', stei) - np.einsum('ijlk', stei)
    molecular_hamiltonian = of.InteractionOperator(0, soei, 0.25 * astei)
    reduced_ham = of.chem.make_reduced_hamiltonian(molecular_hamiltonian,
                                                   molecule.n_electrons)

    fqe_wf = fqe.Wavefunction([[n_electrons, sz, molecule.n_orbitals]])
    graph = fqe_wf.sector((n_electrons, sz)).get_fcigraph()
    fci_coeffs = np.zeros((graph.lena(), graph.lenb()), dtype=np.complex128)
    fci_coeffs[0, 0] = 1.0
    fqe_wf.set_wfn(strategy="from_data",
                   raw_data={(n_electrons, sz): fci_coeffs})

    bcsolve = BrillouinCondition(molecule, run_parallel=False)
    assert bcsolve.reduced_ham == reduced_ham
    for pp, qq in zip(elec_hamil.tensors(), bcsolve.elec_hamil.tensors()):
        assert np.allclose(pp, qq)

    bcsolve.iter_max = 1
    bcsolve.bc_solve_rdms(fqe_wf)
    assert np.allclose(bcsolve.acse_energy,
                       [-8.957417182801088, -8.969256797233033])
Beispiel #2
0
def test_get_l_m():
    molecule = build_lih_moleculardata()
    oei, tei = molecule.get_integrals()
    lrt_obj = LowRankTrotter(oei=oei, tei=tei)
    num_l, m_list = lrt_obj.get_l_and_m(1.0e-8, 1.0e-8)
    assert isinstance(num_l, int)
    assert isinstance(m_list, list)
    assert len(m_list) == num_l
Beispiel #3
0
def test_initialization():
    empty = LowRankTrotter()
    obj_attributes = ["molecule", "oei", "tei", "icut", "lmax", "mcut", "mmax"]
    for oa in obj_attributes:
        assert hasattr(empty, oa)

    molecule = build_lih_moleculardata()
    oei, tei = molecule.get_integrals()
    molecule_load = LowRankTrotter(molecule=molecule)
    assert np.allclose(molecule_load.oei, oei)
    assert np.allclose(molecule_load.tei, tei)
    assert np.isclose(molecule_load.icut, 1.0e-8)
    assert np.isclose(molecule_load.mcut, 1.0e-8)
Beispiel #4
0
def test_second_factorization():
    molecule = build_lih_moleculardata()
    oei, tei = molecule.get_integrals()
    lrt_obj = LowRankTrotter(oei=oei, tei=tei)
    eigenvalues, one_body_squares, _ = lrt_obj.first_factorization()

    s_rho_rho, basis_changes = lrt_obj.second_factorization(
        eigenvalues, one_body_squares)
    true_basis_changes = []
    for l in range(one_body_squares.shape[0]):
        w, v = np.linalg.eigh(one_body_squares[l][::2, ::2])
        true_basis_changes.append(v.conj().T)
        assert np.allclose(v.conj().T, basis_changes[l])

        assert np.allclose(s_rho_rho[l], eigenvalues[l] * np.outer(w, w))
Beispiel #5
0
def test_vbc():
    molecule = build_lih_moleculardata()
    n_electrons = molecule.n_electrons
    oei, tei = molecule.get_integrals()
    nalpha = molecule.n_electrons // 2
    nbeta = nalpha
    sz = nalpha - nbeta

    fqe_wf = fqe.Wavefunction([[n_electrons, sz, molecule.n_orbitals]])
    fqe_wf.set_wfn(strategy='hartree-fock')

    adapt = VBC(oei, tei, nalpha, nbeta, iter_max=1, verbose=False)
    adapt.vbc(fqe_wf)
    assert np.isclose(adapt.energies[0], -8.957417182801091)
    assert np.isclose(adapt.energies[-1], -8.97304439380826)
Beispiel #6
0
def test_trotter_prep():
    times = [0.1, 0.2, 0.3]
    molecule = build_lih_moleculardata()
    oei, tei = molecule.get_integrals()
    lrt_obj = LowRankTrotter(oei=oei, tei=tei)
    (
        eigenvalues,
        one_body_squares,
        one_body_correction,
    ) = lrt_obj.first_factorization()
    (
        scaled_density_density_matrices,
        basis_change_matrices,
    ) = lrt_obj.second_factorization(eigenvalues, one_body_squares)

    for tt in times:
        # get values from function to test
        test_tbasis, test_srr = lrt_obj.prepare_trotter_sequence(tt)

        # compute true values
        trotter_basis_change = [
            basis_change_matrices[0] @ expm(
                -1j * tt * (lrt_obj.oei + one_body_correction[::2, ::2]))
        ]
        time_scaled_rho_rho_matrices = []
        for ii in range(len(basis_change_matrices) - 1):
            trotter_basis_change.append(basis_change_matrices[ii + 1]
                                        @ basis_change_matrices[ii].conj().T)
            time_scaled_rho_rho_matrices.append(
                tt * scaled_density_density_matrices[ii])
        time_scaled_rho_rho_matrices.append(tt *
                                            scaled_density_density_matrices[-1])
        trotter_basis_change.append(basis_change_matrices[ii + 1].conj().T)

        assert len(trotter_basis_change) == len(test_tbasis)
        assert len(time_scaled_rho_rho_matrices) == len(test_srr)
        # check against true values
        for t1, t2 in zip(trotter_basis_change, test_tbasis):
            assert np.allclose(t1, t2)
            assert np.allclose(t1.conj().T @ t1, np.eye(t1.shape[0]))

        for t1, t2 in zip(test_srr, time_scaled_rho_rho_matrices):
            assert np.allclose(t1, t2)
            assert of.is_hermitian(t1)
def test_adapt():
    molecule = build_lih_moleculardata()
    n_electrons = molecule.n_electrons
    oei, tei = molecule.get_integrals()
    norbs = molecule.n_orbitals
    nalpha = molecule.n_electrons // 2
    nbeta = nalpha
    sz = nalpha - nbeta
    occ = list(range(nalpha))
    virt = list(range(nalpha, norbs))
    soei, stei = spinorb_from_spatial(oei, tei)
    astei = np.einsum('ijkl', stei) - np.einsum('ijlk', stei)
    molecular_hamiltonian = of.InteractionOperator(0, soei, 0.25 * astei)
    reduced_ham = of.chem.make_reduced_hamiltonian(molecular_hamiltonian,
                                                   molecule.n_electrons)

    fqe_wf = fqe.Wavefunction([[n_electrons, sz, molecule.n_orbitals]])
    fqe_wf.set_wfn(strategy='hartree-fock')

    sop = OperatorPool(norbs, occ, virt)
    sop.two_body_sz_adapted()  # initialize pool
    adapt = ADAPT(oei, tei, sop, nalpha, nbeta, iter_max=1, verbose=False)
    assert np.isclose(
        np.linalg.norm(adapt.reduced_ham.two_body_tensor -
                       reduced_ham.two_body_tensor), 0)

    adapt.adapt_vqe(fqe_wf)
    assert np.isclose(adapt.energies[0], -8.957417182801091)
    assert np.isclose(adapt.energies[-1], -8.970532463968661)

    sop = OperatorPool(norbs, occ, virt)
    sop.one_body_sz_adapted()
    adapt = ADAPT(oei,
                  tei,
                  sop,
                  nalpha,
                  nbeta,
                  iter_max=10,
                  stopping_epsilon=10,
                  verbose=True)
    adapt.adapt_vqe(fqe_wf)
    assert np.isclose(adapt.energies[-1], -8.957417182801091)
    assert np.isclose(adapt.energies[0], -8.95741717733075)
Beispiel #8
0
def test_first_factorization():
    molecule = build_lih_moleculardata()
    oei, tei = molecule.get_integrals()
    lrt_obj = LowRankTrotter(oei=oei, tei=tei)
    (
        eigenvalues,
        one_body_squares,
        one_body_correction,
    ) = lrt_obj.first_factorization()

    # get true op
    n_qubits = molecule.n_qubits
    fermion_tei = of.FermionOperator()
    test_tei_tensor = np.zeros((n_qubits, n_qubits, n_qubits, n_qubits))
    for p, q, r, s in product(range(oei.shape[0]), repeat=4):
        if np.abs(tei[p, q, r, s]) < EQ_TOLERANCE:
            coefficient = 0.0
        else:
            coefficient = tei[p, q, r, s] / 2.0

        for sigma, tau in product(range(2), repeat=2):
            if 2 * p + sigma == 2 * q + tau or 2 * r + tau == 2 * s + sigma:
                continue
            term = (
                (2 * p + sigma, 1),
                (2 * q + tau, 1),
                (2 * r + tau, 0),
                (2 * s + sigma, 0),
            )
            fermion_tei += of.FermionOperator(term, coefficient=coefficient)
            test_tei_tensor[2 * p + sigma, 2 * q + tau, 2 * r + tau, 2 * s +
                            sigma] = coefficient

    mol_ham = of.InteractionOperator(
        one_body_tensor=np.zeros((n_qubits, n_qubits)),
        two_body_tensor=test_tei_tensor,
        constant=0,
    )

    # check induced norm on operator
    checked_op = of.FermionOperator()
    for (
            p,
            q,
    ) in product(range(n_qubits), repeat=2):
        term = ((p, 1), (q, 0))
        coefficient = one_body_correction[p, q]
        checked_op += of.FermionOperator(term, coefficient)

    # Build back two-body component.
    for l in range(one_body_squares.shape[0]):
        one_body_operator = of.FermionOperator()
        for p, q in product(range(n_qubits), repeat=2):
            term = ((p, 1), (q, 0))
            coefficient = one_body_squares[l, p, q]
            one_body_operator += of.FermionOperator(term, coefficient)
        checked_op += eigenvalues[l] * (one_body_operator**2)

    true_fop = of.normal_ordered(of.get_fermion_operator(mol_ham))
    difference = of.normal_ordered(checked_op - true_fop)
    assert np.isclose(0, difference.induced_norm())
Beispiel #9
0
def test_generalized_doubles_takagi():
    molecule = build_lih_moleculardata()
    oei, tei = molecule.get_integrals()
    nele = 4
    nalpha = 2
    nbeta = 2
    sz = 0
    norbs = oei.shape[0]
    nso = 2 * norbs
    fqe_wf = fqe.Wavefunction([[nele, sz, norbs]])
    fqe_wf.set_wfn(strategy='hartree-fock')
    fqe_wf.normalize()
    _, tpdm = fqe_wf.sector((nele, sz)).get_openfermion_rdms()
    d3 = fqe_wf.sector((nele, sz)).get_three_pdm()

    soei, stei = spinorb_from_spatial(oei, tei)
    astei = np.einsum('ijkl', stei) - np.einsum('ijlk', stei)
    molecular_hamiltonian = of.InteractionOperator(0, soei, 0.25 * astei)
    reduced_ham = make_reduced_hamiltonian(molecular_hamiltonian,
                                           nalpha + nbeta)
    acse_residual = two_rdo_commutator_symm(reduced_ham.two_body_tensor, tpdm,
                                            d3)
    for p, q, r, s in product(range(nso), repeat=4):
        if p == q or r == s:
            continue
        assert np.isclose(acse_residual[p, q, r, s],
                          -acse_residual[s, r, q, p].conj())

    Zlp, Zlm, _, one_body_residual = doubles_factorization_takagi(acse_residual)
    test_fop = get_fermion_op(one_body_residual)
    # test the first four factors
    for ll in range(4):
        test_fop += 0.25 * get_fermion_op(Zlp[ll])**2
        test_fop += 0.25 * get_fermion_op(Zlm[ll])**2

        op1mat = Zlp[ll]
        op2mat = Zlm[ll]
        w1, v1 = sp.linalg.schur(op1mat)
        w1 = np.diagonal(w1)
        assert np.allclose(v1 @ np.diag(w1) @ v1.conj().T, op1mat)

        v1c = v1.conj()
        w2, v2 = sp.linalg.schur(op2mat)
        w2 = np.diagonal(w2)
        assert np.allclose(v2 @ np.diag(w2) @ v2.conj().T, op2mat)
        oww1 = np.outer(w1, w1)

        fqe_wf = fqe.Wavefunction([[nele, sz, norbs]])
        fqe_wf.set_wfn(strategy='hartree-fock')
        fqe_wf.normalize()
        nfqe_wf = fqe.get_number_conserving_wavefunction(nele, norbs)
        nfqe_wf.sector((nele, sz)).coeff = fqe_wf.sector((nele, sz)).coeff

        this_generatory = np.einsum('pi,si,ij,qj,rj->pqrs', v1, v1c, oww1, v1,
                                    v1c)
        fop = of.FermionOperator()
        for p, q, r, s in product(range(nso), repeat=4):
            op = ((p, 1), (s, 0), (q, 1), (r, 0))
            fop += of.FermionOperator(op,
                                      coefficient=this_generatory[p, q, r, s])

        fqe_fop = build_hamiltonian(1j * fop, norb=norbs, conserve_number=True)
        exact_wf = fqe.apply_generated_unitary(nfqe_wf, 1, 'taylor', fqe_fop)

        test_wf = fqe.algorithm.low_rank.evolve_fqe_givens_unrestricted(
            nfqe_wf,
            v1.conj().T)
        test_wf = fqe.algorithm.low_rank.evolve_fqe_charge_charge_unrestricted(
            test_wf, -oww1.imag)
        test_wf = fqe.algorithm.low_rank.evolve_fqe_givens_unrestricted(
            test_wf, v1)

        assert np.isclose(abs(fqe.vdot(test_wf, exact_wf))**2, 1)