PennyLane-Open Quantum Plugin
A PennyLane plugin for the Open Quantum quantum computing platform. Submit quantum circuits to real quantum hardware through the Open Quantum SDK.
Installation
pip install openquantum-sdk-pennylane
That's it. Installing the package automatically registers the openquantum.device with PennyLane via Python entry points — no extra imports needed. Just import pennylane as qml and use qml.device("openquantum.device", ...).
For development:
pip install openquantum-sdk-pennylane[dev]
Quick Start
import pennylane as qml
# No need to import openquantum — the device registers automatically on install.
dev = qml.device(
"openquantum.device",
wires=2,
shots=1024,
backend="ionq:aria-1",
client_id="your_client_id",
client_secret="your_client_secret",
)
@qml.qnode(dev)
def bell_state():
qml.Hadamard(wires=0)
qml.CNOT(wires=[0, 1])
return qml.counts()
result = bell_state()
# The device shows backend status, credit cost, and prompts for confirmation:
# [Open Quantum] ● IonQ Aria-1 (ionq:aria-1): Online | queue: 0 job(s)
# [Open Quantum] Batch: 1 circuit(s) × 2 credit(s) each = 2 credit(s) total
# [Open Quantum] Proceed? [y/N] y
print(result) # {'00': 512, '11': 512}
Configuration
Required Parameters
| Parameter | Description |
|---|---|
wires |
Number of qubits |
shots |
Number of measurement shots (required, no analytic mode) |
backend |
Backend class ID or short_code (e.g., "ionq:aria-1") |
Authentication
The plugin supports three authentication methods, checked in order:
- Pre-built OpenQuantumClient -- pass
client=for full control. - Bearer token -- pass
token=or setOPENQUANTUM_TOKEN. - Client credentials -- pass
client_id=+client_secret=or setOPENQUANTUM_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 |
The device calls OpenQuantumClient.from_env(). Missing credentials raise AuthenticationError. The constructor parameter is client=, not scheduler=.
Cost Control and Execution Flow
Before executing circuits, the device:
- Checks backend status — with
verbose=True, reports whether the target QPU is online and its queue depth. If the backend is unavailable, lists alternatives and asks before continuing unlessauto_confirm=True. - Shows credit cost — prepares the first circuit to get a real quote. The cost is printed when
verbose=True, and whenever the confirmation prompt is shown. - Prompts for confirmation (terminal only) — asks
Proceed? [y/N]. In Jupyter notebooks, execution proceeds immediately (useauto_confirm=Trueor interrupt the kernel to cancel). - Live status updates — with
verbose=True, shows a spinner during execution. While the job is pending, you can interrupt (Ctrl+C or Jupyter stop button) to cancel it on the platform. Once the job is queued, it can no longer be cancelled. The wait is bounded byjob_timeout_seconds.
| Parameter | Default | Description |
|---|---|---|
auto_confirm |
False |
Skip the interactive cost confirmation prompt (terminal) and backend-unavailable warnings. |
verbose |
False |
Print submission progress and the credit cost. Same default on every plugin. |
# Default: prints the cost and prompts in the terminal
dev = qml.device("openquantum.device", wires=2, shots=1024, backend="ionq:aria-1", ...)
# Skip prompts and stay quiet
dev = qml.device("openquantum.device", wires=2, shots=1024, backend="ionq:aria-1", auto_confirm=True, ...)
# Skip prompts, print progress and credit cost
dev = qml.device("openquantum.device", wires=2, shots=1024, backend="ionq:aria-1", auto_confirm=True, verbose=True, ...)
# Check cumulative credits spent at any time
print(dev.total_credits_used)
Example output with verbose=True (the status lines are omitted when verbose is left at False; the cost line and prompt still appear unless auto_confirm=True):
[Open Quantum] ● IonQ Aria-1 (ionq:aria-1): Online | queue: 2 job(s)
[Open Quantum] Batch: 1 circuit(s) × 2 credit(s) each = 2 credit(s) total
[Open Quantum] Proceed? [y/N] y
[1/1] ⠹ Pending... (interrupt to cancel) (3s)
[1/1] Queued — can no longer be cancelled.
[1/1] ⠸ Running... (12s)
[Open Quantum] Batch complete: 2 credits used in 18s (session total: 2)
Multi-circuit batch with verbose=True:
[Open Quantum] Batch: 40 circuit(s) × 2 credit(s) each = 80 credit(s) total
[Open Quantum] Proceed? [y/N] y
[1/40] done (2/80 credits)
[2/40] done (4/80 credits)
...
[Open Quantum] Batch complete: 80 credits used in 245s (session total: 80)
Execution Plans & Queue Priority
Control cost and scheduling with execution_plan and queue_priority:
dev = qml.device(
"openquantum.device",
wires=2,
shots=1024,
backend="ionq:aria-1",
execution_plan="private", # "auto", "public", or "private"
queue_priority="priority", # "auto", "standard", "priority", or "instant"
...
)
| Parameter | Values | Default | Description |
|---|---|---|---|
execution_plan |
"auto", "public", "private", enum, or UUID |
"auto" |
"auto" selects the cheapest available plan. "private" uses dedicated resources at higher cost. |
queue_priority |
"auto", "standard", "priority", "instant", enum, or UUID |
"auto" |
"auto" selects the cheapest priority. Higher priorities cost more but reduce queue wait time. |
Job Subcategory
The job_subcategory_id parameter classifies the type of workload you're running. It defaults to "oth:oth" (Other) but you should set it to the most specific subcategory that matches your use case. See the core SDK README for the full list of subcategory short codes.
dev = qml.device(
"openquantum.device",
wires=2,
shots=1024,
backend="ionq:aria-1",
job_subcategory_id="ml:qcl", # Quantum Classification
...
)
Other Optional Parameters
| Parameter | Default | Description |
|---|---|---|
scheduler_url |
https://scheduler.openquantum.com |
Scheduler API base URL |
management_url |
https://management.openquantum.com |
Management API base URL |
keycloak_base |
https://id.openquantum.com |
Keycloak auth base URL |
realm |
"platform" |
Keycloak realm |
job_timeout_seconds |
86400 |
Max wait for job completion |
Supported Operations
Gates
PauliX, PauliY, PauliZ, Hadamard, CNOT, CZ, SWAP, RX, RY, RZ, PhaseShift, S, T, SX, Toffoli, CSWAP, CRX, CRY, CRZ, Identity
Measurements
qml.counts()- Measurement countsqml.expval()- Expectation valuesqml.var()- Varianceqml.probs()- Probabilitiesqml.sample()- Samples
All measurements require finite shots.
Examples
Expectation Values
@qml.qnode(dev)
def circuit(x):
qml.RX(x, wires=0)
qml.Hadamard(wires=1)
qml.CNOT(wires=[0, 1])
return qml.expval(qml.PauliZ(0))
result = circuit(0.543)
VQE Workflow
# Use auto_confirm=True for iterative algorithms to avoid
# being prompted on every optimization step.
dev = qml.device("openquantum.device", wires=2, shots=4096,
backend="ionq:aria-1", auto_confirm=True, ...)
@qml.qnode(dev)
def cost_fn(params):
qml.RY(params[0], wires=0)
qml.RY(params[1], wires=1)
qml.CNOT(wires=[0, 1])
return qml.expval(qml.PauliZ(0) @ qml.PauliZ(1))
opt = qml.GradientDescentOptimizer(stepsize=0.4)
params = np.array([0.5, 0.1])
for _ in range(100):
params = opt.step(cost_fn, params)
# Check total credits consumed
print(f"Total credits used: {dev.total_credits_used}")
Device Features
The PennyLane device loads the backend's full constraint_data (including the features array). This enables:
- Early, client-side rejection of constructs the device does not advertise (e.g.
reset,barrier, mid-circuit measurement patterns) duringqml.QNodeexecution /device.preprocess(). - The
decomposestep in preprocess is driven by the device's supported gate set (fromnative_ops/supported_ops). - You can query features at runtime:
dev = qml.device("openquantum.device", wires=4, shots=1000, backend="iqm:emerald", ...)
print(dev.features)
print(dev.allows_reset()) # False for most real QPUs today
print(dev.allows_mid_circuit_measure())
print(dev.supports_feature("dynamic_circuits"))
print(dev.allows_barriers())
The platform precompilers (in the worker) perform the definitive validation using the same feature list and will produce clear errors with source locations if something slips through.
See sdk/docs/device-features.md for the canonical list and sdk/docs/capabilities.md for the schema.
Comparison with Qiskit Plugin
| Feature | PennyLane | Qiskit |
|---|---|---|
| Execution plan | execution_plan= on device |
execution_plan= on create_sampler() / create_estimator() / config dict |
| Queue priority | queue_priority= on device |
queue_priority= on create_sampler() / create_estimator() / config dict |
| Job subcategory | job_subcategory_id= (default "oth:oth") |
job_subcategory_id= (default "oth:oth") |
| Shots | Required, no default | Default 100 (sampler) / 1024 (backend) |
| Cost confirmation | Interactive prompt (auto_confirm=False) |
No prompt (submits immediately) |
| Backend status check | Automatic pre-flight check | Not built-in |
| Interrupt handling | Ctrl+C cancels queued jobs | Not built-in |
| Auth | Token or client credentials (env vars or constructor) | Token, client credentials, or saved accounts with keyring |
| Credit tracking | dev.total_credits_used |
Not built-in |
| QASM format | QASM 3.0 (automatic) | "qasm2" or "qasm3" (configurable) |
License
Apache License 2.0
Metadata
Release files for openquantum-sdk-pennylane 1.0.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | Actions |
|---|---|---|---|---|
| openquantum_sdk_pennylane-1.0.0.tar.gz | 22.9 kB | Without provenance | Details for openquantum_sdk_pennylane-1.0.0.tar.gz |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Actions Reset |
|---|---|---|---|---|
| openquantum_sdk_pennylane-1.0.0-py3-none-any.whl | Python 3 | none | any | Details for openquantum_sdk_pennylane-1.0.0-py3-none-any.whl |
Total release size: 41.4 kB
Release files / openquantum_sdk_pennylane-1.0.0.tar.gz
| Download URL | openquantum_sdk_pennylane-1.0.0.tar.gz |
|---|---|
| Size | 22.9 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
f9f9110b2643bb79a3c750402891e1ee26ca9bdf8bc047fd6139616da4ee30c7
|
|
BLAKE2b-256 checksum How to use checksums |
95ee3b3465bd46722d1480ee526198f3ee0c824328488cfeca1654be5b321bba
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Release files / openquantum_sdk_pennylane-1.0.0-py3-none-any.whl
| Download URL | openquantum_sdk_pennylane-1.0.0-py3-none-any.whl |
|---|---|
| Size | 18.5 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
bdc3c667f6d010bd96ebbf54e094a73cacc6d544f51c05aea12e614a3c41f3b6
|
|
BLAKE2b-256 checksum How to use checksums |
53356c1067232a708d54cef32a43d5e9b158602599d6941c11cc407f20f16c07
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Security for openquantum-sdk-pennylane 1.0.0
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
No provenance found
None of the files in this release were uploaded with provenance metadata.
A note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.