dense-evolution 8.2.0__tar.gz → 8.2.2__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (164) hide show
  1. {dense_evolution-8.2.0 → dense_evolution-8.2.2}/PKG-INFO +8 -2
  2. {dense_evolution-8.2.0 → dense_evolution-8.2.2}/README.md +1 -1
  3. {dense_evolution-8.2.0 → dense_evolution-8.2.2}/dense_evolution/__init__.py +9 -4
  4. {dense_evolution-8.2.0 → dense_evolution-8.2.2}/dense_evolution/mitigation/__init__.py +4 -0
  5. {dense_evolution-8.2.0 → dense_evolution-8.2.2}/dense_evolution/mitigation/zne.py +153 -1
  6. {dense_evolution-8.2.0 → dense_evolution-8.2.2}/dense_evolution/native_hf/scf.py +51 -4
  7. {dense_evolution-8.2.0 → dense_evolution-8.2.2}/dense_evolution/noise/__init__.py +13 -2
  8. {dense_evolution-8.2.0 → dense_evolution-8.2.2}/dense_evolution/noise/density_matrix_channels.py +30 -1
  9. dense_evolution-8.2.2/dense_evolution/noise/pink.py +80 -0
  10. dense_evolution-8.2.2/dense_evolution/utils/mass_decomposition.py +246 -0
  11. {dense_evolution-8.2.0 → dense_evolution-8.2.2}/dense_evolution.egg-info/PKG-INFO +8 -2
  12. {dense_evolution-8.2.0 → dense_evolution-8.2.2}/dense_evolution.egg-info/SOURCES.txt +9 -0
  13. {dense_evolution-8.2.0 → dense_evolution-8.2.2}/dense_evolution.egg-info/requires.txt +8 -0
  14. {dense_evolution-8.2.0 → dense_evolution-8.2.2}/pyproject.toml +38 -2
  15. {dense_evolution-8.2.0 → dense_evolution-8.2.2}/research/local_site/app/server.py +184 -0
  16. {dense_evolution-8.2.0 → dense_evolution-8.2.2}/tools/dashboard/core/__init__.py +12 -0
  17. dense_evolution-8.2.2/tools/dashboard/core/crypto_protocols.py +77 -0
  18. dense_evolution-8.2.2/tools/dashboard/core/mass_decomposition_tool.py +47 -0
  19. {dense_evolution-8.2.0 → dense_evolution-8.2.2}/tools/dashboard/core/mitigation.py +76 -1
  20. dense_evolution-8.2.2/tools/dashboard/core/native_hf_diagnostics.py +62 -0
  21. dense_evolution-8.2.2/tools/dashboard/core/rag_tool.py +45 -0
  22. dense_evolution-8.2.2/tools/ia_utils/rag.py +288 -0
  23. {dense_evolution-8.2.0 → dense_evolution-8.2.2}/tools/mcp_server/client.py +105 -0
  24. {dense_evolution-8.2.0 → dense_evolution-8.2.2}/tools/mcp_server/models.py +52 -0
  25. {dense_evolution-8.2.0 → dense_evolution-8.2.2}/tools/mcp_server/server.py +24 -11
  26. {dense_evolution-8.2.0 → dense_evolution-8.2.2}/tools/mcp_server/tools/chemistry_tools.py +45 -2
  27. dense_evolution-8.2.2/tools/mcp_server/tools/crypto_tools.py +66 -0
  28. {dense_evolution-8.2.0 → dense_evolution-8.2.2}/tools/mcp_server/tools/mitigation_tools.py +20 -0
  29. dense_evolution-8.2.2/tools/mcp_server/tools/retrieval_tools.py +44 -0
  30. {dense_evolution-8.2.0 → dense_evolution-8.2.2}/tools/mcp_server/tools/system_tools.py +12 -3
  31. {dense_evolution-8.2.0 → dense_evolution-8.2.2}/dense_evolution/autodiff.py +0 -0
  32. {dense_evolution-8.2.0 → dense_evolution-8.2.2}/dense_evolution/backends/__init__.py +0 -0
  33. {dense_evolution-8.2.0 → dense_evolution-8.2.2}/dense_evolution/backends/chunk/__init__.py +0 -0
  34. {dense_evolution-8.2.0 → dense_evolution-8.2.2}/dense_evolution/backends/chunk/_engine_imports.py +0 -0
  35. {dense_evolution-8.2.0 → dense_evolution-8.2.2}/dense_evolution/backends/chunk/circuit_chunker.py +0 -0
  36. {dense_evolution-8.2.0 → dense_evolution-8.2.2}/dense_evolution/backends/chunk/core.py +0 -0
  37. {dense_evolution-8.2.0 → dense_evolution-8.2.2}/dense_evolution/backends/chunk/disk_overflow.py +0 -0
  38. {dense_evolution-8.2.0 → dense_evolution-8.2.2}/dense_evolution/backends/chunk/geometry.py +0 -0
  39. {dense_evolution-8.2.0 → dense_evolution-8.2.2}/dense_evolution/backends/chunk/guard.py +0 -0
  40. {dense_evolution-8.2.0 → dense_evolution-8.2.2}/dense_evolution/backends/chunk/kernels.py +0 -0
  41. {dense_evolution-8.2.0 → dense_evolution-8.2.2}/dense_evolution/backends/mps.py +0 -0
  42. {dense_evolution-8.2.0 → dense_evolution-8.2.2}/dense_evolution/backends/statevector.py +0 -0
  43. {dense_evolution-8.2.0 → dense_evolution-8.2.2}/dense_evolution/chunk.py +0 -0
  44. {dense_evolution-8.2.0 → dense_evolution-8.2.2}/dense_evolution/circuits/__init__.py +0 -0
  45. {dense_evolution-8.2.0 → dense_evolution-8.2.2}/dense_evolution/circuits/compiler.py +0 -0
  46. {dense_evolution-8.2.0 → dense_evolution-8.2.2}/dense_evolution/circuits/diagram.py +0 -0
  47. {dense_evolution-8.2.0 → dense_evolution-8.2.2}/dense_evolution/circuits/gates.py +0 -0
  48. {dense_evolution-8.2.0 → dense_evolution-8.2.2}/dense_evolution/circuits/parser.py +0 -0
  49. {dense_evolution-8.2.0 → dense_evolution-8.2.2}/dense_evolution/circuits/qft.py +0 -0
  50. {dense_evolution-8.2.0 → dense_evolution-8.2.2}/dense_evolution/circuits/random_circuit.py +0 -0
  51. {dense_evolution-8.2.0 → dense_evolution-8.2.2}/dense_evolution/circuits/registry.py +0 -0
  52. {dense_evolution-8.2.0 → dense_evolution-8.2.2}/dense_evolution/circuits/topology.py +0 -0
  53. {dense_evolution-8.2.0 → dense_evolution-8.2.2}/dense_evolution/circuits/trotter.py +0 -0
  54. {dense_evolution-8.2.0 → dense_evolution-8.2.2}/dense_evolution/circuits/uccsd.py +0 -0
  55. {dense_evolution-8.2.0 → dense_evolution-8.2.2}/dense_evolution/cli.py +0 -0
  56. {dense_evolution-8.2.0 → dense_evolution-8.2.2}/dense_evolution/compiler.py +0 -0
  57. {dense_evolution-8.2.0 → dense_evolution-8.2.2}/dense_evolution/config.py +0 -0
  58. {dense_evolution-8.2.0 → dense_evolution-8.2.2}/dense_evolution/drawing.py +0 -0
  59. {dense_evolution-8.2.0 → dense_evolution-8.2.2}/dense_evolution/entropy.py +0 -0
  60. {dense_evolution-8.2.0 → dense_evolution-8.2.2}/dense_evolution/fermions.py +0 -0
  61. {dense_evolution-8.2.0 → dense_evolution-8.2.2}/dense_evolution/gates.py +0 -0
  62. {dense_evolution-8.2.0 → dense_evolution-8.2.2}/dense_evolution/harrison_tb.py +0 -0
  63. {dense_evolution-8.2.0 → dense_evolution-8.2.2}/dense_evolution/healing.py +0 -0
  64. {dense_evolution-8.2.0 → dense_evolution-8.2.2}/dense_evolution/interop/__init__.py +0 -0
  65. {dense_evolution-8.2.0 → dense_evolution-8.2.2}/dense_evolution/interop/qiskit_pennylane.py +0 -0
  66. {dense_evolution-8.2.0 → dense_evolution-8.2.2}/dense_evolution/measurement.py +0 -0
  67. {dense_evolution-8.2.0 → dense_evolution-8.2.2}/dense_evolution/mitigation/healing.py +0 -0
  68. {dense_evolution-8.2.0 → dense_evolution-8.2.2}/dense_evolution/mitigation/kl_divergence.py +0 -0
  69. {dense_evolution-8.2.0 → dense_evolution-8.2.2}/dense_evolution/mitigation/magic_entropy.py +0 -0
  70. {dense_evolution-8.2.0 → dense_evolution-8.2.2}/dense_evolution/mitigation/magic_entropy_shadows.py +0 -0
  71. {dense_evolution-8.2.0 → dense_evolution-8.2.2}/dense_evolution/mitigation/renyi.py +0 -0
  72. {dense_evolution-8.2.0 → dense_evolution-8.2.2}/dense_evolution/mitigation/stabilizer_renyi_entropy.py +0 -0
  73. {dense_evolution-8.2.0 → dense_evolution-8.2.2}/dense_evolution/mps.py +0 -0
  74. {dense_evolution-8.2.0 → dense_evolution-8.2.2}/dense_evolution/native_hf/__init__.py +0 -0
  75. {dense_evolution-8.2.0 → dense_evolution-8.2.2}/dense_evolution/native_hf/assembly.py +0 -0
  76. {dense_evolution-8.2.0 → dense_evolution-8.2.2}/dense_evolution/native_hf/basis.py +0 -0
  77. {dense_evolution-8.2.0 → dense_evolution-8.2.2}/dense_evolution/native_hf/boys.py +0 -0
  78. {dense_evolution-8.2.0 → dense_evolution-8.2.2}/dense_evolution/native_hf/bridge.py +0 -0
  79. {dense_evolution-8.2.0 → dense_evolution-8.2.2}/dense_evolution/native_hf/cartesian.py +0 -0
  80. {dense_evolution-8.2.0 → dense_evolution-8.2.2}/dense_evolution/native_hf/coulomb.py +0 -0
  81. {dense_evolution-8.2.0 → dense_evolution-8.2.2}/dense_evolution/native_hf/differentiable.py +0 -0
  82. {dense_evolution-8.2.0 → dense_evolution-8.2.2}/dense_evolution/native_hf/gaussians.py +0 -0
  83. {dense_evolution-8.2.0 → dense_evolution-8.2.2}/dense_evolution/native_hf/kinetic.py +0 -0
  84. {dense_evolution-8.2.0 → dense_evolution-8.2.2}/dense_evolution/native_hf/libcint_bridge.py +0 -0
  85. {dense_evolution-8.2.0 → dense_evolution-8.2.2}/dense_evolution/native_hf/overlap.py +0 -0
  86. {dense_evolution-8.2.0 → dense_evolution-8.2.2}/dense_evolution/noise/coherent_attack.py +0 -0
  87. {dense_evolution-8.2.0 → dense_evolution-8.2.2}/dense_evolution/noise/cosmic_ray.py +0 -0
  88. {dense_evolution-8.2.0 → dense_evolution-8.2.2}/dense_evolution/noise/differentiable.py +0 -0
  89. {dense_evolution-8.2.0 → dense_evolution-8.2.2}/dense_evolution/noise/kraus/__init__.py +0 -0
  90. {dense_evolution-8.2.0 → dense_evolution-8.2.2}/dense_evolution/noise/kraus/amplitude_damping.py +0 -0
  91. {dense_evolution-8.2.0 → dense_evolution-8.2.2}/dense_evolution/noise/kraus/bitflip.py +0 -0
  92. {dense_evolution-8.2.0 → dense_evolution-8.2.2}/dense_evolution/noise/kraus/combined.py +0 -0
  93. {dense_evolution-8.2.0 → dense_evolution-8.2.2}/dense_evolution/noise/kraus/depolarizing.py +0 -0
  94. {dense_evolution-8.2.0 → dense_evolution-8.2.2}/dense_evolution/noise/kraus/ideal.py +0 -0
  95. {dense_evolution-8.2.0 → dense_evolution-8.2.2}/dense_evolution/noise/kraus/phaseflip.py +0 -0
  96. {dense_evolution-8.2.0 → dense_evolution-8.2.2}/dense_evolution/noise/kraus_channels.py +0 -0
  97. {dense_evolution-8.2.0 → dense_evolution-8.2.2}/dense_evolution/noise/oscillating.py +0 -0
  98. {dense_evolution-8.2.0 → dense_evolution-8.2.2}/dense_evolution/observables.py +0 -0
  99. {dense_evolution-8.2.0 → dense_evolution-8.2.2}/dense_evolution/parser.py +0 -0
  100. {dense_evolution-8.2.0 → dense_evolution-8.2.2}/dense_evolution/physics/__init__.py +0 -0
  101. {dense_evolution-8.2.0 → dense_evolution-8.2.2}/dense_evolution/physics/entropy.py +0 -0
  102. {dense_evolution-8.2.0 → dense_evolution-8.2.2}/dense_evolution/physics/fermions.py +0 -0
  103. {dense_evolution-8.2.0 → dense_evolution-8.2.2}/dense_evolution/physics/observables.py +0 -0
  104. {dense_evolution-8.2.0 → dense_evolution-8.2.2}/dense_evolution/physics/qec.py +0 -0
  105. {dense_evolution-8.2.0 → dense_evolution-8.2.2}/dense_evolution/physics/spectral.py +0 -0
  106. {dense_evolution-8.2.0 → dense_evolution-8.2.2}/dense_evolution/physics/states.py +0 -0
  107. {dense_evolution-8.2.0 → dense_evolution-8.2.2}/dense_evolution/qec.py +0 -0
  108. {dense_evolution-8.2.0 → dense_evolution-8.2.2}/dense_evolution/qft.py +0 -0
  109. {dense_evolution-8.2.0 → dense_evolution-8.2.2}/dense_evolution/qmmm/__init__.py +0 -0
  110. {dense_evolution-8.2.0 → dense_evolution-8.2.2}/dense_evolution/qmmm/ase_bridge.py +0 -0
  111. {dense_evolution-8.2.0 → dense_evolution-8.2.2}/dense_evolution/qmmm/forces.py +0 -0
  112. {dense_evolution-8.2.0 → dense_evolution-8.2.2}/dense_evolution/qmmm/propagation.py +0 -0
  113. {dense_evolution-8.2.0 → dense_evolution-8.2.2}/dense_evolution/qmmm/region.py +0 -0
  114. {dense_evolution-8.2.0 → dense_evolution-8.2.2}/dense_evolution/random_circuit.py +0 -0
  115. {dense_evolution-8.2.0 → dense_evolution-8.2.2}/dense_evolution/registry.py +0 -0
  116. {dense_evolution-8.2.0 → dense_evolution-8.2.2}/dense_evolution/simulator.py +0 -0
  117. {dense_evolution-8.2.0 → dense_evolution-8.2.2}/dense_evolution/solvers/__init__.py +0 -0
  118. {dense_evolution-8.2.0 → dense_evolution-8.2.2}/dense_evolution/solvers/autodiff.py +0 -0
  119. {dense_evolution-8.2.0 → dense_evolution-8.2.2}/dense_evolution/solvers/harrison_tb.py +0 -0
  120. {dense_evolution-8.2.0 → dense_evolution-8.2.2}/dense_evolution/solvers/vhd_tb.py +0 -0
  121. {dense_evolution-8.2.0 → dense_evolution-8.2.2}/dense_evolution/states.py +0 -0
  122. {dense_evolution-8.2.0 → dense_evolution-8.2.2}/dense_evolution/topology.py +0 -0
  123. {dense_evolution-8.2.0 → dense_evolution-8.2.2}/dense_evolution/trotter.py +0 -0
  124. {dense_evolution-8.2.0 → dense_evolution-8.2.2}/dense_evolution/utils/__init__.py +0 -0
  125. {dense_evolution-8.2.0 → dense_evolution-8.2.2}/dense_evolution/utils/drawing.py +0 -0
  126. {dense_evolution-8.2.0 → dense_evolution-8.2.2}/dense_evolution/utils/measurement.py +0 -0
  127. {dense_evolution-8.2.0 → dense_evolution-8.2.2}/dense_evolution/vhd_tb.py +0 -0
  128. {dense_evolution-8.2.0 → dense_evolution-8.2.2}/dense_evolution.egg-info/dependency_links.txt +0 -0
  129. {dense_evolution-8.2.0 → dense_evolution-8.2.2}/dense_evolution.egg-info/entry_points.txt +0 -0
  130. {dense_evolution-8.2.0 → dense_evolution-8.2.2}/dense_evolution.egg-info/top_level.txt +0 -0
  131. {dense_evolution-8.2.0 → dense_evolution-8.2.2}/license.md +0 -0
  132. {dense_evolution-8.2.0 → dense_evolution-8.2.2}/research/local_site/__init__.py +0 -0
  133. {dense_evolution-8.2.0 → dense_evolution-8.2.2}/research/local_site/app/__init__.py +0 -0
  134. {dense_evolution-8.2.0 → dense_evolution-8.2.2}/setup.cfg +0 -0
  135. {dense_evolution-8.2.0 → dense_evolution-8.2.2}/tools/dashboard/core/_gate_tables.py +0 -0
  136. {dense_evolution-8.2.0 → dense_evolution-8.2.2}/tools/dashboard/core/band_structure.py +0 -0
  137. {dense_evolution-8.2.0 → dense_evolution-8.2.2}/tools/dashboard/core/circuit_builder_component.py +0 -0
  138. {dense_evolution-8.2.0 → dense_evolution-8.2.2}/tools/dashboard/core/circuit_diagram.py +0 -0
  139. {dense_evolution-8.2.0 → dense_evolution-8.2.2}/tools/dashboard/core/engine.py +0 -0
  140. {dense_evolution-8.2.0 → dense_evolution-8.2.2}/tools/dashboard/core/graphical_builder.py +0 -0
  141. {dense_evolution-8.2.0 → dense_evolution-8.2.2}/tools/dashboard/core/hamiltonians.py +0 -0
  142. {dense_evolution-8.2.0 → dense_evolution-8.2.2}/tools/dashboard/core/noise_tools.py +0 -0
  143. {dense_evolution-8.2.0 → dense_evolution-8.2.2}/tools/dashboard/core/qasm_library.py +0 -0
  144. {dense_evolution-8.2.0 → dense_evolution-8.2.2}/tools/dashboard/core/qmmm.py +0 -0
  145. {dense_evolution-8.2.0 → dense_evolution-8.2.2}/tools/dashboard/core/state_visuals.py +0 -0
  146. {dense_evolution-8.2.0 → dense_evolution-8.2.2}/tools/dashboard/core/system_limits.py +0 -0
  147. {dense_evolution-8.2.0 → dense_evolution-8.2.2}/tools/dashboard/core/vector_healing.py +0 -0
  148. {dense_evolution-8.2.0 → dense_evolution-8.2.2}/tools/dashboard/core/visuals.py +0 -0
  149. {dense_evolution-8.2.0 → dense_evolution-8.2.2}/tools/dashboard/core/vqe.py +0 -0
  150. {dense_evolution-8.2.0 → dense_evolution-8.2.2}/tools/dashboard/core/wormhole.py +0 -0
  151. {dense_evolution-8.2.0 → dense_evolution-8.2.2}/tools/ia_utils/__init__.py +0 -0
  152. {dense_evolution-8.2.0 → dense_evolution-8.2.2}/tools/ia_utils/adversarial_vector_attack.py +0 -0
  153. {dense_evolution-8.2.0 → dense_evolution-8.2.2}/tools/ia_utils/vector_healing.py +0 -0
  154. {dense_evolution-8.2.0 → dense_evolution-8.2.2}/tools/mcp_server/__init__.py +0 -0
  155. {dense_evolution-8.2.0 → dense_evolution-8.2.2}/tools/mcp_server/config.py +0 -0
  156. {dense_evolution-8.2.0 → dense_evolution-8.2.2}/tools/mcp_server/molecules.py +0 -0
  157. {dense_evolution-8.2.0 → dense_evolution-8.2.2}/tools/mcp_server/tools/__init__.py +0 -0
  158. {dense_evolution-8.2.0 → dense_evolution-8.2.2}/tools/mcp_server/tools/circuit_tools.py +0 -0
  159. {dense_evolution-8.2.0 → dense_evolution-8.2.2}/tools/mcp_server/tools/noise_tools.py +0 -0
  160. {dense_evolution-8.2.0 → dense_evolution-8.2.2}/tools/mcp_server/tools/wormhole_tools.py +0 -0
  161. {dense_evolution-8.2.0 → dense_evolution-8.2.2}/tools/mcp_server/utils/__init__.py +0 -0
  162. {dense_evolution-8.2.0 → dense_evolution-8.2.2}/tools/mcp_server/utils/cache.py +0 -0
  163. {dense_evolution-8.2.0 → dense_evolution-8.2.2}/tools/mcp_server/utils/images.py +0 -0
  164. {dense_evolution-8.2.0 → dense_evolution-8.2.2}/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.2.0
