westquant-bluequbit 0.1.0__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.
- westquant_bluequbit-0.1.0/PKG-INFO +203 -0
- westquant_bluequbit-0.1.0/README.md +180 -0
- westquant_bluequbit-0.1.0/benchmarks/__init__.py +0 -0
- westquant_bluequbit-0.1.0/benchmarks/ghz.py +60 -0
- westquant_bluequbit-0.1.0/benchmarks/pauli.py +99 -0
- westquant_bluequbit-0.1.0/benchmarks/qaoa.py +125 -0
- westquant_bluequbit-0.1.0/benchmarks/qft.py +56 -0
- westquant_bluequbit-0.1.0/benchmarks/random.py +141 -0
- westquant_bluequbit-0.1.0/benchmarks/suite.py +319 -0
- westquant_bluequbit-0.1.0/benchmarks/vqe.py +87 -0
- westquant_bluequbit-0.1.0/pyproject.toml +32 -0
- westquant_bluequbit-0.1.0/setup.cfg +4 -0
- westquant_bluequbit-0.1.0/tests/test_core.py +173 -0
- westquant_bluequbit-0.1.0/westquant_bluequbit/__init__.py +71 -0
- westquant_bluequbit-0.1.0/westquant_bluequbit/cli.py +317 -0
- westquant_bluequbit-0.1.0/westquant_bluequbit/cost_model.py +281 -0
- westquant_bluequbit-0.1.0/westquant_bluequbit/device_search.py +195 -0
- westquant_bluequbit-0.1.0/westquant_bluequbit/executor.py +211 -0
- westquant_bluequbit-0.1.0/westquant_bluequbit/metrics.py +279 -0
- westquant_bluequbit-0.1.0/westquant_bluequbit/mps_search.py +193 -0
- westquant_bluequbit-0.1.0/westquant_bluequbit/pauli_path_search.py +153 -0
- westquant_bluequbit-0.1.0/westquant_bluequbit/provider.py +282 -0
- westquant_bluequbit-0.1.0/westquant_bluequbit/representation.py +224 -0
- westquant_bluequbit-0.1.0/westquant_bluequbit/training_data.py +304 -0
- westquant_bluequbit-0.1.0/westquant_bluequbit/verification.py +214 -0
- westquant_bluequbit-0.1.0/westquant_bluequbit.egg-info/PKG-INFO +203 -0
- westquant_bluequbit-0.1.0/westquant_bluequbit.egg-info/SOURCES.txt +29 -0
- westquant_bluequbit-0.1.0/westquant_bluequbit.egg-info/dependency_links.txt +1 -0
- westquant_bluequbit-0.1.0/westquant_bluequbit.egg-info/entry_points.txt +2 -0
- westquant_bluequbit-0.1.0/westquant_bluequbit.egg-info/requires.txt +15 -0
- westquant_bluequbit-0.1.0/westquant_bluequbit.egg-info/top_level.txt +2 -0
|
@@ -0,0 +1,203 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: westquant-bluequbit
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: WestQuant Execution Representation Scheduling on BlueQubit compute
|
|
5
|
+
Author: WestQuant
|
|
6
|
+
License: Apache-2.0
|
|
7
|
+
Project-URL: Homepage, https://github.com/WestQuantOpen/westquant-bluequbit
|
|
8
|
+
Project-URL: Documentation, https://github.com/WestQuantOpen/westquant-bluequbit#readme
|
|
9
|
+
Keywords: quantum,scheduling,optimization,bluequbit,representation,mps,pauli-path
|
|
10
|
+
Requires-Python: >=3.10
|
|
11
|
+
Description-Content-Type: text/markdown
|
|
12
|
+
Requires-Dist: numpy<2,>=1.24
|
|
13
|
+
Provides-Extra: bluequbit
|
|
14
|
+
Requires-Dist: bluequbit>=0.18; extra == "bluequbit"
|
|
15
|
+
Provides-Extra: qiskit
|
|
16
|
+
Requires-Dist: qiskit>=1.0; extra == "qiskit"
|
|
17
|
+
Provides-Extra: all
|
|
18
|
+
Requires-Dist: bluequbit>=0.18; extra == "all"
|
|
19
|
+
Requires-Dist: qiskit>=1.0; extra == "all"
|
|
20
|
+
Provides-Extra: dev
|
|
21
|
+
Requires-Dist: pytest>=7; extra == "dev"
|
|
22
|
+
Requires-Dist: pytest-cov; extra == "dev"
|
|
23
|
+
|
|
24
|
+
# westquant-bluequbit
|
|
25
|
+
|
|
26
|
+
**WestQuant Execution Representation Scheduling on BlueQubit compute.**
|
|
27
|
+
|
|
28
|
+
WestQuant learns to map `(algorithm, circuit structure, accuracy target)` to `(representation, simulator, parameters)` on BlueQubit's multi-backend compute platform.
|
|
29
|
+
|
|
30
|
+
```
|
|
31
|
+
WestQuant
|
|
32
|
+
│
|
|
33
|
+
circuit / problem
|
|
34
|
+
│
|
|
35
|
+
┌───▼───────────┐
|
|
36
|
+
│ Representation│
|
|
37
|
+
│ Search │
|
|
38
|
+
└───┬───────────┘
|
|
39
|
+
│
|
|
40
|
+
┌───┴───────────────┐
|
|
41
|
+
│ Circuit rep │ Execution rep
|
|
42
|
+
│ gates/layout/basis │ CPU / GPU / MPS / Pauli-path / QPU
|
|
43
|
+
│ transpilation │ bond dimension / truncation threshold
|
|
44
|
+
└───┬───────────────┘
|
|
45
|
+
▼
|
|
46
|
+
BlueQubit
|
|
47
|
+
│
|
|
48
|
+
▼
|
|
49
|
+
cost / runtime / accuracy
|
|
50
|
+
│
|
|
51
|
+
▼
|
|
52
|
+
WQT training data
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
## Why not just a wrapper?
|
|
56
|
+
|
|
57
|
+
BlueQubit exposes multiple ways to solve the same quantum computation: CPU, GPU, MPS (CPU/GPU), Pauli-path, and QPU. Each has tunable parameters (MPS bond dimension, Pauli-path truncation threshold, shots, transpilation level).
|
|
58
|
+
|
|
59
|
+
This means WestQuant can search over:
|
|
60
|
+
|
|
61
|
+
```
|
|
62
|
+
a = (R_c, D, P, θ)
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
where `R_c` = circuit representation, `D` = device/simulator, `P` = preprocessing/transpilation, `θ` = simulator parameters.
|
|
66
|
+
|
|
67
|
+
The optimization target is:
|
|
68
|
+
|
|
69
|
+
```
|
|
70
|
+
min(T, C, E) subject to E < ε
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
where `T` = runtime, `C` = cost, `E` = approximation error.
|
|
74
|
+
|
|
75
|
+
## Installation
|
|
76
|
+
|
|
77
|
+
```bash
|
|
78
|
+
pip install westquant-bluequbit[bluequbit,qiskit]
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
## Quick Start
|
|
82
|
+
|
|
83
|
+
```python
|
|
84
|
+
from westquant_bluequbit import BlueQubitSearch
|
|
85
|
+
|
|
86
|
+
search = BlueQubitSearch()
|
|
87
|
+
|
|
88
|
+
result = search.optimize(
|
|
89
|
+
circuit,
|
|
90
|
+
objectives=["runtime", "cost", "error"],
|
|
91
|
+
devices=["cpu", "gpu", "mps.gpu", "pauli-path"],
|
|
92
|
+
mps_bond_dimensions=[4, 8, 16, 32, 64],
|
|
93
|
+
pauli_path_thresholds=[1e-1, 1e-3, 1e-5],
|
|
94
|
+
)
|
|
95
|
+
|
|
96
|
+
# Pareto-optimal execution configurations
|
|
97
|
+
for config in result["pareto_front"]:
|
|
98
|
+
print(f"{config['device']}: {config['runtime_ms']:.0f}ms, ${config['cost']:.4f}")
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
## CLI
|
|
102
|
+
|
|
103
|
+
```bash
|
|
104
|
+
# Search across devices
|
|
105
|
+
wq-bq search --circuit ghz --n-qubits 24 --devices cpu,gpu,mps.gpu
|
|
106
|
+
|
|
107
|
+
# MPS bond dimension sweep
|
|
108
|
+
wq-bq mps-sweep --circuit qaoa --n-qubits 28 --chi 4,8,16,32,64 --target-fidelity 0.999
|
|
109
|
+
|
|
110
|
+
# Pauli-path truncation sweep
|
|
111
|
+
wq-bq pps-sweep --circuit pauli --n-qubits 32 --thresholds 1e-1,1e-3,1e-5
|
|
112
|
+
|
|
113
|
+
# Full benchmark suite
|
|
114
|
+
wq-bq benchmark --families ghz,qft,qaoa,vqe,random,pauli --n-qubits 8,16,24 --devices cpu,gpu
|
|
115
|
+
|
|
116
|
+
# Cost estimate
|
|
117
|
+
wq-bq estimate --circuit ghz --n-qubits 32 --device mps.gpu
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
## Architecture
|
|
121
|
+
|
|
122
|
+
### Core Modules
|
|
123
|
+
|
|
124
|
+
| Module | Purpose |
|
|
125
|
+
|--------|---------|
|
|
126
|
+
| `provider.py` | BlueQubit SDK wrapper with ledger tracking |
|
|
127
|
+
| `executor.py` | Circuit execution with wall-clock timing |
|
|
128
|
+
| `representation.py` | Circuit + execution representation dataclasses |
|
|
129
|
+
| `device_search.py` | Multi-device Pareto search |
|
|
130
|
+
| `mps_search.py` | MPS bond dimension sweep |
|
|
131
|
+
| `pauli_path_search.py` | Pauli-path truncation threshold sweep |
|
|
132
|
+
| `cost_model.py` | Learned cost/runtime prediction |
|
|
133
|
+
| `verification.py` | Fidelity, JS divergence, TV distance |
|
|
134
|
+
| `metrics.py` | Circuit features, Pareto front, hypervolume |
|
|
135
|
+
| `training_data.py` | WQT policy record generation |
|
|
136
|
+
| `cli.py` | Command-line interface |
|
|
137
|
+
|
|
138
|
+
### Benchmark Suite
|
|
139
|
+
|
|
140
|
+
| Family | What it tests |
|
|
141
|
+
|--------|--------------|
|
|
142
|
+
| GHZ | Low entanglement, ideal MPS candidate |
|
|
143
|
+
| QFT | Dense global structure |
|
|
144
|
+
| QAOA | Graph optimization |
|
|
145
|
+
| VQE | Hardware-efficient ansatz |
|
|
146
|
+
| Random Clifford | Stabilizer correctness baseline |
|
|
147
|
+
| Random Universal | Generic hard simulation |
|
|
148
|
+
| Pauli Evolution | Pauli-path relevant |
|
|
149
|
+
|
|
150
|
+
Default qubit counts: 8, 12, 16, 20, 24, 28, 32, 36, 40.
|
|
151
|
+
|
|
152
|
+
### WQT Training Data
|
|
153
|
+
|
|
154
|
+
Each execution produces a policy record:
|
|
155
|
+
|
|
156
|
+
```json
|
|
157
|
+
{
|
|
158
|
+
"circuit_features": {"n_qubits": 24, "n_gates": 120, "n_2q_gates": 45, "depth": 30},
|
|
159
|
+
"representation": "mps.gpu_chi64",
|
|
160
|
+
"action": {"device": "mps.gpu", "options": {"mps_bond_dimension": 64}},
|
|
161
|
+
"prediction": {"estimated_runtime_ms": 820, "estimated_cost": 0.04},
|
|
162
|
+
"result": {"runtime_ms": 734, "cost": 0.037, "fidelity": 0.99991},
|
|
163
|
+
"reward": {"accuracy": 0.99991, "runtime": 734, "cost": 0.037}
|
|
164
|
+
}
|
|
165
|
+
```
|
|
166
|
+
|
|
167
|
+
## Five WestQuant Experiments
|
|
168
|
+
|
|
169
|
+
### A. Backend Router
|
|
170
|
+
Learn `f(circuit) → {CPU, GPU, MPS, PPS}`. Which simulator representation is best for this circuit?
|
|
171
|
+
|
|
172
|
+
### B. MPS Bond-Dimension Scheduler
|
|
173
|
+
Search `χ ∈ {2, 4, 8, 16, 32, 64, 128}`. Measure `(χ, fidelity, runtime, cost)`. Learn `χ* = f(C, ε)`.
|
|
174
|
+
|
|
175
|
+
### C. Pauli-Path Threshold Scheduler
|
|
176
|
+
Search thresholds `10^{-1}` to `10^{-5}`. Get the accuracy-vs-compute curve.
|
|
177
|
+
|
|
178
|
+
### D. Circuit Representation × Simulator Representation
|
|
179
|
+
Not just `C → D`, but `(C, R) → (C', D)`. WestQuant changes gate decomposition, routing, basis — then selects the simulator. Same algorithm, different classical cost.
|
|
180
|
+
|
|
181
|
+
### E. Learned Cost Model
|
|
182
|
+
Compare BlueQubit's `estimate()` against actual runtime. Train `T̂_WQ(C, R, D)` — a representation-aware cost model.
|
|
183
|
+
|
|
184
|
+
## BlueQubit Devices
|
|
185
|
+
|
|
186
|
+
| Device | Cost | Use Case |
|
|
187
|
+
|--------|------|----------|
|
|
188
|
+
| `cpu` | Free | Small circuits, exact statevector |
|
|
189
|
+
| `gpu` | $0.20/job | Medium circuits, fast exact simulation |
|
|
190
|
+
| `mps.cpu` | Free | Large circuits, approximate |
|
|
191
|
+
| `mps.gpu` | $0.20/job | Large circuits, fast approximate |
|
|
192
|
+
| `pauli-path` | varies | Observable estimation, large circuits |
|
|
193
|
+
| `quantum` | varies | Real QPU execution |
|
|
194
|
+
|
|
195
|
+
## License
|
|
196
|
+
|
|
197
|
+
Apache-2.0
|
|
198
|
+
|
|
199
|
+
## Links
|
|
200
|
+
|
|
201
|
+
- [GitHub](https://github.com/WestQuantOpen/westquant-bluequbit)
|
|
202
|
+
- [WestQuant Open](https://github.com/WestQuantOpen)
|
|
203
|
+
- [BlueQubit](https://bluequbit.io)
|
|
@@ -0,0 +1,180 @@
|
|
|
1
|
+
# westquant-bluequbit
|
|
2
|
+
|
|
3
|
+
**WestQuant Execution Representation Scheduling on BlueQubit compute.**
|
|
4
|
+
|
|
5
|
+
WestQuant learns to map `(algorithm, circuit structure, accuracy target)` to `(representation, simulator, parameters)` on BlueQubit's multi-backend compute platform.
|
|
6
|
+
|
|
7
|
+
```
|
|
8
|
+
WestQuant
|
|
9
|
+
│
|
|
10
|
+
circuit / problem
|
|
11
|
+
│
|
|
12
|
+
┌───▼───────────┐
|
|
13
|
+
│ Representation│
|
|
14
|
+
│ Search │
|
|
15
|
+
└───┬───────────┘
|
|
16
|
+
│
|
|
17
|
+
┌───┴───────────────┐
|
|
18
|
+
│ Circuit rep │ Execution rep
|
|
19
|
+
│ gates/layout/basis │ CPU / GPU / MPS / Pauli-path / QPU
|
|
20
|
+
│ transpilation │ bond dimension / truncation threshold
|
|
21
|
+
└───┬───────────────┘
|
|
22
|
+
▼
|
|
23
|
+
BlueQubit
|
|
24
|
+
│
|
|
25
|
+
▼
|
|
26
|
+
cost / runtime / accuracy
|
|
27
|
+
│
|
|
28
|
+
▼
|
|
29
|
+
WQT training data
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
## Why not just a wrapper?
|
|
33
|
+
|
|
34
|
+
BlueQubit exposes multiple ways to solve the same quantum computation: CPU, GPU, MPS (CPU/GPU), Pauli-path, and QPU. Each has tunable parameters (MPS bond dimension, Pauli-path truncation threshold, shots, transpilation level).
|
|
35
|
+
|
|
36
|
+
This means WestQuant can search over:
|
|
37
|
+
|
|
38
|
+
```
|
|
39
|
+
a = (R_c, D, P, θ)
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
where `R_c` = circuit representation, `D` = device/simulator, `P` = preprocessing/transpilation, `θ` = simulator parameters.
|
|
43
|
+
|
|
44
|
+
The optimization target is:
|
|
45
|
+
|
|
46
|
+
```
|
|
47
|
+
min(T, C, E) subject to E < ε
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
where `T` = runtime, `C` = cost, `E` = approximation error.
|
|
51
|
+
|
|
52
|
+
## Installation
|
|
53
|
+
|
|
54
|
+
```bash
|
|
55
|
+
pip install westquant-bluequbit[bluequbit,qiskit]
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
## Quick Start
|
|
59
|
+
|
|
60
|
+
```python
|
|
61
|
+
from westquant_bluequbit import BlueQubitSearch
|
|
62
|
+
|
|
63
|
+
search = BlueQubitSearch()
|
|
64
|
+
|
|
65
|
+
result = search.optimize(
|
|
66
|
+
circuit,
|
|
67
|
+
objectives=["runtime", "cost", "error"],
|
|
68
|
+
devices=["cpu", "gpu", "mps.gpu", "pauli-path"],
|
|
69
|
+
mps_bond_dimensions=[4, 8, 16, 32, 64],
|
|
70
|
+
pauli_path_thresholds=[1e-1, 1e-3, 1e-5],
|
|
71
|
+
)
|
|
72
|
+
|
|
73
|
+
# Pareto-optimal execution configurations
|
|
74
|
+
for config in result["pareto_front"]:
|
|
75
|
+
print(f"{config['device']}: {config['runtime_ms']:.0f}ms, ${config['cost']:.4f}")
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
## CLI
|
|
79
|
+
|
|
80
|
+
```bash
|
|
81
|
+
# Search across devices
|
|
82
|
+
wq-bq search --circuit ghz --n-qubits 24 --devices cpu,gpu,mps.gpu
|
|
83
|
+
|
|
84
|
+
# MPS bond dimension sweep
|
|
85
|
+
wq-bq mps-sweep --circuit qaoa --n-qubits 28 --chi 4,8,16,32,64 --target-fidelity 0.999
|
|
86
|
+
|
|
87
|
+
# Pauli-path truncation sweep
|
|
88
|
+
wq-bq pps-sweep --circuit pauli --n-qubits 32 --thresholds 1e-1,1e-3,1e-5
|
|
89
|
+
|
|
90
|
+
# Full benchmark suite
|
|
91
|
+
wq-bq benchmark --families ghz,qft,qaoa,vqe,random,pauli --n-qubits 8,16,24 --devices cpu,gpu
|
|
92
|
+
|
|
93
|
+
# Cost estimate
|
|
94
|
+
wq-bq estimate --circuit ghz --n-qubits 32 --device mps.gpu
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
## Architecture
|
|
98
|
+
|
|
99
|
+
### Core Modules
|
|
100
|
+
|
|
101
|
+
| Module | Purpose |
|
|
102
|
+
|--------|---------|
|
|
103
|
+
| `provider.py` | BlueQubit SDK wrapper with ledger tracking |
|
|
104
|
+
| `executor.py` | Circuit execution with wall-clock timing |
|
|
105
|
+
| `representation.py` | Circuit + execution representation dataclasses |
|
|
106
|
+
| `device_search.py` | Multi-device Pareto search |
|
|
107
|
+
| `mps_search.py` | MPS bond dimension sweep |
|
|
108
|
+
| `pauli_path_search.py` | Pauli-path truncation threshold sweep |
|
|
109
|
+
| `cost_model.py` | Learned cost/runtime prediction |
|
|
110
|
+
| `verification.py` | Fidelity, JS divergence, TV distance |
|
|
111
|
+
| `metrics.py` | Circuit features, Pareto front, hypervolume |
|
|
112
|
+
| `training_data.py` | WQT policy record generation |
|
|
113
|
+
| `cli.py` | Command-line interface |
|
|
114
|
+
|
|
115
|
+
### Benchmark Suite
|
|
116
|
+
|
|
117
|
+
| Family | What it tests |
|
|
118
|
+
|--------|--------------|
|
|
119
|
+
| GHZ | Low entanglement, ideal MPS candidate |
|
|
120
|
+
| QFT | Dense global structure |
|
|
121
|
+
| QAOA | Graph optimization |
|
|
122
|
+
| VQE | Hardware-efficient ansatz |
|
|
123
|
+
| Random Clifford | Stabilizer correctness baseline |
|
|
124
|
+
| Random Universal | Generic hard simulation |
|
|
125
|
+
| Pauli Evolution | Pauli-path relevant |
|
|
126
|
+
|
|
127
|
+
Default qubit counts: 8, 12, 16, 20, 24, 28, 32, 36, 40.
|
|
128
|
+
|
|
129
|
+
### WQT Training Data
|
|
130
|
+
|
|
131
|
+
Each execution produces a policy record:
|
|
132
|
+
|
|
133
|
+
```json
|
|
134
|
+
{
|
|
135
|
+
"circuit_features": {"n_qubits": 24, "n_gates": 120, "n_2q_gates": 45, "depth": 30},
|
|
136
|
+
"representation": "mps.gpu_chi64",
|
|
137
|
+
"action": {"device": "mps.gpu", "options": {"mps_bond_dimension": 64}},
|
|
138
|
+
"prediction": {"estimated_runtime_ms": 820, "estimated_cost": 0.04},
|
|
139
|
+
"result": {"runtime_ms": 734, "cost": 0.037, "fidelity": 0.99991},
|
|
140
|
+
"reward": {"accuracy": 0.99991, "runtime": 734, "cost": 0.037}
|
|
141
|
+
}
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
## Five WestQuant Experiments
|
|
145
|
+
|
|
146
|
+
### A. Backend Router
|
|
147
|
+
Learn `f(circuit) → {CPU, GPU, MPS, PPS}`. Which simulator representation is best for this circuit?
|
|
148
|
+
|
|
149
|
+
### B. MPS Bond-Dimension Scheduler
|
|
150
|
+
Search `χ ∈ {2, 4, 8, 16, 32, 64, 128}`. Measure `(χ, fidelity, runtime, cost)`. Learn `χ* = f(C, ε)`.
|
|
151
|
+
|
|
152
|
+
### C. Pauli-Path Threshold Scheduler
|
|
153
|
+
Search thresholds `10^{-1}` to `10^{-5}`. Get the accuracy-vs-compute curve.
|
|
154
|
+
|
|
155
|
+
### D. Circuit Representation × Simulator Representation
|
|
156
|
+
Not just `C → D`, but `(C, R) → (C', D)`. WestQuant changes gate decomposition, routing, basis — then selects the simulator. Same algorithm, different classical cost.
|
|
157
|
+
|
|
158
|
+
### E. Learned Cost Model
|
|
159
|
+
Compare BlueQubit's `estimate()` against actual runtime. Train `T̂_WQ(C, R, D)` — a representation-aware cost model.
|
|
160
|
+
|
|
161
|
+
## BlueQubit Devices
|
|
162
|
+
|
|
163
|
+
| Device | Cost | Use Case |
|
|
164
|
+
|--------|------|----------|
|
|
165
|
+
| `cpu` | Free | Small circuits, exact statevector |
|
|
166
|
+
| `gpu` | $0.20/job | Medium circuits, fast exact simulation |
|
|
167
|
+
| `mps.cpu` | Free | Large circuits, approximate |
|
|
168
|
+
| `mps.gpu` | $0.20/job | Large circuits, fast approximate |
|
|
169
|
+
| `pauli-path` | varies | Observable estimation, large circuits |
|
|
170
|
+
| `quantum` | varies | Real QPU execution |
|
|
171
|
+
|
|
172
|
+
## License
|
|
173
|
+
|
|
174
|
+
Apache-2.0
|
|
175
|
+
|
|
176
|
+
## Links
|
|
177
|
+
|
|
178
|
+
- [GitHub](https://github.com/WestQuantOpen/westquant-bluequbit)
|
|
179
|
+
- [WestQuant Open](https://github.com/WestQuantOpen)
|
|
180
|
+
- [BlueQubit](https://bluequbit.io)
|
|
File without changes
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
"""GHZ state benchmark circuits.
|
|
2
|
+
|
|
3
|
+
Generates Greenberger-Horne-Zeilinger (GHZ) state preparation circuits,
|
|
4
|
+
which place a register of qubits into the maximally entangled superposition
|
|
5
|
+
|
|
6
|
+
|0...0> + |1...1> / sqrt(2)
|
|
7
|
+
|
|
8
|
+
via a Hadamard on qubit 0 followed by a chain of CNOT gates.
|
|
9
|
+
"""
|
|
10
|
+
|
|
11
|
+
from __future__ import annotations
|
|
12
|
+
|
|
13
|
+
from typing import Sequence
|
|
14
|
+
|
|
15
|
+
__all__ = ["ghz_circuit", "ghz_family"]
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
def ghz_circuit(n_qubits: int):
|
|
19
|
+
"""Return a circuit preparing an ``n_qubits``-qubit GHZ state.
|
|
20
|
+
|
|
21
|
+
The circuit applies a Hadamard gate to qubit 0 and then a chain of
|
|
22
|
+
CNOT gates ``qubit[i] -> qubit[i + 1]`` for ``i`` in ``range(n_qubits - 1)``.
|
|
23
|
+
|
|
24
|
+
Parameters
|
|
25
|
+
----------
|
|
26
|
+
n_qubits:
|
|
27
|
+
Number of qubits in the register. Must be at least 1.
|
|
28
|
+
|
|
29
|
+
Returns
|
|
30
|
+
-------
|
|
31
|
+
qiskit.QuantumCircuit
|
|
32
|
+
A circuit that prepares the GHZ state on ``n_qubits`` qubits.
|
|
33
|
+
"""
|
|
34
|
+
if n_qubits < 1:
|
|
35
|
+
raise ValueError(f"n_qubits must be >= 1, got {n_qubits}")
|
|
36
|
+
|
|
37
|
+
from qiskit import QuantumCircuit
|
|
38
|
+
|
|
39
|
+
qc = QuantumCircuit(n_qubits, name=f"ghz_{n_qubits}")
|
|
40
|
+
qc.h(0)
|
|
41
|
+
for i in range(n_qubits - 1):
|
|
42
|
+
qc.cx(i, i + 1)
|
|
43
|
+
qc.measure_all()
|
|
44
|
+
return qc
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
def ghz_family(n_qubits_list: Sequence[int]) -> list[tuple[str, "object"]]:
|
|
48
|
+
"""Return a list of ``(name, circuit)`` GHZ circuits for each qubit count.
|
|
49
|
+
|
|
50
|
+
Parameters
|
|
51
|
+
----------
|
|
52
|
+
n_qubits_list:
|
|
53
|
+
Iterable of qubit counts for which to build GHZ circuits.
|
|
54
|
+
|
|
55
|
+
Returns
|
|
56
|
+
-------
|
|
57
|
+
list[tuple[str, qiskit.QuantumCircuit]]
|
|
58
|
+
One ``(name, circuit)`` pair per requested qubit count.
|
|
59
|
+
"""
|
|
60
|
+
return [(f"ghz_{n}", ghz_circuit(n)) for n in n_qubits_list]
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
"""Trotterized Pauli-evolution benchmark circuits.
|
|
2
|
+
|
|
3
|
+
Builds circuits that implement the time evolution under a sum of random
|
|
4
|
+
Pauli operators using Qiskit's :class:`~qiskit.circuit.library.PauliEvolutionGate`
|
|
5
|
+
(first-order Trotter synthesis). These circuits are representative of
|
|
6
|
+
simulated quantum dynamics / chemistry workloads.
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
from __future__ import annotations
|
|
10
|
+
|
|
11
|
+
from typing import Sequence
|
|
12
|
+
|
|
13
|
+
__all__ = ["pauli_evolution_circuit", "pauli_family"]
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
def pauli_evolution_circuit(n_qubits: int, n_paulis: int, time: float, seed: int):
|
|
17
|
+
"""Return a Trotterized Pauli-evolution circuit.
|
|
18
|
+
|
|
19
|
+
A Hamiltonian is sampled as a sum of ``n_paulis`` random Pauli strings
|
|
20
|
+
(over ``I, X, Y, Z``) with random real coefficients in ``[-1, 1]``. The
|
|
21
|
+
circuit implements ``exp(-i * time * H)`` via first-order Trotterization.
|
|
22
|
+
|
|
23
|
+
Parameters
|
|
24
|
+
----------
|
|
25
|
+
n_qubits:
|
|
26
|
+
Number of qubits. Must be at least 1.
|
|
27
|
+
n_paulis:
|
|
28
|
+
Number of random Pauli terms in the Hamiltonian. Must be at least 1.
|
|
29
|
+
time:
|
|
30
|
+
Evolution time (a non-negative float).
|
|
31
|
+
seed:
|
|
32
|
+
Random seed for reproducibility.
|
|
33
|
+
|
|
34
|
+
Returns
|
|
35
|
+
-------
|
|
36
|
+
qiskit.QuantumCircuit
|
|
37
|
+
A Pauli-evolution circuit with measurements appended.
|
|
38
|
+
"""
|
|
39
|
+
if n_qubits < 1:
|
|
40
|
+
raise ValueError(f"n_qubits must be >= 1, got {n_qubits}")
|
|
41
|
+
if n_paulis < 1:
|
|
42
|
+
raise ValueError(f"n_paulis must be >= 1, got {n_paulis}")
|
|
43
|
+
if time < 0:
|
|
44
|
+
raise ValueError(f"time must be >= 0, got {time}")
|
|
45
|
+
|
|
46
|
+
import numpy as np
|
|
47
|
+
from qiskit import QuantumCircuit
|
|
48
|
+
from qiskit.circuit.library import PauliEvolutionGate
|
|
49
|
+
from qiskit.quantum_info import SparsePauliOp
|
|
50
|
+
|
|
51
|
+
rng = np.random.default_rng(seed)
|
|
52
|
+
pauli_chars = np.array(["I", "X", "Y", "Z"])
|
|
53
|
+
|
|
54
|
+
terms: list[tuple[str, float]] = []
|
|
55
|
+
for _ in range(n_paulis):
|
|
56
|
+
# Qiskit Pauli strings are little-endian: rightmost char is qubit 0.
|
|
57
|
+
label = "".join(rng.choice(pauli_chars, size=n_qubits))
|
|
58
|
+
coeff = float(rng.uniform(-1.0, 1.0))
|
|
59
|
+
terms.append((label, coeff))
|
|
60
|
+
|
|
61
|
+
hamiltonian = SparsePauliOp.from_list(terms)
|
|
62
|
+
gate = PauliEvolutionGate(hamiltonian, time=time, label=f"pauli_evo_{n_qubits}")
|
|
63
|
+
|
|
64
|
+
qc = QuantumCircuit(n_qubits, name=f"pauli_{n_qubits}_m{n_paulis}")
|
|
65
|
+
qc.append(gate, range(n_qubits))
|
|
66
|
+
qc = qc.decompose()
|
|
67
|
+
qc.measure_all()
|
|
68
|
+
return qc
|
|
69
|
+
|
|
70
|
+
|
|
71
|
+
def pauli_family(
|
|
72
|
+
n_qubits_list: Sequence[int], n_paulis_values: Sequence[int]
|
|
73
|
+
) -> list[tuple[str, "object"]]:
|
|
74
|
+
"""Return a list of ``(name, circuit)`` Pauli-evolution circuits.
|
|
75
|
+
|
|
76
|
+
For each qubit count in ``n_qubits_list`` and each term count in
|
|
77
|
+
``n_paulis_values``, a Pauli-evolution circuit is generated with a fixed
|
|
78
|
+
evolution time and a seed derived from the qubit count and term count.
|
|
79
|
+
|
|
80
|
+
Parameters
|
|
81
|
+
----------
|
|
82
|
+
n_qubits_list:
|
|
83
|
+
Iterable of qubit counts.
|
|
84
|
+
n_paulis_values:
|
|
85
|
+
Iterable of Hamiltonian term counts.
|
|
86
|
+
|
|
87
|
+
Returns
|
|
88
|
+
-------
|
|
89
|
+
list[tuple[str, qiskit.QuantumCircuit]]
|
|
90
|
+
One ``(name, circuit)`` pair per ``(n_qubits, n_paulis)`` combination.
|
|
91
|
+
"""
|
|
92
|
+
circuits: list[tuple[str, object]] = []
|
|
93
|
+
for n in n_qubits_list:
|
|
94
|
+
for m in n_paulis_values:
|
|
95
|
+
name = f"pauli_{n}_m{m}"
|
|
96
|
+
circuits.append(
|
|
97
|
+
(name, pauli_evolution_circuit(n, m, time=0.5, seed=5000 + n + m))
|
|
98
|
+
)
|
|
99
|
+
return circuits
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
"""QAOA benchmark circuits for graph-optimization problems.
|
|
2
|
+
|
|
3
|
+
Builds Quantum Approximate Optimization Algorithm (QAOA) circuits for a
|
|
4
|
+
random Maximum-Weight Independent Set (MWIS)-like combinatorial problem
|
|
5
|
+
defined on an Erdos-Renyi random graph.
|
|
6
|
+
|
|
7
|
+
The cost Hamiltonian is
|
|
8
|
+
|
|
9
|
+
H_C = sum_{(i,j) in E} ZZ_{ij} - sum_{i in V} w_i Z_i
|
|
10
|
+
|
|
11
|
+
where edges penalize two adjacent vertices both being selected and vertex
|
|
12
|
+
weights reward selecting high-weight vertices. The mixer is the standard
|
|
13
|
+
transverse-field ``sum_i X_i``.
|
|
14
|
+
"""
|
|
15
|
+
|
|
16
|
+
from __future__ import annotations
|
|
17
|
+
|
|
18
|
+
from typing import Sequence
|
|
19
|
+
|
|
20
|
+
__all__ = ["qaoa_circuit", "qaoa_family"]
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
def qaoa_circuit(n_qubits: int, p: int, graph_density: float, seed: int):
|
|
24
|
+
"""Build a QAOA circuit for a random MWIS-like problem.
|
|
25
|
+
|
|
26
|
+
A random graph on ``n_qubits`` vertices is generated with the given
|
|
27
|
+
``graph_density`` (probability of each edge). Each vertex is assigned a
|
|
28
|
+
random weight in ``[0, 1)``. The QAOA ansatz with ``p`` layers is then
|
|
29
|
+
constructed from the cost and mixer unitaries.
|
|
30
|
+
|
|
31
|
+
Parameters
|
|
32
|
+
----------
|
|
33
|
+
n_qubits:
|
|
34
|
+
Number of qubits (graph vertices). Must be at least 2.
|
|
35
|
+
p:
|
|
36
|
+
Number of QAOA layers (repetitions of cost + mixer). Must be >= 1.
|
|
37
|
+
graph_density:
|
|
38
|
+
Edge probability in ``[0, 1]`` for the random graph.
|
|
39
|
+
seed:
|
|
40
|
+
Seed for the random graph and weights.
|
|
41
|
+
|
|
42
|
+
Returns
|
|
43
|
+
-------
|
|
44
|
+
qiskit.QuantumCircuit
|
|
45
|
+
A parameterized-free QAOA circuit (parameters fixed to deterministic
|
|
46
|
+
values derived from the seed) with measurements appended.
|
|
47
|
+
"""
|
|
48
|
+
if n_qubits < 2:
|
|
49
|
+
raise ValueError(f"n_qubits must be >= 2, got {n_qubits}")
|
|
50
|
+
if p < 1:
|
|
51
|
+
raise ValueError(f"p must be >= 1, got {p}")
|
|
52
|
+
if not 0.0 <= graph_density <= 1.0:
|
|
53
|
+
raise ValueError(f"graph_density must be in [0, 1], got {graph_density}")
|
|
54
|
+
|
|
55
|
+
import numpy as np
|
|
56
|
+
from qiskit import QuantumCircuit
|
|
57
|
+
|
|
58
|
+
rng = np.random.default_rng(seed)
|
|
59
|
+
|
|
60
|
+
# Build the random graph as a list of edges.
|
|
61
|
+
edges: list[tuple[int, int]] = []
|
|
62
|
+
for i in range(n_qubits):
|
|
63
|
+
for j in range(i + 1, n_qubits):
|
|
64
|
+
if rng.random() < graph_density:
|
|
65
|
+
edges.append((i, j))
|
|
66
|
+
|
|
67
|
+
# Random vertex weights in [0, 1).
|
|
68
|
+
weights = rng.random(n_qubits)
|
|
69
|
+
|
|
70
|
+
# Deterministic but problem-dependent QAOA angles.
|
|
71
|
+
gammas = (np.pi / 4) * (np.arange(1, p + 1) / p)
|
|
72
|
+
betas = (np.pi / 4) * (np.arange(p, 0, -1) / p)
|
|
73
|
+
|
|
74
|
+
qc = QuantumCircuit(n_qubits, name=f"qaoa_{n_qubits}_p{p}")
|
|
75
|
+
|
|
76
|
+
# Initial uniform superposition.
|
|
77
|
+
qc.h(range(n_qubits))
|
|
78
|
+
|
|
79
|
+
for layer in range(p):
|
|
80
|
+
gamma = float(gammas[layer])
|
|
81
|
+
beta = float(betas[layer])
|
|
82
|
+
|
|
83
|
+
# Cost unitary: exp(-i gamma H_C).
|
|
84
|
+
# Edge terms: RZZ(2 * gamma) for each edge.
|
|
85
|
+
for i, j in edges:
|
|
86
|
+
qc.rzz(2.0 * gamma, i, j)
|
|
87
|
+
# Vertex terms: RZ(2 * w * gamma) for each vertex.
|
|
88
|
+
for i in range(n_qubits):
|
|
89
|
+
qc.rz(2.0 * float(weights[i]) * gamma, i)
|
|
90
|
+
|
|
91
|
+
# Mixer unitary: exp(-i beta sum_i X_i) -> RX(2 * beta) per qubit.
|
|
92
|
+
for i in range(n_qubits):
|
|
93
|
+
qc.rx(2.0 * beta, i)
|
|
94
|
+
|
|
95
|
+
qc.measure_all()
|
|
96
|
+
return qc
|
|
97
|
+
|
|
98
|
+
|
|
99
|
+
def qaoa_family(
|
|
100
|
+
n_qubits_list: Sequence[int], p_values: Sequence[int]
|
|
101
|
+
) -> list[tuple[str, "object"]]:
|
|
102
|
+
"""Return a list of ``(name, circuit)`` QAOA circuits.
|
|
103
|
+
|
|
104
|
+
For each qubit count in ``n_qubits_list`` and each layer count in
|
|
105
|
+
``p_values``, a QAOA circuit is generated with a fixed graph density and
|
|
106
|
+
a seed derived from the qubit count and ``p``.
|
|
107
|
+
|
|
108
|
+
Parameters
|
|
109
|
+
----------
|
|
110
|
+
n_qubits_list:
|
|
111
|
+
Iterable of qubit counts (graph sizes).
|
|
112
|
+
p_values:
|
|
113
|
+
Iterable of QAOA layer counts.
|
|
114
|
+
|
|
115
|
+
Returns
|
|
116
|
+
-------
|
|
117
|
+
list[tuple[str, qiskit.QuantumCircuit]]
|
|
118
|
+
One ``(name, circuit)`` pair per ``(n_qubits, p)`` combination.
|
|
119
|
+
"""
|
|
120
|
+
circuits: list[tuple[str, object]] = []
|
|
121
|
+
for n in n_qubits_list:
|
|
122
|
+
for p in p_values:
|
|
123
|
+
name = f"qaoa_{n}_p{p}"
|
|
124
|
+
circuits.append((name, qaoa_circuit(n, p, graph_density=0.5, seed=1000 + n + p)))
|
|
125
|
+
return circuits
|