Imports
open Finset

CLRS Section 23.2 - Kruskal and Prim

This section builds on the safe-edge theorem from Section 23.1. It contains the mathematical Kruskal pass, cut-certificate induction, finite-graph wrappers, and the component-oracle interface. It also isolates the sorted-edge-order lightness argument used by CLRS: once previously processed edges are known not to cross the current component cut, the current edge is light by sorted order. Union-find implementation correctness is deliberately deferred: the current proof works at the mathematical cycle-test interface level.

Main results:

  • Theorem lightest_crossing_of_sorted_prefix: sorted edge order plus a processed-prefix exclusion invariant proves the lightness condition for a cut.

  • Theorem cut_certificate_of_component_oracle_sorted_prefix: packages that sorted-order lightness proof into a component-oracle cut certificate.

  • Theorem processed_prefix_excludes_of_exact_component_kruskal: exact components derive the processed-prefix exclusion invariant for a Kruskal prefix.

  • Theorem cut_certificate_of_exact_component_kruskal_prefix: packages the exact-component prefix invariant into a sorted-order cut certificate.

  • Theorem FiniteGraph.kruskal_forest_of_exact_component: an exact-component Kruskal pass preserves the forest invariant.

  • Theorem FiniteGraph.kruskal_spans_of_complete_exact_component: a complete Kruskal edge scan over a connected finite graph spans all vertices.

  • Theorem FiniteGraph.kruskal_spanning_tree_of_complete_exact_component: a complete exact-component Kruskal scan starting from a forest returns a spanning tree.

  • Theorem FiniteGraph.spanningTree_exchange_of_path_certificate: a path-decomposition certificate proves that adding one edge and deleting one tree edge preserves the spanning-tree property.

  • Theorems Graph.exchangePath_connected_insert, Graph.exchangePath_of_insert_connected, Graph.exchangePath_iff_insertedEdgeConnection, and FiniteGraph.exchangePath_iff_insertedEdgeConnection_of_spanningTree: the bridge between a cycle-style inserted-edge connection and the reusable ExchangePath certificate.

  • Theorem kruskal_optimal: safe-edge induction for the mathematical Kruskal pass.

  • Theorem FiniteGraph.kruskal_minimum_spanning_tree_of_cycle_test: the finite-graph MST conclusion for any cycle-test implementation whose accepted set is known to be a spanning tree.

Current gaps:

  • Refine the exact component model to an executable union-find implementation if implementation correctness becomes part of scope.

  • Derive InsertedEdgeConnection automatically from a canonical finite simple path/cycle representation.

  • Add Prim's theorem interface.

namespace CLRSnamespace MSTvariable {V E : Type} [DecidableEq V] [DecidableEq E]

Component-based cycle-test interface

A mathematical component oracle for the current selected edge set. It is exactly the specification a union-find implementation should refine.

structure ComponentOracle (G : Graph V E) where component : Finset E V Finset V mem_self : A v, v component A v closed_src : A root e, e A G.src e component A root G.dst e component A root closed_dst : A root e, e A G.dst e component A root G.src e component A root
namespace ComponentOracleomit [DecidableEq V] [DecidableEq E] in theorem respects (C : ComponentOracle G) (A : Finset E) (root : V) : G.Respects (C.component A root) A := end ComponentOracle

Exact component oracles

An exact component oracle returns precisely the vertices connected to the root by the currently selected edge set.

def ExactComponentOracle (G : Graph V E) (C : ComponentOracle G) : Prop := A root v, v C.component A root G.ConnectedIn A root v
namespace Graph

The undirected adjacency relation is symmetric.

omit [DecidableEq V] [DecidableEq E] intheorem adjIn_symm {G : Graph V E} {A : Finset E} {u v : V} (h : G.AdjIn A u v) : G.AdjIn A v u :=

Connectivity induced by selected undirected edges is symmetric.

omit [DecidableEq V] [DecidableEq E] intheorem connected_symm {G : Graph V E} {A : Finset E} {u v : V} (h : G.ConnectedIn A u v) : G.ConnectedIn A v u := induction h with

Connectivity induced by selected edges is transitive.

omit [DecidableEq V] [DecidableEq E] intheorem connected_trans {G : Graph V E} {A : Finset E} {u v x : V} (huv : G.ConnectedIn A u v) (hvx : G.ConnectedIn A v x) : G.ConnectedIn A u x := Relation.ReflTransGen.trans huv hvx

