Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add conversion support for Qiskit's NoiseModels #569

Closed
wants to merge 39 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
39 commits
Select commit Hold shift + click to select a range
7ea085a
initial helper functions
obliviateandsurrender Jul 5, 2024
aaa3ae9
add conversion and coellection
obliviateandsurrender Jul 5, 2024
a31c8e4
add options
obliviateandsurrender Jul 8, 2024
a23a8e3
add documentation
obliviateandsurrender Jul 8, 2024
10768b9
tweak docs
obliviateandsurrender Jul 8, 2024
0badd30
minor tweaks
obliviateandsurrender Jul 8, 2024
717f78f
add tests
obliviateandsurrender Jul 8, 2024
974d70f
add tests
obliviateandsurrender Jul 9, 2024
7d97b96
add missing test
obliviateandsurrender Jul 9, 2024
fc73f7a
minor tweak
obliviateandsurrender Jul 9, 2024
caf5da2
update pl sphinx
obliviateandsurrender Jul 9, 2024
d936023
minor test tweak
obliviateandsurrender Jul 9, 2024
c30f35a
Merge branch 'master' into noise-model-convert
obliviateandsurrender Jul 9, 2024
46d60f1
missing test
obliviateandsurrender Jul 9, 2024
7035492
Merge branch 'noise-model-convert' of https://github.com/PennyLaneAI/…
obliviateandsurrender Jul 9, 2024
3eb56e0
tweak
obliviateandsurrender Jul 9, 2024
ea7d6f7
doc tweak
obliviateandsurrender Jul 10, 2024
b4a6e3c
Merge branch 'master' into noise-model-convert
obliviateandsurrender Jul 10, 2024
134b4f0
thermal error edge cases
obliviateandsurrender Jul 12, 2024
ab7a11e
happy `black`
obliviateandsurrender Jul 12, 2024
7d6333a
optional readout
obliviateandsurrender Jul 12, 2024
b6f1a1f
lil twix
obliviateandsurrender Jul 12, 2024
9016f22
doc tweak
obliviateandsurrender Jul 12, 2024
ab64443
add example
obliviateandsurrender Jul 12, 2024
48ada9a
black fix
obliviateandsurrender Jul 12, 2024
5b03736
tweak example
obliviateandsurrender Jul 12, 2024
1a8b4ee
update gate times
obliviateandsurrender Jul 13, 2024
061ca00
happy black
obliviateandsurrender Jul 13, 2024
d2cfc4a
improve gate times
obliviateandsurrender Jul 13, 2024
8d9e9ff
gate times test
obliviateandsurrender Jul 13, 2024
9f5f96c
minor tweak
obliviateandsurrender Jul 13, 2024
123cf43
minor tweaks
obliviateandsurrender Jul 14, 2024
787c85e
docs tweak
obliviateandsurrender Jul 14, 2024
c2af70d
tweaks
obliviateandsurrender Jul 14, 2024
ff73066
tweak
obliviateandsurrender Jul 15, 2024
4b97f4d
whitespaces
obliviateandsurrender Jul 15, 2024
cfb6304
doc fix?
obliviateandsurrender Jul 15, 2024
1af5805
improve a test
obliviateandsurrender Jul 15, 2024
53c26c1
changelog
obliviateandsurrender Jul 15, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@

### New features since last release

