Skip to content

Commit

Permalink
Merge branch 'main' into qctrl-integration-tests
Browse files Browse the repository at this point in the history
  • Loading branch information
kt474 authored Nov 13, 2023
2 parents 81d0d49 + ac4efe2 commit cf5d284
Show file tree
Hide file tree
Showing 82 changed files with 5,709 additions and 724 deletions.
1 change: 1 addition & 0 deletions docs/.vale.ini
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ MinAlertLevel = suggestion

[[!_]**.{md,rst}]
BasedOnStyles = IBMQuantum
IBMQuantum.Latin = warning

[apidocs/ibm-runtime.rst]
IBMQuantum.Headings = NO
Expand Down
25 changes: 8 additions & 17 deletions docs/_templates/autosummary/class.rst
Original file line number Diff line number Diff line change
Expand Up @@ -12,34 +12,25 @@
:no-inherited-members:
:no-special-members:

{% block attributes_summary %}
{% block attributes_summary %}
{% if attributes %}

.. rubric:: Attributes

{% for item in all_attributes %}
{%- if not item.startswith('_') %}
{% for item in all_attributes %}
{%- if not item.startswith('_') %}
.. autoattribute:: {{ name }}.{{ item }}
{%- endif -%}
{%- endfor %}
{%- endif -%}
{%- endfor %}
{% endif %}
{% endblock %}
{% endblock %}

{% block methods_summary %}
{% block methods_summary %}
{% if methods %}

.. rubric:: Methods

{% for item in all_methods %}
{%- if not item.startswith('_') or item in ['__call__', '__mul__', '__getitem__', '__len__'] %}
.. automethod:: {{ name }}.{{ item }}
{%- endif -%}
{%- endfor %}
{% for item in inherited_members %}
{%- if item in ['__call__', '__mul__', '__getitem__', '__len__'] %}
.. automethod:: {{ name }}.{{ item }}
{%- endif -%}
{%- endfor %}

{% endif %}
{% endblock %}
{% endblock %}
2 changes: 1 addition & 1 deletion docs/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@
# The short X.Y version
version = ''
# The full version, including alpha/beta/rc tags
release = '0.13.1'
release = '0.14.1'

docs_url_prefix = "ecosystem/ibm-runtime"

Expand Down
31 changes: 11 additions & 20 deletions docs/how_to/error-suppression.rst
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,13 @@ Error suppression typically results in some classical pre-processing overhead to
Primitives let you employ error suppression techniques by setting the optimization level (``optimization_level`` option) and by choosing advanced transpilation options.

Setting the optimization level
------------------------------
-------------------------------

The ``optimization_level`` setting specifies how much optimization to perform on the circuits. Higher levels generate more optimized circuits, at the expense of longer transpilation times.

..note::
When using primitives, optimization levels 2 and 3 behave like level 1.

+--------------------+---------------------------------------------------------------------------------------------------+
| Optimization Level | Estimator & Sampler |
+====================+===================================================================================================+
Expand All @@ -22,29 +25,17 @@ The ``optimization_level`` setting specifies how much optimization to perform on
| | - routing (stochastic swaps) |
| | |
+--------------------+---------------------------------------------------------------------------------------------------+
| 1 | Light optimization: |
| 1, 2, 3 | Light optimization: |
| | |
| | - Layout (trivial → vf2 → SabreLayout if routing is required) |
| | - routing (SabreSWAPs if needed) |
| | - 1Q gate optimization |
| | - Error Suppression: Dynamical Decoupling |
| | |
+--------------------+---------------------------------------------------------------------------------------------------+
| 2 | Medium optimization: |
| | |
| | - Layout/Routing: Optimization level 1 (without trivial) + heuristic optimized with greater |
| | search depth and trials of optimization function |
| | - commutative cancellation |
| | - Error Suppression: Dynamical Decoupling |
| | |
+--------------------+---------------------------------------------------------------------------------------------------+
| 3 (default) | High Optimization: |
| | |
| | * Optimization level 2 + heuristic optimized on layout/routing further with greater effort/trials |
| | * 2 qubit KAK optimization |
| | * Error Suppression: Dynamical Decoupling |
| | |
+--------------------+---------------------------------------------------------------------------------------------------+

