Skip to content

Commit cfa3bc5

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 5961646 commit cfa3bc5

1 file changed

Lines changed: 31 additions & 29 deletions

File tree

Mathlib/Combinatorics/SimpleGraph/Copy.lean

Lines changed: 31 additions & 29 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`
@@ -496,45 +497,48 @@ end LabelledCopyCount
496497
section CopyCount
497498
variable [Fintype V]
498499

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

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

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

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

524538
@[simp] lemma copyCount_bot (G : SimpleGraph V) : copyCount G (⊥ : SimpleGraph V) = 1 := by
525539
classical
526540
rw [copyCount]
527-
convert card_singleton (α := G.Subgraph)
528-
{ verts := .univ
529-
Adj := ⊥
530-
adj_sub := False.elim
531-
edge_vert := False.elim }
532-
simp only [eq_singleton_iff_unique_mem, mem_filter_univ, Nonempty.forall]
533-
refine ⟨⟨⟨(Equiv.Set.univ _).symm, by simp⟩⟩, fun H' e ↦
534-
Subgraph.ext ((set_fintype_card_eq_univ_iff _).1 <| Fintype.card_congr e.toEquiv.symm) ?_⟩
535-
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
541+
exact Fintype.card_unique
538542

539543
@[simp] lemma copyCount_of_isEmpty [IsEmpty W] (G : SimpleGraph V) (H : SimpleGraph W) :
540544
G.copyCount H = 1 := by
@@ -643,15 +647,13 @@ lemma le_card_edgeFinset_killCopies [Fintype V] :
643647
classical
644648
obtain rfl | hH := eq_or_ne H ⊥
645649
· simp [← card_edgeSet]
646-
let f (G' : {G' : G.Subgraph // Nonempty (H ≃g G'.coe)}) := (aux hH G'.2).some
650+
let f (G' : H.Sub G) := (aux hH G'.2).some
647651
calc
648-
_ = #G.edgeFinset - card {G' : G.Subgraph // Nonempty (H ≃g G'.coe)} := ?_
652+
_ = #G.edgeFinset - card (H.Sub G) := by rw [copyCount]
649653
_ ≤ #G.edgeFinset - #(univ.image f) := Nat.sub_le_sub_left card_image_le _
650654
_ = #G.edgeFinset - #(Set.range f).toFinset := by rw [Set.toFinset_range]
651655
_ ≤ #(G.edgeFinset \ (Set.range f).toFinset) := le_card_sdiff ..
652656
_ = #(G.killCopies H).edgeFinset := ?_
653-
· simp only [edgeFinset, Set.toFinset_card]
654-
rw [← Set.toFinset_card, ← edgeFinset, copyCount, ← card_subtype, subtype_univ, card_univ]
655657
congr 1
656658
ext e
657659
induction e using Sym2.inductionOn with | hf v w

0 commit comments

Comments
 (0)