|
| 1 | +/- |
| 2 | +Copyright (c) 2026 Christoph Spiegel. All rights reserved. |
| 3 | +Released under Apache 2.0 license as described in the file LICENSE. |
| 4 | +Authors: Christoph Spiegel |
| 5 | +-/ |
| 6 | +module |
| 7 | + |
| 8 | +public import Mathlib.Algebra.BigOperators.Field |
| 9 | +public import Mathlib.Combinatorics.SimpleGraph.Automorphism |
| 10 | +public import Mathlib.Combinatorics.SimpleGraph.Finite |
| 11 | +public import Mathlib.Data.Nat.Choose.Sum |
| 12 | +public import Mathlib.Data.Rat.Cast.Defs |
| 13 | + |
| 14 | +/-! |
| 15 | +# Möbius inversion between copy counts and induced copy counts |
| 16 | +
|
| 17 | +For a guest graph `G : SimpleGraph V` and a host graph `H : SimpleGraph W` with finite |
| 18 | +vertex types, this file establishes the standard summation identity expressing the copy |
| 19 | +count `H.copyCount G` as a sum over supergraphs of `G` (on the same vertex type `V`) of |
| 20 | +induced copy counts `H.embeddingCount G'`, together with its Möbius inverse expressing |
| 21 | +`H.embeddingCount G` as a signed sum of `H.copyCount G'`. |
| 22 | +
|
| 23 | +Following the convention from `Mathlib/Combinatorics/SimpleGraph/Copy.lean` and |
| 24 | +`Mathlib/Combinatorics/SimpleGraph/InducedCopy.lean`, counting operations are host-first |
| 25 | +(`H.copyCount G`, `H.embeddingCount G`); types are guest-first (`Copy G H`, `Embedding G H`). |
| 26 | +
|
| 27 | +## Main declarations |
| 28 | +
|
| 29 | +* `SimpleGraph.Copy.inducedShape` — for `f : Copy G H`, the supergraph of `G` on `V` |
| 30 | + recording the induced adjacency on the image, transported back via `f.toEmbedding`. |
| 31 | +* `SimpleGraph.Copy.fiberInducedShapeEquiv` — the per-fiber bijection between copies with a |
| 32 | + prescribed induced shape and graph embeddings of that shape. |
| 33 | +* `SimpleGraph.Copy.equivSigmaEmbedding` — the load-bearing bijection |
| 34 | + `Copy G H ≃ Σ G' ∈ Icc G ⊤, Embedding G'.val H`. |
| 35 | +* `SimpleGraph.iccEquivPowersetEdgeFinsetSdiff` — for `G ≤ K`, the equivalence |
| 36 | + `Finset.Icc G K ≃ (K.edgeFinset \ G.edgeFinset).powerset` used to reduce the inner |
| 37 | + alternating sum to `Finset.sum_powerset_neg_one_pow_card`. |
| 38 | +
|
| 39 | +## Main results |
| 40 | +
|
| 41 | +* `SimpleGraph.copyCount_eq_sum_embeddingCount` — forward identity: |
| 42 | + `H.copyCount G = ∑ G' ∈ Icc G ⊤, H.embeddingCount G'`. |
| 43 | +* `SimpleGraph.embeddingCount_eq_sum_signed_copyCount` — Möbius inverse over `ℤ`: |
| 44 | + `(H.embeddingCount G : ℤ) = ∑ G' ∈ Icc G ⊤, |
| 45 | + (-1) ^ #(G'.edgeFinset \ G.edgeFinset) * (H.copyCount G' : ℤ)`. |
| 46 | +
|
| 47 | +## Implementation notes |
| 48 | +
|
| 49 | +The forward bijection `Copy.equivSigmaEmbedding` is the only "real" content; the Möbius |
| 50 | +direction reduces to it via the classical alternating-sum identity |
| 51 | +`Finset.sum_powerset_neg_one_pow_card`, reindexed through the order-isomorphism |
| 52 | +`G' ∈ Icc G ⊤ ↔ S ⊆ E(⊤) \ E(G)`. |
| 53 | +
|
| 54 | +The Möbius identity is stated in `ℤ` (rather than `ℕ`) because the signs are essential. |
| 55 | +
|
| 56 | +The `LocallyFiniteOrder (SimpleGraph V)` instance consumed by `Finset.Icc G ⊤` comes from |
| 57 | +`SimpleGraph.Finite.instLocallyFiniteOrder`, which requires `[DecidableLE (SimpleGraph V)]`. |
| 58 | +The declarations below routinely invoke `Classical.decRel _` since the bijection is already |
| 59 | +noncomputable. |
| 60 | +-/ |
| 61 | + |
| 62 | +public section |
| 63 | + |
| 64 | +open Finset Function |
| 65 | + |
| 66 | +namespace SimpleGraph |
| 67 | + |
| 68 | +variable {V W : Type*} |
| 69 | + |
| 70 | +/-! ### Induced shape of a copy |
| 71 | +
|
| 72 | +The pullback `H.comap f.toEmbedding` records the induced adjacency on the image of a copy |
| 73 | +`f : Copy G H`, transported back to `V`. It is always a supergraph of `G`, and pinning it |
| 74 | +down to a specific supergraph `G'` promotes the copy to an embedding `G' ↪g H`. -/ |
| 75 | + |
| 76 | +namespace Copy |
| 77 | + |
| 78 | +variable {G G' : SimpleGraph V} {H : SimpleGraph W} |
| 79 | + |
| 80 | +/-- The pullback of the host graph along the underlying injection of a copy. -/ |
| 81 | +def inducedShape (f : Copy G H) : SimpleGraph V := |
| 82 | + H.comap f.toEmbedding |
| 83 | + |
| 84 | +@[simp] lemma inducedShape_adj (f : Copy G H) {a b : V} : |
| 85 | + f.inducedShape.Adj a b ↔ H.Adj (f a) (f b) := Iff.rfl |
| 86 | + |
| 87 | +lemma le_inducedShape (f : Copy G H) : G ≤ f.inducedShape := |
| 88 | + fun _ _ => f.toHom.map_adj |
| 89 | + |
| 90 | +/-- A copy with induced shape `G'` promotes to a graph embedding `G' ↪g H`. -/ |
| 91 | +@[expose] def toEmbeddingOfInducedShapeEq (f : Copy G H) (h : f.inducedShape = G') : |
| 92 | + G' ↪g H where |
| 93 | + toFun := f |
| 94 | + inj' := f.injective |
| 95 | + map_rel_iff' {a b} := by |
| 96 | + change H.Adj (f a) (f b) ↔ G'.Adj a b |
| 97 | + rw [← h, inducedShape_adj] |
| 98 | + |
| 99 | +@[simp] lemma toEmbeddingOfInducedShapeEq_apply (f : Copy G H) (h : f.inducedShape = G') |
| 100 | + (v : V) : f.toEmbeddingOfInducedShapeEq h v = f v := rfl |
| 101 | + |
| 102 | +/-- The fiber of `inducedShape` over a supergraph `G' ≥ G` is canonically `Embedding G' H`. -/ |
| 103 | +def fiberInducedShapeEquiv (hGG' : G ≤ G') : |
| 104 | + {f : Copy G H // f.inducedShape = G'} ≃ Embedding G' H where |
| 105 | + toFun f := f.val.toEmbeddingOfInducedShapeEq f.prop |
| 106 | + invFun e := ⟨e.toCopy.comp (Copy.ofLE G G' hGG'), by ext a b; simp [inducedShape]⟩ |
| 107 | + left_inv f := by apply Subtype.ext; ext v; simp |
| 108 | + right_inv e := by apply DFunLike.ext; intro v; simp |
| 109 | + |
| 110 | +end Copy |
| 111 | + |
| 112 | +@[simp] lemma Embedding.inducedShape_toCopy {G : SimpleGraph V} {H : SimpleGraph W} |
| 113 | + (e : Embedding G H) : e.toCopy.inducedShape = G := by |
| 114 | + ext a b; rw [Copy.inducedShape_adj]; exact e.map_rel_iff |
| 115 | + |
| 116 | +/-! ### Forward bijection and count identity -/ |
| 117 | + |
| 118 | +section Forward |
| 119 | + |
| 120 | +variable {G : SimpleGraph V} {H : SimpleGraph W} |
| 121 | + |
| 122 | +/-- The load-bearing equivalence: a copy of `G` in `H` is the same data as a choice of |
| 123 | +supergraph `G' ∈ Icc G ⊤` (the induced shape) together with a graph embedding |
| 124 | +`G' ↪g H`. This expresses every copy uniquely as an induced copy of some shape `G'` |
| 125 | +between `G` and the complete graph. |
| 126 | +
|
| 127 | +The proof goes via the canonical fiber decomposition `Equiv.sigmaFiberEquiv` for the map |
| 128 | +`Copy.inducedShape`. The index `K : SimpleGraph V` is restricted to `Icc G ⊤`, which is |
| 129 | +exactly the set of shapes with nonempty fiber. The per-fiber bijection is |
| 130 | +`Copy.fiberInducedShapeEquiv`. -/ |
| 131 | +noncomputable def Copy.equivSigmaEmbedding (G : SimpleGraph V) (H : SimpleGraph W) |
| 132 | + [Fintype V] [DecidableEq V] [DecidableLE (SimpleGraph V)] : |
| 133 | + Copy G H ≃ Σ G' : ↥(Finset.Icc G ⊤), Embedding G'.val H := |
| 134 | + (Equiv.sigmaFiberEquiv (Copy.inducedShape : Copy G H → SimpleGraph V)).symm.trans <| |
| 135 | + { toFun := fun ⟨K, f⟩ => |
| 136 | + let hGK : G ≤ K := f.prop ▸ f.val.le_inducedShape |
| 137 | + ⟨⟨K, Finset.mem_Icc.mpr ⟨hGK, le_top⟩⟩, |
| 138 | + Copy.fiberInducedShapeEquiv hGK f⟩ |
| 139 | + invFun := fun ⟨⟨K, hK⟩, e⟩ => |
| 140 | + ⟨K, (Copy.fiberInducedShapeEquiv (Finset.mem_Icc.mp hK).1).symm e⟩ |
| 141 | + left_inv := by |
| 142 | + rintro ⟨K, f⟩ |
| 143 | + simp |
| 144 | + right_inv := by |
| 145 | + rintro ⟨⟨K, hK⟩, e⟩ |
| 146 | + simp only [Equiv.apply_symm_apply] } |
| 147 | + |
| 148 | +/-- Forward identity: every copy of `G` in `H` is an induced copy of some unique |
| 149 | +supergraph `G' ∈ Icc G ⊤` of `G`. -/ |
| 150 | +theorem copyCount_eq_sum_embeddingCount [Fintype V] [DecidableEq V] |
| 151 | + [DecidableLE (SimpleGraph V)] [Finite W] (G : SimpleGraph V) (H : SimpleGraph W) : |
| 152 | + H.copyCount G = ∑ G' ∈ Finset.Icc G ⊤, H.embeddingCount G' := by |
| 153 | + rw [copyCount_eq_nat_card, Nat.card_congr (Copy.equivSigmaEmbedding G H), Nat.card_sigma, |
| 154 | + ← Finset.sum_attach (Finset.Icc G ⊤) (fun G' => H.embeddingCount G')] |
| 155 | + refine Finset.sum_congr rfl fun G' _ => ?_ |
| 156 | + exact (embeddingCount_eq_nat_card _ _).symm |
| 157 | + |
| 158 | +end Forward |
| 159 | + |
| 160 | +/-! ### Möbius (signed-sum) inverse |
| 161 | +
|
| 162 | +The Möbius inverse to the forward identity, expressing `H.embeddingCount G` as a signed |
| 163 | +sum of `H.copyCount G'` over supergraphs `G' ∈ Icc G ⊤`. The proof reduces, via the |
| 164 | +order-isomorphism `iccEquivPowersetEdgeFinsetSdiff` below, to the alternating-sum |
| 165 | +identity `Finset.sum_powerset_neg_one_pow_card`. |
| 166 | +-/ |
| 167 | + |
| 168 | +section Mobius |
| 169 | + |
| 170 | +open Classical in |
| 171 | +/-- Order-isomorphism between the closed interval `Finset.Icc G K` of graphs and the |
| 172 | +powerset of the edge difference `K.edgeFinset \ G.edgeFinset`, valid when `G ≤ K`. |
| 173 | +
|
| 174 | +The forward map sends a graph `G'` with `G ≤ G' ≤ K` to its "extra edges over `G`", |
| 175 | +namely `G'.edgeFinset \ G.edgeFinset`. The inverse sends a subset `S` of "missing edges |
| 176 | +of `G` inside `K`" to the graph whose edge set is `G.edgeFinset ∪ S`, constructed via |
| 177 | +`fromEdgeSet`. -/ |
| 178 | +noncomputable def iccEquivPowersetEdgeFinsetSdiff [Fintype V] [DecidableEq V] |
| 179 | + [DecidableLE (SimpleGraph V)] {G K : SimpleGraph V} (hGK : G ≤ K) : |
| 180 | + ↥(Finset.Icc G K) ≃ ↥(K.edgeFinset \ G.edgeFinset).powerset where |
| 181 | + toFun G' := |
| 182 | + ⟨G'.val.edgeFinset \ G.edgeFinset, by |
| 183 | + have h₁ : G ≤ G'.val := (Finset.mem_Icc.mp G'.prop).1 |
| 184 | + have h₂ : G'.val ≤ K := (Finset.mem_Icc.mp G'.prop).2 |
| 185 | + simp only [Finset.mem_powerset] |
| 186 | + exact Finset.sdiff_subset_sdiff (edgeFinset_mono h₂) (Finset.Subset.refl _)⟩ |
| 187 | + invFun S := |
| 188 | + ⟨fromEdgeSet ((G.edgeFinset : Set (Sym2 V)) ∪ S.val), by |
| 189 | + have hSK : S.val ⊆ K.edgeFinset \ G.edgeFinset := Finset.mem_powerset.mp S.prop |
| 190 | + refine Finset.mem_Icc.mpr ⟨?_, ?_⟩ |
| 191 | + · -- `G ≤ fromEdgeSet (G.edgeFinset ∪ S)` |
| 192 | + intro a b hab |
| 193 | + refine (fromEdgeSet_adj _).mpr ⟨Or.inl ?_, hab.ne⟩ |
| 194 | + rw [mem_coe, mem_edgeFinset]; exact hab |
| 195 | + · -- `fromEdgeSet (G.edgeFinset ∪ S) ≤ K` |
| 196 | + rw [fromEdgeSet_le] |
| 197 | + intro e he |
| 198 | + rw [Set.mem_diff] at he |
| 199 | + obtain ⟨heGS, _⟩ := he |
| 200 | + rcases heGS with heG | heS |
| 201 | + · rw [mem_coe, mem_edgeFinset] at heG |
| 202 | + exact edgeSet_subset_edgeSet.mpr hGK heG |
| 203 | + · have : e ∈ K.edgeFinset := (Finset.mem_sdiff.mp (hSK heS)).1 |
| 204 | + rwa [mem_edgeFinset] at this⟩ |
| 205 | + left_inv := by |
| 206 | + rintro ⟨G', hG'⟩ |
| 207 | + have hGG' : G ≤ G' := (Finset.mem_Icc.mp hG').1 |
| 208 | + apply Subtype.ext |
| 209 | + ext a b |
| 210 | + simp only [fromEdgeSet_adj, Set.mem_union, mem_coe, mem_edgeFinset, Finset.coe_sdiff, |
| 211 | + Set.mem_diff] |
| 212 | + constructor |
| 213 | + · rintro ⟨h | ⟨h, _⟩, _⟩ |
| 214 | + · exact hGG' h |
| 215 | + · exact h |
| 216 | + · intro h |
| 217 | + refine ⟨?_, h.ne⟩ |
| 218 | + by_cases hG : G.Adj a b |
| 219 | + · exact Or.inl hG |
| 220 | + · exact Or.inr ⟨h, hG⟩ |
| 221 | + right_inv := by |
| 222 | + rintro ⟨S, hS⟩ |
| 223 | + have hSK : S ⊆ K.edgeFinset \ G.edgeFinset := Finset.mem_powerset.mp hS |
| 224 | + apply Subtype.ext |
| 225 | + ext e |
| 226 | + simp only [Finset.mem_sdiff, mem_edgeFinset, edgeSet_fromEdgeSet, Set.mem_diff, |
| 227 | + Set.mem_union, mem_coe] |
| 228 | + constructor |
| 229 | + · rintro ⟨⟨hGS, _⟩, heG⟩ |
| 230 | + cases hGS with |
| 231 | + | inl h => exact absurd h heG |
| 232 | + | inr h => exact h |
| 233 | + · intro heS |
| 234 | + have heK : e ∈ K.edgeFinset := (Finset.mem_sdiff.mp (hSK heS)).1 |
| 235 | + have heNotDiag : e ∉ Sym2.diagSet := fun hd => |
| 236 | + K.not_isDiag_of_mem_edgeSet (mem_edgeFinset.mp heK) hd |
| 237 | + have heNotG : e ∉ G.edgeSet := fun heG => |
| 238 | + (Finset.mem_sdiff.mp (hSK heS)).2 (mem_edgeFinset.mpr heG) |
| 239 | + exact ⟨⟨Or.inr heS, heNotDiag⟩, heNotG⟩ |
| 240 | + |
| 241 | +open Classical in |
| 242 | +/-- The Möbius (signed-sum) inverse to `copyCount_eq_sum_embeddingCount`: the induced |
| 243 | +copy count is recovered as an alternating sum of copy counts indexed by supergraphs |
| 244 | +`G' ∈ Icc G ⊤`, with sign `(-1) ^ #(G'.edgeFinset \ G.edgeFinset)`. -/ |
| 245 | +theorem embeddingCount_eq_sum_signed_copyCount [Fintype V] [DecidableEq V] |
| 246 | + [DecidableLE (SimpleGraph V)] [Finite W] (G : SimpleGraph V) (H : SimpleGraph W) : |
| 247 | + (H.embeddingCount G : ℤ) = |
| 248 | + ∑ G' ∈ Finset.Icc G ⊤, |
| 249 | + (-1 : ℤ) ^ #(G'.edgeFinset \ G.edgeFinset) * (H.copyCount G' : ℤ) := by |
| 250 | + -- (1) The inner alternating sum collapses to `if L = G then 1 else 0`. |
| 251 | + have hinner : ∀ L : SimpleGraph V, G ≤ L → |
| 252 | + ∑ K' ∈ Finset.Icc G L, (-1 : ℤ) ^ #(K'.edgeFinset \ G.edgeFinset) |
| 253 | + = if L = G then 1 else 0 := by |
| 254 | + intro L hGL |
| 255 | + have key : ∑ K' ∈ Finset.Icc G L, (-1 : ℤ) ^ #(K'.edgeFinset \ G.edgeFinset) |
| 256 | + = ∑ S ∈ (L.edgeFinset \ G.edgeFinset).powerset, (-1 : ℤ) ^ #S := by |
| 257 | + rw [← Finset.sum_attach (Finset.Icc G L) |
| 258 | + (fun K' => (-1 : ℤ) ^ #(K'.edgeFinset \ G.edgeFinset)), |
| 259 | + ← Finset.sum_attach (L.edgeFinset \ G.edgeFinset).powerset |
| 260 | + (fun S => (-1 : ℤ) ^ #S)] |
| 261 | + exact Finset.sum_equiv (iccEquivPowersetEdgeFinsetSdiff hGL) |
| 262 | + (fun _ => by simp) (fun _ _ => rfl) |
| 263 | + rw [key, Finset.sum_powerset_neg_one_pow_card] |
| 264 | + by_cases hLG : L = G |
| 265 | + · subst hLG; simp |
| 266 | + · have hne : L.edgeFinset \ G.edgeFinset ≠ ∅ := by |
| 267 | + intro hempty |
| 268 | + apply hLG |
| 269 | + have hsub : L ≤ G := by |
| 270 | + simpa [Finset.sdiff_eq_empty_iff_subset, edgeFinset_subset_edgeFinset] using hempty |
| 271 | + exact le_antisymm hsub hGL |
| 272 | + rw [if_neg hne, if_neg hLG] |
| 273 | + -- (2) Substitute the forward identity into the right-hand side. |
| 274 | + simp_rw [fun K' : SimpleGraph V => copyCount_eq_sum_embeddingCount K' H, |
| 275 | + Nat.cast_sum, Finset.mul_sum] |
| 276 | + -- (3) Swap the order of summation: pairs (K', L) with G ≤ K' ≤ L ≤ ⊤. |
| 277 | + rw [Finset.sum_comm' (s := Finset.Icc G (⊤ : SimpleGraph V)) |
| 278 | + (t := fun K' => Finset.Icc K' ⊤) |
| 279 | + (s' := fun L => Finset.Icc G L) (t' := Finset.Icc G (⊤ : SimpleGraph V)) |
| 280 | + (h := fun K' L => by |
| 281 | + simp only [Finset.mem_Icc]; constructor |
| 282 | + · rintro ⟨⟨hGK', _⟩, hKL, _⟩ |
| 283 | + exact ⟨⟨hGK', hKL⟩, ⟨hGK'.trans hKL, le_top⟩⟩ |
| 284 | + · rintro ⟨⟨hGK', hKL⟩, _⟩ |
| 285 | + exact ⟨⟨hGK', le_top⟩, ⟨hKL, le_top⟩⟩)] |
| 286 | + -- (4) Pull `embeddingCount L` out of the inner sum and apply `hinner`. |
| 287 | + simp_rw [mul_comm ((-1 : ℤ) ^ _) ((H.embeddingCount _ : ℤ)), ← Finset.mul_sum] |
| 288 | + -- (5) Apply `hinner` to each inner sum. |
| 289 | + rw [Finset.sum_congr rfl fun L hL => by |
| 290 | + rw [hinner L (Finset.mem_Icc.mp hL).1]] |
| 291 | + -- (6) Collapse using `sum_ite_eq'`: only the `L = G` term survives. |
| 292 | + simp_rw [mul_ite, mul_one, mul_zero] |
| 293 | + rw [Finset.sum_ite_eq' (Finset.Icc G ⊤) G (fun L => (H.embeddingCount L : ℤ))] |
| 294 | + rw [if_pos (Finset.mem_Icc.mpr ⟨le_refl _, le_top⟩)] |
| 295 | + |
| 296 | +end Mobius |
| 297 | + |
| 298 | +end SimpleGraph |
0 commit comments