IBM Quantum Compute service
IBM Quantum Compute service is IBM's session-based quantum computing offering on IBM Cloud. Strangeworks lets you run Qiskit circuits on IBM hardware and simulators through the Platform.
Install the strangeworks-qiskit-runtime package—a drop-in replacement for the qiskit-ibm-runtime client. Use the same Sampler, Estimator, and Session APIs while Strangeworks routes jobs to IBM Quantum Compute service.
pip install -U pip 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 StrangeworksQiskitRuntimeService—the Strangeworks client for IBM Quantum Compute service—to list backends available on your resource:
service = StrangeworksQiskitRuntimeService()
backends = service.backends()
print('Available backends:')
for backend in backends:
print(f' - {backend.name} - Status: {backend.remote_status}')
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 StrangeworksQiskitRuntimeService, which replaces QiskitRuntimeService for IBM Quantum Compute service.
For more information see IBM's guide to get started with the Sampler primitive.
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("ibm_brisbane")
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? Contact us at support@strangeworks.com for assistance.
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 IBM's guide to get started with the Estimator primitive.
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("ibm_brisbane")
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? Contact us at support@strangeworks.com for assistance.
Sessions
Here's a simple example of running jobs in a session to improve the feasibility of hybrid quantum-classical algorithms on IBM Quantum Compute service.
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)
# Strangeworks client for IBM Quantum Compute service
service = StrangeworksQiskitRuntimeService()
backend = service.backend("ibm_brisbane")
# 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? Contact us at support@strangeworks.com for assistance.
Error Suppresion and Mitigation
There is a wide variety of built-in error suppression and mitigation techniques in qiskit-ibm-runtime. These work with Strangeworks on IBM Quantum Compute service—add them in the options for Sampler and Estimator. See IBM's guides on error mitigation and suppression and specifying runtime options.