Any selected edge connects its own endpoints.

omit [DecidableEq V] [DecidableEq E] intheorem connected_of_mem_edge {G : Graph V E} {A : Finset E} {e : E} (he : e A) : G.ConnectedIn A (G.src e) (G.dst e) :=

If every edge of B has endpoints already connected in A, then one adjacency step in B can be simulated by an A-connection.

omit [DecidableEq V] [DecidableEq E] intheorem connected_of_adjIn_of_edge_connected {G : Graph V E} {A B : Finset E} (hedge : e, e B G.ConnectedIn A (G.src e) (G.dst e)) {u v : V} (hadj : G.AdjIn B u v) : G.ConnectedIn A u v :=

If every edge of B has endpoints connected in A, then every B-path can be transported to an A-path.

omit [DecidableEq V] [DecidableEq E] intheorem connected_of_edgewise_connected {G : Graph V E} {A B : Finset E} (hedge : e, e B G.ConnectedIn A (G.src e) (G.dst e)) {u v : V} (h : G.ConnectedIn B u v) : G.ConnectedIn A u v := induction h with

Any path after inserting one edge either already existed before the insertion or crosses the inserted edge once, with old paths on both sides.

omit [DecidableEq V] in

A path-decomposition certificate for the CLRS tree-exchange step. After removing tree edge f, the endpoints of the new edge e reconnect the two sides of f, in one of the two undirected orientations.

def ExchangePath (G : Graph V E) (T : Finset E) (e f : E) : Prop := (G.ConnectedIn (T.erase f) (G.src f) (G.src e) G.ConnectedIn (T.erase f) (G.dst e) (G.dst f)) (G.ConnectedIn (T.erase f) (G.src f) (G.dst e) G.ConnectedIn (T.erase f) (G.src e) (G.dst f))

Cycle-style exchange witness: after deleting tree edge f, inserting the new edge e reconnects the endpoints of f. This is the compact connectivity fact a future finite path/cycle API should produce.

def InsertedEdgeConnection (G : Graph V E) (T : Finset E) (e f : E) : Prop := G.ConnectedIn (insert e (T.erase f)) (G.src f) (G.dst f)

An ExchangePath certificate reconnects the endpoints of the deleted tree edge after the new edge is inserted.

omit [DecidableEq V] intheorem exchangePath_connected_insert {G : Graph V E} {T : Finset E} {e f : E} (hpath : G.ExchangePath T e f) : G.ConnectedIn (insert e (T.erase f)) (G.src f) (G.dst f) :=

An ExchangePath certificate is an inserted-edge connection.

omit [DecidableEq V] intheorem insertedEdgeConnection_of_exchangePath {G : Graph V E} {T : Finset E} {e f : E} (hpath : G.ExchangePath T e f) : G.InsertedEdgeConnection T e f := Graph.exchangePath_connected_insert hpath

Conversely, if inserting e reconnects the endpoints of f, and those endpoints were not already connected after erasing f, then the connection decomposes into an ExchangePath certificate.

omit [DecidableEq V] intheorem exchangePath_of_insert_connected {G : Graph V E} {T : Finset E} {e f : E} (hconn : G.ConnectedIn (insert e (T.erase f)) (G.src f) (G.dst f)) (hnot : ¬ G.ConnectedIn (T.erase f) (G.src f) (G.dst f)) : G.ExchangePath T e f :=

Equivalence between the path-decomposition certificate and the compact cycle-style inserted-edge connection, assuming deleting f really separates its endpoints.

omit [DecidableEq V] intheorem exchangePath_iff_insertedEdgeConnection {G : Graph V E} {T : Finset E} {e f : E} (hnot : ¬ G.ConnectedIn (T.erase f) (G.src f) (G.dst f)) : G.ExchangePath T e f G.InsertedEdgeConnection T e f :=
end Graph

The executable-style cycle test induced by a component oracle: accept an edge iff its destination is outside the source component.

def acceptByComponent (G : Graph V E) (C : ComponentOracle G) (A : Finset E) (e : E) : Bool := decide (G.dst e C.component A (G.src e))
omit [DecidableEq E] in private theorem not_mem_component_of_accept {G : Graph V E} {C : ComponentOracle G} {A : Finset E} {e : E} (h : acceptByComponent G C A e = true) : G.dst e C.component A (G.src e) :=

