Skip to content

Commit d6e6d4e

Browse files
committed
Release 1.3.0
1 parent 6913faf commit d6e6d4e

14 files changed

+993
-4
lines changed

.gitignore

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,4 +13,5 @@ __pycache__/
1313
.DS_Store
1414
FULL.md
1515
dist/
16-
docs/
16+
build/
17+
docs/

CHANGELOG.md

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
# Changelog
2+
3+
## 1.3.0 — 2026-02-04
4+
5+
- Added witness "passport" utilities: CHSH (d=2) and CGLMP (d>2) in `witnesses.py`.
6+
- Added Σ-consistent vs generic unitary noise helpers in `sigma_noise.py`.
7+
- Added NumPy time-series pseudomultipolar cascade engine (`physics/pseudomultipolar_timeseries.py`) and demo scenario writing `.npz` + `summary.json`.
8+
- Added translation gap (n→2 projection) helpers (`physics/translation_gap.py`) and demo scenario writing `.npz` + `summary.json`.
9+
10+
## 1.2.0
11+
12+
- Sigma tools: `physics/sigma.py` (`p_perp`, `n_stage`, `nx_stage`) + `devices/sigma_guard.py`.
13+
- CPU pseudo-quantum layer: `simulation/multipolar_pseudo_quantum`.

CITATION.cff

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,8 @@ authors:
55
given-names: "Maxim"
66
email: "radaevm@gmail.com"
77
title: "loka_light: Compact multipolar toolkit for n-polar information systems"
8-
version: 1.2.0
9-
date-released: 2026-02-03
8+
version: 1.3.0
9+
date-released: 2026-02-04
1010
url: "https://github.com/r4dm/loka_light"
1111
license: "CC-BY-NC-4.0"
1212
keywords:

README.md

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -163,6 +163,47 @@ PY
163163
Writes `summary.json` under the chosen `outdir` with the measurement histogram,
164164
Σ trace by stage and a snapshot of the final state.
165165

166+
## DSP/physics‑toy demos (NumPy)
167+
168+
These scenarios write machine‑readable artefacts (JSON/NPZ) under `runs/` so you
169+
can inspect Σ traces, witness values, and projection losses without notebooks.
170+
171+
### 9. Pseudo‑Quantum Witness Pack (CHSH/CGLMP + Σ‑noise)
172+
173+
```bash
174+
python - <<'PY'
175+
from loka_light.applications.scenarios import pseudo_quantum_witness_pack
176+
pseudo_quantum_witness_pack({"seed": 123, "epsilon": 0.2})
177+
PY
178+
```
179+
180+
Writes `runs/pseudo_quantum_witness_pack/summary.json` with CHSH/CGLMP values and
181+
Σ‑invariant vs generic noise deltas (same seed/ε).
182+
183+
### 10. Pseudomultipolar Time‑Series Cascade (M→NX)
184+
185+
```bash
186+
python - <<'PY'
187+
from loka_light.applications.scenarios import pseudomultipolar_timeseries_demo
188+
pseudomultipolar_timeseries_demo({"n": 6, "steps": 256, "sections": 3, "tap": 0.5, "seed": 123})
189+
PY
190+
```
191+
192+
Writes `runs/pseudomultipolar_timeseries/series.npz` (O1/O2/O3 signals + traces)
193+
and `summary.json` (mean |Σ| per stage, monotonicity, RX mismatch metrics).
194+
195+
### 11. Translation Gap (n→2 projection)
196+
197+
```bash
198+
python - <<'PY'
199+
from loka_light.applications.scenarios import translation_gap_demo
200+
translation_gap_demo({"n": 6, "seed": 123})
201+
PY
202+
```
203+
204+
Writes `runs/translation_gap/gap.npz` and `summary.json` with visibility/loss
205+
metrics for a matched vs mismatched 2‑pole projection after Σ purification.
206+
166207
## Cascade Map (M → N/NX → RX)
167208

