Qiskit Runtime
Qiskit Runtime provides access to quantum computing resources via a session-based interface. The Strangeworks Qiskit Runtime Service allows you to run your Qiskit circuits on IBM Quantum.
strangeworks-qiskit-runtime
The strangeworks-qiskit-runtime
package provides a drop-in replacement for executing Qiskit Runtime Sessions on the Strangeworks Platform.
Installation
To get started, make sure you have Python 3.10 or 3.11 (installation) and are familiar with setting up and using virtual environments.
pip install -U pip && pip install strangeworks-qiskit-runtime
Authentication
First, authenticate via the Strangeworks SDK with your api-key taken from the Portal homepage:
import strangeworks as sw
from strangeworks_qiskit_runtime import StrangeworksQiskitRuntimeService
sw.authenticate(api_key)
Backends
Instantiate an instance of StrangeworksQiskitRuntimeService
and you can list the backends that you have available on your Resource:
service = StrangeworksQiskitRuntimeService()
backends = service.backends()
print('Available backends:')
for backend in backends:
print(f' - {backend.name} - Status: {backend.remote_status}')
Company | Processor | Qubits | Framework | Processors |
---|---|---|---|---|
IBM | Heron r2 | 156 | Qiskit | ibm_fez |
IBM | Heron r1 | 133 | Qiskit | ibm_torino |
IBM | Eagle r3 | 127 | Qiskit | ibm_brisbane , ibm_kyiv , ibm_sherbrooke |
Disclaimer: This list of backends is subject to change at any time.
Jobs
Get a Job
from strangeworks_qiskit_runtime import StrangeworksRuntimeJob
service = StrangeworksQiskitRuntimeService()
job = StrangeworksRuntimeJob(job_slug=job_slug, service=service)
result = job.result()
Cancel a Job
To cancel a job, you can use the cancel
method:
service = StrangeworksQiskitRuntimeService()
StrangeworksRuntimeJob(job_slug=job_slug, service=service).cancel()
List Jobs
List all jobs in the workspace:
service = StrangeworksQiskitRuntimeService()
jobs = service.jobs()
Examples
Sampler Primitive
Here's a simple example of creating a Bell state with the StrangeworksQiskitRuntimeService, our replacement for Qiskits RuntimeService
For more information see the Qiskit Documentation.
import qiskit
import strangeworks as sw
from qiskit.transpiler.preset_passmanagers import generate_preset_pass_manager
from qiskit_ibm_runtime import Sampler, Session
from strangeworks_qiskit_runtime import StrangeworksQiskitRuntimeService
sw.authenticate(api_key)
service = StrangeworksQiskitRuntimeService()
backend = service.backend("ibmq_qasm_simulator")
session = Session(backend=backend)
sampler = Sampler(mode=session)
# circuit = random_circuit(2, 2, seed=1, measure=True).decompose(reps=1)
circuit = qiskit.QuantumCircuit(2)
circuit.h(0)
circuit.cx(0, 1)
circuit.measure_all()
# We must compile the circuit for the backend. Can be skipped for simulators.
pm = generate_preset_pass_manager(backend=backend, optimization_level=1)
tps_circuit = pm.run(circuit)
job = sampler.run([tps_circuit], shots=1000)
# At this point, the job is running on the Strangeworks Platform.
# You can check the status of the job in the Portal, even if
# stop this script.
print(f'⏳ Job {job.job_slug} submitted!\n')
sw.add_tags(job.job_slug, ["sampler"])
# Check on the status of the job
status = job.status()
# Lots of good info in here
result = job.result()
🥳 Success! You may view your job in the portal.
😅 Something went wrong? Find us in Slack!
Estimator Primitive
Here's a simple example of finding the lowest energy of a simple two qubit quantum operator with the Estimator primitive
For more information see Qiskit Documentation.
import strangeworks as sw
from qiskit.circuit.library import RealAmplitudes
from qiskit.quantum_info import SparsePauliOp
from qiskit.transpiler.preset_passmanagers import generate_preset_pass_manager
from qiskit_ibm_runtime import Estimator, EstimatorOptions, Session
from strangeworks_qiskit_runtime import StrangeworksQiskitRuntimeService
sw.authenticate(api_key)
service = StrangeworksQiskitRuntimeService()
backend = service.backend("ibmq_qasm_simulator")
session = Session(backend=backend)
# Prepare inputs.
psi = RealAmplitudes(num_qubits=2, reps=2)
H1 = SparsePauliOp.from_list([("II", 1), ("IZ", 2), ("XI", 3)])
theta = [0, 1, 1, 2, 3, 5]
# We must compile the circuit for the backend. Can be skipped for simulators.
pm = generate_preset_pass_manager(backend=backend, optimization_level=1)
tps_circuit = pm.run(psi)
tps_observable = H1.apply_layout(tps_circuit.layout)
options = EstimatorOptions(resilience_level=1)
# Submit a request to the Estimator primitive within the session.
estimator = Estimator(mode=session, options=options)
job = estimator.run([(tps_circuit, tps_observable, theta)])
sw.add_tags(job.job_slug, ["estimator"])
# At this point, the job is running on the Strangeworks Platform.
# You can check the status of the job in the Portal, even if
# stop this script.
print(f'⏳ Job {job.job_slug} submitted!\n')
# Check on the status of the job
status = job.status()
# Lots of good info in here
result = job.result()
🥳 Success! You may view your job in the portal.
😅 Something went wrong? Find us in Slack!
Sessions
Here's a simple example of using qiskit-ibm-runtimes Sessions object to improve the feasibility of hybrid quantum-classical algorithms.
import strangeworks as sw
from qiskit import QuantumCircuit
from qiskit.circuit.library import RealAmplitudes
from qiskit.quantum_info import SparsePauliOp
from qiskit_ibm_runtime import Options, Session
from qiskit.transpiler.preset_passmanagers import generate_preset_pass_manager
from qiskit_ibm_runtime import Estimator, EstimatorOptions, Sampler, Session
from strangeworks_qiskit_runtime import (
StrangeworksQiskitRuntimeService,
)
# get your API key from the Strangeworks Portal
sw.authenticate(api_key)
# Create the strangeworks runtime service
service = StrangeworksQiskitRuntimeService()
backend = service.backend(backend_name)
# Prepare inputs.
bell = QuantumCircuit(2)
bell.h(0)
bell.cx(0, 1)
bell.measure_all()
psi = RealAmplitudes(num_qubits=2, reps=2)
H1 = SparsePauliOp.from_list([("II", 1), ("IZ", 2), ("XI", 3)])
theta = [0, 1, 1, 2, 3, 5]
pm = generate_preset_pass_manager(backend=backend, optimization_level=1)
tps_bell = pm.run(bell)
tps_psi = pm.run(psi)
tps_H1 = H1.apply_layout(tps_psi.layout)
# Use the standard Session object from qiskit-ibm-runtime
# Open a Session and run multiple jobs
# Only the first job must wait in the queue, subsequent jobs will be
# given priority
with Session(service=service, backend=backend) as session:
# Submit a request to the Sampler primitive within the session.
sampler = Sampler(mode=session)
job = sampler.run([tps_bell], shots=10)
sw.add_tags(job.job_slug, ["sampler"])
print(f"external ID: {job.job_id()}")
print(f"session ID: {job.session_id}")
print(f"Sampler results: {job.result()}")
# Submit a request to the Estimator primitive within the session.
estimator = Estimator(mode=session)
job = estimator.run([(tps_psi, tps_H1, theta)])
sw.add_tags(job.job_slug, ["estimator"])
print(f"external ID: {job.job_id()}")
print(f"session ID: {job.session_id}")
print(f"Estimator results: {job.result()}")
# Close the session only if all jobs are finished
# and you don't need to run more in the session.
session.close()
🥳 Success! You may view your job in the portal.
😅 Something went wrong? Find us in Slack!
Error Suppresion and Mitigation
There is a wide variety of built in error suppression and mitigation techniques coming from qiskit-ibm-runtime. Note that these are all compatable with this Strangeworks Runtime Service, simply add these in the options field for the Sampler
and Estimator
. More information can be found here.