RigettiProvider
Runtime integration for direct access to Rigetti quantum processors via QCS.
API Reference: qbraid.runtime.rigetti
On-demand access to Rigetti quantum systems (Ankaa, Cepheus) is restricted. You must contact Rigetti to request access credentials before using this provider.
Prerequisites
Before getting started, ensure you have:
- A Rigetti QCS account with an active refresh token (contact Rigetti to obtain access).
- The Forest SDK installed locally — specifically the
quilccompiler. Theqvmsimulator is optional. - Python > 3.10 and < 3.13
Install the Forest SDK
The quilc compiler is required to compile Quil programs into the native gate set of the target QPU. Install it for your platform:
- macOS / Linux: Download from qcs.rigetti.com/sdk-downloads
- Docker:
docker run --rm -p 5555:5555 rigetti/quilc -S
Verify the installation:
quilc --versionInstallation & Setup
Install the rigetti extra:
pip install 'qbraid[rigetti]'This installs the required dependencies: pyquil and qcs-sdk-python.
Authentication
The RigettiProvider authenticates with Rigetti QCS using an OAuth refresh token. Set it as an environment variable (required):
export RIGETTI_REFRESH_TOKEN="your-refresh-token"Then initialize the provider:
from qbraid.runtime.rigetti import RigettiProvider
provider = RigettiProvider()Optional Environment Variables
| Variable | Description | Default |
|---|---|---|
RIGETTI_CLIENT_ID | Custom OAuth client ID | Rigetti default |
RIGETTI_ISSUER | Custom OAuth issuer URL | Rigetti default |
QCS_GRPC_ENDPOINT | QCS gRPC API endpoint | https://grpc.qcs.rigetti.com |
QCS_QUILC_ENDPOINT | quilc compiler endpoint | tcp://127.0.0.1:5555 |
QCS_QVM_ENDPOINT | QVM simulator endpoint | http://127.0.0.1:5000 |
Provider Setup
After initializing the provider, call setup() to manage the local quilc compiler process. This ensures quilc is running and ready to compile programs:
provider = RigettiProvider()
# Start a local quilc process (default behavior)
provider.setup()
# Or, point to an existing quilc endpoint
provider.setup(quilc_endpoint="tcp://my-quilc-host:5555")The setup() method accepts the following keyword arguments:
| Parameter | Type | Default | Description |
|---|---|---|---|
quilc_endpoint | str | None | Pre-existing quilc endpoint. Skips local process start. |
qvm_endpoint | str | None | Pre-existing QVM endpoint. Skips local process start. |
grpc_endpoint | str | None | Override for the QCS gRPC endpoint. |
start_quilc | bool | True | Auto-start local quilc if not already running. |
start_qvm | bool | False | Auto-start local QVM if not already running. |
Getting Available Devices
List all quantum processors available through your QCS account:
from qbraid.runtime.rigetti import RigettiProvider
provider = RigettiProvider()
provider.setup()
devices = provider.get_devices()
print(devices)
# [RigettiDevice('ankaa-3'), RigettiDevice('cepheus-108')]Get a specific device by its processor ID:
device = provider.get_device("ankaa-3")
print(device.status())
# <DeviceStatus.ONLINE>
# Get the list of live qubit IDs on the device
qubits = device.live_qubits()
print(f"Live qubits ({len(qubits)}): {qubits[:10]}...")Submitting Jobs
The RigettiProvider accepts programs written in Quil using the pyquil library. Programs are compiled via quilc before submission to the QPU.
Create a Program
from pyquil import Program
# Bell state circuit
program = Program("""
DECLARE ro BIT[2]
H 0
CNOT 0 1
MEASURE 0 ro[0]
MEASURE 1 ro[1]
""")Run a Job
Use device.run() to compile and submit in one step:
from pyquil import Program
from qbraid.runtime.rigetti import RigettiProvider
provider = RigettiProvider()
provider.setup()
device = provider.get_device("ankaa-3")
program = Program("""
DECLARE ro BIT[2]
H 0
CNOT 0 1
MEASURE 0 ro[0]
MEASURE 1 ro[1]
""")
job = device.run(program, shots=1000)
print(f"Job ID: {job.id}")Batch Submission
Submit multiple programs in a single call:
from pyquil import Program
from qbraid.runtime.rigetti import RigettiProvider
provider = RigettiProvider()
provider.setup()
device = provider.get_device("ankaa-3")
programs = [
Program("DECLARE ro BIT[1]\nH 0\nMEASURE 0 ro[0]"),
Program("DECLARE ro BIT[1]\nX 0\nMEASURE 0 ro[0]"),
Program("DECLARE ro BIT[1]\nH 0\nS 0\nMEASURE 0 ro[0]"),
]
jobs = device.run(programs, shots=500)
for job in jobs:
print(f"Job ID: {job.id}")Retrieving Results
result = job.result()
# Measurement counts as a dictionary
print(result.data.measurement_counts)
# {'00': 512, '11': 488}
# Job metadata
print(f"Device: {result.device_id}")
print(f"Job ID: {result.job_id}")
print(f"Success: {result.success}")
print(f"Duration (us): {result.execution_duration_microseconds}")Check Job Status
from qbraid.runtime.enums import JobStatus
status = job.status()
print(status)
# <JobStatus.COMPLETED>Cancel a Job
job.cancel()Cancellation is best-effort. Jobs already in a terminal state (COMPLETED,
FAILED, CANCELLED) cannot be cancelled.
Runtime Options
The device.run() method accepts an optional runtime_options dict to control compilation
and translation behavior:
job = device.run(
program,
shots=1000,
runtime_options={
"compiler_timeout": 60,
"prepend_default_calibrations": True,
"passive_reset_delay_seconds": 1.0,
},
)Options Reference
| Parameter | Type | Description |
|---|---|---|
compiler_timeout | float | quilc compilation timeout in seconds. |
initial_rewiring | str | quilc qubit-placement strategy: "NAIVE", "PARTIAL", "GREEDY", or "RANDOM". Omit to keep quilc’s default. |
prepend_default_calibrations | bool | Prepend default calibration pulses during translation. |
passive_reset_delay_seconds | float | Delay between passive resets. |
allow_unchecked_pointer_arithmetic | bool | Disable runtime memory bounds checking (authorized access). |
allow_frame_redefinition | bool | Allow frame definitions that differ from Rigetti defaults (authorized access). |
initial_rewiring
quilc chooses the logical-to-physical qubit mapping with its INITIAL_REWIRING strategy. The strategy is a Quil pragma rather than a compiler flag, so this option works by rewriting the submitted program: PRAGMA INITIAL_REWIRING "<STRATEGY>" is prepended before compilation.
job = device.run(
program,
shots=1000,
runtime_options={"initial_rewiring": "GREEDY"},
)- Omit the key and the program is left untouched, so quilc’s own default applies (
PARTIAL, unless your qubit indices already satisfy the device’s connectivity). - Why change it:
PARTIALsearches for a placement at a cost that grows steeply with qubit count and is independent of circuit depth — on Rigetti’s 100+-qubit processors it can dominate compile time. On wide, shallow circuitsGREEDYcompiles roughly an order of magnitude faster with comparable output, andNAIVEis the fastest choice when the circuit is already laid out on the device’s lattice. On deeper circuitsPARTIALcosts about the same asGREEDYand produces better output, which is why the default is unchanged and this is opt-in. - A program that already carries its own
PRAGMA INITIAL_REWIRINGkeeps it — the runtime option is ignored with a logged warning, since two pragmas would silently change which strategy governs the program. - Values are case-insensitive; an unrecognized strategy raises
ValueErrornaming the supported set before anything is submitted.
Full Example
A complete end-to-end workflow targeting the Ankaa-3 processor:
import os
from pyquil import Program
from qbraid.runtime.rigetti import RigettiProvider
# 1. Set credentials (or export as env var beforehand)
os.environ["RIGETTI_REFRESH_TOKEN"] = "your-refresh-token"
# 2. Initialize provider and start quilc
provider = RigettiProvider()
provider.setup()
# 3. Get the target device
device = provider.get_device("ankaa-3")
print(f"Device status: {device.status()}")
print(f"Number of qubits: {len(device.live_qubits())}")
# 4. Define a GHZ state circuit
program = Program("""
DECLARE ro BIT[3]
H 0
CNOT 0 1
CNOT 1 2
MEASURE 0 ro[0]
MEASURE 1 ro[1]
MEASURE 2 ro[2]
""")
# 5. Submit the job
job = device.run(program, shots=1000)
print(f"Submitted job: {job.id}")
# 6. Retrieve results
result = job.result()
print(f"Counts: {result.data.measurement_counts}")
# Expected output (approximate): {'000': ~500, '111': ~500}Related Links
Thanks for your feedback.

