mirror of
https://github.com/allaunthefox/SilverSight.git
synced 2026-07-30 17:16:16 +00:00
Systematic native_decide → dec_trivial/rfl migration across all Lean modules to comply with AGENTS.md rule 5 (no native_decide unless only option): - CoreFormalism: BraidEigensolid, BraidField, ChentsovFinite, HachimojiBase, HachimojiBridging, HachimojiCodec, HachimojiLUT, HachimojiManifoldAxiom, Q16_16Numerics - BindingSite: BindingSiteCodec, BindingSiteEntropy, BindingSiteHachimoji - SilverSight: ProductSchema, ProductWireFormat, PolyFactorIdentity, Schema, WireFormat - PVGS_DQ_Bridge: all three files (native_decide->dec_trivial) - UniversalEncoding/ChiralitySpace Additional changes: - gemma4_mcp.py: upgraded to two-tier routing (local Gemma4 + FreeLLMAPI proxy) - ChentsovFinite: added traceability map and Chentsov (1972) citation - HachimojiBase: renamed Σ→Sig, Π→Pi to avoid non-ASCII issues - Import path fixes for Mathlib 4.30.0-rc2 compatibility - Doc updates: PURE_FORMULAS, SOS_CERTIFICATE, fundamental math derivations - Build log: 2026-06-26 session findings - BRKGLASS_NR_BRACKET_PROPOSAL: updated to REAL-DATA VALIDATED status - New docs: FOUNDATIONAL_GUIDANCE, PURE_EQUATION_MAP, CHENTSOV_FINITE_MATH, BREAKGLASS_FUSION_REVIEW_SPEC, COLD_REVIEWER_FORMULA - New python: phi pipeline (equation_dna_encoder, ast_parse, charclass, consistency, embed, output), nr_bracket_validation with receipt Build: lake build SilverSightRRC — passes on all committed modules. Excluded: HachimojiN8Bridge, HachimojiCharClass (missing CoreFormalism.HachimojiManifoldAxiom olean — WIP)
161 lines
8.9 KiB
Text
161 lines
8.9 KiB
Text
/-
|
||
BindingSiteCodec.lean — Deterministic Pipeline: PDB → Binding Site Receipt
|
||
|
||
The protein-structure analog of HachimojiCodec.lean.
|
||
Takes raw PDB residue data (residueName, modification, bFactor, neighborBFactors),
|
||
computes the entropy profile, classifies residues via the 8-state Hachimoji system,
|
||
and emits a typed BindingSiteReceipt.
|
||
|
||
Design constraints:
|
||
- No Float, no Real in compute path — all arithmetic is Q16_16
|
||
- No PVGS_DQ_Bridge dependency (avoids Bridge Q16_16 / Core Q16_16 type collision)
|
||
- dqEnergy and stellarRank are computed directly from the entropy profile
|
||
- Delegates to BindingSiteHachimoji.buildProfile and BindingSiteEntropy functions
|
||
|
||
Pipeline:
|
||
(residueName, mod, bFactor, neighborBFs)
|
||
→ bindingSiteEntropyProfile (BindingSiteEntropy §3)
|
||
→ buildProfile (BindingSiteHachimoji §4)
|
||
→ stellarRank, dqEnergy
|
||
→ BindingSiteReceipt
|
||
-/
|
||
import BindingSite.BindingSiteHachimoji
|
||
import BindingSite.BindingSiteEntropy
|
||
|
||
namespace BindingSiteCodec
|
||
|
||
open BindingSite SilverSight.FixedPoint
|
||
|
||
-- ═══════════════════════════════════════════════════════════════════════════
|
||
-- §1 PDB data interface (IO layer, placeholder for RCSB API)
|
||
-- ═══════════════════════════════════════════════════════════════════════════
|
||
|
||
-- PDB residue record type — matches bindingSiteEntropyProfile's input signature.
|
||
-- bFactor and neighborBFactors are Nat (PDB stores as integers scaled ×100; caller
|
||
-- should pass the integer value, e.g., B=35.12 → 35).
|
||
abbrev PDBResidue := String × String × Nat × List Nat
|
||
-- resName mod bFac neighborBFacs
|
||
|
||
/-- Placeholder: in production calls RCSB REST API and parses mmCIF.
|
||
Returns empty list; actual data is injected by the IO layer. -/
|
||
def fetchPDB (pdbId : String) : IO (List PDBResidue) := do
|
||
IO.println s!"[BindingSiteCodec] fetchPDB {pdbId} (placeholder)"
|
||
pure []
|
||
|
||
/-- Placeholder: fetches sequence cluster membership from RCSB.
|
||
Returns (entityId, clusterId) or none. -/
|
||
def fetchClusterMembership (pdbId : String) : IO (Option (Nat × Nat)) := do
|
||
IO.println s!"[BindingSiteCodec] fetchCluster {pdbId} (placeholder)"
|
||
pure none
|
||
|
||
-- ═══════════════════════════════════════════════════════════════════════════
|
||
-- §2 Stellar rank and DQ energy (pure Q16_16, no PVGS Bridge)
|
||
-- ═══════════════════════════════════════════════════════════════════════════
|
||
|
||
/-- Stellar rank = number of distinct BindingSiteStates present in the profile.
|
||
Maps to photon variation count in the PVGS-DQ formalism. -/
|
||
def stellarRank (residues : List BindingSiteResidue) : Nat :=
|
||
let states : List BindingSiteState :=
|
||
[ .Phi, .Lambda, .Rho, .Kappa, .Omega, .Sigma, .Pi, .Zeta ]
|
||
states.countP (fun s => residues.any (fun r => r.state == s))
|
||
|
||
/-- DQ energy proxy: sum of entropy.val over all residues (Int).
|
||
Tracks total disorder; lower = more ordered = stronger pocket signal.
|
||
This is an entropy-only proxy; the full dual-quaternion energy requires
|
||
spatial coordinates (not available in the B-factor-only pipeline). -/
|
||
def dqEnergyFromProfile (profile : BindingSiteProfile) : Int :=
|
||
profile.residues.foldl (fun acc r => acc + r.entropy.val) 0
|
||
|
||
/-- Helstrom bound placeholder (Q16_16).
|
||
Full computation requires pairwise quantum state discrimination across residue
|
||
pairs — research-level; left as zero pending the quantum sensing module. -/
|
||
def helstromBoundPlaceholder : Q16_16 := Q16_16.zero
|
||
|
||
-- ═══════════════════════════════════════════════════════════════════════════
|
||
-- §3 Pipeline stages
|
||
-- ═══════════════════════════════════════════════════════════════════════════
|
||
|
||
/-- Stage 1: PDB residues → entropy-classified list.
|
||
Delegates to BindingSiteEntropy.bindingSiteEntropyProfile. -/
|
||
def classifyResidues
|
||
(pdbData : List PDBResidue)
|
||
: List (AminoAcidToken × Q16_16 × BindingSiteState) :=
|
||
bindingSiteEntropyProfile pdbData
|
||
|
||
/-- Stage 2: classified list → BindingSiteProfile.
|
||
Delegates to BindingSiteHachimoji.buildProfile. -/
|
||
def profileFromClassified
|
||
(classified : List (AminoAcidToken × Q16_16 × BindingSiteState))
|
||
: BindingSiteProfile :=
|
||
buildProfile classified
|
||
|
||
/-- Stage 3: profile → BindingSiteReceipt. -/
|
||
def emitReceipt (pdbId : String) (entityId clusterId : Nat)
|
||
(profile : BindingSiteProfile) : BindingSiteReceipt :=
|
||
{ version := "BindingSite:v1"
|
||
, pdbId := pdbId
|
||
, entityId := entityId
|
||
, clusterId := clusterId
|
||
, profile := profile
|
||
, dqEnergy := dqEnergyFromProfile profile
|
||
, stellarRank := stellarRank profile.residues
|
||
, helstromBound := helstromBoundPlaceholder
|
||
, sha256 := "PENDING" }
|
||
|
||
-- ═══════════════════════════════════════════════════════════════════════════
|
||
-- §4 One-function API
|
||
-- ═══════════════════════════════════════════════════════════════════════════
|
||
|
||
/-- `pdbToReceipt : PDB ID → IO BindingSiteReceipt`
|
||
|
||
Complete pipeline in one call. This is the protein-structure analog of
|
||
`equation_to_emit` from HachimojiCodec.lean.
|
||
|
||
Usage:
|
||
let receipt ← pdbToReceipt "1YY9"
|
||
IO.println s!"{receipt.profile.siteState}" -- Pi or Lambda → druggable
|
||
|
||
The receipt is compatible with the PVGS-DQ receipt system:
|
||
- receipt.dqEnergy → entropy-sum proxy (full DQ requires coordinates)
|
||
- receipt.stellarRank → photon variation count
|
||
- receipt.sha256 → hash chain anchor (populated by caller) -/
|
||
def pdbToReceipt (pdbId : String) : IO BindingSiteReceipt := do
|
||
let pdbData ← fetchPDB pdbId
|
||
let classified := classifyResidues pdbData
|
||
let profile := profileFromClassified classified
|
||
let clusterInfo ← fetchClusterMembership pdbId
|
||
let (entity, cluster) := clusterInfo.getD (0, 0)
|
||
pure (emitReceipt pdbId entity cluster profile)
|
||
|
||
-- ═══════════════════════════════════════════════════════════════════════════
|
||
-- §5 Batch screening API
|
||
-- ═══════════════════════════════════════════════════════════════════════════
|
||
|
||
/-- Screen a library of PDB IDs, returning only druggable sites. -/
|
||
def screenDruggable (pdbIds : List String) : IO (List BindingSiteReceipt) := do
|
||
let receipts ← pdbIds.mapM pdbToReceipt
|
||
pure (receipts.filter (fun r => r.profile.druggable))
|
||
|
||
/-- Rank receipts by DQ energy (lower = more ordered = stronger pocket). -/
|
||
def rankByEnergy (receipts : List BindingSiteReceipt) : List BindingSiteReceipt :=
|
||
receipts.insertionSort (fun r1 r2 => r1.dqEnergy < r2.dqEnergy)
|
||
|
||
-- ═══════════════════════════════════════════════════════════════════════════
|
||
-- §6 Sanity checks (no IO, pure, decidable)
|
||
-- ═══════════════════════════════════════════════════════════════════════════
|
||
|
||
/-- stellarRank is bounded by the 8 Hachimoji states. -/
|
||
theorem stellarRank_le_8 (residues : List BindingSiteResidue) :
|
||
stellarRank residues ≤ 8 := by
|
||
simp only [stellarRank]
|
||
apply List.countP_le_length
|
||
|
||
/-- An empty profile has dqEnergy = 0. -/
|
||
theorem dqEnergy_empty :
|
||
dqEnergyFromProfile (show BindingSiteProfile from
|
||
{ residues := [], totalEntropy := Q16_16.zero,
|
||
maxEntropy := Q16_16.zero, minEntropy := Q16_16.zero,
|
||
siteState := .Phi, druggable := false, receiptHash := "" }) = 0 := by
|
||
simp [dqEnergyFromProfile]
|
||
|
||
end BindingSiteCodec
|