Skip to content

Commit

Permalink
misc session updates (#1175)
Browse files Browse the repository at this point in the history
* misc session updates

* fix SciPy

* edit

* only option 1

* fix link

* fix links

---------

Co-authored-by: Kevin Tian <[email protected]>
  • Loading branch information
beckykd and kt474 authored Oct 27, 2023
1 parent ab408dd commit ccd41a5
Show file tree
Hide file tree
Showing 4 changed files with 72 additions and 43 deletions.
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
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

0 comments on commit ccd41a5

Please sign in to comment.