Skip to content

Commit c74f5c5

Browse files
committed
feat(Combinatorics/SimpleGraph): add toUnlabeledCopy / out Quot-style pair
Standard "labeled ↔ unlabeled" toolage for `Copy` / `Embedding` ↔ `UnlabeledCopy` / `UnlabeledEmbedding`, mirroring the `Quot.mk` / `Quot.out` pattern: * `Copy.toUnlabeledCopy : Copy G H → G.UnlabeledCopy H` — canonical projection (computable). * `UnlabeledCopy.out : G.UnlabeledCopy H → Copy G H` — non-canonical representative (noncomputable, via `exists_toSubgraph_eq_val.choose`). * `Copy.toUnlabeledCopy_val` and `UnlabeledCopy.toSubgraph_out` are the matching simp specs. Mirrored on the Embedding side: `Embedding.toUnlabeledEmbedding` / `UnlabeledEmbedding.out` with their respective spec lemmas. Refactor existing inlined anonymous-constructor / `.choose`+`.choose_spec` call sites to use the new functions: * `unlabeledCopyCount_le_copyCount` / `unlabeledEmbeddingCount_le_embeddingCount` * `Copy.equivSigma` / `Embedding.equivSigma` in `Automorphism.lean` * `Copy.fiberEquivAutOf` / `Embedding.fiberEquivAutOf` in `Automorphism.lean` Both `Copy.toUnlabeledCopy` and `Embedding.toUnlabeledEmbedding` are marked `@[expose]` so their `_val` spec lemmas (which are `rfl`) work across modules.
1 parent 00f0743 commit c74f5c5

3 files changed

Lines changed: 36 additions & 19 deletions

File tree

