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.
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()