openquantum-sdk-pennylane 0.1.7__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- openquantum_sdk_pennylane-0.1.7/PKG-INFO +275 -0
- openquantum_sdk_pennylane-0.1.7/README.md +257 -0
- openquantum_sdk_pennylane-0.1.7/openquantum_sdk_pennylane.egg-info/PKG-INFO +275 -0
- openquantum_sdk_pennylane-0.1.7/openquantum_sdk_pennylane.egg-info/SOURCES.txt +16 -0
- openquantum_sdk_pennylane-0.1.7/openquantum_sdk_pennylane.egg-info/dependency_links.txt +1 -0
- openquantum_sdk_pennylane-0.1.7/openquantum_sdk_pennylane.egg-info/entry_points.txt +2 -0
- openquantum_sdk_pennylane-0.1.7/openquantum_sdk_pennylane.egg-info/requires.txt +10 -0
- openquantum_sdk_pennylane-0.1.7/openquantum_sdk_pennylane.egg-info/top_level.txt +2 -0
- openquantum_sdk_pennylane-0.1.7/pennylane_openquantum/__init__.py +6 -0
- openquantum_sdk_pennylane-0.1.7/pennylane_openquantum/device.py +935 -0
- openquantum_sdk_pennylane-0.1.7/pennylane_openquantum/device_config.toml +50 -0
- openquantum_sdk_pennylane-0.1.7/pennylane_openquantum/exceptions.py +19 -0
- openquantum_sdk_pennylane-0.1.7/pennylane_openquantum/qasm_serializer.py +147 -0
- openquantum_sdk_pennylane-0.1.7/pyproject.toml +42 -0
- openquantum_sdk_pennylane-0.1.7/setup.cfg +4 -0
- openquantum_sdk_pennylane-0.1.7/tests/test_device.py +457 -0
- openquantum_sdk_pennylane-0.1.7/tests/test_integration.py +71 -0
- openquantum_sdk_pennylane-0.1.7/tests/test_qasm_serializer.py +165 -0
|
@@ -0,0 +1,275 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: openquantum-sdk-pennylane
|
|
3
|
+
Version: 0.1.7
|
|
4
|
+
Summary: PennyLane Python SDK for Open Quantum
|
|
5
|
+
License: Apache-2.0
|
|
6
|
+
Classifier: Programming Language :: Python :: 3
|
|
7
|
+
Classifier: License :: OSI Approved :: Apache Software License
|
|
8
|
+
Classifier: Operating System :: OS Independent
|
|
9
|
+
Requires-Python: >=3.10
|
|
10
|
+
Description-Content-Type: text/markdown
|
|
11
|
+
Requires-Dist: openquantum-sdk>=0.3.7
|
|
12
|
+
Requires-Dist: pennylane>=0.38
|
|
13
|
+
Provides-Extra: dev
|
|
14
|
+
Requires-Dist: pytest>=7.0; extra == "dev"
|
|
15
|
+
Requires-Dist: pytest-cov; extra == "dev"
|
|
16
|
+
Requires-Dist: pytest-mock>=3.10; extra == "dev"
|
|
17
|
+
Requires-Dist: tomli; python_version < "3.11" and extra == "dev"
|
|
18
|
+
|
|
19
|
+
# PennyLane-Open Quantum Plugin
|
|
20
|
+
|
|
21
|
+
A [PennyLane](https://pennylane.ai/) plugin for the [Open Quantum](https://openquantum.com) quantum computing platform. Submit quantum circuits to real quantum hardware through the Open Quantum SDK.
|
|
22
|
+
|
|
23
|
+
## Installation
|
|
24
|
+
|
|
25
|
+
```bash
|
|
26
|
+
pip install openquantum-sdk-pennylane
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
**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", ...)`.
|
|
30
|
+
|
|
31
|
+
For development:
|
|
32
|
+
|
|
33
|
+
```bash
|
|
34
|
+
pip install openquantum-sdk-pennylane[dev]
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
## Quick Start
|
|
38
|
+
|
|
39
|
+
```python
|
|
40
|
+
import pennylane as qml
|
|
41
|
+
|
|
42
|
+
# No need to import openquantum — the device registers automatically on install.
|
|
43
|
+
dev = qml.device(
|
|
44
|
+
"openquantum.device",
|
|
45
|
+
wires=2,
|
|
46
|
+
shots=1024,
|
|
47
|
+
backend="ionq:aria-1",
|
|
48
|
+
client_id="your_client_id",
|
|
49
|
+
client_secret="your_client_secret",
|
|
50
|
+
)
|
|
51
|
+
|
|
52
|
+
@qml.qnode(dev)
|
|
53
|
+
def bell_state():
|
|
54
|
+
qml.Hadamard(wires=0)
|
|
55
|
+
qml.CNOT(wires=[0, 1])
|
|
56
|
+
return qml.counts()
|
|
57
|
+
|
|
58
|
+
result = bell_state()
|
|
59
|
+
# The device shows backend status, credit cost, and prompts for confirmation:
|
|
60
|
+
# [Open Quantum] ● IonQ Aria-1 (ionq:aria-1): Online | queue: 0 job(s)
|
|
61
|
+
# [Open Quantum] Batch: 1 circuit(s) × 2 credit(s) each = 2 credit(s) total
|
|
62
|
+
# [Open Quantum] Proceed? [y/N] y
|
|
63
|
+
print(result) # {'00': 512, '11': 512}
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
## Configuration
|
|
67
|
+
|
|
68
|
+
### Required Parameters
|
|
69
|
+
|
|
70
|
+
| Parameter | Description |
|
|
71
|
+
|-----------|-------------|
|
|
72
|
+
| `wires` | Number of qubits |
|
|
73
|
+
| `shots` | Number of measurement shots (required, no analytic mode) |
|
|
74
|
+
| `backend` | Backend class ID or short_code (e.g., `"ionq:aria-1"`) |
|
|
75
|
+
|
|
76
|
+
### Authentication
|
|
77
|
+
|
|
78
|
+
The plugin supports three authentication methods, checked in order:
|
|
79
|
+
|
|
80
|
+
1. **Pre-built SchedulerClient** -- pass `scheduler=` for full control.
|
|
81
|
+
2. **Bearer token** -- pass `token=` or set `OPENQUANTUM_TOKEN`.
|
|
82
|
+
3. **Client credentials** -- pass `client_id=` + `client_secret=` or set `OPENQUANTUM_CLIENT_ID` + `OPENQUANTUM_CLIENT_SECRET`.
|
|
83
|
+
|
|
84
|
+
| Parameter | Environment Variable | Description |
|
|
85
|
+
|-----------|---------------------|-------------|
|
|
86
|
+
| `token` | `OPENQUANTUM_TOKEN` | Bearer token |
|
|
87
|
+
| `client_id` | `OPENQUANTUM_CLIENT_ID` | OAuth2 client ID |
|
|
88
|
+
| `client_secret` | `OPENQUANTUM_CLIENT_SECRET` | OAuth2 client secret |
|
|
89
|
+
| `organization_id` | `OPENQUANTUM_ORGANIZATION_ID` | Organization UUID (optional if single org) |
|
|
90
|
+
|
|
91
|
+
### Cost Control and Execution Flow
|
|
92
|
+
|
|
93
|
+
Before executing circuits, the device:
|
|
94
|
+
|
|
95
|
+
1. **Checks backend status** — reports whether the target QPU is online, its queue depth, and lists online alternatives if it is offline or not accepting jobs.
|
|
96
|
+
2. **Shows credit cost** — prepares the first circuit to get a real quote, then displays the per-circuit and total cost.
|
|
97
|
+
3. **Prompts for confirmation** (terminal only) — asks `Proceed? [y/N]`. In Jupyter notebooks, execution proceeds immediately (use `auto_confirm=True` or interrupt the kernel to cancel).
|
|
98
|
+
4. **Live status updates** — shows a spinner with job status 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.
|
|
99
|
+
|
|
100
|
+
| Parameter | Default | Description |
|
|
101
|
+
|-----------|---------|-------------|
|
|
102
|
+
| `auto_confirm` | `False` | Skip the interactive cost confirmation prompt (terminal) and backend-unavailable warnings. Credits used are still printed to stdout. |
|
|
103
|
+
|
|
104
|
+
```python
|
|
105
|
+
# Default: shows cost, prompts in terminal
|
|
106
|
+
dev = qml.device("openquantum.device", wires=2, shots=1024, backend="ionq:aria-1", ...)
|
|
107
|
+
|
|
108
|
+
# Skip prompts (still prints cost and status)
|
|
109
|
+
dev = qml.device("openquantum.device", wires=2, shots=1024, backend="ionq:aria-1", auto_confirm=True, ...)
|
|
110
|
+
|
|
111
|
+
# Check cumulative credits spent at any time
|
|
112
|
+
print(dev.total_credits_used)
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
Example output during execution:
|
|
116
|
+
```
|
|
117
|
+
[Open Quantum] ● IonQ Aria-1 (ionq:aria-1): Online | queue: 2 job(s)
|
|
118
|
+
[Open Quantum] Batch: 1 circuit(s) × 2 credit(s) each = 2 credit(s) total
|
|
119
|
+
[Open Quantum] Proceed? [y/N] y
|
|
120
|
+
[1/1] ⠹ Pending... (interrupt to cancel) (3s)
|
|
121
|
+
[1/1] Queued — can no longer be cancelled.
|
|
122
|
+
[1/1] ⠸ Running... (12s)
|
|
123
|
+
[Open Quantum] Batch complete: 2 credits used in 18s (session total: 2)
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
Multi-circuit batch:
|
|
127
|
+
```
|
|
128
|
+
[Open Quantum] Batch: 40 circuit(s) × 2 credit(s) each = 80 credit(s) total
|
|
129
|
+
[Open Quantum] Proceed? [y/N] y
|
|
130
|
+
[1/40] done (2/80 credits)
|
|
131
|
+
[2/40] done (4/80 credits)
|
|
132
|
+
...
|
|
133
|
+
[Open Quantum] Batch complete: 80 credits used in 245s (session total: 80)
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
### Execution Plans & Queue Priority
|
|
137
|
+
|
|
138
|
+
Control cost and scheduling with `execution_plan` and `queue_priority`:
|
|
139
|
+
|
|
140
|
+
```python
|
|
141
|
+
dev = qml.device(
|
|
142
|
+
"openquantum.device",
|
|
143
|
+
wires=2,
|
|
144
|
+
shots=1024,
|
|
145
|
+
backend="ionq:aria-1",
|
|
146
|
+
execution_plan="private", # "auto", "public", or "private"
|
|
147
|
+
queue_priority="priority", # "auto", "standard", "priority", or "instant"
|
|
148
|
+
...
|
|
149
|
+
)
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
| Parameter | Values | Default | Description |
|
|
153
|
+
|-----------|--------|---------|-------------|
|
|
154
|
+
| `execution_plan` | `"auto"`, `"public"`, `"private"` | `"auto"` | `"auto"` selects the cheapest plan (public). `"private"` uses dedicated resources at higher cost. |
|
|
155
|
+
| `queue_priority` | `"auto"`, `"standard"`, `"priority"`, `"instant"` | `"auto"` | `"auto"` selects the cheapest priority (standard). Higher priorities cost more but reduce queue wait time. |
|
|
156
|
+
|
|
157
|
+
### Job Subcategory
|
|
158
|
+
|
|
159
|
+
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](../../README.md) for the full list of subcategory short codes.
|
|
160
|
+
|
|
161
|
+
```python
|
|
162
|
+
dev = qml.device(
|
|
163
|
+
"openquantum.device",
|
|
164
|
+
wires=2,
|
|
165
|
+
shots=1024,
|
|
166
|
+
backend="ionq:aria-1",
|
|
167
|
+
job_subcategory_id="ml:qcl", # Quantum Classification
|
|
168
|
+
...
|
|
169
|
+
)
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
### Other Optional Parameters
|
|
173
|
+
|
|
174
|
+
| Parameter | Default | Description |
|
|
175
|
+
|-----------|---------|-------------|
|
|
176
|
+
| `scheduler_url` | `https://scheduler.openquantum.com` | Scheduler API base URL |
|
|
177
|
+
| `management_url` | `https://management.openquantum.com` | Management API base URL |
|
|
178
|
+
| `keycloak_base` | `https://id.openquantum.com` | Keycloak auth base URL |
|
|
179
|
+
| `realm` | `"platform"` | Keycloak realm |
|
|
180
|
+
| `job_timeout_seconds` | `86400` | Max wait for job completion |
|
|
181
|
+
|
|
182
|
+
## Supported Operations
|
|
183
|
+
|
|
184
|
+
### Gates
|
|
185
|
+
|
|
186
|
+
PauliX, PauliY, PauliZ, Hadamard, CNOT, CZ, SWAP, RX, RY, RZ, PhaseShift, S, T, SX, Toffoli, CSWAP, CRX, CRY, CRZ, Identity
|
|
187
|
+
|
|
188
|
+
### Measurements
|
|
189
|
+
|
|
190
|
+
- `qml.counts()` - Measurement counts
|
|
191
|
+
- `qml.expval()` - Expectation values
|
|
192
|
+
- `qml.var()` - Variance
|
|
193
|
+
- `qml.probs()` - Probabilities
|
|
194
|
+
- `qml.sample()` - Samples
|
|
195
|
+
|
|
196
|
+
All measurements require finite shots.
|
|
197
|
+
|
|
198
|
+
## Examples
|
|
199
|
+
|
|
200
|
+
### Expectation Values
|
|
201
|
+
|
|
202
|
+
```python
|
|
203
|
+
@qml.qnode(dev)
|
|
204
|
+
def circuit(x):
|
|
205
|
+
qml.RX(x, wires=0)
|
|
206
|
+
qml.Hadamard(wires=1)
|
|
207
|
+
qml.CNOT(wires=[0, 1])
|
|
208
|
+
return qml.expval(qml.PauliZ(0))
|
|
209
|
+
|
|
210
|
+
result = circuit(0.543)
|
|
211
|
+
```
|
|
212
|
+
|
|
213
|
+
### VQE Workflow
|
|
214
|
+
|
|
215
|
+
```python
|
|
216
|
+
# Use auto_confirm=True for iterative algorithms to avoid
|
|
217
|
+
# being prompted on every optimization step.
|
|
218
|
+
dev = qml.device("openquantum.device", wires=2, shots=4096,
|
|
219
|
+
backend="ionq:aria-1", auto_confirm=True, ...)
|
|
220
|
+
|
|
221
|
+
@qml.qnode(dev)
|
|
222
|
+
def cost_fn(params):
|
|
223
|
+
qml.RY(params[0], wires=0)
|
|
224
|
+
qml.RY(params[1], wires=1)
|
|
225
|
+
qml.CNOT(wires=[0, 1])
|
|
226
|
+
return qml.expval(qml.PauliZ(0) @ qml.PauliZ(1))
|
|
227
|
+
|
|
228
|
+
opt = qml.GradientDescentOptimizer(stepsize=0.4)
|
|
229
|
+
params = np.array([0.5, 0.1])
|
|
230
|
+
for _ in range(100):
|
|
231
|
+
params = opt.step(cost_fn, params)
|
|
232
|
+
|
|
233
|
+
# Check total credits consumed
|
|
234
|
+
print(f"Total credits used: {dev.total_credits_used}")
|
|
235
|
+
```
|
|
236
|
+
|
|
237
|
+
## Device Features
|
|
238
|
+
|
|
239
|
+
The PennyLane device loads the backend's full `constraint_data` (including the `features` array). This enables:
|
|
240
|
+
|
|
241
|
+
- Early, client-side rejection of constructs the device does not advertise (e.g. `reset`, `barrier`, mid-circuit measurement patterns) during `qml.QNode` execution / `device.preprocess()`.
|
|
242
|
+
- The `decompose` step in preprocess is driven by the device's supported gate set (from `native_ops` / `supported_ops`).
|
|
243
|
+
- You can query features at runtime:
|
|
244
|
+
|
|
245
|
+
```python
|
|
246
|
+
dev = qml.device("openquantum.device", wires=4, shots=1000, backend="iqm:emerald", ...)
|
|
247
|
+
print(dev.features)
|
|
248
|
+
print(dev.allows_reset()) # False for most real QPUs today
|
|
249
|
+
print(dev.allows_mid_circuit_measure())
|
|
250
|
+
print(dev.supports_feature("dynamic_circuits"))
|
|
251
|
+
print(dev.allows_barriers())
|
|
252
|
+
```
|
|
253
|
+
|
|
254
|
+
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.
|
|
255
|
+
|
|
256
|
+
See `sdk/docs/device-features.md` for the canonical list and `sdk/docs/capabilities.md` for the schema.
|
|
257
|
+
|
|
258
|
+
## Comparison with Qiskit Plugin
|
|
259
|
+
|
|
260
|
+
| Feature | PennyLane | Qiskit |
|
|
261
|
+
|---------|-----------|--------|
|
|
262
|
+
| Execution plan | `execution_plan=` on device | `execution_plan=` on `create_sampler()` / `create_estimator()` / config dict |
|
|
263
|
+
| Queue priority | `queue_priority=` on device | `queue_priority=` on `create_sampler()` / `create_estimator()` / config dict |
|
|
264
|
+
| Job subcategory | `job_subcategory_id=` (default `"oth:oth"`) | `job_subcategory_id=` (default `"oth:oth"`) |
|
|
265
|
+
| Shots | Required, no default | Default `100` (sampler) / `1024` (backend) |
|
|
266
|
+
| Cost confirmation | Interactive prompt (`auto_confirm=False`) | No prompt (submits immediately) |
|
|
267
|
+
| Backend status check | Automatic pre-flight check | Not built-in |
|
|
268
|
+
| Interrupt handling | Ctrl+C cancels queued jobs | Not built-in |
|
|
269
|
+
| Auth | Token or client credentials (env vars or constructor) | Token, client credentials, or saved accounts with keyring |
|
|
270
|
+
| Credit tracking | `dev.total_credits_used` | Not built-in |
|
|
271
|
+
| QASM format | QASM 3.0 (automatic) | `"qasm2"` or `"qasm3"` (configurable) |
|
|
272
|
+
|
|
273
|
+
## License
|
|
274
|
+
|
|
275
|
+
Apache License 2.0
|
|
@@ -0,0 +1,257 @@
|
|
|
1
|
+
# PennyLane-Open Quantum Plugin
|
|
2
|
+
|
|
3
|
+
A [PennyLane](https://pennylane.ai/) plugin for the [Open Quantum](https://openquantum.com) quantum computing platform. Submit quantum circuits to real quantum hardware through the Open Quantum SDK.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
pip install openquantum-sdk-pennylane
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
**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", ...)`.
|
|
12
|
+
|
|
13
|
+
For development:
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
pip install openquantum-sdk-pennylane[dev]
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
## Quick Start
|
|
20
|
+
|
|
21
|
+
```python
|
|
22
|
+
import pennylane as qml
|
|
23
|
+
|
|
24
|
+
# No need to import openquantum — the device registers automatically on install.
|
|
25
|
+
dev = qml.device(
|
|
26
|
+
"openquantum.device",
|
|
27
|
+
wires=2,
|
|
28
|
+
shots=1024,
|
|
29
|
+
backend="ionq:aria-1",
|
|
30
|
+
client_id="your_client_id",
|
|
31
|
+
client_secret="your_client_secret",
|
|
32
|
+
)
|
|
33
|
+
|
|
34
|
+
@qml.qnode(dev)
|
|
35
|
+
def bell_state():
|
|
36
|
+
qml.Hadamard(wires=0)
|
|
37
|
+
qml.CNOT(wires=[0, 1])
|
|
38
|
+
return qml.counts()
|
|
39
|
+
|
|
40
|
+
result = bell_state()
|
|
41
|
+
# The device shows backend status, credit cost, and prompts for confirmation:
|
|
42
|
+
# [Open Quantum] ● IonQ Aria-1 (ionq:aria-1): Online | queue: 0 job(s)
|
|
43
|
+
# [Open Quantum] Batch: 1 circuit(s) × 2 credit(s) each = 2 credit(s) total
|
|
44
|
+
# [Open Quantum] Proceed? [y/N] y
|
|
45
|
+
print(result) # {'00': 512, '11': 512}
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
## Configuration
|
|
49
|
+
|
|
50
|
+
### Required Parameters
|
|
51
|
+
|
|
52
|
+
| Parameter | Description |
|
|
53
|
+
|-----------|-------------|
|
|
54
|
+
| `wires` | Number of qubits |
|
|
55
|
+
| `shots` | Number of measurement shots (required, no analytic mode) |
|
|
56
|
+
| `backend` | Backend class ID or short_code (e.g., `"ionq:aria-1"`) |
|
|
57
|
+
|
|
58
|
+
### Authentication
|
|
59
|
+
|
|
60
|
+
The plugin supports three authentication methods, checked in order:
|
|
61
|
+
|
|
62
|
+
1. **Pre-built SchedulerClient** -- pass `scheduler=` for full control.
|
|
63
|
+
2. **Bearer token** -- pass `token=` or set `OPENQUANTUM_TOKEN`.
|
|
64
|
+
3. **Client credentials** -- pass `client_id=` + `client_secret=` or set `OPENQUANTUM_CLIENT_ID` + `OPENQUANTUM_CLIENT_SECRET`.
|
|
65
|
+
|
|
66
|
+
| Parameter | Environment Variable | Description |
|
|
67
|
+
|-----------|---------------------|-------------|
|
|
68
|
+
| `token` | `OPENQUANTUM_TOKEN` | Bearer token |
|
|
69
|
+
| `client_id` | `OPENQUANTUM_CLIENT_ID` | OAuth2 client ID |
|
|
70
|
+
| `client_secret` | `OPENQUANTUM_CLIENT_SECRET` | OAuth2 client secret |
|
|
71
|
+
| `organization_id` | `OPENQUANTUM_ORGANIZATION_ID` | Organization UUID (optional if single org) |
|
|
72
|
+
|
|
73
|
+
### Cost Control and Execution Flow
|
|
74
|
+
|
|
75
|
+
Before executing circuits, the device:
|
|
76
|
+
|
|
77
|
+
1. **Checks backend status** — reports whether the target QPU is online, its queue depth, and lists online alternatives if it is offline or not accepting jobs.
|
|
78
|
+
2. **Shows credit cost** — prepares the first circuit to get a real quote, then displays the per-circuit and total cost.
|
|
79
|
+
3. **Prompts for confirmation** (terminal only) — asks `Proceed? [y/N]`. In Jupyter notebooks, execution proceeds immediately (use `auto_confirm=True` or interrupt the kernel to cancel).
|
|
80
|
+
4. **Live status updates** — shows a spinner with job status 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.
|
|
81
|
+
|
|
82
|
+
| Parameter | Default | Description |
|
|
83
|
+
|-----------|---------|-------------|
|
|
84
|
+
| `auto_confirm` | `False` | Skip the interactive cost confirmation prompt (terminal) and backend-unavailable warnings. Credits used are still printed to stdout. |
|
|
85
|
+
|
|
86
|
+
```python
|
|
87
|
+
# Default: shows cost, prompts in terminal
|
|
88
|
+
dev = qml.device("openquantum.device", wires=2, shots=1024, backend="ionq:aria-1", ...)
|
|
89
|
+
|
|
90
|
+
# Skip prompts (still prints cost and status)
|
|
91
|
+
dev = qml.device("openquantum.device", wires=2, shots=1024, backend="ionq:aria-1", auto_confirm=True, ...)
|
|
92
|
+
|
|
93
|
+
# Check cumulative credits spent at any time
|
|
94
|
+
print(dev.total_credits_used)
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
Example output during execution:
|
|
98
|
+
```
|
|
99
|
+
[Open Quantum] ● IonQ Aria-1 (ionq:aria-1): Online | queue: 2 job(s)
|
|
100
|
+
[Open Quantum] Batch: 1 circuit(s) × 2 credit(s) each = 2 credit(s) total
|
|
101
|
+
[Open Quantum] Proceed? [y/N] y
|
|
102
|
+
[1/1] ⠹ Pending... (interrupt to cancel) (3s)
|
|
103
|
+
[1/1] Queued — can no longer be cancelled.
|
|
104
|
+
[1/1] ⠸ Running... (12s)
|
|
105
|
+
[Open Quantum] Batch complete: 2 credits used in 18s (session total: 2)
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
Multi-circuit batch:
|
|
109
|
+
```
|
|
110
|
+
[Open Quantum] Batch: 40 circuit(s) × 2 credit(s) each = 80 credit(s) total
|
|
111
|
+
[Open Quantum] Proceed? [y/N] y
|
|
112
|
+
[1/40] done (2/80 credits)
|
|
113
|
+
[2/40] done (4/80 credits)
|
|
114
|
+
...
|
|
115
|
+
[Open Quantum] Batch complete: 80 credits used in 245s (session total: 80)
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
### Execution Plans & Queue Priority
|
|
119
|
+
|
|
120
|
+
Control cost and scheduling with `execution_plan` and `queue_priority`:
|
|
121
|
+
|
|
122
|
+
```python
|
|
123
|
+
dev = qml.device(
|
|
124
|
+
"openquantum.device",
|
|
125
|
+
wires=2,
|
|
126
|
+
shots=1024,
|
|
127
|
+
backend="ionq:aria-1",
|
|
128
|
+
execution_plan="private", # "auto", "public", or "private"
|
|
129
|
+
queue_priority="priority", # "auto", "standard", "priority", or "instant"
|
|
130
|
+
...
|
|
131
|
+
)
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
| Parameter | Values | Default | Description |
|
|
135
|
+
|-----------|--------|---------|-------------|
|
|
136
|
+
| `execution_plan` | `"auto"`, `"public"`, `"private"` | `"auto"` | `"auto"` selects the cheapest plan (public). `"private"` uses dedicated resources at higher cost. |
|
|
137
|
+
| `queue_priority` | `"auto"`, `"standard"`, `"priority"`, `"instant"` | `"auto"` | `"auto"` selects the cheapest priority (standard). Higher priorities cost more but reduce queue wait time. |
|
|
138
|
+
|
|
139
|
+
### Job Subcategory
|
|
140
|
+
|
|
141
|
+
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](../../README.md) for the full list of subcategory short codes.
|
|
142
|
+
|
|
143
|
+
```python
|
|
144
|
+
dev = qml.device(
|
|
145
|
+
"openquantum.device",
|
|
146
|
+
wires=2,
|
|
147
|
+
shots=1024,
|
|
148
|
+
backend="ionq:aria-1",
|
|
149
|
+
job_subcategory_id="ml:qcl", # Quantum Classification
|
|
150
|
+
...
|
|
151
|
+
)
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
### Other Optional Parameters
|
|
155
|
+
|
|
156
|
+
| Parameter | Default | Description |
|
|
157
|
+
|-----------|---------|-------------|
|
|
158
|
+
| `scheduler_url` | `https://scheduler.openquantum.com` | Scheduler API base URL |
|
|
159
|
+
| `management_url` | `https://management.openquantum.com` | Management API base URL |
|
|
160
|
+
| `keycloak_base` | `https://id.openquantum.com` | Keycloak auth base URL |
|
|
161
|
+
| `realm` | `"platform"` | Keycloak realm |
|
|
162
|
+
| `job_timeout_seconds` | `86400` | Max wait for job completion |
|
|
163
|
+
|
|
164
|
+
## Supported Operations
|
|
165
|
+
|
|
166
|
+
### Gates
|
|
167
|
+
|
|
168
|
+
PauliX, PauliY, PauliZ, Hadamard, CNOT, CZ, SWAP, RX, RY, RZ, PhaseShift, S, T, SX, Toffoli, CSWAP, CRX, CRY, CRZ, Identity
|
|
169
|
+
|
|
170
|
+
### Measurements
|
|
171
|
+
|
|
172
|
+
- `qml.counts()` - Measurement counts
|
|
173
|
+
- `qml.expval()` - Expectation values
|
|
174
|
+
- `qml.var()` - Variance
|
|
175
|
+
- `qml.probs()` - Probabilities
|
|
176
|
+
- `qml.sample()` - Samples
|
|
177
|
+
|
|
178
|
+
All measurements require finite shots.
|
|
179
|
+
|
|
180
|
+
## Examples
|
|
181
|
+
|
|
182
|
+
### Expectation Values
|
|
183
|
+
|
|
184
|
+
```python
|
|
185
|
+
@qml.qnode(dev)
|
|
186
|
+
def circuit(x):
|
|
187
|
+
qml.RX(x, wires=0)
|
|
188
|
+
qml.Hadamard(wires=1)
|
|
189
|
+
qml.CNOT(wires=[0, 1])
|
|
190
|
+
return qml.expval(qml.PauliZ(0))
|
|
191
|
+
|
|
192
|
+
result = circuit(0.543)
|
|
193
|
+
```
|
|
194
|
+
|
|
195
|
+
### VQE Workflow
|
|
196
|
+
|
|
197
|
+
```python
|
|
198
|
+
# Use auto_confirm=True for iterative algorithms to avoid
|
|
199
|
+
# being prompted on every optimization step.
|
|
200
|
+
dev = qml.device("openquantum.device", wires=2, shots=4096,
|
|
201
|
+
backend="ionq:aria-1", auto_confirm=True, ...)
|
|
202
|
+
|
|
203
|
+
@qml.qnode(dev)
|
|
204
|
+
def cost_fn(params):
|
|
205
|
+
qml.RY(params[0], wires=0)
|
|
206
|
+
qml.RY(params[1], wires=1)
|
|
207
|
+
qml.CNOT(wires=[0, 1])
|
|
208
|
+
return qml.expval(qml.PauliZ(0) @ qml.PauliZ(1))
|
|
209
|
+
|
|
210
|
+
opt = qml.GradientDescentOptimizer(stepsize=0.4)
|
|
211
|
+
params = np.array([0.5, 0.1])
|
|
212
|
+
for _ in range(100):
|
|
213
|
+
params = opt.step(cost_fn, params)
|
|
214
|
+
|
|
215
|
+
# Check total credits consumed
|
|
216
|
+
print(f"Total credits used: {dev.total_credits_used}")
|
|
217
|
+
```
|
|
218
|
+
|
|
219
|
+
## Device Features
|
|
220
|
+
|
|
221
|
+
The PennyLane device loads the backend's full `constraint_data` (including the `features` array). This enables:
|
|
222
|
+
|
|
223
|
+
- Early, client-side rejection of constructs the device does not advertise (e.g. `reset`, `barrier`, mid-circuit measurement patterns) during `qml.QNode` execution / `device.preprocess()`.
|
|
224
|
+
- The `decompose` step in preprocess is driven by the device's supported gate set (from `native_ops` / `supported_ops`).
|
|
225
|
+
- You can query features at runtime:
|
|
226
|
+
|
|
227
|
+
```python
|
|
228
|
+
dev = qml.device("openquantum.device", wires=4, shots=1000, backend="iqm:emerald", ...)
|
|
229
|
+
print(dev.features)
|
|
230
|
+
print(dev.allows_reset()) # False for most real QPUs today
|
|
231
|
+
print(dev.allows_mid_circuit_measure())
|
|
232
|
+
print(dev.supports_feature("dynamic_circuits"))
|
|
233
|
+
print(dev.allows_barriers())
|
|
234
|
+
```
|
|
235
|
+
|
|
236
|
+
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.
|
|
237
|
+
|
|
238
|
+
See `sdk/docs/device-features.md` for the canonical list and `sdk/docs/capabilities.md` for the schema.
|
|
239
|
+
|
|
240
|
+
## Comparison with Qiskit Plugin
|
|
241
|
+
|
|
242
|
+
| Feature | PennyLane | Qiskit |
|
|
243
|
+
|---------|-----------|--------|
|
|
244
|
+
| Execution plan | `execution_plan=` on device | `execution_plan=` on `create_sampler()` / `create_estimator()` / config dict |
|
|
245
|
+
| Queue priority | `queue_priority=` on device | `queue_priority=` on `create_sampler()` / `create_estimator()` / config dict |
|
|
246
|
+
| Job subcategory | `job_subcategory_id=` (default `"oth:oth"`) | `job_subcategory_id=` (default `"oth:oth"`) |
|
|
247
|
+
| Shots | Required, no default | Default `100` (sampler) / `1024` (backend) |
|
|
248
|
+
| Cost confirmation | Interactive prompt (`auto_confirm=False`) | No prompt (submits immediately) |
|
|
249
|
+
| Backend status check | Automatic pre-flight check | Not built-in |
|
|
250
|
+
| Interrupt handling | Ctrl+C cancels queued jobs | Not built-in |
|
|
251
|
+
| Auth | Token or client credentials (env vars or constructor) | Token, client credentials, or saved accounts with keyring |
|
|
252
|
+
| Credit tracking | `dev.total_credits_used` | Not built-in |
|
|
253
|
+
| QASM format | QASM 3.0 (automatic) | `"qasm2"` or `"qasm3"` (configurable) |
|
|
254
|
+
|
|
255
|
+
## License
|
|
256
|
+
|
|
257
|
+
Apache License 2.0
|