Merge pull request 'feat(adr-0243): flagship cognitive_lifecycle.py — ingress/relax/egress, Tier-2 off-serving' (#56) from feat/adr-0243-phase2-lifecycle into main
This commit is contained in:
commit
8624ea9a0e
10 changed files with 2329 additions and 1 deletions
4
.gitignore
vendored
4
.gitignore
vendored
|
|
@ -87,3 +87,7 @@ engine_state/_life_backup_*/
|
|||
|
||||
# Local MCP configuration (contains local tokens)
|
||||
.mcp.json
|
||||
|
||||
# Google Drive sync pointer stubs (JSON pointers to Drive docs, not content).
|
||||
# The canonical committed copy of any R&D doc lives under docs/ as real markdown.
|
||||
*.gdoc
|
||||
|
|
|
|||
|
|
@ -118,6 +118,32 @@ _LAZY_EXPORTS: dict[str, str] = {
|
|||
"multi_scale_energy_for_schedule": "core.physics.multi_scale_energy",
|
||||
"multi_scale_energy_vector": "core.physics.multi_scale_energy",
|
||||
"schedule_mid_span_fraction": "core.physics.multi_scale_energy",
|
||||
# cognitive_lifecycle — ADR-0243 ingress→relaxation→egress (never serve)
|
||||
"CognitiveLifecycleEngine": "core.physics.cognitive_lifecycle",
|
||||
"CognitiveLifecycleError": "core.physics.cognitive_lifecycle",
|
||||
"CrystallizationProposal": "core.physics.cognitive_lifecycle",
|
||||
"EgressValidationError": "core.physics.cognitive_lifecycle",
|
||||
"EgressVerdict": "core.physics.cognitive_lifecycle",
|
||||
"HamiltonianCompileError": "core.physics.cognitive_lifecycle",
|
||||
"IngressDegenerate": "core.physics.cognitive_lifecycle",
|
||||
"IngressWavePacket": "core.physics.cognitive_lifecycle",
|
||||
"LifecycleOutcome": "core.physics.cognitive_lifecycle",
|
||||
"ProblemHamiltonian": "core.physics.cognitive_lifecycle",
|
||||
"PropositionalEntailmentVerdict": "core.physics.cognitive_lifecycle",
|
||||
"PropositionalProblem": "core.physics.cognitive_lifecycle",
|
||||
"RelaxationCertificate": "core.physics.cognitive_lifecycle",
|
||||
"RelaxationInputError": "core.physics.cognitive_lifecycle",
|
||||
"RelaxationNotConverged": "core.physics.cognitive_lifecycle",
|
||||
"RelaxationNumericalFailure": "core.physics.cognitive_lifecycle",
|
||||
"RelaxationResult": "core.physics.cognitive_lifecycle",
|
||||
"assignment_component_index": "core.physics.cognitive_lifecycle",
|
||||
"compile_propositional": "core.physics.cognitive_lifecycle",
|
||||
"compile_quadratic_well": "core.physics.cognitive_lifecycle",
|
||||
"egress_gate": "core.physics.cognitive_lifecycle",
|
||||
"ingest_context": "core.physics.cognitive_lifecycle",
|
||||
"propositional_entails": "core.physics.cognitive_lifecycle",
|
||||
"relax_to_ground": "core.physics.cognitive_lifecycle",
|
||||
"uniform_assignment_state": "core.physics.cognitive_lifecycle",
|
||||
}
|
||||
|
||||
from typing import TYPE_CHECKING
|
||||
|
|
@ -153,6 +179,33 @@ if TYPE_CHECKING: # static-analysis only — never imported at runtime (serve q
|
|||
multi_scale_energy_vector,
|
||||
schedule_mid_span_fraction,
|
||||
)
|
||||
from core.physics.cognitive_lifecycle import (
|
||||
CognitiveLifecycleEngine,
|
||||
CognitiveLifecycleError,
|
||||
CrystallizationProposal,
|
||||
EgressValidationError,
|
||||
EgressVerdict,
|
||||
HamiltonianCompileError,
|
||||
IngressDegenerate,
|
||||
IngressWavePacket,
|
||||
LifecycleOutcome,
|
||||
ProblemHamiltonian,
|
||||
PropositionalEntailmentVerdict,
|
||||
PropositionalProblem,
|
||||
RelaxationCertificate,
|
||||
RelaxationInputError,
|
||||
RelaxationNotConverged,
|
||||
RelaxationNumericalFailure,
|
||||
RelaxationResult,
|
||||
assignment_component_index,
|
||||
compile_propositional,
|
||||
compile_quadratic_well,
|
||||
egress_gate,
|
||||
ingest_context,
|
||||
propositional_entails,
|
||||
relax_to_ground,
|
||||
uniform_assignment_state,
|
||||
)
|
||||
|
||||
__all__ = [
|
||||
"SalienceOperator", "SalienceMap", "FieldRegion",
|
||||
|
|
@ -207,6 +260,31 @@ __all__ = [
|
|||
"multi_scale_energy_for_schedule",
|
||||
"multi_scale_energy_vector",
|
||||
"schedule_mid_span_fraction",
|
||||
"CognitiveLifecycleEngine",
|
||||
"CognitiveLifecycleError",
|
||||
"CrystallizationProposal",
|
||||
"EgressValidationError",
|
||||
"EgressVerdict",
|
||||
"HamiltonianCompileError",
|
||||
"IngressDegenerate",
|
||||
"IngressWavePacket",
|
||||
"LifecycleOutcome",
|
||||
"ProblemHamiltonian",
|
||||
"PropositionalEntailmentVerdict",
|
||||
"PropositionalProblem",
|
||||
"RelaxationCertificate",
|
||||
"RelaxationInputError",
|
||||
"RelaxationNotConverged",
|
||||
"RelaxationNumericalFailure",
|
||||
"RelaxationResult",
|
||||
"assignment_component_index",
|
||||
"compile_propositional",
|
||||
"compile_quadratic_well",
|
||||
"egress_gate",
|
||||
"ingest_context",
|
||||
"propositional_entails",
|
||||
"relax_to_ground",
|
||||
"uniform_assignment_state",
|
||||
]
|
||||
|
||||
|
||||
|
|
|
|||
960
core/physics/cognitive_lifecycle.py
Normal file
960
core/physics/cognitive_lifecycle.py
Normal file
|
|
@ -0,0 +1,960 @@
|
|||
"""ADR-0243 §2 — Wave-Field Cognitive Lifecycle (Tier-2, OFF-SERVING).
|
||||
|
||||
Ingress → Hamiltonian-well relaxation → egress, on the Cl(4,1) coefficient
|
||||
space. Implements the ADR-0243 lifecycle honestly, with the §3 reference
|
||||
prototype's defects corrected (they are pinned in
|
||||
``tests/test_adr_0243_sketch_defect_pins.py``; deviations D-1…D-5 are recorded
|
||||
in ``docs/plans/adr-0243-implementation-plan.md`` §4):
|
||||
|
||||
* **Ingress** delegates to :mod:`core.physics.sensorium_wave_feed`
|
||||
(superposition) and normalizes ONCE at this module's owned construction
|
||||
boundary (deviation D-3; master-plan doctrine note — no hot-path repair).
|
||||
* **Relaxation** is the dissipative imaginary-time semigroup
|
||||
``ψ ← normalize(exp(−(H−λ0)·dt)·ψ)`` — deterministic power iteration that
|
||||
provably converges to the ground eigenspace at a rate set by the spectral
|
||||
gap (deviation D-1). The sketch's ``exp(H·I·t)`` loop oscillates and cannot
|
||||
relax (pin SD-B). Convergence is certified, never assumed (deviation D-2):
|
||||
the certificate carries the exact ground energy from the spectrum, the
|
||||
achieved Rayleigh energy, the eigen-residual, the gap (certification
|
||||
requires the gap be resolvable at the requested tolerance), and a byte
|
||||
digest of the certified state binding the evidence to that exact ψ.
|
||||
* **Egress** composes the existing organs — unit amplitude density,
|
||||
the certificate↔state binding check (a borrowed certificate refuses),
|
||||
:meth:`WaveManifold.measure_unitary_residual` (the ADR's R_GoldTether;
|
||||
reported, and REQUIRED only on the crystallization route where states must
|
||||
be closed versors), ADR-0006 energy classes via
|
||||
:func:`core.physics.wave_energy_boundary.energy_profile_from_wave`, and the
|
||||
E0/E1 crystallization policy via
|
||||
:func:`~core.physics.wave_energy_boundary.crystallization_for_holographic_seal`.
|
||||
Gating a multi-mode superposition on versor closure would reject every
|
||||
legitimate interference state (the dual of pin SD-A), so versor closure
|
||||
routes rather than admits.
|
||||
* **No mutation**: cold states emit a :class:`CrystallizationProposal`
|
||||
(``epistemic_status="SPECULATIVE"`` enforced by the type) — never a vault
|
||||
write (deviation D-5 / cohesion I-03). This module imports no vault store.
|
||||
|
||||
Problem domains (v1, plan §5 Phase 2 — two checkable domains only):
|
||||
|
||||
* ``quadratic_well`` — H = curvature·(Id − ψ₀ψ₀ᵀ): ground space is span(ψ₀);
|
||||
relaxation decodes the target from any non-orthogonal start.
|
||||
* ``propositional`` — the Cl(4,1) blade lattice IS the assignment lattice of
|
||||
≤ 5 atoms: blade {e_{i₁}…e_{i_k}} ↔ assignment with exactly those atoms
|
||||
True. Clauses compile to a DIAGONAL penalty Hamiltonian counting falsified
|
||||
clauses per assignment; the ground space is the span of satisfying
|
||||
assignments and relaxation decodes the model set. Verdicts (SAT /
|
||||
entailment) read the exact ground energy of the same H — integer counts
|
||||
scaled by ``penalty``, no floating eigensolve on the diagonal path.
|
||||
|
||||
Honesty note (D-2): the propositional compiler enumerates the ≤ 32 assignment
|
||||
components — this is exact small-domain decoding, not a scalability claim.
|
||||
Its value is falsifiability: verdicts are scored against independent gold
|
||||
(truth tables here; ``generate.proof_chain`` ROBDD in the Phase 4 eval).
|
||||
|
||||
Serve quarantine (A-04): never imported by ``chat/runtime.py``; exported
|
||||
lazily via the ``core.physics`` barrel; enforced by
|
||||
``tests/test_serve_quarantine_transitive.py`` and the cohesion suite.
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import hashlib
|
||||
import json
|
||||
from dataclasses import dataclass, field
|
||||
from typing import Any, Mapping, Sequence
|
||||
|
||||
import numpy as np
|
||||
|
||||
from algebra.cl41 import N_COMPONENTS, geometric_product
|
||||
from core.physics.energy import EnergyClass, EnergyProfile, FieldEnergyOperator
|
||||
from core.physics.sensorium_wave_feed import PacketLike, _coerce_packet, superpose_packets
|
||||
from core.physics.wave_energy_boundary import (
|
||||
CrystallizationDecision,
|
||||
crystallization_for_holographic_seal,
|
||||
energy_profile_from_wave,
|
||||
)
|
||||
from core.physics.wave_manifold import WaveManifold
|
||||
|
||||
_NEAR_ZERO = 1e-12
|
||||
_UNIT_TOL = 1e-9
|
||||
_EPSILON_DRIFT = 1e-6
|
||||
_MAX_ATOMS = 5
|
||||
_SPECULATIVE = "SPECULATIVE"
|
||||
|
||||
|
||||
# --- Typed fail-closed errors --------------------------------------------------
|
||||
|
||||
|
||||
class CognitiveLifecycleError(ValueError):
|
||||
"""Fail-closed lifecycle refusal with structured disclosure."""
|
||||
|
||||
def __init__(self, reason: str, **disclosure: Any) -> None:
|
||||
self.reason = reason
|
||||
self.disclosure = dict(disclosure)
|
||||
super().__init__(f"cognitive_lifecycle refused [{reason}]: {self.disclosure}")
|
||||
|
||||
|
||||
class IngressDegenerate(CognitiveLifecycleError):
|
||||
"""Superposed context has no resolvable amplitude (no confabulated field)."""
|
||||
|
||||
|
||||
class HamiltonianCompileError(CognitiveLifecycleError):
|
||||
"""Problem → Hamiltonian compilation refused (malformed constraints)."""
|
||||
|
||||
|
||||
class RelaxationInputError(CognitiveLifecycleError):
|
||||
"""Relaxer input refused (shape / non-finite / non-unit ψ0). No repair."""
|
||||
|
||||
|
||||
class RelaxationNumericalFailure(CognitiveLifecycleError):
|
||||
"""Non-finite value produced during relaxation (mirrors OptimizationFailure)."""
|
||||
|
||||
|
||||
class RelaxationNotConverged(CognitiveLifecycleError):
|
||||
"""Relaxation did not certify the ground state; carries the certificate."""
|
||||
|
||||
def __init__(self, reason: str, certificate: "RelaxationCertificate", **disclosure: Any) -> None:
|
||||
self.certificate = certificate
|
||||
super().__init__(reason, **disclosure)
|
||||
|
||||
|
||||
class EgressValidationError(CognitiveLifecycleError):
|
||||
"""Egress gate refused to evaluate a malformed state (shape / non-finite)."""
|
||||
|
||||
|
||||
# --- Content addressing ----------------------------------------------------------
|
||||
|
||||
|
||||
def _content_id(payload: Mapping[str, Any]) -> str:
|
||||
raw = json.dumps(payload, sort_keys=True, separators=(",", ":"), default=str)
|
||||
return hashlib.sha256(raw.encode("utf-8")).hexdigest()[:24]
|
||||
|
||||
|
||||
def _psi_digest(psi: np.ndarray) -> str:
|
||||
return hashlib.sha256(np.ascontiguousarray(psi, dtype=np.float64).tobytes()).hexdigest()[:24]
|
||||
|
||||
|
||||
def _as_psi(x: np.ndarray, name: str, *, error: type[CognitiveLifecycleError]) -> np.ndarray:
|
||||
arr = np.asarray(x, dtype=np.float64)
|
||||
if arr.shape != (N_COMPONENTS,):
|
||||
raise error("bad_shape", name=name, shape=list(np.shape(x)))
|
||||
if not np.all(np.isfinite(arr)):
|
||||
raise error("non_finite", name=name)
|
||||
return arr
|
||||
|
||||
|
||||
# --- Blade lattice ↔ assignment lattice (propositional substrate) -----------------
|
||||
#
|
||||
# Subset S ⊆ {0..4} of basis-vector indices ↔ the canonical blade e_{i1}…e_{ik}
|
||||
# (ascending product) ↔ the truth assignment with exactly the atoms in S True.
|
||||
# The component index and sign are DERIVED from the algebra's own geometric
|
||||
# product — no hand-maintained table to drift from algebra/cl41.
|
||||
|
||||
|
||||
def _vector_onehot(i: int) -> np.ndarray:
|
||||
v = np.zeros(N_COMPONENTS, dtype=np.float64)
|
||||
v[1 + i] = 1.0 # basis vector e_i lives at component 1+i (0-indexed atoms)
|
||||
return v
|
||||
|
||||
|
||||
def _build_subset_component_map() -> tuple[tuple[int, ...], tuple[float, ...]]:
|
||||
indices: list[int] = []
|
||||
signs: list[float] = []
|
||||
for mask in range(1 << _MAX_ATOMS):
|
||||
blade = np.zeros(N_COMPONENTS, dtype=np.float64)
|
||||
blade[0] = 1.0
|
||||
for i in range(_MAX_ATOMS):
|
||||
if mask & (1 << i):
|
||||
blade = geometric_product(blade, _vector_onehot(i))
|
||||
support = np.nonzero(np.abs(blade) > 0.5)[0]
|
||||
if support.size != 1:
|
||||
raise RuntimeError(f"blade map degenerate for mask {mask}: support={support}")
|
||||
idx = int(support[0])
|
||||
indices.append(idx)
|
||||
signs.append(float(np.sign(blade[idx])))
|
||||
if len(set(indices)) != (1 << _MAX_ATOMS):
|
||||
raise RuntimeError("blade map is not a bijection onto components")
|
||||
return tuple(indices), tuple(signs)
|
||||
|
||||
|
||||
_SUBSET_COMPONENT, _SUBSET_SIGN = _build_subset_component_map()
|
||||
|
||||
|
||||
def assignment_component_index(assignment_mask: int) -> int:
|
||||
"""Component index of the blade encoding *assignment_mask* (bit i = atom i True)."""
|
||||
if not (0 <= int(assignment_mask) < (1 << _MAX_ATOMS)):
|
||||
raise HamiltonianCompileError("assignment_mask_out_of_range", mask=int(assignment_mask))
|
||||
return _SUBSET_COMPONENT[int(assignment_mask)]
|
||||
|
||||
|
||||
# --- Ingress ----------------------------------------------------------------------
|
||||
|
||||
|
||||
@dataclass(frozen=True, slots=True)
|
||||
class IngressWavePacket:
|
||||
"""Normalized ingress field ψ_context with provenance (ADR-0243 §2.1)."""
|
||||
|
||||
psi: np.ndarray
|
||||
domain_id: str
|
||||
modality_ids: tuple[str, ...]
|
||||
packet_digest: str
|
||||
|
||||
def __post_init__(self) -> None:
|
||||
arr = _as_psi(self.psi, "ψ_context", error=IngressDegenerate)
|
||||
arr = arr.copy()
|
||||
arr.setflags(write=False)
|
||||
object.__setattr__(self, "psi", arr)
|
||||
|
||||
|
||||
def ingest_context(packets: Sequence[PacketLike], domain_id: str) -> IngressWavePacket:
|
||||
"""Superpose modality packets and normalize at the owned construction boundary.
|
||||
|
||||
Delegates superposition to :func:`sensorium_wave_feed.superpose_packets`
|
||||
(which refuses empty input). Normalization here is the ONE owned
|
||||
construction boundary of the lifecycle (D-3) — a degenerate superposition
|
||||
(destructive cancellation below ``1e-12``) is refused, never zero-filled.
|
||||
"""
|
||||
domain = str(domain_id).strip()
|
||||
if not domain:
|
||||
raise IngressDegenerate("empty_domain_id")
|
||||
total = superpose_packets(packets)
|
||||
norm = float(np.linalg.norm(total))
|
||||
if not np.isfinite(norm) or norm < _NEAR_ZERO:
|
||||
raise IngressDegenerate("degenerate_superposition", norm=norm, n_packets=len(packets))
|
||||
psi = (total / norm).astype(np.float64)
|
||||
modality_ids = tuple(_coerce_packet(p).modality_id for p in packets)
|
||||
return IngressWavePacket(
|
||||
psi=psi,
|
||||
domain_id=domain,
|
||||
modality_ids=modality_ids,
|
||||
packet_digest=_content_id(
|
||||
{"psi": _psi_digest(psi), "domain": domain, "modalities": list(modality_ids)}
|
||||
),
|
||||
)
|
||||
|
||||
|
||||
# --- Problem Hamiltonians -----------------------------------------------------------
|
||||
|
||||
|
||||
@dataclass(frozen=True, slots=True)
|
||||
class ProblemHamiltonian:
|
||||
"""Typed, content-addressed constraint operator H (symmetric, 32×32, f64).
|
||||
|
||||
``matrix`` is validated (shape, finiteness, symmetry ≤ 1e-12) and frozen
|
||||
read-only; asymmetric input is refused, never symmetrized (no repair).
|
||||
"""
|
||||
|
||||
matrix: np.ndarray
|
||||
domain: str
|
||||
metadata: Mapping[str, Any] = field(default_factory=dict)
|
||||
hamiltonian_id: str = ""
|
||||
is_diagonal: bool = False
|
||||
|
||||
def __post_init__(self) -> None:
|
||||
arr = np.asarray(self.matrix, dtype=np.float64)
|
||||
if arr.shape != (N_COMPONENTS, N_COMPONENTS):
|
||||
raise HamiltonianCompileError("bad_shape", shape=list(arr.shape))
|
||||
if not np.all(np.isfinite(arr)):
|
||||
raise HamiltonianCompileError("non_finite_matrix")
|
||||
asym = float(np.max(np.abs(arr - arr.T)))
|
||||
if asym > 1e-12:
|
||||
raise HamiltonianCompileError("not_symmetric", max_asymmetry=asym)
|
||||
arr = arr.copy()
|
||||
arr.setflags(write=False)
|
||||
diagonal = bool(np.count_nonzero(arr - np.diag(np.diagonal(arr))) == 0)
|
||||
meta = dict(self.metadata)
|
||||
object.__setattr__(self, "matrix", arr)
|
||||
object.__setattr__(self, "metadata", meta)
|
||||
object.__setattr__(self, "is_diagonal", diagonal)
|
||||
object.__setattr__(
|
||||
self,
|
||||
"hamiltonian_id",
|
||||
_content_id(
|
||||
{
|
||||
"domain": str(self.domain),
|
||||
"matrix_sha": hashlib.sha256(arr.tobytes()).hexdigest(),
|
||||
"metadata": {k: str(v) for k, v in sorted(meta.items())},
|
||||
}
|
||||
),
|
||||
)
|
||||
|
||||
|
||||
def compile_quadratic_well(target_psi: np.ndarray, *, curvature: float = 1.0) -> ProblemHamiltonian:
|
||||
"""H = curvature·(Id − ψ₀ψ₀ᵀ): ground space span(ψ₀) at energy 0, gap = curvature."""
|
||||
target = _as_psi(target_psi, "target_psi", error=HamiltonianCompileError)
|
||||
c = float(curvature)
|
||||
if not np.isfinite(c) or c <= 0.0:
|
||||
raise HamiltonianCompileError("curvature_not_positive", curvature=c)
|
||||
norm_err = abs(float(np.linalg.norm(target)) - 1.0)
|
||||
if norm_err > _UNIT_TOL:
|
||||
raise HamiltonianCompileError("target_not_unit", norm_residual=norm_err)
|
||||
matrix = c * (np.eye(N_COMPONENTS, dtype=np.float64) - np.outer(target, target))
|
||||
return ProblemHamiltonian(
|
||||
matrix=matrix,
|
||||
domain="quadratic_well",
|
||||
metadata={"curvature": c, "target_digest": _psi_digest(target)},
|
||||
)
|
||||
|
||||
|
||||
PropositionalLiteral = tuple[str, bool]
|
||||
Clause = tuple[PropositionalLiteral, ...]
|
||||
|
||||
|
||||
@dataclass(frozen=True, slots=True)
|
||||
class PropositionalProblem:
|
||||
"""CNF over ≤ 5 atoms; atom i ↔ basis vector e_i (order as given)."""
|
||||
|
||||
atoms: tuple[str, ...]
|
||||
clauses: tuple[Clause, ...]
|
||||
problem_id: str = ""
|
||||
|
||||
def __post_init__(self) -> None:
|
||||
atoms = tuple(str(a) for a in self.atoms)
|
||||
if not (1 <= len(atoms) <= _MAX_ATOMS):
|
||||
raise HamiltonianCompileError("atom_count_out_of_range", n_atoms=len(atoms))
|
||||
if len(set(atoms)) != len(atoms) or any(not a.strip() for a in atoms):
|
||||
raise HamiltonianCompileError("atoms_not_unique_nonempty", atoms=list(atoms))
|
||||
clauses: list[Clause] = []
|
||||
for ci, clause in enumerate(self.clauses):
|
||||
lits = tuple((str(a), bool(p)) for a, p in clause)
|
||||
if not lits:
|
||||
raise HamiltonianCompileError("empty_clause", clause_index=ci)
|
||||
if len(set(lits)) != len(lits):
|
||||
raise HamiltonianCompileError("duplicate_literal", clause_index=ci)
|
||||
for atom, _ in lits:
|
||||
if atom not in atoms:
|
||||
raise HamiltonianCompileError("unknown_atom", clause_index=ci, atom=atom)
|
||||
clauses.append(lits)
|
||||
object.__setattr__(self, "atoms", atoms)
|
||||
object.__setattr__(self, "clauses", tuple(clauses))
|
||||
object.__setattr__(
|
||||
self,
|
||||
"problem_id",
|
||||
_content_id({"atoms": list(atoms), "clauses": [list(c) for c in clauses]}),
|
||||
)
|
||||
|
||||
@property
|
||||
def n_atoms(self) -> int:
|
||||
return len(self.atoms)
|
||||
|
||||
|
||||
def _falsification_counts(problem: PropositionalProblem) -> tuple[int, ...]:
|
||||
"""Clauses falsified per assignment mask (exact integer counts)."""
|
||||
k = problem.n_atoms
|
||||
index = {a: i for i, a in enumerate(problem.atoms)}
|
||||
counts = [0] * (1 << k)
|
||||
for mask in range(1 << k):
|
||||
for clause in problem.clauses:
|
||||
satisfied = False
|
||||
for atom, polarity in clause:
|
||||
bit = bool(mask & (1 << index[atom]))
|
||||
if bit == polarity:
|
||||
satisfied = True
|
||||
break
|
||||
if not satisfied:
|
||||
counts[mask] += 1
|
||||
return tuple(counts)
|
||||
|
||||
|
||||
def compile_propositional(problem: PropositionalProblem, *, penalty: float = 1.0) -> ProblemHamiltonian:
|
||||
"""Diagonal penalty Hamiltonian: diag[component(a)] = penalty · #clauses falsified by a.
|
||||
|
||||
Out-of-domain components (blades using vectors beyond the atom set) get
|
||||
``penalty·(len(clauses)+1)`` — strictly above every in-domain value, so
|
||||
the ground space is always inside the assignment lattice. Satisfiable iff
|
||||
the exact ground energy is 0.
|
||||
"""
|
||||
p = float(penalty)
|
||||
if not np.isfinite(p) or p <= 0.0:
|
||||
raise HamiltonianCompileError("penalty_not_positive", penalty=p)
|
||||
counts = _falsification_counts(problem)
|
||||
diag = np.full(N_COMPONENTS, p * float(len(problem.clauses) + 1), dtype=np.float64)
|
||||
for mask, count in enumerate(counts):
|
||||
diag[_SUBSET_COMPONENT[mask]] = p * float(count)
|
||||
return ProblemHamiltonian(
|
||||
matrix=np.diag(diag),
|
||||
domain="propositional",
|
||||
metadata={"problem_id": problem.problem_id, "penalty": p, "n_atoms": problem.n_atoms},
|
||||
)
|
||||
|
||||
|
||||
def uniform_assignment_state(problem: PropositionalProblem) -> np.ndarray:
|
||||
"""Unit uniform superposition over the problem's assignment components.
|
||||
|
||||
Uses the algebra-derived blade signs so every assignment basis state enters
|
||||
with amplitude +1/√(2^k) on the CANONICAL blade orientation.
|
||||
"""
|
||||
k = problem.n_atoms
|
||||
psi = np.zeros(N_COMPONENTS, dtype=np.float64)
|
||||
amp = 1.0 / float(np.sqrt(1 << k))
|
||||
for mask in range(1 << k):
|
||||
psi[_SUBSET_COMPONENT[mask]] = amp * _SUBSET_SIGN[mask]
|
||||
return psi
|
||||
|
||||
|
||||
# --- Relaxation (imaginary-time semigroup; deviation D-1) ---------------------------
|
||||
|
||||
|
||||
@dataclass(frozen=True, slots=True)
|
||||
class RelaxationCertificate:
|
||||
"""Convergence evidence for one relaxation run (D-2: certified, not assumed).
|
||||
|
||||
``psi_digest`` binds the certificate to the exact final state it describes
|
||||
(byte digest of ψ_steady) — the egress gate refuses a certificate presented
|
||||
with any other state, so convergence evidence cannot be borrowed.
|
||||
"""
|
||||
|
||||
hamiltonian_id: str
|
||||
domain: str
|
||||
dt: float
|
||||
tol: float
|
||||
max_steps: int
|
||||
steps_taken: int
|
||||
ground_energy: float
|
||||
achieved_energy: float
|
||||
spectral_gap: float
|
||||
eigen_residual: float
|
||||
energy_monotone: bool
|
||||
converged: bool
|
||||
reason: str
|
||||
psi_digest: str
|
||||
certificate_id: str = ""
|
||||
|
||||
def __post_init__(self) -> None:
|
||||
payload = {
|
||||
"hamiltonian_id": self.hamiltonian_id,
|
||||
"domain": self.domain,
|
||||
"dt": repr(float(self.dt)),
|
||||
"tol": repr(float(self.tol)),
|
||||
"max_steps": int(self.max_steps),
|
||||
"steps_taken": int(self.steps_taken),
|
||||
"ground_energy": repr(float(self.ground_energy)),
|
||||
"achieved_energy": repr(float(self.achieved_energy)),
|
||||
"spectral_gap": repr(float(self.spectral_gap)),
|
||||
"eigen_residual": repr(float(self.eigen_residual)),
|
||||
"energy_monotone": bool(self.energy_monotone),
|
||||
"converged": bool(self.converged),
|
||||
"reason": self.reason,
|
||||
"psi_digest": self.psi_digest,
|
||||
}
|
||||
object.__setattr__(self, "certificate_id", _content_id(payload))
|
||||
|
||||
def as_dict(self) -> dict[str, Any]:
|
||||
return {
|
||||
"hamiltonian_id": self.hamiltonian_id,
|
||||
"domain": self.domain,
|
||||
"dt": float(self.dt),
|
||||
"tol": float(self.tol),
|
||||
"max_steps": int(self.max_steps),
|
||||
"steps_taken": int(self.steps_taken),
|
||||
"ground_energy": float(self.ground_energy),
|
||||
"achieved_energy": float(self.achieved_energy),
|
||||
"spectral_gap": float(self.spectral_gap),
|
||||
"eigen_residual": float(self.eigen_residual),
|
||||
"energy_monotone": bool(self.energy_monotone),
|
||||
"converged": bool(self.converged),
|
||||
"reason": self.reason,
|
||||
"psi_digest": self.psi_digest,
|
||||
"certificate_id": self.certificate_id,
|
||||
}
|
||||
|
||||
|
||||
@dataclass(frozen=True, slots=True)
|
||||
class RelaxationResult:
|
||||
psi_steady: np.ndarray
|
||||
certificate: RelaxationCertificate
|
||||
|
||||
def __post_init__(self) -> None:
|
||||
arr = np.asarray(self.psi_steady, dtype=np.float64).copy()
|
||||
arr.setflags(write=False)
|
||||
object.__setattr__(self, "psi_steady", arr)
|
||||
|
||||
|
||||
def _spectral_gap(evals: np.ndarray, tol: float) -> tuple[float, float, float]:
|
||||
"""(λ0, gap, energy_tol) with the degeneracy cluster ⊆ the acceptance window.
|
||||
|
||||
Capping ``deg_tol`` at ``energy_tol`` keeps the certificate internally
|
||||
consistent: an eigenvalue counted into the ground cluster is never refused
|
||||
by the energy check, and ``gap`` is the honest rate-limiting gap (a split
|
||||
just above ``energy_tol`` is reported, not absorbed).
|
||||
"""
|
||||
lam0 = float(evals[0])
|
||||
energy_tol = float(tol) * max(1.0, abs(lam0))
|
||||
deg_tol = min(1e-9 * max(1.0, abs(lam0)) + 1e-12, energy_tol)
|
||||
above = evals[evals > lam0 + deg_tol]
|
||||
gap = float(above[0] - lam0) if above.size else 0.0
|
||||
return lam0, gap, energy_tol
|
||||
|
||||
|
||||
def relax_to_ground(
|
||||
psi0: np.ndarray,
|
||||
hamiltonian: ProblemHamiltonian,
|
||||
*,
|
||||
dt: float = 1.0,
|
||||
max_steps: int = 512,
|
||||
tol: float = 1e-10,
|
||||
require_converged: bool = True,
|
||||
) -> RelaxationResult:
|
||||
"""Deterministic imaginary-time relaxation to the ground eigenspace of H.
|
||||
|
||||
``ψ ← normalize(exp(−(H−λ0)·dt)·ψ)`` — normalized power iteration on the
|
||||
dissipative semigroup (D-1; the λ0 shift only rescales, dynamics
|
||||
identical). Along the iteration the Rayleigh energy is non-increasing (a
|
||||
falsifiable physics invariant, recorded as ``energy_monotone``).
|
||||
|
||||
Converged means ``‖Hψ − Eψ‖ ≤ tol`` AND ``E − λ0 ≤ tol·max(1,|λ0|)`` AND,
|
||||
when the spectral gap is positive, ``E − λ0 ≤ tol·gap`` — the excited-space
|
||||
weight of ψ is bounded by ``(E−λ0)/gap``, so the third check certifies
|
||||
ground weight ≥ 1−tol instead of trusting an energy window the spectrum
|
||||
may not resolve. A start orthogonal to the ground space settles in an
|
||||
excited eigenspace with a small residual and is refused as
|
||||
``excited_eigenspace``; a state whose energy sits inside the window while
|
||||
the gap is below the requested resolution is refused as
|
||||
``spectral_gap_below_tolerance``, never mis-certified. Degenerate ground
|
||||
spaces (gap 0 after clustering) converge to the normalized projection of
|
||||
ψ0 (input-dependent decoding within the solution space). Fail-closed:
|
||||
non-finite input/iterates and non-unit ψ0 raise typed errors; nothing is
|
||||
repaired.
|
||||
"""
|
||||
psi = _as_psi(psi0, "ψ0", error=RelaxationInputError).copy()
|
||||
unit_err = abs(float(np.linalg.norm(psi)) - 1.0)
|
||||
if unit_err > _UNIT_TOL:
|
||||
raise RelaxationInputError("psi0_not_normalized", norm_residual=unit_err)
|
||||
dt_f = float(dt)
|
||||
if not np.isfinite(dt_f) or dt_f <= 0.0:
|
||||
raise RelaxationInputError("dt_not_positive", dt=dt_f)
|
||||
steps = int(max_steps)
|
||||
if steps < 1:
|
||||
raise RelaxationInputError("max_steps_not_positive", max_steps=steps)
|
||||
tol_f = float(tol)
|
||||
if not np.isfinite(tol_f) or tol_f <= 0.0:
|
||||
raise RelaxationInputError("tol_not_positive", tol=tol_f)
|
||||
|
||||
H_mat = hamiltonian.matrix
|
||||
if hamiltonian.is_diagonal:
|
||||
# Exact spectrum from the diagonal — no LAPACK on the propositional path.
|
||||
diag = np.diagonal(H_mat).copy()
|
||||
lam0, gap, energy_tol = _spectral_gap(np.sort(diag), tol_f)
|
||||
decay = np.exp(-(diag - lam0) * dt_f)
|
||||
|
||||
def step(v: np.ndarray) -> np.ndarray:
|
||||
return decay * v
|
||||
|
||||
def apply_h(v: np.ndarray) -> np.ndarray:
|
||||
return diag * v
|
||||
|
||||
else:
|
||||
evals_full, evecs_full = np.linalg.eigh(H_mat)
|
||||
lam0, gap, energy_tol = _spectral_gap(evals_full, tol_f)
|
||||
propagator = evecs_full @ np.diag(np.exp(-(evals_full - lam0) * dt_f)) @ evecs_full.T
|
||||
|
||||
def step(v: np.ndarray) -> np.ndarray:
|
||||
return propagator @ v
|
||||
|
||||
def apply_h(v: np.ndarray) -> np.ndarray:
|
||||
return H_mat @ v
|
||||
|
||||
def _measure(v: np.ndarray) -> tuple[float, float]:
|
||||
hv = apply_h(v)
|
||||
energy = float(v @ hv)
|
||||
residual = float(np.linalg.norm(hv - energy * v))
|
||||
return energy, residual
|
||||
|
||||
def _certified(energy: float, residual: float) -> bool:
|
||||
near_ground = (energy - lam0) <= energy_tol
|
||||
gap_resolved = gap == 0.0 or (energy - lam0) <= tol_f * gap
|
||||
return residual <= tol_f and near_ground and gap_resolved
|
||||
|
||||
energies: list[float] = []
|
||||
energy, residual = _measure(psi)
|
||||
energies.append(energy)
|
||||
steps_taken = 0
|
||||
for _ in range(steps):
|
||||
if _certified(energy, residual):
|
||||
break
|
||||
psi = step(psi)
|
||||
if not np.all(np.isfinite(psi)):
|
||||
# Defensive only: decay/propagator entries are exp(−x) with x ≥ 0.
|
||||
raise RelaxationNumericalFailure("non_finite_iterate", steps_taken=steps_taken)
|
||||
norm = float(np.linalg.norm(psi))
|
||||
if norm < _NEAR_ZERO:
|
||||
raise RelaxationNumericalFailure("iterate_collapsed", steps_taken=steps_taken)
|
||||
psi = psi / norm
|
||||
steps_taken += 1
|
||||
energy, residual = _measure(psi)
|
||||
energies.append(energy)
|
||||
|
||||
monotone = all(
|
||||
energies[i + 1] <= energies[i] + 1e-9 * max(1.0, abs(energies[i]))
|
||||
for i in range(len(energies) - 1)
|
||||
)
|
||||
residual_ok = residual <= tol_f
|
||||
at_ground = (energy - lam0) <= energy_tol
|
||||
converged = _certified(energy, residual)
|
||||
if converged:
|
||||
reason = "ground_state_certified"
|
||||
elif residual_ok and not at_ground:
|
||||
reason = "excited_eigenspace"
|
||||
elif residual_ok:
|
||||
reason = "spectral_gap_below_tolerance"
|
||||
else:
|
||||
reason = "max_steps_exhausted"
|
||||
|
||||
certificate = RelaxationCertificate(
|
||||
hamiltonian_id=hamiltonian.hamiltonian_id,
|
||||
domain=hamiltonian.domain,
|
||||
dt=dt_f,
|
||||
tol=tol_f,
|
||||
max_steps=steps,
|
||||
steps_taken=steps_taken,
|
||||
ground_energy=lam0,
|
||||
achieved_energy=energy,
|
||||
spectral_gap=gap,
|
||||
eigen_residual=residual,
|
||||
energy_monotone=monotone,
|
||||
converged=converged,
|
||||
reason=reason,
|
||||
psi_digest=_psi_digest(psi),
|
||||
)
|
||||
if not converged and require_converged:
|
||||
raise RelaxationNotConverged(
|
||||
reason,
|
||||
certificate,
|
||||
achieved_energy=energy,
|
||||
ground_energy=lam0,
|
||||
eigen_residual=residual,
|
||||
)
|
||||
return RelaxationResult(psi_steady=psi, certificate=certificate)
|
||||
|
||||
|
||||
# --- Propositional verdicts (exact spectrum path) -----------------------------------
|
||||
|
||||
|
||||
@dataclass(frozen=True, slots=True)
|
||||
class PropositionalEntailmentVerdict:
|
||||
"""Entailment via UNSAT(premises ∧ ¬conclusion) on the SAME compiled H family.
|
||||
|
||||
``satisfiable_premises=False`` discloses vacuous (ex falso) entailment.
|
||||
Distinct name from ``generate.proof_chain.EntailmentVerdict`` (the ROBDD
|
||||
flagship) — that is the independent gold this domain is scored against.
|
||||
"""
|
||||
|
||||
entailed: bool
|
||||
satisfiable_premises: bool
|
||||
ground_energy_premises: float
|
||||
ground_energy_augmented: float
|
||||
penalty: float
|
||||
verdict_id: str = ""
|
||||
|
||||
def __post_init__(self) -> None:
|
||||
object.__setattr__(
|
||||
self,
|
||||
"verdict_id",
|
||||
_content_id(
|
||||
{
|
||||
"entailed": bool(self.entailed),
|
||||
"satisfiable_premises": bool(self.satisfiable_premises),
|
||||
"ge_premises": repr(float(self.ground_energy_premises)),
|
||||
"ge_augmented": repr(float(self.ground_energy_augmented)),
|
||||
"penalty": repr(float(self.penalty)),
|
||||
}
|
||||
),
|
||||
)
|
||||
|
||||
|
||||
def _in_domain_ground_energy(problem: PropositionalProblem, *, penalty: float) -> float:
|
||||
counts = _falsification_counts(problem)
|
||||
return float(penalty) * float(min(counts))
|
||||
|
||||
|
||||
def propositional_entails(
|
||||
premises: PropositionalProblem,
|
||||
conclusion: Clause,
|
||||
*,
|
||||
penalty: float = 1.0,
|
||||
) -> PropositionalEntailmentVerdict:
|
||||
"""premises ⊨ (⋁ conclusion) iff premises ∧ ¬conclusion is UNSAT.
|
||||
|
||||
¬conclusion compiles to unit clauses over the SAME atom set (unknown atoms
|
||||
are refused — the v1 domain is closed-vocabulary). The verdict reads exact
|
||||
integer ground energies of the compiled Hamiltonians; relaxation is the
|
||||
constructive decoder of the same operators, so what is asserted and what
|
||||
relaxes are one object.
|
||||
"""
|
||||
p = float(penalty)
|
||||
if not np.isfinite(p) or p <= 0.0:
|
||||
raise HamiltonianCompileError("penalty_not_positive", penalty=p)
|
||||
lits = tuple((str(a), bool(pol)) for a, pol in conclusion)
|
||||
if not lits:
|
||||
raise HamiltonianCompileError("empty_conclusion")
|
||||
for atom, _ in lits:
|
||||
if atom not in premises.atoms:
|
||||
raise HamiltonianCompileError("unknown_atom_in_conclusion", atom=atom)
|
||||
negation_units: tuple[Clause, ...] = tuple(((atom, not pol),) for atom, pol in lits)
|
||||
augmented = PropositionalProblem(
|
||||
atoms=premises.atoms,
|
||||
clauses=premises.clauses + negation_units,
|
||||
)
|
||||
ge_premises = _in_domain_ground_energy(premises, penalty=p)
|
||||
ge_augmented = _in_domain_ground_energy(augmented, penalty=p)
|
||||
return PropositionalEntailmentVerdict(
|
||||
entailed=bool(ge_augmented > 0.0),
|
||||
satisfiable_premises=bool(ge_premises == 0.0),
|
||||
ground_energy_premises=ge_premises,
|
||||
ground_energy_augmented=ge_augmented,
|
||||
penalty=p,
|
||||
)
|
||||
|
||||
|
||||
# --- Egress (ADR-0243 §2.3) ----------------------------------------------------------
|
||||
|
||||
|
||||
@dataclass(frozen=True, slots=True)
|
||||
class CrystallizationProposal:
|
||||
"""Proposal-only cold-state artifact (D-5 / I-03). NEVER a vault write.
|
||||
|
||||
``epistemic_status`` is pinned to ``"SPECULATIVE"`` by the type itself;
|
||||
ratification and any COHERENT promotion live outside this module, behind
|
||||
the one-mutation-path.
|
||||
"""
|
||||
|
||||
proposal_id: str
|
||||
epistemic_status: str
|
||||
psi_digest: str
|
||||
certificate_id: str
|
||||
decision: CrystallizationDecision
|
||||
adr_refs: tuple[str, ...] = ("ADR-0243", "ADR-0241")
|
||||
|
||||
def __post_init__(self) -> None:
|
||||
if self.epistemic_status != _SPECULATIVE:
|
||||
raise CognitiveLifecycleError(
|
||||
"proposal_must_be_speculative", epistemic_status=self.epistemic_status
|
||||
)
|
||||
|
||||
def as_dict(self) -> dict[str, Any]:
|
||||
return {
|
||||
"proposal_id": self.proposal_id,
|
||||
"epistemic_status": self.epistemic_status,
|
||||
"psi_digest": self.psi_digest,
|
||||
"certificate_id": self.certificate_id,
|
||||
"decision": self.decision.as_dict(),
|
||||
"adr_refs": list(self.adr_refs),
|
||||
}
|
||||
|
||||
|
||||
@dataclass(frozen=True, slots=True)
|
||||
class EgressVerdict:
|
||||
"""Composed egress verdict (ADR-0243 §2.3, corrected per pin SD-A).
|
||||
|
||||
``admitted`` = unit amplitude density + a converged certificate BOUND to
|
||||
this exact ψ (``certificate.psi_digest`` must match the presented state
|
||||
byte-for-byte; a borrowed certificate refuses as
|
||||
``certificate_state_mismatch``, so no proposal can pair a state with
|
||||
foreign convergence evidence). ``versor_closed`` (the ADR's R_GoldTether
|
||||
≤ ε) ROUTES — it is required on the crystallization path (only closed
|
||||
versors may SPECULATIVE-seal) and reported on all paths; demanding it of
|
||||
multi-mode superpositions would reject every legitimate interference
|
||||
state.
|
||||
"""
|
||||
|
||||
admitted: bool
|
||||
reason: str
|
||||
route: str # refused | readback_eligible | crystallization_proposal | hold
|
||||
unit_norm_residual: float
|
||||
versor_residual: float
|
||||
versor_closed: bool
|
||||
energy_class: EnergyClass
|
||||
energy_profile: EnergyProfile
|
||||
proposal: CrystallizationProposal | None
|
||||
|
||||
|
||||
def egress_gate(
|
||||
psi_steady: np.ndarray,
|
||||
certificate: RelaxationCertificate,
|
||||
*,
|
||||
epsilon_drift: float = _EPSILON_DRIFT,
|
||||
manifold: WaveManifold | None = None,
|
||||
operator: FieldEnergyOperator | None = None,
|
||||
**energy_kwargs: object,
|
||||
) -> EgressVerdict:
|
||||
"""Thermodynamic egress: admit → classify → route (E0/E1 cold, E3/E4 hot).
|
||||
|
||||
Structural energy axes (convergence, activation, aspect) are
|
||||
caller-supplied via ``energy_kwargs`` — never invented here; the
|
||||
coherence residual is measured on ψ by the energy boundary itself.
|
||||
Malformed states raise; legitimate bad states get ``admitted=False``.
|
||||
"""
|
||||
arr = _as_psi(psi_steady, "ψ_steady", error=EgressValidationError)
|
||||
m = manifold if manifold is not None else WaveManifold(epsilon_drift=float(epsilon_drift))
|
||||
unit_norm_residual = abs(float(np.linalg.norm(arr)) - 1.0)
|
||||
versor_residual = float(m.measure_unitary_residual(arr))
|
||||
versor_closed = versor_residual <= float(epsilon_drift)
|
||||
psi_dig = _psi_digest(arr)
|
||||
profile = energy_profile_from_wave(
|
||||
arr, operator=operator, manifold=m, epsilon_drift=float(epsilon_drift), **energy_kwargs
|
||||
)
|
||||
energy_class = profile.energy_class
|
||||
|
||||
if unit_norm_residual > float(epsilon_drift):
|
||||
admitted, reason = False, "amplitude_density_not_unit"
|
||||
elif psi_dig != certificate.psi_digest:
|
||||
admitted, reason = False, "certificate_state_mismatch"
|
||||
elif not certificate.converged:
|
||||
admitted, reason = False, f"relaxation_not_certified:{certificate.reason}"
|
||||
else:
|
||||
admitted, reason = True, "admitted"
|
||||
|
||||
proposal: CrystallizationProposal | None = None
|
||||
if not admitted:
|
||||
route = "refused"
|
||||
elif energy_class in (EnergyClass.E3, EnergyClass.E4):
|
||||
route = "readback_eligible"
|
||||
elif energy_class.vault_candidate:
|
||||
decision = crystallization_for_holographic_seal(
|
||||
arr,
|
||||
epsilon_drift=float(epsilon_drift),
|
||||
manifold=m,
|
||||
operator=operator,
|
||||
**energy_kwargs,
|
||||
)
|
||||
if decision.may_speculative_seal:
|
||||
route = "crystallization_proposal"
|
||||
proposal = CrystallizationProposal(
|
||||
proposal_id="crystal-"
|
||||
+ _content_id(
|
||||
{
|
||||
"psi": psi_dig,
|
||||
"certificate": certificate.certificate_id,
|
||||
"decision": decision.as_dict(),
|
||||
}
|
||||
),
|
||||
epistemic_status=_SPECULATIVE,
|
||||
psi_digest=psi_dig,
|
||||
certificate_id=certificate.certificate_id,
|
||||
decision=decision,
|
||||
)
|
||||
else:
|
||||
route = "hold" # cold but not crystalline (e.g. open superposition)
|
||||
else:
|
||||
route = "hold" # E2 mid-band: neither vault-cold nor readback-hot
|
||||
|
||||
return EgressVerdict(
|
||||
admitted=admitted,
|
||||
reason=reason,
|
||||
route=route,
|
||||
unit_norm_residual=unit_norm_residual,
|
||||
versor_residual=versor_residual,
|
||||
versor_closed=versor_closed,
|
||||
energy_class=energy_class,
|
||||
energy_profile=profile,
|
||||
proposal=proposal,
|
||||
)
|
||||
|
||||
|
||||
# --- Composed lifecycle ---------------------------------------------------------------
|
||||
|
||||
|
||||
@dataclass(frozen=True, slots=True)
|
||||
class LifecycleOutcome:
|
||||
ingress: IngressWavePacket
|
||||
relaxation: RelaxationResult
|
||||
verdict: EgressVerdict
|
||||
outcome_id: str = ""
|
||||
|
||||
def __post_init__(self) -> None:
|
||||
object.__setattr__(
|
||||
self,
|
||||
"outcome_id",
|
||||
_content_id(
|
||||
{
|
||||
"ingress": self.ingress.packet_digest,
|
||||
"certificate": self.relaxation.certificate.certificate_id,
|
||||
"route": self.verdict.route,
|
||||
"psi": _psi_digest(self.relaxation.psi_steady),
|
||||
}
|
||||
),
|
||||
)
|
||||
|
||||
|
||||
class CognitiveLifecycleEngine:
|
||||
"""Thin deterministic composer over the pure lifecycle functions.
|
||||
|
||||
Name matches the ADR §3 sketch for traceability; the implementation is
|
||||
the corrected one (pins SD-A/SD-B/SD-C; deviations D-1…D-5).
|
||||
"""
|
||||
|
||||
def __init__(self, *, epsilon_drift: float = _EPSILON_DRIFT) -> None:
|
||||
self.epsilon_drift = float(epsilon_drift)
|
||||
self.manifold = WaveManifold(epsilon_drift=self.epsilon_drift)
|
||||
|
||||
def ingest_context(self, packets: Sequence[PacketLike], domain_id: str) -> IngressWavePacket:
|
||||
return ingest_context(packets, domain_id)
|
||||
|
||||
def relax(
|
||||
self,
|
||||
ingress: IngressWavePacket,
|
||||
hamiltonian: ProblemHamiltonian,
|
||||
**kwargs: Any,
|
||||
) -> RelaxationResult:
|
||||
return relax_to_ground(ingress.psi, hamiltonian, **kwargs)
|
||||
|
||||
def egress(
|
||||
self,
|
||||
psi_steady: np.ndarray,
|
||||
certificate: RelaxationCertificate,
|
||||
**energy_kwargs: Any,
|
||||
) -> EgressVerdict:
|
||||
return egress_gate(
|
||||
psi_steady,
|
||||
certificate,
|
||||
epsilon_drift=self.epsilon_drift,
|
||||
manifold=self.manifold,
|
||||
**energy_kwargs,
|
||||
)
|
||||
|
||||
def solve(
|
||||
self,
|
||||
packets: Sequence[PacketLike],
|
||||
domain_id: str,
|
||||
hamiltonian: ProblemHamiltonian,
|
||||
*,
|
||||
dt: float = 1.0,
|
||||
max_steps: int = 512,
|
||||
tol: float = 1e-10,
|
||||
energy_inputs: Mapping[str, object] | None = None,
|
||||
) -> LifecycleOutcome:
|
||||
"""Ingress → relax → egress. Fail-closed at every stage (typed errors)."""
|
||||
ingress = self.ingest_context(packets, domain_id)
|
||||
result = relax_to_ground(ingress.psi, hamiltonian, dt=dt, max_steps=max_steps, tol=tol)
|
||||
verdict = self.egress(
|
||||
result.psi_steady, result.certificate, **dict(energy_inputs or {})
|
||||
)
|
||||
return LifecycleOutcome(ingress=ingress, relaxation=result, verdict=verdict)
|
||||
|
||||
|
||||
__all__ = [
|
||||
"CognitiveLifecycleEngine",
|
||||
"CognitiveLifecycleError",
|
||||
"CrystallizationProposal",
|
||||
"EgressValidationError",
|
||||
"EgressVerdict",
|
||||
"HamiltonianCompileError",
|
||||
"IngressDegenerate",
|
||||
"IngressWavePacket",
|
||||
"LifecycleOutcome",
|
||||
"ProblemHamiltonian",
|
||||
"PropositionalEntailmentVerdict",
|
||||
"PropositionalProblem",
|
||||
"RelaxationCertificate",
|
||||
"RelaxationInputError",
|
||||
"RelaxationNotConverged",
|
||||
"RelaxationNumericalFailure",
|
||||
"RelaxationResult",
|
||||
"assignment_component_index",
|
||||
"compile_propositional",
|
||||
"compile_quadratic_well",
|
||||
"egress_gate",
|
||||
"ingest_context",
|
||||
"propositional_entails",
|
||||
"relax_to_ground",
|
||||
"uniform_assignment_state",
|
||||
]
|
||||
|
|
@ -0,0 +1,309 @@
|
|||
# ADR-0243: Wave-Field Cognitive Lifecycle — Comprehension, Resonant Reasoning, and Lifelong Learning
|
||||
|
||||
**Status**: Proposed (acceptance path: benchmark evidence \+ Joshua review)
|
||||
**Date**: 2026-07-14
|
||||
**Deciders**: Joshua Shay \+ multi-model R\&D
|
||||
**Traceability**: Notion R\&D (Engineering Reference Vault Interconnection: `core_HA` Patterns)
|
||||
**Related**: ADR-0003, ADR-0006, ADR-0238, ADR-0239, ADR-0240, ADR-0241, ADR-0242, `core/physics/wave_manifold.py`
|
||||
**Canonical path**: `docs/adr/`
|
||||
|
||||
---
|
||||
|
||||
## 1\. Context and Problem Statement
|
||||
|
||||
With the successful unification of the **$Cl(4,1)$ Conformal Wave-Field ($\\psi$)** substrate ([ADR-0241](https://drive.google.com/file/d/1F_7QYtPysBP4qMbLGlGPnXgYx9IXug8nUYrpiCGSunE/view?usp=drivesdk)) and the implementation of the **Deterministic Fibonacci search** ([ADR-0242](https://drive.google.com/file/d/15_NECCPy-tEWGfYi_BNqawm8GytUTMkz1DsOqGVMXhI/view?usp=drivesdk)), CORE's physical layer has reached structural maturity.
|
||||
|
||||
However, we must now define how these new physical and geometric evolutions are leveraged to solve the fundamental cognitive tasks where traditional architectures struggle:
|
||||
|
||||
- **Comprehension & Ingress**: Traditional architectures parse and embed inputs into flat, context-dry vectors, leading to representation drift, attention decay over long contexts, and loss of structural relations.
|
||||
- **Problem Solving & Reasoning**: Traditional systems treat reasoning as probabilistic path-search or auto-regressive step generation. This lacks mathematical guarantees of correctness and suffers from cumulative error propagation.
|
||||
- **Egress & Generation**: Probabilistic autoregressive decoding selects discrete tokens one-by-one via softmax sampling, which has no global coherence guarantees, leading to hallucinations and semantic drift.
|
||||
- **Contemplation & Learning**: Standard models require gradient-descent backpropagation to update static weights, which is computationally expensive, non-reconstructible, and prone to catastrophic forgetting.
|
||||
|
||||
This ADR defines the complete **Wave-Field Cognitive Lifecycle**, leveraging the wave function to establish a fully deterministic, closed-loop, physical-relaxation-based paradigm for comprehension, reasoning, generation, and learning.
|
||||
|
||||
---
|
||||
|
||||
## 2\. Decision and Architectural Formulation
|
||||
|
||||
We dissolve the probabilistic, token-by-token paradigm of classical AI. We establish that **cognition is the continuous physical evolution, resonance, and relaxation of a Conformal Wave-Field ($\\psi$) across a single $Cl(4,1)$ geometric substrate**.
|
||||
|
||||
\[INGRESS\] \[REASONING\] \[EGRESS\]
|
||||
|
||||
Continuous Modalities Hamiltonian Well (H\_p) Thermodynamic State
|
||||
|
||||
| | |
|
||||
|
||||
v (Superposition) v (Physical Relaxation) v (Energy Class check)
|
||||
|
||||
Ingress Wave (psi\_in) \=======\> Steady State (psi\_final) \=======\> Linguistic Readback
|
||||
|
||||
^ ^ |
|
||||
|
||||
| (Resonant recall) | (Unitary update) v (GoldTether Gate)
|
||||
|
||||
Standing-Wave Atlas \<===================+===========================\> safe, aligned output
|
||||
|
||||
|
|
||||
|
||||
v (Verified holonomy R)
|
||||
|
||||
Biography update (R\_bio)
|
||||
|
||||
---
|
||||
|
||||
### 2.1 Ingress and Reading Comprehension: Wave Ingestion and Holomorphic Dispersion
|
||||
|
||||
Reading comprehension is modeled as **Wave-Packet Ingestion and Holomorphic Dispersion**, replacing flat token embeddings.
|
||||
|
||||
1. **Ingress Wave Packet**: An incoming text block, symbolic formula, or multimodal sensory stream is compiled into a localized, coherent wave packet $\\psi\_{ ext{context}}(X)$. This compilation preserves spatial-temporal phase relationships: $$\\psi\_{ ext{context}}(X) \= \\sum\_i c\_i \\psi\_{ ext{token}\_i}(X)$$
|
||||
2. **Holomorphic Dispersion**: As $\\psi\_{ ext{context}}$ is injected, it propagates through the `VocabManifold`. Proximity and meaning are not calculated via nearest-neighbor vector scans. Instead, the wave disperses and performs parallel cross-correlation with the registered standing-wave modes ${\\psi\_k}$ of the Hyperbolic Atlas, generating a spectrum of resonant coefficients: $$R\_k \= \\int\_M \\langle \\psi\_{ ext{context}}(X) \\widetilde{\\psi}\_k(X) angle\_0 dX$$ This represents the instant, parallel projection of the input context onto the entire known semantic manifold.
|
||||
|
||||
---
|
||||
|
||||
### 2.2 Reasoning and Problem Solving: Hamiltonian Well Relaxation
|
||||
|
||||
Problem-solving is re-engineered as a **Physical Wave-Field Relaxation Process**, replacing probabilistic step-by-step tree search.
|
||||
|
||||
1. **The Problem Hamiltonian**: The constraints and boundary conditions of a given problem (e.g. mathematical equalities, safety rules, or logical premises) are formulated as potential energy barriers or wells in a problem-specific Hamiltonian operator $\\mathcal{H}\_{ ext{problem}}$.
|
||||
2. **Relaxation to Eigenstates**: The ingress wave field $\\psi\_{ ext{context}}(X)$ is set as the initial state $\\psi(X, 0)$. The system is allowed to evolve under the Algebraic Schrödinger Equation: $$\\partial\_t \\psi \= \\mathcal{H}*{ ext{problem}}(\\psi) I$$ Through this evolution, the wave field naturally disperses away from high-potential barriers (representing logical contradictions or safety violations) and settles (relaxes) into the lowest-energy, stable standing-wave eigenmodes of the problem manifold: $$\\psi*{ ext{steady}}(X) \= \\lim\_{t o \\infty} \\exp\\left( \\mathcal{H}*{ ext{problem}} I t ight) \\psi*{ ext{context}}(X)$$ The resulting steady-state wave $\\psi\_{ ext{steady}}(X)$ represents the exact, geometrically congruent solution to the problem. It is mathematically guaranteed to satisfy all boundary conditions with zero room for intermediate fabrication.
|
||||
|
||||
---
|
||||
|
||||
### 2.3 Egress and Generative Articulation: Thermodynamic Wave Readback
|
||||
|
||||
We replace probabilistic softmax token generation with **Thermodynamic Wave Readback**, providing ironclad coherence guarantees.
|
||||
|
||||
1. **Thermodynamic Energy Classes**: The Field Energy Operator ($H$, defined in [ADR-0006](https://core-gitquarters.acbcontent.org/core-labs/core/src/branch/main/docs/adr/ADR-0006-field-energy-operator.md)) evaluates the "energy class" (E0 to E4) of the relaxed wave-field $\\psi\_{ ext{steady}}(X)$.
|
||||
- **E0/E1 (Crystalline/Stable)**: Represents cold, settled knowledge. It is bypassed for generation and vaulted into the sharded Delta-CRDT registers.
|
||||
- **E3/E4 (Hot/Critical)**: Indicates a high-activation, settled state that carries maximum semantic charge and "wants" to be articulated.
|
||||
2. **Linguistic Readback**: For E3/E4 states, the system invokes the readback rules of the active language pack (`en/readback_rules.py`, `he/readback_rules.py`, `el/readback_rules.py`). These rules map the geometric components—the principal bivector directions and scale-invariant parameters of the wave field—directly to symbolic tokens or motor commands.
|
||||
3. **GoldTether Gate**: Before any token or continuous action is permitted to exit the boundary, the **GoldTether unit residual** is evaluated: $$R\_{ ext{GoldTether}} \= \\sup\_{X \\in M} \\left| \\psi\_{ ext{steady}}(X) \\widetilde{\\psi}\_{ ext{steady}}(X) \- 1 ight|\_F \< 10^{-6}$$ If the generated state would introduce non-unitary drift (hallucination or ungrounded statements), the gate closes instantly, blocking the output and prompting a pre-ratified, safe fallback.
|
||||
|
||||
---
|
||||
|
||||
### 2.4 Speculative Contemplation and Non-Resonant Curiosity
|
||||
|
||||
Active thinking, self-reflection, and learning are modeled as **Speculative Contemplation and Non-Resonant Curiosity**, replacing classical gradient-descent backpropagation.
|
||||
|
||||
1. **Speculative Generation**: During idle cycles, the contemplation loop (`core/contemplation/runner.py`) speculatively generates wave-packets $\\psi\_{ ext{speculative}}(X)$ representing potential hypotheses or analogical transfers.
|
||||
2. **Orthogonal Surprise Check**: The non-resonant surprise residual of the speculative wave is evaluated: $$\\mathcal{S}(\\psi) \= \\psi\_{ ext{speculative}} \- \\mathcal{P}*{ ext{resonance}}(\\psi*{ ext{speculative}})$$
|
||||
- **Low Surprise**: The hypothesis is fully explained by the existing resonant schema. It is integrated immediately with no learning required.
|
||||
- **High Surprise (Discovery Signal)**: If $E\_{ ext{surprise}} \> \\gamma$, the speculative wave contains structural novelty. This signal is held as a `DiscoveryCandidate` and routed to the offline review corridor. It does *not* alter active knowledge but directs the self-authorship loop (`core/physics/self_authorship.py`) to generate a proposal to expand the active Hamiltonian $\\mathcal{H}$, enabling structured learning without catastrophic forgetting.
|
||||
|
||||
---
|
||||
|
||||
### 2.5 Lifelong Resonant Learning: Biography Holonomy Update
|
||||
|
||||
CORE-native learning is the permanent record of the entity's lived experiences as a sequence of geometric transformations.
|
||||
|
||||
Once a sequence of reasoning and action steps is validated (via the validation harness, [ADR-0240](https://drive.google.com/file/d/1eFNoXQl5BbUo6g4GBzRXi5tyIhT5RUGZQG6afaVXTg4/view?usp=drivesdk)), the exact unitary transformation $R \\in Spin(4,1)$ undergone by the wave-field is compiled into the **Biography Holonomy Blade** (`biography.py`): $$\\mathcal{H}*{ ext{bio}} \\leftarrow \\mathcal{H}*{ ext{bio}} \\cdot R$$ This is the ultimate, non-lossy, reconstruction-over-storage compilation of experience. It represents the "wisdom" of the entity, which can be replayed and audited byte-for-byte\!
|
||||
|
||||
---
|
||||
|
||||
## 3\. Implementation Specification (The Cognitive Relaxation Loop)
|
||||
|
||||
Below is the Python prototype implementing wave-field ingestion, Hamiltonian well relaxation (problem-solving), and the GoldTether egress gate inside the active reasoning pipeline.
|
||||
|
||||
\# core/physics/cognitive\_lifecycle.py
|
||||
|
||||
from \_\_future\_\_ import annotations
|
||||
|
||||
import numpy as np
|
||||
|
||||
import scipy.linalg as la
|
||||
|
||||
from dataclasses import dataclass
|
||||
|
||||
from typing import Callable, Tuple
|
||||
|
||||
N\_COMPONENTS \= 32
|
||||
|
||||
@dataclass(frozen=True, slots=True)
|
||||
|
||||
class IngressWavePacket:
|
||||
|
||||
psi: np.ndarray \# 32-vector coefficients
|
||||
|
||||
domain\_id: str
|
||||
|
||||
@dataclass(frozen=True, slots=True)
|
||||
|
||||
class EgressVerdict:
|
||||
|
||||
admitted: bool
|
||||
|
||||
wave\_out: np.ndarray
|
||||
|
||||
residual: float
|
||||
|
||||
message: str
|
||||
|
||||
class CognitiveLifecycleEngine:
|
||||
|
||||
def \_\_init\_\_(self, epsilon\_drift: float \= 1e-6):
|
||||
|
||||
self.epsilon\_drift \= epsilon\_drift
|
||||
|
||||
self.I \= np.zeros((N\_COMPONENTS, N\_COMPONENTS))
|
||||
|
||||
\# Central pseudoscalar proxy
|
||||
|
||||
for i in range(N\_COMPONENTS // 2):
|
||||
|
||||
self.I\[2\*i, 2\*i+1\] \= 1.0
|
||||
|
||||
self.I\[2\*i+1, 2\*i\] \= \-1.0
|
||||
|
||||
def ingest\_context(self, tokens: list\[np.ndarray\], domain\_id: str) \-\> IngressWavePacket:
|
||||
|
||||
"""
|
||||
|
||||
Compiles discrete symbolic token wave-packets into a superposed,
|
||||
|
||||
coherent IngressWavePacket.
|
||||
|
||||
"""
|
||||
|
||||
psi\_sum \= np.zeros(N\_COMPONENTS, dtype=np.float64)
|
||||
|
||||
for t in tokens:
|
||||
|
||||
arr \= np.asarray(t, dtype=np.float64)
|
||||
|
||||
psi\_sum \+= arr
|
||||
|
||||
\# Normalize to preserve unitary probability amplitude
|
||||
|
||||
norm \= np.linalg.norm(psi\_sum)
|
||||
|
||||
psi\_norm \= (psi\_sum / norm) if norm \> 1e-12 else psi\_sum
|
||||
|
||||
return IngressWavePacket(psi=psi\_norm, domain\_id=domain\_id)
|
||||
|
||||
def solve\_via\_relaxation(
|
||||
|
||||
self,
|
||||
|
||||
ingress: IngressWavePacket,
|
||||
|
||||
H\_problem: np.ndarray,
|
||||
|
||||
relaxation\_steps: int \= 100,
|
||||
|
||||
dt: float \= 0.01
|
||||
|
||||
) \-\> np.ndarray:
|
||||
|
||||
"""
|
||||
|
||||
Solves a problem via continuous wave-field relaxation.
|
||||
|
||||
The wave relaxes into the minimum-energy eigenstate of H\_problem.
|
||||
|
||||
"""
|
||||
|
||||
psi \= ingress.psi.copy()
|
||||
|
||||
\# Schrödinger propagator: R \= exp(H\_problem \* I \* dt)
|
||||
|
||||
generator \= np.dot(H\_problem, self.I)
|
||||
|
||||
R \= la.expm(generator \* dt)
|
||||
|
||||
|
||||
|
||||
\# Relaxation loop (Euler/exponential integrator)
|
||||
|
||||
for \_ in range(relaxation\_steps):
|
||||
|
||||
psi \= np.dot(R, psi)
|
||||
|
||||
\# Enforce the null-cone amplitude normalization step
|
||||
|
||||
norm \= np.linalg.norm(psi)
|
||||
|
||||
if norm \> 1e-12:
|
||||
|
||||
psi /= norm
|
||||
|
||||
|
||||
|
||||
return psi
|
||||
|
||||
def egress\_gate(self, psi\_steady: np.ndarray) \-\> EgressVerdict:
|
||||
|
||||
"""
|
||||
|
||||
Unitary GoldTether egress gate: blocks non-unitary/hallucinated
|
||||
|
||||
wave-states from entering the readback and serving paths.
|
||||
|
||||
"""
|
||||
|
||||
psi\_arr \= np.asarray(psi\_steady, dtype=np.float64)
|
||||
|
||||
\# Unitary residual check: || psi \* rev(psi) \- 1 ||\_F
|
||||
|
||||
\# rev(psi) proxied via conjugate transpose under I-metric
|
||||
|
||||
psi\_rev \= np.dot(self.I.T, psi\_arr)
|
||||
|
||||
norm\_product \= np.dot(psi\_arr.T, psi\_rev)
|
||||
|
||||
drift \= np.abs(norm\_product \- 1.0)
|
||||
|
||||
|
||||
|
||||
if drift \> self.epsilon\_drift:
|
||||
|
||||
return EgressVerdict(
|
||||
|
||||
admitted=False,
|
||||
|
||||
wave\_out=np.zeros\_like(psi\_arr),
|
||||
|
||||
residual=float(drift),
|
||||
|
||||
message="REJECTED: Unitary propagator drift exceeds epsilon\_drift limit (ungrounded state)."
|
||||
|
||||
)
|
||||
|
||||
|
||||
|
||||
return EgressVerdict(
|
||||
|
||||
admitted=True,
|
||||
|
||||
wave\_out=psi\_arr,
|
||||
|
||||
residual=float(drift),
|
||||
|
||||
message="ADMITTED: Wave-field verified and promoted to readback path."
|
||||
|
||||
)
|
||||
|
||||
---
|
||||
|
||||
## 4\. Consequences and Gating Rules
|
||||
|
||||
### 4.1 Benefits
|
||||
|
||||
- **Autoregressive Hallucination Eliminated**: By replacing step-by-step probabilistic token sampling with physical wave relaxation, output generation is strictly constrained by the geometry of the problem Hamiltonian.
|
||||
- **Zero Coordinate Loss**: Resonant standing-wave lock-in ensures that recalled memories are mathematically exact, preventing the fuzzy centroid degradation of legacy architectures.
|
||||
- **Topologically Protected Wisdom**: Experience is compiled directly into the Biography Holonomy Blade as unitary rotor products, providing an untamperable, replayable audit trail of lifelong learning.
|
||||
|
||||
### 4.2 Gating Rules
|
||||
|
||||
- **No Direct Hot-Path Promotion**: Reconstructed wave-fields or proposed Hamiltonian adjustments from the self-authorship loop (`core/physics/self_authorship.py`) must never bypass the one-mutation-path. Speculative changes must reside strictly within the `evals/` and `calibration/` quarantine zones until ratified by a signed human certificate.
|
||||
|
||||
---
|
||||
|
||||
## 5\. References
|
||||
|
||||
1. `docs/adr/ADR-0003-coordinate-system-dissolution.md` — Relational fields replacing coordinate frames.
|
||||
2. `docs/adr/ADR-0238-GoldTether-Modulated-Supervised-Autonomy.md` — GoldTether residual monitoring.
|
||||
3. `docs/adr/ADR-0239-Conformal-Procrustes-Surprise-Dual-Operator.md` — Conformal Procrustes and surprise.
|
||||
4. `docs/adr/ADR-0241-wave-field-driven-hyperbolic-atlas-and-resonant-cognition.md` — Continuous wave-field framework.
|
||||
5. `docs/adr/ADR-0242-deterministic-fibonacci-operators-and-evidence-gated-optimization.md` — Fibonacci search contract.
|
||||
|
||||
|
|
@ -78,7 +78,7 @@ GitHub Actions became billing-locked (~$6, account-level) mid-arc, forcing a piv
|
|||
## Current state (2026-07-16)
|
||||
|
||||
- Both ADRs: **Accepted**, ratified, full audit trail.
|
||||
- `main` was @ `18d3c70d` at arc close; post-Accept backlog follow-through is on `feat/adr-0241-0242-implementation` (tip includes `d388fc9e` feature commit + status notes; local-first validation; merge when ready).
|
||||
- Post-Accept backlog **merged**: PR #55 (`d388fc9e` feature commit + status notes) landed on `main` @ `19819194`; all `[Verification]` numbers were independently reproduced by the 2026-07-16 audit (smoke 176; fast lane 11709 passed / 108 skipped; f64 parity 21/21 incl. Rust-path; invariants+demos+A-04 140). Three seam-vs-integration caveats carried into the ADR-0243 arc — see `docs/plans/adr-0243-implementation-plan.md` §1.
|
||||
- CI: **local-first is the real merge gate** (no Docker CI for merge); `uv.lock` committed and locked installs enforced in workflows; optional Mac Act runner must be `ubuntu-latest:host` (native), not `docker://…`.
|
||||
|
||||
## Remaining backlog (post-Accept follow-through; 2026-07-16 mastery close)
|
||||
|
|
|
|||
172
docs/plans/adr-0243-implementation-plan.md
Normal file
172
docs/plans/adr-0243-implementation-plan.md
Normal file
|
|
@ -0,0 +1,172 @@
|
|||
# ADR-0243 Implementation Plan — Wave-Field Cognitive Lifecycle
|
||||
|
||||
**Status**: Approved by Shay 2026-07-16 (plan-of-record for the 0243 arc)
|
||||
**Authority docs**: `docs/adr/ADR-0243-wave-field-cognitive-lifecycle-comprehension-reasoning-and-resonant-learning.md` (Proposed), `docs/analysis/core_cohesion_master_plan.md` (canonical, doctrine-annotated)
|
||||
**Related**: ADR-0006, ADR-0055, ADR-0145, ADR-0238, ADR-0239, ADR-0240, ADR-0241, ADR-0242
|
||||
**Prior-arc record**: `docs/plans/adr-0241-0242-mastery-close-status.md`
|
||||
|
||||
---
|
||||
|
||||
## 1. Inputs carried from the ADR-0241/0242 close audit (2026-07-16)
|
||||
|
||||
The independent audit of PR #55 confirmed the 0241/0242 close as genuine, with three
|
||||
seam-vs-integration caveats that this arc must resolve or consciously inherit:
|
||||
|
||||
1. **D9 "f64 GP parity" is a Python-SOT freeze, not cross-implementation parity.**
|
||||
No Rust f64 geometric product exists. All f64 wave-field math stays in Python
|
||||
until a `geometric_product_f64` PyO3 export is built *and* parity-gated.
|
||||
Consequence here: the ADR-0243 relaxer is pure-Python f64 by doctrine, and the
|
||||
master plan's §5 Rust bindings are **deferred** (see §7 below).
|
||||
2. **The ADR-0242 §5 carry seams have zero live call sites.** `kappa_search_event`
|
||||
(goldtether) and `cross_band_discovery_gate` (multi_scale_energy) are tested
|
||||
primitives that nothing live invokes. Phase 3 Lane A wires them.
|
||||
3. **The I-04 real-compiler sensorium feed is test-only** (correct per A-04
|
||||
quarantine) and the audio versor is float32-origin upcast to f64. Phase 3
|
||||
Lane B gives the feed its first (off-serving) consumer.
|
||||
|
||||
## 2. Substrate inventory — what exists vs. what this arc builds
|
||||
|
||||
Already landed (verified on `main` @ `19819194`):
|
||||
|
||||
| Lifecycle stage | Existing organ |
|
||||
| --- | --- |
|
||||
| §2.1 ingress superposition | `core/physics/sensorium_wave_feed.py` (`ModalityPacket`, `compile_packet_to_psi`, `superpose_packets`, `phase_correlate`) |
|
||||
| §2.1 resonant projection R_k | `WaveManifold.phase_correlation` / `resonant_recall` / `resonant_reconstruct` |
|
||||
| §2.3 energy classes E0–E4 | `core/physics/energy.py` (`EnergyClass`, `FieldEnergyOperator`; ADR-0006) |
|
||||
| §2.3 readback rules | `packs/en/readback_rules.py` (ADR-0145 energy-modulated readback) |
|
||||
| §2.3 GoldTether residual | `core/physics/goldtether.py` (`coherence_residual`, `GoldTetherMonitor`) + `WaveManifold.measure_unitary_residual` |
|
||||
| §2.4 surprise + γ check | `core/physics/surprise.py` (`surprise_residual`, `is_discovery_eligible`, `dual_operator`; ADR-0239) |
|
||||
| §2.4 discovery plumbing | `core/contemplation/runner.py` already accepts a `DiscoveryCandidateSink`; `teaching/discovery.py` `DiscoveryCandidate` (ADR-0055 Phase B) |
|
||||
| §2.4 self-authorship | `core/physics/self_authorship.py` (`SelfAuthorshipMiner`, I-03 pinned speculative-only) |
|
||||
| §2.5 biography holonomy | `core/physics/biography.py` (`integrate_biography`, `reconstruct_biography`) — **no live call sites yet** |
|
||||
| I-01…I-05, A-02/A-04, `core_ha` absence | `tests/test_third_door_cohesion.py` (master plan §3/§8 already pinned; §7 `core_ha` migration is **moot** — package absent and test-pinned) |
|
||||
|
||||
Genuinely unbuilt: the §2.2 relaxation reasoner (`cognitive_lifecycle.py`), the
|
||||
inter-organ wiring (three lanes), and the §4 falsifiability benchmarks.
|
||||
|
||||
## 3. Sketch-defect ledger (ADR §3 reference prototype)
|
||||
|
||||
Pinned executable in `tests/test_adr_0243_sketch_defect_pins.py`; the reference
|
||||
prototype must **never** be ported verbatim (precedent: PR #52 sketch-defect pins).
|
||||
|
||||
- **SD-A — the sketch egress gate always rejects.** It computes
|
||||
`drift = |ψᵀIᵀψ − 1|` with `I` antisymmetric; `ψᵀIᵀψ ≡ 0` identically, so
|
||||
`drift ≡ 1 > ε` for *every* state, valid or not. A fail-always gate is the
|
||||
inverse of a hollow gate and equally worthless. The real residual already
|
||||
exists: `WaveManifold.measure_unitary_residual` / `goldtether.coherence_residual`.
|
||||
- **SD-B — the sketch "relaxation" cannot relax.** Iterating
|
||||
`R = expm(H·I·dt)` with renormalization does not settle into the minimum-energy
|
||||
eigenmode: the generator's spectrum is (block-wise) purely imaginary, so the
|
||||
iterates oscillate and preserve mode magnitudes; nothing dissipates. Relaxation
|
||||
to the ground state requires the **dissipative (imaginary-time) semigroup**
|
||||
`ψ ← normalize(exp(−H·dt)·ψ)` — deterministic power iteration converging at a
|
||||
rate set by the spectral gap of H.
|
||||
- **SD-C — the sketch's block matrix "I" is not the Cl(4,1) pseudoscalar action.**
|
||||
It shares the property I² = −Id but is a different operator from
|
||||
left-multiplication by e₀e₁e₂e₃e₄ in the real algebra. All algebra goes
|
||||
through `algebra/` — no bespoke component-shuffling proxies.
|
||||
|
||||
## 4. Deviations ledger (implementation vs. ADR prose — for the acceptance packet)
|
||||
|
||||
- **D-1 imaginary-time relaxer** replaces the sketch's `exp(H·I·t)` loop (SD-B).
|
||||
Implemented via `np.linalg.eigh` on symmetric H: `exp(−H·dt) = Q·exp(−Λ·dt)·Qᵀ`,
|
||||
pure numpy f64, no scipy dependency added.
|
||||
- **D-2 honest guarantee restatement.** The ADR's "mathematically guaranteed …
|
||||
zero room for intermediate fabrication" is conditional: it holds only insofar
|
||||
as (a) the Hamiltonian compiler encodes the constraints faithfully, (b) the
|
||||
ground state is separated by a positive spectral gap, and (c) the iteration has
|
||||
converged (certified, not assumed). The acceptance packet states it this way.
|
||||
- **D-3 I-05 reconciliation.** Relaxation is *deliberately non-unitary* inside
|
||||
the off-serving solver — that is what dissipation is. I-05 (amplitude
|
||||
conservation) governs live serve-path transitions; the relaxer's terminal
|
||||
normalize is an **owned construction boundary** per the master plan's
|
||||
doctrine note (no hot-path drift repair; breaches at the boundary fail closed).
|
||||
- **D-4 R-02 premise retired at v1 scale.** `expm` of a 32×32 symmetric matrix
|
||||
in numpy is trivial; no Rust port is needed or permitted (caveat 1) for v1.
|
||||
- **D-5 E0/E1 crystallization is proposal-only.** No vault writes from the
|
||||
lifecycle; cold states emit a typed crystallization *proposal artifact*
|
||||
through the one-mutation-path (I-03), never a direct `COHERENT` write.
|
||||
|
||||
## 5. Phases
|
||||
|
||||
- **Phase 0 — Governance + doc hygiene** (this PR): commit ADR-0243 verbatim as
|
||||
Proposed; sketch-defect pins; `*.gdoc` gitignored; stale prior-arc status line
|
||||
fixed; this plan committed. Local strays (research-copy duplicates,
|
||||
`core-rs/uv.lock`) removed from the working tree.
|
||||
- **Phase 1 — merged into Phase 0** (pins land with the plan).
|
||||
- **Phase 2 — flagship `core/physics/cognitive_lifecycle.py`** (1 PR): Tier-2
|
||||
off-serving (A-04 list + lazy barrel + transitive guard). Typed
|
||||
content-addressed `ProblemHamiltonian` compiler for two checkable domains only
|
||||
(propositional penalty projectors; convex quadratic). Imaginary-time relaxer
|
||||
(D-1) with convergence certificate (eigen-residual + gap estimate) and typed
|
||||
fail-closed errors. Egress verdict composing `measure_unitary_residual` +
|
||||
`coherence_residual` + `EnergyClass` routing (E0/E1 → proposal artifact per
|
||||
D-5; E3/E4 → readback-eligible). Ingress delegates to `sensorium_wave_feed` /
|
||||
`WaveManifold` — no duplication. TDD; ground-state property test vs. direct
|
||||
eigensolve; determinism digests.
|
||||
- *Phase 2 verification record:* adversarial finder/verifier workflow over
|
||||
the module (most verify agents were lost to a session limit; every
|
||||
surviving finding was reproduced in-tree before acting). Two hardenings
|
||||
landed beyond the plan text: (1) `RelaxationCertificate.psi_digest` binds
|
||||
convergence evidence to the exact certified state and `egress_gate`
|
||||
refuses borrowed certificates (`certificate_state_mismatch`) — closes a
|
||||
false-provenance `CrystallizationProposal`; (2) certification additionally
|
||||
requires the spectral gap be resolvable at the requested tolerance
|
||||
(excited weight ≤ (E−λ0)/gap ≤ tol, refusal
|
||||
`spectral_gap_below_tolerance`), and the degeneracy cluster is capped at
|
||||
the acceptance window so the certificate reports the honest rate-limiting
|
||||
gap — closes a zero-ground-overlap mis-certification reachable at loose
|
||||
`tol`. Dense-branch refusals, the E2 hold route, iterate-collapse, and
|
||||
hardcoded canonical entailment verdicts are pinned in tests.
|
||||
- **Phase 3 — wiring lanes** (three independent PRs after Phase 2 API lands):
|
||||
- **Lane A (§2.4; closes caveat 2):** wire `is_discovery_eligible` +
|
||||
`cross_band_discovery_gate` into the contemplation runner's existing sink;
|
||||
high-surprise speculative packets emit `DiscoveryCandidate`s
|
||||
(proposal-only). Give `kappa_search_event` its live telemetry call site at
|
||||
the κ line-search (calibration-gated per R-04).
|
||||
- **Lane B (§2.1→§2.3; closes caveat 3):** off-serving corridor in `evals/`:
|
||||
real Audio/Vision compilers → ψ_in → relaxation → E-class → `en` readback
|
||||
rules → GoldTether gate. First live consumer of the I-04 feed.
|
||||
- **Lane C (§2.5):** ADR-0240 validation-harness PASS →
|
||||
`integrate_biography`, with I-01 closure asserts and provenance recording.
|
||||
- **Phase 4 — falsifiability benchmarks** (1 PR):
|
||||
`evals/adr_0243_cognitive_lifecycle/` fixed-replay eval
|
||||
(`adr_0242_v2_energy_compare` pattern): fidelity score, surprise separation
|
||||
(ID vs OOD), insertion cost, f32 drift over T=1000, typed failure thresholds.
|
||||
**Decisive falsifier:** a propositional slice scored against
|
||||
`evals/deductive_logic` ROBDD gold with wrong=0 accounting. "Field engine is
|
||||
NOT the reasoner today" stands unless this evidence says otherwise.
|
||||
- **Phase 5 — acceptance packet** (1 PR): D10-pattern packet — claims vs.
|
||||
evidence, deviations D-1…D-5, deferred items — for Joshua's ruling. Status
|
||||
flip via governance commit only (provenance-guard compliant).
|
||||
|
||||
## 6. Dependencies and process
|
||||
|
||||
Phase 2 precedes 3/4; Lanes A/B/C are mutually independent; Phase 5 last.
|
||||
Every PR: dedicated worktree off `forgejo/main`, in-worktree smoke gate
|
||||
(`uv run core test --suite smoke -q`) before push, `[Verification]:` line in the
|
||||
PR description, Forgejo MCP for PR operations (no `gh`, no `tea`), stacked
|
||||
merges substrate-first, merged branches + worktrees deleted immediately.
|
||||
Lane briefs for Phase 3 are written at Phase 2 completion (production-line
|
||||
pattern, `docs/handoff/`); dispatch is Shay's call.
|
||||
|
||||
## 7. Explicitly deferred (not in this arc)
|
||||
|
||||
- Master plan §5 Rust bindings (`cl41::wedge` exists; `expm`/`versor_unit_residual`
|
||||
SIMD do not) — blocked on a Rust f64 GP + D9-style parity gate (caveat 1).
|
||||
- MLX / Apple-UMA lanes — aspirational prose; no benchmark evidence.
|
||||
- Delta-CRDT multi-writer vault — behind the multi-writer gate (PR #42 ruling).
|
||||
- `he`/`el` readback rules — packs are skeletal; `en` only for the corridor.
|
||||
- Any serve-path activation of lifecycle machinery — A-04 quarantine holds
|
||||
until ratification.
|
||||
|
||||
## 8. Risks
|
||||
|
||||
- **H-compiler scope explosion** → v1 fixed at two typed domains; extensions
|
||||
require new evidence, not new matchers (ADR-0175 discipline).
|
||||
- **Reasoner overclaim / thesis drift** → the Phase 4 wrong=0 ROBDD cross-check
|
||||
is the gate; disagreements fail the run and go in the packet verbatim.
|
||||
- **Hollow gates in egress wiring** → every gate ships with a must-reject test
|
||||
(and SD-A shows the dual failure mode: a gate that rejects everything).
|
||||
- **I-05 doctrinal tension** → D-3 reconciliation text; normalize only at the
|
||||
owned construction boundary; boundary breaches fail closed, never repaired.
|
||||
662
tests/test_adr_0243_cognitive_lifecycle.py
Normal file
662
tests/test_adr_0243_cognitive_lifecycle.py
Normal file
|
|
@ -0,0 +1,662 @@
|
|||
"""ADR-0243 §2 cognitive lifecycle — ingress → relaxation → egress (Tier-2).
|
||||
|
||||
Authority: docs/plans/adr-0243-implementation-plan.md §5 Phase 2.
|
||||
Companion pins: tests/test_adr_0243_sketch_defect_pins.py (SD-A/SD-B/SD-C).
|
||||
|
||||
Gold is INDEPENDENT of the module under test: propositional truth is a
|
||||
truth-table evaluator written here; ground states are cross-checked against
|
||||
direct spectral projection. Deterministic fixtures only — no random spinors.
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import ast
|
||||
import hashlib
|
||||
import json
|
||||
import subprocess
|
||||
import sys
|
||||
from pathlib import Path
|
||||
|
||||
import numpy as np
|
||||
import pytest
|
||||
|
||||
from algebra.cl41 import N_COMPONENTS
|
||||
from algebra.rotor import make_rotor_from_angle
|
||||
from core.physics.cognitive_lifecycle import (
|
||||
CognitiveLifecycleEngine,
|
||||
CognitiveLifecycleError,
|
||||
CrystallizationProposal,
|
||||
EgressValidationError,
|
||||
HamiltonianCompileError,
|
||||
IngressDegenerate,
|
||||
ProblemHamiltonian,
|
||||
PropositionalProblem,
|
||||
RelaxationInputError,
|
||||
RelaxationNotConverged,
|
||||
RelaxationNumericalFailure,
|
||||
assignment_component_index,
|
||||
compile_propositional,
|
||||
compile_quadratic_well,
|
||||
egress_gate,
|
||||
ingest_context,
|
||||
propositional_entails,
|
||||
relax_to_ground,
|
||||
uniform_assignment_state,
|
||||
)
|
||||
from core.physics.sensorium_wave_feed import fake_deterministic_packet
|
||||
from core.physics.wave_energy_boundary import crystallization_for_holographic_seal
|
||||
from core.physics.wave_manifold import WaveManifold
|
||||
|
||||
_ROOT = Path(__file__).resolve().parents[1]
|
||||
|
||||
|
||||
def _onehot(i: int) -> np.ndarray:
|
||||
v = np.zeros(N_COMPONENTS, dtype=np.float64)
|
||||
v[i] = 1.0
|
||||
return v
|
||||
|
||||
|
||||
def _unit(v: np.ndarray) -> np.ndarray:
|
||||
return v / np.linalg.norm(v)
|
||||
|
||||
|
||||
# --- Independent gold ---------------------------------------------------------
|
||||
|
||||
|
||||
def _truth_table_counts(atoms, clauses) -> list[int]:
|
||||
"""Clauses falsified per assignment mask — independent of the module."""
|
||||
index = {a: i for i, a in enumerate(atoms)}
|
||||
counts = []
|
||||
for mask in range(1 << len(atoms)):
|
||||
c = 0
|
||||
for clause in clauses:
|
||||
if not any(bool(mask >> index[a] & 1) == pol for a, pol in clause):
|
||||
c += 1
|
||||
counts.append(c)
|
||||
return counts
|
||||
|
||||
|
||||
def _entails_gold(atoms, premises, conclusion) -> bool:
|
||||
"""Semantic entailment by truth table — independent of the module."""
|
||||
index = {a: i for i, a in enumerate(atoms)}
|
||||
for mask in range(1 << len(atoms)):
|
||||
model = all(
|
||||
any(bool(mask >> index[a] & 1) == pol for a, pol in clause)
|
||||
for clause in premises
|
||||
)
|
||||
if model and not any(
|
||||
bool(mask >> index[a] & 1) == pol for a, pol in conclusion
|
||||
):
|
||||
return False
|
||||
return True
|
||||
|
||||
|
||||
_ATOMS3 = ("a", "b", "c")
|
||||
_PREMISES3 = (
|
||||
(("a", True), ("b", True)),
|
||||
(("a", False), ("c", True)),
|
||||
(("b", False), ("c", True)),
|
||||
)
|
||||
|
||||
|
||||
# --- Blade lattice ↔ assignment lattice ----------------------------------------
|
||||
|
||||
|
||||
def test_assignment_component_map_is_bijective_and_grade_consistent():
|
||||
indices = [assignment_component_index(m) for m in range(32)]
|
||||
assert sorted(indices) == list(range(32))
|
||||
assert assignment_component_index(0) == 0 # ∅ ↔ scalar
|
||||
for i in range(5):
|
||||
assert assignment_component_index(1 << i) == 1 + i # {e_i} ↔ vector slot
|
||||
assert assignment_component_index(0b11111) == 31 # full set ↔ pseudoscalar
|
||||
|
||||
|
||||
def test_assignment_component_index_out_of_range_refused():
|
||||
with pytest.raises(HamiltonianCompileError):
|
||||
assignment_component_index(32)
|
||||
|
||||
|
||||
# --- Ingress --------------------------------------------------------------------
|
||||
|
||||
|
||||
def test_ingest_context_superposes_normalizes_and_digests():
|
||||
packets = [
|
||||
fake_deterministic_packet("audio", angle=0.3, plane=6),
|
||||
fake_deterministic_packet("vision", angle=0.4, plane=7),
|
||||
]
|
||||
ingress = ingest_context(packets, "demo")
|
||||
assert abs(float(np.linalg.norm(ingress.psi)) - 1.0) < 1e-12
|
||||
assert ingress.modality_ids == ("audio", "vision")
|
||||
again = ingest_context(packets, "demo")
|
||||
assert ingress.packet_digest == again.packet_digest
|
||||
assert np.array_equal(ingress.psi, again.psi)
|
||||
with pytest.raises(ValueError):
|
||||
ingress.psi[0] = 5.0 # frozen read-only field
|
||||
|
||||
|
||||
def test_ingest_context_refuses_empty_and_degenerate():
|
||||
with pytest.raises(ValueError):
|
||||
ingest_context([], "demo") # delegation: superpose_packets refuses empty
|
||||
p = fake_deterministic_packet("audio")
|
||||
anti = {"modality_id": "anti", "coefficients": -p.coefficients}
|
||||
with pytest.raises(IngressDegenerate):
|
||||
ingest_context([p, anti], "demo") # destructive cancellation
|
||||
with pytest.raises(IngressDegenerate):
|
||||
ingest_context([p], " ") # empty domain id
|
||||
|
||||
|
||||
# --- Hamiltonian compilers -------------------------------------------------------
|
||||
|
||||
|
||||
def test_quadratic_well_spectrum_and_refusals():
|
||||
target = _onehot(0)
|
||||
ham = compile_quadratic_well(target, curvature=2.0)
|
||||
evals, evecs = np.linalg.eigh(ham.matrix)
|
||||
assert abs(evals[0]) < 1e-12
|
||||
assert np.allclose(evals[1:], 2.0, atol=1e-12)
|
||||
assert abs(abs(float(evecs[:, 0] @ target)) - 1.0) < 1e-9
|
||||
with pytest.raises(HamiltonianCompileError):
|
||||
compile_quadratic_well(2.0 * target) # non-unit target — no repair
|
||||
with pytest.raises(HamiltonianCompileError):
|
||||
compile_quadratic_well(target, curvature=0.0)
|
||||
bad = target.copy()
|
||||
bad[3] = np.nan
|
||||
with pytest.raises(HamiltonianCompileError):
|
||||
compile_quadratic_well(bad)
|
||||
|
||||
|
||||
def test_problem_hamiltonian_validation_and_immutability():
|
||||
asym = np.zeros((N_COMPONENTS, N_COMPONENTS))
|
||||
asym[0, 1] = 1.0
|
||||
with pytest.raises(HamiltonianCompileError):
|
||||
ProblemHamiltonian(matrix=asym, domain="test")
|
||||
with pytest.raises(HamiltonianCompileError):
|
||||
ProblemHamiltonian(matrix=np.eye(16), domain="test") # wrong shape
|
||||
nan_mat = np.eye(N_COMPONENTS)
|
||||
nan_mat[4, 4] = np.nan
|
||||
with pytest.raises(HamiltonianCompileError):
|
||||
ProblemHamiltonian(matrix=nan_mat, domain="test")
|
||||
ham = ProblemHamiltonian(matrix=np.eye(N_COMPONENTS), domain="test")
|
||||
assert ham.is_diagonal
|
||||
assert ham.hamiltonian_id
|
||||
with pytest.raises(ValueError):
|
||||
ham.matrix[0, 0] = 9.0 # read-only
|
||||
dense = compile_quadratic_well(_unit(_onehot(0) + _onehot(6)))
|
||||
assert not dense.is_diagonal
|
||||
|
||||
|
||||
def test_propositional_diag_matches_independent_truth_table_gold():
|
||||
problem = PropositionalProblem(atoms=_ATOMS3, clauses=_PREMISES3)
|
||||
ham = compile_propositional(problem, penalty=1.0)
|
||||
assert ham.is_diagonal
|
||||
diag = np.diagonal(ham.matrix)
|
||||
gold = _truth_table_counts(_ATOMS3, _PREMISES3)
|
||||
mapped = set()
|
||||
for mask, count in enumerate(gold):
|
||||
idx = assignment_component_index(mask)
|
||||
mapped.add(idx)
|
||||
assert diag[idx] == float(count)
|
||||
out_of_domain = 1.0 * (len(_PREMISES3) + 1)
|
||||
for idx in set(range(N_COMPONENTS)) - mapped:
|
||||
assert diag[idx] == out_of_domain
|
||||
|
||||
|
||||
def test_propositional_problem_validation():
|
||||
with pytest.raises(HamiltonianCompileError):
|
||||
PropositionalProblem(atoms=("a",) * 6, clauses=()) # >5 and duplicate
|
||||
with pytest.raises(HamiltonianCompileError):
|
||||
PropositionalProblem(atoms=("a", "a"), clauses=())
|
||||
with pytest.raises(HamiltonianCompileError):
|
||||
PropositionalProblem(atoms=("a",), clauses=((),)) # empty clause
|
||||
with pytest.raises(HamiltonianCompileError):
|
||||
PropositionalProblem(atoms=("a",), clauses=((("z", True),),))
|
||||
with pytest.raises(HamiltonianCompileError):
|
||||
PropositionalProblem(atoms=("a",), clauses=((("a", True), ("a", True)),))
|
||||
p1 = PropositionalProblem(atoms=("a", "b"), clauses=((("a", True),),))
|
||||
p2 = PropositionalProblem(atoms=("a", "b"), clauses=((("b", True),),))
|
||||
assert p1.problem_id and p1.problem_id != p2.problem_id
|
||||
with pytest.raises(HamiltonianCompileError):
|
||||
compile_propositional(p1, penalty=-1.0)
|
||||
|
||||
|
||||
# --- Relaxation --------------------------------------------------------------------
|
||||
|
||||
|
||||
def test_relaxation_decodes_quadratic_well_target_dense_path():
|
||||
target = np.asarray(make_rotor_from_angle(0.3, bivector_idx=6), dtype=np.float64)
|
||||
ham = compile_quadratic_well(target, curvature=1.0)
|
||||
psi0 = _unit(target + 0.5 * _onehot(2) + 0.3 * _onehot(9))
|
||||
result = relax_to_ground(psi0, ham)
|
||||
cert = result.certificate
|
||||
assert cert.converged and cert.reason == "ground_state_certified"
|
||||
assert abs(cert.ground_energy) < 1e-9
|
||||
assert abs(cert.spectral_gap - 1.0) < 1e-9
|
||||
assert cert.steps_taken >= 1
|
||||
# Independent gold: normalized spectral projection onto the ground space.
|
||||
proj = target * float(target @ psi0)
|
||||
gold = proj / np.linalg.norm(proj)
|
||||
assert np.allclose(result.psi_steady, gold, atol=1e-6)
|
||||
assert abs(abs(float(result.psi_steady @ target)) - 1.0) < 1e-8
|
||||
|
||||
|
||||
def test_relaxation_decodes_propositional_model_set_uniform_start():
|
||||
problem = PropositionalProblem(
|
||||
atoms=("a", "b"),
|
||||
clauses=((("a", True), ("b", True)), (("a", False), ("b", True))),
|
||||
)
|
||||
gold_counts = _truth_table_counts(problem.atoms, problem.clauses)
|
||||
models = [m for m, c in enumerate(gold_counts) if c == 0]
|
||||
assert models == [2, 3] # b=True with a free — independent check
|
||||
ham = compile_propositional(problem)
|
||||
result = relax_to_ground(uniform_assignment_state(problem), ham)
|
||||
cert = result.certificate
|
||||
assert cert.converged
|
||||
assert cert.ground_energy == 0.0 # exact on the diagonal path
|
||||
assert cert.spectral_gap == 1.0 # min nonzero falsification count × penalty
|
||||
psi = result.psi_steady
|
||||
model_components = {assignment_component_index(m) for m in models}
|
||||
for idx in range(N_COMPONENTS):
|
||||
if idx in model_components:
|
||||
assert abs(abs(psi[idx]) - 1.0 / np.sqrt(2.0)) < 1e-9
|
||||
else:
|
||||
assert abs(psi[idx]) < 1e-9
|
||||
|
||||
|
||||
def test_relaxation_degenerate_ground_preserves_input_weighting():
|
||||
problem = PropositionalProblem(
|
||||
atoms=("a", "b"),
|
||||
clauses=((("a", True), ("b", True)), (("a", False), ("b", True))),
|
||||
)
|
||||
ham = compile_propositional(problem)
|
||||
c2, c3 = assignment_component_index(2), assignment_component_index(3)
|
||||
psi0 = np.zeros(N_COMPONENTS)
|
||||
psi0[c2], psi0[c3] = 0.8, 0.6 # unit by construction
|
||||
result = relax_to_ground(psi0, ham)
|
||||
assert abs(abs(result.psi_steady[c2]) - 0.8) < 1e-9
|
||||
assert abs(abs(result.psi_steady[c3]) - 0.6) < 1e-9
|
||||
|
||||
|
||||
def test_relaxation_energy_is_monotone_nonincreasing():
|
||||
target = np.asarray(make_rotor_from_angle(0.3, bivector_idx=6), dtype=np.float64)
|
||||
psi0 = _unit(target + 0.5 * _onehot(2) + 0.3 * _onehot(9))
|
||||
result = relax_to_ground(psi0, compile_quadratic_well(target))
|
||||
assert result.certificate.energy_monotone
|
||||
|
||||
|
||||
def test_relaxation_refuses_orthogonal_start_as_excited_eigenspace():
|
||||
ham = compile_quadratic_well(_onehot(0), curvature=1.0)
|
||||
with pytest.raises(RelaxationNotConverged) as exc_info:
|
||||
relax_to_ground(_onehot(6), ham) # exactly orthogonal to the ground space
|
||||
cert = exc_info.value.certificate
|
||||
assert cert.reason == "excited_eigenspace"
|
||||
assert not cert.converged
|
||||
assert abs(cert.achieved_energy - 1.0) < 1e-9 # settled at the excited level
|
||||
|
||||
|
||||
def test_relaxation_max_steps_exhaustion_and_nonconverged_return_path():
|
||||
diag = np.ones(N_COMPONENTS)
|
||||
diag[0], diag[1] = 0.0, 1e-6 # tiny gap — cannot converge in 3 steps
|
||||
ham = ProblemHamiltonian(matrix=np.diag(diag), domain="tiny_gap")
|
||||
psi0 = _unit(_onehot(0) + _onehot(1))
|
||||
with pytest.raises(RelaxationNotConverged) as exc_info:
|
||||
relax_to_ground(psi0, ham, max_steps=3)
|
||||
assert exc_info.value.certificate.reason == "max_steps_exhausted"
|
||||
result = relax_to_ground(psi0, ham, max_steps=3, require_converged=False)
|
||||
assert not result.certificate.converged
|
||||
|
||||
|
||||
def test_relaxation_input_refusals_fail_closed():
|
||||
ham = compile_quadratic_well(_onehot(0))
|
||||
with pytest.raises(RelaxationInputError):
|
||||
relax_to_ground(0.5 * _onehot(0), ham) # non-unit ψ0 — no hidden repair
|
||||
nan_psi = _onehot(0).copy()
|
||||
nan_psi[7] = np.nan
|
||||
with pytest.raises(RelaxationInputError):
|
||||
relax_to_ground(nan_psi, ham)
|
||||
with pytest.raises(RelaxationInputError):
|
||||
relax_to_ground(_onehot(0), ham, dt=0.0)
|
||||
with pytest.raises(RelaxationInputError):
|
||||
relax_to_ground(_onehot(0), ham, max_steps=0)
|
||||
with pytest.raises(RelaxationInputError):
|
||||
relax_to_ground(_onehot(0), ham, tol=0.0)
|
||||
|
||||
|
||||
def test_relaxation_refuses_unresolvable_spectral_gap_but_certifies_true_ground():
|
||||
"""A gap below the requested tolerance must never mis-certify (audit F4a).
|
||||
|
||||
With gap 1e-7 and tol 1e-6 the energy window alone cannot separate ground
|
||||
from first-excited: the pure excited e-state passed both legacy checks with
|
||||
ZERO ground overlap. The excited-weight check refuses it — while the TRUE
|
||||
ground state (energy exactly λ0) still certifies under the same H and tol.
|
||||
"""
|
||||
diag = np.ones(N_COMPONENTS)
|
||||
diag[0], diag[1] = 0.0, 1e-7
|
||||
ham = ProblemHamiltonian(matrix=np.diag(diag), domain="sub_tol_gap")
|
||||
with pytest.raises(RelaxationNotConverged) as exc_info:
|
||||
relax_to_ground(_onehot(1), ham, tol=1e-6)
|
||||
cert = exc_info.value.certificate
|
||||
assert cert.reason == "spectral_gap_below_tolerance"
|
||||
assert not cert.converged
|
||||
assert cert.spectral_gap == 1e-7 # exact on the diagonal path
|
||||
ground = relax_to_ground(_onehot(0), ham, tol=1e-6)
|
||||
assert ground.certificate.converged
|
||||
assert ground.certificate.reason == "ground_state_certified"
|
||||
|
||||
|
||||
def test_relaxation_certificate_reports_rate_limiting_gap():
|
||||
"""Cluster ⊆ acceptance window: the reported gap is the honest rate (audit F4b).
|
||||
|
||||
A 5e-10 split sat inside the old 1e-9 degeneracy cluster, so the refusal
|
||||
certificate claimed gap=1.0 while the energy check refused that very level.
|
||||
The cluster is now capped at the acceptance window, so the certificate
|
||||
reports the true rate-limiting split.
|
||||
"""
|
||||
diag = np.ones(N_COMPONENTS)
|
||||
diag[0], diag[1] = 0.0, 5e-10
|
||||
ham = ProblemHamiltonian(matrix=np.diag(diag), domain="hairline_split")
|
||||
with pytest.raises(RelaxationNotConverged) as exc_info:
|
||||
relax_to_ground(_onehot(1), ham)
|
||||
cert = exc_info.value.certificate
|
||||
assert cert.reason == "excited_eigenspace"
|
||||
assert cert.spectral_gap == 5e-10 # not the 1.0 the old cluster absorbed it into
|
||||
|
||||
|
||||
def test_relaxation_dense_path_refusals_fail_closed():
|
||||
"""The eigh/propagator branch must refuse honestly, not just decode happy paths.
|
||||
|
||||
A projection-returning mutant with a fabricated converged certificate
|
||||
passed the suite when refusals were exercised only on the diagonal branch
|
||||
(audit F2a) — these two pin the dense branch's refusal mechanics.
|
||||
"""
|
||||
target = np.asarray(make_rotor_from_angle(0.3, bivector_idx=6), dtype=np.float64)
|
||||
slow = compile_quadratic_well(target, curvature=1e-6)
|
||||
assert not slow.is_diagonal
|
||||
psi0 = _unit(target + 0.5 * _onehot(2))
|
||||
with pytest.raises(RelaxationNotConverged) as exc_info:
|
||||
relax_to_ground(psi0, slow, max_steps=3)
|
||||
assert exc_info.value.certificate.reason == "max_steps_exhausted"
|
||||
|
||||
well = compile_quadratic_well(target, curvature=1.0)
|
||||
assert not well.is_diagonal
|
||||
with pytest.raises(RelaxationNotConverged) as exc_info:
|
||||
relax_to_ground(_onehot(2), well, max_steps=8) # e2 ⊥ span(scalar, biv6)
|
||||
cert = exc_info.value.certificate
|
||||
assert cert.reason == "excited_eigenspace"
|
||||
assert not cert.converged
|
||||
|
||||
|
||||
def test_relaxation_iterate_collapse_raises_numerical_failure():
|
||||
"""Underflow of every surviving component is a typed failure, not a repair."""
|
||||
diag = np.ones(N_COMPONENTS)
|
||||
diag[0] = 0.0
|
||||
ham = ProblemHamiltonian(matrix=np.diag(diag), domain="collapse")
|
||||
psi0 = np.zeros(N_COMPONENTS)
|
||||
psi0[0], psi0[1] = 1e-13, 1.0 # ground weight below _NEAR_ZERO after one decay
|
||||
with pytest.raises(RelaxationNumericalFailure) as exc_info:
|
||||
relax_to_ground(_unit(psi0), ham, dt=100.0)
|
||||
assert exc_info.value.reason == "iterate_collapsed"
|
||||
|
||||
|
||||
def test_relaxation_is_bit_deterministic():
|
||||
target = np.asarray(make_rotor_from_angle(0.3, bivector_idx=6), dtype=np.float64)
|
||||
ham = compile_quadratic_well(target)
|
||||
psi0 = _unit(target + 0.5 * _onehot(2))
|
||||
r1 = relax_to_ground(psi0, ham)
|
||||
r2 = relax_to_ground(psi0, ham)
|
||||
assert np.array_equal(r1.psi_steady, r2.psi_steady)
|
||||
assert r1.certificate.certificate_id == r2.certificate.certificate_id
|
||||
|
||||
|
||||
# --- Propositional verdicts (exact spectrum path) -----------------------------------
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"conclusion",
|
||||
[
|
||||
(("c", True),),
|
||||
(("a", True),),
|
||||
(("a", True), ("b", True)),
|
||||
(("b", False),),
|
||||
],
|
||||
)
|
||||
def test_entailment_matches_independent_truth_table_gold(conclusion):
|
||||
premises = PropositionalProblem(atoms=_ATOMS3, clauses=_PREMISES3)
|
||||
verdict = propositional_entails(premises, conclusion)
|
||||
assert verdict.entailed == _entails_gold(_ATOMS3, _PREMISES3, conclusion)
|
||||
assert verdict.satisfiable_premises # these premises have models
|
||||
assert verdict.verdict_id
|
||||
|
||||
|
||||
def test_entailment_hardcoded_canonical_verdicts():
|
||||
"""Hand-verified verdicts, hardcoded — no shared code shape with the module.
|
||||
|
||||
The truth-table gold above uses the same literal-evaluation idiom as the
|
||||
compiler (audit F2e), so these canonical cases pin absolute truth values.
|
||||
"""
|
||||
mp = PropositionalProblem(
|
||||
atoms=("p", "q"),
|
||||
clauses=((("p", False), ("q", True)), (("p", True),)), # p→q, p
|
||||
)
|
||||
assert propositional_entails(mp, (("q", True),)).entailed is True # modus ponens
|
||||
assert propositional_entails(mp, (("q", False),)).entailed is False
|
||||
|
||||
disj = PropositionalProblem(atoms=("p", "q"), clauses=((("p", True), ("q", True)),))
|
||||
assert propositional_entails(disj, (("p", True),)).entailed is False # p∨q ⊭ p
|
||||
|
||||
chain = PropositionalProblem(
|
||||
atoms=("p", "q", "r"),
|
||||
clauses=(
|
||||
(("p", False), ("q", True)), # p→q
|
||||
(("q", False), ("r", True)), # q→r
|
||||
(("p", True),),
|
||||
),
|
||||
)
|
||||
verdict = propositional_entails(chain, (("r", True),))
|
||||
assert verdict.entailed is True # hypothetical syllogism
|
||||
assert verdict.satisfiable_premises is True
|
||||
|
||||
|
||||
def test_entailment_vacuous_from_unsat_premises_is_disclosed():
|
||||
premises = PropositionalProblem(
|
||||
atoms=("a",), clauses=((("a", True),), (("a", False),))
|
||||
)
|
||||
verdict = propositional_entails(premises, (("a", True),))
|
||||
assert verdict.entailed
|
||||
assert not verdict.satisfiable_premises # ex falso — disclosed, not hidden
|
||||
assert verdict.ground_energy_premises > 0.0
|
||||
|
||||
|
||||
def test_entailment_refuses_unknown_atom_and_empty_conclusion():
|
||||
premises = PropositionalProblem(atoms=("a",), clauses=((("a", True),),))
|
||||
with pytest.raises(HamiltonianCompileError):
|
||||
propositional_entails(premises, (("z", True),))
|
||||
with pytest.raises(HamiltonianCompileError):
|
||||
propositional_entails(premises, ())
|
||||
|
||||
|
||||
# --- Egress ---------------------------------------------------------------------------
|
||||
|
||||
|
||||
def _crystalline_outcome():
|
||||
engine = CognitiveLifecycleEngine()
|
||||
target = np.asarray(make_rotor_from_angle(0.3, bivector_idx=6), dtype=np.float64)
|
||||
ham = compile_quadratic_well(target)
|
||||
packets = [fake_deterministic_packet("audio", angle=0.25, plane=6)]
|
||||
return engine, engine.solve(packets, "crystal-demo", ham)
|
||||
|
||||
|
||||
def test_egress_routes_cold_closed_versor_to_crystallization_proposal():
|
||||
_engine, outcome = _crystalline_outcome()
|
||||
verdict = outcome.verdict
|
||||
assert verdict.admitted and verdict.reason == "admitted"
|
||||
assert verdict.versor_closed
|
||||
assert verdict.energy_class.vault_candidate
|
||||
assert verdict.route == "crystallization_proposal"
|
||||
proposal = verdict.proposal
|
||||
assert proposal is not None
|
||||
assert proposal.epistemic_status == "SPECULATIVE"
|
||||
assert proposal.certificate_id == outcome.relaxation.certificate.certificate_id
|
||||
assert proposal.decision.may_speculative_seal
|
||||
json.dumps(proposal.as_dict()) # JSON-serializable artifact
|
||||
|
||||
|
||||
def test_egress_routes_hot_state_to_readback_eligible():
|
||||
_engine, outcome = _crystalline_outcome()
|
||||
verdict = egress_gate(
|
||||
outcome.relaxation.psi_steady,
|
||||
outcome.relaxation.certificate,
|
||||
convergence_density=8,
|
||||
activation_count=8,
|
||||
current_cycle=1,
|
||||
last_activation_cycle=1,
|
||||
morphology_features={"mood": "imperative"},
|
||||
)
|
||||
assert verdict.admitted
|
||||
assert verdict.energy_class.value in ("E3", "E4")
|
||||
assert verdict.route == "readback_eligible"
|
||||
assert verdict.proposal is None
|
||||
|
||||
|
||||
def test_egress_holds_cold_open_superposition_without_proposal():
|
||||
problem = PropositionalProblem(
|
||||
atoms=("a", "b"),
|
||||
clauses=((("a", True), ("b", True)), (("a", False), ("b", True))),
|
||||
)
|
||||
result = relax_to_ground(uniform_assignment_state(problem), compile_propositional(problem))
|
||||
verdict = egress_gate(result.psi_steady, result.certificate)
|
||||
assert verdict.admitted
|
||||
assert not verdict.versor_closed # interference state, not a versor
|
||||
assert verdict.energy_class.vault_candidate
|
||||
assert verdict.route == "hold" # cold but not crystalline: no proposal
|
||||
assert verdict.proposal is None
|
||||
|
||||
|
||||
def test_egress_refuses_unnormalized_and_uncertified_states():
|
||||
_engine, outcome = _crystalline_outcome()
|
||||
cert = outcome.relaxation.certificate
|
||||
scaled = 0.5 * outcome.relaxation.psi_steady
|
||||
verdict = egress_gate(scaled, cert)
|
||||
assert not verdict.admitted and verdict.route == "refused"
|
||||
assert verdict.reason == "amplitude_density_not_unit"
|
||||
|
||||
diag = np.ones(N_COMPONENTS)
|
||||
diag[0], diag[1] = 0.0, 1e-6
|
||||
slow = ProblemHamiltonian(matrix=np.diag(diag), domain="tiny_gap")
|
||||
nonconv = relax_to_ground(
|
||||
_unit(_onehot(0) + _onehot(1)), slow, max_steps=3, require_converged=False
|
||||
)
|
||||
verdict2 = egress_gate(nonconv.psi_steady, nonconv.certificate)
|
||||
assert not verdict2.admitted and verdict2.route == "refused"
|
||||
assert verdict2.reason.startswith("relaxation_not_certified")
|
||||
|
||||
bad = outcome.relaxation.psi_steady.copy()
|
||||
bad[3] = np.inf
|
||||
with pytest.raises(EgressValidationError):
|
||||
egress_gate(bad, cert)
|
||||
with pytest.raises(EgressValidationError):
|
||||
egress_gate(np.zeros(16), cert) # wrong shape — malformed, not refused
|
||||
|
||||
|
||||
def test_egress_refuses_certificate_not_bound_to_state():
|
||||
"""A borrowed converged certificate must not admit a foreign ψ (audit A).
|
||||
|
||||
Before the binding, any unit state paired with any converged certificate
|
||||
was admitted and could emit a CrystallizationProposal whose psi_digest and
|
||||
certificate_id asserted a provenance that never existed.
|
||||
"""
|
||||
_engine, outcome = _crystalline_outcome()
|
||||
psi = outcome.relaxation.psi_steady
|
||||
cert = outcome.relaxation.certificate
|
||||
# Independent gold for the binding: byte digest of the certified state.
|
||||
gold_digest = hashlib.sha256(
|
||||
np.ascontiguousarray(psi, dtype=np.float64).tobytes()
|
||||
).hexdigest()[:24]
|
||||
assert cert.psi_digest == gold_digest
|
||||
assert cert.as_dict()["psi_digest"] == gold_digest
|
||||
|
||||
foreign = np.asarray(make_rotor_from_angle(1.1, bivector_idx=8), dtype=np.float64)
|
||||
verdict = egress_gate(foreign, cert) # unit closed versor, never relaxed
|
||||
assert not verdict.admitted
|
||||
assert verdict.reason == "certificate_state_mismatch"
|
||||
assert verdict.route == "refused"
|
||||
assert verdict.proposal is None
|
||||
|
||||
|
||||
def test_egress_holds_e2_midband_without_proposal():
|
||||
"""The E2 else-branch routes to hold — neither vault-cold nor readback-hot."""
|
||||
_engine, outcome = _crystalline_outcome()
|
||||
verdict = egress_gate(
|
||||
outcome.relaxation.psi_steady,
|
||||
outcome.relaxation.certificate,
|
||||
convergence_density=8,
|
||||
morphology_features={"aspect": "qatal"},
|
||||
)
|
||||
assert verdict.admitted
|
||||
assert verdict.energy_class.value == "E2"
|
||||
assert not verdict.energy_class.vault_candidate
|
||||
assert verdict.route == "hold"
|
||||
assert verdict.proposal is None
|
||||
|
||||
|
||||
def test_crystallization_proposal_type_pins_speculative_status():
|
||||
rotor = np.asarray(make_rotor_from_angle(0.2, bivector_idx=6), dtype=np.float64)
|
||||
decision = crystallization_for_holographic_seal(rotor)
|
||||
with pytest.raises(CognitiveLifecycleError):
|
||||
CrystallizationProposal(
|
||||
proposal_id="crystal-x",
|
||||
epistemic_status="COHERENT", # forbidden by the type itself (I-03)
|
||||
psi_digest="d",
|
||||
certificate_id="c",
|
||||
decision=decision,
|
||||
)
|
||||
|
||||
|
||||
def test_composed_lifecycle_outcome_is_deterministic():
|
||||
_e1, o1 = _crystalline_outcome()
|
||||
_e2, o2 = _crystalline_outcome()
|
||||
assert o1.outcome_id == o2.outcome_id
|
||||
assert np.array_equal(o1.relaxation.psi_steady, o2.relaxation.psi_steady)
|
||||
|
||||
|
||||
# --- Quarantine / structural pins -----------------------------------------------------
|
||||
|
||||
|
||||
def test_module_imports_no_vault_surface():
|
||||
"""I-03 structural pin: the lifecycle can propose, never touch a vault."""
|
||||
src = (_ROOT / "core/physics/cognitive_lifecycle.py").read_text()
|
||||
tree = ast.parse(src)
|
||||
for node in ast.walk(tree):
|
||||
if isinstance(node, ast.Import):
|
||||
for alias in node.names:
|
||||
assert "vault" not in alias.name, alias.name
|
||||
if isinstance(node, ast.ImportFrom) and node.module:
|
||||
assert "vault" not in node.module, node.module
|
||||
|
||||
|
||||
def test_barrel_export_is_lazy_and_resolves():
|
||||
probe = (
|
||||
"import sys;"
|
||||
"import core.physics;"
|
||||
"assert 'core.physics.cognitive_lifecycle' not in sys.modules, 'eager load';"
|
||||
"core.physics.CognitiveLifecycleEngine;"
|
||||
"assert 'core.physics.cognitive_lifecycle' in sys.modules;"
|
||||
"print('ok')"
|
||||
)
|
||||
result = subprocess.run(
|
||||
[sys.executable, "-c", probe],
|
||||
cwd=str(_ROOT),
|
||||
capture_output=True,
|
||||
text=True,
|
||||
env={"PYTHONPATH": str(_ROOT), "PATH": ""},
|
||||
)
|
||||
assert result.returncode == 0, result.stderr[-2000:]
|
||||
assert result.stdout.strip().endswith("ok")
|
||||
|
||||
|
||||
def test_versor_closure_of_steady_state_reported_via_wave_manifold():
|
||||
"""Egress residual is the canonical WaveManifold measurement, not a fork."""
|
||||
_engine, outcome = _crystalline_outcome()
|
||||
manifold = WaveManifold()
|
||||
assert outcome.verdict.versor_residual == pytest.approx(
|
||||
manifold.measure_unitary_residual(outcome.relaxation.psi_steady), abs=0.0
|
||||
)
|
||||
140
tests/test_adr_0243_sketch_defect_pins.py
Normal file
140
tests/test_adr_0243_sketch_defect_pins.py
Normal file
|
|
@ -0,0 +1,140 @@
|
|||
"""ADR-0243 §3 reference-prototype sketch-defect pins (SD-A, SD-B, SD-C).
|
||||
|
||||
Authority: docs/plans/adr-0243-implementation-plan.md §3 (sketch-defect ledger).
|
||||
Precedent: PR #52 sketch-defect pins for the rejected Drive-draft re-implementation.
|
||||
|
||||
The ADR-0243 §3 Python prototype (``CognitiveLifecycleEngine``) contains
|
||||
mathematical defects that make a verbatim port worthless or misleading. These
|
||||
pins prove each defect with a deterministic counterexample so the sketch can
|
||||
never be re-landed as-is:
|
||||
|
||||
SD-A The sketch egress gate computes ``drift = |psi^T I^T psi - 1|`` with an
|
||||
antisymmetric ``I``. The quadratic form of an antisymmetric matrix is
|
||||
identically zero, so drift == 1 for EVERY state and the gate rejects
|
||||
everything — valid and invalid alike. A fail-always gate is the inverse
|
||||
of a hollow gate and equally worthless. The real residual is
|
||||
``WaveManifold.measure_unitary_residual`` / ``goldtether.coherence_residual``.
|
||||
|
||||
SD-B The sketch "relaxation" loop iterates ``R = expm(H @ I * dt)`` with
|
||||
renormalization. The generator's spectrum is (block-wise) purely
|
||||
imaginary, so iterates oscillate and nothing dissipates: the loop never
|
||||
settles into the minimum-energy eigenmode of H. Honest deterministic
|
||||
relaxation is the dissipative (imaginary-time) semigroup
|
||||
``psi <- normalize(exp(-H dt) psi)`` — power iteration whose convergence
|
||||
rate is the spectral gap of H.
|
||||
|
||||
SD-C The sketch's block matrix "I" ("central pseudoscalar proxy") is NOT the
|
||||
Cl(4,1) pseudoscalar action: it shares I^2 = -Id but is a different
|
||||
operator from left-multiplication by e0 e1 e2 e3 e4 in the real algebra.
|
||||
All algebra goes through ``algebra/`` — no component-shuffling proxies.
|
||||
|
||||
Deterministic fixtures only — no random spinors as truth.
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import numpy as np
|
||||
|
||||
from algebra.cl41 import N_COMPONENTS, geometric_product
|
||||
|
||||
|
||||
def _sketch_proxy_i() -> np.ndarray:
|
||||
"""The ADR-0243 §3 prototype's 'central pseudoscalar proxy' matrix."""
|
||||
proxy = np.zeros((N_COMPONENTS, N_COMPONENTS), dtype=np.float64)
|
||||
for i in range(N_COMPONENTS // 2):
|
||||
proxy[2 * i, 2 * i + 1] = 1.0
|
||||
proxy[2 * i + 1, 2 * i] = -1.0
|
||||
return proxy
|
||||
|
||||
|
||||
def _expm_series(M: np.ndarray, terms: int = 60) -> np.ndarray:
|
||||
"""Deterministic truncated-series matrix exponential (no scipy)."""
|
||||
out = np.eye(M.shape[0], dtype=np.float64)
|
||||
term = np.eye(M.shape[0], dtype=np.float64)
|
||||
for k in range(1, terms):
|
||||
term = term @ M / float(k)
|
||||
out = out + term
|
||||
return out
|
||||
|
||||
|
||||
def _onehot(i: int) -> np.ndarray:
|
||||
v = np.zeros(N_COMPONENTS, dtype=np.float64)
|
||||
v[i] = 1.0
|
||||
return v
|
||||
|
||||
|
||||
# --- SD-A: the sketch egress gate rejects every state -------------------------
|
||||
|
||||
|
||||
def test_sd_a_sketch_egress_gate_rejects_every_state():
|
||||
proxy = _sketch_proxy_i()
|
||||
mixed = np.arange(1, N_COMPONENTS + 1, dtype=np.float64)
|
||||
mixed /= np.linalg.norm(mixed)
|
||||
candidates = [_onehot(0), _onehot(5), _onehot(31), mixed]
|
||||
|
||||
for psi in candidates:
|
||||
# Exactly the sketch's egress computation.
|
||||
psi_rev = proxy.T @ psi
|
||||
norm_product = psi @ psi_rev
|
||||
drift = abs(norm_product - 1.0)
|
||||
# Antisymmetric quadratic form vanishes identically...
|
||||
assert abs(norm_product) < 1e-12
|
||||
# ...so the sketch gate rejects EVERYTHING, unit-norm states included.
|
||||
assert drift > 1e-6 # sketch epsilon_drift
|
||||
assert abs(drift - 1.0) < 1e-12
|
||||
|
||||
|
||||
# --- SD-B: the sketch loop cannot relax; imaginary time can -------------------
|
||||
|
||||
|
||||
def test_sd_b_sketch_loop_oscillates_while_imaginary_time_relaxes():
|
||||
energies = np.linspace(0.5, 4.0, N_COMPONENTS)
|
||||
hamiltonian = np.diag(energies) # ground state = component 0
|
||||
psi0 = np.ones(N_COMPONENTS, dtype=np.float64)
|
||||
psi0 /= np.linalg.norm(psi0)
|
||||
|
||||
# Exactly the sketch's relaxation loop: R = expm(H @ I * dt), 100 steps.
|
||||
propagator = _expm_series(hamiltonian @ _sketch_proxy_i() * 0.01)
|
||||
psi = psi0.copy()
|
||||
for _ in range(100):
|
||||
psi = propagator @ psi
|
||||
norm = np.linalg.norm(psi)
|
||||
if norm > 1e-12:
|
||||
psi /= norm
|
||||
sketch_ground_overlap = abs(psi[0])
|
||||
|
||||
# Honest dissipative semigroup: psi <- normalize(exp(-H dt) psi).
|
||||
decay = np.exp(-energies * 0.5)
|
||||
phi = psi0.copy()
|
||||
for _ in range(200):
|
||||
phi = decay * phi
|
||||
phi /= np.linalg.norm(phi)
|
||||
imaginary_time_ground_overlap = abs(phi[0])
|
||||
|
||||
# The sketch never concentrates on the ground state...
|
||||
assert sketch_ground_overlap < 0.9
|
||||
# ...while imaginary time converges to it (rate = spectral gap).
|
||||
assert imaginary_time_ground_overlap > 1.0 - 1e-8
|
||||
|
||||
|
||||
# --- SD-C: the proxy matrix is not the Cl(4,1) pseudoscalar action ------------
|
||||
|
||||
|
||||
def test_sd_c_proxy_matrix_is_not_the_pseudoscalar_action():
|
||||
# Real pseudoscalar e0 e1 e2 e3 e4 (0-indexed basis vectors, f64).
|
||||
pseudoscalar = _onehot(1) # e0 lives at component 1
|
||||
for i in range(1, 5):
|
||||
pseudoscalar = geometric_product(pseudoscalar, _onehot(1 + i))
|
||||
|
||||
# Left-multiplication-by-pseudoscalar as a 32x32 matrix.
|
||||
action = np.zeros((N_COMPONENTS, N_COMPONENTS), dtype=np.float64)
|
||||
for j in range(N_COMPONENTS):
|
||||
action[:, j] = geometric_product(pseudoscalar, _onehot(j))
|
||||
|
||||
proxy = _sketch_proxy_i()
|
||||
identity = np.eye(N_COMPONENTS)
|
||||
# Both square to -Id (I5^2 = -1 in Cl(4,1)) — the proxy mimics the square...
|
||||
assert np.allclose(action @ action, -identity, atol=1e-12)
|
||||
assert np.allclose(proxy @ proxy, -identity, atol=1e-12)
|
||||
# ...but is a DIFFERENT operator: the actions disagree outright.
|
||||
assert float(np.max(np.abs(action - proxy))) > 0.5
|
||||
|
|
@ -28,6 +28,7 @@ _BANNED = (
|
|||
"core.physics.wave_energy_boundary",
|
||||
"core.physics.multi_scale_energy",
|
||||
"core.physics.sensorium_wave_feed",
|
||||
"core.physics.cognitive_lifecycle", # ADR-0243 lifecycle — never serve
|
||||
# NOTE: core.physics.wave_manifold is intentionally excluded pending the
|
||||
# Joshua design ruling (goldtether delegates to it). Add it here if the
|
||||
# ruling is "quarantine wave_manifold for real".
|
||||
|
|
|
|||
|
|
@ -70,6 +70,7 @@ def test_phase0_a04_serve_path_quarantines_wave_and_fibonacci():
|
|||
"wave_energy_boundary", # P10 Trace B — energy/τ gate, never serve
|
||||
"multi_scale_energy", # ADR-0242 V2 research multi-band E_n(t), never serve
|
||||
"sensorium_wave_feed", # D7 I-04 sensorium→ψ feed, never serve
|
||||
"cognitive_lifecycle", # ADR-0243 ingress→relaxation→egress, never serve
|
||||
}
|
||||
banned_substrings = (
|
||||
"holographic_vault",
|
||||
|
|
@ -80,6 +81,7 @@ def test_phase0_a04_serve_path_quarantines_wave_and_fibonacci():
|
|||
"wave_energy_boundary",
|
||||
"multi_scale_energy",
|
||||
"sensorium_wave_feed",
|
||||
"cognitive_lifecycle",
|
||||
)
|
||||
for node in ast.walk(tree):
|
||||
if isinstance(node, ast.Import):
|
||||
|
|
|
|||
Loading…
Reference in a new issue