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: pyquil.noise._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]) pyquil.noise.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: Union[List[Any], numpy.ndarray]) numpy.ndarray[source]

Helper to optionally 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: pyquil.noise._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]) pyquil.noise.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[pyquil.noise.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: Union[Dict[int, float], float] = 3e-05, T2: Union[Dict[int, float], float] = 3e-05, gate_time_1q: float = 5e-08, gate_time_2q: float = 1.5e-07, ro_fidelity: Union[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[numpy.ndarray], gate_matrix: numpy.ndarray) List[Union[numpy.number, numpy.ndarray]][source]

Follow a gate gate_matrix by a Kraus map described by kraus_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: pyquil.noise.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: numpy.ndarray) numpy.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 that p[i,j,...,k] gives the estimated probability of bitstring ij...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[numpy.ndarray], k2: List[numpy.ndarray]) List[numpy.ndarray][source]

Generate the Kraus map corresponding to the composition of two maps on the same qubits with k1 being applied to the state after k2.

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: numpy.ndarray, assignment_probabilities: List[numpy.ndarray]) numpy.ndarray[source]

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 that p[i,j,...,k] gives the estimated probability of bitstring ij...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 bitstring ij...k.

pyquil.noise.corrupt_bitstring_probs(p: numpy.ndarray, assignment_probabilities: List[numpy.ndarray]) numpy.ndarray[source]

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 that p[i,j,...,k] gives the estimated probability of bitstring ij...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 bitstring ij...k.

pyquil.noise.damping_after_dephasing(T1: float, T2: float, gate_time: float) List[numpy.ndarray][source]

Generate the Kraus map corresponding to the composition of 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[numpy.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: pyquil.external.rpcq.CompilerISA, p00: float = 0.975, p11: float = 0.911) pyquil.noise.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[numpy.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: QuantumComputer, p0: Optional[Program] = None) numpy.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: numpy.ndarray) numpy.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 bitstring ij...k.

pyquil.noise.get_noisy_gate(gate_name: str, params: Iterable[Union[Expression, MemoryReference, numpy.int64, int, float, complex]]) Tuple[numpy.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[numpy.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[numpy.ndarray], k2: List[numpy.ndarray]) List[numpy.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.