Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
d38d893
Remove locale from a release note link (#2437)
arnaucasau Oct 15, 2025
99cbd6a
Update logging level for account messages (#2445)
kt474 Oct 23, 2025
553b2dd
Prepare 0.43.1 patch release (#2446)
kt474 Oct 23, 2025
a29deaa
Merged QDC2025
SamFerracin Oct 28, 2025
ff38e0b
revert unimportant changes
SamFerracin Oct 28, 2025
8b37514
format,lint,mypy pass
SamFerracin Oct 28, 2025
f475d92
from __future__ import annotations
SamFerracin Oct 28, 2025
4f6457b
from __future__ import annotations
SamFerracin Oct 28, 2025
49c1b23
Added dummy fallback for typing.Self, not supported in Python < 3.11
SamFerracin Oct 29, 2025
45d0512
fixed
SamFerracin Oct 29, 2025
a561556
try skip docs build for 3.9
SamFerracin Oct 29, 2025
1530583
try skip docs build for 3.9
SamFerracin Oct 29, 2025
681545c
try skip docs build for 3.9
SamFerracin Oct 29, 2025
08bc8a3
conflicts
SamFerracin Oct 29, 2025
8bbcffb
aliased 'Self' in schema repo
SamFerracin Oct 29, 2025
a612209
added 'from __future__ import annotations' in schemas
SamFerracin Oct 29, 2025
fe30890
using optionals and unions in schemas instead of '|'
SamFerracin Oct 29, 2025
fc271eb
Replaced a few 'X | None' with Optional[X]
SamFerracin Oct 29, 2025
0628967
updated schemas
SamFerracin Oct 30, 2025
2b81637
update default image
SamFerracin Oct 30, 2025
e989428
Initial commit for Executor and NoiseLearnerV3
ihincks Oct 30, 2025
9a31806
Merge branch 'executor_preview' of https://github.com/Qiskit/qiskit-i…
SamFerracin Oct 30, 2025
fe55c9c
Render docs for executor branch (reintroduce) and update docs (#2459)
diego-plan9 Oct 30, 2025
95c1082
Update `DEFAULT_IMAGE` (#2460)
SamFerracin Oct 30, 2025
857e0c6
[executor_preview] Add execution timing information to Executor retur…
ihincks Nov 4, 2025
5dd13ed
Docs for Executor (#2467)
SamFerracin Nov 6, 2025
32c0a21
[Executor] Update to samplomatic>=0.12 (#2471)
ihincks Nov 6, 2025
67f2bab
[executor] Fix validation bug in NoiseLearnerV3 (#2472)
ihincks Nov 7, 2025
7c47a79
Fix guide rendering (#2473)
SamFerracin Nov 7, 2025
e8d3302
[executor-preview] Add compatibility with auto-chunk-size generation …
ihincks Nov 8, 2025
30a8303
[executor-preview] Tests for validation of NLV3 (#2496)
yaelbh Dec 8, 2025
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
4 changes: 2 additions & 2 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -48,10 +48,10 @@ jobs:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Set up Python 3.9
- name: Set up Python 3.10
uses: actions/setup-python@v5
with:
python-version: 3.9
python-version: '3.10'
- name: Install dependencies
run: |
python -m pip install --upgrade pip
Expand Down
34 changes: 34 additions & 0 deletions .github/workflows/docs-executor.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
---
name: Docs Upload (executor)

on:
push:
branches: [ "executor_preview" ]

jobs:
doc_publish:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: '3.9.12'
- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install -U virtualenv setuptools wheel tox
sudo apt-get install -y graphviz pandoc
- name: Build docs
run: tox -e docs -- --tag executor
- name: Upload artifact
uses: actions/upload-artifact@v4
with:
name: html_docs_executor
path: docs/_build/html
- name: Bypass Jekyll Processing # Necessary for setting the correct css path
run: touch docs/_build/html/.nojekyll
- name: Deploy
uses: JamesIves/github-pages-deploy-action@v4
with:
folder: docs/_build/html/
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@ target/

# Jupyter Notebook
.ipynb_checkpoints
.notebooks

# pyenv
.python-version
Expand Down
3 changes: 3 additions & 0 deletions .whitesource
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"settingsInheritedFrom": "ibm-q-research/whitesource-config@main"
}
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
*** THIS IS A PROTOTYPE FORK TO TEST A DEMO ***

# Qiskit Runtime IBM Client
[![License](https://img.shields.io/github/license/Qiskit/qiskit-ibm-runtime.svg?style=popout-square)](https://opensource.org/licenses/Apache-2.0)
[![CI](https://github.com/Qiskit/qiskit-ibm-runtime/actions/workflows/ci.yml/badge.svg)](https://github.com/Qiskit/qiskit-ibm-runtime/actions/workflows/ci.yml)
Expand Down
2 changes: 2 additions & 0 deletions docs/apidocs/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,10 @@
:maxdepth: 1

runtime_service
quantum_program
noise_learner
noise_learner_result
noise_learner_v3
options
transpiler
qiskit_ibm_runtime.transpiler.passes.scheduling
Expand Down
4 changes: 4 additions & 0 deletions docs/apidocs/noise_learner_v3.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
.. automodule:: qiskit_ibm_runtime.noise_learner_v3
:no-members:
:no-inherited-members:
:no-special-members:
4 changes: 4 additions & 0 deletions docs/apidocs/quantum_program.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
.. automodule:: qiskit_ibm_runtime.quantum_program
:no-members:
:no-inherited-members:
:no-special-members:
27 changes: 26 additions & 1 deletion docs/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
import os
import re
import sys
import typing

sys.path.insert(0, os.path.abspath("."))

Expand All @@ -27,7 +28,7 @@
# The short X.Y version
version = ""
# The full version, including alpha/beta/rc tags
release = '0.43.0'
release = '0.43.1'

# -- General configuration ---------------------------------------------------

Expand Down Expand Up @@ -64,6 +65,20 @@
link_str = f" https://github.com/Qiskit/qiskit-ibm-runtime/blob/stable/{vers[0]}.{vers[1]}/docs/"
nbsphinx_prolog += link_str + "{{ docname }}"


# ----------------------------------------------------------------------------------
# Patch 'Self' for Python < 3.11 if missing
# ----------------------------------------------------------------------------------

if not hasattr(typing, "Self"):
try:
from typing_extensions import Self
except ImportError:
class Self:
"""Dummy fallback for 'Self' for older python versions."""
pass
typing.Self = Self

# ----------------------------------------------------------------------------------
# Intersphinx
# ----------------------------------------------------------------------------------
Expand Down Expand Up @@ -137,6 +152,16 @@
html_sourcelink_suffix = ""


# -----------------------------------------------------------------------------
# `executor`-specific options
# -----------------------------------------------------------------------------
if "executor" in tags:
extensions += ["qiskit_sphinx_theme"]
html_theme = "qiskit-ecosystem"
html_theme_options = {
"sidebar_qiskit_ecosystem_member": False,
}

# ----------------------------------------------------------------------------------
# Source code links
# ----------------------------------------------------------------------------------
Expand Down
253 changes: 253 additions & 0 deletions docs/guides/executor_basic.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,253 @@
The Executor: A quick-start guide
=================================

This guide provides a basic overview of the :class:`~.Executor`, a runtime program that allows
executing :class:`~.QuantumProgram`\s on IBM backends. At the end of this guide, you will
know how to:

* Initialize a :class:`~.QuantumProgram` with your workload.
* Run :class:`~.QuantumProgram`\s on IBM backends using the :class:`~.Executor`.
* Interpret the outputs of the :class:`~.Executor`.

In the remainder of the guide, we consider a circuit that generates a three-qubit GHZ state, rotates
the qubits around the Pauli-Z axis, and measures the qubits in the computational basis. We show how
to add this circuit to a :class:`~.QuantumProgram`, optionally randomizing its content with twirling
gates, and how to execute the program via the :class:`~.Executor`.

.. code-block:: python

from qiskit.circuit import Parameter, QuantumCircuit

# A circuit of the type considered in this guide
circuit = QuantumCircuit(3)
circuit.h(0)
circuit.h(1)
circuit.cz(0, 1)
circuit.h(1)
circuit.h(2)
circuit.cz(1, 2)
circuit.h(2)
circuit.rz(Parameter("theta"), 0)
circuit.rz(Parameter("phi"), 1)
circuit.rz(Parameter("lam"), 2)
circuit.measure_all()

Let us choose a backend to run our executor jobs with:

.. code-block:: python

from qiskit_ibm_runtime import QiskitRuntimeService

service = QiskitRuntimeService()
backend = service.least_busy(operational=True, simulator=False)

We can now begin by taking a look at the inputs to the :class:`~.Executor`, the :class:`~.QuantumProgram`\s.

The inputs to the Executor: Quantum Programs
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

A :class:`~.QuantumProgram` is an iterable of
:class:`~.qiskit_ibm_runtime.quantum_program.QuantumProgramItem`\s. Each of these items represents a
different task for the :class:`~.Executor` to perform. Typically, each item owns:

* a :class:`~qiskit.circuit.QuantumCircuit` with static, non-parametrized gates;
* or a parametrized :class:`~qiskit.circuit.QuantumCircuit`, together with an array of parameter values;
* or a parametrized :class:`~qiskit.circuit.QuantumCircuit`, together with a
:class:`~samplomatic.samplex.Samplex` to generate randomize arrays of parameter values.

Let us take a closer look at each of these items and how to add them to a :class:`~.QuantumProgram`\.

In the cell below, we initialize a :class:`~.QuantumProgram` and specify that we wish to perform ``1024``
shots for every configuration of each item in the program. Next, we append a version of our target circuit with set parameters,
transpiled according to the backend's ISA.

.. code-block:: python

from qiskit.transpiler import generate_preset_pass_manager
from qiskit_ibm_runtime.quantum_program import QuantumProgram

# Initialize an empty program
program = QuantumProgram(shots=1024)

# Initialize circuit to generate and measure GHZ state
circuit = QuantumCircuit(3)
circuit.h(0)
circuit.h(1)
circuit.cz(0, 1)
circuit.h(1)
circuit.h(2)
circuit.cz(1, 2)
circuit.h(2)
circuit.rz(0.1, 0)
circuit.rz(0.2, 1)
circuit.rz(0.3, 2)
circuit.measure_all()

# Transpile the circuit
preset_pass_manager = generate_preset_pass_manager(backend=backend, optimization_level=0)
isa_circuit = preset_pass_manager.run(circuit)

# Append the circuit to the program
program.append(isa_circuit)

We proceed to append a second item that contains a parametrized :class:`~qiskit.circuit.QuantumCircuit`
and an array containing ``10`` sets of parameter values. This amounts to a circuit task requiring a total
of ``10240`` shots (namely ``1024`` per set of parameter values).

.. code-block:: python

from qiskit.circuit import Parameter
import numpy as np

# Initialize circuit to generate a GHZ state, rotate it around the Pauli-Z
# axis, and measure it
circuit = QuantumCircuit(3)
circuit.h(0)
circuit.h(1)
circuit.cz(0, 1)
circuit.h(1)
circuit.h(2)
circuit.cz(1, 2)
circuit.h(2)
circuit.rz(Parameter("theta"), 0)
circuit.rz(Parameter("phi"), 1)
circuit.rz(Parameter("lam"), 2)
circuit.measure_all()

# Transpile the circuit
isa_circuit = preset_pass_manager.run(circuit)

# Append the circuit and the parameter value to the program
program.append(
isa_circuit,
circuit_arguments=np.random.rand(10, 3), # 10 sets of parameter values
)

Finally, in the next cell we append a parametrized :class:`~qiskit.circuit.QuantumCircuit` and a
:class:`~samplomatic.samplex.Samplex`, which is responsible for generating randomized sets of
parameters for the given circuit. As part of the :class:`~samplomatic.samplex.Samplex` arguments,
we provide ``10`` sets of parameters for the parametric gates in the original circuit.
Additionally, we use the ``shape`` request argument to request an extension of the implicit shape
defined by the :class:`~samplomatic.samplex.Samplex` arguments. In particular, by setting ``shape``
to ``(2, 14, 10)`` we request to randomize each of the ``10`` sets of parameters ``28`` times, and
to arrange the randomized parameter sets in an array of be arranged in an array of shape
``(2, 14, 10)``.

We refer the reader to :mod:`~samplomatic` and its documentation for more details on the
:class:`~samplomatic.samplex.Samplex` and its arguments.

.. code-block:: python

from samplomatic import build
from samplomatic.transpiler import generate_boxing_pass_manager

# Initialize circuit to generate a GHZ state, rotate it around the Pauli-Z
# axis, and measure it
circuit = QuantumCircuit(3)
circuit.h(0)
circuit.h(1)
circuit.cz(0, 1)
circuit.h(1)
circuit.h(2)
circuit.cz(1, 2)
circuit.h(2)
circuit.rz(Parameter("theta"), 0)
circuit.rz(Parameter("phi"), 1)
circuit.rz(Parameter("lam"), 2)
circuit.measure_all()

# Transpile the circuit, additionally grouping gates and measurements into annotated boxes
preset_pass_manager = generate_preset_pass_manager(backend=backend, optimization_level=0)
preset_pass_manager.post_scheduling = generate_boxing_pass_manager(
enable_gates=True,
enable_measures=True,
)
boxed_circuit = preset_pass_manager.run(circuit)

# Build the template and the samplex
template, samplex = build(boxed_circuit)

# Append the template and samplex as a samplex item
program.append(
template,
samplex=samplex,
samplex_arguments={
# the arguments required by the samplex.sample method
"parameter_values": np.random.rand(10, 3),
},
shape=(2, 14, 10),
)

Now that we have populated our :class:`~.QuantumProgram`, we can proceed with execution.

Running an Executor job
~~~~~~~~~~~~~~~~~~~~~~~

In the cell below we initialize an :class:`~.Executor` and leave the default options:

.. code-block:: python

from qiskit_ibm_runtime import Executor

executor = Executor(backend)

Next, we use the :meth:`~.Executor.run` method to submit the job.

.. code-block:: python

job = executor.run(program)

# Retrieve the result
result = job.result()

Here, ``result`` is of type :class:`~.qiskit_ibm_runtime.quantum_program.QuantumProgramResult`.
We now take a closer look at this result object.

The outputs of the Executor
~~~~~~~~~~~~~~~~~~~~~~~~~~~

:class:`~.qiskit_ibm_runtime.quantum_program.QuantumProgramResult` is an iterable. It contains one
item per circuit task, and the items are in the same order as the items in the program. Every one of
these items is a dictionary from strings to an ``np.ndarray``. with elements of type ``bool``. Let us
take a look at the three items in ``result`` to understand the meaning of their key-value pairs.

The first item in ``result`` contains the results of running the first task in the program, namely
the circuit with static gates. It contains a single key, ``'meas'``, corresponding to the name of the
classical register in the input circuit. The ``'meas'`` key is mapped to the results collected for this
classical registers, stored in an ``np.ndarray`` of shape ``(1024, 3)``. The first axis
is over shots, the second is over bits in the classical register.

.. code-block:: python

# Access the results of the classical register of task #0
result_0 = result[0]["meas"]
print(f"Result shape: {result_0.shape}")

The second item contains the results of running the second task in the program, namely
the circuit with parametrized gates. Again, it contains a single key, ``'meas'``, mapped to a
``np.ndarray`` of shape ``(1024, 10, 3)``. The central axis is over parameter sets, while the first
and last are again over shots and bits respectively.

.. code-block:: python

# Access the results of the classical register of task #1
result_1 = result[1]["meas"]
print(f"Result shape: {result_1.shape}")

Finally, the third item in ``result`` contains the results of running the third task in the program. This item
contains multiple key. In more detail, in addition to the ``'meas'`` key (mapped to the array of results for
that classical register), it contains ``'measurement_flips.meas'``, namely the bit-flip corrections to undo
the measurement twirling for the ``'meas'`` register.

.. code-block:: python

# Access the results of the classical register of task #2
result_2 = result[2]["meas"]
print(f"Result shape: {result_2.shape}")

# Access the bit-flip corrections
flips_2 = result[2]["measurement_flips.meas"]
print(f"Result shape: {result_0.shape}")

# Undo the bit flips via classical XOR
unflipped_result_2 = result_2 ^ flips_2
Loading
Loading