Skip to content

Commit 71644f4

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 58f2aa3 commit 71644f4

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
@@ -438,6 +438,23 @@ abbrev UnlabeledCopy (G : SimpleGraph V) (H : SimpleGraph W) : Type _ :=
438438

439439
instance [Finite W] : Finite (G.UnlabeledCopy H) := Subtype.finite
440440

441+
/-- The canonical map from a labeled copy to its unlabeled image. -/
442+
@[expose] def Copy.toUnlabeledCopy (f : Copy G H) : G.UnlabeledCopy H :=
443+
⟨f.toSubgraph, ⟨f.isoToSubgraph⟩⟩
444+
445+
@[simp] lemma Copy.toUnlabeledCopy_val (f : Copy G H) : f.toUnlabeledCopy.val = f.toSubgraph := rfl
446+
447+
lemma UnlabeledCopy.exists_toSubgraph_eq_val (S : G.UnlabeledCopy H) :
448+
∃ f : Copy G H, f.toSubgraph = S.val :=
449+
Set.mem_range.mp (Copy.range_toSubgraph ▸ S.property)
450+
451+
/-- A noncomputable representative labeled copy of an unlabeled copy. -/
452+
noncomputable def UnlabeledCopy.out (S : G.UnlabeledCopy H) : Copy G H :=
453+
S.exists_toSubgraph_eq_val.choose
454+
455+
@[simp] lemma UnlabeledCopy.toSubgraph_out (S : G.UnlabeledCopy H) : S.out.toSubgraph = S.val :=
456+
S.exists_toSubgraph_eq_val.choose_spec
457+
441458
/-- `H.unlabeledCopyCount G` is the number of `SimpleGraph.Subgraph`s of `H` isomorphic to `G`. See
442459
`SimpleGraph.copyCount` for the number of labeled copies. -/
443460
noncomputable def unlabeledCopyCount (H : SimpleGraph W) (G : SimpleGraph V) : ℕ :=
@@ -458,12 +475,8 @@ lemma unlabeledCopyCount_eq_nat_card (H : SimpleGraph W) (G : SimpleGraph V) :
458475
lemma unlabeledCopyCount_le_copyCount [Finite V] [Finite W] :
459476
H.unlabeledCopyCount G ≤ H.copyCount G := by
460477
rw [unlabeledCopyCount, copyCount]
461-
apply Nat.card_le_card_of_surjective
462-
(fun c : Copy G H ↦ (⟨c.toSubgraph, ⟨c.isoToSubgraph⟩⟩ : G.UnlabeledCopy H))
463-
rintro ⟨H', hG'⟩
464-
obtain ⟨c, hc⟩ : ∃ c, Copy.toSubgraph c = H' := by
465-
rwa [← Set.mem_range, Copy.range_toSubgraph]
466-
exact ⟨c, Subtype.ext hc⟩
478+
exact Nat.card_le_card_of_surjective Copy.toUnlabeledCopy
479+
fun S ↦ ⟨S.out, Subtype.ext S.toSubgraph_out⟩
467480

468481
instance uniqueUnlabeledCopyBot [Finite W] (H : SimpleGraph W) :
469482
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
@@ -274,6 +274,25 @@ abbrev UnlabeledEmbedding (G : SimpleGraph V) (H : SimpleGraph W) : Type _ :=
274274

275275
instance [Finite W] : Finite (G.UnlabeledEmbedding H) := Subtype.finite
276276

277+
/-- The canonical map from a labeled embedding to its unlabeled induced image. -/
278+
@[expose] def Embedding.toUnlabeledEmbedding (f : Embedding G H) : G.UnlabeledEmbedding H :=
279+
⟨f.toSubgraph, f.toSubgraph_isInduced, ⟨f.toCopy.isoToSubgraph⟩⟩
280+
281+
@[simp] lemma Embedding.toUnlabeledEmbedding_val (f : Embedding G H) :
282+
f.toUnlabeledEmbedding.val = f.toSubgraph := rfl
283+
284+
lemma UnlabeledEmbedding.exists_toSubgraph_eq_val (S : G.UnlabeledEmbedding H) :
285+
∃ f : Embedding G H, f.toSubgraph = S.val :=
286+
Set.mem_range.mp (Embedding.range_toSubgraph ▸ S.property)
287+
288+
/-- A noncomputable representative labeled embedding of an unlabeled induced copy. -/
289+
noncomputable def UnlabeledEmbedding.out (S : G.UnlabeledEmbedding H) : Embedding G H :=
290+
S.exists_toSubgraph_eq_val.choose
291+
292+
@[simp] lemma UnlabeledEmbedding.toSubgraph_out (S : G.UnlabeledEmbedding H) :
293+
S.out.toSubgraph = S.val :=
294+
S.exists_toSubgraph_eq_val.choose_spec
295+
277296
/-- `H.unlabeledEmbeddingCount G` is the number of induced `SimpleGraph.Subgraph`s of `H`
278297
isomorphic to `G`.
279298
See `SimpleGraph.embeddingCount` for the number of induced labeled copies. -/
@@ -298,13 +317,8 @@ unlabeled ones. -/
298317
lemma unlabeledEmbeddingCount_le_embeddingCount [Finite V] [Finite W] :
299318
H.unlabeledEmbeddingCount G ≤ H.embeddingCount G := by
300319
rw [unlabeledEmbeddingCount, embeddingCount]
301-
apply Nat.card_le_card_of_surjective
302-
(fun f : Embedding G H ↦ (⟨Embedding.toSubgraph f, f.toSubgraph_isInduced,
303-
⟨f.toCopy.isoToSubgraph⟩⟩ : G.UnlabeledEmbedding H))
304-
rintro ⟨H', hInd, ⟨e⟩⟩
305-
obtain ⟨f, hf⟩ : ∃ f : Embedding G H, Embedding.toSubgraph f = H' := by
306-
rw [← Set.mem_range, Embedding.range_toSubgraph]; exact ⟨hInd, ⟨e⟩⟩
307-
exact ⟨f, Subtype.ext hf⟩
320+
exact Nat.card_le_card_of_surjective Embedding.toUnlabeledEmbedding
321+
fun S ↦ ⟨S.out, Subtype.ext S.toSubgraph_out⟩
308322

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

0 commit comments

Comments
 (0)