qmlkit 0.1.0__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.
Files changed (83) hide show
  1. qmlkit/__init__.py +495 -0
  2. qmlkit/_aliases.py +135 -0
  3. qmlkit/algorithms/__init__.py +82 -0
  4. qmlkit/algorithms/adapt.py +297 -0
  5. qmlkit/algorithms/autoencoder.py +206 -0
  6. qmlkit/algorithms/chemistry.py +222 -0
  7. qmlkit/algorithms/clustering.py +149 -0
  8. qmlkit/algorithms/hamiltonians.py +143 -0
  9. qmlkit/algorithms/molecule.py +442 -0
  10. qmlkit/algorithms/qaoa.py +208 -0
  11. qmlkit/algorithms/rl.py +198 -0
  12. qmlkit/algorithms/vqe.py +198 -0
  13. qmlkit/ansatz/__init__.py +68 -0
  14. qmlkit/ansatz/blocks.py +348 -0
  15. qmlkit/ansatz/library.py +570 -0
  16. qmlkit/ansatz/reupload.py +168 -0
  17. qmlkit/baselines.py +604 -0
  18. qmlkit/budget.py +234 -0
  19. qmlkit/core/__init__.py +1 -0
  20. qmlkit/core/backends/__init__.py +22 -0
  21. qmlkit/core/backends/_sampling.py +43 -0
  22. qmlkit/core/backends/base.py +256 -0
  23. qmlkit/core/backends/cirq_backend.py +110 -0
  24. qmlkit/core/backends/cirq_density_backend.py +71 -0
  25. qmlkit/core/backends/noisy.py +86 -0
  26. qmlkit/core/backends/numpy_backend.py +276 -0
  27. qmlkit/core/backends/qiskit_aer_backend.py +79 -0
  28. qmlkit/core/backends/qiskit_backend.py +104 -0
  29. qmlkit/core/backends/registry.py +210 -0
  30. qmlkit/core/backends/spinqit_backend.py +233 -0
  31. qmlkit/core/backends/torch_backend.py +185 -0
  32. qmlkit/core/builder.py +189 -0
  33. qmlkit/core/execute.py +193 -0
  34. qmlkit/core/gates.py +243 -0
  35. qmlkit/core/ir.py +320 -0
  36. qmlkit/core/observables.py +269 -0
  37. qmlkit/datasets.py +178 -0
  38. qmlkit/diagnostics.py +719 -0
  39. qmlkit/draw.py +177 -0
  40. qmlkit/encoding/__init__.py +63 -0
  41. qmlkit/encoding/amplitude.py +178 -0
  42. qmlkit/encoding/angle.py +61 -0
  43. qmlkit/encoding/feature_maps.py +353 -0
  44. qmlkit/encoding/hamiltonian.py +206 -0
  45. qmlkit/encoding/pipeline.py +198 -0
  46. qmlkit/encoding/scaling.py +139 -0
  47. qmlkit/evaluate.py +686 -0
  48. qmlkit/fourier.py +124 -0
  49. qmlkit/generative.py +406 -0
  50. qmlkit/gradients/__init__.py +61 -0
  51. qmlkit/gradients/adjoint.py +138 -0
  52. qmlkit/gradients/batch.py +275 -0
  53. qmlkit/gradients/dispatch.py +247 -0
  54. qmlkit/gradients/hadamard.py +108 -0
  55. qmlkit/gradients/parameter_shift.py +142 -0
  56. qmlkit/gradients/rules.py +151 -0
  57. qmlkit/gradients/spsa.py +134 -0
  58. qmlkit/imbalance.py +335 -0
  59. qmlkit/info.py +153 -0
  60. qmlkit/interop.py +778 -0
  61. qmlkit/kernels/__init__.py +69 -0
  62. qmlkit/kernels/estimators.py +206 -0
  63. qmlkit/kernels/matrix.py +439 -0
  64. qmlkit/kernels/models.py +315 -0
  65. qmlkit/metrics.py +394 -0
  66. qmlkit/nn/__init__.py +18 -0
  67. qmlkit/nn/advanced.py +254 -0
  68. qmlkit/nn/layer.py +343 -0
  69. qmlkit/nn/losses.py +124 -0
  70. qmlkit/nn/models.py +245 -0
  71. qmlkit/optim.py +306 -0
  72. qmlkit/provenance.py +271 -0
  73. qmlkit/py.typed +0 -0
  74. qmlkit/search.py +561 -0
  75. qmlkit/shadows.py +117 -0
  76. qmlkit/utils/__init__.py +19 -0
  77. qmlkit/utils/errors.py +130 -0
  78. qmlkit/utils/shots.py +55 -0
  79. qmlkit-0.1.0.dist-info/METADATA +745 -0
  80. qmlkit-0.1.0.dist-info/RECORD +83 -0
  81. qmlkit-0.1.0.dist-info/WHEEL +4 -0
  82. qmlkit-0.1.0.dist-info/licenses/LICENSE +202 -0
  83. qmlkit-0.1.0.dist-info/licenses/NOTICE +4 -0
