Sweep-line segment intersection detection
Non-vertical segments as graphs
DefinitionHeight of a line at an abscissa#βfully proved
For points \(p = (p_1, p_2)\) and \(q = (q_1, q_2)\) in \(K^2\), \(K\) a field, and \(x \in K\), this is \(p_2 + (x - p_1)(q_2 - p_2)/(q_1 - p_1)\), with division by zero read as \(0\). When \(p_1 \ne q_1\) it is the height at \(x\) of the line through \(p\) and \(q\).
def lineY (p q : π Γ π) (x : π) : π := p.2 + (x - p.1) * (q.2 - p.2) / (q.1 - p.1)
Used by 12
TheoremA non-vertical segment is the graph of its line#βfully proved
Let \(p\) and \(q\) be points of the plane over a linearly ordered field, where a point \(z\) has coordinates \((z_1, z_2)\), and suppose \(p_1 < q_1\). A point \(z\) lies on the segment from \(p\) to \(q\) if and only if \(p_1 \le z_1 \le q_1\) and \(z_2\) is the height at abscissa \(z_1\) of the line through \(p\) and \(q\).
theorem mem_segment_iff_lineY {p q z : π Γ π} (hpq : p.1 < q.1) :
z β segment π p q β p.1 β€ z.1 β§ z.1 β€ q.1 β§ z.2 = lineY p q z.1
def lineY (p q : π Γ π) (x : π) : π := p.2 + (x - p.1) * (q.2 - p.2) / (q.1 - p.1)
CSLibExt/Algorithms/Lean/Geometry/AnySegmentsIntersect.lean:80
Uses 1 Β· Used by 6
TheoremDIRECTION as a scaled vertical offset#βfully proved
Let \(\Bbbk\) be a field with a linear order, let \(p, q, r \in \Bbbk^2\), writing \(p = (p_x, p_y)\) and likewise for \(q\) and \(r\), with \(p_x < q_x\), and let \(y_{pq}(x)\) be the height at \(x\) of the line through \(p\) and \(q\). Then \(\mathrm{DIRECTION}(p, q, r) = (q_x - p_x)\,(y_{pq}(r_x) - r_y)\).
theorem direction_eq_lineY {p q : π Γ π} (hpq : p.1 < q.1) (r : π Γ π) :
direction p q r = (q.1 - p.1) * (lineY p q r.1 - r.2)
def direction (pi pj pk : π Γ π) : π := cross (pk - pi) (pj - pi)
CSLibExt/Algorithms/Lean/Geometry/SegmentIntersection.lean:55
def lineY (p q : π Γ π) (x : π) : π := p.2 + (x - p.1) * (q.2 - p.2) / (q.1 - p.1)
CSLibExt/Algorithms/Lean/Geometry/AnySegmentsIntersect.lean:80
Uses 2 Β· Used by 3
TheoremCrossing of two non-vertical segments#βfully proved
Let \(K\) be a linearly ordered field, write \(z_1\) for the first coordinate of a point \(z \in K^2\), and let \([p, q]\) and \([p', q']\) be segments in \(K^2\) with \(p_1 < q_1\) and \(p'_1 < q'_1\). For \(t \in K\) let \(y(t)\) be the height at \(t\) of the line through \(p\) and \(q\), and \(y'(t)\) that of the line through \(p'\) and \(q'\). Let \(a < b\) with \(p_1 \le a\), \(p'_1 \le a\), \(b \le q_1\) and \(b \le q'_1\). If \(y(a) < y'(a)\) and \(y'(b) \le y(b)\), then some \(z \in [p, q] \cap [p', q']\) has \(a < z_1 \le b\), and \(z_1 < b\) if moreover \(y'(b) < y(b)\).
theorem exists_mem_inter_of_cross {p q p' q' : π Γ π} (hpq : p.1 < q.1) (hpq' : p'.1 < q'.1)
{xβ xβ : π} (hx : xβ < xβ) (hp : p.1 β€ xβ) (hq : xβ β€ q.1) (hp' : p'.1 β€ xβ)
(hq' : xβ β€ q'.1) (hβ : lineY p q xβ < lineY p' q' xβ)
(hβ : lineY p' q' xβ β€ lineY p q xβ) :
β z β segment π p q β© segment π p' q', xβ < z.1 β§ z.1 β€ xβ β§
(lineY p' q' xβ < lineY p q xβ β z.1 < xβ)
def lineY (p q : π Γ π) (x : π) : π := p.2 + (x - p.1) * (q.2 - p.2) / (q.1 - p.1)
CSLibExt/Algorithms/Lean/Geometry/AnySegmentsIntersect.lean:80
Uses 2 Β· Used by 2
TheoremLeftmost point of the intersection of two segments#βfully proved
Let \(K\) be a linearly ordered field, write \(x_1\) for the first coordinate of a point \(x \in K^2\), and let \([p, q]\) and \([p', q']\) be segments in \(K^2\) with \(p_1 < q_1\) and \(p'_1 < q'_1\). If \([p, q] \cap [p', q']\) is nonempty, then it contains a point \(m\) with \(m_1 \le w_1\) for every \(w \in [p, q] \cap [p', q']\).
theorem exists_leftmost_mem_inter {p q p' q' z : π Γ π} (hpq : p.1 < q.1) (hpq' : p'.1 < q'.1)
(hz : z β segment π p q β© segment π p' q') :
β m β segment π p q β© segment π p' q', β w β segment π p q β© segment π p' q', m.1 β€ w.1
Uses 2 Β· Used by 1
Sorted lists of graphs
TheoremInserting into a strictly sorted list#βfully proved
Let \(f\) map a type \(\alpha\) to a linearly ordered set, let \(T\) be a list over \(\alpha\) with \(f(j) < f(k)\) whenever \(j\) occurs before \(k\), let \(i \in \alpha\) be such that \(f(j) \ne f(i)\) for every \(j\) in \(T\), and let \(P\) be a predicate that holds for an element \(j\) of \(T\) exactly when \(f(j) < f(i)\). Insert \(i\) just before the first element of \(T\) not satisfying \(P\): the list made of the longest prefix of \(T\) satisfying \(P\), then \(i\), then the rest of \(T\). In this list, \(f(j) < f(k)\) whenever \(j\) occurs before \(k\).
TheoremInserting into a weakly sorted list#βfully proved
Let \(f\) map a type \(\alpha\) to a linearly ordered set, let \(T\) be a list over \(\alpha\) with \(f(j) \le f(k)\) whenever \(j\) occurs before \(k\), let \(i \in \alpha\), and let \(P\) be a predicate that holds for an element \(j\) of \(T\) exactly when \(f(j) < f(i)\). Insert \(i\) just before the first element of \(T\) not satisfying \(P\): the list made of the longest prefix of \(T\) satisfying \(P\), then \(i\), then the rest of \(T\). In this list, \(f(j) \le f(k)\) whenever \(j\) occurs before \(k\).
TheoremFirst element at or above a uniquely attained height#βfully proved
Let \(f\) map a type to a linearly ordered set, let \(y\) be a value, and let \(T\) be a list sorted non-strictly by \(f\), that is, \(f(j) \le f(k)\) whenever \(j\) occurs before \(k\) in \(T\). Suppose \(b\) lies in \(T\) with \(f(b) = y\), and every element \(c \ne b\) of \(T\) has \(f(c) \ne y\). Then removing from \(T\) its longest prefix of elements \(j\) with \(f(j) < y\) leaves a list whose first element is \(b\).
theorem head?_dropWhile_eq_of_unique {T : List Ξ±} {b : Ξ±} (p : Ξ± β Bool)
(hp : β j β T, p j = true β f j < y) (hT : T.Pairwise (fun j k => f j β€ f k)) (hb : b β T)
(hfb : f b = y) (huniq : β c β T, c β b β f c β y) :
(T.dropWhile p).head? = some b
Used by 1
TheoremSplitting a list at two distinct members#βfully proved
If \(a\) and \(b\) are distinct members of a list \(T\), then there are elements \(u\), \(w\) with either \(u = a\) and \(w = b\), or \(u = b\) and \(w = a\), and lists \(A\), \(M\), \(B\) such that \(T\) is the concatenation of \(A\), the element \(u\), \(M\), the element \(w\) and \(B\), in this order.
theorem exists_append_of_mem_of_mem {T : List Ξ±} {a b : Ξ±} (ha : a β T) (hb : b β T)
(hab : a β b) :
β u w A M B, (u = a β§ w = b β¨ u = b β§ w = a) β§ T = A ++ u :: (M ++ w :: B)
The algorithm
DefinitionLeft endpoint of a segment#βfully proved
Let \(K\) be a linearly ordered set and \(S\) a family of segments in \(K^2\), segment \(i\) being given by its two endpoints \((a, b)\) in either order. The left endpoint of segment \(i\) is \(a\) if \(a_1 \le b_1\) and \(b\) otherwise, where \(a_1\) and \(b_1\) are the first coordinates.
def left (i : Fin n) : π Γ π := if (S i).1.1 β€ (S i).2.1 then (S i).1 else (S i).2
Used by 21
DefinitionRight endpoint of a segment#βfully proved
Write \(z_1\) for the abscissa of a point \(z\). If segment \(i\) is given by the endpoints \(u\) and \(v\), in this order, its right endpoint is \(v\) when \(u_1 \le v_1\) and \(u\) otherwise.
def right (i : Fin n) : π Γ π := if (S i).1.1 β€ (S i).2.1 then (S i).2 else (S i).1
Used by 18
AbbreviationSweep event#βfully proved
For \(n\) segments indexed by \(0, \dots, n-1\), an event is a pair \((i, b)\) of a segment index \(i\) and a Boolean \(b\); it stands for the left endpoint of segment \(i\) when \(b\) is true and for its right endpoint when \(b\) is false.
Used by 19
DefinitionEndpoint of an event#βfully proved
The point of the sweep event \((i, b)\) is the left endpoint of segment \(i\) when \(b\) is true (a left-endpoint event) and the right endpoint of segment \(i\) when \(b\) is false.
def point (e : Event n) : π Γ π := if e.2 then left S e.1 else right S e.1
abbrev Event (n : β) := Fin n Γ Bool
CSLibExt/Algorithms/Lean/Geometry/AnySegmentsIntersect.lean:358
def left (i : Fin n) : π Γ π := if (S i).1.1 β€ (S i).2.1 then (S i).1 else (S i).2
CSLibExt/Algorithms/Lean/Geometry/AnySegmentsIntersect.lean:352
def right (i : Fin n) : π Γ π := if (S i).1.1 β€ (S i).2.1 then (S i).2 else (S i).1
CSLibExt/Algorithms/Lean/Geometry/AnySegmentsIntersect.lean:355
Uses 3 Β· Used by 8
DefinitionSweep order on endpoint events#βfully proved
Let \(K\) be a linearly ordered set and \(S\) a family of segments in \(K^2\), each given by its two endpoints. An endpoint event \(e\) of \(S\) standing for the point \((x, y)\) gets the key \((x, \varepsilon, y)\), compared lexicographically, where \(\varepsilon = 0\) if \(e\) is a left endpoint and \(\varepsilon = 1\) if it is a right endpoint. So events are ordered by \(x\); at equal \(x\), left endpoints come first; then by \(y\). This is the endpoint order of CLRS.
def key (e : Event n) : π Γβ (β Γβ π) :=
toLex ((point S e).1, toLex (if e.2 then 0 else 1, (point S e).2))
abbrev Event (n : β) := Fin n Γ Bool
CSLibExt/Algorithms/Lean/Geometry/AnySegmentsIntersect.lean:358
def point (e : Event n) : π Γ π := if e.2 then left S e.1 else right S e.1
CSLibExt/Algorithms/Lean/Geometry/AnySegmentsIntersect.lean:361
Uses 2 Β· Used by 12
DefinitionSorted sweep events#βfully proved
For \(n\) segments, each given by its two endpoints, the left endpoint of a segment is its endpoint with the smaller \(x\)-coordinate, or its first given endpoint when both \(x\)-coordinates agree, and the right endpoint is the other one. The event list consists of the \(2n\) events, the left and the right endpoint of each segment, sorted by the \(x\)-coordinate of the endpoint, with left endpoints before right endpoints at equal \(x\), and then by the \(y\)-coordinate of the endpoint; events that tie appear in increasing order of segment index. This is line 2 of CLRS ANY-SEGMENTS-INTERSECT.
def events : List (Event n) :=
((List.finRange n).map (Β·, true) ++ (List.finRange n).map (Β·, false)).mergeSort
fun e f => decide (key S e β€ key S f)
abbrev Event (n : β) := Fin n Γ Bool
CSLibExt/Algorithms/Lean/Geometry/AnySegmentsIntersect.lean:358
def key (e : Event n) : π Γβ (β Γβ π) :=
toLex ((point S e).1, toLex (if e.2 then 0 else 1, (point S e).2))
CSLibExt/Algorithms/Lean/Geometry/AnySegmentsIntersect.lean:364
Uses 2 Β· Used by 13
DefinitionSegment strictly below a point#βfully proved
For a segment \(j\), write \(l_j\) for its endpoint with the smaller \(x\)-coordinate, or for its first given endpoint when both \(x\)-coordinates agree, and \(r_j\) for its other endpoint. For a point \(q\), segment \(j\) is below \(q\) when \(\mathrm{DIRECTION}(l_j, r_j, q) < 0\).
For a non-vertical segment this says that the line through \(l_j\) and \(r_j\) passes strictly below \(q\) at the abscissa of \(q\).
def below (j : Fin n) (q : π Γ π) : Bool := decide (direction (left S j) (right S j) q < 0)
def direction (pi pj pk : π Γ π) : π := cross (pk - pi) (pj - pi)
CSLibExt/Algorithms/Lean/Geometry/SegmentIntersection.lean:55
def left (i : Fin n) : π Γ π := if (S i).1.1 β€ (S i).2.1 then (S i).1 else (S i).2
CSLibExt/Algorithms/Lean/Geometry/AnySegmentsIntersect.lean:352
def right (i : Fin n) : π Γ π := if (S i).1.1 β€ (S i).2.1 then (S i).2 else (S i).1
CSLibExt/Algorithms/Lean/Geometry/AnySegmentsIntersect.lean:355
Uses 3 Β· Used by 10
DefinitionIntersection test for two input segments#βfully proved
Given \(n\) segments in the plane over a
linearly ordered field, each given by its two endpoints, and indices \(i, j < n\), this runs CLRS
SEGMENTS-INTERSECT on the left and right endpoints of segment \(i\) and the left and right
endpoints of segment \(j\). It returns that procedure's Boolean answer together with its cost in
DIRECTION and ON-SEGMENT evaluations.
def test (i j : Fin n) : TimeM β Bool :=
segmentsIntersect (left S i) (right S i) (left S j) (right S j)
def segmentsIntersect (p1 p2 p3 p4 : π Γ π) : TimeM β Bool := do
β[4]
let d1 := direction p3 p4 p1
let d2 := direction p3 p4 p2
let d3 := direction p1 p2 p3
let d4 := direction p1 p2 p4
if Straddles d1 d2 β§ Straddles d3 d4 then pure true
else do
let b1 β collinearBranch d1 p3 p4 p1
if b1 then pure true else do
let b2 β collinearBranch d2 p3 p4 p2
if b2 then pure true else do
β―
CSLibExt/Algorithms/Lean/Geometry/SegmentIntersection.lean:76
def left (i : Fin n) : π Γ π := if (S i).1.1 β€ (S i).2.1 then (S i).1 else (S i).2
CSLibExt/Algorithms/Lean/Geometry/AnySegmentsIntersect.lean:352
def right (i : Fin n) : π Γ π := if (S i).1.1 β€ (S i).2.1 then (S i).2 else (S i).1
CSLibExt/Algorithms/Lean/Geometry/AnySegmentsIntersect.lean:355
Uses 3 Β· Used by 6
DefinitionTesting a segment against an optional neighbour#βfully proved
Given a segment \(i\) and possibly a
neighbour \(j\), return the result of SEGMENTS-INTERSECT on segments \(i\) and \(j\), with its cost,
when \(j\) is given, and return false at no cost when there is no neighbour.
def testOpt (i : Fin n) : Option (Fin n) β TimeM β Bool
| none => pure false
| some j => test S i j
def test (i j : Fin n) : TimeM β Bool :=
segmentsIntersect (left S i) (right S i) (left S j) (right S j)
CSLibExt/Algorithms/Lean/Geometry/AnySegmentsIntersect.lean:376
Uses 1 Β· Used by 10
DefinitionTesting the neighbours of a deleted segment#βfully proved
Given \(n\) segments in the plane over a
linearly ordered field and two optional segment indices \(a\) and \(b\) (in the sweep, the segments
just below and just above a deleted segment, when they exist), this runs the intersection test
of segments \(a\) and \(b\) when both indices are present, and otherwise returns false at no
cost.
def testPair : Option (Fin n) β Option (Fin n) β TimeM β Bool
| some a, some b => test S a b
| _, _ => pure false
def test (i j : Fin n) : TimeM β Bool :=
segmentsIntersect (left S i) (right S i) (left S j) (right S j)
CSLibExt/Algorithms/Lean/Geometry/AnySegmentsIntersect.lean:376
Uses 1 Β· Used by 8
DefinitionThe any-segments-intersect sweep#βfully proved
CLRS ANY-SEGMENTS-INTERSECT, lines 3-11: the sweep
processes a list of events with a status list \(T\) of segments ordered from bottom to top, returns
true as soon as an intersection test succeeds, and returns false once the events run out. At the
left endpoint \(p\) of segment \(i\), split \(T\) as \(A\) followed by \(B\), where \(A\) is the longest
initial part of \(T\) whose segments pass strictly below \(p\) by the DIRECTION test; this scan
costs \(\min(|A| + 1, |T|)\), one DIRECTION per segment scanned. Segment \(i\) is tested with
SEGMENTS-INTERSECT against the first segment of \(B\) and then against the last segment of \(A\)
(when these exist), and the sweep continues with \(A\), then \(i\), then \(B\). At the right endpoint
of segment \(i\), with \(A\) the part of \(T\) before the first occurrence of \(i\) and \(B\) the part
after it, the last segment of \(A\) is tested against the first segment of \(B\) when both exist,
and the sweep continues with \(A\) followed by \(B\).
def sweep : List (Event n) β List (Fin n) β TimeM β Bool
| [], _ => pure false
| (i, true) :: es, T => do
β[min ((T.takeWhile (below S Β· (left S i))).length + 1) T.length]
let bβ β testOpt S i (T.dropWhile (below S Β· (left S i))).head?
if bβ then pure true else do
let bβ β testOpt S i (T.takeWhile (below S Β· (left S i))).getLast?
if bβ then pure true else
sweep es (T.takeWhile (below S Β· (left S i)) ++ i :: T.dropWhile (below S Β· (left S i)))
| (i, false) :: es, T => do
let b β testPair S (T.takeWhile (Β· != i)).getLast? (T.dropWhile (Β· != i)).tail.head?
if b then pure true else sweep es (T.takeWhile (Β· != i) ++ (T.dropWhile (Β· != i)).tail)
abbrev Event (n : β) := Fin n Γ Bool
CSLibExt/Algorithms/Lean/Geometry/AnySegmentsIntersect.lean:358
def below (j : Fin n) (q : π Γ π) : Bool := decide (direction (left S j) (right S j) q < 0)
CSLibExt/Algorithms/Lean/Geometry/AnySegmentsIntersect.lean:373
def left (i : Fin n) : π Γ π := if (S i).1.1 β€ (S i).2.1 then (S i).1 else (S i).2
CSLibExt/Algorithms/Lean/Geometry/AnySegmentsIntersect.lean:352
def testOpt (i : Fin n) : Option (Fin n) β TimeM β Bool
| none => pure false
| some j => test S i j
CSLibExt/Algorithms/Lean/Geometry/AnySegmentsIntersect.lean:380
def testPair : Option (Fin n) β Option (Fin n) β TimeM β Bool
| some a, some b => test S a b
| _, _ => pure false
CSLibExt/Algorithms/Lean/Geometry/AnySegmentsIntersect.lean:385
Uses 5 Β· Used by 3
DefinitionOne step of the sweep#βfully proved
A step takes an event and a status list \(T\) of segments, ordered
from bottom to top, and returns a new status list, or no result when an intersection is reported.
At the left endpoint \(p\) of segment \(i\), split \(T\) as \(A\) followed by \(B\), where \(A\) is the longest
initial part of \(T\) whose segments pass strictly below \(p\) by the DIRECTION test. If
SEGMENTS-INTERSECT reports that \(i\) meets the first segment of \(B\) or the last segment of \(A\)
(when these exist), there is no result; otherwise the new status list is \(A\), then \(i\), then \(B\).
At the right endpoint of segment \(i\), let \(A\) be the part of \(T\) before the first occurrence of
\(i\) and \(B\) the part after it (so \(A\) is all of \(T\) and \(B\) is empty when \(i\) does not occur). If
both the last segment of \(A\) and the first segment of \(B\) exist and SEGMENTS-INTERSECT reports
that they meet, there is no result; otherwise the new status list is \(A\) followed by \(B\).
def step : Event n β List (Fin n) β Option (List (Fin n))
| (i, true), T =>
if (testOpt S i (T.dropWhile (below S Β· (left S i))).head?).ret ||
(testOpt S i (T.takeWhile (below S Β· (left S i))).getLast?).ret then none
else some (T.takeWhile (below S Β· (left S i)) ++ i :: T.dropWhile (below S Β· (left S i)))
| (i, false), T =>
if (testPair S (T.takeWhile (Β· != i)).getLast? (T.dropWhile (Β· != i)).tail.head?).ret then
none
else some (T.takeWhile (Β· != i) ++ (T.dropWhile (Β· != i)).tail)
abbrev Event (n : β) := Fin n Γ Bool
CSLibExt/Algorithms/Lean/Geometry/AnySegmentsIntersect.lean:358
def testOpt (i : Fin n) : Option (Fin n) β TimeM β Bool
| none => pure false
| some j => test S i j
CSLibExt/Algorithms/Lean/Geometry/AnySegmentsIntersect.lean:380
def below (j : Fin n) (q : π Γ π) : Bool := decide (direction (left S j) (right S j) q < 0)
CSLibExt/Algorithms/Lean/Geometry/AnySegmentsIntersect.lean:373
def left (i : Fin n) : π Γ π := if (S i).1.1 β€ (S i).2.1 then (S i).1 else (S i).2
CSLibExt/Algorithms/Lean/Geometry/AnySegmentsIntersect.lean:352
def testPair : Option (Fin n) β Option (Fin n) β TimeM β Bool
| some a, some b => test S a b
| _, _ => pure false
CSLibExt/Algorithms/Lean/Geometry/AnySegmentsIntersect.lean:385
Uses 5 Β· Used by 9
DefinitionRunning the sweep over a list of events#βfully proved
Starting from a status list \(T\), the sweep steps are applied to the events in order, each to the status list left by the previous one. The result is the final status list, or no result as soon as some step reports an intersection; on the empty list of events the result is \(T\).
def run : List (Event n) β List (Fin n) β Option (List (Fin n))
| [], T => some T
| e :: es, T => (step S e T).bind (run es)
abbrev Event (n : β) := Fin n Γ Bool
CSLibExt/Algorithms/Lean/Geometry/AnySegmentsIntersect.lean:358
def step : Event n β List (Fin n) β Option (List (Fin n))
| (i, true), T =>
if (testOpt S i (T.dropWhile (below S Β· (left S i))).head?).ret ||
(testOpt S i (T.takeWhile (below S Β· (left S i))).getLast?).ret then none
else some (T.takeWhile (below S Β· (left S i)) ++ i :: T.dropWhile (below S Β· (left S i)))
| (i, false), T =>
if (testPair S (T.takeWhile (Β· != i)).getLast? (T.dropWhile (Β· != i)).tail.head?).ret then
none
else some (T.takeWhile (Β· != i) ++ (T.dropWhile (Β· != i)).tail)
CSLibExt/Algorithms/Lean/Geometry/AnySegmentsIntersect.lean:408
Uses 2 Β· Used by 11
Endpoints and events
TheoremLeft endpoint events precede right endpoint events#βfully proved
Let \(K\) be a linearly ordered set and \(S\) a family of segments in \(K^2\), each given by its two endpoints. For every segment \(i\) of \(S\), the left endpoint event of \(i\) is strictly smaller than its right endpoint event in the sweep order on events (by \(x\)-coordinate, then left endpoints before right endpoints, then by \(y\)-coordinate).
theorem key_left_lt_right (i : Fin n) : key S (i, true) < key S (i, false)
def key (e : Event n) : π Γβ (β Γβ π) :=
toLex ((point S e).1, toLex (if e.2 then 0 else 1, (point S e).2))
CSLibExt/Algorithms/Lean/Geometry/AnySegmentsIntersect.lean:364
Uses 4 Β· Used by 1
TheoremA sweep prefix with a right endpoint has its left endpoint#βfully proved
Let \(K\) be a linearly ordered set and \(S\) a family of \(n\) segments in \(K^2\), each given by its two endpoints. If the sorted sweep event list of \(S\) is a list \(P\) followed by a list \(Q\), and \(P\) contains the right endpoint event of a segment \(j\), then \(P\) also contains the left endpoint event of \(j\).
theorem left_mem_of_right_mem {P Q : List (Event n)} (hE : events S = P ++ Q) {j : Fin n}
(hj : (j, false) β P) : (j, true) β P
abbrev Event (n : β) := Fin n Γ Bool
CSLibExt/Algorithms/Lean/Geometry/AnySegmentsIntersect.lean:358
def events : List (Event n) :=
((List.finRange n).map (Β·, true) ++ (List.finRange n).map (Β·, false)).mergeSort
fun e f => decide (key S e β€ key S f)
CSLibExt/Algorithms/Lean/Geometry/AnySegmentsIntersect.lean:368
Uses 4 Β· Used by 4
Invariants of the status list
TheoremSplitting a list at the first occurrence of a member#βfully proved
If \(i\) occurs in a list \(T\) of indices in \(\{0, \dots, n-1\}\), then \(T\) is the longest initial part of \(T\) not containing \(i\), followed by \(i\), followed by the part of \(T\) after the first occurrence of \(i\).
TheoremThe sweep status holds the active segments#βfully proved
Let \(P\) be an initial part of the sorted list of events. If running the sweep over \(P\) from the empty status list reports no intersection and ends with status list \(T\), then \(T\) has no repeated entries, and a segment \(j\) belongs to \(T\) exactly when the left endpoint event of \(j\) is in \(P\) and the right endpoint event of \(j\) is not.
theorem run_mem_iff {P Q : List (Event n)} (hE : events S = P ++ Q) {T : List (Fin n)}
(hT : run S P [] = some T) : T.Nodup β§ β j, j β T β (j, true) β P β§ (j, false) β P
abbrev Event (n : β) := Fin n Γ Bool
CSLibExt/Algorithms/Lean/Geometry/AnySegmentsIntersect.lean:358
def events : List (Event n) :=
((List.finRange n).map (Β·, true) ++ (List.finRange n).map (Β·, false)).mergeSort
fun e f => decide (key S e β€ key S f)
CSLibExt/Algorithms/Lean/Geometry/AnySegmentsIntersect.lean:368
def run : List (Event n) β List (Fin n) β Option (List (Fin n))
| [], T => some T
| e :: es, T => (step S e T).bind (run es)
CSLibExt/Algorithms/Lean/Geometry/AnySegmentsIntersect.lean:419
Uses 11 Β· Used by 7
DefinitionMeeting segments#βfully proved
Let \(K\) be a field with a linear order and \(S\) a family of segments in \(K^2\), each given by its two endpoints. Segments \(i\) and \(j\) of \(S\) meet when the closed segment between the endpoints of \(i\) and the closed segment between the endpoints of \(j\) have a point in common.
def Meets (S : Fin n β (π Γ π) Γ (π Γ π)) (i j : Fin n) : Prop :=
(segment π (left S i) (right S i) β© segment π (left S j) (right S j)).Nonempty
def left (i : Fin n) : π Γ π := if (S i).1.1 β€ (S i).2.1 then (S i).1 else (S i).2
CSLibExt/Algorithms/Lean/Geometry/AnySegmentsIntersect.lean:352
def right (i : Fin n) : π Γ π := if (S i).1.1 β€ (S i).2.1 then (S i).2 else (S i).1
CSLibExt/Algorithms/Lean/Geometry/AnySegmentsIntersect.lean:355
Uses 2 Β· Used by 7
TheoremNeighbours on the sweep status are disjoint#βfully proved
Let \(P\) be an initial part of the sorted list of events. If running the sweep over \(P\) from the empty status list reports no intersection and ends with status list \(T\), then no two consecutive segments of \(T\) meet.
theorem run_isChain {P Q : List (Event n)} (hE : events S = P ++ Q) {T : List (Fin n)}
(hT : run S P [] = some T) : T.IsChain fun j k => Β¬ Meets S j k
abbrev Event (n : β) := Fin n Γ Bool
CSLibExt/Algorithms/Lean/Geometry/AnySegmentsIntersect.lean:358
def events : List (Event n) :=
((List.finRange n).map (Β·, true) ++ (List.finRange n).map (Β·, false)).mergeSort
fun e f => decide (key S e β€ key S f)
CSLibExt/Algorithms/Lean/Geometry/AnySegmentsIntersect.lean:368
def run : List (Event n) β List (Fin n) β Option (List (Fin n))
| [], T => some T
| e :: es, T => (step S e T).bind (run es)
CSLibExt/Algorithms/Lean/Geometry/AnySegmentsIntersect.lean:419
def Meets (S : Fin n β (π Γ π) Γ (π Γ π)) (i j : Fin n) : Prop :=
(segment π (left S i) (right S i) β© segment π (left S j) (right S j)).Nonempty
CSLibExt/Algorithms/Lean/Geometry/AnySegmentsIntersect.lean:629
Uses 16 Β· Used by 1
TheoremSoundness of the any-segments-intersect sweep#βfully proved
Let \(S\) be a family of \(n\) segments in \(K^2\), \(K\) a linearly ordered field, and split the sorted list of their \(2n\) endpoint events as \(P\) followed by \(Q\). If running the sweep over \(P\) from the empty status list succeeds with status list \(T\), and running it over \(Q\) from \(T\) reports an intersection, then there are two distinct indices \(i \ne j\) such that segments \(i\) and \(j\) meet.
In particular, when the sweep over all the events reports an intersection, two distinct segments meet.
theorem exists_meets_of_run_eq_none {P Q : List (Event n)} (hE : events S = P ++ Q)
{T : List (Fin n)} (hT : run S P [] = some T) (hQ : run S Q T = none) :
β i j, i β j β§ Meets S i j
abbrev Event (n : β) := Fin n Γ Bool
CSLibExt/Algorithms/Lean/Geometry/AnySegmentsIntersect.lean:358
def events : List (Event n) :=
((List.finRange n).map (Β·, true) ++ (List.finRange n).map (Β·, false)).mergeSort
fun e f => decide (key S e β€ key S f)
CSLibExt/Algorithms/Lean/Geometry/AnySegmentsIntersect.lean:368
def run : List (Event n) β List (Fin n) β Option (List (Fin n))
| [], T => some T
| e :: es, T => (step S e T).bind (run es)
CSLibExt/Algorithms/Lean/Geometry/AnySegmentsIntersect.lean:419
def Meets (S : Fin n β (π Γ π) Γ (π Γ π)) (i j : Fin n) : Prop :=
(segment π (left S i) (right S i) β© segment π (left S j) (right S j)).Nonempty
CSLibExt/Algorithms/Lean/Geometry/AnySegmentsIntersect.lean:629
Uses 16 Β· Used by 1
Completeness
TheoremThe sweep order persists before the leftmost intersection#βfully proved
Let finitely many segments in the plane over a linearly ordered field be given, where a point \(z\) has coordinates \((z_1, z_2)\) and segment \(j\) has left endpoint \(l_j\) and right endpoint \(r_j\) with \((l_j)_1 < (r_j)_1\). Write \(y_j(t)\) for the height at abscissa \(t\) of the line through \(l_j\) and \(r_j\). Let \(p_x\) be such that every point shared by two distinct segments has abscissa at least \(p_x\), let \(x \le x' < p_x\), and let \(T\) be a list of segments such that \((l_j)_1 \le x\) and \(x' \le (r_j)_1\) for every \(j\) in \(T\). If \(y_j(x) < y_k(x)\) whenever \(j\) occurs before \(k\) in \(T\), then \(y_j(x') < y_k(x')\) whenever \(j\) occurs before \(k\) in \(T\).
theorem pairwise_lt_of_pairwise_lt {T : List (Fin n)} {x x' : π} (hxx : x β€ x') (hx' : x' < px)
(hact : β j β T, (left S j).1 β€ x β§ x' β€ (right S j).1)
(hT : T.Pairwise fun j k => lineY (left S j) (right S j) x < lineY (left S k) (right S k) x) :
T.Pairwise fun j k => lineY (left S j) (right S j) x' < lineY (left S k) (right S k) x'
def left (i : Fin n) : π Γ π := if (S i).1.1 β€ (S i).2.1 then (S i).1 else (S i).2
CSLibExt/Algorithms/Lean/Geometry/AnySegmentsIntersect.lean:352
def right (i : Fin n) : π Γ π := if (S i).1.1 β€ (S i).2.1 then (S i).2 else (S i).1
CSLibExt/Algorithms/Lean/Geometry/AnySegmentsIntersect.lean:355
def lineY (p q : π Γ π) (x : π) : π := p.2 + (x - p.1) * (q.2 - p.2) / (q.1 - p.1)
CSLibExt/Algorithms/Lean/Geometry/AnySegmentsIntersect.lean:80
Uses 4 Β· Used by 1
TheoremThe sweep order holds weakly at the leftmost intersection#βfully proved
Let finitely many segments in the plane over a linearly ordered field be given, where a point \(z\) has coordinates \((z_1, z_2)\) and segment \(j\) has left endpoint \(l_j\) and right endpoint \(r_j\) with \((l_j)_1 < (r_j)_1\). Write \(y_j(t)\) for the height at abscissa \(t\) of the line through \(l_j\) and \(r_j\). Let \(p_x\) be such that every point shared by two distinct segments has abscissa at least \(p_x\), let \(x < p_x\), and let \(T\) be a list of segments such that \((l_j)_1 \le x\) and \(p_x \le (r_j)_1\) for every \(j\) in \(T\). If \(y_j(x) < y_k(x)\) whenever \(j\) occurs before \(k\) in \(T\), then \(y_j(p_x) \le y_k(p_x)\) whenever \(j\) occurs before \(k\) in \(T\).
theorem pairwise_le_of_pairwise_lt {T : List (Fin n)} {x : π} (hx : x < px)
(hact : β j β T, (left S j).1 β€ x β§ px β€ (right S j).1)
(hT : T.Pairwise fun j k => lineY (left S j) (right S j) x < lineY (left S k) (right S k) x) :
T.Pairwise fun j k => lineY (left S j) (right S j) px β€ lineY (left S k) (right S k) px
def left (i : Fin n) : π Γ π := if (S i).1.1 β€ (S i).2.1 then (S i).1 else (S i).2
CSLibExt/Algorithms/Lean/Geometry/AnySegmentsIntersect.lean:352
def right (i : Fin n) : π Γ π := if (S i).1.1 β€ (S i).2.1 then (S i).2 else (S i).1
CSLibExt/Algorithms/Lean/Geometry/AnySegmentsIntersect.lean:355
def lineY (p q : π Γ π) (x : π) : π := p.2 + (x - p.1) * (q.2 - p.2) / (q.1 - p.1)
CSLibExt/Algorithms/Lean/Geometry/AnySegmentsIntersect.lean:80
Uses 4 Β· Used by 1
TheoremPhase one: the status list is strictly sorted between the processed and remaining events#βfully proved
Fix a number \(p_x\) in the field of coordinates. Suppose no segment is vertical (each segment's left endpoint has smaller \(x\)-coordinate than its right endpoint) and every point common to two distinct segments has \(x\)-coordinate at least \(p_x\). Split the sorted list of events as \(P\) followed by \(Q\), where the endpoint of every event of \(P\) has \(x\)-coordinate less than \(p_x\), and suppose running the sweep over \(P\) from the empty status list reports no intersection and ends with status list \(T\). Let \(x < p_x\) be at least the \(x\)-coordinate of the endpoint of every event of \(P\) and at most that of every event of \(Q\). Then whenever segment \(j\) comes before segment \(k\) in \(T\), the height at \(x\) of the line through the endpoints of \(j\) is less than that of the line through the endpoints of \(k\).
theorem run_pairwise_lt {P Q : List (Event n)} (hE : events S = P ++ Q)
(hP : β e β P, (point S e).1 < px) {T : List (Fin n)} (hT : run S P [] = some T) {x : π}
(hxP : β e β P, (point S e).1 β€ x) (hxQ : β e β Q, x β€ (point S e).1) (hx : x < px) :
T.Pairwise fun j k => lineY (left S j) (right S j) x < lineY (left S k) (right S k) x
abbrev Event (n : β) := Fin n Γ Bool
CSLibExt/Algorithms/Lean/Geometry/AnySegmentsIntersect.lean:358
def events : List (Event n) :=
((List.finRange n).map (Β·, true) ++ (List.finRange n).map (Β·, false)).mergeSort
fun e f => decide (key S e β€ key S f)
CSLibExt/Algorithms/Lean/Geometry/AnySegmentsIntersect.lean:368
def point (e : Event n) : π Γ π := if e.2 then left S e.1 else right S e.1
CSLibExt/Algorithms/Lean/Geometry/AnySegmentsIntersect.lean:361
def run : List (Event n) β List (Fin n) β Option (List (Fin n))
| [], T => some T
| e :: es, T => (step S e T).bind (run es)
CSLibExt/Algorithms/Lean/Geometry/AnySegmentsIntersect.lean:419
def lineY (p q : π Γ π) (x : π) : π := p.2 + (x - p.1) * (q.2 - p.2) / (q.1 - p.1)
CSLibExt/Algorithms/Lean/Geometry/AnySegmentsIntersect.lean:80
def left (i : Fin n) : π Γ π := if (S i).1.1 β€ (S i).2.1 then (S i).1 else (S i).2
CSLibExt/Algorithms/Lean/Geometry/AnySegmentsIntersect.lean:352
def right (i : Fin n) : π Γ π := if (S i).1.1 β€ (S i).2.1 then (S i).2 else (S i).1
CSLibExt/Algorithms/Lean/Geometry/AnySegmentsIntersect.lean:355
Uses 20 Β· Used by 1
TheoremThe status list is weakly sorted after the events left of a vertical line#βfully proved
Fix a number \(p_x\) in the field of coordinates. Suppose no segment is vertical (each segment's left endpoint has smaller \(x\)-coordinate than its right endpoint) and every point common to two distinct segments has \(x\)-coordinate at least \(p_x\). Split the sorted list of events as \(P\) followed by \(Q\), where the endpoint of every event of \(P\) has \(x\)-coordinate less than \(p_x\) and that of every event of \(Q\) has \(x\)-coordinate at least \(p_x\). If running the sweep over \(P\) from the empty status list reports no intersection and ends with status list \(T\), then whenever segment \(j\) comes before segment \(k\) in \(T\), the height at \(p_x\) of the line through the endpoints of \(j\) is at most that of the line through the endpoints of \(k\).
theorem run_pairwise_le_of_lt {P Q : List (Event n)} (hE : events S = P ++ Q)
(hP : β e β P, (point S e).1 < px) (hQ : β e β Q, px β€ (point S e).1) {T : List (Fin n)}
(hT : run S P [] = some T) :
T.Pairwise fun j k => lineY (left S j) (right S j) px β€ lineY (left S k) (right S k) px
abbrev Event (n : β) := Fin n Γ Bool
CSLibExt/Algorithms/Lean/Geometry/AnySegmentsIntersect.lean:358
def events : List (Event n) :=
((List.finRange n).map (Β·, true) ++ (List.finRange n).map (Β·, false)).mergeSort
fun e f => decide (key S e β€ key S f)
CSLibExt/Algorithms/Lean/Geometry/AnySegmentsIntersect.lean:368
def point (e : Event n) : π Γ π := if e.2 then left S e.1 else right S e.1
CSLibExt/Algorithms/Lean/Geometry/AnySegmentsIntersect.lean:361
def run : List (Event n) β List (Fin n) β Option (List (Fin n))
| [], T => some T
| e :: es, T => (step S e T).bind (run es)
CSLibExt/Algorithms/Lean/Geometry/AnySegmentsIntersect.lean:419
def lineY (p q : π Γ π) (x : π) : π := p.2 + (x - p.1) * (q.2 - p.2) / (q.1 - p.1)
CSLibExt/Algorithms/Lean/Geometry/AnySegmentsIntersect.lean:80
def left (i : Fin n) : π Γ π := if (S i).1.1 β€ (S i).2.1 then (S i).1 else (S i).2
CSLibExt/Algorithms/Lean/Geometry/AnySegmentsIntersect.lean:352
def right (i : Fin n) : π Γ π := if (S i).1.1 β€ (S i).2.1 then (S i).2 else (S i).1
CSLibExt/Algorithms/Lean/Geometry/AnySegmentsIntersect.lean:355
Uses 11 Β· Used by 2
TheoremPhase two: inserting left endpoints on a vertical line keeps the status weakly sorted#βfully proved
Fix a number \(p_x\) in the field of coordinates. Suppose no segment is vertical (each segment's left endpoint has smaller \(x\)-coordinate than its right endpoint) and every point common to two distinct segments has \(x\)-coordinate at least \(p_x\). Split the sorted list of events as \(P_1\), then \(P_2\), then \(Q\), where the endpoint of every event of \(P_1\) has \(x\)-coordinate less than \(p_x\), every event of \(P_2\) is a left endpoint with \(x\)-coordinate equal to \(p_x\), and the endpoint of every event of \(Q\) has \(x\)-coordinate at least \(p_x\). If running the sweep over \(P_1\) followed by \(P_2\) from the empty status list reports no intersection and ends with status list \(T\), then whenever segment \(j\) comes before segment \(k\) in \(T\), the height at \(p_x\) of the line through the endpoints of \(j\) is at most that of the line through the endpoints of \(k\).
theorem run_pairwise_le {Pβ Pβ Q : List (Event n)} (hE : events S = Pβ ++ Pβ ++ Q)
(hPβ : β e β Pβ, (point S e).1 < px) (hPβ : β e β Pβ, e.2 = true β§ (point S e).1 = px)
(hQ : β e β Q, px β€ (point S e).1) {T : List (Fin n)} (hT : run S (Pβ ++ Pβ) [] = some T) :
T.Pairwise fun j k => lineY (left S j) (right S j) px β€ lineY (left S k) (right S k) px
abbrev Event (n : β) := Fin n Γ Bool
CSLibExt/Algorithms/Lean/Geometry/AnySegmentsIntersect.lean:358
def events : List (Event n) :=
((List.finRange n).map (Β·, true) ++ (List.finRange n).map (Β·, false)).mergeSort
fun e f => decide (key S e β€ key S f)
CSLibExt/Algorithms/Lean/Geometry/AnySegmentsIntersect.lean:368
def point (e : Event n) : π Γ π := if e.2 then left S e.1 else right S e.1
CSLibExt/Algorithms/Lean/Geometry/AnySegmentsIntersect.lean:361
def run : List (Event n) β List (Fin n) β Option (List (Fin n))
| [], T => some T
| e :: es, T => (step S e T).bind (run es)
CSLibExt/Algorithms/Lean/Geometry/AnySegmentsIntersect.lean:419
def lineY (p q : π Γ π) (x : π) : π := p.2 + (x - p.1) * (q.2 - p.2) / (q.1 - p.1)
CSLibExt/Algorithms/Lean/Geometry/AnySegmentsIntersect.lean:80
def left (i : Fin n) : π Γ π := if (S i).1.1 β€ (S i).2.1 then (S i).1 else (S i).2
CSLibExt/Algorithms/Lean/Geometry/AnySegmentsIntersect.lean:352
def right (i : Fin n) : π Γ π := if (S i).1.1 β€ (S i).2.1 then (S i).2 else (S i).1
CSLibExt/Algorithms/Lean/Geometry/AnySegmentsIntersect.lean:355
Uses 14 Β· Used by 1
TheoremSweep completeness when the leftmost intersection is inside both segments#βfully proved
Let \(n\) segments in the plane over a linearly ordered field be given, where \(z_1\) is the abscissa of a point \(z\) and segment \(i\) has left endpoint \(l_i\) and right endpoint \(r_i\) with \((l_i)_1 < (r_i)_1\), and suppose no point lies on three distinct segments. Let \(a \ne b\) be segments that share a point \(p\) such that every point shared by two distinct segments has abscissa at least \(p_1\), and suppose \((l_a)_1 < p_1\) and \((l_b)_1 < p_1\). Then the sweep, run on the sorted list of endpoint events from the empty status list, reports an intersection.
Just before the sweep line reaches \(p\), the segments \(a\) and \(b\) are neighbours on the status list, so they were tested.
theorem run_eq_none_of_lt {a b : Fin n} (hab : a β b) {p : π Γ π}
(hpa : p β segment π (left S a) (right S a)) (hpb : p β segment π (left S b) (right S b))
(hmin : β i j z, i β j β z β segment π (left S i) (right S i) β
z β segment π (left S j) (right S j) β p.1 β€ z.1)
(hla : (left S a).1 < p.1) (hlb : (left S b).1 < p.1) : run S (events S) [] = none
def left (i : Fin n) : π Γ π := if (S i).1.1 β€ (S i).2.1 then (S i).1 else (S i).2
CSLibExt/Algorithms/Lean/Geometry/AnySegmentsIntersect.lean:352
def right (i : Fin n) : π Γ π := if (S i).1.1 β€ (S i).2.1 then (S i).2 else (S i).1
CSLibExt/Algorithms/Lean/Geometry/AnySegmentsIntersect.lean:355
def run : List (Event n) β List (Fin n) β Option (List (Fin n))
| [], T => some T
| e :: es, T => (step S e T).bind (run es)
CSLibExt/Algorithms/Lean/Geometry/AnySegmentsIntersect.lean:419
def events : List (Event n) :=
((List.finRange n).map (Β·, true) ++ (List.finRange n).map (Β·, false)).mergeSort
fun e f => decide (key S e β€ key S f)
CSLibExt/Algorithms/Lean/Geometry/AnySegmentsIntersect.lean:368
Uses 15 Β· Used by 1
TheoremSweep completeness when the leftmost intersection is a left endpoint#βfully proved
Let \(n\) segments in the plane over a linearly ordered field be given, where \(z_1\) is the abscissa of a point \(z\) and segment \(i\) has left endpoint \(l_i\) and right endpoint \(r_i\) with \((l_i)_1 < (r_i)_1\), and suppose no point lies on three distinct segments. Let \(a \ne b\) be segments such that \(l_a\) lies on segment \(b\) and every point shared by two distinct segments has abscissa at least \((l_a)_1\). If the left endpoint of \(b\) comes before the left endpoint of \(a\) in the sorted list of endpoint events, then the sweep, run on that list from the empty status list, reports an intersection.
Inserting \(a\) places it right next to \(b\), so the two are tested.
theorem run_eq_none_of_left {a b : Fin n} (hab : a β b)
(hpb : left S a β segment π (left S b) (right S b))
(hmin : β i j z, i β j β z β segment π (left S i) (right S i) β
z β segment π (left S j) (right S j) β (left S a).1 β€ z.1)
{P Q : List (Event n)} (hE : events S = P ++ (a, true) :: Q) (hbP : (b, true) β P) :
run S (events S) [] = none
def left (i : Fin n) : π Γ π := if (S i).1.1 β€ (S i).2.1 then (S i).1 else (S i).2
CSLibExt/Algorithms/Lean/Geometry/AnySegmentsIntersect.lean:352
def right (i : Fin n) : π Γ π := if (S i).1.1 β€ (S i).2.1 then (S i).2 else (S i).1
CSLibExt/Algorithms/Lean/Geometry/AnySegmentsIntersect.lean:355
abbrev Event (n : β) := Fin n Γ Bool
CSLibExt/Algorithms/Lean/Geometry/AnySegmentsIntersect.lean:358
def events : List (Event n) :=
((List.finRange n).map (Β·, true) ++ (List.finRange n).map (Β·, false)).mergeSort
fun e f => decide (key S e β€ key S f)
CSLibExt/Algorithms/Lean/Geometry/AnySegmentsIntersect.lean:368
def run : List (Event n) β List (Fin n) β Option (List (Fin n))
| [], T => some T
| e :: es, T => (step S e T).bind (run es)
CSLibExt/Algorithms/Lean/Geometry/AnySegmentsIntersect.lean:419
Uses 20 Β· Used by 1
TheoremA leftmost intersection point#βfully proved
Let \(\Bbbk\) be a linearly ordered field, let \(s_0, \dots, s_{n-1}\) be closed segments in \(\Bbbk^2\), none of them vertical, and write \(z_x\) for the \(x\)-coordinate of a point \(z\). If some \(s_i\) and \(s_j\) with \(i \ne j\) meet, then there are indices \(a \ne b\) and a point \(p \in s_a \cap s_b\) such that \(p_x \le z_x\) for all indices \(k \ne l\) and every point \(z \in s_k \cap s_l\).
theorem exists_leftmost_meet (h : β i j, i β j β§ Meets S i j) :
β a b p, a β b β§ p β segment π (left S a) (right S a) β§
p β segment π (left S b) (right S b) β§
β i j z, i β j β z β segment π (left S i) (right S i) β
z β segment π (left S j) (right S j) β p.1 β€ z.1
def Meets (S : Fin n β (π Γ π) Γ (π Γ π)) (i j : Fin n) : Prop :=
(segment π (left S i) (right S i) β© segment π (left S j) (right S j)).Nonempty
CSLibExt/Algorithms/Lean/Geometry/AnySegmentsIntersect.lean:629
def left (i : Fin n) : π Γ π := if (S i).1.1 β€ (S i).2.1 then (S i).1 else (S i).2
CSLibExt/Algorithms/Lean/Geometry/AnySegmentsIntersect.lean:352
def right (i : Fin n) : π Γ π := if (S i).1.1 β€ (S i).2.1 then (S i).2 else (S i).1
CSLibExt/Algorithms/Lean/Geometry/AnySegmentsIntersect.lean:355
Uses 4 Β· Used by 1
TheoremCompleteness of the segment-intersection sweep#βfully proved
Let \(n\) segments in the plane over a linearly ordered field be given, none of them vertical (the left endpoint of each has strictly smaller abscissa than its right endpoint), and assume, as CLRS does, that no point lies on three distinct segments. If two distinct segments meet, then the sweep, run on the sorted list of endpoint events from the empty status list, reports an intersection.
theorem run_eq_none_of_meets
(h3 : β i j k, i β j β j β k β i β k β β z, z β segment π (left S i) (right S i) β
z β segment π (left S j) (right S j) β z β segment π (left S k) (right S k))
(h : β i j, i β j β§ Meets S i j) : run S (events S) [] = none
def left (i : Fin n) : π Γ π := if (S i).1.1 β€ (S i).2.1 then (S i).1 else (S i).2
CSLibExt/Algorithms/Lean/Geometry/AnySegmentsIntersect.lean:352
def right (i : Fin n) : π Γ π := if (S i).1.1 β€ (S i).2.1 then (S i).2 else (S i).1
CSLibExt/Algorithms/Lean/Geometry/AnySegmentsIntersect.lean:355
def Meets (S : Fin n β (π Γ π) Γ (π Γ π)) (i j : Fin n) : Prop :=
(segment π (left S i) (right S i) β© segment π (left S j) (right S j)).Nonempty
CSLibExt/Algorithms/Lean/Geometry/AnySegmentsIntersect.lean:629
def run : List (Event n) β List (Fin n) β Option (List (Fin n))
| [], T => some T
| e :: es, T => (step S e T).bind (run es)
CSLibExt/Algorithms/Lean/Geometry/AnySegmentsIntersect.lean:419
def events : List (Event n) :=
((List.finRange n).map (Β·, true) ++ (List.finRange n).map (Β·, false)).mergeSort
fun e f => decide (key S e β€ key S f)
CSLibExt/Algorithms/Lean/Geometry/AnySegmentsIntersect.lean:368
Uses 13 Β· Used by 1
Cost
DefinitionCost charged to a sweep event#βfully proved
For \(n\) segments, the charge of an event is \(n + 16\) if it is the left endpoint of a segment and \(8\) if it is the right endpoint of a segment.
These charges bound the actual costs: a left endpoint scans at most \(n\) segments of the status list and runs two SEGMENTS-INTERSECT tests, and a right endpoint runs one test.
def eventCost (n : β) : Event n β β
| (_, true) => n + 16
| (_, false) => 8
abbrev Event (n : β) := Fin n Γ Bool
CSLibExt/Algorithms/Lean/Geometry/AnySegmentsIntersect.lean:358
Uses 1 Β· Used by 1
DefinitionANY-SEGMENTS-INTERSECT#βfully proved
Let \(\Bbbk\) be a linearly ordered field. Given \(n\) segments \(s_0, \dots, s_{n-1}\) in \(\Bbbk^2\), each given by its two endpoints, write \(l_t\), the left endpoint of \(s_t\), for its endpoint with the smaller \(x\)-coordinate, or for its first given endpoint when both \(x\)-coordinates agree, and \(r_t\), the right endpoint, for the other one. The procedure sorts the \(2n\) endpoints by \(x\)-coordinate, left endpoints before right endpoints at equal \(x\), then by \(y\)-coordinate, with remaining ties in increasing order of segment index. It then sweeps a vertical line across them, starting with an empty status list of segments, kept from bottom to top. At the left endpoint \(l_i\) of \(s_i\), let \(P\) be the longest initial part of the status list consisting of segments \(s_t\) with \(\mathrm{DIRECTION}(l_t, r_t, l_i) < 0\). Then \(s_i\) is tested with SEGMENTS-INTERSECT first against the segment just after \(P\) and then against the last segment of \(P\), when these exist, and is inserted directly after \(P\). At the right endpoint of \(s_i\), the segments just before and just after \(s_i\) in the status list, when both exist, are tested against each other and \(s_i\) is deleted. The procedure returns true as soon as a test succeeds and false after the last event. Cost counts one unit per evaluation of DIRECTION or ON-SEGMENT (CLRS, third edition, Section 33.2).
The status is kept in a list rather than CLRS's red-black tree.
def anySegmentsIntersect {n : β} (S : Fin n β (π Γ π) Γ (π Γ π)) : TimeM β Bool :=
AnySegments.sweep S (AnySegments.events S) []
def sweep : List (Event n) β List (Fin n) β TimeM β Bool
| [], _ => pure false
| (i, true) :: es, T => do
β[min ((T.takeWhile (below S Β· (left S i))).length + 1) T.length]
let bβ β testOpt S i (T.dropWhile (below S Β· (left S i))).head?
if bβ then pure true else do
let bβ β testOpt S i (T.takeWhile (below S Β· (left S i))).getLast?
if bβ then pure true else
sweep es (T.takeWhile (below S Β· (left S i)) ++ i :: T.dropWhile (below S Β· (left S i)))
| (i, false) :: es, T => do
let b β testPair S (T.takeWhile (Β· != i)).getLast? (T.dropWhile (Β· != i)).tail.head?
if b then pure true else sweep es (T.takeWhile (Β· != i) ++ (T.dropWhile (Β· != i)).tail)
CSLibExt/Algorithms/Lean/Geometry/AnySegmentsIntersect.lean:394
def events : List (Event n) :=
((List.finRange n).map (Β·, true) ++ (List.finRange n).map (Β·, false)).mergeSort
fun e f => decide (key S e β€ key S f)
CSLibExt/Algorithms/Lean/Geometry/AnySegmentsIntersect.lean:368
Uses 2 Β· Used by 2
TheoremCorrectness of ANY-SEGMENTS-INTERSECT#βfully proved
Let \(\Bbbk\) be a linearly ordered field and let \(s_0, \dots, s_{n-1}\) be closed segments in \(\Bbbk^2\), each given by its two endpoints in either order. Suppose no segment is vertical (its two endpoints have different \(x\)-coordinates) and no point lies on three segments \(s_i\), \(s_j\), \(s_k\) with \(i\), \(j\), \(k\) pairwise distinct. Then ANY-SEGMENTS-INTERSECT returns true on these segments if and only if there are indices \(i \ne j\) such that \(s_i\) and \(s_j\) intersect (CLRS, third edition, Theorem 33.1).
theorem anySegmentsIntersect_ret_eq_true_iff {n : β} (S : Fin n β (π Γ π) Γ (π Γ π))
(hv : β i, (S i).1.1 β (S i).2.1)
(h3 : β i j k, i β j β j β k β i β k β
segment π (S i).1 (S i).2 β© segment π (S j).1 (S j).2 β© segment π (S k).1 (S k).2 = β
) :
(anySegmentsIntersect S).ret = true β
β i j, i β j β§ (segment π (S i).1 (S i).2 β© segment π (S j).1 (S j).2).Nonempty
def anySegmentsIntersect {n : β} (S : Fin n β (π Γ π) Γ (π Γ π)) : TimeM β Bool :=
AnySegments.sweep S (AnySegments.events S) []
CSLibExt/Algorithms/Lean/Geometry/AnySegmentsIntersect.lean:1321
Uses 13
TheoremRunning time of ANY-SEGMENTS-INTERSECT#βfully proved
Let \(\Bbbk\) be a field with a linear order. For every \(n\) segments in \(\Bbbk^2\), each given by its two endpoints, ANY-SEGMENTS-INTERSECT costs at most \(n^2 + 24n\), so it runs in time \(O(n^2)\). Cost counts one unit per evaluation of DIRECTION or ON-SEGMENT.
The bound comes from at most \(n\) DIRECTION evaluations to place each segment in the list-based status and at most three SEGMENTS-INTERSECT tests per segment.
theorem anySegmentsIntersect_time_le {n : β} (S : Fin n β (π Γ π) Γ (π Γ π)) :
(anySegmentsIntersect S).time β€ n * n + 24 * n
def anySegmentsIntersect {n : β} (S : Fin n β (π Γ π) Γ (π Γ π)) : TimeM β Bool :=
AnySegments.sweep S (AnySegments.events S) []
CSLibExt/Algorithms/Lean/Geometry/AnySegmentsIntersect.lean:1321
Uses 17
Loading dependency explorerβ¦
The dependency explorer needs JavaScript and its graph data.