Skip to main content

Strangeworks-Qiskit-Runtime

PyPI version

The strangeworks-qiskit-runtime package provides a drop-in Qiskit Runtime Service replacement for executing across all of the supported providers and backends.

šŸ“‘ Package Documentation

Installationā€‹

To get started, make sure you have Python 3.10 or above (installation) and are familiar with setting up and using virtual environments.

pip install -U pip && pip install strangeworks-qiskit-runtime

Usageā€‹

Before running:

  1. Set up your environment and install strangeworks-qiskit-runtime
  2. In the portal, Activate IBM Quantum to create a Resource and access the free devices from IBM Quantum Experience
  3. Alternatively, Activate IBM Cloud to create a Resource and access the pay-as-you-go devices
  4. Replace your-api-key with your key from the Portal homepage
  5. Run the example scripts below!

Authenticationā€‹

First, authenticate the base strangeworks sdk with your api-key:

import strangeworks
from strangeworks_qiskit_runtime import StrangeworksQiskitRuntimeService
strangeworks.authenticate(api_key="your-api-key")

Next, instantiate an instance of StrangeworksQiskitRuntimeService:

service = StrangeworksQiskitRuntimeService(channel="ibm_quantum", resource_slug='your-resource-slug')

If you have an IBM Cloud resource added to your account, simply change the channel name to "ibm_cloud". Also, if you only have a single IBM Quantum or IBM Cloud resource then there is no need to specify your resource slug.

And you can list the backends that you have available on your Resource:

backends = service.backends()
print('Available backends:')
for backend in backends:
print(f' - {backend.name} - Status: {backend.remote_status}')

List all jobs ran from the current resource:

job_list = service.jobs()

Examplesā€‹

Sampler Primitiveā€‹

Here's a simple example of creating a Bell state with the StrangeworksSampler primitive, our replacement for Qiskits Sampler.

Qiskit: Hello World
import qiskit
import strangeworks

from qiskit_ibm_runtime import Session, Options

from strangeworks_qiskit_runtime import (
StrangeworksQiskitRuntimeService,
StrangeworksSampler,
)

# get your API key from the Strangeworks Portal
strangeworks.authenticate(
api_key="your-api-key",
)

# Create the strangeworks runtime service
service = StrangeworksQiskitRuntimeService(channel="ibm_quantum")

# Use the standard Session object from qiskit-ibm-runtime
# Set the backend as the simulator
# Change the backend name string to run on hardware
session = Session(service=service, backend="ibmq_qasm_simulator")

# Use Strangeworks Sampler
sampler = StrangeworksSampler(session=session, options = Options(optimization_level=1))

# create a simple quantum circuit
circuit = qiskit.QuantumCircuit(2)
circuit.h(0)
circuit.cx(0, 1)
circuit.measure_all()

# Execute the circuit
print('\nšŸ¤– Executing Circuit...\n')
job = sampler.run(circuit, shots=100)

# 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!

Estimator Primitiveā€‹

Here's a simple example of finding the lowest energy of a simple two qubit quantum operator with the StrangeworksEstimator primitive, our replacement for Qiskits Estimator.

Qiskit: Estimator
import strangeworks
from qiskit.circuit.library import RealAmplitudes
from qiskit.quantum_info import SparsePauliOp

from qiskit_ibm_runtime import Session, Options

from strangeworks_qiskit_runtime import (
StrangeworksEstimator,
StrangeworksQiskitRuntimeService,
)

# get your API key from the Strangeworks Portal
strangeworks.authenticate(
api_key="your-api-key",
)

# Create the strangeworks runtime service
service = StrangeworksQiskitRuntimeService(channel="ibm_quantum")

# Use the standard Session object from qiskit-ibm-runtime
# Set the backend as the simulator
# Change the backend name string to run on hardware
session = Session(service=service, backend="ibmq_qasm_simulator")

# Use Strangeworks Estimator
estimator = StrangeworksEstimator(session=session, options = Options(optimization_level=1))

# 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]

# Execute the circuit
print('\nšŸ¤– Executing Circuit...\n')
job = estimator.run(
circuits=[psi], observables=[H1], parameter_values=[theta]
)

# 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
from qiskit import QuantumCircuit
from qiskit.circuit.library import RealAmplitudes
from qiskit.quantum_info import SparsePauliOp
from qiskit_ibm_runtime import Options, Session

from strangeworks_qiskit_runtime import (
StrangeworksEstimator,
StrangeworksQiskitRuntimeService,
StrangeworksSampler,
)

# get your API key from the Strangeworks Portal
strangeworks.authenticate(
api_key="your-api-key",
)

# Create the strangeworks runtime service
service = StrangeworksQiskitRuntimeService(channel="ibm_quantum")

# Set options, which can be overwritten at job level.
options = Options(optimization_level=1)

# 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]

# 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="ibmq_qasm_simulator") as session:
# Submit a request to the Sampler primitive within the session.
sampler = StrangeworksSampler(session=session, options=options)
job = sampler.run(circuits=bell)
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 = StrangeworksEstimator(session=session, options=options)
job = estimator.run(
circuits=[psi], observables=[H1], parameter_values=[theta]
)
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!

Pre Transpilation of Circuitsā€‹

import strangeworks
from qiskit import QuantumCircuit
from qiskit_ibm_runtime import Options, Session
from qiskit.transpiler.preset_passmanagers import generate_preset_pass_manager

from strangeworks_qiskit_runtime import (
StrangeworksQiskitRuntimeService,
StrangeworksSampler,
)

# get your API key from the Strangeworks Portal
strangeworks.authenticate(
api_key="your-api-key",
)

# Create the strangeworks runtime service
service = StrangeworksQiskitRuntimeService(channel="ibm_cloud")

backend = service.backend(name="ibm_brisbane")

session = Session(service=service, backend=backend)
sampler = StrangeworksSampler(session=session)

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

# Transpile circuit for backend yourself
pm = generate_preset_pass_manager(optimization_level=1, target=backend.target)
circuit = pm.run(circuit)

job = sampler.run(circuit, shots=100, skip_transpilation=True)

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 StrangeworksSampler and StrangeworksEstimator. More information can be found here.