pyquil.noise module¶
Module for creating and verifying noisy gate and readout definitions.
- pyquil.noise.INFINITY = inf¶
Used for infinite coherence times.
- class pyquil.noise.KrausModel(gate, params, targets, kraus_ops, fidelity)[source]¶
Bases:
_KrausModel
Encapsulate a single gate’s noise model.
- Variables:
gate (str) – The name of the gate.
params (Sequence[float]) – Optional parameters for the gate.
targets (Sequence[int]) – The target qubit ids.
kraus_ops (Sequence[np.array]) – The Kraus operators (must be square complex numpy arrays).
fidelity (float) – The average gate fidelity associated with the Kraus map relative to the ideal operation.
Create new instance of _KrausModel(gate, params, targets, kraus_ops, fidelity)
- static from_dict(d: dict[str, Any]) KrausModel [source]¶
Recreate a KrausModel from the dictionary representation.
- Parameters:
d – The dictionary representing the KrausModel. See to_dict for an example.
- Returns:
The deserialized KrausModel.
- to_dict() dict[str, Any] [source]¶
Create a dictionary representation of a KrausModel.
For example:
{ "gate": "RX", "params": np.pi, "targets": [0], "kraus_ops": [ # In this example single Kraus op = ideal RX(pi) gate [ [ [0, 0], # element-wise real part of matrix [0, 0], ], [ [0, -1], # element-wise imaginary part of matrix [-1, 0], ], ] ], "fidelity": 1.0, }
- Returns:
A JSON compatible dictionary representation.
- Return type:
dict[str,Any]
- static unpack_kraus_matrix(m: list[Any] | ndarray) ndarray [source]¶
Unpack a JSON compatible representation of a complex Kraus matrix.
- Parameters:
m – The representation of a Kraus operator. Either a complex square matrix (as numpy array or nested lists) or a JSON-able pair of real matrices (as nested lists) representing the element-wise real and imaginary part of m.
- Returns:
A complex square numpy array representing the Kraus operator.
- class pyquil.noise.NoiseModel(gates, assignment_probs)[source]¶
Bases:
_NoiseModel
Encapsulate the QPU noise model containing information about the noisy gates.
- Variables:
gates (Sequence[KrausModel]) – The tomographic estimates of all gates.
assignment_probs (dict[int,np.array]) – The single qubit readout assignment probability matrices keyed by qubit id.
Create new instance of _NoiseModel(gates, assignment_probs)
- static from_dict(d: dict[str, Any]) NoiseModel [source]¶
Re-create the noise model from a dictionary representation.
- Parameters:
d – The dictionary representation.
- Returns:
The restored noise model.
- gates_by_name(name: str) list[KrausModel] [source]¶
Return all defined noisy gates of a particular gate name.
- Parameters:
name (str) – The gate name.
- Returns:
A list of noise models representing that gate.
- to_dict() dict[str, Any] [source]¶
Create a JSON serializable representation of the noise model.
For example:
{ "gates": [ # list of embedded dictionary representations of KrausModels here [...] ] "assignment_probs": { "0": [[.8, .1], [.2, .9]], "1": [[.9, .4], [.1, .6]], } }
- Returns:
A dictionary representation of self.
- exception pyquil.noise.NoisyGateUndefined[source]¶
Bases:
Exception
Raise when user attempts to use noisy gate outside of currently supported set.
- pyquil.noise.add_decoherence_noise(prog: Program, T1: dict[int, float] | float = 3e-05, T2: dict[int, float] | float = 3e-05, gate_time_1q: float = 5e-08, gate_time_2q: float = 1.5e-07, ro_fidelity: dict[int, float] | float = 0.95) Program [source]¶
Add generic damping and dephasing noise to a program.
This high-level function is provided as a convenience to investigate the effects of a generic noise model on a program. For more fine-grained control, please investigate the other methods available in the
pyquil.noise
module.In an attempt to closely model the QPU, noisy versions of RX(+-pi/2) and CZ are provided; I and parametric RZ are noiseless, and other gates are not allowed. To use this function, you need to compile your program to this native gate set.
The default noise parameters
T1 = 30 us
T2 = 30 us
1q gate time = 50 ns
2q gate time = 150 ns
are currently typical for near-term devices.
This function will define new gates and add Kraus noise to these gates. It will translate the input program to use the noisy version of the gates.
- Parameters:
prog – A pyquil program consisting of I, RZ, CZ, and RX(+-pi/2) instructions
T1 – The T1 amplitude damping time either globally or in a dictionary indexed by qubit id. By default, this is 30 us.
T2 – The T2 dephasing time either globally or in a dictionary indexed by qubit id. By default, this is also 30 us.
gate_time_1q – The duration of the one-qubit gates, namely RX(+pi/2) and RX(-pi/2). By default, this is 50 ns.
gate_time_2q – The duration of the two-qubit gates, namely CZ. By default, this is 150 ns.
ro_fidelity – The readout assignment fidelity \(F = (p(0|0) + p(1|1))/2\) either globally or in a dictionary indexed by qubit id.
- Returns:
A new program with noisy operators.
- pyquil.noise.append_kraus_to_gate(kraus_ops: Sequence[ndarray], gate_matrix: ndarray) list[number | ndarray] [source]¶
Follow a gate
gate_matrix
by a Kraus map described bykraus_ops
.- Parameters:
kraus_ops – The Kraus operators.
gate_matrix – The unitary gate.
- Returns:
A list of transformed Kraus operators.
- pyquil.noise.apply_noise_model(prog: Program, noise_model: NoiseModel) Program [source]¶
Apply a noise model to a program and generated a ‘noisy-fied’ version of the program.
- Parameters:
prog – A Quil Program object.
noise_model – A NoiseModel, either generated from an ISA or from a simple decoherence model.
- Returns:
A new program translated to a noisy gateset and with noisy readout as described by the noisemodel.
- pyquil.noise.bitstring_probs_to_z_moments(p: ndarray) ndarray [source]¶
Convert between bitstring probabilities and joint Z moment expectations.
- Parameters:
p – An array that enumerates bitstring probabilities. When flattened out
p = [p_00...0, p_00...1, ...,p_11...1]
. The total number of elements must therefore be a power of 2. The canonical shape has a separate axis for each qubit, such thatp[i,j,...,k]
gives the estimated probability of bitstringij...k
.- Returns:
z_moments
, an np.array with one length-2 axis per qubit which contains the expectations of all monomials in{I, Z_0, Z_1, ..., Z_{n-1}}
. The expectations of each monomial can be accessed via:<Z_0^j_0 Z_1^j_1 ... Z_m^j_m> = z_moments[j_0,j_1,...,j_m]
- pyquil.noise.combine_kraus_maps(k1: list[ndarray], k2: list[ndarray]) list[ndarray] [source]¶
Generate the Kraus map for two composed maps, with k1 applied after k2 on the same qubits.
- Parameters:
k1 – The list of Kraus operators that are applied second.
k2 – The list of Kraus operators that are applied first.
- Returns:
A combinatorially generated list of composed Kraus operators.
- pyquil.noise.correct_bitstring_probs(p: ndarray, assignment_probabilities: list[ndarray]) ndarray [source]¶
Given a 2D array of corrupted bitstring probabilities and assignment matrices, compute the corrected probabilities.
Given a 2d array of corrupted bitstring probabilities (outer axis iterates over shots, inner axis over bits) and a list of assignment probability matrices (one for each bit in the readout) compute the corrected probabilities.
- Parameters:
p – An array that enumerates bitstring probabilities. When flattened out
p = [p_00...0, p_00...1, ...,p_11...1]
. The total number of elements must therefore be a power of 2. The canonical shape has a separate axis for each qubit, such thatp[i,j,...,k]
gives the estimated probability of bitstringij...k
.assignment_probabilities –
A list of assignment probability matrices per qubit. Each assignment probability matrix is expected to be of the form:
[[p00 p01] [p10 p11]]
- Returns:
p_corrected
an array with as many dimensions as there are qubits that contains the noisy-readout-corrected estimated probabilities for each measured bitstring, i.e.,p[i,j,...,k]
gives the estimated probability of bitstringij...k
.
- pyquil.noise.corrupt_bitstring_probs(p: ndarray, assignment_probabilities: list[ndarray]) ndarray [source]¶
Given a 2D array of bitstring probabilities and assignment matrices, compute the corrupted probabilities.
Given a 2d array of true bitstring probabilities (outer axis iterates over shots, inner axis over bits) and a list of assignment probability matrices (one for each bit in the readout, ordered like the inner axis of results) compute the corrupted probabilities.
- Parameters:
p – An array that enumerates bitstring probabilities. When flattened out
p = [p_00...0, p_00...1, ...,p_11...1]
. The total number of elements must therefore be a power of 2. The canonical shape has a separate axis for each qubit, such thatp[i,j,...,k]
gives the estimated probability of bitstringij...k
.assignment_probabilities –
A list of assignment probability matrices per qubit. Each assignment probability matrix is expected to be of the form:
[[p00 p01] [p10 p11]]
- Returns:
p_corrected
an array with as many dimensions as there are qubits that contains the noisy-readout-corrected estimated probabilities for each measured bitstring, i.e.,p[i,j,...,k]
gives the estimated probability of bitstringij...k
.
- pyquil.noise.damping_after_dephasing(T1: float, T2: float, gate_time: float) list[ndarray] [source]¶
Generate the Kraus map for a dephasing channel followed by an amplitude damping channel.
- Parameters:
T1 – The amplitude damping time
T2 – The dephasing time
gate_time – The gate duration.
- Returns:
A list of Kraus operators.
- pyquil.noise.damping_kraus_map(p: float = 0.1) list[ndarray] [source]¶
Generate the Kraus operators corresponding to an amplitude damping noise channel.
- Parameters:
p – The one-step damping probability.
- Returns:
A list [k1, k2] of the Kraus operators that parametrize the map.
- Return type:
list
- pyquil.noise.decoherence_noise_with_asymmetric_ro(isa: CompilerISA, p00: float = 0.975, p11: float = 0.911) NoiseModel [source]¶
Similar to
_decoherence_noise_model()
, but with asymmetric readout.For simplicity, we use the default values for T1, T2, gate times, et al. and only allow the specification of readout fidelities.
- pyquil.noise.dephasing_kraus_map(p: float = 0.1) list[ndarray] [source]¶
Generate the Kraus operators corresponding to a dephasing channel.
- Params float p:
The one-step dephasing probability.
- Returns:
A list [k1, k2] of the Kraus operators that parametrize the map.
- Return type:
list
- pyquil.noise.estimate_assignment_probs(q: int, trials: int, qc: PyquilApiQuantumComputer, p0: Program | None = None) ndarray [source]¶
Estimate the readout assignment probabilities for a given qubit
q
.The returned matrix is of the form:
[[p00 p01] [p10 p11]]
- Parameters:
q – The index of the qubit.
trials – The number of samples for each state preparation.
qc – The quantum computer to sample from.
p0 – A header program to prepend to the state preparation programs. Will not be compiled by quilc, so it must be native Quil.
- Returns:
The assignment probability matrix
- pyquil.noise.estimate_bitstring_probs(results: ndarray) ndarray [source]¶
Given an array of single shot results estimate the probability distribution over all bitstrings.
- Parameters:
results – A 2d array where the outer axis iterates over shots and the inner axis over bits.
- Returns:
An array with as many axes as there are qubit and normalized such that it sums to one.
p[i,j,...,k]
gives the estimated probability of bitstringij...k
.
- pyquil.noise.get_noisy_gate(gate_name: str, params: Iterable[Expression | MemoryReference | int | float | complex | number]) tuple[ndarray, str] [source]¶
Look up the numerical gate representation and a proposed ‘noisy’ name.
- Parameters:
gate_name – The Quil gate name
params – The gate parameters.
- Returns:
A tuple (matrix, noisy_name) with the representation of the ideal gate matrix and a proposed name for the noisy version.
- pyquil.noise.pauli_kraus_map(probabilities: Sequence[float]) list[ndarray] [source]¶
Generate the Kraus operators corresponding to a pauli channel.
- Params probabilities:
The 4^num_qubits list of probabilities specifying the desired pauli channel. There should be either 4 or 16 probabilities specified in the order I, X, Y, Z for 1 qubit or II, IX, IY, IZ, XI, XX, XY, etc for 2 qubits.
For example:
The d-dimensional depolarizing channel \Delta parameterized as \Delta(\rho) = p \rho + [(1-p)/d] I is specified by the list of probabilities [p + (1-p)/d, (1-p)/d, (1-p)/d), ... , (1-p)/d)]
- Returns:
A list of the 4^num_qubits Kraus operators that parametrize the map.
- pyquil.noise.tensor_kraus_maps(k1: list[ndarray], k2: list[ndarray]) list[ndarray] [source]¶
Generate the Kraus map corresponding to the composition of two maps on different qubits.
- Parameters:
k1 – The Kraus operators for the first qubit.
k2 – The Kraus operators for the second qubit.
- Returns:
A list of tensored Kraus operators.