Closest pair of points problem
DefinitionSquared distance in the plane#βfully proved
Let \(K\) be a linearly ordered field. The squared distance between points \(p = (p_1, p_2)\) and \(q = (q_1, q_2)\) of \(K^2\) is \((p_1 - q_1)^2 + (p_2 - q_2)^2\).
def dist2 (p q : π Γ π) : π := (p.1 - q.1) ^ 2 + (p.2 - q.2) ^ 2
Used by 16
DefinitionLeast pairwise squared distance#βfully proved
Let \(K\) be a linearly ordered field, and write \(d(p, q) = (p_1 - q_1)^2 + (p_2 - q_2)^2\) for the squared distance between points \(p = (p_1, p_2)\) and \(q = (q_1, q_2)\) of \(K^2\). For a list \(c_1, \dots, c_n\) of points of \(K^2\), an element \(\delta\) of \(K\) is the least pairwise squared distance of the list when \(\delta = d(c_i, c_j)\) for some \(i < j\) and \(\delta \le d(c_i, c_j)\) for all \(i < j\).
def IsMinPairDist2 (ps : List (π Γ π)) (Ξ΄ : π) : Prop :=
(β p q, [p, q] <+ ps β§ dist2 p q = Ξ΄) β§ β p q, [p, q] <+ ps β Ξ΄ β€ dist2 p q
def dist2 (p q : π Γ π) : π := (p.1 - q.1) ^ 2 + (p.2 - q.2) ^ 2
CSLibExt/Algorithms/Lean/Geometry/ClosestPair.lean:59
Uses 1 Β· Used by 2
DefinitionLeast squared distance from a point to a list#βfully proved
Let \(K\) be a linearly ordered field, and write \(d(p, q) = (p_1 - q_1)^2 + (p_2 - q_2)^2\) for the squared distance between points \(p = (p_1, p_2)\) and \(q = (q_1, q_2)\) of \(K^2\). For a point \(p\) and a list \(c_1, \dots, c_m\) of points of \(K^2\), the least squared distance from \(p\) to the list is no value if \(m = 0\) and \(\min_{1 \le k \le m} d(p, c_k)\) otherwise. Computing it is charged one unit of cost per point of the list, \(m\) units in total.
def minDistFrom (p : π Γ π) : List (π Γ π) β TimeM β (Option π)
| [] => pure none
| q :: qs => do
β
let r β minDistFrom p qs
pure (omin (some (dist2 p q)) r)
def omin {Ξ± : Type u} [Min Ξ±] : Option Ξ± β Option Ξ± β Option Ξ±
| none, b => b
| some a, none => some a
| some a, some b => some (min a b)
CSLibExt/Algorithms/Lean/DataStructures/SparseTable.lean:59
def dist2 (p q : π Γ π) : π := (p.1 - q.1) ^ 2 + (p.2 - q.2) ^ 2
CSLibExt/Algorithms/Lean/Geometry/ClosestPair.lean:59
Uses 2 Β· Used by 5
DefinitionBrute-force closest pair#βfully proved
Let \(K\) be a field with a linear order, and write \(d(p, q) = (x - x')^2 + (y - y')^2\) for the squared distance between points \(p = (x, y)\) and \(q = (x', y')\) of \(K^2\). On a list \(c_1, \dots, c_n\) of points in \(K^2\), the brute-force scan returns no value if \(n < 2\), and otherwise returns \(\min_{i < j} d(c_i, c_j)\): for each \(i\) it computes the least squared distance from \(c_i\) to the later points \(c_{i+1}, \dots, c_n\), and takes the least of these minima. It is charged one unit of cost per squared distance computed.
def bruteMin : List (π Γ π) β TimeM β (Option π)
| [] => pure none
| p :: ps => do
let a β minDistFrom p ps
let b β bruteMin ps
pure (omin a b)
def minDistFrom (p : π Γ π) : List (π Γ π) β TimeM β (Option π)
| [] => pure none
| q :: qs => do
β
let r β minDistFrom p qs
pure (omin (some (dist2 p q)) r)
CSLibExt/Algorithms/Lean/Geometry/ClosestPair.lean:66
def omin {Ξ± : Type u} [Min Ξ±] : Option Ξ± β Option Ξ± β Option Ξ±
| none, b => b
| some a, none => some a
| some a, some b => some (min a b)
CSLibExt/Algorithms/Lean/DataStructures/SparseTable.lean:59
Uses 2 Β· Used by 5
DefinitionStrip scan from a point#βfully proved
Let \(K\) be a linearly ordered field, and write \(d(p, q) = (p_1 - q_1)^2 + (p_2 - q_2)^2\) for the squared distance between points \(p = (p_1, p_2)\) and \(q = (q_1, q_2)\) of \(K^2\). Let \(\delta \in K\), let \(p = (p_1, p_2)\) be a point of \(K^2\) and \(c_1, \dots, c_m\) a list of points \(c_l = (x_l, y_l)\) of \(K^2\), and let \(k \le m\) be largest such that \((y_l - p_2)^2 < \delta\) for all \(1 \le l \le k\). The scan from \(p\) with threshold \(\delta\) returns no value if \(k = 0\) and \(\min_{1 \le l \le k} d(p, c_l)\) otherwise. It is charged one unit of cost per point \(c_1, \dots, c_k\): it stops at the first point whose squared vertical gap to \(p\) is at least \(\delta\), without computing its distance.
def scanFrom (Ξ΄ : π) (p : π Γ π) : List (π Γ π) β TimeM β (Option π)
| [] => pure none
| q :: qs =>
if (q.2 - p.2) ^ 2 < Ξ΄ then do
β
let r β scanFrom Ξ΄ p qs
pure (omin (some (dist2 p q)) r)
else pure none
def omin {Ξ± : Type u} [Min Ξ±] : Option Ξ± β Option Ξ± β Option Ξ±
| none, b => b
| some a, none => some a
| some a, some b => some (min a b)
CSLibExt/Algorithms/Lean/DataStructures/SparseTable.lean:59
def dist2 (p q : π Γ π) : π := (p.1 - q.1) ^ 2 + (p.2 - q.2) ^ 2
CSLibExt/Algorithms/Lean/Geometry/ClosestPair.lean:59
Uses 2 Β· Used by 5
DefinitionClosest-pair strip scan#βfully proved
Let \(K\) be a linearly ordered field, \(\delta \in K\) and \(c_1, \dots, c_n\) a list of points of \(K^2\). For each \(i\), the strip scan runs the strip scan from \(c_i\) with threshold \(\delta\) on the later points \(c_{i+1}, \dots, c_n\). It returns the least of the values these scans return, or no value if none of them returns a value, and its cost is the sum of their costs.
def stripScan (Ξ΄ : π) : List (π Γ π) β TimeM β (Option π)
| [] => pure none
| p :: ps => do
let a β scanFrom Ξ΄ p ps
let b β stripScan Ξ΄ ps
pure (omin a b)
def scanFrom (Ξ΄ : π) (p : π Γ π) : List (π Γ π) β TimeM β (Option π)
| [] => pure none
| q :: qs =>
if (q.2 - p.2) ^ 2 < Ξ΄ then do
β
let r β scanFrom Ξ΄ p qs
pure (omin (some (dist2 p q)) r)
else pure none
CSLibExt/Algorithms/Lean/Geometry/ClosestPair.lean:83
def omin {Ξ± : Type u} [Min Ξ±] : Option Ξ± β Option Ξ± β Option Ξ±
| none, b => b
| some a, none => some a
| some a, some b => some (min a b)
CSLibExt/Algorithms/Lean/DataStructures/SparseTable.lean:59
Uses 2 Β· Used by 5
DefinitionClosest-pair recursion#βfully proved
Let \(K\) be a linearly ordered field and \(c_1, \dots, c_n\) a list of points \(c_i = (x_i, y_i)\) of \(K^2\). If \(n \le 3\), the recursion returns the brute-force scan of the list. Otherwise let \(m = \lfloor n/2 \rfloor\), and run the recursion on \(c_1, \dots, c_m\) and on \(c_{m+1}, \dots, c_n\). If neither call returns a value, it returns no value. Otherwise let \(\delta\) be the least of the returned values, let \(T\) be the list of the points \(c_i\) with \((x_i - x_m)^2 < \delta\) in their original order, sorted by second coordinate with a stable merge sort, and run the strip scan with threshold \(\delta\) on \(T\). The recursion returns \(\min(\delta, s)\) if the strip scan returns a value \(s\), and \(\delta\) otherwise. In the base case its cost is that of the brute-force scan; otherwise it is the sum of the costs of the two recursive calls and of the strip scan when it is run, and splitting, filtering and sorting are free.
Cslib.Algorithms.Lean.Geometry.closestRec Β· 19 lines
def closestRec (xs : List (π Γ π)) : TimeM β (Option π) :=
if _h : xs.length β€ 3 then bruteMin xs
else do
let L := xs.take (xs.length / 2)
let R := xs.drop (xs.length / 2)
let dl β closestRec L
let dr β closestRec R
match omin dl dr with
| none => pure none
| some Ξ΄ =>
let xmid := (L.getLast?.map Prod.fst).getD 0
let strip := xs.filter fun p => (p.1 - xmid) ^ 2 < Ξ΄
let ys := strip.mergeSort fun a b => a.2 β€ b.2
let s β stripScan Ξ΄ ys
pure (omin (some Ξ΄) s)
termination_by xs.length
decreasing_by
all_goals simp only [List.length_take, List.length_drop]
all_goals omega
def bruteMin : List (π Γ π) β TimeM β (Option π)
| [] => pure none
| p :: ps => do
let a β minDistFrom p ps
let b β bruteMin ps
pure (omin a b)
CSLibExt/Algorithms/Lean/Geometry/ClosestPair.lean:74
def omin {Ξ± : Type u} [Min Ξ±] : Option Ξ± β Option Ξ± β Option Ξ±
| none, b => b
| some a, none => some a
| some a, some b => some (min a b)
CSLibExt/Algorithms/Lean/DataStructures/SparseTable.lean:59
def stripScan (Ξ΄ : π) : List (π Γ π) β TimeM β (Option π)
| [] => pure none
| p :: ps => do
let a β scanFrom Ξ΄ p ps
let b β stripScan Ξ΄ ps
pure (omin a b)
CSLibExt/Algorithms/Lean/Geometry/ClosestPair.lean:93
Uses 3 Β· Used by 5
DefinitionDivide-and-conquer closest pair#βfully proved
Let \(K\) be a field with a linear order. Given a list of points in \(K^2\), the closest-pair algorithm sorts the points by first coordinate (merge sort, at no cost) and runs the closest-pair recursion on the sorted list. It returns a squared distance or no value, and is charged one unit of cost per squared distance computed.
This is CLRS CLOSEST-PAIR (Section 33.4), with distances compared squared.
def closestPair (ps : List (π Γ π)) : TimeM β (Option π) :=
closestRec (ps.mergeSort fun a b => a.1 β€ b.1)
def closestRec (xs : List (π Γ π)) : TimeM β (Option π) :=
if _h : xs.length β€ 3 then bruteMin xs
else do
let L := xs.take (xs.length / 2)
let R := xs.drop (xs.length / 2)
let dl β closestRec L
let dr β closestRec R
match omin dl dr with
| none => pure none
| some Ξ΄ =>
let xmid := (L.getLast?.map Prod.fst).getD 0
let strip := xs.filter fun p => (p.1 - xmid) ^ 2 < Ξ΄
β―
CSLibExt/Algorithms/Lean/Geometry/ClosestPair.lean:101
Uses 1 Β· Used by 5
StructureClosest-pair answer#βfully proved
Let \(K\) be a linearly ordered field, and write \(d(p, q) = (p_1 - q_1)^2 + (p_2 - q_2)^2\) for the squared distance between points \(p = (p_1, p_2)\) and \(q = (q_1, q_2)\) of \(K^2\). For a list \(c_1, \dots, c_n\) of points of \(K^2\), an optional value \(r\) (an element of \(K\) or no value) is an answer for the list when every value \(\delta\) that \(r\) holds equals \(d(c_i, c_j)\) for some \(i < j\), and when for all \(i < j\), \(r\) holds a value \(\delta\) with \(\delta \le d(c_i, c_j)\).
structure IsAnswer (ps : List (π Γ π)) (r : Option π) : Prop where
attained : β Ξ΄, r = some Ξ΄ β β p q, [p, q] <+ ps β§ dist2 p q = Ξ΄
lower : β p q, [p, q] <+ ps β β Ξ΄, r = some Ξ΄ β§ Ξ΄ β€ dist2 p q
def dist2 (p q : π Γ π) : π := (p.1 - q.1) ^ 2 + (p.2 - q.2) ^ 2
CSLibExt/Algorithms/Lean/Geometry/ClosestPair.lean:59
Uses 1 Β· Used by 6
TheoremThe nearest-point scan returns the least squared distance#βfully proved
Let \(K\) be a linearly ordered field, write \(d(u, v) = (x - x')^2 + (y - y')^2\) for the squared distance between points \(u = (x, y)\) and \(v = (x', y')\) of \(K^2\), let \(p \in K^2\), and let \(qs\) be a list of points in \(K^2\). If the scan for the least squared distance from \(p\) to the entries of \(qs\) returns a value \(\delta\), then \(\delta = d(p, q)\) for some entry \(q\) of \(qs\). For every entry \(q\) of \(qs\), the scan returns a value \(\delta\) with \(\delta \le d(p, q)\).
theorem minDistFrom_spec (p : π Γ π) (qs : List (π Γ π)) :
(β Ξ΄, (minDistFrom p qs).ret = some Ξ΄ β β q β qs, dist2 p q = Ξ΄) β§
β q β qs, β Ξ΄, (minDistFrom p qs).ret = some Ξ΄ β§ Ξ΄ β€ dist2 p q
def minDistFrom (p : π Γ π) : List (π Γ π) β TimeM β (Option π)
| [] => pure none
| q :: qs => do
β
let r β minDistFrom p qs
pure (omin (some (dist2 p q)) r)
CSLibExt/Algorithms/Lean/Geometry/ClosestPair.lean:66
def dist2 (p q : π Γ π) : π := (p.1 - q.1) ^ 2 + (p.2 - q.2) ^ 2
CSLibExt/Algorithms/Lean/Geometry/ClosestPair.lean:59
Uses 3 Β· Used by 2
TheoremThe strip scan bounds every pair with a small vertical gap#βfully proved
Let \(K\) be a linearly ordered field, write \(d(p, q) = (x - x')^2 + (y - y')^2\) for the squared distance between points \(p = (x, y)\) and \(q = (x', y')\) of \(K^2\), and let \(\delta \in K\). Let \(ys\) be a list of points in \(K^2\) sorted by second coordinate: whenever an entry precedes another, its second coordinate is at most the other's. If \(a = (a_1, a_2)\) and \(b = (b_1, b_2)\) are entries of \(ys\) at positions \(i < j\) respectively and \((b_2 - a_2)^2 < \delta\), then the strip scan with threshold \(\delta\) on \(ys\) returns a value \(e\) with \(e \le d(a, b)\).
theorem stripScan_lower (Ξ΄ : π) (ys : List (π Γ π)) (hs : ys.Pairwise fun a b => a.2 β€ b.2)
(a b : π Γ π) (hab : [a, b] <+ ys) (hgap : (b.2 - a.2) ^ 2 < Ξ΄) :
β d, (stripScan Ξ΄ ys).ret = some d β§ d β€ dist2 a b
def stripScan (Ξ΄ : π) : List (π Γ π) β TimeM β (Option π)
| [] => pure none
| p :: ps => do
let a β scanFrom Ξ΄ p ps
let b β stripScan Ξ΄ ps
pure (omin a b)
CSLibExt/Algorithms/Lean/Geometry/ClosestPair.lean:93
def dist2 (p q : π Γ π) : π := (p.1 - q.1) ^ 2 + (p.2 - q.2) ^ 2
CSLibExt/Algorithms/Lean/Geometry/ClosestPair.lean:59
Uses 4 Β· Used by 1
TheoremThe closest-pair recursion is correct on lists sorted by first coordinate#βfully proved
Let \(K\) be a linearly ordered field, write \(d(u, v) = (x - x')^2 + (y - y')^2\) for the squared distance between points \(u = (x, y)\) and \(v = (x', y')\) of \(K^2\), and let \(xs\) be a list of points in \(K^2\) sorted by first coordinate: whenever an entry precedes another, its first coordinate is at most the other's. If the closest-pair recursion returns a value \(\delta\) on \(xs\), then \(\delta = d(p, q)\) for some entries \(p\), \(q\) of \(xs\) at different positions. For any two entries \(p\), \(q\) of \(xs\) at different positions, the recursion returns a value \(\delta\) with \(\delta \le d(p, q)\).
theorem closestRec_isAnswer (xs : List (π Γ π)) (hs : xs.Pairwise fun a b => a.1 β€ b.1) :
IsAnswer xs (closestRec xs).ret
structure IsAnswer (ps : List (π Γ π)) (r : Option π) : Prop where
attained : β Ξ΄, r = some Ξ΄ β β p q, [p, q] <+ ps β§ dist2 p q = Ξ΄
lower : β p q, [p, q] <+ ps β β Ξ΄, r = some Ξ΄ β§ Ξ΄ β€ dist2 p q
CSLibExt/Algorithms/Lean/Geometry/ClosestPair.lean:129
def closestRec (xs : List (π Γ π)) : TimeM β (Option π) :=
if _h : xs.length β€ 3 then bruteMin xs
else do
let L := xs.take (xs.length / 2)
let R := xs.drop (xs.length / 2)
let dl β closestRec L
let dr β closestRec R
match omin dl dr with
| none => pure none
| some Ξ΄ =>
let xmid := (L.getLast?.map Prod.fst).getD 0
let strip := xs.filter fun p => (p.1 - xmid) ^ 2 < Ξ΄
β―
CSLibExt/Algorithms/Lean/Geometry/ClosestPair.lean:101
Uses 10 Β· Used by 2
TheoremThe closest-pair algorithm returns the answer#βfully proved
Let \(K\) be a linearly ordered field, write \(d(p, q) = (x - x')^2 + (y - y')^2\) for the squared distance between points \(p = (x, y)\) and \(q = (x', y')\) of \(K^2\), and let \(ps\) be a list of points in \(K^2\). If the divide-and-conquer closest-pair algorithm returns a value \(\delta\) on \(ps\), then \(\delta = d(p, q)\) for some entries \(p\), \(q\) of \(ps\) at different positions. For any two entries \(p\), \(q\) of \(ps\) at different positions, the algorithm returns a value \(\delta\) with \(\delta \le d(p, q)\).
theorem closestPair_isAnswer (ps : List (π Γ π)) : IsAnswer ps (closestPair ps).ret
structure IsAnswer (ps : List (π Γ π)) (r : Option π) : Prop where
attained : β Ξ΄, r = some Ξ΄ β β p q, [p, q] <+ ps β§ dist2 p q = Ξ΄
lower : β p q, [p, q] <+ ps β β Ξ΄, r = some Ξ΄ β§ Ξ΄ β€ dist2 p q
CSLibExt/Algorithms/Lean/Geometry/ClosestPair.lean:129
def closestPair (ps : List (π Γ π)) : TimeM β (Option π) :=
closestRec (ps.mergeSort fun a b => a.1 β€ b.1)
CSLibExt/Algorithms/Lean/Geometry/ClosestPair.lean:122
Uses 5 Β· Used by 3
TheoremCorrectness of divide-and-conquer closest pair#βfully proved
Let \(K\) be a linearly ordered field and let \(ps\) be a list of at least two points in \(K^2\). Then the divide-and-conquer closest-pair algorithm returns a value \(\delta\), and \(\delta\) is the least squared distance between two entries of \(ps\) at different positions: some two entries at different positions have squared distance \(\delta\), and any two entries at different positions have squared distance at least \(\delta\).
This is the correctness of CLRS Section 33.4, with distances compared squared.
theorem closestPair_spec (ps : List (π Γ π)) (hps : 2 β€ ps.length) :
β Ξ΄, (closestPair ps).ret = some Ξ΄ β§ IsMinPairDist2 ps Ξ΄
def closestPair (ps : List (π Γ π)) : TimeM β (Option π) :=
closestRec (ps.mergeSort fun a b => a.1 β€ b.1)
CSLibExt/Algorithms/Lean/Geometry/ClosestPair.lean:122
def IsMinPairDist2 (ps : List (π Γ π)) (Ξ΄ : π) : Prop :=
(β p q, [p, q] <+ ps β§ dist2 p q = Ξ΄) β§ β p q, [p, q] <+ ps β Ξ΄ β€ dist2 p q
CSLibExt/Algorithms/Lean/Geometry/ClosestPair.lean:62
Uses 5 Β· Used by 1
TheoremThe closest-pair algorithm returns no value exactly on fewer than two points#βfully proved
Let \(K\) be a linearly ordered field. For every list of points in \(K^2\), the divide-and-conquer closest-pair algorithm returns no value if and only if the list has fewer than two entries.
theorem closestPair_eq_none_iff (ps : List (π Γ π)) :
(closestPair ps).ret = none β ps.length < 2
def closestPair (ps : List (π Γ π)) : TimeM β (Option π) :=
closestRec (ps.mergeSort fun a b => a.1 β€ b.1)
CSLibExt/Algorithms/Lean/Geometry/ClosestPair.lean:122
TheoremDivide and conquer agrees with brute force#βfully proved
Let \(K\) be a linearly ordered field. For every list of points in \(K^2\), the divide-and-conquer closest-pair algorithm returns the same value as the brute-force scan (their costs may differ).
theorem closestPair_eq_bruteMin (ps : List (π Γ π)) :
(closestPair ps).ret = (bruteMin ps).ret
def closestPair (ps : List (π Γ π)) : TimeM β (Option π) :=
closestRec (ps.mergeSort fun a b => a.1 β€ b.1)
CSLibExt/Algorithms/Lean/Geometry/ClosestPair.lean:122
def bruteMin : List (π Γ π) β TimeM β (Option π)
| [] => pure none
| p :: ps => do
let a β minDistFrom p ps
let b β bruteMin ps
pure (omin a b)
CSLibExt/Algorithms/Lean/Geometry/ClosestPair.lean:74
Uses 8
TheoremCost of the brute-force closest-pair scan#βfully proved
Let \(K\) be a field with a linear order and let \(ps\) be a list of \(n\) points in \(K^2\). Counting one unit of cost per squared distance computed, twice the cost of the brute-force scan on \(ps\) equals \(n(n-1)\); that is, the scan computes exactly \(n(n-1)/2\) squared distances.
theorem bruteMin_time (ps : List (π Γ π)) :
2 * (bruteMin ps).time = ps.length * (ps.length - 1)
def bruteMin : List (π Γ π) β TimeM β (Option π)
| [] => pure none
| p :: ps => do
let a β minDistFrom p ps
let b β bruteMin ps
pure (omin a b)
CSLibExt/Algorithms/Lean/Geometry/ClosestPair.lean:74
Uses 4 Β· Used by 1
AbbreviationSide-tagged points#βfully proved
A tagged point is a pair \((p, s)\) of a point \(p \in \mathbb{R}^2\) and a Boolean \(s\), read as the side of the dividing line on which \(p\) lies: false for left, true for right.
abbrev Tagged := (β Γ β) Γ Bool
Used by 5
DefinitionSame-side points far apart#βfully proved
For a real \(\delta\), two tagged points \(a\) and \(b\) are same-side far apart when, if \(a\) and \(b\) carry the same side, the squared distance between their points is at least \(\delta\).
def SameSideFar (Ξ΄ : β) (a b : Tagged) : Prop := a.2 = b.2 β Ξ΄ β€ dist2 a.1 b.1
abbrev Tagged := (β Γ β) Γ Bool
CSLibExt/Algorithms/Lean/Geometry/ClosestPairTime.lean:52
def dist2 (p q : π Γ π) : π := (p.1 - q.1) ^ 2 + (p.2 - q.2) ^ 2
CSLibExt/Algorithms/Lean/Geometry/ClosestPair.lean:59
Uses 2 Β· Used by 3
DefinitionStrip points#βfully proved
Given reals \(\delta\) and \(x_{\mathrm{mid}}\), a tagged point \(((x, y), s)\) lies in the strip when \((x - x_{\mathrm{mid}})^2 < \delta\), and moreover \(x \le x_{\mathrm{mid}}\) if its side \(s\) is left (\(s\) false) and \(x_{\mathrm{mid}} \le x\) if its side \(s\) is right (\(s\) true).
def InStrip (Ξ΄ xmid : β) (a : Tagged) : Prop :=
(a.1.1 - xmid) ^ 2 < Ξ΄ β§ (a.2 = false β a.1.1 β€ xmid) β§ (a.2 = true β xmid β€ a.1.1)
abbrev Tagged := (β Γ β) Γ Bool
CSLibExt/Algorithms/Lean/Geometry/ClosestPairTime.lean:52
Uses 1 Β· Used by 3
TheoremPacking bound for the strip#βfully proved
Let \(\delta\) and \(x_{\mathrm{mid}}\) be reals, \(p\) a tagged point, \(Z\) a list of tagged points, and \(L\) the list \(p\) followed by \(Z\); write \(y_a\) for the \(y\)-coordinate of a tagged point \(a\). Suppose every point of \(L\) lies in the strip for \(\delta\) and \(x_{\mathrm{mid}}\), any two points of \(L\) at different positions with the same side are at squared distance at least \(\delta\), and every point \(a\) of \(Z\) satisfies \(y_p \le y_a\) and \((y_a - y_p)^2 < \delta\). Then \(Z\) has at most \(7\) entries.
theorem length_le_seven {Ξ΄ xmid : β} (p : Tagged) (Z : List Tagged)
(hpair : (p :: Z).Pairwise (SameSideFar Ξ΄))
(hstrip : β a β p :: Z, InStrip Ξ΄ xmid a)
(hy : β a β Z, p.1.2 β€ a.1.2 β§ (a.1.2 - p.1.2) ^ 2 < Ξ΄) :
Z.length β€ 7
abbrev Tagged := (β Γ β) Γ Bool
CSLibExt/Algorithms/Lean/Geometry/ClosestPairTime.lean:52
def SameSideFar (Ξ΄ : β) (a b : Tagged) : Prop := a.2 = b.2 β Ξ΄ β€ dist2 a.1 b.1
CSLibExt/Algorithms/Lean/Geometry/ClosestPairTime.lean:55
def InStrip (Ξ΄ xmid : β) (a : Tagged) : Prop :=
(a.1.1 - xmid) ^ 2 < Ξ΄ β§ (a.2 = false β a.1.1 β€ xmid) β§ (a.2 = true β xmid β€ a.1.1)
CSLibExt/Algorithms/Lean/Geometry/ClosestPairTime.lean:58
Sources
- CLRS, third edition, Section 33.4, the packing argument.
Uses 4 Β· Used by 1
TheoremCost of the scan from one strip point#βfully proved
Let \(\delta\) be a real, \(q = (q_1, q_2)\) a point of \(\mathbb{R}^2\) and \(L\) a list of points of \(\mathbb{R}^2\). The cost of the scan from \(q\) over \(L\) with threshold \(\delta\), one unit per squared distance computed, equals the length of the longest initial segment of \(L\) all of whose points \(r = (r_1, r_2)\) satisfy \((r_2 - q_2)^2 < \delta\).
theorem scanFrom_time (Ξ΄ : β) (q : β Γ β) (L : List (β Γ β)) :
(scanFrom Ξ΄ q L).time = (L.takeWhile fun r => decide ((r.2 - q.2) ^ 2 < Ξ΄)).length
def scanFrom (Ξ΄ : π) (p : π Γ π) : List (π Γ π) β TimeM β (Option π)
| [] => pure none
| q :: qs =>
if (q.2 - p.2) ^ 2 < Ξ΄ then do
β
let r β scanFrom Ξ΄ p qs
pure (omin (some (dist2 p q)) r)
else pure none
CSLibExt/Algorithms/Lean/Geometry/ClosestPair.lean:83
Uses 3 Β· Used by 1
TheoremCost of the strip scan#βfully proved
Let \(\delta\) and \(x_{\mathrm{mid}}\) be reals and \(Y\) a list of tagged points that is sorted by nondecreasing \(y\)-coordinate, whose points all lie in the strip for \(\delta\) and \(x_{\mathrm{mid}}\), and in which any two points at different positions with the same side are at squared distance at least \(\delta\). Then the strip scan with parameter \(\delta\) over the underlying points of \(Y\) (tags forgotten) computes at most \(7m\) squared distances, where \(m\) is the length of \(Y\).
theorem stripScan_time_le (Ξ΄ xmid : β) (Y : List Tagged)
(hsorted : Y.Pairwise fun a b => a.1.2 β€ b.1.2) (hpair : Y.Pairwise (SameSideFar Ξ΄))
(hstrip : β a β Y, InStrip Ξ΄ xmid a) :
(stripScan Ξ΄ (Y.map Prod.fst)).time β€ 7 * Y.length
abbrev Tagged := (β Γ β) Γ Bool
CSLibExt/Algorithms/Lean/Geometry/ClosestPairTime.lean:52
def SameSideFar (Ξ΄ : β) (a b : Tagged) : Prop := a.2 = b.2 β Ξ΄ β€ dist2 a.1 b.1
CSLibExt/Algorithms/Lean/Geometry/ClosestPairTime.lean:55
def InStrip (Ξ΄ xmid : β) (a : Tagged) : Prop :=
(a.1.1 - xmid) ^ 2 < Ξ΄ β§ (a.2 = false β a.1.1 β€ xmid) β§ (a.2 = true β xmid β€ a.1.1)
CSLibExt/Algorithms/Lean/Geometry/ClosestPairTime.lean:58
def stripScan (Ξ΄ : π) : List (π Γ π) β TimeM β (Option π)
| [] => pure none
| p :: ps => do
let a β scanFrom Ξ΄ p ps
let b β stripScan Ξ΄ ps
pure (omin a b)
CSLibExt/Algorithms/Lean/Geometry/ClosestPair.lean:93
Uses 8 Β· Used by 1
TheoremRunning time of the closest-pair recursion#βfully proved
For every list of \(n\) points in \(\mathbb{R}^2\) sorted by nondecreasing \(x\)-coordinate, the divide-and-conquer recursion of the closest-pair algorithm computes at most \(7 n \lceil \log_2 n \rceil + n\) squared distances, where \(\lceil \log_2 0 \rceil\) is read as \(0\).
theorem closestRec_time_le (xs : List (β Γ β)) (hs : xs.Pairwise fun a b => a.1 β€ b.1) :
(closestRec xs).time β€ 7 * xs.length * Nat.clog 2 xs.length + xs.length
def closestRec (xs : List (π Γ π)) : TimeM β (Option π) :=
if _h : xs.length β€ 3 then bruteMin xs
else do
let L := xs.take (xs.length / 2)
let R := xs.drop (xs.length / 2)
let dl β closestRec L
let dr β closestRec R
match omin dl dr with
| none => pure none
| some Ξ΄ =>
let xmid := (L.getLast?.map Prod.fst).getD 0
let strip := xs.filter fun p => (p.1 - xmid) ^ 2 < Ξ΄
β―
CSLibExt/Algorithms/Lean/Geometry/ClosestPair.lean:101
Uses 12 Β· Used by 1
TheoremRunning time of the closest-pair algorithm#βfully proved
For every list of \(n\) points in \(\mathbb{R}^2\), the closest-pair algorithm computes at most \(7 n \lceil \log_2 n \rceil + n\) squared distances, where \(\lceil \log_2 0 \rceil\) is read as \(0\). In particular it computes \(O(n \log n)\) distances.
theorem closestPair_time_le (ps : List (β Γ β)) :
(closestPair ps).time β€ 7 * ps.length * Nat.clog 2 ps.length + ps.length
def closestPair (ps : List (π Γ π)) : TimeM β (Option π) :=
closestRec (ps.mergeSort fun a b => a.1 β€ b.1)
CSLibExt/Algorithms/Lean/Geometry/ClosestPair.lean:122
Sources
- CLRS, third edition, Section 33.4.
Uses 3
Loading dependency explorerβ¦
The dependency explorer needs JavaScript and its graph data.