Cortex.Pulse.Fact


On this page
  1. Overview
  2. Context
  3. Theorem Split
  4. Worker Outcomes
  5. Durable Node Facts
  6. Invariant Preservation
  7. Frontier-Fold Accumulation
  8. Disjoint-Key Accumulation
Imports
import Cortex.Pulse.Frontier import Mathlib.Data.List.Pairwise import Mathlib.Data.List.Perm.Basic

Overview

Frontier workers produce node-local facts. The fixed-topology kernel only needs the node key, the resulting status, and an optional output; payload and failure detail contents remain abstract.

Context

The runtime applies a wave of frontier results by folding node-local updates into a graph state. The theorem-level fact this page needs is that two results for distinct nodes commute because they update disjoint keys.

Theorem Split

The page defines abstract worker outcomes, packages them as durable node results, and proves the disjoint-key commutativity lemma used by later frontier-fold proofs. Arbitrary node facts are not assumed safe: the Admissible predicate records the frontier precondition needed by preservation theorems.

namespace Cortex.Pulse

Worker Outcomes

NodeOutcome payload is the abstract worker outcome for a single node.

inductive NodeOutcome (payload : Type v) : Type v where | succeeded : payload NodeOutcome payload | skipped : NodeOutcome payload | suspended : NodeOutcome payload | failed : NodeOutcome payload | timedOut : NodeOutcome payload | cancelled : NodeOutcome payload | shutdown : NodeOutcome payload | runCancelled : NodeOutcome payload | rewritten : payload NodeOutcome payload deriving Reprnamespace NodeOutcomevariable {payload : Type v}

NodeOutcome.status outcome is the status contributed by an outcome.

def status : NodeOutcome payload NodeStatus | succeeded _ => NodeStatus.completed | skipped => NodeStatus.skipped | suspended => NodeStatus.waiting | failed => NodeStatus.failed | timedOut => NodeStatus.failed | cancelled => NodeStatus.interrupted | shutdown => NodeStatus.interrupted | runCancelled => NodeStatus.interrupted | rewritten _ => NodeStatus.rewritten

NodeOutcome.output outcome is the optional output contributed by an outcome.

def output : NodeOutcome payload Option payload | succeeded value => some value | rewritten value => some value | skipped => none | suspended => none | failed => none | timedOut => none | cancelled => none | shutdown => none | runCancelled => none

output_respects_status says emitted outputs match statuses that own payloads.

theorem output_respects_status (outcome : NodeOutcome payload) (value : payload) (hOutput : output outcome = some value) : NodeStatus.mayHaveOutput (status outcome) := payload:Type voutcome:NodeOutcome payloadvalue:payloadhOutput:outcome.output = some valueoutcome.status.mayHaveOutput payload:Type vvalue:payloada✝:payloadhOutput:(succeeded a✝).output = some value(succeeded a✝).status.mayHaveOutputpayload:Type vvalue:payloadhOutput:skipped.output = some valueskipped.status.mayHaveOutputpayload:Type vvalue:payloadhOutput:suspended.output = some valuesuspended.status.mayHaveOutputpayload:Type vvalue:payloadhOutput:failed.output = some valuefailed.status.mayHaveOutputpayload:Type vvalue:payloadhOutput:timedOut.output = some valuetimedOut.status.mayHaveOutputpayload:Type vvalue:payloadhOutput:cancelled.output = some valuecancelled.status.mayHaveOutputpayload:Type vvalue:payloadhOutput:shutdown.output = some valueshutdown.status.mayHaveOutputpayload:Type vvalue:payloadhOutput:runCancelled.output = some valuerunCancelled.status.mayHaveOutputpayload:Type vvalue:payloada✝:payloadhOutput:(rewritten a✝).output = some value(rewritten a✝).status.mayHaveOutput payload:Type vvalue:payloada✝:payloadhOutput:(succeeded a✝).output = some value(succeeded a✝).status.mayHaveOutputpayload:Type vvalue:payloadhOutput:skipped.output = some valueskipped.status.mayHaveOutputpayload:Type vvalue:payloadhOutput:suspended.output = some valuesuspended.status.mayHaveOutputpayload:Type vvalue:payloadhOutput:failed.output = some valuefailed.status.mayHaveOutputpayload:Type vvalue:payloadhOutput:timedOut.output = some valuetimedOut.status.mayHaveOutputpayload:Type vvalue:payloadhOutput:cancelled.output = some valuecancelled.status.mayHaveOutputpayload:Type vvalue:payloadhOutput:shutdown.output = some valueshutdown.status.mayHaveOutputpayload:Type vvalue:payloadhOutput:runCancelled.output = some valuerunCancelled.status.mayHaveOutputpayload:Type vvalue:payloada✝:payloadhOutput:(rewritten a✝).output = some value(rewritten a✝).status.mayHaveOutput All goals completed! 🐙

status_ne_running says durable worker outcomes never write running.

theorem status_ne_running (outcome : NodeOutcome payload) : status outcome NodeStatus.running := payload:Type voutcome:NodeOutcome payloadoutcome.status NodeStatus.running payload:Type va✝:payload(succeeded a✝).status NodeStatus.runningpayload:Type vskipped.status NodeStatus.runningpayload:Type vsuspended.status NodeStatus.runningpayload:Type vfailed.status NodeStatus.runningpayload:Type vtimedOut.status NodeStatus.runningpayload:Type vcancelled.status NodeStatus.runningpayload:Type vshutdown.status NodeStatus.runningpayload:Type vrunCancelled.status NodeStatus.runningpayload:Type va✝:payload(rewritten a✝).status NodeStatus.running payload:Type va✝:payload(succeeded a✝).status NodeStatus.runningpayload:Type vskipped.status NodeStatus.runningpayload:Type vsuspended.status NodeStatus.runningpayload:Type vfailed.status NodeStatus.runningpayload:Type vtimedOut.status NodeStatus.runningpayload:Type vcancelled.status NodeStatus.runningpayload:Type vshutdown.status NodeStatus.runningpayload:Type vrunCancelled.status NodeStatus.runningpayload:Type va✝:payload(rewritten a✝).status NodeStatus.running All goals completed! 🐙end NodeOutcome

Durable Node Facts

NodeResult ν payload is the durable fact emitted for one node.

structure NodeResult (ν : Type u) (payload : Type v) where

node is the state key updated by this fact.

node : ν

outcome is the abstract result for the node.

outcome : NodeOutcome payloadnamespace NodeResultvariable {ν : Type u} {payload : Type v}

InTopology G result says a durable node fact targets a topology node.

def InTopology (G : DAG ν) (result : NodeResult ν payload) : Prop := result.node G.nodes

Admissible G state result says a node fact came from the executable frontier.

def Admissible (G : DAG ν) (state : GraphState ν payload) (result : NodeResult ν payload) : Prop := InTopology G result DirectReady G state result.node

admissible_inTopology extracts the topology target precondition.

theorem admissible_inTopology {G : DAG ν} {state : GraphState ν payload} {result : NodeResult ν payload} (hResult : Admissible G state result) : InTopology G result := hResult.1

admissible_directReady extracts the executable-frontier precondition.

theorem admissible_directReady {G : DAG ν} {state : GraphState ν payload} {result : NodeResult ν payload} (hResult : Admissible G state result) : DirectReady G state result.node := hResult.2

admissible_ready turns an admissible runtime fact into proof-level readiness.

theorem admissible_ready (G : DAG ν) (state : GraphState ν payload) (result : NodeResult ν payload) (hCausal : CausalHistoryClosed G state) (hResult : Admissible G state result) : Ready G state result.node := directReady_ready_of_causalHistoryClosed G state hCausal hResult.2

applyNodeFact result state applies a node-local fact to the graph state.

def applyNodeFact [DecidableEq ν] (result : NodeResult ν payload) (state : GraphState ν payload) : GraphState ν payload where status := fun n => if n = result.node then result.outcome.status else state.status n output := fun n => if n = result.node then result.outcome.output else state.output n

Invariant Preservation

applyNodeFact_preserves_topologyDomain preserves off-topology absence.

