dense-evolution 8.1.7__tar.gz → 8.1.9__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 (23) hide show
  1. {dense_evolution-8.1.7 → dense_evolution-8.1.9}/PKG-INFO +90 -3
  2. {dense_evolution-8.1.7 → dense_evolution-8.1.9}/README.md +89 -2
  3. {dense_evolution-8.1.7 → dense_evolution-8.1.9}/dense_evolution/__init__.py +2 -1
  4. {dense_evolution-8.1.7 → dense_evolution-8.1.9}/dense_evolution/chunk.py +10 -0
  5. {dense_evolution-8.1.7 → dense_evolution-8.1.9}/dense_evolution/healing.py +2 -2
  6. {dense_evolution-8.1.7 → dense_evolution-8.1.9}/dense_evolution/parser.py +28 -6
  7. {dense_evolution-8.1.7 → dense_evolution-8.1.9}/dense_evolution.egg-info/PKG-INFO +90 -3
  8. {dense_evolution-8.1.7 → dense_evolution-8.1.9}/dense_evolution.egg-info/SOURCES.txt +0 -2
  9. {dense_evolution-8.1.7 → dense_evolution-8.1.9}/ia_utils/vector_healing.py +13 -19
  10. {dense_evolution-8.1.7 → dense_evolution-8.1.9}/pyproject.toml +1 -1
  11. dense_evolution-8.1.7/dense_evolution/stress_test.py +0 -76
  12. dense_evolution-8.1.7/dense_evolution/test2.py +0 -76
  13. {dense_evolution-8.1.7 → dense_evolution-8.1.9}/dash.py +0 -0
  14. {dense_evolution-8.1.7 → dense_evolution-8.1.9}/dense_evolution/compiler.py +0 -0
  15. {dense_evolution-8.1.7 → dense_evolution-8.1.9}/dense_evolution/gates.py +0 -0
  16. {dense_evolution-8.1.7 → dense_evolution-8.1.9}/dense_evolution/registry.py +0 -0
  17. {dense_evolution-8.1.7 → dense_evolution-8.1.9}/dense_evolution/simulator.py +0 -0
  18. {dense_evolution-8.1.7 → dense_evolution-8.1.9}/dense_evolution.egg-info/dependency_links.txt +0 -0
  19. {dense_evolution-8.1.7 → dense_evolution-8.1.9}/dense_evolution.egg-info/requires.txt +0 -0
  20. {dense_evolution-8.1.7 → dense_evolution-8.1.9}/dense_evolution.egg-info/top_level.txt +0 -0
  21. {dense_evolution-8.1.7 → dense_evolution-8.1.9}/ia_utils/__init__.py +0 -0
  22. {dense_evolution-8.1.7 → dense_evolution-8.1.9}/license.md +0 -0
  23. {dense_evolution-8.1.7 → dense_evolution-8.1.9}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: dense-evolution
3
- Version: 8.1.7
3
+ Version: 8.1.9
4
4
  Summary: Micro-optimized High-Performance NISQ Statevector Quantum Circuit Simulator (Hardware-Adaptive Integration of Native NumPy, CUDA-Accelerated CuPy, and Linear Kernel Fusion via JAX JIT/XLA Compilation)
5
5
  Author-email: Salvatore Pennacchio <jtatopenn@libero.it>
6
6
  License: Business Source License 1.1
@@ -63,10 +63,16 @@ Dynamic: license-file
63
63
 
