1-- Sums over the divisors of a natural number: ∑_{d ∣ n} w(d) for an2-- integer-valued weight w, its value at n = 1, congruence, scaling,3-- vanishing, restriction to a support, the complementary divisor d ↦ n / d4-- as an involution of divisors(n) with the reflection of a divisor sum along5-- it, the Dirichlet summands a(d) · b(n / d), and the summatory function6-- Part of Cumulus, the Grace17 mathematics library.7-- Copyright (c) 2026 Grant Passmore.8-- Released under the Apache License 2.0. See LICENSE in the repository root.9-- Authors: Grant Passmore1011module Grace.Cumulus.Combinatorics.DivisorSums12import IntegerSum13import NumberTheory1415-- Arithmetic of the quotient of a number by one of its divisors.16theorem divides.quotient_ne_zero (d n : Nat)17requires nonzero : n ≠018requires factor : d ∣ n19shows quotientNat(n, d) ≠020proof21have dNonzero := divides.nonzero with factor, nonzero22have equation := divides.quotient_equation with dNonzero, factor23intro zero24rw zero at equation25have product : d *0=0byring26have same : n =0bycc27exact nonzero with same2829theorem quotientNat.mul_left (a b : Nat)30requires nonzero : a ≠031shows quotientNat(a * b, a) = b32proof33have factor := divides.mul_left_self at a, b34have equation := divides.quotient_equation with nonzero, factor35 symm36exact mul.left_cancel_positive with nonzero, equation3738theorem quotientNat.complement (d n : Nat)39requires nonzero : n ≠040requires factor : d ∣ n41shows quotientNat(n, quotientNat(n, d)) = d42proof43have dNonzero := divides.nonzero with factor, nonzero44have equation := divides.quotient_equation with dNonzero, factor45have quotientNonzero := divides.quotient_ne_zero with nonzero, factor46have commuted := mul.commutative at d, quotientNat(n, d)47have shape : n = quotientNat(n, d) * d bycc48have reduced := quotientNat.mul_left at quotientNat(n, d), d with49 quotientNonzero50cc5152theorem divides.mul_iff_quotient (d e n : Nat)53requires nonzero : n ≠054requires factor : d ∣ n55shows d * e ∣ n ↔ e ∣ quotientNat(n, d)56proof57have dNonzero := divides.nonzero with factor, nonzero58have equation := divides.quotient_equation with dNonzero, factor59have cancel := divides.mul_cancel_left at d, e, quotientNat(n, d) with60 dNonzero61rw← equation at cancel62exact cancel6364theorem divisors.quotient_member (n d : Nat)65requires nonzero : n ≠066requires member : d ∈ divisors(n)67shows quotientNat(n, d) ∈ divisors(n)68proof69have factor := divisors.divides with member70have dNonzero := divides.nonzero with factor, nonzero71have quotientDivides := divides.quotient with dNonzero, factor72have below := divides.le with quotientDivides, nonzero73have characterization := divisors.membership_le at n, quotientNat(n, d)74exact characterization.backward with⟨below, quotientDivides⟩7576theorem divisors.quotient_subset (n d : Nat)77requires nonzero : n ≠078requires factor : d ∣ n79shows divisors(quotientNat(n, d)) ⊆ divisors(n)80proof81have dNonzero := divides.nonzero with factor, nonzero82have quotientDivides := divides.quotient with dNonzero, factor83exact divisors.subset_of_divides with nonzero, quotientDivides8485-- The sum ∑_{d ∣ n} w(d) of an integer-valued weight over the divisors of n.86def divisorSum (n : Nat, w : Set) : Set:= integerSetSum(divisors(n), w)8788theorem divisorSum.integer (n : Nat, w : Set)89requires weights : w : ℕ → ℤ90shows Integer(divisorSum(n, w))91proof92have finite := divisors.finite at n93have subset := divisors.subset_naturals at n94have total := integerSetSum.integer with finite, weights, subset95unfold divisorSum96exact total9798theorem divisorSum.one (w : Set)99requires weights : w : ℕ → ℤ100shows divisorSum(1, w) = w(1)101proof102have oneNat : Nat(1) bytypecheck103have oneMember := nat.omega.forward with oneNat104have single := integerSetSum.singleton with weights, oneMember105have same := divisors.one106unfold divisorSum107cc108109theorem divisorSum.congr (n : Nat, w v : Set)110requires weightsW : w : ℕ → ℤ111requires weightsV : v : ℕ → ℤ112requires values : ∀ d ∈ divisors(n), w(d) = v(d)113shows divisorSum(n, w) = divisorSum(n, v)114proof115have subset := divisors.subset_naturals at n116have same := integerSetSum.congr with weightsW, weightsV, subset, values117unfold divisorSum118cc119120theorem divisorSum.scale (n : Nat, w v : Set) (a : Integer)121requires weightsW : w : ℕ → ℤ122requires weightsV : v : ℕ → ℤ123requires values : ∀ d ∈ divisors(n), v(d) = integerMulValue(a, w(d))124shows divisorSum(n, v) = integerMulValue(a, divisorSum(n, w))125proof126have finite := divisors.finite at n127have subset := divisors.subset_naturals at n128have scaled := integerSetSum.scale with finite, weightsW, weightsV, subset,129 values130unfold divisorSum131cc132133theorem divisorSum.zero (n : Nat, w : Set)134requires weights : w : ℕ → ℤ135requires values : ∀ d ∈ divisors(n), w(d) = integerZero136shows divisorSum(n, w) = integerZero137proof138have finite := divisors.finite at n139have subset := divisors.subset_naturals at n140have vanishing := integerSetSum.zero with finite, weights, subset, values141unfold divisorSum142cc143144theorem divisorSum.support (n : Nat, S w : Set)145requires weights : w : ℕ → ℤ146requires inner : S ⊆ divisors(n)147requires vanishes : ∀ d ∈ divisors(n), ¬(d ∈ S) → w(d) = integerZero148shows divisorSum(n, w) = integerSetSum(S, w)149proof150have finite := divisors.finite at n151have subset := divisors.subset_naturals at n152have restricted := integerSetSum.support with finite, weights, subset, inner,153 vanishes154unfold divisorSum155cc156157-- A weight vanishing at every proper divisor of n sums to its value at n.158theorem divisorSum.single (n : Nat, w : Set)159requires weights : w : ℕ → ℤ160requires vanishes : ∀ d ∈ divisors(n), d ≠ n → w(d) = integerZero161shows divisorSum(n, w) = w(n)162proof163haveself:= divisors.self_member at n164have inner : {n} ⊆ divisors(n) bysimp165have nNat : Nat(n) bytypecheck166have nMember := nat.omega.forward with nNat167have outside : ∀ d ∈ divisors(n), ¬(d ∈ {n}) → w(d) = integerZero168intros d hd absent169have different : d ≠ n170intro same171apply absent172rw same173simp174exact vanishes with d, hd, different175have restricted := divisorSum.support with weights, inner, outside176have single := integerSetSum.singleton with weights, nMember177rw [restricted, single]178rfl179180-- The complementary divisor n / d of a divisor d of n.181defgraph complementaryDivisor (n : Nat) (d ∈ divisors(n)) : divisors(n) :=182 quotientNat(n, d)183requires nonzero : n ≠0184proof185have dNat := divisors.natural with member186exact divisors.quotient_member with nonzero, member187188theorem complementaryDivisor.involution (n : Nat)189requires nonzero : n ≠0190shows InvolutionOn(complementaryDivisor(n), divisors(n))191proof192have function := complementaryDivisor.function at n with nonzero193refine⟨function, _⟩194intros d hd195have dNat := divisors.natural with hd196have factor := divisors.divides with hd197have image := divisors.quotient_member with nonzero, hd198have first := complementaryDivisor.value at n, d with nonzero, hd199have second := complementaryDivisor.value at n, quotientNat(n, d) with200 nonzero, image201have twice := quotientNat.complement with nonzero, factor202rw [first, second, twice]203rfl204205theorem complementaryDivisor.bijective (n : Nat)206requires nonzero : n ≠0207shows BijectiveBetween(complementaryDivisor(n), divisors(n), divisors(n))208proof209have involution := complementaryDivisor.involution with nonzero210exact InvolutionOn.bijective with involution211212-- The weight d ↦ w(n / d).213defgraph complementaryWeights (n : Nat) (w : Set) (d ∈ ℕ) : ℤ :=214 w(quotientNat(n, d))215requires weights : w : ℕ → ℤ216proof217have dNat := nat.omega.backward with member218have quotientNatural := quotientNat.natural at d, n219have quotientMember := nat.omega.forward with quotientNatural220exact FunctionBetween.apply_closed with weights, quotientMember221222-- Summing w(n / d) over the divisors d of n is summing w over them.223theorem divisorSum.reflect (n : Nat, w : Set)224requires nonzero : n ≠0225requires weights : w : ℕ → ℤ226shows divisorSum(n, complementaryWeights(n, w)) = divisorSum(n, w)227proof228have finite := divisors.finite at n229have subset := divisors.subset_naturals at n230have reflected := complementaryWeights.function at n, w with weights231have bijective := complementaryDivisor.bijective with nonzero232have values : ∀ d ∈ divisors(n),233 complementaryWeights(n, w)(d) = w(complementaryDivisor(n)(d))234intros d hd235have dMember := subset with d, hd236have value := complementaryWeights.value at n, w, d with weights237have image := complementaryDivisor.value at n, d with nonzero, hd238cc239have sum := integerSetSum.reindex at divisors(n), divisors(n), ℕ, ℕ,240 complementaryWeights(n, w), w, complementaryDivisor(n) with finite,241 reflected, weights, subset, subset, bijective, values242unfold divisorSum243cc244245-- The summands a(d) · b(n / d) of a Dirichlet convolution at n.246defgraph dirichletTerms (a b : Set) (n : Nat) (d ∈ ℕ) : ℤ :=247 integerMulValue(a(d), b(quotientNat(n, d)))248requires weightsA : a : ℕ → ℤ249requires weightsB : b : ℕ → ℤ250proof251have dNat := nat.omega.backward with member252have quotientNatural := quotientNat.natural at d, n253have quotientMember := nat.omega.forward with quotientNatural254haveleft:= FunctionBetween.apply_closed with weightsA, member255haveright:= FunctionBetween.apply_closed with weightsB, quotientMember256exact integerMulValue.integer at a(d), b(quotientNat(n, d)) with*257258-- The summatory function n ↦ ∑_{d ∣ n} w(d) of an integer-valued weight.259defgraph summatory (w : Set) (n ∈ ℕ) : ℤ := divisorSum(n, w)260requires weights : w : ℕ → ℤ261proof262have nNat := nat.omega.backward with member263exact divisorSum.integer with weights264