Skip to content
8 changes: 8 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,16 @@

### Documentation 📝

* The documentation for `qiskit.basicsim` and `qiskit.aer` device have been updated with a mention that
they must be used in finite-shot mode.
[(#549)](https://github.com/PennyLaneAI/pennylane-qiskit/pull/549)

### Bug fixes 🐛

* The `qiskit.basicsim` and `qiskit.aer` device (with the `aer_simulator` backend) now raise a warning
when `shots=None` and change the number of shots to `shots=1024`.
[(#549)](https://github.com/PennyLaneAI/pennylane-qiskit/pull/549)

### Contributors ✍️

This release contains contributions from (in alphabetical order):
Expand Down
3 changes: 3 additions & 0 deletions doc/devices/aer.rst
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,9 @@ You can instantiate a ``'qiskit.aer'`` device for PennyLane with:
import pennylane as qml
dev = qml.device('qiskit.aer', wires=2)

This device must be used in finite-shots mode with the ``aer_simulator`` backend. If ``shots=None`` in this setting,
it will be overwritten to ``shots=1024``.

This device can then be used just like other devices for the definition and evaluation of QNodes within PennyLane.
A simple quantum function that returns the expectation value of a measurement and depends on three classical input
parameters would look like:
Expand Down
3 changes: 2 additions & 1 deletion doc/devices/basicsim.rst
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,12 @@ that can be accessed in this plugin through:

This device uses the Qiskit ``BasicSimulator`` backend from the
`basic_provider <https://docs.quantum.ibm.com/api/qiskit/providers_basic_provider>`_ module in Qiskit.
This device must be used in finite-shots mode. If ``shots=None``, it will be overwritten to ``shots=1024``.

.. note::

The `Qiskit Aer <https://qiskit.github.io/qiskit-aer/>`_ device
provides a fast simulator that is also capable of simulating
noise. It is available as :ref:`"qiskit.aer" <aer device page>`, but the backend must be
installed separately with ``pip install qiskit-aer``.


6 changes: 3 additions & 3 deletions pennylane_qiskit/basic_aer.py
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ class BasicAerDevice(QiskitDevice):

short_name = "qiskit.basicaer"

def __init__(self, wires, shots=1024, backend="qasm_simulator", **kwargs):
def __init__(self, wires, shots=None, backend="qasm_simulator", **kwargs):

max_ver = Version("0.46", partial=True)

Expand Down Expand Up @@ -93,10 +93,10 @@ class BasicSimulatorDevice(QiskitDevice):
analytic_warning_message = (
"The plugin does not currently support analytic calculation of expectations, variances "
"and probabilities with the BasicProvider backend {}. Such statistics obtained from this "
"device are estimates based on samples."
"device are estimates based on samples. The simulation will be run with shots=1024."
)

def __init__(self, wires, shots=1024, backend="basic_simulator", **kwargs):
def __init__(self, wires, shots=None, backend="basic_simulator", **kwargs):

min_version = Version("1.0.0")

Expand Down
1 change: 1 addition & 0 deletions pennylane_qiskit/qiskit_device.py
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,7 @@ class QiskitDevice(QubitDevice, abc.ABC):
"The analytic calculation of expectations, variances and "
"probabilities is only supported on statevector backends, not on the {}. "
"Such statistics obtained from this device are estimates based on samples."
"The simulation will be run with shots=1024."
)

_eigs = {}
Expand Down
56 changes: 44 additions & 12 deletions tests/test_qiskit_device.py
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,9 @@ class TestSupportForV1andV2:
)
def test_v1_and_v2_mocked(self, dev_backend):
"""Test that device initializes with no error mocked"""
dev = qml.device("qiskit.remote", wires=10, backend=dev_backend, use_primitives=True)
dev = qml.device(
"qiskit.remote", wires=10, backend=dev_backend, use_primitives=True
)
assert dev._backend == dev_backend

@pytest.mark.parametrize(
Expand All @@ -120,7 +122,9 @@ def test_v1_and_v2_mocked(self, dev_backend):
)
def test_v1_and_v2_manila(self, dev_backend):
"""Test that device initializes with no error with V1 and V2 backends by Qiskit"""
dev = qml.device("qiskit.remote", wires=5, backend=dev_backend, use_primitives=True)
dev = qml.device(
"qiskit.remote", wires=5, backend=dev_backend, use_primitives=True
)

@qml.qnode(dev)
def circuit(x):
Expand Down Expand Up @@ -156,7 +160,9 @@ def test_device_with_transpilation_options(self, device, wires, device_options):
assert dev.transpile_args == device_options

@pytest.mark.parametrize("transpile_options", test_transpile_options)
def test_transpilation_option_update(self, device, wires, device_options, transpile_options):
def test_transpilation_option_update(
self, device, wires, device_options, transpile_options
):
"""Test that the transpilation options are updated as expected."""
dev = device(wires, device_options)
assert dev.transpile_args == device_options
Expand All @@ -167,22 +173,46 @@ def test_transpilation_option_update(self, device, wires, device_options, transp
class TestAnalyticWarningHWSimulator:
"""Tests the warnings for when the analytic attribute of a device is set to true"""

def test_warning_raised_for_hardware_backend_analytic_expval(self, recorder):
testcases_warning_raised_for_hardware_backend_analytic_expval = [
(
"qiskit.aer",
"aer_simulator",
(
"The analytic calculation of expectations, variances and "
"probabilities is only supported on statevector backends, not on the aer_simulator. "
"Such statistics obtained from this device are estimates based on samples."
"The simulation will be run with shots=1024."
),
),
(
"qiskit.basicsim",
"basic_simulator",
(
"The plugin does not currently support analytic calculation of expectations, variances "
"and probabilities with the BasicProvider backend basic_simulator. Such statistics obtained from this "
"device are estimates based on samples. The simulation will be run with shots=1024."
),
),
]

@pytest.mark.parametrize(
"device_backend_msg",
testcases_warning_raised_for_hardware_backend_analytic_expval,
)
def test_warning_raised_for_hardware_backend_analytic_expval(
self, device_backend_msg, recorder
):
Comment thread
isaacdevlugt marked this conversation as resolved.
"""Tests that a warning is raised if the analytic attribute is true on
hardware simulators when calculating the expectation"""

with pytest.warns(UserWarning) as record:
dev = qml.device("qiskit.aer", backend="aer_simulator", wires=2, shots=None)
shortname, backend, msg = device_backend_msg
dev = qml.device(shortname, backend=backend, wires=2, shots=None)

# check that only one warning was raised
assert len(record) == 1
# check that the message matches
assert (
record[0].message.args[0] == "The analytic calculation of "
"expectations, variances and probabilities is only supported on "
f"statevector backends, not on the {dev.backend.name}. Such statistics obtained from this "
"device are estimates based on samples."
)
assert record[0].message.args[0] == msg

@pytest.mark.parametrize("method", ["unitary", "statevector"])
def test_no_warning_raised_for_software_backend_analytic_expval(
Expand All @@ -191,7 +221,9 @@ def test_no_warning_raised_for_software_backend_analytic_expval(
"""Tests that no warning is raised if the analytic attribute is true on
statevector simulators when calculating the expectation"""

_ = qml.device("qiskit.aer", backend="aer_simulator", method=method, wires=2, shots=None)
_ = qml.device(
"qiskit.aer", backend="aer_simulator", method=method, wires=2, shots=None
)

# check that no warnings were raised
assert len(recwarn) == 0
Expand Down