physicskit 0.1.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (484) hide show
  1. physicskit/__init__.py +51 -0
  2. physicskit/astro/__init__.py +66 -0
  3. physicskit/astro/cosmic_web.py +395 -0
  4. physicskit/astro/galactic_dynamics.py +137 -0
  5. physicskit/astro/nbody.py +208 -0
  6. physicskit/astro/orbital_mechanics.py +220 -0
  7. physicskit/astro/stellar_dynamo.py +628 -0
  8. physicskit/astro/stellar_structure.py +198 -0
  9. physicskit/astro/tests/__init__.py +0 -0
  10. physicskit/astro/tests/conftest.py +7 -0
  11. physicskit/astro/tests/test_cosmic_web.py +159 -0
  12. physicskit/astro/tests/test_galactic_dynamics.py +46 -0
  13. physicskit/astro/tests/test_nbody.py +81 -0
  14. physicskit/astro/tests/test_orbital_mechanics.py +73 -0
  15. physicskit/astro/tests/test_stellar_dynamo.py +198 -0
  16. physicskit/astro/tests/test_stellar_structure.py +52 -0
  17. physicskit/astro/tests/test_visualizers.py +159 -0
  18. physicskit/astro/visualizers.py +628 -0
  19. physicskit/chaos/__init__.py +55 -0
  20. physicskit/chaos/core/__init__.py +3 -0
  21. physicskit/chaos/core/base_system.py +342 -0
  22. physicskit/chaos/core/integrators.py +40 -0
  23. physicskit/chaos/exceptions.py +24 -0
  24. physicskit/chaos/quantum/__init__.py +38 -0
  25. physicskit/chaos/quantum/billiards.py +274 -0
  26. physicskit/chaos/quantum/husimi.py +85 -0
  27. physicskit/chaos/quantum/maps.py +366 -0
  28. physicskit/chaos/systems/__init__.py +38 -0
  29. physicskit/chaos/systems/billiards.py +1131 -0
  30. physicskit/chaos/systems/continuous.py +1276 -0
  31. physicskit/chaos/systems/maps.py +557 -0
  32. physicskit/chaos/tests/__init__.py +0 -0
  33. physicskit/chaos/tests/test_basins.py +76 -0
  34. physicskit/chaos/tests/test_bifurcation.py +132 -0
  35. physicskit/chaos/tests/test_billiards.py +115 -0
  36. physicskit/chaos/tests/test_continuous.py +224 -0
  37. physicskit/chaos/tests/test_dimension.py +69 -0
  38. physicskit/chaos/tests/test_divergence.py +90 -0
  39. physicskit/chaos/tests/test_dynamic_plots.py +269 -0
  40. physicskit/chaos/tests/test_integrators.py +96 -0
  41. physicskit/chaos/tests/test_io.py +41 -0
  42. physicskit/chaos/tests/test_maps.py +110 -0
  43. physicskit/chaos/tests/test_metrics.py +115 -0
  44. physicskit/chaos/tests/test_phase_space.py +73 -0
  45. physicskit/chaos/tests/test_properties.py +116 -0
  46. physicskit/chaos/tests/test_quantum_billiards.py +94 -0
  47. physicskit/chaos/tests/test_quantum_maps.py +144 -0
  48. physicskit/chaos/tests/test_recurrence.py +51 -0
  49. physicskit/chaos/tests/test_repr_and_api_consistency.py +134 -0
  50. physicskit/chaos/tests/test_section.py +49 -0
  51. physicskit/chaos/tests/test_spectral.py +48 -0
  52. physicskit/chaos/tests/test_streamlit_app.py +45 -0
  53. physicskit/chaos/tests/test_timeseries.py +131 -0
  54. physicskit/chaos/tests/test_viewer3d.py +41 -0
  55. physicskit/chaos/utils/__init__.py +46 -0
  56. physicskit/chaos/utils/dimension.py +139 -0
  57. physicskit/chaos/utils/io.py +95 -0
  58. physicskit/chaos/utils/metrics.py +304 -0
  59. physicskit/chaos/utils/recurrence.py +122 -0
  60. physicskit/chaos/utils/spectral.py +69 -0
  61. physicskit/chaos/utils/timeseries.py +303 -0
  62. physicskit/chaos/visualizers/__init__.py +85 -0
  63. physicskit/chaos/visualizers/basins.py +185 -0
  64. physicskit/chaos/visualizers/bifurcation.py +273 -0
  65. physicskit/chaos/visualizers/divergence.py +374 -0
  66. physicskit/chaos/visualizers/dynamic_plots.py +1372 -0
  67. physicskit/chaos/visualizers/phase_space.py +133 -0
  68. physicskit/chaos/visualizers/quantum.py +299 -0
  69. physicskit/chaos/visualizers/recurrence.py +91 -0
  70. physicskit/chaos/visualizers/section.py +161 -0
  71. physicskit/chaos/visualizers/theme.py +31 -0
  72. physicskit/chaos/visualizers/viewer3d.py +82 -0
  73. physicskit/classical/__init__.py +55 -0
  74. physicskit/classical/core/__init__.py +17 -0
  75. physicskit/classical/core/base_system.py +510 -0
  76. physicskit/classical/core/integrators.py +397 -0
  77. physicskit/classical/systems/__init__.py +32 -0
  78. physicskit/classical/systems/chains.py +334 -0
  79. physicskit/classical/systems/hamiltonian.py +215 -0
  80. physicskit/classical/systems/lagrangian.py +308 -0
  81. physicskit/classical/systems/newtonian.py +536 -0
  82. physicskit/classical/systems/rotations.py +614 -0
  83. physicskit/classical/tests/__init__.py +0 -0
  84. physicskit/classical/tests/conftest.py +7 -0
  85. physicskit/classical/tests/test_base_system.py +113 -0
  86. physicskit/classical/tests/test_chains.py +84 -0
  87. physicskit/classical/tests/test_conservation.py +244 -0
  88. physicskit/classical/tests/test_conservation_utils.py +47 -0
  89. physicskit/classical/tests/test_hamiltonian.py +44 -0
  90. physicskit/classical/tests/test_integrators.py +123 -0
  91. physicskit/classical/tests/test_lagrangian.py +69 -0
  92. physicskit/classical/tests/test_newtonian.py +45 -0
  93. physicskit/classical/tests/test_rotations.py +160 -0
  94. physicskit/classical/tests/test_stepsize.py +149 -0
  95. physicskit/classical/tests/test_symbolic.py +125 -0
  96. physicskit/classical/tests/test_visualizers.py +172 -0
  97. physicskit/classical/utils/__init__.py +20 -0
  98. physicskit/classical/utils/conservation.py +126 -0
  99. physicskit/classical/utils/stepsize.py +187 -0
  100. physicskit/classical/utils/symbolic.py +235 -0
  101. physicskit/classical/visualizers/__init__.py +25 -0
  102. physicskit/classical/visualizers/animations.py +508 -0
  103. physicskit/classical/visualizers/interactive.py +113 -0
  104. physicskit/classical/visualizers/modal_analysis.py +97 -0
  105. physicskit/classical/visualizers/phase_space.py +214 -0
  106. physicskit/condensed/__init__.py +122 -0
  107. physicskit/condensed/anderson_localization.py +155 -0
  108. physicskit/condensed/correlated.py +284 -0
  109. physicskit/condensed/ginzburg_landau.py +220 -0
  110. physicskit/condensed/landau_levels.py +246 -0
  111. physicskit/condensed/laughlin.py +229 -0
  112. physicskit/condensed/models.py +627 -0
  113. physicskit/condensed/tests/__init__.py +0 -0
  114. physicskit/condensed/tests/test_condensed.py +518 -0
  115. physicskit/condensed/tests/test_visualizers.py +87 -0
  116. physicskit/condensed/tight_binding.py +445 -0
  117. physicskit/condensed/topological_insulator_3d.py +178 -0
  118. physicskit/condensed/topology.py +217 -0
  119. physicskit/condensed/visualizers.py +296 -0
  120. physicskit/condensed/weyl.py +180 -0
  121. physicskit/constants.py +184 -0
  122. physicskit/fields/__init__.py +111 -0
  123. physicskit/fields/electrodynamics.py +671 -0
  124. physicskit/fields/quantum_fields.py +510 -0
  125. physicskit/fields/solitons.py +527 -0
  126. physicskit/fields/tests/__init__.py +0 -0
  127. physicskit/fields/tests/conftest.py +7 -0
  128. physicskit/fields/tests/test_field_animations.py +154 -0
  129. physicskit/fields/tests/test_fields.py +439 -0
  130. physicskit/fields/tests/test_visualizers.py +101 -0
  131. physicskit/fields/visualizers.py +503 -0
  132. physicskit/fluids/__init__.py +134 -0
  133. physicskit/fluids/core/__init__.py +23 -0
  134. physicskit/fluids/core/grid.py +165 -0
  135. physicskit/fluids/core/timestepping.py +231 -0
  136. physicskit/fluids/exceptions.py +26 -0
  137. physicskit/fluids/systems/__init__.py +70 -0
  138. physicskit/fluids/systems/compressible_flow.py +281 -0
  139. physicskit/fluids/systems/instabilities.py +343 -0
  140. physicskit/fluids/systems/navier_stokes.py +221 -0
  141. physicskit/fluids/systems/potential_flow.py +440 -0
  142. physicskit/fluids/systems/viscous_flow.py +425 -0
  143. physicskit/fluids/systems/vortex_dynamics.py +304 -0
  144. physicskit/fluids/tests/__init__.py +0 -0
  145. physicskit/fluids/tests/conftest.py +7 -0
  146. physicskit/fluids/tests/test_compressible_flow.py +66 -0
  147. physicskit/fluids/tests/test_instabilities.py +115 -0
  148. physicskit/fluids/tests/test_navier_stokes.py +67 -0
  149. physicskit/fluids/tests/test_potential_flow.py +92 -0
  150. physicskit/fluids/tests/test_static_visualizers.py +91 -0
  151. physicskit/fluids/tests/test_utils.py +100 -0
  152. physicskit/fluids/tests/test_viscous_flow.py +110 -0
  153. physicskit/fluids/tests/test_visualizers.py +34 -0
  154. physicskit/fluids/tests/test_vortex_dynamics.py +88 -0
  155. physicskit/fluids/utils/__init__.py +18 -0
  156. physicskit/fluids/utils/dimensionless.py +239 -0
  157. physicskit/fluids/utils/spectral_analysis.py +142 -0
  158. physicskit/fluids/visualizers/__init__.py +14 -0
  159. physicskit/fluids/visualizers/compressible.py +39 -0
  160. physicskit/fluids/visualizers/flow_fields.py +252 -0
  161. physicskit/fluids/visualizers/potential_flow.py +51 -0
  162. physicskit/fluids/visualizers/spectra.py +62 -0
  163. physicskit/fluids/visualizers/theme.py +38 -0
  164. physicskit/integrators/__init__.py +52 -0
  165. physicskit/integrators/adaptive.py +199 -0
  166. physicskit/integrators/fixed_step.py +360 -0
  167. physicskit/integrators/tests/__init__.py +0 -0
  168. physicskit/integrators/tests/test_integrators.py +101 -0
  169. physicskit/optics/__init__.py +124 -0
  170. physicskit/optics/_compat.py +5 -0
  171. physicskit/optics/gaussian.py +382 -0
  172. physicskit/optics/quantum_optics.py +428 -0
  173. physicskit/optics/ray.py +469 -0
  174. physicskit/optics/tests/__init__.py +0 -0
  175. physicskit/optics/tests/test_diffraction_animation.py +38 -0
  176. physicskit/optics/tests/test_gaussian.py +170 -0
  177. physicskit/optics/tests/test_quantum_optics.py +147 -0
  178. physicskit/optics/tests/test_ray.py +177 -0
  179. physicskit/optics/tests/test_visualizers.py +58 -0
  180. physicskit/optics/tests/test_wave.py +146 -0
  181. physicskit/optics/visualizers.py +264 -0
  182. physicskit/optics/wave.py +365 -0
  183. physicskit/particle/__init__.py +152 -0
  184. physicskit/particle/collider.py +382 -0
  185. physicskit/particle/confinement.py +125 -0
  186. physicskit/particle/decays.py +357 -0
  187. physicskit/particle/electroweak.py +300 -0
  188. physicskit/particle/kinematics.py +271 -0
  189. physicskit/particle/neutrinos.py +84 -0
  190. physicskit/particle/nuclear.py +100 -0
  191. physicskit/particle/scattering.py +159 -0
  192. physicskit/particle/tests/__init__.py +0 -0
  193. physicskit/particle/tests/conftest.py +7 -0
  194. physicskit/particle/tests/test_collider.py +119 -0
  195. physicskit/particle/tests/test_confinement.py +42 -0
  196. physicskit/particle/tests/test_decays.py +112 -0
  197. physicskit/particle/tests/test_electroweak.py +97 -0
  198. physicskit/particle/tests/test_kinematics.py +138 -0
  199. physicskit/particle/tests/test_neutrinos.py +36 -0
  200. physicskit/particle/tests/test_nuclear.py +45 -0
  201. physicskit/particle/tests/test_scattering.py +64 -0
  202. physicskit/particle/tests/test_visualizers.py +214 -0
  203. physicskit/particle/visualizers/__init__.py +38 -0
  204. physicskit/particle/visualizers/animations.py +705 -0
  205. physicskit/particle/visualizers/static.py +101 -0
  206. physicskit/plasma/__init__.py +176 -0
  207. physicskit/plasma/acceleration.py +152 -0
  208. physicskit/plasma/instabilities.py +417 -0
  209. physicskit/plasma/kinetic.py +588 -0
  210. physicskit/plasma/mhd.py +463 -0
  211. physicskit/plasma/single_particle.py +562 -0
  212. physicskit/plasma/tests/__init__.py +0 -0
  213. physicskit/plasma/tests/conftest.py +7 -0
  214. physicskit/plasma/tests/test_new_time_domain_features.py +222 -0
  215. physicskit/plasma/tests/test_plasma.py +232 -0
  216. physicskit/plasma/tests/test_visualizers.py +79 -0
  217. physicskit/plasma/turbulence.py +219 -0
  218. physicskit/plasma/visualizers.py +868 -0
  219. physicskit/plasma/waves.py +549 -0
  220. physicskit/quantum/__init__.py +180 -0
  221. physicskit/quantum/_compat.py +20 -0
  222. physicskit/quantum/chapters/__init__.py +0 -0
  223. physicskit/quantum/chapters/entanglement.py +489 -0
  224. physicskit/quantum/chapters/harmonic_spin.py +517 -0
  225. physicskit/quantum/chapters/hydrogen_am.py +292 -0
  226. physicskit/quantum/chapters/perturbation.py +350 -0
  227. physicskit/quantum/chapters/potentials.py +997 -0
  228. physicskit/quantum/chapters/spin.py +306 -0
  229. physicskit/quantum/chapters/wave_packets.py +541 -0
  230. physicskit/quantum/core/__init__.py +0 -0
  231. physicskit/quantum/core/eigensolvers.py +311 -0
  232. physicskit/quantum/core/operators.py +296 -0
  233. physicskit/quantum/core/solvers.py +271 -0
  234. physicskit/quantum/tests/__init__.py +0 -0
  235. physicskit/quantum/tests/conftest.py +7 -0
  236. physicskit/quantum/tests/test_animations.py +225 -0
  237. physicskit/quantum/tests/test_compat.py +43 -0
  238. physicskit/quantum/tests/test_eigensolvers.py +24 -0
  239. physicskit/quantum/tests/test_entanglement.py +127 -0
  240. physicskit/quantum/tests/test_harmonic_spin.py +140 -0
  241. physicskit/quantum/tests/test_hydrogen_am.py +48 -0
  242. physicskit/quantum/tests/test_measure.py +110 -0
  243. physicskit/quantum/tests/test_operators.py +105 -0
  244. physicskit/quantum/tests/test_perturbation.py +112 -0
  245. physicskit/quantum/tests/test_physics_checks.py +131 -0
  246. physicskit/quantum/tests/test_potentials.py +191 -0
  247. physicskit/quantum/tests/test_solvers.py +70 -0
  248. physicskit/quantum/tests/test_spin.py +22 -0
  249. physicskit/quantum/tests/test_unitarity.py +84 -0
  250. physicskit/quantum/tests/test_wave_packets.py +53 -0
  251. physicskit/quantum/utils/__init__.py +0 -0
  252. physicskit/quantum/utils/measure.py +253 -0
  253. physicskit/quantum/visualizers/__init__.py +0 -0
  254. physicskit/quantum/visualizers/bloch_sphere.py +205 -0
  255. physicskit/quantum/visualizers/entanglement.py +58 -0
  256. physicskit/quantum/visualizers/orbitals.py +187 -0
  257. physicskit/quantum/visualizers/phase_space.py +179 -0
  258. physicskit/quantum/visualizers/wavefunctions.py +230 -0
  259. physicskit/relativity/__init__.py +61 -0
  260. physicskit/relativity/chapters/__init__.py +33 -0
  261. physicskit/relativity/chapters/cosmology.py +190 -0
  262. physicskit/relativity/chapters/gw_merger.py +399 -0
  263. physicskit/relativity/chapters/kerr.py +371 -0
  264. physicskit/relativity/chapters/lensing.py +196 -0
  265. physicskit/relativity/chapters/neutron_star.py +149 -0
  266. physicskit/relativity/chapters/schwarzschild.py +412 -0
  267. physicskit/relativity/chapters/timekeeping.py +133 -0
  268. physicskit/relativity/core/__init__.py +12 -0
  269. physicskit/relativity/core/geodesics.py +216 -0
  270. physicskit/relativity/core/kerr_raytracer.py +259 -0
  271. physicskit/relativity/core/raytracer.py +241 -0
  272. physicskit/relativity/core/tensors.py +468 -0
  273. physicskit/relativity/tests/__init__.py +0 -0
  274. physicskit/relativity/tests/test_conservations.py +54 -0
  275. physicskit/relativity/tests/test_constants.py +34 -0
  276. physicskit/relativity/tests/test_cosmology.py +61 -0
  277. physicskit/relativity/tests/test_gw_merger.py +117 -0
  278. physicskit/relativity/tests/test_kerr.py +116 -0
  279. physicskit/relativity/tests/test_kerr_raytracer.py +103 -0
  280. physicskit/relativity/tests/test_lensing.py +75 -0
  281. physicskit/relativity/tests/test_neutron_star.py +48 -0
  282. physicskit/relativity/tests/test_raytracer.py +67 -0
  283. physicskit/relativity/tests/test_schwarzschild.py +126 -0
  284. physicskit/relativity/tests/test_shadow_render.py +81 -0
  285. physicskit/relativity/tests/test_tensors.py +86 -0
  286. physicskit/relativity/tests/test_timekeeping.py +51 -0
  287. physicskit/relativity/tests/test_visualizers_misc.py +115 -0
  288. physicskit/relativity/utils/__init__.py +1 -0
  289. physicskit/relativity/utils/constants.py +232 -0
  290. physicskit/relativity/visualizers/__init__.py +46 -0
  291. physicskit/relativity/visualizers/interactive.py +127 -0
  292. physicskit/relativity/visualizers/shadow_render.py +367 -0
  293. physicskit/relativity/visualizers/spacetime_3d.py +92 -0
  294. physicskit/relativity/visualizers/spacetime_diagrams.py +198 -0
  295. physicskit/relativity/visualizers/wave_plots.py +185 -0
  296. physicskit/rmt/__init__.py +8 -0
  297. physicskit/rmt/ensembles/__init__.py +108 -0
  298. physicskit/rmt/ensembles/banded.py +114 -0
  299. physicskit/rmt/ensembles/base.py +135 -0
  300. physicskit/rmt/ensembles/bdg.py +218 -0
  301. physicskit/rmt/ensembles/chiral.py +308 -0
  302. physicskit/rmt/ensembles/circular.py +104 -0
  303. physicskit/rmt/ensembles/crossover.py +82 -0
  304. physicskit/rmt/ensembles/density_matrix.py +148 -0
  305. physicskit/rmt/ensembles/effective_hamiltonian.py +230 -0
  306. physicskit/rmt/ensembles/embedded.py +207 -0
  307. physicskit/rmt/ensembles/gaussian.py +153 -0
  308. physicskit/rmt/ensembles/ginibre.py +110 -0
  309. physicskit/rmt/ensembles/girko.py +190 -0
  310. physicskit/rmt/ensembles/graph_laplacian.py +92 -0
  311. physicskit/rmt/ensembles/haar.py +57 -0
  312. physicskit/rmt/ensembles/jacobi.py +182 -0
  313. physicskit/rmt/ensembles/poisson.py +77 -0
  314. physicskit/rmt/ensembles/polynomial.py +139 -0
  315. physicskit/rmt/ensembles/pt_symmetric.py +120 -0
  316. physicskit/rmt/ensembles/single_ring.py +170 -0
  317. physicskit/rmt/ensembles/sparse.py +95 -0
  318. physicskit/rmt/ensembles/syk.py +170 -0
  319. physicskit/rmt/ensembles/truncated_unitary.py +80 -0
  320. physicskit/rmt/ensembles/universality.py +92 -0
  321. physicskit/rmt/ensembles/wishart.py +88 -0
  322. physicskit/rmt/py.typed +0 -0
  323. physicskit/rmt/spectrum.py +82 -0
  324. physicskit/rmt/stats/__init__.py +160 -0
  325. physicskit/rmt/stats/characteristic_polynomial.py +77 -0
  326. physicskit/rmt/stats/circular_law.py +54 -0
  327. physicskit/rmt/stats/correlations.py +162 -0
  328. physicskit/rmt/stats/density.py +70 -0
  329. physicskit/rmt/stats/entanglement.py +36 -0
  330. physicskit/rmt/stats/free_probability.py +202 -0
  331. physicskit/rmt/stats/localization.py +338 -0
  332. physicskit/rmt/stats/marchenko_pastur.py +55 -0
  333. physicskit/rmt/stats/pt_symmetric.py +265 -0
  334. physicskit/rmt/stats/ratios.py +110 -0
  335. physicskit/rmt/stats/real_ginibre.py +134 -0
  336. physicskit/rmt/stats/rigidity.py +272 -0
  337. physicskit/rmt/stats/single_ring.py +95 -0
  338. physicskit/rmt/stats/spacing.py +150 -0
  339. physicskit/rmt/stats/tracy_widom.py +175 -0
  340. physicskit/rmt/stats/truncated_unitary.py +40 -0
  341. physicskit/rmt/stats/unfolding.py +37 -0
  342. physicskit/rmt/stats/wachter.py +67 -0
  343. physicskit/rmt/tests/__init__.py +0 -0
  344. physicskit/rmt/tests/cache_utils.py +107 -0
  345. physicskit/rmt/tests/conftest.py +8 -0
  346. physicskit/rmt/tests/test_banded.py +86 -0
  347. physicskit/rmt/tests/test_base.py +29 -0
  348. physicskit/rmt/tests/test_bdg.py +133 -0
  349. physicskit/rmt/tests/test_characteristic_polynomial.py +50 -0
  350. physicskit/rmt/tests/test_chiral.py +273 -0
  351. physicskit/rmt/tests/test_circular.py +225 -0
  352. physicskit/rmt/tests/test_crossover.py +72 -0
  353. physicskit/rmt/tests/test_density.py +23 -0
  354. physicskit/rmt/tests/test_density_matrix.py +181 -0
  355. physicskit/rmt/tests/test_effective_hamiltonian.py +140 -0
  356. physicskit/rmt/tests/test_embedded.py +169 -0
  357. physicskit/rmt/tests/test_free_probability.py +81 -0
  358. physicskit/rmt/tests/test_gaussian_ensembles.py +22 -0
  359. physicskit/rmt/tests/test_gaussian_semicircle.py +127 -0
  360. physicskit/rmt/tests/test_ginibre_circular_law.py +131 -0
  361. physicskit/rmt/tests/test_girko.py +178 -0
  362. physicskit/rmt/tests/test_graph_laplacian.py +102 -0
  363. physicskit/rmt/tests/test_haar.py +118 -0
  364. physicskit/rmt/tests/test_jacobi_wachter.py +136 -0
  365. physicskit/rmt/tests/test_localization.py +240 -0
  366. physicskit/rmt/tests/test_poisson.py +149 -0
  367. physicskit/rmt/tests/test_polynomial.py +107 -0
  368. physicskit/rmt/tests/test_pt_symmetric.py +178 -0
  369. physicskit/rmt/tests/test_random_state.py +19 -0
  370. physicskit/rmt/tests/test_real_ginibre.py +112 -0
  371. physicskit/rmt/tests/test_rigidity_universality.py +167 -0
  372. physicskit/rmt/tests/test_single_ring.py +132 -0
  373. physicskit/rmt/tests/test_spacing_and_ratios.py +122 -0
  374. physicskit/rmt/tests/test_sparse.py +71 -0
  375. physicskit/rmt/tests/test_spectrum.py +27 -0
  376. physicskit/rmt/tests/test_syk.py +136 -0
  377. physicskit/rmt/tests/test_tracy_widom.py +113 -0
  378. physicskit/rmt/tests/test_tridiagonal.py +41 -0
  379. physicskit/rmt/tests/test_truncated_unitary.py +80 -0
  380. physicskit/rmt/tests/test_validation_base.py +25 -0
  381. physicskit/rmt/tests/test_validation_misc.py +67 -0
  382. physicskit/rmt/tests/test_wishart_marchenko_pastur.py +120 -0
  383. physicskit/rmt/utils/__init__.py +0 -0
  384. physicskit/rmt/utils/haar.py +128 -0
  385. physicskit/rmt/utils/random_state.py +24 -0
  386. physicskit/rmt/utils/tridiagonal.py +167 -0
  387. physicskit/rmt/validation/__init__.py +36 -0
  388. physicskit/rmt/validation/base.py +126 -0
  389. physicskit/rmt/validation/circular_law.py +80 -0
  390. physicskit/rmt/validation/marchenko_pastur.py +53 -0
  391. physicskit/rmt/validation/ratio_distribution.py +53 -0
  392. physicskit/rmt/validation/real_ginibre.py +60 -0
  393. physicskit/rmt/validation/sine_kernel.py +57 -0
  394. physicskit/rmt/validation/single_ring.py +68 -0
  395. physicskit/rmt/validation/tracy_widom.py +89 -0
  396. physicskit/rmt/validation/universality.py +100 -0
  397. physicskit/rmt/validation/wachter.py +52 -0
  398. physicskit/rmt/validation/wigner_semicircle.py +40 -0
  399. physicskit/rmt/validation/wigner_surmise.py +58 -0
  400. physicskit/semiclassical/__init__.py +94 -0
  401. physicskit/semiclassical/_compat.py +5 -0
  402. physicskit/semiclassical/core/__init__.py +41 -0
  403. physicskit/semiclassical/core/gutzwiller.py +215 -0
  404. physicskit/semiclassical/core/path_integral.py +594 -0
  405. physicskit/semiclassical/core/propagators.py +579 -0
  406. physicskit/semiclassical/core/wkb.py +308 -0
  407. physicskit/semiclassical/systems/__init__.py +13 -0
  408. physicskit/semiclassical/systems/scarring.py +278 -0
  409. physicskit/semiclassical/tests/__init__.py +0 -0
  410. physicskit/semiclassical/tests/test_gutzwiller.py +35 -0
  411. physicskit/semiclassical/tests/test_path_integral.py +194 -0
  412. physicskit/semiclassical/tests/test_propagators.py +82 -0
  413. physicskit/semiclassical/tests/test_scarring.py +43 -0
  414. physicskit/semiclassical/tests/test_visualizers.py +89 -0
  415. physicskit/semiclassical/tests/test_wkb.py +30 -0
  416. physicskit/semiclassical/visualizers/__init__.py +17 -0
  417. physicskit/semiclassical/visualizers/gutzwiller.py +55 -0
  418. physicskit/semiclassical/visualizers/path_integral.py +195 -0
  419. physicskit/semiclassical/visualizers/propagators.py +89 -0
  420. physicskit/semiclassical/visualizers/scarring.py +146 -0
  421. physicskit/semiclassical/visualizers/wkb.py +55 -0
  422. physicskit/statphys/__init__.py +80 -0
  423. physicskit/statphys/chapters/__init__.py +43 -0
  424. physicskit/statphys/chapters/ehrenfest_urn.py +112 -0
  425. physicskit/statphys/chapters/ising_lattice.py +431 -0
  426. physicskit/statphys/chapters/kpz_growth.py +129 -0
  427. physicskit/statphys/chapters/molecular_dynamics.py +258 -0
  428. physicskit/statphys/chapters/nonequilibrium_work.py +146 -0
  429. physicskit/statphys/chapters/percolation.py +305 -0
  430. physicskit/statphys/chapters/random_walk.py +142 -0
  431. physicskit/statphys/chapters/renormalization.py +148 -0
  432. physicskit/statphys/chapters/sandpile.py +109 -0
  433. physicskit/statphys/chapters/spin_glass.py +275 -0
  434. physicskit/statphys/core/__init__.py +10 -0
  435. physicskit/statphys/core/kpz_engine.py +53 -0
  436. physicskit/statphys/core/md_engine.py +157 -0
  437. physicskit/statphys/core/monte_carlo.py +462 -0
  438. physicskit/statphys/core/random_walk_engine.py +68 -0
  439. physicskit/statphys/core/sandpile_engine.py +52 -0
  440. physicskit/statphys/tests/__init__.py +0 -0
  441. physicskit/statphys/tests/test_dynamics.py +66 -0
  442. physicskit/statphys/tests/test_ehrenfest_urn.py +44 -0
  443. physicskit/statphys/tests/test_finite_size_scaling.py +62 -0
  444. physicskit/statphys/tests/test_interactive.py +33 -0
  445. physicskit/statphys/tests/test_ising.py +68 -0
  446. physicskit/statphys/tests/test_kpz.py +55 -0
  447. physicskit/statphys/tests/test_landau_theory.py +49 -0
  448. physicskit/statphys/tests/test_md_engine.py +31 -0
  449. physicskit/statphys/tests/test_molecular_dynamics.py +72 -0
  450. physicskit/statphys/tests/test_nonequilibrium_work.py +33 -0
  451. physicskit/statphys/tests/test_partition_function.py +26 -0
  452. physicskit/statphys/tests/test_percolation.py +116 -0
  453. physicskit/statphys/tests/test_potts_model.py +46 -0
  454. physicskit/statphys/tests/test_random_walk.py +50 -0
  455. physicskit/statphys/tests/test_renormalization.py +44 -0
  456. physicskit/statphys/tests/test_sandpile.py +44 -0
  457. physicskit/statphys/tests/test_spin_glass.py +73 -0
  458. physicskit/statphys/tests/test_thermodynamics.py +121 -0
  459. physicskit/statphys/tests/test_xy_model.py +45 -0
  460. physicskit/statphys/utils/__init__.py +1 -0
  461. physicskit/statphys/utils/dynamics.py +100 -0
  462. physicskit/statphys/utils/finite_size_scaling.py +171 -0
  463. physicskit/statphys/utils/landau_theory.py +151 -0
  464. physicskit/statphys/utils/partition_function.py +109 -0
  465. physicskit/statphys/utils/thermodynamics.py +356 -0
  466. physicskit/statphys/visualizers/__init__.py +87 -0
  467. physicskit/statphys/visualizers/interactive.py +161 -0
  468. physicskit/statphys/visualizers/jarzynski_render.py +44 -0
  469. physicskit/statphys/visualizers/kpz_render.py +65 -0
  470. physicskit/statphys/visualizers/lattice_render.py +212 -0
  471. physicskit/statphys/visualizers/particle_render.py +121 -0
  472. physicskit/statphys/visualizers/random_walk_render.py +106 -0
  473. physicskit/statphys/visualizers/rg_render.py +45 -0
  474. physicskit/statphys/visualizers/sandpile_render.py +65 -0
  475. physicskit/statphys/visualizers/spin_glass_render.py +40 -0
  476. physicskit/statphys/visualizers/urn_render.py +38 -0
  477. physicskit/statphys/visualizers/vortex_render.py +84 -0
  478. physicskit/tests/__init__.py +0 -0
  479. physicskit/tests/test_constants.py +38 -0
  480. physicskit-0.1.0.dist-info/METADATA +196 -0
  481. physicskit-0.1.0.dist-info/RECORD +484 -0
  482. physicskit-0.1.0.dist-info/WHEEL +5 -0
  483. physicskit-0.1.0.dist-info/licenses/LICENSE +21 -0
  484. physicskit-0.1.0.dist-info/top_level.txt +1 -0
