Code Documentation¶
vqe¶
VQEexperiment¶

class
vqe.
VQEexperiment
(qc: Optional[pyquil.api._quantum_computer.QuantumComputer] = None, hamiltonian: Union[pyquil.paulis.PauliSum, List[pyquil.paulis.PauliTerm], None] = None, molecule: openfermion.hamiltonians._molecular_data.MolecularData = None, method: str = 'Numpy', strategy: str = 'UCCSD', optimizer: str = 'BFGS', maxiter: int = 100000000, shotN: int = 10000, active_reset: bool = True, tomography: bool = False, verbose: bool = False, parametric: bool = False, custom_qubits=None)¶ 
__init__
(qc: Optional[pyquil.api._quantum_computer.QuantumComputer] = None, hamiltonian: Union[pyquil.paulis.PauliSum, List[pyquil.paulis.PauliTerm], None] = None, molecule: openfermion.hamiltonians._molecular_data.MolecularData = None, method: str = 'Numpy', strategy: str = 'UCCSD', optimizer: str = 'BFGS', maxiter: int = 100000000, shotN: int = 10000, active_reset: bool = True, tomography: bool = False, verbose: bool = False, parametric: bool = False, custom_qubits=None)¶ VQE experiment class. Initialize an instance of this class to prepare a VQE experiment. One may instantiate this class either based on an OpenFermion MolecularData object (containing a chemistry problem Hamiltonian) or manually suggest a Hamiltonian.
The VQE can run circuits on different virtual or real backends: currently, we support the Rigetti QPU backend, locally running QVM, a WavefunctionSimulator, a NumpyWavefunctionSimulator, a PyQVM. Alternatively, one may run the VQE ansatz unitary directly (not decomposed as a circuit) via direct exponentiation of the unitary ansatz, with the ‘linalg’ method. The different backends do not all support parametric gates (yet), and the user can specify whether or not to use it.
Currently, we support two builtin ansatz strategies and the option of setting your own ansatz circuit. The builtin UCCSD and HF strategies are based on data from MolecularData object and thus require one. For finding the groundstate of a custom Hamiltonian, it is required to manually set an ansatz strategy.
Currently, the only classical optimizer for the VQE is the scipy.optimize.minimize module. This may be straightforwardly extended in future releases, contributions are welcome. This class can be initialized with any algorithm in the scipy class, and the max number of iterations can be specified.
For some QuantumComputer objects, the qubit lattice is not numbered 0..N1 but has architecturespecific logical labels. These need to be manually read from the lattice topology and specified in the list custom_qubits. On the physical hardware QPU, actively resetting the qubits is supported to speed up the repetition time of VQE.
To debug and during development, set verbose=True to print output details to the console.
Parameters:  qc ([QuantumComputer(),None]) – object
 list(PauliTerm)] hamiltonian ([PauliSum,) – Hamiltonian which one would like to simulate
 molecule (MolecularData) – OpenFermion Molecule data object. If this is given, the VQE module assumes a chemistry experiment using OpenFermion
 method (str) – string describing the Backend solver method. current options: {Numpy, WFS, linalg, QC}
 strategy (str) – string describing circuit VQE strategy. current options: {UCCSD, HF, custom_program}
 optimizer (str) – classical optimization algorithm, choose from scipy.optimize.minimize options
 maxiter (int) – max number of iterations
 shotN (int) – number of shots in the Tomography experiments
 active_reset (bool) – whether or not to actively reset the qubits (see )
 tomography (bool) – set to False for access to full wavefunction, set to True for just sampling from it
 verbose (bool) – set to True for verbose output to the console, for all methods in this class
 parametric (bool) – set to True to use parametric gate compilation, False to compile a new circuit for every iteration
 custom_qubits (list()) – list of qubits, i.e. [7,0,1,2] ordering the qubit IDs as they appear on the QPU lattice of the QuantumComputer() object.

compile_tomo_expts
()¶ This method compiles the tomography experiment circuits and prepares them for simulation. Every time the circuits are adjusted, recompiling the tomography experiments is required to affect the outcome.

get_circuit
()¶ This method returns the reference state preparation circuit followed by the ansatz circuit.
Returns: return the PyQuil program which defines the circuit. Excludes tomography rotations. Return type: Program

get_exact_gs
(hamiltonian=None)¶ Calculate the exact groundstate energy of the loaded Hamiltonian
Parameters: hamiltonian (PauliSum) – (optional) Hamiltonian of which one would like to calculate the GS energy Returns: groundstate energy Return type: float

get_history
()¶ Get historical values of objective_function from the classical optimization algorithm. Note: resets at every start_vqe().
Returns: Historical energy values from the optimizer Return type: list()

get_qubit_req
()¶ This method computes the number of qubits required to represent the desired Hamiltonian: * assumes all Pauli term indices up to the largest one are in use. * assumes pauli_list has been loaded properly.
Returns: number of qubits required in the circuit, as set by the Hamiltonian terms’ indices. Return type: int

get_results
()¶ get results from the VQE experiment
Returns: scipy.optimize.minimize result object Return type: OptimizeResult

objective_function
(amps=None)¶ This function returns the Hamiltonian expectation value over the final circuit output state. If argument packed_amps is given, the circuit will run with those parameters. Otherwise, the initial angles will be used.
Parameters: numpy.ndarray] amps ([list(),) – list of circuit angles to run the objective function over. Returns: energy estimate Return type: float

save_program
(filename)¶ this saves the preparation circuit as a quil program which can be parsed with pyquil.parser.parse
Parameters: filename (str) – saves the quil program to this filename.

set_circuit_unitary
(unitary)¶ Sets the circuit unitary for use in the ‘linalg’ method.
Parameters: unitary (numpy.ndarray) – np.ndarray of size [2^N x 2^N] where N is the number of qubits

set_custom_ansatz
(prog: pyquil.quil.Program = <pyquil.quil.Program object>)¶ Parameters: prog (Program()) – set a custom ansatz circuit as a program. All variational angles must be parametric !

set_custom_ref_preparation
(prog: pyquil.quil.Program = <pyquil.quil.Program object>)¶ Parameters: prog (Program()) – set a custom reference state preparation circuit as a program. All variational angles must be parametric.

set_initial_angles
(angles: List[T])¶ Userspecify the initial angles for the experiment.
Parameters: angles (list()) – list of angles for the circuit

set_initial_state
(psi)¶ Manually set the complexvalued initial state for the qubits (). Only makes sense for the linalg method
Parameters: psi (numpy.ndarray) – np.ndarray or scipy.sparse array: the complexvalued initial state of the qubits

set_maxiter
(maxiter: int)¶ Set the maximum iteration number for the classical optimizer
Parameters: maxiter (int) – maximum iteration number for the classical optimizer

set_tomo_shots
(shotN)¶ Set the number of shots for the tomography experiment. Warning: requires recompilation of the circuits.
Parameters: shotN (int) – number of tomography repetitions.

start_vqe
(theta=None, maxiter: int = 0, options: dict = {})¶ This method starts the VQE algorithm. User can supply an initial circuit setting, otherwise the stored initial settings are used. the maxiter refers to the scipy optimizer number of iterations (which may well be much less than the number of function calls)
Parameters:  theta ([list(),numpy.ndarray]) – list of initial angles for the circuit to start the optimizer in.
 maxiter (int) – maximum number of iterations.
 options (Dict) – options for the scipy.minimize classical optimizer
Returns: scipy.optimize.minimize result object containing convergence details and final energies. See scipy docs
Return type: OptimizeResult

verbose_output
(verbose: bool = True)¶ Parameters: verbose (bool) – set verbose output to console.

GroupedPauliSetting¶

class
vqe.
GroupedPauliSetting
(list_gsuit_paulis: List[pyquil.paulis.PauliTerm], qc: pyquil.api._quantum_computer.QuantumComputer, ref_state: pyquil.quil.Program, ansatz: pyquil.quil.Program, shotN: int, parametric_way: bool, n_qubits: int, active_reset: bool = True, cq=None, method='QC', verbose: bool = False)¶ 
__init__
(list_gsuit_paulis: List[pyquil.paulis.PauliTerm], qc: pyquil.api._quantum_computer.QuantumComputer, ref_state: pyquil.quil.Program, ansatz: pyquil.quil.Program, shotN: int, parametric_way: bool, n_qubits: int, active_reset: bool = True, cq=None, method='QC', verbose: bool = False)¶ A tomography experiment class for use in VQE. In a real experiment, one only has access to measurements in the Zbasis, giving a result 0 or 1 for each qubit. The Hamiltonian may have terms like sigma_x or sigma_y, for which a basis rotation is required. As quantum mechanics prohibits measurements in multiple bases at once, the Hamiltonian needs to be grouped into commuting Pauli terms and for each set of terms the appropriate basis rotations is applied to each qubits.
A parity_matrix is constructed to keep track of what consequence a qubit measurement of 0 or 1 has as a contribution to the Pauli estimation.
The experiments are constructed as objects with class methods to run and adjust them.
Instantiate using the following parameters:
Parameters:  list_gsuit_paulis (list()) – list of Pauli terms which can be measured at the same time (they share a TPB!)
 qc (QuantumComputer) – QuantumComputer() object which will simulate the terms
 ref_state (Program) – Program() circuit object which produces the initial reference state (f.ex. HartreeFock)
 ansatz (Program) – Program() circuit object which produces the ansatz (f.ex. UCCSD)
 shotN (int) – number of shots to run this Setting for
 parametric_way (bool) – boolean whether to use parametric gates or hardcoded gates
 n_qubits (int) – total number of qubits used for the program
 active_reset (bool) – boolean whether or not to actively reset the qubits
 cq (list()) – list of qubit labels instead of the default [0,1,2,3,…,N1]
 method (str) – string describing the computational method from {QC, linalg, WFS, Numpy}
 verbose (bool) – boolean, whether or not to give verbose output during execution

static
construct_parity_matrix
(pauli_list, n_qubits)¶ This method constructs a matrix which is used to evaluate PauliTerm expectation values from an array of bitstrings returned by qc.run(). See run_experiment() how this parity_matrix is used.
Parameters:  pauli_list (list(PauliTerm)) – list of PauliTerm() objects which should be measured. Assumes a list of nonempty pauli terms only!
 n_qubits (int) – number of qubits assumed for the parity matrix
Returns: returns parity_matrix, 2D numpyarray of dimensions [n_qubits, len(pauli_list)]
Return type: numpy.ndarray

run_experiment
(qc: Optional[pyquil.api._quantum_computer.QuantumComputer], angles=None)¶ method to run the Tomography experiment for this instance’s setting, repeating for shotN shots.
Parameters:  None] qc ([QuantumComputer,) – quantum computer object to run the experiment on, or None in case of WFS/Numpy methods
 angles (list()) – circuit parameters to feed
Returns: returns sum of all commuting pauli terms estimations for this experiment
Return type: float

circuits¶

circuits.
augment_program_with_memory_values
(quil_program, memory_map)¶ This function allocates the classical memory values (gate angles) to a parametric quil program in order to use it on a Numpybased simulator
Parameters:  quil_program (Program) – parametric quil program which would require classical memory allocation
 memory_map (Dict) – dictionary with as keys the MemoryReference or String descrbing the classical memory, and with items() an array of values for that classical memory
Returns: quil program with gate angles from memory_map allocated to the (originally parametric) program
Return type: Program

circuits.
exponentiate_commuting_pauli_sum_parametric
(pauli_sum, term_dict, memref)¶ Returns a Program() (NOT A function) that maps all substituent PauliTerms and sums them into a program. NOTE: Use this function with care. Substituent PauliTerms in pauli_sum should commute for this to work correctly!
Parameters:  pauli_sum (List) – list of Pauli terms to exponentiate.
 term_dict (Dict) – Dictionary containing as keys the Pauliterm frozensets, and as values the indices in packed_amplitudes (and in Memoreference pointer, same index!), corresponding to the same index in pauli_sum list
 memref (MemoryReference) – memory reference which should be inserted to generate the program
Returns: A program that parametrizes the exponential.
Return type: Program()

circuits.
pauli_meas
(idx, op)¶ Generate gate sequence to measure in the eigenbasis of a Pauli operator, assuming we are only able to measure in the Z eigenbasis. The available operations are the following:
\[ \begin{align}\begin{aligned}\begin{split}'X' = \begin{bmatrix} 0 & \frac{\pi}{2} \\ \frac{\pi}{2} & 0 \end{bmatrix}\end{split}\\\begin{split}'Y' = \begin{bmatrix} 0 & \frac{i\pi}{2} \\ \frac{i\pi}{2} & 0 \end{bmatrix}\end{split}\end{aligned}\end{align} \]and \('Z' = 'I' = \mathbb{I}\).
Parameters:  idx (int) – the qubit index on which the measurement basis rotation is to be performed.
 op (str) – enumeration (‘X’, ‘Y’, ‘Z’, ‘I’) representing the axis of the given Pauli matrix
Returns: a pyquil Program representing the Pauli matrix projected onto the Z eigenbasis.
Return type: Program

circuits.
ref_state_preparation_circuit
(molecule, ref_type='HF', cq=None)¶ This function returns a program which prepares a reference state to begin from with a Variational ansatz.
Parameters:  molecule (MolecularData) – molecule data object containing information on HF state.
 ref_type (str) – type of reference state desired
 cq (list()) – (optional) list of qubit labels if different from standard 0 to N1 convention
Returns: pyquil program which prepares the reference state
Return type: Program

circuits.
uccsd_ansatz_circuit
(packed_amplitudes, n_orbitals, n_electrons, cq=None)¶ This function returns a UCCSD variational ansatz with hardcoded gate angles. The number of orbitals specifies the number of qubits, the number of electrons specifies the initial HF reference state which is assumed was prepared. The packed_amplitudes input defines which gate angles to apply for each CC operation. The list cq is an optional list which specifies the qubit label ordering which is to be assumed.
Parameters:  packed_amplitudes (list()) – amplitudes t_ij and t_ijkl of the T_1 and T_2 operators of the UCCSD ansatz
 n_orbitals (int) – number of spatial orbitals
 n_electrons (int) – number of electrons considered
 cq (list()) – list of qubit label order
Returns: circuit which prepares the UCCSD variational ansatz
Return type: Program

circuits.
uccsd_ansatz_circuit_parametric
(n_orbitals, n_electrons, cq=None)¶ This function returns a UCCSD variational ansatz with hardcoded gate angles. The number of orbitals specifies the number of qubits, the number of electrons specifies the initial HF reference state which is assumed was prepared. The list cq is an optional list which specifies the qubit label ordering which is to be assumed.
Parameters:  n_orbitals (int) – number of spatial orbitals in the molecule (for building UCCSD singlet generator)
 n_electrons (int) – number of electrons in the molecule
 cq (list()) – custom qubits
Returns: program which prepares the UCCSD \(T_1 + T_2\) propagator with a spinsinglet assumption.
Return type: Program
utils¶

utils.
pyquilpauli_to_qubitop
(pyquil_pauli)¶ Convert a pyQuil PauliSum to an OpenFermion QubitOperator
Parameters: pyquil_pauli ([PauliTerm, PauliSum]) – pyQuil PauliTerm or PauliSum to convert to an OpenFermion QubitOperator Returns: a QubitOperator representing the PauliSum or PauliTerm Return type: QubitOperator

utils.
qubitop_to_pyquilpauli
(qubit_operator)¶ Convert an OpenFermion QubitOperator to a PauliSum
Parameters: qubit_operator (QubitOperator) – OpenFermion QubitOperator to convert to a pyquil.PauliSum Returns: PauliSum representing the qubit operator Return type: PauliSum

utils.
uccsd_singlet_generator_with_indices
(n_qubits, n_electrons)¶ Create a singlet UCCSD generator for a system with n_electrons, but return a list of Fermion operators, for each term in packed_amplitudes, name it a list called generator, instead of a sum called generator. It also returns a list of indices matching each term. This function generates a FermionOperator for a UCCSD generator designed to act on a single reference state consisting of n_qubits spin orbitals and n_electrons electrons, that is a spin singlet operator, meaning it conserves spin.
Parameters:  n_qubits (int) – Number of spinorbitals used to represent the system, which also corresponds to number of qubits in a noncompact map.
 n_electrons (int) – Number of electrons in the physical system.
Returns: Generator of the UCCSD operator that builds the UCCSD wavefunction.
Return type: list(FermionOperator)