Accepted component edges induce the cut used in the CLRS proof.

theorem cut_certificate_of_component_oracle {G : Graph V E} {P : Problem E} {w : E Nat} (C : ComponentOracle G) {A : Finset E} {e : E} (haccept : acceptByComponent G C A e = true) (hlight : f, G.Crosses (C.component A (G.src e)) f w e w f) (hexchange : T, IsMSTExtending P w A T e T f, f T G.Crosses (C.component A (G.src e)) f P.IsSpanningTree (insert e (T.erase f)) A insert e (T.erase f)) : CutCertificate G P w A (C.component A (G.src e)) e :=

An edge whose endpoints are already connected by the current selected edge set cannot cross any exact component cut for that selected edge set.

omit [DecidableEq V] [DecidableEq E] intheorem not_crosses_component_of_connected {G : Graph V E} {C : ComponentOracle G} (hexact : ExactComponentOracle G C) {A : Finset E} {root : V} {e : E} (hconn : G.ConnectedIn A (G.src e) (G.dst e)) : ¬ G.Crosses (C.component A root) e :=

If an edge is either selected already or internally connected by the selected edge set, it cannot cross an exact component cut.

omit [DecidableEq V] [DecidableEq E] intheorem not_crosses_component_of_mem_or_connected {G : Graph V E} {C : ComponentOracle G} (hexact : ExactComponentOracle G C) {A : Finset E} {root : V} {e : E} (haccounted : e A G.ConnectedIn A (G.src e) (G.dst e)) : ¬ G.Crosses (C.component A root) e :=

Sorted-order lightness certificates

An edge list is sorted in nondecreasing weight order.

This CLRS-facing predicate is deliberately small: the head is no heavier than every later edge, and the tail is sorted recursively.

def WeightSorted (w : E Nat) : List E Prop | [] => True | e :: es => ( f, f es w e w f) WeightSorted w es

A suffix of a sorted edge list is sorted.

omit [DecidableEq E] intheorem weightSorted_suffix_of_append (w : E Nat) (processed rest : List E) : WeightSorted w (processed ++ rest) WeightSorted w rest := induction processed with

In a sorted nonempty edge list, the head is no heavier than any member.

omit [DecidableEq E] in

If every crossing edge appears in processed ++ e :: suffix, and the processed edge prefix contains no crossing edge for the current cut, then every crossing edge appears at or after e.

omit [DecidableEq V] [DecidableEq E] intheorem crossing_mem_current_suffix_of_prefix_excludes {G : Graph V E} {S : Finset V} {processed suffix : List E} {e f : E} (hall : g, G.Crosses S g g processed ++ e :: suffix) (hprefix : g, g processed ¬ G.Crosses S g) (hcross : G.Crosses S f) : f e :: suffix :=

Sorted edge order plus the processed-prefix exclusion invariant proves the lightness side condition for the current Kruskal cut.

This isolates the CLRS sorted-order argument from the graph-specific proof that previously processed edges do not cross the current component cut.

omit [DecidableEq V] [DecidableEq E] intheorem lightest_crossing_of_sorted_prefix {G : Graph V E} {w : E Nat} {S : Finset V} {processed suffix : List E} {e : E} (hsorted : WeightSorted w (processed ++ e :: suffix)) (hall : f, G.Crosses S f f processed ++ e :: suffix) (hprefix : f, f processed ¬ G.Crosses S f) : f, G.Crosses S f w e w f :=

Component-oracle cut certificate where the lightness field is discharged from sorted edge order and a processed-prefix exclusion invariant.

theorem cut_certificate_of_component_oracle_sorted_prefix {G : Graph V E} {P : Problem E} {w : E Nat} (C : ComponentOracle G) {A : Finset E} {e : E} {processed suffix : List E} (haccept : acceptByComponent G C A e = true) (hsorted : WeightSorted w (processed ++ e :: suffix)) (hall : f, G.Crosses (C.component A (G.src e)) f f processed ++ e :: suffix) (hprefix : f, f processed ¬ G.Crosses (C.component A (G.src e)) f) (hexchange : T, IsMSTExtending P w A T e T f, f T G.Crosses (C.component A (G.src e)) f P.IsSpanningTree (insert e (T.erase f)) A insert e (T.erase f)) : CutCertificate G P w A (C.component A (G.src e)) e :=

Kruskal-style safe-edge induction

A mathematical Kruskal pass over a fixed edge order.

