Research-Stack/0-Core-Formalism/lean/external/OTOM/CriticalityDynamics.lean

314 lines
9.8 KiB
Text

import Semantics.PhysicsScalar
import Semantics.RegimeCore
import Semantics.BoundaryDynamics
import Semantics.SpikingDynamics
import Semantics.ExoticSpacetime
namespace Semantics.CriticalityDynamics
open Semantics.PhysicsScalar
open Semantics.RegimeCore
open Semantics.BoundaryDynamics
open Semantics.SpikingDynamics
open Semantics.ExoticSpacetime
abbrev CriticalSiteId := UInt16
abbrev AvalancheId := UInt16
abbrev ToppleCount := UInt16
inductive PotentialRegime
| subcritical
| nearCritical
| critical
| supercritical
| dissipative
deriving Repr, DecidableEq
inductive AvalancheClass
| none
| local
| cascading
| systemWide
| recurrent
deriving Repr, DecidableEq
inductive StabilizationStatus
| stable
| unstable
| stabilizing
| dissipated
| unresolved
deriving Repr, DecidableEq
structure CriticalPotential where
load : Q16_16
threshold : Q16_16
gradient : Q16_16
dissipation : Q16_16
manifoldBias : Q16_16
deriving Repr, DecidableEq
structure CriticalSite where
siteId : CriticalSiteId
label : String
regionId : RegionId
load : Q16_16
threshold : Q16_16
capacity : UInt16
sink : Bool
manifoldWeight : Q16_16
temporalDifferential? : Option TemporalDifferential
boundaryId? : Option BoundaryId
deriving Repr, DecidableEq
structure RedistributionEdge where
sourceId : CriticalSiteId
targetId : CriticalSiteId
weight : Q16_16
gated : Bool
boundaryInfluence : Q16_16
deriving Repr, DecidableEq
structure CriticalNetwork where
sites : List CriticalSite
edges : List RedistributionEdge
defaultDissipation : Q16_16
deriving Repr, DecidableEq
structure ToppleStep where
siteId : CriticalSiteId
outgoingCount : UInt16
emittedLoad : Q16_16
remainingLoad : Q16_16
avalancheClass : AvalancheClass
deriving Repr, DecidableEq
structure Avalanche where
avalancheId : AvalancheId
seedSiteId : CriticalSiteId
steps : List ToppleStep
dischargedLoad : Q16_16
span : UInt16
class : AvalancheClass
deriving Repr, DecidableEq
structure StabilizationResult where
network : CriticalNetwork
avalanches : List Avalanche
status : StabilizationStatus
totalDischargedLoad : Q16_16
deriving Repr, DecidableEq
def potentialOf (site : CriticalSite) : CriticalPotential :=
{ load := site.load
, threshold := site.threshold
, gradient := absDiff site.load site.threshold
, dissipation := if site.sink then one else quarter
, manifoldBias := site.manifoldWeight }
def classifyPotentialRegime (potential : CriticalPotential) : PotentialRegime :=
if le potential.load (subSaturating potential.threshold quarter) then
PotentialRegime.subcritical
else if lt potential.load potential.threshold then
PotentialRegime.nearCritical
else if eq potential.load potential.threshold then
PotentialRegime.critical
else if gt potential.load (addSaturating potential.threshold half) then
PotentialRegime.supercritical
else
PotentialRegime.dissipative
def siteUnstable (site : CriticalSite) : Bool :=
ge site.load site.threshold
def edgeActive (edge : RedistributionEdge) : Bool :=
edge.gated && nonZero edge.weight
def siteEdges (network : CriticalNetwork) (siteId : CriticalSiteId) : List RedistributionEdge :=
network.edges.filter (fun edge => edge.sourceId = siteId && edgeActive edge)
def activeNeighborCount (network : CriticalNetwork) (siteId : CriticalSiteId) : UInt16 :=
UInt16.ofNat (siteEdges network siteId |>.length)
def redistributedLoadPerEdge (site : CriticalSite) (network : CriticalNetwork) : Q16_16 :=
let count := activeNeighborCount network site.siteId
if count = 0 then zero else divQ16_16 site.threshold (UInt32.ofNat count.toNat)
def toppledLoad (site : CriticalSite) : Q16_16 :=
if site.sink then site.load else site.threshold
def remainingAfterTopple (site : CriticalSite) : Q16_16 :=
if site.sink then zero else subSaturating site.load (toppledLoad site)
def classifyAvalancheClass (toppleCount : ToppleCount) (span : UInt16) : AvalancheClass :=
if toppleCount = 0 then AvalancheClass.none
else if toppleCount = 1 then AvalancheClass.local
else if toppleCount <= 4 then AvalancheClass.cascading
else if span <= 2 then AvalancheClass.recurrent
else AvalancheClass.systemWide
def toppleStepOf (site : CriticalSite) (network : CriticalNetwork) : ToppleStep :=
let count := activeNeighborCount network site.siteId
let remaining := remainingAfterTopple site
{ siteId := site.siteId
, outgoingCount := count
, emittedLoad := toppledLoad site
, remainingLoad := remaining
, avalancheClass := classifyAvalancheClass 1 (if count = 0 then 0 else 1) }
def applyToppleToSite (site : CriticalSite) : CriticalSite :=
{ site with load := remainingAfterTopple site }
def receiveLoad (site : CriticalSite) (incoming : Q16_16) : CriticalSite :=
{ site with load := addSaturating site.load incoming }
def edgeContribution (source : CriticalSite) (network : CriticalNetwork) (edge : RedistributionEdge) : Q16_16 :=
let base := redistributedLoadPerEdge source network
let boundaryAdjusted := mulQ16_16 base (subSaturating one edge.boundaryInfluence)
boundaryAdjusted
def findSite? (network : CriticalNetwork) (siteId : CriticalSiteId) : Option CriticalSite :=
network.sites.find? (fun site => site.siteId = siteId)
def rewriteSite (sites : List CriticalSite) (updated : CriticalSite) : List CriticalSite :=
sites.map (fun site => if site.siteId = updated.siteId then updated else site)
def applyIncomingForEdge (network : CriticalNetwork) (source : CriticalSite) (edge : RedistributionEdge) : CriticalNetwork :=
match findSite? network edge.targetId with
| none => network
| some targetSite =>
let incoming := edgeContribution source network edge
let updatedTarget := receiveLoad targetSite incoming
{ network with sites := rewriteSite network.sites updatedTarget }
def distributeFromSite (network : CriticalNetwork) (source : CriticalSite) : CriticalNetwork :=
let initialNetwork := { network with sites := rewriteSite network.sites (applyToppleToSite source) }
(siteEdges network source.siteId).foldl (fun acc edge => applyIncomingForEdge acc source edge) initialNetwork
def firstUnstableSite? (network : CriticalNetwork) : Option CriticalSite :=
network.sites.find? siteUnstable
def boundaryFluidityForSite (site : CriticalSite) (boundary? : Option BoundaryLayer) : BoundaryFluidity :=
match boundary? with
| none => BoundaryFluidity.rigid
| some boundary => classifyBoundaryFluidity boundary.fluidity
def temporalPotentialBias (site : CriticalSite) : Q16_16 :=
match site.temporalDifferential? with
| none => zero
| some differential => temporalGradient differential
def manifoldPotentialOf (site : CriticalSite) : Q16_16 :=
addSaturating site.manifoldWeight (temporalPotentialBias site)
def stabilizeStep (network : CriticalNetwork) : StabilizationResult :=
match firstUnstableSite? network with
| none =>
{ network := network
, avalanches := []
, status := StabilizationStatus.stable
, totalDischargedLoad := zero }
| some unstableSite =>
let step := toppleStepOf unstableSite network
let nextNetwork := distributeFromSite network unstableSite
let avalanche : Avalanche :=
{ avalancheId := unstableSite.siteId
, seedSiteId := unstableSite.siteId
, steps := [step]
, dischargedLoad := step.emittedLoad
, span := step.outgoingCount
, class := step.avalancheClass }
{ network := nextNetwork
, avalanches := [avalanche]
, status := StabilizationStatus.stabilizing
, totalDischargedLoad := step.emittedLoad }
def stabilizationStatusOf (network : CriticalNetwork) : StabilizationStatus :=
match firstUnstableSite? network with
| none => StabilizationStatus.stable
| some site => if site.sink then StabilizationStatus.dissipated else StabilizationStatus.unstable
def stableByRepeatedTopple (fuel : Nat) (network : CriticalNetwork) : StabilizationResult :=
match fuel with
| 0 =>
{ network := network
, avalanches := []
, status := StabilizationStatus.unresolved
, totalDischargedLoad := zero }
| fuel + 1 =>
let stepResult := stabilizeStep network
match stepResult.status with
| StabilizationStatus.stable => stepResult
| _ =>
let recursive := stableByRepeatedTopple fuel stepResult.network
{ network := recursive.network
, avalanches := stepResult.avalanches ++ recursive.avalanches
, status := recursive.status
, totalDischargedLoad := addSaturating stepResult.totalDischargedLoad recursive.totalDischargedLoad }
def abelianInvariantHoldsByLoadSum (before after : CriticalNetwork) : Bool :=
let sumLoads := fun (sites : List CriticalSite) => sites.foldl (fun acc site => addSaturating acc site.load) zero
le (sumLoads after.sites) (sumLoads before.sites)
def sinkSites (network : CriticalNetwork) : List CriticalSite :=
network.sites.filter (fun site => site.sink)
def criticalFrontier (network : CriticalNetwork) : List CriticalSite :=
network.sites.filter (fun site => classifyPotentialRegime (potentialOf site) = PotentialRegime.nearCritical)
def manifoldCriticalityScore (site : CriticalSite) : Q16_16 :=
addSaturating (manifoldPotentialOf site) (absDiff site.load site.threshold)
def criticalityCompatibleWithSpike (site : CriticalSite) (state : MembraneState) : Bool :=
ge site.load state.threshold || ge (manifoldCriticalityScore site) state.potential
def defaultCriticalSite (siteId : CriticalSiteId) (regionId : RegionId) : CriticalSite :=
{ siteId := siteId
, label := "critical-site"
, regionId := regionId
, load := zero
, threshold := one
, capacity := 4
, sink := false
, manifoldWeight := quarter
, temporalDifferential? := none
, boundaryId? := none }
def defaultCriticalNetwork : CriticalNetwork :=
{ sites := []
, edges := []
, defaultDissipation := quarter }
end Semantics.CriticalityDynamics