Skip to main content
IBM Quantum Platform

PEC (qiskit_mitigation.pec)

PEC

class PEC

GitHub

Bases: MitigationTask

Calculates expectation values of observables using Probabilistic Error Cancellation (PEC) mitigation method.

The class enables preparing a QuantumProgram with circuit mitigated using PEC method, that can be executed on hardware using the Executor, and post process the results to calculate mitigated expectation values of given observables. The task parameters should be given as input to the prepare function, and the relevant variables needed for post-processing are saved internally:

pec = PEC()
program = pec.prepare(circuit=circuit,
                      observables=observables,
                      parameters=parameter_valuesת
                      noise_maps=learned_noise)
job = executor.run(program)
results = job.result()
mitigated_result = pec.postprocess(results)

To calculate expectation values of a loaded job result, a PEC task can be created from the job results with all the internal variables needed for post-processing. Alternatively, the variables required for post-processing can be given as input directly to the compute_expectation_value static method. Example for running post-processing for a loaded result:

pec = PEC()
program = pec.prepare(circuit=circuit,
                      observables=observables,
                      parameters=parameter_valuesת
                      noise_maps=learned_noise)
job_id = executor.run(program).job_id

job = service.job(job_id)
results = job.result()
pec = load_tasks_from_result(results)[0]
mitigated_result = pec.postprocess(results)

Instantiate a PEC task.

Methods

find_unique_layers

find_unique_layers(circuit, custom_boxing_options=None, box_types='all', observables=None, trex=None)

GitHub

Return the unique boxed layers of the given circuit using the given boxing options.

If the instance already holds a boxed circuit of the given circuit (for example, after calling prepare), and custom_boxing_options is None or equal to the saved boxing options, the saved boxed circuit is used instead of boxing the circuit again.

Parameters

  • circuit (QuantumCircuit) – The circuit to found its unique layers.

  • custom_boxing_options (dict | None) – The custom boxing options that will be used by generate_boxing_pass_manager() function.

  • box_types (Literal['gates', 'measurement', 'all']) – Can be either "gates", "measurement" or "all", corresponding to filter boxes with only gate layers, only measurement layers or all layers, respectively.

  • observables (ObservablesArray |Sequence[SparsePauliOp] | None) –

    If given, the layers are found for a circuit whose measurements are trimmed to the active and observed qubits, exactly as when prepare is called with trim_measurements=True and the same observables. If None (default), all the qubits are measured.

    Warning

    Pass observables if and only if trim_measurements=True is passed to prepare, together with the same observables. The measured qubits change the boxing, so layers learned with a different choice are not found by prepare.

  • trex (bool | None) – Whether to add the boxing options that prepare enforces when a TREX is used (measurement boxes annotated for all qubits). If True, these options are always added. If False, they are never added. If None (default), they are added if and only if this task has a TREX mitigation.

Returns

Unique boxed layers of the given circuit.

Raises

ValueError – If observables is given and no qubit is active or observed.

Return type

list[CircuitInstruction]

prepare

prepare(circuit, observables, parameters, custom_boxing_options=None, shots_per_randomization=64, num_randomizations=128, broadcast_obs_and_params=False, trex=None, quantum_program=None, trim_measurements=False, *, noise_maps=None, scale_randomizations_by_gamma=True, noise_gain='auto', max_sampling_overhead=100)

GitHub

Creates a QuantumProgram with PEC mitigated item for executing via Executor.

Creates an item for a QuantumProgram, that can be executed via Executor and is PEC mitigated (injects inverse noise to cancel the learned noise). If a quantum_program is provided, the new item will be added to the existing program, otherwise, a new program will be created, containing only the created item. In the created program item the final measurement layer of the given circuit is removed and a new measurement layer with a dedicated classical register named _meas is added. If broadcast_obs_and_params is True, the observables and parameters will be broadcasted using the samplomatic broadcasting rules, to allow attaching some of the parameters to some of the observables. Otherwise, every parameter will be executed for each observable (outer product of the parameters and observables). Note that the post-processing of an outer product is usually faster.

