示例#1
0
def test_prepare_gaussian_state(n_qubits,
                                conserves_particle_number,
                                occupied_orbitals,
                                initial_state,
                                atol=1e-5):

    qubits = LineQubit.range(n_qubits)
    if isinstance(initial_state, list):
        initial_state = sum(1 << (n_qubits - 1 - i) for i in initial_state)

    # Initialize a random quadratic Hamiltonian
    quad_ham = random_quadratic_hamiltonian(
            n_qubits, conserves_particle_number, real=False)
    quad_ham_sparse = get_sparse_operator(quad_ham)

    # Compute the energy of the desired state
    if occupied_orbitals is None:
        energy = quad_ham.ground_energy()
    else:
        orbital_energies, _, constant = (
                quad_ham.diagonalizing_bogoliubov_transform())
        energy = sum(orbital_energies[i] for i in occupied_orbitals) + constant

    # Get the state using a circuit simulation
    circuit = cirq.Circuit.from_ops(
            prepare_gaussian_state(
                qubits, quad_ham, occupied_orbitals,
                initial_state=initial_state))
    state = circuit.apply_unitary_effect_to_state(initial_state)

    # Check that the result is an eigenstate with the correct eigenvalue
    numpy.testing.assert_allclose(
            quad_ham_sparse.dot(state), energy * state, atol=atol)