theorem applyNodeFact_preserves_topologyDomain [DecidableEq ν] (G : DAG ν) (result : NodeResult ν payload) (state : GraphState ν payload) (hDomain : GraphState.topologyDomain G state) (hResult : InTopology G result) : GraphState.topologyDomain G (applyNodeFact result state) := ν:Type upayload:Type vinst✝:DecidableEq νG:DAG νresult:NodeResult ν payloadstate:GraphState ν payloadhDomain:GraphState.topologyDomain G statehResult:InTopology G resultGraphState.topologyDomain G (result.applyNodeFact state) intro node ν:Type upayload:Type vinst✝:DecidableEq νG:DAG νresult:NodeResult ν payloadstate:GraphState ν payloadhDomain:GraphState.topologyDomain G statehResult:InTopology G resultnode:νhNotMem:node G.nodes(result.applyNodeFact state).status node = NodeStatus.pending (result.applyNodeFact state).output node = none ν:Type upayload:Type vinst✝:DecidableEq νG:DAG νresult:NodeResult ν payloadstate:GraphState ν payloadhDomain:GraphState.topologyDomain G statehResult:InTopology G resultnode:νhNotMem:node G.nodeshNode:node = result.node(result.applyNodeFact state).status node = NodeStatus.pending (result.applyNodeFact state).output node = noneν:Type upayload:Type vinst✝:DecidableEq νG:DAG νresult:NodeResult ν payloadstate:GraphState ν payloadhDomain:GraphState.topologyDomain G statehResult:InTopology G resultnode:νhNotMem:node G.nodeshNode:¬node = result.node(result.applyNodeFact state).status node = NodeStatus.pending (result.applyNodeFact state).output node = none ν:Type upayload:Type vinst✝:DecidableEq νG:DAG νresult:NodeResult ν payloadstate:GraphState ν payloadhDomain:GraphState.topologyDomain G statehResult:InTopology G resultnode:νhNotMem:node G.nodeshNode:node = result.node(result.applyNodeFact state).status node = NodeStatus.pending (result.applyNodeFact state).output node = none ν:Type upayload:Type vinst✝:DecidableEq νG:DAG νresult:NodeResult ν payloadstate:GraphState ν payloadhDomain:GraphState.topologyDomain G statehResult:InTopology G resulthNotMem:result.node G.nodes(result.applyNodeFact state).status result.node = NodeStatus.pending (result.applyNodeFact state).output result.node = none All goals completed! 🐙 ν:Type upayload:Type vinst✝:DecidableEq νG:DAG νresult:NodeResult ν payloadstate:GraphState ν payloadhDomain:GraphState.topologyDomain G statehResult:InTopology G resultnode:νhNotMem:node G.nodeshNode:¬node = result.node(result.applyNodeFact state).status node = NodeStatus.pending (result.applyNodeFact state).output node = none ν:Type upayload:Type vinst✝:DecidableEq νG:DAG νresult:NodeResult ν payloadstate:GraphState ν payloadhDomain:GraphState.topologyDomain G statehResult:InTopology G resultnode:νhNotMem:node G.nodeshNode:¬node = result.nodehStatus:state.status node = NodeStatus.pendinghOutput:state.output node = none(result.applyNodeFact state).status node = NodeStatus.pending (result.applyNodeFact state).output node = none ν:Type upayload:Type vinst✝:DecidableEq νG:DAG νresult:NodeResult ν payloadstate:GraphState ν payloadhDomain:GraphState.topologyDomain G statehResult:InTopology G resultnode:νhNotMem:node G.nodeshNode:¬node = result.nodehStatus:state.status node = NodeStatus.pendinghOutput:state.output node = none(result.applyNodeFact state).status node = NodeStatus.pendingν:Type upayload:Type vinst✝:DecidableEq νG:DAG νresult:NodeResult ν payloadstate:GraphState ν payloadhDomain:GraphState.topologyDomain G statehResult:InTopology G resultnode:νhNotMem:node G.nodeshNode:¬node = result.nodehStatus:state.status node = NodeStatus.pendinghOutput:state.output node = none(result.applyNodeFact state).output node = none ν:Type upayload:Type vinst✝:DecidableEq νG:DAG νresult:NodeResult ν payloadstate:GraphState ν payloadhDomain:GraphState.topologyDomain G statehResult:InTopology G resultnode:νhNotMem:node G.nodeshNode:¬node = result.nodehStatus:state.status node = NodeStatus.pendinghOutput:state.output node = none(result.applyNodeFact state).status node = NodeStatus.pending All goals completed! 🐙 ν:Type upayload:Type vinst✝:DecidableEq νG:DAG νresult:NodeResult ν payloadstate:GraphState ν payloadhDomain:GraphState.topologyDomain G statehResult:InTopology G resultnode:νhNotMem:node G.nodeshNode:¬node = result.nodehStatus:state.status node = NodeStatus.pendinghOutput:state.output node = none(result.applyNodeFact state).output node = none All goals completed! 🐙

applyNodeFact_preserves_outputsRespectStatuses preserves output ownership.

theorem applyNodeFact_preserves_outputsRespectStatuses [DecidableEq ν] (result : NodeResult ν payload) (state : GraphState ν payload) (hOutputs : GraphState.outputsRespectStatuses state) : GraphState.outputsRespectStatuses (applyNodeFact result state) := ν:Type upayload:Type vinst✝:DecidableEq νresult:NodeResult ν payloadstate:GraphState ν payloadhOutputs:state.outputsRespectStatuses(result.applyNodeFact state).outputsRespectStatuses intro node ν:Type upayload:Type vinst✝:DecidableEq νresult:NodeResult ν payloadstate:GraphState ν payloadhOutputs:state.outputsRespectStatusesnode:νvalue:payload(result.applyNodeFact state).output node = some value ((result.applyNodeFact state).status node).mayHaveOutput ν:Type upayload:Type vinst✝:DecidableEq νresult:NodeResult ν payloadstate:GraphState ν payloadhOutputs:state.outputsRespectStatusesnode:νvalue:payloadhOutput:(result.applyNodeFact state).output node = some value((result.applyNodeFact state).status node).mayHaveOutput ν:Type upayload:Type vinst✝:DecidableEq νresult:NodeResult ν payloadstate:GraphState ν payloadhOutputs:state.outputsRespectStatusesnode:νvalue:payloadhOutput:(result.applyNodeFact state).output node = some valuehNode:node = result.node((result.applyNodeFact state).status node).mayHaveOutputν:Type upayload:Type vinst✝:DecidableEq νresult:NodeResult ν payloadstate:GraphState ν payloadhOutputs:state.outputsRespectStatusesnode:νvalue:payloadhOutput:(result.applyNodeFact state).output node = some valuehNode:¬node = result.node((result.applyNodeFact state).status node).mayHaveOutput ν:Type upayload:Type vinst✝:DecidableEq νresult:NodeResult ν payloadstate:GraphState ν payloadhOutputs:state.outputsRespectStatusesnode:νvalue:payloadhOutput:(result.applyNodeFact state).output node = some valuehNode:node = result.node((result.applyNodeFact state).status node).mayHaveOutput ν:Type upayload:Type vinst✝:DecidableEq νresult:NodeResult ν payloadstate:GraphState ν payloadhOutputs:state.outputsRespectStatusesvalue:payloadhOutput:(result.applyNodeFact state).output result.node = some value((result.applyNodeFact state).status result.node).mayHaveOutput ν:Type upayload:Type vinst✝:DecidableEq νresult:NodeResult ν payloadstate:GraphState ν payloadhOutputs:state.outputsRespectStatusesvalue:payloadhOutput:result.outcome.output = some valueresult.outcome.status.mayHaveOutput All goals completed! 🐙 ν:Type upayload:Type vinst✝:DecidableEq νresult:NodeResult ν payloadstate:GraphState ν payloadhOutputs:state.outputsRespectStatusesnode:νvalue:payloadhOutput:(result.applyNodeFact state).output node = some valuehNode:¬node = result.node((result.applyNodeFact state).status node).mayHaveOutput have hOriginalOutput : state.output node = some value := ν:Type upayload:Type vinst✝:DecidableEq νresult:NodeResult ν payloadstate:GraphState ν payloadhOutputs:state.outputsRespectStatuses(result.applyNodeFact state).outputsRespectStatuses All goals completed! 🐙 ν:Type upayload:Type vinst✝:DecidableEq νresult:NodeResult ν payloadstate:GraphState ν payloadhOutputs:state.outputsRespectStatusesnode:νvalue:payloadhOutput:(result.applyNodeFact state).output node = some valuehNode:¬node = result.nodehOriginalOutput:state.output node = some valuehMayHaveOutput:(state.status node).mayHaveOutput((result.applyNodeFact state).status node).mayHaveOutput All goals completed! 🐙

applyNodeFact_preserves_outputsCompleteForStatuses preserves required outputs.

