feat(Combinatorics/SimpleGraph/Bipartite): Prove upper bound of edge set cardinality of bipartite graph#34315
Conversation
|
PR summary 84442bd12fImport changes for modified filesNo significant changes to the import graph Import changes for all files
|
vlad902
left a comment
There was a problem hiding this comment.
Just a few comments, I haven't looked through everything. I wonder if it might be easier to show this by showing that the complete bipartite graph has cardinality equal to s*t and that every bipartite graph embeds into it and hence has cardinality bounded by that value, but I haven't looked at trying it.
|
Out of curiosity I tried to outline this approach. It's messy and I'm not sure what the exact right form is but here's what I got before running out of time import Mathlib
namespace SimpleGraph
variable {V W₁ W₂ : Type*} (G : SimpleGraph V) {s t : Set V}
theorem eq_sym2_out (v : Sym2 V) : v = s(v.out.1, v.out.2) := by
ext
simp
theorem edgeSet_eq : G.edgeSet = { x | ∃ v w : V, x = s(v, w) ∧ G.Adj v w } := by
refine Set.ext fun x ↦ ⟨fun h ↦ ?_, by grind [mem_edgeSet]⟩
exact ⟨x.out.1, x.out.2, by simp [G.mem_edgeSet.mp <| eq_sym2_out x ▸ h]⟩
theorem completeBipartiteGraph_edgeSet : (completeBipartiteGraph W₁ W₂).edgeSet = Set.range (fun x : W₁ × W₂ ↦ s(.inl x.1, .inr x.2)) := by
refine Set.ext fun x ↦ ⟨fun h ↦ ?_, fun h ↦ ?_⟩
· simp only [edgeSet_eq, completeBipartiteGraph_adj, Sum.exists, Sum.isRight_inl,
Bool.false_eq_true, and_false, Sum.isLeft_inl, and_true, false_or, exists_and_right,
Sum.isRight_inr, Sum.isLeft_inr, or_false, Set.mem_setOf_eq] at h
cases h with | inl h' | inr h' <;> obtain ⟨u,v,huv⟩ := h' <;> simp_all
· obtain ⟨u, v, huv⟩ := h
simp
theorem completeBipartiteGraph_edgeSet_encard : (completeBipartiteGraph W₁ W₂).edgeSet.encard = ENat.card W₁ * ENat.card W₂ := by
let g (x : W₁ × W₂) : Sym2 (W₁ ⊕ W₂) := s(.inl x.1, .inr x.2)
have : Function.Injective g := fun _ _ _ ↦ by grind
have := this.encard_image Set.univ
simpa [completeBipartiteGraph_edgeSet, this]
theorem IsBipartiteWith.encard_edgeSet_le {s t : Set V} (hG : G.IsBipartiteWith s t) :
G.edgeSet.encard ≤ s.encard * t.encard := by
have : G.edgeSet.encard ≤ (completeBipartiteGraph s t).edgeSet.encard := by
refine Function.Embedding.encard_le ?_
sorry
grw [this, completeBipartiteGraph_edgeSet_encard]
simp |
|
Thank you! It definitely looks shorter and better than my current attempt to implement your suggestion. I will try to fill the |
|
I kind of filled the |
|
Probably it can be shortened in many ways, but I will postpone my attempts at that until tomorrow. |
|
This compiles though I don't love import Mathlib
variable {V W₁ W₂ : Type*} (G : SimpleGraph V) {s t : Set V}
theorem Sym2.eq_out (v : Sym2 V) : v = s(v.out.1, v.out.2) := Sym2.ext (by simp)
namespace SimpleGraph
theorem edgeSet_eq : G.edgeSet = { x | ∃ v w : V, x = s(v, w) ∧ G.Adj v w } := by
refine Set.ext fun x ↦ ⟨fun h ↦ ?_, by grind [mem_edgeSet]⟩
exact ⟨x.out.1, x.out.2, by simp [G.mem_edgeSet.mp <| x.eq_out ▸ h]⟩
theorem completeBipartiteGraph_edgeSet : (completeBipartiteGraph W₁ W₂).edgeSet = Set.range (fun x : W₁ × W₂ ↦ s(.inl x.1, .inr x.2)) := by
refine Set.ext fun x ↦ ⟨fun h ↦ ?_, fun h ↦ ?_⟩
· simp only [edgeSet_eq, completeBipartiteGraph_adj, Sum.exists, Sum.isRight_inl,
Bool.false_eq_true, and_false, Sum.isLeft_inl, and_true, false_or, exists_and_right,
Sum.isRight_inr, Sum.isLeft_inr, or_false, Set.mem_setOf_eq] at h
rcases h with ⟨_, _, _⟩ | ⟨_, _, _⟩ <;> simp_all
· obtain ⟨_, _, _⟩ := h
simp
theorem completeBipartiteGraph_edgeSet_encard : (completeBipartiteGraph W₁ W₂).edgeSet.encard = ENat.card W₁ * ENat.card W₂ := by
let g (x : W₁ × W₂) : Sym2 (W₁ ⊕ W₂) := s(.inl x.1, .inr x.2)
have : Function.Injective g := fun _ _ _ ↦ by grind
have := this.encard_image Set.univ
simpa [completeBipartiteGraph_edgeSet, this]
theorem myembedding (hG : G.IsBipartiteWith s t) : Nonempty (G.edgeSet ↪ (completeBipartiteGraph s t).edgeSet) := by
refine ⟨⟨fun ⟨x, hx⟩ ↦ ?_, fun _ _ _ ↦ ?_⟩⟩
· by_cases! h : x.out.1 ∈ s
· refine ⟨s(.inl ⟨x.out.1, h⟩, .inr ⟨x.out.2, ?_⟩), by simp⟩
grind [hG.disjoint, hG.mem_of_adj, edgeSet_eq, Sym2.eq_out]
· refine ⟨s(.inr ⟨x.out.1, ?_⟩, .inl ⟨x.out.2, ?_⟩), by simp⟩
· grind [hG.mem_of_adj <| G.mem_edgeSet.mpr <| x.eq_out ▸ hx]
· grind [hG.disjoint, hG.mem_of_adj, edgeSet_eq, Sym2.eq_out]
· grind [Sym2.eq_out]
theorem IsBipartiteWith.encard_edgeSet_le {s t : Set V} (hG : G.IsBipartiteWith s t) :
G.edgeSet.encard ≤ s.encard * t.encard := by
grw [Classical.choice (myembedding G hG) |>.encard_le, completeBipartiteGraph_edgeSet_encard]
simpThere was a recent discussion about |
|
I have so much to learn... 🤔 Thank you. |
|
May I use/copy-paste your proof in this PR, instead of mine? Adding you as author, of course. |
|
Please do |
…four_mul_encard_edgeSet_le back
|
I did it. Also added |
| theorem completeBipartiteGraph_edgeSet_encard : | ||
| (completeBipartiteGraph W₁ W₂).edgeSet.encard = | ||
| ENat.card W₁ * ENat.card W₂ := by | ||
| let g (x : W₁ × W₂) : Sym2 (W₁ ⊕ W₂) := s(.inl x.1, .inr x.2) | ||
| have : Function.Injective g := fun _ _ _ ↦ by grind | ||
| have := this.encard_image Set.univ | ||
| simpa [completeBipartiteGraph_edgeSet, this] |
There was a problem hiding this comment.
| theorem completeBipartiteGraph_edgeSet_encard : | |
| (completeBipartiteGraph W₁ W₂).edgeSet.encard = | |
| ENat.card W₁ * ENat.card W₂ := by | |
| let g (x : W₁ × W₂) : Sym2 (W₁ ⊕ W₂) := s(.inl x.1, .inr x.2) | |
| have : Function.Injective g := fun _ _ _ ↦ by grind | |
| have := this.encard_image Set.univ | |
| simpa [completeBipartiteGraph_edgeSet, this] | |
| theorem completeBipartiteGraph_edgeSet_encard : | |
| (completeBipartiteGraph W₁ W₂).edgeSet.encard = ENat.card W₁ * ENat.card W₂ := by | |
| rw [completeBipartiteGraph_edgeSet, ← ENat.card_prod, ← Set.encard_univ, ← Set.image_univ] | |
| exact Function.Injective.encard_image (by grind [Function.Injective]) Set.univ |
Also I think it would be great to add a lemma that combines Function.Injective.encard_image with Set.image_univ creating (Set.range f).encard = (Set.univ : α).encard for an injective f : α → β, though I'm not sure what it should be called since Function.Injective.encard_image already exists.
There was a problem hiding this comment.
Maybe Function.Injective.encard_range? 🤔
Although it seems to be very simple (too simple?), if I understood everything correctly. Almost the same as Function.Injective.encard_image.
import Mathlib
lemma Function.Injective.encard_range {α β} {f : α → β} (hf : Function.Injective f) :
(Set.range f).encard = (Set.univ : Set α).encard :=
Set.image_univ.symm ▸ Function.Injective.encard_image hf Set.univ
| theorem IsBipartiteWith.nonempty_embedding_completeBipartiteGraph_edgeSet | ||
| (hG : G.IsBipartiteWith s t) : | ||
| Nonempty (G.edgeSet ↪ (completeBipartiteGraph s t).edgeSet) := by | ||
| refine ⟨⟨fun ⟨x, hx⟩ ↦ ?_, fun _ _ _ ↦ ?_⟩⟩ | ||
| · by_cases! h : x.out.1 ∈ s | ||
| · refine ⟨s(.inl ⟨x.out.1, h⟩, .inr ⟨x.out.2, ?_⟩), by simp⟩ | ||
| grind [hG.disjoint, hG.mem_of_adj, mem_edgeSet, Sym2.eq_out] | ||
| · refine ⟨s(.inr ⟨x.out.1, ?_⟩, .inl ⟨x.out.2, ?_⟩), by simp⟩ | ||
| · grind [hG.mem_of_adj <| G.mem_edgeSet.mpr <| x.eq_out ▸ hx] | ||
| · grind [hG.disjoint, hG.mem_of_adj, mem_edgeSet, Sym2.eq_out] | ||
| · grind [Sym2.eq_out] |
There was a problem hiding this comment.
An alternative version with a computable function, that might be useful:
| theorem IsBipartiteWith.nonempty_embedding_completeBipartiteGraph_edgeSet | |
| (hG : G.IsBipartiteWith s t) : | |
| Nonempty (G.edgeSet ↪ (completeBipartiteGraph s t).edgeSet) := by | |
| refine ⟨⟨fun ⟨x, hx⟩ ↦ ?_, fun _ _ _ ↦ ?_⟩⟩ | |
| · by_cases! h : x.out.1 ∈ s | |
| · refine ⟨s(.inl ⟨x.out.1, h⟩, .inr ⟨x.out.2, ?_⟩), by simp⟩ | |
| grind [hG.disjoint, hG.mem_of_adj, mem_edgeSet, Sym2.eq_out] | |
| · refine ⟨s(.inr ⟨x.out.1, ?_⟩, .inl ⟨x.out.2, ?_⟩), by simp⟩ | |
| · grind [hG.mem_of_adj <| G.mem_edgeSet.mpr <| x.eq_out ▸ hx] | |
| · grind [hG.disjoint, hG.mem_of_adj, mem_edgeSet, Sym2.eq_out] | |
| · grind [Sym2.eq_out] | |
| /-- An embedding of the edges of a bipartite graph into the edges of the complete bipartite graph -/ | |
| def IsBipartiteWith.edgeSetEmbeddingCompleteBipartiteGraph [DecidableRel (· ∈ · : V → Set V → _)] | |
| (hG : G.IsBipartiteWith s t) : G.edgeSet ↪ (completeBipartiteGraph s t).edgeSet where | |
| toFun := fun ⟨e, he⟩ ↦ | |
| e.hrec (fun u v h ↦ hG.mem_of_adj h |>.by_cases | |
| (fun h ↦ ⟨s(.inl ⟨u, h.left⟩, .inr ⟨v, h.right⟩), .inl ⟨rfl, rfl⟩⟩) | |
| (fun h ↦ ⟨s(.inl ⟨v, h.right⟩, .inr ⟨u, h.left⟩), .inl ⟨rfl, rfl⟩⟩) | |
| ) (fun _ _ ↦ Function.hfunext (by grind) <| by grind [Or.by_cases, hG.disjoint]) he | |
| inj' := by | |
| rintro ⟨⟨⟩⟩ ⟨⟨⟩⟩ | |
| change (if _ : _ then _ else _) = (if _ : _ then _ else _) → _ | |
| grind |
The theorem that uses this just needs to call classical before to satisfy the DecidableRel
(edit: fixed after the signature of Sym2.hrec was changed, requires merging master)
There was a problem hiding this comment.
If we adopt this we can also get rid of Sym2.eq_out, though stylistically I'm unsure which one is preferable.
There was a problem hiding this comment.
I would prefer this version (with a computable function), but I'm not sure too.
There was a problem hiding this comment.
It's generally better to use recursion on the quotient rather than .out, and in this case actually not for computability reasons!
There was a problem hiding this comment.
Actually I think I have a lemma somewhere which combines Sym2.hrec with the hfunext call, let me go looking
There was a problem hiding this comment.
I also have a def that combines the two, I inlined it before posting the code above.
Just PRed it in #34909 if you're interested (but it shouldn't block this PR)
|
Sorry for disappearing, caught some flu 😓 Now getting back on my feet. |
|
Is there something more I can do on this PR? |
|
Oh, |
Nope, it seems I'm too dumb and need help. My apologies. 😓 |
Do you mean a proof for btw my suggestion above alleviates the need for |
|
Applied suggestion by SnirBroshi, and, hoorah, everything is back to working state! Thank you. |
|
This pull request has conflicts, please merge |
Two ways to express upper bound of the edge set of bipartite graph: