Skip to content

Commit e5ccc78

Browse files
Impl bipartiteDoubleCover
1 parent f02860e commit e5ccc78

1 file changed

Lines changed: 84 additions & 0 deletions

File tree

Mathlib/Combinatorics/SimpleGraph/Bipartite.lean

Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -445,4 +445,88 @@ theorem degree_le_between_add_compl (hw : w ∈ sᶜ) :
445445

446446
end Between
447447

448+
section BipartiteDoubleCover
449+
450+
/-- `bipartiteDoubleCover G` has two vertices `inl v` and `inr v` for each vertex `v` in `G`
451+
such that `inl v` (`inr v`) is adjacent to `inr w` (`inl w`) iff `v` is adjacent to `w` in `G`. -/
452+
@[simp] def bipartiteDoubleCover (G : SimpleGraph V) : SimpleGraph (V ⊕ V) where
453+
Adj v w := match v, w with
454+
| .inl v', .inr w' | .inr v', .inl w' => G.Adj v' w'
455+
| _, _ => False
456+
symm v w := match v, w with
457+
| .inl _, .inr _ | .inr _, .inl _ => G.adj_symm
458+
| .inl _, .inl _ | .inr _, .inr _ => id
459+
460+
instance [h : DecidableRel G.Adj] : DecidableRel G.bipartiteDoubleCover.Adj :=
461+
fun v w ↦ match v, w with
462+
| .inl _, .inr _ | .inr _, .inl _ => h _ _
463+
| .inl _, .inl _ | .inr _, .inr _ => inferInstanceAs (Decidable False)
464+
465+
/-- The bipartite double cover of `G` is contained in the corresponding complete bipartite graph,
466+
that is, the bipartite double cover of `G` is bipartite. -/
467+
theorem bipartiteDoubleCover_le : G.bipartiteDoubleCover ≤ completeBipartiteGraph V V :=
468+
fun v w hadj ↦ match v, w with
469+
| .inl _, .inr _ | .inr _, .inl _ => by simp
470+
| .inl _, .inl _ | .inr _, .inr _ => by simp at hadj
471+
472+
/-- The bipartite double cover of `G` has twice the number of edges as `G`. -/
473+
theorem bipartiteDoubleCover_card_edgeFinset [Fintype V] [DecidableRel G.Adj] :
474+
#G.bipartiteDoubleCover.edgeFinset = 2 * #G.edgeFinset := by
475+
rw [two_mul_card_edgeFinset, eq_comm]
476+
apply card_bij (fun (v, w) _ ↦ s(.inl v, .inr w)) (fun _ h ↦ by simpa using h)
477+
(fun (_, _) _ (_, _) _ ↦ by simp) (fun e he ↦ ?_)
478+
induction e with | _ v w
479+
rw [Set.mem_toFinset, mem_edgeSet] at he
480+
match v, w with
481+
| .inl _, .inr _ => simpa using he
482+
| .inr _, .inl _ => simpa using he.symm
483+
| .inl _, .inl _ | .inr _, .inr _ => simp at he
484+
485+
/-- If the double cover of `G` contains `completeBipartiteGraph α β`, then `G` also
486+
contains `completeBipartiteGraph α β`. -/
487+
theorem bipartiteDoubleCover_completeBipartiteGraph_isContained
488+
{α β : Type*} [Fintype α] [Fintype β] [Nonempty α] [Nonempty β]
489+
(h : completeBipartiteGraph α β ⊑ G.bipartiteDoubleCover) :
490+
completeBipartiteGraph α β ⊑ G := by
491+
rw [completeBipartiteGraph_isContained_iff] at h ⊢
492+
obtain ⟨left, right, card_left, card_right, h⟩ := h
493+
simp_rw [← card_left, ← card_right]
494+
obtain ⟨l, hl⟩ : left.Nonempty := card_pos.mp <| card_pos.trans_le card_left.ge
495+
obtain ⟨r, hr⟩ : right.Nonempty := card_pos.mp <| card_pos.trans_le card_right.ge
496+
have hmem_left {l'} (hl' : l' ∈ left) : (l.isLeft → l'.isLeft) ∧ (l.isRight → l'.isRight) := by
497+
rcases l with l | l <;> rcases r with r | r <;> rcases l' with l' | l'
498+
all_goals solve | simp | simpa using h hl hr | simpa using h hl' hr
499+
have hmem_right {r'} (hr' : r' ∈ right) : (r.isLeft → r'.isLeft) ∧ (r.isRight → r'.isRight) := by
500+
rcases l with l | l <;> rcases r with r | r <;> rcases r' with r' | r'
501+
all_goals solve | simp | simpa using h hl hr | simpa using h hl hr'
502+
rcases l with l | l <;> rcases r with r | r
503+
· simpa using h hl hr
504+
· refine ⟨left.toLeft, right.toRight, ?_, ?_, fun i hi j hj ↦ ?_⟩
505+
· exact card_bij (fun i _ ↦ .inl i) (fun i hi ↦ by simpa using hi) (fun i hi j hj ↦ by simp)
506+
(fun i hi ↦ ⟨i.getLeft <| (hmem_left hi).left Sum.isLeft_inl, by simp [hi]⟩)
507+
· exact card_bij (fun j hj ↦ .inr j) (fun j hj ↦ by simpa using hj) (fun i hi j hj ↦ by simp)
508+
(fun j hj ↦ ⟨j.getRight <| (hmem_right hj).right Sum.isRight_inr, by simp [hj]⟩)
509+
· rw [mem_coe, mem_toLeft] at hi
510+
rw [mem_coe, mem_toRight] at hj
511+
simpa using h hi hj
512+
· refine ⟨left.toRight, right.toLeft, ?_, ?_, fun i hi j hj ↦ ?_⟩
513+
· exact card_bij (fun i _ ↦ .inr i) (fun i hi ↦ by simpa using hi) (fun i hi j hj ↦ by simp)
514+
(fun i hi ↦ ⟨i.getRight <| (hmem_left hi).right Sum.isRight_inr, by simp [hi]⟩)
515+
· exact card_bij (fun j hj ↦ .inl j) (fun j hj ↦ by simpa using hj) (fun i hi j hj ↦ by simp)
516+
(fun j hj ↦ ⟨j.getLeft <| (hmem_right hj).left Sum.isLeft_inl, by simp [hj]⟩)
517+
· rw [mem_coe, mem_toRight] at hi
518+
rw [mem_coe, mem_toLeft] at hj
519+
simpa using h hi hj
520+
· simpa using h hl hr
521+
522+
theorem bipartiteDoubleCover_isBipartiteWith :
523+
G.bipartiteDoubleCover.IsBipartiteWith {v | v.isLeft} {w | w.isRight} where
524+
disjoint := by simp [Set.disjoint_iff_forall_ne]
525+
mem_of_adj := by simp
526+
527+
theorem bipartiteDoubleCover_isBipartite : G.bipartiteDoubleCover.IsBipartite :=
528+
bipartiteDoubleCover_isBipartiteWith.isBipartite
529+
530+
end BipartiteDoubleCover
531+
448532
end SimpleGraph

0 commit comments

Comments
 (0)