theorem applyNodeFact_preserves_outputsCompleteForStatuses [DecidableEq ν] (result : NodeResult ν payload) (state : GraphState ν payload) (hOutputs : GraphState.outputsCompleteForStatuses state) : GraphState.outputsCompleteForStatuses (applyNodeFact result state) := ν:Type upayload:Type vinst✝:DecidableEq νresult:NodeResult ν payloadstate:GraphState ν payloadhOutputs:state.outputsCompleteForStatuses(result.applyNodeFact state).outputsCompleteForStatuses intro node ν:Type upayload:Type vinst✝:DecidableEq νresult:NodeResult ν payloadstate:GraphState ν payloadhOutputs:state.outputsCompleteForStatusesnode:νhRequiresOutput:((result.applyNodeFact state).status node).requiresOutput value, (result.applyNodeFact state).output node = some value ν:Type upayload:Type vinst✝:DecidableEq νresult:NodeResult ν payloadstate:GraphState ν payloadhOutputs:state.outputsCompleteForStatusesnode:νhRequiresOutput:((result.applyNodeFact state).status node).requiresOutputhNode:node = result.node value, (result.applyNodeFact state).output node = some valueν:Type upayload:Type vinst✝:DecidableEq νresult:NodeResult ν payloadstate:GraphState ν payloadhOutputs:state.outputsCompleteForStatusesnode:νhRequiresOutput:((result.applyNodeFact state).status node).requiresOutputhNode:¬node = result.node value, (result.applyNodeFact state).output node = some value ν:Type upayload:Type vinst✝:DecidableEq νresult:NodeResult ν payloadstate:GraphState ν payloadhOutputs:state.outputsCompleteForStatusesnode:νhRequiresOutput:((result.applyNodeFact state).status node).requiresOutputhNode:node = result.node value, (result.applyNodeFact state).output node = some value ν:Type upayload:Type vinst✝:DecidableEq νresult:NodeResult ν payloadstate:GraphState ν payloadhOutputs:state.outputsCompleteForStatuseshRequiresOutput:((result.applyNodeFact state).status result.node).requiresOutput value, (result.applyNodeFact state).output result.node = some value cases hOutcome : result.outcome with ν:Type upayload:Type vinst✝:DecidableEq νresult:NodeResult ν payloadstate:GraphState ν payloadhOutputs:state.outputsCompleteForStatuseshRequiresOutput:((result.applyNodeFact state).status result.node).requiresOutputvalue:payloadhOutcome:result.outcome = NodeOutcome.succeeded value value, (result.applyNodeFact state).output result.node = some value exact value, ν:Type upayload:Type vinst✝:DecidableEq νresult:NodeResult ν payloadstate:GraphState ν payloadhOutputs:state.outputsCompleteForStatuseshRequiresOutput:((result.applyNodeFact state).status result.node).requiresOutputvalue:payloadhOutcome:result.outcome = NodeOutcome.succeeded value(result.applyNodeFact state).output result.node = some value All goals completed! 🐙 ν:Type upayload:Type vinst✝:DecidableEq νresult:NodeResult ν payloadstate:GraphState ν payloadhOutputs:state.outputsCompleteForStatuseshRequiresOutput:((result.applyNodeFact state).status result.node).requiresOutputhOutcome:result.outcome = NodeOutcome.skipped value, (result.applyNodeFact state).output result.node = some value All goals completed! 🐙 ν:Type upayload:Type vinst✝:DecidableEq νresult:NodeResult ν payloadstate:GraphState ν payloadhOutputs:state.outputsCompleteForStatuseshRequiresOutput:((result.applyNodeFact state).status result.node).requiresOutputhOutcome:result.outcome = NodeOutcome.suspended value, (result.applyNodeFact state).output result.node = some value All goals completed! 🐙 ν:Type upayload:Type vinst✝:DecidableEq νresult:NodeResult ν payloadstate:GraphState ν payloadhOutputs:state.outputsCompleteForStatuseshRequiresOutput:((result.applyNodeFact state).status result.node).requiresOutputhOutcome:result.outcome = NodeOutcome.failed value, (result.applyNodeFact state).output result.node = some value All goals completed! 🐙 ν:Type upayload:Type vinst✝:DecidableEq νresult:NodeResult ν payloadstate:GraphState ν payloadhOutputs:state.outputsCompleteForStatuseshRequiresOutput:((result.applyNodeFact state).status result.node).requiresOutputhOutcome:result.outcome = NodeOutcome.timedOut value, (result.applyNodeFact state).output result.node = some value All goals completed! 🐙 ν:Type upayload:Type vinst✝:DecidableEq νresult:NodeResult ν payloadstate:GraphState ν payloadhOutputs:state.outputsCompleteForStatuseshRequiresOutput:((result.applyNodeFact state).status result.node).requiresOutputhOutcome:result.outcome = NodeOutcome.cancelled value, (result.applyNodeFact state).output result.node = some value All goals completed! 🐙 ν:Type upayload:Type vinst✝:DecidableEq νresult:NodeResult ν payloadstate:GraphState ν payloadhOutputs:state.outputsCompleteForStatuseshRequiresOutput:((result.applyNodeFact state).status result.node).requiresOutputhOutcome:result.outcome = NodeOutcome.shutdown value, (result.applyNodeFact state).output result.node = some value All goals completed! 🐙 ν:Type upayload:Type vinst✝:DecidableEq νresult:NodeResult ν payloadstate:GraphState ν payloadhOutputs:state.outputsCompleteForStatuseshRequiresOutput:((result.applyNodeFact state).status result.node).requiresOutputhOutcome:result.outcome = NodeOutcome.runCancelled value, (result.applyNodeFact state).output result.node = some value All goals completed! 🐙 ν:Type upayload:Type vinst✝:DecidableEq νresult:NodeResult ν payloadstate:GraphState ν payloadhOutputs:state.outputsCompleteForStatuseshRequiresOutput:((result.applyNodeFact state).status result.node).requiresOutputvalue:payloadhOutcome:result.outcome = NodeOutcome.rewritten value value, (result.applyNodeFact state).output result.node = some value exact value, ν:Type upayload:Type vinst✝:DecidableEq νresult:NodeResult ν payloadstate:GraphState ν payloadhOutputs:state.outputsCompleteForStatuseshRequiresOutput:((result.applyNodeFact state).status result.node).requiresOutputvalue:payloadhOutcome:result.outcome = NodeOutcome.rewritten value(result.applyNodeFact state).output result.node = some value All goals completed! 🐙 ν:Type upayload:Type vinst✝:DecidableEq νresult:NodeResult ν payloadstate:GraphState ν payloadhOutputs:state.outputsCompleteForStatusesnode:νhRequiresOutput:((result.applyNodeFact state).status node).requiresOutputhNode:¬node = result.node value, (result.applyNodeFact state).output node = some value have hOriginalRequires : NodeStatus.requiresOutput (state.status node) := ν:Type upayload:Type vinst✝:DecidableEq νresult:NodeResult ν payloadstate:GraphState ν payloadhOutputs:state.outputsCompleteForStatuses(result.applyNodeFact state).outputsCompleteForStatuses All goals completed! 🐙 ν:Type upayload:Type vinst✝:DecidableEq νresult:NodeResult ν payloadstate:GraphState ν payloadhOutputs:state.outputsCompleteForStatusesnode:νhRequiresOutput:((result.applyNodeFact state).status node).requiresOutputhNode:¬node = result.nodehOriginalRequires:(state.status node).requiresOutputvalue:payloadhOutput:state.output node = some value value, (result.applyNodeFact state).output node = some value exact value, ν:Type upayload:Type vinst✝:DecidableEq νresult:NodeResult ν payloadstate:GraphState ν payloadhOutputs:state.outputsCompleteForStatusesnode:νhRequiresOutput:((result.applyNodeFact state).status node).requiresOutputhNode:¬node = result.nodehOriginalRequires:(state.status node).requiresOutputvalue:payloadhOutput:state.output node = some value(result.applyNodeFact state).output node = some value All goals completed! 🐙

applyNodeFact_preserves_noRunning preserves the absence of running nodes.

theorem applyNodeFact_preserves_noRunning [DecidableEq ν] (result : NodeResult ν payload) (state : GraphState ν payload) (hNoRunning : GraphState.noRunningNodes state) : GraphState.noRunningNodes (applyNodeFact result state) := ν:Type upayload:Type vinst✝:DecidableEq νresult:NodeResult ν payloadstate:GraphState ν payloadhNoRunning:state.noRunningNodes(result.applyNodeFact state).noRunningNodes ν:Type upayload:Type vinst✝:DecidableEq νresult:NodeResult ν payloadstate:GraphState ν payloadhNoRunning:state.noRunningNodesnode:ν(result.applyNodeFact state).status node NodeStatus.running ν:Type upayload:Type vinst✝:DecidableEq νresult:NodeResult ν payloadstate:GraphState ν payloadhNoRunning:state.noRunningNodesnode:νhNode:node = result.node(result.applyNodeFact state).status node NodeStatus.runningν:Type upayload:Type vinst✝:DecidableEq νresult:NodeResult ν payloadstate:GraphState ν payloadhNoRunning:state.noRunningNodesnode:νhNode:¬node = result.node(result.applyNodeFact state).status node NodeStatus.running ν:Type upayload:Type vinst✝:DecidableEq νresult:NodeResult ν payloadstate:GraphState ν payloadhNoRunning:state.noRunningNodesnode:νhNode:node = result.node(result.applyNodeFact state).status node NodeStatus.running ν:Type upayload:Type vinst✝:DecidableEq νresult:NodeResult ν payloadstate:GraphState ν payloadhNoRunning:state.noRunningNodes(result.applyNodeFact state).status result.node NodeStatus.running All goals completed! 🐙 ν:Type upayload:Type vinst✝:DecidableEq νresult:NodeResult ν payloadstate:GraphState ν payloadhNoRunning:state.noRunningNodesnode:νhNode:¬node = result.node(result.applyNodeFact state).status node NodeStatus.running All goals completed! 🐙

applyNodeFact_preserves_causalHistoryClosed preserves causal history for admissible facts.