The Boolean accept A e abstracts the cycle test: when it returns true, the edge is inserted into the current forest; otherwise it is skipped.

def kruskal (accept : Finset E E Bool) : List E Finset E Finset E | [], A => A | e :: es, A => kruskal accept es (if accept A e then insert e A else A)

The proof obligation needed by the abstract Kruskal induction: every edge accepted by the cycle test is safe for the current prefix. In a concrete graph development this is discharged by a cut-property certificate.

structure KruskalCertificate (P : Problem E) (w : E Nat) (accept : Finset E E Bool) : Prop where safe : A e, accept A e = true SafeEdge P w A e

A CLRS-style certificate for Kruskal: each accepted edge has a cut certificate showing it is light across some cut respecting the current forest.

structure KruskalCutCertificate (G : Graph V E) (P : Problem E) (w : E Nat) (accept : Finset E E Bool) : Prop where cut : A e, accept A e = true S, CutCertificate G P w A S e
omit [DecidableEq V] in theorem kruskal_certificate_of_cut_certificates {G : Graph V E} {P : Problem E} {w : E Nat} {accept : Finset E E Bool} (cert : KruskalCutCertificate G P w accept) : KruskalCertificate P w accept := theorem kruskal_cut_certificate_of_component_oracle {G : Graph V E} {P : Problem E} {w : E Nat} (C : ComponentOracle G) (hlight : A e, acceptByComponent G C A e = true f, G.Crosses (C.component A (G.src e)) f w e w f) (hexchange : A e, acceptByComponent G C A e = true T, IsMSTExtending P w A T e T f, f T G.Crosses (C.component A (G.src e)) f P.IsSpanningTree (insert e (T.erase f)) A insert e (T.erase f)) : KruskalCutCertificate G P w (acceptByComponent G C) :=

Kruskal never selects an edge outside the initial set or the scanned edge list.

After a Kruskal prefix has been processed by an exact component oracle, every processed edge is accounted for: it is either selected in the current forest or its endpoints are already connected in that forest.

After an exact-component Kruskal pass, every processed edge has connected endpoints in the final selected set.

theorem processed_edge_connected_of_exact_component_kruskal {G : Graph V E} (C : ComponentOracle G) (hexact : ExactComponentOracle G C) (processed : List E) (A : Finset E) : f, f processed G.ConnectedIn (kruskal (acceptByComponent G C) processed A) (G.src f) (G.dst f) :=

Exact components derive the processed-prefix exclusion invariant needed by the sorted-order Kruskal lightness proof.

theorem processed_prefix_excludes_of_exact_component_kruskal {G : Graph V E} (C : ComponentOracle G) (hexact : ExactComponentOracle G C) (processed : List E) (A : Finset E) (root : V) : f, f processed ¬ G.Crosses (C.component (kruskal (acceptByComponent G C) processed A) root) f :=

Kruskal's sorted edge order proves lightness without a standalone prefix exclusion hypothesis when the component oracle is exact.

theorem lightest_crossing_of_exact_component_kruskal_prefix {G : Graph V E} {w : E Nat} (C : ComponentOracle G) (hexact : ExactComponentOracle G C) {processed suffix : List E} {A : Finset E} {e : E} (hsorted : WeightSorted w (processed ++ e :: suffix)) (hall : f, G.Crosses (C.component (kruskal (acceptByComponent G C) processed A) (G.src e)) f f processed ++ e :: suffix) : f, G.Crosses (C.component (kruskal (acceptByComponent G C) processed A) (G.src e)) f w e w f :=

Exact-component cut certificate for the current Kruskal edge. This packages the derived processed-prefix exclusion invariant with the sorted edge order.

theorem cut_certificate_of_exact_component_kruskal_prefix {G : Graph V E} {P : Problem E} {w : E Nat} (C : ComponentOracle G) (hexact : ExactComponentOracle G C) {processed suffix : List E} {A : Finset E} {e : E} (haccept : acceptByComponent G C (kruskal (acceptByComponent G C) processed A) e = true) (hsorted : WeightSorted w (processed ++ e :: suffix)) (hall : f, G.Crosses (C.component (kruskal (acceptByComponent G C) processed A) (G.src e)) f f processed ++ e :: suffix) (hexchange : T, IsMSTExtending P w (kruskal (acceptByComponent G C) processed A) T e T f, f T G.Crosses (C.component (kruskal (acceptByComponent G C) processed A) (G.src e)) f P.IsSpanningTree (insert e (T.erase f)) kruskal (acceptByComponent G C) processed A insert e (T.erase f)) : CutCertificate G P w (kruskal (acceptByComponent G C) processed A) (C.component (kruskal (acceptByComponent G C) processed A) (G.src e)) e :=
private theorem optimal_for_smaller_prefix {P : Problem E} {w : E Nat} {A₀ A T T' : Finset E} (hA₀A : A₀ A) (hcur : IsMSTExtending P w A T) (hbase : IsMSTExtending P w A₀ T) (hnew : IsMSTExtending P w A T') : IsMSTExtending P w A₀ T' :=

