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.
Files changed (31) hide show
  1. westquant_bluequbit-0.1.0/PKG-INFO +203 -0
  2. westquant_bluequbit-0.1.0/README.md +180 -0
  3. westquant_bluequbit-0.1.0/benchmarks/__init__.py +0 -0
  4. westquant_bluequbit-0.1.0/benchmarks/ghz.py +60 -0
  5. westquant_bluequbit-0.1.0/benchmarks/pauli.py +99 -0
  6. westquant_bluequbit-0.1.0/benchmarks/qaoa.py +125 -0
  7. westquant_bluequbit-0.1.0/benchmarks/qft.py +56 -0
  8. westquant_bluequbit-0.1.0/benchmarks/random.py +141 -0
  9. westquant_bluequbit-0.1.0/benchmarks/suite.py +319 -0
  10. westquant_bluequbit-0.1.0/benchmarks/vqe.py +87 -0
  11. westquant_bluequbit-0.1.0/pyproject.toml +32 -0
  12. westquant_bluequbit-0.1.0/setup.cfg +4 -0
  13. westquant_bluequbit-0.1.0/tests/test_core.py +173 -0
  14. westquant_bluequbit-0.1.0/westquant_bluequbit/__init__.py +71 -0
  15. westquant_bluequbit-0.1.0/westquant_bluequbit/cli.py +317 -0
  16. westquant_bluequbit-0.1.0/westquant_bluequbit/cost_model.py +281 -0
  17. westquant_bluequbit-0.1.0/westquant_bluequbit/device_search.py +195 -0
  18. westquant_bluequbit-0.1.0/westquant_bluequbit/executor.py +211 -0
  19. westquant_bluequbit-0.1.0/westquant_bluequbit/metrics.py +279 -0
  20. westquant_bluequbit-0.1.0/westquant_bluequbit/mps_search.py +193 -0
  21. westquant_bluequbit-0.1.0/westquant_bluequbit/pauli_path_search.py +153 -0
  22. westquant_bluequbit-0.1.0/westquant_bluequbit/provider.py +282 -0
  23. westquant_bluequbit-0.1.0/westquant_bluequbit/representation.py +224 -0
  24. westquant_bluequbit-0.1.0/westquant_bluequbit/training_data.py +304 -0
  25. westquant_bluequbit-0.1.0/westquant_bluequbit/verification.py +214 -0
  26. westquant_bluequbit-0.1.0/westquant_bluequbit.egg-info/PKG-INFO +203 -0
  27. westquant_bluequbit-0.1.0/westquant_bluequbit.egg-info/SOURCES.txt +29 -0
  28. westquant_bluequbit-0.1.0/westquant_bluequbit.egg-info/dependency_links.txt +1 -0
  29. westquant_bluequbit-0.1.0/westquant_bluequbit.egg-info/entry_points.txt +2 -0
  30. westquant_bluequbit-0.1.0/westquant_bluequbit.egg-info/requires.txt +15 -0
  31. 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