Traveling salesperson problem
DefinitionHamiltonian-cycle to TSP converter#✓fully proved
The Hamiltonian-cycle to TSP converter takes a Boolean array \(x\) and, starting from the empty array, scans \(x\) from left to right and appends the negation of each cell, charging one time unit before and one time unit after each append (one read and one write per cell). It returns the resulting array of negated cells together with the total time charged.
def hamiltonianCycleToTsp (x : Array Bool) : TimeM Nat (Array Bool) :=
x.foldlM (fun out bit => do
TimeM.tick (1 : Nat)
let out := out.push (!bit)
TimeM.tick (1 : Nat)
pure out) #[]
Used by 7
TheoremThe Hamiltonian-cycle to TSP converter preserves length#✓fully proved
For every Boolean array \(x\), the array output by the Hamiltonian-cycle to TSP converter on \(x\) has the same length as \(x\).
No assumption that \(x\) encodes a graph is needed.
theorem hamiltonianCycleToTsp_size (x : Array Bool) :
(hamiltonianCycleToTsp x).ret.size = x.size
def hamiltonianCycleToTsp (x : Array Bool) : TimeM Nat (Array Bool) :=
x.foldlM (fun out bit => do
TimeM.tick (1 : Nat)
let out := out.push (!bit)
TimeM.tick (1 : Nat)
pure out) #[]
CSLibExt/Algorithms/Lean/Graph/HamiltonianCycleToTsp.lean:35
Uses 1
TheoremThe Hamiltonian-cycle to TSP converter negates every cell#✓fully proved
For every Boolean array \(x\) and every index \(k\), the array output by the Hamiltonian-cycle to TSP converter on \(x\) has a cell at index \(k\) exactly when \(x\) does, and that cell is the negation of the cell of \(x\) at index \(k\).
theorem hamiltonianCycleToTsp_getElem? (x : Array Bool) (k : Nat) :
(hamiltonianCycleToTsp x).ret[k]? = x[k]?.map Bool.not
def hamiltonianCycleToTsp (x : Array Bool) : TimeM Nat (Array Bool) :=
x.foldlM (fun out bit => do
TimeM.tick (1 : Nat)
let out := out.push (!bit)
TimeM.tick (1 : Nat)
pure out) #[]
CSLibExt/Algorithms/Lean/Graph/HamiltonianCycleToTsp.lean:35
Uses 1 · Used by 1
TheoremRunning time of the Hamiltonian-cycle to TSP converter#✓fully proved
For every Boolean array \(x\), the time charged by the Hamiltonian-cycle to TSP converter on \(x\) is \(2m\), where \(m\) is the length of \(x\): one unit for reading and one unit for writing each cell.
theorem hamiltonianCycleToTsp_time (x : Array Bool) :
(hamiltonianCycleToTsp x).time = 2 * x.size
def hamiltonianCycleToTsp (x : Array Bool) : TimeM Nat (Array Bool) :=
x.foldlM (fun out bit => do
TimeM.tick (1 : Nat)
let out := out.push (!bit)
TimeM.tick (1 : Nat)
pure out) #[]
CSLibExt/Algorithms/Lean/Graph/HamiltonianCycleToTsp.lean:35
Uses 1
TheoremCosts produced by the Hamiltonian-cycle to TSP converter#✓fully proved
Let \(G\) be a simple graph on the vertex set \(\{0, \dots, n-1\}\), let \(x\) be a Boolean array of length \(n^2\) such that for all \(i, j < n\) the cell of \(x\) at index \(in + j\) exists and is true exactly when \(i\) and \(j\) are adjacent in \(G\), and let \(y\) be the array output by the Hamiltonian-cycle to TSP converter on \(x\), with a Boolean cell read as \(1\) if true and \(0\) if false. Then for all \(i, j < n\) the cell of \(y\) at index \(in + j\) exists and equals \(0\) if \(i\) and \(j\) are adjacent in \(G\) and \(1\) otherwise; for every \(i < n\) the cell of \(y\) at index \(in + i\) exists and equals \(1\); and for all \(i, j < n\) the cells of \(y\) at indices \(in + j\) and \(jn + i\) are equal.
theorem hamiltonianCycleToTsp_costs (x : Array Bool) (n : Nat)
(G : SimpleGraph (Fin n)) [DecidableRel G.Adj]
(_hsize : x.size = n * n)
(henc : ∀ i j : Fin n, x[i.val * n + j.val]? = some (decide (G.Adj i j))) :
(∀ i j : Fin n,
((hamiltonianCycleToTsp x).ret[i.val * n + j.val]?).map Bool.toNat =
some (if G.Adj i j then 0 else 1)) ∧
(∀ i : Fin n,
((hamiltonianCycleToTsp x).ret[i.val * n + i.val]?).map Bool.toNat = some 1) ∧
(∀ i j : Fin n,
(hamiltonianCycleToTsp x).ret[i.val * n + j.val]? =
(hamiltonianCycleToTsp x).ret[j.val * n + i.val]?)
def hamiltonianCycleToTsp (x : Array Bool) : TimeM Nat (Array Bool) :=
x.foldlM (fun out bit => do
TimeM.tick (1 : Nat)
let out := out.push (!bit)
TimeM.tick (1 : Nat)
pure out) #[]
CSLibExt/Algorithms/Lean/Graph/HamiltonianCycleToTsp.lean:35
Uses 2 · Used by 2
TheoremHamiltonian cycles of the source graph give zero-cost tours#✓fully proved
Let \(G\) be a simple graph on the vertex set \(\{0, \dots, n-1\}\), let \(x\) be a Boolean array of length \(n^2\) such that for all \(i, j < n\) the cell of \(x\) at index \(in + j\) exists and is true exactly when \(i\) and \(j\) are adjacent in \(G\), and let \(y\) be the array output by the Hamiltonian-cycle to TSP converter on \(x\), with a Boolean cell read as \(1\) if true and \(0\) if false. Let \(p\) be a Hamiltonian cycle in \(G\) based at a vertex \(a\), and let \(p'\) be \(p\) regarded as a closed walk in the complete graph on \(\{0, \dots, n-1\}\). Then \(p'\) is a Hamiltonian cycle, \(p'\) visits the same sequence of vertices as \(p\), and for every directed edge \((u, v)\) traversed by \(p'\) the cell of \(y\) at index \(un + v\) exists, and the sum of these cells over the directed edges of \(p'\) is \(0\).
theorem hamiltonianCycleToTsp_forward (x : Array Bool) (n : Nat)
(G : SimpleGraph (Fin n)) [DecidableRel G.Adj]
(hsize : x.size = n * n)
(henc : ∀ i j : Fin n, x[i.val * n + j.val]? = some (decide (G.Adj i j)))
(a : Fin n) (p : G.Walk a a) (hp : p.IsHamiltonianCycle) :
(p.mapLe (show G ≤ SimpleGraph.completeGraph (Fin n) from le_top)).IsHamiltonianCycle ∧
(p.mapLe (show G ≤ SimpleGraph.completeGraph (Fin n) from le_top)).support = p.support ∧
∃ costs : List Nat,
(p.mapLe (show G ≤ SimpleGraph.completeGraph (Fin n) from le_top)).darts.mapM
(fun d => ((hamiltonianCycleToTsp x).ret[d.fst.val * n + d.snd.val]?).map
Bool.toNat) = some costs ∧ costs.sum = 0
def hamiltonianCycleToTsp (x : Array Bool) : TimeM Nat (Array Bool) :=
x.foldlM (fun out bit => do
TimeM.tick (1 : Nat)
let out := out.push (!bit)
TimeM.tick (1 : Nat)
pure out) #[]
CSLibExt/Algorithms/Lean/Graph/HamiltonianCycleToTsp.lean:35
Uses 2 · Used by 1
TheoremTours of cost zero give Hamiltonian cycles of the source graph#✓fully proved
Let \(G\) be a simple graph on the vertex set \(\{0, \dots, n-1\}\), let \(x\) be a Boolean array of length \(n^2\) such that for all \(i, j < n\) the cell of \(x\) at index \(in + j\) exists and is true exactly when \(i\) and \(j\) are adjacent in \(G\), and let \(y\) be the array output by the Hamiltonian-cycle to TSP converter on \(x\), with a Boolean cell read as \(1\) if true and \(0\) if false. Let \(p\) be a Hamiltonian cycle based at a vertex \(a\) in the complete graph on \(\{0, \dots, n-1\}\) such that for every directed edge \((u, v)\) traversed by \(p\) the cell of \(y\) at index \(un + v\) exists and the sum of these cells over the directed edges of \(p\) is at most \(0\). Then there is a Hamiltonian cycle \(q\) in \(G\) based at \(a\) that visits the same sequence of vertices as \(p\).
theorem hamiltonianCycleToTsp_reverse (x : Array Bool) (n : Nat)
(G : SimpleGraph (Fin n)) [DecidableRel G.Adj]
(hsize : x.size = n * n)
(henc : ∀ i j : Fin n, x[i.val * n + j.val]? = some (decide (G.Adj i j)))
(a : Fin n) (p : (SimpleGraph.completeGraph (Fin n)).Walk a a)
(hp : p.IsHamiltonianCycle)
(hcost : ∃ costs : List Nat,
p.darts.mapM
(fun d => ((hamiltonianCycleToTsp x).ret[d.fst.val * n + d.snd.val]?).map
Bool.toNat) = some costs ∧ costs.sum ≤ 0) :
∃ q : G.Walk a a, q.IsHamiltonianCycle ∧ q.support = p.support
def hamiltonianCycleToTsp (x : Array Bool) : TimeM Nat (Array Bool) :=
x.foldlM (fun out bit => do
TimeM.tick (1 : Nat)
let out := out.push (!bit)
TimeM.tick (1 : Nat)
pure out) #[]
CSLibExt/Algorithms/Lean/Graph/HamiltonianCycleToTsp.lean:35
Uses 2 · Used by 1
TheoremCorrectness of the Hamiltonian-cycle to TSP reduction#✓fully proved
Let \(G\) be a simple graph on the vertex set \(V = \{0, \dots, n-1\}\), let \(x\) be a Boolean array of length \(n^2\) such that for all \(i, j < n\) the cell of \(x\) at index \(in + j\) exists and is true exactly when \(i\) and \(j\) are adjacent in \(G\), and let \(y\) be the array output by the Hamiltonian-cycle to TSP converter on \(x\), with a Boolean cell read as \(1\) if true and \(0\) if false. Then \(G\) has a Hamiltonian cycle if and only if the complete graph on \(V\) has a Hamiltonian cycle \(p\) such that for every directed edge \((u, v)\) traversed by \(p\) the cell of \(y\) at index \(un + v\) exists and the sum of these cells over the directed edges of \(p\) is at most \(0\).
theorem hamiltonianCycleToTsp_iff (x : Array Bool) (n : Nat)
(G : SimpleGraph (Fin n)) [DecidableRel G.Adj]
(hsize : x.size = n * n)
(henc : ∀ i j : Fin n, x[i.val * n + j.val]? = some (decide (G.Adj i j))) :
((∃ (a : Fin n) (p : G.Walk a a), p.IsHamiltonianCycle) ↔
∃ (a : Fin n) (p : (SimpleGraph.completeGraph (Fin n)).Walk a a),
p.IsHamiltonianCycle ∧ ∃ costs : List Nat,
p.darts.mapM
(fun d => ((hamiltonianCycleToTsp x).ret[d.fst.val * n + d.snd.val]?).map
Bool.toNat) = some costs ∧ costs.sum ≤ 0)
def hamiltonianCycleToTsp (x : Array Bool) : TimeM Nat (Array Bool) :=
x.foldlM (fun out bit => do
TimeM.tick (1 : Nat)
let out := out.push (!bit)
TimeM.tick (1 : Nat)
pure out) #[]
CSLibExt/Algorithms/Lean/Graph/HamiltonianCycleToTsp.lean:35
AbbreviationSymmetric TSP instances#✓fully proved
An instance of the symmetric traveling salesperson problem is a triple \((n, w, B)\) of a natural number \(n\), the number of cities, a weight matrix \(w\) given as a finite list of rows, each a finite list of natural numbers, and a natural number \(B\), the bound.
The type itself does not require \(w\) to be an \(n \times n\) symmetric matrix with zero diagonal.
DefinitionLength of a tour in the symmetric TSP#✓fully proved
Let \(w\) be a matrix of natural numbers given as a list of rows, where an entry \(w_{a,b}\) outside the list (no row \(a\), or row \(a\) too short) is read as \(0\), and rows and columns are numbered from \(0\). The length of a list \((t_0, \dots, t_{k-1})\) of natural numbers with respect to \(w\) is \(\sum_{j\lt k} w_{t_j, t_{(j+1) \bmod k}}\), the total weight of the edges along the cycle \(t_0, t_1, \dots, t_{k-1}, t_0\), including the return edge; the empty list has length \(0\).
def TourLength (w : List (List ℕ)) (tour : List ℕ) : ℕ :=
((List.range tour.length).map (fun j =>
(w.getD (tour.getD j 0) []).getD (tour.getD ((j + 1) % tour.length) 0) 0)).sum
Used by 1
DefinitionWell-formed symmetric TSP instances#✓fully proved
A symmetric TSP instance \((n, w, B)\) is well formed when \(n > 0\), the weight matrix \(w\) has exactly \(n\) rows and each row has exactly \(n\) entries, \(w\) is symmetric, that is \(w_{a,b} = w_{b,a}\) for all \(a, b < n\), and \(w\) has zero diagonal, that is \(w_{a,a} = 0\) for all \(a < n\). Rows and columns are numbered from \(0\).
def WellFormed (i : TspInstance) : Prop :=
0 < i.1 ∧ i.2.1.length = i.1 ∧ (∀ row ∈ i.2.1, row.length = i.1) ∧
(∀ a < i.1, ∀ b < i.1, (i.2.1.getD a []).getD b 0 = (i.2.1.getD b []).getD a 0) ∧
∀ a < i.1, (i.2.1.getD a []).getD a 0 = 0
abbrev TspInstance := ℕ × List (List ℕ) × ℕ
WantedExt/Complexity/NPComplete/TspWanted.lean:47
Uses 1 · Used by 1
DefinitionFeasible symmetric TSP instances#✓fully proved
A symmetric TSP instance \((n, w, B)\) is feasible when there is a list of \(n\) pairwise distinct natural numbers containing every \(v < n\), that is, an ordering of the cities \(0, 1, \dots, n-1\) visiting each exactly once, whose tour length with respect to \(w\) (the sum of the weights of consecutive edges, including the return edge) is at most \(B\).
def TspFeasible
(i : TspInstance) : Prop :=
∃ tour : List ℕ, tour.Nodup ∧ tour.length = i.1 ∧ (∀ v < i.1, v ∈ tour) ∧
TourLength i.2.1 tour ≤ i.2.2
abbrev TspInstance := ℕ × List (List ℕ) × ℕ
WantedExt/Complexity/NPComplete/TspWanted.lean:47
def TourLength (w : List (List ℕ)) (tour : List ℕ) : ℕ :=
((List.range tour.length).map (fun j =>
(w.getD (tour.getD j 0) []).getD (tour.getD ((j + 1) % tour.length) 0) 0)).sum
WantedExt/Complexity/NPComplete/TspWanted.lean:51
Uses 2 · Used by 1
DefinitionSymmetric TSP as a decision problem#✓fully proved
The symmetric traveling salesperson problem is the decision problem that accepts a bitstring \(x\) exactly when \(x\) decodes, under the canonical bitstring encoding of symmetric TSP instances, to an instance \((n, w, B)\) that is well formed and feasible. Bitstrings that fail to decode, and bitstrings that decode to instances that are not well formed, are rejected.
noncomputable def tspDec :
MetaMathlibExt.ComplexityTheory.DecisionProblem := fun x =>
match MetaMathlibExt.BitstringEncoding.bitDecode
(α := TspInstance) x with
| some i => decide (WellFormed i ∧ TspFeasible i)
| none => false
abbrev DecisionProblem := List Bool → Bool
MathlibExt/Computability/Complexity.lean:170
def bitDecode [BitstringEncoding α] (l : List Bool) : Option α := toEncoding.decode l
MathlibExt/Computability/Complexity.lean:58
abbrev TspInstance := ℕ × List (List ℕ) × ℕ
WantedExt/Complexity/NPComplete/TspWanted.lean:47
def WellFormed (i : TspInstance) : Prop :=
0 < i.1 ∧ i.2.1.length = i.1 ∧ (∀ row ∈ i.2.1, row.length = i.1) ∧
(∀ a < i.1, ∀ b < i.1, (i.2.1.getD a []).getD b 0 = (i.2.1.getD b []).getD a 0) ∧
∀ a < i.1, (i.2.1.getD a []).getD a 0 = 0
WantedExt/Complexity/NPComplete/TspWanted.lean:57
def TspFeasible
(i : TspInstance) : Prop :=
∃ tour : List ℕ, tour.Nodup ∧ tour.length = i.1 ∧ (∀ v < i.1, v ∈ tour) ∧
TourLength i.2.1 tour ≤ i.2.2
WantedExt/Complexity/NPComplete/TspWanted.lean:63
Uses 12 · Used by 1
TheoremTRAVELING SALESPERSON (SYMMETRIC) is NP-complete#●ready to prove
The symmetric traveling salesperson decision problem belongs to NP, and every decision problem in NP reduces to it by a polynomial-time many-one reduction.
public theorem_wanted tsp_npComplete :
tspDec ∈ MetaMathlibExt.ComplexityTheory.NP ∧
∀ L : MetaMathlibExt.ComplexityTheory.DecisionProblem,
L ∈ MetaMathlibExt.ComplexityTheory.NP →
Cslib.CookLevin.PolyManyOneRed L tspDec
noncomputable def tspDec :
MetaMathlibExt.ComplexityTheory.DecisionProblem := fun x =>
match MetaMathlibExt.BitstringEncoding.bitDecode
(α := TspInstance) x with
| some i => decide (WellFormed i ∧ TspFeasible i)
| none => false
WantedExt/Complexity/NPComplete/TspWanted.lean:70
def NP : DecisionComplexityClass :=
{ L | ∃ (p : Polynomial ℕ), ∃ R : (List Bool × List Bool) → Bool,
IsPolyTime R ∧
∀ x, L x ↔ ∃ w : List Bool, w.length ≤ p.eval x.length ∧ R (x, w) }
MathlibExt/Computability/Complexity.lean:200
abbrev DecisionProblem := List Bool → Bool
MathlibExt/Computability/Complexity.lean:170
def PolyManyOneRed (L₁ L₂ : MetaMathlibExt.ComplexityTheory.DecisionProblem) : Prop :=
∃ reduce : List Bool → List Bool,
MetaMathlibExt.ComplexityTheory.IsPolyTime reduce ∧ ∀ x, L₁ x = L₂ (reduce x)
CSLibExt/Computability/CookLevin.lean:396
Sources
- M. R. Garey and D. S. Johnson, Computers and Intractability (1979), TRAVELING SALESPERSON PROBLEM.
Uses 5
Loading dependency explorer…
The dependency explorer needs JavaScript and its graph data.