示例#2
0
    def kevin_hubbard_cirq(self):
        # Create Hubbard model Hamiltonian
        # --------------------------------
        x_dim = 3
        y_dim = 2
        n_sites = x_dim * y_dim
        n_modes = 2 * n_sites

        tunneling = 1.0
        coulomb = 4.0

        hubbard_model = of.fermi_hubbard(x_dim, y_dim, tunneling, coulomb)

        # Reorder indices
        hubbard_model = of.reorder(hubbard_model, of.up_then_down)

        # Convert to DiagonalCoulombHamiltonian
        hubbard_hamiltonian = of.get_diagonal_coulomb_hamiltonian(
            hubbard_model)

        # Create qubits
        qubits = cirq.LineQubit.range(n_modes)

        # State preparation circuit for eigenstate of one-body term
        # ---------------------------------------------------------
        # Set the pseudo-particle orbitals to fill
        up_orbitals = range(n_sites // 2)
        down_orbitals = range(n_sites // 2)

        # Create the circuit
        hubbard_state_preparation_circuit = cirq.Circuit.from_ops(
            ofc.prepare_gaussian_state(
                qubits,
                of.QuadraticHamiltonian(hubbard_hamiltonian.one_body),
                occupied_orbitals=(up_orbitals, down_orbitals)),
            strategy=cirq.InsertStrategy.EARLIEST)

        # Trotter simulation circuit
        # --------------------------
        n_steps = 10
        order = 0

        hubbard_simulation_circuit = cirq.Circuit.from_ops(
            ofc.simulate_trotter(qubits,
                                 hubbard_hamiltonian,
                                 time=1.0,
                                 n_steps=n_steps,
                                 order=order,
                                 algorithm=ofc.trotter.LINEAR_SWAP_NETWORK),
            strategy=cirq.InsertStrategy.EARLIEST)

        t0 = time.time()
        self.kevin_optimize_circuit(hubbard_state_preparation_circuit)
        self.kevin_optimize_circuit(hubbard_simulation_circuit)
        t1 = time.time()

        # print('Optimizing circuits took {} seconds'.format(t1 - t0))
        # print(hubbard_state_preparation_circuit.to_text_diagram(transpose=True))

        return hubbard_state_preparation_circuit, hubbard_simulation_circuit
示例#3
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)
示例#4
0
def test_prepare_gaussian_state_with_spin_symmetry(n_spatial_orbitals,
                                                   conserves_particle_number,
                                                   occupied_orbitals,
                                                   initial_state,
                                                   atol=1e-5):

    n_qubits = 2 * n_spatial_orbitals
    qubits = LineQubit.range(n_qubits)

    # Initialize a random quadratic Hamiltonian
    quad_ham = random_quadratic_hamiltonian(
            n_spatial_orbitals,
            conserves_particle_number,
            real=True,
            expand_spin=True,
            seed=639)

    # Reorder the Hamiltonian and get sparse matrix
    quad_ham = openfermion.get_quadratic_hamiltonian(
            openfermion.reorder(
                openfermion.get_fermion_operator(quad_ham),
                openfermion.up_then_down)
    )
    quad_ham_sparse = get_sparse_operator(quad_ham)

    # Compute the energy of the desired state
    energy = 0.0
    for spin_sector in range(2):
        orbital_energies, _, _ = (
            quad_ham.diagonalizing_bogoliubov_transform(
                spin_sector=spin_sector)
        )
        energy += sum(orbital_energies[i]
                      for i in occupied_orbitals[spin_sector])
    energy += quad_ham.constant

    # Get the state using a circuit simulation
    circuit = cirq.Circuit.from_ops(
            prepare_gaussian_state(
                qubits, quad_ham, occupied_orbitals,
                initial_state=initial_state))

    if isinstance(initial_state, list):
        initial_state = sum(1 << (n_qubits - 1 - i) for i in initial_state)
    state = circuit.apply_unitary_effect_to_state(initial_state)

    # Check that the result is an eigenstate with the correct eigenvalue
    numpy.testing.assert_allclose(
            quad_ham_sparse.dot(state), energy * state, atol=atol)
def test_trotter_ansatzes_evaluate_order_2(ansatz_factory, trotter_algorithm,
                                           hamiltonian, atol):
    """Check that a Trotter ansatz with two iterations and default parameters
    is consistent with time evolution with two Trotter steps."""

    ansatz = ansatz_factory(hamiltonian, iterations=2)
    qubits = ansatz.qubits

    preparation_circuit = cirq.Circuit.from_ops(
        prepare_gaussian_state(qubits,
                               openfermion.QuadraticHamiltonian(
                                   hamiltonian.one_body),
                               occupied_orbitals=range(len(qubits) // 2)))
    study = HamiltonianVariationalStudy(
        'study', ansatz, hamiltonian, preparation_circuit=preparation_circuit)

    simulator = cirq.google.XmonSimulator()

    # Compute value using ansatz
    val = study.evaluate(study.default_initial_params())

    # Compute value by simulating time evolution
    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)
    simulation_circuit = cirq.Circuit.from_ops(
        simulate_trotter(qubits,
                         quarter_way_hamiltonian,
                         time=0.5 * ansatz.adiabatic_evolution_time,
                         n_steps=1,
                         order=1,
                         algorithm=trotter_algorithm),
        simulate_trotter(qubits,
                         three_quarters_way_hamiltonian,
                         time=0.5 * ansatz.adiabatic_evolution_time,
                         n_steps=1,
                         order=1,
                         algorithm=trotter_algorithm))
    circuit = preparation_circuit + simulation_circuit
    result = simulator.simulate(circuit)
    final_state = result.final_state
    correct_val = openfermion.expectation(study._hamiltonian_linear_op,
                                          final_state).real

    numpy.testing.assert_allclose(val, correct_val, atol=atol)
示例#6
0
    def kevin_lih_cirq(self):
        x_dim = 3
        y_dim = 2
        n_sites = x_dim * y_dim
        n_modes = 2 * n_sites

        # Create LiH Hamiltonian
        # ----------------------
        bond_length = 1.45
        geometry = [('Li', (0., 0., 0.)), ('H', (0., 0., bond_length))]
        n_active_electrons = 4
        n_active_orbitals = 4
        lih_hamiltonian = of.load_molecular_hamiltonian(
            geometry, 'sto-3g', 1, format(bond_length), n_active_electrons,
            n_active_orbitals)

        # Generate qubits
        n_qubits = of.count_qubits(lih_hamiltonian)
        qubits = cirq.LineQubit.range(n_qubits)

        # State preparation circuit for eigenstate of one-body term
        # ---------------------------------------------------------
        # Set the pseudo-particle orbitals to fill
        occupied_orbitals = range(n_qubits // 2)

        # State preparation circuit for eigenstate of one-body term
        # ---------------------------------------------------------
        # Set the pseudo-particle orbitals to fill
        up_orbitals = range(n_sites // 2)
        down_orbitals = range(n_sites // 2)

        # Create the circuit
        lih_state_preparation_circuit = cirq.Circuit.from_ops(
            ofc.prepare_gaussian_state(
                qubits,
                of.QuadraticHamiltonian(lih_hamiltonian.one_body_tensor),
                occupied_orbitals=(up_orbitals, down_orbitals)),
            strategy=cirq.InsertStrategy.EARLIEST)

        # Trotter simulation circuit
        # --------------------------
        n_steps = 10
        order = 0

        lih_simulation_circuit = cirq.Circuit.from_ops(
            ofc.simulate_trotter(qubits,
                                 lih_hamiltonian,
                                 time=1.0,
                                 n_steps=n_steps,
                                 order=order,
                                 algorithm=ofc.trotter.LOW_RANK),
            strategy=cirq.InsertStrategy.EARLIEST)

        t0 = time.time()
        self.kevin_optimize_circuit(lih_state_preparation_circuit)
        self.kevin_optimize_circuit(lih_simulation_circuit)
        t1 = time.time()

        # print('Optimizing circuits took {} seconds'.format(t1 - t0))
        # print(lih_state_preparation_circuit.to_text_diagram(transpose=True))

        return lih_state_preparation_circuit, lih_simulation_circuit
# Define the objective function
objective = openfermioncirq.HamiltonianObjective(hamiltonian)

# Create a swap network Trotter ansatz.
iterations = 1  # This is the number of Trotter steps to use in the ansatz.
ansatz = openfermioncirq.SwapNetworkTrotterAnsatz(hamiltonian,
                                                  iterations=iterations)

print('Created a variational ansatz with the following circuit:')
print(ansatz.circuit.to_text_diagram(transpose=True))

# Use preparation circuit for mean-field state
import cirq
preparation_circuit = cirq.Circuit(
    openfermioncirq.prepare_gaussian_state(
        ansatz.qubits,
        openfermion.QuadraticHamiltonian(hamiltonian.one_body),
        occupied_orbitals=range(n_electrons)))

kc_simulator = cirq.KnowledgeCompilationSimulator(preparation_circuit +
                                                  ansatz.circuit,
                                                  initial_state=0)

# Create a Hamiltonian variational study
study = openfermioncirq.VariationalStudy(
    'jellium_study',
    ansatz,
    objective,
    preparation_circuit=preparation_circuit)

print("Created a variational study with {} qubits and {} parameters".format(
    len(study.ansatz.qubits), study.num_params))
示例#8
0
def get_qubit_hamiltonian(g, basis, charge=0, spin=1, qubit_transf='jw'):

    ## Create OpenFermion molecule
    #mol = gto.Mole()
    #mol.atom = g
    #mol.basis = basis
    #mol.spin = spin
    #mol.charge = charge
    #mol.symmetry = False
    ##mol.max_memory = 1024
    #mol.build()

    multiplicity = spin + 1  # spin here is 2S ?
    mol = MolecularData(g, basis, multiplicity, charge)
    #mol.load()

    # Convert to PySCF molecule and run SCF
    print("Running run_pyscf...")
    print(f"Time: {time()}")
    print("=" * 20)
    mol = run_pyscf(mol)

    # Freeze some orbitals?
    occupied_indices = None
    active_indices = None

    #import pdb; pdb.set_trace()

    # Try:
    occupied_indices = range(183)
    active_indices = range(15)
    # when it stops lagging

    # Get Hamiltonian
    print("Running get_molecular_hamiltonian...")
    print(f"Time: {time()}")
    print("=" * 20)
    ham = mol.get_molecular_hamiltonian(occupied_indices=occupied_indices,
                                        active_indices=active_indices)

    print("Running get_fermion_operator...")
    print(f"Time: {time()}")
    print("=" * 20)
    hamf = get_fermion_operator(ham)

    print(f"Running {qubit_transf}...")
    print(f"Time: {time()}")
    print("=" * 20)

    if qubit_transf == 'bk':
        hamq = bravyi_kitaev(hamf)
    elif qubit_transf == 'jw':
        hamq = jordan_wigner(hamf)
    else:
        raise (ValueError(qubit_transf, 'Unknown transformation specified'))

    # Adapted from 10.5281/zenodo.2880550
    hamd = openfermion.get_diagonal_coulomb_hamiltonian(
        hamf, ignore_incompatible_terms=True)
    nqubits = openfermion.count_qubits(hamd)
    ansatz = openfermioncirq.SwapNetworkTrotterAnsatz(hamd, iterations=3)
    print(ansatz.circuit.to_text_diagram(transpose=True))

    nelectrons = 8  # TODO: CHECK WHICH ORBITALS ARE SAMPLED!!

    prep_circuit = cirq.Circuit(
        openfermioncirq.prepare_gaussian_state(
            ansatz.qubits, openfermion.QuadraticHamiltonian(
                hamd.one_body)))  # TODO: Verify this line
    objective = openfermioncirq.HamiltonianObjective(hamd)
    study = openfermioncirq.VariationalStudy(name='hamil',
                                             ansatz=ansatz,
                                             objective=objective,
                                             preparation_circuit=prep_circuit)

    print("The energy of the default initial guess is {}.".format(
        study.value_of(ansatz.default_initial_params())))
    print()

    alg = openfermioncirq.optimization.ScipyOptimizationAlgorithm(
        kwargs={'method': 'COBYLA'}, uses_bounds=False)
    opt_params = openfermioncirq.optimization.OptimizationParams(
        algorith=alg, initial_guess=ansat.default_initial_params())
    result = study.optimize(opt_param)

    print("Optimized energy: {}".format(result.optimal_value))
    print()
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)