vqe-pennylane 0.2.2__py3-none-any.whl
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.
- qpe/__init__.py +77 -0
- qpe/__main__.py +233 -0
- qpe/core.py +317 -0
- qpe/hamiltonian.py +100 -0
- qpe/io_utils.py +132 -0
- qpe/noise.py +47 -0
- qpe/visualize.py +212 -0
- vqe/__init__.py +118 -0
- vqe/__main__.py +318 -0
- vqe/ansatz.py +420 -0
- vqe/core.py +907 -0
- vqe/engine.py +390 -0
- vqe/hamiltonian.py +260 -0
- vqe/io_utils.py +265 -0
- vqe/optimizer.py +58 -0
- vqe/ssvqe.py +271 -0
- vqe/visualize.py +308 -0
- vqe_pennylane-0.2.2.dist-info/METADATA +239 -0
- vqe_pennylane-0.2.2.dist-info/RECORD +28 -0
- vqe_pennylane-0.2.2.dist-info/WHEEL +5 -0
- vqe_pennylane-0.2.2.dist-info/entry_points.txt +3 -0
- vqe_pennylane-0.2.2.dist-info/licenses/LICENSE +21 -0
- vqe_pennylane-0.2.2.dist-info/top_level.txt +3 -0
- vqe_qpe_common/__init__.py +67 -0
- vqe_qpe_common/geometry.py +52 -0
- vqe_qpe_common/hamiltonian.py +58 -0
- vqe_qpe_common/molecules.py +107 -0
- vqe_qpe_common/plotting.py +167 -0
vqe/__main__.py
ADDED
|
@@ -0,0 +1,318 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Command-line interface for the vqe package.
|
|
3
|
+
|
|
4
|
+
This file powers:
|
|
5
|
+
|
|
6
|
+
$ python -m vqe ...
|
|
7
|
+
|
|
8
|
+
It supports:
|
|
9
|
+
- Standard VQE
|
|
10
|
+
- Noisy vs noiseless comparison
|
|
11
|
+
- Noise sweeps
|
|
12
|
+
- Optimizer comparison
|
|
13
|
+
- Ansatz comparison
|
|
14
|
+
- Multi-seed noise averaging
|
|
15
|
+
- Geometry scans (bond length, bond angle)
|
|
16
|
+
- Fermion-to-qubit mapping comparison
|
|
17
|
+
- SSVQE for excited states
|
|
18
|
+
|
|
19
|
+
All CLI modes dispatch into vqe.core.* or vqe.ssvqe.run_ssvqe.
|
|
20
|
+
"""
|
|
21
|
+
|
|
22
|
+
from __future__ import annotations
|
|
23
|
+
import argparse
|
|
24
|
+
import numpy as np
|
|
25
|
+
|
|
26
|
+
from vqe import (
|
|
27
|
+
run_vqe,
|
|
28
|
+
run_vqe_noise_sweep,
|
|
29
|
+
run_vqe_optimizer_comparison,
|
|
30
|
+
run_vqe_ansatz_comparison,
|
|
31
|
+
run_vqe_multi_seed_noise,
|
|
32
|
+
run_vqe_geometry_scan,
|
|
33
|
+
run_vqe_mapping_comparison,
|
|
34
|
+
run_ssvqe,
|
|
35
|
+
plot_convergence,
|
|
36
|
+
)
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
# ================================================================
|
|
40
|
+
# SPECIAL MODES DISPATCHER
|
|
41
|
+
# ================================================================
|
|
42
|
+
def handle_special_modes(args):
|
|
43
|
+
"""
|
|
44
|
+
Dispatch CLI options for all extended experiment modes.
|
|
45
|
+
Returns True if a special mode handled the execution.
|
|
46
|
+
"""
|
|
47
|
+
|
|
48
|
+
# ---------------------------
|
|
49
|
+
# SSVQE
|
|
50
|
+
# ---------------------------
|
|
51
|
+
if args.ssvqe:
|
|
52
|
+
print("🔹 Running SSVQE (excited states)...")
|
|
53
|
+
res = run_ssvqe(
|
|
54
|
+
molecule=args.molecule,
|
|
55
|
+
ansatz_name=args.ansatz,
|
|
56
|
+
optimizer_name=args.optimizer,
|
|
57
|
+
steps=args.steps,
|
|
58
|
+
stepsize=args.stepsize,
|
|
59
|
+
penalty_weight=args.penalty_weight,
|
|
60
|
+
seed=args.seed,
|
|
61
|
+
noisy=args.noisy,
|
|
62
|
+
depolarizing_prob=args.depolarizing_prob,
|
|
63
|
+
amplitude_damping_prob=args.amplitude_damping_prob,
|
|
64
|
+
force=args.force,
|
|
65
|
+
)
|
|
66
|
+
print("Final energies per state:")
|
|
67
|
+
for i, Es in enumerate(res["energies_per_state"]):
|
|
68
|
+
print(f" E{i}: {Es[-1]:.8f} Ha")
|
|
69
|
+
return True
|
|
70
|
+
|
|
71
|
+
# ---------------------------
|
|
72
|
+
# Mapping comparison
|
|
73
|
+
# ---------------------------
|
|
74
|
+
if args.mapping_comparison:
|
|
75
|
+
run_vqe_mapping_comparison(
|
|
76
|
+
molecule=args.molecule,
|
|
77
|
+
ansatz_name=args.ansatz,
|
|
78
|
+
optimizer_name=args.optimizer,
|
|
79
|
+
steps=args.steps,
|
|
80
|
+
stepsize=args.stepsize,
|
|
81
|
+
seed=args.seed,
|
|
82
|
+
force=args.force,
|
|
83
|
+
)
|
|
84
|
+
return True
|
|
85
|
+
|
|
86
|
+
# ---------------------------
|
|
87
|
+
# Multi-seed noise sweep
|
|
88
|
+
# ---------------------------
|
|
89
|
+
if args.multi_seed_noise:
|
|
90
|
+
run_vqe_multi_seed_noise(
|
|
91
|
+
molecule=args.molecule,
|
|
92
|
+
ansatz_name=args.ansatz,
|
|
93
|
+
optimizer_name=args.optimizer,
|
|
94
|
+
steps=args.steps,
|
|
95
|
+
stepsize=args.stepsize,
|
|
96
|
+
noise_type=args.noise_type,
|
|
97
|
+
force=args.force,
|
|
98
|
+
)
|
|
99
|
+
return True
|
|
100
|
+
|
|
101
|
+
# ---------------------------
|
|
102
|
+
# Geometry scan
|
|
103
|
+
# ---------------------------
|
|
104
|
+
if args.scan_geometry:
|
|
105
|
+
start, end, num = args.range
|
|
106
|
+
values = np.linspace(start, end, int(num))
|
|
107
|
+
run_vqe_geometry_scan(
|
|
108
|
+
molecule=args.scan_geometry,
|
|
109
|
+
param_name=args.param_name,
|
|
110
|
+
param_values=values,
|
|
111
|
+
ansatz_name=args.ansatz,
|
|
112
|
+
optimizer_name=args.optimizer,
|
|
113
|
+
steps=args.steps,
|
|
114
|
+
stepsize=args.stepsize,
|
|
115
|
+
force=args.force,
|
|
116
|
+
)
|
|
117
|
+
return True
|
|
118
|
+
|
|
119
|
+
# ---------------------------
|
|
120
|
+
# Optimizer comparison
|
|
121
|
+
# ---------------------------
|
|
122
|
+
if args.compare_optimizers:
|
|
123
|
+
run_vqe_optimizer_comparison(
|
|
124
|
+
molecule=args.molecule,
|
|
125
|
+
ansatz_name=args.ansatz,
|
|
126
|
+
optimizers=args.compare_optimizers,
|
|
127
|
+
steps=args.steps,
|
|
128
|
+
stepsize=args.stepsize,
|
|
129
|
+
noisy=args.noisy,
|
|
130
|
+
depolarizing_prob=args.depolarizing_prob,
|
|
131
|
+
amplitude_damping_prob=args.amplitude_damping_prob,
|
|
132
|
+
)
|
|
133
|
+
return True
|
|
134
|
+
|
|
135
|
+
# ---------------------------
|
|
136
|
+
# Ansatz comparison
|
|
137
|
+
# ---------------------------
|
|
138
|
+
if args.compare_ansatzes:
|
|
139
|
+
run_vqe_ansatz_comparison(
|
|
140
|
+
molecule=args.molecule,
|
|
141
|
+
optimizer_name=args.optimizer,
|
|
142
|
+
ansatzes=args.compare_ansatzes,
|
|
143
|
+
steps=args.steps,
|
|
144
|
+
stepsize=args.stepsize,
|
|
145
|
+
noisy=args.noisy,
|
|
146
|
+
depolarizing_prob=args.depolarizing_prob,
|
|
147
|
+
amplitude_damping_prob=args.amplitude_damping_prob,
|
|
148
|
+
)
|
|
149
|
+
return True
|
|
150
|
+
|
|
151
|
+
# ---------------------------
|
|
152
|
+
# Noise sweep
|
|
153
|
+
# ---------------------------
|
|
154
|
+
if args.noise_sweep:
|
|
155
|
+
run_vqe_noise_sweep(
|
|
156
|
+
molecule=args.molecule,
|
|
157
|
+
ansatz_name=args.ansatz,
|
|
158
|
+
optimizer_name=args.optimizer,
|
|
159
|
+
steps=args.steps,
|
|
160
|
+
stepsize=args.stepsize,
|
|
161
|
+
force=args.force,
|
|
162
|
+
)
|
|
163
|
+
return True
|
|
164
|
+
|
|
165
|
+
# ---------------------------
|
|
166
|
+
# Compare noisy vs noiseless
|
|
167
|
+
# ---------------------------
|
|
168
|
+
if args.compare_noise:
|
|
169
|
+
print(f"🔹 Comparing noisy vs noiseless VQE for {args.molecule}")
|
|
170
|
+
res_noiseless = run_vqe(
|
|
171
|
+
args.molecule,
|
|
172
|
+
args.steps,
|
|
173
|
+
stepsize=args.stepsize,
|
|
174
|
+
ansatz_name=args.ansatz,
|
|
175
|
+
optimizer_name=args.optimizer,
|
|
176
|
+
noisy=False,
|
|
177
|
+
)
|
|
178
|
+
res_noisy = run_vqe(
|
|
179
|
+
args.molecule,
|
|
180
|
+
args.steps,
|
|
181
|
+
stepsize=args.stepsize,
|
|
182
|
+
ansatz_name=args.ansatz,
|
|
183
|
+
optimizer_name=args.optimizer,
|
|
184
|
+
noisy=True,
|
|
185
|
+
depolarizing_prob=args.depolarizing_prob,
|
|
186
|
+
amplitude_damping_prob=args.amplitude_damping_prob,
|
|
187
|
+
)
|
|
188
|
+
plot_convergence(
|
|
189
|
+
res_noiseless["energies"],
|
|
190
|
+
args.molecule,
|
|
191
|
+
energies_noisy=res_noisy["energies"],
|
|
192
|
+
optimizer=args.optimizer,
|
|
193
|
+
ansatz=args.ansatz,
|
|
194
|
+
dep_prob=args.depolarizing_prob,
|
|
195
|
+
amp_prob=args.amplitude_damping_prob,
|
|
196
|
+
)
|
|
197
|
+
return True
|
|
198
|
+
|
|
199
|
+
return False
|
|
200
|
+
|
|
201
|
+
|
|
202
|
+
# ================================================================
|
|
203
|
+
# MAIN ENTRYPOINT
|
|
204
|
+
# ================================================================
|
|
205
|
+
def main():
|
|
206
|
+
parser = argparse.ArgumentParser(
|
|
207
|
+
prog="vqe",
|
|
208
|
+
description="VQE/SSVQE Simulation Toolkit",
|
|
209
|
+
formatter_class=argparse.RawTextHelpFormatter,
|
|
210
|
+
)
|
|
211
|
+
|
|
212
|
+
# ------------------------------------------------------------------
|
|
213
|
+
# Core parameters
|
|
214
|
+
# ------------------------------------------------------------------
|
|
215
|
+
core = parser.add_argument_group("Core")
|
|
216
|
+
core.add_argument("-m", "--molecule", type=str, default="H2",
|
|
217
|
+
help="Molecule (H2, LiH, H2O, H3+)")
|
|
218
|
+
core.add_argument("-a", "--ansatz", type=str, default="UCCSD",
|
|
219
|
+
help="Ansatz name")
|
|
220
|
+
core.add_argument("-o", "--optimizer", type=str, default="Adam",
|
|
221
|
+
help="Optimizer name")
|
|
222
|
+
core.add_argument("-map", "--mapping", type=str,
|
|
223
|
+
default="jordan_wigner",
|
|
224
|
+
choices=["jordan_wigner", "bravyi_kitaev", "parity"],
|
|
225
|
+
help="Fermion-to-qubit mapping")
|
|
226
|
+
core.add_argument("-s", "--steps", type=int, default=50,
|
|
227
|
+
help="Number of optimization iterations")
|
|
228
|
+
core.add_argument("-lr", "--stepsize", type=float, default=0.2,
|
|
229
|
+
help="Optimizer step size")
|
|
230
|
+
|
|
231
|
+
# ------------------------------------------------------------------
|
|
232
|
+
# Noise controls
|
|
233
|
+
# ------------------------------------------------------------------
|
|
234
|
+
noise = parser.add_argument_group("Noise")
|
|
235
|
+
noise.add_argument("--noisy", action="store_true", help="Enable noise")
|
|
236
|
+
noise.add_argument("--depolarizing-prob", type=float, default=0.0)
|
|
237
|
+
noise.add_argument("--amplitude-damping-prob", type=float, default=0.0)
|
|
238
|
+
|
|
239
|
+
# ------------------------------------------------------------------
|
|
240
|
+
# Experiment modes
|
|
241
|
+
# ------------------------------------------------------------------
|
|
242
|
+
exp = parser.add_argument_group("Modes")
|
|
243
|
+
exp.add_argument("--compare-noise", action="store_true")
|
|
244
|
+
exp.add_argument("--noise-sweep", action="store_true")
|
|
245
|
+
exp.add_argument("--compare-optimizers", nargs="+")
|
|
246
|
+
exp.add_argument("--compare-ansatzes", nargs="+")
|
|
247
|
+
exp.add_argument("--multi-seed-noise", action="store_true")
|
|
248
|
+
exp.add_argument("--noise-type", type=str,
|
|
249
|
+
choices=["depolarizing", "amplitude", "combined"],
|
|
250
|
+
default="depolarizing")
|
|
251
|
+
|
|
252
|
+
exp.add_argument("--mapping-comparison", action="store_true")
|
|
253
|
+
|
|
254
|
+
# ------------------------------------------------------------------
|
|
255
|
+
# Geometry & SSVQE
|
|
256
|
+
# ------------------------------------------------------------------
|
|
257
|
+
geom = parser.add_argument_group("Geometry / SSVQE")
|
|
258
|
+
geom.add_argument("--scan-geometry", type=str,
|
|
259
|
+
help="Parametric geometry: H2_BOND, LiH_BOND, H2O_ANGLE")
|
|
260
|
+
geom.add_argument("--range", nargs=3, type=float,
|
|
261
|
+
metavar=("START", "END", "NUM"),
|
|
262
|
+
help="Geometry scan range")
|
|
263
|
+
geom.add_argument("--param-name", type=str, default="param")
|
|
264
|
+
geom.add_argument("--ssvqe", action="store_true")
|
|
265
|
+
geom.add_argument("--penalty-weight", type=float, default=10.0)
|
|
266
|
+
|
|
267
|
+
# ------------------------------------------------------------------
|
|
268
|
+
# Misc
|
|
269
|
+
# ------------------------------------------------------------------
|
|
270
|
+
misc = parser.add_argument_group("Misc")
|
|
271
|
+
misc.add_argument("--seed", type=int, default=0)
|
|
272
|
+
misc.add_argument("--force", action="store_true", help="Ignore cached results")
|
|
273
|
+
misc.add_argument("--plot", action="store_true", help="Plot convergence")
|
|
274
|
+
|
|
275
|
+
args = parser.parse_args()
|
|
276
|
+
|
|
277
|
+
# ------------------------------------------------------------------
|
|
278
|
+
# Summary banner
|
|
279
|
+
# ------------------------------------------------------------------
|
|
280
|
+
print("\n🧮 VQE Simulation")
|
|
281
|
+
print(f"• Molecule: {args.molecule}")
|
|
282
|
+
print(f"• Ansatz: {args.ansatz}")
|
|
283
|
+
print(f"• Optimizer: {args.optimizer}")
|
|
284
|
+
print(f"• Mapping: {args.mapping}")
|
|
285
|
+
print(f"• Steps: {args.steps} | Stepsize: {args.stepsize}")
|
|
286
|
+
print(f"• Noise: {'ON' if args.noisy else 'OFF'}")
|
|
287
|
+
print(f"• Seed: {args.seed}")
|
|
288
|
+
print()
|
|
289
|
+
|
|
290
|
+
# Try special modes first
|
|
291
|
+
if handle_special_modes(args):
|
|
292
|
+
return
|
|
293
|
+
|
|
294
|
+
# ------------------------------------------------------------------
|
|
295
|
+
# Default VQE run
|
|
296
|
+
# ------------------------------------------------------------------
|
|
297
|
+
print(f"🔹 Running standard VQE for {args.molecule}")
|
|
298
|
+
result = run_vqe(
|
|
299
|
+
molecule=args.molecule,
|
|
300
|
+
n_steps=args.steps,
|
|
301
|
+
stepsize=args.stepsize,
|
|
302
|
+
ansatz_name=args.ansatz,
|
|
303
|
+
optimizer_name=args.optimizer,
|
|
304
|
+
mapping=args.mapping,
|
|
305
|
+
noisy=args.noisy,
|
|
306
|
+
depolarizing_prob=args.depolarizing_prob,
|
|
307
|
+
amplitude_damping_prob=args.amplitude_damping_prob,
|
|
308
|
+
force=args.force,
|
|
309
|
+
plot=args.plot,
|
|
310
|
+
)
|
|
311
|
+
|
|
312
|
+
print("\nFinal result:")
|
|
313
|
+
print({k: (float(v) if hasattr(v, "item") else v)
|
|
314
|
+
for k, v in result.items()})
|
|
315
|
+
|
|
316
|
+
|
|
317
|
+
if __name__ == "__main__":
|
|
318
|
+
main()
|