Skip to content

Commit 807dab3

Browse files
committed
feat(Combinatorics/SimpleGraph/Copy): introduce Sub carrier subtype
Adds `abbrev Sub A B := {B' : B.Subgraph // Nonempty (A ≃g B'.coe)}`, the subtype of `SimpleGraph.Subgraph`s of `B` isomorphic to `A`. Redefines `copyCount G H` via `Fintype.card (H.Sub G)`, replacing the previous inline filter-set body, and rewrites the affected proofs (`copyCount_eq_zero`, `copyCount_pos`, `copyCount_le_labelledCopyCount`, `copyCount_bot`, `le_card_edgeFinset_killCopies`) to use `Sub` directly. The singleton-empty-subgraph reasoning previously inlined in `copyCount_bot`'s proof is factored out as `instance uniqueSubBot (G : SimpleGraph V) : Unique ((⊥ : SimpleGraph V).Sub G)`, making `copyCount_bot` a one-liner via `Fintype.card_unique`. The cardinality proof inside the instance stays inline to keep the introduction minimal — extraction to a separate private helper and the rename to `_emptyGraph` per the convention from #23838 (and adopted in `AdjMatrix.lean`) happen in the next PR. Drops `copyCount_eq_card_image_copyToSubgraph` (the legacy bridge between the filter-set and Finset.image-of-Copy.toSubgraph forms) — unused after the type-form refactor.
1 parent 11a4a72 commit 807dab3

1 file changed

Lines changed: 31 additions & 30 deletions

File tree

Mathlib/Combinatorics/SimpleGraph/Copy.lean

Lines changed: 31 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ Containment:
3535
same underlying vertex type.
3636
* `SimpleGraph.Free` is the predicate that `H` is `G`-free, that is, `H` does not contain a copy of
3737
`G`. This is the negation of `SimpleGraph.IsContained` implemented for convenience.
38+
* `SimpleGraph.Sub H G`: Type of `SimpleGraph.Subgraph`s of `G` isomorphic to `H`.
3839
* `SimpleGraph.killCopies G H`: Subgraph of `G` that does not contain `H`. Obtained by arbitrarily
3940
removing an edge from each copy of `H` in `G`.
4041
* `SimpleGraph.copyCount G H`: Number of copies of `H` in `G`, i.e. number of subgraphs of `G`
@@ -497,46 +498,48 @@ end LabelledCopyCount
497498
section CopyCount
498499
variable [Fintype V]
499500