Parameters

  • circuit (QuantumCircuit) – The quantum circuit.

  • observables (ObservablesArray |Sequence[SparsePauliOp]) – The observables to calculate their expectation values.

  • parameters (ndarray |BindingsArray | None) – The parameters of a parametric circuit.

  • custom_boxing_options (dict | None) – The custom boxing options that will be used by generate_boxing_pass_manager() function.

  • shots_per_randomization (int) – The number of shots per randomization.

  • num_randomizations (int) – The number of randomizations.

  • broadcast_obs_and_params (bool) – Whether to broadcast observables and parameters.

  • trex (TREX | None) – A TREX mitigation instance that will be used to mitigate readout errors.

  • quantum_program (QuantumProgram | None) – The quantum program to add an item for. If None, a new program will be created.

  • trim_measurements (bool) –

    Whether to measure only the qubits that have instructions on them or are in the support of the observables, instead of all the qubits of the circuit. The measured qubits are available in meas_qubits after the call.

    Warning

    Trimming changes the boxing of the circuit, so noise_maps must be learned on the layers of a trimmed circuit: pass observables to the layer finder (find_combined_unique_layers() or find_unique_layers()) if and only if trim_measurements=True is passed to prepare, and pass the same observables.

  • noise_maps (dict[str, PauliLindbladMap] | None) – A mapping between layer ref to a noise model to use for PEC mitigation method. The dict might contain layers not present in the given circuit, but must contain all the mitigated layers. Assumes that the unique layers used for noise learning were extracted using the find_unique_layers method with the same custom boxing options, and with observables passed if and only if trim_measurements=True.

  • scale_randomizations_by_gamma (bool) – Whether to automatically scale the number of randomizations by gamma**2.

  • noise_gain (float |Literal['auto', 'slc_local_scales']) – The fraction of noise to keep after the mitigation. A value of 0 corresponds to removing the full learned noise. A value of 1 corresponds to no removal of the learned noise. A value between 0 and 1 corresponds to partially removing the learned noise. A value greater than one corresponds to amplifying the learned noise. A value of “slc_local_scales” corresponds to partially removing the learned noise of each box according to the local scales learned using shaded light-cones (slc). In order to compute those local scales, first use generate_slc_bounds_computation_input() and the qiskit-addon-slc bounds functions, and then use set_slc_local_scales() (see its documentation). If "auto", the value in the range [0, 1] will be chosen automatically by the formula 1 - log(max_overhead) / log(gamma^2).

  • max_sampling_overhead (float | None) – If scale_randomizations_by_gamma is True, limit the multiplicative ratio of the number of randomizations.

Returns

A QuantumProgram with PEC mitigated item that can be executed via Executor.

Raises

ValueError – If trim_measurements is True and no qubit is active or observed.

Return type

QuantumProgram

postprocess

postprocess(results, measure_noise_data=None)

GitHub

Process expectation values for a single pec mitigated item result.

Parameters

  • results (QuantumProgramItemResult |QuantumProgramResult) – The execution results. Can be either the entire results object or the pec mitigated item result of this task. If TREX calibration task is added to the quantum program, its results will be used to compute the measure noise data if the entire results object is provided.
  • measure_noise_data (PauliLindbladMap |ndarray | None) – The learned measurement noise data to use for TREX mitigation. If None and a calibration task is present the quantum program, the measure noise will be computed from the calibration task results if the entire results object is provided.

Returns

A PubResult which contains evs and std as fields in its data, where evs are expectation values, and std are the standard deviation of the expectation values. If broadcast_obs_and_params is set to True, the data will contain also a twirl_stds field which is the standard deviation between different randomizations.

