Skip to content

Commit

Permalink
Remove references to deprecated qiskit.execute
Browse files Browse the repository at this point in the history
  • Loading branch information
airwoodix committed Feb 16, 2024
1 parent 92a9ad4 commit aaf5b07
Show file tree
Hide file tree
Showing 11 changed files with 149 additions and 238 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

## Unreleased

* Remove references to the deprecated function `qiskit.execute` (#136)

## qiskit-aqt-provider v1.2.0

* Add support for Python 3.12 (#79)
Expand Down
22 changes: 10 additions & 12 deletions docs/guide.rst
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,6 @@ This guide covers usage of the Qiskit AQT provider package with the AQT cloud po
.. jupyter-execute::
:hide-code:

import warnings
warnings.simplefilter("ignore", category=DeprecationWarning)

import qiskit
from math import pi

Expand Down Expand Up @@ -104,11 +101,13 @@ Basic quantum circuit execution follows the regular Qiskit workflow. A quantum c

.. warning:: AQT backends currently require a single projective measurement as last operation in a circuit. The hardware implementation always targets all the qubits in the quantum register, even if the circuit defines a partial measurement.

The :func:`qiskit.execute <qiskit.execute_function.execute>` schedules the circuit for execution on a backend and immediately returns the corresponding job handle:
Prior to execution circuits must be transpiled to only use gates supported by the selected backend. The transpiler's entry point is the :func:`qiskit.transpile <qiskit.compiler.transpile>` function. See `Quantum circuit transpilation`_ for more information.
The :meth:`AQTResource.run <qiskit_aqt_provider.aqt_resource.AQTResource.run>` method schedules the circuit for execution on a backend and immediately returns the corresponding job handle:

.. jupyter-execute::

job = qiskit.execute(circuit, backend)
transpiled_circuit = qiskit.transpile(circuit, backend)
job = backend.run(transpiled_circuit)

The :meth:`AQTJob.result <qiskit_aqt_provider.aqt_job.AQTJob.result>` method blocks until the job completes (either successfully or not). The return type is a standard Qiskit :class:`Result <qiskit.result.Result>` instance:

Expand All @@ -121,16 +120,17 @@ The :meth:`AQTJob.result <qiskit_aqt_provider.aqt_job.AQTJob.result>` method blo
else:
raise RuntimeError

Multiple options can be passed to :func:`qiskit.execute <qiskit.execute_function.execute>` that influence the backend behavior and interaction with the AQT cloud. See the reference documentation of the :class:`AQTOptions <qiskit_aqt_provider.aqt_options.AQTOptions>` class for a complete list.
Multiple options can be passed to :meth:`AQTResource.run <qiskit_aqt_provider.aqt_resource.AQTResource.run>` that influence the backend behavior and interaction with the AQT cloud. See the reference documentation of the :class:`AQTOptions <qiskit_aqt_provider.aqt_options.AQTOptions>` class for a complete list.

Batch circuits evaluation
-------------------------

The :func:`qiskit.execute <qiskit.execute_function.execute>` function can also be given a list of quantum circuits to execute as a batch. The returned :class:`AQTJob <qiskit_aqt_provider.aqt_job.AQTJob>` is a handle for all the circuit executions. Execution of individual circuits within such a batch job can be monitored using the :meth:`AQTJob.progress <qiskit_aqt_provider.aqt_job.AQTJob.progress>` method. The :attr:`with_progress_bar <qiskit_aqt_provider.aqt_options.AQTOptions.with_progress_bar>` option on AQT backends (enabled by default) allows printing an interactive progress bar on the standard error stream (:data:`sys.stderr`).
The :meth:`AQTResource.run <qiskit_aqt_provider.aqt_resource.AQTResource.run>` method can also be given a list of quantum circuits to execute as a batch. The returned :class:`AQTJob <qiskit_aqt_provider.aqt_job.AQTJob>` is a handle for all the circuit executions. Execution of individual circuits within such a batch job can be monitored using the :meth:`AQTJob.progress <qiskit_aqt_provider.aqt_job.AQTJob.progress>` method. The :attr:`with_progress_bar <qiskit_aqt_provider.aqt_options.AQTOptions.with_progress_bar>` option on AQT backends (enabled by default) allows printing an interactive progress bar on the standard error stream (:data:`sys.stderr`).

.. jupyter-execute::

job = qiskit.execute([circuit, circuit], backend)
transpiled_circuit0, transpiled_circuit1 = qiskit.transpile([circuit, circuit], backend)
job = backend.run([transpiled_circuit0, transpiled_circuit1])
print(job.progress())

The result of a batch job is also a standard Qiskit :class:`Result <qiskit.result.Result>` instance. The `success` marker is true if and only if all individual circuits were successfully executed:
Expand All @@ -155,7 +155,7 @@ Due to the limited availability of quantum computing resources, a job may have t

job_ids = set()

job = qiskit.execute(circuit, backend)
job = backend.run(transpiled_circuit)
job.persist()
job_ids.add(job.job_id())

Expand Down Expand Up @@ -224,9 +224,7 @@ AQT backends only natively implement a limited but complete set of quantum gates

.. warning:: For implementation reasons, the transpilation target declares :class:`RXGate <qiskit.circuit.library.RXGate>` as basis gate. The AQT API, however, only accepts the more general :class:`RGate <qiskit.circuit.library.RGate>`, in addition to :class:`RZGate <qiskit.circuit.library.RZGate>`, the entangling :class:`RXXGate <qiskit.circuit.library.RXXGate>`, and the :class:`Measure <qiskit.circuit.library.Measure>` operation.

Circuit transpilation targeting the AQT backends is automatically performed when using the :func:`qiskit.execute <qiskit.execute_function.execute>` function. The optimization level can be tuned using the ``optimization_level=0,1,2,3`` argument.

Transpilation can also be triggered separately from job submission using the :func:`qiskit.transpile <qiskit.compiler.transpile>` function, allowing to inspect the transformation from the original circuit:
The transpiler's entry point is the :func:`qiskit.transpile <qiskit.compiler.transpile>` function. The optimization level can be tuned using the ``optimization_level=0,1,2,3`` argument. One can inspect how the circuit is converted from the original one:

.. jupyter-execute::
:hide-code:
Expand Down
8 changes: 6 additions & 2 deletions examples/example.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,15 +34,19 @@
# match. For example:
backend = provider.get_backend("offline_simulator_no_noise", workspace="default")

# Create a 4-qubit GHZ state
# Define a quantum circuit that produces a 2-qubit GHZ state.
qc = QuantumCircuit(4)
qc.h(0)
qc.cx(0, 1)
qc.cx(0, 2)
qc.cx(0, 3)
qc.measure_all()

result = qiskit.execute(qc, backend, shots=200).result()
# Transpile for the target backend.
qc = qiskit.transpile(qc, backend)

# Execute on the target backend.
result = backend.run(qc, shots=200).result()

if result.success:
print(result.get_counts())
Expand Down
8 changes: 6 additions & 2 deletions examples/example_noise.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,13 +37,17 @@
# match. For example:
backend = provider.get_backend("offline_simulator_noise", workspace="default")

# Create a 2-qubit GHZ state
# Define a quantum circuit that produces a 2-qubit GHZ state.
qc = QuantumCircuit(2)
qc.h(0)
qc.cx(0, 1)
qc.measure_all()

result = qiskit.execute(qc, backend, shots=200).result()
# Transpile for the target backend.
qc = qiskit.transpile(qc, backend)

# Execute on the target backend.
result = backend.run(qc, shots=200).result()

if result.success:
# due to the noise, also the states '01' and '10' may be populated!
Expand Down
16 changes: 8 additions & 8 deletions qiskit_aqt_provider/aqt_job.py
Original file line number Diff line number Diff line change
Expand Up @@ -120,23 +120,23 @@ class AQTJob(JobV1):
Jobs contain one or more quantum circuits that are executed with a common
set of options (see :class:`AQTOptions <qiskit_aqt_provider.aqt_options.AQTOptions>`).
Job handles should be retrieved from calls to
:func:`qiskit.execute <qiskit.execute_function.execute>`
or :meth:`AQTResource.run <qiskit_aqt_provider.aqt_resource.AQTResource.run>`, both of which
immediately submit the job for execution. The :meth:`result` method allows blocking until a job
Job handles should be retrieved from calls
to :meth:`AQTResource.run <qiskit_aqt_provider.aqt_resource.AQTResource.run>`, which immediately
returns after submitting the job. The :meth:`result` method allows blocking until a job
completes:
>>> import qiskit
>>> from qiskit.providers import JobStatus
>>> from qiskit_aqt_provider import AQTProvider
...
>>>
>>> backend = AQTProvider("").get_backend("offline_simulator_no_noise")
...
>>>
>>> qc = qiskit.QuantumCircuit(1)
>>> _ = qc.rx(3.14, 0)
>>> _ = qc.measure_all()
...
>>> job = qiskit.execute(qc, backend, shots=100)
>>> qc = qiskit.transpile(qc, backend)
>>>
>>> job = backend.run(qc, shots=100)
>>> result = job.result()
>>> job.status() is JobStatus.DONE
True
Expand Down
12 changes: 6 additions & 6 deletions qiskit_aqt_provider/aqt_options.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,25 +28,25 @@ class AQTOptions(pdt.BaseModel, Mapping[str, Any]):
>>> import qiskit
>>> from qiskit_aqt_provider import AQTProvider
...
>>>
>>> backend = AQTProvider("").get_backend("offline_simulator_no_noise")
...
>>>
>>> qc = qiskit.QuantumCircuit(1)
>>> _ = qc.rx(3.14, 0)
>>> _ = qc.measure_all()
...
>>> qc = qiskit.transpile(qc, backend)
>>>
>>> backend.options.shots = 50
>>> result = qiskit.execute(qc, backend).result()
>>> result = backend.run(qc).result()
>>> sum(result.get_counts().values())
50
Option overrides can also be applied on a per-job basis, as keyword arguments to
:func:`qiskit.execute <qiskit.execute_function.execute>` or
:meth:`AQTResource.run <qiskit_aqt_provider.aqt_resource.AQTResource.run>`:
>>> backend.options.shots
50
>>> result = qiskit.execute(qc, backend, shots=100).result()
>>> result = backend.run(qc, shots=100).result()
>>> sum(result.get_counts().values())
100
"""
Expand Down
70 changes: 70 additions & 0 deletions qiskit_aqt_provider/test/utils.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
# This code is part of Qiskit.
#
# (C) Alpine Quantum Technologies GmbH 2024
#
# This code is licensed under the Apache License, Version 2.0. You may
# obtain a copy of this license in the LICENSE.txt file in the root directory
# of this source tree or at http://www.apache.org/licenses/LICENSE-2.0.
#
# Any modifications or derivative works of this code must retain this
# copyright notice, and modified files need to carry a notice indicating
# that they have been altered from the originals.

"""Miscellaneous testing utilities."""

from typing import TypeVar, Union

import annotated_types
from pydantic import BaseModel

T = TypeVar("T", bound=annotated_types.BaseMetadata)


def get_field_constraint(
model: Union[BaseModel, type[BaseModel]],
field: str,
constraint: type[T],
) -> T:
"""Retrieve a given piece of metadata from a Pydantic model field.
Args:
model: model owning the field.
field: name of the field to inspect.
constraint: type of the annotation to retrieve.
Returns:
instance of the first matching annotation.
Raises:
AttributeError: the passed model doesn't contain a field with the given name.
ValueError: the target field doesn't contain a matching annotation.
Examples:
>>> from pydantic import BaseModel
>>> from typing import Annotated
>>> from annotated_types import Ge, Le
>>>
>>> class M(BaseModel):
... x: Annotated[int, Ge(3)]
...
>>> get_field_constraint(M, "x", Ge)
Ge(ge=3)
>>> get_field_constraint(M(x=4), "x", Ge)
Ge(ge=3)
>>> get_field_constraint(M, "x", Le)
Traceback (most recent call last):
...
ValueError: <class 'annotated_types.Le'>
>>> get_field_constraint(M, "y", Ge)
Traceback (most recent call last):
...
AttributeError: y
"""
if (field_info := model.model_fields.get(field)) is None:
raise AttributeError(field)

for metadata in field_info.metadata:
if isinstance(metadata, constraint):
return metadata

raise ValueError(constraint)
Loading

0 comments on commit aaf5b07

Please sign in to comment.