3
+ Version: 8.2.2
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
@@ -64,6 +64,11 @@ Provides-Extra: qmmm
64
64
  Requires-Dist: rdkit>=2023.9.1; extra == "qmmm"
65
65
  Provides-Extra: ase
66
66
  Requires-Dist: ase>=3.22.0; extra == "ase"
67
+ Provides-Extra: rag
68
+ Requires-Dist: scikit-learn>=1.0.0; extra == "rag"
69
+ Requires-Dist: sentence-transformers>=2.2.0; extra == "rag"
70
+ Provides-Extra: armor
71
+ Requires-Dist: dense-armor>=1.1.18; extra == "armor"
67
72
  Provides-Extra: full
68
73
  Requires-Dist: cupy-cuda12x>=12.0.0; extra == "full"
69
74
  Requires-Dist: streamlit>=1.30.0; extra == "full"
@@ -80,6 +85,7 @@ Requires-Dist: httpx>=0.27; extra == "full"
80
85
  Provides-Extra: dev
81
86
  Requires-Dist: pytest>=7.0.0; extra == "dev"
82
87
  Requires-Dist: pytest-cov>=4.0.0; extra == "dev"
88
+ Requires-Dist: pytest-env>=1.0.0; extra == "dev"
83
89
  Provides-Extra: docs
