1-- The sum of an indicator over a finite set counts the members it marks2-- 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.IndicatorSum8import NaturalSum9import Set.Indicator1011defgraph indicatorMap (A V : Set) (v ∈ V) : ℕ := indicator(A, v)12proof13have natural := indicator.natural at A, v14exact nat.omega.forward with natural1516theorem indicatorMap.natural (A V : Set)17shows∀ v ∈ V, indicatorMap(A, V)(v) ∈ ℕ18proof19intros v hv20rw indicatorMap.value with hv21exact nat.omega.forward with (indicator.natural at A, v)2223-- Meeting a point counts it exactly when the point is a member.24theorem cardinality.intersection_singleton (X a : Set)25shows cardinality(X ∩ {a}) = indicator(X, a)26proof27 by_cases member : a ∈ X28 . have same : X ∩ {a} = {a}29ext y30simp31have one := indicator.member at X, a with member32rw [same, cardinality.singleton, one]33rfl34 . have same : X ∩ {a} =∅35ext y36simp37have zero := indicator.absent at X, a with member38rw [same, zero]39exact cardinality.empty4041theorem natSum.indicator_of_size (A : Set, n : Nat)42shows∀ V, Finite(V) → cardinality(V) = n → natSum(V, indicatorMap(A, V)) = cardinality(V ∩ A)43proof44induction n45| zero =>46intros V finite size47have has := cardinality.correct with finite48rw size at has49have empty := HasCardinality.empty_of_zero at V with has50rw [empty, natSum.empty, intersection.left_empty]51rw← nat.zero52rw cardinality.natural53rfl54| succ(k) using ih =>55intros V finite size56have has := cardinality.correct with finite57rw size at has58obtain⟨a, ha⟩:= HasCardinality.exists_member with has59have removed := cardinality.remove with finite, ha60rw size at removed61have smaller := Naturals.injective.succ with removed62have restSize : cardinality(V ∖ {a}) = k63 symm64exact smaller65have restInside := difference.subset_left at V, {a}66have restFinite := Finite.subset with finite, restInside67have rest := ih with V ∖ {a}, restFinite, restSize68have fresh : ¬a ∈ V ∖ {a}69intro inside70have parts := difference.singleton_membership.forward with inside71apply parts.right72rfl73have restore := insert.restore with ha74have graph := indicatorMap.function at A, V75have restGraph := indicatorMap.function at A, V ∖ {a}76have weights : ∀ v ∈ V ∖ {a}, indicatorMap(A, V)(v) ∈ ℕ77intros v hv78exact FunctionBetween.apply_closed with graph, (restInside with v, hv)79have weightA := FunctionBetween.apply_closed with graph, ha80have agree : ∀ v ∈ V ∖ {a}, indicatorMap(A, V ∖ {a})(v) = indicatorMap(A, V)(v)81intros v hv82have valueRest := indicatorMap.value at A, V ∖ {a}, v with hv83have value := indicatorMap.value at A, V, v with (restInside with v, hv)84rw [valueRest, value]85rfl86have sameSum := natSum.congr with agree87have inserted := natSum.insert with restFinite, weights, weightA, fresh88rw restore at inserted89have valueA := indicatorMap.value at A, V, a with ha90have restIntersection := Finite.subset with restFinite, (intersection.subset_left at V ∖ {a}, A)91havesplit : a ∈ A ∨¬a ∈ A bytauto92casessplitwith inA | outA93 . have one := indicator.member with inA94have decomposition : V ∩ A = insert(a, (V ∖ {a}) ∩ A)95ext x96constructor97 . intro hx98have both := intersection.membership.forward with hx99have split2 : x = a ∨ x ≠ a bytauto100apply insert.membership.backward101cases split2 with same | different102 . left103exact same104 . right105have inRest : x ∈ V ∖ {a} := difference.singleton_membership.backward with⟨both.left, different⟩106exact intersection.membership.backward with⟨inRest, both.right⟩107 . intro hx108have split2 := insert.membership.forward with hx109apply intersection.membership.backward110cases split2 with same | inRest111 . rw same112exact⟨ha, inA⟩113 . have both := intersection.membership.forward with inRest114have parts := difference.singleton_membership.forward with both.left115exact⟨parts.left, both.right⟩116have freshIntersection : ¬a ∈ (V ∖ {a}) ∩ A117intro inside118have both := intersection.membership.forward with inside119exact fresh with both.left120have counted := cardinality.insert with restIntersection, freshIntersection121rw [inserted, ← sameSum, rest, valueA, one, decomposition, counted]122have correct := cardinality.correct with restIntersection123have cardNat := correct.left124rw add.right_one125rfl126 . have zero := indicator.absent with outA127have decomposition : V ∩ A = (V ∖ {a}) ∩ A128ext x129constructor130 . intro hx131have both := intersection.membership.forward with hx132have different : x ≠ a133intro same134rw same at both135exact outA with both.right136have inRest : x ∈ V ∖ {a} := difference.singleton_membership.backward with⟨both.left, different⟩137exact intersection.membership.backward with⟨inRest, both.right⟩138 . intro hx139have both := intersection.membership.forward with hx140have parts := difference.singleton_membership.forward with both.left141exact intersection.membership.backward with⟨parts.left, both.right⟩142rw [inserted, ← sameSum, rest, valueA, zero, decomposition]143have correct := cardinality.correct with restIntersection144have cardNat := correct.left145rw add.right_unit146rfl147148149-- The same for a finite set, with no size parameter.150theorem natSum.indicator (V A : Set)151requires finite : Finite(V)152shows natSum(V, indicatorMap(A, V)) = cardinality(V ∩ A)153proof154have correct := cardinality.correct with finite155have natural := correct.left156have size : cardinality(V) = cardinality(V) byrfl157exact natSum.indicator_of_size at A, cardinality(V)158with natural, V, finite, size159160