Raises

  • ValueError – If the task’s item result has no '_meas' key.
  • ValueError – If the item result’s '_meas' data has an invalid number of axes.
  • ValueError – If param_shape and observables.shape cannot be broadcasted against each other, while broadcast_obs_and_params was set to True in the task preparation.

Return type

PubResult

compute_expectation_value_pec

static compute_expectation_value_pec(item_result, observables, gamma, param_shape=None, param_basis_pairs=None, meas_bases=None, broadcast_obs_and_params=False, measure_noise_data=None, meas_qubits=None, circuit_num_qubits=None)

GitHub

Process expectation values for a single pec mitigated item result.

This function can be used to calculate expectation values for a single pec mitigated item result without instantiating a new class instance.

Parameters

  • item_result (QuantumProgramItemResult) – The item result.
  • observables (ObservablesArray |Sequence[SparsePauliOp]) – The observables to calculate expectation values for.
  • gamma (float) – The gamma factor of the learned noise model for the executed circuit.
  • param_shape (tuple[int, ...] | None) – The shape of the parameter values.
  • param_basis_pairs (list[tuple[tuple[int, ...], str]] | None) – The map between params ndindexes to measure basis.
  • meas_bases (Sequence[Pauli] | Sequence[str] | PauliList | None) – A list of the measured Pauli bases. The i th item is a measurement basis assumed to correspond to the i th slice of the data in item_result.
  • broadcast_obs_and_params (bool) – Whether to broadcast observables and parameter values.
  • measure_noise_data (PauliLindbladMap |ndarray | None) – Measurement noise calibration data for TREX mitigation.
  • meas_qubits (list[int] | None) – Sorted list of the circuit qubit indices that were measured, if the task was prepared with trim_measurements=True (available as task.meas_qubits). Must be given together with circuit_num_qubits. If None, all the qubits are assumed to be measured, which gives wrong results for trimmed data.
  • circuit_num_qubits (int | None) – The total number of qubits in the circuit. Used together with meas_qubits to expand the data back to the full width. Must be given together with meas_qubits.

Returns

A PubResult which contains evs and std as fields in its data, where evs are expectation values, and std are the standard deviation of the expectation values. If broadcast_obs_and_params is set to True, the data will contain also a twirl_stds field which is the standard deviation between different randomizations.

Raises

  • ValueError – If item_result has no '_meas' key.
  • ValueError – If item_result['_meas'] has invalid number of axes.
  • ValueError – If item_result has no 'pauli_signs' key and gamma is not 1.
  • ValueError – If param_shape and observables.shape cannot be broadcasted against each other.
  • ValueError – If only one of meas_qubits and circuit_num_qubits is given.

Return type

PubResult

create_instance_from_passthrough_data

static create_instance_from_passthrough_data(passthrough, trex=None)

GitHub

Create a PEC instance from a passthrough dictionary loaded from a quantum program execution result.

Parameters

  • passthrough (dict[str, Any]) – Passthrough_data dictionary loaded from a quantum program execution result.
  • trex (TREX | None) – A TREX instance containing a calibration circuit results executed in the same quantum program. Should remain None in case TREX mitigation was not used or a TREX calibration was not executed as part of thq same quantum program.

Returns

A PEC instance.

Return type

PEC

generate_slc_bounds_computation_input

generate_slc_bounds_computation_input(circuit, coupling_map=None, custom_boxing_options=None)

GitHub

Prepare the inputs required for computing the shaded light-cone (SLC) bounds of a circuit.

The circuit is boxed, and the Pauli error terms of each noisy layer are generated using qiskit_addon_slc.utils.generate_noise_model_paulis(). The circuit, boxed circuit and the boxing options are saved in the class instance. If the instance already holds a boxed circuit of the given circuit (for example, from a previous call to this function or to prepare), and custom_boxing_options is None or equal to the saved boxing options, the saved boxed circuit is reused instead of boxing the circuit again.

Important

