1-- A cubic loopless graph with an even cover has an even double cover indexed2-- by the eight vectors: the compatibility system is unobstructed, so it has3-- a solution, whose vertex vectors are compatible and give the labels.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.DoubleCover.CubicLabeling10import Obstruction11import Set.Choice1213-- The base points of e at v, and a chosen sum of base points at the two14-- ends of each edge, as a function on E.15def basePoints (V E leftEnd rightEnd F v e : Set) : Set:=16 { c ∈𝒫(3) | BasePoint(V, E, leftEnd, rightEnd, F, v, e, c) }1718def baseSum (V E leftEnd rightEnd F e : Set) : Set:=19 choose(basePoints(V, E, leftEnd, rightEnd, F, leftEnd(e), e)) △20 choose(basePoints(V, E, leftEnd, rightEnd, F, rightEnd(e), e))2122def baseFunction (V E leftEnd rightEnd F : Set) : Set:=23 { p ∈ E ×𝒫(3) |∃ e ∈ E, p = (e, baseSum(V, E, leftEnd, rightEnd, F, e)) }2425-- The value of another edge at v is a base point of e there.26theorem basePoints.nonempty (V E leftEnd rightEnd F v e : Set)27requires cubic : Cubic(V, E, leftEnd, rightEnd)28requires vertex : v ∈ V29requires edge : e ∈ E30requires incident : leftEnd(e) = v ∨ rightEnd(e) = v31shows Nonempty(basePoints(V, E, leftEnd, rightEnd, F, v, e))32proof33obtain⟨f, hf, g, hg, distinct, atF, _⟩:=34 Cubic.others with cubic, vertex, edge, incident35have inside : flowValue(F, f) ∈𝒫(3) :=36 powerset.membership_iff.backward with flowValue.subset37have fe : f ≠ e bycc38have point : BasePoint(V, E, leftEnd, rightEnd, F, v, e, flowValue(F, f)) :=39⟨f, hf, fe, atF, rfl⟩40witness flowValue(F, f)41exact⟨inside, point⟩4243theorem baseSum.subset (V E leftEnd rightEnd F e : Set)44requires graph : Graph(V, E, leftEnd, rightEnd)45requires cubic : Cubic(V, E, leftEnd, rightEnd)46requires edge : e ∈ E47shows baseSum(V, E, leftEnd, rightEnd, F, e) ⊆348proof49have ends := Graph.ends with graph50obtain⟨vertexL, vertexR⟩:= ends with e, edge51have atL : leftEnd(e) = leftEnd(e) ∨ rightEnd(e) = leftEnd(e) bysimp52have atR : leftEnd(e) = rightEnd(e) ∨ rightEnd(e) = rightEnd(e) bysimp53have chosenL := choose.member54with (basePoints.nonempty at _, _, _, _, F, _, _55with cubic, vertexL, edge, atL)56have chosenR := choose.member57with (basePoints.nonempty at _, _, _, _, F, _, _58with cubic, vertexR, edge, atR)59have insideL := powerset.membership_iff.forward with chosenL.left60have insideR := powerset.membership_iff.forward with chosenR.left61unfold baseSum62exact symmetricDifference.subset with insideL, insideR6364theorem baseFunction.function (V E leftEnd rightEnd F : Set)65requires graph : Graph(V, E, leftEnd, rightEnd)66requires cubic : Cubic(V, E, leftEnd, rightEnd)67shows baseFunction(V, E, leftEnd, rightEnd, F) : E →𝒫(3)68proof69constructor70 . intros p member71exact member.left72 . constructor73 . intros x y xy z xz74obtain⟨_, a, _, shapeY⟩:= xy75obtain⟨_, b, _, shapeZ⟩:= xz76obtain⟨sameA, valueY⟩:= orderedPair.injective with shapeY77obtain⟨sameB, valueZ⟩:= orderedPair.injective with shapeZ78cc79 . intros e he80have inside : baseSum(V, E, leftEnd, rightEnd, F, e) ∈𝒫(3) :=81 powerset.membership_iff.backward82with (baseSum.subset with graph, cubic, he)83refine⟨baseSum(V, E, leftEnd, rightEnd, F, e), inside, _⟩84exact baseFunction.membership.backward85with⟨(product.pair with he, inside), e, he, rfl⟩8687theorem baseFunction.value (V E leftEnd rightEnd F e : Set)88requires graph : Graph(V, E, leftEnd, rightEnd)89requires cubic : Cubic(V, E, leftEnd, rightEnd)90requires member : e ∈ E91shows baseFunction(V, E, leftEnd, rightEnd, F)(e) =92 baseSum(V, E, leftEnd, rightEnd, F, e)93proof94have inside : baseSum(V, E, leftEnd, rightEnd, F, e) ∈𝒫(3) :=95 powerset.membership_iff.backward96with (baseSum.subset with graph, cubic, member)97have related : relates(baseFunction(V, E, leftEnd, rightEnd, F), e,98 baseSum(V, E, leftEnd, rightEnd, F, e)) :=99 baseFunction.membership.backward100with⟨(product.pair with member, inside), e, member, rfl⟩101have function := baseFunction.function at _, _, _, _, F with graph, cubic102exact FunctionBetween.apply_value with function, member, related103104-- The chosen sums of base points form a base assignment.105theorem baseFunction.base (V E leftEnd rightEnd F : Set)106requires graph : Graph(V, E, leftEnd, rightEnd)107requires cubic : Cubic(V, E, leftEnd, rightEnd)108shows FunctionBetween(baseFunction(V, E, leftEnd, rightEnd, F), E, 𝒫(3)) ∧109 (∀ e ∈ E, ∃ a, ∃ b,110 BasePoint(V, E, leftEnd, rightEnd, F, leftEnd(e), e, a) ∧111 BasePoint(V, E, leftEnd, rightEnd, F, rightEnd(e), e, b) ∧112 baseFunction(V, E, leftEnd, rightEnd, F)(e) = a △ b)113proof114have ends := Graph.ends with graph115constructor116 . exact baseFunction.function at _, _, _, _, F with graph, cubic117 . intros e he118obtain⟨vertexL, vertexR⟩:= ends with e, he119have atL : leftEnd(e) = leftEnd(e) ∨ rightEnd(e) = leftEnd(e) bysimp120have atR : leftEnd(e) = rightEnd(e) ∨ rightEnd(e) = rightEnd(e) bysimp121have chosenL := choose.member122with (basePoints.nonempty at _, _, _, _, F, _, _123with cubic, vertexL, he, atL)124have chosenR := choose.member125with (basePoints.nonempty at _, _, _, _, F, _, _126with cubic, vertexR, he, atR)127have value := baseFunction.value at _, _, _, _, F, _ with graph, cubic, he128unfold baseSum at value129witness choose(basePoints(V, E, leftEnd, rightEnd, F, leftEnd(e), e))130witness choose(basePoints(V, E, leftEnd, rightEnd, F, rightEnd(e), e))131exact⟨chosenL.right, chosenR.right, value⟩132133-- A cubic loopless graph with an even cover has an even double cover indexed134-- by the eight vectors: the compatibility system is unobstructed, so it has135-- a solution, whose vertex vectors are compatible and give the labels.136theorem Cubic.even_double_cover (V E leftEnd rightEnd F : Set)137requires graph : Graph(V, E, leftEnd, rightEnd)138requires finiteVertices : Finite(V)139requires finiteEdges : Finite(E)140requires cubic : Cubic(V, E, leftEnd, rightEnd)141requires cover : EvenCover(V, E, leftEnd, rightEnd, F)142shows∃ H, EvenDoubleCover(V, E, leftEnd, rightEnd, H, 𝒫(3))143proof144have base := baseFunction.base at _, _, _, _, F with graph, cubic145have unobstructed := compatibility.unobstructed146with graph, finiteVertices, finiteEdges, cubic, cover, base147have finiteThree := Finite.natural at3148have finiteRows : Finite(E ×3) :=149 Finite.product with finiteEdges, finiteThree150have finiteColumns : Finite((V ×3) ∪ (E × {3})) :=151 Finite.union with (Finite.product with finiteVertices, finiteThree),152 (Finite.product with finiteEdges, Finite.singleton)153have matrix : compatibilityMatrix(V, E, leftEnd, rightEnd, F) ⊆154 (E ×3) × ((V ×3) ∪ (E × {3}))155intros p hp156exact hp.left157have side : compatibilitySide(E, baseFunction(V, E, leftEnd, rightEnd, F)) ⊆158 E ×3159intros p hp160exact hp.left161have alternative := paritySystem.alternative162with finiteRows, finiteColumns, matrix, side163obtain⟨t, solution⟩:= alternative.backward with unobstructed164obtain⟨u, compatible⟩:=165 Compatible.of_solution with graph, cubic, base.left, solution166obtain⟨P, function, two, balanced⟩:= Compatible.labels167with graph, finiteEdges, cubic, cover, base, compatible168have finiteLabels : Finite(𝒫(3)) := Finite.powerset with finiteThree169have labels : FunctionBetween(P, E, 𝒫(𝒫(3))) ∧170 (∀ e ∈ E, cardinality(P(e)) =2) :=⟨function, two⟩171witness labelFamily(E, P, 𝒫(3))172exact labels.double_cover173with graph, finiteEdges, finiteLabels, labels, balanced174