Mathematical Kruskal optimality.

If the accept rule only accepts safe edges, the initial prefix has an optimum, and the final selected edge set is itself a maximal spanning tree, then the Kruskal result is an optimum extending the initial prefix. The final maximality assumption is the graph-specific fact that a spanning tree cannot be properly extended by another spanning tree; concrete graph modules can prove it from the usual cardinality characterization of spanning trees.

theorem kruskal_optimal {P : Problem E} {w : E Nat} {accept : Finset E E Bool} (cert : KruskalCertificate P w accept) (edges : List E) {A₀ T₀ : Finset E} (hstart : IsMSTExtending P w A₀ T₀) (hfinal_tree : P.IsSpanningTree (kruskal accept edges A₀)) (hfinal_maximal : T, P.IsSpanningTree T kruskal accept edges A₀ T T = kruskal accept edges A₀) : IsMSTExtending P w A₀ (kruskal accept edges A₀) :=

Kruskal optimality stated directly from CLRS cut certificates.

omit [DecidableEq V] intheorem kruskal_optimal_of_cut_certificates {G : Graph V E} {P : Problem E} {w : E Nat} {accept : Finset E E Bool} (cert : KruskalCutCertificate G P w accept) (edges : List E) {A₀ T₀ : Finset E} (hstart : IsMSTExtending P w A₀ T₀) (hfinal_tree : P.IsSpanningTree (kruskal accept edges A₀)) (hfinal_maximal : T, P.IsSpanningTree T kruskal accept edges A₀ T T = kruskal accept edges A₀) : IsMSTExtending P w A₀ (kruskal accept edges A₀) :=
theorem kruskal_optimal_of_component_oracle {G : Graph V E} {P : Problem E} {w : E Nat} (C : ComponentOracle G) (hlight : A e, acceptByComponent G C A e = true f, G.Crosses (C.component A (G.src e)) f w e w f) (hexchange : A e, acceptByComponent G C A e = true T, IsMSTExtending P w A T e T f, f T G.Crosses (C.component A (G.src e)) f P.IsSpanningTree (insert e (T.erase f)) A insert e (T.erase f)) (edges : List E) {A₀ T₀ : Finset E} (hstart : IsMSTExtending P w A₀ T₀) (hfinal_tree : P.IsSpanningTree (kruskal (acceptByComponent G C) edges A₀)) (hfinal_maximal : T, P.IsSpanningTree T kruskal (acceptByComponent G C) edges A₀ T T = kruskal (acceptByComponent G C) edges A₀) : IsMSTExtending P w A₀ (kruskal (acceptByComponent G C) edges A₀) :=

A verified executable cycle test. A union-find implementation should provide an accept function and prove that it agrees with the component oracle.

structure CycleTestImplementation (G : Graph V E) (C : ComponentOracle G) where accept : Finset E E Bool correct : A e, accept A e = acceptByComponent G C A e

The canonical executable cycle test associated to a component oracle.

def componentCycleTest (G : Graph V E) (C : ComponentOracle G) : CycleTestImplementation G C where accept := acceptByComponent G C correct :=
namespace FiniteGraph

The empty edge set is a forest.

