From 2fccc4f3867f413aa6a565a4d4f7e5a9b4ca006f Mon Sep 17 00:00:00 2001 From: masteris777 Date: Sun, 23 Aug 2026 16:16:34 +0300 Subject: [PATCH 1/2] solaris 1.1.0: pluggable quantum layer (ports & adapters) - table, numpy, qutip, qiskit/aer Developers of quantum algorithms routinely run their code on classical simulators while the hardware is still scarce - that is what libraries like QuTiP and Qiskit Aer are for. Solaris 1.0.0 carried its own such simulation of the quantum layer: the amplitude table inside each shared contract. This release refactors that layer behind a ports-and-adapters (hexagonal) interface, so the ledger no longer cares whose mathematics holds the wave. - labs/engine/: the WaveEngine port, five methods (prepare / apply1 / cnot / branch_weight / project). The ledger reads branch norms and orders projections; the hash draw and the double-entry settlement decision stay on the ledger side. The port deliberately has no measure(): no backend can re-import the Born rule the model derives from two-signature settlement. - Adapters: table (our own implementation, the DEFAULT - stdlib-only reference semantics), numpy statevector, QuTiP, Qiskit/Aer (C++ statevector), plus a broken negative control for the harness. - labs/qm_battery.py --engine (or SOLARIS_ENGINE): all four adapters reproduce the frozen reference battery labs/qm_tests.py byte-identically (deterministic hash-fed draws make the comparison exact, not statistical). The broken control (weights |a| instead of |a|^2) fails 4/9 checks with CHSH ~1.9 - below even the classical bound. - Every physical mechanism is unchanged from implementation 0; the full 150-row battery was re-sat for this version: 147 pass, 3 pre-registered red (GR-34..36), expected-red gate green (tests/results/solaris-1.1.0.md). - Version card -> Solaris 1.1.0 (implementation 1); the compounding composition law moves to the implementation-2 candidate slot. The port is also the long-horizon socket: a future substrate construction that produces wave behaviour without storing amplitudes plugs in as one more adapter and sits the same exam. Co-Authored-By: Claude Fable 5 --- CHANGELOG.md | 26 ++++ CITATION.cff | 4 +- README.md | 19 +++ labs/engine/__init__.py | 37 +++++ labs/engine/broken.py | 17 +++ labs/engine/domain.py | 71 ++++++++++ labs/engine/numpy_sv.py | 67 +++++++++ labs/engine/port.py | 45 ++++++ labs/engine/qiskit_sv.py | 110 ++++++++++++++ labs/engine/qutip_qobj.py | 93 ++++++++++++ labs/engine/table.py | 55 +++++++ labs/qm_battery.py | 252 +++++++++++++++++++++++++++++++++ model/card.md | 6 +- model/implementation.md | 22 ++- requirements-engines.txt | 6 + tests/results/solaris-1.1.0.md | 161 +++++++++++++++++++++ 16 files changed, 983 insertions(+), 8 deletions(-) create mode 100644 labs/engine/__init__.py create mode 100644 labs/engine/broken.py create mode 100644 labs/engine/domain.py create mode 100644 labs/engine/numpy_sv.py create mode 100644 labs/engine/port.py create mode 100644 labs/engine/qiskit_sv.py create mode 100644 labs/engine/qutip_qobj.py create mode 100644 labs/engine/table.py create mode 100644 labs/qm_battery.py create mode 100644 requirements-engines.txt create mode 100644 tests/results/solaris-1.1.0.md diff --git a/CHANGELOG.md b/CHANGELOG.md index f4e8616..48368f6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,31 @@ # Changelog +## solaris-1.1.0 - 2026-08-23 + +The pluggable quantum layer. Developers of quantum algorithms routinely run +their code on classical simulators while hardware is scarce - that is what +libraries like QuTiP and Qiskit Aer are for. Solaris 1.0.0 carried its own +such simulation (the amplitude table inside each shared contract); this +release refactors it behind a ports-and-adapters interface so the ledger no +longer cares whose mathematics holds the wave. + +- `labs/engine/`: the WaveEngine port (prepare / apply1 / cnot / + branch_weight / project - deliberately no `measure()`: the hash draw and + the double-entry settlement decision stay on the ledger side) with four + adapters: `table` (the original arithmetic, DEFAULT, stdlib-only), + `numpy`, `qutip`, `qiskit` (Aer statevector), plus a `broken` negative + control for the harness. +- `labs/qm_battery.py --engine ` (or `SOLARIS_ENGINE`): the nine-check + QM battery, engine-parameterized. All four adapters reproduce the frozen + reference `labs/qm_tests.py` byte-identically (hash-fed deterministic + draws make the comparison exact); the broken control fails 4/9 checks and + its CHSH drops to ~1.9, below even the classical bound - the |a| law is + not almost-quantum, it is worse than classical. +- Every physical mechanism is unchanged from implementation 0; the full + 150-row battery was re-sat for this version (`tests/results/solaris-1.1.0.md`, + same 147 pass / 3 pre-registered red). +- Optional backends install: `pip install -r requirements-engines.txt`. + ## Unreleased Repository restructure (2026-08-21): `model/` added (version card + the three diff --git a/CITATION.cff b/CITATION.cff index f7f36dc..a9770f2 100644 --- a/CITATION.cff +++ b/CITATION.cff @@ -5,8 +5,8 @@ authors: - family-names: Masteika given-names: Marijus orcid: "https://orcid.org/0009-0004-2464-3008" -version: solaris-1.0.0 -date-released: 2026-08-20 +version: solaris-1.1.0 +date-released: 2026-08-23 license: MIT repository-code: "https://github.com/questforentropy/iceberg-model" doi: 10.5281/zenodo.22046196 diff --git a/README.md b/README.md index 10f2d84..e845dbe 100644 --- a/README.md +++ b/README.md @@ -36,6 +36,25 @@ never softened. Version-independent row definitions live in `tests/definitions/` the generated record - status, declared criterion, and measured detail per row - in `tests/results/`. Individual sets run by name: `python labs/run_exams.py QM GR`. +### Swap the quantum engine (Solaris 1.1.0) + +The amplitude arithmetic sits behind a small port (`labs/engine/`), so the wave +storage is swappable. The nine-check QM battery runs on any of four backends and +must reproduce the frozen reference `labs/qm_tests.py` byte-for-byte: + +``` +python labs/qm_battery.py # default: table (stdlib-only) +pip install -r requirements-engines.txt # then: +python labs/qm_battery.py --engine numpy +python labs/qm_battery.py --engine qutip +python labs/qm_battery.py --engine qiskit # Aer statevector +``` + +Draws are hash-fed and deterministic, so conformance is exact - identical output, +not statistically similar. `--engine broken` runs the negative control (weights +|a| instead of |a|²): it fails 4 of 9 checks, demonstrating the battery detects a +wrong engine. + All numbers - like every experiment behind them - were produced with AI assistance and are under continuing verification and validation; the one-command reproduction exists precisely so any reader can check any number diff --git a/labs/engine/__init__.py b/labs/engine/__init__.py new file mode 100644 index 0000000..289e744 --- /dev/null +++ b/labs/engine/__init__.py @@ -0,0 +1,37 @@ +# Solaris 1.1.0 - the pluggable quantum layer (ports & adapters). +# +# The ledger (domain.py Contract: hash draws + settlement decisions) talks to the wave +# storage only through the WaveEngine port (port.py). Adapters are selected here, lazily: +# a missing library only disables its own name, never the package. +# +# Certified: all four engines +# reproduce the Solaris 1.0.0 qm_tests.py battery BYTE-IDENTICALLY (see CHANGELOG 1.1.0); the "broken" negative +# control (|a| instead of |a|^2) is caught by the same differential. +# +# Selection: qm_battery.py --engine , or the SOLARIS_ENGINE env var. Default: table +# (our reference implementation - stdlib-only, the semantics every other adapter must match). + +import os + +DEFAULT_ENGINE = "table" +ENGINE_NAMES = ("table", "numpy", "qutip", "qiskit", "broken") + + +def select_engine(name=None): + name = name or os.environ.get("SOLARIS_ENGINE") or DEFAULT_ENGINE + if name == "table": + from .table import TableEngine + return TableEngine() + if name == "numpy": + from .numpy_sv import NumpyEngine + return NumpyEngine() + if name == "qutip": + from .qutip_qobj import QutipEngine + return QutipEngine() + if name == "qiskit": + from .qiskit_sv import QiskitEngine + return QiskitEngine() + if name == "broken": # negative control - harness self-test only, never physics + from .broken import BrokenEngine + return BrokenEngine() + raise ValueError("unknown engine %r (expected one of %s)" % (name, ", ".join(ENGINE_NAMES))) diff --git a/labs/engine/broken.py b/labs/engine/broken.py new file mode 100644 index 0000000..e17115f --- /dev/null +++ b/labs/engine/broken.py @@ -0,0 +1,17 @@ +# Solaris 1.1.0 - BrokenEngine: negative control adapter (harness self-test only). +# When plugged in, the battery fails 4/9 checks and CHSH falls to ~1.9 - below even the classical bound. +# +# TableEngine with exactly one defect: branch_weight returns p1 ** 0.5 instead of p1 +# (the "1-signer" law, known wrong under the double-entry / |alpha|**2 ruling). project() +# is inherited unchanged - it recomputes the TRUE p1 from ref.amps itself (not the broken +# value handed to the domain), so the state stays a valid normalized vector; only the +# accept/reject THRESHOLD the domain compares its draw against is wrong. This isolates the +# defect to a single method. + +from .table import TableEngine + + +class BrokenEngine(TableEngine): + def branch_weight(self, ref, q): + p1 = super().branch_weight(ref, q) + return p1 ** 0.5 diff --git a/labs/engine/domain.py b/labs/engine/domain.py new file mode 100644 index 0000000..61ed565 --- /dev/null +++ b/labs/engine/domain.py @@ -0,0 +1,71 @@ +# Solaris 1.1.0 - domain.py: Contract (seed + draw counter, hash-fed measurement decisions) +# Verified byte-identical to the reference battery (see CHANGELOG 1.1.0). +# +# Contract mirrors QContract's public method surface (labs/qm_tests.py, +# repo root, READ-ONLY) exactly, but never touches amplitudes directly - every state read or +# mutation goes through the five WaveEngine port methods on self.engine. H, u01, and the gate +# matrices are IMPORTED (read-only) from the original module, never copied. +# +# measure_z/measure_angle/measure_pauli reproduce QContract's operation order verbatim: +# weight <- port.branch_weight, bit <- domain draw (u01(H(seed,"draw",n))), project <- +# port.project, (un)rotations via port.apply1 in the same order as the original methods. +# Draw counter semantics: one draw per z-measurement, counter starts at 0, incremented +# BEFORE use (self.draws += 1 then hash) - matches QContract._draw exactly. + +import sys +import math +from pathlib import Path + +_QM_TESTS_DIR = Path(__file__).resolve().parents[1] +if not (_QM_TESTS_DIR / "qm_tests.py").exists(): + raise RuntimeError("qm_tests.py not found at %s - repo layout assumption broken" % _QM_TESTS_DIR) +sys.path.insert(0, str(_QM_TESTS_DIR)) +import qm_tests # noqa: E402 (READ-ONLY import, never modified) +from qm_tests import H, u01, RY, RZ, HAD, S_GATE, SDG # noqa: E402,F401 + + +class Contract: + """Domain object: seed + draw counter + a bound (engine, ref) pair. + No amplitude arithmetic lives here - every state operation is a port call.""" + + def __init__(self, seed, engine, ref): + self.seed = seed + self.engine = engine + self.ref = ref + self.draws = 0 + + def _draw(self): + self.draws += 1 + return u01(H(self.seed, "draw", self.draws)) + + def apply1(self, U, q): + self.engine.apply1(self.ref, U, q) + + def cnot(self, c, t): + self.engine.cnot(self.ref, c, t) + + def measure_z(self, q): + # GLOBAL UPDATE (via port): weight read, hash draw, projection - same order as + # QContract.measure_z, split across the port boundary. + p1 = self.engine.branch_weight(self.ref, q) + bit = 1 if self._draw() < p1 else 0 + self.engine.project(self.ref, q, bit) + return -1 if bit else 1 + + def measure_angle(self, q, theta): + self.apply1(RY(-theta), q) + r = self.measure_z(q) + self.apply1(RY(theta), q) + return r + + def measure_pauli(self, q, which): + if which == "Z": + return self.measure_z(q) + if which == "X": + return self.measure_angle(q, math.pi / 2) + self.apply1(SDG, q) + self.apply1(HAD, q) + r = self.measure_z(q) + self.apply1(HAD, q) + self.apply1(S_GATE, q) + return r diff --git a/labs/engine/numpy_sv.py b/labs/engine/numpy_sv.py new file mode 100644 index 0000000..93f2143 --- /dev/null +++ b/labs/engine/numpy_sv.py @@ -0,0 +1,67 @@ +# Solaris 1.1.0 - NumpyEngine: NumPy statevector adapter. +# +# complex128 ndarray state, vectorized apply1/cnot/branch_weight/project. NO numpy.random +# anywhere - the only entropy in this lab is the domain's u01(H(seed,"draw",n)), never +# touched by this file. Index sets are built once per call from Python range() (deterministic, +# not RNG) so the branch masks are constructed in the SAME index order as TableEngine's +# generator expressions - kept for the closest possible float agreement, not required for +# correctness (the conformance bar is byte-identical battery stdout; a near-threshold +# fence covers float-order edge cases). + +import math +import numpy as np + + +class NpStateRef: + __slots__ = ("amps",) + + def __init__(self, amps): + self.amps = np.array([complex(a) for a in amps], dtype=np.complex128) + + +class NumpyEngine: + def prepare(self, amps): + return NpStateRef(amps) + + def apply1(self, ref, U, q): + step = 1 << q + a = ref.amps + n = len(a) + idx0 = np.array([i for i in range(n) if not (i & step)], dtype=np.int64) + idx1 = idx0 | step + a0 = a[idx0].copy() + a1 = a[idx1].copy() + a[idx0] = U[0][0] * a0 + U[0][1] * a1 + a[idx1] = U[1][0] * a0 + U[1][1] * a1 + + def cnot(self, ref, c, t): + cs, ts = 1 << c, 1 << t + a = ref.amps + n = len(a) + idx = np.array([i for i in range(n) if (i & cs) and not (i & ts)], dtype=np.int64) + jdx = idx | ts + old_i = a[idx].copy() + old_j = a[jdx].copy() + a[idx] = old_j + a[jdx] = old_i + + def _mask(self, ref, q): + step = 1 << q + n = len(ref.amps) + return np.array([bool(i & step) for i in range(n)], dtype=bool) + + def branch_weight(self, ref, q): + mask = self._mask(ref, q) + return float(np.sum(np.abs(ref.amps[mask]) ** 2)) + + def project(self, ref, q, bit): + mask = self._mask(ref, q) + p1 = float(np.sum(np.abs(ref.amps[mask]) ** 2)) + norm = math.sqrt(p1 if bit else 1 - p1) + keep = mask if bit else ~mask + new = np.where(keep, ref.amps / norm, 0j).astype(np.complex128) + ref.amps = new + + def overlap(self, ref, amps): + b = np.array([complex(x) for x in amps], dtype=np.complex128) + return complex(np.vdot(ref.amps, b)) diff --git a/labs/engine/port.py b/labs/engine/port.py new file mode 100644 index 0000000..60f6cee --- /dev/null +++ b/labs/engine/port.py @@ -0,0 +1,45 @@ +# Solaris 1.1.0 - The WaveEngine Port (interface only, no logic). +# +# WaveEngine: holds the wave: answers SMALL questions; never draws, never decides. +# Concrete adapters (table_engine.py, broken_engine.py, numpy_engine.py) implement this +# structurally (duck typing via typing.Protocol) - no inheritance required. +# +# Five port methods used by the domain/battery: prepare, apply1, cnot, branch_weight, project. +# `overlap` exists for probe-stage diagnostics only (never called from domain.py or the +# battery's measurement path). +# +# Deliberately absent: measure() (would re-import Born sampling), get_amplitudes() / +# branch iteration (the "hand me your entire contents" question the design note forbids). + +from typing import Protocol, Sequence, Any, runtime_checkable + +StateRef = Any # opaque per-adapter handle; callers never introspect its attributes + + +@runtime_checkable +class WaveEngine(Protocol): + """Port. Structural interface - adapters need not inherit this class.""" + + def prepare(self, amps: Sequence[complex]) -> StateRef: + """Contract genesis from an explicit branch-amplitude list.""" + ... + + def apply1(self, ref: StateRef, U, q: int) -> None: + """Apply a single-qubit unitary U to qubit q of ref, in place.""" + ... + + def cnot(self, ref: StateRef, c: int, t: int) -> None: + """Apply CNOT(control=c, target=t) to ref, in place.""" + ... + + def branch_weight(self, ref: StateRef, q: int) -> float: + """|branch|**2 for qubit q's '1' branch. A norm read. NO sampling.""" + ... + + def project(self, ref: StateRef, q: int, bit: int) -> None: + """Keep the chosen branch, renormalize. The caller (domain) already drew.""" + ... + + def overlap(self, ref: StateRef, amps: Sequence[complex]) -> complex: + """ - diagnostics only (probe / sanity checks), never domain logic.""" + ... diff --git a/labs/engine/qiskit_sv.py b/labs/engine/qiskit_sv.py new file mode 100644 index 0000000..16eb069 --- /dev/null +++ b/labs/engine/qiskit_sv.py @@ -0,0 +1,110 @@ +# Solaris 1.1.0 - QiskitEngine: Qiskit/Aer-backed adapter. +# +# State = qiskit_aer.quantum_info.AerStatevector (Aer's C++ arithmetic). Falls back to +# qiskit.quantum_info.Statevector only if AerStatevector lacks a needed op; AER_STATEVECTOR_USED +# module flag records which was actually exercised (checked by the harness, not +# hand-set - a real fallback would flip it to False during the run). +# +# Qiskit's own statevector indexing is little-endian (qubit q = bit q of the index, q=0 least +# significant) - the SAME convention this port uses, verified empirically before writing this +# file: AerStatevector([0,1,0,0]).probabilities([0]) == [0,1] (weight(q0)=1) and +# .probabilities([1]) == [1,0] (weight(q1)=0), matching the ordering-gate case 1 expectation +# directly, with no reversal needed. evolve(Operator(...), qargs=[...]) was also verified to +# apply CNOT(control=0,target=1) to [0,1,0,0] -> [0,0,0,1], matching gate case 3. +# +# apply1/cnot go through real qiskit Operator.evolve() (the "foreign arithmetic" this lab +# tests). branch_weight uses .probabilities() (a norm read, not a sample). project manipulates +# .data directly inside the adapter (permitted - "an adapter may introspect its own state +# freely"). No qiskit_aer.run()/sample(), no Statevector.measure(), no RNG anywhere here. + +import math +import numpy as np +import qiskit +import qiskit_aer +from qiskit.circuit.library import CXGate +from qiskit.quantum_info import Operator, Statevector +from qiskit_aer.quantum_info import AerStatevector + +QISKIT_VERSION = qiskit.__version__ +QISKIT_AER_VERSION = qiskit_aer.__version__ + + +class QiskitStateRef: + __slots__ = ("state", "nq", "used_aer") + + def __init__(self, state, nq, used_aer): + self.state = state + self.nq = nq + self.used_aer = used_aer + + +def _nq_from_len(n): + nq = n.bit_length() - 1 + if (1 << nq) != n: + raise ValueError("amplitude vector length %d is not a power of 2" % n) + return nq + + +class QiskitEngine: + def __init__(self): + self.aer_statevector_used = True # flips to False if any fallback is exercised + + def prepare(self, amps): + amps = list(amps) + nq = _nq_from_len(len(amps)) + data = np.array([complex(a) for a in amps], dtype=np.complex128) + try: + state = AerStatevector(data) + used_aer = True + except Exception: + state = Statevector(data) + used_aer = False + self.aer_statevector_used = False + return QiskitStateRef(state, nq, used_aer) + + def apply1(self, ref, U, q): + op = Operator(np.array(U, dtype=np.complex128)) + try: + ref.state = ref.state.evolve(op, qargs=[q]) + except Exception: + ref.state = Statevector(ref.state.data).evolve(op, qargs=[q]) + ref.used_aer = False + self.aer_statevector_used = False + + def cnot(self, ref, c, t): + # Operator(CXGate()) is defined with LOCAL qubit 0 = control, LOCAL qubit 1 = target, + # in Qiskit's own little-endian convention; qargs=[c, t] maps local 0->c, local 1->t, + # which was verified empirically (before writing this file) to reproduce + # cnot(c=0,t=1) on [0,1,0,0] -> [0,0,0,1], matching the ordering-gate case 3 target. + # (A hand-derived 4x4 matrix in the opposite control/target convention was tried first + # and failed the ordering self-test - the one fix iteration this adapter + # needed; CXGate() replaced it.) + op = Operator(CXGate()) + try: + ref.state = ref.state.evolve(op, qargs=[c, t]) + except Exception: + ref.state = Statevector(ref.state.data).evolve(op, qargs=[c, t]) + ref.used_aer = False + self.aer_statevector_used = False + + def branch_weight(self, ref, q): + probs = ref.state.probabilities([q]) + return float(probs[1]) + + def project(self, ref, q, bit): + step = 1 << q + data = np.asarray(ref.state.data) + mask = np.array([(i & step) != 0 for i in range(len(data))], dtype=bool) + keep = mask if bit else ~mask + p1 = float(np.sum(np.abs(data[mask]) ** 2)) + norm = math.sqrt(p1 if bit else 1 - p1) + new_data = np.where(keep, data / norm, 0j).astype(np.complex128) + if ref.used_aer: + ref.state = AerStatevector(new_data) + else: + ref.state = Statevector(new_data) + + def overlap(self, ref, amps): + b = np.array([complex(x) for x in amps], dtype=np.complex128) + a = np.asarray(ref.state.data) + return complex(np.vdot(a, b)) diff --git a/labs/engine/qutip_qobj.py b/labs/engine/qutip_qobj.py new file mode 100644 index 0000000..9b7b584 --- /dev/null +++ b/labs/engine/qutip_qobj.py @@ -0,0 +1,93 @@ +# Solaris 1.1.0 - QutipEngine: QuTiP-backed adapter. +# +# State = a plain qutip.Qobj ket, built directly from the amplitude list passed to prepare() +# (no reordering on construction - .full() returns exactly what was stored, verified against +# TableEngine's byte-for-byte index convention: bit q of index i, q=0 least significant). +# +# QuTiP's tensor() puts the FIRST factor as the MOST significant digit of the composite index +# (standard Kronecker convention). Our convention is the opposite (q=0 is LEAST significant). +# So every operator built via qutip.tensor([...]) below places qubit q at tensor POSITION +# nq-1-q (the endianness reversal). This mapping was verified empirically before +# writing this file (not guessed): apply1(HAD, q=0) on prepare([0,1,0,0]) with this position +# map reproduces TableEngine's [1/sqrt2, -1/sqrt2, 0, 0] exactly, and cnot(c=0,t=1) on +# prepare([0,1,0,0]) reproduces [0,0,0,1] - both cross-checked by hand first. +# +# apply1/cnot go through real qutip.Qobj matrix multiplication (the "foreign arithmetic" this +# lab tests). branch_weight/project introspect the adapter's OWN state via .full() (permitted - +# "an adapter may introspect its own state freely"; the forbidden thing is the DOMAIN doing +# it). No qutip.measurement, no library sampling, no RNG anywhere in this file. + +import math +import numpy as np +import qutip + +QUTIP_VERSION = qutip.__version__ + + +class QutipStateRef: + __slots__ = ("state", "nq") + + def __init__(self, state, nq): + self.state = state + self.nq = nq + + +def _nq_from_len(n): + nq = n.bit_length() - 1 + if (1 << nq) != n: + raise ValueError("amplitude vector length %d is not a power of 2" % n) + return nq + + +class QutipEngine: + def prepare(self, amps): + amps = list(amps) + n = len(amps) + nq = _nq_from_len(n) + data = np.array([complex(a) for a in amps], dtype=np.complex128).reshape(-1, 1) + state = qutip.Qobj(data, dims=[[2] * nq, [1] * nq]) + return QutipStateRef(state, nq) + + def apply1(self, ref, U, q): + nq = ref.nq + pos = nq - 1 - q + Uq = qutip.Qobj(np.array(U, dtype=np.complex128)) + ops = [qutip.qeye(2)] * nq + ops[pos] = Uq + full = qutip.tensor(ops) + ref.state = full * ref.state + + def cnot(self, ref, c, t): + nq = ref.nq + pc, pt = nq - 1 - c, nq - 1 - t + proj0 = qutip.Qobj(np.array([[1, 0], [0, 0]], dtype=np.complex128)) + proj1 = qutip.Qobj(np.array([[0, 0], [0, 1]], dtype=np.complex128)) + X = qutip.Qobj(np.array([[0, 1], [1, 0]], dtype=np.complex128)) + ops_a = [qutip.qeye(2)] * nq + ops_a[pc] = proj0 + ops_b = [qutip.qeye(2)] * nq + ops_b[pc] = proj1 + ops_b[pt] = X + full = qutip.tensor(ops_a) + qutip.tensor(ops_b) + ref.state = full * ref.state + + def branch_weight(self, ref, q): + step = 1 << q + amps = ref.state.full().flatten() + return float(sum(abs(a) ** 2 for i, a in enumerate(amps) if i & step)) + + def project(self, ref, q, bit): + step = 1 << q + amps = ref.state.full().flatten() + p1 = float(sum(abs(a) ** 2 for i, a in enumerate(amps) if i & step)) + norm = math.sqrt(p1 if bit else 1 - p1) + new_amps = np.array( + [a / norm if bool(i & step) == bool(bit) else 0j for i, a in enumerate(amps)], + dtype=np.complex128, + ).reshape(-1, 1) + ref.state = qutip.Qobj(new_amps, dims=[[2] * ref.nq, [1] * ref.nq]) + + def overlap(self, ref, amps): + b = np.array([complex(x) for x in amps], dtype=np.complex128) + a = ref.state.full().flatten() + return complex(np.vdot(a, b)) diff --git a/labs/engine/table.py b/labs/engine/table.py new file mode 100644 index 0000000..9016132 --- /dev/null +++ b/labs/engine/table.py @@ -0,0 +1,55 @@ +# Solaris 1.1.0 - TableEngine: the reference WaveEngine adapter (DEFAULT). +# +# QContract's list arithmetic (labs/qm_tests.py) +# copied VERBATIM: same loops, same summation order, minus _draw/measure_* (moved to +# domain.py). This is the reference adapter every other backend must match byte-for-byte. + +import math + + +class StateRef: + """Opaque per-contract handle. Only table_engine.py ever reads/writes .amps.""" + + __slots__ = ("amps",) + + def __init__(self, amps): + self.amps = [complex(a) for a in amps] + + +class TableEngine: + def prepare(self, amps): + return StateRef(amps) + + def apply1(self, ref, U, q): + step = 1 << q + a = ref.amps + for i in range(len(a)): + if not (i & step): + j = i | step + a0, a1 = a[i], a[j] + a[i] = U[0][0] * a0 + U[0][1] * a1 + a[j] = U[1][0] * a0 + U[1][1] * a1 + + def cnot(self, ref, c, t): + cs, ts = 1 << c, 1 << t + a = ref.amps + for i in range(len(a)): + if (i & cs) and not (i & ts): + j = i | ts + a[i], a[j] = a[j], a[i] + + def branch_weight(self, ref, q): + step = 1 << q + return sum(abs(a) ** 2 for i, a in enumerate(ref.amps) if i & step) + + def project(self, ref, q, bit): + step = 1 << q + a = ref.amps + p1 = sum(abs(x) ** 2 for i, x in enumerate(a) if i & step) + norm = math.sqrt(p1 if bit else 1 - p1) + ref.amps = [x / norm if bool(i & step) == bool(bit) else 0j + for i, x in enumerate(a)] + + def overlap(self, ref, amps): + b = [complex(x) for x in amps] + return sum(x.conjugate() * y for x, y in zip(ref.amps, b)) diff --git a/labs/qm_battery.py b/labs/qm_battery.py new file mode 100644 index 0000000..6cf3481 --- /dev/null +++ b/labs/qm_battery.py @@ -0,0 +1,252 @@ +# Solaris 1.1.0 - qm_battery.py: the nine qm_tests.py checks through the WaveEngine port. +# Byte-identical to qm_tests.py for the table/numpy/qutip/qiskit adapters (see CHANGELOG 1.1.0). +# +# python labs/qm_battery.py # default engine (table, stdlib-only) +# python labs/qm_battery.py --engine qiskit # or SOLARIS_ENGINE env var +# +# Foreign engines need their library installed: +# pip install -r requirements-engines.txt # numpy, qutip, qiskit, qiskit-aer +# qm_tests.py remains the frozen Solaris 1.0.0 reference battery; this file must reproduce +# its stdout byte-for-byte on every conformant engine. +# +# Every check body below is copied from labs/qm_tests.py main() with PLUMBING-ONLY edits: +# - QContract(seed, amps) -> Contract(seed, engine, engine.prepare(amps)) +# - singlet(seed)/ghz(seed)/... -> make_singlet(engine, seed)/make_ghz(engine, seed)/... +# - chsh(make, qa, qb, n, tag) -> chsh_ported(engine, make, qa, qb, n, tag) +# - c.apply1/cnot/measure_* -> UNCHANGED (Contract exposes the identical method +# surface as QContract; only its internals moved +# behind the port) +# H, u01, SQ2, RY, RZ, HAD, S_GATE, SDG, ALICE_ANGLES, BOB_ANGLES are IMPORTED from qm_tests, +# never copied. Prints NO extra lines beyond the original's checks + summary line. + +import sys +import math +from pathlib import Path + +_QM_TESTS_DIR = Path(__file__).resolve().parent +sys.path.insert(0, str(_QM_TESTS_DIR)) +from qm_tests import H, u01, SQ2, RY, RZ, HAD, S_GATE, SDG, ALICE_ANGLES, BOB_ANGLES # noqa: E402,F401 + +from engine import select_engine, DEFAULT_ENGINE, ENGINE_NAMES # noqa: E402 +from engine.domain import Contract # noqa: E402 + + +# --- amplitude literals (restated verbatim from qm_tests.py singlet/ghz/w_state/ +# singlet_plus_spectator - not importable as bare amps since the originals return a +# QContract, not a list; SQ2 is the imported constant so the float values are identical) --- + +def singlet_amps(): + return [0, 1 / SQ2, -1 / SQ2, 0] + + +def ghz_amps(): + a = [0j] * 8 + a[0] = a[7] = 1 / SQ2 + return a + + +def w_state_amps(): + a = [0j] * 8 + a[1] = a[2] = a[4] = 1 / math.sqrt(3) + return a + + +def singlet_plus_spectator_amps(): + a = [0j] * 8 + a[1] = 1 / SQ2 + a[2] = -1 / SQ2 + return a + + +def make_singlet(engine, seed): + return Contract(seed, engine, engine.prepare(singlet_amps())) + + +def make_ghz(engine, seed): + return Contract(seed, engine, engine.prepare(ghz_amps())) + + +def make_w_state(engine, seed): + return Contract(seed, engine, engine.prepare(w_state_amps())) + + +def make_singlet_plus_spectator(engine, seed): + return Contract(seed, engine, engine.prepare(singlet_plus_spectator_amps())) + + +def chsh_ported(engine, make, qa, qb, n, tag): + bins = {} + for t in range(n): + c = make(engine, H(tag, t)) + ia = int(H(tag, t, "sa"), 16) % 2 + ib = int(H(tag, t, "sb"), 16) % 2 + ra = c.measure_angle(qa, ALICE_ANGLES[ia]) + rb = c.measure_angle(qb, BOB_ANGLES[ib]) + bins.setdefault((ia, ib), []).append(ra * rb) + E = {k: sum(v) / len(v) for k, v in bins.items()} + S = abs(E[(0, 0)] - E[(0, 1)] + E[(1, 0)] + E[(1, 1)]) + return S, min(len(v) for v in bins.values()) + + +def check(label, ok, detail): + print("%-6s %-6s %s" % ("PASS" if ok else "FAIL", label, detail)) + return ok + + +def main(engine): + R = [] + + # C0: engine consistency - singlet correlation curve and CHSH + n = 4000 + worst = 0.0 + for k in range(9): + delta = k * math.pi / 8 + tot = 0 + for t in range(n): + c = make_singlet(engine, H("c0", k, t)) + tot += c.measure_angle(0, 0.0) * c.measure_angle(1, delta) + worst = max(worst, abs(tot / n + math.cos(delta))) + S, nb = chsh_ported(engine, make_singlet, 0, 1, 16000, "c0chsh") + sig = 2 / math.sqrt(nb) + R.append(check("C0", worst < 0.09 and abs(S - 2 * SQ2) < 5 * sig, + "E(d) = -cos d, max dev %.4f (<0.09); CHSH S = %.4f (2.8284 +/- %.3f)" + % (worst, S, 5 * sig))) + + # Q1: repeatability - same axis twice always agrees + agree = 0 + n = 3000 + for t in range(n): + c = Contract(H("q1", t), engine, engine.prepare([1, 0])) + th = 2 * math.pi * u01(H("q1prep", t)) + c.apply1(RY(th), 0) + axis = 2 * math.pi * u01(H("q1axis", t)) + agree += c.measure_angle(0, axis) == c.measure_angle(0, axis) + R.append(check("Q1", agree == n, "same-axis remeasure: %d/%d agree" % (agree, n))) + + # Q2: non-commutativity - Z,X,Z re-randomizes; Z,Z stays + n = 4000 + same_zxz = 0 + same_zz = 0 + for t in range(n): + c = Contract(H("q2", t), engine, engine.prepare([1 / SQ2, 1 / SQ2])) + r1 = c.measure_z(0) + c.measure_pauli(0, "X") + same_zxz += r1 == c.measure_z(0) + c2 = Contract(H("q2b", t), engine, engine.prepare([1 / SQ2, 1 / SQ2])) + same_zz += c2.measure_z(0) == c2.measure_z(0) + frac = same_zxz / n + R.append(check("Q2", abs(frac - 0.5) < 5 / (2 * math.sqrt(n)) and same_zz == n, + "Z,X,Z agree %.4f (target 0.5); Z,Z agree %d/%d" % (frac, same_zz, n))) + + # Q4: interference and which-path decoherence (P3, P9) + def mz(t, phi, record): + c = Contract(H("q4", t, phi, record), engine, engine.prepare([1, 0, 0, 0])) + c.apply1(HAD, 0) + if record: + c.cnot(0, 1) + c.apply1(RZ(phi), 0) + c.apply1(HAD, 0) + return c.measure_z(0) == 1 + n = 2500 + + def visibility(record): + ps = [] + for k in range(9): + phi = k * 2 * math.pi / 8 + p0 = sum(mz(t, phi, record) for t in range(n)) / n + ps.append(p0) + return (max(ps) - min(ps)) / (max(ps) + min(ps)) + v_free, v_rec = visibility(False), visibility(True) + R.append(check("Q4", v_free > 0.95 and v_rec < 0.10, + "visibility %.3f without record, %.3f with which-path record" % (v_free, v_rec))) + + # Q5: GHZ / Mermin - deterministic wins, M = 4; best LHV = 2 + settings = [("X", "X", "X", 1), ("X", "Y", "Y", -1), ("Y", "X", "Y", -1), ("Y", "Y", "X", -1)] + n = 1500 + ok_all = True + M = 0.0 + for sa, sb, sc, target in settings: + tot = 0 + for t in range(n): + c = make_ghz(engine, H("q5", sa, sb, sc, t)) + p = c.measure_pauli(0, sa) * c.measure_pauli(1, sb) * c.measure_pauli(2, sc) + tot += p + if p != target: + ok_all = False + M += (tot / n) * (1 if target == 1 else -1) + lhv_M = abs(1 - 1 - 1 - 1) # best deterministic LHV assignment: |M| = 2 + R.append(check("Q5", ok_all and abs(M - 4) < 1e-9 and lhv_M == 2, + "every round exact: M = %.4f (LHV best = %d)" % (M, lhv_M))) + + # Q6: monogamy - GHZ pairwise classical; Toner bound on all states + S_ghz_ab, _ = chsh_ported(engine, make_ghz, 0, 1, 12000, "q6ghz") + S_sp_ab, nb1 = chsh_ported(engine, make_singlet_plus_spectator, 0, 1, 12000, "q6ab") + S_sp_ac, _ = chsh_ported(engine, make_singlet_plus_spectator, 0, 2, 12000, "q6ac") + S_w_ab, _ = chsh_ported(engine, make_w_state, 0, 1, 12000, "q6w") + S_w_ac, _ = chsh_ported(engine, make_w_state, 0, 2, 12000, "q6wc") + toner = [("singlet+spec", S_sp_ab, S_sp_ac), ("W", S_w_ab, S_w_ac)] + toner_ok = all(sab ** 2 + sac ** 2 <= 8 + 0.45 for _, sab, sac in toner) + sig1 = 2 / math.sqrt(nb1) + R.append(check("Q6", S_ghz_ab <= 2 + 5 * sig1 and abs(S_sp_ab - 2 * SQ2) < 5 * sig1 and toner_ok, + "GHZ pair S = %.3f (<=2); singlet S_AB = %.3f, S_AC = %.3f; " + "W S_AB = %.3f, S_AC = %.3f; Toner sums %.2f, %.2f (<=8)" + % (S_ghz_ab, S_sp_ab, S_sp_ac, S_w_ab, S_w_ac, + S_sp_ab ** 2 + S_sp_ac ** 2, S_w_ab ** 2 + S_w_ac ** 2))) + + # Q7: three-party no-signalling - marginals flat across others' settings + n = 2000 + marg = {} + for sa, sb, sc, _ in settings: + for t in range(n): + c = make_ghz(engine, H("q7", sa, sb, sc, t)) + outs = (c.measure_pauli(0, sa), c.measure_pauli(1, sb), c.measure_pauli(2, sc)) + for who in range(3): + marg.setdefault((who, (sa, sb, sc)), []).append(outs[who]) + shift = 0.0 + for who in range(3): + means = [sum(v) / len(v) for (w, _), v in marg.items() if w == who] + shift = max(shift, max(means) - min(means)) + R.append(check("Q7", shift < 5 * math.sqrt(2.0 / n), + "max marginal shift across settings %.4f (< %.4f)" % (shift, 5 * math.sqrt(2.0 / n)))) + + # Q8: record consistency - friend's record matches every later reader + n = 2000 + ok8 = True + for t in range(n): + c = make_singlet(engine, H("q8", t)) + axis = 2 * math.pi * u01(H("q8axis", t)) + friend_outcome = c.measure_angle(0, axis) + record = friend_outcome # block appended to friend's chain + wigner_remeasure = c.measure_angle(0, axis) # Wigner repeats on the same contract + if not (record == wigner_remeasure): + ok8 = False + R.append(check("Q8", ok8, "%d/%d: record == re-measurement for every reader" % (n, n))) + + # Q9: classicality by replication - ring gossip, monotone coverage, linear reversal cost + # (no engine involvement - pure classical simulation, copied unchanged) + N = 64 + informed = {0} + curve = [] + rounds = 0 + while len(informed) < N: + rounds += 1 + informed |= {(i + 1) % N for i in informed} | {(i - 1) % N for i in informed} + curve.append(len(informed)) + monotone = all(b >= a for a, b in zip(curve, curve[1:])) + R.append(check("Q9", monotone and rounds == N // 2 and curve[-1] == N, + "consensus in %d rounds (ring N=%d), coverage monotone, reversal cost = %d replicas" + % (rounds, N, N))) + + print() + print("TIERS 1-3: %s (%d checks)" % ("ALL PASS" if all(R) else "FAILURES PRESENT", len(R))) + return all(R) + + +if __name__ == "__main__": + import argparse + ap = argparse.ArgumentParser(description="Solaris 1.1 QM battery, engine-parameterized") + ap.add_argument("--engine", default=None, choices=ENGINE_NAMES, + help="wave engine (default: SOLARIS_ENGINE env var, else %r)" % DEFAULT_ENGINE) + args = ap.parse_args() + ok = main(select_engine(args.engine)) + sys.exit(0 if ok else 1) diff --git a/model/card.md b/model/card.md index a04a51d..35d2b8d 100644 --- a/model/card.md +++ b/model/card.md @@ -6,15 +6,15 @@ it. A release is a commit where this card changes, tagged with the version below ``` instance: Solaris -version: 1.0.0 +version: 1.1.0 architecture: 1 -implementation: 0 +implementation: 1 configuration: 0 ``` ``` expected red: GR-34,GR-35,GR-36 -record: tests/results/solaris-1.0.0.md +record: tests/results/solaris-1.1.0.md ``` Semantic versioning ` M.m.p`: diff --git a/model/implementation.md b/model/implementation.md index fffb86b..25ee33c 100644 --- a/model/implementation.md +++ b/model/implementation.md @@ -1,10 +1,26 @@ -# Implementation 0 — Solaris's mechanisms +# Implementation 1 — Solaris's mechanisms The implementation layer names the concrete mechanisms realizing each architectural principle. Changing any mechanism bumps the minor version and requires re-sitting the full examination battery. Several implementations may legally coexist as branches, each with its own record. -## Mechanism choices (implementation 0) +## Implementation 1 (Solaris 1.1.0) — the pluggable quantum layer + +Every mechanism below is **unchanged** from implementation 0. What changed is the engine +architecture: the amplitude arithmetic now sits behind a ports-and-adapters interface +(`labs/engine/` — the WaveEngine port), so the wave storage is swappable. Adapters: `table` +(the original hand-rolled arithmetic, the default and reference), `numpy`, `qutip`, `qiskit` +(Aer statevector). The port deliberately has no `measure()` — the hash draw and the +double-entry settlement decision stay on the ledger side (`labs/engine/domain.py`), so no +backend can re-import the Born rule the model derives from the signature ladder. + +Conformance bar, met by all four adapters: `labs/qm_battery.py --engine ` reproduces the +frozen reference battery `labs/qm_tests.py` **byte-identically** (draws are hash-fed and +deterministic, so the comparison is exact, not statistical). A deliberately broken adapter +(weights |a| instead of |a|²) fails 4/9 checks — the differential detects wrong engines. The +full battery was re-sat for this version: `tests/results/solaris-1.1.0.md`. + +## Mechanism choices (unchanged from implementation 0) | Mechanism | Choice | Evidence rows | |---|---|---| @@ -18,7 +34,7 @@ battery. Several implementations may legally coexist as branches, each with its **Known implementation candidate:** the **compounding composition law** c = e^(−Φ) (rates multiply — each shell taxes the already-taxed rate). Measured on this codebase (GR-37..39): β = 1 recovered (the +17% Mercury deviation of the linear law closes to +0.7%), γ = 1 kept, no -coordinate horizon. Its adoption as the default would be **implementation 1** (Solaris 1.1.0) +coordinate horizon. Its adoption as the default would be **implementation 2** (Solaris 1.2.0) and re-sits the battery on its own branch first. ## Row-ID ↔ lab map diff --git a/requirements-engines.txt b/requirements-engines.txt new file mode 100644 index 0000000..caf975a --- /dev/null +++ b/requirements-engines.txt @@ -0,0 +1,6 @@ +# Optional wave-engine backends for labs/qm_battery.py --engine ... +# The default engine (table) is stdlib-only and needs none of these. +numpy +qutip +qiskit +qiskit-aer diff --git a/tests/results/solaris-1.1.0.md b/tests/results/solaris-1.1.0.md new file mode 100644 index 0000000..59ef8a3 --- /dev/null +++ b/tests/results/solaris-1.1.0.md @@ -0,0 +1,161 @@ +# Examination record - SOLARIS-1.1.0 (run 2026-08-23) + +Generated by `run_exams.py all --record solaris-1.1.0`. Declared criteria: `../definitions/` (shown truncated); measured detail as printed by the lab. + +| Test | Row | Status | Declared criterion | Measured | +|---|---|---|---|---| +| SUB-1 | S1a | PASS | determinism: same genesis → bit-identical transcript | same genesis -> identical transcript | +| SUB-2 | S1b | PASS | sensitivity: different genesis → different transcript | different genesis -> different transcript | +| SUB-3 | S2 | PASS | causal DAG integrity: all hashes recompute; parents precede children | hashes recompute, all parents precede children (160002 blocks) | +| SUB-4 | S3a | PASS | CHSH from the shared contract reaches 2√2 | quantum S = 2.8327 (target 2.8284 +/- 0.101) | +| SUB-5 | S3b | PASS | LHV control stays ≤ 2 (the harness can see the classical ceiling) | LHV control S = 2.0424 (must stay <= 2) | +| SUB-6 | S3c | PASS | PR-box control reaches 4 (the harness can see the algebraic ceiling) | PR-box control S = 4.0000 (algebraic ceiling 4) | +| SUB-7 | S4 | PASS | no-signalling: each party's marginal deaf to the partner's setting | marginal shift B\|A-setting 0.0071 (<0.0707), A\|B-setting 0.0040 (<0.0707) | +| SUB-8 | S5 | PASS | measurement-order invariance (no preferred frame in settlement) | Alice-first S = 2.8102, Bob-first S = 2.8362, \|diff\| < 0.202 | +| SUB-9 | S6 | PASS | no-conspiracy: settings re-hashed from own history, uncorrelated with the pair seed | corr(seed, setting) A = 0.0013, B = 0.0020 (< 0.0250); settings built from own genesis only | +| SUB-10 | S7 | PASS | ancestry audit: correlated outcomes with NO in-layer causal path between the measurements | 200 trials: first measurement never in causal ancestry of second (correlation with no in-layer path) | +| SUB-11 | R1 | PASS | chain-fed randomness (P6 amended): determinism survives head-fed draws | determinism survives: same genesis -> identical transcript (120002 blocks) | +| SUB-12 | R2 | PASS | CHSH intact when every draw consumes the current head hash | CHSH from head-fed draws: S = 2.8166 (2.8284 +/- 0.117) | +| SUB-13 | R3 | PASS | no-signalling intact under head-fed draws | no-signalling: Bob marginal shift 0.0025 (< 0.0817) | +| SUB-14 | R4 | PASS | order invariance intact under head-fed draws | order invariance: A-first S = 2.8513 vs B-first 2.8074 (\|diff\| < 0.225) | +| SUB-15 | R5 | PASS | no-conspiracy intact under head-fed draws (ledger = its own dice) | no-conspiracy: corr(pair seed, settings) = 0.0005 (< 0.0289) | +| SUB-16 | U1 | PASS | the ledger IS the universal wave function stored factorized: random circuit universes run as global 2^n table vs contract DAG (merge = tensor, settlement = re-factorize), event-keyed draws → outcomes… | 60 random universes (n=8, 40 ops each): outcomes bit-identical global-table vs contract-DAG, settlement probabilities m… | +| SUB-17 | U2 | PASS | sparsity: settlements keep live storage well under 2^n (measured: mean peak 55 amps vs 256 global; 97% of universes never reach global size) — pay 2^k only where entanglement lives | peak live storage mean 55 amplitudes vs 2^n = 256 global (477 merges tensor factors together, 889 settlements re-factor… | +| SUB-18 | U3 | PASS | the Everett corner: never settle → contracts merge to ONE 2^n factor equal to the textbook table exactly — universal Ψ is the DAG's settlement-free limit | no settlements: contracts merge to ONE factor of dimension 256 = 2^n, equal to the textbook table to 0.0e+00 - Everett'… | +| SUB-19 | SN1 | PASS | the snapshot isomorphism (Chandy–Lamport): two valid cuts → DIFFERENT instantaneous Ψ (min gap 0.316) yet IDENTICAL settled records 20/20; two linear extensions of one cut → same Ψ (the cut is bookke… | 20 executions: two valid cuts -> DIFFERENT instantaneous Psi (min gap 0.316) yet IDENTICAL settled records 20/20; two l… | +| SUB-20 | SC1 | PASS | the entanglement phase diagram: pre-registered singleton law 1−r CONFIRMED (0.85/0.85, 0.74/0.75); pre-registered r_c = 1 REFUTED — gel onsets between r = 0.25 and 0.5 (merges pick particles → multip… | giant-cluster fraction vs r=merge/settle: r=0.15: 0.00, r=0.25: 0.01, r=0.35: 0.12, r=0.5: 0.30, r=1: 0.59, r=2: 0.77; … | +| SUB-21 | SC2 | PASS | the linear-storage law + THE STORAGE TRANSITION: cheap phase S = c(r)·N with c(0.05)=2.00, c(0.1)=2.02 (R² 1.0000, stable across N within 1%); linearity needs the size tail to beat 2^k (slope > ln 2)… | cheap-phase storage is LINEAR: S = c(r)*N with c(0.05) = 2.00, c(0.1) = 2.02 amplitudes/particle (fit R^2 1.0000/1.0000… | +| QM-1 | C0 | PASS | singlet correlation E(d) = −cos d at all angle gaps + CHSH at 2√2 | E(d) = -cos d, max dev 0.0142 (<0.09); CHSH S = 2.8506 (2.8284 +/- 0.159) | +| QM-2 | Q1 | PASS | repeatability: same-axis remeasurement always agrees | same-axis remeasure: 3000/3000 agree | +| QM-3 | Q2 | PASS | post-measurement blurring: Z,X,Z chain agrees at 1/2 | Z,X,Z agree 0.4915 (target 0.5); Z,Z agree 4000/4000 | +| QM-4 | Q4 | PASS | a which-path record kills interference (visibility → 0) | visibility 1.000 without record, 0.027 with which-path record | +| QM-5 | Q5 | PASS | GHZ/Mermin M = 4 exactly, every round (LHV best: 2) | every round exact: M = 4.0000 (LHV best = 2) | +| QM-6 | Q6 | PASS | monogamy: Toner bound S_AB + S_AC ≤ 4 across GHZ/singlet/W | GHZ pair S = 1.424 (<=2); singlet S_AB = 2.822, S_AC = 0.010; W S_AB = 0.486, S_AC = 0.507; Toner sums 7.96, 0.49 (<=8) | +| QM-7 | Q7 | PASS | no-signalling across all setting pairs | max marginal shift across settings 0.0610 (< 0.1581) | +| QM-8 | Q8 | PASS | record consistency: ledger read = re-measurement, for every reader | 2000/2000: record == re-measurement for every reader | +| QM-9 | Q9 | PASS | consensus spread (quantum-Darwinism ring): monotone coverage, reversal cost = replicas | consensus in 32 rounds (ring N=64), coverage monotone, reversal cost = 64 replicas | +| QM-10 | CH-01 | PASS | Born statistics: P = cos² to tolerance | Born: max \|P - cos^2\| = 0.0072 (< 0.0395) | +| QM-11 | CH-02 | PASS | frame shift leaves statistics invariant | frame shift leaves stats: max diff 0.0110 (< 0.0559) | +| QM-12 | CH-03 | PASS | marginal independent of partner's measurement context | Alice marginal vs partner context (none/Z/X): spread 0.0025 (< 0.0395) | +| QM-13 | CH-04 | PASS | superposition (V ≈ 1) vs mixture (V ≈ 0) distinguished | superposition V = 1.000 (>0.95); mixture V = 0.036 (<0.10) | +| QM-14 | CH-05 | PASS | harmonic purity: no higher harmonics in the fringe | higher-harmonic / first-harmonic = 0.0135 (< 0.06) | +| QM-15 | CH-06 | PASS* | exact null at φ = π (PASS\* — exact because amplitudes are imported) | null at phi=pi: 0/50000 clicks (Machine's floor was ~1%; ours is exact BECAUSE amplitudes are imported) | +| QM-16 | CH-07 | PASS | visibility law V(η) = cos(η/2) | V(eta) vs cos(eta/2): max dev 0.0428 (< 0.05) | +| QM-17 | CH-08 | PASS | recorded pattern = average of single-path patterns | P_recorded = avg of single-path patterns: max dev 0.0122 (< 0.0645) | +| QM-18 | CH-09 | BANKED | repeatability (BANKED = QM-2) | repeatability = Q1 (3000/3000 same-axis agree) | +| QM-19 | CH-09b | PASS | 3-step chain = product of conditionals (Markov property) | 3-step chain vs product of conditionals: max dev 0.0068 (< 0.02) | +| QM-20 | CH-10 | BANKED | post-measurement blurring (BANKED = QM-3) | post-measurement blurring = Q2 (Z,X,Z agree 0.4915) | +| QM-21 | CH-11 | PASS | early-drawn vs late-drawn choice indistinguishable (delayed choice) | early-drawn vs late-drawn choice: max curve diff 0.0541 (< 0.1118) | +| QM-22 | CH-12 | PASS | silent detector still collapses (null-outcome measurement) | visibility conditioned on SILENT detector = 0.060 (< 0.10; no click, still collapsed) | +| QM-23 | CH-13 | PASS | quantum eraser: sorting restores anti-phased fringes | sorted by eraser: anti-phased fringes restored (P0 at phi=0: 1.000 vs 0.000); unsorted flat | +| QM-24 | CH-14 | PASS | complementarity: V² + D² = 1 | V^2 + D^2 = 1: max dev 0.0317 (< 0.06) | +| QM-25 | CH-15 | BANKED | no-signalling (BANKED = SUB-7 + QM-7) | no-signalling = S4 + Q7 (max marginal shift 0.007 / 0.061) | +| QM-26 | CH-16 | PASS* | CHSH = 2√2 (PASS\* — THE MACHINE'S UNFINISHED ROW; passes because the correlation rule is imported) | CHSH = 2.83 (C0/S3a) - THE MACHINE'S UNFINISHED ROW; passes here because the correlation rule is imported, and we say so | +| QM-27 | CH-17 | MERGED | apparatus recoil (MERGED into QM-24: the apparatus IS the record qubit) | apparatus recoil merged into CH-14 here: the apparatus IS the record qubit; this model has no mass dial | +| QM-28 | CH-18 | IMPORTED | complex-unitary observer view (IMPORTED — disclosure, not a pass) | complex-unitary observer view: true BY CONSTRUCTION (we imported complex amplitudes) - not a pass, a confession | +| QM-29 | CH-19 | PASS | no joint block: unentangled watcher gains nothing, visibility stays 1 | no joint block: visibility stays 1.000 (>0.95); watcher's outcome guess 0.508 (chance) | +| QM-30 | DE1 | PASS | the signature ladder: 1 signer ∝ \\|α\\| (wrong), 2 signers = Born, 3 ∝ \\|α\\|³ (wrong) — the square comes from dyadic settlement | signature ladder, max deviation from Born: 1 signature 0.149 (P ~ \|alpha\|, wrong), 2 signatures 0.004 (BORN), 3 signa… | +| QM-31 | DE2 | PASS | full QM battery with the Born line replaced by double-entry settlement — everything passes; residual import = norm-linear acceptance per signer | full battery under the settlement sampler: qm_tests 9 pass / 0 fail, CH retake 20 pass / 0 fail - the Born LINE is gone… | +| QM-32 | LG1 | PASS | Leggett–Garg watcher controls capped at 1: passive rotor sits exactly ON the ceiling (gaps ≤ 90°); ledger settled at all three checkpoints writes a diary of triples, K = 2cos t − cos²t ≤ 1 | watchers capped at 1: rotor flat ON the ceiling to 90 deg [30 deg: 1.0000 (0 zigzags); 60 deg: 1.0000 (0 zigzags); 90 d… | +| QM-33 | LG2 | PASS | temporal Bell violation by the fold: two checkpoints per run, three batches, settlement re-preparation → K = 2cos t − cos 2t, 3/2 at 60° (temporal Tsirelson) — identical under the double-entry sample… | the fold crosses the ceiling: K = 2cos t - cos 2t [30 deg: 1.216 (pred 1.232); 60 deg: 1.511 (pred 1.500); 90 deg: 1.01… | +| QX-1 | X1 | PASS | no-cloning: basis states copy perfectly; unknown superpositions at fidelity 2/3 | basis copy 3000/3000; superposition clone fidelity 0.662 (theory 2/3, optimal-cloner bound 5/6, perfect copy impossible) | +| QX-2 | X2 | PASS | teleportation: exact with the 2 classical bits, garbage without (light-speed channel is load-bearing) | with the 2 classical bits: 3000/3000 exact; without them: 0.525 (garbage) - the light-speed channel is mandatory | +| QX-3 | X3 | PASS | entanglement swapping: A–D violate CHSH without ever interacting (post-selected on the swap) | CHSH(A,D) after swap = 2.853 (2.83 target; A and D never interacted); without the swap = 0.044 | +| QX-4 | X5 | PASS | quantum Darwinism: visibility = 0.866^N with N records; reversal cost = N | V(N) = 1.00/0.87/0.75/0.67/0.59/0.49 vs product law 0.866^N (max dev 0.028); reversal cost = N records | +| QX-5 | X6 | PASS | Zeno effect: survival → 1 as measurement frequency grows | survival 0.00 -> 0.92 as measurements go 1 -> 32 (theory match 0.014) | +| QX-6 | X7 | PASS | Robertson uncertainty ΔZ·ΔX ≥ \\|⟨Y⟩\\| on all preparations | Robertson bound dZ*dX >= \|\| holds on all 7 preps (worst margin 0.0051) | +| QX-7 | X8 | PASS | twin paradox on the DAG: bent chain carries fewer blocks (interval arithmetic) | bent twin aged x0.755 of straight (interval arithmetic: 0.800) - fewer blocks on the bent chain, episode #15's twins me… | +| QX-8 | X9 | PASS | Myrheim–Meyer: dimension ≈ 2 recovered from order-counting alone | Myrheim-Meyer estimate d = 2.008 (true: 1+1) from order counting alone | +| QX-9 | X10 | PASS | PR-box contract runs fine in-layer (fail-on-purpose: the model does NOT explain the Tsirelson ceiling — standing confession) | PR contract: S = 4.0, marginals flat (-0.006) - no-signalling intact, nothing in-layer breaks; the model cannot say why… | +| QX-10 | X11 | PASS | Elitzur–Vaidman bomb tester: interaction-free detection at 0.25 | live bomb: boom 0.503 / detected-without-touching 0.257 / inconclusive 0.239 (theory 0.50/0.25/0.25); dud never clicks … | +| QX-11 | TS1 | PASS | the model's own contract class (one table + local settings + double-entry) saturates at exactly 2√2 under adversarial search — Tsirelson internal to the model | one shared table + local settings + double-entry settlement: 10,000-point adversarial search reaches 2.82843 and NEVER … | +| QX-12 | TS2 | PASS | the same settlement serving a rewrite-contract reaches 4 (PR) — the ceiling is the one-table discipline, not the square alone; residue: why nature keeps single-table contracts | the SAME two-signature settlement serving a rewrite-contract: S = 4.000 (PR box; Alice marginal 0.502, flat) - the squa… | +| ST-1 | Q10 | PASS | causal cone: reach after k gossip rounds = exactly graph distance k | reach after k rounds = exactly distance k, 14 rounds checked | +| ST-2 | Q11a | PASS | PRE-REGISTERED FAILURE: naive block-budget dilation τ = T(1−v) fails Lorentz (the O3 prediction, confirmed) | PREDICTED FAILURE CONFIRMED, max gap 0.414; v=0.3: budget 0.701 vs Lorentz 0.954; v=0.5: budget 0.500 vs Lorentz 0.866;… | +| ST-3 | Q11b | PASS | sprinkled-DAG longest chain is boost-invariant and linear in the interval (proper time = block count) | boost invariance: s=0.28: L=23.6/24.0/25.0 spread 5.8%; s=0.42: L=36.6/36.8/39.2 spread 6.9%; s=0.56: L=48.6/52.2/53.0 … | +| ST-4 | Q12 | PASS | photon chain: null-ish interval carries ~no blocks (light doesn't age) | same coordinate time: null-ish chain / timelike chain = 0.16 (< 0.40) | +| GR-1 | G1 | PASS | Poisson far field (log d in 2D) from neighbor exchange only; dilation in EMPTY space (a field, not contact) | far field ~ log d (R^2 = 1.0000); EMPTY-space dilation: clock at d=30 runs x0.955 of far clock (density there = 0) | +| GR-2 | G2 | PASS | light bending toward the crowd; deflection ∝ mass (weak field) | all rays bend toward crowd; deflection 0.0678+/-0.0066 rad, flatness 0.10 (2D log signature); double mass -> x2.13 defl… | +| GR-3 | G3 | PASS | free fall: packet at rest drifts toward the crowd (slow region = potential well) | packet at rest falls TOWARD crowd: drift 3.40 cells (naive (1/2)at^2 = 3.30; field steepens on approach) | +| GR-4 | G4 | PASS | equivalence principle holds iff internal frequency ∝ mass (Compton clock, isolated by control) | Compton-scaled: m=1 and m=2 trajectories agree to 0.00 cells (equivalence); control without scaling separates by 1.72 c… | +| GR-5 | G5 | PASS | orbits: v_orb from the measured field holds its radius; rest falls, overspeed escapes | v_orb from the field: radius held in [24.0, 25.0] (r0 = 25), swept 104 deg; at rest falls to r = 0.1; at 1.5x escapes t… | +| GR-6 | G6 | PASS | gravity at c: wave-type budget exchange arrives ballistically (t = d), statics still Poisson | wave exchange: arrival t ~ 1.00 * d (ballistic - the field change rides the causal cone); diffusion control: t ~ d^2.15… | +| GR-7 | W1a | PASS | at rest: point particle unmoved, wave packet falls — no steering rule exists or is needed | at rest: point particle moves 0.0e+00 cells (slowdown has no lever on it); wave packet falls 40.7 cells toward the crow… | +| GR-8 | W1b | PASS | passing: point crosses dead straight, wave deflects — gravity is an interference effect | passing at b = 18: point deflects 0.0e+00 (dead straight); wave deflects -2.2 cells toward the crowd - gravity here is … | +| GR-9 | COW-1 | PASS | quantum interference reads the gravity field: fringe frequency = field-predicted clock-rate gap | fringe frequency 0.10114 vs field prediction 0.10098 (ratio 1.002) - the two arms' clock-rate gap, read out as counted … | +| GR-10 | COW-2 | PASS | COW fringe scales with arm separation | narrower arms: frequency ratio 0.518 vs dPhi ratio 0.519 | +| GR-11 | COW-3 | PASS | COW fringe scales with mass (Compton) | double mass: frequency x1.994 (Compton clock: rest frequency ~ mass) | +| GR-12 | COW-4 | PASS | control: no crowd, no fringes | no crowd: fringes flat (min P0 = 1.000) - no field, no shift | +| GR-13 | L1 | PASS | gravitational wavelength compression: pattern occupies fewer nodes where compute is busy | wavelength in the busy region / outside = 0.708 (c ratio 0.700) - the pattern occupies fewer nodes where compute is bus… | +| GR-14 | L2 | PASS | Lorentz contraction with no rule: sine-Gordon kink self-squeezes to w₀/γ (w·γ invariant) | kink launched at rest-width relaxes to w0/gamma by itself: v=0.29: width 0.959, w*gamma = 1.001; v=0.45: width 0.896, w… | +| GR-15 | Q1 | PASS | quasicrystal ruler verdict: Fibonacci = lattice = broken at e^(−η); only randomness cures counting | boosted/straight chain: lattice 0.607, Fibonacci quasicrystal 0.607 - BOTH stuck at e^-eta = 0.607; sprinkle 1.010. Ape… | +| GR-16 | SG1 | PASS | sphere ruler: graph travel distance tracks great-circle distance (one zigzag factor) | travel distance = 1.012 x great-circle distance, R^2 = 0.9999 - one isotropic zigzag factor, divided out below | +| GR-17 | SG2 | PASS | insider curvature: circle areas = 2π(1−cos r), not πr² | circle areas fall short of pi*r^2 exactly as 2pi(1-cos r): r=1: A=2.85 (sphere 2.89, flat 3.14); r=2: A=8.91 (sphere 8.… | +| GR-18 | SG3 | PASS | closed topology: diameter = π, all geodesics reconverge at one antipode | diameter 3.108 (pi = 3.142); the 20 farthest nodes all sit within 0.14 rad of the true antipode - every direction recon… | +| GR-19 | SG4 | PASS | wave refocus: a pulse re-peaks at the antipode at the predicted time | front speed 0.229 -> predicted focus t=14.1; antipodal energy peaks at t=13.7 with 20.2x the global mean - the wave its… | +| GR-20 | SG5 | PASS | THE ILLUSION: c(θ) = 1+cos θ makes the sphere measure exactly Euclidean (stereographic; CM flatness at noise floor) | travel distance = 1.019 x tan(theta/2), R^2 = 0.9995 (stereographic plane, measured); 4-point flatness score: sphere 0.… | +| GR-21 | SG6 | PASS | the price: the antipode exiled to infinite travel time (horizon point = fake spatial infinity) | farthest node now sits at travel distance 173.0 vs the honest diameter pi = 3.1 - the antipode is exiled toward infinit… | +| GR-22 | SG7 | PASS | the betrayal: grain density thins as (1+r²)⁻² — geometry can lie, the grain cannot | grain density inner disk / outer annulus = 48 (prediction from (1+r^2)^-2: 48; honest sphere: 1) - the metric lies perf… | +| GR-23 | SB1 | PASS | SPRINKLED GRAVITY: Poisson field on the random closed sphere graph fits the sphere Green's function (statics need no lattice) | SPRINKLED gravity: field on the random closed graph fits the sphere Green's function -ln sin(theta/2) with R^2 = 0.9997… | +| GR-24 | SB2 | PASS | Shapiro delay: signals grazing the crowd arrive late vs a control path | Shapiro: excess delay past the crowd 0.908 (straight-path prediction 0.985; Fermat lets the path dodge, so <= is expect… | +| GR-25 | SB3 | PASS | gravitational redshift: coordinate frequency conserved crossing a static well (emitter pacing = the declared Compton assertion) | coordinate frequency conserved crossing the static well: received/emitted = 1.000; so the receiver's faster clock reads… | +| GR-26 | SB4 | PASS | Girard closure: locally measured angles and globally measured sides agree on the curvature | Girard closure: angle sum - pi = 1.587 rad measured at the corners vs 1.651 predicted from the three side lengths (l'Hu… | +| GR-27 | SB5 | PASS | apsidal precession at the log-potential value 2π/√2 (DRAWBACK on record: 2D log ≠ GR 1/r; the GR number needs 3D) | eccentric orbit: perihelion-to-perihelion sweep 4.43 rad vs log-potential prediction 2pi/sqrt2 = 4.44 (Kepler would be … | +| GR-28 | SB6 | PASS | wave on the disguised sphere: no antipodal refocus — the fake plane has no far side | disguised sphere c = (1+cos)/2: max antipodal energy contrast 0.00 over the whole run (honest sphere: ~20x refocus) - t… | +| GR-29 | RIP | PASS | budget ripples: an oscillating crowd radiates; wiggles ride the causal cone and decay outward (gravitational waves as load transients) | oscillating crowd radiates: probe-to-probe lag 24.0 vs causal 25.0 (field wiggles ride the cone); amplitude 3.07e+00 at… | +| GR-30 | FF3 | PASS | 3D far field: the congestion potential falls as 1/r — Newton's shape; the 2D log was the toy's artifact | 3D budget field: fits 1/r with R^2 = 0.9990 (log fit: 0.9871) - in three dimensions the congestion far field IS Newton'… | +| GR-31 | K3D | PASS | Kepler closure in 3D: eccentric orbits close (apsidal angle π) — the 2D precession drawback resolved as dimensional artifact | eccentric orbit in the 3D 1/r field: apsidal angle 3.1416 (pi = 3.1416; the 2D log field gave 2.22) - closed ellipses: … | +| GR-32 | BEND | PASS | absolute bending: leading coefficient = 4GM/b, the full GR value (γ = 1 measured), 1/b law | deflection fits alpha = c1/b + c2/b^2 with c1 = 0.989 x 4GM (the FULL GR leading value: gamma = 1 measured; c2 = 19.4 G… | +| GR-33 | PPN | PASS | the β = ½ audit: g₀₀ = −(1−GM/r)² gives perihelion advance 7/6 of GR (Schwarzschild control certifies the integrator) — a NAMED deviation: +17% on Mercury; deriving β = 1 is the sharpest open gravity… | perihelion advance: Schwarzschild control through the same integrator = 1.0065 x GR (instrument certified); the model's… | +| GR-34 | FL1 | FAIL | (Dorau-Much bridge; marks declared 2026-08-20 BEFORE first run) dumb-hole thermodynamics, mass-radius: horizon radius vs absorbed flux J fits a power law with exponent p in [0.7, 1.3] (Schwarzschild … | mass-radius on 5 appetites: r_h ~ J^4.88 (R^2=0.880; Schwarzschild pattern r ~ M is exponent 1) - the bigger the appeti… | +| GR-35 | FL2 | FAIL | temperature-mass: measured surface gravity kappa vs J fits exponent q in [-1.35, -0.65] (Schwarzschild pattern T ~ 1/M) - same pre-registered alternative as FL1 | temperature-mass: kappa ~ J^2.80 (R^2=0.688; Schwarzschild T ~ 1/M is exponent -1) - bigger holes are COLDER, the black… | +| GR-36 | FL3 | FAIL | the first-law closure: Clausius entropy S = INT 2pi dJ/kappa built from the MEASURED kappa(J) fits S ~ r_h^s with s in [1.5, 2.5] - the Bekenstein square (S ~ area in 3D reads S ~ r_h^2 here) assembl… | the first law assembled: Clausius S = INT dJ/T from the measured temperatures fits S ~ r_h^0.16 (R^2=0.882) - the BEKEN… | +| GR-37 | FE1 | PASS | the compounding rate law: slowdowns COMPOUND (each shell taxes the already-taxed rate; rates multiply - the ledger-native composition) -> c = e^(-Phi) instead of 1-Phi -> g00 = -e^(-2GM/r), grr = e^(… | perihelion, same certified integrator as GR-33: compounded metric 1.0071 x GR vs Schwarzschild control 1.0065 x GR (the… | +| GR-38 | FE2 | PASS | compounding bending: deflection still fits 4GM/b with leading coefficient in [0.95, 1.05] - gamma = 1 preserved (weak field identical; only second order moves) | bending: deflection fits c1/b with c1 = 0.991 x 4GM - gamma = 1 preserved (weak field identical to the linear law; only… | +| GR-39 | FE3 | PASS | no coordinate horizon: the compounded redshift e^(-GM/r) is finite, positive, monotone at every r > 0 (Schwarzschild control hits zero at 2GM) - the metric-level echo of the BH-4 compute floor: rate … | the compounded redshift e^(-GM/r): finite, positive, monotone at every sampled r down to 0.05 GM (min 2.1e-09) while th… | +| EN-1 | N1 | PASS | Noether locally: static well conserves ⟨E⟩; oscillating well pumps it (conservation ⇔ time symmetry) | drift: static well 1.0e-08 vs oscillating well 4.7e-01 (x46196469) - conservation holds exactly where time symmetry… | +| EN-2 | N2 | PASS | the audit: slow uniform tax — energy loss rate = redshift rate = tax rate (the leak equals the bill) | slow tax: frequency ratio 0.702 (tax 0.700), energy ratio 0.707 - the photon's energy leaks at EXACTLY the redshift rat… | +| EN-3 | N3a | PASS | Ehrenfest: E/ω invariant through slow expansion (ħ constant while everything slows) | E/omega before vs after the slow 30% tax: ratio 1.0071 - the quantum of action rides through expansion untouched (Ehren… | +| EN-4 | N3b | PASS | sudden tax: E/ω jumps by (ω₁²+ω₂²)/(2ω₁ω₂) — quanta created when change outruns adiabaticity | sudden halving of c: E/omega jumps x1.244 (predicted (w1^2+w2^2)/(2 w1 w2) = 1.250) - quanta created from nothing when … | +| EN-5 | U1 | PASS | (declared 2026-08-20 before first run) Unruh-in-toy: a uniformly accelerated observer sampling the random-phase vacuum ensemble (zero-point spectrum IMPORTED, declared) measures a correlation of the … | the accelerated observer reads the vacuum as HEAT: the correlation fits [piT/sinh(piT dtau)]^2 (residuals 1.1e-05 / 1.0… | +| EN-6 | U2 | PASS | inertial control: the same field sampled on an unaccelerated worldline shows the cold vacuum 1/Δτ² law (power −2 ± 0.3) and the thermal fit pins to the scan floor — no acceleration, no temperature | inertial control: same field, unaccelerated worldline - correlation falls as dtau^-2.00 (the cold vacuum's 1/dtau^2) an… | +| EX-1 | E1 | PASS | fixed space FEELS bigger: same hop-count world takes ×2.6 longer to cross as the ledger grows | same 500-hop world takes 526 ticks to cross at S=0 and 1367 at late S (x2.60) - fixed space FEELS bigger as the ledger … | +| EX-2 | E2 | PASS | Hubble law: hop-tax gives redshift z ∝ distance | REDSHIFT, z proportional to d (Hubble law): z = ['0.0200', '0.0400', '0.0830', '0.1730'] at d = [100, 200, 400, 800]; s… | +| EX-3 | E3 | PASS | the fork: tick-tax BLUEshifts (falsified as expansion); uniform tax cancels (invisibility measured) — the bill must bite the message fabric | tick-tax: z = -0.0741 (BLUEshift - anti-cosmology, falsified as expansion); uniform: z = -0.0003 vs hop-tax 0.0830 (fir… | +| EX-4 | M2a | PASS | P10 v2: wells decay as their stuff radiates (gravity is the transient) | well depth decays monotonically to 1.1% of initial - gravity fades as its stuff radiates | +| EX-5 | M2b | PASS | global stretch monotone, landing on the uniform prediction (expansion is the residue) | global stretch 96 -> 158 ticks (x1.65), never shrinks, riding radiated mass; uniform prediction 158.8 | +| EX-6 | M2c | PASS | entropy–stretch lockstep (rank correlation 1) — the conversion IS entropy increase | spatial entropy 6.71 -> 9.10, monotone; global stretch monotone with it (rank correlation 1.0) - the fabric stretches B… | +| EX-7 | M2d | PASS | coexistence: deep wells while stretch accumulates (gravity and expansion at once) | mid-run coexistence at t=[60, 90, 120]: wells still >= 35% deep while >= 30% of the final stretch is already in - bubbl… | +| EX-8 | M2e | PASS | bubble-to-fabric signature: clump row overshoots then relaxes; far row only stretches | clump row overshoots to 190 (bubble), relaxes to 170 toward uniform 158.8; far row only ever stretches (96 -> 138); nea… | +| EX-9 | M3a | PASS | closed fabric: uniform bath bends NOTHING (forced by Poisson solvability — only contrast bends) | same mass: uniform bath -> field 0.0e+00 (nothing bends, forced by solvability); clumped -> well contrast 1164 | +| EX-10 | M3b | PASS | radiation clump bends = matter clump (massless stuff bends while concentrated) | radiation clump well / matter clump well = 1.0000 - massless stuff bends too, while concentrated | +| EX-11 | M3c | PASS | radiation levels into the mean, matter well persists (FRW background/perturbation split in-toy) | radiation well 1057 -> -30 (leveled into the mean); matter well 1057 -> 1158 (persists); closed-fabric conservation dri… | +| EX-12 | H1a | PASS | linear ledger growth: whole fabric stays reachable (slower, no horizon) | constant law covers the fabric at t = 500; linear ledger growth still covers it, but at t = 14738 (x29 later) - slower … | +| EX-13 | H1b | PASS | exponential ledger growth: reach saturates at 1/β — a PERMANENT horizon; the edge is a property of the entropy curve | exponential ledger growth: reach saturates at 100.0 (analytic 1/b = 100) < L/2 = 500 - a PERMANENT horizon; visible pat… | +| EX-14 | H1c | PASS | horizons are observer-centered and equal-sized (the edge is relational, not a place) | homogeneous fabric: identical patches (spread 6.3e-13); 5%-lumpy fabric: sizes 200/209/191 (spread 8.9% - bounded by th… | +| EX-15 | EX15 | PASS | supernova stretch: pulse pairs arrive (1+z) apart, exactly c(emit)/c(arrive) — light-curves dilate like spectra shift (tired-light cannot) | pulse pairs arrive stretched by exactly c(emit)/c(arrive), growing with distance: d=200: stretch 1.071 (pred 1.071); d=… | +| EX-16 | EX16 | PASS | CLOSED LOOP: the tax fed by the real ledger's fold count; fold rate doubles → redshift rate doubles (no script) | ledger-fed tax: redshift rate 5.26e-05 (1 fold/tick era) -> 1.26e-04 (2 folds/tick era), ratio 2.39 vs predicted 2.35 -… | +| EX-17 | EX17 | PASS | the price audit: energy lost per written bit = constant K·β across epochs — dE = −Kβ·dS, the leak IS the bill | energy lost per written bit: 1.227e-04 (slow era) = 1.225e-04 (busy era) = K*beta predicted 1.224e-04 - an absolute con… | +| DS-1 | D1 | PASS | the counting layer: a regular lattice's boosted chain is stuck at e^(−η) at EVERY resolution — fineness fixes nothing | lattice: boosted/straight chain = 0.590 (L=40) and 0.595 (L=80) - stuck at e^-eta = 0.607 at BOTH densities, fineness f… | +| DS-2 | D2 | PASS | the dynamics layer: bending converges with grid refinement — fineness is all dynamics needs | bending angle -0.06839 rad at N=96 vs -0.06706 at N=192 (rel diff 2.0%) - the dynamics rules converge with fineness, ex… | +| DS-3 | DS3 | PASS | the last tell: statistical travel-time blur fades with fineness (~density^−0.64) — any finite observational precision can be out-run by a finer sprinkle | travel-time jitter: 0.0222 at n=1000 -> 0.0092 at n=4000 (falls as density^-0.64) - the last grain tell is statistical … | +| ENT-1 | EN1 | PASS | entropy written per fold = Born H(cos²), memoryless; compressor floored at H — the ledger pays full price for every fold | entropy written per fold = Born H(cos^2), memoryless, compressor floored at H: p=0.50: H=1.000 (theory 1.000), H(X\|pre… | +| ENT-2 | EN2 | PASS | memory or compute, both explode: archive linear in folds; replay-from-genesis linear in time (the C3 storage bill, measured) | archive after 2N folds = exactly 2x the archive after N (append-only, by construction); replay-from-genesis cost 2N/N =… | +| ENT-3 | EN3 | PASS | the arrow is structural: the head hash is an injective accumulator of all history — recurrence would need a hash collision (150k folds, zero repeats) | 150000 folds, 150001 distinct heads (zero repeats): the head is an injective accumulator of ALL history, so exact recur… | +| ENT-4 | EN4 | PASS | the fold split: 100 pre-states → 2 records (observer cannot invert) BUT full replay is bit-exact (substrate can) — L2 fold, L3 rewind, measured | 100 distinct pre-fold states -> 2 distinct records (50:1 collapse; the record alone cannot invert the fold) BUT full re… | +| FLU-1 | F1 | PASS | vortex quantization: circulation in integer 2π units, conserved; fractional attempts read as integers — Wallstrom's axiom free in a ledger (single-valued storage) | circulation quantized in units of 2*pi and conserved: charge 1.0: winding 1 -> 1 after evolution; charge 2.0: winding 2… | +| FLU-2 | F2 | PASS | continuity: ∂ρ/∂t + ∇·j = 0 — probability is a locally conserved fluid, flows and never teleports | continuity d(rho)/dt + div j = 0 mid-fall: residual 0.0000 of the flow term - probability is a locally conserved fluid;… | +| FLU-3 | F3 | PASS | Euler: mean velocity = current/density and acceleration = congestion force — gravity accelerates the probability fluid (W1 = Madelung, quantitative) | Euler in fluid variables: d/dt = current/density (ratio 1.000) and d/dt = congestion force (ratio 1.000) - gravit… | +| FLU-4 | F4 | PASS | drag (founding scout): waves in a drifting medium travel at u±c, measured from the full wave equation — the flux is the off-diagonal metric term, frame dragging's seed | drifting medium u=0.3: wave speeds 1.29 / -0.70 (u+c and u-c; control u=0: 1.00 / -1.00) - the fabric's FLUX drags wave… | +| FLU-5 | F5 | PASS | dumb hole (founding scout): supersonic drift = one-way membrane, nothing frozen; outside observer receives nothing (characteristic-transport instrument, speeds certified by FLU-4) | launch INSIDE the supersonic region: leftmost reach 1973 (horizon at 1500) and outside-probe amplitude 0.0e+00 vs the o… | +| FLU-6 | F6 | PASS | DERIVED drift: a moving demand drags a budget circulation ∝ v·D·τ — and pure diffusion (τ→0) drags NOTHING: frame dragging requires the exchange to have memory/inertia (the G6 wave-type channel, now … | budget circulation: wave-type exchange -0.60 vs derived -v*cg^2*tau^2*Int(lnb')^2 = -0.60 (2x speed: -0.84 vs -0.87 - s… | +| FLU-7 | F7 | PASS | Sagnac on the derived field: counter-propagating laps differ by 2∮u/c², using the u the budget dynamics produced (coupling magnitude = declared dial; shape derived); static-crowd control ≈ 0 | counter-propagating laps: dt = -1.80 vs 2*circ/c^2 = -1.64 (static-crowd control -0.00) - the derived drag is REAL to w… | +| FLU-8 | F8 | PASS | dynamic horizon formation: a consuming sink builds its own inflow; below critical hunger no horizon, above it \\|u\\| crosses c at a radius that grows with the appetite | the sink builds its own inflow: appetite 0.005: max\|u\| 0.04, horizon radius 0; appetite 0.300: max\|u\| 1.41, horizon… | +| BH-1 | B1 | PASS | one-way membrane on the derived hole: launch inside cannot cross the horizon outward; outside launch escapes; outside observer receives nothing | horizon SELF-LOCATED at x=1468 (u crosses c): inside launch reaches min x=1467 (never out), outside probe hears 8.2e-04… | +| BH-2 | B2 | PASS | nothing frozen, door open inward: signals from outside cross the horizon INWARD and reach the core in finite time; the budget inside stays alive (contrast with a frozen patch, which blocks both ways) | infalling signal from x=800 crosses the horizon and reaches the core at t=642 (schedule 644); budget at the center stil… | +| BH-3 | B3 | PASS | the hovering pile-up: an outward launch from inside stalls AT the horizon and its amplitude grows — the analog infinite-blueshift signature | emission at 24/12/6 cells outside: t=478/502/521 - each HALVING of the distance costs the same extra delay (24, 19: the… | +| BH-4 | C1 | PASS | the compute floor is asymptotic: tick-scheduler redshift 1+z = 1+L exact; load ladder to 1e300 with the rate strictly positive, finite, monotone — the singularity is continuum language (1+L diverges;… | sim rungs L=1..1e5: measured redshift 1+z = 1+L exact (worst dev 0.0e+00); algebraic ladder to L=1e300: rate strictly p… | +| BH-5 | C2 | PASS | frozen, not sealed: a core signal in an exponentially loaded well ESCAPES in finite time; equal steps deeper multiply the delay by the constant e^(Δ/λ) — the density-route analog of BH-3's log law | core signal ESCAPES: T=61128 steps from the floor (finite for any finite load); emission 15 cells deeper each time mult… | +| BH-6 | C3 | PASS | the two horizon routes are distinguishable: density hole two-way (escape, arbitrarily slow) vs flux hole one-way (BH-1 membrane) — a real black hole is both at once | the SAME escape attempt: density hole lets it out (T=61128, two-way, just slow); flux hole (BH-1's derived horizon at x… | + +**Total: 147 pass, 3 fail.** From aa28e9a8d45ffb263686e2235800aadb7216fc8e Mon Sep 17 00:00:00 2001 From: masteris777 Date: Sun, 23 Aug 2026 16:17:20 +0300 Subject: [PATCH 2/2] README: examination run command records solaris-1.1.0 Co-Authored-By: Claude Fable 5 --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index e845dbe..787fcfc 100644 --- a/README.md +++ b/README.md @@ -26,7 +26,7 @@ truth for the version triplet, with the three layers described beside it: ``` pip install -r requirements.txt -python labs/run_exams.py all --record solaris-1.0.0 --expect-red GR-34,GR-35,GR-36 +python labs/run_exams.py all --record solaris-1.1.0 --expect-red GR-34,GR-35,GR-36 ``` Expected: **150 rows - 147 pass and exactly 3 red.** The red rows (GR-34..36)