1-- Even edge sets: every vertex meets an even number of edge ends. They are2-- the Eulerian subgraphs, and they form a group under symmetric difference.3-- Part of Cumulus, the Grace17 mathematics library.4-- Copyright (c) 2026 Grant Passmore.5-- Released under the Apache License 2.0. See LICENSE in the repository root.6-- Authors: Grant Passmore78module Grace.Cumulus.GraphTheory.Multigraph.Even9import Degree10import Cardinal.SumParity1112predicate EvenEdgeSet (V leftEnd rightEnd F : Set) :=13 Finite(F) ∧ (∀ v ∈ V, Even(degreeIn(leftEnd, rightEnd, F, v)))1415theorem EvenEdgeSet.empty (V leftEnd rightEnd : Set)16shows EvenEdgeSet(V, leftEnd, rightEnd, ∅)17proof18constructor19 . exact Finite.empty20 . intros v hv21rw degreeIn.empty22exact Even.zero2324-- A loop contributes two ends at its vertex and none elsewhere.25theorem EvenEdgeSet.loop (V leftEnd rightEnd e : Set)26requires loop : leftEnd(e) = rightEnd(e)27shows EvenEdgeSet(V, leftEnd, rightEnd, {e})28proof29constructor30 . exact Finite.singleton31 . intros v hv32 by_cases atV : leftEnd(e) = v33 . haveright : rightEnd(e) = v bycc34rw degreeIn.loop with atV, right35exact Even.two36 . haveright : rightEnd(e) ≠ v bycc37rw degreeIn.absent with atV, right38exact Even.zero3940-- Degrees add modulo two under symmetric difference, so even sets are closed41-- under it.42theorem EvenEdgeSet.symmetricDifference (V leftEnd rightEnd F G : Set)43requires first : EvenEdgeSet(V, leftEnd, rightEnd, F)44requires second : EvenEdgeSet(V, leftEnd, rightEnd, G)45shows EvenEdgeSet(V, leftEnd, rightEnd, F △ G)46proof47have finiteF := first.left48have finiteG := second.left49constructor50 . have inside : F △ G ⊆ F ∪ G :=51 symmetricDifference.subset with union2.subset_left, union2.subset_right52exact Finite.subset with (Finite.union with finiteF, finiteG), inside53 . intros v hv54rw degreeIn.symmetricDifference_parity with finiteF, finiteG55have evenF := first.right with v, hv56have evenG := second.right with v, hv57tauto5859theorem EvenEdgeSet.union_disjoint (V leftEnd rightEnd F G : Set)60requires first : EvenEdgeSet(V, leftEnd, rightEnd, F)61requires second : EvenEdgeSet(V, leftEnd, rightEnd, G)62requires apart : Disjoint(F, G)63shows EvenEdgeSet(V, leftEnd, rightEnd, F ∪ G)64proof65have finiteF := first.left66have finiteG := second.left67constructor68 . exact Finite.union with finiteF, finiteG69 . intros v hv70rw degreeIn.union_disjoint with finiteF, finiteG, apart71exact Even.add with (first.right with v, hv), (second.right with v, hv)7273-- Of F, G, and F △ G, if two are even so is the third.74theorem EvenEdgeSet.of_symmetricDifference (V leftEnd rightEnd F G : Set)75requires first : EvenEdgeSet(V, leftEnd, rightEnd, F)76requires finite : Finite(G)77requires difference : EvenEdgeSet(V, leftEnd, rightEnd, F △ G)78shows EvenEdgeSet(V, leftEnd, rightEnd, G)79proof80have finiteF := first.left81constructor82 . exact finite83 . intros v hv84have evenD := difference.right with v, hv85rw degreeIn.symmetricDifference_parity with finiteF, finite at evenD86exact evenD.forward with (first.right with v, hv)87