Skip to main content

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.

PyPI version

📑 Package Documentation

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}')
CompanyProcessorQubitsFrameworkProcessors
IBMHeron r2156Qiskitibm_fez
IBMHeron r1133Qiskitibm_torino
IBMEagle r3127Qiskitibm_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.

Qiskit: Hello World
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.

Qiskit: Estimator
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.

Qiskit: Sessions
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.