..note::
If you want to use more advanced optimization, use the Qiskit transpiler locally and then pass the transpiled circuits to the primitives. For instructions see the `Submitting user-transpiled circuits using primitives <https://learning.quantum-computing.ibm.com/tutorial/submitting-user-transpiled-circuits-using-primitives>`__ tutorial.

Example: configure Estimator with optimization levels
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Expand All @@ -56,7 +47,7 @@ Example: configure Estimator with optimization levels
from qiskit.quantum_info import SparsePauliOp
service = QiskitRuntimeService()
options = Options(optimization_level=2)
options = Options(optimization_level=1)
psi = RealAmplitudes(num_qubits=2, reps=2)
H = SparsePauliOp.from_list([("II", 1), ("IZ", 2), ("XI", 3)])
Expand All @@ -68,7 +59,7 @@ Example: configure Estimator with optimization levels
psi1_H1 = job.result()
.. note::
If optimization level is not specified, the service uses ``optimization_level = 3``.
If optimization level is not specified, the service uses ``optimization_level = 1``.

Example: configure Sampler with optimization levels
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Expand All @@ -78,7 +69,7 @@ Example: configure Sampler with optimization levels
from qiskit_ibm_runtime import QiskitRuntimeService, Session, Sampler, Options
service = QiskitRuntimeService()
options = Options(optimization_level=3)
options = Options(optimization_level=1)
with Session(service=service, backend="ibmq_qasm_simulator") as session:
sampler = Sampler(session=session, options=options)
Expand Down
22 changes: 12 additions & 10 deletions docs/how_to/run_session.rst
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ Open a session
You can open a runtime session by using the context manager `with Session(…)` or by initializing the `Session` class. When you start a session, you can specify options, such as the backend to run on. This topic describes the most commonly used options. For the full list, see the `Sessions API documentation <https://qiskit.org/documentation/partners/qiskit_ibm_runtime/stubs/qiskit_ibm_runtime.Session.html#qiskit_ibm_runtime.Session>`__.

.. important::
Data from the first session job is cached and used by subsequent jobs. Therefore, if the first job is cancelled, subsequent session jobs will all fail.
If the first session job is canceled, subsequent session jobs will all fail.

**Session class**

Expand Down Expand Up @@ -50,21 +50,23 @@ When you start a session, you can specify session options, such as the backend t

There are two ways to specify a backend in a session:

**Directly specify a string with the backend name.** Example:
**Directly specify a string with the backend name.**

.. code-block:: python
Example:

.. code-block:: python
backend = "ibmq_qasm_simulator"
with Session(backend=backend):
...
service = QiskitRuntimeService()
with Session(service=service, backend="ibmq_qasm_simulator"):
...
**Pass the backend object.** Example:

.. code-block:: python
.. code-block:: python
backend = service.get_backend("ibmq_qasm_simulator")
with Session(backend=backend):
...
backend = service.get_backend("ibmq_qasm_simulator")
with Session(backend=backend):
...
.. _session_length:

Expand Down
2 changes: 1 addition & 1 deletion docs/index.rst
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
#########################################
Qiskit Runtime 0.13.0 documentation
Qiskit Runtime 0.14.0 documentation
#########################################

Overview
Expand Down
19 changes: 9 additions & 10 deletions docs/migrate/migrate-tuning.rst
Original file line number Diff line number Diff line change
Expand Up @@ -55,23 +55,24 @@ For more information about the primitive options, refer to the
2. Transpilation
~~~~~~~~~~~~~~~~

By default, the Qiskit Runtime primitives perform circuit transpilation. There are several optimization
levels you can choose from. These levels affect the transpilation strategy and might include additional error
suppression mechanisms. Level 0 only involves basic transpilation.
By default, the Qiskit Runtime primitives perform circuit transpilation. The optimization level you choose affects the transpilation strategy and might include additional error suppression mechanisms. Level 0 only involves basic transpilation.
To learn about each optimization level, view the Optimization level table in the
`Error suppression topic <https://qiskit.org/documentation/partners/qiskit_ibm_runtime/how_to/error-suppression.html#setting-the-optimization-level>`__.

