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)
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)
def test_simulate_trotter_omit_final_swaps(): n_qubits = 5 qubits = cirq.LineQubit.range(n_qubits) hamiltonian = openfermion.DiagonalCoulombHamiltonian( one_body=numpy.ones((n_qubits, n_qubits)), two_body=numpy.ones((n_qubits, n_qubits))) time = 1.0 circuit_with_swaps = cirq.Circuit.from_ops( simulate_trotter( qubits, hamiltonian, time, order=0, algorithm=LINEAR_SWAP_NETWORK)) circuit_without_swaps = cirq.Circuit.from_ops( simulate_trotter( qubits, hamiltonian, time, order=0, algorithm=LINEAR_SWAP_NETWORK, omit_final_swaps=True)) assert len(circuit_without_swaps) < len(circuit_with_swaps) circuit_with_swaps = cirq.Circuit.from_ops( simulate_trotter( qubits, hamiltonian, time, order=1, n_steps=3, algorithm=SPLIT_OPERATOR), strategy=cirq.InsertStrategy.NEW) circuit_without_swaps = cirq.Circuit.from_ops( simulate_trotter( qubits, hamiltonian, time, order=1, n_steps=3, algorithm=SPLIT_OPERATOR, omit_final_swaps=True), strategy=cirq.InsertStrategy.NEW) assert len(circuit_without_swaps) < len(circuit_with_swaps) hamiltonian = lih_hamiltonian qubits = cirq.LineQubit.range(4) circuit_with_swaps = cirq.Circuit.from_ops( simulate_trotter( qubits, hamiltonian, time, order=0, algorithm=LOW_RANK)) circuit_without_swaps = cirq.Circuit.from_ops( simulate_trotter( qubits, hamiltonian, time, order=0, algorithm=LOW_RANK, omit_final_swaps=True)) assert len(circuit_without_swaps) < len(circuit_with_swaps)
def as_diagonal_coulomb_hamiltonian( self) -> openfermion.DiagonalCoulombHamiltonian: """Exports Fermi Hubbard Hamiltonian as DiagonalCoulombHamiltonian. Returns: Description of Fermi Hubbard problem as openfermion.DiagonalCoulombHamiltonian. """ def spin_map(j: int, spin: int) -> int: """Mapping from site and spin to index (separated in spin sectors). Assigns indices 0 through self.sites_count - 1 when spin = 0 and indices self.sites_count through 2 * self.sites_count - 1 when spin = 1. """ return j + spin * self.sites_count modes = 2 * self.sites_count # Prepare one-body matrix T_ij. one_body = np.zeros((modes, modes)) # Nearest-neighbor hopping terms. t = self.j_array for j, s in product(range(self.interactions_count), [0, 1]): j1 = (j + 1) % self.sites_count one_body[spin_map(j, s), spin_map(j1, s)] += -t[j] one_body[spin_map(j1, s), spin_map(j, s)] += -t[j] # Local interaction terms. local_up = self.local_up_array local_down = self.local_down_array for j in range(self.sites_count): one_body[spin_map(j, 0), spin_map(j, 0)] += local_up[j] one_body[spin_map(j, 1), spin_map(j, 1)] += local_down[j] # Prepare the two-body matrix V_ij. two_body = np.zeros((modes, modes)) # On-site interaction terms. u = self.u_array for j in range(self.sites_count): two_body[spin_map(j, 0), spin_map(j, 1)] += u[j] / 2. two_body[spin_map(j, 1), spin_map(j, 0)] += u[j] / 2. # Nearest-neighbor interaction terms. v = self.v_array for j, (s0, s1) in product(range(self.interactions_count), np.ndindex((2, 2))): j1 = (j + 1) % self.sites_count two_body[spin_map(j, s0), spin_map(j1, s1)] += v[j] / 2. two_body[spin_map(j1, s1), spin_map(j, s0)] += v[j] / 2. return openfermion.DiagonalCoulombHamiltonian(one_body, two_body)
import numpy import cirq import openfermion from openfermioncirq.variational.ansatzes import SwapNetworkTrotterAnsatz # Construct a Hubbard model Hamiltonian hubbard_model = openfermion.fermi_hubbard(2, 2, 1., 4.) hubbard_hamiltonian = openfermion.get_diagonal_coulomb_hamiltonian( hubbard_model) # Construct an empty Hamiltonian zero_hamiltonian = openfermion.DiagonalCoulombHamiltonian(one_body=numpy.zeros( (4, 4)), two_body=numpy.zeros( (4, 4))) def test_swap_network_trotter_ansatz_params(): ansatz = SwapNetworkTrotterAnsatz(hubbard_hamiltonian) assert (set(ansatz.params()) == { cirq.Symbol(name) for name in { 'T_0_2_0', 'T_4_6_0', 'T_1_3_0', 'T_5_7_0', 'T_0_4_0', 'T_2_6_0', 'T_1_5_0', 'T_3_7_0', 'V_0_1_0', 'V_2_3_0', 'V_4_5_0', 'V_6_7_0' } }) ansatz = SwapNetworkTrotterAnsatz(hubbard_hamiltonian, iterations=2)
# See the License for the specific language governing permissions and # limitations under the License. import numpy import cirq import openfermion from openfermioncirq.trotter import SPLIT_OPERATOR n_qubits = 4 qubits = cirq.LineQubit.range(n_qubits) control = cirq.LineQubit(-1) ones_hamiltonian = openfermion.DiagonalCoulombHamiltonian(one_body=numpy.ones( (n_qubits, n_qubits)), two_body=numpy.ones( (n_qubits, n_qubits)), constant=1.0) def test_split_operator_trotter_step_symmetric(): circuit = cirq.Circuit.from_ops( SPLIT_OPERATOR.symmetric(ones_hamiltonian).trotter_step(qubits, 1.0), strategy=cirq.InsertStrategy.EARLIEST) assert circuit.to_text_diagram(transpose=True).strip() == """ 0 1 2 3 │ │ │ │ Z^-0.159 Z^-0.159 Z^-0.159 Z^-0.796 │ │ │ │ Z Z^0.0 Z^0.0 Z^0.0 │ │ │ │
from openfermioncirq.variational.ansatzes import SplitOperatorTrotterAnsatz # Construct a Hubbard model Hamiltonian hubbard_model = openfermion.fermi_hubbard(2, 2, 1., 4.) hubbard_hamiltonian = openfermion.get_diagonal_coulomb_hamiltonian( hubbard_model) # Construct a jellium model Hamiltonian grid = openfermion.Grid(2, 2, 1.0) jellium = openfermion.jellium_model(grid, spinless=True, plane_wave=False) jellium_hamiltonian = openfermion.get_diagonal_coulomb_hamiltonian(jellium) # Construct a Hamiltonian of ones ones_hamiltonian = openfermion.DiagonalCoulombHamiltonian(one_body=numpy.ones( (5, 5)), two_body=numpy.ones( (5, 5))) def test_split_operator_trotter_ansatz_params(): ansatz = SplitOperatorTrotterAnsatz(hubbard_hamiltonian) assert (set(ansatz.params()) == { cirq.Symbol(name) for name in { 'U_0_0', 'U_1_0', 'U_6_0', 'U_7_0', 'V_0_1_0', 'V_2_3_0', 'V_4_5_0', 'V_6_7_0' } }) ansatz = SplitOperatorTrotterAnsatz(hubbard_hamiltonian, iterations=2)
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)
def test_simulate_trotter_omit_final_swaps(): n_qubits = 5 qubits = cirq.LineQubit.range(n_qubits) hamiltonian = openfermion.DiagonalCoulombHamiltonian(one_body=numpy.ones( (n_qubits, n_qubits)), two_body=numpy.ones( (n_qubits, n_qubits))) time = 1.0 circuit_with_swaps = cirq.Circuit.from_ops( simulate_trotter(qubits, hamiltonian, time, order=0, algorithm=LINEAR_SWAP_NETWORK)) circuit_without_swaps = cirq.Circuit.from_ops( simulate_trotter(qubits, hamiltonian, time, order=0, algorithm=LINEAR_SWAP_NETWORK, omit_final_swaps=True)) assert (circuit_with_swaps.to_text_diagram(transpose=True).strip() == ( circuit_without_swaps.to_text_diagram(transpose=True).strip() + """ │ ×ᶠ─────────×ᶠ ×ᶠ─────────×ᶠ │ │ │ │ │ ×ᶠ───────×ᶠ ×ᶠ─────────×ᶠ │ │ │ │ │ │ │ ×ᶠ─────────×ᶠ ×ᶠ─────────×ᶠ │ │ │ │ │ ×ᶠ───────×ᶠ ×ᶠ─────────×ᶠ │ │ │ │ │ │ │ ×ᶠ─────────×ᶠ ×ᶠ─────────×ᶠ │ │ │ │ │ """).strip()) circuit_with_swaps = cirq.Circuit.from_ops( simulate_trotter(qubits, hamiltonian, time, order=1, n_steps=3, algorithm=SPLIT_OPERATOR), strategy=cirq.InsertStrategy.NEW) circuit_without_swaps = cirq.Circuit.from_ops( simulate_trotter(qubits, hamiltonian, time, order=1, n_steps=3, algorithm=SPLIT_OPERATOR, omit_final_swaps=True), strategy=cirq.InsertStrategy.NEW) assert (circuit_with_swaps.to_text_diagram(transpose=True).strip() == ( circuit_without_swaps.to_text_diagram(transpose=True).strip() + """ │ │ │ ×────────────× │ │ │ │ │ │ ×───────────× │ │ │ │ │ │ │ │ │ ×───────────× │ │ │ │ │ │ ×─────────× │ │ │ │ │ │ │ │ │ │ │ ×────────────× │ │ │ │ │ │ ×───────────× │ │ │ │ │ │ │ │ │ ×───────────× │ │ │ │ │ │ ×─────────× │ │ │ │ │ │ │ │ │ │ │ ×────────────× │ │ │ │ │ │ ×───────────× │ │ │ │ │ │ │ """).strip()) hamiltonian = random_interaction_operator(n_qubits, seed=0) circuit_with_swaps = cirq.Circuit.from_ops( simulate_trotter(qubits, hamiltonian, time, order=0, algorithm=LOW_RANK)) circuit_without_swaps = cirq.Circuit.from_ops( simulate_trotter(qubits, hamiltonian, time, order=0, algorithm=LOW_RANK, omit_final_swaps=True)) assert len(circuit_without_swaps) < len(circuit_with_swaps)