theorem applyNodeFact_preserves_causalHistoryClosed [DecidableEq ν] (G : DAG ν) (result : NodeResult ν payload) (state : GraphState ν payload) (hCausal : CausalHistoryClosed G state) (hResult : Admissible G state result) : CausalHistoryClosed G (applyNodeFact result state) := ν:Type upayload:Type vinst✝:DecidableEq νG:DAG νresult:NodeResult ν payloadstate:GraphState ν payloadhCausal:CausalHistoryClosed G statehResult:Admissible G state resultCausalHistoryClosed G (result.applyNodeFact state) classical ν:Type upayload:Type vinst✝:DecidableEq νG:DAG νresult:NodeResult ν payloadstate:GraphState ν payloadhCausal:CausalHistoryClosed G statehResult:Admissible G state resulthReady:Ready G state result.nodeCausalHistoryClosed G (result.applyNodeFact state) intro node ν:Type upayload:Type vinst✝:DecidableEq νG:DAG νresult:NodeResult ν payloadstate:GraphState ν payloadhCausal:CausalHistoryClosed G statehResult:Admissible G state resulthReady:Ready G state result.nodenode:νhUnblocks:((result.applyNodeFact state).status node).unblocksSuccessors (predecessor : ν), G.reaches predecessor node ((result.applyNodeFact state).status predecessor).terminal ν:Type upayload:Type vinst✝:DecidableEq νG:DAG νresult:NodeResult ν payloadstate:GraphState ν payloadhCausal:CausalHistoryClosed G statehResult:Admissible G state resulthReady:Ready G state result.nodenode:νhUnblocks:((result.applyNodeFact state).status node).unblocksSuccessorspredecessor:νG.reaches predecessor node ((result.applyNodeFact state).status predecessor).terminal ν:Type upayload:Type vinst✝:DecidableEq νG:DAG νresult:NodeResult ν payloadstate:GraphState ν payloadhCausal:CausalHistoryClosed G statehResult:Admissible G state resulthReady:Ready G state result.nodenode:νhUnblocks:((result.applyNodeFact state).status node).unblocksSuccessorspredecessor:νhReach:G.reaches predecessor node((result.applyNodeFact state).status predecessor).terminal ν:Type upayload:Type vinst✝:DecidableEq νG:DAG νresult:NodeResult ν payloadstate:GraphState ν payloadhCausal:CausalHistoryClosed G statehResult:Admissible G state resulthReady:Ready G state result.nodenode:νhUnblocks:((result.applyNodeFact state).status node).unblocksSuccessorspredecessor:νhReach:G.reaches predecessor nodehNode:node = result.node((result.applyNodeFact state).status predecessor).terminalν:Type upayload:Type vinst✝:DecidableEq νG:DAG νresult:NodeResult ν payloadstate:GraphState ν payloadhCausal:CausalHistoryClosed G statehResult:Admissible G state resulthReady:Ready G state result.nodenode:νhUnblocks:((result.applyNodeFact state).status node).unblocksSuccessorspredecessor:νhReach:G.reaches predecessor nodehNode:¬node = result.node((result.applyNodeFact state).status predecessor).terminal ν:Type upayload:Type vinst✝:DecidableEq νG:DAG νresult:NodeResult ν payloadstate:GraphState ν payloadhCausal:CausalHistoryClosed G statehResult:Admissible G state resulthReady:Ready G state result.nodenode:νhUnblocks:((result.applyNodeFact state).status node).unblocksSuccessorspredecessor:νhReach:G.reaches predecessor nodehNode:node = result.node((result.applyNodeFact state).status predecessor).terminal ν:Type upayload:Type vinst✝:DecidableEq νG:DAG νresult:NodeResult ν payloadstate:GraphState ν payloadhCausal:CausalHistoryClosed G statehResult:Admissible G state resulthReady:Ready G state result.nodepredecessor:νhUnblocks:((result.applyNodeFact state).status result.node).unblocksSuccessorshReach:G.reaches predecessor result.node((result.applyNodeFact state).status predecessor).terminal ν:Type upayload:Type vinst✝:DecidableEq νG:DAG νresult:NodeResult ν payloadstate:GraphState ν payloadhCausal:CausalHistoryClosed G statehResult:Admissible G state resulthReady:Ready G state result.nodepredecessor:νhUnblocks:((result.applyNodeFact state).status result.node).unblocksSuccessorshReach:G.reaches predecessor result.nodehPred:predecessor = result.node((result.applyNodeFact state).status predecessor).terminalν:Type upayload:Type vinst✝:DecidableEq νG:DAG νresult:NodeResult ν payloadstate:GraphState ν payloadhCausal:CausalHistoryClosed G statehResult:Admissible G state resulthReady:Ready G state result.nodepredecessor:νhUnblocks:((result.applyNodeFact state).status result.node).unblocksSuccessorshReach:G.reaches predecessor result.nodehPred:¬predecessor = result.node((result.applyNodeFact state).status predecessor).terminal ν:Type upayload:Type vinst✝:DecidableEq νG:DAG νresult:NodeResult ν payloadstate:GraphState ν payloadhCausal:CausalHistoryClosed G statehResult:Admissible G state resulthReady:Ready G state result.nodepredecessor:νhUnblocks:((result.applyNodeFact state).status result.node).unblocksSuccessorshReach:G.reaches predecessor result.nodehPred:predecessor = result.node((result.applyNodeFact state).status predecessor).terminal ν:Type upayload:Type vinst✝:DecidableEq νG:DAG νresult:NodeResult ν payloadstate:GraphState ν payloadhCausal:CausalHistoryClosed G statehResult:Admissible G state resulthReady:Ready G state result.nodehUnblocks:((result.applyNodeFact state).status result.node).unblocksSuccessorshReach:G.reaches result.node result.node((result.applyNodeFact state).status result.node).terminal All goals completed! 🐙 ν:Type upayload:Type vinst✝:DecidableEq νG:DAG νresult:NodeResult ν payloadstate:GraphState ν payloadhCausal:CausalHistoryClosed G statehResult:Admissible G state resulthReady:Ready G state result.nodepredecessor:νhUnblocks:((result.applyNodeFact state).status result.node).unblocksSuccessorshReach:G.reaches predecessor result.nodehPred:¬predecessor = result.node((result.applyNodeFact state).status predecessor).terminal ν:Type upayload:Type vinst✝:DecidableEq νG:DAG νresult:NodeResult ν payloadstate:GraphState ν payloadhCausal:CausalHistoryClosed G statehResult:Admissible G state resulthReady:Ready G state result.nodepredecessor:νhUnblocks:((result.applyNodeFact state).status result.node).unblocksSuccessorshReach:G.reaches predecessor result.nodehPred:¬predecessor = result.nodehOriginalTerminal:(state.status predecessor).terminal((result.applyNodeFact state).status predecessor).terminal All goals completed! 🐙 ν:Type upayload:Type vinst✝:DecidableEq νG:DAG νresult:NodeResult ν payloadstate:GraphState ν payloadhCausal:CausalHistoryClosed G statehResult:Admissible G state resulthReady:Ready G state result.nodenode:νhUnblocks:((result.applyNodeFact state).status node).unblocksSuccessorspredecessor:νhReach:G.reaches predecessor nodehNode:¬node = result.node((result.applyNodeFact state).status predecessor).terminal have hOriginalUnblocks : NodeStatus.unblocksSuccessors (state.status node) := ν:Type upayload:Type vinst✝:DecidableEq νG:DAG νresult:NodeResult ν payloadstate:GraphState ν payloadhCausal:CausalHistoryClosed G statehResult:Admissible G state resultCausalHistoryClosed G (result.applyNodeFact state) All goals completed! 🐙 ν:Type upayload:Type vinst✝:DecidableEq νG:DAG νresult:NodeResult ν payloadstate:GraphState ν payloadhCausal:CausalHistoryClosed G statehResult:Admissible G state resulthReady:Ready G state result.nodenode:νhUnblocks:((result.applyNodeFact state).status node).unblocksSuccessorspredecessor:νhReach:G.reaches predecessor nodehNode:¬node = result.nodehOriginalUnblocks:(state.status node).unblocksSuccessorshPred:predecessor = result.node((result.applyNodeFact state).status predecessor).terminalν:Type upayload:Type vinst✝:DecidableEq νG:DAG νresult:NodeResult ν payloadstate:GraphState ν payloadhCausal:CausalHistoryClosed G statehResult:Admissible G state resulthReady:Ready G state result.nodenode:νhUnblocks:((result.applyNodeFact state).status node).unblocksSuccessorspredecessor:νhReach:G.reaches predecessor nodehNode:¬node = result.nodehOriginalUnblocks:(state.status node).unblocksSuccessorshPred:¬predecessor = result.node((result.applyNodeFact state).status predecessor).terminal ν:Type upayload:Type vinst✝:DecidableEq νG:DAG νresult:NodeResult ν payloadstate:GraphState ν payloadhCausal:CausalHistoryClosed G statehResult:Admissible G state resulthReady:Ready G state result.nodenode:νhUnblocks:((result.applyNodeFact state).status node).unblocksSuccessorspredecessor:νhReach:G.reaches predecessor nodehNode:¬node = result.nodehOriginalUnblocks:(state.status node).unblocksSuccessorshPred:predecessor = result.node((result.applyNodeFact state).status predecessor).terminal ν:Type upayload:Type vinst✝:DecidableEq νG:DAG νresult:NodeResult ν payloadstate:GraphState ν payloadhCausal:CausalHistoryClosed G statehResult:Admissible G state resulthReady:Ready G state result.nodenode:νhUnblocks:((result.applyNodeFact state).status node).unblocksSuccessorshNode:¬node = result.nodehOriginalUnblocks:(state.status node).unblocksSuccessorshReach:G.reaches result.node node((result.applyNodeFact state).status result.node).terminal ν:Type upayload:Type vinst✝:DecidableEq νG:DAG νresult:NodeResult ν payloadstate:GraphState ν payloadhCausal:CausalHistoryClosed G statehResult:Admissible G state resulthReady:Ready G state result.nodenode:νhUnblocks:((result.applyNodeFact state).status node).unblocksSuccessorshNode:¬node = result.nodehOriginalUnblocks:(state.status node).unblocksSuccessorshReach:G.reaches result.node nodehOriginalTerminal:(state.status result.node).terminal((result.applyNodeFact state).status result.node).terminal have hPendingTerminal : NodeStatus.terminal NodeStatus.pending := ν:Type upayload:Type vinst✝:DecidableEq νG:DAG νresult:NodeResult ν payloadstate:GraphState ν payloadhCausal:CausalHistoryClosed G statehResult:Admissible G state resultCausalHistoryClosed G (result.applyNodeFact state) All goals completed! 🐙 All goals completed! 🐙 ν:Type upayload:Type vinst✝:DecidableEq νG:DAG νresult:NodeResult ν payloadstate:GraphState ν payloadhCausal:CausalHistoryClosed G statehResult:Admissible G state resulthReady:Ready G state result.nodenode:νhUnblocks:((result.applyNodeFact state).status node).unblocksSuccessorspredecessor:νhReach:G.reaches predecessor nodehNode:¬node = result.nodehOriginalUnblocks:(state.status node).unblocksSuccessorshPred:¬predecessor = result.node((result.applyNodeFact state).status predecessor).terminal ν:Type upayload:Type vinst✝:DecidableEq νG:DAG νresult:NodeResult ν payloadstate:GraphState ν payloadhCausal:CausalHistoryClosed G statehResult:Admissible G state resulthReady:Ready G state result.nodenode:νhUnblocks:((result.applyNodeFact state).status node).unblocksSuccessorspredecessor:νhReach:G.reaches predecessor nodehNode:¬node = result.nodehOriginalUnblocks:(state.status node).unblocksSuccessorshPred:¬predecessor = result.nodehOriginalTerminal:(state.status predecessor).terminal((result.applyNodeFact state).status predecessor).terminal All goals completed! 🐙

