Experiment¶
The experiment
module offers a schema and utilities for succinctly expressing commonly
used applications and algorithms in nearterm quantum programming. An Experiment
object
is intended to be consumed by the QuantumComputer.experiment
method.
NOTE: When working with the experiment method, the following declared memory labels are reserved:
 “preparation_alpha”, “preparation_beta”, and “preparation_gamma”
 “measurement_alpha”, “measurement_beta”, and “measurement_gamma”
 “symmetrization”
 “ro”
Schema¶

class
pyquil.experiment.
Experiment
(settings, program, qubits=None, *, symmetrization=<SymmetrizationLevel.EXHAUSTIVE: 1>, calibration=<CalibrationMethod.PLUS_EIGENSTATE: 1>)[source]¶ A tomographylike experiment.
Many nearterm quantum algorithms involve:
 some limited state preparation
 enacting a quantum process (like in tomography) or preparing a variational ansatz state (like in VQE)
 measuring observables of the state.
Where we typically use a large number of (state_prep, measure) pairs but keep the ansatz program consistent. This class stores the ansatz program as a
Program
and maintains a list ofExperimentSetting
objects which each represent a (state_prep, measure) pair.Settings diagonalized by a shared tensor product basis (TPB) can (optionally) be estimated simultaneously. Therefore, this class is backed by a list of list of ExperimentSettings. Settings sharing an inner list will be estimated simultaneously. If you don’t want this, provide a list of length1lists. As a convenience, if you pass a 1D list to the constructor will expand it to a list of length1lists.
This class will not group settings for you. Please see
group_experiments()
for a function that will automatically process a Experiment to group Experiments sharing a TPB.Variables:  settings – The collection of ExperimentSetting objects that define this experiment.
 program – The main program body of this experiment. Also determines the
shots
andreset
instance variables. Theshots
instance variable is the number of shots to take per ExperimentSetting. Thereset
instance variable is whether to actively reset qubits instead of waiting several times the coherence length for qubits to decay to0>
naturally. Setting this to True is much faster but there is a ~1% error per qubit in the reset operation. Thermal noise from “traditional” reset is not routinely characterized but is of the same order.  symmetrization –
the level of readout symmetrization to perform for the estimation and optional calibration of each observable. The following integer levels, encapsulated in the
SymmetrizationLevel
integer enum, are currently supported: 1 – exhaustive symmetrization uses every possible combination of flips
 0 – no symmetrization
 1 – symmetrization using an orthogonal array (OA) with strength 1
 2 – symmetrization using an orthogonal array (OA) with strength 2
 3 – symmetrization using an orthogonal array (OA) with strength 3
Note that (default) exhaustive symmetrization requires a number of QPU calls exponential in the number of qubits in the union of the support of the observables in any group of settings in
tomo_experiment
; the number of shots may need to be increased to accommodate this. seerun_symmetrized_readout()
in api._quantum_computer for more information.
Methods
get_meas_qubits
()Return the sorted list of qubits that are involved in the all the out_operators of the settings for this Experiment
object.get_meas_registers
([qubits])Return the sorted list of memory registers corresponding to the list of qubits provided. generate_experiment_program
()Generate a parameterized program containing the main body program along with some additions to support the various state preparation, measurement, and symmetrization specifications of this Experiment
.build_setting_memory_map
(setting)Build the memory map corresponding to the state preparation and measurement specifications encoded in the provided ExperimentSetting
, taking into account the full set of qubits that are present in theExperiment
object.build_symmetrization_memory_maps
(qubits[, label])Build a list of memory maps to be used in a program that is trying to perform readout symmetrization via parametric compilation. generate_calibration_experiment
()Generate another Experiment
object that can be used to calibrate the various multiqubit observables involved in thisExperiment
.

class
pyquil.experiment.
ExperimentSetting
(in_state, out_operator, additional_expectations=None)[source]¶ Input and output settings for a tomographylike experiment.
Many nearterm quantum algorithms take the following form:
 Start in a pauli state
 Prepare some ansatz
 Measure it w.r.t. pauli operators
Where we typically use a large number of (start, measure) pairs but keep the ansatz preparation program consistent. This class represents the (start, measure) pairs. Typically a large number of these
ExperimentSetting
objects will be created and grouped into anExperiment
.Variables: additional_expectations – A list of lists, where each inner list specifies a qubit subset to calculate the joint expectation value for. This attribute allows users to extract simultaneously measurable expectation values from a single experiment setting.

