Exemple #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])
Exemple #2
0
def test_trotter_ansatzes_default_initial_params_iterations_1(
        ansatz_factory, trotter_algorithm, order, hamiltonian, atol):
    """Check that a Trotter ansatz with one iteration and default parameters
    is consistent with time evolution with one Trotter step."""

    ansatz = ansatz_factory(hamiltonian, iterations=1)
    objective = HamiltonianObjective(hamiltonian)

    qubits = ansatz.qubits

    if isinstance(hamiltonian, openfermion.DiagonalCoulombHamiltonian):
        one_body = hamiltonian.one_body
    elif isinstance(hamiltonian, openfermion.InteractionOperator):
        one_body = hamiltonian.one_body_tensor

    preparation_circuit = cirq.Circuit.from_ops(
        prepare_gaussian_state(qubits,
                               openfermion.QuadraticHamiltonian(one_body),
                               occupied_orbitals=range(len(qubits) // 2)))

    # Compute value using ansatz circuit and objective
    circuit = (preparation_circuit +
               ansatz.circuit).with_parameters_resolved_by(
                   ansatz.param_resolver(ansatz.default_initial_params()))
    result = circuit.apply_unitary_effect_to_state(
        qubit_order=ansatz.qubit_permutation(qubits))
    obj_val = objective.value(result)

    # Compute value using study
    study = VariationalStudy('study',
                             ansatz,
                             objective,
                             preparation_circuit=preparation_circuit)
    study_val = study.value_of(ansatz.default_initial_params())

    # Compute value by simulating time evolution
    if isinstance(hamiltonian, openfermion.DiagonalCoulombHamiltonian):
        half_way_hamiltonian = openfermion.DiagonalCoulombHamiltonian(
            one_body=hamiltonian.one_body, two_body=0.5 * hamiltonian.two_body)
    elif isinstance(hamiltonian, openfermion.InteractionOperator):
        half_way_hamiltonian = openfermion.InteractionOperator(
            constant=hamiltonian.constant,
            one_body_tensor=hamiltonian.one_body_tensor,
            two_body_tensor=0.5 * hamiltonian.two_body_tensor)

    simulation_circuit = cirq.Circuit.from_ops(
        simulate_trotter(qubits,
                         half_way_hamiltonian,
                         time=ansatz.adiabatic_evolution_time,
                         n_steps=1,
                         order=order,
                         algorithm=trotter_algorithm))
    final_state = (preparation_circuit +
                   simulation_circuit).apply_unitary_effect_to_state()
    correct_val = openfermion.expectation(objective._hamiltonian_linear_op,
                                          final_state).real

    numpy.testing.assert_allclose(obj_val, study_val, atol=atol)
    numpy.testing.assert_allclose(obj_val, correct_val, atol=atol)
Exemple #3
0
def test_fqe_givens():
    """Test Givens Rotation evolution for correctness."""
    # set up
    norbs = 4
    n_elec = norbs
    sz = 0
    n_qubits = 2 * norbs
    time = 0.126
    fqe_wfn = fqe.Wavefunction([[n_elec, sz, norbs]])
    fqe_wfn.set_wfn(strategy="random")
    ikappa = random_quadratic_hamiltonian(
        norbs,
        conserves_particle_number=True,
        real=False,
        expand_spin=False,
        seed=2,
    )
    fqe_ham = RestrictedHamiltonian((ikappa.n_body_tensors[1, 0], ))
    u = expm(-1j * ikappa.n_body_tensors[1, 0] * time)

    # time-evolve
    final_fqe_wfn = fqe_wfn.time_evolve(time, fqe_ham)
    spin_ham = np.kron(ikappa.n_body_tensors[1, 0], np.eye(2))
    assert of.is_hermitian(spin_ham)
    ikappa_spin = of.InteractionOperator(
        constant=0,
        one_body_tensor=spin_ham,
        two_body_tensor=np.zeros((n_qubits, n_qubits, n_qubits, n_qubits)),
    )
    bigU = expm(-1j * of.get_sparse_operator(ikappa_spin).toarray() * time)
    initial_wf = fqe.to_cirq(fqe_wfn).reshape((-1, 1))
    final_wf = bigU @ initial_wf
    final_wfn_test = fqe.from_cirq(final_wf.flatten(), 1.0e-12)

    assert np.allclose(final_fqe_wfn.rdm("i^ j"), final_wfn_test.rdm("i^ j"))
    assert np.allclose(final_fqe_wfn.rdm("i^ j^ k l"),
                       final_wfn_test.rdm("i^ j^ k l"))

    final_wfn_test2 = fqe.from_cirq(
        evolve_wf_givens(initial_wf.copy(), u.copy()).flatten(), 1.0e-12)
    givens_fqe_wfn = evolve_fqe_givens(fqe_wfn, u.copy())
    assert np.allclose(givens_fqe_wfn.rdm("i^ j"), final_wfn_test2.rdm("i^ j"))
    assert np.allclose(givens_fqe_wfn.rdm("i^ j^ k l"),
                       final_wfn_test2.rdm("i^ j^ k l"))
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)
Exemple #5
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())
Exemple #6
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)
def test_trotter_ansatzes_default_initial_params_iterations_2(
        ansatz, trotter_algorithm, order, hamiltonian, atol):
    """Check that a Trotter ansatz with two iterations and default parameters
    is consistent with time evolution with two Trotter steps."""

    objective = HamiltonianObjective(hamiltonian)

    qubits = ansatz.qubits

    if isinstance(hamiltonian, openfermion.DiagonalCoulombHamiltonian):
        one_body = hamiltonian.one_body
    elif isinstance(hamiltonian, openfermion.InteractionOperator):
        one_body = hamiltonian.one_body_tensor

    if isinstance(ansatz, SwapNetworkTrotterHubbardAnsatz):
        occupied_orbitals = (range(len(qubits) // 4), range(len(qubits) // 4))
    else:
        occupied_orbitals = range(len(qubits) // 2)

    preparation_circuit = cirq.Circuit(
        prepare_gaussian_state(qubits,
                               openfermion.QuadraticHamiltonian(one_body),
                               occupied_orbitals=occupied_orbitals))

    # Compute value using ansatz circuit and objective
    circuit = cirq.resolve_parameters(
        preparation_circuit + ansatz.circuit,
        ansatz.param_resolver(ansatz.default_initial_params()))
    result = circuit.final_wavefunction(
        qubit_order=ansatz.qubit_permutation(qubits))
    obj_val = objective.value(result)

    # Compute value using study
    study = VariationalStudy('study',
                             ansatz,
                             objective,
                             preparation_circuit=preparation_circuit)
    study_val = study.value_of(ansatz.default_initial_params())

    # Compute value by simulating time evolution
    if isinstance(hamiltonian, openfermion.DiagonalCoulombHamiltonian):
        quarter_way_hamiltonian = openfermion.DiagonalCoulombHamiltonian(
            one_body=hamiltonian.one_body,
            two_body=0.25 * hamiltonian.two_body)
        three_quarters_way_hamiltonian = openfermion.DiagonalCoulombHamiltonian(
            one_body=hamiltonian.one_body,
            two_body=0.75 * hamiltonian.two_body)
    elif isinstance(hamiltonian, openfermion.InteractionOperator):
        quarter_way_hamiltonian = openfermion.InteractionOperator(
            constant=hamiltonian.constant,
            one_body_tensor=hamiltonian.one_body_tensor,
            two_body_tensor=0.25 * hamiltonian.two_body_tensor)
        three_quarters_way_hamiltonian = openfermion.InteractionOperator(
            constant=hamiltonian.constant,
            one_body_tensor=hamiltonian.one_body_tensor,
            two_body_tensor=0.75 * hamiltonian.two_body_tensor)

    simulation_circuit = cirq.Circuit(
        simulate_trotter(qubits,
                         quarter_way_hamiltonian,
                         time=0.5 * ansatz.adiabatic_evolution_time,
                         n_steps=1,
                         order=order,
                         algorithm=trotter_algorithm),
        simulate_trotter(qubits,
                         three_quarters_way_hamiltonian,
                         time=0.5 * ansatz.adiabatic_evolution_time,
                         n_steps=1,
                         order=order,
                         algorithm=trotter_algorithm))
    final_state = (preparation_circuit +
                   simulation_circuit).final_wavefunction()
    correct_val = openfermion.expectation(objective._hamiltonian_linear_op,
                                          final_state).real

    numpy.testing.assert_allclose(obj_val, study_val, atol=atol)
    numpy.testing.assert_allclose(obj_val, correct_val, atol=atol)