Skip to content

Commit 21db757

Browse files
committed
feat(Combinatorics/SimpleGraph): Copy.toUnlabeledCopy / UnlabeledCopy.out (and embedding mirror)
Add the standard `Quot.mk` / `Quot.out` style toolage for converting between labeled and unlabeled copies / embeddings: * `Copy.toUnlabeledCopy : Copy G H → G.UnlabeledCopy H` — canonical projection (computable). * `UnlabeledCopy.out : G.UnlabeledCopy H → Copy G H` — non-canonical representative (noncomputable). * `Copy.toUnlabeledCopy_val` and `UnlabeledCopy.toSubgraph_out` give the matching simp specs. * `UnlabeledCopy.exists_toSubgraph_eq_val` packages the underlying existence statement. Mirrored on the Embedding side: `Embedding.toUnlabeledEmbedding`, `UnlabeledEmbedding.exists_toSubgraph_eq_val`, `UnlabeledEmbedding.out`, and their respective spec lemmas. Refactor the existing `unlabeledCopyCount_le_copyCount` and `unlabeledEmbeddingCount_le_embeddingCount` proofs to use the new names — both shrink from a 5- and 7-line `apply ... ; rintro ...; obtain ...; exact ...` chain to a two-line `exact Nat.card_le_card_of_surjective ... fun S ↦ ⟨S.out, ...⟩`.
1 parent 3e317f2 commit 21db757

2 files changed

Lines changed: 40 additions & 13 deletions

File tree

Mathlib/Combinatorics/SimpleGraph/Copy.lean

Lines changed: 19 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -461,6 +461,23 @@ abbrev UnlabeledCopy (G : SimpleGraph V) (H : SimpleGraph W) : Type _ :=
461461

462462
instance [Finite W] : Finite (G.UnlabeledCopy H) := Subtype.finite
463463

