Skip to content

Commit c6caa5c

Browse files
committed
chore(Combinatorics/SimpleGraph/Copy): migrate copyCount/subCount to Nat.card
* `copyCount` and `subCount` redefined via `Nat.card` instead of `Fintype.card`. * `Fintype` hypotheses weakened to `Finite` throughout (`copyCount_eq_zero`, `copyCount_pos`, `subCount_eq_zero`, `subCount_pos`, `subCount_le_copyCount`, `uniqueSubBot`, `subCount_bot`, `subCount_of_isEmpty`, `bot_isContained_iff_card_le`, `le_card_edgeFinset_killCopies`, `le_card_edgeFinset_killCopies_add_subCount`). * `bot_isContained_iff_card_le`: `Fintype.card → Nat.card`. * New `Finite (G.Copy H)` instance (sibling to the existing `Fintype` instance). * New `Nonempty (Copy G H)` instance for `[IsEmpty V]`, used to give a one-line `copyCount_of_isEmpty` proof via `Nat.card_unique`. * New `subCount_eq_nat_card_range_toSubgraph` lemma exposing the link to `Copy.toSubgraph`'s range, used in `subCount_le_copyCount`. * New private `subgraph_iso_bot` lemma extracting the singleton-subgraph fact for `uniqueSubBot`, replacing the previous `Fintype.card_congr` / `set_fintype_card_eq_univ_iff` reasoning. * `le_card_edgeFinset_killCopies` proof avoids the `Fintype.ofFinite` round-trip via `Set.finite_range` + `Set.Finite.toFinset`.
1 parent 7c1a473 commit c6caa5c

1 file changed

Lines changed: 71 additions & 63 deletions

File tree

Mathlib/Combinatorics/SimpleGraph/Copy.lean

Lines changed: 71 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@ module
77

88
public import Mathlib.Algebra.Order.Group.Nat
99
public import Mathlib.Combinatorics.SimpleGraph.Subgraph
10+
public import Mathlib.Data.Finite.Card
11+
public import Mathlib.Data.Set.Finite.Range
1012

1113
/-!
1214
# Copies, containment, and counting of subgraphs
@@ -68,7 +70,6 @@ The following notation is declared in scope `SimpleGraph`:
6870
public section
6971

7072
open Finset Function
71-
open Fintype (card)
7273