84
90
  Requires-Dist: mkdocs>=1.6.0; extra == "docs"
85
91
  Requires-Dist: mkdocs-material>=9.5.0; extra == "docs"
@@ -343,7 +349,7 @@ If Dense-Evolution is useful in academic work, please cite it via the metadata i
343
349
  Archived on [Zenodo](https://zenodo.org/):
344
350
 
345
351
  - **Concept DOI** (always resolves to the latest version): [10.5281/zenodo.21855643](https://doi.org/10.5281/zenodo.21855643)
346
- - **This release (v8.1.78)**: [10.5281/zenodo.22706039](https://doi.org/10.5281/zenodo.22706039)
352
+ - **This release (v8.2.0)**: [10.5281/zenodo.22818319](https://doi.org/10.5281/zenodo.22818319)
347
353
 
348
354
  ---
349
355
 
@@ -249,7 +249,7 @@ If Dense-Evolution is useful in academic work, please cite it via the metadata i
249
249
  Archived on [Zenodo](https://zenodo.org/):
250
250
 
251
251
  - **Concept DOI** (always resolves to the latest version): [10.5281/zenodo.21855643](https://doi.org/10.5281/zenodo.21855643)
252
- - **This release (v8.1.78)**: [10.5281/zenodo.22706039](https://doi.org/10.5281/zenodo.22706039)
252
+ - **This release (v8.2.0)**: [10.5281/zenodo.22818319](https://doi.org/10.5281/zenodo.22818319)
253
253
 
254
254
  ---
255
255
 
@@ -6,7 +6,8 @@ from .backends.statevector import DenseSVSimulator
6
6
  from .circuits.parser import QASMParser, QASMCircuit
7
7
  from .circuits.compiler import QuantumTranspiler
8
8
  from .noise import (NoiseModel, NoiseSpec, global_depolarizing_channel, amplitude_damping_channel,
9
- cosmic_ray_burst_profile, oscillating_p_eff)
9
+ phaseflip_channel_exact, cosmic_ray_burst_profile, oscillating_p_eff,
10
+ pink_noise_p_eff)
10
11
  from .circuits.registry import QuantumHardwareRegistry
11
12
  from .circuits.gates import GATES, PARAMETRIC_GATES, GATE_IDS
12
13
  from .backends.chunk import Chunk
@@ -32,6 +33,8 @@ from .mitigation.zne import (richardson_extrapolate, richardson_amplification_fa
32
33
  bounded_exponential_extrapolate,
33
34
  project_to_physical, uhlmann_fidelity, zne_density_matrix,
34
35
  jsd_predictive_zne_density_matrix,
36
+ coherence_predictive_zne_density_matrix,
37
+ classically_augmented_zne_phaseflip,
35
38
  richardson_extrapolate_jit, zero_noise_extrapolation_jit,
36
39
  polynomial_extrapolate_jit, uhlmann_fidelity_jit, zne_density_matrix_jit)
37
40
  from .circuits.diagram import plot_circuit
@@ -57,7 +60,7 @@ from .physics.qec import (pauli_commutes, compute_syndrome, erasure_aware_decode
57
60
  blind_minimum_weight_decode, decode_with_erasure_fallback,
58
61
  counts_in_intervals_dimension, nearest_coset_decode)
59
62
 
60
- __version__ = "8.1.81"
63
+ __version__ = "8.2.2"
61
64
 
62
65
  __all__ = [
63
66
  "__version__",
@@ -87,8 +90,10 @@ __all__ = [
87
90
  "zero_noise_extrapolation", "polynomial_extrapolate",
88
91
  "bounded_exponential_extrapolate",
89
92
  "project_to_physical", "uhlmann_fidelity", "zne_density_matrix",
90
- "jsd_predictive_zne_density_matrix", "global_depolarizing_channel", "amplitude_damping_channel",
91
- "cosmic_ray_burst_profile", "oscillating_p_eff",
93
+ "jsd_predictive_zne_density_matrix", "coherence_predictive_zne_density_matrix",
94
+ "classically_augmented_zne_phaseflip",
95
+ "global_depolarizing_channel", "amplitude_damping_channel", "phaseflip_channel_exact",
96
+ "cosmic_ray_burst_profile", "oscillating_p_eff", "pink_noise_p_eff",
92
97
  "richardson_extrapolate_jit", "zero_noise_extrapolation_jit",
93
98
  "polynomial_extrapolate_jit", "uhlmann_fidelity_jit", "zne_density_matrix_jit",
94
99
  # Physics -- states, observables, entropy, fermions, QEC
@@ -13,6 +13,8 @@ from .zne import (
13
13
  bounded_exponential_extrapolate,
14
14
  project_to_physical, uhlmann_fidelity, zne_density_matrix,
15
15
  jsd_predictive_zne_density_matrix,
16
+ coherence_predictive_zne_density_matrix,
17
+ classically_augmented_zne_phaseflip,
16
18
  richardson_extrapolate_jit, zero_noise_extrapolation_jit,
17
19
  polynomial_extrapolate_jit, uhlmann_fidelity_jit, zne_density_matrix_jit,
18
20
  )
@@ -36,6 +38,8 @@ __all__ = [
36
38
  "bounded_exponential_extrapolate",
37
39
  "project_to_physical", "uhlmann_fidelity", "zne_density_matrix",
38
40
  "jsd_predictive_zne_density_matrix",
41
+ "coherence_predictive_zne_density_matrix",
42
+ "classically_augmented_zne_phaseflip",
39
43
  "richardson_extrapolate_jit", "zero_noise_extrapolation_jit",
40
44
  "polynomial_extrapolate_jit", "uhlmann_fidelity_jit", "zne_density_matrix_jit",
41
45
  "calculate_advanced_sigma", "calculate_phi_ab", "calculate_vettore_dinamico",
@@ -23,7 +23,8 @@ from .healing import calculate_delta_preemp
23
23
  __all__ = ["richardson_extrapolate", "richardson_amplification_factor", "zero_noise_extrapolation",
24
24
  "polynomial_extrapolate", "bounded_exponential_extrapolate",
25
25
  "project_to_physical", "uhlmann_fidelity", "zne_density_matrix",
26
- "jsd_predictive_zne_density_matrix", "global_depolarizing_channel",
26
+ "jsd_predictive_zne_density_matrix", "coherence_predictive_zne_density_matrix",
27
+ "classically_augmented_zne_phaseflip", "global_depolarizing_channel",
27
28
  "amplitude_damping_channel", "cosmic_ray_burst_profile",
28
29
  "richardson_extrapolate_jit", "zero_noise_extrapolation_jit",
29
30
  "polynomial_extrapolate_jit", "uhlmann_fidelity_jit", "zne_density_matrix_jit"]
@@ -836,3 +837,154 @@ def _jsd_predictive_zne_density_matrix_core(rho_at_scales: jnp.ndarray, nudge_sc
836
837
  c3 = 1.0 - nudge_scale * rectified
837
838
  extrapolated = (c1 * e_l1 + c2 * e_l2 + c3 * e_l3) / (c1 + c2 + c3)
838
839
  return project_to_physical(extrapolated)
840
+
841
+
842
+ def _coherence_l1(rho: jnp.ndarray) -> jnp.ndarray:
843
+ """l1-norm of coherence (Baumgratz, Cramer & Plenio, Phys. Rev. Lett.
844
+ 113, 140401, 2014): the sum of the magnitudes of every off-diagonal
845
+ density-matrix entry. A standard, basis-dependent measure of how much
846
+ quantum coherence a state carries in the computational basis --
847
+ unlike `_js_divergence`, which only ever sees the diagonal
848
+ (populations), this is sensitive to exactly what dephasing destroys."""
849
+ n = rho.shape[0]
850
+ return jnp.sum(jnp.abs(rho) * (1.0 - jnp.eye(n, dtype=rho.dtype)))
851
+
852
+
853
+ def coherence_predictive_zne_density_matrix(rho_at_scales, noise_factors) -> jnp.ndarray:
854
+ """Density-matrix ZNE with a coherence-informed coefficient nudge --
855
+ the same adaptive-nonlinearity mechanism as
856
+ `jsd_predictive_zne_density_matrix`, but signaled by the l1-norm of
857
+ coherence (`_coherence_l1`) instead of the Jensen-Shannon divergence
858
+ of the diagonal populations.
859
+
860
+ Motivation: `jsd_predictive_zne_density_matrix`'s signal is the
861
+ density-matrix diagonal only. Any purely dephasing-type noise
862
+ (phase-flip, or a coherent Z-axis over-rotation) is diagonal in the
863
+ computational basis -- it moves phase, never populations -- so that
864
+ signal is blind to it BY CONSTRUCTION, not merely weak: verified
865
+ directly in Dense-Evolution-Discovery's
866
+ scripts/jsd_zne_noise_generalization.py, the fidelity delta from the
867
+ classical-JSD nudge is exactly 0.0 at every tested phase-flip noise
868
+ strength and every tested coherent-rotation angle. A quantum-JSD
869
+ variant (von Neumann entropy of the full density matrix instead of
870
+ Shannon entropy of the diagonal) was tried there too and rejected: it
871
+ weakens the already-working amplitude-damping/combined-noise case
872
+ without fixing the coherent-error case, since a smooth deterministic
873
+ function of the noise-scale factor has `jsd_12~=jsd_23` regardless of
874
+ which divergence measures it -- the nonlinearity trigger this whole
875
+ family of methods relies on is structurally near-zero there no
876
+ matter the signal.
877
+
878
+ Validated scope, checked directly rather than assumed universal: real
879
+ effect on phase-flip/dephasing-dominated noise for `base_p<=0.10`;
880
+ NOT validated (and not claimed) for amplitude-damping-dominated noise
881
+ (use `jsd_predictive_zne_density_matrix` there instead) or for
882
+ coherent/deterministic errors (out of reach for this entire family of
883
+ methods, not just this signal -- see above).
884
+
885
+ Verified at 200 independent seeds on phase-flip noise (GHZ(4),
886
+ `base_p=0.05`, K=150 trajectories/scale) before promotion: the nudge
887
+ activates (rectified nonlinearity > 0) on 63/200 seeds (31.5%) --
888
+ among those, 63/63 improve over plain `zne_density_matrix`, mean
889
+ fidelity gain +0.014892, one-sample t-test against zero
890
+ p=1.07e-08, a 20000-resample permutation test finding no resample
891
+ matching or exceeding the observed effect (p<0.00005). Confirmed
892
+ across a noise-level sweep (100 seeds/level, GHZ(4)): significant by
893
+ both tests, 100% win rate among active points, at base_p in (0.03,
894
+ 0.05, 0.08, 0.10); NOT significant at base_p=0.15 (p=0.288 t-test,
895
+ p=0.301 permutation) -- a real, honest upper boundary, not a
896
+ universal effect at any noise strength. Confirmed on a second circuit
897
+ family (hardware-efficient VQE-style ansatz, 2 layers) at
898
+ `base_p=0.05`: 69/150 active (46%, a higher activation rate than
899
+ GHZ), 67/69 positive, p=4.4e-06 -- the effect is not GHZ-specific.
900
+ When inactive, reduces EXACTLY to `zne_density_matrix` at 3
901
+ equally-spaced scales (verified: max deviation ~1e-8, floating-point
902
+ noise) -- zero risk in that regime, by construction, the same safety
903
+ property `jsd_predictive_zne_density_matrix` has.
904
+
905
+ Only defined for exactly 3 equally-spaced noise factors (1x, 2x, 3x),
906
+ same restriction and reason as `jsd_predictive_zne_density_matrix`:
907
+ the Lagrange coefficients (3, -3, 1) this nudges are specific to that
908
+ spacing."""
909
+ rho_at_scales = jnp.asarray(rho_at_scales, dtype=jnp.complex128)
910
+ noise_factors = jnp.asarray(noise_factors, dtype=jnp.float64)
911
+ if noise_factors.shape[0] != 3:
912
+ raise NotImplementedError(
913
+ "coherence_predictive_zne_density_matrix is only defined for exactly 3 noise "
914
+ "factors; call zne_density_matrix(...) directly for the plain N-point case."
915
+ )
916
+ return _coherence_predictive_zne_density_matrix_core(rho_at_scales)
917
+
918
+
919
+ def _coherence_predictive_zne_density_matrix_core(rho_at_scales: jnp.ndarray, nudge_scale: float = 0.5) -> jnp.ndarray:
920
+ """`jax.jit`-traceable core of `coherence_predictive_zne_density_matrix`
921
+ -- `rho_at_scales` already complex128. See the public wrapper's
922
+ docstring for the method and its validation."""
923
+ c1_, c2_, c3_ = (_coherence_l1(rho_at_scales[i]) for i in range(3))
924
+ gap_12 = jnp.abs(c1_ - c2_)
925
+ gap_23 = jnp.abs(c2_ - c3_)
926
+ nonlinearity = (gap_23 - gap_12) / (gap_23 + gap_12 + 1e-12)
927
+ rectified = jnp.maximum(nonlinearity, 0.0)
928
+
929
+ e_l1, e_l2, e_l3 = rho_at_scales[0], rho_at_scales[1], rho_at_scales[2]
930
+ c1 = 3.0 - nudge_scale * rectified
931
+ c2 = -3.0 + 2.0 * nudge_scale * rectified
932
+ c3 = 1.0 - nudge_scale * rectified
933
+ extrapolated = (c1 * e_l1 + c2 * e_l2 + c3 * e_l3) / (c1 + c2 + c3)
934
+ return project_to_physical(extrapolated)
935
+
936
+
937
+ def classically_augmented_zne_phaseflip(rho_at_scales_measured, noise_factors, rho_ideal, base_p, degree: int = 2) -> jnp.ndarray:
938
+ """Classically Augmented ZNE (Scheiber et al., arXiv:2607.25746) for
939
+ phaseflip noise: the highest-noise Richardson/polynomial-extrapolation
940
+ nodes -- the ones contributing most to sampling variance -- are
941
+ replaced by `phaseflip_channel_exact`'s zero-sampling-variance exact
942
+ channel instead of a Monte-Carlo-sampled density matrix, then combined
943
+ exactly as `zne_density_matrix` already does (same extrapolation
944
+ coefficients; only the source of the high-noise inputs changes).
945
+
946
+ `rho_at_scales_measured[i]` must be the measured/sampled density
947
+ matrix at `noise_factors[i]` for `i < len(rho_at_scales_measured)`
948
+ (the low-noise nodes, kept as real measurements); every remaining
949
+ factor in `noise_factors` is filled in with the exact channel computed
950
+ from `rho_ideal` and `base_p`. `rho_ideal` and `base_p` are required
951
+ inputs, not optional, because the exact channel needs the noise-free
952
+ state to condition on -- unlike every other function in this module,
953
+ this one is not usable from noisy measurements alone.
954
+
955
+ Honest, verified scope (GHZ(3), phaseflip, 150 trials/measured node,
956
+ 60 seeds each): with exactly 3 total noise factors and only the single
957
+ highest one replaced, no measurable benefit (variance ratio 0.99x,
958
+ i.e. no effect within noise) -- too little room for the exact node to
959
+ matter against only 2 remaining measured ones. With 5 noise factors
960
+ (1x-5x, `base_p=0.03`) and the top 3 replaced by the exact channel,
961
+ variance drops by a real, measured 1.30x versus plain `zne_density_matrix`
962
+ using 5 fully-measured nodes at the same per-node trial budget. This is
963
+ the naive-allocation regime, not the paper's own optimal importance-
964
+ sampling allocation (their Eq. 9) -- that allocation is not implemented
965
+ here, so the exponential variance reduction the paper reports under it
966
+ is not claimed or expected from this function as shipped.
967
+
968
+ Only implemented for phaseflip noise, since `phaseflip_channel_exact`
969
+ is the only exact density-matrix channel currently available that
970
+ matches a `NoiseModel` statevector model exactly (see that function's
971
+ docstring) -- extending this to other noise models needs their own
972
+ exact channel first."""
973
+ from ..noise import phaseflip_channel_exact
974
+
975
+ rho_at_scales_measured = jnp.asarray(rho_at_scales_measured, dtype=jnp.complex128)
976
+ noise_factors = jnp.asarray(noise_factors, dtype=jnp.float64)
977
+ rho_ideal = jnp.asarray(rho_ideal, dtype=jnp.complex128)
978
+ cutoff = rho_at_scales_measured.shape[0]
979
+ if cutoff >= noise_factors.shape[0]:
980
+ raise ValueError(
981
+ f"rho_at_scales_measured has {cutoff} entries but noise_factors only has "
982
+ f"{noise_factors.shape[0]} -- at least one factor must be left for the exact "
983
+ "classical node, or there is nothing to augment."
984
+ )
985
+ classical_rhos = jnp.stack([
986
+ phaseflip_channel_exact(rho_ideal, jnp.minimum(base_p * f, 1.0))
987
+ for f in noise_factors[cutoff:]
988
+ ])
989
+ rho_at_scales = jnp.concatenate([rho_at_scales_measured, classical_rhos], axis=0)
990
+ return zne_density_matrix(rho_at_scales, noise_factors, degree=degree)
@@ -90,6 +90,7 @@ import dataclasses
90
90
  import functools
91
91
 
92
92
  import jax
93
+ import numpy as np
93
94
  import jax.numpy as jnp
94
95
 
95
96
  from dense_evolution.config import ensure_x64
@@ -107,6 +108,7 @@ class HFResult:
107
108
  orbital_energies: jax.Array
108
109
  orbital_coefficients: jax.Array # C, shape (n_basis, n_basis)
109
110
  density_matrix: jax.Array
111
+ energy_history: jax.Array # shape (max_iterations,), NaN past n_iterations
110
112
 
111
113
 
112
114
  def nuclear_repulsion_energy(nuclear_charges: list[float], nuclear_positions: jax.Array) -> jax.Array:
@@ -231,11 +233,11 @@ def run_scf(
231
233
  return F, energy
232
234
 
233
235
  def cond_fun(state):
234
- iteration, _P, _C, _orbital_energies, _energy_prev, converged, _fock_history, _error_history = state
236
+ iteration, _P, _C, _orbital_energies, _energy_prev, converged, _fock_history, _error_history, _energy_history = state
235
237
  return jnp.logical_and(jnp.logical_not(converged), iteration < max_iterations)
236
238
 
237
239
  def body_fun(state):
238
- iteration, P, C_prev, _orbital_energies, energy_prev, _converged, fock_history, error_history = state
240
+ iteration, P, C_prev, _orbital_energies, energy_prev, _converged, fock_history, error_history, energy_history = state
239
241
 
240
242
  F, energy = _fock_and_energy(P)
241
243
  error = _diis_error(F, P, S, X)
@@ -262,7 +264,9 @@ def run_scf(
262
264
  P_damped = jnp.where(history_count < 2, damping * P_new + (1.0 - damping) * P, P_new)
263
265
  P_next = jnp.where(converged, P_new, P_damped)
264
266
 
265
- return (iteration + 1, P_next, C, orbital_energies, energy, converged, fock_history, error_history)
267
+ energy_history = energy_history.at[iteration].set(energy)
268
+
269
+ return (iteration + 1, P_next, C, orbital_energies, energy, converged, fock_history, error_history, energy_history)
266
270
 
267
271
  init_state = (
268
272
  jnp.array(0),
@@ -273,8 +277,9 @@ def run_scf(
273
277
  jnp.array(False),
274
278
  jnp.zeros((diis_dim, n_basis, n_basis), dtype=H_core.dtype),
275
279
  jnp.zeros((diis_dim, n_basis, n_basis), dtype=H_core.dtype),
280
+ jnp.full((max_iterations,), jnp.nan, dtype=H_core.dtype),
276
281
  )
277
- iteration, P, C, orbital_energies, _energy_prev, converged, _fh, _eh = jax.lax.while_loop(cond_fun, body_fun, init_state)
282
+ iteration, P, C, orbital_energies, _energy_prev, converged, _fh, _eh, energy_history = jax.lax.while_loop(cond_fun, body_fun, init_state)
278
283
 
279
284
  _F, electronic_energy = _fock_and_energy(P)
280
285
  e_nuc = nuclear_repulsion_energy(nuclear_charges, nuclear_positions)
@@ -288,9 +293,51 @@ def run_scf(
288
293
  orbital_energies=orbital_energies,
289
294
  orbital_coefficients=C,
290
295
  density_matrix=P,
296
+ energy_history=energy_history,
291
297
  )
292
298
 
293
299
 
300
+ def _import_dense_armor_robust_filters():
301
+ try:
302
+ from dense_armor.utility.robust_filters import hampel_filter, tukey_fences
303
+ except ImportError as exc:
304
+ raise ImportError(
305
+ "native_hf.scf.diagnose_convergence needs Dense-Armor (pip install dense-evolution[armor])"
306
+ ) from exc
307
+ return hampel_filter, tukey_fences
308
+
309
+
310
+ def diagnose_convergence(result: HFResult, radius: int = 5, n_sigmas: float = 3.0) -> dict:
311
+ """Real automatic guard on HFResult.energy_history, instead of trusting
312
+ the final `converged` flag in isolation: Dense-Armor's Hampel filter
313
+ and Tukey fences (dense_evolution.utility.robust_filters -- the sister
314
+ project's own anomaly detectors, Chauvenet/Tukey/Hampel/sigma-clipping,
315
+ validated with 0 false positives on real H2 dissociation-curve
316
+ chemistry) applied to the real per-iteration electronic energy trace.
317
+
318
+ Validated on a real non-converging case (a 28-heavy-atom CASMI26
319
+ fragment, level_shift=0.0): the broken run flags 19-24% of its 200
320
+ iterations as anomalous; the same fragment fixed with level_shift=0.5
321
+ (converges in 55 iterations) flags only ~4% -- background noise, not a
322
+ false-alarm storm. Needs the `armor` extra (pip install
323
+ dense-evolution[armor]) -- Dense-Armor is not a hard dependency of this
324
+ module."""
325
+ hampel_filter, tukey_fences = _import_dense_armor_robust_filters()
326
+ trace = np.asarray(result.energy_history[:result.n_iterations])
327
+ n = max(1, result.n_iterations)
328
+
329
+ _cleaned_h, anomalies_h = hampel_filter(trace, radius=radius, n_sigmas=n_sigmas)
330
+ _cleaned_t, anomalies_t = tukey_fences(trace, radius=len(trace))
331
+
332
+ return {
333
+ "n_iterations": result.n_iterations,
334
+ "n_anomalies_hampel": len(anomalies_h),
335
+ "n_anomalies_tukey": len(anomalies_t),
336
+ "anomaly_fraction_hampel": len(anomalies_h) / n,
337
+ "anomaly_fraction_tukey": len(anomalies_t) / n,
338
+ }
339
+
340
+
294
341
  @functools.partial(jax.custom_vjp, nondiff_argnums=(3,))
295
342
  def scf_electronic_energy(S: jax.Array, H_core: jax.Array, repulsion: jax.Array, n_electrons: int) -> jax.Array:
296
343
  """The RHF electronic energy (run_scf's own `electronic_energy`, not
@@ -17,12 +17,20 @@
17
17
  - **Density-matrix channels** (`.density_matrix_channels`) --
18
18
  `global_depolarizing_channel`, `amplitude_damping_channel`: noise applied
19
19
  directly to a density matrix instead of a statevector, for density-matrix
20
- ZNE's noise ensemble.
20
+ ZNE's noise ensemble. `phaseflip_channel_exact`: the same phaseflip model
21
+ as `NoiseModel`'s `'phaseflip'` statevector Kraus channel, but computed as
22
+ its exact zero-sampling-variance limit directly on a density matrix, for
23
+ use as a "classical node" in Classically Augmented ZNE (see
24
+ `dense_evolution.mitigation.classically_augmented_zne_phaseflip`).
21
25
  - **`cosmic_ray_burst_profile`** (`.cosmic_ray`) -- a real, time-dependent
22
26
  noise-strength profile for a cosmic-ray-induced quasiparticle burst.
23
27
  - **`oscillating_p_eff`** (`.oscillating`) -- a noise strength that
24
28
  oscillates instead of scaling smoothly, for stress-testing mitigation
25
29
  techniques that assume smoothness.
30
+ - **`pink_noise_p_eff`** (`.pink`) -- a noise-strength trace with a real
31
+ 1/f (pink/flicker) power spectrum, the dominant decoherence mechanism
32
+ in real superconducting qubits, via the Timmer & Koenig (1995)
33
+ spectral-synthesis algorithm.
26
34
 
27
35
  Real device noise from a Qiskit backend's own calibration data
28
36
  (`noise_model_from_qiskit_backend`) lives in `dense_evolution.interop`,
@@ -47,9 +55,10 @@ from .coherent_attack import (
47
55
  decoder_failure_rate,
48
56
  random_delta_failure_stats,
49
57
  )
50
- from .density_matrix_channels import global_depolarizing_channel, amplitude_damping_channel
58
+ from .density_matrix_channels import global_depolarizing_channel, amplitude_damping_channel, phaseflip_channel_exact
51
59
  from .cosmic_ray import cosmic_ray_burst_profile
52
60
  from .oscillating import oscillating_p_eff
61
+ from .pink import pink_noise_p_eff
53
62
 
54
63
  __all__ = [
55
64
  "NoiseModel",
@@ -63,6 +72,8 @@ __all__ = [
63
72
  "random_delta_failure_stats",
64
73
  "global_depolarizing_channel",
65
74
  "amplitude_damping_channel",
75
+ "phaseflip_channel_exact",
66
76
  "cosmic_ray_burst_profile",
67
77
  "oscillating_p_eff",
78
+ "pink_noise_p_eff",
68
79
  ]
@@ -3,7 +3,7 @@ what density-matrix ZNE (`dense_evolution.mitigation.zne_density_matrix`)
3
3
  needs its noise ensemble built from."""
4
4
  import jax.numpy as jnp
5
5
 
6
- __all__ = ["global_depolarizing_channel", "amplitude_damping_channel"]
6
+ __all__ = ["global_depolarizing_channel", "amplitude_damping_channel", "phaseflip_channel_exact"]
7
7
 
8
8
 
9
9
  def global_depolarizing_channel(rho: jnp.ndarray, p: float) -> jnp.ndarray:
@@ -47,3 +47,32 @@ def amplitude_damping_channel(rho: jnp.ndarray, gamma: float) -> jnp.ndarray:
47
47
  e0 = jnp.array([[1.0, 0.0], [0.0, jnp.sqrt(1.0 - gamma)]], dtype=jnp.complex128)
48
48
  e1 = jnp.array([[0.0, jnp.sqrt(gamma)], [0.0, 0.0]], dtype=jnp.complex128)
49
49
  return e0 @ rho @ e0.conj().T + e1 @ rho @ e1.conj().T
50
+
51
+
52
+ def phaseflip_channel_exact(rho: jnp.ndarray, p: float) -> jnp.ndarray:
53
+ """Exact (zero-variance) multi-qubit phaseflip channel: K0=sqrt(1-p)*I,
54
+ K1=sqrt(p)*Z, applied independently per qubit across the whole
55
+ register, matching `NoiseModel`'s `'phaseflip'` statevector model
56
+ (`noise/kraus/phaseflip.py`) in the limit of infinitely many Monte
57
+ Carlo trials -- this function computes that limit directly instead of
58
+ averaging finite trials, for use as a zero-sampling-variance
59
+ "classical node" in Classically Augmented ZNE (Scheiber et al., "CA-ZNE:
60
+ high-noise Richardson nodes replaced by classically simulated
61
+ estimates", arXiv:2607.25746).
62
+
63
+ Since Z is diagonal in the computational basis, conjugating rho by Z_q
64
+ (Pauli-Z on qubit q, identity elsewhere) only flips the sign of
65
+ off-diagonal entries whose row and column disagree on bit q --
66
+ (Z_q rho Z_q)_ij = rho_ij * s_i * s_j, s_k = -1 if bit q of k else +1
67
+ -- so each qubit's channel (1-p)*rho + p*(Z_q rho Z_q) is one
68
+ elementwise multiply, no explicit operator ever built.
69
+ """
70
+ rho = jnp.asarray(rho, dtype=jnp.complex128)
71
+ dim = rho.shape[0]
72
+ n_qubits = dim.bit_length() - 1
73
+ idx = jnp.arange(dim)
74
+ for q in range(n_qubits):
75
+ sign = 1.0 - 2.0 * ((idx >> q) & 1)
76
+ flip_sign = jnp.outer(sign, sign)
77
+ rho = (1.0 - p) * rho + p * (flip_sign * rho)
78
+ return rho
@@ -0,0 +1,80 @@
1
+ """1/f ("pink") noise: a noise-strength trace with a power-law power
2
+ spectral density, S(f) ~ 1/f^alpha, instead of the flat (white) or
3
+ purely time-local (oscillating, burst) profiles this package's other
4
+ generators produce -- the dominant real decoherence source (flux noise,
5
+ charge noise) in superconducting qubits."""
6
+ import jax
7
+ import jax.numpy as jnp
8
+
9
+ __all__ = ["pink_noise_p_eff"]
10
+
11
+
12
+ def pink_noise_p_eff(base_p: float, n_samples: int, key, alpha: float = 1.0, amp: float = 0.5) -> jnp.ndarray:
13
+ """Effective noise probability trace of length `n_samples` fluctuating
14
+ around `base_p` with a 1/f^alpha power spectrum (`alpha=1.0` is the
15
+ real, standard "pink"/flicker-noise case; other values interpolate
16
+ toward white noise, `alpha=0`, or Brownian noise, `alpha=2`), instead
17
+ of `oscillating_p_eff`'s single deterministic frequency or
18
+ `cosmic_ray_burst_profile`'s one-shot deterministic event -- for
19
+ stress-testing mitigation techniques against the actual dominant
20
+ decoherence mechanism (1/f flux/charge noise) in real superconducting
21
+ hardware, not just synthetic worst cases.
22
+
23
+ Generated by the spectral-synthesis method of Timmer & Koenig (1995,
24
+ "On generating power law noise", Astronomy and Astrophysics 300, 707):
25
+ both the amplitude and the phase of each Fourier component are drawn
26
+ randomly (independent real/imaginary Gaussian draws, giving the
27
+ correct chi-squared-distributed power per bin, not just the correct
28
+ mean spectrum), scaled by `frequency ** (-alpha / 2)` so the power
29
+ spectrum scales as `frequency ** (-alpha)`, then inverse-transformed
30
+ to the time domain -- the standard algorithm for this exact problem,
31
+ not a bespoke construction. The zero-frequency (DC) component is
32
+ fixed to exactly 0, so the trace has zero mean before rescaling.
33
+ Verified during development: the fitted log-log power-spectrum slope
34
+ over 30 independent realizations at `alpha=1.0` is -0.996, matching
35
+ the expected -1 to within numerical/finite-sample tolerance.
36
+
37
+ The resulting zero-mean, unit-variance trace is rescaled to
38
+ `base_p * (1 + amp * trace)` and clipped to `[0.01, 0.5]`, the same
39
+ valid-probability range `oscillating_p_eff` uses, so it can be fed
40
+ directly wherever a per-trial or per-timestep `p` is expected.
41
+
42
+ Parameters
43
+ ----------
44
+ base_p : float
45
+ Center noise probability the trace fluctuates around.
46
+ n_samples : int
47
+ Length of the trace (e.g. one value per Monte Carlo trial, or per
48
+ time step of a trajectory).
49
+ key : jax.random.PRNGKey
50
+ Random key; two independent draws are taken from it internally
51
+ (real and imaginary Fourier-amplitude parts).
52
+ alpha : float
53
+ Spectral exponent: power spectral density ~ `1/frequency**alpha`.
54
+ `1.0` (default) is real 1/f/pink/flicker noise.
55
+ amp : float
56
+ Fractional modulation depth around `base_p`, same role as in
57
+ `oscillating_p_eff`.
58
+
59
+ Examples
60
+ --------
61
+ >>> import jax
62
+ >>> from dense_evolution.noise import pink_noise_p_eff
63
+ >>> trace = pink_noise_p_eff(0.05, 256, jax.random.PRNGKey(0))
64
+ >>> trace.shape
65
+ (256,)
66
+ >>> bool((trace >= 0.01).all() and (trace <= 0.5).all())
67
+ True
68
+ """
69
+ freqs = jnp.fft.rfftfreq(n_samples)
70
+ freqs = freqs.at[0].set(freqs[1]) # avoid a 1/0 singularity at DC; DC amplitude is zeroed below anyway
71
+ key_re, key_im = jax.random.split(key)
72
+ real_part = jax.random.normal(key_re, shape=freqs.shape)
73
+ imag_part = jax.random.normal(key_im, shape=freqs.shape)
74
+ scale = freqs ** (-alpha / 2.0)
75
+ spectrum = (real_part + 1j * imag_part) * scale
76
+ spectrum = spectrum.at[0].set(0.0)
77
+ trace = jnp.fft.irfft(spectrum, n=n_samples)
78
+ trace = (trace - jnp.mean(trace)) / jnp.std(trace)
79
+ p = base_p * (1.0 + amp * trace)
80
+ return jnp.clip(p, 0.01, 0.5)