theorem isForest_empty (G : FiniteGraph V E) : G.IsForest :=
private theorem connected_insert_erase_self_eq {A : Finset E} {e : E} (heA : e A) : (insert e A).erase e = A := private theorem erase_insert_comm_of_ne {A : Finset E} {e f : E} (hef : e f) : (insert e A).erase f = insert e (A.erase f) := omit [DecidableEq V] in private theorem connected_insert_bridge_case_left {G : Graph V E} {A : Finset E} {e f : E} (hfA : f A) (hleft : G.ConnectedIn (A.erase f) (G.src f) (G.src e)) (hright : G.ConnectedIn (A.erase f) (G.dst e) (G.dst f)) : G.ConnectedIn A (G.src e) (G.dst e) := omit [DecidableEq V] in private theorem connected_insert_bridge_case_right {G : Graph V E} {A : Finset E} {e f : E} (hfA : f A) (hleft : G.ConnectedIn (A.erase f) (G.src f) (G.dst e)) (hright : G.ConnectedIn (A.erase f) (G.src e) (G.dst f)) : G.ConnectedIn A (G.src e) (G.dst e) :=

Inserting an edge whose endpoints are disconnected preserves the edge-removal forest invariant.

The edge-removal forest invariant is downward closed under edge subsets.

Finite-graph bridge from a cycle-style connection to the reusable ExchangePath certificate. In a spanning tree, deleting f disconnects its endpoints; if inserting e reconnects them, Lean can decompose that connection into the two sides of the exchange path.

theorem exchangePath_of_insert_connects_erased_edge (G : FiniteGraph V E) {T : Finset E} {e f : E} (hT : G.IsSpanningTree T) (hfT : f T) (hconn : G.toGraph.ConnectedIn (insert e (T.erase f)) (G.src f) (G.dst f)) : G.toGraph.ExchangePath T e f :=

Named finite-graph wrapper for the compact inserted-edge connection interface. In a spanning tree, erasing f disconnects its endpoints, so the compact cycle-style witness is equivalent to an ExchangePath certificate.

theorem exchangePath_iff_insertedEdgeConnection_of_spanningTree (G : FiniteGraph V E) {T : Finset E} {e f : E} (hT : G.IsSpanningTree T) (hfT : f T) : G.toGraph.ExchangePath T e f G.toGraph.InsertedEdgeConnection T e f := Graph.exchangePath_iff_insertedEdgeConnection (hT.2.2 f hfT)

Finite-graph bridge from the named inserted-edge connection to the reusable ExchangePath certificate.

theorem exchangePath_of_insertedEdgeConnection (G : FiniteGraph V E) {T : Finset E} {e f : E} (hT : G.IsSpanningTree T) (hfT : f T) (hconn : G.toGraph.InsertedEdgeConnection T e f) : G.toGraph.ExchangePath T e f := (G.exchangePath_iff_insertedEdgeConnection_of_spanningTree hT hfT).2 hconn

If a path-decomposition certificate says that new edge e reconnects the two components produced by deleting tree edge f, then replacing f by e preserves the finite-graph spanning-tree property.

Cut-local exchange certificate from an explicit path-decomposition certificate. This packages the reusable finite-graph part needed by the CLRS safe-edge theorem.

Existential replacement form: once a crossing tree edge is accompanied by an ExchangePath certificate, Lean constructs the exchanged spanning tree and proves that the accepted prefix is preserved.

theorem exists_replacement_spanning_tree_of_cut (G : FiniteGraph V E) {A T : Finset E} {S : Finset V} {e : E} (hT : G.IsSpanningTree T) (hAT : A T) (hrespects : G.toGraph.Respects S A) (heG : e G.edges) (hpath : f, f T G.toGraph.Crosses S f G.toGraph.ExchangePath T e f) : f, f T G.toGraph.Crosses S f G.IsSpanningTree (insert e (T.erase f)) A insert e (T.erase f) :=

Finite-graph cut certificate from a light crossing edge and explicit exchange paths for optimum trees. This is the bridge between the mathematical path/cycle exchange argument and the abstract safe-edge theorem.

theorem cutCertificate_of_lightest_crossing (G : FiniteGraph V E) {w : E Nat} {A : Finset E} {S : Finset V} {e : E} (heG : e G.edges) (hcross : G.toGraph.Crosses S e) (hrespects : G.toGraph.Respects S A) (hlight : f, G.toGraph.Crosses S f w e w f) (hexchangePath : T, IsMSTExtending G.toProblem w A T e T f, f T G.toGraph.Crosses S f G.toGraph.ExchangePath T e f) : CutCertificate G.toGraph G.toProblem w A S e :=

An exact-component Kruskal pass preserves the forest invariant: every accepted edge joins two previously disconnected components.

A finite-graph Kruskal run selects only graph edges, provided the initial set and scanned list contain only graph edges.

