Metadata-Version: 2.4
Name: openquantum-sdk-qrisp
Version: 0.5.0
Summary: Qrisp Python SDK for Open Quantum
License: Apache-2.0
Classifier: Development Status :: 4 - Beta
Classifier: Programming Language :: Python :: 3
Classifier: License :: OSI Approved :: Apache Software License
Classifier: Operating System :: OS Independent
Requires-Python: >=3.11
Description-Content-Type: text/markdown
Requires-Dist: openquantum-sdk>=1.0.0
Requires-Dist: openquantum-sdk-qiskit>=1.0.0
Requires-Dist: qrisp>=0.9
Provides-Extra: dev
Requires-Dist: pytest>=7.0; extra == "dev"
Requires-Dist: pytest-cov; extra == "dev"
Requires-Dist: pytest-mock>=3.10; extra == "dev"

# Qrisp-Open Quantum Plugin

> **Beta.** This plugin is in beta; its API and defaults may still change. Feedback is welcome in the [Quantum Rings community](https://www.quantumrings.com/community).

A backend for the [Qrisp](https://www.qrisp.eu/) quantum programming framework
that submits circuits to the [Open Quantum](https://www.openquantum.com)
platform. Write high-level Qrisp programs and run them on real quantum hardware.

## How it works

Qrisp already depends on Qiskit and can convert any circuit to a Qiskit circuit
(`QuantumCircuit.to_qiskit()`). This backend uses that bridge to reuse the Open
Quantum Qiskit plugin:

- `OpenQuantumService` handles authentication and backend discovery.
- The capability-aware `OpenQuantumBackend` (a Qiskit `BackendV2`) validates each
  circuit against the target device (gate set, coupling map, shot and qubit
  limits).
- `export_circuit_to_qasm` serialises to OpenQASM.

Submission runs through the framework-agnostic `SchedulerClient` in the core
SDK. No separate QASM serializer or auth code is reimplemented here.

## Installation

```bash
# Plugin (and core SDK + Qiskit plugin)
pip install openquantum-sdk-qrisp

# or via extras:
pip install "openquantum-sdk[qrisp]"
```

This pulls in `qrisp`, `openquantum-sdk`, and `openquantum-sdk-qiskit`.

## Quick Start

```python
from qrisp import QuantumVariable, h, cx
from qrisp_openquantum import OpenQuantumBackend

oq = OpenQuantumBackend(
    backend="ionq:aria-1",
    shots=1024,
    client_id="your_client_id",
    client_secret="your_client_secret",
)

qv = QuantumVariable(2)
h(qv[0])
cx(qv[0], qv[1])

print(qv.get_measurement(backend=oq, shots=1024))
# {'00': 0.5, '11': 0.5}
```

`get_measurement` returns Qrisp's decoded outcomes as probabilities (its own
normalization, applied for every backend). To get integer shot counts, run a
raw `QuantumCircuit` directly:

```python
from qrisp import QuantumCircuit

qc = QuantumCircuit(2)
qc.h(0)
qc.cx(0, 1)
qc.measure([0, 1])

counts = qc.run(backend=oq, shots=1024)
# e.g. {'00': 518, '11': 506}
```

## Authentication

Resolved in this order:

1. **Pre-built service** — pass `service=OpenQuantumService(...)` for full control
   (saved accounts, custom URLs, keyring).
2. **Bearer token** — pass `token=` or set `OPENQUANTUM_TOKEN`.
3. **Client credentials** — pass `client_id=` + `client_secret=` or set
   `OPENQUANTUM_CLIENT_ID` + `OPENQUANTUM_CLIENT_SECRET`.

| Parameter | Environment Variable | Description |
|-----------|---------------------|-------------|
| `token` | `OPENQUANTUM_TOKEN` | Bearer token |
| `client_id` | `OPENQUANTUM_CLIENT_ID` | OAuth2 client ID |
| `client_secret` | `OPENQUANTUM_CLIENT_SECRET` | OAuth2 client secret |
| | `OPENQUANTUM_SDK_KEY` | Path to an SDK-key JSON file (`{client_id, client_secret}`) |
| `organization_id` | `OPENQUANTUM_ORGANIZATION_ID` | Organization UUID (optional if single org) |
| `scheduler_url` | `OPENQUANTUM_SCHEDULER_URL` | Scheduler API base, when the argument is omitted |
| `management_url` | `OPENQUANTUM_MANAGEMENT_URL` | Management API base, when the argument is omitted |
| `keycloak_base` | `OPENQUANTUM_KEYCLOAK_BASE` | Keycloak base, when the argument is omitted |
| `realm` | `OPENQUANTUM_KEYCLOAK_REALM` | Keycloak realm, when the argument is omitted |

`OpenQuantumService.from_env()` raises `AuthenticationError` when no credential resolves. Circuits are serialized with the public `export_circuit_to_qasm` helper from `openquantum_sdk_qiskit`. The older `OPENQUANTUM_*_BASE` URL names are not read here; those remain an MCP-only fallback.

## Configuration

| Parameter | Default | Description |
|-----------|---------|-------------|
| `backend` | required | Backend class ID or short_code (e.g. `"ionq:aria-1"`) |
| `shots` | `1024` | Default shots when a Qrisp call omits them |
| `job_subcategory_id` | `"oth:oth"` | Workload subcategory (set the most specific match) |
| `execution_plan` | `"auto"` | `"auto"`, `"public"`, `"private"`, an enum, or a plan UUID. `"auto"` picks the cheapest plan |
| `queue_priority` | `"auto"` | `"auto"`, `"standard"`, `"priority"`, `"instant"`, an enum, or a priority UUID. `"auto"` picks the cheapest priority |
| `export_format` | `"qasm3"` | `"qasm2"` or `"qasm3"` |
| `configuration_data` | `{}` | Backend-specific config passthrough (e.g. `{"engine": "amber_quantum_rings"}`) |
| `reverse_bits` | `False` | Reverse returned bitstring order if a backend needs it |
| `verbose` | `False` | Print submission progress and credit cost to stdout |
| `job_timeout_seconds` | `86400` | Max wait for job completion (1 day) |

## Backend-specific configuration

Some backends require extra fields. The free Quantum Rings simulator
(`qr:gpu-gb10`) requires an `engine`:

```python
oq = OpenQuantumBackend(
    backend="qr:gpu-gb10",
    shots=1024,
    configuration_data={"engine": "amber_quantum_rings"},
)
```

## Bit ordering

Qrisp reads the leftmost character of a bitstring as the most-significant bit.
The platform's counts are passed through unchanged by default. If a specific
backend returns counts in the opposite order, construct the backend with
`reverse_bits=True`.

## License

Apache License 2.0
