PauliX not working on qiskit.aer

I’m trying to build a circuit with the noise model imported from qiskit. This is the minimal code with the error:

import pennylane as qml
from functools import partial

from qiskit_aer.noise import NoiseModel
from qiskit.providers.fake_provider import GenericBackendV2

backend = GenericBackendV2(num_qubits=2, seed=42)
qk_noise_model = NoiseModel.from_backend(backend)
pl_noise_model = qml.from_qiskit_noise(qk_noise_model)

dev = qml.device("qiskit.aer", wires=2, shots=1000)

@partial(qml.transforms.add_noise, noise_model=pl_noise_model)
@qml.qnode(dev)
def circuit():
    qml.PauliX(wires=1)
    return qml.probs(wires=[0,1])

circuit()

This is the full error message:

---------------------------------------------------------------------------
KeyError                                  Traceback (most recent call last)
Cell In[47], line 13
     10     qml.PauliX(wires=1)
     11     return qml.probs(wires=[0,1])
---> 13 circuit()

File /project/PERCUSA_1516/tmp/.venv/lib/python3.11/site-packages/pennylane/workflow/qnode.py:922, in QNode.__call__(self, *args, **kwargs)
    919     from ._capture_qnode import capture_qnode  # pylint: disable=import-outside-toplevel
    921     return capture_qnode(self, *args, **kwargs)
--> 922 return self._impl_call(*args, **kwargs)

File /project/PERCUSA_1516/tmp/.venv/lib/python3.11/site-packages/pennylane/workflow/qnode.py:895, in QNode._impl_call(self, *args, **kwargs)
    892 # Calculate the classical jacobians if necessary
    893 self._transform_program.set_classical_component(self, args, kwargs)
--> 895 res = execute(
    896     (tape,),
    897     device=self.device,
    898     diff_method=self.diff_method,
    899     interface=self.interface,
    900     transform_program=self._transform_program,
    901     gradient_kwargs=self.gradient_kwargs,
    902     **self.execute_kwargs,
    903 )
    904 res = res[0]
    906 # convert result to the interface in case the qfunc has no parameters

File /project/PERCUSA_1516/tmp/.venv/lib/python3.11/site-packages/pennylane/workflow/execution.py:233, in execute(tapes, device, diff_method, interface, grad_on_execution, cache, cachesize, max_diff, device_vjp, postselect_mode, mcm_method, gradient_kwargs, transform_program, executor_backend)
    229 tapes, outer_post_processing = outer_transform(tapes)
    231 assert not outer_transform.is_informative, "should only contain device preprocessing"
--> 233 results = run(tapes, device, config, inner_transform)
    234 return user_post_processing(outer_post_processing(results))

File /project/PERCUSA_1516/tmp/.venv/lib/python3.11/site-packages/pennylane/workflow/run.py:291, in run(tapes, device, config, inner_transform_program)
    287 no_interface_boundary_required = (
    288     config.interface == Interface.NUMPY or config.gradient_method == "backprop"
    289 )
    290 if no_interface_boundary_required:
--> 291     results = inner_execute(tapes)
    292     return results
    294 # TODO: Prune once support for tf-autograph is dropped

File /project/PERCUSA_1516/tmp/.venv/lib/python3.11/site-packages/pennylane/workflow/run.py:256, in _make_inner_execute.<locals>.inner_execute(tapes)
    253 transformed_tapes, transform_post_processing = inner_transform(tapes)
    255 if transformed_tapes:
--> 256     results = device.execute(transformed_tapes, execution_config=execution_config)
    257 else:
    258     results = ()

File /project/PERCUSA_1516/tmp/.venv/lib/python3.11/site-packages/pennylane/devices/modifiers/single_tape_support.py:30, in _make_execute.<locals>.execute(self, circuits, execution_config)
     28     is_single_circuit = True
     29     circuits = (circuits,)
---> 30 results = batch_execute(self, circuits, execution_config)
     31 return results[0] if is_single_circuit else results

File /project/PERCUSA_1516/tmp/.venv/lib/python3.11/site-packages/pennylane/devices/legacy_facade.py:378, in LegacyDeviceFacade.execute(self, circuits, execution_config)
    376 first_shot = circuits[0].shots
    377 if all(t.shots == first_shot for t in circuits):
--> 378     return _set_shots(dev, first_shot)(dev.batch_execute)(circuits, **kwargs)
    379 return tuple(
    380     _set_shots(dev, t.shots)(dev.batch_execute)((t,), **kwargs)[0] for t in circuits
    381 )

File /apps/spack/2406/apps/linux-rocky8-x86_64_v3/gcc-13.3.0/python-3.11.9-x74mtjf/lib/python3.11/contextlib.py:81, in ContextDecorator.__call__.<locals>.inner(*args, **kwds)
     78 @wraps(func)
     79 def inner(*args, **kwds):
     80     with self._recreate_cm():