theorem kruskal_subset_edges (G : FiniteGraph V E) {accept : Finset E E Bool} (edges : List E) {A : Finset E} (hA : A G.edges) (hedges : e, e edges e G.edges) : kruskal accept edges A G.edges := CLRS.MST.kruskal_subset_of_start_and_edges accept edges hA hedges

If the edge list contains every graph edge and the full graph is connected, then an exact-component Kruskal pass spans the finite graph.

theorem kruskal_spans_of_complete_exact_component (G : FiniteGraph V E) (C : ComponentOracle G.toGraph) (hexact : ExactComponentOracle G.toGraph C) (edges : List E) (A : Finset E) (hcomplete : e, e G.edges e edges) (hconnected : G.Spans G.edges) : G.Spans (kruskal (acceptByComponent G.toGraph C) edges A) :=

A complete exact-component Kruskal scan starting from a forest returns a spanning tree of a connected finite graph.

theorem kruskal_spanning_tree_of_complete_exact_component (G : FiniteGraph V E) (C : ComponentOracle G.toGraph) (hexact : ExactComponentOracle G.toGraph C) (edges : List E) {A : Finset E} (hA : A G.edges) (hedges : e, e edges e G.edges) (hcomplete : e, e G.edges e edges) (hconnected : G.Spans G.edges) (hforest : G.IsForest A) : G.IsSpanningTree (kruskal (acceptByComponent G.toGraph C) edges A) :=

Finite-graph Kruskal optimality. The concrete spanning-tree definition discharges the abstract maximality side condition.

theorem kruskal_optimal (G : FiniteGraph V E) {w : E Nat} {accept : Finset E E Bool} (cert : KruskalCertificate G.toProblem w accept) (edges : List E) {A₀ T₀ : Finset E} (hstart : IsMSTExtending G.toProblem w A₀ T₀) (hfinal_tree : G.IsSpanningTree (kruskal accept edges A₀)) : IsMSTExtending G.toProblem w A₀ (kruskal accept edges A₀) := exact CLRS.MST.kruskal_optimal cert edges hstart hfinal_tree ( )
theorem kruskal_optimal_of_component_oracle (G : FiniteGraph V E) {w : E Nat} (C : ComponentOracle G.toGraph) (hlight : A e, acceptByComponent G.toGraph C A e = true f, G.toGraph.Crosses (C.component A (G.src e)) f w e w f) (hexchange : A e, acceptByComponent G.toGraph C A e = true T, IsMSTExtending G.toProblem w A T e T f, f T G.toGraph.Crosses (C.component A (G.src e)) f G.IsSpanningTree (insert e (T.erase f)) A insert e (T.erase f)) (edges : List E) {A₀ T₀ : Finset E} (hstart : IsMSTExtending G.toProblem w A₀ T₀) (hfinal_tree : G.IsSpanningTree (kruskal (acceptByComponent G.toGraph C) edges A₀)) : IsMSTExtending G.toProblem w A₀ (kruskal (acceptByComponent G.toGraph C) edges A₀) := exact CLRS.MST.kruskal_optimal_of_component_oracle (G := G.toGraph) (P := G.toProblem) (w := w) C hlight hexchange edges hstart hfinal_tree ( )

Finite-graph Kruskal optimality with the final spanning-tree side condition discharged from exact components, a complete edge scan, graph connectedness, and an initial forest.

theorem kruskal_optimal_of_complete_exact_component (G : FiniteGraph V E) {w : E Nat} (C : ComponentOracle G.toGraph) (hexact : ExactComponentOracle G.toGraph C) (hlight : A e, acceptByComponent G.toGraph C A e = true f, G.toGraph.Crosses (C.component A (G.src e)) f w e w f) (hexchange : A e, acceptByComponent G.toGraph C A e = true T, IsMSTExtending G.toProblem w A T e T f, f T G.toGraph.Crosses (C.component A (G.src e)) f G.IsSpanningTree (insert e (T.erase f)) A insert e (T.erase f)) (edges : List E) {A₀ T₀ : Finset E} (hstart : IsMSTExtending G.toProblem w A₀ T₀) (hA₀ : A₀ G.edges) (hforest : G.IsForest A₀) (hedges : e, e edges e G.edges) (hcomplete : e, e G.edges e edges) (hconnected : G.Spans G.edges) : IsMSTExtending G.toProblem w A₀ (kruskal (acceptByComponent G.toGraph C) edges A₀) :=