The bounds are keyed by the modifier_ref of each noisy box, so custom_boxing_options["inject_noise_strategy"] must be "individual_modification" (see qiskit_addon_slc.bounds.compute_forward_bounds()). If it is not specified, it is set to "individual_modification". If custom_boxing_options is None and the saved boxing options are used, the same rule applies to them.

Note

This function uses the optional dependency of qiskit-addon-slc package.

Parameters

  • circuit (QuantumCircuit) – The target circuit to compute bounds for.
  • coupling_map (CouplingMap | None) – The coupling map of the backend on which the instructions have been laid out. Used to generate all the relevant Pauli error terms. If None, a 1d line of qubits is assumed.
  • custom_boxing_options (dict | None) – The custom boxing options that will be used by generate_boxing_pass_manager() function. If None and circuit is the same object as the circuit saved in the class instance (e.g. from a previous call to prepare), the custom_boxing_options saved in the instance are used.

Returns

  • The boxed circuit.
  • A dict mapping the ref of each noise model to the Pauli error terms to consider. Can be given as the noise_model_paulis input of the qiskit-addon-slc bounds functions.

Raises

  • MissingOptionalLibraryError – if qiskit-addon-slc package is not installed.
  • ValueError – If the circuit has unbounded parameters.
  • ValueError – If custom_boxing_options["inject_noise_strategy"] is specified and is not "individual_modification".

Return type

tuple[QuantumCircuit, dict[str, QubitSparsePauliList]]

set_slc_local_scales

set_slc_local_scales(local_scales, reduced_gamma, reduced_bias=None)

GitHub

Set the shaded light-cone (SLC) local scales and reduced gamma on the instance.

These values determine which individual Pauli error terms are mitigated and at what cost when noise_gain="slc_local_scales" is passed to prepare().

The parameters local_scales, reduced_gamma, and reduced_bias can be computed using the qiskit-addon-slc package. See the package guide for more information. A summary of the computation flow is shown below.

  1. Call generate_slc_bounds_computation_input() with the target circuit to obtain the boxed circuit and noise_model_paulis.

  2. Compute the bounds to pass to qiskit_addon_slc.bounds.compute_local_scales(). At least one direction is required. Examples:

    • Forward only (optionally tightened):

      bounds = compute_forward_bounds(boxed_circuit, noise_model_paulis, observable)
      bounds = tighten_with_speed_limit(bounds, boxed_circuit, noise_model_paulis, observable)  # optional
    • Backward only:

      bounds = compute_backward_bounds(boxed_circuit, noise_model_paulis)
    • Both directions merged (use qiskit_addon_slc.bounds.merge_bounds()):

      bounds = merge_bounds(
          boxed_circuit,
          tighten_with_speed_limit(
              compute_forward_bounds(boxed_circuit, noise_model_paulis, observable),
              boxed_circuit, noise_model_paulis, observable,
          ),
          compute_backward_bounds(boxed_circuit, noise_model_paulis),
          noise_maps,
      )
  3. Call qiskit_addon_slc.bounds.compute_local_scales() with either a sampling_cost_budget (upper bound on gamma^2) or a bias_tolerance (upper bound on the remaining bias) to obtain local_scales, sampling_cost, and reduced_bias. Pass sqrt(sampling_cost) as reduced_gamma:

    local_scales, sampling_cost, reduced_bias = compute_local_scales(
        boxed_circuit, bounds, noise_maps, sampling_cost_budget=<budget>
    )
    pec.set_slc_local_scales(local_scales, float(np.sqrt(sampling_cost)), reduced_bias)

Parameters

  • local_scales (dict[str, ndarray]) – Dict mapping each box ref to an array of per-term local scales, indicating which individual error terms to mitigate.
  • reduced_gamma (float) – The square root of the sampling cost overhead (gamma) associated with the given local_scales.
  • reduced_bias (float | None) – The remaining bias on expectation values for the given local_scales. If None, no bias value is stored.

Return type

None

Was this page helpful?
Report a bug, typo, or request content on GitHub.