Frontier-Fold Accumulation

applyNodeFacts results state folds node-local facts in list order.

def applyNodeFacts [DecidableEq ν] (results : List (NodeResult ν payload)) (state : GraphState ν payload) : GraphState ν payload := results.foldl (fun current result => applyNodeFact result current) state

AllAdmissibleFold G state results requires each folded fact to be frontier-admissible.

def AllAdmissibleFold [DecidableEq ν] (G : DAG ν) : GraphState ν payload List (NodeResult ν payload) Prop | _state, [] => True | state, result :: rest => Admissible G state result AllAdmissibleFold G (applyNodeFact result state) rest

applyNodeFacts_preserves_topologyDomain preserves off-topology absence.

theorem applyNodeFacts_preserves_topologyDomain [DecidableEq ν] (G : DAG ν) (results : List (NodeResult ν payload)) (state : GraphState ν payload) (hDomain : GraphState.topologyDomain G state) (hResults : AllAdmissibleFold G state results) : GraphState.topologyDomain G (applyNodeFacts results state) := ν:Type upayload:Type vinst✝:DecidableEq νG:DAG νresults:List (NodeResult ν payload)state:GraphState ν payloadhDomain:GraphState.topologyDomain G statehResults:AllAdmissibleFold G state resultsGraphState.topologyDomain G (applyNodeFacts results state) induction results generalizing state with ν:Type upayload:Type vinst✝:DecidableEq νG:DAG νstate:GraphState ν payloadhDomain:GraphState.topologyDomain G statehResults:AllAdmissibleFold G state []GraphState.topologyDomain G (applyNodeFacts [] state) All goals completed! 🐙 ν:Type upayload:Type vinst✝:DecidableEq νG:DAG νresult:NodeResult ν payloadrest:List (NodeResult ν payload)ih: (state : GraphState ν payload), GraphState.topologyDomain G state AllAdmissibleFold G state rest GraphState.topologyDomain G (applyNodeFacts rest state)state:GraphState ν payloadhDomain:GraphState.topologyDomain G statehResults:AllAdmissibleFold G state (result :: rest)GraphState.topologyDomain G (applyNodeFacts (result :: rest) state) ν:Type upayload:Type vinst✝:DecidableEq νG:DAG νresult:NodeResult ν payloadrest:List (NodeResult ν payload)ih: (state : GraphState ν payload), GraphState.topologyDomain G state AllAdmissibleFold G state rest GraphState.topologyDomain G (applyNodeFacts rest state)state:GraphState ν payloadhDomain:GraphState.topologyDomain G statehResult:Admissible G state resulthRest:AllAdmissibleFold G (result.applyNodeFact state) restGraphState.topologyDomain G (applyNodeFacts (result :: rest) state) ν:Type upayload:Type vinst✝:DecidableEq νG:DAG νresult:NodeResult ν payloadrest:List (NodeResult ν payload)ih: (state : GraphState ν payload), GraphState.topologyDomain G state AllAdmissibleFold G state rest GraphState.topologyDomain G (applyNodeFacts rest state)state:GraphState ν payloadhDomain:GraphState.topologyDomain G statehResult:Admissible G state resulthRest:AllAdmissibleFold G (result.applyNodeFact state) resthStep:GraphState.topologyDomain G (result.applyNodeFact state)GraphState.topologyDomain G (applyNodeFacts (result :: rest) state) All goals completed! 🐙

applyNodeFacts_preserves_outputsRespectStatuses preserves output ownership.

theorem applyNodeFacts_preserves_outputsRespectStatuses [DecidableEq ν] (G : DAG ν) (results : List (NodeResult ν payload)) (state : GraphState ν payload) (hOutputs : GraphState.outputsRespectStatuses state) (hResults : AllAdmissibleFold G state results) : GraphState.outputsRespectStatuses (applyNodeFacts results state) := ν:Type upayload:Type vinst✝:DecidableEq νG:DAG νresults:List (NodeResult ν payload)state:GraphState ν payloadhOutputs:state.outputsRespectStatuseshResults:AllAdmissibleFold G state results(applyNodeFacts results state).outputsRespectStatuses induction results generalizing state with ν:Type upayload:Type vinst✝:DecidableEq νG:DAG νstate:GraphState ν payloadhOutputs:state.outputsRespectStatuseshResults:AllAdmissibleFold G state [](applyNodeFacts [] state).outputsRespectStatuses All goals completed! 🐙 ν:Type upayload:Type vinst✝:DecidableEq νG:DAG νresult:NodeResult ν payloadrest:List (NodeResult ν payload)ih: (state : GraphState ν payload), state.outputsRespectStatuses AllAdmissibleFold G state rest (applyNodeFacts rest state).outputsRespectStatusesstate:GraphState ν payloadhOutputs:state.outputsRespectStatuseshResults:AllAdmissibleFold G state (result :: rest)(applyNodeFacts (result :: rest) state).outputsRespectStatuses ν:Type upayload:Type vinst✝:DecidableEq νG:DAG νresult:NodeResult ν payloadrest:List (NodeResult ν payload)ih: (state : GraphState ν payload), state.outputsRespectStatuses AllAdmissibleFold G state rest (applyNodeFacts rest state).outputsRespectStatusesstate:GraphState ν payloadhOutputs:state.outputsRespectStatuses_hResult:Admissible G state resulthRest:AllAdmissibleFold G (result.applyNodeFact state) rest(applyNodeFacts (result :: rest) state).outputsRespectStatuses ν:Type upayload:Type vinst✝:DecidableEq νG:DAG νresult:NodeResult ν payloadrest:List (NodeResult ν payload)ih: (state : GraphState ν payload), state.outputsRespectStatuses AllAdmissibleFold G state rest (applyNodeFacts rest state).outputsRespectStatusesstate:GraphState ν payloadhOutputs:state.outputsRespectStatuses_hResult:Admissible G state resulthRest:AllAdmissibleFold G (result.applyNodeFact state) resthStep:(result.applyNodeFact state).outputsRespectStatuses(applyNodeFacts (result :: rest) state).outputsRespectStatuses All goals completed! 🐙

applyNodeFacts_preserves_outputsCompleteForStatuses preserves required outputs.

theorem applyNodeFacts_preserves_outputsCompleteForStatuses [DecidableEq ν] (G : DAG ν) (results : List (NodeResult ν payload)) (state : GraphState ν payload) (hOutputs : GraphState.outputsCompleteForStatuses state) (hResults : AllAdmissibleFold G state results) : GraphState.outputsCompleteForStatuses (applyNodeFacts results state) := ν:Type upayload:Type vinst✝:DecidableEq νG:DAG νresults:List (NodeResult ν payload)state:GraphState ν payloadhOutputs:state.outputsCompleteForStatuseshResults:AllAdmissibleFold G state results(applyNodeFacts results state).outputsCompleteForStatuses induction results generalizing state with ν:Type upayload:Type vinst✝:DecidableEq νG:DAG νstate:GraphState ν payloadhOutputs:state.outputsCompleteForStatuseshResults:AllAdmissibleFold G state [](applyNodeFacts [] state).outputsCompleteForStatuses All goals completed! 🐙 ν:Type upayload:Type vinst✝:DecidableEq νG:DAG νresult:NodeResult ν payloadrest:List (NodeResult ν payload)ih: (state : GraphState ν payload), state.outputsCompleteForStatuses AllAdmissibleFold G state rest (applyNodeFacts rest state).outputsCompleteForStatusesstate:GraphState ν payloadhOutputs:state.outputsCompleteForStatuseshResults:AllAdmissibleFold G state (result :: rest)(applyNodeFacts (result :: rest) state).outputsCompleteForStatuses ν:Type upayload:Type vinst✝:DecidableEq νG:DAG νresult:NodeResult ν payloadrest:List (NodeResult ν payload)ih: (state : GraphState ν payload), state.outputsCompleteForStatuses AllAdmissibleFold G state rest (applyNodeFacts rest state).outputsCompleteForStatusesstate:GraphState ν payloadhOutputs:state.outputsCompleteForStatuses_hResult:Admissible G state resulthRest:AllAdmissibleFold G (result.applyNodeFact state) rest(applyNodeFacts (result :: rest) state).outputsCompleteForStatuses ν:Type upayload:Type vinst✝:DecidableEq νG:DAG νresult:NodeResult ν payloadrest:List (NodeResult ν payload)ih: (state : GraphState ν payload), state.outputsCompleteForStatuses AllAdmissibleFold G state rest (applyNodeFacts rest state).outputsCompleteForStatusesstate:GraphState ν payloadhOutputs:state.outputsCompleteForStatuses_hResult:Admissible G state resulthRest:AllAdmissibleFold G (result.applyNodeFact state) resthStep:(result.applyNodeFact state).outputsCompleteForStatuses(applyNodeFacts (result :: rest) state).outputsCompleteForStatuses All goals completed! 🐙

