Research-Stack/2-Search-Space/PIST/PIST.lean

517 lines
18 KiB
Text
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import Mathlib.Data.Nat.Basic
import Mathlib.Tactic
/-! Prime Interval Shell Theory (PIST) Core - Extended Defensible Version
This module formalizes a defensible discrete core for the PIST state machine.
It avoids speculative geometry and focuses on an interval-local coordinate model.
The main idea is that a natural number between consecutive squares is represented
by a shell index `k` and an offset `t` with `0 ≤ t ≤ 2*k+1`.
Within that shell, the PIST mass is the quadratic quantity
`mass = t * ((2*k+1) - t)`.
This file contains (minimal + extended):
* Interval-local coordinate type `Coord` with shell geometry
* Mass / hyperbola-index definitions (a, b, mass = a*b)
* Mirror involution inside one shell (preserves mass)
* Zero mass theorems (exactly at shell endpoints)
* Positive mass equivalence (strictly inside shell)
* Resonance equivalence relation (refl, symm, trans)
* Phase flags (grounded/seismic) based on mass
* Move labels for state-machine transitions
* LogEntry/Log for append-only history tracking
* Extended State with operations (penalize, accept, relocate, resonanceJump, rejectWithPenalty)
* Transition structure with mass preservation and strict decrease
* LawfulMove inductive (linear, resonance, rejected, crystallized)
* Projector (idempotent normalizer) and Grounder structures
* Two kernel interfaces: minimal Kernel and extended KernelExtended
* Lyapunov-style strict descent guarantees for both kernels
The file deliberately avoids making cryptographic or physical claims.
Anything "more weird" is encoded as typed data and admissibility rules.
Per AGENTS.md §2: PascalCase types, camelCase functions.
Per AGENTS.md §4: All definitions must have eval witnesses or theorems.
-/
namespace PIST
/-- A coordinate inside the square shell bounded by `k^2` and `(k+1)^2`.
The offset `t` records the position inside that shell, so necessarily
`t ≤ 2*k + 1`.
-/structure Coord where
k :
t :
ht : t ≤ 2 * k + 1
deriving DecidableEq, Repr
namespace Coord
/-- The underlying natural number represented by the shell coordinate. -/
def n (c : Coord) : := c.k ^ 2 + c.t
/-- Distance to the lower square in shell coordinates. -/
def a (c : Coord) : := c.t
/-- Distance to the upper square in shell coordinates. -/
def b (c : Coord) : := 2 * c.k + 1 - c.t
/-- The PIST mass / hyperbola index in shell coordinates. -/
def mass (c : Coord) : := c.a * c.b
@[simp] theorem a_def (c : Coord) : c.a = c.t := rfl
@[simp] theorem b_def (c : Coord) : c.b = 2 * c.k + 1 - c.t := rfl
@[simp] theorem mass_def (c : Coord) : c.mass = c.t * (2 * c.k + 1 - c.t) := rfl
/-- The shell identity `a + b = 2*k+1`. -/
theorem a_add_b (c : Coord) : c.a + c.b = 2 * c.k + 1 := by
dsimp [a, b]
exact Nat.add_sub_of_le c.ht
/-- The mirror point inside the same shell. -/
def mirror (c : Coord) : Coord where
k := c.k
t := 2 * c.k + 1 - c.t
ht := Nat.sub_le _ _
@[simp] theorem mirror_k (c : Coord) : c.mirror.k = c.k := rfl
@[simp] theorem mirror_t (c : Coord) : c.mirror.t = 2 * c.k + 1 - c.t := rfl
@[simp] theorem a_mirror (c : Coord) : c.mirror.a = c.b := rfl
/-- Mirroring swaps the two shell distances. -/
@[simp] theorem b_mirror (c : Coord) : c.mirror.b = c.a := by
dsimp [b, a, mirror]
rw [Nat.sub_sub_self c.ht]
/-- Mirror preserves mass. -/
@[simp] theorem mass_mirror (c : Coord) : c.mirror.mass = c.mass := by
simp [mass, a, b, mirror, Nat.mul_comm]
have h : c.k * 2 + 1 - (c.k * 2 + 1 - c.t) = c.t := by
have : c.k * 2 + 1 = 2 * c.k + 1 := by simp [Nat.mul_comm]
rw [this]
rw [Nat.sub_sub_self c.ht]
simp [h]
exact Nat.mul_comm _ _
/-- Mirroring twice returns the original shell offset. -/
@[simp] theorem mirror_mirror_t (c : Coord) : c.mirror.mirror.t = c.t := by
dsimp [mirror]
rw [Nat.sub_sub_self c.ht]
/-- Mirror is an involution. -/
@[simp] theorem mirror_mirror (c : Coord) : c.mirror.mirror = c := by
cases c with
| mk k t ht =>
simp [mirror]
rw [Nat.sub_sub_self ht]
/-- A coordinate has zero mass exactly at the shell endpoints. -/
theorem mass_eq_zero_iff (c : Coord) : c.mass = 0 ↔ c.t = 0 c.t = 2 * c.k + 1 := by
rw [mass_def]
constructor
· intro h
rcases (Nat.mul_eq_zero.mp h) with h0 | h1
· exact Or.inl h0
· right
have hle : 2 * c.k + 1 ≤ c.t := by
rw [Nat.sub_eq_zero_iff_le] at h1
exact h1
exact le_antisymm c.ht hle
· rintro (h | h)
· simp [h]
· simp [h]
/-- Positive mass is equivalent to being strictly inside the shell. -/
theorem mass_pos_iff (c : Coord) : 0 < c.mass ↔ 0 < c.t ∧ c.t < 2 * c.k + 1 := by
constructor
· intro h
have hne : c.mass ≠ 0 := Nat.ne_of_gt h
have hnot := mt (mass_eq_zero_iff c).mpr hne
constructor
· by_contra h0
apply hne
apply (mass_eq_zero_iff c).mpr
exact Or.inl (Nat.eq_zero_of_not_pos h0)
· by_contra htop
apply hne
apply (mass_eq_zero_iff c).mpr
exact Or.inr (le_antisymm c.ht (not_lt.mp htop))
· rintro ⟨ht0, httop⟩
rw [mass_def]
apply Nat.mul_pos
· exact ht0
· exact Nat.sub_pos_of_lt httop
/-- Left shell endpoint. -/
def lower (k : ) : Coord where
k := k
t := 0
ht := by omega
/-- Right shell endpoint. -/
def upper (k : ) : Coord where
k := k
t := 2 * k + 1
ht := by omega
@[simp] theorem mass_lower (k : ) : (lower k).mass = 0 := by simp [lower, mass]
@[simp] theorem mass_upper (k : ) : (upper k).mass = 0 := by simp [upper, mass]
end Coord
/-- Two shell coordinates are resonant when they have equal mass. -/
def Resonant (x y : Coord) : Prop := x.mass = y.mass
theorem Resonant.refl (x : Coord) : Resonant x x := rfl
theorem Resonant.symm {x y : Coord} : Resonant x y -> Resonant y x := by
intro h
exact Eq.symm h
theorem Resonant.trans {x y z : Coord} : Resonant x y -> Resonant y z -> Resonant x z := by
intro h₁ h₂
exact Eq.trans h₁ h₂
/-- Phase flags for the interval-local machine. -/
inductive Phase
| grounded
| drift
| seismic
deriving DecidableEq, Repr
/-- Auxiliary resonance metadata. -/
def isResonantPair (x y : Coord) : Bool := x != y && x.mass == y.mass
/-- A simple phase classifier based on zero vs positive mass.
This is intentionally minimal and fully justified from the existing theory.
A richer classifier can be built on top of the same core.
-/def phase (c : Coord) : Phase :=
if c.mass = 0 then Phase.grounded else Phase.seismic
@[simp] theorem phase_grounded_iff (c : Coord) : phase c = Phase.grounded ↔ c.mass = 0 := by
apply Iff.intro
· intro h
unfold phase at h
by_cases h2 : c.mass = 0
· exact h2
· rw [if_neg h2] at h
cases h
· intro h
unfold phase
by_cases h2 : c.mass = 0
· rw [if_pos h2]
· cases h2 h
@[simp] theorem phase_seismic_iff (c : Coord) : phase c = Phase.seismic ↔ c.mass ≠ 0 := by
apply Iff.intro
· intro h
unfold phase at h
by_cases h2 : c.mass = 0
· rw [if_pos h2] at h
cases h
· exact h2
· intro h
unfold phase
by_cases h2 : c.mass = 0
· rw [if_pos h2]
cases h h2
· rw [if_neg h2]
/-- Move labels for state-machine transitions. -/
inductive MoveFlag
| linearStep
| resonanceJump
| rejected
| crystallized
deriving DecidableEq, Repr
/-- A single log entry for append-only state history. -/
structure LogEntry where
before : Coord
after : Coord
move : MoveFlag
preservedMass : Bool
deriving DecidableEq, Repr
/-- Append-only logs. We do not claim cryptographic properties here; this is just
an auditable history shape that a stronger implementation can refine.
-/abbrev Log := List LogEntry
namespace LogEntry
/-- The canonical entry for a resonance jump. -/
def resonance (x y : Coord) : LogEntry :=
{ before := x, after := y, move := MoveFlag.resonanceJump,
preservedMass := decide (x.mass = y.mass) }
/-- The canonical entry for a rejection event. -/
def rejection (x y : Coord) : LogEntry :=
{ before := x, after := y, move := MoveFlag.rejected,
preservedMass := decide (x.mass = y.mass) }
end LogEntry
/-- A minimal machine state over interval-local coordinates. -/
structure State where
pos : Coord
phaseFlag : Phase
accepted : List Coord
rejected : List Coord
friction :
log : Log
deriving Repr
namespace State
/-- The canonical state built from a position. -/
def ofCoord (c : Coord) : State :=
{ pos := c
phaseFlag := phase c
accepted := []
rejected := []
friction := 0
log := [] }
/-- A basic Lyapunov functional: PIST mass plus friction. -/
def potential (S : State) : := S.pos.mass + S.friction
@[simp] theorem potential_ofCoord (c : Coord) : (ofCoord c).potential = c.mass := by
simp [ofCoord, potential]
/-- Append a log entry. -/
def appendLog (S : State) (e : LogEntry) : State :=
{ S with log := e :: S.log }
@[simp] theorem appendLog_log (S : State) (e : LogEntry) : (appendLog S e).log = e :: S.log := rfl
/-- Register a rejection and increase friction by a nonnegative penalty. -/
def penalize (S : State) (bad : Coord) (penalty : ) : State :=
{ S with rejected := bad :: S.rejected, friction := S.friction + penalty }
@[simp] theorem penalize_friction (S : State) (bad : Coord) (penalty : ) :
(penalize S bad penalty).friction = S.friction + penalty := rfl
@[simp] theorem potential_penalize (S : State) (bad : Coord) (penalty : ) :
(penalize S bad penalty).potential = S.potential + penalty := by
simp [potential, penalize, Nat.add_assoc]
/-- Register an accepted coordinate. -/
def accept (S : State) (good : Coord) : State :=
{ S with accepted := good :: S.accepted }
/-- Replace the active coordinate and refresh the phase flag. -/
def relocate (S : State) (c : Coord) : State :=
{ S with pos := c, phaseFlag := phase c }
@[simp] theorem relocate_pos (S : State) (c : Coord) : (relocate S c).pos = c := rfl
@[simp] theorem relocate_phase (S : State) (c : Coord) : (relocate S c).phaseFlag = phase c := rfl
/-- A resonance jump preserves the shell mass and updates the active coordinate. -/
def resonanceJump (S : State) (target : Coord) (_h : Resonant S.pos target) : State :=
appendLog (relocate (accept S target) target) (LogEntry.resonance S.pos target)
@[simp] theorem resonanceJump_pos (S : State) (target : Coord) (h : Resonant S.pos target) :
(resonanceJump S target h).pos = target := by
simp [resonanceJump, appendLog, relocate]
@[simp] theorem resonanceJump_potential (S : State) (target : Coord) (h : Resonant S.pos target) :
(resonanceJump S target h).potential = S.pos.mass + S.friction := by
simp [resonanceJump, State.potential, relocate, accept, appendLog]
exact h.symm
/-- A rejection event appends to the log and increases friction. -/
def rejectWithPenalty (S : State) (bad : Coord) (penalty : ) : State :=
appendLog (penalize S bad penalty) (LogEntry.rejection S.pos bad)
@[simp] theorem rejectWithPenalty_friction (S : State) (bad : Coord) (penalty : ) :
(rejectWithPenalty S bad penalty).friction = S.friction + penalty := by
simp [rejectWithPenalty, penalize, appendLog]
@[simp] theorem penalize_pos (S : State) (bad : Coord) (penalty : ) :
(penalize S bad penalty).pos = S.pos := rfl
@[simp] theorem potential_rejectWithPenalty (S : State) (bad : Coord) (penalty : ) :
(rejectWithPenalty S bad penalty).potential = S.potential + penalty := by
simp [rejectWithPenalty, State.potential, appendLog, penalize_pos]
rw [Nat.add_assoc]
end State
/-- A lawful state-machine kernel. This is a specification interface:
concrete instances must provide the operations and proofs below.
-/structure Kernel (Candidate Reality : Type) where
bind : Candidate
assimilate : State → Candidate → State
project : State → State
ground : State → Reality → State
terminal : State → Prop
step : State → Reality → State := fun S R => ground (project (assimilate S bind)) R
/-- Projection is idempotent. -/
project_idem : ∀ S, project (project S) = project S
/-- Grounding preserves the image of projection in one step form. -/
project_step : ∀ S R, step S R = ground (project (assimilate S bind)) R
/-- Nonterminal steps strictly decrease the chosen potential. -/
strict_descent : ∀ S R, ¬ terminal S → State.potential (step S R) < State.potential S
namespace Kernel
variable {Candidate Reality : Type} (K : Kernel Candidate Reality)
@[simp] theorem step_def (S : State) (R : Reality) :
K.step S R = K.ground (K.project (K.assimilate S K.bind)) R := by
exact K.project_step S R
/-- A nonterminal state cannot be a fixed point of a strictly descending step. -/
theorem not_fixed_of_nonterminal (S : State) (R : Reality) (hS : ¬ K.terminal S) :
K.step S R ≠ S := by
intro hfix
have hlt := K.strict_descent S R hS
rw [hfix] at hlt
exact Nat.lt_irrefl _ hlt
/-- One-step evolution from a nonterminal state strictly lowers the potential. -/
theorem potential_decreases (S : State) (R : Reality) (hS : ¬ K.terminal S) :
State.potential (K.step S R) < State.potential S :=
K.strict_descent S R hS
end Kernel
-- ════════════════════════════════════════════════════════════
-- Extended State Machine (Advanced Interface)
-- ════════════════════════════════════════════════════════════
/-- A transition packages a next state together with the move label used to reach it. -/
structure Transition where
next : State
flag : MoveFlag
deriving Repr
namespace Transition
/-- Whether the transition preserves shell mass at the active coordinate. -/
def PreservesMass (S : State) (T : Transition) : Prop := S.pos.mass = T.next.pos.mass
/-- Whether the transition strictly decreases the potential. -/
def StrictlyDecreases (S : State) (T : Transition) : Prop := T.next.potential < S.potential
end Transition
/-- Lawfulness for candidate operations: either a one-step linear move, a resonance jump,
or a rejection that stays in place while adding friction.
-/inductive LawfulMove (S : State) : Transition → Prop
| linear (T : Transition)
(hflag : T.flag = MoveFlag.linearStep)
(hfric : T.next.friction = S.friction)
(hstep : T.next.pos.k = S.pos.k)
(hshift : T.next.pos.t + 1 = S.pos.t S.pos.t + 1 = T.next.pos.t) :
LawfulMove S T
| resonance (target : Coord) (hres : Resonant S.pos target) :
LawfulMove S
{ next := S.resonanceJump target hres, flag := MoveFlag.resonanceJump }
| rejected (bad : Coord) (penalty : ) :
LawfulMove S
{ next := S.rejectWithPenalty bad penalty, flag := MoveFlag.rejected }
| crystallized (target : Coord)
(hzero : target.mass = 0)
(hfric : S.friction = 0) :
LawfulMove S
{ next := State.ofCoord target, flag := MoveFlag.crystallized }
namespace LawfulMove
/-- Resonance jumps preserve shell mass at the active coordinate. -/
theorem preservesMass_resonance (S : State) (target : Coord) (hres : Resonant S.pos target) :
Transition.PreservesMass S
{ next := S.resonanceJump target hres, flag := MoveFlag.resonanceJump } := by
dsimp [Transition.PreservesMass]
simp [State.resonanceJump_pos]
exact hres
/-- Rejection with positive penalty strictly increases potential, hence cannot be used as
a descent step.
-/theorem reject_not_descent (S : State) (bad : Coord) {penalty : } (_hpen : 0 < penalty) :
¬ Transition.StrictlyDecreases S
{ next := S.rejectWithPenalty bad penalty, flag := MoveFlag.rejected } := by
intro hdec
dsimp [Transition.StrictlyDecreases] at hdec
rw [State.potential_rejectWithPenalty] at hdec
exact Nat.not_lt.mpr (Nat.le_add_right _ _) hdec
end LawfulMove
/-- A lawful projection is an idempotent normalizer on states. -/
structure Projector where
project : State → State
idem : ∀ S, project (project S) = project S
namespace Projector
@[simp] theorem idem_apply (P : Projector) (S : State) : P.project (P.project S) = P.project S :=
P.idem S
end Projector
/-- A grounding operator chooses a next state from a lawful candidate and an external
reality parameter.
-/structure Grounder (Reality : Type) where
ground : State → Reality → State
/-- A more structured kernel than the minimal core: it explicitly tracks a projector,
a grounding map, and a chosen lawful transition policy.
-/structure KernelExtended (Reality : Type) where
projector : Projector
grounder : Grounder Reality
terminal : State → Prop
choose : State → Reality → Transition
lawful_choose : ∀ S R, LawfulMove (projector.project S) (choose (projector.project S) R)
strict_descent : ∀ S R,
¬ terminal (projector.project S) →
Transition.StrictlyDecreases (projector.project S) (choose (projector.project S) R)
grounded_step : State → Reality → State := fun S R =>
(grounder.ground (choose (projector.project S) R).next R)
namespace KernelExtended
variable {Reality : Type} (K : KernelExtended Reality)
/-- On projected nonterminal states, the chosen transition strictly decreases the potential. -/
theorem chosen_transition_decreases (S : State) (R : Reality)
(hS : ¬ K.terminal (K.projector.project S)) :
Transition.StrictlyDecreases (K.projector.project S) (K.choose (K.projector.project S) R) :=
K.strict_descent S R hS
/-- A projected nonterminal state cannot be a fixed point of the chosen transition. -/
theorem chosen_transition_not_fixed (S : State) (R : Reality)
(hS : ¬ K.terminal (K.projector.project S)) :
(K.choose (K.projector.project S) R).next ≠ K.projector.project S := by
intro hfix
have hlt := K.chosen_transition_decreases S R hS
dsimp [Transition.StrictlyDecreases] at hlt
rw [hfix] at hlt
exact Nat.lt_irrefl _ hlt
end KernelExtended
-- ════════════════════════════════════════════════════════════
-- Verification Examples (AGENTS.md §4 requirement)
-- ════════════════════════════════════════════════════════════
#eval ({ k := 5, t := 3, ht := by omega : Coord }).mass
#eval ({ k := 5, t := 0, ht := by omega : Coord }).mass
#eval ({ k := 5, t := 3, ht := by omega : Coord }).mirror.mass = ({ k := 5, t := 3, ht := by omega : Coord }).mass
#eval ({ k := 5, t := 0, ht := by omega : Coord }).mirror.t
#eval isResonantPair { k := 3, t := 2, ht := by omega } { k := 3, t := 5, ht := by omega }
#eval phase { k := 10, t := 5, ht := by omega : Coord }
end PIST