qmlkit/__init__.py ADDED
@@ -0,0 +1,495 @@
1
+ """qmlkit — a backend-agnostic quantum machine learning library.
2
+
3
+ The same circuit runs on SpinQit, Qiskit, Cirq or the built-in exact NumPy
4
+ reference. Simulator-only for the 0.x line; expectations are exact unless you
5
+ ask for shots:
6
+
7
+ >>> import qmlkit as qk
8
+ >>> import numpy as np
9
+ >>> spec = qk.angle_encode([0.7])
10
+ >>> round(qk.expectation(spec, qk.Z(0)), 12) == round(float(np.cos(0.7)), 12)
11
+ True
12
+ """
13
+
14
+ from __future__ import annotations
15
+
16
+ __version__ = "0.1.0"
17
+
18
+ from qmlkit import (
19
+ algorithms,
20
+ datasets,
21
+ evaluate,
22
+ fourier,
23
+ generative,
24
+ imbalance,
25
+ info,
26
+ kernels,
27
+ metrics,
28
+ optim,
29
+ shadows,
30
+ )
31
+ from qmlkit.ansatz import (
32
+ Ansatz,
33
+ Custom,
34
+ EncodingLayer,
35
+ EntanglerLayer,
36
+ ParametricEntangler,
37
+ PoolLayer,
38
+ RotationLayer,
39
+ basic_entangler,
40
+ conv_block,
41
+ get_ansatz,
42
+ hardware_efficient,
43
+ list_ansatze,
44
+ list_conv_filters,
45
+ mps_ansatz,
46
+ qaoa_ansatz,
47
+ qcnn_ansatz,
48
+ random_layers,
49
+ register_ansatz,
50
+ register_conv_filter,
51
+ repeat,
52
+ reupload,
53
+ share,
54
+ simplified_two_design,
55
+ strongly_entangling,
56
+ tree_tensor_network,
57
+ two_local,
58
+ )
59
+ from qmlkit.baselines import (
60
+ BaselineRow,
61
+ BaselineSpec,
62
+ BaselineTable,
63
+ baseline,
64
+ get_baseline,
65
+ list_baselines,
66
+ register_baseline,
67
+ )
68
+ from qmlkit.budget import Plan, Reduction, plan
69
+ from qmlkit.core.backends.base import Backend, BackendNotAvailable
70
+ from qmlkit.core.backends.numpy_backend import NumpyBackend
71
+ from qmlkit.core.backends.registry import (
72
+ available_backends,
73
+ backend_report,
74
+ default_backend,
75
+ get_backend,
76
+ is_available,
77
+ list_backends,
78
+ register_backend,
79
+ set_default_backend,
80
+ )
81
+ from qmlkit.core.builder import QCircuit, entangler_pairs
82
+ from qmlkit.core.execute import (
83
+ expectation,
84
+ expectation_batch,
85
+ expectation_over,
86
+ expval,
87
+ probabilities,
88
+ run_counts,
89
+ statevector,
90
+ )
91
+ from qmlkit.core.gates import GateDef, get_gate, list_gates, register_gate
92
+ from qmlkit.core.ir import CircuitSpec, Op, ParamRef, Slot
93
+ from qmlkit.core.observables import ZZ, I, PauliString, PauliSum, X, Y, Z
94
+ from qmlkit.diagnostics import Finding, Report, diagnose
95
+ from qmlkit.draw import draw, specs
96
+ from qmlkit.encoding import (
97
+ AngleFeatureMap,
98
+ AngleScaler,
99
+ DataReuploadEncoder,
100
+ FeatureMap,
101
+ FeaturePipeline,
102
+ PauliFeatureMap,
103
+ PCAReducer,
104
+ SklearnCompatible,
105
+ ZFeatureMap,
106
+ ZZFeatureMap,
107
+ amplitude_encode,
108
+ angle_encode,
109
+ basis_encode,
110
+ basis_index,
111
+ hamiltonian_encode,
112
+ n_qubits_for,
113
+ reduce_to_qubits,
114
+ to_angle_range,
115
+ )
116
+ from qmlkit.gradients import (
117
+ SPSASchedule,
118
+ adjoint_grad,
119
+ choose_method,
120
+ grad,
121
+ gradient_cost,
122
+ hadamard_grad,
123
+ hessian,
124
+ list_gradient_methods,
125
+ minimize_spsa,
126
+ register_gradient,
127
+ spsa_grad,
128
+ supports_adjoint,
129
+ )
130
+ from qmlkit.gradients.batch import (
131
+ adjoint_grad_batch,
132
+ grad_batch,
133
+ param_shift_grad_batch,
134
+ )
135
+ from qmlkit.gradients.parameter_shift import (
136
+ finite_diff_grad,
137
+ grad_circuit_cost,
138
+ param_shift_grad,
139
+ param_shift_grad_circuit,
140
+ )
141
+ from qmlkit.gradients.rules import (
142
+ ShiftRule,
143
+ four_term_rule,
144
+ general_shift_rule,
145
+ rule_for_gate,
146
+ two_term_rule,
147
+ )
148
+ from qmlkit.info import (
149
+ bloch_vector,
150
+ concurrence,
151
+ mutual_info,
152
+ purity,
153
+ reduced_dm,
154
+ state_fidelity,
155
+ vn_entropy,
156
+ )
157
+ from qmlkit.interop import (
158
+ UnsupportedGate,
159
+ from_cirq,
160
+ from_pennylane,
161
+ from_qasm,
162
+ from_qiskit,
163
+ get_importer,
164
+ list_importers,
165
+ register_importer,
166
+ )
167
+ from qmlkit.kernels import (
168
+ QSVC,
169
+ QSVR,
170
+ NearestFidelityClassifier,
171
+ QuantumKernel,
172
+ TrainableKernel,
173
+ closest_psd_matrix,
174
+ concentration_report,
175
+ displace_matrix,
176
+ fidelity_kernel,
177
+ flip_matrix,
178
+ geometric_difference,
179
+ hadamard_test,
180
+ is_psd,
181
+ kernel_matrix,
182
+ min_eigenvalue,
183
+ projected_kernel_matrix,
184
+ swap_test_kernel,
185
+ target_alignment,
186
+ threshold_matrix,
187
+ )
188
+ from qmlkit.metrics import (
189
+ AnsatzReport,
190
+ barren_plateau_scan,
191
+ compare_ansatze,
192
+ effective_dimension,
193
+ entangling_capability,
194
+ expressibility,
195
+ generalization_bound,
196
+ gradient_variance,
197
+ meyer_wallach,
198
+ )
199
+ from qmlkit.optim import (
200
+ metric_tensor,
201
+ minimize_qng,
202
+ minimize_rotosolve,
203
+ quantum_fisher_information,
204
+ rotosolve_step,
205
+ )
206
+ from qmlkit.provenance import Fingerprint, fingerprint, selfcheck
207
+ from qmlkit.search import (
208
+ AXES,
209
+ SearchResult,
210
+ SearchRow,
211
+ list_feature_maps,
212
+ register_feature_map,
213
+ search,
214
+ )
215
+ from qmlkit.utils.shots import (
216
+ p0_from_z,
217
+ shots_for_precision,
218
+ standard_error,
219
+ variance,
220
+ z_from_p0,
221
+ )
222
+
223
+ __all__ = [
224
+ "__version__",
225
+ # core
226
+ "CircuitSpec",
227
+ "Op",
228
+ "ParamRef",
229
+ "Slot",
230
+ "QCircuit",
231
+ "entangler_pairs",
232
+ # gates
233
+ "GateDef",
234
+ "get_gate",
235
+ "list_gates",
236
+ "register_gate",
237
+ # observables
238
+ "PauliString",
239
+ "PauliSum",
240
+ "I",
241
+ "X",
242
+ "Y",
243
+ "Z",
244
+ "ZZ",
245
+ # backends
246
+ "Backend",
247
+ "BackendNotAvailable",
248
+ "NumpyBackend",
249
+ "get_backend",
250
+ "default_backend",
251
+ "set_default_backend",
252
+ "register_backend",
253
+ "list_backends",
254
+ "available_backends",
255
+ "is_available",
256
+ "backend_report",
257
+ # execution
258
+ "statevector",
259
+ "run_counts",
260
+ "probabilities",
261
+ "expectation",
262
+ "expectation_batch",
263
+ "expectation_over",
264
+ # encoding
265
+ "angle_encode",
266
+ "basis_encode",
267
+ "basis_index",
268
+ "n_qubits_for",
269
+ "amplitude_encode",
270
+ "hamiltonian_encode",
271
+ "FeatureMap",
272
+ "PauliFeatureMap",
273
+ "ZFeatureMap",
274
+ "ZZFeatureMap",
275
+ "AngleFeatureMap",
276
+ "DataReuploadEncoder",
277
+ "to_angle_range",
278
+ "AngleScaler",
279
+ "FeaturePipeline",
280
+ "SklearnCompatible",
281
+ "reduce_to_qubits",
282
+ "PCAReducer",
283
+ # gradients
284
+ "ShiftRule",
285
+ "two_term_rule",
286
+ "four_term_rule",
287
+ "general_shift_rule",
288
+ "rule_for_gate",
289
+ "param_shift_grad",
290
+ "param_shift_grad_circuit",
291
+ "grad_circuit_cost",
292
+ "finite_diff_grad",
293
+ "grad_batch",
294
+ "adjoint_grad_batch",
295
+ "param_shift_grad_batch",
296
+ # submodules
297
+ "kernels",
298
+ "metrics",
299
+ "optim",
300
+ "fourier",
301
+ "info",
302
+ "algorithms",
303
+ "datasets",
304
+ "shadows",
305
+ "generative",
306
+ "evaluate",
307
+ "imbalance",
308
+ # baselines
309
+ "baseline",
310
+ "BaselineTable",
311
+ "BaselineRow",
312
+ "BaselineSpec",
313
+ "register_baseline",
314
+ "list_baselines",
315
+ "get_baseline",
316
+ # search
317
+ "search",
318
+ "SearchResult",
319
+ "SearchRow",
320
+ "AXES",
321
+ "register_feature_map",
322
+ "list_feature_maps",
323
+ # interop
324
+ "from_qasm",
325
+ "from_qiskit",
326
+ "from_pennylane",
327
+ "from_cirq",
328
+ "register_importer",
329
+ "list_importers",
330
+ "get_importer",
331
+ "UnsupportedGate",
332
+ # budget and provenance
333
+ "plan",
334
+ "Plan",
335
+ "Reduction",
336
+ "fingerprint",
337
+ "Fingerprint",
338
+ "selfcheck",
339
+ # kernels
340
+ "QuantumKernel",
341
+ "fidelity_kernel",
342
+ "swap_test_kernel",
343
+ "hadamard_test",
344
+ "kernel_matrix",
345
+ "target_alignment",
346
+ "is_psd",
347
+ "closest_psd_matrix",
348
+ "threshold_matrix",
349
+ "displace_matrix",
350
+ "flip_matrix",
351
+ "min_eigenvalue",
352
+ "projected_kernel_matrix",
353
+ "concentration_report",
354
+ "geometric_difference",
355
+ "QSVC",
356
+ "QSVR",
357
+ "NearestFidelityClassifier",
358
+ "TrainableKernel",
359
+ # metrics
360
+ "expressibility",
361
+ "meyer_wallach",
362
+ "entangling_capability",
363
+ "gradient_variance",
364
+ "barren_plateau_scan",
365
+ "effective_dimension",
366
+ "generalization_bound",
367
+ "AnsatzReport",
368
+ "compare_ansatze",
369
+ # optimisers
370
+ "minimize_rotosolve",
371
+ "rotosolve_step",
372
+ "metric_tensor",
373
+ "quantum_fisher_information",
374
+ "minimize_qng",
375
+ # quantum information
376
+ "reduced_dm",
377
+ "purity",
378
+ "vn_entropy",
379
+ "mutual_info",
380
+ "state_fidelity",
381
+ "concurrence",
382
+ "bloch_vector",
383
+ # diagnostics
384
+ "diagnose",
385
+ "Finding",
386
+ "Report",
387
+ # visualisation
388
+ "draw",
389
+ "specs",
390
+ "expval",
391
+ # ansatz
392
+ "Ansatz",
393
+ "register_ansatz",
394
+ "get_ansatz",
395
+ "list_ansatze",
396
+ "RotationLayer",
397
+ "EntanglerLayer",
398
+ "ParametricEntangler",
399
+ "PoolLayer",
400
+ "Custom",
401
+ "EncodingLayer",
402
+ "reupload",
403
+ "repeat",
404
+ "share",
405
+ "hardware_efficient",
406
+ "strongly_entangling",
407
+ "simplified_two_design",
408
+ "tree_tensor_network",
409
+ "mps_ansatz",
410
+ "qcnn_ansatz",
411
+ "qaoa_ansatz",
412
+ "conv_block",
413
+ "list_conv_filters",
414
+ "register_conv_filter",
415
+ "basic_entangler",
416
+ "two_local",
417
+ "random_layers",
418
+ # gradient dispatch
419
+ "grad",
420
+ "choose_method",
421
+ "register_gradient",
422
+ "list_gradient_methods",
423
+ "adjoint_grad",
424
+ "hadamard_grad",
425
+ "hessian",
426
+ "gradient_cost",
427
+ "supports_adjoint",
428
+ "spsa_grad",
429
+ "minimize_spsa",
430
+ "SPSASchedule",
431
+ # shots
432
+ "standard_error",
433
+ "variance",
434
+ "shots_for_precision",
435
+ "p0_from_z",
436
+ "z_from_p0",
437
+ ]
438
+
439
+
440
+ #: Names served by :mod:`qmlkit.nn`, resolved on demand so that importing qmlkit
441
+ #: never requires torch. Deliberately outside ``__all__``, which keeps
442
+ #: ``from qmlkit import *`` torch-free.
443
+ _TORCH_EXPORTS = (
444
+ "QuantumLayer",
445
+ "QuantumFunction",
446
+ "VQC",
447
+ "VQRegressor",
448
+ "HybridModel",
449
+ "QCNNLayer",
450
+ "MPSLayer",
451
+ "QLSTMCell",
452
+ "QLSTM",
453
+ "DressedQuantumNet",
454
+ "nn",
455
+ )
456
+
457
+
458
+ def __getattr__(name: str) -> object:
459
+ """Resolve the torch bridge lazily, and answer a wrong name with the right one.
460
+
461
+ A missing attribute is where most first attempts at an unfamiliar library land,
462
+ so it is worth more than ``has no attribute``. Three things are tried, in order
463
+ of how much they know: the lazy torch exports; the table of what PennyLane and
464
+ Qiskit call the same thing (:mod:`qmlkit._aliases`); and failing both, a
465
+ near-match over everything qmlkit does export.
466
+
467
+ ``qk.AngleEmbedding`` reports that PennyLane's name for it is
468
+ :class:`~qmlkit.encoding.feature_maps.AngleFeatureMap`, rather than only that
469
+ the attribute is missing.
470
+ """
471
+ if name in _TORCH_EXPORTS:
472
+ try:
473
+ import qmlkit.nn as _nn
474
+ except ImportError as exc: # pragma: no cover - depends on the environment
475
+ raise ImportError(
476
+ f"{name} needs PyTorch, which is an optional extra:\n"
477
+ " pip install 'qmlkit[torch]'"
478
+ ) from exc
479
+ return _nn if name == "nn" else getattr(_nn, name)
480
+
481
+ from qmlkit._aliases import advice
482
+ from qmlkit.utils.errors import did_you_mean
483
+
484
+ hint = advice(name)
485
+ if hint is None:
486
+ near = did_you_mean(name, (*__all__, *_TORCH_EXPORTS))
487
+ if near:
488
+ hint = "Did you mean " + " or ".join(repr(s) for s in near) + "?"
489
+ message = f"module 'qmlkit' has no attribute {name!r}."
490
+ raise AttributeError(f"{message} {hint}" if hint else message)
491
+
492
+
493
+ def __dir__() -> list[str]:
494
+ """List the lazily-served torch exports too, so introspection finds them."""
495
+ return sorted({*globals(), *__all__, *_TORCH_EXPORTS})
qmlkit/_aliases.py ADDED
@@ -0,0 +1,135 @@
1
+ """What the other libraries call it.
2
+
3
+ A model writing qmlkit has read far more PennyLane and Qiskit than qmlkit, so its
4
+ first guess at a name is usually *their* name. ``qk.AngleEmbedding``,
5
+ ``qk.QuantumCircuit``, ``qk.PauliZ`` — all reasonable, all wrong here, and all
6
+ producing the same bare ``AttributeError`` that says only that the name is absent.
7
+
8
+ This table turns that dead end into a correction. It is a translation, not an
9
+ alias: the foreign name still raises. Two reasons for that choice.
10
+
11
+ *Aliases become API.* Anything importable is something somebody depends on, and a
12
+ shadow vocabulary of thirty PennyLane spellings is a second public surface to keep
13
+ working forever.
14
+
15
+ *Aliases hide semantic drift.* ``qml.expval`` takes a QNode; ``qk.expectation``
16
+ takes a :class:`~qmlkit.core.ir.CircuitSpec` and an observable. A name that
17
+ silently resolves would fail later, further from its cause, with a worse message.
18
+ Correcting costs one round trip and leaves the caller holding the real name.
19
+
20
+ Genuine aliases are still fine where the semantics are *identical* and only the
21
+ spelling differs — ``expval`` for ``expectation`` is one, and it is a real export.
22
+
23
+ ``tests/test_agent_api.py`` asserts every target below exists, so the table cannot
24
+ drift out of date without the build going red.
25
+ """
26
+
27
+ from __future__ import annotations
28
+
29
+ __all__ = ["ELSEWHERE", "advice"]
30
+
31
+ #: foreign name -> (qmlkit attribute, extra guidance). ``None`` means there is no
32
+ #: single equivalent and the note carries the whole answer.
33
+ _PENNYLANE: dict[str, tuple[str | None, str]] = {
34
+ "qnode": (None, "qmlkit has no QNode - build a CircuitSpec and call expectation(spec, obs)"),
35
+ "QNode": (None, "qmlkit has no QNode - build a CircuitSpec and call expectation(spec, obs)"),
36
+ "device": ("get_backend", ""),
37
+ "probs": ("probabilities", ""),
38
+ "state": ("statevector", ""),
39
+ "sample": ("run_counts", ""),
40
+ "counts": ("run_counts", ""),
41
+ "jacobian": ("grad", ""),
42
+ "about": ("backend_report", ""),
43
+ "AngleEmbedding": ("AngleFeatureMap", "or angle_encode(x) for a one-shot circuit"),
44
+ "AmplitudeEmbedding": ("amplitude_encode", "or the AmplitudeEncoder feature map"),
45
+ "BasisEmbedding": ("basis_encode", ""),
46
+ "IQPEmbedding": ("ZZFeatureMap", ""),
47
+ "StatePrep": ("amplitude_encode", ""),
48
+ "QubitStateVector": ("amplitude_encode", ""),
49
+ "StronglyEntanglingLayers": ("strongly_entangling", ""),
50
+ "BasicEntanglerLayers": ("basic_entangler", ""),
51
+ "SimplifiedTwoDesign": ("simplified_two_design", ""),
52
+ "RandomLayers": ("random_layers", ""),
53
+ "MPS": ("mps_ansatz", ""),
54
+ "TTN": ("tree_tensor_network", ""),
55
+ "PauliX": ("X", ""),
56
+ "PauliY": ("Y", ""),
57
+ "PauliZ": ("Z", ""),
58
+ "Identity": ("I", ""),
59
+ "Hamiltonian": ("PauliSum", ""),
60
+ "density_matrix": ("reduced_dm", ""),
61
+ "TorchLayer": ("QuantumLayer", ""),
62
+ }
63
+
64
+ _QISKIT: dict[str, tuple[str | None, str]] = {
65
+ "QuantumCircuit": ("QCircuit", ""),
66
+ "Statevector": ("statevector", ""),
67
+ "SparsePauliOp": ("PauliSum", ""),
68
+ "Pauli": ("PauliString", ""),
69
+ "Operator": (None, "build observables from Z/X/Y/I, PauliString or PauliSum"),
70
+ "Estimator": ("expectation", "qmlkit needs no primitive object"),
71
+ "Sampler": ("run_counts", "qmlkit needs no primitive object"),
72
+ "AerSimulator": ("get_backend", 'get_backend("qiskit") runs the same circuit on Aer'),
73
+ "transpile": (None, "qmlkit has no transpiler - a simulator runs the circuit as written"),
74
+ "EfficientSU2": ("hardware_efficient", ""),
75
+ "RealAmplitudes": ("two_local", 'two_local(n, rotations=("ry",), entangler="cx")'),
76
+ "TwoLocal": ("two_local", ""),
77
+ "NLocal": ("two_local", ""),
78
+ "FidelityQuantumKernel": ("QuantumKernel", ""),
79
+ "TrainableFidelityQuantumKernel": ("TrainableKernel", ""),
80
+ "TorchConnector": ("QuantumLayer", "a QuantumLayer already is an nn.Module"),
81
+ "EstimatorQNN": ("QuantumLayer", ""),
82
+ "SamplerQNN": ("QuantumLayer", ""),
83
+ "NeuralNetworkClassifier": ("VQC", ""),
84
+ "NeuralNetworkRegressor": ("VQRegressor", ""),
85
+ }
86
+
87
+ #: Plausible names that belong to no library in particular - the shape of guess a
88
+ #: model makes when it is reasoning from the domain rather than from another API.
89
+ _GUESSES: dict[str, tuple[str | None, str]] = {
90
+ "Circuit": ("QCircuit", ""),
91
+ "expectation_value": ("expectation", ""),
92
+ "expected_value": ("expectation", ""),
93
+ "parameter_shift": ("param_shift_grad", 'or grad(..., method="parameter-shift")'),
94
+ "parameter_shift_grad": ("param_shift_grad", ""),
95
+ "gradient": ("grad", ""),
96
+ "QNN": ("QuantumLayer", ""),
97
+ "Model": ("VQC", "or VQRegressor for regression"),
98
+ "Classifier": ("VQC", ""),
99
+ "Regressor": ("VQRegressor", ""),
100
+ "encode": ("angle_encode", "or a FeatureMap for something reusable"),
101
+ "measure": ("expectation", "or run_counts for samples"),
102
+ "simulate": ("statevector", ""),
103
+ "Observable": (None, "build observables from Z/X/Y/I, PauliString or PauliSum"),
104
+ "Kernel": ("QuantumKernel", ""),
105
+ "FeatureMapBase": ("FeatureMap", ""),
106
+ }
107
+
108
+ #: Every foreign name, with the library it came from.
109
+ ELSEWHERE: dict[str, tuple[str, str | None, str]] = {
110
+ **{k: ("PennyLane", *v) for k, v in _PENNYLANE.items()},
111
+ **{k: ("Qiskit", *v) for k, v in _QISKIT.items()},
112
+ **{k: ("", *v) for k, v in _GUESSES.items()},
113
+ }
114
+
115
+
116
+ def advice(name: str) -> str | None:
117
+ """One sentence naming the qmlkit equivalent of ``name``, or ``None``.
118
+
119
+ >>> advice("PauliZ")
120
+ "'PauliZ' is PennyLane's name for qmlkit.Z."
121
+ >>> advice("gradient")
122
+ "qmlkit calls that 'grad'."
123
+ >>> advice("not_a_real_name") is None
124
+ True
125
+ """
126
+ if name not in ELSEWHERE:
127
+ return None
128
+ source, target, note = ELSEWHERE[name]
129
+ tail = f" ({note})" if note else ""
130
+ if target is None:
131
+ lead = f"{name!r} is {source}'s;" if source else f"There is no {name!r};"
132
+ return f"{lead} {note}."
133
+ if source:
134
+ return f"{name!r} is {source}'s name for qmlkit.{target}{tail}."
135
+ return f"qmlkit calls that {target!r}{tail}."
@@ -0,0 +1,82 @@
1
+ """Algorithms built on the rest of the library.
2
+
3
+ Each one is a *loop* over machinery that already exists — ansatz, gradients,
4
+ optimisers, observables — so each is thin, and every structural choice it makes is
5
+ an argument rather than something baked in.
6
+ """
7
+
8
+ from __future__ import annotations
9
+
10
+ from qmlkit.algorithms.adapt import (
11
+ AdaptResult,
12
+ AdaptVQE,
13
+ chemistry_operator_pool,
14
+ default_operator_pool,
15
+ pauli_rotation,
16
+ )
17
+ from qmlkit.algorithms.autoencoder import AutoencoderResult, QuantumAutoencoder
18
+ from qmlkit.algorithms.chemistry import (
19
+ CHEMICAL_ACCURACY,
20
+ HARTREE_TO_KCAL,
21
+ h2_curve,
22
+ h2_hamiltonian,
23
+ )
24
+ from qmlkit.algorithms.clustering import QMeans, QMeansResult
25
+ from qmlkit.algorithms.hamiltonians import (
26
+ exact_ground_energy,
27
+ exact_ground_state,
28
+ hamiltonian_matrix,
29
+ heisenberg_hamiltonian,
30
+ ising_hamiltonian,
31
+ max_cut_hamiltonian,
32
+ pauli_hamiltonian,
33
+ )
34
+ from qmlkit.algorithms.molecule import (
35
+ MolecularInfo,
36
+ Molecule,
37
+ from_integrals,
38
+ hydrogen_chain,
39
+ hydrogen_ring,
40
+ molecular_hamiltonian,
41
+ )
42
+ from qmlkit.algorithms.qaoa import QAOA, QAOAResult
43
+ from qmlkit.algorithms.rl import ContextualBandit, QuantumPolicy, ReinforceResult, train_reinforce
44
+ from qmlkit.algorithms.vqe import OPTIMIZERS, VQE, VQEResult
45
+
46
+ __all__ = [
47
+ "VQE",
48
+ "QAOA",
49
+ "QAOAResult",
50
+ "AdaptVQE",
51
+ "AdaptResult",
52
+ "pauli_rotation",
53
+ "default_operator_pool",
54
+ "chemistry_operator_pool",
55
+ "QuantumAutoencoder",
56
+ "AutoencoderResult",
57
+ "QMeans",
58
+ "h2_hamiltonian",
59
+ "Molecule",
60
+ "MolecularInfo",
61
+ "molecular_hamiltonian",
62
+ "from_integrals",
63
+ "hydrogen_chain",
64
+ "hydrogen_ring",
65
+ "h2_curve",
66
+ "CHEMICAL_ACCURACY",
67
+ "HARTREE_TO_KCAL",
68
+ "QMeansResult",
69
+ "QuantumPolicy",
70
+ "ContextualBandit",
71
+ "train_reinforce",
72
+ "ReinforceResult",
73
+ "VQEResult",
74
+ "OPTIMIZERS",
75
+ "pauli_hamiltonian",
76
+ "ising_hamiltonian",
77
+ "heisenberg_hamiltonian",
78
+ "max_cut_hamiltonian",
79
+ "hamiltonian_matrix",
80
+ "exact_ground_energy",
81
+ "exact_ground_state",
82
+ ]