64
64
  [![CI](https://github.com/tatopenn-cell/Dense-Evolution/actions/workflows/ci.yml/badge.svg)](https://github.com/tatopenn-cell/Dense-Evolution/actions/workflows/ci.yml)
65
65
  [![PyPI](https://img.shields.io/pypi/v/dense-evolution?style=flat-square&color=00e5ff)](https://pypi.org/project/dense-evolution/)
66
+ [![PyPI Downloads](https://img.shields.io/pypi/dm/dense-evolution?style=flat-square&color=00e5ff)](https://pypi.org/project/dense-evolution/)
66
67
  [![Python](https://img.shields.io/badge/Python-3.9+-blue?style=flat-square&logo=python&logoColor=white)](https://www.python.org/)
67
68
  [![License](https://img.shields.io/badge/License-BSL_1.1-orange?style=flat-square)](LICENSE.md)
68
69
  [![Build](https://img.shields.io/badge/Build-Passing-00ff9d?style=flat-square)](https://github.com/tatopenn-cell/Dense-Evolution/actions)
69
70
  [![Cross-Validation CI](https://github.com/tatopenn-cell/Dense-Evolution-Ising-Tests/actions/workflows/ci.yml/badge.svg)](https://github.com/tatopenn-cell/Dense-Evolution-Ising-Tests/actions/workflows/ci.yml)
71
+ [![Latest Release](https://img.shields.io/github/v/release/tatopenn-cell/Dense-Evolution?style=flat-square&color=blueviolet)](https://github.com/tatopenn-cell/Dense-Evolution/releases)
72
+ [![Last Commit](https://img.shields.io/github/last-commit/tatopenn-cell/Dense-Evolution?style=flat-square)](https://github.com/tatopenn-cell/Dense-Evolution/commits/main)
73
+ [![Issues](https://img.shields.io/github/issues/tatopenn-cell/Dense-Evolution?style=flat-square)](https://github.com/tatopenn-cell/Dense-Evolution/issues)
74
+ [![Stars](https://img.shields.io/github/stars/tatopenn-cell/Dense-Evolution?style=flat-square&color=yellow)](https://github.com/tatopenn-cell/Dense-Evolution/stargazers)
75
+ [![JAX](https://img.shields.io/badge/Backend-JAX_XLA-f9ab00?style=flat-square&logo=google&logoColor=white)](https://github.com/google/jax)
70
76
 
71
77
  ---
72
78
 
@@ -160,6 +166,9 @@ dense_evolution/
160
166
  ├── chunk.py SafeMemoryGuard · MemoryChunker · CircuitChunker · Chunk (Anti-OOM)
161
167
  ├── simulator.py DenseSVSimulator · run_parametric_batch_jit · vmap batch VQE
162
168
  └── dash.py ipywidgets dashboard · VQE engine · QM/MM · MD simulation · 3D wavefunction
169
+
170
+ ia_utils/
171
+ └── vector_healing.py median_healing · enhanced_dense_healing_hybrid (NaN/Inf-safe, lazy JAX import)
163
172
  ```
164
173
 
165
174
  **Data flow per run:**
@@ -185,6 +194,7 @@ dense_evolution/
185
194
  | **VQE + ADAM** | Hellmann-Feynman gradient · positional parameter injection into any OpenQASM 2.0 circuit |
186
195
  | **Anti-OOM Engine** | `SafeMemoryGuard` blocks execution before JAX raises `RESOURCE_EXHAUSTED` |
187
196
  | **Predictive Healing** | `healing.py` — Φ_AB alignment, dynamic vector, Σ-sync, `MemoryReflectionEngine` |
197
+ | **Vector Sequence Healing** | `ia_utils/` — `median_healing`, `enhanced_dense_healing_hybrid` — NaN/Inf-safe, lazy JAX import |
188
198
  | **Backend Agnostic** | NumPy CPU · JAX XLA CPU/TPU · CuPy CUDA — runtime selection, zero code changes |
189
199
  | **Live Dashboard** | 8-panel ipywidgets telemetry: probability, VQE energy, entropy, purity, gradient, noise, θ-correction, Pearson heatmap |
190
200
 
@@ -240,6 +250,7 @@ sim = DenseSVSimulator(
240
250
  | Method | Description |
241
251
  |---|---|
242
252
  | `set_initial_state(state=None)` | Reset to `\|0⟩ⁿ` or inject custom statevector |
253
+ | `run_circuit(circuit, transpile=True)` | Plain (non-JIT) gate execution — takes the tuple format below |
243
254
  | `run_circuit_jit_beast_mode(circuit)` | JIT-compiled gate execution — primary execution path |
244
255
  | `run_circuit_with_chunking(circuit, chunk_size=500)` | Chunked execution for long circuits |
245
256
  | `run_parametric_batch_jit(base_circuit, parameter_batch)` | `vmap` over parameter grid — returns full batch of statevectors |
@@ -258,16 +269,34 @@ circuit = parser.parse(qasm_str) # → QASMCircuit
258
269
  valid, msg = parser.validate(circuit)
259
270
  ```
260
271
 
261
- `QASMCircuit` fields: `n_qubits`, `n_cbits`, `ops` (list of gate tuples).
272
+ `QASMCircuit` fields: `n_qubits`, `n_cbits`, `ops` (list of gate dicts, e.g.
273
+ `{'name': 'h', 'qubits': [0], 'params': []}`). Use `circuit.to_tuples()` to
274
+ convert `ops` to the `(name, qubit0[, qubit1, ...][, param0, ...])` tuple
275
+ format that `run_circuit` / `run_circuit_jit_beast_mode` expect — don't
276
+ build that format by hand.
262
277
 
263
278
  ### `NoiseModel`
264
279
 
265
280
  ```python
266
281
  noise = NoiseModel()
267
- noise.apply(sv, model='depolarizing', p=0.01, n_qubits=4, rng=rng)
282
+ noise.apply_to_sv(sv, n=4, model='depolarizing', p=0.01, rng=rng)
268
283
  desc = NoiseModel.kraus_description('amplitude_damping')
269
284
  ```
270
285
 
286
+ ### End-to-end: parse → run → apply noise
287
+
288
+ ```python
289
+ parser = QASMParser()
290
+ circuit = parser.parse(qasm_str) # → QASMCircuit
291
+ sim = DenseSVSimulator(n_qubits=circuit.n_qubits)
292
+ sim.run_circuit(circuit.to_tuples()) # dicts -> tuples, then execute
293
+
294
+ sv_noisy = NoiseModel().apply_to_sv(
295
+ sim.get_statevector(), n=circuit.n_qubits, model='depolarizing', p=0.01,
296
+ rng=np.random.default_rng(42),
297
+ )
298
+ ```
299
+
271
300
  ### `Chunk` (Anti-OOM)
272
301
 
273
302
  ```python
@@ -283,6 +312,17 @@ sim.run_chunk(circuit, chunk_size_gates=500)
283
312
 
284
313
  Backward-compatibility aliases: `chunk1 = MemoryChunker`, `chunk2 = Chunk`, `Chunk2Incrociato = Chunk`.
285
314
 
315
+ ### `ia_utils.vector_healing`
316
+
317
+ ```python
318
+ from ia_utils.vector_healing import median_healing, enhanced_dense_healing_hybrid
319
+
320
+ healed, radius = median_healing(vettori, radius_baseline=None)
321
+ healed, metadata = enhanced_dense_healing_hybrid(vettori, radius_baseline=None, median_fallback_threshold=0.1)
322
+ ```
323
+
324
+ See **IA Utils — Vector Sequence Healing** above for details.
325
+
286
326
  ---
287
327
 
288
328
  ## ▍ Gate Library
@@ -350,6 +390,42 @@ All core functions compiled via `@jax.jit`. Event history managed by `MemoryRefl
350
390
 
351
391
  ---
352
392
 
393
+ ## ▍ IA Utils — Vector Sequence Healing
394
+
395
+ `ia_utils/vector_healing.py` — standalone module for cleaning sequences of vectors (e.g. hidden states / embeddings) that may contain `NaN` or `Inf` entries. Both functions preprocess the input (Inf → NaN → column-mean imputation) before healing, so corrupted values never propagate into the output.
396
+
397
+ | Function | Approach | Returns |
398
+ |---|---|---|
399
+ | `median_healing(vettori, radius_baseline=None)` | `scipy.ndimage.median_filter`, dynamic radius `min(20, max(3, n // 3))` | `(healed: np.ndarray, radius: int)` |
400
+ | `enhanced_dense_healing_hybrid(vettori, radius_baseline=None, median_fallback_threshold=0.1)` | Blends the `dense_evolution.healing` Φ-trigger logic with a median fallback, decided per-step | `(healed: np.ndarray, metadata: dict)` |
401
+
402
+ `enhanced_dense_healing_hybrid` metadata:
403
+
404
+ | Key | Type | Description |
405
+ |---|---|---|
406
+ | `fallback_triggered` | `bool` | `True` if the median fallback or dense blending fired at least once |
407
+ | `adaptive_radius_used` | `int` | Baseline radius actually applied |
408
+ | `reconstruction_error` | `float` | Mean norm of the correction applied vs. the sanitized input |
409
+
410
+ ```python
411
+ import numpy as np
412
+ from ia_utils.vector_healing import median_healing, enhanced_dense_healing_hybrid
413
+
414
+ vettori = np.random.default_rng(0).normal(size=(50, 128))
415
+ vettori[10, 3] = np.nan # simulate a corrupted hidden state
416
+ vettori[30, 7] = np.inf
417
+
418
+ healed, radius = median_healing(vettori)
419
+
420
+ healed_hybrid, meta = enhanced_dense_healing_hybrid(vettori)
421
+ print(meta)
422
+ # {'fallback_triggered': True, 'adaptive_radius_used': 16, 'reconstruction_error': 11.48}
423
+ ```
424
+
425
+ `jax` is imported lazily inside `enhanced_dense_healing_hybrid` — `median_healing` and the module import itself work without the `[jax]` extra installed; only calling `enhanced_dense_healing_hybrid` requires it.
426
+
427
+ ---
428
+
353
429
  ## ▍ Anti-OOM Chunk Engine
354
430
 
355
431
  All operations parcellized dynamically using a 4-layer architectural shield.
@@ -468,6 +544,17 @@ All circuits stored as OpenQASM 2.0 strings in `QASM_LIBRARY`.
468
544
 
469
545
  ## ▍ Changelog
470
546
 
547
+ ### v8.1.9
548
+ - **Fixed**: `ia_utils/vector_healing.py` — `enhanced_dense_healing_hybrid` had an unreachable third branch (a dense/blend fallback): the underlying `trigger` signal from `evaluate_phi_trigger` is strictly binary (0.0/1.0), so the branch could never execute. Collapsed to the genuine 2-state logic (pass-through vs. median fallback); runtime output is unchanged since the branch never ran.
549
+ - **Fixed**: `dashboard_core.py` — `run_simulation` / `run_vqe_telemetry` mutated the process-wide JAX `jax_enable_x64` flag without ever restoring it, so running one float32 simulation silently downgraded numerical precision for unrelated code later in the same process (e.g. the Vector Healing page, which sets no precision of its own). Both now save/restore the flag around their own execution.
550
+ - **Docs**: README's `NoiseModel` example called a nonexistent `.apply()` method with a wrong parameter name (`n_qubits` instead of `n`) — corrected to `apply_to_sv(sv, n=..., ...)`. Documented `QASMCircuit.to_tuples()` and `DenseSVSimulator.run_circuit`, which already existed and work correctly but were never mentioned in the README.
551
+
552
+ ### v8.1.8
553
+ - **Fixed**: `parser.py` — controlled two-qubit gates (`cx`/`cy`/`cz`/`cp`/`crz`) parsed from QASM in the dashboard layer had control and target swapped relative to `compiler.py`'s documented `(gate, control, target)` contract, breaking entanglement for circuits run through the dashboard. The core `QASMCircuit.to_tuples()` path was already correct.
554
+ - **Fixed**: `parser.py` — range syntax (`q[0:3]`) on single-qubit gates only applied to the first qubit in the range, silently dropping the rest. Now expands into one gate application per qubit, matching the parser's own documented contract.
555
+ - **Fixed**: `from dense_evolution import Chunk` raised `ImportError` — `Chunk` is now re-exported from the package root. Added `get_probabilities()`/`get_statevector()` to `Chunk` for parity with `DenseSVSimulator`.
556
+ - **Removed**: `dense_evolution/test2.py` and `stress_test.py` — byte-identical, assertion-free debug scripts that shipped inside every install with 0% test coverage. Their one real check (Kraus noise is genuinely stochastic across independent runs) is now a real regression test.
557
+
471
558
  ### v8.1.7
472
559
  - `ia_utils/` — new package: `median_healing`, `enhanced_dense_healing_hybrid` for vector sequence healing (NaN/Inf-safe)
473
560
  - `jax` import in `ia_utils.vector_healing` made lazy — importable without the `[jax]` extra
@@ -18,10 +18,16 @@
18
18
 
19
19
  [![CI](https://github.com/tatopenn-cell/Dense-Evolution/actions/workflows/ci.yml/badge.svg)](https://github.com/tatopenn-cell/Dense-Evolution/actions/workflows/ci.yml)
20
20
  [![PyPI](https://img.shields.io/pypi/v/dense-evolution?style=flat-square&color=00e5ff)](https://pypi.org/project/dense-evolution/)
21
+ [![PyPI Downloads](https://img.shields.io/pypi/dm/dense-evolution?style=flat-square&color=00e5ff)](https://pypi.org/project/dense-evolution/)
21
22
  [![Python](https://img.shields.io/badge/Python-3.9+-blue?style=flat-square&logo=python&logoColor=white)](https://www.python.org/)
22
23
  [![License](https://img.shields.io/badge/License-BSL_1.1-orange?style=flat-square)](LICENSE.md)
23
24
  [![Build](https://img.shields.io/badge/Build-Passing-00ff9d?style=flat-square)](https://github.com/tatopenn-cell/Dense-Evolution/actions)
24
25
  [![Cross-Validation CI](https://github.com/tatopenn-cell/Dense-Evolution-Ising-Tests/actions/workflows/ci.yml/badge.svg)](https://github.com/tatopenn-cell/Dense-Evolution-Ising-Tests/actions/workflows/ci.yml)
26
+ [![Latest Release](https://img.shields.io/github/v/release/tatopenn-cell/Dense-Evolution?style=flat-square&color=blueviolet)](https://github.com/tatopenn-cell/Dense-Evolution/releases)
27
+ [![Last Commit](https://img.shields.io/github/last-commit/tatopenn-cell/Dense-Evolution?style=flat-square)](https://github.com/tatopenn-cell/Dense-Evolution/commits/main)
28
+ [![Issues](https://img.shields.io/github/issues/tatopenn-cell/Dense-Evolution?style=flat-square)](https://github.com/tatopenn-cell/Dense-Evolution/issues)
29
+ [![Stars](https://img.shields.io/github/stars/tatopenn-cell/Dense-Evolution?style=flat-square&color=yellow)](https://github.com/tatopenn-cell/Dense-Evolution/stargazers)
30
+ [![JAX](https://img.shields.io/badge/Backend-JAX_XLA-f9ab00?style=flat-square&logo=google&logoColor=white)](https://github.com/google/jax)
25
31
 
26
32
  ---
27
33
 
@@ -115,6 +121,9 @@ dense_evolution/
115
121
  ├── chunk.py SafeMemoryGuard · MemoryChunker · CircuitChunker · Chunk (Anti-OOM)
116
122
  ├── simulator.py DenseSVSimulator · run_parametric_batch_jit · vmap batch VQE
117
123
  └── dash.py ipywidgets dashboard · VQE engine · QM/MM · MD simulation · 3D wavefunction
124
+
125
+ ia_utils/
126
+ └── vector_healing.py median_healing · enhanced_dense_healing_hybrid (NaN/Inf-safe, lazy JAX import)
118
127
  ```
119
128
 
120
129
  **Data flow per run:**
@@ -140,6 +149,7 @@ dense_evolution/
140
149
  | **VQE + ADAM** | Hellmann-Feynman gradient · positional parameter injection into any OpenQASM 2.0 circuit |
141
150
  | **Anti-OOM Engine** | `SafeMemoryGuard` blocks execution before JAX raises `RESOURCE_EXHAUSTED` |
142
151
  | **Predictive Healing** | `healing.py` — Φ_AB alignment, dynamic vector, Σ-sync, `MemoryReflectionEngine` |
152
+ | **Vector Sequence Healing** | `ia_utils/` — `median_healing`, `enhanced_dense_healing_hybrid` — NaN/Inf-safe, lazy JAX import |
143
153
  | **Backend Agnostic** | NumPy CPU · JAX XLA CPU/TPU · CuPy CUDA — runtime selection, zero code changes |
144
154
  | **Live Dashboard** | 8-panel ipywidgets telemetry: probability, VQE energy, entropy, purity, gradient, noise, θ-correction, Pearson heatmap |
145
155
 
@@ -195,6 +205,7 @@ sim = DenseSVSimulator(
195
205
  | Method | Description |
196
206
  |---|---|
197
207
  | `set_initial_state(state=None)` | Reset to `\|0⟩ⁿ` or inject custom statevector |
208
+ | `run_circuit(circuit, transpile=True)` | Plain (non-JIT) gate execution — takes the tuple format below |
198
209
  | `run_circuit_jit_beast_mode(circuit)` | JIT-compiled gate execution — primary execution path |
199
210
  | `run_circuit_with_chunking(circuit, chunk_size=500)` | Chunked execution for long circuits |
200
211
  | `run_parametric_batch_jit(base_circuit, parameter_batch)` | `vmap` over parameter grid — returns full batch of statevectors |
@@ -213,16 +224,34 @@ circuit = parser.parse(qasm_str) # → QASMCircuit
213
224
  valid, msg = parser.validate(circuit)
214
225
  ```
215
226
 
216
- `QASMCircuit` fields: `n_qubits`, `n_cbits`, `ops` (list of gate tuples).
227
+ `QASMCircuit` fields: `n_qubits`, `n_cbits`, `ops` (list of gate dicts, e.g.
228
+ `{'name': 'h', 'qubits': [0], 'params': []}`). Use `circuit.to_tuples()` to
229
+ convert `ops` to the `(name, qubit0[, qubit1, ...][, param0, ...])` tuple
230
+ format that `run_circuit` / `run_circuit_jit_beast_mode` expect — don't
231
+ build that format by hand.
217
232
 
218
233
  ### `NoiseModel`
219
234
 
220
235
  ```python
221
236
  noise = NoiseModel()
222
- noise.apply(sv, model='depolarizing', p=0.01, n_qubits=4, rng=rng)
237
+ noise.apply_to_sv(sv, n=4, model='depolarizing', p=0.01, rng=rng)
223
238
  desc = NoiseModel.kraus_description('amplitude_damping')
224
239
  ```
225
240
 
241
+ ### End-to-end: parse → run → apply noise
242
+
243
+ ```python
244
+ parser = QASMParser()
245
+ circuit = parser.parse(qasm_str) # → QASMCircuit
246
+ sim = DenseSVSimulator(n_qubits=circuit.n_qubits)
247
+ sim.run_circuit(circuit.to_tuples()) # dicts -> tuples, then execute
248
+
249
+ sv_noisy = NoiseModel().apply_to_sv(
250
+ sim.get_statevector(), n=circuit.n_qubits, model='depolarizing', p=0.01,
251
+ rng=np.random.default_rng(42),
252
+ )
253
+ ```
254
+
226
255
  ### `Chunk` (Anti-OOM)
227
256
 
228
257
  ```python
@@ -238,6 +267,17 @@ sim.run_chunk(circuit, chunk_size_gates=500)
238
267
 
239
268
  Backward-compatibility aliases: `chunk1 = MemoryChunker`, `chunk2 = Chunk`, `Chunk2Incrociato = Chunk`.
240
269
 
270
+ ### `ia_utils.vector_healing`
271
+
272
+ ```python
273
+ from ia_utils.vector_healing import median_healing, enhanced_dense_healing_hybrid
274
+
275
+ healed, radius = median_healing(vettori, radius_baseline=None)
276
+ healed, metadata = enhanced_dense_healing_hybrid(vettori, radius_baseline=None, median_fallback_threshold=0.1)
277
+ ```
278
+
279
+ See **IA Utils — Vector Sequence Healing** above for details.
280
+
241
281
  ---
242
282
 
243
283
  ## ▍ Gate Library
@@ -305,6 +345,42 @@ All core functions compiled via `@jax.jit`. Event history managed by `MemoryRefl
305
345
 
306
346
  ---
307
347
 
348
+ ## ▍ IA Utils — Vector Sequence Healing
349
+
350
+ `ia_utils/vector_healing.py` — standalone module for cleaning sequences of vectors (e.g. hidden states / embeddings) that may contain `NaN` or `Inf` entries. Both functions preprocess the input (Inf → NaN → column-mean imputation) before healing, so corrupted values never propagate into the output.
351
+
352
+ | Function | Approach | Returns |
353
+ |---|---|---|
354
+ | `median_healing(vettori, radius_baseline=None)` | `scipy.ndimage.median_filter`, dynamic radius `min(20, max(3, n // 3))` | `(healed: np.ndarray, radius: int)` |
355
+ | `enhanced_dense_healing_hybrid(vettori, radius_baseline=None, median_fallback_threshold=0.1)` | Blends the `dense_evolution.healing` Φ-trigger logic with a median fallback, decided per-step | `(healed: np.ndarray, metadata: dict)` |
356
+
357
+ `enhanced_dense_healing_hybrid` metadata:
358
+
359
+ | Key | Type | Description |
360
+ |---|---|---|
361
+ | `fallback_triggered` | `bool` | `True` if the median fallback or dense blending fired at least once |
362
+ | `adaptive_radius_used` | `int` | Baseline radius actually applied |
363
+ | `reconstruction_error` | `float` | Mean norm of the correction applied vs. the sanitized input |
364
+
365
+ ```python
366
+ import numpy as np
367
+ from ia_utils.vector_healing import median_healing, enhanced_dense_healing_hybrid
368
+
369
+ vettori = np.random.default_rng(0).normal(size=(50, 128))
370
+ vettori[10, 3] = np.nan # simulate a corrupted hidden state
371
+ vettori[30, 7] = np.inf
372
+
373
+ healed, radius = median_healing(vettori)
374
+
375
+ healed_hybrid, meta = enhanced_dense_healing_hybrid(vettori)
376
+ print(meta)
377
+ # {'fallback_triggered': True, 'adaptive_radius_used': 16, 'reconstruction_error': 11.48}
378
+ ```
379
+
380
+ `jax` is imported lazily inside `enhanced_dense_healing_hybrid` — `median_healing` and the module import itself work without the `[jax]` extra installed; only calling `enhanced_dense_healing_hybrid` requires it.
381
+
382
+ ---
383
+
308
384
  ## ▍ Anti-OOM Chunk Engine
309
385
 
310
386
  All operations parcellized dynamically using a 4-layer architectural shield.
@@ -423,6 +499,17 @@ All circuits stored as OpenQASM 2.0 strings in `QASM_LIBRARY`.
423
499
 
424
500
  ## ▍ Changelog
425
501
 
502
+ ### v8.1.9
503
+ - **Fixed**: `ia_utils/vector_healing.py` — `enhanced_dense_healing_hybrid` had an unreachable third branch (a dense/blend fallback): the underlying `trigger` signal from `evaluate_phi_trigger` is strictly binary (0.0/1.0), so the branch could never execute. Collapsed to the genuine 2-state logic (pass-through vs. median fallback); runtime output is unchanged since the branch never ran.
504
+ - **Fixed**: `dashboard_core.py` — `run_simulation` / `run_vqe_telemetry` mutated the process-wide JAX `jax_enable_x64` flag without ever restoring it, so running one float32 simulation silently downgraded numerical precision for unrelated code later in the same process (e.g. the Vector Healing page, which sets no precision of its own). Both now save/restore the flag around their own execution.
505
+ - **Docs**: README's `NoiseModel` example called a nonexistent `.apply()` method with a wrong parameter name (`n_qubits` instead of `n`) — corrected to `apply_to_sv(sv, n=..., ...)`. Documented `QASMCircuit.to_tuples()` and `DenseSVSimulator.run_circuit`, which already existed and work correctly but were never mentioned in the README.
506
+
507
+ ### v8.1.8
508
+ - **Fixed**: `parser.py` — controlled two-qubit gates (`cx`/`cy`/`cz`/`cp`/`crz`) parsed from QASM in the dashboard layer had control and target swapped relative to `compiler.py`'s documented `(gate, control, target)` contract, breaking entanglement for circuits run through the dashboard. The core `QASMCircuit.to_tuples()` path was already correct.
509
+ - **Fixed**: `parser.py` — range syntax (`q[0:3]`) on single-qubit gates only applied to the first qubit in the range, silently dropping the rest. Now expands into one gate application per qubit, matching the parser's own documented contract.
510
+ - **Fixed**: `from dense_evolution import Chunk` raised `ImportError` — `Chunk` is now re-exported from the package root. Added `get_probabilities()`/`get_statevector()` to `Chunk` for parity with `DenseSVSimulator`.
511
+ - **Removed**: `dense_evolution/test2.py` and `stress_test.py` — byte-identical, assertion-free debug scripts that shipped inside every install with 0% test coverage. Their one real check (Kraus noise is genuinely stochastic across independent runs) is now a real regression test.
512
+
426
513
  ### v8.1.7
427
514
  - `ia_utils/` — new package: `median_healing`, `enhanced_dense_healing_hybrid` for vector sequence healing (NaN/Inf-safe)
428
515
  - `jax` import in `ia_utils.vector_healing` made lazy — importable without the `[jax]` extra
@@ -7,5 +7,6 @@ from .parser import QASMParser, QASMCircuit
7
7
  from .compiler import QuantumTranspiler
8
8
  from .registry import NoiseModel, QuantumHardwareRegistry
9
9
  from .gates import GATES, PARAMETRIC_GATES, GATE_IDS
10
+ from .chunk import Chunk
10
11
 
11
- __version__ = "8.1.7"
12
+ __version__ = "8.1.9"
@@ -334,6 +334,16 @@ class Chunk:
334
334
  """RAM used by the physical statevector in MB."""
335
335
  return self._inner_sim.memory_mb()
336
336
 
337
+ def get_probabilities(self):
338
+ """|amplitude|^2 for every basis state — forwards to the inner
339
+ DenseSVSimulator for parity with its own get_probabilities()."""
340
+ return self._inner_sim.get_probabilities()
341
+
342
+ def get_statevector(self):
343
+ """Full complex statevector — forwards to the inner DenseSVSimulator
344
+ for parity with its own get_statevector()."""
345
+ return self._inner_sim.get_statevector()
346
+
337
347
  # ── Public API ───────────────────────────────────────────────────────────
338
348
 
339
349
  def run_chunk(
@@ -1,7 +1,7 @@
1
1
  import jax
2
2
  import jax.numpy as jnp
3
3
  import json
4
- from datetime import datetime
4
+ from datetime import datetime, timezone
5
5
  from typing import Dict, Tuple, List, Any
6
6
 
7
7
 
@@ -104,7 +104,7 @@ class MemoryReflectionEngine:
104
104
 
105
105
  def record_event(self, event_type: str, value: float, description: str = ""):
106
106
  event = {
107
- "timestamp": datetime.utcnow().isoformat(),
107
+ "timestamp": datetime.now(timezone.utc).isoformat(),
108
108
  "type": event_type,
109
109
  "value": float(value),
110
110
  "description": description
@@ -93,6 +93,18 @@ class QASMParser:
93
93
  'ccx': 'ccx',
94
94
  }
95
95
 
96
+ # ── gate names that only ever take one qubit ─────────────────────
97
+ # Used to expand range syntax (q[0:3]) into one op per qubit instead
98
+ # of a single op with multiple qubits attached — see BUG FIX 3 note
99
+ # on parse(): the original fix resolved q[0:3] to the qubit list
100
+ # [0,1,2], but nothing expanded that list into separate applications
101
+ # for gates that are only ever single-qubit, so e.g. `h q[0:3]` ended
102
+ # up applying H to qubit 0 only, silently dropping qubits 1 and 2.
103
+ _SINGLE_QUBIT_GATES = frozenset((
104
+ 'h', 'x', 'y', 'z', 's', 'sdg', 't', 'tdg', 'sx', 'id',
105
+ 'rx', 'ry', 'rz', 'p', 'u1', 'u2', 'u3',
106
+ ))
107
+
96
108
  # ── statements to skip entirely ──────────────────────────────────
97
109
  # BUG FIX (original): 'gate ' had a trailing space making it miss
98
110
  # 'gate foo(...)' where the token is 'gate' followed by space.
@@ -211,11 +223,21 @@ class QASMParser:
211
223
  # ── gate application ─────────────────────────────────────
212
224
  op = self._parse_gate(instr, qubit_map)
213
225
  if op is not None:
214
- ops.append(op)
215
- # update n_qubits from seen qubit indices
216
- # (handles circuits without explicit qreg declarations)
217
- if op['qubits']:
218
- n_qubits = max(n_qubits, max(op['qubits']) + 1)
226
+ if op['name'] in self._SINGLE_QUBIT_GATES and len(op['qubits']) > 1:
227
+ # range syntax on an inherently single-qubit gate
228
+ # (e.g. `h q[0:3]`) expand into one op per qubit.
229
+ for q in op['qubits']:
230
+ ops.append({
231
+ 'type': op['type'], 'name': op['name'],
232
+ 'qubits': [q], 'params': list(op['params']),
233
+ })
234
+ n_qubits = max(n_qubits, q + 1)
235
+ else:
236
+ ops.append(op)
237
+ # update n_qubits from seen qubit indices
238
+ # (handles circuits without explicit qreg declarations)
239
+ if op['qubits']:
240
+ n_qubits = max(n_qubits, max(op['qubits']) + 1)
219
241
 
220
242
  return QASMCircuit(n_qubits, n_cbits, ops)
221
243
 
@@ -360,7 +382,7 @@ class QASMParser:
360
382
  def _resolve_qubits(self,
361
383
  s: str,
362
384
  qmap: Dict[str, int]) -> List[int]:
363
- """
385
+ r"""
364
386
  Resolve a comma-separated qubit argument string to absolute indices.
365
387
 
366
388
  Handles
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: dense-evolution
3
- Version: 8.1.7
3
+ Version: 8.1.9
4
4
  Summary: Micro-optimized High-Performance NISQ Statevector Quantum Circuit Simulator (Hardware-Adaptive Integration of Native NumPy, CUDA-Accelerated CuPy, and Linear Kernel Fusion via JAX JIT/XLA Compilation)
5
5
  Author-email: Salvatore Pennacchio <jtatopenn@libero.it>
6
6
  License: Business Source License 1.1
@@ -63,10 +63,16 @@ Dynamic: license-file
63
63
 
64
64
  [![CI](https://github.com/tatopenn-cell/Dense-Evolution/actions/workflows/ci.yml/badge.svg)](https://github.com/tatopenn-cell/Dense-Evolution/actions/workflows/ci.yml)
65
65
  [![PyPI](https://img.shields.io/pypi/v/dense-evolution?style=flat-square&color=00e5ff)](https://pypi.org/project/dense-evolution/)
66
+ [![PyPI Downloads](https://img.shields.io/pypi/dm/dense-evolution?style=flat-square&color=00e5ff)](https://pypi.org/project/dense-evolution/)
66
67
  [![Python](https://img.shields.io/badge/Python-3.9+-blue?style=flat-square&logo=python&logoColor=white)](https://www.python.org/)
67
68
  [![License](https://img.shields.io/badge/License-BSL_1.1-orange?style=flat-square)](LICENSE.md)
68
69
  [![Build](https://img.shields.io/badge/Build-Passing-00ff9d?style=flat-square)](https://github.com/tatopenn-cell/Dense-Evolution/actions)
69
70
  [![Cross-Validation CI](https://github.com/tatopenn-cell/Dense-Evolution-Ising-Tests/actions/workflows/ci.yml/badge.svg)](https://github.com/tatopenn-cell/Dense-Evolution-Ising-Tests/actions/workflows/ci.yml)
71
+ [![Latest Release](https://img.shields.io/github/v/release/tatopenn-cell/Dense-Evolution?style=flat-square&color=blueviolet)](https://github.com/tatopenn-cell/Dense-Evolution/releases)
72
+ [![Last Commit](https://img.shields.io/github/last-commit/tatopenn-cell/Dense-Evolution?style=flat-square)](https://github.com/tatopenn-cell/Dense-Evolution/commits/main)
73
+ [![Issues](https://img.shields.io/github/issues/tatopenn-cell/Dense-Evolution?style=flat-square)](https://github.com/tatopenn-cell/Dense-Evolution/issues)
74
+ [![Stars](https://img.shields.io/github/stars/tatopenn-cell/Dense-Evolution?style=flat-square&color=yellow)](https://github.com/tatopenn-cell/Dense-Evolution/stargazers)
75
+ [![JAX](https://img.shields.io/badge/Backend-JAX_XLA-f9ab00?style=flat-square&logo=google&logoColor=white)](https://github.com/google/jax)
70
76
 
71
77
  ---
72
78
 
@@ -160,6 +166,9 @@ dense_evolution/
160
166
  ├── chunk.py SafeMemoryGuard · MemoryChunker · CircuitChunker · Chunk (Anti-OOM)
161
167
  ├── simulator.py DenseSVSimulator · run_parametric_batch_jit · vmap batch VQE
162
168
  └── dash.py ipywidgets dashboard · VQE engine · QM/MM · MD simulation · 3D wavefunction
169
+
170
+ ia_utils/
171
+ └── vector_healing.py median_healing · enhanced_dense_healing_hybrid (NaN/Inf-safe, lazy JAX import)
163
172
  ```
164
173
 
165
174
  **Data flow per run:**
@@ -185,6 +194,7 @@ dense_evolution/
185
194
  | **VQE + ADAM** | Hellmann-Feynman gradient · positional parameter injection into any OpenQASM 2.0 circuit |
186
195
  | **Anti-OOM Engine** | `SafeMemoryGuard` blocks execution before JAX raises `RESOURCE_EXHAUSTED` |
187
196
  | **Predictive Healing** | `healing.py` — Φ_AB alignment, dynamic vector, Σ-sync, `MemoryReflectionEngine` |
197
+ | **Vector Sequence Healing** | `ia_utils/` — `median_healing`, `enhanced_dense_healing_hybrid` — NaN/Inf-safe, lazy JAX import |
188
198
  | **Backend Agnostic** | NumPy CPU · JAX XLA CPU/TPU · CuPy CUDA — runtime selection, zero code changes |
189
199
  | **Live Dashboard** | 8-panel ipywidgets telemetry: probability, VQE energy, entropy, purity, gradient, noise, θ-correction, Pearson heatmap |
190
200
 
@@ -240,6 +250,7 @@ sim = DenseSVSimulator(
240
250
  | Method | Description |
241
251
  |---|---|
242
252
  | `set_initial_state(state=None)` | Reset to `\|0⟩ⁿ` or inject custom statevector |
253
+ | `run_circuit(circuit, transpile=True)` | Plain (non-JIT) gate execution — takes the tuple format below |
243
254
  | `run_circuit_jit_beast_mode(circuit)` | JIT-compiled gate execution — primary execution path |
244
255
  | `run_circuit_with_chunking(circuit, chunk_size=500)` | Chunked execution for long circuits |
245
256
  | `run_parametric_batch_jit(base_circuit, parameter_batch)` | `vmap` over parameter grid — returns full batch of statevectors |
@@ -258,16 +269,34 @@ circuit = parser.parse(qasm_str) # → QASMCircuit
258
269
  valid, msg = parser.validate(circuit)
259
270
  ```
260
271
 
261
- `QASMCircuit` fields: `n_qubits`, `n_cbits`, `ops` (list of gate tuples).
272
+ `QASMCircuit` fields: `n_qubits`, `n_cbits`, `ops` (list of gate dicts, e.g.
273
+ `{'name': 'h', 'qubits': [0], 'params': []}`). Use `circuit.to_tuples()` to
274
+ convert `ops` to the `(name, qubit0[, qubit1, ...][, param0, ...])` tuple
275
+ format that `run_circuit` / `run_circuit_jit_beast_mode` expect — don't
276
+ build that format by hand.
262
277
 
263
278
  ### `NoiseModel`
264
279
 
265
280
  ```python
266
281
  noise = NoiseModel()
267
- noise.apply(sv, model='depolarizing', p=0.01, n_qubits=4, rng=rng)
282
+ noise.apply_to_sv(sv, n=4, model='depolarizing', p=0.01, rng=rng)
268
283
  desc = NoiseModel.kraus_description('amplitude_damping')
269
284
  ```
270
285
 
286
+ ### End-to-end: parse → run → apply noise
287
+
288
+ ```python
289
+ parser = QASMParser()
290
+ circuit = parser.parse(qasm_str) # → QASMCircuit
291
+ sim = DenseSVSimulator(n_qubits=circuit.n_qubits)
292
+ sim.run_circuit(circuit.to_tuples()) # dicts -> tuples, then execute
293
+
294
+ sv_noisy = NoiseModel().apply_to_sv(
295
+ sim.get_statevector(), n=circuit.n_qubits, model='depolarizing', p=0.01,
296
+ rng=np.random.default_rng(42),
297
+ )
298
+ ```
299
+
271
300
  ### `Chunk` (Anti-OOM)
272
301
 
273
302
  ```python
@@ -283,6 +312,17 @@ sim.run_chunk(circuit, chunk_size_gates=500)
283
312
 
284
313
  Backward-compatibility aliases: `chunk1 = MemoryChunker`, `chunk2 = Chunk`, `Chunk2Incrociato = Chunk`.
285
314
 
315
+ ### `ia_utils.vector_healing`
316
+
317
+ ```python
318
+ from ia_utils.vector_healing import median_healing, enhanced_dense_healing_hybrid
319
+
320
+ healed, radius = median_healing(vettori, radius_baseline=None)
321
+ healed, metadata = enhanced_dense_healing_hybrid(vettori, radius_baseline=None, median_fallback_threshold=0.1)
322
+ ```
323
+
324
+ See **IA Utils — Vector Sequence Healing** above for details.
325
+
286
326
  ---
287
327
 
288
328
  ## ▍ Gate Library
@@ -350,6 +390,42 @@ All core functions compiled via `@jax.jit`. Event history managed by `MemoryRefl
350
390
 
351
391
  ---
352
392
 
393
+ ## ▍ IA Utils — Vector Sequence Healing
394
+
395
+ `ia_utils/vector_healing.py` — standalone module for cleaning sequences of vectors (e.g. hidden states / embeddings) that may contain `NaN` or `Inf` entries. Both functions preprocess the input (Inf → NaN → column-mean imputation) before healing, so corrupted values never propagate into the output.
396
+
397
+ | Function | Approach | Returns |
398
+ |---|---|---|
399
+ | `median_healing(vettori, radius_baseline=None)` | `scipy.ndimage.median_filter`, dynamic radius `min(20, max(3, n // 3))` | `(healed: np.ndarray, radius: int)` |
400
+ | `enhanced_dense_healing_hybrid(vettori, radius_baseline=None, median_fallback_threshold=0.1)` | Blends the `dense_evolution.healing` Φ-trigger logic with a median fallback, decided per-step | `(healed: np.ndarray, metadata: dict)` |
401
+
402
+ `enhanced_dense_healing_hybrid` metadata:
403
+
404
+ | Key | Type | Description |
405
+ |---|---|---|
406
+ | `fallback_triggered` | `bool` | `True` if the median fallback or dense blending fired at least once |
407
+ | `adaptive_radius_used` | `int` | Baseline radius actually applied |
408
+ | `reconstruction_error` | `float` | Mean norm of the correction applied vs. the sanitized input |
409
+
410
+ ```python
411
+ import numpy as np
412
+ from ia_utils.vector_healing import median_healing, enhanced_dense_healing_hybrid
413
+
414
+ vettori = np.random.default_rng(0).normal(size=(50, 128))
415
+ vettori[10, 3] = np.nan # simulate a corrupted hidden state
416
+ vettori[30, 7] = np.inf
417
+
418
+ healed, radius = median_healing(vettori)
419
+
420
+ healed_hybrid, meta = enhanced_dense_healing_hybrid(vettori)
421
+ print(meta)
422
+ # {'fallback_triggered': True, 'adaptive_radius_used': 16, 'reconstruction_error': 11.48}
423
+ ```
424
+
425
+ `jax` is imported lazily inside `enhanced_dense_healing_hybrid` — `median_healing` and the module import itself work without the `[jax]` extra installed; only calling `enhanced_dense_healing_hybrid` requires it.
426
+
427
+ ---
428
+
353
429
  ## ▍ Anti-OOM Chunk Engine
354
430
 
355
431
  All operations parcellized dynamically using a 4-layer architectural shield.
@@ -468,6 +544,17 @@ All circuits stored as OpenQASM 2.0 strings in `QASM_LIBRARY`.
468
544
 
469
545
  ## ▍ Changelog
470
546
 
547
+ ### v8.1.9
548
+ - **Fixed**: `ia_utils/vector_healing.py` — `enhanced_dense_healing_hybrid` had an unreachable third branch (a dense/blend fallback): the underlying `trigger` signal from `evaluate_phi_trigger` is strictly binary (0.0/1.0), so the branch could never execute. Collapsed to the genuine 2-state logic (pass-through vs. median fallback); runtime output is unchanged since the branch never ran.
549
+ - **Fixed**: `dashboard_core.py` — `run_simulation` / `run_vqe_telemetry` mutated the process-wide JAX `jax_enable_x64` flag without ever restoring it, so running one float32 simulation silently downgraded numerical precision for unrelated code later in the same process (e.g. the Vector Healing page, which sets no precision of its own). Both now save/restore the flag around their own execution.
550
+ - **Docs**: README's `NoiseModel` example called a nonexistent `.apply()` method with a wrong parameter name (`n_qubits` instead of `n`) — corrected to `apply_to_sv(sv, n=..., ...)`. Documented `QASMCircuit.to_tuples()` and `DenseSVSimulator.run_circuit`, which already existed and work correctly but were never mentioned in the README.
551
+
552
+ ### v8.1.8
553
+ - **Fixed**: `parser.py` — controlled two-qubit gates (`cx`/`cy`/`cz`/`cp`/`crz`) parsed from QASM in the dashboard layer had control and target swapped relative to `compiler.py`'s documented `(gate, control, target)` contract, breaking entanglement for circuits run through the dashboard. The core `QASMCircuit.to_tuples()` path was already correct.
554
+ - **Fixed**: `parser.py` — range syntax (`q[0:3]`) on single-qubit gates only applied to the first qubit in the range, silently dropping the rest. Now expands into one gate application per qubit, matching the parser's own documented contract.
555
+ - **Fixed**: `from dense_evolution import Chunk` raised `ImportError` — `Chunk` is now re-exported from the package root. Added `get_probabilities()`/`get_statevector()` to `Chunk` for parity with `DenseSVSimulator`.
556
+ - **Removed**: `dense_evolution/test2.py` and `stress_test.py` — byte-identical, assertion-free debug scripts that shipped inside every install with 0% test coverage. Their one real check (Kraus noise is genuinely stochastic across independent runs) is now a real regression test.
557
+
471
558
  ### v8.1.7
472
559
  - `ia_utils/` — new package: `median_healing`, `enhanced_dense_healing_hybrid` for vector sequence healing (NaN/Inf-safe)
473
560
  - `jax` import in `ia_utils.vector_healing` made lazy — importable without the `[jax]` extra
@@ -10,8 +10,6 @@ dense_evolution/healing.py
10
10
  dense_evolution/parser.py
11
11
  dense_evolution/registry.py
12
12
  dense_evolution/simulator.py
13
- dense_evolution/stress_test.py
14
- dense_evolution/test2.py
15
13
  dense_evolution.egg-info/PKG-INFO
16
14
  dense_evolution.egg-info/SOURCES.txt
17
15
  dense_evolution.egg-info/dependency_links.txt
@@ -69,15 +69,20 @@ def enhanced_dense_healing_hybrid(
69
69
  Se `None`, il raggio viene calcolato dinamicamente
70
70
  come `min(20, max(3, n_tokens // 3))`.
71
71
  Defaults to None.
72
- median_fallback_threshold (float): Soglia del trigger sotto la quale scatta il fallback
73
- mediano. Defaults to 0.1.
72
+ median_fallback_threshold (float): Non più utilizzato dalla logica interna `trigger`
73
+ (da `evaluate_phi_trigger`) è strettamente binario
74
+ (0.0 o 1.0 per design: ciclo aperto/dinamico → incluso,
75
+ ciclo chiuso/statico → escluso), quindi non esiste un
76
+ valore intermedio su cui questa soglia possa agire.
77
+ Mantenuto nella firma per compatibilità con i chiamanti
78
+ esistenti. Defaults to 0.1.
74
79
 
75
80
  Returns:
76
81
  tuple: Contiene:
77
82
  - np.ndarray: Vettori curati, della stessa shape dell'input.
78
83
  - dict: Metadati di telemetria contenenti:
79
- - 'fallback_triggered' (bool): `True` se il fallback mediano o il blending denso
80
- è stato applicato almeno una volta durante il healing.
84
+ - 'fallback_triggered' (bool): `True` se il fallback mediano è stato applicato
85
+ almeno una volta durante il healing.
81
86
  - 'adaptive_radius_used' (int): Il raggio effettivamente calcolato e applicato.
82
87
  - 'reconstruction_error' (float): La norma media di variazione (errore di ricostruzione)
83
88
  introdotta rispetto ai vettori originali (potenzialmente corrotti).
@@ -86,7 +91,6 @@ def enhanced_dense_healing_hybrid(
86
91
  from dense_evolution.healing import (
87
92
  calculate_phi_ab,
88
93
  calculate_vettore_dinamico,
89
- calculate_delta_preemp,
90
94
  evaluate_phi_trigger,
91
95
  GLOBAL_CONSTANTS,
92
96
  )
@@ -137,24 +141,14 @@ def enhanced_dense_healing_hybrid(
137
141
  E_B = jnp.linalg.norm(state_B)
138
142
 
139
143
  v_dinamic = calculate_vettore_dinamico(E_A, E_B, phi_ab)
140
- delta_preemp = calculate_delta_preemp(E_A, E_B)
141
- trigger, lambda_step, epsilon_dissip = evaluate_phi_trigger(v_dinamic)
142
-
143
- healed_vector = processed_vettori[i]
144
+ trigger, _, _ = evaluate_phi_trigger(v_dinamic)
144
145
 
145
146
  if float(trigger) > GLOBAL_CONSTANTS['NON_STATIC_THRESHOLD_A']:
147
+ # trigger == 1.0: ciclo aperto/dinamico -> cambio genuino, si tiene il valore
146
148
  healed_vector = processed_vettori[i]
147
- elif float(trigger) < median_fallback_threshold:
148
- baseline_median = np.median(processed_vettori[lo:i], axis=0)
149
- healed_vector = baseline_median
150
- fallback_triggered_at_all = True
151
149
  else:
152
- blend_factor = float(lambda_step)
153
- if delta_preemp > GLOBAL_CONSTANTS['THRESHOLD_DELTA_PREEMP']:
154
- blend_factor = min(1.0, blend_factor + GLOBAL_CONSTANTS['DAMPING_BOOST_ON_STASIS'])
155
- else:
156
- blend_factor = max(0.0, blend_factor - GLOBAL_CONSTANTS['DAMPING_BOOST_ON_STASIS'])
157
- healed_vector = (1 - blend_factor) * processed_vettori[i] + blend_factor * baseline_mean
150
+ # trigger == 0.0: ciclo chiuso/statico -> rumore, si sostituisce con la mediana locale
151
+ healed_vector = np.median(processed_vettori[lo:i], axis=0)
158
152
  fallback_triggered_at_all = True
159
153
 
160
154
  out[i] = healed_vector
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "dense-evolution"
7
- version = "8.1.7"
7
+ version = "8.1.9"
8
8
  description = "Micro-optimized High-Performance NISQ Statevector Quantum Circuit Simulator (Hardware-Adaptive Integration of Native NumPy, CUDA-Accelerated CuPy, and Linear Kernel Fusion via JAX JIT/XLA Compilation)"
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.9"
@@ -1,76 +0,0 @@
1
- import time
2
- import numpy as np
3
- from dense_evolution import DenseSVSimulator, QASMParser, QuantumTranspiler, NoiseModel
4
-
5
- print("====================================================")
6
- print("🔬 ADVANCED PRODUCTION STRESS-TEST: KRAUS & JIT SIMULATION")
7
- print("====================================================")
8
-
9
- try:
10
- qasm_bench = """
11
- OPENQASM 2.0;
12
- include "qelib1.inc";
13
- qreg q[6];
14
- h q[0];
15
- cx q[0], q[1];
16
- cx q[1], q[2];
17
- cx q[2], q[3];
18
- cx q[3], q[4];
19
- cx q[4], q[5];
20
- rx(1.570796) q[0];
21
- ry(0.785398) q[1];
22
- rz(0.392699) q[2];
23
- """
24
-
25
- print("1. Parsing e Transpilazione del circuito QASM...")
26
- # Questo testa la corretta importazione e funzione di parser.py e compiler.py
27
- parser = QASMParser()
28
- circ = parser.parse(qasm_bench)
29
- tuples = QuantumTranspiler.transpile(circ.to_tuples())
30
- n_qubits = circ.n_qubits
31
- print(f"✓ Parsing completato. Qubit: {n_qubits}, Gate transpilati: {len(tuples)}")
32
-
33
- print("\n2. Validazione Core JIT in modalità ideale (simulator.py)...")
34
- t0 = time.perf_counter()
35
- sim_ideale = DenseSVSimulator(n_qubits)
36
- sim_ideale.run_circuit_jit_beast_mode(tuples)
37
- t_ideale = time.perf_counter() - t0
38
- prob_ideale = sim_ideale.get_probabilities()
39
- print(f"✓ Successo ideale in {t_ideale:.4f} s | Dimensione stato: {len(prob_ideale)}")
40
-
41
- print("\n3. Validazione NoiseModel (registry.py): Canale stocastico Amplitude Damping...")
42
-
43
- # Run Noisy 1
44
- t0 = time.perf_counter()
45
- sim_noisy1 = DenseSVSimulator(n_qubits)
46
- sim_noisy1.run_circuit_jit_beast_mode(tuples)
47
- # Iniezione diretta del rumore Kraus sullo statevector compilato
48
- sim_noisy1.sv = NoiseModel.apply_to_sv(sim_noisy1.sv, n_qubits, model='amplitude_damping', p=0.15)
49
- prob_noisy1 = sim_noisy1.get_probabilities()
50
- t_noisy1 = time.perf_counter() - t0
51
-
52
- # Run Noisy 2
53
- sim_noisy2 = DenseSVSimulator(n_qubits)
54
- sim_noisy2.run_circuit_jit_beast_mode(tuples)
55
- sim_noisy2.sv = NoiseModel.apply_to_sv(sim_noisy2.sv, n_qubits, model='amplitude_damping', p=0.15)
56
- prob_noisy2 = sim_noisy2.get_probabilities()
57
-
58
- print(f"✓ Successo noisy in {t_noisy1:.4f} s")
59
-
60
- print("\n4. Analisi statistica delle fluttuazioni (Shot Noise Reale)...")
61
- scostamento_stocastico = np.linalg.norm(prob_noisy1 - prob_noisy2)
62
- scostamento_ideale = np.linalg.norm(prob_ideale - prob_noisy1)
63
-
64
- print(f"🔬 Distanza ideale-noisy: {scostamento_ideale:.6f}")
65
- print(f"🔬 Fluttuazione quantistica indipendente (Shot Noise): {scostamento_stocastico:.6f}")
66
-
67
- if scostamento_stocastico > 1e-12:
68
- print("\n✅ TEST SUPERATO: Moduli collegati, PRNG JAX funzionante e rumore autenticamente non-deterministico!")
69
- else:
70
- print("\n❌ FALLIMENTO: Il rumore è ancora lineare o statico. Le due run hanno prodotto stati identici.")
71
-
72
- print("====================================================")
73
-
74
- except Exception as e:
75
- print(f"\n❌ CRASH DURANTE L'ELABORAZIONE HARDWARE: {str(e)}")
76
- print("====================================================")
@@ -1,76 +0,0 @@
1
- import time
2
- import numpy as np
3
- from dense_evolution import DenseSVSimulator, QASMParser, QuantumTranspiler, NoiseModel
4
-
5
- print("====================================================")
6
- print("TEST: KRAUS & JIT SIMULATION")
7
- print("====================================================")
8
-
9
- try:
10
- qasm_bench = """
11
- OPENQASM 2.0;
12
- include "qelib1.inc";
13
- qreg q[6];
14
- h q[0];
15
- cx q[0], q[1];
16
- cx q[1], q[2];
17
- cx q[2], q[3];
18
- cx q[3], q[4];
19
- cx q[4], q[5];
20
- rx(1.570796) q[0];
21
- ry(0.785398) q[1];
22
- rz(0.392699) q[2];
23
- """
24
-
25
- print("1. Parsing e Transpilazione del circuito QASM...")
26
- # Questo testa la corretta importazione e funzione di parser.py e compiler.py
27
- parser = QASMParser()
28
- circ = parser.parse(qasm_bench)
29
- tuples = QuantumTranspiler.transpile(circ.to_tuples())
30
- n_qubits = circ.n_qubits
31
- print(f"✓ Parsing completato. Qubit: {n_qubits}, Gate transpilati: {len(tuples)}")
32
-
33
- print("\n2. Validazione Core JIT in modalità ideale (simulator.py)...")
34
- t0 = time.perf_counter()
35
- sim_ideale = DenseSVSimulator(n_qubits)
36
- sim_ideale.run_circuit_jit_beast_mode(tuples)
37
- t_ideale = time.perf_counter() - t0
38
- prob_ideale = sim_ideale.get_probabilities()
39
- print(f"✓ Successo ideale in {t_ideale:.4f} s | Dimensione stato: {len(prob_ideale)}")
40
-
41
- print("\n3. Validazione NoiseModel (registry.py): Canale stocastico Amplitude Damping...")
42
-
43
- # Run Noisy 1
44
- t0 = time.perf_counter()
45
- sim_noisy1 = DenseSVSimulator(n_qubits)
46
- sim_noisy1.run_circuit_jit_beast_mode(tuples)
47
- # Iniezione diretta del rumore Kraus sullo statevector compilato
48
- sim_noisy1.sv = NoiseModel.apply_to_sv(sim_noisy1.sv, n_qubits, model='amplitude_damping', p=0.15)
49
- prob_noisy1 = sim_noisy1.get_probabilities()
50
- t_noisy1 = time.perf_counter() - t0
51
-
52
- # Run Noisy 2
53
- sim_noisy2 = DenseSVSimulator(n_qubits)
54
- sim_noisy2.run_circuit_jit_beast_mode(tuples)
55
- sim_noisy2.sv = NoiseModel.apply_to_sv(sim_noisy2.sv, n_qubits, model='amplitude_damping', p=0.15)
56
- prob_noisy2 = sim_noisy2.get_probabilities()
57
-
58
- print(f"✓ Successo noisy in {t_noisy1:.4f} s")
59
-
60
- print("\n4. Analisi statistica delle fluttuazioni (Shot Noise Reale)...")
61
- scostamento_stocastico = np.linalg.norm(prob_noisy1 - prob_noisy2)
62
- scostamento_ideale = np.linalg.norm(prob_ideale - prob_noisy1)
63
-
64
- print(f"🔬 Distanza ideale-noisy: {scostamento_ideale:.6f}")
65
- print(f"🔬 Fluttuazione quantistica indipendente (Shot Noise): {scostamento_stocastico:.6f}")
66
-
67
- if scostamento_stocastico > 1e-12:
68
- print("\n✅ TEST SUPERATO: Moduli collegati, PRNG JAX funzionante e rumore autenticamente non-deterministico!")
69
- else:
70
- print("\n❌ FALLIMENTO: Il rumore è ancora lineare o statico. Le due run hanno prodotto stati identici.")
71
-
72
- print("====================================================")
73
-
74
- except Exception as e:
75
- print(f"\n❌ CRASH DURANTE L'ELABORAZIONE HARDWARE: {str(e)}")
76
- print("====================================================")
File without changes