Skip to content
Browse chapters
Imports

Edges used by an ordered Hamiltonian cycle

CycleLinked vertices u v forgets the orientation of the certificate list: v is either the cyclic successor or predecessor of u. This proof-free relation is symmetric on duplicate-free lists and lets the finite gadget argument reason about undirected cycle edges.

namespace CLRS.Chapter34.HamiltonianCycleReductiondef CycleLinked (vertices : List Nat) (u v : Nat) : Prop := ∃ hu : u ∈ vertices, vertices.next u hu = v ∨ vertices.prev u hu = vtheorem cycleLinked_iff {vertices : List Nat} {u v : Nat} (hu : u ∈ vertices) : CycleLinked vertices u v ↔ vertices.next u hu = v ∨ vertices.prev u hu = v := by simp only [CycleLinked] constructor · rintro ⟨_, h⟩ simpa using h · exact fun h => ⟨hu, h⟩theorem cycleLinked_symm {vertices : List Nat} (hnodup : vertices.Nodup) {u v : Nat} (hlinked : CycleLinked vertices u v) : CycleLinked vertices v u := by rcases hlinked with ⟨hu, hnext | hprev⟩ · subst v refine ⟨List.next_mem vertices u hu, Or.inr ?_⟩ exact List.prev_next vertices hnodup u hu · subst v refine ⟨List.prev_mem vertices u hu, Or.inl ?_⟩ exact List.next_prev vertices hnodup u hu theorem adj_of_cycleLinked {I : CliqueInstance} {vertices : List Nat} (hnodup : vertices.Nodup) (hcycle : I.CycleAdjacent vertices) {u v : Nat} (hlinked : CycleLinked vertices u v) : I.Adj u v := by rcases hlinked with ⟨hu, hnext | hprev⟩ · rw [← hnext] exact I.adj_next_of_cycleAdjacent hnodup hcycle hu · rw [← hprev] exact I.adj_prev_of_cycleAdjacent hnodup hcycle hutheorem cycleLinked_next {vertices : List Nat} {u : Nat} (hu : u ∈ vertices) : CycleLinked vertices u (vertices.next u hu) := ⟨hu, Or.inl rfl⟩theorem cycleLinked_prev {vertices : List Nat} {u : Nat} (hu : u ∈ vertices) : CycleLinked vertices u (vertices.prev u hu) := ⟨hu, Or.inr rfl⟩ theorem exists_cycleLinked_ne_of_cycleLinked {vertices : List Nat} (hnodup : vertices.Nodup) (hlength : 3 ≤ vertices.length) {u first : Nat} (hu : u ∈ vertices) (hfirst : CycleLinked vertices u first) : ∃ second, CycleLinked vertices u second ∧ second ≠ first := by have hne := CliqueInstance.next_ne_prev_of_three_le_length hnodup hlength hu rw [cycleLinked_iff hu] at hfirst rcases hfirst with hnext | hprev · refine ⟨vertices.prev u hu, cycleLinked_prev hu, ?_⟩ intro heq exact hne (hnext.trans heq.symm) · refine ⟨vertices.next u hu, cycleLinked_next hu, ?_⟩ intro heq exact hne (heq.trans hprev.symm)theorem cycleLinked_pair_of_neighbors {vertices : List Nat} {u first second : Nat} (hu : u ∈ vertices) (hneighbors : (vertices.next u hu = first ∧ vertices.prev u hu = second) ∨ (vertices.next u hu = second ∧ vertices.prev u hu = first)) : CycleLinked vertices u first ∧ CycleLinked vertices u second := by rcases hneighbors with ⟨hnext, hprev⟩ | ⟨hnext, hprev⟩ · exact ⟨⟨hu, Or.inl hnext⟩, ⟨hu, Or.inr hprev⟩⟩ · exact ⟨⟨hu, Or.inr hprev⟩, ⟨hu, Or.inl hnext⟩⟩

Once two distinct cyclic neighbors are known, no third distinct vertex can also be a cyclic neighbor.

theorem not_cycleLinked_of_two {vertices : List Nat} {u first second third : Nat} (hu : u ∈ vertices) (hfirst : CycleLinked vertices u first) (hsecond : CycleLinked vertices u second) (hfirstSecond : first ≠ second) (hthirdFirst : third ≠ first) (hthirdSecond : third ≠ second) : ¬ CycleLinked vertices u third := by rw [cycleLinked_iff hu] at hfirst hsecond ⊢ rcases hfirst with hnextFirst | hprevFirst · rcases hsecond with hnextSecond | hprevSecond · exact (hfirstSecond (hnextFirst.symm.trans hnextSecond)).elim · rintro (hnextThird | hprevThird) · exact hthirdFirst (hnextThird.symm.trans hnextFirst) · exact hthirdSecond (hprevThird.symm.trans hprevSecond) · rcases hsecond with hnextSecond | hprevSecond · rintro (hnextThird | hprevThird) · exact hthirdSecond (hnextThird.symm.trans hnextSecond) · exact hthirdFirst (hprevThird.symm.trans hprevFirst) · exact (hfirstSecond (hprevFirst.symm.trans hprevSecond)).elim
theorem eq_or_eq_of_cycleLinked_two {vertices : List Nat} {u first second third : Nat} (hu : u ∈ vertices) (hfirst : CycleLinked vertices u first) (hsecond : CycleLinked vertices u second) (hfirstSecond : first ≠ second) (hthird : CycleLinked vertices u third) : third = first ∨ third = second := by by_cases hthirdFirst : third = first · exact Or.inl hthirdFirst by_cases hthirdSecond : third = second · exact Or.inr hthirdSecond exact (not_cycleLinked_of_two hu hfirst hsecond hfirstSecond hthirdFirst hthirdSecond hthird).elim

At a three-neighbor graph vertex, once the cycle is known to use the first neighbor, it must use at least one of the other two.

theorem cycleLinked_other_of_adj_iff_three {I : CliqueInstance} {vertices : List Nat} (hnodup : vertices.Nodup) (hlength : 3 ≤ vertices.length) (hcycle : I.CycleAdjacent vertices) {u first second third : Nat} (hu : u ∈ vertices) (hadj : ∀ vertex, I.Adj u vertex ↔ vertex = first ∨ vertex = second ∨ vertex = third) (hfirst : CycleLinked vertices u first) : CycleLinked vertices u second ∨ CycleLinked vertices u third := by have hne := CliqueInstance.next_ne_prev_of_three_le_length hnodup hlength hu rw [cycleLinked_iff hu] at hfirst rcases hfirst with hnextFirst | hprevFirst · have hprevAdj := (hadj _).1 (I.adj_prev_of_cycleAdjacent hnodup hcycle hu) rcases hprevAdj with hprev | hprev | hprev · exact (hne (hnextFirst.trans hprev.symm)).elim · exact Or.inl ⟨hu, Or.inr hprev⟩ · exact Or.inr ⟨hu, Or.inr hprev⟩ · have hnextAdj := (hadj _).1 (I.adj_next_of_cycleAdjacent hnodup hcycle hu) rcases hnextAdj with hnext | hnext | hnext · exact (hne (hnext.trans hprevFirst.symm)).elim · exact Or.inl ⟨hu, Or.inl hnext⟩ · exact Or.inr ⟨hu, Or.inl hnext⟩
end CLRS.Chapter34.HamiltonianCycleReduction