> ## Documentation Index
> Fetch the complete documentation index at: https://docs.qbraid.com/llms.txt
> Use this file to discover all available pages before exploring further.

# RigettiProvider

> Runtime integration for direct access to Rigetti quantum processors via QCS.

<Info>
  API Reference:
  [qbraid.runtime.rigetti](https://qbraid.github.io/qBraid/stubs/qbraid.runtime.rigetti.html)
</Info>

<Warning>
  On-demand access to Rigetti quantum systems (Ankaa, Cepheus) is restricted.
  You must contact [Rigetti](https://www.rigetti.com/contact) to request access
  credentials before using this provider.
</Warning>

## Prerequisites

Before getting started, ensure you have:

1. A **Rigetti QCS account** with an active refresh token (contact Rigetti to obtain access).
2. The **Forest SDK** installed locally — specifically the `quilc` compiler. The `qvm` simulator is optional.
3. 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](https://qcs.rigetti.com/sdk-downloads)
* **Docker**: `docker run --rm -p 5555:5555 rigetti/quilc -S`

Verify the installation:

```bash theme={null}
quilc --version
```

## Installation & Setup

Install the `rigetti` extra:

```bash theme={null}
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):

```bash theme={null}
export RIGETTI_REFRESH_TOKEN="your-refresh-token"
```

Then initialize the provider:

```python theme={null}
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:

```python theme={null}
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:

```python theme={null}
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:

```python theme={null}
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](https://quil-lang.github.io/) using the `pyquil` library. Programs are compiled via `quilc` before submission to the QPU.

### Create a Program

```python theme={null}
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:

```python theme={null}
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:

```python theme={null}
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

```python theme={null}
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

```python theme={null}
from qbraid.runtime.enums import JobStatus

status = job.status()
print(status)
# <JobStatus.COMPLETED>
```

### Cancel a Job

```python theme={null}
job.cancel()
```

<Note>
  Cancellation is best-effort. Jobs already in a terminal state (`COMPLETED`,
  `FAILED`, `CANCELLED`) cannot be cancelled.
</Note>

## Runtime Options

The `device.run()` method accepts an optional `runtime_options` dict to control compilation
and translation behavior:

```python theme={null}
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.                                          |
| `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). |

## Full Example

A complete end-to-end workflow targeting the Ankaa-3 processor:

```python theme={null}
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

* [Rigetti QCS Documentation](https://docs.rigetti.com/)
* [PyQuil Documentation](https://pyquil-docs.rigetti.com/)
* [Quil Language Specification](https://quil-lang.github.io/)
* [Forest SDK Downloads](https://qcs.rigetti.com/sdk-downloads)
