diff --git a/docs/how_to/error-suppression.rst b/docs/how_to/error-suppression.rst index 04132cad1..71cb45834 100644 --- a/docs/how_to/error-suppression.rst +++ b/docs/how_to/error-suppression.rst @@ -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 | +====================+===================================================================================================+ @@ -22,7 +25,7 @@ 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) | @@ -30,21 +33,9 @@ The ``optimization_level`` setting specifies how much optimization to perform on | | - 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 `__ tutorial. Example: configure Estimator with optimization levels ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -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)]) @@ -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 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -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) diff --git a/docs/how_to/run_session.rst b/docs/how_to/run_session.rst index 1339e983a..9511f74b0 100644 --- a/docs/how_to/run_session.rst +++ b/docs/how_to/run_session.rst @@ -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 `__. .. 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** @@ -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: diff --git a/docs/migrate/migrate-tuning.rst b/docs/migrate/migrate-tuning.rst index 9f29966c5..40527d8e0 100644 --- a/docs/migrate/migrate-tuning.rst +++ b/docs/migrate/migrate-tuning.rst @@ -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 `__. +.. 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 `__ 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) @@ -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 `__. -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 `_. -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 @@ -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... diff --git a/docs/sessions.rst b/docs/sessions.rst index ba28143c8..3a986d077 100644 --- a/docs/sessions.rst +++ b/docs/sessions.rst @@ -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. @@ -117,7 +117,7 @@ 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 @@ -125,19 +125,56 @@ Any session job submitted within the five-minute interactive timeout, also known .. 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 -------------------------