Mathlib/Combinatorics/SimpleGraph/Automorphism.lean

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -94,14 +94,13 @@ noncomputable def fiberEquivAut (f₀ : Copy G H) :
9494
equivalent to `Aut G`. -/
9595
noncomputable def fiberEquivAutOf (S : G.UnlabeledCopy H) :
9696
{f : Copy G H // f.toSubgraph = S.val} ≃ G.Aut :=
97-
have h := S.exists_toSubgraph_eq_val
98-
h.choose_spec ▸ fiberEquivAut h.choose
97+
S.toSubgraph_out ▸ fiberEquivAut S.out
9998

10099
/-- `Copy G H` decomposes as the dependent sum over unlabelled copies of `G` in `H`, with each
101100
fiber the set of labelled copies sharing that image subgraph. -/
102101
noncomputable def equivSigma :
103102
Copy G H ≃ Σ S : G.UnlabeledCopy H, {f : Copy G H // f.toSubgraph = S.val} where
104-
toFun f := ⟨⟨f.toSubgraph, ⟨f.isoToSubgraph⟩⟩, ⟨f, rfl⟩⟩
103+
toFun f := ⟨f.toUnlabeledCopy, ⟨f, rfl⟩⟩
105104
invFun := fun ⟨_, f⟩ ↦ f.1
106105
left_inv _ := rfl
107106
right_inv := fun ⟨⟨S, hS⟩, ⟨f, hf⟩⟩ => by
@@ -151,14 +150,13 @@ noncomputable def fiberEquivAut (f₀ : Embedding G H) :
151150
`S.val` is equivalent to `Aut G`. -/
152151
noncomputable def fiberEquivAutOf (S : G.UnlabeledEmbedding H) :
153152
{f : Embedding G H // f.toSubgraph = S.val} ≃ G.Aut :=
154-
have h := S.exists_toSubgraph_eq_val
155-
h.choose_spec ▸ fiberEquivAut h.choose
153+
S.toSubgraph_out ▸ fiberEquivAut S.out
156154

157155
/-- `Embedding G H` decomposes as the dependent sum over unlabelled induced copies of `G` in `H`,
158156
with each fiber the set of labelled induced copies sharing that image subgraph. -/
159157
noncomputable def equivSigma :
160158
Embedding G H ≃ Σ S : G.UnlabeledEmbedding H, {f : Embedding G H // f.toSubgraph = S.val} where
161-
toFun f := ⟨⟨f.toSubgraph, f.toSubgraph_isInduced, ⟨f.toCopy.isoToSubgraph⟩⟩, ⟨f, rfl⟩⟩
159+
toFun f := ⟨f.toUnlabeledEmbedding, ⟨f, rfl⟩⟩
162160
invFun := fun ⟨_, f⟩ ↦ f.1
163161
left_inv _ := rfl
164162
right_inv := fun ⟨⟨S, hS⟩, ⟨f, hf⟩⟩ => by

Mathlib/Combinatorics/SimpleGraph/Copy.lean

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

494494
instance [Finite W] : Finite (G.UnlabeledCopy H) := Subtype.finite
495495

496+
/-- The canonical map from a labeled copy to its unlabeled image. -/
497+
@[expose] def Copy.toUnlabeledCopy (f : Copy G H) : G.UnlabeledCopy H :=
498+
⟨f.toSubgraph, ⟨f.isoToSubgraph⟩⟩
499+
500+
@[simp] lemma Copy.toUnlabeledCopy_val (f : Copy G H) : f.toUnlabeledCopy.val = f.toSubgraph := rfl
501+
496502
lemma UnlabeledCopy.exists_toSubgraph_eq_val (S : G.UnlabeledCopy H) :
497503
∃ f : Copy G H, f.toSubgraph = S.val :=
498504
Set.mem_range.mp (Copy.range_toSubgraph ▸ S.property)
499505

506+
/-- A noncomputable representative labeled copy of an unlabeled copy. -/
507+
noncomputable def UnlabeledCopy.out (S : G.UnlabeledCopy H) : Copy G H :=
508+
S.exists_toSubgraph_eq_val.choose
509+
510+
@[simp] lemma UnlabeledCopy.toSubgraph_out (S : G.UnlabeledCopy H) : S.out.toSubgraph = S.val :=
511+
S.exists_toSubgraph_eq_val.choose_spec
512+
500513
/-- `H.unlabeledCopyCount G` is the number of `SimpleGraph.Subgraph`s of `H` isomorphic to `G`. See
501514
`SimpleGraph.copyCount` for the number of labeled copies. -/
502515
noncomputable def unlabeledCopyCount (H : SimpleGraph W) (G : SimpleGraph V) : ℕ :=
@@ -517,12 +530,8 @@ lemma unlabeledCopyCount_eq_nat_card (H : SimpleGraph W) (G : SimpleGraph V) :
517530
lemma unlabeledCopyCount_le_copyCount [Finite V] [Finite W] :
518531
H.unlabeledCopyCount G ≤ H.copyCount G := by
519532
rw [unlabeledCopyCount, copyCount]
520-
apply Nat.card_le_card_of_surjective
521-
(fun c : Copy G H ↦ (⟨c.toSubgraph, ⟨c.isoToSubgraph⟩⟩ : G.UnlabeledCopy H))
522-
rintro ⟨H', hG'⟩
523-
obtain ⟨c, hc⟩ : ∃ c, Copy.toSubgraph c = H' := by
524-
rwa [← Set.mem_range, Copy.range_toSubgraph]
525-
exact ⟨c, Subtype.ext hc⟩
533+
exact Nat.card_le_card_of_surjective Copy.toUnlabeledCopy
534+
fun S ↦ ⟨S.out, Subtype.ext S.toSubgraph_out⟩
526535

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

Mathlib/Combinatorics/SimpleGraph/InducedCopy.lean

Lines changed: 17 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -324,10 +324,25 @@ abbrev UnlabeledEmbedding (G : SimpleGraph V) (H : SimpleGraph W) : Type _ :=
324324

325325
instance [Finite W] : Finite (G.UnlabeledEmbedding H) := Subtype.finite
326326

327+
/-- The canonical map from a labeled embedding to its unlabeled induced image. -/
328+
@[expose] def Embedding.toUnlabeledEmbedding (f : Embedding G H) : G.UnlabeledEmbedding H :=
329+
⟨f.toSubgraph, f.toSubgraph_isInduced, ⟨f.toCopy.isoToSubgraph⟩⟩
330+
331+
@[simp] lemma Embedding.toUnlabeledEmbedding_val (f : Embedding G H) :
332+
f.toUnlabeledEmbedding.val = f.toSubgraph := rfl
333+
327334
lemma UnlabeledEmbedding.exists_toSubgraph_eq_val (S : G.UnlabeledEmbedding H) :
328335
∃ f : Embedding G H, f.toSubgraph = S.val :=
329336
Set.mem_range.mp (Embedding.range_toSubgraph ▸ S.property)
330337

338+
/-- A noncomputable representative labeled embedding of an unlabeled induced copy. -/
339+
noncomputable def UnlabeledEmbedding.out (S : G.UnlabeledEmbedding H) : Embedding G H :=
340+
S.exists_toSubgraph_eq_val.choose
341+
342+
@[simp] lemma UnlabeledEmbedding.toSubgraph_out (S : G.UnlabeledEmbedding H) :
343+
S.out.toSubgraph = S.val :=
344+
S.exists_toSubgraph_eq_val.choose_spec
345+
331346
/-- `H.unlabeledEmbeddingCount G` is the number of induced `SimpleGraph.Subgraph`s of `H`
332347
isomorphic to `G`.
333348
See `SimpleGraph.embeddingCount` for the number of induced labeled copies. -/
@@ -352,13 +367,8 @@ unlabeled ones. -/
352367
lemma unlabeledEmbeddingCount_le_embeddingCount [Finite V] [Finite W] :
353368
H.unlabeledEmbeddingCount G ≤ H.embeddingCount G := by
354369
rw [unlabeledEmbeddingCount, embeddingCount]
355-
apply Nat.card_le_card_of_surjective
356-
(fun f : Embedding G H ↦ (⟨Embedding.toSubgraph f, f.toSubgraph_isInduced,
357-
⟨f.toCopy.isoToSubgraph⟩⟩ : G.UnlabeledEmbedding H))
358-
rintro ⟨H', hInd, ⟨e⟩⟩
359-
obtain ⟨f, hf⟩ : ∃ f : Embedding G H, Embedding.toSubgraph f = H' := by
360-
rw [← Set.mem_range, Embedding.range_toSubgraph]; exact ⟨hInd, ⟨e⟩⟩
361-
exact ⟨f, Subtype.ext hf⟩
370+
exact Nat.card_le_card_of_surjective Embedding.toUnlabeledEmbedding
371+
fun S ↦ ⟨S.out, Subtype.ext S.toSubgraph_out⟩
362372

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

0 commit comments

Comments
 (0)