.. note::
When using primitives, optimization levels 2 and 3 behave like level 1. If you want to use more advanced optimization, use the Qiskit transpiler locally and then pass the transpiled circuits to the primitives. For instructions see the `Submitting user-transpiled circuits using primitives <https://learning.quantum-computing.ibm.com/tutorial/submitting-user-transpiled-circuits-using-primitives>`__ tutorial.

The optimization level option is a "first level option", and can be set as follows:

.. code-block:: python
from qiskit_ibm_runtime import Estimator, Options
options = Options(optimization_level=2)
options = Options(optimization_level=1)
# or..
options = Options()
options.optimization_level = 2
options.optimization_level = 1
estimator = Estimator(session=session, options=options)
Expand All @@ -92,12 +93,10 @@ options you can set up. These are "second level options", and can be set as foll
For more information, and a complete list of advanced transpilation options, see the Advanced transpilation options table in the
`Error suppression topic <https://qiskit.org/documentation/partners/qiskit_ibm_runtime/how_to/error-suppression.html#advanced-transpilation-options>`__.

Finally, you might want to specify settings that are not available through the primitives interface,
or use custom transpiler passes. In these cases, you can set ``skip_transpilation=True`` to submit
user-transpiled circuits. To learn how this is done, refer to the
To specify settings that are not available through the primitives interface or use custom transpiler passes, set ``skip_transpilation=True`` to submit user-transpiled circuits. This is described in the
`Submitting user-transpiled circuits using primitives tutorial <https://qiskit.org/documentation/partners/qiskit_ibm_runtime/tutorials/user-transpiled-circuits.html>`_.

The ``skip_transpilation`` option is an advanced transpilation option, set as follows:
The ``skip_transpilation`` option is an advanced transpilation option, and is set as follows:

.. code-block:: python
Expand All @@ -123,7 +122,7 @@ The configuration is similar to the other options:
from qiskit_ibm_runtime import Estimator, Options
options = Options(resilience_level = 2)
options = Options(resilience_level = )
# or...
Expand Down
43 changes: 40 additions & 3 deletions docs/sessions.rst
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ There are several benefits to using sessions:

.. note::
* The queuing time does not decrease for the first job submitted within a session. Therefore, a session does not provide any benefits if you only need to run a single job.
* Since data from the first session job is cached and used by subsequent jobs, if the first job is cancelled, subsequent session jobs will all fail.
* If the first session job is cancelled, subsequent session jobs will all fail.

* When using sessions, the uncertainty around queuing time is significantly reduced. This allows better estimation of a workload's total runtime and better resource management.
* In a device characterization context, being able to run experiments closely together helps prevent device drifts and provide more accurate results.
Expand Down Expand Up @@ -117,27 +117,64 @@ Iterative

Any session job submitted within the five-minute interactive timeout, also known as interactive time to live (ITTL), is processed immediately. This allows some time for variational algorithms, such as VQE, to perform classical post-processing.

- The quantum device is locked to the session user unless the TTL is reached.
- When a session is active, its jobs get priority until ITTL or max timeout is reached.
- Post-processing could be done anywhere, such as a personal computer, cloud service, or an HPC environment.

.. image:: images/iterative.png

.. note::
There might be a limit imposed on the ITTL value depending on whether your hub is Premium, Open, and so on.

This is an example of running an iterative workload that uses the classical SciPy optimizer to minimize a cost function. In this model, SciPy uses the output of the cost function to calculate its next input.

.. code-block:: python
def cost_func(params, ansatz, hamiltonian, estimator):
# Return estimate of energy from estimator
energy = estimator.run(ansatz, hamiltonian, parameter_values=params).result().values[0]
return energy
x0 = 2 * np.pi * np.random.random(num_params)
session = Session(backend=backend)
estimator = Estimator(session=session, options={"shots": int(1e4)})
res = minimize(cost_func, x0, args=(ansatz, hamiltonian, estimator), method="cobyla")
# Close the session because we didn't use a context manager.
session.close()
Batch
+++++++++++++++++++++