applyNodeFacts_preserves_noRunning preserves the absence of running nodes.

theorem applyNodeFacts_preserves_noRunning [DecidableEq ν] (G : DAG ν) (results : List (NodeResult ν payload)) (state : GraphState ν payload) (hNoRunning : GraphState.noRunningNodes state) (hResults : AllAdmissibleFold G state results) : GraphState.noRunningNodes (applyNodeFacts results state) := ν:Type upayload:Type vinst✝:DecidableEq νG:DAG νresults:List (NodeResult ν payload)state:GraphState ν payloadhNoRunning:state.noRunningNodeshResults:AllAdmissibleFold G state results(applyNodeFacts results state).noRunningNodes induction results generalizing state with ν:Type upayload:Type vinst✝:DecidableEq νG:DAG νstate:GraphState ν payloadhNoRunning:state.noRunningNodeshResults:AllAdmissibleFold G state [](applyNodeFacts [] state).noRunningNodes All goals completed! 🐙 ν:Type upayload:Type vinst✝:DecidableEq νG:DAG νresult:NodeResult ν payloadrest:List (NodeResult ν payload)ih: (state : GraphState ν payload), state.noRunningNodes AllAdmissibleFold G state rest (applyNodeFacts rest state).noRunningNodesstate:GraphState ν payloadhNoRunning:state.noRunningNodeshResults:AllAdmissibleFold G state (result :: rest)(applyNodeFacts (result :: rest) state).noRunningNodes ν:Type upayload:Type vinst✝:DecidableEq νG:DAG νresult:NodeResult ν payloadrest:List (NodeResult ν payload)ih: (state : GraphState ν payload), state.noRunningNodes AllAdmissibleFold G state rest (applyNodeFacts rest state).noRunningNodesstate:GraphState ν payloadhNoRunning:state.noRunningNodes_hResult:Admissible G state resulthRest:AllAdmissibleFold G (result.applyNodeFact state) rest(applyNodeFacts (result :: rest) state).noRunningNodes ν:Type upayload:Type vinst✝:DecidableEq νG:DAG νresult:NodeResult ν payloadrest:List (NodeResult ν payload)ih: (state : GraphState ν payload), state.noRunningNodes AllAdmissibleFold G state rest (applyNodeFacts rest state).noRunningNodesstate:GraphState ν payloadhNoRunning:state.noRunningNodes_hResult:Admissible G state resulthRest:AllAdmissibleFold G (result.applyNodeFact state) resthStep:(result.applyNodeFact state).noRunningNodes(applyNodeFacts (result :: rest) state).noRunningNodes All goals completed! 🐙

applyNodeFacts_preserves_causalHistoryClosed preserves causal history.

theorem applyNodeFacts_preserves_causalHistoryClosed [DecidableEq ν] (G : DAG ν) (results : List (NodeResult ν payload)) (state : GraphState ν payload) (hCausal : CausalHistoryClosed G state) (hResults : AllAdmissibleFold G state results) : CausalHistoryClosed G (applyNodeFacts results state) := ν:Type upayload:Type vinst✝:DecidableEq νG:DAG νresults:List (NodeResult ν payload)state:GraphState ν payloadhCausal:CausalHistoryClosed G statehResults:AllAdmissibleFold G state resultsCausalHistoryClosed G (applyNodeFacts results state) induction results generalizing state with ν:Type upayload:Type vinst✝:DecidableEq νG:DAG νstate:GraphState ν payloadhCausal:CausalHistoryClosed G statehResults:AllAdmissibleFold G state []CausalHistoryClosed G (applyNodeFacts [] state) All goals completed! 🐙 ν:Type upayload:Type vinst✝:DecidableEq νG:DAG νresult:NodeResult ν payloadrest:List (NodeResult ν payload)ih: (state : GraphState ν payload), CausalHistoryClosed G state AllAdmissibleFold G state rest CausalHistoryClosed G (applyNodeFacts rest state)state:GraphState ν payloadhCausal:CausalHistoryClosed G statehResults:AllAdmissibleFold G state (result :: rest)CausalHistoryClosed G (applyNodeFacts (result :: rest) state) ν:Type upayload:Type vinst✝:DecidableEq νG:DAG νresult:NodeResult ν payloadrest:List (NodeResult ν payload)ih: (state : GraphState ν payload), CausalHistoryClosed G state AllAdmissibleFold G state rest CausalHistoryClosed G (applyNodeFacts rest state)state:GraphState ν payloadhCausal:CausalHistoryClosed G statehResult:Admissible G state resulthRest:AllAdmissibleFold G (result.applyNodeFact state) restCausalHistoryClosed G (applyNodeFacts (result :: rest) state) ν:Type upayload:Type vinst✝:DecidableEq νG:DAG νresult:NodeResult ν payloadrest:List (NodeResult ν payload)ih: (state : GraphState ν payload), CausalHistoryClosed G state AllAdmissibleFold G state rest CausalHistoryClosed G (applyNodeFacts rest state)state:GraphState ν payloadhCausal:CausalHistoryClosed G statehResult:Admissible G state resulthRest:AllAdmissibleFold G (result.applyNodeFact state) resthStep:CausalHistoryClosed G (result.applyNodeFact state)CausalHistoryClosed G (applyNodeFacts (result :: rest) state) All goals completed! 🐙

Disjoint-Key Accumulation

applyNodeFact_comm proves facts for distinct nodes commute.