464+
/-- The canonical map from a labeled copy to its unlabeled image. -/
465+
@[expose] def Copy.toUnlabeledCopy (f : Copy G H) : G.UnlabeledCopy H :=
466+
⟨f.toSubgraph, ⟨f.isoToSubgraph⟩⟩
467+
468+
@[simp] lemma Copy.toUnlabeledCopy_val (f : Copy G H) : f.toUnlabeledCopy.val = f.toSubgraph := rfl
469+
470+
lemma UnlabeledCopy.exists_toSubgraph_eq_val (S : G.UnlabeledCopy H) :
471+
∃ f : Copy G H, f.toSubgraph = S.val :=
472+
Set.mem_range.mp (Copy.range_toSubgraph ▸ S.property)
473+
474+
/-- A noncomputable representative labeled copy of an unlabeled copy. -/
475+
noncomputable def UnlabeledCopy.out (S : G.UnlabeledCopy H) : Copy G H :=
476+
S.exists_toSubgraph_eq_val.choose
477+
478+
@[simp] lemma UnlabeledCopy.toSubgraph_out (S : G.UnlabeledCopy H) : S.out.toSubgraph = S.val :=
479+
S.exists_toSubgraph_eq_val.choose_spec
480+
464481
/-- `H.unlabeledCopyCount G` is the number of `SimpleGraph.Subgraph`s of `H` isomorphic to `G`. See
465482
`SimpleGraph.copyCount` for the number of labeled copies. -/
466483
noncomputable def unlabeledCopyCount (H : SimpleGraph W) (G : SimpleGraph V) : ℕ :=
@@ -492,12 +509,8 @@ lemma copyCount_eq_card_image_copyToSubgraph [Fintype {f : G →g H // Injective
492509
lemma unlabeledCopyCount_le_copyCount [Finite V] [Finite W] :
493510
H.unlabeledCopyCount G ≤ H.copyCount G := by
494511
rw [unlabeledCopyCount, copyCount]
495-
apply Nat.card_le_card_of_surjective
496-
(fun c : Copy G H ↦ (⟨c.toSubgraph, ⟨c.isoToSubgraph⟩⟩ : G.UnlabeledCopy H))
497-
rintro ⟨H', hG'⟩
498-
obtain ⟨c, hc⟩ : ∃ c, Copy.toSubgraph c = H' := by
499-
rwa [← Set.mem_range, Copy.range_toSubgraph]
500-
exact ⟨c, Subtype.ext hc⟩
512+
exact Nat.card_le_card_of_surjective Copy.toUnlabeledCopy
513+
fun S ↦ ⟨S.out, Subtype.ext S.toSubgraph_out⟩
501514

502515
instance uniqueUnlabeledCopyBot [Finite W] (H : SimpleGraph W) :
503516
Unique ((⊥ : SimpleGraph W).UnlabeledCopy H) where

Mathlib/Combinatorics/SimpleGraph/InducedCopy.lean

Lines changed: 21 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -280,6 +280,25 @@ abbrev UnlabeledEmbedding (G : SimpleGraph V) (H : SimpleGraph W) : Type _ :=
280280

281281
instance [Finite W] : Finite (G.UnlabeledEmbedding H) := Subtype.finite
282282

283+
/-- The canonical map from a labeled embedding to its unlabeled induced image. -/
284+
@[expose] def Embedding.toUnlabeledEmbedding (f : Embedding G H) : G.UnlabeledEmbedding H :=
285+
⟨f.toSubgraph, f.toSubgraph_isInduced, ⟨f.toCopy.isoToSubgraph⟩⟩
286+
287+
@[simp] lemma Embedding.toUnlabeledEmbedding_val (f : Embedding G H) :
288+
f.toUnlabeledEmbedding.val = f.toSubgraph := rfl
289+
290+
lemma UnlabeledEmbedding.exists_toSubgraph_eq_val (S : G.UnlabeledEmbedding H) :
291+
∃ f : Embedding G H, f.toSubgraph = S.val :=
292+
Set.mem_range.mp (Embedding.range_toSubgraph ▸ S.property)
293+
294+
/-- A noncomputable representative labeled embedding of an unlabeled induced copy. -/
295+
noncomputable def UnlabeledEmbedding.out (S : G.UnlabeledEmbedding H) : Embedding G H :=
296+
S.exists_toSubgraph_eq_val.choose
297+
298+
@[simp] lemma UnlabeledEmbedding.toSubgraph_out (S : G.UnlabeledEmbedding H) :
299+
S.out.toSubgraph = S.val :=
300+
S.exists_toSubgraph_eq_val.choose_spec
301+
283302
/-- `H.unlabeledEmbeddingCount G` is the number of induced `SimpleGraph.Subgraph`s of `H`
284303
isomorphic to `G`.
285304
See `SimpleGraph.embeddingCount` for the number of induced labeled copies. -/
@@ -304,13 +323,8 @@ unlabeled ones. -/
304323
lemma unlabeledEmbeddingCount_le_embeddingCount [Finite V] [Finite W] :
305324
H.unlabeledEmbeddingCount G ≤ H.embeddingCount G := by
306325
rw [unlabeledEmbeddingCount, embeddingCount]
307-
apply Nat.card_le_card_of_surjective
308-
(fun f : Embedding G H ↦ (⟨Embedding.toSubgraph f, f.toSubgraph_isInduced,
309-
⟨f.toCopy.isoToSubgraph⟩⟩ : G.UnlabeledEmbedding H))
310-
rintro ⟨H', hInd, ⟨e⟩⟩
311-
obtain ⟨f, hf⟩ : ∃ f : Embedding G H, Embedding.toSubgraph f = H' := by
312-
rw [← Set.mem_range, Embedding.range_toSubgraph]; exact ⟨hInd, ⟨e⟩⟩
313-
exact ⟨f, Subtype.ext hf⟩
326+
exact Nat.card_le_card_of_surjective Embedding.toUnlabeledEmbedding
327+
fun S ↦ ⟨S.out, Subtype.ext S.toSubgraph_out⟩
314328

315329
private instance [IsEmpty V] : Nonempty (G.UnlabeledEmbedding H) :=
316330
let ⟨H', hInd, ⟨e⟩⟩ := (IsIndContained.of_isEmpty (G := G) (H := H)).exists_iso_subgraph

0 commit comments

Comments
 (0)