* Added the support for converting Qiskit noise models to
PennyLane ``NoiseModels`` using ``load_noise_model``.
[(#569)](https://github.com/PennyLaneAI/pennylane-qiskit/pull/569)

### Improvements 🛠

### Breaking changes 💔
Expand All @@ -16,6 +20,9 @@

This release contains contributions from (in alphabetical order):

Utkarsh Azad


---
# Release 0.37.0

Expand Down
2 changes: 1 addition & 1 deletion pennylane_qiskit/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,6 @@
from .basic_aer import BasicAerDevice, BasicSimulatorDevice
from .ibmq import IBMQDevice
from .remote import RemoteDevice
from .converter import load, load_pauli_op, load_qasm, load_qasm_from_file
from .converter import load, load_pauli_op, load_qasm, load_qasm_from_file, load_noise_model
from .runtime_devices import IBMQCircuitRunnerDevice
from .runtime_devices import IBMQSamplerDevice
113 changes: 109 additions & 4 deletions pennylane_qiskit/converter.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,15 +15,19 @@
This module contains functions for converting Qiskit QuantumCircuit objects
into PennyLane circuit templates.
"""
from typing import Dict, Any, Iterable, Sequence, Union
import warnings
from functools import partial, reduce
from typing import Any, Dict, Iterable, Sequence, Union

import numpy as np
import pennylane as qml
import pennylane.ops as pennylane_ops
import qiskit.qasm2
from pennylane.noise.conditionals import WiresIn, _rename
from pennylane.operation import AnyWires
from qiskit import QuantumCircuit
from qiskit.circuit import Barrier, Clbit, ControlFlowOp, Measure
from qiskit.circuit import Parameter, ParameterExpression, ParameterVector
from qiskit.circuit import Measure, Barrier, ControlFlowOp, Clbit
from qiskit.circuit.classical import expr
from qiskit.circuit.controlflow.switch_case import _DefaultCaseType
from qiskit.circuit.library import GlobalPhaseGate
Expand All @@ -32,10 +36,10 @@
from qiskit.quantum_info import SparsePauliOp
from sympy import lambdify

import pennylane as qml
import pennylane.ops as pennylane_ops
from pennylane_qiskit.qiskit_device import QISKIT_OPERATION_MAP

from .noise_models import _build_noise_model_map

# pylint: disable=too-many-instance-attributes

inv_map = {v.__name__: k for k, v in QISKIT_OPERATION_MAP.items()}
Expand Down Expand Up @@ -1042,3 +1046,104 @@ def _expr_eval_clvals(clbits, clvals, expr_func, bitwise=False):
condition_res = expr_func(meas1, clreg2)

return condition_res


def load_noise_model(noise_model, **kwargs) -> qml.NoiseModel:
"""Loads a PennyLane `NoiseModel <https://docs.pennylane.ai/en/stable/code/api/pennylane.NoiseModel.html>`_
from a Qiskit `noise model <https://qiskit.github.io/qiskit-aer/stubs/qiskit_aer.noise.NoiseModel.html>`_.

Args:
noise_model (qiskit_aer.noise.NoiseModel): A Qiskit noise model object
kwargs: Optional keyword arguments for conversion of the noise model.

Keyword Arguments:
thermal_relaxation (bool): prefer conversion of ``QiskitErrors`` to thermal relaxation errors
over damping errors. Default is ``False``.
readout_error (bool): include readout error in the converted noise model. Default is ``True``.
gate_times (Dict[Tuple(str, Tuple[int]), float]): a dictionary to provide gate times for building
thermal relaxation error. Each key will be a tuple of instruction name and qubit indices and
the corresponding value will be the time in seconds. If it is not provided or a gate/qubit
is missing, then a default value of ``1.0 s`` will be used for the specific constructions.
optimize (bool): controls if a contraction order optimization is used for ``einsum`` while
transforming Kraus operators to a Choi matrix, wherever required. Default is ``False``.
kraus_shape (bool): use shape of the Kraus operators to display ``qml.QubitChannel``
instead of the complete list of matrices. Default is ``True``.
options (dict[str, Union[int, float]]): optional parameters related to tolerance and rounding:

- **decimals** (*int*): number of decimal places to round the Kraus matrices. Default is ``10``.
- **atol** (*float*): the relative tolerance parameter. Default value is ``1e-05``.
- **rtol** (*float*): the absolute tolernace parameters. Defualt value is ``1e-08``.

Returns:
pennylane.NoiseModel: An equivalent noise model constructed in PennyLane

Raises:
ValueError: When an encountered quantum error cannoted be converted.

.. note::

Currently, PennyLane noise models does not support readout errors, so those will be skipped during conversion.

**Example**

Consider the following noise model constructed in Qiskit:

.. code-block:: python

>>> import qiskit.providers.aer.noise as noise
>>> error_1 = noise.depolarizing_error(0.001, 1) # 1-qubit noise
>>> error_2 = noise.depolarizing_error(0.01, 2) # 2-qubit noise
>>> noise_model = noise.NoiseModel()
>>> noise_model.add_all_qubit_quantum_error(error_1, ['rz', 'ry'])
>>> noise_model.add_all_qubit_quantum_error(error_2, ['cx'])
>>> load_noise_model(noise_model)
NoiseModel({
OpIn(['RZ', 'RY']): DepolarizingChannel(p=0.00075)
OpIn(['CNOT']): QubitChannel(Klist=Tensor(16, 4, 4))
})

Equivalently, in PennyLane this will be:

.. code-block:: python

import numpy as np
import pennylane as qml
import itertools as it
import functools as ft

pauli_mats = [
ft.reduce(np.kron, prod, 1.0)
for prod in it.product(
map(qml.matrix, tuple(getattr(qml, i)(0) for i in ["I", "X", "Y", "Z"]))
repeat=2
)
]
pauli_prob = np.sqrt(error_2.probabilities)
kraus_ops = [prob * kraus_op for prob, kraus_op in zip(pauli_prob, pauli_mats)]

c0 = qml.noise.op_eq(qml.RZ) | qml.noise.op_eq(qml.RY)
c1 = qml.noise.op_eq(qml.CNOT)

n0 = qml.noise.partial_wires(qml.DepolarizingChannel, 0.001)
n1 = qml.noise.partial_wires(qml.QubitChanel(kraus_ops))

equivalent_pl_noise_model = qml.NoiseModel({c0: n0, c1: n1})
"""
qerror_dmap, _ = _build_noise_model_map(noise_model, **kwargs)
model_map = {}
for error, wires_map in qerror_dmap.items():
conditions = []
for wires, operations in wires_map.items():
cond = qml.noise.op_in(operations)
if wires != AnyWires:
cond &= WiresIn(wires)
conditions.append(cond)
fcond = reduce(lambda cond1, cond2: cond1 | cond2, conditions)

noise = qml.noise.partial_wires(error)
if isinstance(error, qml.QubitChannel) and kwargs.get("kraus_shape", True):
noise = _rename(f"QubitChannel(Klist=Tensor{qml.math.shape(error.data)})")(noise)

model_map[fcond] = noise

return qml.NoiseModel(model_map)
Loading
Loading