Ideal for running experiments closely together to avoid device drifts, that is, to maintain device characterization.

- Suitable for batching many jobs together.
- Jobs that fit within the maximum session time run back-to-back on hardware.
- The classical computation, such as compilation, of the jobs is run in parallel. This means running multiple jobs in a batch would be significantly faster than running them serially.


.. note::
When batching, jobs are not guaranteed to run in the order they are submitted.

.. image:: images/batch.png

The following example shows how you can divide up a long list of circuits into multiple jobs and run them as a batch to take advantage of the parallel processing.

.. code-block:: python
backend = service.backend("ibm_sherbrooke")
with Session(backend=backend):
estimator = Estimator()
start_idx = 0
jobs = []
while start_idx < len(circuits):
end_idx = start_idx + backend.max_circuits
jobs.append(estimator.run(circuits[start_idx:end_idx], obs[start_idx:end_idx], params[start_idx:end_idx]))
start_idx = end_idx
Sessions and reservations
-------------------------

Expand Down
2 changes: 1 addition & 1 deletion qiskit_ibm_runtime/VERSION.txt
Original file line number Diff line number Diff line change
@@ -1 +1 @@
0.13.1
0.14.1
1 change: 1 addition & 0 deletions qiskit_ibm_runtime/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -181,6 +181,7 @@ def result_callback(job_id, result):
from .runtime_options import RuntimeOptions
from .utils.json import RuntimeEncoder, RuntimeDecoder
from .session import Session # pylint: disable=cyclic-import
from .batch import Batch # pylint: disable=cyclic-import

from .exceptions import *
from .utils.utils import setup_logger
Expand Down
2 changes: 1 addition & 1 deletion qiskit_ibm_runtime/accounts/account.py
Original file line number Diff line number Diff line change
Expand Up @@ -182,7 +182,7 @@ def _assert_valid_channel(channel: ChannelType) -> None:
if not (channel in ["ibm_cloud", "ibm_quantum"]):
raise InvalidAccountError(
f"Invalid `channel` value. Expected one of "
f"{['ibm_cloud', 'ibm_quantum']}, got '{channel}'."
f"['ibm_cloud', 'ibm_quantum'], got '{channel}'."
)

@staticmethod
Expand Down
8 changes: 8 additions & 0 deletions qiskit_ibm_runtime/api/clients/runtime.py
Original file line number Diff line number Diff line change
Expand Up @@ -374,6 +374,14 @@ def list_backends(
"""
return self._api.backends(hgp=hgp, channel_strategy=channel_strategy)["devices"]

def cloud_instance(self) -> bool:
"""Returns a boolean of whether or not the instance has q-ctrl enabled.
Returns:
Boolean value.
"""
return self._api.cloud_instance()

def backend_configuration(self, backend_name: str) -> Dict[str, Any]:
"""Return the configuration of the IBM backend.
Expand Down
10 changes: 10 additions & 0 deletions qiskit_ibm_runtime/api/rest/runtime.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ class Runtime(RestAdapterBase):
"programs": "/programs",
"jobs": "/jobs",
"backends": "/backends",
"cloud_instance": "/instance",
}

def program(self, program_id: str) -> "Program":
Expand Down Expand Up @@ -293,3 +294,12 @@ def backends(
if channel_strategy:
params["channel_strategy"] = channel_strategy
return self.session.get(url, params=params, timeout=timeout).json()

def cloud_instance(self) -> bool:
"""Return boolean of whether or not the instance has q-ctrl enabled.
Returns:
Boolean value.
"""
url = self.get_url("cloud_instance")
return self.session.get(url).json().get("qctrl_enabled")
21 changes: 21 additions & 0 deletions qiskit_ibm_runtime/batch.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# This code is part of Qiskit.
#
# (C) Copyright IBM 2023.
#
# 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.

"""Qiskit Runtime batch mode."""

from .session import Session


class Batch(Session):
"""Class for creating a batch mode in Qiskit Runtime."""

pass
Loading

0 comments on commit cf5d284

Please sign in to comment.