theorem applyNodeFact_comm [DecidableEq ν] (r1 r2 : NodeResult ν payload) (state : GraphState ν payload) (hDistinct : r1.node r2.node) : applyNodeFact r1 (applyNodeFact r2 state) = applyNodeFact r2 (applyNodeFact r1 state) := ν:Type upayload:Type vinst✝:DecidableEq νr1:NodeResult ν payloadr2:NodeResult ν payloadstate:GraphState ν payloadhDistinct:r1.node r2.noder1.applyNodeFact (r2.applyNodeFact state) = r2.applyNodeFact (r1.applyNodeFact state) have hDistinctSymm : r2.node r1.node := ν:Type upayload:Type vinst✝:DecidableEq νr1:NodeResult ν payloadr2:NodeResult ν payloadstate:GraphState ν payloadhDistinct:r1.node r2.noder1.applyNodeFact (r2.applyNodeFact state) = r2.applyNodeFact (r1.applyNodeFact state) ν:Type upayload:Type vinst✝:DecidableEq νr1:NodeResult ν payloadr2:NodeResult ν payloadstate:GraphState ν payloadhDistinct:r1.node r2.nodehEq:r2.node = r1.nodeFalse All goals completed! 🐙 ν:Type upayload:Type vinst✝:DecidableEq νr1:NodeResult ν payloadr2:NodeResult ν payloadstate:GraphState ν payloadhDistinct:r1.node r2.nodehDistinctSymm:r2.node r1.noden:ν(r1.applyNodeFact (r2.applyNodeFact state)).status n = (r2.applyNodeFact (r1.applyNodeFact state)).status nν:Type upayload:Type vinst✝:DecidableEq νr1:NodeResult ν payloadr2:NodeResult ν payloadstate:GraphState ν payloadhDistinct:r1.node r2.nodehDistinctSymm:r2.node r1.noden:νa✝:payload(r1.applyNodeFact (r2.applyNodeFact state)).output n = some a✝ (r2.applyNodeFact (r1.applyNodeFact state)).output n = some a✝ ν:Type upayload:Type vinst✝:DecidableEq νr1:NodeResult ν payloadr2:NodeResult ν payloadstate:GraphState ν payloadhDistinct:r1.node r2.nodehDistinctSymm:r2.node r1.noden:ν(r1.applyNodeFact (r2.applyNodeFact state)).status n = (r2.applyNodeFact (r1.applyNodeFact state)).status n ν:Type upayload:Type vinst✝:DecidableEq νr1:NodeResult ν payloadr2:NodeResult ν payloadstate:GraphState ν payloadhDistinct:r1.node r2.nodehDistinctSymm:r2.node r1.noden:νh1:n = r1.node(r1.applyNodeFact (r2.applyNodeFact state)).status n = (r2.applyNodeFact (r1.applyNodeFact state)).status nν:Type upayload:Type vinst✝:DecidableEq νr1:NodeResult ν payloadr2:NodeResult ν payloadstate:GraphState ν payloadhDistinct:r1.node r2.nodehDistinctSymm:r2.node r1.noden:νh1:¬n = r1.node(r1.applyNodeFact (r2.applyNodeFact state)).status n = (r2.applyNodeFact (r1.applyNodeFact state)).status n ν:Type upayload:Type vinst✝:DecidableEq νr1:NodeResult ν payloadr2:NodeResult ν payloadstate:GraphState ν payloadhDistinct:r1.node r2.nodehDistinctSymm:r2.node r1.noden:νh1:n = r1.node(r1.applyNodeFact (r2.applyNodeFact state)).status n = (r2.applyNodeFact (r1.applyNodeFact state)).status n ν:Type upayload:Type vinst✝:DecidableEq νr1:NodeResult ν payloadr2:NodeResult ν payloadstate:GraphState ν payloadhDistinct:r1.node r2.nodehDistinctSymm:r2.node r1.noden:νh1:n = r1.nodeh2:n = r2.node(r1.applyNodeFact (r2.applyNodeFact state)).status n = (r2.applyNodeFact (r1.applyNodeFact state)).status nν:Type upayload:Type vinst✝:DecidableEq νr1:NodeResult ν payloadr2:NodeResult ν payloadstate:GraphState ν payloadhDistinct:r1.node r2.nodehDistinctSymm:r2.node r1.noden:νh1:n = r1.nodeh2:¬n = r2.node(r1.applyNodeFact (r2.applyNodeFact state)).status n = (r2.applyNodeFact (r1.applyNodeFact state)).status n ν:Type upayload:Type vinst✝:DecidableEq νr1:NodeResult ν payloadr2:NodeResult ν payloadstate:GraphState ν payloadhDistinct:r1.node r2.nodehDistinctSymm:r2.node r1.noden:νh1:n = r1.nodeh2:n = r2.node(r1.applyNodeFact (r2.applyNodeFact state)).status n = (r2.applyNodeFact (r1.applyNodeFact state)).status n exact False.elim (hDistinct (ν:Type upayload:Type vinst✝:DecidableEq νr1:NodeResult ν payloadr2:NodeResult ν payloadstate:GraphState ν payloadhDistinct:r1.node r2.nodehDistinctSymm:r2.node r1.noden:νh1:n = r1.nodeh2:n = r2.noder1.node = r2.node All goals completed! 🐙)) ν:Type upayload:Type vinst✝:DecidableEq νr1:NodeResult ν payloadr2:NodeResult ν payloadstate:GraphState ν payloadhDistinct:r1.node r2.nodehDistinctSymm:r2.node r1.noden:νh1:n = r1.nodeh2:¬n = r2.node(r1.applyNodeFact (r2.applyNodeFact state)).status n = (r2.applyNodeFact (r1.applyNodeFact state)).status n All goals completed! 🐙 ν:Type upayload:Type vinst✝:DecidableEq νr1:NodeResult ν payloadr2:NodeResult ν payloadstate:GraphState ν payloadhDistinct:r1.node r2.nodehDistinctSymm:r2.node r1.noden:νh1:¬n = r1.node(r1.applyNodeFact (r2.applyNodeFact state)).status n = (r2.applyNodeFact (r1.applyNodeFact state)).status n ν:Type upayload:Type vinst✝:DecidableEq νr1:NodeResult ν payloadr2:NodeResult ν payloadstate:GraphState ν payloadhDistinct:r1.node r2.nodehDistinctSymm:r2.node r1.noden:νh1:¬n = r1.nodeh2:n = r2.node(r1.applyNodeFact (r2.applyNodeFact state)).status n = (r2.applyNodeFact (r1.applyNodeFact state)).status nν:Type upayload:Type vinst✝:DecidableEq νr1:NodeResult ν payloadr2:NodeResult ν payloadstate:GraphState ν payloadhDistinct:r1.node r2.nodehDistinctSymm:r2.node r1.noden:νh1:¬n = r1.nodeh2:¬n = r2.node(r1.applyNodeFact (r2.applyNodeFact state)).status n = (r2.applyNodeFact (r1.applyNodeFact state)).status n ν:Type upayload:Type vinst✝:DecidableEq νr1:NodeResult ν payloadr2:NodeResult ν payloadstate:GraphState ν payloadhDistinct:r1.node r2.nodehDistinctSymm:r2.node r1.noden:νh1:¬n = r1.nodeh2:n = r2.node(r1.applyNodeFact (r2.applyNodeFact state)).status n = (r2.applyNodeFact (r1.applyNodeFact state)).status n All goals completed! 🐙 ν:Type upayload:Type vinst✝:DecidableEq νr1:NodeResult ν payloadr2:NodeResult ν payloadstate:GraphState ν payloadhDistinct:r1.node r2.nodehDistinctSymm:r2.node r1.noden:νh1:¬n = r1.nodeh2:¬n = r2.node(r1.applyNodeFact (r2.applyNodeFact state)).status n = (r2.applyNodeFact (r1.applyNodeFact state)).status n All goals completed! 🐙 ν:Type upayload:Type vinst✝:DecidableEq νr1:NodeResult ν payloadr2:NodeResult ν payloadstate:GraphState ν payloadhDistinct:r1.node r2.nodehDistinctSymm:r2.node r1.noden:νa✝:payload(r1.applyNodeFact (r2.applyNodeFact state)).output n = some a✝ (r2.applyNodeFact (r1.applyNodeFact state)).output n = some a✝ ν:Type upayload:Type vinst✝:DecidableEq νr1:NodeResult ν payloadr2:NodeResult ν payloadstate:GraphState ν payloadhDistinct:r1.node r2.nodehDistinctSymm:r2.node r1.noden:νa✝:payloadh1:n = r1.node(r1.applyNodeFact (r2.applyNodeFact state)).output n = some a✝ (r2.applyNodeFact (r1.applyNodeFact state)).output n = some a✝ν:Type upayload:Type vinst✝:DecidableEq νr1:NodeResult ν payloadr2:NodeResult ν payloadstate:GraphState ν payloadhDistinct:r1.node r2.nodehDistinctSymm:r2.node r1.noden:νa✝:payloadh1:¬n = r1.node(r1.applyNodeFact (r2.applyNodeFact state)).output n = some a✝ (r2.applyNodeFact (r1.applyNodeFact state)).output n = some a✝ ν:Type upayload:Type vinst✝:DecidableEq νr1:NodeResult ν payloadr2:NodeResult ν payloadstate:GraphState ν payloadhDistinct:r1.node r2.nodehDistinctSymm:r2.node r1.noden:νa✝:payloadh1:n = r1.node(r1.applyNodeFact (r2.applyNodeFact state)).output n = some a✝ (r2.applyNodeFact (r1.applyNodeFact state)).output n = some a✝ ν:Type upayload:Type vinst✝:DecidableEq νr1:NodeResult ν payloadr2:NodeResult ν payloadstate:GraphState ν payloadhDistinct:r1.node r2.nodehDistinctSymm:r2.node r1.noden:νa✝:payloadh1:n = r1.nodeh2:n = r2.node(r1.applyNodeFact (r2.applyNodeFact state)).output n = some a✝ (r2.applyNodeFact (r1.applyNodeFact state)).output n = some a✝ν:Type upayload:Type vinst✝:DecidableEq νr1:NodeResult ν payloadr2:NodeResult ν payloadstate:GraphState ν payloadhDistinct:r1.node r2.nodehDistinctSymm:r2.node r1.noden:νa✝:payloadh1:n = r1.nodeh2:¬n = r2.node(r1.applyNodeFact (r2.applyNodeFact state)).output n = some a✝ (r2.applyNodeFact (r1.applyNodeFact state)).output n = some a✝ ν:Type upayload:Type vinst✝:DecidableEq νr1:NodeResult ν payloadr2:NodeResult ν payloadstate:GraphState ν payloadhDistinct:r1.node r2.nodehDistinctSymm:r2.node r1.noden:νa✝:payloadh1:n = r1.nodeh2:n = r2.node(r1.applyNodeFact (r2.applyNodeFact state)).output n = some a✝ (r2.applyNodeFact (r1.applyNodeFact state)).output n = some a✝ exact False.elim (hDistinct (ν:Type upayload:Type vinst✝:DecidableEq νr1:NodeResult ν payloadr2:NodeResult ν payloadstate:GraphState ν payloadhDistinct:r1.node r2.nodehDistinctSymm:r2.node r1.noden:νa✝:payloadh1:n = r1.nodeh2:n = r2.noder1.node = r2.node All goals completed! 🐙)) ν:Type upayload:Type vinst✝:DecidableEq νr1:NodeResult ν payloadr2:NodeResult ν payloadstate:GraphState ν payloadhDistinct:r1.node r2.nodehDistinctSymm:r2.node r1.noden:νa✝:payloadh1:n = r1.nodeh2:¬n = r2.node(r1.applyNodeFact (r2.applyNodeFact state)).output n = some a✝ (r2.applyNodeFact (r1.applyNodeFact state)).output n = some a✝ All goals completed! 🐙 ν:Type upayload:Type vinst✝:DecidableEq νr1:NodeResult ν payloadr2:NodeResult ν payloadstate:GraphState ν payloadhDistinct:r1.node r2.nodehDistinctSymm:r2.node r1.noden:νa✝:payloadh1:¬n = r1.node(r1.applyNodeFact (r2.applyNodeFact state)).output n = some a✝ (r2.applyNodeFact (r1.applyNodeFact state)).output n = some a✝ ν:Type upayload:Type vinst✝:DecidableEq νr1:NodeResult ν payloadr2:NodeResult ν payloadstate:GraphState ν payloadhDistinct:r1.node r2.nodehDistinctSymm:r2.node r1.noden:νa✝:payloadh1:¬n = r1.nodeh2:n = r2.node(r1.applyNodeFact (r2.applyNodeFact state)).output n = some a✝ (r2.applyNodeFact (r1.applyNodeFact state)).output n = some a✝ν:Type upayload:Type vinst✝:DecidableEq νr1:NodeResult ν payloadr2:NodeResult ν payloadstate:GraphState ν payloadhDistinct:r1.node r2.nodehDistinctSymm:r2.node r1.noden:νa✝:payloadh1:¬n = r1.nodeh2:¬n = r2.node(r1.applyNodeFact (r2.applyNodeFact state)).output n = some a✝ (r2.applyNodeFact (r1.applyNodeFact state)).output n = some a✝ ν:Type upayload:Type vinst✝:DecidableEq νr1:NodeResult ν payloadr2:NodeResult ν payloadstate:GraphState ν payloadhDistinct:r1.node r2.nodehDistinctSymm:r2.node r1.noden:νa✝:payloadh1:¬n = r1.nodeh2:n = r2.node(r1.applyNodeFact (r2.applyNodeFact state)).output n = some a✝ (r2.applyNodeFact (r1.applyNodeFact state)).output n = some a✝ All goals completed! 🐙 ν:Type upayload:Type vinst✝:DecidableEq νr1:NodeResult ν payloadr2:NodeResult ν payloadstate:GraphState ν payloadhDistinct:r1.node r2.nodehDistinctSymm:r2.node r1.noden:νa✝:payloadh1:¬n = r1.nodeh2:¬n = r2.node(r1.applyNodeFact (r2.applyNodeFact state)).output n = some a✝ (r2.applyNodeFact (r1.applyNodeFact state)).output n = some a✝ All goals completed! 🐙

