openfermioncirq.SplitOperatorTrotterAnsatz

class openfermioncirq.SplitOperatorTrotterAnsatz(hamiltonian: openfermion.ops._diagonal_coulomb_hamiltonian.DiagonalCoulombHamiltonian, iterations: int = 1, include_all_cz: bool = False, include_all_z: bool = False, adiabatic_evolution_time: Optional[float] = None, qubits: Optional[Sequence[cirq.ops.raw_types.Qid]] = None)[source]

An ansatz based on a split-operator Trotter step.

This ansatz uses as a template the form of a second-order Trotter step based on the split-operator simulation method described in arXiv:1706.00023. The ansatz circuit and default initial parameters are determined by an instance of the DiagonalCoulombHamiltonian class.

Example: The ansatz for a spinless jellium Hamiltonian on a 2x2 grid with one iteration has the circuit:

# pylint: disable=line-too-long
0 1 2 3 │ │ │ │ │ │ PhISwap(0.25)────────PhISwap(0.25)^0.5 │ │ │ │ │ PhISwap(0.25)────────PhISwap(0.25)^0.608 │ │ │ │ │ │ │ PhISwap(0.25)────────PhISwap(0.25)^(-1/3) │ │ │ │ PhISwap(0.25)─PhISwap(0.25)^(2/3) │ │ │ │ │ │ Rz(-π) PhISwap(0.25)────────PhISwap(0.25) │ │ │ │ │ Rz(π) Rz(-π) PhISwap(0.25)────────PhISwap(0.25)^-0.392 │ │ │ │ │ Z^U_1_0 │ Rz(-π) │ │ │ │ │ Rz(π) Z^U_2_0 Z^U_3_0 │ │ │ │ │ │ │ Rz(π) │ │ │ │ │ │ PhISwap(0.25)────────PhISwap(0.25)^0.392 │ │ │ │ │ PhISwap(0.25)────────PhISwap(0.25)^-1 │ │ │ │ │ PhISwap(0.25)─PhISwap(0.25)^(-2/3) │ │ │ │ │ │ │ │ PhISwap(0.25)────────PhISwap(0.25)^(1/3) │ │ │ │ │ PhISwap(0.25)────────PhISwap(0.25)^-0.608 │ │ │ │ │ @─────────────@^V_0_1_0 │ │ │ │ │ │ ×─────────────× PhISwap(0.25)────────PhISwap(0.25)^-0.5 │ │ │ │ │ │ @────────────────────@^V_2_3_0 │ │ │ │ │ │ ×────────────────────× │ │ │ │ │ @────────────────────@^V_0_3_0 │ │ │ │ │ │ ×────────────────────× │ │ │ │ │ @─────────────@^V_1_3_0 @────────────────────@^V_0_2_0 │ │ │ │ ×─────────────× ×────────────────────× │ │ │ │ │ @────────────────────@^V_1_2_0 │ │ │ │ │ │ ×────────────────────× │ │ │ │ │ PhISwap(0.25)─PhISwap(0.25)^0.5 │ │ │ │ │ │ │ PhISwap(0.25)────────PhISwap(0.25)^0.608 │ │ │ │ │ PhISwap(0.25)─PhISwap(0.25)^(-1/3) │ │ │ │ │ │ │ │ PhISwap(0.25)────────PhISwap(0.25)^(2/3) │ │ │ │ │ PhISwap(0.25)────────PhISwap(0.25) Rz(-π) │ │ │ │ PhISwap(0.25)─PhISwap(0.25)^-0.392 Rz(-π) Rz(π) │ │ │ │ Rz(-π) │ Z^U_1_0 │ │ │ │ │ Z^U_3_0 Z^U_2_0 Rz(π) │ │ │ │ │ Rz(π) │ │ │ │ │ │ │ PhISwap(0.25)─PhISwap(0.25)^0.392 │ │ │ │ │ │ │ PhISwap(0.25)────────PhISwap(0.25)^-1 │ │ │ │ │ │ │ PhISwap(0.25)────────PhISwap(0.25)^(-2/3) │ │ │ │ PhISwap(0.25)─PhISwap(0.25)^(1/3) │ │ │ │ │ │ │ PhISwap(0.25)────────PhISwap(0.25)^-0.608 │ │ │ │ │ PhISwap(0.25)─PhISwap(0.25)^-0.5 │ │ │ │ │ │

# pylint: enable=line-too-long

This basic template can be repeated, with each iteration introducing a new set of parameters.

The default initial parameters of the ansatz are chosen so that the ansatz circuit consists of a sequence of second-order Trotter steps approximating the dynamics of the time-dependent Hamiltonian H(t) = T + (t/A)V, where T is the one-body term and V is the two-body term of the Hamiltonian used to generate the ansatz circuit, and t ranges from 0 to A and A is an adjustable value that defaults to the sum of the absolute values of the coefficients of the Jordan-Wigner transformed two-body operator V. The number of Trotter steps is equal to the number of iterations in the ansatz. This choice is motivated by the idea of state preparation via adiabatic evolution. The dynamics of H(t) are approximated as follows. First, the total evolution time of A is split into segments of length A / r, where r is the number of Trotter steps. Then, each Trotter step simulates H(t) for a time length of A / r, where t is the midpoint of the corresponding time segment. As an example, suppose A is 100 and the ansatz has two iterations. Then the approximation is achieved with two Trotter steps. The first Trotter step simulates H(25) for a time length of 50, and the second Trotter step simulates H(75) for a time length of 50.

__init__(hamiltonian: openfermion.ops._diagonal_coulomb_hamiltonian.DiagonalCoulombHamiltonian, iterations: int = 1, include_all_cz: bool = False, include_all_z: bool = False, adiabatic_evolution_time: Optional[float] = None, qubits: Optional[Sequence[cirq.ops.raw_types.Qid]] = None) → None[source]
Parameters:
  • hamiltonian – The Hamiltonian used to generate the ansatz circuit and default initial parameters.
  • iterations – The number of iterations of the basic template to include in the circuit. The number of parameters grows linearly with this value.
  • include_all_cz – Whether to include all possible CZ-type parameterized gates in the ansatz (irrespective of the ansatz Hamiltonian)
  • include_all_z – Whether to include all possible Z-type parameterized gates in the ansatz (irrespective of the ansatz Hamiltonian)
  • adiabatic_evolution_time – The time scale for Hamiltonian evolution used to determine the default initial parameters of the ansatz. This is the value A from the docstring of this class. If not specified, defaults to the sum of the absolute values of the entries of the two-body tensor of the Hamiltonian.
  • qubits – Qubits to be used by the ansatz circuit. If not specified, then qubits will automatically be generated by the _generate_qubits method.

Methods

__init__(hamiltonian, iterations, …)
param hamiltonian:
 The Hamiltonian used to generate the ansatz
default_initial_params() Approximate evolution by H(t) = T + (t/A)V.
operations(qubits) Produce the operations of the ansatz circuit.
param_bounds() Bounds on the parameters.
param_resolver(param_values) Interprets parameters input as an array of real numbers.
param_scale_factors() Coefficients to scale parameters by during optimization.
params() The names of the parameters of the ansatz.
qubit_permutation(qubits) The qubit permutation induced by the ansatz circuit.