---> 81         return func(*args, **kwds)

File /project/PERCUSA_1516/tmp/.venv/lib/python3.11/site-packages/pennylane_qiskit/qiskit_device_legacy.py:446, in QiskitDeviceLegacy.batch_execute(self, circuits, timeout)
    443 def batch_execute(self, circuits, timeout: int = None):
    444     """Batch execute the circuits on the device"""
--> 446     compiled_circuits = self.compile_circuits(circuits)
    448     if not compiled_circuits:
    449         # At least one circuit must always be provided to the backend.
    450         return []

File /project/PERCUSA_1516/tmp/.venv/lib/python3.11/site-packages/pennylane_qiskit/qiskit_device_legacy.py:435, in QiskitDeviceLegacy.compile_circuits(self, circuits)
    431 for circuit in circuits:
    432     # We need to reset the device here, else it will
    433     # not start the next computation in the zero state
    434     self.reset()
--> 435     self.create_circuit_object(circuit.operations, rotations=circuit.diagonalizing_gates)
    437     compiled_circ = self.compile()
    438     compiled_circ.name = f"circ{len(compiled_circuits)}"

File /project/PERCUSA_1516/tmp/.venv/lib/python3.11/site-packages/pennylane_qiskit/qiskit_device_legacy.py:247, in QiskitDeviceLegacy.create_circuit_object(self, operations, **kwargs)
    235 """Builds the circuit objects based on the operations and measurements
    236 specified to apply.
    237 
   (...)    243         pre-measurement into the eigenbasis of the observables.
    244 """
    245 rotations = kwargs.get("rotations", [])
--> 247 applied_operations = self.apply_operations(operations)
    249 # Rotating the state for measurement in the computational basis
    250 rotation_circuits = self.apply_operations(rotations)

File /project/PERCUSA_1516/tmp/.venv/lib/python3.11/site-packages/pennylane_qiskit/qiskit_device_legacy.py:297, in QiskitDeviceLegacy.apply_operations(self, operations)
    293         par[idx] = p.tolist()
    295 operation = operation.name
--> 297 mapped_operation = self._operation_map[operation]
    299 self.qubit_state_vector_check(operation)
    301 qregs = [self._reg[i] for i in device_wires.labels]

KeyError: 'QubitChannel'

This is the output of qml.about():

Name: pennylane
Version: 0.42.1
Summary: PennyLane is a cross-platform Python library for quantum computing, quantum machine learning, and quantum chemistry. Train a quantum computer the same way as a neural network.
Home-page: 
Author: 
Author-email: 
License-Expression: Apache-2.0
Location: /project/PERCUSA_1516/tmp/.venv/lib/python3.11/site-packages
Requires: appdirs, autograd, autoray, cachetools, diastatic-malt, networkx, numpy, packaging, pennylane-lightning, requests, rustworkx, scipy, tomlkit, typing_extensions
Required-by: PennyLane-qiskit, pennylane_lightning

Platform info:           Linux-4.18.0-553.8.1.el8_10.x86_64-x86_64-with-glibc2.28
Python version:          3.11.9
Numpy version:           2.3.2
Scipy version:           1.16.0
Installed devices:
- default.clifford (pennylane-0.42.1)
- default.gaussian (pennylane-0.42.1)
- default.mixed (pennylane-0.42.1)
- default.qubit (pennylane-0.42.1)
- default.qutrit (pennylane-0.42.1)
- default.qutrit.mixed (pennylane-0.42.1)
- default.tensor (pennylane-0.42.1)
- null.qubit (pennylane-0.42.1)
- reference.qubit (pennylane-0.42.1)
- lightning.qubit (pennylane_lightning-0.42.0)
- qiskit.aer (PennyLane-qiskit-0.42.0)
- qiskit.basicaer (PennyLane-qiskit-0.42.0)
- qiskit.basicsim (PennyLane-qiskit-0.42.0)
- qiskit.remote (PennyLane-qiskit-0.42.0)

Hi @jorpena , I think the info in this issue and the latest version of the docs might help you. It looks like you’re using a deprecated keyword argument.

Let me know if this solves the issue.

Hi @CatalinaAlbornoz , thank you for your help! I’m having trouble seeing which is the deprecated keyword argument. Could you point out where in my code I;m using the argument?

Hi @jorpena ,

The issue was actually not what I originally thought. The problem you’re having here is that you’re trying to use a PennyLane noise model on a Qiskit device (qiskit.aer), which is not supported by Qiskit.

So instead of using qiskit.aer you can define a PennyLane device:
dev = qml.device("default.mixed", wires=2, shots=1000)

It’s the exact same code you had except for this one line. Let me know if this is what you needed.

On the other hand, if you want to keep using qiskit.aer then you need to add the Qiskit noise model in the creation of your device.

You can learn more about this in the first section of our Importing noise models from Qiskit demo.

I hope this helps!