1-- Tagged disjoint unions and cardinal addition2-- Part of Cumulus, the Grace17 mathematics library.3-- Copyright (c) 2026 Grant Passmore.4-- Released under the Apache License 2.0. See LICENSE in the repository root.5-- Authors: Grant Passmore67module Grace.Cumulus.Cardinal.Sum8import Finite910-- Tags are Kuratowski pairs. Distinct von Neumann tags make the two11-- images disjoint even when the original carriers overlap.12def inl (x : Set) : Set:= (x, 0)13def inr (y : Set) : Set:= (y, 1)14def disjointSum (A B : Set) : Set:= (A × {0}) ∪ (B × {1})15notationinfixr55"⊎"=> disjointSum16def sumMap (f g A B C D : Set) : Set:= { p ∈ (A ⊎ B) × (C ⊎ D) | (∃ x ∈ A, ∃ y ∈ C, relates(f, x, y) ∧ p = (inl(x) ↦ inl(y))) ∨ (∃ x ∈ B, ∃ y ∈ D, relates(g, x, y) ∧ p = (inr(x) ↦ inr(y))) }17def rightProjection (n : Set) : Set:= { p ∈ (0⊎ n) × n |∃ y ∈ n, p = (inr(y) ↦ y) }1819def natSumEquiv (m n : Nat) →Set20| zero, n => rightProjection(n)21| succ(m), n => adjoinMap(natSumEquiv(m, n), inl(m), add(m, n))2223theorem disjointSum.left (x A B : Set)24requires hx : x ∈ A25shows inl(x) ∈ A ⊎ B26proof27unfold inl28unfold disjointSum29apply union2.left30apply product.pair31exact hx32exact singleton.self3334theorem disjointSum.right (y A B : Set)35requires hy : y ∈ B36shows inr(y) ∈ A ⊎ B37proof38unfold inr39unfold disjointSum40apply union2.right41apply product.pair42exact hy43exact singleton.self4445theorem disjointSum.membership (p A B : Set)46shows p ∈ A ⊎ B ↔ ((∃ x ∈ A, p = inl(x)) ∨ (∃ y ∈ B, p = inr(y)))47proof48constructor49intro hp50simp [disjointSum, union2.membership, product.membership, singleton.membership] at hp51cases hp with hleft | hright52simp [product.membership, singleton.membership] at hleft53rcases hleft with (hbound, witnesses)54obtain (x, hx) := witnesses55rcases hx with (hxA, rest)56obtain⟨tag, tagZero, pairShape⟩:= rest57simp [singleton.membership] at tagZero58left59witness x60constructor61exact hxA62unfold inl63cc64simp [product.membership, singleton.membership] at hright65rcases hright with⟨hbound, y, hyB, tagRight, tagOne, pairShapeRight⟩66simp [singleton.membership] at tagOne67right68witness y69constructor70exact hyB71unfold inr72cc73intro hp74cases hp with hleft | hright75obtain⟨xBack, hxBackA, pairShapeBack⟩:= hleft76rw pairShapeBack77exact disjointSum.left with hxBackA78obtain⟨yBack, hyBackB, pairShapeRightBack⟩:= hright79rw pairShapeRightBack80exact disjointSum.right with hyBackB8182theorem zero.ne_one83shows0≠184proof85intro equal86have member := next.contains at087have successorZero := next.natural at088rw [← successorZero, ← equal, nat.zero] at member89simp9091theorem tags.disjoint (x y : Set)92shows inl(x) ≠ inr(y)93proof94intro equal95unfold inl at equal96unfold inr at equal97obtain (first, tagsEqual) := orderedPair.injective with equal98exact zero.ne_one with tagsEqual99100theorem inl.injective (x y : Set)101requires h : inl(x) = inl(y)102shows x = y103proof104simp [inl] at h105obtain (first, second) := orderedPair.injective with h106exact first107108theorem inr.injective (x y : Set)109requires h : inr(x) = inr(y)110shows x = y111proof112simp [inr] at h113obtain (first, second) := orderedPair.injective with h114exact first115116theorem sumMap.relates_left (f g A B C D x y : Set)117requires hx : x ∈ A118requires hy : y ∈ C119requires hxy : relates(f, x, y)120shows relates(sumMap(f, g, A, B, C, D), inl(x), inl(y))121proof122unfold relates123apply sumMap.membership.backward124constructor125apply product.pair126exact disjointSum.left with hx127exact disjointSum.left with hy128left129refine⟨x, hx, y, hy, hxy, rfl⟩130131theorem sumMap.relates_right (f g A B C D x y : Set)132requires hx : x ∈ B133requires hy : y ∈ D134requires hxy : relates(g, x, y)135shows relates(sumMap(f, g, A, B, C, D), inr(x), inr(y))136proof137unfold relates138apply sumMap.membership.backward139constructor140apply product.pair141exact disjointSum.right with hx142exact disjointSum.right with hy143right144refine⟨x, hx, y, hy, hxy, rfl⟩145146theorem sumMap.factors (f g A B C D u v : Set)147requires h : relates(sumMap(f, g, A, B, C, D), u, v)148shows (∃ x ∈ A, ∃ y ∈ C, u = inl(x) ∧ v = inl(y) ∧ relates(f, x, y)) ∨ (∃ x ∈ B, ∃ y ∈ D, u = inr(x) ∧ v = inr(y) ∧ relates(g, x, y))149proof150unfold relates at h151simp [sumMap.membership] at h152rcases h with (hProduct, hShape)153cases hShape with hleft | hright154obtain⟨x, hxA, y, hyC, hxy, hPair⟩:= hleft155obtain (source, target) := orderedPair.injective with hPair156left157refine⟨x, hxA, y, hyC, source, target, hxy⟩158obtain⟨xRight, hxB, yRight, hyD, hgxy, hPairRight⟩:= hright159obtain (sourceRight, targetRight) := orderedPair.injective with hPairRight160right161refine⟨xRight, hxB, yRight, hyD, sourceRight, targetRight, hgxy⟩162163theorem sumMap.relation (f g A B C D : Set)164shows RelationBetween(sumMap(f, g, A, B, C, D), A ⊎ B, C ⊎ D)165proof166simp [RelationBetween, Subset]167168theorem sumMap.total (f g A B C D : Set)169requires hf : f : A → C170requires hg : g : B → D171shows TotalBetween(sumMap(f, g, A, B, C, D), A ⊎ B, C ⊎ D)172proof173intros u hu174have sourceShape := disjointSum.membership.forward with hu175cases sourceShape with leftShape | rightShape176obtain⟨x, hxA, uShape⟩:= leftShape177obtain⟨y, hyC, hxy⟩:= FunctionBetween.exists_value with hf, hxA178witness inl(y)179constructor180exact disjointSum.left with hyC181rw uShape182exact sumMap.relates_left with hxA, hyC, hxy183obtain⟨xRight, hxB, uShapeRight⟩:= rightShape184obtain⟨yRight, hyD, hgxy⟩:= FunctionBetween.exists_value with hg, hxB185witness inr(yRight)186constructor187exact disjointSum.right with hyD188rw uShapeRight189exact sumMap.relates_right with hxB, hyD, hgxy190191theorem sumMap.functional (f g A B C D : Set)192requires hf : f : A → C193requires hg : g : B → D194shows Functional(sumMap(f, g, A, B, C, D))195proof196intros u v huv w huw197have firstFactor := sumMap.factors with huv198have secondFactor := sumMap.factors with huw199cases firstFactor with firstLeft | firstRight200cases secondFactor with secondLeft | secondRight201obtain⟨x1, hx1A, y1, hy1C, uLeft1, vLeft, hfxy1⟩:= firstLeft202obtain⟨x2, hx2A, y2, hy2C, uLeft2, wLeft, hfxy2⟩:= secondLeft203rw uLeft1 at uLeft2204have sameInput := inl.injective with uLeft2205rw← sameInput at hfxy2206have unique := FunctionBetween.functional with hf, x1, y1, hfxy1, y2, hfxy2207rw [vLeft, wLeft, unique]208rfl209obtain⟨xLeftCross, hxLeftCrossA, yLeftCross, hyLeftCrossC, uLeftCross, hyLeftCrossLast⟩:= firstLeft210obtain⟨xr, hxrB, yr, hyrD, uRight2, hyrLast⟩:= secondRight211rw uLeftCross at uRight2212have impossible := tags.disjoint with uRight2213contradiction214cases secondFactor with secondLeftAfterRight | secondRightAfterRight215obtain⟨xl, hxlA, yl, hylC, uLeftAfterRight, hylLast⟩:= secondLeftAfterRight216obtain⟨xr1, hxr1B, yr1, hyr1D, uRight1, hyr1Last⟩:= firstRight217rw uLeftAfterRight at uRight1218have impossibleReverse := tags.disjoint with uRight1219contradiction220obtain⟨xr2, hxr2B, yr2, hyr2D, uRight2b, wRight, hgxy2⟩:= secondRightAfterRight221obtain⟨xrFirst, hxrFirstB, yrFirst, hyrFirstD, uRightFirst, vRight, hgxyFirst⟩:= firstRight222rw uRightFirst at uRight2b223have sameInputRight := inr.injective with uRight2b224rw← sameInputRight at hgxy2225have uniqueRight := FunctionBetween.functional with hg, xrFirst, yrFirst, hgxyFirst, yr2, hgxy2226rw [vRight, wRight, uniqueRight]227rfl228229theorem sumMap.function (f g A B C D : Set)230requires hf : f : A → C231requires hg : g : B → D232shows sumMap(f, g, A, B, C, D) : A ⊎ B → C ⊎ D233proof234constructor235exact sumMap.relation236constructor237exact sumMap.functional with hf, hg238exact sumMap.total with hf, hg239240theorem sumMap.surjective (f g A B C D : Set)241requires hf : SurjectiveBetween(f, A, C)242requires hg : SurjectiveBetween(g, B, D)243shows SurjectiveBetween(sumMap(f, g, A, B, C, D), A ⊎ B, C ⊎ D)244proof245constructor246have fFunction := Surjective.function with hf247have gFunction := Surjective.function with hg248exact sumMap.function with fFunction, gFunction249intros v hv250have targetShape := disjointSum.membership.forward with hv251cases targetShape with targetLeft | targetRight252obtain⟨y, hyC, vShape⟩:= targetLeft253rcases hf with (fFunctionAgain, fOnto)254specialize fOnto with y, hyC255obtain⟨x, hxA, hxy⟩:= fOnto256witness inl(x)257constructor258exact disjointSum.left with hxA259rw vShape260exact sumMap.relates_left with hxA, hyC, hxy261obtain⟨yRight, hyD, vShapeRight⟩:= targetRight262rcases hg with (gFunctionAgain, gOnto)263specialize gOnto with yRight, hyD264obtain⟨xRight, hxB, hgxy⟩:= gOnto265witness inr(xRight)266constructor267exact disjointSum.right with hxB268rw vShapeRight269exact sumMap.relates_right with hxB, hyD, hgxy270271theorem sumMap.injective (f g A B C D : Set)272requires hf : InjectiveBetween(f, A, C)273requires hg : InjectiveBetween(g, B, D)274shows InjectiveBetween(sumMap(f, g, A, B, C, D), A ⊎ B, C ⊎ D)275proof276constructor277have fFunction := Injective.function with hf278have gFunction := Injective.function with hg279exact sumMap.function with fFunction, gFunction280intros u hu v hv z hz huz hvz281have firstFactor := sumMap.factors with huz282have secondFactor := sumMap.factors with hvz283cases firstFactor with firstLeft | firstRight284cases secondFactor with secondLeft | secondRight285obtain⟨x1, hx1A, y1, hy1C, uLeft, zLeft1, hfxy1⟩:= firstLeft286obtain⟨x2, hx2A, y2, hy2C, vLeft, zLeft2, hfxy2⟩:= secondLeft287rw zLeft1 at zLeft2288have sameOutput := inl.injective with zLeft2289rw← sameOutput at hfxy2290have sameInput := Injective.cancel with hf, hx1A, hx2A, hy1C, hfxy1, hfxy2291rw [uLeft, vLeft, sameInput]292rfl293obtain⟨xLeftCross, hxLeftCrossA, yLeftCross, hyLeftCrossC, uLeftCross, zLeftCross, hfLeftCross⟩:= firstLeft294obtain⟨xRightCross, hxRightCrossB, yRightCross, hyRightCrossD, vRightCross, zRightCross, hgRightCross⟩:= secondRight295rw zLeftCross at zRightCross296have impossible := tags.disjoint with zRightCross297contradiction298cases secondFactor with secondLeftAfterRight | secondRightAfterRight299obtain⟨xLeftAfterRight, hxLeftAfterRightA, yLeftAfterRight, hyLeftAfterRightC, vLeftAfterRight, zLeftAfterRight, hfLeftAfterRight⟩:= secondLeftAfterRight300obtain⟨xRightFirst, hxRightFirstB, yRightFirst, hyRightFirstD, uRightFirst, zRightFirst, hgRightFirst⟩:= firstRight301rw zLeftAfterRight at zRightFirst302have impossibleReverse := tags.disjoint with zRightFirst303contradiction304obtain⟨xRight2, hxRight2B, yRight2, hyRight2D, vRight2, zRight2, hgxy2⟩:= secondRightAfterRight305obtain⟨xRight1, hxRight1B, yRight1, hyRight1D, uRight1, zRight1, hgxy1⟩:= firstRight306rw zRight1 at zRight2307have sameOutputRight := inr.injective with zRight2308rw← sameOutputRight at hgxy2309have sameInputRight := Injective.cancel with hg, hxRight1B, hxRight2B, hyRight1D, hgxy1, hgxy2310rw [uRight1, vRight2, sameInputRight]311rfl312313theorem sumMap.bijective (f g A B C D : Set)314requires hf : BijectiveBetween(f, A, C)315requires hg : BijectiveBetween(g, B, D)316shows BijectiveBetween(sumMap(f, g, A, B, C, D), A ⊎ B, C ⊎ D)317proof318constructor319have fInjective := Bijective.injective with hf320have gInjective := Bijective.injective with hg321exact sumMap.injective with fInjective, gInjective322have fSurjective := Bijective.surjective with hf323have gSurjective := Bijective.surjective with hg324exact sumMap.surjective with fSurjective, gSurjective325326theorem Equipotent.disjointSum (A B C D : Set)327requires hAC : Equipotent(A, C)328requires hBD : Equipotent(B, D)329shows Equipotent(A ⊎ B, C ⊎ D)330proof331obtain (f, hf) := hAC332obtain (g, hg) := hBD333witness sumMap(f, g, A, B, C, D)334exact sumMap.bijective with hf, hg335336theorem rightProjection.relates (y n : Set)337requires hy : y ∈ n338shows relates(rightProjection(n), inr(y), y)339proof340unfold relates341apply rightProjection.membership.backward342constructor343apply product.pair344exact disjointSum.right with hy345exact hy346refine⟨y, hy, rfl⟩347348theorem rightProjection.factors (u v n : Set)349requires h : relates(rightProjection(n), u, v)350shows v ∈ n ∧ u = inr(v)351proof352simp [relates, rightProjection.membership, orderedPair.injective]353354theorem rightProjection.relation (n : Set)355shows RelationBetween(rightProjection(n), 0⊎ n, n)356proof357simp [RelationBetween, Subset]358359theorem rightProjection.total (n : Set)360shows TotalBetween(rightProjection(n), 0⊎ n, n)361proof362intros u hu363have sourceShape := disjointSum.membership.forward with hu364cases sourceShape with impossibleLeft | rightShape365obtain⟨x, hxZero, uLeft⟩:= impossibleLeft366rw nat.zero at hxZero367simp368obtain⟨y, hyN, uRight⟩:= rightShape369witness y370constructor371exact hyN372rw uRight373exact rightProjection.relates with hyN374375theorem rightProjection.functional (n : Set)376shows Functional(rightProjection(n))377proof378simp [Functional, rightProjection.factors, inr.injective]379380theorem rightProjection.function (n : Set)381shows rightProjection(n) : 0⊎ n → n382proof383constructor384exact rightProjection.relation385constructor386exact rightProjection.functional387exact rightProjection.total at n388389theorem rightProjection.injective (n : Set)390shows InjectiveBetween(rightProjection(n), 0⊎ n, n)391proof392constructor393exact rightProjection.function394intros u hu v hv y hy huy hvy395obtain (hyN, uShape) := rightProjection.factors with huy396obtain (hyNAgain, vShape) := rightProjection.factors with hvy397rw [uShape, vShape]398rfl399400theorem rightProjection.surjective (n : Set)401shows SurjectiveBetween(rightProjection(n), 0⊎ n, n)402proof403constructor404exact rightProjection.function405intros y hy406witness inr(y)407constructor408exact disjointSum.right with hy409exact rightProjection.relates with hy410411theorem rightProjection.bijective (n : Set)412shows BijectiveBetween(rightProjection(n), 0⊎ n, n)413proof414refine⟨rightProjection.injective at n, rightProjection.surjective at n⟩415416theorem inl.fresh (m n : Nat)417shows¬inl(m) ∈ m ⊎ n418proof419intro member420have shape := disjointSum.membership.forward with member421cases shape with leftShape | rightShape422obtain⟨x, hxM, tagsEqual⟩:= leftShape423have same := inl.injective with tagsEqual424rw← same at hxM425have irreflexive := membership.irreflexive with hxM426contradiction427obtain⟨y, hyN, tagsEqualRight⟩:= rightShape428have disjoint := tags.disjoint with tagsEqualRight429contradiction430431theorem disjointSum.successor_left (m n : Nat)432shows succ(m) ⊎ n = insert(inl(m), m ⊎ n)433proof434ext p435constructor436 . intro hp437have shape := disjointSum.membership.forward with hp438cases shape with leftShape | rightShape439 . obtain (x, hx) := leftShape440rcases hx with (hxSucc, pairShape)441have successorShape := membership.successor_set{n := m}.forward with hxSucc442cases successorShape with oldMember | newest443 . apply insert.contains at p, inl(m), m ⊎ n444rw pairShape445exact disjointSum.left with oldMember446 . rw [pairShape, newest]447exact insert.self448 . obtain (y, hy) := rightShape449rcases hy with (hyN, pairShape)450apply insert.contains451rw pairShape452exact disjointSum.right with hyN453 . intro hp454have shape := insert.membership.forward with hp455cases shape with newest | oldMember456 . rw newest457simp [disjointSum.membership, membership.successor_set]458 . have oldShape := disjointSum.membership.forward with oldMember459cases oldShape with leftShape | rightShape460 . obtain (xOld, hxOld) := leftShape461rcases hxOld with (hxM, pairShapeOld)462rw pairShapeOld463simp [disjointSum.membership, membership.successor_set]464 . obtain (yOld, hyOld) := rightShape465rcases hyOld with (hyN, pairShapeRight)466rw pairShapeRight467exact disjointSum.right with hyN468469theorem natural.successor_as_insert (n : Nat)470shows succ(n) = insert(n, n)471proof472simp [next.natural, next, insert, union2.commutative]473474theorem natSumEquiv.bijective (n m : Nat)475shows BijectiveBetween(natSumEquiv(m, n), m ⊎ n, add(m, n))476proof477induction m478| zero =>settlewith natSumEquiv, add, rightProjection.bijective479| succ(k) using ih =>480rw [natSumEquiv, add, disjointSum.successor_left, natural.successor_as_insert]481apply adjoinMap.bijective482 . exact ih483 . intro member484have shape := disjointSum.membership.forward with member485cases shape with leftShape | rightShape486 . obtain (xFresh, hxFresh) := leftShape487rcases hxFresh with (hxK, tagsEqual)488have same := inl.injective with tagsEqual489rw← same at hxK490have irreflexive := membership.irreflexive with hxK491contradiction492 . obtain (yFresh, hyFresh) := rightShape493rcases hyFresh with (hyN, tagsEqualRight)494have disjoint := tags.disjoint with tagsEqualRight495contradiction496 . exact membership.irreflexive at add(k, n)497498theorem Equipotent.nat_disjointSum (m n : Set)499requires hm : Nat(m)500requires hn : Nat(n)501shows (m ⊎ n) ≃ add(m, n)502proof503witness natSumEquiv(m, n)504exact natSumEquiv.bijective with hn, hm505506theorem HasCardinality.disjointSum (A B m n : Set)507requires hA : HasCardinality(A, m)508requires hB : HasCardinality(B, n)509shows HasCardinality(A ⊎ B, add(m, n))510proof511rcases hA with (hm, equipotentA)512rcases hB with (hn, equipotentB)513constructor514 . exact Grace.Core.Nat.Algebra.add.closed at n, m515 . have tagged := Equipotent.disjointSum with equipotentA, equipotentB516have numeric := Equipotent.nat_disjointSum with hm, hn517exact Equipotent.transitive with tagged, numeric518519theorem Finite.disjointSum (A B : Set)520requires finiteA : Finite(A)521requires finiteB : Finite(B)522shows Finite(A ⊎ B)523proof524obtain (m, hA) := finiteA525obtain (n, hB) := finiteB526witness add(m, n)527exact HasCardinality.disjointSum with hA, hB528