@@ -0,0 +1,104 @@
1
+ """Circular ensembles -- COE, CUE, CSE.
2
+
3
+ References
4
+ ----------
5
+ F. J. Dyson, "Statistical Theory of the Energy Levels of Complex Systems
6
+ I-III", J. Math. Phys. 3 (1962) 140, 157, 166 -- the original
7
+ circular-ensemble classification, and the source of Dyson's beta=1,2,4
8
+ threefold way.
9
+ F. Mezzadri, Notices Amer. Math. Soc. 54 (2007) 592 -- the Haar-random
10
+ sampling recipe used here.
11
+
12
+ Important construction note (this is easy to get wrong): COE and CSE
13
+ are NOT simply "eigenvalues of a Haar-random matrix from O(n) / Sp(n)".
14
+ A real orthogonal matrix's eigenvalues are either +-1 or complex-conjugate
15
+ pairs -- not the generic unit-circle structure a circular ensemble
16
+ requires. Dyson's actual constructions::
17
+
18
+ CUE: eigenvalues of U, U Haar-random from U(n).
19
+ COE: eigenvalues of U = V^T V, V Haar-random from U(n) -- a
20
+ *symmetric* unitary matrix, built from a unitary building block.
21
+ CSE: eigenvalues of U = V^R V, V Haar-random from U(2n), where
22
+ V^R = Z V^T Z^{-1} is the symplectic dual (Z the symplectic
23
+ form). U is self-dual unitary; its 2n eigenvalues come in n
24
+ doubly-degenerate pairs, of which n distinct values are the CSE
25
+ eigenvalues.
26
+
27
+ All three were verified during development by checking their unfolded
28
+ level-spacing statistics against the already-validated (generalized)
29
+ Wigner surmise at the matching beta -- see ``tests/test_circular.py``.
30
+ This is a meaningful cross-family check: spacing statistics are
31
+ universal in beta across the Gaussian and circular families, so
32
+ agreement here is independent evidence the constructions are correct,
33
+ not just that "some points ended up on a circle".
34
+
35
+ Eigenvalue representation: ``Spectrum.eigenvalues`` for these ensembles
36
+ holds the eigenvalue *phases* theta in [0, 2*pi), not the complex
37
+ eigenvalues e^{i*theta} themselves -- this keeps the rest of the
38
+ (real-array-based) stats machinery directly usable. ``natural_scale`` is
39
+ set to 2*pi/n, so ``Spectrum.rescaled`` is already fully unfolded with
40
+ exactly unit mean spacing -- exactly, not just asymptotically, since
41
+ Haar measure is exactly rotation-invariant at any finite n. This is a
42
+ structural simplification relative to the Gaussian/Wishart ensembles,
43
+ which only have unit mean spacing after unfolding against their
44
+ (asymptotic) limiting density.
45
+ """
46
+
47
+ import numpy as np
48
+
49
+ from ..utils.haar import haar_unitary, symplectic_form
50
+ from .base import MatrixEnsemble
51
+
52
+
53
+ class COE(MatrixEnsemble):
54
+ """Circular Orthogonal Ensemble (beta=1)."""
55
+
56
+ beta: float = 1
57
+
58
+ def _sample_eigenvalues(self, rng: np.random.Generator) -> np.ndarray:
59
+ v = haar_unitary(self.n, rng)
60
+ u = v.T @ v # symmetric unitary
61
+ eigs = np.linalg.eigvals(u)
62
+ return np.sort(np.angle(eigs) % (2.0 * np.pi))
63
+
64
+ def natural_scale(self) -> float:
65
+ return 2.0 * np.pi / self.n
66
+
67
+
68
+ class CUE(MatrixEnsemble):
69
+ """Circular Unitary Ensemble (beta=2)."""
70
+
71
+ beta: float = 2
72
+
73
+ def _sample_eigenvalues(self, rng: np.random.Generator) -> np.ndarray:
74
+ u = haar_unitary(self.n, rng)
75
+ eigs = np.linalg.eigvals(u)
76
+ return np.sort(np.angle(eigs) % (2.0 * np.pi))
77
+
78
+ def natural_scale(self) -> float:
79
+ return 2.0 * np.pi / self.n
80
+
81
+
82
+ class CSE(MatrixEnsemble):
83
+ """Circular Symplectic Ensemble (beta=4).
84
+
85
+ ``n`` here is the number of *distinct* CSE eigenvalues; internally a
86
+ Haar-random matrix of size 2n is used (each eigenvalue of the dual
87
+ construction is doubly degenerate).
88
+ """
89
+
90
+ beta: float = 4
91
+
92
+ def _sample_eigenvalues(self, rng: np.random.Generator) -> np.ndarray:
93
+ n2 = 2 * self.n
94
+ v = haar_unitary(n2, rng)
95
+ z = symplectic_form(n2)
96
+ v_dual = (-z) @ v.T @ z # Z^{-1} = -Z since Z^2 = -I
97
+ u = v_dual @ v
98
+ eigs = np.linalg.eigvals(u)
99
+ theta = np.sort(np.angle(eigs) % (2.0 * np.pi))
100
+ # Degenerate pairs are adjacent after sorting; keep one of each.
101
+ return theta[0::2]
102
+
103
+ def natural_scale(self) -> float:
104
+ return 2.0 * np.pi / self.n
@@ -0,0 +1,82 @@
1
+ """The Pandey-Mehta GOE-GUE crossover ensemble: a continuous
2
+ symmetry-breaking deformation interpolating between time-reversal-
3
+ symmetric (GOE, beta=1) and time-reversal-broken (GUE, beta=2) level
4
+ statistics.
5
+
6
+ References
7
+ ----------
8
+ A. Pandey, M. L. Mehta, "Gaussian ensembles of random Hermitian
9
+ matrices intermediate between orthogonal and unitary ones", Commun.
10
+ Math. Phys. 87 (1982) 449.
11
+ F. J. Dyson, "A Brownian-motion model for the eigenvalues of a random
12
+ matrix", J. Math. Phys. 3 (1962) 1191 -- the same crossover realized as
13
+ a continuous-time stochastic (Dyson Brownian motion) process; the
14
+ static construction here is the same family at one fixed "time".
15
+
16
+ Construction: H(lambda) = A + i*lambda*B, for A an independent real
17
+ symmetric (GOE-type) matrix and B an independent real ANTIsymmetric
18
+ matrix (so i*B is Hermitian: (i*B)^dagger = -i*B^dagger = -i*(-B) =
19
+ i*B). H is Hermitian for any real lambda. lambda=0 recovers GOE exactly
20
+ (H = A); as lambda grows, the added antisymmetric-times-i piece breaks
21
+ time-reversal symmetry, and level statistics cross over toward GUE.
22
+
23
+ Verified numerically during development (see
24
+ ``tests/test_crossover.py``): the raw eigenvalue spread grows as
25
+ ``sqrt(n*(1+lambda^2))`` (each off-diagonal entry's variance is
26
+ Var(A_ij) + lambda^2*Var(B_ij) = 1 + lambda^2, by independence),
27
+ confirmed by checking the empirical eigenvalue standard deviation
28
+ against this formula at several (n, lambda) pairs before using it as
29
+ ``natural_scale``. The consecutive-spacing-ratio statistic
30
+ (``physicskit.rmt.stats.ratios.ratio_statistics``, no unfolding needed) was
31
+ checked against both the GOE and GUE surmises across a lambda sweep at
32
+ n=400: KS distance to the GOE surmise is smallest at lambda=0 (0.013)
33
+ and grows monotonically; KS distance to the GUE surmise is smallest by
34
+ lambda~0.1 (0.012) -- a genuine, verified crossover, with the
35
+ half-way point falling at a small lambda (roughly 0.03-0.05 at n=400),
36
+ consistent with the well-known finite-size scaling of this crossover
37
+ (the transition lambda shrinks like 1/sqrt(n) as n grows) -- that
38
+ specific scaling law itself is not derived or asserted exactly here.
39
+ """
40
+
41
+ from __future__ import annotations
42
+
43
+ import numpy as np
44
+
45
+ from .base import MatrixEnsemble
46
+
47
+
48
+ class GOEGUECrossoverEnsemble(MatrixEnsemble):
49
+ """Pandey-Mehta GOE-GUE crossover ensemble (see module docstring):
50
+ H = A + i*lambda*B, A real symmetric, B real antisymmetric.
51
+
52
+ Parameters
53
+ ----------
54
+ n : int
55
+ Matrix dimension.
56
+ lam : float
57
+ Symmetry-breaking (time-reversal-breaking) crossover parameter.
58
+ lam=0 recovers GOE exactly; lam -> infinity approaches GUE-like
59
+ statistics (at a lam scale that shrinks with n -- see module
60
+ docstring).
61
+ seed : int, numpy.random.Generator, or None, optional
62
+ """
63
+
64
+ def __init__(self, n: int, lam: float, seed: int | np.random.Generator | None = None) -> None:
65
+ if lam < 0:
66
+ raise ValueError(f"lam must be >= 0, got {lam}")
67
+ super().__init__(n, seed=seed)
68
+ self.lam = float(lam)
69
+
70
+ def _sample_eigenvalues(self, rng: np.random.Generator) -> np.ndarray:
71
+ n = self.n
72
+ x = rng.standard_normal((n, n))
73
+ a = (x + x.T) / np.sqrt(2.0)
74
+ y = rng.standard_normal((n, n))
75
+ b = (y - y.T) / np.sqrt(2.0)
76
+ h = a + 1j * self.lam * b
77
+ return np.linalg.eigvalsh(h)
78
+
79
+ def natural_scale(self) -> float:
80
+ # Verified numerically (see module docstring): raw eigenvalue
81
+ # spread grows as sqrt(n*(1+lambda^2)).
82
+ return np.sqrt(self.n * (1.0 + self.lam**2))
@@ -0,0 +1,148 @@
1
+ """Random quantum state (density matrix) ensembles: the induced measure
2
+ (Hilbert-Schmidt as its special case) and the Bures-Hall measure.
3
+
4
+ References
5
+ ----------
6
+ K. Zyczkowski, H.-J. Sommers, "Induced measures in the space of mixed
7
+ quantum states", J. Phys. A 34 (2001) 7111 -- the induced-measure
8
+ construction, its joint eigenvalue density, and the mean-purity formula
9
+ used for validation here.
10
+ D. N. Page, "Average entropy of a subsystem", Phys. Rev. Lett. 71
11
+ (1993) 1291 -- the exact average-entanglement-entropy formula (the
12
+ "Page curve"), realized directly by this ensemble at general k -- see
13
+ below.
14
+ K. Zyczkowski, K. A. Penson, I. Nechita, B. Collins, "Generating random
15
+ density matrices", J. Math. Phys. 52 (2011) 062201 -- survey covering
16
+ both measures used here.
17
+ V. Osipov, H.-J. Sommers, K. Zyczkowski, "Random Bures mixed states and
18
+ the distribution of their purity", J. Phys. A 43 (2010) 055302 -- the
19
+ Bures-Hall construction and joint eigenvalue density.
20
+ J. Hall, "Random quantum correlations and density operator
21
+ distributions", Phys. Lett. A 242 (1998) 123 -- the original Bures-Hall
22
+ measure.
23
+
24
+ Induced measure (and its Hilbert-Schmidt special case)
25
+ --------------------------------------------------------
26
+ A Haar-random pure state on C^n (x) C^k (n <= k WLOG), traced out over
27
+ the k-dimensional second factor, gives a reduced density matrix on the
28
+ n-dimensional first factor distributed EXACTLY as
29
+
30
+ rho = A @ A^dagger / Tr(A @ A^dagger)
31
+
32
+ for A an n x k complex Ginibre matrix -- the "induced measure" with
33
+ environment dimension k (Zyczkowski-Sommers 2001). k=n is the
34
+ Hilbert-Schmidt measure (the flat/uniform measure induced by the
35
+ natural volume element on the space of density matrices);
36
+ k -> infinity concentrates rho near the maximally mixed state I/n; k=1
37
+ forces A to be a single column, so A @ A^dagger is rank 1 and rho is
38
+ exactly a Haar-random PURE state (a rank-1 projector).
39
+
40
+ This SAME construction is, with no modification, exactly the standard
41
+ matrix model used to study the "Page curve": since A n x k IS the
42
+ (unnormalized) reduced density matrix of a random bipartite pure state
43
+ on C^n (x) C^k, ``InducedMeasureEnsemble(n, k)`` directly generates that
44
+ bipartite ensemble too -- ``physicskit.rmt.stats.entanglement`` provides the
45
+ matching von Neumann entropy calculation and Page's (1993) exact average
46
+ -- see ``tests/test_density_matrix.py`` for the verification (both the
47
+ mean-purity formula (n+k)/(n*k+1) and Page's average-entropy formula
48
+ were checked directly against Monte Carlo, at several (n, k) pairs,
49
+ before being trusted here).
50
+
51
+ Bures-Hall measure
52
+ -------------------
53
+ A genuinely different, non-Hilbert-Schmidt measure on density matrices,
54
+ induced by the Bures (fidelity) metric rather than the flat
55
+ Hilbert-Schmidt one. Realized here as
56
+
57
+ rho = (I + U) @ G @ G^dagger @ (I + U)^dagger / Tr(...)
58
+
59
+ for G an independent n x n complex Ginibre matrix and U an independent
60
+ Haar-random unitary (Osipov-Sommers-Zyczkowski 2010). This construction
61
+ was verified directly here (not assumed from a remembered formula, given
62
+ how easy this measure is to get subtly wrong) by comparing Monte Carlo
63
+ samples against the EXACT joint eigenvalue density
64
+
65
+ P(lambda) ~ prod_{i<j} (lambda_i-lambda_j)^2 / (lambda_i+lambda_j)
66
+ * prod_i lambda_i^(-1/2), sum_i lambda_i = 1
67
+
68
+ at n=2 (closed-form 1-D marginal, checked via a KS test) and n=3
69
+ (2-D numerical integration over the simplex, checked via mean purity) --
70
+ both matched to within Monte Carlo noise; see ``tests/test_density_matrix.py``.
71
+
72
+ Unlike the induced measure (whose joint density is a pure Vandermonde
73
+ power ``|Delta(lambda)|^2``, exactly the classical Dyson beta=2 form, so
74
+ ``beta=2`` is used below), the Bures-Hall joint density has the EXTRA
75
+ prod 1/(lambda_i+lambda_j) factor -- not one of Dyson's classical
76
+ beta-ensembles, so ``beta`` is left ``None`` for it.
77
+
78
+ All three ensembles return eigenvalues already in the natural [0, 1]
79
+ range, summing to 1 (a genuine probability distribution) --
80
+ ``natural_scale`` is 1.0 throughout, no rescaling needed.
81
+ """
82
+
83
+ from __future__ import annotations
84
+
85
+ import numpy as np
86
+
87
+ from ..utils.haar import haar_unitary
88
+ from .base import MatrixEnsemble
89
+
90
+
91
+ class InducedMeasureEnsemble(MatrixEnsemble):
92
+ """Induced-measure random density matrix: rho = A @ A^dagger / Tr(...)
93
+ for an n x k complex Ginibre matrix A.
94
+
95
+ Parameters
96
+ ----------
97
+ n : int
98
+ Dimension of the density matrix (the traced-IN subsystem).
99
+ k : int, optional
100
+ Environment/other-subsystem dimension (default: n, the
101
+ Hilbert-Schmidt measure). k=1 gives Haar-random pure states.
102
+ """
103
+
104
+ beta: float = 2
105
+
106
+ def __init__(self, n: int, k: int | None = None, seed: int | np.random.Generator | None = None) -> None:
107
+ k = n if k is None else k
108
+ if k < 1:
109
+ raise ValueError(f"k must be >= 1, got {k}")
110
+ super().__init__(n, seed=seed)
111
+ self.k = k
112
+
113
+ def _sample_eigenvalues(self, rng: np.random.Generator) -> np.ndarray:
114
+ a = (rng.standard_normal((self.n, self.k)) + 1j * rng.standard_normal((self.n, self.k))) / np.sqrt(2.0)
115
+ rho = a @ a.conj().T
116
+ rho = rho / np.trace(rho).real
117
+ rho = (rho + rho.conj().T) / 2.0
118
+ return np.linalg.eigvalsh(rho)
119
+
120
+ def natural_scale(self) -> float:
121
+ return 1.0
122
+
123
+
124
+ class HilbertSchmidtEnsemble(InducedMeasureEnsemble):
125
+ """Hilbert-Schmidt random density matrix: the k=n special case of
126
+ :class:`InducedMeasureEnsemble` (the flat/uniform measure on the
127
+ space of n x n density matrices)."""
128
+
129
+ def __init__(self, n: int, seed: int | np.random.Generator | None = None) -> None:
130
+ super().__init__(n, k=n, seed=seed)
131
+
132
+
133
+ class BuresHallEnsemble(MatrixEnsemble):
134
+ """Bures-Hall random density matrix (see module docstring)."""
135
+
136
+ def _sample_eigenvalues(self, rng: np.random.Generator) -> np.ndarray:
137
+ n = self.n
138
+ g = (rng.standard_normal((n, n)) + 1j * rng.standard_normal((n, n))) / np.sqrt(2.0)
139
+ w = g @ g.conj().T
140
+ u = haar_unitary(n, rng)
141
+ ip = np.eye(n) + u
142
+ rho = ip @ w @ ip.conj().T
143
+ rho = rho / np.trace(rho).real
144
+ rho = (rho + rho.conj().T) / 2.0
145
+ return np.linalg.eigvalsh(rho)
146
+
147
+ def natural_scale(self) -> float:
148
+ return 1.0
@@ -0,0 +1,230 @@
1
+ """Non-Hermitian effective Hamiltonians for open quantum systems (Feshbach
2
+ projection / chaotic-scattering resonance ensembles).
3
+
4
+ References
5
+ ----------
6
+ V.V. Sokolov, V.G. Zelevinsky, "Dynamics and statistics of unstable
7
+ quantum states", Nucl. Phys. A 504 (1989) 562.
8
+ Y.V. Fyodorov, H.-J. Sommers, "Statistics of resonance poles, phase
9
+ shifts and time delays in quantum chaotic scattering: Random matrix
10
+ approach for systems with broken time-reversal invariance", J. Math.
11
+ Phys. 38 (1997) 1918.
12
+ Y.V. Fyodorov, D.V. Savin, H.-J. Sommers, "Scattering, reflection and
13
+ impedance of waves in chaotic and disordered systems with absorption",
14
+ J. Phys. A 38 (2005) 10731 (review).
15
+
16
+ Physical picture
17
+ -----------------
18
+ A quantum system with N internal levels, coupled to M open decay/
19
+ scattering channels, is no longer described by a Hermitian Hamiltonian
20
+ once the continuum is eliminated via a Feshbach projection: the
21
+ resulting effective Hamiltonian is
22
+
23
+ H_eff = H - (i / 2) * coupling**2 * V @ V^dagger
24
+
25
+ where H (N x N) is drawn from the closed-system ensemble (GOE/GUE/GSE)
26
+ and V (N x M) collects the amplitudes coupling each internal level to
27
+ each open channel, drawn from the matching Dyson symmetry class.
28
+ Complex eigenvalues E_k - i*Gamma_k/2 of H_eff are resonance poles:
29
+ Re(E_k) are resonance positions, Gamma_k >= 0 are widths (decay rates).
30
+ beta = 1, 2, 4 fixes both H's and V's symmetry class together
31
+ (time-reversal-invariant / broken / self-dual), so this is the direct
32
+ non-Hermitian analogue of GOE/GUE/GSE, not an unrelated construction --
33
+ see :class:`EffGOE`, :class:`EffGUE`, :class:`EffGSE`.
34
+
35
+ ``m`` (number of open channels) controls the openness of the system::
36
+
37
+ m=0: recovers the parent Hermitian ensemble exactly
38
+ (H_eff = H, eigenvalues real to machine precision).
39
+ m << n: weak-coupling/isolated-resonance regime.
40
+ m ~ n or m >> n: strong-coupling/overlapping-resonance regime --
41
+ "resonance trapping", where a few short-lived
42
+ states absorb most of the total decay width and
43
+ n-m long-lived states remain.
44
+
45
+ Causality (widths are never negative): for ANY complex vector x with
46
+ H_eff @ x = lam * x,
47
+
48
+ lam = (x^dagger @ H @ x - (i/2) * x^dagger @ Gamma @ x) / (x^dagger @ x)
49
+
50
+ where Gamma = coupling**2 * V @ V^dagger. x^dagger @ H @ x and
51
+ x^dagger @ x are real (H Hermitian), and x^dagger @ Gamma @ x is real
52
+ and >= 0 (Gamma Hermitian positive semi-definite), so
53
+ Im(lam) = -(x^dagger @ Gamma @ x) / (2 * x^dagger @ x) <= 0 always --
54
+ this holds for every eigenvalue of every realization, not just on
55
+ average, regardless of beta, n, or m. See ``tests/test_effective_hamiltonian.py``.
56
+
57
+ beta=4 (:class:`EffGSE`) construction note: both H and V are built from
58
+ 2x2 quaternion blocks (the same embedding as :class:`~physicskit.rmt.ensembles.ginibre.GinSE`),
59
+ so H is quaternionic self-dual Hermitian and Gamma = V @ V^dagger is
60
+ quaternionic self-dual Hermitian PSD (the quaternion embedding is an
61
+ algebra homomorphism, so products and adjoints of embedded matrices stay
62
+ embedded). H_eff = H - (i/2)*Gamma is therefore a sum of two self-dual
63
+ matrices and, verified numerically during development (to ~1e-14,
64
+ machine precision -- see the test suite), its 2n eigenvalues retain
65
+ Kramers' exact two-fold degeneracy even though H_eff itself is not
66
+ Hermitian -- the same true degeneracy GSE itself has, unlike
67
+ :class:`~physicskit.rmt.ensembles.ginibre.GinSE`'s *distinct* conjugate pairs.
68
+ Only the n distinct values are returned (one representative per
69
+ degenerate pair), mirroring :class:`~physicskit.rmt.ensembles.circular.CSE`.
70
+ """
71
+
72
+ from __future__ import annotations
73
+
74
+ import numpy as np
75
+
76
+ from .base import MatrixEnsemble
77
+
78
+
79
+ def _quaternion_block_embedding(rows: int, cols: int, rng: np.random.Generator) -> np.ndarray:
80
+ """N x M quaternion matrix, embedded as a 2N x 2M complex matrix via
81
+ the standard quaternion-to-2x2-complex-block map (same convention as
82
+ ``physicskit.rmt.ensembles.ginibre.GinSE``)."""
83
+ a = rng.standard_normal((rows, cols))
84
+ b = rng.standard_normal((rows, cols))
85
+ c = rng.standard_normal((rows, cols))
86
+ d = rng.standard_normal((rows, cols))
87
+ m = np.zeros((2 * rows, 2 * cols), dtype=complex)
88
+ m[0::2, 0::2] = a + 1j * b
89
+ m[0::2, 1::2] = c + 1j * d
90
+ m[1::2, 0::2] = -c + 1j * d
91
+ m[1::2, 1::2] = a - 1j * b
92
+ return m
93
+
94
+
95
+ def _sample_hamiltonian(n: int, rng: np.random.Generator, beta: float) -> np.ndarray:
96
+ """Dense closed-system Hamiltonian H for the given Dyson index."""
97
+ if beta == 1:
98
+ x = rng.standard_normal((n, n))
99
+ return (x + x.T) / np.sqrt(2.0)
100
+ if beta == 2:
101
+ x = (rng.standard_normal((n, n)) + 1j * rng.standard_normal((n, n))) / np.sqrt(2.0)
102
+ return (x + x.conj().T) / 2.0
103
+ if beta == 4:
104
+ m = _quaternion_block_embedding(n, n, rng)
105
+ return (m + m.conj().T) / 2.0 # quaternionic self-dual Hermitian
106
+ raise ValueError(f"beta must be 1, 2, or 4, got {beta}")
107
+
108
+
109
+ def _sample_coupling(n: int, m: int, rng: np.random.Generator, beta: float) -> np.ndarray:
110
+ """Dense N x M (or, for beta=4, 2N x 2M) coupling matrix V."""
111
+ if beta == 1:
112
+ return rng.standard_normal((n, m))
113
+ if beta == 2:
114
+ return (rng.standard_normal((n, m)) + 1j * rng.standard_normal((n, m))) / np.sqrt(2.0)
115
+ if beta == 4:
116
+ return _quaternion_block_embedding(n, m, rng) / np.sqrt(2.0)
117
+ raise ValueError(f"beta must be 1, 2, or 4, got {beta}")
118
+
119
+
120
+ class EffectiveHamiltonianEnsemble(MatrixEnsemble):
121
+ """Non-Hermitian effective Hamiltonian H_eff = H - (i/2) * coupling**2 * V @ V^dagger.
122
+
123
+ Use the named subclasses (:class:`EffGOE`, :class:`EffGUE`,
124
+ :class:`EffGSE`) for the classical beta=1,2,4 cases.
125
+
126
+ Parameters
127
+ ----------
128
+ n : int
129
+ Dimension of the closed system (number of resonances).
130
+ m : int
131
+ Number of open decay/scattering channels (m=0 recovers the
132
+ parent Hermitian ensemble exactly).
133
+ beta : {1, 2, 4}
134
+ Dyson index shared by the parent Hamiltonian H and the coupling
135
+ matrix V.
136
+ coupling : float, optional
137
+ Overall coupling strength scaling V (default 1.0); larger values
138
+ drive the system from the isolated-resonance regime towards
139
+ resonance trapping without changing beta or the number of
140
+ channels m.
141
+ """
142
+
143
+ def __init__(
144
+ self,
145
+ n: int,
146
+ m: int,
147
+ beta: int,
148
+ coupling: float = 1.0,
149
+ seed: int | np.random.Generator | None = None,
150
+ ) -> None:
151
+ if beta not in (1, 2, 4):
152
+ raise ValueError(f"beta must be 1, 2, or 4, got {beta}")
153
+ if m < 0:
154
+ raise ValueError(f"m (number of open channels) must be >= 0, got {m}")
155
+ super().__init__(n, seed=seed)
156
+ self.m = m
157
+ self.beta: float = beta
158
+ self.coupling = float(coupling)
159
+
160
+ def _sample_eigenvalues(self, rng: np.random.Generator) -> np.ndarray:
161
+ n, m, beta = self.n, self.m, self.beta
162
+ h = _sample_hamiltonian(n, rng, beta)
163
+ if m > 0:
164
+ v = self.coupling * _sample_coupling(n, m, rng, beta)
165
+ gamma = v @ v.conj().T
166
+ else:
167
+ gamma = np.zeros_like(h)
168
+ h_eff = h - 0.5j * gamma
169
+ eigs = np.linalg.eigvals(h_eff)
170
+ if beta == 4:
171
+ # Exact Kramers double degeneracy (see module docstring) --
172
+ # keep one representative per pair, as CSE does.
173
+ order = np.lexsort((eigs.imag, eigs.real))
174
+ eigs = eigs[order][0::2]
175
+ return eigs.astype(complex)
176
+
177
+ def natural_scale(self) -> float:
178
+ # Re(eigenvalues) inherit the parent Hermitian ensemble's level
179
+ # scale (exactly, at m=0; approximately for weak-to-moderate
180
+ # coupling) -- see HermiteBetaEnsemble.natural_scale. Widths
181
+ # (Im part) have no comparably universal n-independent scale --
182
+ # they depend on m and coupling as well as n -- so this factor
183
+ # should be treated as a Re-axis convenience, not a full
184
+ # normalization of the complex plane.
185
+ return np.sqrt(self.n * self.beta)
186
+
187
+
188
+ class EffGOE(EffectiveHamiltonianEnsemble):
189
+ """Effective Hamiltonian built on GOE (beta=1): time-reversal
190
+ invariant closed system, real coupling to the open channels."""
191
+
192
+ def __init__(
193
+ self,
194
+ n: int,
195
+ m: int,
196
+ coupling: float = 1.0,
197
+ seed: int | np.random.Generator | None = None,
198
+ ) -> None:
199
+ super().__init__(n, m, beta=1, coupling=coupling, seed=seed)
200
+
201
+
202
+ class EffGUE(EffectiveHamiltonianEnsemble):
203
+ """Effective Hamiltonian built on GUE (beta=2): broken time-reversal
204
+ symmetry, complex coupling to the open channels."""
205
+
206
+ def __init__(
207
+ self,
208
+ n: int,
209
+ m: int,
210
+ coupling: float = 1.0,
211
+ seed: int | np.random.Generator | None = None,
212
+ ) -> None:
213
+ super().__init__(n, m, beta=2, coupling=coupling, seed=seed)
214
+
215
+
216
+ class EffGSE(EffectiveHamiltonianEnsemble):
217
+ """Effective Hamiltonian built on GSE (beta=4): self-dual
218
+ (Kramers-degenerate) closed system, quaternionic coupling to the
219
+ open channels. ``n`` is the quaternionic dimension; each sample
220
+ produces n distinct complex resonances (each an exact Kramers pair
221
+ internally -- see module docstring)."""
222
+
223
+ def __init__(
224
+ self,
225
+ n: int,
226
+ m: int,
227
+ coupling: float = 1.0,
228
+ seed: int | np.random.Generator | None = None,
229
+ ) -> None:
230
+ super().__init__(n, m, beta=4, coupling=coupling, seed=seed)