501+
/-- `Sub A B` is the type of `SimpleGraph.Subgraph`s of `B` isomorphic to `A`. The corresponding
502+
count is `SimpleGraph.copyCount`. -/
503+
abbrev Sub (A : SimpleGraph α) (B : SimpleGraph β) : Type _ :=
504+
{B' : B.Subgraph // Nonempty (A ≃g B'.coe)}
505+
500506
/-- `G.copyCount H` is the number of unlabelled copies of `H` in `G`, i.e. the number of subgraphs
501507
of `G` isomorphic to `H`. See `SimpleGraph.labelledCopyCount` for the number of labelled copies. -/
502508
noncomputable def copyCount (G : SimpleGraph V) (H : SimpleGraph W) : ℕ := by
503-
classical exact #{G' : G.Subgraph | Nonempty (H ≃g G'.coe)}
504-
505-
lemma copyCount_eq_card_image_copyToSubgraph [Fintype {f : H →g G // Injective f}]
506-
[DecidableEq G.Subgraph] :
507-
copyCount G H = #((Finset.univ : Finset (H.Copy G)).image Copy.toSubgraph) := by
508-
rw [copyCount]
509-
congr
510-
refine Finset.coe_injective ?_
511-
simpa [-Copy.range_toSubgraph] using Copy.range_toSubgraph.symm
509+
classical exact Fintype.card (H.Sub G)
512510

513511
@[simp] lemma copyCount_eq_zero : G.copyCount H = 0 ↔ H.Free G := by
514-
simp [copyCount, Free, -nonempty_subtype, isContained_iff_exists_iso_subgraph,
515-
filter_eq_empty_iff]
512+
classical
513+
rw [copyCount, Fintype.card_eq_zero_iff, isEmpty_subtype]
514+
simp [Free, isContained_iff_exists_iso_subgraph]
516515

517516
@[simp] lemma copyCount_pos : 0 < G.copyCount H ↔ H ⊑ G := by
518-
simp [copyCount, -nonempty_subtype, isContained_iff_exists_iso_subgraph, card_pos,
519-
filter_nonempty_iff]
517+
simp [Nat.pos_iff_ne_zero, copyCount_eq_zero]
520518

521519
/-- There's at least as many labelled copies of `H` in `G` than unlabelled ones. -/
522520
lemma copyCount_le_labelledCopyCount [Fintype W] : G.copyCount H ≤ G.labelledCopyCount H := by
523-
classical rw [copyCount_eq_card_image_copyToSubgraph]; exact card_image_le
521+
classical
522+
rw [copyCount, labelledCopyCount]
523+
apply Fintype.card_le_of_surjective
524+
(fun c : Copy H G ↦ (⟨c.toSubgraph, ⟨c.isoToSubgraph⟩⟩ : H.Sub G))
525+
rintro ⟨G', hG'⟩
526+
obtain ⟨c, hc⟩ : ∃ c : Copy H G, c.toSubgraph = G' := by
527+
rwa [← Set.mem_range, Copy.range_toSubgraph]
528+
exact ⟨c, Subtype.ext hc⟩
529+
530+
instance uniqueSubBot (G : SimpleGraph V) : Unique ((⊥ : SimpleGraph V).Sub G) where
531+
default := ⟨{ verts := .univ, Adj := ⊥, adj_sub := False.elim, edge_vert := False.elim },
532+
⟨(Equiv.Set.univ _).symm, by simp⟩⟩
533+
uniq := fun ⟨G', ⟨e⟩⟩ ↦ Subtype.ext <| Subgraph.ext
534+
(by classical exact (set_fintype_card_eq_univ_iff _).1 <| Fintype.card_congr e.toEquiv.symm)
535+
(by ext a b
536+
simp only [Prop.bot_eq_false, Pi.bot_apply, iff_false]
537+
exact fun hab ↦ e.symm.map_rel_iff.2 hab.coe)
524538

525539
@[simp] lemma copyCount_bot (G : SimpleGraph V) : copyCount G (⊥ : SimpleGraph V) = 1 := by
526540
classical
527541
rw [copyCount]
528-
convert!
529-
card_singleton (α := G.Subgraph)
530-
{ verts := .univ
531-
Adj := ⊥
532-
adj_sub := False.elim
533-
edge_vert := False.elim }
534-
simp only [eq_singleton_iff_unique_mem, mem_filter_univ, Nonempty.forall]
535-
refine ⟨⟨⟨(Equiv.Set.univ _).symm, by simp⟩⟩, fun H' e ↦
536-
Subgraph.ext ((set_fintype_card_eq_univ_iff _).1 <| Fintype.card_congr e.toEquiv.symm) ?_⟩
537-
ext a b
538-
simp only [Prop.bot_eq_false, Pi.bot_apply, iff_false]
539-
exact fun hab ↦ e.symm.map_rel_iff.2 hab.coe
542+
exact Fintype.card_unique
540543

541544
@[simp] lemma copyCount_of_isEmpty [IsEmpty W] (G : SimpleGraph V) (H : SimpleGraph W) :
542545
G.copyCount H = 1 := by
@@ -645,15 +648,13 @@ lemma le_card_edgeFinset_killCopies [Fintype V] :
645648
classical
646649
obtain rfl | hH := eq_or_ne H ⊥
647650
· simp [← card_edgeSet]
648-
let f (G' : {G' : G.Subgraph // Nonempty (H ≃g G'.coe)}) := (aux hH G'.2).some
651+
let f (G' : H.Sub G) := (aux hH G'.2).some
649652
calc
650-
_ = #G.edgeFinset - card {G' : G.Subgraph // Nonempty (H ≃g G'.coe)} := ?_
653+
_ = #G.edgeFinset - card (H.Sub G) := by rw [copyCount]
651654
_ ≤ #G.edgeFinset - #(univ.image f) := Nat.sub_le_sub_left card_image_le _
652655
_ = #G.edgeFinset - #(Set.range f).toFinset := by rw [Set.toFinset_range]
653656
_ ≤ #(G.edgeFinset \ (Set.range f).toFinset) := le_card_sdiff ..
654657
_ = #(G.killCopies H).edgeFinset := ?_
655-
· simp only [edgeFinset, Set.toFinset_card]
656-
rw [← Set.toFinset_card, ← edgeFinset, copyCount, ← card_subtype, subtype_univ, card_univ]
657658
congr 1
658659
ext e
659660
induction e using Sym2.inductionOn with | hf v w

0 commit comments

Comments
 (0)