summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Brooks.lean504
1 files changed, 422 insertions, 82 deletions
diff --git a/Brooks.lean b/Brooks.lean
index 669ecc7..1619387 100644
--- a/Brooks.lean
+++ b/Brooks.lean
@@ -20,41 +20,120 @@ open Classical
variable
{α : Type}
{V : Type} [Fintype V]
- (G : SimpleGraph V) [DecidableRel G.Adj]
+ {G : SimpleGraph V}
+
+-- API for partial colorings
+
+namespace SimpleGraph.Coloring
+
+ structure Extension {S : Set V} (C : (G.induce S).Coloring α) (T : Set V) where
+ subset : S ⊆ T
+ coloring : (G.induce T).Coloring α
+ compatible : @Set.restrict₂ V (fun _ => α) S T subset coloring = C
+
+ def trivial_extension {S : Set V} (C : (G.induce S).Coloring α) : Extension C S := by
+ apply Extension.mk
+ case subset => exact subset_refl S
+ case coloring => exact C
+ case compatible =>
+ ext x
+ simp only [Set.restrict₂, Subtype.coe_eta]
+
+ def extension_trans
+ {S T U : Set V}
+ (C : (G.induce S).Coloring α)
+ (E : Extension C T)
+ (F : Extension E.coloring U)
+ : Extension C U := by
+ apply Extension.mk
+ case subset => exact subset_trans E.subset F.subset
+ case coloring => exact F.coloring
+ case compatible => simp only [←(Set.restrict₂_comp_restrict₂ E.subset F.subset), Function.comp_apply, F.compatible, E.compatible]
+
+end SimpleGraph.Coloring
+
+namespace SimpleGraph.Path
+
+ def split [dec_eq : DecidableEq V] {u v : V} (p : G.Path u v) (z : V) (hz : z ∈ p.val.support)
+ : Σ p₁ : G.Path u z, Σ' p₂ : G.Path z v, p.val = p₁.val.append p₂.val := by
+ replace ⟨p, hp⟩ := p
+ cases dec_eq z u with
+ | isTrue h =>
+ rw [h]
+ use Path.nil, ⟨p, hp⟩
+ simp only [nil_coe, Walk.nil_append]
+ | isFalse h =>
+ cases p with
+ | nil =>
+ simp only [support_nil, mem_cons, not_mem_nil, or_false] at hz
+ contradiction
+ | @cons u w v adj tl =>
+ simp only [support_cons, mem_cons, h, false_or] at hz
+ obtain ⟨⟨tl₁, htl₁⟩, ⟨tl₂, htl₂⟩, happ⟩ := split ⟨tl, IsPath.of_cons hp⟩ z hz
+ simp only at happ
+ simp only [happ, cons_isPath_iff, mem_support_append_iff, not_or] at hp
+ let p₁ := Walk.cons adj tl₁
+ have hp₁ : IsPath p₁ := IsPath.cons htl₁ hp.right.left
+ use ⟨p₁, hp₁⟩, ⟨tl₂, htl₂⟩
+ simp only [Walk.cons_append, p₁, happ]
+
+end SimpleGraph.Path
noncomputable def extend_coloring
- (S : Set V) (S_coloring : Coloring (G.induce S) α)
+ (S : Set V) (C : Coloring (G.induce S) α)
(v : V) (c : α)
- (h : c ∉ S_coloring '' (S ↓∩ G.neighborSet v))
- : Coloring (G.induce (S ∪ {v})) α
+ (h : c ∉ C '' (S ↓∩ G.neighborSet v))
+ : Coloring.Extension C (S ∪ {v})
:= by
- simp at h
- apply Coloring.mk
- case color =>
- intro ⟨x, mem⟩
- by_cases hx : x ∈ S
- · exact S_coloring ⟨x, hx⟩
- · exact c
- case valid =>
- rintro ⟨x₁, mem_x₁⟩ ⟨x₂, mem_x₂⟩
- intro adj
- by_cases hx₁ : x₁ ∈ S <;> by_cases hx₂ : x₂ ∈ S
- -- 4 cases according to whether x₁ and/or x₂ are in S or not
- · simp [hx₁, hx₂]
- exact S_coloring.valid adj
- · simp [hx₁, hx₂]
- replace hx₂ : x₂ = v := mem_x₂.resolve_left hx₂
- simp [hx₂] at adj
- exact h x₁ (G.adj_symm adj) hx₁
- · simp [hx₁, hx₂]
- replace hx₁ : x₁ = v := mem_x₁.resolve_left hx₁
- simp [hx₁] at adj
- -- TODO the following 2 lines are kind of cumbersome
- intro wrong
- exact (h x₂ adj hx₂) (Eq.symm wrong)
- · intro a
- simp_all only [comap_adj, Function.Embedding.coe_subtype]
- simp_all only [Set.union_singleton, Set.mem_insert_iff, or_false, SimpleGraph.irrefl]
+ apply Coloring.Extension.mk
+ case subset => exact Set.subset_union_left
+ case coloring =>
+ apply Coloring.mk
+ case color =>
+ intro ⟨x, _⟩
+ by_cases hx : x ∈ S
+ · exact C ⟨x, hx⟩
+ · exact c
+ case valid =>
+ simp only [Set.mem_image, Set.mem_preimage, mem_neighborSet, Subtype.exists,
+ exists_and_left, not_exists, not_and] at h
+ rintro ⟨x, hx⟩ ⟨y, hy⟩ adj
+ by_cases hxS : x ∈ S <;> by_cases hyS : y ∈ S
+ · simp only [hxS, hyS]
+ exact C.valid adj
+ · simp only [hxS, hyS]
+ replace hyS : y = v := hy.resolve_left hyS
+ simp only [hyS, comap_adj, Function.Embedding.subtype_apply] at adj
+ exact h x (G.adj_symm adj) hxS
+ · simp only [hxS, hyS]
+ replace hxS : x = v := hx.resolve_left hxS
+ simp only [hxS] at adj
+ intro wrong
+ exact h y adj hyS (Eq.symm wrong)
+ · intro a
+ simp_all only [comap_adj, Function.Embedding.coe_subtype]
+ simp_all only [Set.union_singleton, Set.mem_insert_iff, or_false, SimpleGraph.irrefl]
+
+ case compatible =>
+ ext ⟨x, hx⟩
+ simp only [Coloring.mk, Set.restrict₂_def, RelHom.instFunLike]
+ simp only [hx, ↓reduceDIte, RelHom.coe_fn_toFun]
+
+noncomputable def extend_coloring_of_image_card
+ {k : ℕ}
+ (S : Set V) (C : Coloring (G.induce S) (Fin k))
+ (v : V) (h : (C '' (S ↓∩ G.neighborSet v)).toFinset.card < k)
+ : Coloring.Extension C (S ∪ {v}) := by
+ let N := G.neighborSet v
+
+ have unused_color : ∃ c : Fin k, c ∉ C '' (S ↓∩ N) := by
+ suffices (C '' (S ↓∩ N)).toFinset.card < (Set.univ : Set (Fin k)).toFinset.card from by
+ have ⟨c, hc⟩ := Finset.exists_mem_not_mem_of_card_lt_card this
+ simp only [Set.mem_toFinset] at hc
+ exact ⟨c, hc.right⟩
+ simp only [Set.toFinset_univ, Finset.card_univ, Fintype.card_fin]
+ exact h
+ exact extend_coloring S C v (Exists.choose unused_color) (Exists.choose_spec unused_color)
lemma preimage_val_card (A B : Set V) : (A ↓∩ B).toFinset.card = (A ∩ B).toFinset.card := by
apply Finset.card_bij'
@@ -78,12 +157,11 @@ lemma preimage_val_card (A B : Set V) : (A ↓∩ B).toFinset.card = (A ∩ B).t
intro a ha
simp_all only [not_false_eq_true, true_and]
-lemma extend_coloring'
+noncomputable def extend_coloring_of_lt_colored_neighbors
{k : ℕ}
- (S : Set V) (S_colorable : Colorable (G.induce S) k)
+ (S : Set V) (C : Coloring (G.induce S) (Fin k))
(v : V) (h : (G.neighborSet v ∩ S).toFinset.card < k)
- : Colorable (G.induce (S ∪ {v})) k := by
- have S_coloring := S_colorable.some
+ : Coloring.Extension C (S ∪ {v}) := by
let N := G.neighborSet v
have card_fact : (S ↓∩ N).toFinset.card = (S ∩ N).toFinset.card := by
@@ -91,28 +169,23 @@ lemma extend_coloring'
have foo := preimage_val_card S N
convert foo
- have unused_color : ∃ c : Fin k, c ∉ S_coloring '' (S ↓∩ N) := by
- suffices (S_coloring '' (S ↓∩ N)).toFinset.card < (Set.univ : Set (Fin k)).toFinset.card from by
- have ⟨c, hc⟩ := Finset.exists_mem_not_mem_of_card_lt_card this
- simp only [Set.mem_toFinset] at hc
- exact ⟨c, hc.right⟩
+ replace h : (C '' (S ↓∩ G.neighborSet v)).toFinset.card < k := by
simp only [Set.toFinset_image, Set.toFinset_univ, Finset.card_univ, Fintype.card_fin]
calc
- (Finset.image (⇑S_coloring) (S ↓∩ N).toFinset).card ≤ (S ↓∩ N).toFinset.card := Finset.card_image_le
+ (Finset.image C (S ↓∩ N).toFinset).card ≤ (S ↓∩ N).toFinset.card := Finset.card_image_le
_ = (S ∩ N).toFinset.card := card_fact
_ = (N ∩ S).toFinset.card := by simp only [Set.inter_comm]
_ < k := h
- have ⟨c, hc⟩ := unused_color
- exact Nonempty.intro (extend_coloring G S S_coloring v c hc)
-lemma extend_coloring''
+ exact extend_coloring_of_image_card S C v h
+
+noncomputable def extend_coloring_of_degree_lt
{k : ℕ}
- (S : Set V) (S_colorable : Colorable (G.induce S) k)
+ (S : Set V) (C : Coloring (G.induce S) (Fin k))
(v : V) (h : G.degree v < k)
- : Colorable (G.induce (S ∪ {v})) k := by
- apply extend_coloring'
- · assumption
- · calc
+ : Coloring.Extension C (S ∪ {v}) := by
+ apply extend_coloring_of_lt_colored_neighbors
+ calc
(G.neighborSet v ∩ S).toFinset.card ≤ (G.neighborSet v).toFinset.card := by
simp only [Set.toFinset_inter]
apply Finset.card_le_card
@@ -120,28 +193,63 @@ lemma extend_coloring''
_ = G.degree v := by simp only [Set.toFinset_card, G.card_neighborSet_eq_degree]
_ < k := h
-theorem color_path
+noncomputable def extend_coloring_of_two_neighbors_eq_color
+ {k : ℕ}
+ (S : Set V) (C : Coloring (G.induce S) (Fin k))
+ (v : V) (hv : G.degree v ≤ k)
+ (x y : S) (hx : G.Adj v x) (hy : G.Adj v y) (x_ne_y : x ≠ y)
+ (hC : C x = C y)
+ : Coloring.Extension C (S ∪ {v}) := by
+ let N := G.neighborSet v
+ apply extend_coloring_of_image_card
+ simp only [Set.toFinset_image, Set.toFinset_univ, Finset.card_univ, Fintype.card_fin]
+
+ have card_fact : (S ↓∩ N).toFinset.card = (S ∩ N).toFinset.card := by
+ -- without "convert" this gives a timeout error
+ have foo := preimage_val_card S N
+ convert foo
+
+ have S_inter_N_card_le_k : (S ↓∩ N).toFinset.card ≤ k := calc
+ (S ↓∩ N).toFinset.card = (S ∩ N).toFinset.card := card_fact
+ _ ≤ N.toFinset.card := Finset.card_le_card (Set.toFinset_subset_toFinset.mpr Set.inter_subset_right)
+ _ ≤ k := hv
+
+ apply Ne.lt_of_le
+ · intro hk
+ have k_le_S_inter_N_card : k ≤ (S ↓∩ N).toFinset.card := calc
+ k = (Finset.image C (S ↓∩ N).toFinset).card := hk.symm
+ _ ≤ (S ↓∩ N).toFinset.card := Finset.card_image_le
+ have k_eq_S_inter_N_card := Nat.le_antisymm k_le_S_inter_N_card S_inter_N_card_le_k
+ simp only [k_eq_S_inter_N_card] at hk
+ have C_inj_on_S_inter_N := Finset.card_image_iff.mp hk
+ simp only [Set.coe_toFinset] at C_inj_on_S_inter_N
+ have x_eq_y := C_inj_on_S_inter_N hx hy hC
+ contradiction
+ · calc
+ (Finset.image C (S ↓∩ N).toFinset).card ≤ (S ↓∩ N).toFinset.card := Finset.card_image_le
+ _ ≤ k := S_inter_N_card_le_k
+
+noncomputable def color_path
(k : ℕ) (maxDeg_le_k : G.maxDegree ≤ k)
{u v : V} (P : G.Path u v)
(S : Set V)
(P_outside_S : ∀ x ∈ P.val.support, x ∉ S)
- (S_colorable : Colorable (G.induce S) k)
- : Colorable (G.induce (S ∪ P.val.support.tail.toFinset)) k := by
- classical
+ (S_coloring : Coloring (G.induce S) (Fin k))
+ : Coloring.Extension S_coloring (S ∪ P.val.support.tail.toFinset) := by
let ⟨W, W_is_path⟩ := P
cases W with
| nil =>
- simp
- rw [Finset.coe_empty, Set.union_empty]
- exact S_colorable
+ simp only [support_nil, List.tail_cons, toFinset_nil, Finset.coe_empty, Set.union_empty]
+ exact Coloring.trivial_extension S_coloring
| @cons u w v adj W' =>
- simp at *
+ simp only [support_cons, mem_cons, forall_eq_or_imp] at P_outside_S
+
let P' : G.Path w v := ⟨W', IsPath.of_cons W_is_path⟩
- have P'_colorable := color_path k maxDeg_le_k P' S (P_outside_S.right) S_colorable
+ have T_ext := color_path k maxDeg_le_k P' S (P_outside_S.right) S_coloring
let N := G.neighborSet w
-- set of vertices already colored by P'_coloring
- let C := S ∪ W'.support.tail.toFinset
+ let T := S ∪ W'.support.tail.toFinset
have u_not_in_W' : u ∉ W'.support := ((Walk.cons_isPath_iff adj W').mp W_is_path).right
have u_not_in_W'_tail : u ∉ W'.support.tail := by
@@ -149,22 +257,22 @@ theorem color_path
have u_in_W' := List.Mem.tail w wrong
rw [←(Walk.support_eq_cons W')] at u_in_W'
contradiction
- have hu : u ∈ (N \ C) := by
- simp [N, C]
+ have hu : u ∈ (N \ T) := by
+ simp [N, T]
exact ⟨G.adj_symm adj, P_outside_S.left, u_not_in_W'_tail⟩
- have h : (N ∩ C).toFinset.card < k := by
- have ineq1 : (N ∩ C).toFinset.card + (N \ C).toFinset.card ≤ k := calc
+ have h : (N ∩ T).toFinset.card < k := by
+ have ineq1 : (N ∩ T).toFinset.card + (N \ T).toFinset.card ≤ k := calc
_ = N.toFinset.card := by simp only [Set.toFinset_inter, Set.toFinset_diff, Finset.card_inter_add_card_sdiff]
_ ≤ G.maxDegree := G.degree_le_maxDegree w
_ ≤ k := maxDeg_le_k
- have ineq2 : 1 ≤ (N \ C).toFinset.card := by
+ have ineq2 : 1 ≤ (N \ T).toFinset.card := by
simp only [Finset.one_le_card, Set.toFinset_nonempty]
exact ⟨u, hu⟩
linarith
have extended_coloring := by
- apply extend_coloring' G C P'_colorable w
+ apply extend_coloring_of_lt_colored_neighbors T T_ext.coloring w
-- TODO without "convert" this gives a timeout error
convert h
@@ -172,7 +280,7 @@ theorem color_path
simp only [coe_toFinset, Set.union_def, Set.mem_setOf_eq, Set.mem_singleton_iff, Or.comm, mem_support_iff]
rw [Set.union_assoc, fact] at extended_coloring
- exact extended_coloring
+ exact Coloring.extension_trans S_coloring T_ext extended_coloring
lemma induce_maxDegree_mono (S : Set V) : (G.induce S).maxDegree ≤ G.maxDegree := by
simp only [G.induce_eq_coe_induce_top S]
@@ -184,7 +292,7 @@ lemma induce_maxDegree_mono (S : Set V) : (G.induce S).maxDegree ≤ G.maxDegree
_ ≤ G.maxDegree := G.degree_le_maxDegree v
noncomputable def extend_path_maximally {u v : V} (P : G.Path u v)
- : ∃ w : V, ∃ Q : G.Walk w u, IsPath (Walk.append Q P.1) ∧ G.neighborFinset w ⊆ (Walk.append Q P.1).support.toFinset := by
+ : ∃ w : V, ∃ Q : G.Walk w u, IsPath (Q.append P.1) ∧ G.neighborFinset w ⊆ (Q.append P.1).support.toFinset := by
replace ⟨P, hP⟩ := P
induction hn : Fintype.card V - P.support.length generalizing u P
@@ -222,46 +330,44 @@ noncomputable def extend_path_maximally {u v : V} (P : G.Path u v)
simp only [P'] at hQ'
assumption
-
theorem brooks'
(k : ℕ) (k_ge_3 : k ≥ 3)
(maxDeg_le_k : G.maxDegree ≤ k)
(no_max_clique : CliqueFree G (k + 1))
: Colorable G k := by
induction hn : Fintype.card V using Nat.strong_induction_on generalizing V G
- case h n ih _ _ =>
- by_cases h : n ≤ k
+ case h n ih _ =>
+ by_cases hnk : n ≤ k
· have n_colorable := G.colorable_of_fintype
rw [hn] at n_colorable
- exact Colorable.mono h n_colorable
+ exact Colorable.mono hnk n_colorable
· by_cases k_reg : G.IsRegularOfDegree k
-- Assume G is not k-regular.
case neg =>
simp [IsRegularOfDegree] at k_reg
+ -- x is a vertex of degree strictly less than k
have ⟨x, hx⟩ := k_reg
let S : Set V := Set.univ \ {x}
let G' := G.induce S
- -- Apply induction
- have S_maxDeg_le_k : G'.maxDegree ≤ k := sorry -- induce_maxDegree_mono G S
+ -- Color every vertex except x by induction
+ have S_maxDeg_le_k : G'.maxDegree ≤ k := sorry -- Nat.le_trans (induce_maxDegree_mono S) maxDeg_le_k
have S_no_max_clique : G'.CliqueFree (k + 1) := CliqueFree.comap (Embedding.induce S) no_max_clique
have S_card : Fintype.card (↑S) = n - 1 := by
simp only [S, ←Set.toFinset_card, Set.toFinset_diff, Set.toFinset_univ, Set.toFinset_singleton]
have fact := Finset.card_inter_add_card_sdiff Finset.univ {x}
simp [hn] at fact
omega
- have fact : n - 1 < n := by omega
- have S_colorable : (G.induce S).Colorable k := ih (n - 1) fact (G.induce S) S_maxDeg_le_k S_no_max_clique S_card
+ have S_colorable : (G.induce S).Colorable k := ih (n - 1) (by omega) S_maxDeg_le_k S_no_max_clique S_card
- replace hx : G.degree x < k := by
- have hx' : G.degree x ≤ k := Nat.le_trans (G.degree_le_maxDegree x) maxDeg_le_k
- omega
+ replace hx : G.degree x < k := Ne.lt_of_le hx (Nat.le_trans (G.degree_le_maxDegree x) maxDeg_le_k)
- have G_colorable := extend_coloring'' G S S_colorable x hx
+ -- We can also color x since it has degree < k
+ have ⟨_, G_colorable, _⟩ := extend_coloring_of_degree_lt S S_colorable.some x hx
have fact : S ∪ {x} = Set.univ := by simp only [Set.union_singleton,
Set.insert_diff_singleton, Set.mem_univ, Set.insert_eq_of_mem, S]
rw [fact] at G_colorable
- exact Colorable.of_embedding (G.induceUnivIso.symm.toEmbedding) G_colorable
+ exact Colorable.of_embedding (G.induceUnivIso.symm.toEmbedding) (Nonempty.intro G_colorable)
-- Assume G is k-regular.
case pos =>
@@ -276,6 +382,7 @@ theorem brooks'
have claim : ∃ x y : V, x ≠ y ∧ G.Adj v x ∧ G.Adj v y ∧ ¬G.Adj x y := by
by_contra wrong
apply no_max_clique
+ -- If not, v and its neighbors would form a clique on k+1 vertices.
case t => exact (G.neighborSet v ∪ {v}).toFinset
case a =>
apply IsNClique.mk
@@ -301,6 +408,239 @@ theorem brooks'
exact G.adj_symm hx
· simp at wrong
exact wrong x y x_ne_y hx hy
+ have ⟨x, y, x_ne_y, v_adj_x, v_adj_y, x_nadj_y⟩ := claim
+
+ -- P is the path x → v → y
+ let P : G.Walk x y := Walk.cons (G.adj_symm v_adj_x) (Walk.cons v_adj_y nil)
+ have hP : IsPath P := by
+ apply IsPath.cons
+ · simp only [cons_isPath_iff, isPath_iff_eq_nil, support_nil, mem_cons, not_mem_nil,
+ or_false, true_and]
+ by_contra v_eq_y
+ rw [v_eq_y] at v_adj_y
+ exact G.irrefl v_adj_y
+ · simp only [support_cons, support_nil, mem_cons, not_mem_nil, or_false, not_or]
+ apply And.intro
+ · by_contra x_eq_v
+ rw [x_eq_v] at v_adj_x
+ exact G.irrefl v_adj_x
+ · assumption
+
+ -- Extend P maximally to the front by a path Q from w to x
+ have ⟨w, Q, hQP, hw⟩ := extend_path_maximally ⟨P, hP⟩
+ have hQ : IsPath Q := IsPath.of_append_left hQP
+ simp only [isPath_def, Walk.support_append, List.nodup_append] at hQP
+ replace hQP := hQP.right.right
+ simp only at hw
+
+ by_cases h : (Q.append P).support.toFinset = Finset.univ
+
+ -- Case 1: Q.append P visits every vertex of G
+ case pos =>
+ -- Since G is k-regular with k ≥ 3, v has another neighbor z not equal to x or y
+ have existsThirdNeighbor : (G.neighborFinset v \ {x, y}).Nonempty := by
+ apply Finset.card_pos.mp
+ calc
+ (G.neighborFinset v \ {x, y}).card ≥ (G.neighborFinset v).card - Finset.card {x, y} := Finset.le_card_sdiff {x, y} (G.neighborFinset v)
+ _ = k - Finset.card {x, y} := by simp only [card_neighborFinset_eq_degree, k_reg v]
+ _ > 0 := by
+ have fact : Finset.card {x, y} ≤ 2 := Finset.card_le_two
+ omega -- recall that k ≥ 3
+ have ⟨z, hz⟩ := existsThirdNeighbor
+ simp only [Finset.mem_sdiff, mem_neighborFinset, Finset.mem_insert, Finset.mem_singleton,
+ not_or] at hz
+ have ⟨v_adj_z, z_ne_x, z_ne_y⟩ := hz
+
+ -- By definition z is not on P
+ have z_not_on_P : z ∉ P.support := by
+ simp only [P, support_cons, support_nil, mem_cons, z_ne_x, z_ne_y, not_mem_nil, or_self,
+ or_false, false_or]
+ by_contra z_eq_v
+ simp only [z_eq_v, SimpleGraph.irrefl] at v_adj_z
+
+ -- By assumption, z must lie on Q then
+ have z_on_Q : z ∈ Q.support := by
+ have obv : z ∈ Finset.univ := Finset.mem_univ z
+ simp only [←h, mem_toFinset, mem_support_append_iff, z_not_on_P, or_false] at obv
+ assumption
+
+ -- Split the path Q at z
+ obtain ⟨⟨Q₁, hQ₁⟩, ⟨Q₂, hQ₂⟩, happ⟩ := Path.split ⟨Q, hQ⟩ z z_on_Q
+ simp only at happ
+
+ -- Start by giving x and y the same color
+ let C₁ : Coloring (G.induce {x, y}) (Fin k) := by
+ apply Coloring.mk
+ case color =>
+ exact fun _ => Fin.mk 0 (by omega)
+ case valid =>
+ rintro ⟨a, ha⟩ ⟨b, hb⟩ adj _
+ by_cases hab : a = b
+ · simp only [hab] at adj
+ exact G.irrefl adj
+ · simp at ha hb adj
+ cases ha with
+ | inl a_eq_x =>
+ rw [a_eq_x, Eq.comm] at hab
+ have b_eq_y := Or.resolve_left hb hab
+ rw [a_eq_x, b_eq_y] at adj
+ contradiction
+ | inr a_eq_y =>
+ rw [a_eq_y, Eq.comm] at hab
+ have b_eq_x := Or.resolve_right hb hab
+ rw [a_eq_y, b_eq_x, G.adj_comm] at adj
+ contradiction
+
+ -- u is the vertex on Q next to x
+ let u := Q₂.penultimate
+ have u_adj_x : G.Adj u x := Walk.adj_penultimate (Walk.not_nil_of_ne z_ne_x)
+
+ -- We will color the paths R₁ and R₂
+ let R₁ : G.Walk z u := Q₂.dropLast
+ let R₂ : G.Walk v w := Walk.cons v_adj_z Q₁.reverse
+
+ have v_not_on_Q : v ∉ Q.support := by
+ have v_on_P_tail : v ∈ P.support.tail := by simp [P]
+ exact List.disjoint_symm hQP v_on_P_tail
+ have v_not_on_Q₁_rev : v ∉ Q₁.reverse.support := by
+ simp [happ] at v_not_on_Q
+ simp only [Walk.support_reverse, List.mem_reverse]
+ exact v_not_on_Q.1
+ have v_not_on_Q₂ : v ∉ Q₂.support := by
+ simp [happ] at v_not_on_Q
+ exact v_not_on_Q.2
+
+ have hR₁ : IsPath R₁ := by
+ have obv : R₁.concat u_adj_x = Q₂ := by simp only [concat_dropLast, R₁]
+ simp [←obv, Walk.concat_eq_append] at hQ₂
+ exact IsPath.of_append_left hQ₂
+ have hR₂ : IsPath R₂ := IsPath.cons ((isPath_reverse_iff Q₁).mpr hQ₁) v_not_on_Q₁_rev
+
+ have R₁_support : Q₂.support = R₁.support.concat x := by
+ rw [←(Walk.support_concat R₁ u_adj_x)]
+ simp only [concat_dropLast, R₁]
+
+ have x_not_on_R₁ : x ∉ R₁.support := by
+ simp [isPath_def, R₁_support] at hQ₂
+ simpa using List.disjoint_of_nodup_append hQ₂
+
+ have Q₁_disj_Q₂_tail : Q₁.support.Disjoint Q₂.support.tail := by
+ simp [isPath_def, happ, Walk.support_append] at hQ
+ exact List.disjoint_of_nodup_append hQ
+
+ have x_not_on_Q₁ : x ∉ Q₁.support := by
+ have Q₂_not_nil : ¬Q₂.Nil := Walk.not_nil_of_ne z_ne_x
+ exact Q₁_disj_Q₂_tail.symm (Walk.end_mem_tail_support Q₂_not_nil)
+
+ have y_not_on_Q : y ∉ Q.support := by
+ have y_on_P_tail : y ∈ P.support.tail := by simp [P]
+ exact List.disjoint_symm hQP y_on_P_tail
+
+ simp only [happ, mem_support_append_iff, not_or] at y_not_on_Q
+ have ⟨y_not_on_Q₁, y_not_on_Q₂⟩ := y_not_on_Q
+
+ have y_not_on_R₁ : y ∉ R₁.support := by
+ simp only [R₁_support, List.concat_eq_append, mem_append, mem_cons, not_mem_nil,
+ or_false, not_or] at y_not_on_Q₂
+ exact y_not_on_Q₂.left
+
+ have v_not_on_R₁ : v ∉ R₁.support := by
+ simp only [R₁_support, List.concat_eq_append, mem_append, mem_cons, not_mem_nil,
+ or_false, not_or] at v_not_on_Q₂
+ exact v_not_on_Q₂.left
+
+ have xy_not_on_R₁ : ∀ t ∈ R₁.support, t ∉ ({x, y} : Set V) := by
+ intro t ht
+ simp only [Set.mem_insert_iff, Set.mem_singleton_iff, not_or]
+ apply And.intro
+ · intro hx
+ rw [hx] at ht
+ contradiction
+ · intro hy
+ rw [hy] at ht
+ contradiction
+
+ -- Color the path R₁.
+ let C₂ := color_path k maxDeg_le_k ⟨R₁, hR₁⟩ {x, y} xy_not_on_R₁ C₁
+ simp only at C₂
+
+ have R₂_not_colored_by_C₂ : ∀ t ∈ R₂.support, t ∉ (({x, y} : Set V) ∪ R₁.support.tail.toFinset) := by
+ intro t ht
+ simp only [support_cons, support_reverse, mem_cons, mem_reverse, R₂] at ht
+
+ simp only [coe_toFinset, Set.mem_union, Set.mem_insert_iff, Set.mem_singleton_iff,
+ Set.mem_setOf_eq, not_or]
+
+ cases ht with
+ | inl t_eq_v =>
+ rw [t_eq_v]
+ use ⟨G.ne_of_adj v_adj_x, G.ne_of_adj v_adj_y⟩
+ intro hv
+ exact v_not_on_R₁ (List.mem_of_mem_tail hv)
+ | inr t_on_Q₁ =>
+ constructor
+ · constructor
+ · intro hx
+ rw [hx] at t_on_Q₁
+ contradiction
+ · intro hy
+ rw [hy] at t_on_Q₁
+ contradiction
+ · intro ht
+ have t_not_on_Q₂_tail := Q₁_disj_Q₂_tail t_on_Q₁
+ simp only [R₁_support, List.concat_eq_append, ne_eq, support_ne_nil,
+ not_false_eq_true, tail_append_of_ne_nil, mem_append, mem_cons, not_mem_nil,
+ or_false, imp_false, not_or] at t_not_on_Q₂_tail
+ exact t_not_on_Q₂_tail.left ht
+
+ -- Now color the path R₂.
+ let C₃ := color_path k maxDeg_le_k ⟨R₂, hR₂⟩ ({x, y} ∪ R₁.support.tail.toFinset) R₂_not_colored_by_C₂ C₂.coloring
+ replace C₃ := Coloring.extension_trans C₁ C₂ C₃
+ simp only at C₃
+
+ -- C₃ colors the set S, which contains every vertex of G except v.
+ -- We can also color v because v has two neighbors of the same color
+ -- (namely x and y).
+ let S : Set V := {x, y} ∪ R₁.support.tail.toFinset ∪ R₂.support.tail.toFinset
+ have x_in_xy : x ∈ ({x, y} : Set V) := by simp only [Set.mem_insert_iff, Set.mem_singleton_iff, true_or]
+ have y_in_xy : y ∈ ({x, y} : Set V) := by simp only [Set.mem_insert_iff, Set.mem_singleton_iff, or_true]
+ have x_in_S : x ∈ S := by simp only [S, x_in_xy, Set.mem_union, true_or]
+ have y_in_S : y ∈ S := by simp only [S, y_in_xy, Set.mem_union, true_or]
+ have x_ne_y : (⟨x, x_in_S⟩ : S) ≠ ⟨y, y_in_S⟩ := by
+ intro wrong
+ simp only [Subtype.mk.injEq] at wrong
+ contradiction
+ have x_y_same_color : C₃.coloring ⟨x, x_in_S⟩ = C₃.coloring ⟨y, y_in_S⟩ := by
+ calc
+ C₃.coloring ⟨x, x_in_S⟩ = C₁ ⟨x, x_in_xy⟩ := by simp only [←C₃.compatible, Set.restrict₂]
+ _ = C₁ ⟨y, y_in_xy⟩ := rfl
+ _ = C₃.coloring ⟨y, y_in_S⟩ := by simp only [←C₃.compatible, Set.restrict₂]
+
+ have deg_v_le_k := Nat.le_trans (G.degree_le_maxDegree v) maxDeg_le_k
+ let C₄ := extend_coloring_of_two_neighbors_eq_color S C₃.coloring v deg_v_le_k ⟨x, x_in_S⟩ ⟨y, y_in_S⟩ v_adj_x v_adj_y x_ne_y x_y_same_color
+
+ -- Now we just need to check that the union of all these paths is indeed all of V.
+ have C₄_colors_G : S ∪ {v} = Set.univ := by
+ rw [Set.union_comm]
+ apply Set.toFinset_inj.mp
+ simp only [S, Set.toFinset_univ, Set.toFinset_union, Finset.toFinset_coe, Set.toFinset_singleton, Set.toFinset_insert]
+ simp only [Finset.insert_union, support_cons, support_reverse, List.tail_cons,
+ toFinset_reverse, Finset.union_assoc, Finset.union_insert, R₂]
+ simp only [happ, support_append, R₁_support, List.concat_eq_append, ne_eq,
+ support_ne_nil, not_false_eq_true, tail_append_of_ne_nil, support_cons, support_nil,
+ List.tail_cons, List.append_assoc, List.cons_append, List.nil_append, toFinset_append,
+ toFinset_cons, toFinset_nil, insert_emptyc_eq, Finset.union_insert, P] at h
+ rw [←h]
+ congr
+ rw [←Finset.insert_eq]
+ congr 1
+ rw [←Finset.union_assoc, Finset.union_comm]
+ conv =>
+ lhs
+ arg 2
+ rw [Finset.union_comm]
+
+ rw [C₄_colors_G] at C₄
+ exact Colorable.of_embedding G.induceUnivIso.symm.toEmbedding (Nonempty.intro C₄.coloring)
- have ⟨x, y, x_ne_y, hx, hy, x_nadj_y⟩ := claim
- sorry
+ case neg => sorry