applyNodeFacts_perm_invariant lifts disjoint-key commutativity to fact folds.

theorem applyNodeFacts_perm_invariant [DecidableEq ν] {left right : List (NodeResult ν payload)} (hPerm : left.Perm right) (hDistinct : left.Pairwise (fun first second => first.node second.node)) (state : GraphState ν payload) : applyNodeFacts left state = applyNodeFacts right state := ν:Type upayload:Type vinst✝:DecidableEq νleft:List (NodeResult ν payload)right:List (NodeResult ν payload)hPerm:left.Perm righthDistinct:List.Pairwise (fun first second => first.node second.node) leftstate:GraphState ν payloadapplyNodeFacts left state = applyNodeFacts right state ν:Type upayload:Type vinst✝:DecidableEq νleft:List (NodeResult ν payload)right:List (NodeResult ν payload)hPerm:left.Perm righthDistinct:List.Pairwise (fun first second => first.node second.node) leftstate:GraphState ν payloadList.foldl (fun current result => result.applyNodeFact current) state left = List.foldl (fun current result => result.applyNodeFact current) state right ν:Type upayload:Type vinst✝:DecidableEq νleft:List (NodeResult ν payload)right:List (NodeResult ν payload)hPerm:left.Perm righthDistinct:List.Pairwise (fun first second => first.node second.node) leftstate:GraphState ν payload x left, y left, (z : GraphState ν payload), y.applyNodeFact (x.applyNodeFact z) = x.applyNodeFact (y.applyNodeFact z) intro first ν:Type upayload:Type vinst✝:DecidableEq νleft:List (NodeResult ν payload)right:List (NodeResult ν payload)hPerm:left.Perm righthDistinct:List.Pairwise (fun first second => first.node second.node) leftstate:GraphState ν payloadfirst:NodeResult ν payloadhFirst:first left y left, (z : GraphState ν payload), y.applyNodeFact (first.applyNodeFact z) = first.applyNodeFact (y.applyNodeFact z) ν:Type upayload:Type vinst✝:DecidableEq νleft:List (NodeResult ν payload)right:List (NodeResult ν payload)hPerm:left.Perm righthDistinct:List.Pairwise (fun first second => first.node second.node) leftstate:GraphState ν payloadfirst:NodeResult ν payloadhFirst:first leftsecond:NodeResult ν payloadsecond left (z : GraphState ν payload), second.applyNodeFact (first.applyNodeFact z) = first.applyNodeFact (second.applyNodeFact z) ν:Type upayload:Type vinst✝:DecidableEq νleft:List (NodeResult ν payload)right:List (NodeResult ν payload)hPerm:left.Perm righthDistinct:List.Pairwise (fun first second => first.node second.node) leftstate:GraphState ν payloadfirst:NodeResult ν payloadhFirst:first leftsecond:NodeResult ν payloadhSecond:second left (z : GraphState ν payload), second.applyNodeFact (first.applyNodeFact z) = first.applyNodeFact (second.applyNodeFact z) ν:Type upayload:Type vinst✝:DecidableEq νleft:List (NodeResult ν payload)right:List (NodeResult ν payload)hPerm:left.Perm righthDistinct:List.Pairwise (fun first second => first.node second.node) leftstate:GraphState ν payloadfirst:NodeResult ν payloadhFirst:first leftsecond:NodeResult ν payloadhSecond:second leftcurrent:GraphState ν payloadsecond.applyNodeFact (first.applyNodeFact current) = first.applyNodeFact (second.applyNodeFact current) ν:Type upayload:Type vinst✝:DecidableEq νleft:List (NodeResult ν payload)right:List (NodeResult ν payload)hPerm:left.Perm righthDistinct:List.Pairwise (fun first second => first.node second.node) leftstate:GraphState ν payloadfirst:NodeResult ν payloadhFirst:first leftsecond:NodeResult ν payloadhSecond:second leftcurrent:GraphState ν payloadhSame:first = secondsecond.applyNodeFact (first.applyNodeFact current) = first.applyNodeFact (second.applyNodeFact current)ν:Type upayload:Type vinst✝:DecidableEq νleft:List (NodeResult ν payload)right:List (NodeResult ν payload)hPerm:left.Perm righthDistinct:List.Pairwise (fun first second => first.node second.node) leftstate:GraphState ν payloadfirst:NodeResult ν payloadhFirst:first leftsecond:NodeResult ν payloadhSecond:second leftcurrent:GraphState ν payloadhSame:¬first = secondsecond.applyNodeFact (first.applyNodeFact current) = first.applyNodeFact (second.applyNodeFact current) ν:Type upayload:Type vinst✝:DecidableEq νleft:List (NodeResult ν payload)right:List (NodeResult ν payload)hPerm:left.Perm righthDistinct:List.Pairwise (fun first second => first.node second.node) leftstate:GraphState ν payloadfirst:NodeResult ν payloadhFirst:first leftsecond:NodeResult ν payloadhSecond:second leftcurrent:GraphState ν payloadhSame:first = secondsecond.applyNodeFact (first.applyNodeFact current) = first.applyNodeFact (second.applyNodeFact current) ν:Type upayload:Type vinst✝:DecidableEq νleft:List (NodeResult ν payload)right:List (NodeResult ν payload)hPerm:left.Perm righthDistinct:List.Pairwise (fun first second => first.node second.node) leftstate:GraphState ν payloadfirst:NodeResult ν payloadhFirst:first leftcurrent:GraphState ν payloadhSecond:first leftfirst.applyNodeFact (first.applyNodeFact current) = first.applyNodeFact (first.applyNodeFact current) All goals completed! 🐙 ν:Type upayload:Type vinst✝:DecidableEq νleft:List (NodeResult ν payload)right:List (NodeResult ν payload)hPerm:left.Perm righthDistinct:List.Pairwise (fun first second => first.node second.node) leftstate:GraphState ν payloadfirst:NodeResult ν payloadhFirst:first leftsecond:NodeResult ν payloadhSecond:second leftcurrent:GraphState ν payloadhSame:¬first = secondsecond.applyNodeFact (first.applyNodeFact current) = first.applyNodeFact (second.applyNodeFact current) have hSymm : Symmetric (fun first second : NodeResult ν payload => first.node second.node) := ν:Type upayload:Type vinst✝:DecidableEq νleft:List (NodeResult ν payload)right:List (NodeResult ν payload)hPerm:left.Perm righthDistinct:List.Pairwise (fun first second => first.node second.node) leftstate:GraphState ν payloadapplyNodeFacts left state = applyNodeFacts right state intro a ν:Type upayload:Type vinst✝:DecidableEq νleft:List (NodeResult ν payload)right:List (NodeResult ν payload)hPerm:left.Perm righthDistinct:List.Pairwise (fun first second => first.node second.node) leftstate:GraphState ν payloadfirst:NodeResult ν payloadhFirst:first leftsecond:NodeResult ν payloadhSecond:second leftcurrent:GraphState ν payloadhSame:¬first = seconda:NodeResult ν payloadb:NodeResult ν payload(fun first second => first.node second.node) a b (fun first second => first.node second.node) b a ν:Type upayload:Type vinst✝:DecidableEq νleft:List (NodeResult ν payload)right:List (NodeResult ν payload)hPerm:left.Perm righthDistinct:List.Pairwise (fun first second => first.node second.node) leftstate:GraphState ν payloadfirst:NodeResult ν payloadhFirst:first leftsecond:NodeResult ν payloadhSecond:second leftcurrent:GraphState ν payloadhSame:¬first = seconda:NodeResult ν payloadb:NodeResult ν payloadhDistinctNodes:a.node b.nodeb.node a.node ν:Type upayload:Type vinst✝:DecidableEq νleft:List (NodeResult ν payload)right:List (NodeResult ν payload)hPerm:left.Perm righthDistinct:List.Pairwise (fun first second => first.node second.node) leftstate:GraphState ν payloadfirst:NodeResult ν payloadhFirst:first leftsecond:NodeResult ν payloadhSecond:second leftcurrent:GraphState ν payloadhSame:¬first = seconda:NodeResult ν payloadb:NodeResult ν payloadhDistinctNodes:a.node b.nodehEq:b.node = a.nodeFalse All goals completed! 🐙 ν:Type upayload:Type vinst✝:DecidableEq νleft:List (NodeResult ν payload)right:List (NodeResult ν payload)hPerm:left.Perm righthDistinct:List.Pairwise (fun first second => first.node second.node) leftstate:GraphState ν payloadfirst:NodeResult ν payloadhFirst:first leftsecond:NodeResult ν payloadhSecond:second leftcurrent:GraphState ν payloadhSame:¬first = secondhSymm:Symmetric fun first second => first.node second.nodehDistinctNodes:first.node second.nodesecond.applyNodeFact (first.applyNodeFact current) = first.applyNodeFact (second.applyNodeFact current) All goals completed! 🐙end NodeResultend Cortex.Pulse