Qiskit Runtime
strangeworks-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.
The strangeworks-qiskit-runtime
SDK provides a drop-in replacement for executing Qiskit Runtime Sessions on the Strangeworks Platform.
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()
Quickstart
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.