dense-evolution 8.2.3__tar.gz → 8.3.1__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.
- {dense_evolution-8.2.3 → dense_evolution-8.3.1}/PKG-INFO +14 -4
- {dense_evolution-8.2.3 → dense_evolution-8.3.1}/README.md +11 -1
- {dense_evolution-8.2.3 → dense_evolution-8.3.1}/dense_evolution/__init__.py +18 -4
- {dense_evolution-8.2.3 → dense_evolution-8.3.1}/dense_evolution/circuits/__init__.py +10 -0
- dense_evolution-8.3.1/dense_evolution/circuits/arithmetic.py +241 -0
- {dense_evolution-8.2.3 → dense_evolution-8.3.1}/dense_evolution/circuits/parser.py +69 -6
- dense_evolution-8.3.1/dense_evolution/circuits/postselect.py +59 -0
- {dense_evolution-8.2.3 → dense_evolution-8.3.1}/dense_evolution/config.py +13 -0
- {dense_evolution-8.2.3 → dense_evolution-8.3.1}/dense_evolution/mitigation/__init__.py +4 -4
- {dense_evolution-8.2.3 → dense_evolution-8.3.1}/dense_evolution/mitigation/kl_divergence.py +3 -1
- {dense_evolution-8.2.3 → dense_evolution-8.3.1}/dense_evolution/mitigation/magic_entropy.py +3 -1
- {dense_evolution-8.2.3 → dense_evolution-8.3.1}/dense_evolution/mitigation/magic_entropy_shadows.py +5 -0
- {dense_evolution-8.2.3 → dense_evolution-8.3.1}/dense_evolution/mitigation/renyi.py +3 -1
- {dense_evolution-8.2.3 → dense_evolution-8.3.1}/dense_evolution/mitigation/stabilizer_renyi_entropy.py +3 -1
- {dense_evolution-8.2.3 → dense_evolution-8.3.1}/dense_evolution/mitigation/zne.py +123 -7
- dense_evolution-8.3.1/dense_evolution/native_hf/libcint_bridge.py +167 -0
- {dense_evolution-8.2.3 → dense_evolution-8.3.1}/dense_evolution/physics/__init__.py +5 -1
- {dense_evolution-8.2.3 → dense_evolution-8.3.1}/dense_evolution/physics/qec.py +359 -0
- {dense_evolution-8.2.3 → dense_evolution-8.3.1}/dense_evolution/qec.py +5 -2
- {dense_evolution-8.2.3 → dense_evolution-8.3.1}/dense_evolution.egg-info/PKG-INFO +14 -4
- {dense_evolution-8.2.3 → dense_evolution-8.3.1}/dense_evolution.egg-info/SOURCES.txt +2 -0
- {dense_evolution-8.2.3 → dense_evolution-8.3.1}/dense_evolution.egg-info/requires.txt +2 -3
- {dense_evolution-8.2.3 → dense_evolution-8.3.1}/pyproject.toml +5 -11
- {dense_evolution-8.2.3 → dense_evolution-8.3.1}/tools/dashboard/core/hamiltonians.py +21 -4
- dense_evolution-8.2.3/dense_evolution/native_hf/libcint_bridge.py +0 -225
- {dense_evolution-8.2.3 → dense_evolution-8.3.1}/dense_evolution/autodiff.py +0 -0
- {dense_evolution-8.2.3 → dense_evolution-8.3.1}/dense_evolution/backends/__init__.py +0 -0
- {dense_evolution-8.2.3 → dense_evolution-8.3.1}/dense_evolution/backends/chunk/__init__.py +0 -0
- {dense_evolution-8.2.3 → dense_evolution-8.3.1}/dense_evolution/backends/chunk/_engine_imports.py +0 -0
- {dense_evolution-8.2.3 → dense_evolution-8.3.1}/dense_evolution/backends/chunk/circuit_chunker.py +0 -0
- {dense_evolution-8.2.3 → dense_evolution-8.3.1}/dense_evolution/backends/chunk/core.py +0 -0
- {dense_evolution-8.2.3 → dense_evolution-8.3.1}/dense_evolution/backends/chunk/disk_overflow.py +0 -0
- {dense_evolution-8.2.3 → dense_evolution-8.3.1}/dense_evolution/backends/chunk/geometry.py +0 -0
- {dense_evolution-8.2.3 → dense_evolution-8.3.1}/dense_evolution/backends/chunk/guard.py +0 -0
- {dense_evolution-8.2.3 → dense_evolution-8.3.1}/dense_evolution/backends/chunk/kernels.py +0 -0
- {dense_evolution-8.2.3 → dense_evolution-8.3.1}/dense_evolution/backends/mps.py +0 -0
- {dense_evolution-8.2.3 → dense_evolution-8.3.1}/dense_evolution/backends/statevector.py +0 -0
- {dense_evolution-8.2.3 → dense_evolution-8.3.1}/dense_evolution/chunk.py +0 -0
- {dense_evolution-8.2.3 → dense_evolution-8.3.1}/dense_evolution/circuits/compiler.py +0 -0
- {dense_evolution-8.2.3 → dense_evolution-8.3.1}/dense_evolution/circuits/diagram.py +0 -0
- {dense_evolution-8.2.3 → dense_evolution-8.3.1}/dense_evolution/circuits/gates.py +0 -0
- {dense_evolution-8.2.3 → dense_evolution-8.3.1}/dense_evolution/circuits/qft.py +0 -0
- {dense_evolution-8.2.3 → dense_evolution-8.3.1}/dense_evolution/circuits/random_circuit.py +0 -0
- {dense_evolution-8.2.3 → dense_evolution-8.3.1}/dense_evolution/circuits/registry.py +0 -0
- {dense_evolution-8.2.3 → dense_evolution-8.3.1}/dense_evolution/circuits/topology.py +0 -0
- {dense_evolution-8.2.3 → dense_evolution-8.3.1}/dense_evolution/circuits/trotter.py +0 -0
- {dense_evolution-8.2.3 → dense_evolution-8.3.1}/dense_evolution/circuits/uccsd.py +0 -0
- {dense_evolution-8.2.3 → dense_evolution-8.3.1}/dense_evolution/cli.py +0 -0
- {dense_evolution-8.2.3 → dense_evolution-8.3.1}/dense_evolution/compiler.py +0 -0
- {dense_evolution-8.2.3 → dense_evolution-8.3.1}/dense_evolution/drawing.py +0 -0
- {dense_evolution-8.2.3 → dense_evolution-8.3.1}/dense_evolution/entropy.py +0 -0
- {dense_evolution-8.2.3 → dense_evolution-8.3.1}/dense_evolution/fermions.py +0 -0
- {dense_evolution-8.2.3 → dense_evolution-8.3.1}/dense_evolution/gates.py +0 -0
- {dense_evolution-8.2.3 → dense_evolution-8.3.1}/dense_evolution/harrison_tb.py +0 -0
- {dense_evolution-8.2.3 → dense_evolution-8.3.1}/dense_evolution/healing.py +0 -0
- {dense_evolution-8.2.3 → dense_evolution-8.3.1}/dense_evolution/interop/__init__.py +0 -0
- {dense_evolution-8.2.3 → dense_evolution-8.3.1}/dense_evolution/interop/qiskit_pennylane.py +0 -0
- {dense_evolution-8.2.3 → dense_evolution-8.3.1}/dense_evolution/measurement.py +0 -0
- {dense_evolution-8.2.3 → dense_evolution-8.3.1}/dense_evolution/mitigation/healing.py +0 -0
- {dense_evolution-8.2.3 → dense_evolution-8.3.1}/dense_evolution/mps.py +0 -0
- {dense_evolution-8.2.3 → dense_evolution-8.3.1}/dense_evolution/native_hf/__init__.py +0 -0
- {dense_evolution-8.2.3 → dense_evolution-8.3.1}/dense_evolution/native_hf/assembly.py +0 -0
- {dense_evolution-8.2.3 → dense_evolution-8.3.1}/dense_evolution/native_hf/basis.py +0 -0
- {dense_evolution-8.2.3 → dense_evolution-8.3.1}/dense_evolution/native_hf/boys.py +0 -0
- {dense_evolution-8.2.3 → dense_evolution-8.3.1}/dense_evolution/native_hf/bridge.py +0 -0
- {dense_evolution-8.2.3 → dense_evolution-8.3.1}/dense_evolution/native_hf/cartesian.py +0 -0
- {dense_evolution-8.2.3 → dense_evolution-8.3.1}/dense_evolution/native_hf/coulomb.py +0 -0
- {dense_evolution-8.2.3 → dense_evolution-8.3.1}/dense_evolution/native_hf/differentiable.py +0 -0
- {dense_evolution-8.2.3 → dense_evolution-8.3.1}/dense_evolution/native_hf/gaussians.py +0 -0
- {dense_evolution-8.2.3 → dense_evolution-8.3.1}/dense_evolution/native_hf/kinetic.py +0 -0
- {dense_evolution-8.2.3 → dense_evolution-8.3.1}/dense_evolution/native_hf/overlap.py +0 -0
- {dense_evolution-8.2.3 → dense_evolution-8.3.1}/dense_evolution/native_hf/scf.py +0 -0
- {dense_evolution-8.2.3 → dense_evolution-8.3.1}/dense_evolution/noise/__init__.py +0 -0
- {dense_evolution-8.2.3 → dense_evolution-8.3.1}/dense_evolution/noise/coherent_attack.py +0 -0
- {dense_evolution-8.2.3 → dense_evolution-8.3.1}/dense_evolution/noise/cosmic_ray.py +0 -0
- {dense_evolution-8.2.3 → dense_evolution-8.3.1}/dense_evolution/noise/density_matrix_channels.py +0 -0
- {dense_evolution-8.2.3 → dense_evolution-8.3.1}/dense_evolution/noise/differentiable.py +0 -0
- {dense_evolution-8.2.3 → dense_evolution-8.3.1}/dense_evolution/noise/kraus/__init__.py +0 -0
- {dense_evolution-8.2.3 → dense_evolution-8.3.1}/dense_evolution/noise/kraus/amplitude_damping.py +0 -0
- {dense_evolution-8.2.3 → dense_evolution-8.3.1}/dense_evolution/noise/kraus/bitflip.py +0 -0
- {dense_evolution-8.2.3 → dense_evolution-8.3.1}/dense_evolution/noise/kraus/combined.py +0 -0
- {dense_evolution-8.2.3 → dense_evolution-8.3.1}/dense_evolution/noise/kraus/depolarizing.py +0 -0
- {dense_evolution-8.2.3 → dense_evolution-8.3.1}/dense_evolution/noise/kraus/ideal.py +0 -0
- {dense_evolution-8.2.3 → dense_evolution-8.3.1}/dense_evolution/noise/kraus/phaseflip.py +0 -0
- {dense_evolution-8.2.3 → dense_evolution-8.3.1}/dense_evolution/noise/kraus_channels.py +0 -0
- {dense_evolution-8.2.3 → dense_evolution-8.3.1}/dense_evolution/noise/oscillating.py +0 -0
- {dense_evolution-8.2.3 → dense_evolution-8.3.1}/dense_evolution/noise/pink.py +0 -0
- {dense_evolution-8.2.3 → dense_evolution-8.3.1}/dense_evolution/observables.py +0 -0
- {dense_evolution-8.2.3 → dense_evolution-8.3.1}/dense_evolution/parser.py +0 -0
- {dense_evolution-8.2.3 → dense_evolution-8.3.1}/dense_evolution/physics/entropy.py +0 -0
- {dense_evolution-8.2.3 → dense_evolution-8.3.1}/dense_evolution/physics/fermions.py +0 -0
- {dense_evolution-8.2.3 → dense_evolution-8.3.1}/dense_evolution/physics/observables.py +0 -0
- {dense_evolution-8.2.3 → dense_evolution-8.3.1}/dense_evolution/physics/spectral.py +0 -0
- {dense_evolution-8.2.3 → dense_evolution-8.3.1}/dense_evolution/physics/states.py +0 -0
- {dense_evolution-8.2.3 → dense_evolution-8.3.1}/dense_evolution/protocols/__init__.py +0 -0
- {dense_evolution-8.2.3 → dense_evolution-8.3.1}/dense_evolution/protocols/bb84.py +0 -0
- {dense_evolution-8.2.3 → dense_evolution-8.3.1}/dense_evolution/protocols/di_qkd_ghz.py +0 -0
- {dense_evolution-8.2.3 → dense_evolution-8.3.1}/dense_evolution/protocols/dicka_protocol2.py +0 -0
- {dense_evolution-8.2.3 → dense_evolution-8.3.1}/dense_evolution/qft.py +0 -0
- {dense_evolution-8.2.3 → dense_evolution-8.3.1}/dense_evolution/qmmm/__init__.py +0 -0
- {dense_evolution-8.2.3 → dense_evolution-8.3.1}/dense_evolution/qmmm/ase_bridge.py +0 -0
- {dense_evolution-8.2.3 → dense_evolution-8.3.1}/dense_evolution/qmmm/forces.py +0 -0
- {dense_evolution-8.2.3 → dense_evolution-8.3.1}/dense_evolution/qmmm/propagation.py +0 -0
- {dense_evolution-8.2.3 → dense_evolution-8.3.1}/dense_evolution/qmmm/region.py +0 -0
- {dense_evolution-8.2.3 → dense_evolution-8.3.1}/dense_evolution/random_circuit.py +0 -0
- {dense_evolution-8.2.3 → dense_evolution-8.3.1}/dense_evolution/registry.py +0 -0
- {dense_evolution-8.2.3 → dense_evolution-8.3.1}/dense_evolution/simulator.py +0 -0
- {dense_evolution-8.2.3 → dense_evolution-8.3.1}/dense_evolution/solvers/__init__.py +0 -0
- {dense_evolution-8.2.3 → dense_evolution-8.3.1}/dense_evolution/solvers/autodiff.py +0 -0
- {dense_evolution-8.2.3 → dense_evolution-8.3.1}/dense_evolution/solvers/harrison_tb.py +0 -0
- {dense_evolution-8.2.3 → dense_evolution-8.3.1}/dense_evolution/solvers/vhd_tb.py +0 -0
- {dense_evolution-8.2.3 → dense_evolution-8.3.1}/dense_evolution/states.py +0 -0
- {dense_evolution-8.2.3 → dense_evolution-8.3.1}/dense_evolution/topology.py +0 -0
- {dense_evolution-8.2.3 → dense_evolution-8.3.1}/dense_evolution/trotter.py +0 -0
- {dense_evolution-8.2.3 → dense_evolution-8.3.1}/dense_evolution/utils/__init__.py +0 -0
- {dense_evolution-8.2.3 → dense_evolution-8.3.1}/dense_evolution/utils/drawing.py +0 -0
- {dense_evolution-8.2.3 → dense_evolution-8.3.1}/dense_evolution/utils/mass_decomposition.py +0 -0
- {dense_evolution-8.2.3 → dense_evolution-8.3.1}/dense_evolution/utils/measurement.py +0 -0
- {dense_evolution-8.2.3 → dense_evolution-8.3.1}/dense_evolution/vhd_tb.py +0 -0
- {dense_evolution-8.2.3 → dense_evolution-8.3.1}/dense_evolution.egg-info/dependency_links.txt +0 -0
- {dense_evolution-8.2.3 → dense_evolution-8.3.1}/dense_evolution.egg-info/entry_points.txt +0 -0
- {dense_evolution-8.2.3 → dense_evolution-8.3.1}/dense_evolution.egg-info/top_level.txt +0 -0
- {dense_evolution-8.2.3 → dense_evolution-8.3.1}/license.md +0 -0
- {dense_evolution-8.2.3 → dense_evolution-8.3.1}/research/local_site/__init__.py +0 -0
- {dense_evolution-8.2.3 → dense_evolution-8.3.1}/research/local_site/app/__init__.py +0 -0
- {dense_evolution-8.2.3 → dense_evolution-8.3.1}/research/local_site/app/server.py +0 -0
- {dense_evolution-8.2.3 → dense_evolution-8.3.1}/setup.cfg +0 -0
- {dense_evolution-8.2.3 → dense_evolution-8.3.1}/tools/dashboard/core/__init__.py +0 -0
- {dense_evolution-8.2.3 → dense_evolution-8.3.1}/tools/dashboard/core/_gate_tables.py +0 -0
- {dense_evolution-8.2.3 → dense_evolution-8.3.1}/tools/dashboard/core/band_structure.py +0 -0
- {dense_evolution-8.2.3 → dense_evolution-8.3.1}/tools/dashboard/core/circuit_builder_component.py +0 -0
- {dense_evolution-8.2.3 → dense_evolution-8.3.1}/tools/dashboard/core/circuit_diagram.py +0 -0
- {dense_evolution-8.2.3 → dense_evolution-8.3.1}/tools/dashboard/core/crypto_protocols.py +0 -0
- {dense_evolution-8.2.3 → dense_evolution-8.3.1}/tools/dashboard/core/engine.py +0 -0
- {dense_evolution-8.2.3 → dense_evolution-8.3.1}/tools/dashboard/core/graphical_builder.py +0 -0
- {dense_evolution-8.2.3 → dense_evolution-8.3.1}/tools/dashboard/core/mass_decomposition_tool.py +0 -0
- {dense_evolution-8.2.3 → dense_evolution-8.3.1}/tools/dashboard/core/mitigation.py +0 -0
- {dense_evolution-8.2.3 → dense_evolution-8.3.1}/tools/dashboard/core/native_hf_diagnostics.py +0 -0
- {dense_evolution-8.2.3 → dense_evolution-8.3.1}/tools/dashboard/core/noise_tools.py +0 -0
- {dense_evolution-8.2.3 → dense_evolution-8.3.1}/tools/dashboard/core/qasm_library.py +0 -0
- {dense_evolution-8.2.3 → dense_evolution-8.3.1}/tools/dashboard/core/qmmm.py +0 -0
- {dense_evolution-8.2.3 → dense_evolution-8.3.1}/tools/dashboard/core/rag_tool.py +0 -0
- {dense_evolution-8.2.3 → dense_evolution-8.3.1}/tools/dashboard/core/state_visuals.py +0 -0
- {dense_evolution-8.2.3 → dense_evolution-8.3.1}/tools/dashboard/core/system_limits.py +0 -0
- {dense_evolution-8.2.3 → dense_evolution-8.3.1}/tools/dashboard/core/vector_healing.py +0 -0
- {dense_evolution-8.2.3 → dense_evolution-8.3.1}/tools/dashboard/core/visuals.py +0 -0
- {dense_evolution-8.2.3 → dense_evolution-8.3.1}/tools/dashboard/core/vqe.py +0 -0
- {dense_evolution-8.2.3 → dense_evolution-8.3.1}/tools/dashboard/core/wormhole.py +0 -0
- {dense_evolution-8.2.3 → dense_evolution-8.3.1}/tools/ia_utils/__init__.py +0 -0
- {dense_evolution-8.2.3 → dense_evolution-8.3.1}/tools/ia_utils/adversarial_vector_attack.py +0 -0
- {dense_evolution-8.2.3 → dense_evolution-8.3.1}/tools/ia_utils/rag.py +0 -0
- {dense_evolution-8.2.3 → dense_evolution-8.3.1}/tools/ia_utils/vector_healing.py +0 -0
- {dense_evolution-8.2.3 → dense_evolution-8.3.1}/tools/mcp_server/__init__.py +0 -0
- {dense_evolution-8.2.3 → dense_evolution-8.3.1}/tools/mcp_server/client.py +0 -0
- {dense_evolution-8.2.3 → dense_evolution-8.3.1}/tools/mcp_server/config.py +0 -0
- {dense_evolution-8.2.3 → dense_evolution-8.3.1}/tools/mcp_server/models.py +0 -0
- {dense_evolution-8.2.3 → dense_evolution-8.3.1}/tools/mcp_server/molecules.py +0 -0
- {dense_evolution-8.2.3 → dense_evolution-8.3.1}/tools/mcp_server/server.py +0 -0
- {dense_evolution-8.2.3 → dense_evolution-8.3.1}/tools/mcp_server/tools/__init__.py +0 -0
- {dense_evolution-8.2.3 → dense_evolution-8.3.1}/tools/mcp_server/tools/chemistry_tools.py +0 -0
- {dense_evolution-8.2.3 → dense_evolution-8.3.1}/tools/mcp_server/tools/circuit_tools.py +0 -0
- {dense_evolution-8.2.3 → dense_evolution-8.3.1}/tools/mcp_server/tools/crypto_tools.py +0 -0
- {dense_evolution-8.2.3 → dense_evolution-8.3.1}/tools/mcp_server/tools/mitigation_tools.py +0 -0
- {dense_evolution-8.2.3 → dense_evolution-8.3.1}/tools/mcp_server/tools/noise_tools.py +0 -0
- {dense_evolution-8.2.3 → dense_evolution-8.3.1}/tools/mcp_server/tools/retrieval_tools.py +0 -0
- {dense_evolution-8.2.3 → dense_evolution-8.3.1}/tools/mcp_server/tools/system_tools.py +0 -0
- {dense_evolution-8.2.3 → dense_evolution-8.3.1}/tools/mcp_server/tools/wormhole_tools.py +0 -0
- {dense_evolution-8.2.3 → dense_evolution-8.3.1}/tools/mcp_server/utils/__init__.py +0 -0
- {dense_evolution-8.2.3 → dense_evolution-8.3.1}/tools/mcp_server/utils/cache.py +0 -0
- {dense_evolution-8.2.3 → dense_evolution-8.3.1}/tools/mcp_server/utils/images.py +0 -0
- {dense_evolution-8.2.3 → dense_evolution-8.3.1}/tools/mcp_server/utils/truncation.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: dense-evolution
|
|
3
|
-
Version: 8.
|
|
3
|
+
Version: 8.3.1
|
|
4
4
|
Summary: High-performance quantum simulation toolkit -- Statevector/MPS engines with JIT compilation, noise modeling, VQE, QEC, quantum chemistry, and agent-native tooling
|
|
5
5
|
Author-email: Salvatore Pennacchio <jtatopenn@libero.it>
|
|
6
6
|
License: Business Source License 1.1
|
|
@@ -39,6 +39,8 @@ Requires-Dist: streamlit>=1.30.0; extra == "dashboard"
|
|
|
39
39
|
Requires-Dist: qiskit>=1.0.0; extra == "dashboard"
|
|
40
40
|
Requires-Dist: pylatexenc>=2.10; extra == "dashboard"
|
|
41
41
|
Requires-Dist: plotly>=5.0.0; extra == "dashboard"
|
|
42
|
+
Requires-Dist: rdkit>=2023.9.1; extra == "dashboard"
|
|
43
|
+
Requires-Dist: basis_set_exchange>=0.9; extra == "dashboard"
|
|
42
44
|
Provides-Extra: qiskit
|
|
43
45
|
Requires-Dist: qiskit>=1.0.0; extra == "qiskit"
|
|
44
46
|
Provides-Extra: pennylane
|
|
@@ -58,8 +60,6 @@ Provides-Extra: mcp
|
|
|
58
60
|
Requires-Dist: mcp>=2.0.0; extra == "mcp"
|
|
59
61
|
Requires-Dist: httpx>=0.27; extra == "mcp"
|
|
60
62
|
Requires-Dist: pydantic>=2.0.0; extra == "mcp"
|
|
61
|
-
Provides-Extra: libcint
|
|
62
|
-
Requires-Dist: pyscf>=2.0.0; extra == "libcint"
|
|
63
63
|
Provides-Extra: qmmm
|
|
64
64
|
Requires-Dist: rdkit>=2023.9.1; extra == "qmmm"
|
|
65
65
|
Provides-Extra: ase
|
|
@@ -108,6 +108,13 @@ Dynamic: license-file
|
|
|
108
108
|
**A high-performance quantum simulation toolkit
|
|
109
109
|
Statevector/MPS engines with compilation, noise, VQE, QEC, chemistry, and agent-native tooling.**
|
|
110
110
|
|
|
111
|
+
<p align="center">
|
|
112
|
+
<img src="docs/assets/favicon.svg" width="32" alt=""><br>
|
|
113
|
+
<b>Download the Dense Evolution Dashboard (Streamlit)</b><br>
|
|
114
|
+
<a href="https://github.com/tatopenn-cell/Dense-Evolution/raw/main/tools/installer/install-dashboard.bat">Windows (.bat)</a> ·
|
|
115
|
+
<a href="https://github.com/tatopenn-cell/Dense-Evolution/raw/main/tools/installer/install-dashboard.sh">macOS / Linux (.sh)</a>
|
|
116
|
+
</p>
|
|
117
|
+
|
|
111
118
|
[](https://github.com/tatopenn-cell/Dense-Evolution/actions/workflows/ci.yml)
|
|
112
119
|
[](https://tatopenn-cell.github.io/Dense-Evolution/)
|
|
113
120
|
[](https://codecov.io/gh/tatopenn-cell/Dense-Evolution)
|
|
@@ -293,8 +300,11 @@ sim.run_chunk(circuit.to_tuples(), chunk_size_gates=500)
|
|
|
293
300
|
|
|
294
301
|
- **JIT-fused statevector engine.** No Kronecker-product overhead — stride-sliced linear kernel fusion compiled through JAX XLA, real GPU/TPU dispatch with no code change. [Simulator](https://tatopenn-cell.github.io/Dense-Evolution/api/simulator/) · [MPS backend](https://tatopenn-cell.github.io/Dense-Evolution/api/mps/) for low-entanglement circuits at scale.
|
|
295
302
|
- **Anti-OOM `Chunk` engine.** Circuits too large for one array, split dynamically and sized off the real compute device's own free memory — with disk-backed overflow past even that ceiling. [Chunk guide](https://tatopenn-cell.github.io/Dense-Evolution/api/chunk/).
|
|
296
|
-
- **Real noise, real mitigation.** Stochastic Kraus channels, real-device noise imported from Qiskit backends, and Zero-Noise Extrapolation to correct for it. [Noise](https://tatopenn-cell.github.io/Dense-Evolution/api/noise/) · [Mitigation](https://tatopenn-cell.github.io/Dense-Evolution/api/mitigation/) · [what noise/mitigation/healing each mean](https://tatopenn-cell.github.io/Dense-Evolution/concepts/).
|
|
303
|
+
- **Real noise, real mitigation.** Stochastic Kraus channels, real-device noise imported from Qiskit backends, and Zero-Noise Extrapolation, with the shot budget split optimally across noise factors and a single-qubit Bloch-vector variant that always returns a valid state, to correct for it. [Noise](https://tatopenn-cell.github.io/Dense-Evolution/api/noise/) · [Mitigation](https://tatopenn-cell.github.io/Dense-Evolution/api/mitigation/) · [what noise/mitigation/healing each mean](https://tatopenn-cell.github.io/Dense-Evolution/concepts/).
|
|
297
304
|
- **Differentiable VQE, from scratch.** `circuit_to_energy_fn` is the same JAX-differentiable engine real molecular VQE runs on — real Hartree-Fock Hamiltonians, UCCSD/hardware-efficient ansätze, Adam optimization. [Autodiff](https://tatopenn-cell.github.io/Dense-Evolution/api/autodiff/).
|
|
305
|
+
- **libcint integrals on Windows, macOS and Linux.** `pip install dense-evolution` ships libcint compiled for each system: the full two-electron tensor of ethanol in 6-31G* in 0.32 s. [native_hf](https://tatopenn-cell.github.io/Dense-Evolution/api/native_hf/).
|
|
306
|
+
- **Reversible arithmetic.** Register adders, subtraction, comparisons and modular arithmetic up to modular exponentiation, applied as exact basis permutations and checked against the Vedral, Cuccaro, Draper and Beauregard circuits. [Arithmetic](https://tatopenn-cell.github.io/Dense-Evolution/api/arithmetic/).
|
|
307
|
+
- **Postselection.** Keep the branch where a qubit is found in `|0>`, `|1>`, `|±>` or `|±i>`, with its probability. [Postselection](https://tatopenn-cell.github.io/Dense-Evolution/api/postselect/).
|
|
298
308
|
- **OpenQASM 2.0/3.0, both directions.** A real parser, plus Qiskit/PennyLane interop bridges. [QASM Parser](https://tatopenn-cell.github.io/Dense-Evolution/api/parser/) · [Interop](https://tatopenn-cell.github.io/Dense-Evolution/api/interop/).
|
|
299
309
|
- **Code-agnostic QEC decoding**, Majorana/Jordan-Wigner fermion mapping, from-scratch Hartree-Fock for elements outside PennyLane's own basis set, a traversable-wormhole-inspired teleportation protocol, and real QM/MM region partitioning (ring-safe BFS, Diffuse2Seg-derived relevance propagation) — see the [full API reference](https://tatopenn-cell.github.io/Dense-Evolution/api/) for all of it.
|
|
300
310
|
|
|
@@ -8,6 +8,13 @@
|
|
|
8
8
|
**A high-performance quantum simulation toolkit
|
|
9
9
|
Statevector/MPS engines with compilation, noise, VQE, QEC, chemistry, and agent-native tooling.**
|
|
10
10
|
|
|
11
|
+
<p align="center">
|
|
12
|
+
<img src="docs/assets/favicon.svg" width="32" alt=""><br>
|
|
13
|
+
<b>Download the Dense Evolution Dashboard (Streamlit)</b><br>
|
|
14
|
+
<a href="https://github.com/tatopenn-cell/Dense-Evolution/raw/main/tools/installer/install-dashboard.bat">Windows (.bat)</a> ·
|
|
15
|
+
<a href="https://github.com/tatopenn-cell/Dense-Evolution/raw/main/tools/installer/install-dashboard.sh">macOS / Linux (.sh)</a>
|
|
16
|
+
</p>
|
|
17
|
+
|
|
11
18
|
[](https://github.com/tatopenn-cell/Dense-Evolution/actions/workflows/ci.yml)
|
|
12
19
|
[](https://tatopenn-cell.github.io/Dense-Evolution/)
|
|
13
20
|
[](https://codecov.io/gh/tatopenn-cell/Dense-Evolution)
|
|
@@ -193,8 +200,11 @@ sim.run_chunk(circuit.to_tuples(), chunk_size_gates=500)
|
|
|
193
200
|
|
|
194
201
|
- **JIT-fused statevector engine.** No Kronecker-product overhead — stride-sliced linear kernel fusion compiled through JAX XLA, real GPU/TPU dispatch with no code change. [Simulator](https://tatopenn-cell.github.io/Dense-Evolution/api/simulator/) · [MPS backend](https://tatopenn-cell.github.io/Dense-Evolution/api/mps/) for low-entanglement circuits at scale.
|
|
195
202
|
- **Anti-OOM `Chunk` engine.** Circuits too large for one array, split dynamically and sized off the real compute device's own free memory — with disk-backed overflow past even that ceiling. [Chunk guide](https://tatopenn-cell.github.io/Dense-Evolution/api/chunk/).
|
|
196
|
-
- **Real noise, real mitigation.** Stochastic Kraus channels, real-device noise imported from Qiskit backends, and Zero-Noise Extrapolation to correct for it. [Noise](https://tatopenn-cell.github.io/Dense-Evolution/api/noise/) · [Mitigation](https://tatopenn-cell.github.io/Dense-Evolution/api/mitigation/) · [what noise/mitigation/healing each mean](https://tatopenn-cell.github.io/Dense-Evolution/concepts/).
|
|
203
|
+
- **Real noise, real mitigation.** Stochastic Kraus channels, real-device noise imported from Qiskit backends, and Zero-Noise Extrapolation, with the shot budget split optimally across noise factors and a single-qubit Bloch-vector variant that always returns a valid state, to correct for it. [Noise](https://tatopenn-cell.github.io/Dense-Evolution/api/noise/) · [Mitigation](https://tatopenn-cell.github.io/Dense-Evolution/api/mitigation/) · [what noise/mitigation/healing each mean](https://tatopenn-cell.github.io/Dense-Evolution/concepts/).
|
|
197
204
|
- **Differentiable VQE, from scratch.** `circuit_to_energy_fn` is the same JAX-differentiable engine real molecular VQE runs on — real Hartree-Fock Hamiltonians, UCCSD/hardware-efficient ansätze, Adam optimization. [Autodiff](https://tatopenn-cell.github.io/Dense-Evolution/api/autodiff/).
|
|
205
|
+
- **libcint integrals on Windows, macOS and Linux.** `pip install dense-evolution` ships libcint compiled for each system: the full two-electron tensor of ethanol in 6-31G* in 0.32 s. [native_hf](https://tatopenn-cell.github.io/Dense-Evolution/api/native_hf/).
|
|
206
|
+
- **Reversible arithmetic.** Register adders, subtraction, comparisons and modular arithmetic up to modular exponentiation, applied as exact basis permutations and checked against the Vedral, Cuccaro, Draper and Beauregard circuits. [Arithmetic](https://tatopenn-cell.github.io/Dense-Evolution/api/arithmetic/).
|
|
207
|
+
- **Postselection.** Keep the branch where a qubit is found in `|0>`, `|1>`, `|±>` or `|±i>`, with its probability. [Postselection](https://tatopenn-cell.github.io/Dense-Evolution/api/postselect/).
|
|
198
208
|
- **OpenQASM 2.0/3.0, both directions.** A real parser, plus Qiskit/PennyLane interop bridges. [QASM Parser](https://tatopenn-cell.github.io/Dense-Evolution/api/parser/) · [Interop](https://tatopenn-cell.github.io/Dense-Evolution/api/interop/).
|
|
199
209
|
- **Code-agnostic QEC decoding**, Majorana/Jordan-Wigner fermion mapping, from-scratch Hartree-Fock for elements outside PennyLane's own basis set, a traversable-wormhole-inspired teleportation protocol, and real QM/MM region partitioning (ring-safe BFS, Diffuse2Seg-derived relevance propagation) — see the [full API reference](https://tatopenn-cell.github.io/Dense-Evolution/api/) for all of it.
|
|
200
210
|
|
|
@@ -31,7 +31,7 @@ from .backends.mps import MPSSimulator
|
|
|
31
31
|
from .mitigation.zne import (richardson_extrapolate, richardson_amplification_factor,
|
|
32
32
|
zero_noise_extrapolation, polynomial_extrapolate,
|
|
33
33
|
bounded_exponential_extrapolate,
|
|
34
|
-
project_to_physical, uhlmann_fidelity, zne_density_matrix,
|
|
34
|
+
project_to_physical, bloch_zne, bloch_zne_jit, uhlmann_fidelity, zne_density_matrix,
|
|
35
35
|
jsd_predictive_zne_density_matrix,
|
|
36
36
|
coherence_predictive_zne_density_matrix,
|
|
37
37
|
classically_augmented_zne_phaseflip,
|
|
@@ -45,6 +45,12 @@ from .physics.observables import (pauli_expectation, pauli_sum_expectation, paul
|
|
|
45
45
|
from .physics.states import ghz_state
|
|
46
46
|
from .utils.measurement import sample_counts, statevector_fidelity
|
|
47
47
|
from .circuits.qft import qft
|
|
48
|
+
from .circuits.arithmetic import (
|
|
49
|
+
add_registers, subtract_registers, add_constant,
|
|
50
|
+
compare_registers, compare_constant,
|
|
51
|
+
add_registers_mod, add_constant_mod, multiply_add_mod, multiply_mod, power_mod,
|
|
52
|
+
)
|
|
53
|
+
from .circuits.postselect import postselect
|
|
48
54
|
from .circuits.random_circuit import random_circuit
|
|
49
55
|
from .utils.drawing import draw_circuit
|
|
50
56
|
from .solvers.harrison_tb import (ELEMENTS as HARRISON_ELEMENTS, ETA as HARRISON_ETA,
|
|
@@ -58,9 +64,11 @@ from .circuits.trotter import (pauli_rotation_ops, trotter_evolve_ops, continuou
|
|
|
58
64
|
from .circuits.uccsd import find_excitations, single_excitation_ops, double_excitation_ops
|
|
59
65
|
from .physics.qec import (pauli_commutes, compute_syndrome, erasure_aware_decode, pymatching_decode,
|
|
60
66
|
blind_minimum_weight_decode, decode_with_erasure_fallback,
|
|
61
|
-
counts_in_intervals_dimension, nearest_coset_decode
|
|
67
|
+
counts_in_intervals_dimension, nearest_coset_decode, erasure_ml_decode,
|
|
68
|
+
peeling_decode, union_find_decode, matching_erasure_decode,
|
|
69
|
+
estimate_edge_probabilities_from_detection_events)
|
|
62
70
|
|
|
63
|
-
__version__ = "8.
|
|
71
|
+
__version__ = "8.3.1"
|
|
64
72
|
|
|
65
73
|
__all__ = [
|
|
66
74
|
"__version__",
|
|
@@ -73,6 +81,10 @@ __all__ = [
|
|
|
73
81
|
"NoiseModel", "NoiseSpec", "QuantumHardwareRegistry",
|
|
74
82
|
"GATES", "PARAMETRIC_GATES", "GATE_IDS",
|
|
75
83
|
"entangling_layer", "qft",
|
|
84
|
+
"add_registers", "subtract_registers", "add_constant",
|
|
85
|
+
"compare_registers", "compare_constant",
|
|
86
|
+
"add_registers_mod", "add_constant_mod", "multiply_add_mod", "multiply_mod", "power_mod",
|
|
87
|
+
"postselect",
|
|
76
88
|
"pauli_rotation_ops", "trotter_evolve_ops", "continuous_pulse_evolve",
|
|
77
89
|
"continuous_dissipative_evolve",
|
|
78
90
|
"find_excitations", "single_excitation_ops", "double_excitation_ops",
|
|
@@ -89,7 +101,7 @@ __all__ = [
|
|
|
89
101
|
"richardson_extrapolate", "richardson_amplification_factor",
|
|
90
102
|
"zero_noise_extrapolation", "polynomial_extrapolate",
|
|
91
103
|
"bounded_exponential_extrapolate",
|
|
92
|
-
"project_to_physical", "uhlmann_fidelity", "zne_density_matrix",
|
|
104
|
+
"project_to_physical", "bloch_zne", "bloch_zne_jit", "uhlmann_fidelity", "zne_density_matrix",
|
|
93
105
|
"jsd_predictive_zne_density_matrix", "coherence_predictive_zne_density_matrix",
|
|
94
106
|
"classically_augmented_zne_phaseflip",
|
|
95
107
|
"global_depolarizing_channel", "amplitude_damping_channel", "phaseflip_channel_exact",
|
|
@@ -105,6 +117,8 @@ __all__ = [
|
|
|
105
117
|
"majorana_pauli_terms", "total_parity_operator", "hubbard_hamiltonian_pauli_terms", "square_lattice_edges",
|
|
106
118
|
"pauli_commutes", "compute_syndrome", "erasure_aware_decode", "pymatching_decode", "blind_minimum_weight_decode",
|
|
107
119
|
"decode_with_erasure_fallback", "counts_in_intervals_dimension", "nearest_coset_decode",
|
|
120
|
+
"erasure_ml_decode", "peeling_decode", "union_find_decode", "matching_erasure_decode",
|
|
121
|
+
"estimate_edge_probabilities_from_detection_events",
|
|
108
122
|
# Utils -- drawing, measurement, random circuits
|
|
109
123
|
"draw_circuit", "plot_circuit", "sample_counts", "statevector_fidelity", "random_circuit",
|
|
110
124
|
]
|
|
@@ -5,6 +5,12 @@ from .compiler import QuantumTranspiler
|
|
|
5
5
|
from .registry import HAS_JAX, NoiseModel, NoiseSpec, QuantumHardwareRegistry
|
|
6
6
|
from .topology import entangling_layer, VALID_PATTERNS
|
|
7
7
|
from .qft import qft
|
|
8
|
+
from .arithmetic import (
|
|
9
|
+
add_registers, subtract_registers, add_constant,
|
|
10
|
+
compare_registers, compare_constant,
|
|
11
|
+
add_registers_mod, add_constant_mod, multiply_add_mod, multiply_mod, power_mod,
|
|
12
|
+
)
|
|
13
|
+
from .postselect import postselect
|
|
8
14
|
from .random_circuit import random_circuit
|
|
9
15
|
from .trotter import pauli_rotation_ops, trotter_evolve_ops
|
|
10
16
|
|
|
@@ -15,6 +21,10 @@ __all__ = [
|
|
|
15
21
|
"HAS_JAX", "NoiseModel", "NoiseSpec", "QuantumHardwareRegistry",
|
|
16
22
|
"entangling_layer", "VALID_PATTERNS",
|
|
17
23
|
"qft",
|
|
24
|
+
"add_registers", "subtract_registers", "add_constant",
|
|
25
|
+
"compare_registers", "compare_constant",
|
|
26
|
+
"add_registers_mod", "add_constant_mod", "multiply_add_mod", "multiply_mod", "power_mod",
|
|
27
|
+
"postselect",
|
|
18
28
|
"random_circuit",
|
|
19
29
|
"pauli_rotation_ops", "trotter_evolve_ops",
|
|
20
30
|
]
|
|
@@ -0,0 +1,241 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Reversible arithmetic on qubit registers, applied to a statevector.
|
|
3
|
+
|
|
4
|
+
Every operation here is a bijection f on computational basis states, so its
|
|
5
|
+
unitary is the permutation U|x> = |f(x)> (Vedral, Barenco, Ekert,
|
|
6
|
+
quant-ph/9511018, Sect. II, Eqs. 2-3). It is applied directly as an index
|
|
7
|
+
permutation of the statevector, which is exact and costs one gather over the
|
|
8
|
+
2^n amplitudes. The gate-level circuits from the papers (Cuccaro et al.
|
|
9
|
+
quant-ph/0410184 ripple-carry adder, Draper quant-ph/0008033 transform
|
|
10
|
+
adder) are the references the tests compare against.
|
|
11
|
+
|
|
12
|
+
A register is a list of qubit indices, least significant bit first. Qubit 0
|
|
13
|
+
is the most significant bit of the statevector index, as everywhere in the
|
|
14
|
+
engine.
|
|
15
|
+
"""
|
|
16
|
+
import numpy as np
|
|
17
|
+
|
|
18
|
+
from ..config import ensure_x64
|
|
19
|
+
from .registry import HAS_JAX
|
|
20
|
+
|
|
21
|
+
if HAS_JAX:
|
|
22
|
+
import jax.numpy as jnp
|
|
23
|
+
xp = jnp
|
|
24
|
+
else:
|
|
25
|
+
xp = np
|
|
26
|
+
|
|
27
|
+
__all__ = ['add_registers', 'subtract_registers', 'add_constant',
|
|
28
|
+
'compare_registers', 'compare_constant',
|
|
29
|
+
'add_registers_mod', 'add_constant_mod', 'multiply_add_mod',
|
|
30
|
+
'multiply_mod', 'power_mod']
|
|
31
|
+
|
|
32
|
+
_COMPARISONS = {
|
|
33
|
+
'<': np.less, '>': np.greater, '<=': np.less_equal,
|
|
34
|
+
'>=': np.greater_equal, '==': np.equal, '!=': np.not_equal,
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
def _register_values(n_qubits, register):
|
|
39
|
+
idx = np.arange(2 ** n_qubits)
|
|
40
|
+
value = np.zeros_like(idx)
|
|
41
|
+
for k, q in enumerate(register):
|
|
42
|
+
value |= ((idx >> (n_qubits - 1 - q)) & 1) << k
|
|
43
|
+
return idx, value
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
def _with_register(n_qubits, idx, register, value):
|
|
47
|
+
out = idx.copy()
|
|
48
|
+
for k, q in enumerate(register):
|
|
49
|
+
shift = n_qubits - 1 - q
|
|
50
|
+
out = (out & ~(1 << shift)) | (((value >> k) & 1) << shift)
|
|
51
|
+
return out
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
def _check(n_qubits, *registers):
|
|
55
|
+
used = [q for r in registers for q in r]
|
|
56
|
+
if len(set(used)) != len(used):
|
|
57
|
+
raise ValueError("registers must not share qubits")
|
|
58
|
+
if any(q < 0 or q >= n_qubits for q in used):
|
|
59
|
+
raise ValueError(f"qubit index out of range for {n_qubits} qubits")
|
|
60
|
+
if any(len(r) == 0 for r in registers):
|
|
61
|
+
raise ValueError("registers must not be empty")
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
def _permute(sv, target):
|
|
65
|
+
if xp is np:
|
|
66
|
+
sv = np.asarray(sv)
|
|
67
|
+
out = np.zeros_like(sv)
|
|
68
|
+
out[target] = sv
|
|
69
|
+
return out
|
|
70
|
+
ensure_x64()
|
|
71
|
+
sv = xp.asarray(sv)
|
|
72
|
+
return xp.zeros_like(sv).at[target].set(sv)
|
|
73
|
+
|
|
74
|
+
|
|
75
|
+
def add_registers(sv, n_qubits, a, b):
|
|
76
|
+
"""
|
|
77
|
+
|a, b> -> |a, (a + b) mod 2^len(b)>.
|
|
78
|
+
|
|
79
|
+
With len(b) = len(a) + 1 the sum never overflows (Vedral et al.,
|
|
80
|
+
Sect. III.A, Eq. 9); with len(b) = len(a) it is addition modulo 2^n
|
|
81
|
+
(Cuccaro et al., Sect. 4.1).
|
|
82
|
+
"""
|
|
83
|
+
_check(n_qubits, a, b)
|
|
84
|
+
idx, va = _register_values(n_qubits, a)
|
|
85
|
+
_, vb = _register_values(n_qubits, b)
|
|
86
|
+
target = _with_register(n_qubits, idx, b, (va + vb) % (1 << len(b)))
|
|
87
|
+
return _permute(sv, target)
|
|
88
|
+
|
|
89
|
+
|
|
90
|
+
def subtract_registers(sv, n_qubits, a, b):
|
|
91
|
+
"""
|
|
92
|
+
|a, b> -> |a, (b - a) mod 2^len(b)>, the inverse of add_registers.
|
|
93
|
+
|
|
94
|
+
If b < a the result is 2^len(b) - (a - b) and, with len(b) = len(a) + 1,
|
|
95
|
+
its most significant qubit is 1 (Vedral et al., Sect. III.A).
|
|
96
|
+
"""
|
|
97
|
+
_check(n_qubits, a, b)
|
|
98
|
+
idx, va = _register_values(n_qubits, a)
|
|
99
|
+
_, vb = _register_values(n_qubits, b)
|
|
100
|
+
target = _with_register(n_qubits, idx, b, (vb - va) % (1 << len(b)))
|
|
101
|
+
return _permute(sv, target)
|
|
102
|
+
|
|
103
|
+
|
|
104
|
+
def add_constant(sv, n_qubits, b, c):
|
|
105
|
+
"""
|
|
106
|
+
|b> -> |(b + c) mod 2^len(b)> for a classical integer c.
|
|
107
|
+
|
|
108
|
+
c = 1 is increment, c = -1 decrement. Same operation as Draper's
|
|
109
|
+
transform adder with classical addend (Sect. 5) and Beauregard's
|
|
110
|
+
phiADD(c) (quant-ph/0205095, Sect. 2.1).
|
|
111
|
+
"""
|
|
112
|
+
_check(n_qubits, b)
|
|
113
|
+
idx, vb = _register_values(n_qubits, b)
|
|
114
|
+
target = _with_register(n_qubits, idx, b, (vb + int(c)) % (1 << len(b)))
|
|
115
|
+
return _permute(sv, target)
|
|
116
|
+
|
|
117
|
+
|
|
118
|
+
def _flip_if(n_qubits, idx, out, condition):
|
|
119
|
+
return idx ^ (condition.astype(idx.dtype) << (n_qubits - 1 - out))
|
|
120
|
+
|
|
121
|
+
|
|
122
|
+
def _comparison(op):
|
|
123
|
+
if op not in _COMPARISONS:
|
|
124
|
+
raise ValueError(f"op must be one of {sorted(_COMPARISONS)}, got {op!r}")
|
|
125
|
+
return _COMPARISONS[op]
|
|
126
|
+
|
|
127
|
+
|
|
128
|
+
def compare_registers(sv, n_qubits, a, b, out, op='<'):
|
|
129
|
+
"""
|
|
130
|
+
|a, b, z> -> |a, b, z XOR [a op b]>, inputs unchanged.
|
|
131
|
+
|
|
132
|
+
op = '<' is the comparator of Cuccaro et al. (Sect. 4.3): the high bit of
|
|
133
|
+
a - b, which is 1 if and only if a < b. The other comparisons follow by
|
|
134
|
+
swapping the operands and negating the output qubit.
|
|
135
|
+
"""
|
|
136
|
+
_check(n_qubits, a, b, [out])
|
|
137
|
+
idx, va = _register_values(n_qubits, a)
|
|
138
|
+
_, vb = _register_values(n_qubits, b)
|
|
139
|
+
return _permute(sv, _flip_if(n_qubits, idx, out, _comparison(op)(va, vb)))
|
|
140
|
+
|
|
141
|
+
|
|
142
|
+
def compare_constant(sv, n_qubits, b, c, out, op='<'):
|
|
143
|
+
"""
|
|
144
|
+
|b, z> -> |b, z XOR [b op c]> for a classical integer c.
|
|
145
|
+
|
|
146
|
+
op = '<' is the most significant qubit after the reverse phiADD(c) of
|
|
147
|
+
Beauregard (quant-ph/0205095, Sect. 2.1, Fig. 4).
|
|
148
|
+
"""
|
|
149
|
+
_check(n_qubits, b, [out])
|
|
150
|
+
idx, vb = _register_values(n_qubits, b)
|
|
151
|
+
return _permute(sv, _flip_if(n_qubits, idx, out, _comparison(op)(vb, int(c))))
|
|
152
|
+
|
|
153
|
+
|
|
154
|
+
def _active(n_qubits, idx, controls):
|
|
155
|
+
on = np.ones(idx.shape, dtype=bool)
|
|
156
|
+
for q in controls:
|
|
157
|
+
on &= ((idx >> (n_qubits - 1 - q)) & 1).astype(bool)
|
|
158
|
+
return on
|
|
159
|
+
|
|
160
|
+
|
|
161
|
+
def _check_modulus(N, *registers):
|
|
162
|
+
if N < 1 or any(N > (1 << len(r)) for r in registers):
|
|
163
|
+
raise ValueError(f"modulus N={N} must be >= 1 and fit in the register")
|
|
164
|
+
|
|
165
|
+
|
|
166
|
+
def add_registers_mod(sv, n_qubits, a, b, N):
|
|
167
|
+
"""
|
|
168
|
+
|a, b> -> |a, (a + b) mod N> for 0 <= a, b < N (Vedral et al., Sect. III.B,
|
|
169
|
+
Eq. 10). Basis states with a >= N or b >= N are left unchanged, which
|
|
170
|
+
keeps the map a permutation.
|
|
171
|
+
"""
|
|
172
|
+
_check(n_qubits, a, b)
|
|
173
|
+
_check_modulus(N, a, b)
|
|
174
|
+
idx, va = _register_values(n_qubits, a)
|
|
175
|
+
_, vb = _register_values(n_qubits, b)
|
|
176
|
+
ok = (va < N) & (vb < N)
|
|
177
|
+
return _permute(sv, _with_register(n_qubits, idx, b, np.where(ok, (va + vb) % N, vb)))
|
|
178
|
+
|
|
179
|
+
|
|
180
|
+
def add_constant_mod(sv, n_qubits, b, c, N, controls=()):
|
|
181
|
+
"""
|
|
182
|
+
|b> -> |(b + c) mod N> for 0 <= b < N, applied only where every control
|
|
183
|
+
qubit is 1: the doubly controlled phiADD(c)MOD(N) of Beauregard
|
|
184
|
+
(quant-ph/0205095, Sect. 2.2, Fig. 5). Basis states with b >= N are left
|
|
185
|
+
unchanged.
|
|
186
|
+
"""
|
|
187
|
+
_check(n_qubits, b, *([list(controls)] if controls else []))
|
|
188
|
+
_check_modulus(N, b)
|
|
189
|
+
idx, vb = _register_values(n_qubits, b)
|
|
190
|
+
ok = _active(n_qubits, idx, controls) & (vb < N)
|
|
191
|
+
return _permute(sv, _with_register(n_qubits, idx, b, np.where(ok, (vb + int(c)) % N, vb)))
|
|
192
|
+
|
|
193
|
+
|
|
194
|
+
def multiply_add_mod(sv, n_qubits, x, b, a, N, controls=()):
|
|
195
|
+
"""
|
|
196
|
+
|x, b> -> |x, (b + a*x) mod N> for 0 <= b < N, applied only where every
|
|
197
|
+
control qubit is 1: CMULT(a)MOD(N) of Beauregard (Sect. 2.3, Fig. 6),
|
|
198
|
+
built in the paper from n controlled modular additions of 2^i*a mod N
|
|
199
|
+
(Vedral et al., Sect. III.C). Basis states with b >= N are left unchanged.
|
|
200
|
+
"""
|
|
201
|
+
_check(n_qubits, x, b, *([list(controls)] if controls else []))
|
|
202
|
+
_check_modulus(N, b)
|
|
203
|
+
idx, vx = _register_values(n_qubits, x)
|
|
204
|
+
_, vb = _register_values(n_qubits, b)
|
|
205
|
+
ok = _active(n_qubits, idx, controls) & (vb < N)
|
|
206
|
+
new = (vb + (int(a) % N) * (vx % N)) % N
|
|
207
|
+
return _permute(sv, _with_register(n_qubits, idx, b, np.where(ok, new, vb)))
|
|
208
|
+
|
|
209
|
+
|
|
210
|
+
def multiply_mod(sv, n_qubits, x, a, N, controls=()):
|
|
211
|
+
"""
|
|
212
|
+
|x> -> |a*x mod N> in place for 0 <= x < N and gcd(a, N) = 1, applied only
|
|
213
|
+
where every control qubit is 1 (Vedral et al., Sect. II, Eqs. 4-6;
|
|
214
|
+
Beauregard, Sect. 2.3, Fig. 7). With N = 2^len(x) and odd a this is plain
|
|
215
|
+
multiplication modulo 2^n. Basis states with x >= N are left unchanged.
|
|
216
|
+
"""
|
|
217
|
+
_check(n_qubits, x, *([list(controls)] if controls else []))
|
|
218
|
+
_check_modulus(N, x)
|
|
219
|
+
if np.gcd(int(a), N) != 1:
|
|
220
|
+
raise ValueError(f"a={a} and N={N} must be coprime for an in-place multiplication")
|
|
221
|
+
idx, vx = _register_values(n_qubits, x)
|
|
222
|
+
ok = _active(n_qubits, idx, controls) & (vx < N)
|
|
223
|
+
return _permute(sv, _with_register(n_qubits, idx, x, np.where(ok, (int(a) * vx) % N, vx)))
|
|
224
|
+
|
|
225
|
+
|
|
226
|
+
def power_mod(sv, n_qubits, x, y, a, N):
|
|
227
|
+
"""
|
|
228
|
+
|x, y> -> |x, y * a^x mod N> for 0 <= y < N and gcd(a, N) = 1. With y = 1
|
|
229
|
+
this is the modular exponentiation |x, 1> -> |x, a^x mod N> of Shor's
|
|
230
|
+
algorithm (Vedral et al., Eq. 1 and Sect. III.D). Basis states with
|
|
231
|
+
y >= N are left unchanged.
|
|
232
|
+
"""
|
|
233
|
+
_check(n_qubits, x, y)
|
|
234
|
+
_check_modulus(N, y)
|
|
235
|
+
if np.gcd(int(a), N) != 1:
|
|
236
|
+
raise ValueError(f"a={a} and N={N} must be coprime")
|
|
237
|
+
idx, vx = _register_values(n_qubits, x)
|
|
238
|
+
_, vy = _register_values(n_qubits, y)
|
|
239
|
+
powers = np.array([pow(int(a), int(e), N) for e in range(1 << len(x))])
|
|
240
|
+
ok = vy < N
|
|
241
|
+
return _permute(sv, _with_register(n_qubits, idx, y, np.where(ok, (vy * powers[vx]) % N, vy)))
|
|
@@ -260,12 +260,9 @@ class QASMParser:
|
|
|
260
260
|
- `for` loops with unresolvable bounds, and all `if`/`while`/`def`
|
|
261
261
|
blocks (no static execution — would need runtime classical bit
|
|
262
262
|
state), are simply removed, leaving the rest of the source intact.
|
|
263
|
-
- `gate` definitions
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
name still falls through as an unrecognized gate (silent no-op,
|
|
267
|
-
same as any other unknown gate name elsewhere in this codebase),
|
|
268
|
-
but no longer corrupts the qubit/statement that follows it.
|
|
263
|
+
- `gate` definitions never reach this loop: parse() lifts them out
|
|
264
|
+
first with _extract_gate_definitions and expands every call site
|
|
265
|
+
into the definition's body (_expand_gate_call).
|
|
269
266
|
|
|
270
267
|
Runs as a search/replace loop rather than recursion: after an outer
|
|
271
268
|
block is unrolled, any inner (nested) blocks are duplicated as raw
|
|
@@ -303,6 +300,70 @@ class QASMParser:
|
|
|
303
300
|
s = s[:m.start()] + replacement + s[close_brace + 1:]
|
|
304
301
|
return s
|
|
305
302
|
|
|
303
|
+
_RE_GATE_DEF = re.compile(r'\bgate\s+([a-zA-Z_]\w*)\s*(?:\(([^)]*)\))?\s*([^{]*)\{')
|
|
304
|
+
|
|
305
|
+
def _extract_gate_definitions(self, s: str) -> Tuple[str, Dict]:
|
|
306
|
+
"""
|
|
307
|
+
Remove every `gate NAME(params) args { body }` definition from the
|
|
308
|
+
source and return it with a table NAME -> (params, args, body).
|
|
309
|
+
|
|
310
|
+
OpenQASM 2.0 defines new gates as a body of earlier gates acting on
|
|
311
|
+
formal arguments; exporters such as qiskit.qasm2.dumps write
|
|
312
|
+
composite and arithmetic circuits this way (e.g. gate_MAJ inside
|
|
313
|
+
CDKMRippleCarryAdder), so call sites must be expanded, not dropped.
|
|
314
|
+
"""
|
|
315
|
+
defs: Dict[str, Tuple[List[str], List[str], str]] = {}
|
|
316
|
+
while True:
|
|
317
|
+
m = self._RE_GATE_DEF.search(s)
|
|
318
|
+
if not m:
|
|
319
|
+
return s, defs
|
|
320
|
+
close = self._find_matching_brace(s, m.end() - 1)
|
|
321
|
+
if close is None:
|
|
322
|
+
return s, defs
|
|
323
|
+
params = [p.strip() for p in (m.group(2) or '').split(',') if p.strip()]
|
|
324
|
+
args = [a.strip() for a in m.group(3).split(',') if a.strip()]
|
|
325
|
+
defs[m.group(1).lower()] = (params, args, s[m.end():close])
|
|
326
|
+
s = s[:m.start()] + s[close + 1:]
|
|
327
|
+
|
|
328
|
+
def _expand_gate_call(self, instr: str, defs: Dict, depth: int = 0) -> List[str]:
|
|
329
|
+
"""
|
|
330
|
+
Replace a call to a user-defined gate by its body, with formal
|
|
331
|
+
arguments and parameters substituted, recursively for nested
|
|
332
|
+
definitions. Anything else is returned unchanged.
|
|
333
|
+
"""
|
|
334
|
+
instr = re.sub(r'\s+', ' ', instr).strip()
|
|
335
|
+
head = re.split(r'[\s(]', instr, 1)[0].lower()
|
|
336
|
+
if head not in defs:
|
|
337
|
+
return [instr]
|
|
338
|
+
if depth > 64:
|
|
339
|
+
raise ValueError(f"gate definitions nested too deeply at '{head}'")
|
|
340
|
+
params, args, body = defs[head]
|
|
341
|
+
rest = instr[len(head):].strip()
|
|
342
|
+
actual_params: List[str] = []
|
|
343
|
+
if rest.startswith('('):
|
|
344
|
+
depth_p, close = 0, -1
|
|
345
|
+
for i, ch in enumerate(rest):
|
|
346
|
+
depth_p += (ch == '(') - (ch == ')')
|
|
347
|
+
if depth_p == 0:
|
|
348
|
+
close = i
|
|
349
|
+
break
|
|
350
|
+
actual_params = [t.strip() for t in self._split_params(rest[1:close])]
|
|
351
|
+
rest = rest[close + 1:]
|
|
352
|
+
actual_args = [a.strip() for a in rest.split(',') if a.strip()]
|
|
353
|
+
if len(actual_args) != len(args) or len(actual_params) != len(params):
|
|
354
|
+
raise ValueError(f"gate '{head}' expects {len(params)} parameters and "
|
|
355
|
+
f"{len(args)} qubits, got '{instr}'")
|
|
356
|
+
table = dict(zip(args, actual_args))
|
|
357
|
+
table.update({p: f'({v})' for p, v in zip(params, actual_params)})
|
|
358
|
+
if table:
|
|
359
|
+
names = re.compile(r'\b(' + '|'.join(re.escape(k) for k in table) + r')\b')
|
|
360
|
+
body = names.sub(lambda mm: table[mm.group(1)], body)
|
|
361
|
+
out: List[str] = []
|
|
362
|
+
for st in body.split(';'):
|
|
363
|
+
if st.strip():
|
|
364
|
+
out.extend(self._expand_gate_call(st, defs, depth + 1))
|
|
365
|
+
return out
|
|
366
|
+
|
|
306
367
|
def parse(self, qasm_str: str) -> QASMCircuit:
|
|
307
368
|
"""
|
|
308
369
|
Parse an OpenQASM 2.0 or 3.0 string into a QASMCircuit.
|
|
@@ -337,10 +398,12 @@ class QASMParser:
|
|
|
337
398
|
# Must run before the ';'-split below: brace-delimited blocks are
|
|
338
399
|
# not single ';'-terminated statements, and left alone they corrupt
|
|
339
400
|
# whatever real statement follows them on the same line.
|
|
401
|
+
cleaned, gate_defs = self._extract_gate_definitions(cleaned)
|
|
340
402
|
cleaned = self._process_block_constructs(cleaned)
|
|
341
403
|
|
|
342
404
|
# ── split into statements ─────────────────────────────────────
|
|
343
405
|
statements = [s.strip() for s in cleaned.split(';') if s.strip()]
|
|
406
|
+
statements = [e for st in statements for e in self._expand_gate_call(st, gate_defs)]
|
|
344
407
|
|
|
345
408
|
for instr in statements:
|
|
346
409
|
# collapse internal whitespace runs to a single space
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Postselection: keep only the branch of the state in which a qubit is found in a
|
|
3
|
+
chosen state, then renormalise.
|
|
4
|
+
|
|
5
|
+
This is the operation in the definition of PostBQP (Aaronson,
|
|
6
|
+
quant-ph/0412187, Definition 1): the computation is conditioned on a
|
|
7
|
+
measurement outcome that has nonzero probability. It is not unitary, so it is
|
|
8
|
+
applied to the statevector directly, as the projector |psi><psi| on the
|
|
9
|
+
qubit followed by renormalisation, and the success probability is returned
|
|
10
|
+
with the new state.
|
|
11
|
+
"""
|
|
12
|
+
import numpy as np
|
|
13
|
+
|
|
14
|
+
from ..config import ensure_x64
|
|
15
|
+
from .registry import HAS_JAX
|
|
16
|
+
|
|
17
|
+
if HAS_JAX:
|
|
18
|
+
import jax.numpy as jnp
|
|
19
|
+
xp = jnp
|
|
20
|
+
else:
|
|
21
|
+
xp = np
|
|
22
|
+
|
|
23
|
+
__all__ = ['postselect', 'POSTSELECT_STATES']
|
|
24
|
+
|
|
25
|
+
_R = 1 / np.sqrt(2)
|
|
26
|
+
POSTSELECT_STATES = {
|
|
27
|
+
'0': np.array([1, 0], dtype=np.complex128),
|
|
28
|
+
'1': np.array([0, 1], dtype=np.complex128),
|
|
29
|
+
'+': np.array([_R, _R], dtype=np.complex128),
|
|
30
|
+
'-': np.array([_R, -_R], dtype=np.complex128),
|
|
31
|
+
'+i': np.array([_R, 1j * _R], dtype=np.complex128),
|
|
32
|
+
'-i': np.array([_R, -1j * _R], dtype=np.complex128),
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
def postselect(sv, n_qubits, qubit, state='1'):
|
|
37
|
+
"""
|
|
38
|
+
Project `qubit` onto `state` and renormalise.
|
|
39
|
+
|
|
40
|
+
`state` is one of '0', '1', '+', '-', '+i', '-i'. Returns
|
|
41
|
+
`(new_sv, probability)`, where `probability` is the chance of that outcome
|
|
42
|
+
before postselection. Raises ValueError if the probability is zero, since
|
|
43
|
+
postselection is only defined for outcomes that can occur (Aaronson,
|
|
44
|
+
Definition 1, condition (i)).
|
|
45
|
+
"""
|
|
46
|
+
if state not in POSTSELECT_STATES:
|
|
47
|
+
raise ValueError(f"state must be one of {list(POSTSELECT_STATES)}, got {state!r}")
|
|
48
|
+
if not 0 <= qubit < n_qubits:
|
|
49
|
+
raise ValueError(f"qubit index out of range for {n_qubits} qubits")
|
|
50
|
+
if HAS_JAX:
|
|
51
|
+
ensure_x64()
|
|
52
|
+
psi = xp.asarray(POSTSELECT_STATES[state])
|
|
53
|
+
t = xp.asarray(sv).reshape(2 ** qubit, 2, 2 ** (n_qubits - qubit - 1))
|
|
54
|
+
overlap = xp.einsum('j,ijk->ik', xp.conj(psi), t)
|
|
55
|
+
probability = float(xp.sum(xp.abs(overlap) ** 2))
|
|
56
|
+
if probability <= 1e-15:
|
|
57
|
+
raise ValueError(f"outcome {state!r} on qubit {qubit} has zero probability")
|
|
58
|
+
projected = xp.einsum('j,ik->ijk', psi, overlap).reshape(-1)
|
|
59
|
+
return projected / np.sqrt(probability), probability
|
|
@@ -19,6 +19,8 @@ QuantumHardwareRegistry.__init__, circuit_to_energy_fn); set_precision()
|
|
|
19
19
|
is the public opt-out for a caller who wants to choose precision
|
|
20
20
|
explicitly, before constructing anything, and have that choice stick.
|
|
21
21
|
"""
|
|
22
|
+
import functools
|
|
23
|
+
|
|
22
24
|
import jax
|
|
23
25
|
|
|
24
26
|
_explicit = False
|
|
@@ -47,3 +49,14 @@ def ensure_x64() -> None:
|
|
|
47
49
|
precision -- never at import time."""
|
|
48
50
|
if not _explicit:
|
|
49
51
|
jax.config.update("jax_enable_x64", True)
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
def with_x64(fn):
|
|
55
|
+
"""Wrap `fn` so ensure_x64() runs before every call -- for public entry
|
|
56
|
+
points that build JAX arrays from user input, which JAX would otherwise
|
|
57
|
+
silently truncate to complex64/float32 if nothing else enabled x64 first."""
|
|
58
|
+
@functools.wraps(fn)
|
|
59
|
+
def wrapper(*args, **kwargs):
|
|
60
|
+
ensure_x64()
|
|
61
|
+
return fn(*args, **kwargs)
|
|
62
|
+
return wrapper
|
|
@@ -8,10 +8,10 @@ snapshots (magic_entropy_shadows), a multi-qubit per-state magic monotone
|
|
|
8
8
|
that module's own docstring for the distinction), and the classical
|
|
9
9
|
Kullback-Leibler divergence over probability distributions (kl_divergence)."""
|
|
10
10
|
from .zne import (
|
|
11
|
-
richardson_extrapolate, richardson_amplification_factor,
|
|
11
|
+
richardson_extrapolate, richardson_amplification_factor, zne_shot_allocation,
|
|
12
12
|
zero_noise_extrapolation, polynomial_extrapolate,
|
|
13
13
|
bounded_exponential_extrapolate,
|
|
14
|
-
project_to_physical, uhlmann_fidelity, zne_density_matrix,
|
|
14
|
+
project_to_physical, bloch_zne, bloch_zne_jit, uhlmann_fidelity, zne_density_matrix,
|
|
15
15
|
jsd_predictive_zne_density_matrix,
|
|
16
16
|
coherence_predictive_zne_density_matrix,
|
|
17
17
|
classically_augmented_zne_phaseflip,
|
|
@@ -33,10 +33,10 @@ from .magic_entropy_shadows import (
|
|
|
33
33
|
from .kl_divergence import kl_divergence, kl_divergence_jit
|
|
34
34
|
|
|
35
35
|
__all__ = [
|
|
36
|
-
"richardson_extrapolate", "richardson_amplification_factor",
|
|
36
|
+
"richardson_extrapolate", "richardson_amplification_factor", "zne_shot_allocation",
|
|
37
37
|
"zero_noise_extrapolation", "polynomial_extrapolate",
|
|
38
38
|
"bounded_exponential_extrapolate",
|
|
39
|
-
"project_to_physical", "uhlmann_fidelity", "zne_density_matrix",
|
|
39
|
+
"project_to_physical", "bloch_zne", "bloch_zne_jit", "uhlmann_fidelity", "zne_density_matrix",
|
|
40
40
|
"jsd_predictive_zne_density_matrix",
|
|
41
41
|
"coherence_predictive_zne_density_matrix",
|
|
42
42
|
"classically_augmented_zne_phaseflip",
|
|
@@ -41,6 +41,7 @@ Additive, not a replacement for the already-validated healing pipeline.
|
|
|
41
41
|
"""
|
|
42
42
|
import jax
|
|
43
43
|
import jax.numpy as jnp
|
|
44
|
+
from ..config import with_x64
|
|
44
45
|
|
|
45
46
|
__all__ = ["kl_divergence", "kl_divergence_jit"]
|
|
46
47
|
|
|
@@ -69,6 +70,7 @@ def _kl_divergence_core(p: jnp.ndarray, q: jnp.ndarray) -> jnp.ndarray:
|
|
|
69
70
|
return jnp.where(is_support_violation, jnp.inf, finite_result)
|
|
70
71
|
|
|
71
72
|
|
|
73
|
+
@with_x64
|
|
72
74
|
def kl_divergence(p: jnp.ndarray, q: jnp.ndarray) -> float:
|
|
73
75
|
"""Classical Kullback-Leibler divergence D_KL(p||q), in bits.
|
|
74
76
|
|
|
@@ -88,6 +90,6 @@ def kl_divergence(p: jnp.ndarray, q: jnp.ndarray) -> float:
|
|
|
88
90
|
return float(_kl_divergence_core(p, q))
|
|
89
91
|
|
|
90
92
|
|
|
91
|
-
kl_divergence_jit = jax.jit(_kl_divergence_core)
|
|
93
|
+
kl_divergence_jit = with_x64(jax.jit(_kl_divergence_core))
|
|
92
94
|
"""`jax.jit`-compiled entry point for `kl_divergence`. `p`/`q` must already
|
|
93
95
|
be `float64` arrays. Returns a jnp scalar, not a Python `float`."""
|