168209
```

applications/__init__.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,10 @@
88
property_transfer_chain,
99
structuring_field,
1010
pseudo_mnx_chain,
11+
pseudomultipolar_timeseries_demo,
12+
pseudo_quantum_hadamard_phase,
13+
pseudo_quantum_witness_pack,
14+
translation_gap_demo,
1115
)
1216

1317
__all__ = [
@@ -18,4 +22,8 @@
1822
"property_transfer_chain",
1923
"structuring_field",
2024
"pseudo_mnx_chain",
25+
"pseudomultipolar_timeseries_demo",
26+
"pseudo_quantum_hadamard_phase",
27+
"pseudo_quantum_witness_pack",
28+
"translation_gap_demo",
2129
]

applications/scenarios.py

Lines changed: 174 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -158,7 +158,10 @@ def _default_capacitor() -> MultiPlateCapacitor:
158158
"property_transfer_chain",
159159
"structuring_field",
160160
"pseudo_mnx_chain",
161+
"pseudomultipolar_timeseries_demo",
162+
"pseudo_quantum_witness_pack",
161163
"pseudo_quantum_hadamard_phase",
164+
"translation_gap_demo",
162165
]
163166

164167

@@ -243,3 +246,174 @@ def pseudo_quantum_hadamard_phase(params: Dict[str, Any]) -> None:
243246
)
244247

245248
(outdir / "summary.json").write_text(json.dumps(summary, indent=2))
249+
250+
251+
def pseudomultipolar_timeseries_demo(params: Dict[str, Any]) -> None:
252+
"""Run a time-series M→NX cascade and persist arrays + Σ/energy summaries.
253+
254+
Writes:
255+
- `series.npz` with O1/O2/O3 signals and Σ/energy traces.
256+
- `summary.json` with mean |Σ| (before and per NX section) and RX mismatch metrics.
257+
"""
258+
259+
from ..physics import pseudomultipolar_timeseries as pmts
260+
261+
n = int(params.get("n", 6))
262+
steps = int(params.get("steps", 256))
263+
seed = params.get("seed", 123)
264+
seed = None if seed is None else int(seed)
265+
carrier_cycles = float(params.get("carrier_cycles", 0.125))
266+
noise_std = float(params.get("noise_std", 0.0))
267+
268+
taps: List[float]
269+
if "taps" in params:
270+
taps = [float(x) for x in params["taps"]]
271+
else:
272+
sections = int(params.get("sections", 3))
273+
tap = float(params.get("tap", 0.5))
274+
taps = pmts.default_profiles(sections=sections, tap=tap)
275+
276+
sources = pmts.generate_sources(
277+
n,
278+
steps=steps,
279+
seed=seed,
280+
carrier_cycles=carrier_cycles,
281+
noise_std=noise_std,
282+
)
283+
result = pmts.run_cascade(sources, sections=taps)
284+
285+
rx_bad_energy = None
286+
rx_bad_mean_sigma = None
287+
if n >= 3:
288+
bad = pmts.project_rank(result.o3, n - 1)
289+
rx_bad_energy = float(np.mean(pmts.energy_trace(bad)))
290+
rx_bad_mean_sigma = float(np.mean(pmts.sigma_trace(bad)))
291+
292+
outdir = _outdir(params, "runs/pseudomultipolar_timeseries")
293+
np.savez(
294+
outdir / "series.npz",
295+
o1=result.o1,
296+
o2=result.o2,
297+
o3=result.o3,
298+
sigma_o1=result.sigma_o1,
299+
sigma_chain=np.stack(result.sigma_chain, axis=0),
300+
energy_o1=result.energy_o1,
301+
energy_o3=result.energy_o3,
302+
)
303+
(outdir / "summary.json").write_text(
304+
json.dumps(
305+
{
306+
"n": n,
307+
"steps": steps,
308+
"taps": list(result.taps),
309+
"seed": seed,
310+
"mean_abs_sigma_o1": result.mean_sigma_o1,
311+
"mean_abs_sigma_chain": result.mean_sigma_chain,
312+
"sigma_monotone": result.is_sigma_monotone(),
313+
"rx_good_energy": float(np.mean(result.energy_o3)),
314+
"rx_bad_energy": rx_bad_energy,
315+
"rx_bad_mean_abs_sigma": rx_bad_mean_sigma,
316+
},
317+
indent=2,
318+
)
319+
)
320+
321+
322+
def pseudo_quantum_witness_pack(params: Dict[str, Any]) -> None:
323+
"""Compute CHSH/CGLMP reference values + Σ-consistent noise telemetry."""
324+
325+
from .. import sigma_noise, witnesses
326+
327+
seed = params.get("seed", 123)
328+
seed = None if seed is None else int(seed)
329+
epsilon = float(params.get("epsilon", 0.2))
330+
d_values = [int(x) for x in params.get("d_values", [2, 3, 4, 5])]
331+
d_values = [d for d in d_values if d >= 2]
332+
if not d_values:
333+
d_values = [2, 3, 4, 5]
334+
335+
witness_table = {str(d): float(witnesses.cglmp_value(d)) for d in d_values}
336+
chsh = float(witnesses.chsh_value())
337+
338+
dim = int(params.get("noise_dim", max(8, max(d_values) ** 2)))
339+
rng_state = np.random.default_rng(seed)
340+
psi = (rng_state.normal(size=dim) + 1j * rng_state.normal(size=dim)).astype(np.complex128)
341+
norm = float(np.linalg.norm(psi))
342+
if norm == 0.0:
343+
psi = (np.ones(dim, dtype=np.complex128) + 0.0j) / np.sqrt(dim)
344+
else:
345+
psi = psi / norm
346+
sigma_in = complex(psi.sum())
347+
348+
rng_consistent = np.random.default_rng(None if seed is None else seed + 1)
349+
rng_generic = np.random.default_rng(None if seed is None else seed + 2)
350+
u_sigma = sigma_noise.unitary_sigma_consistent(dim, rng=rng_consistent, epsilon=epsilon)
351+
u_generic = sigma_noise.unitary_generic(dim, rng=rng_generic, epsilon=epsilon)
352+
sigma_out_sigma = complex((u_sigma @ psi).sum())
353+
sigma_out_generic = complex((u_generic @ psi).sum())
354+
355+
outdir = _outdir(params, "runs/pseudo_quantum_witness_pack")
356+
(outdir / "summary.json").write_text(
357+
json.dumps(
358+
{
359+
"seed": seed,
360+
"epsilon": epsilon,
361+
"witnesses": {
362+
"chsh_d2": chsh,
363+
"cglmp": witness_table,
364+
},
365+
"sigma_noise": {
366+
"dim": dim,
367+
"sigma_in": [float(sigma_in.real), float(sigma_in.imag)],
368+
"sigma_out_sigma_consistent": [float(sigma_out_sigma.real), float(sigma_out_sigma.imag)],
369+
"sigma_out_generic": [float(sigma_out_generic.real), float(sigma_out_generic.imag)],
370+
"delta_sigma_consistent": float(abs(sigma_out_sigma - sigma_in)),
371+
"delta_sigma_generic": float(abs(sigma_out_generic - sigma_in)),
372+
},
373+
},
374+
indent=2,
375+
)
376+
)
377+
378+
379+
def translation_gap_demo(params: Dict[str, Any]) -> None:
380+
"""Demonstrate the n→2 projection gap after Σ purification."""
381+
382+
from ..physics.translation_gap import translation_gap
383+
384+
n = int(params.get("n", 6))
385+
seed = params.get("seed", 123)
386+
seed = None if seed is None else int(seed)
387+
sigma_clean = bool(params.get("sigma_clean", True))
388+
389+
result, x, p_match, p_mismatch, y_match, y_mismatch = translation_gap(
390+
n,
391+
seed=seed,
392+
sigma_clean=sigma_clean,
393+
)
394+
395+
outdir = _outdir(params, "runs/translation_gap")
396+
np.savez(
397+
outdir / "gap.npz",
398+
x=x,
399+
p_match=p_match,
400+
p_mismatch=p_mismatch,
401+
y_match=y_match,
402+
y_mismatch=y_mismatch,
403+
)
404+
(outdir / "summary.json").write_text(
405+
json.dumps(
406+
{
407+
"n": result.n,
408+
"seed": seed,
409+
"sigma_clean": sigma_clean,
410+
"sigma_in": [float(result.sigma_in.real), float(result.sigma_in.imag)],
411+
"sigma_after_purify": [float(result.sigma_after_purify.real), float(result.sigma_after_purify.imag)],
412+
"visibility_match": float(result.visibility_match),
413+
"loss_match": float(result.loss_match),
414+
"visibility_mismatch": float(result.visibility_mismatch),
415+
"loss_mismatch": float(result.loss_mismatch),
416+
},
417+
indent=2,
418+
)
419+
)

0 commit comments

Comments
 (0)