7374
namespace SimpleGraph
7475
variable {V V' W W' X : Type*}
@@ -205,6 +206,9 @@ instance [Fintype {f : G →g H // Injective f}] : Fintype (G.Copy H) :=
205206
invFun f := ⟨f.1, f.2
206207
}
207208

209+
instance [Finite V] [Finite W] : Finite (G.Copy H) :=
210+
Finite.of_injective _ DFunLike.coe_injective
211+
208212
/-- A copy of `⊤` gives rise to an embedding of `⊤`. -/
209213
@[expose] def topEmbedding (f : Copy (⊤ : SimpleGraph V) H) : (⊤ : SimpleGraph V) ↪g H :=
210214
{ f.toEmbedding with
@@ -296,10 +300,11 @@ lemma IsContained.of_isEmpty [IsEmpty V] : G ⊑ H :=
296300
⟨⟨isEmptyElim, fun {a} ↦ isEmptyElim a⟩, isEmptyElim⟩
297301

298302
/-- `⊥` is contained in any simple graph having sufficiently many vertices. -/
299-
lemma bot_isContained_iff_card_le [Fintype V] [Fintype W] :
300-
(⊥ : SimpleGraph V) ⊑ H ↔ Fintype.card V ≤ Fintype.card W :=
301-
fun ⟨f⟩ ↦ Fintype.card_le_of_embedding f.toEmbedding,
302-
fun h ↦ ⟨Copy.bot (Function.Embedding.nonempty_of_card_le h).some⟩⟩
303+
lemma bot_isContained_iff_card_le [Finite V] [Finite W] :
304+
(⊥ : SimpleGraph V) ⊑ H ↔ Nat.card V ≤ Nat.card W :=
305+
fun ⟨f⟩ ↦ Finite.card_le_of_embedding f.toEmbedding,
306+
fun h ↦ ⟨Copy.bot (Cardinal.lift_mk_le'.mp (by
307+
simp only [← Nat.cast_card, Cardinal.lift_natCast]; exact_mod_cast h)).some⟩⟩
303308

304309
protected alias IsContained.bot := bot_isContained_iff_card_le
305310

@@ -471,38 +476,37 @@ For finite `G` and `H`, we count labeled and unlabeled copies of `G` in `H`.
471476
-/
472477

473478
section CopyCount
474-
variable [Fintype V] [Fintype W]
475479

476480
/-- `H.copyCount G` is the number of labeled copies of `G` in `H`, i.e. the number of injective
477481
graph homomorphisms from `G` to `H`. See `SimpleGraph.subCount` for the number of unlabeled
478482
copies. -/
479-
@[expose] noncomputable def copyCount (H : SimpleGraph W) (G : SimpleGraph V) : ℕ := by
480-
classical exact Fintype.card (Copy G H)
483+
@[expose] noncomputable def copyCount (H : SimpleGraph W) (G : SimpleGraph V) : ℕ :=
484+
Nat.card (Copy G H)
481485

482486
@[deprecated (since := "2026-04-30")] alias labelledCopyCount := copyCount
483487

488+
private instance [IsEmpty V] : Nonempty (Copy G H) := IsContained.of_isEmpty
489+
484490
@[simp] lemma copyCount_of_isEmpty [IsEmpty V] (H : SimpleGraph W) (G : SimpleGraph V) :
485-
H.copyCount G = 1 := by
486-
convert Fintype.card_unique
487-
exact { default := ⟨default, isEmptyElim⟩, uniq := fun _ ↦ Subsingleton.elim _ _ }
491+
H.copyCount G = 1 := Nat.card_unique
488492

489493
@[deprecated (since := "2026-04-30")]
490494
alias labelledCopyCount_of_isEmpty := copyCount_of_isEmpty
491495

492-
@[simp] lemma copyCount_eq_zero : H.copyCount G = 0 ↔ G.Free H := by
493-
simp [copyCount, Fintype.card_eq_zero_iff]
496+
@[simp] lemma copyCount_eq_zero [Finite V] [Finite W] : H.copyCount G = 0 ↔ G.Free H := by
497+
rw [copyCount, Nat.card_eq_zero, or_iff_left (Finite.not_infinite inferInstance)]
498+
simp [Free, IsContained]
494499

495500
@[deprecated (since := "2026-04-30")] alias labelledCopyCount_eq_zero := copyCount_eq_zero
496501

497-
@[simp] lemma copyCount_pos : 0 < H.copyCount G ↔ G ⊑ H := by
498-
simp [copyCount, IsContained, Fintype.card_pos_iff]
502+
@[simp] lemma copyCount_pos [Finite V] [Finite W] : 0 < H.copyCount G ↔ G ⊑ H := by
503+
simp [Nat.pos_iff_ne_zero, copyCount_eq_zero]
499504

500505
@[deprecated (since := "2026-04-30")] alias labelledCopyCount_pos := copyCount_pos
501506

502507
end CopyCount
503508

504509
section SubCount
505-
variable [Fintype W]
506510

507511
/-- `G.Sub H` is the type of `SimpleGraph.Subgraph`s of `H` isomorphic to `G`. The corresponding
508512
count is `SimpleGraph.subCount`. -/
@@ -511,46 +515,50 @@ abbrev Sub (G : SimpleGraph V) (H : SimpleGraph W) : Type _ :=
511515

512516
/-- `H.subCount G` is the number of `SimpleGraph.Subgraph`s of `H` isomorphic to `G`. See
513517
`SimpleGraph.copyCount` for the number of labeled copies. -/
514-
@[expose] noncomputable def subCount (H : SimpleGraph W) (G : SimpleGraph V) : ℕ := by
515-
classical exact Fintype.card (G.Sub H)
518+
@[expose] noncomputable def subCount (H : SimpleGraph W) (G : SimpleGraph V) : ℕ :=
519+
Nat.card (G.Sub H)
520+
521+
lemma subCount_eq_nat_card_range_toSubgraph :
522+
H.subCount G = Nat.card (Set.range (Copy.toSubgraph : G.Copy H → H.Subgraph)) := by
523+
rw [subCount, Copy.range_toSubgraph]; rfl
516524

517-
@[simp] lemma subCount_eq_zero : H.subCount G = 0 ↔ G.Free H := by
518-
simp [subCount, Free, -nonempty_subtype, isContained_iff_exists_iso_subgraph,
519-
Fintype.card_eq_zero_iff, isEmpty_subtype, not_nonempty_iff]
525+
@[simp] lemma subCount_eq_zero [Finite W] : H.subCount G = 0 ↔ G.Free H := by
526+
rw [subCount, Nat.card_eq_zero, or_iff_left (Finite.not_infinite inferInstance), isEmpty_subtype]
527+
simp [Free, isContained_iff_exists_iso_subgraph]
520528

521-
@[simp] lemma subCount_pos : 0 < H.subCount G ↔ G ⊑ H := by
522-
rw [Nat.pos_iff_ne_zero, ne_eq, subCount_eq_zero, Free, not_not]
529+
@[simp] lemma subCount_pos [Finite W] : 0 < H.subCount G ↔ G ⊑ H := by
530+
simp [Nat.pos_iff_ne_zero, subCount_eq_zero]
523531

524532
/-- There are at least as many labeled copies of `G` in `H` as there are unlabeled ones. -/
525-
lemma subCount_le_copyCount [Fintype V] : H.subCount G ≤ H.copyCount G := by
526-
classical
527-
rw [subCount, copyCount]
528-
apply Fintype.card_le_of_surjective
529-
(fun c : Copy G H ↦ (⟨c.toSubgraph, ⟨c.isoToSubgraph⟩⟩ : G.Sub H))
530-
rintro ⟨H', hG'⟩
531-
obtain ⟨c, hc⟩ : ∃ c, Copy.toSubgraph c = H' := by
532-
rwa [← Set.mem_range, Copy.range_toSubgraph]
533-
exact ⟨c, Subtype.ext hc⟩
534-
535-
instance uniqueSubEmptyGraph (H : SimpleGraph W) : Unique ((⊥ : SimpleGraph W).Sub H) where
533+
lemma subCount_le_copyCount [Finite V] [Finite W] : H.subCount G ≤ H.copyCount G :=
534+
subCount_eq_nat_card_range_toSubgraph ▸ Finite.card_range_le _
535+
536+
set_option backward.privateInPublic true in
537+
set_option backward.privateInPublic.warn false in
538+
private lemma subgraph_iso_emptyGraph [Finite W] (H' : H.Subgraph)
539+
(e : (⊥ : SimpleGraph W) ≃g H'.coe) : H'.verts = Set.univ ∧ H'.Adj = ⊥ := by
540+
refine ⟨Set.eq_univ_of_forall fun v ↦ ?_,
541+
funext₂ fun a b ↦ eq_false fun hadj ↦ absurd (e.symm.map_rel_iff.mpr hadj.coe) (by simp)⟩
542+
obtain ⟨w, hw⟩ := (Finite.injective_iff_surjective.mp
543+
(Subtype.val_injective.comp e.toEquiv.injective)) v
544+
exact hw ▸ (e.toEquiv w).prop
545+
546+
set_option backward.privateInPublic true in
547+
set_option backward.privateInPublic.warn false in
548+
instance uniqueSubEmptyGraph [Finite W] (H : SimpleGraph W) :
549+
Unique ((⊥ : SimpleGraph W).Sub H) where
536550
default := ⟨{ verts := .univ, Adj := ⊥, adj_sub := False.elim, edge_vert := False.elim },
537551
⟨(Equiv.Set.univ _).symm, by simp⟩⟩
538-
uniq := fun ⟨G', ⟨e⟩⟩ ↦ Subtype.ext <| Subgraph.ext
539-
(by classical exact (set_fintype_card_eq_univ_iff _).1 <| Fintype.card_congr e.toEquiv.symm)
540-
(by ext a b
541-
simp only [Prop.bot_eq_false, Pi.bot_apply, iff_false]
542-
exact fun hab ↦ e.symm.map_rel_iff.2 hab.coe)
552+
uniq := fun ⟨H', ⟨e⟩⟩ ↦ Subtype.ext <|
553+
Subgraph.ext (subgraph_iso_emptyGraph H' e).1 (subgraph_iso_emptyGraph H' e).2
543554

544-
@[simp] lemma subCount_emptyGraph (H : SimpleGraph W) : H.subCount (⊥ : SimpleGraph W) = 1 := by
545-
classical
546-
rw [subCount]
547-
convert Fintype.card_unique
548-
exact uniqueSubEmptyGraph H
549-
550-
@[simp] lemma subCount_of_isEmpty [IsEmpty V] (H : SimpleGraph W) (G : SimpleGraph V) :
551-
H.subCount G = 1 := by
552-
cases nonempty_fintype V
553-
exact (subCount_le_copyCount.trans_eq <| copyCount_of_isEmpty ..).antisymm <|
555+
@[simp] lemma subCount_emptyGraph [Finite W] (H : SimpleGraph W) :
556+
H.subCount (⊥ : SimpleGraph W) = 1 :=
557+
Nat.card_unique
558+
559+
@[simp] lemma subCount_of_isEmpty [Finite V] [Finite W] [IsEmpty V]
560+
(H : SimpleGraph W) (G : SimpleGraph V) : H.subCount G = 1 :=
561+
(subCount_le_copyCount.trans_eq <| copyCount_of_isEmpty ..).antisymm <|
554562
subCount_pos.2 <| .of_isEmpty
555563

556564
end SubCount
@@ -640,28 +648,28 @@ noncomputable instance killCopies.edgeSet.instFintype : Fintype (H.killCopies G)
640648

641649
/-- Removing an edge from `H` for each subgraph isomorphic to `G` means that the number of edges
642650
we've removed is at most the number of copies of `G` in `H`. -/
643-
lemma le_card_edgeFinset_killCopies [Fintype W] :
651+
lemma le_card_edgeFinset_killCopies [Finite W] :
644652
#H.edgeFinset - H.subCount G ≤ #(H.killCopies G).edgeFinset := by
645653
classical
646654
obtain rfl | hG := eq_or_ne G ⊥
647655
· simp [← card_edgeSet]
648656
let f (H' : G.Sub H) := (aux hG H'.2).some
649-
calc
650-
_ = #H.edgeFinset - Fintype.card (G.Sub H) := ?_
651-
_ ≤ #H.edgeFinset - #(univ.image f) := Nat.sub_le_sub_left card_image_le _
652-
_ = #H.edgeFinset - #(Set.range f).toFinset := by rw [Set.toFinset_range]
653-
_ ≤ #(H.edgeFinset \ (Set.range f).toFinset) := le_card_sdiff ..
654-
_ = #(H.killCopies G).edgeFinset := ?_
655-
· simp only [edgeFinset, Set.toFinset_card]
656-
rw [← Set.toFinset_card, ← edgeFinset, subCount]
657-
congr 1
658-
ext e
659-
induction e using Sym2.inductionOn with | hf v w
660-
simp [mem_edgeSet, killCopies_of_ne_bot hG, f, eq_comm]
657+
have hrf : (Set.range f).Finite := Set.finite_range f
658+
have hle : hrf.toFinset.card ≤ H.subCount G := by
659+
rw [← Nat.card_eq_card_finite_toFinset hrf, subCount]
660+
exact Finite.card_range_le f
661+
calc #H.edgeFinset - H.subCount G
662+
≤ #H.edgeFinset - hrf.toFinset.card := Nat.sub_le_sub_left hle _
663+
_ ≤ #(H.edgeFinset \ hrf.toFinset) := le_card_sdiff ..
664+
_ = #(H.killCopies G).edgeFinset := by
665+
congr 1
666+
ext e
667+
induction e using Sym2.inductionOn with | hf v w
668+
simp [mem_edgeSet, killCopies_of_ne_bot hG, f, eq_comm]
661669

662670
/-- Removing an edge from `H` for each subgraph isomorphic to `G` means that the number of edges
663671
we've removed is at most the number of copies of `G` in `H`. -/
664-
lemma le_card_edgeFinset_killCopies_add_subCount [Fintype W] :
672+
lemma le_card_edgeFinset_killCopies_add_subCount [Finite W] :
665673
#H.edgeFinset ≤ #(H.killCopies G).edgeFinset + H.subCount G :=
666674
tsub_le_iff_right.1 le_card_edgeFinset_killCopies
667675

0 commit comments

Comments
 (0)