Skip to content

Commit

Permalink
Initial changes for Mode (#1598)
Browse files Browse the repository at this point in the history
closes #1542 

Frank did a lot of the code changes already (#1580 ), but the migration
guides weren't included, so I still need to update that code.

---------

Co-authored-by: abbycross <[email protected]>
Co-authored-by: Jessie Yu <[email protected]>
  • Loading branch information
3 people authored Jul 10, 2024
1 parent 5961cbc commit be8407d
Show file tree
Hide file tree
Showing 15 changed files with 77 additions and 69 deletions.
2 changes: 1 addition & 1 deletion docs/api/migration-guides/local-simulators.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,7 @@ aer_sim = AerSimulator()
pm = generate_preset_pass_manager(backend=aer_sim, optimization_level=1)
isa_qc = pm.run(qc)
with Session(backend=aer_sim) as session:
sampler = Sampler(session=session)
sampler = Sampler()
result = sampler.run([isa_qc]).result()
```

Expand Down
29 changes: 15 additions & 14 deletions docs/api/migration-guides/qiskit-runtime-examples.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ service = QiskitRuntimeService()
# Get a backend
backend = service.least_busy(operational=True, simulator=False)

# Define Estimator
# Define Estimator
estimator = Estimator(backend)

# Run an expectation value calculation
Expand All @@ -77,10 +77,10 @@ from qiskit_ibm_runtime.fake_provider import FakeManilaV2
# Run the sampler job locally using FakeManilaV2
fake_manila = FakeManilaV2()

# You can use a fixed seed to get fixed results.
# You can use a fixed seed to get fixed results.
options = {"simulator": {"seed_simulator": 42}}

# Define Estimator
# Define Estimator
estimator = Estimator(backend=fake_manila, options=options)

# Run an expectation value calculation
Expand Down Expand Up @@ -225,7 +225,8 @@ Output
</TabItem>

<TabItem value="legacy" label="backend.run()">
The legacy workflow required additional elements and steps to compute an expectation value. The `QuantumInstance` class stored a `PassManager` and a `Backend` instance, and wrapped the conversion step to ISA circuits and `backend.run` calls. The `CircuitSampler` class from `qiskit.opflow` wrapped the `QuantumInstance` `run` and `transpile` methods. This degree of nesting is no longer supported, the new workflow allows to access and directly manipulate all the key components of the computation (backend, pass manager, circuits and observables) at all stages of the algorithm.
The legacy workflow required additional elements and steps to compute an expectation value. The `QuantumInstance` class stored a `PassManager` and a `Backend` instance, and wrapped the conversion step to ISA circuits and `backend.run` calls. The `CircuitSampler` class from `qiskit.opflow` wrapped the `QuantumInstance`, `run`, and `transpile` methods. This degree of nesting is no longer supported; the new workflow allows to access and directly manipulate all the key components of the computation (backend, pass manager, circuits and observables) at all stages of the algorithm.


``` python
from qiskit.opflow import StateFn, PauliExpectation, CircuitSampler
Expand Down Expand Up @@ -256,7 +257,7 @@ expectation: -1.065734058826613
</Tabs>

<span id="sampler-algorithm"></span>
## Use Sampler to design an algorithm
## Use Sampler to design an algorithm

The Sampler primitive is used to design an algorithm that samples
circuits and extracts probability distributions.
Expand Down Expand Up @@ -286,7 +287,7 @@ difference is the format of the output: `backend.run()` outputs
# Run
result = backend.run(isa_circuits)
```

</TabItem>

<TabItem value="aer" label="qiskit-aer">
Expand Down Expand Up @@ -317,7 +318,7 @@ difference is the format of the output: `backend.run()` outputs
backend = service.least_busy(operational=True, simulator=False)

# Define Sampler
sampler = Sampler(backend=backend)
sampler = Sampler(mode=backend)

# Run calculation
job = sampler.run([isa_circuit])
Expand All @@ -334,10 +335,10 @@ from qiskit_ibm_runtime.fake_provider import FakeManilaV2
# Run the sampler job locally using FakeManilaV2
fake_manila = FakeManilaV2()

# You can use a fixed seed to get fixed results.
# You can use a fixed seed to get fixed results.
options = {"simulator": {"seed_simulator": 42}}

# Define Sampler
# Define Sampler
sampler = Sampler(backend=fake_manila, options=options)

# Run calculation
Expand Down Expand Up @@ -366,7 +367,7 @@ When using the `Sampler` primitive, the circuit **must contain measurements**.
<TabItem value="PrimV2" label="Runtime Sampler">
``` python
from qiskit_ibm_runtime import SamplerV2 as Sampler

# Define a local backend
from qiskit_ibm_runtime.fake_provider import FakeManilaV2
backend = FakeManilaV2()
Expand Down Expand Up @@ -430,19 +431,19 @@ isa_circuit = pm.run(circuit)
<Tabs>
<TabItem value="runtime" label="Runtime Sampler">
``` python
sampler = Sampler(backend=backend)
sampler = Sampler(mode=backend)

job = sampler.run([isa_circuit])

result = job.result()
# Get results for the first (and only) PUB
pub_result = result[0]

# Get counts from the classical register "meas".
# Get counts from the classical register "meas".
print(f" >> Meas output register counts: {pub_result.data.meas.get_counts()}")

>> Meas output register counts: {'0001': 210, '0010': 305, '0000': 282, '0011': 201, '0101': 2, '1010': 6, '0110': 5, '0100': 6, '1000': 3, '0111': 1, '1001': 2, '1011': 1}
```
>> Meas output register counts: {'0001': 210, '0010': 305, '0000': 282, '0011': 201, '0101': 2, '1010': 6, '0110': 5, '0100': 6, '1000': 3, '0111': 1, '1001': 2, '1011': 1}
```
</TabItem>

<TabItem value="legacy" label="backend.run()">
Expand Down
22 changes: 11 additions & 11 deletions docs/api/migration-guides/qiskit-runtime-from-ibm-provider.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ information on retrieving account credentials, see [Install and set up](/guides/
``` python
from qiskit_ibm_runtime import QiskitRuntimeService

# IBM Quantum channel; set to default
# IBM Quantum channel; set to default

QiskitRuntimeService.save_account(channel="ibm_quantum", token="<IQP_TOKEN>", overwrite=True, default=true)
```
Expand Down Expand Up @@ -101,7 +101,7 @@ provider = IBMProvider(instance="my_hub/my_group/my_project")
</TabItem>
</Tabs>

## Get a backend
## Get a backend

Use the updated code to specify a backend.

Expand Down Expand Up @@ -153,19 +153,19 @@ Change the import and run statements, instantiate the primitive, and make sure t
from qiskit import QuantumCircuit
from qiskit.transpiler.preset_passmanagers import generate_preset_pass_manager
from qiskit_ibm_runtime import QiskitRuntimeService, SamplerV2 as Sampler

service = QiskitRuntimeService()

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

circuit = QuantumCircuit(2, 2)
circuit.h(0)
circuit.cx(0, 1)
circuit.measure_all()

pm = generate_preset_pass_manager(backend=backend, optimization_level=1)
isa_circuit = pm.run(circuit)

sampler = Sampler(backend)
job = sampler.run([isa_circuit])
result = job.result()
Expand Down Expand Up @@ -203,10 +203,10 @@ print(f" > Counts: {job.result().get_counts()}")
from qiskit_ibm_runtime import Session
from qiskit_ibm_runtime import QiskitRuntimeService, SamplerV2 as Sampler

with Session(service=service, backend=backend) as session:
sampler = Sampler(session=session)
job = sampler.run([isa_circuit])
another_job = sampler.run([another_isa_circuit])
with Session(service=service, backend=backend) as session:
sampler = Sampler()
job = sampler.run([isa_circuit])
another_job = sampler.run([another_isa_circuit])
result = job.result()
another_result = another_job.result()
```
Expand Down
8 changes: 4 additions & 4 deletions docs/api/migration-guides/v2-primitives.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -776,7 +776,7 @@ service = QiskitRuntimeService()
backend = service.least_busy(operational=True, simulator=False, min_num_qubits=127)

with Session(service=service, backend=backend) as session:
estimator = Estimator(session=session)
estimator = Estimator()

estimator.options.optimization_level = 1
estimator.options.resilience_level = 1
Expand Down Expand Up @@ -829,7 +829,7 @@ service = QiskitRuntimeService()
backend = service.least_busy(operational=True, simulator=False, min_num_qubits=127)

with Session(service=service, backend=backend) as session:
estimator = Estimator(session=session, options=options)
estimator = Estimator(options=options)
job = estimator.run(isa_circuit, isa_observable)
another_job = estimator.run(another_isa_circuit, another_isa_observable)
result = job.result()
Expand Down Expand Up @@ -1119,7 +1119,7 @@ sampler.options.dynamical_decoupling.sequence_type = "XpXm"
backend = service.least_busy(operational=True, simulator=False, min_num_qubits=127)

with Session(service=service, backend=backend) as session:
sampler = Sampler(session=session)
sampler = Sampler()
job = sampler.run([isa_circuit])
another_job = sampler.run([another_isa_circuit])
result = job.result()
Expand Down Expand Up @@ -1159,7 +1159,7 @@ service = QiskitRuntimeService()
backend = service.least_busy(operational=True, simulator=False, min_num_qubits=127)

with Session(service=service, backend=backend) as session:
sampler = Sampler(session=session, options=options)
sampler = Sampler(options=options)
job = sampler.run(circuit)
another_job = sampler.run(another_circuit)
result = job.result()
Expand Down
2 changes: 1 addition & 1 deletion docs/guides/configure-error-mitigation.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -334,7 +334,7 @@ options.resilience_level = 2
options.optimization_level = 1
backend = service.least_busy(operational=True, simulator=False)

estimator = Estimator(options=options, mode=backend)
estimator = Estimator(options=options, backend=backend)
```

<Admonition type="info" title="Note">
Expand Down
2 changes: 1 addition & 1 deletion docs/guides/configure-error-suppression.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,7 @@ pm = generate_preset_pass_manager(backend=backend, optimization_level=1)
psi = pm.run(psi)
H = H.apply_layout(psi.layout)

estimator = Estimator(options=options, mode=backend)
estimator = Estimator(options=options, backend=backend)

job = estimator.run(circuits=[psi], observables=[H], parameter_values=[theta])
psi1_H1 = job.result()
Expand Down
12 changes: 8 additions & 4 deletions docs/guides/execution-modes.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,15 @@ description: An overview of the available execution modes in Qiskit Runtime; ses

There are several ways to run workloads, depending on your needs.

**Job mode**: A single primitive request of the estimator or the sampler made without a context manager. Circuits and inputs are packaged as primitive unified blocs (PUBs) and submitted as an execution task on the quantum computer.
<Admonition type="note">
The `mode` option is only available for V2 primitives and requires `qiskit-ibm-runtime` 0.24 or later.
</Admonition>

[**Session mode**](sessions): A dedicated window for running a multi-job workload. This allows users to experiment with variational algorithms in a more predictable way and even run multiple experiments simultaneously taking advantage of parallelism in the stack. Use sessions for iterative workloads or experiments that require dedicated access. See [Run jobs in a session](./run-jobs-session) for examples.
**Job mode**: A single primitive request of the estimator or the sampler made without a context manager. Circuits and inputs are packaged as primitive unified blocs (PUBs) and submitted as an execution task on the quantum computer. To run in job mode, specify `mode=backend` when instantiating a primitive. See [Primitives examples](primitives-examples) for examples.

[**Batch mode**](run-jobs-batch): A multi-job manager for efficiently running an experiment that is comprised of bundle of independent jobs. Use batch mode to submit multiple primitive jobs simultaneously.
[**Session mode**](sessions): A dedicated window for running a multi-job workload. This allows users to experiment with variational algorithms in a more predictable way and even run multiple experiments simultaneously taking advantage of parallelism in the stack. Use sessions for iterative workloads or experiments that require dedicated access. To run in session mode, specify `mode=session` when instantiating a primitive or run the job in a session context manager. See [Run jobs in a session](run-jobs-session) for examples.

[**Batch mode**](run-jobs-batch): A multi-job manager for efficiently running an experiment that is comprised of bundle of independent jobs. Use batch mode to submit multiple primitive jobs simultaneously. To run in batch mode, specify `mode=batch` when instantiating a primitive or run the job in a batch context manager. See [Run jobs in a batch](run-jobs-batch) for examples.

The differences are summarized in the following table:

Expand All @@ -31,7 +35,7 @@ To ensure the most efficient use of the execution modes, the following practices

A job's QPU time is listed in the **Usage** column on the IBM Quantum Platform [Jobs](https://quantum.ibm.com/jobs) page, or you can query it by using `qiskit-ibm-runtime` with this command `job.metrics()["usage"]["quantum_seconds"]`

- If each of your jobs consumes more than one minute of QPU time, or if combining jobs is not practical, you can still run multiple jobs in parallel. Every job goes through both classical and quantum processing. While a QPU can process only one job at a time, up to five classical jobs can be processed in parallel. You can take advantage of this by submitting multiple jobs in [batch](run-jobs-batch#partition) or [session](./run-jobs-session#two-vqe) execution mode.
- If each of your jobs consumes more than one minute of QPU time, or if combining jobs is not practical, you can still run multiple jobs in parallel. Every job goes through both classical and quantum processing. While a QPU can process only one job at a time, up to five classical jobs can be processed in parallel. You can take advantage of this by submitting multiple jobs in [batch](run-jobs-batch#partition) or [session](run-jobs-session#two-vqe) execution mode.

The above are general guidelines, and you should tune your workload to find the optimal ratio, especially when using sessions. For example, if you are using a session to get exclusive access to a backend, consider breaking up large jobs into smaller ones and running them in parallel. This might be more cost effective because it can reduce wall clock time.

Expand Down
Loading

0 comments on commit be8407d

Please sign in to comment.