1-- The level of an edge in the partition sequence of a decomposition: the2-- last stage at which both ends share a class, finite exactly when the ends3-- part at some stage, together with the colour refined at that stage.4-- Part of Cumulus, the Grace17 mathematics library.5-- Copyright (c) 2026 Grant Passmore.6-- Released under the Apache License 2.0. See LICENSE in the repository root.7-- Authors: Grant Passmore89module Grace.Cumulus.GraphTheory.TreePacking.Levels10import Sequences1112-- The level of an edge: the largest n at which both ends share a class of13-- P_n; an edge inside a class of the stable partition has infinite level.14predicate FiniteLevel (V leftEnd rightEnd T e : Set, k n : Nat) :=15 (∃ X ∈ partitionSequence(V, leftEnd, rightEnd, T, k, n),16 leftEnd(e) ∈ X ∧ rightEnd(e) ∈ X) ∧17¬(∃ X ∈ partitionSequence(V, leftEnd, rightEnd, T, k, succ(n)),18 leftEnd(e) ∈ X ∧ rightEnd(e) ∈ X)1920-- At stage 0 the ends of an edge share the one class V.21theorem partitionSequence.together_zero (V leftEnd rightEnd T e : Set, k : Nat)22requires ends : leftEnd(e) ∈ V ∧ rightEnd(e) ∈ V23shows∃ X ∈ partitionSequence(V, leftEnd, rightEnd, T, k, 0),24 leftEnd(e) ∈ X ∧ rightEnd(e) ∈ X25proof26witness V27rw partitionSequence.zero28exact⟨singleton.self, ends.left, ends.right⟩2930-- An edge whose ends share a class at stage 0 but not at stage N has a31-- finite level below N: the last stage at which they still share one.32theorem FiniteLevel.of_parted (V leftEnd rightEnd T e : Set, k N : Nat)33requires together :34∃ X ∈ partitionSequence(V, leftEnd, rightEnd, T, k, 0),35 leftEnd(e) ∈ X ∧ rightEnd(e) ∈ X36requires parted :37¬(∃ X ∈ partitionSequence(V, leftEnd, rightEnd, T, k, N),38 leftEnd(e) ∈ X ∧ rightEnd(e) ∈ X)39shows∃ n ∈ ℕ, n < N ∧ FiniteLevel(V, leftEnd, rightEnd, T, e, k, n)40proof41induction N42| zero =>43intro parted44exfalso45exact parted with together46| succ(m) using ih =>47intro parted48 by_cases shared :49∃ X ∈ partitionSequence(V, leftEnd, rightEnd, T, k, m),50 leftEnd(e) ∈ X ∧ rightEnd(e) ∈ X51 . witness m52refine⟨?_, ?_, ?_⟩53 . exact nat.omega.forward at m with*54 . arith55 . unfold FiniteLevel56constructor57 . exact shared58 . exact parted59 . obtain⟨n, natural, less, level⟩:= ih with shared60have nNat := nat.omega.backward with natural61refine⟨n, natural, ?_, level⟩62arith6364-- An edge crossing the stable partition has a finite level: its ends share65-- the class V at stage 0 and no class at stage |V|.66theorem FiniteLevel.of_crossing (V leftEnd rightEnd T F e : Set, k : Nat)67requires finiteVertices : Finite(V)68requires partition : Partition(V, stablePartition(V, leftEnd, rightEnd, T, k))69requires ends : leftEnd(e) ∈ V ∧ rightEnd(e) ∈ V70requires crossing : e ∈ crossingClasses(71 stablePartition(V, leftEnd, rightEnd, T, k), leftEnd, rightEnd, F)72shows∃ n ∈ ℕ, n < cardinality(V) ∧73 FiniteLevel(V, leftEnd, rightEnd, T, e, k, n)74proof75unfold stablePartition at partition, crossing76have together := partitionSequence.together_zero77at V, leftEnd, rightEnd, T, e, k with ends78have parted : ¬(∃ X ∈79 partitionSequence(V, leftEnd, rightEnd, T, k, cardinality(V)),80 leftEnd(e) ∈ X ∧ rightEnd(e) ∈ X)81intro common82have same := (classOf.eq_iff with partition, ends.left, ends.right).backward83with common84exact crossing.right with same85exact FiniteLevel.of_parted with together, parted8687-- Ends sharing a class at a later stage share one at every earlier stage,88-- since the sequence refines; so an edge has one finite level.89theorem partitionSequence.earlier (V E leftEnd rightEnd T e : Set, k i d : Nat)90requires graph : Graph(V, E, leftEnd, rightEnd)91requires decomposition : Decomposition(E, T, k)92requires together :93∃ X ∈ partitionSequence(V, leftEnd, rightEnd, T, k, i + d),94 leftEnd(e) ∈ X ∧ rightEnd(e) ∈ X95shows∃ X ∈ partitionSequence(V, leftEnd, rightEnd, T, k, i),96 leftEnd(e) ∈ X ∧ rightEnd(e) ∈ X97proof98induction d99| zero =>100intro together101rwunder add.right_unit at together102exact together103| succ(n) using ih =>104intro together105apply ih106rwunder add.succ_right at together107obtain⟨X, class, leftIn, rightIn⟩:= together108have refines := partitionSequence.refines109at V, E, leftEnd, rightEnd, T, k, i + n with graph, decomposition110obtain⟨Y, classY, subset⟩:= refines with X, class111exact⟨Y, classY, (subset with leftEnd(e), leftIn),112 (subset with rightEnd(e), rightIn)⟩113114theorem FiniteLevel.unique (V E leftEnd rightEnd T e : Set, k m n : Nat)115requires graph : Graph(V, E, leftEnd, rightEnd)116requires decomposition : Decomposition(E, T, k)117requires levelM : FiniteLevel(V, leftEnd, rightEnd, T, e, k, m)118requires levelN : FiniteLevel(V, leftEnd, rightEnd, T, e, k, n)119shows m = n120proof121have order := Less.trichotomy at m, n with*122rcases order with before | same | after123 . obtain⟨d, dNat, sum⟩:= before124have together := levelN.left125rwunder← sum at together126exfalso127exact levelM.right with (partitionSequence.earlier with128 graph, decomposition, together)129 . exact same130 . obtain⟨d, dNat, sum⟩:= after131have together := levelM.left132rwunder← sum at together133exfalso134exact levelN.right with (partitionSequence.earlier with135 graph, decomposition, together)136137-- An edge whose every finite level is at least n keeps its ends together138-- at stage n; an edge of finite level p keeps them together only up to p.139theorem FiniteLevel.together_of_least (V leftEnd rightEnd T g : Set, k n : Nat)140requires ends : leftEnd(g) ∈ V ∧ rightEnd(g) ∈ V141requires least : ∀ q ∈ ℕ,142 FiniteLevel(V, leftEnd, rightEnd, T, g, k, q) → n ≤ q143shows∃ Y ∈ partitionSequence(V, leftEnd, rightEnd, T, k, n),144 leftEnd(g) ∈ Y ∧ rightEnd(g) ∈ Y145proof146by_contra apart147have start := partitionSequence.together_zero148at V, leftEnd, rightEnd, T, g, k with ends149obtain⟨q, natural, less, levelG⟩:=150 FiniteLevel.of_parted with start, apart151have below := least with q, natural, levelG152have qNat := nat.omega.backward with natural153arith154155theorem FiniteLevel.le_of_together (V E leftEnd rightEnd T g : Set, k n p : Nat)156requires graph : Graph(V, E, leftEnd, rightEnd)157requires decomposition : Decomposition(E, T, k)158requires level : FiniteLevel(V, leftEnd, rightEnd, T, g, k, p)159requires together :160∃ Y ∈ partitionSequence(V, leftEnd, rightEnd, T, k, n),161 leftEnd(g) ∈ Y ∧ rightEnd(g) ∈ Y162shows n ≤ p163proof164by_contra above165have less := Less.of_not_LessEqual with above166obtain⟨d, dNat, sum⟩:= less167rwunder← sum at together168exact level.right with (partitionSequence.earlier with169 graph, decomposition, together)170171-- Once the sequence has stopped moving it stays, so a stage below a moving172-- stage is moving.173theorem partitionSequence.active (V E leftEnd rightEnd T : Set, k n d : Nat)174requires graph : Graph(V, E, leftEnd, rightEnd)175requires nonempty : V ≠∅176requires decomposition : Decomposition(E, T, k)177requires active : disconnectedColour(leftEnd, rightEnd, T,178 partitionSequence(V, leftEnd, rightEnd, T, k, n + d), k) ≠∅179shows disconnectedColour(leftEnd, rightEnd, T,180 partitionSequence(V, leftEnd, rightEnd, T, k, n), k) ≠∅181proof182intro none183apply active184have partition :185 Partition(V, partitionSequence(V, leftEnd, rightEnd, T, k, n)) :=186 partitionSequence.partition with graph, nonempty, decomposition187have fixed := partitionStep.fixed with partition, none188rw← partitionSequence.succ at fixed189rw (partitionSequence.fixed_from with fixed)190exact none191192-- Vertices joined by F from inside a set closed under F are joined by the193-- edges of F inside that set.194theorem Joined.inside (leftEnd rightEnd F X u v : Set)195requires closed : ClosedUnder(leftEnd, rightEnd, F, X)196requires start : u ∈ X197requires joined : Joined(leftEnd, rightEnd, F, u, v)198shows Joined(leftEnd, rightEnd, inside(leftEnd, rightEnd, F, X), u, v)199proof200intros A inA closedA201have closedBoth : ClosedUnder(leftEnd, rightEnd, F, A ∩ X)202intros e inF203have balanced := closed with e, inF204 by_cases leftX : leftEnd(e) ∈ X205 . have rightX := balanced.forward with leftX206have insideEdge : e ∈ inside(leftEnd, rightEnd, F, X) :=207⟨inF, leftX, rightX⟩208have balancedA := closedA with e, insideEdge209rw [intersection.membership, intersection.membership]210simp [leftX, rightX, balancedA]211 . have rightX : ¬rightEnd(e) ∈ X212intro inX213exact leftX with (balanced.backward with inX)214rw [intersection.membership, intersection.membership]215simp [leftX, rightX]216have startBoth : u ∈ A ∩ X :=217 intersection.membership.backward with⟨inA, start⟩218have reached := joined with A ∩ X, startBoth, closedBoth219exact (intersection.membership.forward with reached).left220221-- Ends of an edge in a class X of P that the edges of F inside X join222-- share a class of the refinement of P along F: the component of F within223-- X holding them.224theorem refineBy.together (leftEnd rightEnd F P X e : Set)225requiresclass : X ∈ P226requires ends : leftEnd(e) ∈ X ∧ rightEnd(e) ∈ X227requires joined : Joined(leftEnd, rightEnd, inside(leftEnd, rightEnd, F, X),228 leftEnd(e), rightEnd(e))229shows∃ Y ∈ refineBy(leftEnd, rightEnd, F, P),230 leftEnd(e) ∈ Y ∧ rightEnd(e) ∈ Y231proof232witness componentBy(X, leftEnd, rightEnd, inside(leftEnd, rightEnd, F, X),233 leftEnd(e))234refine⟨?_, ?_, ?_⟩235 . exact refineBy.membership.backward with236⟨X, class, (componentsBy.contains with ends.left)⟩237 . exact componentBy.self with ends.left238 . exact⟨ends.right, joined⟩239240-- An edge of the colour refined at stage m whose ends share a class there241-- keeps them together at stage m + 1: so at the level of an edge some colour242-- is disconnected, and the edge is not of the refining colour.243theorem FiniteLevel.refining_colour (V E leftEnd rightEnd T e : Set, k m : Nat)244requires graph : Graph(V, E, leftEnd, rightEnd)245requires nonempty : V ≠∅246requires decomposition : Decomposition(E, T, k)247requires level : FiniteLevel(V, leftEnd, rightEnd, T, e, k, m)248shows disconnectedColour(leftEnd, rightEnd, T,249 partitionSequence(V, leftEnd, rightEnd, T, k, m), k) ≠∅∧250¬e ∈ T(leastNatural(disconnectedColour(leftEnd, rightEnd, T,251 partitionSequence(V, leftEnd, rightEnd, T, k, m), k)))252proof253obtain⟨together, parted⟩:= level254obtain⟨X, class, leftIn, rightIn⟩:= together255have partition :256 Partition(V, partitionSequence(V, leftEnd, rightEnd, T, k, m)) :=257 partitionSequence.partition with graph, nonempty, decomposition258have some : disconnectedColour(leftEnd, rightEnd, T,259 partitionSequence(V, leftEnd, rightEnd, T, k, m), k) ≠∅260intro none261have fixed := partitionStep.fixed with partition, none262apply parted263witness X264rw [partitionSequence.succ, fixed]265exact⟨class, leftIn, rightIn⟩266refine⟨some, ?_⟩267intro inColour268obtain⟨colour, _⟩:= disconnectedColour.least with some269have ends := Decomposition.ends with graph, decomposition, colour270have insideEdge : e ∈ inside(leftEnd, rightEnd,271 T(leastNatural(disconnectedColour(leftEnd, rightEnd, T,272 partitionSequence(V, leftEnd, rightEnd, T, k, m), k))), X) :=273⟨inColour, leftIn, rightIn⟩274have joined := Joined.of_edge at leftEnd, rightEnd, _, _ with insideEdge275apply parted276rwunder partitionSequence.succ277rwunder partitionStep.refined with partition, ends, some278exact refineBy.together withclass, ⟨leftIn, rightIn⟩, joined279280-- The colour c refined at the level of an edge e of the last colour is a281-- colour below k not holding e, so e closes an even set in the tree T(c).282theorem FiniteLevel.colour_below (V E leftEnd rightEnd T e : Set, c k m : Nat)283requires graph : Graph(V, E, leftEnd, rightEnd)284requires nonempty : V ≠∅285requires decomposition : Decomposition(E, T, succ(k))286requires level : FiniteLevel(V, leftEnd, rightEnd, T, e, succ(k), m)287requires first : e ∈ T(k)288requires colour : c = leastNatural(disconnectedColour(leftEnd, rightEnd, T,289 partitionSequence(V, leftEnd, rightEnd, T, succ(k), m), succ(k)))290shows c ∈ k ∧¬e ∈ T(c) ∧ disconnectedColour(leftEnd, rightEnd, T,291 partitionSequence(V, leftEnd, rightEnd, T, succ(k), m), succ(k)) ≠∅292proof293obtain⟨some, outside⟩:= FiniteLevel.refining_colour with294 graph, nonempty, decomposition, level295obtain⟨colourIn, _⟩:= disconnectedColour.least with some296rw← colour at outside, colourIn297have notK : c ≠ k298intro same299rw same at outside300exact outside with first301have below := Less.of_membership at c, succ(k) with colourIn302have less := Less.of_successor_upper_ne with below, notK303exact⟨(membership.of_Less at c, k with*, less), outside, some⟩304