class
pyquil.experiment.
ExperimentResult
(setting, expectation, total_counts, stddev=None, std_err=None, raw_expectation=None, raw_stddev=None, raw_std_err=None, calibration_expectation=None, calibration_stddev=None, calibration_std_err=None, calibration_counts=None, additional_results=None)[source]¶ An expectation and standard deviation for the measurement of one experiment setting in a tomographic experiment.
In the case of readout error calibration, we also include expectation, standard deviation and count for the calibration results, as well as the expectation and standard deviation for the corrected results.
Utilities¶

pyquil.experiment.
bitstrings_to_expectations
(bitstrings, joint_expectations=None)[source]¶ Given an array of bitstrings (each of which is represented as an array of bits), map them to expectation values and return the desired joint expectation values. If no joint expectations are desired, then just the 1 > 1, 0 > 1 mapping is performed.
Parameters:  bitstrings (
ndarray
) – Array of bitstrings to map.  joint_expectations (
Optional
[List
[List
[int
]]]) – Joint expectation values to calculate. Each entry is a list which contains the qubits to use in calculating the joint expectation value. Entries of length one just calculate singlequbit expectation values. Defaults to None, which is equivalent to the list of singlequbit expectations [[0], [1], …, [n1]] for bitstrings of length n.
Return type: ndarray
Returns: An array of expectation values, of the same length as the array of bitstrings. The “width” could be different than the length of an individual bitstring (n) depending on the value of the
joint_expectations
parameter. bitstrings (

pyquil.experiment.
correct_experiment_result
(result, calibration)[source]¶ Given a raw, unmitigated result and its associated readout calibration, produce the result absent readout error.
Parameters:  result (
ExperimentResult
) – AnExperimentResult
object with unmitigated readout error.  calibration (
ExperimentResult
) – AnExperimentResult
object resulting from running readout calibration on theExperimentSetting
associated with theresult
parameter.
Return type: ExperimentResult
Returns: An
ExperimentResult
object corrected for symmetric readout error. result (

pyquil.experiment.
merge_memory_map_lists
(mml1, mml2)[source]¶ Given two lists of memory maps, produce the “cartesian product” of the memory maps:
merge_memory_map_lists([{a: 1}, {a: 2}], [{b: 3, c: 4}, {b: 5, c: 6}])
> [{a: 1, b: 3, c: 4}, {a: 1, b: 5, c: 6}, {a: 2, b: 3, c: 4}, {a: 2, b: 5, c: 6}]
Parameters: Return type: Returns: A list of the merged memory maps.

pyquil.experiment.
ratio_variance
(a, var_a, b, var_b)[source]¶ Given random variables ‘A’ and ‘B’, compute the variance on the ratio Y = A/B. Denote the mean of the random variables as a = E[A] and b = E[B] while the variances are var_a = Var[A] and var_b = Var[B] and the covariance as Cov[A,B]. The following expression approximates the variance of Y
Var[Y] approx (a/b) ^2 * ( var_a /a^2 + var_b / b^2  2 * Cov[A,B]/(a*b) )
We assume the covariance of A and B is negligible, resting on the assumption that A and B are independently measured. The expression above rests on the assumption that B is nonzero, an assumption which we expect to hold true in most cases, but makes no such assumptions about A. If we allow E[A] = 0, then calculating the expression above via numpy would complain about dividing by zero. Instead, we can rewrite the above expression as
Var[Y] approx var_a /b^2 + (a^2 * var_b) / b^4
where we have dropped the covariance term as noted above.
 See the following for more details:
 https://doi.org/10.1002/(SICI)10970320(20000401)39:4<300::AIDCYTO8>3.0.CO;2O
 http://www.stat.cmu.edu/~hseltman/files/ratio.pdf
 https://w.wiki/EMh
Parameters: Return type:

pyquil.experiment.
read_json
(fn)[source]¶ Convenience method to read pyquil.experiment objects from a JSON file.
See
to_json()
.Return type: Any

pyquil.experiment.
to_json
(fn, obj)[source]¶ Convenience method to save pyquil.experiment objects as a JSON file.
See
read_json()
.Return type: str