Standard empty-prefix form of the complete exact-component Kruskal theorem.

theorem kruskal_optimal_of_complete_exact_component_empty (G : FiniteGraph V E) {w : E Nat} (C : ComponentOracle G.toGraph) (hexact : ExactComponentOracle G.toGraph C) (hlight : A e, acceptByComponent G.toGraph C A e = true f, G.toGraph.Crosses (C.component A (G.src e)) f w e w f) (hexchange : A e, acceptByComponent G.toGraph C A e = true T, IsMSTExtending G.toProblem w A T e T f, f T G.toGraph.Crosses (C.component A (G.src e)) f G.IsSpanningTree (insert e (T.erase f)) A insert e (T.erase f)) (edges : List E) {T₀ : Finset E} (hstart : IsMSTExtending G.toProblem w T₀) (hedges : e, e edges e G.edges) (hcomplete : e, e G.edges e edges) (hconnected : G.Spans G.edges) : IsMSTExtending G.toProblem w (kruskal (acceptByComponent G.toGraph C) edges ) := exact G.kruskal_optimal_of_complete_exact_component C hexact hlight hexchange edges hstart ( ) G.isForest_empty hedges hcomplete hconnected

Reader-facing finite-graph MST theorem for a complete exact-component Kruskal scan from the empty prefix.

theorem kruskal_minimum_spanning_tree_of_complete_exact_component_empty (G : FiniteGraph V E) {w : E Nat} (C : ComponentOracle G.toGraph) (hexact : ExactComponentOracle G.toGraph C) (hlight : A e, acceptByComponent G.toGraph C A e = true f, G.toGraph.Crosses (C.component A (G.src e)) f w e w f) (hexchange : A e, acceptByComponent G.toGraph C A e = true T, IsMSTExtending G.toProblem w A T e T f, f T G.toGraph.Crosses (C.component A (G.src e)) f G.IsSpanningTree (insert e (T.erase f)) A insert e (T.erase f)) (edges : List E) {T₀ : Finset E} (hstart : IsMSTExtending G.toProblem w T₀) (hedges : e, e edges e G.edges) (hcomplete : e, e G.edges e edges) (hconnected : G.Spans G.edges) : G.IsMinimumSpanningTree w (kruskal (acceptByComponent G.toGraph C) edges ) :=
theorem kruskal_optimal_of_cycle_test (G : FiniteGraph V E) {w : E Nat} {C : ComponentOracle G.toGraph} (impl : CycleTestImplementation G.toGraph C) (hlight : A e, impl.accept A e = true f, G.toGraph.Crosses (C.component A (G.src e)) f w e w f) (hexchange : A e, impl.accept A e = true T, IsMSTExtending G.toProblem w A T e T f, f T G.toGraph.Crosses (C.component A (G.src e)) f G.IsSpanningTree (insert e (T.erase f)) A insert e (T.erase f)) (edges : List E) {A₀ T₀ : Finset E} (hstart : IsMSTExtending G.toProblem w A₀ T₀) (hfinal_tree : G.IsSpanningTree (kruskal impl.accept edges A₀)) : IsMSTExtending G.toProblem w A₀ (kruskal impl.accept edges A₀) := exact CLRS.MST.kruskal_optimal_of_cycle_test (G := G.toGraph) (P := G.toProblem) (w := w) impl hlight hexchange edges hstart hfinal_tree ( )

Reader-facing finite-graph MST theorem for any Kruskal cycle-test implementation, once the accepted edge set is known to be a spanning tree.

theorem kruskal_minimum_spanning_tree_of_cycle_test (G : FiniteGraph V E) {w : E Nat} {C : ComponentOracle G.toGraph} (impl : CycleTestImplementation G.toGraph C) (hlight : A e, impl.accept A e = true f, G.toGraph.Crosses (C.component A (G.src e)) f w e w f) (hexchange : A e, impl.accept A e = true T, IsMSTExtending G.toProblem w A T e T f, f T G.toGraph.Crosses (C.component A (G.src e)) f G.IsSpanningTree (insert e (T.erase f)) A insert e (T.erase f)) (edges : List E) {T₀ : Finset E} (hstart : IsMSTExtending G.toProblem w T₀) (hfinal_tree : G.IsSpanningTree (kruskal impl.accept edges )) : G.IsMinimumSpanningTree w (kruskal impl.accept edges ) :=
end FiniteGraphend MSTend CLRS