IndisputableMonolith.Mathematics.DistanceShellMultiplicity
IndisputableMonolith/Mathematics/DistanceShellMultiplicity.lean · 5701 lines · 337 declarations
show as:
view math explainer →
1import IndisputableMonolith.Mathematics.BipartiteDistanceSpectrum
2
3/-!
4# Distance Shell Multiplicity
5
6This module records the RS physicalization of Erdős problem #132.
7
8Classically, a distance value is a shell in the set of pairwise Euclidean
9distances. Physically, it is a two-body recognition-energy shell. Its
10multiplicity is the shell occupancy.
11
12We use ordered pairs for Lean simplicity. For a positive distance, ordered
13multiplicity is exactly twice the usual unordered multiplicity, so the classical
14threshold `≤ n` becomes `≤ 2n`.
15-/
16
17namespace IndisputableMonolith
18namespace Mathematics
19namespace DistanceShellMultiplicity
20
21open Filter
22open scoped Topology
23
24noncomputable section
25
26abbrev Point2 := BipartiteDistanceSpectrum.Point2
27
28/-- Ordered non-diagonal pair events in a finite planar set. -/
29noncomputable def orderedPairEvents (A : Finset Point2) : Finset (Point2 × Point2) := by
30 classical
31 exact (A.product A).filter (fun pq => pq.1 ≠ pq.2)
32
33/-- The ordered distance spectrum of a finite planar set. -/
34noncomputable def orderedDistanceSpectrum (A : Finset Point2) : Finset ℝ := by
35 classical
36 exact (orderedPairEvents A).image (fun pq => dist pq.1 pq.2)
37
38/-- Ordered multiplicity of one distance shell. -/
39noncomputable def orderedShellMultiplicity (A : Finset Point2) (r : ℝ) : ℕ := by
40 classical
41 exact ((orderedPairEvents A).filter (fun pq => dist pq.1 pq.2 = r)).card
42
43/-- A sparse shell in ordered-pair normalization. This is the classical
44condition "unordered multiplicity at most `n`" written as ordered multiplicity
45at most `2n`. -/
46def SparseShell (A : Finset Point2) (r : ℝ) : Prop :=
47 r ∈ orderedDistanceSpectrum A ∧ orderedShellMultiplicity A r ≤ 2 * A.card
48
49/-- Diameter shell, expressed by the maximum-distance predicate. -/
50def IsDiameterShell (A : Finset Point2) (r : ℝ) : Prop :=
51 r ∈ orderedDistanceSpectrum A ∧
52 ∀ s ∈ orderedDistanceSpectrum A, s ≤ r
53
54/-- The diameter value of a finite planar set is nonnegative because it is the
55distance between two points in the set. -/
56theorem diameter_shell_nonneg
57 {A : Finset Point2} {Δ : ℝ} (hΔ : IsDiameterShell A Δ) :
58 0 ≤ Δ := by
59 classical
60 obtain ⟨pq, _, hpq⟩ := Finset.mem_image.mp hΔ.1
61 rw [← hpq]
62 exact dist_nonneg
63
64/-- The diameter value is uniquely determined by the set: it is the maximum of
65the ordered distance spectrum, and two maxima of the same set are equal. -/
66theorem isDiameterShell_unique
67 {A : Finset Point2} {Δ₁ Δ₂ : ℝ}
68 (h₁ : IsDiameterShell A Δ₁) (h₂ : IsDiameterShell A Δ₂) :
69 Δ₁ = Δ₂ :=
70 le_antisymm (h₂.2 _ h₁.1) (h₁.2 _ h₂.1)
71
72/-- Every pairwise distance in `A` is bounded by the diameter, including the
73case where both points coincide. -/
74theorem dist_le_of_diameter_shell
75 {A : Finset Point2} {Δ : ℝ} (hΔ : IsDiameterShell A Δ)
76 {x y : Point2} (hx : x ∈ A) (hy : y ∈ A) :
77 dist x y ≤ Δ := by
78 classical
79 by_cases hxy : x = y
80 · subst hxy
81 have h0 : dist x x = 0 := by simp
82 rw [h0]
83 exact diameter_shell_nonneg hΔ
84 · have hd : dist x y ∈ orderedDistanceSpectrum A := by
85 unfold orderedDistanceSpectrum
86 refine Finset.mem_image.mpr ⟨(x, y), ?_, rfl⟩
87 unfold orderedPairEvents
88 refine Finset.mem_filter.mpr ⟨?_, hxy⟩
89 exact Finset.mem_product.mpr ⟨hx, hy⟩
90 exact hΔ.2 _ hd
91
92
93/-- Erdős #132 in ordered-pair normalization: for every sufficiently large
94finite planar set there are two distinct sparse distance shells. -/
95def Erdos132Ordered : Prop :=
96 ∀ᶠ n in atTop,
97 ∀ A : Finset Point2,
98 A.card = n →
99 ∃ r s : ℝ,
100 r ≠ s ∧ SparseShell A r ∧ SparseShell A s
101
102/-- Stronger RS target suggested by the shell-flux reading: the number of sparse
103shells should diverge. -/
104def SparseShellsDiverge : Prop :=
105 Tendsto
106 (fun n : ℕ =>
107 sInf
108 {k : ℝ |
109 ∀ A : Finset Point2,
110 A.card = n →
111 k ≤ ((orderedDistanceSpectrum A).filter
112 (fun r => orderedShellMultiplicity A r ≤ 2 * A.card)).card})
113 atTop
114 atTop
115
116/-- Missing bridge named by the RS derivation: once the diameter shell is peeled
117off, shell-flux conservation forces at least one further sparse shell. -/
118def SecondSparseShellFluxBridge : Prop :=
119 ∀ᶠ n in atTop,
120 ∀ A : Finset Point2,
121 A.card = n →
122 ∀ Δ : ℝ,
123 IsDiameterShell A Δ →
124 ∃ r : ℝ, r ≠ Δ ∧ SparseShell A r
125
126/-- The shell-flux bridge implies Erdős #132, because Hopf-Pannwitz supplies
127the diameter shell as the first sparse shell. We leave Hopf-Pannwitz as the
128classical input in this statement surface. -/
129def HopfPannwitzOrderedDiameterBound : Prop :=
130 ∀ᶠ n in atTop,
131 ∀ A : Finset Point2,
132 A.card = n →
133 ∃ Δ : ℝ, IsDiameterShell A Δ ∧ SparseShell A Δ
134
135/-- Existence of a diameter shell for sufficiently large finite planar sets.
136This is finite-order bookkeeping: the nonempty ordered distance spectrum has
137a maximum. It is separated from Hopf-Pannwitz because the latter's genuine
138geometry is the sparsity bound, not maximum existence. -/
139def DiameterShellExistsEventually : Prop :=
140 ∀ᶠ n in atTop,
141 ∀ A : Finset Point2,
142 A.card = n →
143 ∃ Δ : ℝ, IsDiameterShell A Δ
144
145/-- Hopf-Pannwitz sparsity component: every diameter shell is sparse in the
146ordered normalization. This is the straight-line-thrackle theorem bridge. -/
147def DiameterShellSparseBound : Prop :=
148 ∀ᶠ n in atTop,
149 ∀ A : Finset Point2,
150 A.card = n →
151 ∀ Δ : ℝ, IsDiameterShell A Δ → SparseShell A Δ
152
153/-- Ordered diameter-edge set for a given shell value. -/
154noncomputable def diameterOrderedEdges (A : Finset Point2) (Δ : ℝ) :
155 Finset (Point2 × Point2) := by
156 classical
157 exact (orderedPairEvents A).filter (fun pq => dist pq.1 pq.2 = Δ)
158
159/-- Ordered diameter multiplicity is the cardinality of the ordered diameter
160edge set. -/
161theorem orderedShellMultiplicity_eq_diameterOrderedEdges_card
162 (A : Finset Point2) (Δ : ℝ) :
163 orderedShellMultiplicity A Δ = (diameterOrderedEdges A Δ).card := by
164 rfl
165
166/-- An ordered diameter edge has both endpoints in `A`, distinct, and distance
167exactly Δ. -/
168theorem diameter_ordered_edge_data
169 {A : Finset Point2} {Δ : ℝ}
170 {e : Point2 × Point2} (he : e ∈ diameterOrderedEdges A Δ) :
171 e.1 ∈ A ∧ e.2 ∈ A ∧ e.1 ≠ e.2 ∧ dist e.1 e.2 = Δ := by
172 classical
173 have heFilter := Finset.mem_filter.mp he
174 have heDist : dist e.1 e.2 = Δ := heFilter.2
175 have heEvents := Finset.mem_filter.mp heFilter.1
176 have heProd := Finset.mem_product.mp heEvents.1
177 exact ⟨heProd.1, heProd.2, heEvents.2, heDist⟩
178
179/-- Convenience bundle: all four cross-distances between two ordered diameter
180edges are bounded by the diameter, and both edge-distances equal Δ. -/
181theorem diameter_ordered_edges_cross_distances_le
182 {A : Finset Point2} {Δ : ℝ}
183 (hΔ : IsDiameterShell A Δ)
184 {e f : Point2 × Point2}
185 (he : e ∈ diameterOrderedEdges A Δ)
186 (hf : f ∈ diameterOrderedEdges A Δ) :
187 dist e.1 e.2 = Δ ∧ dist f.1 f.2 = Δ ∧
188 dist e.1 f.1 ≤ Δ ∧ dist e.1 f.2 ≤ Δ ∧
189 dist e.2 f.1 ≤ Δ ∧ dist e.2 f.2 ≤ Δ := by
190 rcases diameter_ordered_edge_data he with ⟨he1A, he2A, _, heDist⟩
191 rcases diameter_ordered_edge_data hf with ⟨hf1A, hf2A, _, hfDist⟩
192 refine ⟨heDist, hfDist, ?_, ?_, ?_, ?_⟩
193 · exact dist_le_of_diameter_shell hΔ he1A hf1A
194 · exact dist_le_of_diameter_shell hΔ he1A hf2A
195 · exact dist_le_of_diameter_shell hΔ he2A hf1A
196 · exact dist_le_of_diameter_shell hΔ he2A hf2A
197
198/-- Diameter sparsity stripped to its real content: the ordered diameter shell
199has at most `2n` directed events. Membership in the spectrum comes separately
200from `IsDiameterShell`. -/
201def DiameterShellOrderedMultiplicityBound : Prop :=
202 ∀ᶠ n in atTop,
203 ∀ A : Finset Point2,
204 A.card = n →
205 ∀ Δ : ℝ,
206 IsDiameterShell A Δ →
207 orderedShellMultiplicity A Δ ≤ 2 * A.card
208
209/-- The ordered multiplicity bound implies the sparse-shell bridge. -/
210theorem diameter_shell_sparse_from_ordered_bound
211 (hBound : DiameterShellOrderedMultiplicityBound) :
212 DiameterShellSparseBound := by
213 filter_upwards [hBound] with n hBoundN
214 intro A hA Δ hΔ
215 exact ⟨hΔ.1, hBoundN A hA Δ hΔ⟩
216
217/-- Closed line segment between two visible planar states. -/
218def OnClosedSegment (a b x : Point2) : Prop :=
219 ∃ t : ℝ, 0 ≤ t ∧ t ≤ 1 ∧ x = (1 - t) • a + t • b
220
221/-- The left endpoint lies on its closed segment. -/
222theorem left_endpoint_on_segment (a b : Point2) :
223 OnClosedSegment a b a := by
224 refine ⟨0, by norm_num, by norm_num, ?_⟩
225 simp
226
227/-- The right endpoint lies on its closed segment. -/
228theorem right_endpoint_on_segment (a b : Point2) :
229 OnClosedSegment a b b := by
230 refine ⟨1, by norm_num, by norm_num, ?_⟩
231 simp
232
233/-- A closed segment is symmetric in its endpoints. -/
234theorem on_closed_segment_symm
235 {a b x : Point2} (h : OnClosedSegment a b x) :
236 OnClosedSegment b a x := by
237 rcases h with ⟨t, h0, h1, hx⟩
238 refine ⟨1 - t, by linarith, by linarith, ?_⟩
239 rw [hx]
240 module
241
242/-- Symmetry as an iff. -/
243theorem on_closed_segment_comm (a b x : Point2) :
244 OnClosedSegment a b x ↔ OnClosedSegment b a x :=
245 ⟨on_closed_segment_symm, on_closed_segment_symm⟩
246
247/-- The midpoint of `[a, b]` lies on the closed segment. -/
248theorem midpoint_on_closed_segment (a b : Point2) :
249 OnClosedSegment a b ((1 / 2 : ℝ) • a + (1 / 2 : ℝ) • b) := by
250 refine ⟨(1 / 2 : ℝ), by norm_num, by norm_num, ?_⟩
251 module
252
253/-- A closed segment is convex under affine combinations: any weighted combo of
254two points on `[a, b]` is again on `[a, b]`. -/
255theorem on_closed_segment_convex
256 {a b x y : Point2}
257 (hx : OnClosedSegment a b x) (hy : OnClosedSegment a b y)
258 {s : ℝ} (hs0 : 0 ≤ s) (hs1 : s ≤ 1) :
259 OnClosedSegment a b ((1 - s) • x + s • y) := by
260 rcases hx with ⟨t₁, ht₁0, ht₁1, hx_eq⟩
261 rcases hy with ⟨t₂, ht₂0, ht₂1, hy_eq⟩
262 refine ⟨(1 - s) * t₁ + s * t₂, ?_, ?_, ?_⟩
263 · nlinarith
264 · nlinarith
265 · rw [hx_eq, hy_eq]
266 module
267
268/-- The degenerate segment `[a, a]` contains only the point `a`. -/
269theorem on_closed_segment_self_eq
270 {a x : Point2} (hx : OnClosedSegment a a x) :
271 x = a := by
272 rcases hx with ⟨t, _, _, hx_eq⟩
273 rw [hx_eq]
274 module
275
276/-- Triangle equality on a closed segment: any interior point `x` satisfies
277`dist a x + dist x b = dist a b`. -/
278theorem dist_add_on_closed_segment
279 {a b x : Point2} (hx : OnClosedSegment a b x) :
280 dist a x + dist x b = dist a b := by
281 rcases hx with ⟨t, h0, h1, hx_eq⟩
282 rw [hx_eq, dist_eq_norm, dist_eq_norm, dist_eq_norm]
283 have h_left : a - ((1 - t) • a + t • b) = t • (a - b) := by module
284 have h_right : ((1 - t) • a + t • b) - b = (1 - t) • (a - b) := by module
285 rw [h_left, h_right, norm_smul, norm_smul, Real.norm_eq_abs, Real.norm_eq_abs,
286 abs_of_nonneg h0, abs_of_nonneg (by linarith : (0 : ℝ) ≤ 1 - t)]
287 ring
288
289/-- Either endpoint distance is dominated by the segment length. -/
290theorem dist_left_le_of_on_closed_segment
291 {a b x : Point2} (hx : OnClosedSegment a b x) :
292 dist a x ≤ dist a b := by
293 have hadd := dist_add_on_closed_segment hx
294 have hpos : 0 ≤ dist x b := dist_nonneg
295 linarith
296
297/-- Either endpoint distance is dominated by the segment length. -/
298theorem dist_right_le_of_on_closed_segment
299 {a b x : Point2} (hx : OnClosedSegment a b x) :
300 dist x b ≤ dist a b := by
301 have hadd := dist_add_on_closed_segment hx
302 have hpos : 0 ≤ dist a x := dist_nonneg
303 linarith
304
305/-- If a point on `[a,b]` is as far from `a` as `b` is, then it is `b`. -/
306theorem eq_right_of_on_closed_segment_of_dist_left_eq
307 {a b x : Point2} (hx : OnClosedSegment a b x)
308 (hd : dist a x = dist a b) :
309 x = b := by
310 have hadd := dist_add_on_closed_segment hx
311 have hxb : dist x b = 0 := by linarith [hadd, hd]
312 exact eq_of_dist_eq_zero hxb
313
314/-- If a point on `[a,b]` is as far from `b` as `a` is, then it is `a`. -/
315theorem eq_left_of_on_closed_segment_of_dist_right_eq
316 {a b x : Point2} (hx : OnClosedSegment a b x)
317 (hd : dist x b = dist a b) :
318 x = a := by
319 have hadd := dist_add_on_closed_segment hx
320 have hax : dist a x = 0 := by linarith [hadd, hd]
321 exact eq_of_dist_eq_zero (by simpa [dist_comm] using hax)
322
323/-- `OnClosedSegment` is the same as Mathlib's `segment ℝ`, unlocking the full
324convex-segment library. -/
325theorem onClosedSegment_iff_mem_segment
326 (a b x : Point2) :
327 OnClosedSegment a b x ↔ x ∈ segment ℝ a b := by
328 constructor
329 · rintro ⟨t, h0, h1, hx⟩
330 refine ⟨1 - t, t, by linarith, h0, by ring, ?_⟩
331 rw [← hx]
332 · rintro ⟨s, t, hs, ht, hst, hx⟩
333 refine ⟨t, ht, ?_, ?_⟩
334 · linarith
335 · have hs_eq : s = 1 - t := by linarith
336 rw [← hx, hs_eq]
337
338/-- An interior point of a closed segment that is not an endpoint has strict
339parameter `0 < t < 1`. -/
340theorem on_closed_segment_strict
341 {a b x : Point2} (hx : OnClosedSegment a b x)
342 (hxa : x ≠ a) (hxb : x ≠ b) :
343 ∃ t : ℝ, 0 < t ∧ t < 1 ∧ x = (1 - t) • a + t • b := by
344 rcases hx with ⟨t, h0, h1, hx_eq⟩
345 refine ⟨t, ?_, ?_, hx_eq⟩
346 · by_contra h
347 push_neg at h
348 have ht : t = 0 := le_antisymm h h0
349 apply hxa
350 rw [hx_eq, ht]
351 module
352 · by_contra h
353 push_neg at h
354 have ht : t = 1 := le_antisymm h1 h
355 apply hxb
356 rw [hx_eq, ht]
357 module
358
359/-- Two ordered edges meet geometrically if their closed straight-line segments
360intersect. -/
361def OrderedEdgesMeetGeometrically
362 (e f : Point2 × Point2) : Prop :=
363 ∃ x : Point2, OnClosedSegment e.1 e.2 x ∧ OnClosedSegment f.1 f.2 x
364
365/-- Two ordered edges are geometrically disjoint when their closed straight-line
366segments do not intersect. This is the correct Hopf-Pannwitz / thrackle
367predicate; endpoint-disjointness alone is too strong and would wrongly exclude
368crossing diameter diagonals. -/
369def OrderedEdgesGeometricallyDisjoint
370 (e f : Point2 × Point2) : Prop :=
371 ¬ OrderedEdgesMeetGeometrically e f
372
373/-- Geometric meeting is symmetric in the two ordered edges. -/
374theorem ordered_edges_meet_symm
375 {e f : Point2 × Point2} (h : OrderedEdgesMeetGeometrically e f) :
376 OrderedEdgesMeetGeometrically f e := by
377 rcases h with ⟨x, hex, hfx⟩
378 exact ⟨x, hfx, hex⟩
379
380/-- Symmetric form of the meeting predicate. -/
381theorem ordered_edges_meet_comm (e f : Point2 × Point2) :
382 OrderedEdgesMeetGeometrically e f ↔ OrderedEdgesMeetGeometrically f e :=
383 ⟨ordered_edges_meet_symm, ordered_edges_meet_symm⟩
384
385/-- Swapping the endpoints of the first edge preserves geometric meeting,
386because the closed segment is symmetric in its endpoints. -/
387theorem ordered_edges_meet_swap_left
388 {a b : Point2} {f : Point2 × Point2}
389 (h : OrderedEdgesMeetGeometrically (a, b) f) :
390 OrderedEdgesMeetGeometrically (b, a) f := by
391 rcases h with ⟨x, hab, hf⟩
392 exact ⟨x, on_closed_segment_symm hab, hf⟩
393
394/-- Swapping the endpoints of the second edge preserves geometric meeting. -/
395theorem ordered_edges_meet_swap_right
396 {e : Point2 × Point2} {c d : Point2}
397 (h : OrderedEdgesMeetGeometrically e (c, d)) :
398 OrderedEdgesMeetGeometrically e (d, c) := by
399 rcases h with ⟨x, he, hcd⟩
400 exact ⟨x, he, on_closed_segment_symm hcd⟩
401
402/-- If the first endpoint of `f` lies on segment `e`, the edges meet at that
403endpoint. -/
404theorem ordered_edges_meet_of_fst_on_segment
405 (a b c d : Point2)
406 (hc : OnClosedSegment a b c) :
407 OrderedEdgesMeetGeometrically (a, b) (c, d) :=
408 ⟨c, hc, left_endpoint_on_segment c d⟩
409
410/-- If the second endpoint of `f` lies on segment `e`, the edges meet there. -/
411theorem ordered_edges_meet_of_snd_on_segment
412 (a b c d : Point2)
413 (hd : OnClosedSegment a b d) :
414 OrderedEdgesMeetGeometrically (a, b) (c, d) :=
415 ⟨d, hd, right_endpoint_on_segment c d⟩
416
417/-- If the first endpoint of `e` lies on segment `f`, the edges meet there. -/
418theorem ordered_edges_meet_of_fst_on_segment_symm
419 (a b c d : Point2)
420 (ha : OnClosedSegment c d a) :
421 OrderedEdgesMeetGeometrically (a, b) (c, d) :=
422 ⟨a, left_endpoint_on_segment a b, ha⟩
423
424/-- If the second endpoint of `e` lies on segment `f`, the edges meet there. -/
425theorem ordered_edges_meet_of_snd_on_segment_symm
426 (a b c d : Point2)
427 (hb : OnClosedSegment c d b) :
428 OrderedEdgesMeetGeometrically (a, b) (c, d) :=
429 ⟨b, right_endpoint_on_segment a b, hb⟩
430
431/-- Two ordered edges share an endpoint. -/
432def OrderedEdgesShareEndpoint
433 (e f : Point2 × Point2) : Prop :=
434 e.1 = f.1 ∨ e.1 = f.2 ∨ e.2 = f.1 ∨ e.2 = f.2
435
436/-- Shared endpoint implies geometric meeting of the closed segments. -/
437theorem ordered_edges_meet_of_share_endpoint
438 {e f : Point2 × Point2}
439 (h : OrderedEdgesShareEndpoint e f) :
440 OrderedEdgesMeetGeometrically e f := by
441 rcases h with h11 | h12 | h21 | h22
442 · refine ⟨e.1, left_endpoint_on_segment e.1 e.2, ?_⟩
443 rw [← h11]
444 exact left_endpoint_on_segment e.1 f.2
445 · refine ⟨e.1, left_endpoint_on_segment e.1 e.2, ?_⟩
446 rw [← h12]
447 exact right_endpoint_on_segment f.1 e.1
448 · refine ⟨e.2, right_endpoint_on_segment e.1 e.2, ?_⟩
449 rw [← h21]
450 exact left_endpoint_on_segment e.2 f.2
451 · refine ⟨e.2, right_endpoint_on_segment e.1 e.2, ?_⟩
452 rw [← h22]
453 exact right_endpoint_on_segment f.1 e.2
454
455/-- Diameter-edge graph has no two geometrically disjoint edges. This is the
456geometric observation behind Hopf-Pannwitz. -/
457def NoDisjointDiameterEdges : Prop :=
458 ∀ᶠ n in atTop,
459 ∀ A : Finset Point2,
460 A.card = n →
461 ∀ Δ : ℝ,
462 IsDiameterShell A Δ →
463 ∀ e ∈ diameterOrderedEdges A Δ,
464 ∀ f ∈ diameterOrderedEdges A Δ,
465 ¬ OrderedEdgesGeometricallyDisjoint e f
466
467/-- Local geometric lemma: any two diameter segments in the same finite planar
468set meet. This is the four-point geometric core behind
469`NoDisjointDiameterEdges`. -/
470def DiameterSegmentsMeetLocally : Prop :=
471 ∀ᶠ n in atTop,
472 ∀ A : Finset Point2,
473 A.card = n →
474 ∀ Δ : ℝ,
475 IsDiameterShell A Δ →
476 ∀ e ∈ diameterOrderedEdges A Δ,
477 ∀ f ∈ diameterOrderedEdges A Δ,
478 OrderedEdgesMeetGeometrically e f
479
480/-- The remaining local geometric core after endpoint-sharing cases are
481discharged: endpoint-disjoint diameter segments must meet. -/
482def EndpointDisjointDiameterSegmentsMeetLocally : Prop :=
483 ∀ᶠ n in atTop,
484 ∀ A : Finset Point2,
485 A.card = n →
486 ∀ Δ : ℝ,
487 IsDiameterShell A Δ →
488 ∀ e ∈ diameterOrderedEdges A Δ,
489 ∀ f ∈ diameterOrderedEdges A Δ,
490 ¬ OrderedEdgesShareEndpoint e f →
491 OrderedEdgesMeetGeometrically e f
492
493/-- Endpoint-disjoint local meeting plus the elementary shared-endpoint lemma
494gives the full local meeting bridge. -/
495theorem diameter_segments_meet_from_endpoint_disjoint_core
496 (hCore : EndpointDisjointDiameterSegmentsMeetLocally) :
497 DiameterSegmentsMeetLocally := by
498 filter_upwards [hCore] with n hCoreN
499 intro A hA Δ hΔ e he f hf
500 by_cases hShare : OrderedEdgesShareEndpoint e f
501 · exact ordered_edges_meet_of_share_endpoint hShare
502 · exact hCoreN A hA Δ hΔ e he f hf hShare
503
504/-- Four-point diameter crossing lemma: any two endpoint-disjoint diameter pairs
505in the plane, with all six pairwise distances bounded by the diameter, have
506intersecting closed segments. This is the universal four-point geometric core
507behind Hopf-Pannwitz; it does not depend on `n` or on the ambient finite set. -/
508def FourPointDiameterCrossing : Prop :=
509 ∀ (a b c d : Point2) (Δ : ℝ),
510 a ≠ c → a ≠ d → b ≠ c → b ≠ d →
511 dist a b = Δ →
512 dist c d = Δ →
513 dist a c ≤ Δ →
514 dist a d ≤ Δ →
515 dist b c ≤ Δ →
516 dist b d ≤ Δ →
517 OrderedEdgesMeetGeometrically (a, b) (c, d)
518
519/-- The `Δ = 0` case of `FourPointDiameterCrossing` is vacuously true: the
520hypotheses force `a = c` and `c ≠ a` simultaneously. -/
521theorem four_point_diameter_crossing_zero_case
522 (a b c d : Point2)
523 (h_ac : a ≠ c) (_h_ad : a ≠ d) (_h_bc : b ≠ c) (_h_bd : b ≠ d)
524 (_hab : dist a b = (0 : ℝ))
525 (_hcd : dist c d = (0 : ℝ))
526 (h_ac_le : dist a c ≤ (0 : ℝ))
527 (_h_ad_le : dist a d ≤ (0 : ℝ))
528 (_h_bc_le : dist b c ≤ (0 : ℝ))
529 (_h_bd_le : dist b d ≤ (0 : ℝ)) :
530 OrderedEdgesMeetGeometrically (a, b) (c, d) := by
531 exfalso
532 have hac : dist a c = 0 := le_antisymm h_ac_le dist_nonneg
533 exact h_ac (eq_of_dist_eq_zero hac)
534
535/-- Signed twice-area / orientation determinant in the visible plane. -/
536noncomputable def orient2 (a b c : Point2) : ℝ :=
537 (b 0 - a 0) * (c 1 - a 1) - (b 1 - a 1) * (c 0 - a 0)
538
539/-- Swapping the first two arguments negates orientation. -/
540theorem orient2_swap₁₂ (a b c : Point2) :
541 orient2 b a c = - orient2 a b c := by
542 unfold orient2
543 ring
544
545/-- Swapping the last two arguments negates orientation. -/
546theorem orient2_swap₂₃ (a b c : Point2) :
547 orient2 a c b = - orient2 a b c := by
548 unfold orient2
549 ring
550
551/-- Swapping the first and last arguments negates orientation. -/
552theorem orient2_swap₁₃ (a b c : Point2) :
553 orient2 c b a = - orient2 a b c := by
554 unfold orient2
555 ring
556
557/-- Cyclic permutation preserves orientation: `orient2 a b c = orient2 b c a`. -/
558theorem orient2_cyclic (a b c : Point2) :
559 orient2 a b c = orient2 b c a := by
560 unfold orient2
561 ring
562
563/-- Cyclic permutation preserves orientation: `orient2 a b c = orient2 c a b`. -/
564theorem orient2_cyclic' (a b c : Point2) :
565 orient2 a b c = orient2 c a b := by
566 rw [orient2_cyclic, orient2_cyclic]
567
568/-- Four-point Plücker orientation identity: signed areas of triangles among
569four points satisfy a single linear relation. -/
570theorem orient2_plucker (a b c d : Point2) :
571 orient2 a b c + orient2 a c d = orient2 a b d + orient2 b c d := by
572 unfold orient2
573 ring
574
575/-- Plücker identity solved for `orient2 b c d`. -/
576theorem orient2_bcd_decomposition (a b c d : Point2) :
577 orient2 b c d = orient2 a b c - orient2 a b d + orient2 a c d := by
578 unfold orient2
579 ring
580
581/-- Plücker identity in zero-sum form: an alternating sum of the four triangle
582orientations vanishes. -/
583theorem orient2_alternating_sum_eq_zero (a b c d : Point2) :
584 orient2 a b c - orient2 a b d + orient2 a c d - orient2 b c d = 0 := by
585 unfold orient2
586 ring
587
588/-- Orientation zero is transitive through a fixed line: if `c` and `d` both lie
589on the line through `a, b` (so `orient2 a b c = 0 = orient2 a b d`), and
590`a ≠ b`, then `orient2 a c d = 0`. Equivalently: collinear `{a,b,c}` and
591collinear `{a,b,d}` with `a ≠ b` implies `{a,c,d}` collinear. -/
592theorem orient2_zero_transitive
593 {a b c d : Point2} (hab : a ≠ b)
594 (hc : orient2 a b c = 0) (hd : orient2 a b d = 0) :
595 orient2 a c d = 0 := by
596 have hne : ∃ i : Fin 2, a i ≠ b i := by
597 by_contra h
598 push_neg at h
599 exact hab (by ext i; exact h i)
600 unfold orient2 at hc hd ⊢
601 set p := b 0 - a 0 with hp_def
602 set q := b 1 - a 1 with hq_def
603 set r := c 0 - a 0 with hr_def
604 set s := c 1 - a 1 with hs_def
605 set u := d 0 - a 0 with hu_def
606 set v := d 1 - a 1 with hv_def
607 have key_q : q * (r * v - s * u) = 0 := by linear_combination -v * hc + s * hd
608 have key_p : p * (r * v - s * u) = 0 := by linear_combination -u * hc + r * hd
609 rcases hne with ⟨i, hi⟩
610 fin_cases i
611 · have hp : p ≠ 0 := sub_ne_zero.mpr hi.symm
612 have hrvsu : r * v - s * u = 0 := by
613 rcases mul_eq_zero.mp key_p with h | h
614 · exact absurd h hp
615 · exact h
616 linarith
617 · have hq : q ≠ 0 := sub_ne_zero.mpr hi.symm
618 have hrvsu : r * v - s * u = 0 := by
619 rcases mul_eq_zero.mp key_q with h | h
620 · exact absurd h hq
621 · exact h
622 linarith
623
624/-- Symmetric variant of `orient2_zero_transitive`: with `c ≠ d`, both `a` and
625`b` lie on the line through `c, d`. Useful for the four-point collinear
626analysis. -/
627theorem orient2_zero_transitive_swap
628 {a b c d : Point2} (hcd : c ≠ d)
629 (hca : orient2 c d a = 0) (hcb : orient2 c d b = 0) :
630 orient2 c a b = 0 := orient2_zero_transitive hcd hca hcb
631
632/-- Transfer collinearity through two distinct common points. If `x` and `y`
633are distinct points on line `ab`, and `c` lies on line `xy`, then `c` lies on
634line `ab`. -/
635theorem orient2_zero_of_two_points_on_line_and_point_on_join
636 {a b x y c : Point2} (hxy : x ≠ y)
637 (hx : orient2 a b x = 0) (hy : orient2 a b y = 0)
638 (hc : orient2 x y c = 0) :
639 orient2 a b c = 0 := by
640 have hcoord : x 0 ≠ y 0 ∨ x 1 ≠ y 1 := by
641 by_contra h
642 push_neg at h
643 exact hxy (by ext i; fin_cases i; exact h.1; exact h.2)
644 rcases hcoord with h0 | h1
645 · have hdiff : (b 0 - a 0) * (y 1 - x 1) - (b 1 - a 1) * (y 0 - x 0) = 0 := by
646 unfold orient2 at hx hy
647 linear_combination hy - hx
648 have key : (y 0 - x 0) * orient2 a b c = 0 := by
649 unfold orient2 at hx hc ⊢
650 linear_combination (y 0 - x 0) * hx + (b 0 - a 0) * hc + (c 0 - x 0) * hdiff
651 have hyx : y 0 - x 0 ≠ 0 := sub_ne_zero.mpr h0.symm
652 exact (mul_eq_zero.mp key).resolve_left hyx
653 · have hdiff : (b 0 - a 0) * (y 1 - x 1) - (b 1 - a 1) * (y 0 - x 0) = 0 := by
654 unfold orient2 at hx hy
655 linear_combination hy - hx
656 have key : (y 1 - x 1) * orient2 a b c = 0 := by
657 unfold orient2 at hx hc ⊢
658 linear_combination (y 1 - x 1) * hx + (c 1 - x 1) * hdiff + (b 1 - a 1) * hc
659 have hyx : y 1 - x 1 ≠ 0 := sub_ne_zero.mpr h1.symm
660 exact (mul_eq_zero.mp key).resolve_left hyx
661
662/-- Orientation vanishes when the third point is the first endpoint. -/
663theorem orient2_left_self (a b : Point2) :
664 orient2 a b a = 0 := by
665 unfold orient2
666 ring
667
668/-- Orientation vanishes when the third point is the second endpoint. -/
669theorem orient2_right_self (a b : Point2) :
670 orient2 a b b = 0 := by
671 unfold orient2
672 ring
673
674/-- Any point on a closed segment is collinear with its endpoints in the
675orientation determinant. -/
676theorem orient2_eq_zero_of_on_closed_segment
677 {a b x : Point2} (hx : OnClosedSegment a b x) :
678 orient2 a b x = 0 := by
679 rcases hx with ⟨t, _, _, hx_eq⟩
680 rw [hx_eq]
681 unfold orient2
682 simp
683 ring_nf
684
685/-- Orientation is affine in the third argument along a segment. -/
686theorem orient2_affine_third
687 (a b c d : Point2) (t : ℝ) :
688 orient2 a b ((1 - t) • c + t • d) =
689 (1 - t) * orient2 a b c + t * orient2 a b d := by
690 unfold orient2
691 simp
692 ring_nf
693
694/-- If `x` lies on `[c,d]`, then its orientation relative to line `ab` is a
695convex affine combination of the endpoint orientations. -/
696theorem orient2_of_on_closed_segment
697 {a b c d x : Point2} (hx : OnClosedSegment c d x) :
698 ∃ t : ℝ, 0 ≤ t ∧ t ≤ 1 ∧
699 orient2 a b x = (1 - t) * orient2 a b c + t * orient2 a b d := by
700 rcases hx with ⟨t, h0, h1, hx_eq⟩
701 refine ⟨t, h0, h1, ?_⟩
702 rw [hx_eq]
703 exact orient2_affine_third a b c d t
704
705/-- Parametrization on a line: if `orient2 a b c = 0` with `a ≠ b`, then there
706exists a scalar `t` such that `c i - a i = t * (b i - a i)` for both
707coordinates `i : Fin 2`. This is the central planar-collinearity unpack. -/
708theorem exists_scalar_of_orient2_zero
709 {a b c : Point2} (hab : a ≠ b) (h : orient2 a b c = 0) :
710 ∃ t : ℝ, ∀ i : Fin 2, c i - a i = t * (b i - a i) := by
711 have hcoord : a 0 ≠ b 0 ∨ a 1 ≠ b 1 := by
712 by_contra hh
713 push_neg at hh
714 exact hab (by ext i; fin_cases i; exact hh.1; exact hh.2)
715 unfold orient2 at h
716 rcases hcoord with hi0 | hi1
717 · have hp : b 0 - a 0 ≠ 0 := sub_ne_zero.mpr hi0.symm
718 refine ⟨(c 0 - a 0) / (b 0 - a 0), fun j => ?_⟩
719 fin_cases j
720 · show c 0 - a 0 = (c 0 - a 0) / (b 0 - a 0) * (b 0 - a 0)
721 field_simp
722 · show c 1 - a 1 = (c 0 - a 0) / (b 0 - a 0) * (b 1 - a 1)
723 field_simp
724 linarith
725 · have hq : b 1 - a 1 ≠ 0 := sub_ne_zero.mpr hi1.symm
726 refine ⟨(c 1 - a 1) / (b 1 - a 1), fun j => ?_⟩
727 fin_cases j
728 · show c 0 - a 0 = (c 1 - a 1) / (b 1 - a 1) * (b 0 - a 0)
729 field_simp
730 linarith
731 · show c 1 - a 1 = (c 1 - a 1) / (b 1 - a 1) * (b 1 - a 1)
732 field_simp
733
734/-- Generalised distance lemma: if `v i - u i = t * (b i - a i)` for both
735coordinates, then `dist u v = |t| * dist a b`. This packages the
736collinearity-with-base-segment squared-distance computation in one form
737that handles all four orderings (a, c), (a, d), (b, c), (b, d), (c, d). -/
738theorem dist_from_diff_eq_smul
739 {a b u v : Point2} {t : ℝ}
740 (h : ∀ i : Fin 2, v i - u i = t * (b i - a i)) :
741 dist u v = |t| * dist a b := by
742 have h0 : u 0 - v 0 = -t * (b 0 - a 0) := by linarith [h 0]
743 have h1 : u 1 - v 1 = -t * (b 1 - a 1) := by linarith [h 1]
744 have hsq : (dist u v) ^ 2 = t^2 * (dist a b) ^ 2 := by
745 rw [EuclideanSpace.dist_sq_eq, EuclideanSpace.dist_sq_eq]
746 simp [Fin.sum_univ_two, Real.dist_eq]
747 have e0 : (u 0 - v 0)^2 = t^2 * (b 0 - a 0)^2 := by rw [h0]; ring
748 have e1 : (u 1 - v 1)^2 = t^2 * (b 1 - a 1)^2 := by rw [h1]; ring
749 have e0' : (a 0 - b 0)^2 = (b 0 - a 0)^2 := by ring
750 have e1' : (a 1 - b 1)^2 = (b 1 - a 1)^2 := by ring
751 linarith
752 have huv_nn : 0 ≤ dist u v := dist_nonneg
753 have hab_nn : 0 ≤ dist a b := dist_nonneg
754 have hrhs : 0 ≤ |t| * dist a b := mul_nonneg (abs_nonneg _) hab_nn
755 have hsq2 : (dist u v) ^ 2 = (|t| * dist a b) ^ 2 := by
756 rw [hsq, mul_pow, sq_abs]
757 have h_abs : |dist u v| = |(|t| * dist a b)| :=
758 (sq_eq_sq_iff_abs_eq_abs _ _).mp hsq2
759 rw [abs_of_nonneg huv_nn, abs_of_nonneg hrhs] at h_abs
760 exact h_abs
761
762/-- A real affine segment between a nonpositive and a nonnegative value crosses
763zero. -/
764theorem affine_zero_of_nonpos_nonneg
765 {u v : ℝ} (hu : u ≤ 0) (hv : 0 ≤ v) :
766 ∃ t : ℝ, 0 ≤ t ∧ t ≤ 1 ∧ (1 - t) * u + t * v = 0 := by
767 by_cases hsum : u = v
768 · have hu0 : u = 0 := by linarith
769 have hv0 : v = 0 := by linarith
770 refine ⟨0, by norm_num, by norm_num, ?_⟩
771 rw [hu0, hv0]
772 ring
773 · let t := (-u) / (v - u)
774 have hden_pos : 0 < v - u := by
775 have : u < v := lt_of_le_of_ne (by linarith) hsum
776 linarith
777 refine ⟨t, ?_, ?_, ?_⟩
778 · dsimp [t]
779 exact div_nonneg (by linarith) (le_of_lt hden_pos)
780 · dsimp [t]
781 rw [div_le_one hden_pos]
782 linarith
783 · dsimp [t]
784 field_simp [ne_of_gt hden_pos]
785 ring
786
787/-- If endpoints of segment `[c,d]` have opposite orientation signs with
788respect to line `ab`, then some point of `[c,d]` lies on line `ab`
789(`orient2 = 0`). -/
790theorem exists_orient2_zero_on_segment_of_nonpos_nonneg
791 {a b c d : Point2}
792 (hc : orient2 a b c ≤ 0) (hd : 0 ≤ orient2 a b d) :
793 ∃ x : Point2, OnClosedSegment c d x ∧ orient2 a b x = 0 := by
794 rcases affine_zero_of_nonpos_nonneg (u := orient2 a b c)
795 (v := orient2 a b d) hc hd with ⟨t, ht0, ht1, htzero⟩
796 let x : Point2 := (1 - t) • c + t • d
797 refine ⟨x, ⟨t, ht0, ht1, rfl⟩, ?_⟩
798 rw [orient2_affine_third]
799 exact htzero
800
801/-- Symmetric version of the previous crossing lemma. -/
802theorem exists_orient2_zero_on_segment_of_nonneg_nonpos
803 {a b c d : Point2}
804 (hc : 0 ≤ orient2 a b c) (hd : orient2 a b d ≤ 0) :
805 ∃ x : Point2, OnClosedSegment c d x ∧ orient2 a b x = 0 := by
806 rcases exists_orient2_zero_on_segment_of_nonpos_nonneg
807 (a := a) (b := b) (c := d) (d := c) hd hc with ⟨x, hx, hz⟩
808 exact ⟨x, on_closed_segment_symm hx, hz⟩
809
810/-- Positive product over reals means the two factors have the same strict
811sign. -/
812theorem same_strict_sign_of_pos_mul
813 {x y : ℝ} (h : 0 < x * y) :
814 (0 < x ∧ 0 < y) ∨ (x < 0 ∧ y < 0) := by
815 rcases lt_trichotomy x 0 with hx | hx | hx
816 · right
817 constructor
818 · exact hx
819 · by_contra hy_nonneg
820 push_neg at hy_nonneg
821 have hxy : x * y ≤ 0 :=
822 mul_nonpos_of_nonpos_of_nonneg (le_of_lt hx) hy_nonneg
823 linarith
824 · subst hx
825 simp at h
826 · left
827 constructor
828 · exact hx
829 · by_contra hy_nonpos
830 push_neg at hy_nonpos
831 have hxy : x * y ≤ 0 :=
832 mul_nonpos_of_nonneg_of_nonpos (le_of_lt hx) hy_nonpos
833 linarith
834
835/-- A convex affine combination of two same-strict-sign real numbers is
836nonzero. This is the scalar sign fact used in orientation crossing arguments. -/
837theorem convex_combo_ne_zero_of_same_strict_sign
838 {u v t : ℝ} (ht0 : 0 ≤ t) (ht1 : t ≤ 1)
839 (h : (0 < u ∧ 0 < v) ∨ (u < 0 ∧ v < 0)) :
840 (1 - t) * u + t * v ≠ 0 := by
841 rcases h with hpos | hneg
842 · have hnonneg1 : 0 ≤ 1 - t := by linarith
843 have hterm1 : 0 ≤ (1 - t) * u := mul_nonneg hnonneg1 (le_of_lt hpos.1)
844 have hterm2 : 0 ≤ t * v := mul_nonneg ht0 (le_of_lt hpos.2)
845 have hsum_pos_cases : 0 < (1 - t) * u ∨ 0 < t * v := by
846 by_cases ht_zero : t = 0
847 · left
848 have : 1 - t = 1 := by linarith
849 rw [this]
850 simpa using hpos.1
851 · right
852 have ht_pos : 0 < t := lt_of_le_of_ne ht0 (Ne.symm ht_zero)
853 exact mul_pos ht_pos hpos.2
854 rcases hsum_pos_cases with hp | hp
855 · exact ne_of_gt (add_pos_of_pos_of_nonneg hp hterm2)
856 · exact ne_of_gt (add_pos_of_nonneg_of_pos hterm1 hp)
857 · have hpos' : 0 < -u ∧ 0 < -v := by
858 constructor <;> linarith
859 have hnonzero_pos : (1 - t) * (-u) + t * (-v) ≠ 0 := by
860 have hnonneg1 : 0 ≤ 1 - t := by linarith
861 have hterm1 : 0 ≤ (1 - t) * (-u) := mul_nonneg hnonneg1 (le_of_lt hpos'.1)
862 have hterm2 : 0 ≤ t * (-v) := mul_nonneg ht0 (le_of_lt hpos'.2)
863 have hsum_pos_cases : 0 < (1 - t) * (-u) ∨ 0 < t * (-v) := by
864 by_cases ht_zero : t = 0
865 · left
866 have : 1 - t = 1 := by linarith
867 rw [this]
868 simpa using hpos'.1
869 · right
870 have ht_pos : 0 < t := lt_of_le_of_ne ht0 (Ne.symm ht_zero)
871 exact mul_pos ht_pos hpos'.2
872 rcases hsum_pos_cases with hp | hp
873 · exact ne_of_gt (add_pos_of_pos_of_nonneg hp hterm2)
874 · exact ne_of_gt (add_pos_of_nonneg_of_pos hterm1 hp)
875 intro hzero
876 apply hnonzero_pos
877 nlinarith
878
879/-- If two points are on the same strict side of a line, the segment joining
880them is disjoint from the segment spanning the line. This is the core
881separation lemma for all thrackle and matching arguments. -/
882theorem same_side_segments_disjoint
883 {a b c d : Point2}
884 (h_same : 0 < orient2 a b c * orient2 a b d) :
885 OrderedEdgesGeometricallyDisjoint (a, b) (c, d) := by
886 intro ⟨p, hp_ab, hp_cd⟩
887 have h_zero : orient2 a b p = 0 :=
888 orient2_eq_zero_of_on_closed_segment hp_ab
889 rcases hp_cd with ⟨t, ht0, ht1, hp_eq⟩
890 have h_aff : orient2 a b p = (1 - t) * orient2 a b c + t * orient2 a b d := by
891 rw [hp_eq]; exact orient2_affine_third a b c d t
892 rw [h_zero] at h_aff
893 exact absurd h_aff.symm
894 (convex_combo_ne_zero_of_same_strict_sign ht0 ht1
895 (same_strict_sign_of_pos_mul h_same))
896
897/-- A proper separating orientation certificate for two endpoint-disjoint
898segments: each segment's endpoints lie strictly on one side of the line through
899the other segment. This is the standard orientation witness for two disjoint
900non-collinear closed segments. -/
901def ProperSegmentSeparation (a b c d : Point2) : Prop :=
902 0 < orient2 a b c * orient2 a b d ∧
903 0 < orient2 c d a * orient2 c d b
904
905/-- Unpack proper separation into same-side alternatives for both supporting
906lines. -/
907theorem proper_segment_separation_signs
908 {a b c d : Point2}
909 (h : ProperSegmentSeparation a b c d) :
910 ((0 < orient2 a b c ∧ 0 < orient2 a b d) ∨
911 (orient2 a b c < 0 ∧ orient2 a b d < 0)) ∧
912 ((0 < orient2 c d a ∧ 0 < orient2 c d b) ∨
913 (orient2 c d a < 0 ∧ orient2 c d b < 0)) :=
914 ⟨same_strict_sign_of_pos_mul h.1, same_strict_sign_of_pos_mul h.2⟩
915
916/-- A proper separation certificate really implies geometric disjointness:
917if the segments met, a point of `[c,d]` would also lie on line `ab`, forcing an
918affine combination of two same-strict-sign orientation values to be zero. -/
919theorem proper_segment_separation_geometrically_disjoint
920 {a b c d : Point2}
921 (h : ProperSegmentSeparation a b c d) :
922 OrderedEdgesGeometricallyDisjoint (a, b) (c, d) := by
923 intro hmeet
924 rcases hmeet with ⟨x, hxab, hxcd⟩
925 have hx_zero : orient2 a b x = 0 := orient2_eq_zero_of_on_closed_segment hxab
926 rcases orient2_of_on_closed_segment (a := a) (b := b) hxcd with
927 ⟨t, ht0, ht1, hx_affine⟩
928 have hsigns := (proper_segment_separation_signs h).1
929 have hne :=
930 convex_combo_ne_zero_of_same_strict_sign
931 (u := orient2 a b c) (v := orient2 a b d) (t := t) ht0 ht1 hsigns
932 exact hne (by rw [← hx_affine, hx_zero])
933
934/-- Collinear disjoint-segment separation certificate. The four points lie on
935the same two supporting lines and the closed segments do not meet. This is kept
936separate from the strict orientation case because the products above vanish in
937the collinear case. -/
938def CollinearSegmentSeparation (a b c d : Point2) : Prop :=
939 orient2 a b c = 0 ∧ orient2 a b d = 0 ∧
940 OrderedEdgesGeometricallyDisjoint (a, b) (c, d)
941
942/-- Abstract classical geometry bridge: if two endpoint-disjoint closed
943segments do not meet, then either a proper orientation separation or a collinear
944separation certificate exists. This is the standard planar segment-separation
945case split. -/
946def DisjointSegmentsHaveSeparation : Prop :=
947 ∀ a b c d : Point2,
948 a ≠ c → a ≠ d → b ≠ c → b ≠ d →
949 OrderedEdgesGeometricallyDisjoint (a, b) (c, d) →
950 ProperSegmentSeparation a b c d ∨ CollinearSegmentSeparation a b c d
951
952/-- **Hopf-Pannwitz strict lens-diameter inequality** (coordinate form).
953For two points `(cx, cy)` and `(dx, dy)` in the closed lens
954`D((0,0), Δ) ∩ D((Δ,0), Δ)` (i.e., both visible coordinates satisfy the four
955disk constraints), with `cy > 0` and `dy > 0` strict (i.e., both on the strict
956upper side), the squared distance is strictly less than `Δ²`. Equivalently:
957the vesica piscis has diameter `Δ` with strict inequality on the open
958half-lens.
959
960This is the central classical input for the four-point Hopf-Pannwitz lemma in
961its proper-separation case. The proof is a polynomial Positivstellensatz
962certificate using two orientation-determinant squares as nonnegativity hints. -/
963theorem hopf_pannwitz_strict_lens_coord
964 (Δ cx cy dx dy : ℝ)
965 (hΔ : 0 < Δ)
966 (hi : cx*cx + cy*cy ≤ Δ*Δ)
967 (hii : (cx - Δ)*(cx - Δ) + cy*cy ≤ Δ*Δ)
968 (hiii : dx*dx + dy*dy ≤ Δ*Δ)
969 (hiv : (dx - Δ)*(dx - Δ) + dy*dy ≤ Δ*Δ)
970 (hcy : 0 < cy)
971 (hdy : 0 < dy) :
972 (cx - dx)*(cx - dx) + (cy - dy)*(cy - dy) < Δ*Δ := by
973 have hcx_pos : 0 < cx := by nlinarith [mul_pos hcy hcy]
974 have hdx_pos : 0 < dx := by nlinarith [mul_pos hdy hdy]
975 have hcx_lt : cx < Δ := by nlinarith [mul_pos hcy hcy]
976 have hdx_lt : dx < Δ := by nlinarith [mul_pos hdy hdy]
977 nlinarith [hi, hii, hiii, hiv, hcy, hdy, hcx_pos, hdx_pos, hcx_lt, hdx_lt,
978 mul_pos hcy hdy, mul_self_nonneg (cy*(Δ - dx) - dy*(Δ - cx)),
979 mul_self_nonneg (cy*dx - dy*cx),
980 mul_pos hΔ hcy, mul_pos hΔ hdy,
981 mul_pos (sub_pos.mpr hcx_lt) hdy,
982 mul_pos hcy (sub_pos.mpr hdx_lt),
983 mul_pos hcx_pos hdy, mul_pos hcy hdx_pos]
984
985/-- Symmetric lens inequality: works for `cy < 0` and `dy < 0` too (the lower
986half-lens), obtained by reflecting `y → -y`. -/
987theorem hopf_pannwitz_strict_lens_coord_neg
988 (Δ cx cy dx dy : ℝ)
989 (hΔ : 0 < Δ)
990 (hi : cx*cx + cy*cy ≤ Δ*Δ)
991 (hii : (cx - Δ)*(cx - Δ) + cy*cy ≤ Δ*Δ)
992 (hiii : dx*dx + dy*dy ≤ Δ*Δ)
993 (hiv : (dx - Δ)*(dx - Δ) + dy*dy ≤ Δ*Δ)
994 (hcy : cy < 0)
995 (hdy : dy < 0) :
996 (cx - dx)*(cx - dx) + (cy - dy)*(cy - dy) < Δ*Δ := by
997 have hcy' : 0 < -cy := neg_pos.mpr hcy
998 have hdy' : 0 < -dy := neg_pos.mpr hdy
999 have hi' : cx*cx + (-cy)*(-cy) ≤ Δ*Δ := by nlinarith [hi]
1000 have hii' : (cx - Δ)*(cx - Δ) + (-cy)*(-cy) ≤ Δ*Δ := by nlinarith [hii]
1001 have hiii' : dx*dx + (-dy)*(-dy) ≤ Δ*Δ := by nlinarith [hiii]
1002 have hiv' : (dx - Δ)*(dx - Δ) + (-dy)*(-dy) ≤ Δ*Δ := by nlinarith [hiv]
1003 have := hopf_pannwitz_strict_lens_coord Δ cx (-cy) dx (-dy) hΔ hi' hii' hiii' hiv' hcy' hdy'
1004 nlinarith [this]
1005
1006/-- **Lagrange's identity** in `ℝ²`: `(u·v)² + (u × v)² = |u|² |v|²`. -/
1007theorem lagrange_identity_2d (a b c : Point2) :
1008 ((c 0 - a 0)*(b 0 - a 0) + (c 1 - a 1)*(b 1 - a 1))^2 +
1009 ((b 0 - a 0)*(c 1 - a 1) - (b 1 - a 1)*(c 0 - a 0))^2 =
1010 ((c 0 - a 0)^2 + (c 1 - a 1)^2) * ((b 0 - a 0)^2 + (b 1 - a 1)^2) := by
1011 ring
1012
1013/-- **Polarized Lagrange identity** in `ℝ²`. -/
1014theorem lagrange_identity_polarized_2d (a b c d : Point2) :
1015 ((c 0 - a 0)*(b 0 - a 0) + (c 1 - a 1)*(b 1 - a 1)) *
1016 ((d 0 - a 0)*(b 0 - a 0) + (d 1 - a 1)*(b 1 - a 1)) +
1017 ((b 0 - a 0)*(c 1 - a 1) - (b 1 - a 1)*(c 0 - a 0)) *
1018 ((b 0 - a 0)*(d 1 - a 1) - (b 1 - a 1)*(d 0 - a 0)) =
1019 ((c 0 - a 0)*(d 0 - a 0) + (c 1 - a 1)*(d 1 - a 1)) *
1020 ((b 0 - a 0)^2 + (b 1 - a 1)^2) := by
1021 ring
1022
1023/-- Squared Euclidean distance unfolded for `Point2 = EuclideanSpace ℝ (Fin 2)`. -/
1024theorem dist_sq_unfold (a b : Point2) :
1025 (dist a b)^2 = (a 0 - b 0)^2 + (a 1 - b 1)^2 := by
1026 have h := EuclideanSpace.dist_sq_eq a b
1027 simp [Fin.sum_univ_two, Real.dist_eq, pow_two] at h
1028 linarith [h, sq_abs (a 0 - b 0), sq_abs (a 1 - b 1)]
1029
1030/-- Abstract RS/classical bridge: proper separated diameter pairs cannot satisfy
1031all four cross-distance bounds. This is the positive-Δ orientation-sign core
1032of the four-point Hopf-Pannwitz geometry. This bridge is now a *theorem*
1033(see `properSeparatedDiameterContradiction` below), so any use of
1034`ProperSeparatedDiameterContradiction` as a hypothesis can be discharged
1035unconditionally. -/
1036def ProperSeparatedDiameterContradiction : Prop :=
1037 ∀ (a b c d : Point2) (Δ : ℝ),
1038 a ≠ c → a ≠ d → b ≠ c → b ≠ d →
1039 dist a b = Δ →
1040 dist c d = Δ →
1041 dist a c ≤ Δ →
1042 dist a d ≤ Δ →
1043 dist b c ≤ Δ →
1044 dist b d ≤ Δ →
1045 ProperSegmentSeparation a b c d →
1046 False
1047
1048set_option maxHeartbeats 6400000 in
1049/-- **Theorem.** The proper separated diameter contradiction. Two diameter
1050segments `[a,b]` and `[c,d]` with all cross-distances bounded by the diameter
1051cannot have both `c, d` on the strict same side of line `ab`. Proof: place
1052`a` and `b` in coordinates, rotate so `(b-a)/|b-a|` is the first basis vector;
1053then `c, d` translate to lens-coordinate values `(αc, βc), (αd, βd)` with
1054`βc · Δ = orient2(a,b,c)` and `αc · Δ = ⟨c-a, b-a⟩`. Lagrange's identity
1055gives `αc² + βc² = (dist a c)²` and similar for the other distances. Proper
1056separation forces `βc · βd > 0` strict. Then `hopf_pannwitz_strict_lens_coord`
1057(or its negative variant) gives `(αc - αd)² + (βc - βd)² < Δ²`, but the
1058polarized Lagrange identity gives `(αc - αd)² + (βc - βd)² = (dist c d)² = Δ²`.
1059Contradiction. -/
1060theorem properSeparatedDiameterContradiction :
1061 ProperSeparatedDiameterContradiction := by
1062 intro a b c d Δ h_ac h_ad h_bc h_bd hab hcd hac had hbc hbd hProper
1063 by_cases hΔ : Δ = 0
1064 · subst hΔ
1065 have h : dist a c = 0 := le_antisymm hac dist_nonneg
1066 exact h_ac (eq_of_dist_eq_zero h)
1067 have hΔ_nn : 0 ≤ Δ := hab ▸ dist_nonneg
1068 have hΔ_pos : 0 < Δ := lt_of_le_of_ne hΔ_nn (Ne.symm hΔ)
1069 have hΔ_ne : Δ ≠ 0 := ne_of_gt hΔ_pos
1070 -- Δ² = P² + Q² where P = b 0 - a 0, Q = b 1 - a 1.
1071 have hab_sq : Δ*Δ = (b 0 - a 0)^2 + (b 1 - a 1)^2 := by
1072 have h := dist_sq_unfold a b
1073 rw [hab] at h
1074 nlinarith [h]
1075 -- Squared distances unfolded.
1076 have hac_sq_le : (c 0 - a 0)^2 + (c 1 - a 1)^2 ≤ Δ*Δ := by
1077 have h := dist_sq_unfold a c
1078 have hac_nn : 0 ≤ dist a c := dist_nonneg
1079 have : (dist a c)^2 ≤ Δ^2 := by nlinarith [hac_nn, hac]
1080 nlinarith [h, this]
1081 have had_sq_le : (d 0 - a 0)^2 + (d 1 - a 1)^2 ≤ Δ*Δ := by
1082 have h := dist_sq_unfold a d
1083 have hd_nn : 0 ≤ dist a d := dist_nonneg
1084 have : (dist a d)^2 ≤ Δ^2 := by nlinarith [hd_nn, had]
1085 nlinarith [h, this]
1086 have hbc_sq_le : (b 0 - c 0)^2 + (b 1 - c 1)^2 ≤ Δ*Δ := by
1087 have h := dist_sq_unfold b c
1088 have hd_nn : 0 ≤ dist b c := dist_nonneg
1089 have : (dist b c)^2 ≤ Δ^2 := by nlinarith [hd_nn, hbc]
1090 nlinarith [h, this]
1091 have hbd_sq_le : (b 0 - d 0)^2 + (b 1 - d 1)^2 ≤ Δ*Δ := by
1092 have h := dist_sq_unfold b d
1093 have hd_nn : 0 ≤ dist b d := dist_nonneg
1094 have : (dist b d)^2 ≤ Δ^2 := by nlinarith [hd_nn, hbd]
1095 nlinarith [h, this]
1096 have hcd_sq_eq : (c 0 - d 0)^2 + (c 1 - d 1)^2 = Δ*Δ := by
1097 have h := dist_sq_unfold c d
1098 rw [hcd] at h
1099 nlinarith [h]
1100 -- Un-divided HP coords: Ac, Bc, Ad, Bd.
1101 -- Ac := (c-a)·(b-a) = (c 0 - a 0)*(b 0 - a 0) + (c 1 - a 1)*(b 1 - a 1)
1102 -- Bc := (b-a) × (c-a) = (b 0 - a 0)*(c 1 - a 1) - (b 1 - a 1)*(c 0 - a 0)
1103 -- αc = Ac/Δ, βc = Bc/Δ. Lens constraints become Ac² + Bc² ≤ Δ⁴, etc.
1104 -- Lagrange: Ac² + Bc² = ((c-a)² coords)·(P² + Q²) = (dist a c)² · Δ²
1105 have hLag_c : ((c 0 - a 0)*(b 0 - a 0) + (c 1 - a 1)*(b 1 - a 1))^2 +
1106 ((b 0 - a 0)*(c 1 - a 1) - (b 1 - a 1)*(c 0 - a 0))^2 =
1107 ((c 0 - a 0)^2 + (c 1 - a 1)^2) * ((b 0 - a 0)^2 + (b 1 - a 1)^2) :=
1108 lagrange_identity_2d a b c
1109 have hLag_d : ((d 0 - a 0)*(b 0 - a 0) + (d 1 - a 1)*(b 1 - a 1))^2 +
1110 ((b 0 - a 0)*(d 1 - a 1) - (b 1 - a 1)*(d 0 - a 0))^2 =
1111 ((d 0 - a 0)^2 + (d 1 - a 1)^2) * ((b 0 - a 0)^2 + (b 1 - a 1)^2) :=
1112 lagrange_identity_2d a b d
1113 have hLag_pol : ((c 0 - a 0)*(b 0 - a 0) + (c 1 - a 1)*(b 1 - a 1)) *
1114 ((d 0 - a 0)*(b 0 - a 0) + (d 1 - a 1)*(b 1 - a 1)) +
1115 ((b 0 - a 0)*(c 1 - a 1) - (b 1 - a 1)*(c 0 - a 0)) *
1116 ((b 0 - a 0)*(d 1 - a 1) - (b 1 - a 1)*(d 0 - a 0)) =
1117 ((c 0 - a 0)*(d 0 - a 0) + (c 1 - a 1)*(d 1 - a 1)) *
1118 ((b 0 - a 0)^2 + (b 1 - a 1)^2) :=
1119 lagrange_identity_polarized_2d a b c d
1120 -- Set αc = Ac/Δ, βc = Bc/Δ.
1121 set αc := ((c 0 - a 0)*(b 0 - a 0) + (c 1 - a 1)*(b 1 - a 1)) / Δ with hαc_def
1122 set βc := ((b 0 - a 0)*(c 1 - a 1) - (b 1 - a 1)*(c 0 - a 0)) / Δ with hβc_def
1123 set αd := ((d 0 - a 0)*(b 0 - a 0) + (d 1 - a 1)*(b 1 - a 1)) / Δ with hαd_def
1124 set βd := ((b 0 - a 0)*(d 1 - a 1) - (b 1 - a 1)*(d 0 - a 0)) / Δ with hβd_def
1125 -- Lens constraints in (α, β) form: αc² + βc² ≤ Δ² (= (dist a c)² ≤ Δ²).
1126 have h_αcβc_eq_ac : αc*αc + βc*βc = (c 0 - a 0)^2 + (c 1 - a 1)^2 := by
1127 rw [hαc_def, hβc_def]
1128 have hΔΔ_pos : 0 < Δ*Δ := mul_pos hΔ_pos hΔ_pos
1129 field_simp
1130 nlinarith [hLag_c, hab_sq]
1131 have h_αdβd_eq_ad : αd*αd + βd*βd = (d 0 - a 0)^2 + (d 1 - a 1)^2 := by
1132 rw [hαd_def, hβd_def]
1133 have hΔΔ_pos : 0 < Δ*Δ := mul_pos hΔ_pos hΔ_pos
1134 field_simp
1135 nlinarith [hLag_d, hab_sq]
1136 -- (αc - Δ)² + βc² = (dist b c)².
1137 -- |c - b|² = |c - a|² - 2(c - a)·(b - a) + |b - a|² = (αc² + βc²) - 2αc·Δ + Δ² = (αc - Δ)² + βc².
1138 have h_αcβc_eq_bc : (αc - Δ)*(αc - Δ) + βc*βc = (b 0 - c 0)^2 + (b 1 - c 1)^2 := by
1139 have e1 : αc * Δ = (c 0 - a 0)*(b 0 - a 0) + (c 1 - a 1)*(b 1 - a 1) := by
1140 rw [hαc_def]; field_simp
1141 have e2 : (αc - Δ)*(αc - Δ) + βc*βc = (αc*αc + βc*βc) - 2*(αc*Δ) + Δ*Δ := by ring
1142 rw [e2, h_αcβc_eq_ac, e1, hab_sq]
1143 ring
1144 have h_αdβd_eq_bd : (αd - Δ)*(αd - Δ) + βd*βd = (b 0 - d 0)^2 + (b 1 - d 1)^2 := by
1145 have e1 : αd * Δ = (d 0 - a 0)*(b 0 - a 0) + (d 1 - a 1)*(b 1 - a 1) := by
1146 rw [hαd_def]; field_simp
1147 have e2 : (αd - Δ)*(αd - Δ) + βd*βd = (αd*αd + βd*βd) - 2*(αd*Δ) + Δ*Δ := by ring
1148 rw [e2, h_αdβd_eq_ad, e1, hab_sq]
1149 ring
1150 -- (αc - αd)² + (βc - βd)² = (dist c d)².
1151 -- Expansion: = (αc² + βc²) - 2(αc·αd + βc·βd) + (αd² + βd²)
1152 -- = (|c-a|² + |d-a|²) - 2((c-a)·(d-a)) = |c - d|².
1153 have h_cd_eq : (αc - αd)*(αc - αd) + (βc - βd)*(βc - βd) = (c 0 - d 0)^2 + (c 1 - d 1)^2 := by
1154 have e1 : αc * αd + βc * βd = (c 0 - a 0)*(d 0 - a 0) + (c 1 - a 1)*(d 1 - a 1) := by
1155 have hΔΔ_pos : 0 < Δ*Δ := mul_pos hΔ_pos hΔ_pos
1156 have h1 : αc * αd = (((c 0 - a 0)*(b 0 - a 0) + (c 1 - a 1)*(b 1 - a 1)) *
1157 ((d 0 - a 0)*(b 0 - a 0) + (d 1 - a 1)*(b 1 - a 1))) / (Δ*Δ) := by
1158 rw [hαc_def, hαd_def]; field_simp
1159 have h2 : βc * βd = (((b 0 - a 0)*(c 1 - a 1) - (b 1 - a 1)*(c 0 - a 0)) *
1160 ((b 0 - a 0)*(d 1 - a 1) - (b 1 - a 1)*(d 0 - a 0))) / (Δ*Δ) := by
1161 rw [hβc_def, hβd_def]; field_simp
1162 rw [h1, h2, ← add_div]
1163 rw [hLag_pol, ← hab_sq]
1164 field_simp
1165 have e2 : (αc - αd)*(αc - αd) + (βc - βd)*(βc - βd) =
1166 (αc*αc + βc*βc) + (αd*αd + βd*βd) - 2*(αc*αd + βc*βd) := by ring
1167 rw [e2, h_αcβc_eq_ac, h_αdβd_eq_ad, e1]
1168 ring
1169 -- Translate orient2 sign: orient2 a b c = βc · Δ (with our sign convention).
1170 have hβc_orient : βc * Δ = orient2 a b c := by
1171 rw [hβc_def]
1172 field_simp
1173 unfold orient2
1174 ring
1175 have hβd_orient : βd * Δ = orient2 a b d := by
1176 rw [hβd_def]
1177 field_simp
1178 unfold orient2
1179 ring
1180 have hβ_prod : 0 < βc * βd := by
1181 have h := hProper.1
1182 have : 0 < (βc * Δ) * (βd * Δ) := by
1183 rw [hβc_orient, hβd_orient]; exact h
1184 have hΔΔ_pos : 0 < Δ*Δ := mul_pos hΔ_pos hΔ_pos
1185 nlinarith [this, hΔΔ_pos]
1186 -- Convert squared lens constraints to αc, βc form (≤ Δ*Δ form):
1187 have hi_lens : αc*αc + βc*βc ≤ Δ*Δ := by rw [h_αcβc_eq_ac]; exact hac_sq_le
1188 have hii_lens : (αc - Δ)*(αc - Δ) + βc*βc ≤ Δ*Δ := by rw [h_αcβc_eq_bc]; exact hbc_sq_le
1189 have hiii_lens : αd*αd + βd*βd ≤ Δ*Δ := by rw [h_αdβd_eq_ad]; exact had_sq_le
1190 have hiv_lens : (αd - Δ)*(αd - Δ) + βd*βd ≤ Δ*Δ := by rw [h_αdβd_eq_bd]; exact hbd_sq_le
1191 -- Case split on sign of βc.
1192 rcases lt_trichotomy βc 0 with hβc | hβc | hβc
1193 · -- βc < 0, βd < 0 (from positive product).
1194 have hβd : βd < 0 := by
1195 by_contra h
1196 push_neg at h
1197 have hβd_nn := h
1198 rcases lt_or_eq_of_le hβd_nn with hβd_pos | hβd_zero
1199 · have : βc * βd < 0 := mul_neg_of_neg_of_pos hβc hβd_pos
1200 linarith [hβ_prod, this]
1201 · rw [← hβd_zero] at hβ_prod; linarith
1202 have hp := hopf_pannwitz_strict_lens_coord_neg Δ αc βc αd βd hΔ_pos
1203 hi_lens hii_lens hiii_lens hiv_lens hβc hβd
1204 -- hp : (αc - αd)*(αc - αd) + (βc - βd)*(βc - βd) < Δ*Δ
1205 rw [h_cd_eq] at hp
1206 linarith [hp, hcd_sq_eq]
1207 · -- βc = 0 contradicts hβ_prod.
1208 rw [hβc] at hβ_prod; linarith [hβ_prod]
1209 · -- βc > 0, βd > 0.
1210 have hβd : 0 < βd := by
1211 by_contra h
1212 push_neg at h
1213 have hβd_le := h
1214 rcases lt_or_eq_of_le hβd_le with hβd_neg | hβd_zero
1215 · have : βc * βd < 0 := mul_neg_of_pos_of_neg hβc hβd_neg
1216 linarith [hβ_prod, this]
1217 · rw [hβd_zero] at hβ_prod; linarith
1218 have hp := hopf_pannwitz_strict_lens_coord Δ αc βc αd βd hΔ_pos
1219 hi_lens hii_lens hiii_lens hiv_lens hβc hβd
1220 rw [h_cd_eq] at hp
1221 linarith [hp, hcd_sq_eq]
1222
1223/-- Abstract bridge for the collinear separated case: two disjoint collinear
1224diameter-length segments force one cross-distance to exceed the diameter.
1225This bridge is now a *theorem* (see `collinearSeparatedDiameterContradiction`
1226below), so any use of `CollinearSeparatedDiameterContradiction` as a hypothesis
1227can be discharged unconditionally. -/
1228def CollinearSeparatedDiameterContradiction : Prop :=
1229 ∀ (a b c d : Point2) (Δ : ℝ),
1230 a ≠ c → a ≠ d → b ≠ c → b ≠ d →
1231 dist a b = Δ →
1232 dist c d = Δ →
1233 dist a c ≤ Δ →
1234 dist a d ≤ Δ →
1235 dist b c ≤ Δ →
1236 dist b d ≤ Δ →
1237 CollinearSegmentSeparation a b c d →
1238 False
1239
1240/-- Collinear diameter contradiction without the unused geometric-disjointness
1241field. Four collinear endpoints with equal diameter-length opposite pairs and
1242all four cross distances bounded by that diameter cannot be endpoint-disjoint. -/
1243def CollinearDiameterEndpointContradiction : Prop :=
1244 ∀ (a b c d : Point2) (Δ : ℝ),
1245 a ≠ c → a ≠ d → b ≠ c → b ≠ d →
1246 dist a b = Δ →
1247 dist c d = Δ →
1248 dist a c ≤ Δ →
1249 dist a d ≤ Δ →
1250 dist b c ≤ Δ →
1251 dist b d ≤ Δ →
1252 orient2 a b c = 0 →
1253 orient2 a b d = 0 →
1254 False
1255
1256/-- **Theorem.** Four collinear points with `dist a b = dist c d = Δ` and all
1257four cross distances `≤ Δ` cannot have `a ≠ c, a ≠ d, b ≠ c, b ≠ d`. The
1258geometric-disjointness data in `CollinearSegmentSeparation` is not used here:
1259the four-point coordinate parametrization on the common line gives a
1260contradiction directly from `|s - t| = 1` with `t, s ∈ [0,1]` forcing
1261`{t,s} = {0,1}` and hence `c = a` or `c = b`. -/
1262theorem collinearDiameterEndpointContradiction :
1263 CollinearDiameterEndpointContradiction := by
1264 intro a b c d Δ h_ac h_ad h_bc h_bd hab hcd hac had hbc hbd h_abc h_abd
1265 by_cases hΔ : Δ = 0
1266 · subst hΔ
1267 have h_eq0 : dist a c = 0 := le_antisymm hac dist_nonneg
1268 exact h_ac (eq_of_dist_eq_zero h_eq0)
1269 have hΔ_nn : 0 ≤ Δ := hab ▸ dist_nonneg
1270 have hΔ_pos : 0 < Δ := lt_of_le_of_ne hΔ_nn (Ne.symm hΔ)
1271 have h_ab : a ≠ b := by
1272 intro he
1273 rw [he, dist_self] at hab
1274 exact hΔ hab.symm
1275 obtain ⟨t, ht⟩ := exists_scalar_of_orient2_zero h_ab h_abc
1276 obtain ⟨s, hs⟩ := exists_scalar_of_orient2_zero h_ab h_abd
1277 have hac_eq : dist a c = |t| * Δ := by rw [dist_from_diff_eq_smul ht, hab]
1278 have had_eq : dist a d = |s| * Δ := by rw [dist_from_diff_eq_smul hs, hab]
1279 have hbc_param : ∀ i : Fin 2, c i - b i = (t - 1) * (b i - a i) := by
1280 intro i; have := ht i; linarith
1281 have hbc_eq : dist b c = |t - 1| * Δ := by
1282 rw [dist_from_diff_eq_smul hbc_param, hab]
1283 have hbd_param : ∀ i : Fin 2, d i - b i = (s - 1) * (b i - a i) := by
1284 intro i; have := hs i; linarith
1285 have hbd_eq : dist b d = |s - 1| * Δ := by
1286 rw [dist_from_diff_eq_smul hbd_param, hab]
1287 have hcd_param : ∀ i : Fin 2, d i - c i = (s - t) * (b i - a i) := by
1288 intro i
1289 have h1 := ht i
1290 have h2 := hs i
1291 linarith
1292 have hcd_eq : dist c d = |s - t| * Δ := by
1293 rw [dist_from_diff_eq_smul hcd_param, hab]
1294 have habst : |t| ≤ 1 := by
1295 have h1 : |t| * Δ ≤ 1 * Δ := by
1296 rw [one_mul]; linarith [hac_eq ▸ hac]
1297 exact le_of_mul_le_mul_right h1 hΔ_pos
1298 have habs1mt : |t - 1| ≤ 1 := by
1299 have h1 : |t - 1| * Δ ≤ 1 * Δ := by
1300 rw [one_mul]; linarith [hbc_eq ▸ hbc]
1301 exact le_of_mul_le_mul_right h1 hΔ_pos
1302 have habss : |s| ≤ 1 := by
1303 have h1 : |s| * Δ ≤ 1 * Δ := by
1304 rw [one_mul]; linarith [had_eq ▸ had]
1305 exact le_of_mul_le_mul_right h1 hΔ_pos
1306 have habs1ms : |s - 1| ≤ 1 := by
1307 have h1 : |s - 1| * Δ ≤ 1 * Δ := by
1308 rw [one_mul]; linarith [hbd_eq ▸ hbd]
1309 exact le_of_mul_le_mul_right h1 hΔ_pos
1310 have habs_st : |s - t| = 1 := by
1311 have h1 : |s - t| * Δ = 1 * Δ := by rw [one_mul, ← hcd_eq]; exact hcd
1312 exact mul_right_cancel₀ (ne_of_gt hΔ_pos) h1
1313 have ht_le1 : t ≤ 1 := (abs_le.mp habst).2
1314 have hneg1mt_le1 : -(1:ℝ) ≤ t - 1 := (abs_le.mp habs1mt).1
1315 have ht_nn : 0 ≤ t := by linarith
1316 have hs_le1 : s ≤ 1 := (abs_le.mp habss).2
1317 have hneg1ms_le1 : -(1:ℝ) ≤ s - 1 := (abs_le.mp habs1ms).1
1318 have hs_nn : 0 ≤ s := by linarith
1319 have h_st_diff : s - t = 1 ∨ s - t = -1 :=
1320 (abs_eq (by norm_num : (0:ℝ) ≤ 1)).mp habs_st
1321 rcases h_st_diff with hd | hd
1322 · have ht0 : t = 0 := by linarith
1323 have _hs1 : s = 1 := by linarith
1324 have hca : c = a := by
1325 ext i; have := ht i; rw [ht0] at this; linarith
1326 exact h_ac hca.symm
1327 · have ht1 : t = 1 := by linarith
1328 have _hs0 : s = 0 := by linarith
1329 have hcb : c = b := by
1330 ext i; have := ht i; rw [ht1] at this; linarith
1331 exact h_bc hcb.symm
1332
1333/-- The older separated-case theorem follows immediately from the sharper
1334collinear endpoint contradiction by ignoring the disjointness field. -/
1335theorem collinearSeparatedDiameterContradiction :
1336 CollinearSeparatedDiameterContradiction := by
1337 intro a b c d Δ h_ac h_ad h_bc h_bd hab hcd hac had hbc hbd hCol
1338 exact collinearDiameterEndpointContradiction a b c d Δ
1339 h_ac h_ad h_bc h_bd hab hcd hac had hbc hbd hCol.1 hCol.2.1
1340
1341/-- Unified separated-diameter contradiction: no separated-segment certificate
1342(proper or collinear) can coexist with the diameter equalities and all four
1343cross-distance upper bounds. -/
1344def SeparatedDiameterContradiction : Prop :=
1345 ∀ (a b c d : Point2) (Δ : ℝ),
1346 a ≠ c → a ≠ d → b ≠ c → b ≠ d →
1347 dist a b = Δ →
1348 dist c d = Δ →
1349 dist a c ≤ Δ →
1350 dist a d ≤ Δ →
1351 dist b c ≤ Δ →
1352 dist b d ≤ Δ →
1353 (ProperSegmentSeparation a b c d ∨ CollinearSegmentSeparation a b c d) →
1354 False
1355
1356/-- The unified separated-diameter contradiction supplies the proper case. -/
1357theorem proper_contradiction_from_separated_diameter
1358 (h : SeparatedDiameterContradiction) :
1359 ProperSeparatedDiameterContradiction := by
1360 intro a b c d Δ hac had hbc hbd hab hcd hac_le had_le hbc_le hbd_le hproper
1361 exact h a b c d Δ hac had hbc hbd hab hcd hac_le had_le hbc_le hbd_le
1362 (Or.inl hproper)
1363
1364/-- The unified separated-diameter contradiction supplies the collinear case. -/
1365theorem collinear_contradiction_from_separated_diameter
1366 (h : SeparatedDiameterContradiction) :
1367 CollinearSeparatedDiameterContradiction := by
1368 intro a b c d Δ hac had hbc hbd hab hcd hac_le had_le hbc_le hbd_le hcol
1369 exact h a b c d Δ hac had hbc hbd hab hcd hac_le had_le hbc_le hbd_le
1370 (Or.inr hcol)
1371
1372/-- Segment-separation plus the unified separated-diameter contradiction prove
1373the four-point crossing lemma. -/
1374theorem four_point_diameter_crossing_from_separated_diameter
1375 (hSep : DisjointSegmentsHaveSeparation)
1376 (hContr : SeparatedDiameterContradiction) :
1377 FourPointDiameterCrossing := by
1378 intro a b c d Δ h_ac h_ad h_bc h_bd hab hcd hac had hbc hbd
1379 by_cases hmeet : OrderedEdgesMeetGeometrically (a, b) (c, d)
1380 · exact hmeet
1381 · exfalso
1382 have hdisj : OrderedEdgesGeometricallyDisjoint (a, b) (c, d) := hmeet
1383 exact hContr a b c d Δ h_ac h_ad h_bc h_bd hab hcd hac had hbc hbd
1384 (hSep a b c d h_ac h_ad h_bc h_bd hdisj)
1385
1386/-- The segment-separation case split plus the two separated-diameter
1387contradictions prove the four-point crossing lemma. All easy endpoint-sharing
1388and Δ = 0 cases have already been discharged elsewhere; this theorem handles
1389the remaining proof route by contradiction from geometric disjointness. -/
1390theorem four_point_diameter_crossing_from_separation_bridges
1391 (hSep : DisjointSegmentsHaveSeparation)
1392 (hProper : ProperSeparatedDiameterContradiction)
1393 (hCollinear : CollinearSeparatedDiameterContradiction) :
1394 FourPointDiameterCrossing := by
1395 intro a b c d Δ h_ac h_ad h_bc h_bd hab hcd hac had hbc hbd
1396 by_cases hmeet : OrderedEdgesMeetGeometrically (a, b) (c, d)
1397 · exact hmeet
1398 · exfalso
1399 have hdisj : OrderedEdgesGeometricallyDisjoint (a, b) (c, d) := hmeet
1400 rcases hSep a b c d h_ac h_ad h_bc h_bd hdisj with hProperSep | hColSep
1401 · exact hProper a b c d Δ h_ac h_ad h_bc h_bd hab hcd hac had hbc hbd hProperSep
1402 · exact hCollinear a b c d Δ h_ac h_ad h_bc h_bd hab hcd hac had hbc hbd hColSep
1403
1404/-- The four-point crossing lemma implies the endpoint-disjoint local meeting
1405bridge. All four cross-distances are at most the diameter by `IsDiameterShell`,
1406and endpoint-disjointness is precisely the four `≠` hypotheses. -/
1407theorem endpoint_disjoint_local_meeting_from_four_point
1408 (h4 : FourPointDiameterCrossing) :
1409 EndpointDisjointDiameterSegmentsMeetLocally := by
1410 filter_upwards with n
1411 intro A _hA Δ hΔ e he f hf hShare
1412 classical
1413 -- Unpack `e ∈ diameterOrderedEdges A Δ`.
1414 have heFilter := Finset.mem_filter.mp he
1415 have heDist : dist e.1 e.2 = Δ := heFilter.2
1416 have heEvents := Finset.mem_filter.mp heFilter.1
1417 have heProd := Finset.mem_product.mp heEvents.1
1418 have he1A : e.1 ∈ A := heProd.1
1419 have he2A : e.2 ∈ A := heProd.2
1420 -- Unpack `f ∈ diameterOrderedEdges A Δ`.
1421 have hfFilter := Finset.mem_filter.mp hf
1422 have hfDist : dist f.1 f.2 = Δ := hfFilter.2
1423 have hfEvents := Finset.mem_filter.mp hfFilter.1
1424 have hfProd := Finset.mem_product.mp hfEvents.1
1425 have hf1A : f.1 ∈ A := hfProd.1
1426 have hf2A : f.2 ∈ A := hfProd.2
1427 -- Endpoint-disjointness from `¬ OrderedEdgesShareEndpoint e f`.
1428 have h13 : e.1 ≠ f.1 := fun hk => hShare (Or.inl hk)
1429 have h14 : e.1 ≠ f.2 := fun hk => hShare (Or.inr (Or.inl hk))
1430 have h23 : e.2 ≠ f.1 := fun hk => hShare (Or.inr (Or.inr (Or.inl hk)))
1431 have h24 : e.2 ≠ f.2 := fun hk => hShare (Or.inr (Or.inr (Or.inr hk)))
1432 -- All four cross-distances lie in the ordered distance spectrum, so they are
1433 -- bounded by the diameter `Δ`.
1434 have hΔmax : ∀ s ∈ orderedDistanceSpectrum A, s ≤ Δ := hΔ.2
1435 have hSpec : ∀ x y : Point2,
1436 x ∈ A → y ∈ A → x ≠ y → dist x y ∈ orderedDistanceSpectrum A := by
1437 intro x y hxA hyA hxy
1438 unfold orderedDistanceSpectrum
1439 refine Finset.mem_image.mpr ⟨(x, y), ?_, rfl⟩
1440 unfold orderedPairEvents
1441 refine Finset.mem_filter.mpr ⟨?_, hxy⟩
1442 exact Finset.mem_product.mpr ⟨hxA, hyA⟩
1443 have hd13 : dist e.1 f.1 ≤ Δ := hΔmax _ (hSpec _ _ he1A hf1A h13)
1444 have hd14 : dist e.1 f.2 ≤ Δ := hΔmax _ (hSpec _ _ he1A hf2A h14)
1445 have hd23 : dist e.2 f.1 ≤ Δ := hΔmax _ (hSpec _ _ he2A hf1A h23)
1446 have hd24 : dist e.2 f.2 ≤ Δ := hΔmax _ (hSpec _ _ he2A hf2A h24)
1447 -- Apply the universal four-point lemma.
1448 exact h4 e.1 e.2 f.1 f.2 Δ h13 h14 h23 h24 heDist hfDist hd13 hd14 hd23 hd24
1449
1450/-- The local diameter-segment intersection lemma implies the no-disjoint
1451diameter-edge bridge. -/
1452theorem no_disjoint_diameter_edges_from_local_meeting
1453 (hMeet : DiameterSegmentsMeetLocally) :
1454 NoDisjointDiameterEdges := by
1455 filter_upwards [hMeet] with n hMeetN
1456 intro A hA Δ hΔ e he f hf hDisj
1457 exact hDisj (hMeetN A hA Δ hΔ e he f hf)
1458
1459/-- Ordered straight-line thrackle bound: any ordered edge set on `A` with no
1460geometrically disjoint pairs has at most `2|A|` directed edges. The factor `2`
1461matches the ordered-pair normalization. -/
1462def OrderedThrackleBound : Prop :=
1463 ∀ᶠ n in atTop,
1464 ∀ A : Finset Point2,
1465 A.card = n →
1466 ∀ E : Finset (Point2 × Point2),
1467 (∀ e ∈ E, e.1 ∈ A ∧ e.2 ∈ A ∧ e.1 ≠ e.2) →
1468 (∀ e ∈ E, ∀ f ∈ E, ¬ OrderedEdgesGeometricallyDisjoint e f) →
1469 E.card ≤ 2 * A.card
1470
1471/-- Forget orientation of an ordered edge. -/
1472def unorderedEdgeOfOrdered (e : Point2 × Point2) : Sym2 Point2 :=
1473 Sym2.mk e
1474
1475/-- Reversing an ordered representative does not change its unordered edge. -/
1476theorem unorderedEdgeOfOrdered_swap (e : Point2 × Point2) :
1477 unorderedEdgeOfOrdered e.swap = unorderedEdgeOfOrdered e := by
1478 cases e with
1479 | mk a b =>
1480 unfold unorderedEdgeOfOrdered
1481 exact (Sym2.mk_eq_mk_iff).mpr (Or.inr rfl)
1482
1483/-- Undirected support of an ordered edge set. -/
1484noncomputable def unorderedEdgeSupport (E : Finset (Point2 × Point2)) :
1485 Finset (Sym2 Point2) := by
1486 classical
1487 exact E.image unorderedEdgeOfOrdered
1488
1489/-- Membership in the unordered support is exactly the existence of an ordered
1490representative in the original edge set. -/
1491theorem mem_unorderedEdgeSupport_iff
1492 {E : Finset (Point2 × Point2)} {u : Sym2 Point2} :
1493 u ∈ unorderedEdgeSupport E ↔
1494 ∃ e ∈ E, unorderedEdgeOfOrdered e = u := by
1495 classical
1496 simp [unorderedEdgeSupport]
1497
1498/-- Two unordered support edges have geometrically disjoint representatives if
1499some ordered representatives in `E` are geometrically disjoint. -/
1500def SupportEdgesHaveDisjointRepresentatives
1501 (E : Finset (Point2 × Point2)) (u v : Sym2 Point2) : Prop :=
1502 ∃ e ∈ E, ∃ f ∈ E,
1503 unorderedEdgeOfOrdered e = u ∧
1504 unorderedEdgeOfOrdered f = v ∧
1505 OrderedEdgesGeometricallyDisjoint e f
1506
1507/-- A support-level disjoint pair immediately yields the ordered pair required
1508by the thrackle obstruction. -/
1509theorem ordered_disjoint_pair_of_support_disjoint_pair
1510 {E : Finset (Point2 × Point2)} {u v : Sym2 Point2}
1511 (h : SupportEdgesHaveDisjointRepresentatives E u v) :
1512 ∃ e ∈ E, ∃ f ∈ E, OrderedEdgesGeometricallyDisjoint e f := by
1513 rcases h with ⟨e, he, f, hf, _heu, _hfv, hDisj⟩
1514 exact ⟨e, he, f, hf, hDisj⟩
1515
1516/-- The finite orientation-fiber condition: after forgetting orientation, each
1517undirected edge has at most two directed representatives in `E`. This is pure
1518bookkeeping, separated so it can later be proved once we choose the preferred
1519`Sym2` API for unordered edges. -/
1520def OrientationFiberAtMostTwo (E : Finset (Point2 × Point2)) : Prop :=
1521 ∀ u ∈ unorderedEdgeSupport E,
1522 ((E.filter (fun e => unorderedEdgeOfOrdered e = u)).card) ≤ 2
1523
1524/-- Orientation fibers are universally bounded by two: an unordered pair has at
1525most the two directed representatives `(a,b)` and `(b,a)`. -/
1526theorem orientation_fiber_at_most_two (E : Finset (Point2 × Point2)) :
1527 OrientationFiberAtMostTwo E := by
1528 classical
1529 intro u hu
1530 unfold unorderedEdgeSupport at hu
1531 rw [Finset.mem_image] at hu
1532 rcases hu with ⟨e0, _he0, he0u⟩
1533 let T : Finset (Point2 × Point2) := {e0, e0.swap}
1534 have hsub : (E.filter (fun e => unorderedEdgeOfOrdered e = u)) ⊆ T := by
1535 intro e he
1536 have heu : unorderedEdgeOfOrdered e = u := (Finset.mem_filter.mp he).2
1537 have hmk : Sym2.mk e = Sym2.mk e0 := by
1538 unfold unorderedEdgeOfOrdered at heu he0u
1539 rw [heu, he0u]
1540 have hcases := Sym2.mk_eq_mk_iff.mp hmk
1541 rcases hcases with hEq | hSwap
1542 · subst hEq
1543 simp [T]
1544 · subst hSwap
1545 simp [T]
1546 calc
1547 (E.filter (fun e => unorderedEdgeOfOrdered e = u)).card ≤ T.card :=
1548 Finset.card_le_card hsub
1549 _ ≤ 2 := by
1550 unfold T
1551 exact Finset.card_le_two
1552
1553/-- Pure finite bookkeeping: if every orientation fiber has size at most two,
1554then the ordered edge set has at most twice its undirected support. -/
1555theorem ordered_card_le_two_mul_unordered_support
1556 (E : Finset (Point2 × Point2))
1557 (hFib : OrientationFiberAtMostTwo E) :
1558 E.card ≤ 2 * (unorderedEdgeSupport E).card := by
1559 classical
1560 let f : Point2 × Point2 → Sym2 Point2 := unorderedEdgeOfOrdered
1561 have hMaps :
1562 Set.MapsTo f ↑E ↑(unorderedEdgeSupport E) := by
1563 intro e he
1564 unfold unorderedEdgeSupport f
1565 exact Finset.mem_image.mpr ⟨e, he, rfl⟩
1566 have hFiber :=
1567 Finset.card_eq_sum_card_fiberwise
1568 (s := E)
1569 (t := unorderedEdgeSupport E)
1570 (f := f) hMaps
1571 rw [hFiber]
1572 calc
1573 (∑ u ∈ unorderedEdgeSupport E, {a ∈ E | f a = u}.card)
1574 ≤ ∑ _u ∈ unorderedEdgeSupport E, 2 := by
1575 apply Finset.sum_le_sum
1576 intro u hu
1577 simpa [f, OrientationFiberAtMostTwo] using hFib u hu
1578 _ = 2 * (unorderedEdgeSupport E).card := by
1579 simp [Finset.sum_const, mul_comm]
1580
1581/-- Two ordered edges meet simply if their closed segments share exactly one
1582point. The Conway straight-line thrackle theorem counts edges under this
1583condition; it excludes overlapping collinear segments that can inflate the
1584pairwise-meeting count past `|A|`. -/
1585def OrderedEdgesMeetSimply (e f : Point2 × Point2) : Prop :=
1586 ∃! x : Point2, OnClosedSegment e.1 e.2 x ∧ OnClosedSegment f.1 f.2 x
1587
1588/-- Simple meeting is symmetric in the two ordered edges. -/
1589theorem ordered_edges_meet_simply_symm
1590 {e f : Point2 × Point2} (h : OrderedEdgesMeetSimply e f) :
1591 OrderedEdgesMeetSimply f e := by
1592 rcases h with ⟨x, hx, huniq⟩
1593 refine ⟨x, ⟨hx.2, hx.1⟩, ?_⟩
1594 intro y hy
1595 exact huniq y ⟨hy.2, hy.1⟩
1596
1597/-- Symmetric iff form of simple meeting. -/
1598theorem ordered_edges_meet_simply_comm (e f : Point2 × Point2) :
1599 OrderedEdgesMeetSimply e f ↔ OrderedEdgesMeetSimply f e :=
1600 ⟨ordered_edges_meet_simply_symm, ordered_edges_meet_simply_symm⟩
1601
1602/-- Swapping the first edge's orientation preserves simple meeting. -/
1603theorem ordered_edges_meet_simply_swap_left
1604 {a b : Point2} {f : Point2 × Point2}
1605 (h : OrderedEdgesMeetSimply (a, b) f) :
1606 OrderedEdgesMeetSimply (b, a) f := by
1607 rcases h with ⟨x, hx, huniq⟩
1608 refine ⟨x, ⟨on_closed_segment_symm hx.1, hx.2⟩, ?_⟩
1609 intro y hy
1610 exact huniq y ⟨on_closed_segment_symm hy.1, hy.2⟩
1611
1612/-- Swapping the second edge's orientation preserves simple meeting. -/
1613theorem ordered_edges_meet_simply_swap_right
1614 {e : Point2 × Point2} {c d : Point2}
1615 (h : OrderedEdgesMeetSimply e (c, d)) :
1616 OrderedEdgesMeetSimply e (d, c) := by
1617 rcases h with ⟨x, hx, huniq⟩
1618 refine ⟨x, ⟨hx.1, on_closed_segment_symm hx.2⟩, ?_⟩
1619 intro y hy
1620 exact huniq y ⟨hy.1, on_closed_segment_symm hy.2⟩
1621
1622/-- Swapping both edge orientations preserves simple meeting. -/
1623theorem ordered_edges_meet_simply_swap_both
1624 {a b c d : Point2}
1625 (h : OrderedEdgesMeetSimply (a, b) (c, d)) :
1626 OrderedEdgesMeetSimply (b, a) (d, c) :=
1627 ordered_edges_meet_simply_swap_right
1628 (ordered_edges_meet_simply_swap_left h)
1629
1630/-- Simple meeting implies geometric meeting. -/
1631theorem ordered_edges_meet_of_meet_simply
1632 {e f : Point2 × Point2} (h : OrderedEdgesMeetSimply e f) :
1633 OrderedEdgesMeetGeometrically e f := by
1634 rcases h with ⟨x, hx, _huniq⟩
1635 exact ⟨x, hx⟩
1636
1637/-- Simple meeting only depends on the unordered edge classes, not on the chosen
1638orientation of each ordered representative. -/
1639theorem ordered_edges_meet_simply_of_same_unordered
1640 {e e₀ f f₀ : Point2 × Point2}
1641 (he : unorderedEdgeOfOrdered e = unorderedEdgeOfOrdered e₀)
1642 (hf : unorderedEdgeOfOrdered f = unorderedEdgeOfOrdered f₀)
1643 (h : OrderedEdgesMeetSimply e₀ f₀) :
1644 OrderedEdgesMeetSimply e f := by
1645 unfold unorderedEdgeOfOrdered at he hf
1646 have hecases := Sym2.mk_eq_mk_iff.mp he
1647 have hfcases := Sym2.mk_eq_mk_iff.mp hf
1648 rcases hecases with heq | hswap <;> rcases hfcases with hfeq | hfswap
1649 · subst heq
1650 subst hfeq
1651 exact h
1652 · subst heq
1653 subst hfswap
1654 exact ordered_edges_meet_simply_swap_right h
1655 · subst hswap
1656 subst hfeq
1657 exact ordered_edges_meet_simply_swap_left h
1658 · subst hswap
1659 subst hfswap
1660 exact ordered_edges_meet_simply_swap_both h
1661
1662/-- A pairwise-simply-meeting edge system is a Conway straight-line thrackle:
1663every pair of distinct edges shares exactly one point (shared endpoint or
1664proper crossing). -/
1665def IsConwayThrackle (E : Finset (Point2 × Point2)) : Prop :=
1666 ∀ e ∈ E, ∀ f ∈ E, e ≠ f → OrderedEdgesMeetSimply e f
1667
1668/-- Support-level simple meeting: two unordered support edges have ordered
1669representatives in `E` whose closed segments share exactly one point. This is
1670the right formulation for ordered edge sets that contain both orientations of
1671the same undirected edge. -/
1672def SupportEdgesMeetSimply
1673 (E : Finset (Point2 × Point2)) (u v : Sym2 Point2) : Prop :=
1674 ∃ e ∈ E, ∃ f ∈ E,
1675 unorderedEdgeOfOrdered e = u ∧
1676 unorderedEdgeOfOrdered f = v ∧
1677 OrderedEdgesMeetSimply e f
1678
1679/-- Ordered representatives that meet simply give simple meeting of their
1680unordered support classes. -/
1681theorem support_edges_meet_simply_of_ordered_representatives
1682 {E : Finset (Point2 × Point2)} {e f : Point2 × Point2}
1683 (he : e ∈ E) (hf : f ∈ E)
1684 (hSimple : OrderedEdgesMeetSimply e f) :
1685 SupportEdgesMeetSimply E (unorderedEdgeOfOrdered e) (unorderedEdgeOfOrdered f) :=
1686 ⟨e, he, f, hf, rfl, rfl, hSimple⟩
1687
1688/-- The support-level simple-meeting relation is symmetric. -/
1689theorem support_edges_meet_simply_symm
1690 {E : Finset (Point2 × Point2)} {u v : Sym2 Point2}
1691 (h : SupportEdgesMeetSimply E u v) :
1692 SupportEdgesMeetSimply E v u := by
1693 rcases h with ⟨e, he, f, hf, heu, hfv, hSimple⟩
1694 exact ⟨f, hf, e, he, hfv, heu, ordered_edges_meet_simply_symm hSimple⟩
1695
1696/-- Chosen ordered representative for one unordered support edge. -/
1697noncomputable def chosenSupportRepresentative
1698 (E : Finset (Point2 × Point2))
1699 (u : {u : Sym2 Point2 // u ∈ unorderedEdgeSupport E}) :
1700 Point2 × Point2 :=
1701 Classical.choose (mem_unorderedEdgeSupport_iff.mp u.2)
1702
1703/-- The chosen representative belongs to the original ordered edge set. -/
1704theorem chosenSupportRepresentative_mem
1705 (E : Finset (Point2 × Point2))
1706 (u : {u : Sym2 Point2 // u ∈ unorderedEdgeSupport E}) :
1707 chosenSupportRepresentative E u ∈ E :=
1708 (Classical.choose_spec (mem_unorderedEdgeSupport_iff.mp u.2)).1
1709
1710/-- The chosen representative has the required unordered support class. -/
1711theorem chosenSupportRepresentative_unordered
1712 (E : Finset (Point2 × Point2))
1713 (u : {u : Sym2 Point2 // u ∈ unorderedEdgeSupport E}) :
1714 unorderedEdgeOfOrdered (chosenSupportRepresentative E u) = u.1 :=
1715 (Classical.choose_spec (mem_unorderedEdgeSupport_iff.mp u.2)).2
1716
1717/-- One chosen ordered representative per unordered support edge. -/
1718noncomputable def chosenOrderedSupport (E : Finset (Point2 × Point2)) :
1719 Finset (Point2 × Point2) := by
1720 classical
1721 exact (unorderedEdgeSupport E).attach.image (chosenSupportRepresentative E)
1722
1723/-- Chosen support representatives are drawn from the original ordered edge
1724set. -/
1725theorem chosenOrderedSupport_subset
1726 (E : Finset (Point2 × Point2)) :
1727 chosenOrderedSupport E ⊆ E := by
1728 classical
1729 intro e he
1730 unfold chosenOrderedSupport at he
1731 rw [Finset.mem_image] at he
1732 rcases he with ⟨u, _hu, rfl⟩
1733 exact chosenSupportRepresentative_mem E u
1734
1735/-- The chosen representative set has exactly the same unordered support as the
1736original ordered edge set. -/
1737theorem unorderedEdgeSupport_chosenOrderedSupport
1738 (E : Finset (Point2 × Point2)) :
1739 unorderedEdgeSupport (chosenOrderedSupport E) = unorderedEdgeSupport E := by
1740 classical
1741 ext u
1742 constructor
1743 · intro hu
1744 rcases (mem_unorderedEdgeSupport_iff.mp hu) with ⟨e, he, heu⟩
1745 exact mem_unorderedEdgeSupport_iff.mpr
1746 ⟨e, chosenOrderedSupport_subset E he, heu⟩
1747 · intro hu
1748 let usub : {u : Sym2 Point2 // u ∈ unorderedEdgeSupport E} := ⟨u, hu⟩
1749 apply mem_unorderedEdgeSupport_iff.mpr
1750 refine ⟨chosenSupportRepresentative E usub, ?_, ?_⟩
1751 · unfold chosenOrderedSupport
1752 rw [Finset.mem_image]
1753 exact ⟨usub, Finset.mem_attach _ _, rfl⟩
1754 · exact chosenSupportRepresentative_unordered E usub
1755
1756/-- Chosen representatives are injective as a map from unordered support classes
1757to ordered representatives. -/
1758theorem chosenSupportRepresentative_injective
1759 (E : Finset (Point2 × Point2)) :
1760 Function.Injective (chosenSupportRepresentative E) := by
1761 intro u v huv
1762 apply Subtype.ext
1763 have hu := chosenSupportRepresentative_unordered E u
1764 have hv := chosenSupportRepresentative_unordered E v
1765 calc
1766 u.1 = unorderedEdgeOfOrdered (chosenSupportRepresentative E u) := hu.symm
1767 _ = unorderedEdgeOfOrdered (chosenSupportRepresentative E v) := by rw [huv]
1768 _ = v.1 := hv
1769
1770/-- The chosen representative finset has the same cardinality as the unordered
1771support. -/
1772theorem chosenOrderedSupport_card
1773 (E : Finset (Point2 × Point2)) :
1774 (chosenOrderedSupport E).card = (unorderedEdgeSupport E).card := by
1775 classical
1776 unfold chosenOrderedSupport
1777 rw [Finset.card_image_of_injective]
1778 · simp
1779 · exact chosenSupportRepresentative_injective E
1780
1781/-- Conway condition on unordered support. This is the correct condition for
1782diameter edge sets, because `diameterOrderedEdges` contains both orientations
1783of every edge and therefore cannot be a Conway thrackle as an ordered finset. -/
1784def IsConwayThrackleSupport (E : Finset (Point2 × Point2)) : Prop :=
1785 ∀ u ∈ unorderedEdgeSupport E,
1786 ∀ v ∈ unorderedEdgeSupport E,
1787 u ≠ v → SupportEdgesMeetSimply E u v
1788
1789/-- Support-level Conway condition promotes to the ordinary ordered Conway
1790condition on the chosen representative finset. -/
1791theorem isConwayThrackle_chosenOrderedSupport
1792 {E : Finset (Point2 × Point2)}
1793 (hSupport : IsConwayThrackleSupport E) :
1794 IsConwayThrackle (chosenOrderedSupport E) := by
1795 classical
1796 intro e he f hf hef
1797 unfold chosenOrderedSupport at he hf
1798 rw [Finset.mem_image] at he
1799 rw [Finset.mem_image] at hf
1800 rcases he with ⟨u, _hu, rfl⟩
1801 rcases hf with ⟨v, _hv, rfl⟩
1802 have huv : u.1 ≠ v.1 := by
1803 intro hval
1804 exact hef (congrArg (chosenSupportRepresentative E) (Subtype.ext hval))
1805 rcases hSupport u.1 u.2 v.1 v.2 huv with
1806 ⟨e₀, _he₀, f₀, _hf₀, he₀u, hf₀v, hSimple⟩
1807 exact ordered_edges_meet_simply_of_same_unordered
1808 (by rw [chosenSupportRepresentative_unordered E u, he₀u])
1809 (by rw [chosenSupportRepresentative_unordered E v, hf₀v])
1810 hSimple
1811
1812/-- Conway straight-line thrackle support bound: if every pair of edges meets
1813simply, the undirected support has at most `|A|` edges. This is the correct
1814Lovász-Pach-Szegedy / Cairns-Nikolayevsky counting theorem. The bound is
1815false without the "simply" condition (collinear overlapping counterexample). -/
1816def ConwayThrackleSupportBound : Prop :=
1817 ∀ A : Finset Point2,
1818 ∀ E : Finset (Point2 × Point2),
1819 (∀ e ∈ E, e.1 ∈ A ∧ e.2 ∈ A ∧ e.1 ≠ e.2) →
1820 IsConwayThrackle E →
1821 (unorderedEdgeSupport E).card ≤ A.card
1822
1823/-- Constructive form of the Conway straight-line thrackle theorem: for each
1824finite straight-line Conway thrackle, charge each unordered edge injectively to
1825one ambient vertex. This is equivalent in finite cardinality terms, but is the
1826right target for a future formal proof of the classical theorem. -/
1827def ConwayThrackleEndpointChargeCertificate : Prop :=
1828 ∀ A : Finset Point2,
1829 ∀ E : Finset (Point2 × Point2),
1830 (∀ e ∈ E, e.1 ∈ A ∧ e.2 ∈ A ∧ e.1 ≠ e.2) →
1831 IsConwayThrackle E →
1832 ∃ charge :
1833 {u : Sym2 Point2 // u ∈ unorderedEdgeSupport E} → {x : Point2 // x ∈ A},
1834 Function.Injective charge
1835
1836/-- An injective endpoint charge proves the standard ordered Conway support
1837bound by finite cardinality. -/
1838theorem conway_support_bound_from_endpoint_charge
1839 (hCharge : ConwayThrackleEndpointChargeCertificate) :
1840 ConwayThrackleSupportBound := by
1841 intro A E hEdges hConway
1842 obtain ⟨charge, hInjective⟩ := hCharge A E hEdges hConway
1843 have hcard := Fintype.card_le_of_injective charge hInjective
1844 simpa using hcard
1845
1846/-- Support-level Conway straight-line thrackle support bound. This is the
1847correct theorem surface for ordered finsets that may contain both orientations
1848of an undirected edge. -/
1849def ConwayThrackleSupportBoundOnSupport : Prop :=
1850 ∀ A : Finset Point2,
1851 ∀ E : Finset (Point2 × Point2),
1852 (∀ e ∈ E, e.1 ∈ A ∧ e.2 ∈ A ∧ e.1 ≠ e.2) →
1853 IsConwayThrackleSupport E →
1854 (unorderedEdgeSupport E).card ≤ A.card
1855
1856/-- The standard ordered Conway thrackle theorem implies the support-level form:
1857choose one ordered representative for each unordered support edge, apply the
1858standard theorem to that chosen representative system, then transfer the support
1859cardinality back. -/
1860theorem conway_support_bound_on_support_from_ordered
1861 (hConway : ConwayThrackleSupportBound) :
1862 ConwayThrackleSupportBoundOnSupport := by
1863 intro A E hEdges hSupport
1864 have hChosenEdges :
1865 ∀ e ∈ chosenOrderedSupport E, e.1 ∈ A ∧ e.2 ∈ A ∧ e.1 ≠ e.2 := by
1866 intro e he
1867 exact hEdges e (chosenOrderedSupport_subset E he)
1868 have hCard :
1869 (unorderedEdgeSupport (chosenOrderedSupport E)).card ≤ A.card :=
1870 hConway A (chosenOrderedSupport E) hChosenEdges
1871 (isConwayThrackle_chosenOrderedSupport hSupport)
1872 simpa [unorderedEdgeSupport_chosenOrderedSupport E] using hCard
1873
1874/-- Undirected straight-line thrackle support bound: if an ordered edge set has
1875no geometrically disjoint pairs, then its undirected support has at most `|A|`
1876edges. This is the Perles/Hopf-Pannwitz geometric theorem in its clean
1877undirected form.
1878
1879**Caveat (2026-05-22):** This bound is stated for the set-theoretic meeting
1880predicate (`OrderedEdgesMeetGeometrically`), which allows overlapping segments.
1881For collinear point sets the bound is FALSE in this form. The correct
1882classical statement uses the Conway thrackle condition
1883(`ConwayThrackleSupportBound`). For the Erdős #132 application via diameter
1884segments, the Conway condition is automatically satisfied because distinct
1885diameter segments never overlap (proved by collinear analysis in
1886`collinearSeparatedDiameterContradiction`). -/
1887def UndirectedThrackleSupportBound : Prop :=
1888 ∀ᶠ n in atTop,
1889 ∀ A : Finset Point2,
1890 A.card = n →
1891 ∀ E : Finset (Point2 × Point2),
1892 (∀ e ∈ E, e.1 ∈ A ∧ e.2 ∈ A ∧ e.1 ≠ e.2) →
1893 (∀ e ∈ E, ∀ f ∈ E, ¬ OrderedEdgesGeometricallyDisjoint e f) →
1894 (unorderedEdgeSupport E).card ≤ A.card
1895
1896/-- The Conway support bound implies the general undirected support bound for
1897any edge system that happens to be a Conway thrackle, because simple meeting
1898implies non-disjointness. -/
1899theorem undirected_thrackle_support_of_conway_thrackle
1900 (hConway : ConwayThrackleSupportBound)
1901 (A : Finset Point2) (E : Finset (Point2 × Point2))
1902 (hEdges : ∀ e ∈ E, e.1 ∈ A ∧ e.2 ∈ A ∧ e.1 ≠ e.2)
1903 (hSimple : IsConwayThrackle E) :
1904 (unorderedEdgeSupport E).card ≤ A.card :=
1905 hConway A E hEdges hSimple
1906
1907/-- Diameter-specific ordered thrackle bound. The diameter structure guarantees
1908the Conway condition via the four-point crossing geometry. This is the correct
1909classical target for the Hopf-Pannwitz counting step. -/
1910def DiameterConwayThrackleBound : Prop :=
1911 ∀ A : Finset Point2,
1912 ∀ Δ : ℝ,
1913 IsDiameterShell A Δ →
1914 orderedShellMultiplicity A Δ ≤ 2 * A.card
1915
1916/-- Legacy ordered formulation. This is intentionally kept only as a warning
1917surface: it is false for `diameterOrderedEdges`, because the ordered finset
1918contains both `(a,b)` and `(b,a)` and those two distinct ordered edges have the
1919same segment. Use `DiameterEdgeSupportFormsConwayThrackle` instead. -/
1920def DiameterEdgesFormConwayThrackle : Prop :=
1921 ∀ A : Finset Point2,
1922 ∀ Δ : ℝ,
1923 IsDiameterShell A Δ →
1924 IsConwayThrackle (diameterOrderedEdges A Δ)
1925
1926/-- Correct diameter Conway condition, stated on unordered support rather than
1927the ordered representative finset. -/
1928def DiameterEdgeSupportFormsConwayThrackle : Prop :=
1929 ∀ A : Finset Point2,
1930 ∀ Δ : ℝ,
1931 IsDiameterShell A Δ →
1932 IsConwayThrackleSupport (diameterOrderedEdges A Δ)
1933
1934/-- Local representative form of the diameter-support Conway condition. This is
1935the geometric statement left after removing ordered-orientation duplicates:
1936distinct unordered diameter support edges have ordered representatives whose
1937segments meet in exactly one point. -/
1938def DiameterSupportSimpleRepresentativeCertificate : Prop :=
1939 ∀ A : Finset Point2,
1940 ∀ Δ : ℝ,
1941 IsDiameterShell A Δ →
1942 ∀ u ∈ unorderedEdgeSupport (diameterOrderedEdges A Δ),
1943 ∀ v ∈ unorderedEdgeSupport (diameterOrderedEdges A Δ),
1944 u ≠ v →
1945 SupportEdgesMeetSimply (diameterOrderedEdges A Δ) u v
1946
1947/-- Ordered-representative form of the diameter-support Conway condition. This
1948is the sharp local geometry left on the diameter side: any two ordered diameter
1949representatives of distinct unordered support edges meet in exactly one point. -/
1950def DistinctDiameterRepresentativesMeetSimply : Prop :=
1951 ∀ A : Finset Point2,
1952 ∀ Δ : ℝ,
1953 IsDiameterShell A Δ →
1954 ∀ e ∈ diameterOrderedEdges A Δ,
1955 ∀ f ∈ diameterOrderedEdges A Δ,
1956 unorderedEdgeOfOrdered e ≠ unorderedEdgeOfOrdered f →
1957 OrderedEdgesMeetSimply e f
1958
1959/-- Distinct unordered representatives are distinct ordered edges. This removes
1960the orientation-duplicate pathology from the local diameter representative
1961target. -/
1962theorem ordered_edges_ne_of_unorderedEdgeOfOrdered_ne
1963 {e f : Point2 × Point2}
1964 (h : unorderedEdgeOfOrdered e ≠ unorderedEdgeOfOrdered f) :
1965 e ≠ f := by
1966 intro hef
1967 exact h (by rw [hef])
1968
1969/-- Endpoint-sharing part of the local diameter representative theorem. -/
1970def SharedEndpointDiameterRepresentativesMeetSimply : Prop :=
1971 ∀ A : Finset Point2,
1972 ∀ Δ : ℝ,
1973 IsDiameterShell A Δ →
1974 ∀ e ∈ diameterOrderedEdges A Δ,
1975 ∀ f ∈ diameterOrderedEdges A Δ,
1976 unorderedEdgeOfOrdered e ≠ unorderedEdgeOfOrdered f →
1977 OrderedEdgesShareEndpoint e f →
1978 OrderedEdgesMeetSimply e f
1979
1980/-- Endpoint-disjoint part of the local diameter representative theorem. -/
1981def EndpointDisjointDiameterRepresentativesMeetSimply : Prop :=
1982 ∀ A : Finset Point2,
1983 ∀ Δ : ℝ,
1984 IsDiameterShell A Δ →
1985 ∀ e ∈ diameterOrderedEdges A Δ,
1986 ∀ f ∈ diameterOrderedEdges A Δ,
1987 unorderedEdgeOfOrdered e ≠ unorderedEdgeOfOrdered f →
1988 ¬ OrderedEdgesShareEndpoint e f →
1989 OrderedEdgesMeetSimply e f
1990
1991/-- Uniqueness-only form of the endpoint-disjoint diameter representative
1992geometry. Existence of an intersection is already supplied by
1993`fourPointDiameterCrossing_thm`; this certificate says that two endpoint-disjoint
1994diameter representatives cannot overlap in more than one point. -/
1995def EndpointDisjointDiameterIntersectionUniqueCertificate : Prop :=
1996 ∀ A : Finset Point2,
1997 ∀ Δ : ℝ,
1998 IsDiameterShell A Δ →
1999 ∀ e ∈ diameterOrderedEdges A Δ,
2000 ∀ f ∈ diameterOrderedEdges A Δ,
2001 unorderedEdgeOfOrdered e ≠ unorderedEdgeOfOrdered f →
2002 ¬ OrderedEdgesShareEndpoint e f →
2003 ∀ x y : Point2,
2004 (OnClosedSegment e.1 e.2 x ∧ OnClosedSegment f.1 f.2 x) →
2005 (OnClosedSegment e.1 e.2 y ∧ OnClosedSegment f.1 f.2 y) →
2006 x = y
2007
2008/-- The only remaining geometric content behind endpoint-disjoint uniqueness:
2009if two endpoint-disjoint diameter representatives have two distinct common
2010points, then the second representative's endpoints lie on the line through the
2011first representative. -/
2012def EndpointDisjointTwoPointIntersectionForcesCollinear : Prop :=
2013 ∀ A : Finset Point2,
2014 ∀ Δ : ℝ,
2015 IsDiameterShell A Δ →
2016 ∀ e ∈ diameterOrderedEdges A Δ,
2017 ∀ f ∈ diameterOrderedEdges A Δ,
2018 unorderedEdgeOfOrdered e ≠ unorderedEdgeOfOrdered f →
2019 ¬ OrderedEdgesShareEndpoint e f →
2020 ∀ x y : Point2,
2021 x ≠ y →
2022 (OnClosedSegment e.1 e.2 x ∧ OnClosedSegment f.1 f.2 x) →
2023 (OnClosedSegment e.1 e.2 y ∧ OnClosedSegment f.1 f.2 y) →
2024 orient2 e.1 e.2 f.1 = 0 ∧ orient2 e.1 e.2 f.2 = 0
2025
2026/-- The two-point intersection collinearity certificate is pure affine
2027incidence: two distinct common points determine a line, so both endpoint-disjoint
2028diameter representatives lie on that same line. -/
2029theorem endpoint_disjoint_two_point_intersection_forces_collinear :
2030 EndpointDisjointTwoPointIntersectionForcesCollinear := by
2031 intro A Δ hΔ e he f hf hUne hNoShare x y hxy hx hy
2032 rcases e with ⟨a, b⟩
2033 rcases f with ⟨c, d⟩
2034 have hx_ab : orient2 a b x = 0 := orient2_eq_zero_of_on_closed_segment hx.1
2035 have hy_ab : orient2 a b y = 0 := orient2_eq_zero_of_on_closed_segment hy.1
2036 have hx_cd : orient2 c d x = 0 := orient2_eq_zero_of_on_closed_segment hx.2
2037 have hy_cd : orient2 c d y = 0 := orient2_eq_zero_of_on_closed_segment hy.2
2038 have hcd_ne : c ≠ d := by
2039 rcases diameter_ordered_edge_data hf with ⟨_, _, hne, _⟩
2040 simpa using hne
2041 have hdc_ne : d ≠ c := hcd_ne.symm
2042 have h_cxy : orient2 x y c = 0 := by
2043 have htmp : orient2 c x y = 0 :=
2044 orient2_zero_transitive_swap hcd_ne hx_cd hy_cd
2045 simpa [orient2_cyclic] using htmp
2046 have h_dxy : orient2 x y d = 0 := by
2047 have hx_dc : orient2 d c x = 0 := by
2048 rw [orient2_swap₁₂]
2049 simp [hx_cd]
2050 have hy_dc : orient2 d c y = 0 := by
2051 rw [orient2_swap₁₂]
2052 simp [hy_cd]
2053 have htmp : orient2 d x y = 0 :=
2054 orient2_zero_transitive_swap hdc_ne hx_dc hy_dc
2055 simpa [orient2_cyclic] using htmp
2056 exact ⟨
2057 orient2_zero_of_two_points_on_line_and_point_on_join hxy hx_ab hy_ab h_cxy,
2058 orient2_zero_of_two_points_on_line_and_point_on_join hxy hx_ab hy_ab h_dxy⟩
2059
2060/-- If two common points force collinearity, then endpoint-disjoint diameter
2061intersections are unique: otherwise the sharper collinear diameter endpoint
2062contradiction applies. -/
2063theorem endpoint_disjoint_diameter_intersection_unique_from_two_point_collinear
2064 (hCol : EndpointDisjointTwoPointIntersectionForcesCollinear) :
2065 EndpointDisjointDiameterIntersectionUniqueCertificate := by
2066 intro A Δ hΔ e he f hf hUne hNoShare x y hx hy
2067 by_contra hxy
2068 have hxy_ne : x ≠ y := by exact fun h => hxy h
2069 rcases hCol A Δ hΔ e he f hf hUne hNoShare x y hxy_ne hx hy with
2070 ⟨hcol1, hcol2⟩
2071 rcases e with ⟨a, b⟩
2072 rcases f with ⟨c, d⟩
2073 rcases diameter_ordered_edges_cross_distances_le hΔ he hf with
2074 ⟨hab, hcd, hac, had, hbc, hbd⟩
2075 unfold OrderedEdgesShareEndpoint at hNoShare
2076 simp at hNoShare hcol1 hcol2
2077 have h_ac : a ≠ c := hNoShare.1
2078 have h_ad : a ≠ d := hNoShare.2.1
2079 have h_bc : b ≠ c := hNoShare.2.2.1
2080 have h_bd : b ≠ d := hNoShare.2.2.2
2081 exact collinearDiameterEndpointContradiction a b c d Δ
2082 h_ac h_ad h_bc h_bd hab hcd hac had hbc hbd hcol1 hcol2
2083
2084/-- The shared-endpoint and endpoint-disjoint local diameter representative
2085lemmas combine to give the full ordered-representative certificate. -/
2086theorem distinct_diameter_representatives_meet_simply_from_cases
2087 (hShared : SharedEndpointDiameterRepresentativesMeetSimply)
2088 (hDisjoint : EndpointDisjointDiameterRepresentativesMeetSimply) :
2089 DistinctDiameterRepresentativesMeetSimply := by
2090 intro A Δ hΔ e he f hf hne
2091 by_cases hShare : OrderedEdgesShareEndpoint e f
2092 · exact hShared A Δ hΔ e he f hf hne hShare
2093 · exact hDisjoint A Δ hΔ e he f hf hne hShare
2094
2095/-- The ordered-representative simple-meeting certificate supplies the
2096support-level representative certificate by choosing representatives of the two
2097unordered support edges. -/
2098theorem diameter_support_simple_representatives_from_ordered_representatives
2099 (h : DistinctDiameterRepresentativesMeetSimply) :
2100 DiameterSupportSimpleRepresentativeCertificate := by
2101 intro A Δ hΔ u hu v hv huv
2102 rcases (mem_unorderedEdgeSupport_iff.mp hu) with ⟨e, he, heu⟩
2103 rcases (mem_unorderedEdgeSupport_iff.mp hv) with ⟨f, hf, hfv⟩
2104 refine ⟨e, he, f, hf, heu, hfv, ?_⟩
2105 apply h A Δ hΔ e he f hf
2106 intro hsame
2107 apply huv
2108 rw [← heu, ← hfv]
2109 exact hsame
2110
2111/-- The local representative certificate is exactly enough to show that diameter
2112support forms a Conway thrackle. -/
2113theorem diameter_support_forms_conway_from_simple_representatives
2114 (h : DiameterSupportSimpleRepresentativeCertificate) :
2115 DiameterEdgeSupportFormsConwayThrackle := by
2116 intro A Δ hΔ u hu v hv huv
2117 exact h A Δ hΔ u hu v hv huv
2118
2119/-- Support-level Conway support plus the diameter support Conway condition
2120gives the diameter-specific ordered multiplicity bound. -/
2121theorem diameter_conway_bound_from_support_conway
2122 (hSupport : ConwayThrackleSupportBoundOnSupport)
2123 (hDiam : DiameterEdgeSupportFormsConwayThrackle) :
2124 DiameterConwayThrackleBound := by
2125 intro A Δ hΔ
2126 have hEdges :
2127 ∀ e ∈ diameterOrderedEdges A Δ,
2128 e.1 ∈ A ∧ e.2 ∈ A ∧ e.1 ≠ e.2 := by
2129 intro e he
2130 rcases diameter_ordered_edge_data he with ⟨he1, he2, hne, _hdist⟩
2131 exact ⟨he1, he2, hne⟩
2132 have hOrdered :
2133 (diameterOrderedEdges A Δ).card ≤
2134 2 * (unorderedEdgeSupport (diameterOrderedEdges A Δ)).card :=
2135 ordered_card_le_two_mul_unordered_support
2136 (diameterOrderedEdges A Δ)
2137 (orientation_fiber_at_most_two (diameterOrderedEdges A Δ))
2138 have hSupportCard :
2139 (unorderedEdgeSupport (diameterOrderedEdges A Δ)).card ≤ A.card :=
2140 hSupport A (diameterOrderedEdges A Δ) hEdges (hDiam A Δ hΔ)
2141 simpa [orderedShellMultiplicity_eq_diameterOrderedEdges_card] using
2142 le_trans hOrdered (Nat.mul_le_mul_left 2 hSupportCard)
2143
2144/-- Diameter-specific Conway bound implies the ordinary diameter shell sparsity
2145component used by the Erdős #132 assembly. -/
2146theorem diameter_shell_sparse_from_diameter_conway_bound
2147 (hBound : DiameterConwayThrackleBound) :
2148 DiameterShellSparseBound := by
2149 filter_upwards with n
2150 intro A _hA Δ hΔ
2151 exact ⟨hΔ.1, hBound A Δ hΔ⟩
2152
2153/-- Pointwise form of the undirected straight-line thrackle support theorem.
2154The classical theorem is not asymptotic, so this is the sharper statement that
2155should eventually be proved or imported. -/
2156def PointwiseUndirectedThrackleSupportBound : Prop :=
2157 ∀ A : Finset Point2,
2158 ∀ E : Finset (Point2 × Point2),
2159 (∀ e ∈ E, e.1 ∈ A ∧ e.2 ∈ A ∧ e.1 ≠ e.2) →
2160 (∀ e ∈ E, ∀ f ∈ E, ¬ OrderedEdgesGeometricallyDisjoint e f) →
2161 (unorderedEdgeSupport E).card ≤ A.card
2162
2163/-- Endpoint-charging form of the straight-line thrackle theorem. For each
2164finite pairwise-intersecting straight-line edge system, it asks for an injective
2165charge from unordered support edges into the underlying point set. Once this
2166map is constructed geometrically, the support bound is only finite
2167cardinality. -/
2168def ThrackleEndpointChargingCertificate : Prop :=
2169 ∀ A : Finset Point2,
2170 ∀ E : Finset (Point2 × Point2),
2171 (∀ e ∈ E, e.1 ∈ A ∧ e.2 ∈ A ∧ e.1 ≠ e.2) →
2172 (∀ e ∈ E, ∀ f ∈ E, ¬ OrderedEdgesGeometricallyDisjoint e f) →
2173 ∃ charge :
2174 {u : Sym2 Point2 // u ∈ unorderedEdgeSupport E} → {x : Point2 // x ∈ A},
2175 Function.Injective charge
2176
2177/-- Finite cardinal comparison produces an injection. Mathlib supplies the
2178opposite direction as `Fintype.card_le_of_injective`; this local lemma gives the
2179construction needed to convert support-cardinality proofs into endpoint-charge
2180certificates. -/
2181theorem exists_injective_of_fintype_card_le
2182 {α β : Type*} [Fintype α] [Fintype β]
2183 (h : Fintype.card α ≤ Fintype.card β) :
2184 ∃ f : α → β, Function.Injective f := by
2185 classical
2186 let eα := Fintype.equivFin α
2187 let eβ := Fintype.equivFin β
2188 let f : α → β := fun a => eβ.symm (Fin.castLE h (eα a))
2189 refine ⟨f, ?_⟩
2190 intro a b hab
2191 apply eα.injective
2192 have hfin : Fin.castLE h (eα a) = Fin.castLE h (eα b) := by
2193 apply eβ.symm.injective
2194 exact hab
2195 apply Fin.ext
2196 have hval := congrArg Fin.val hfin
2197 simpa using hval
2198
2199/-- A support-cardinality bound is enough to build the endpoint charge. -/
2200theorem endpoint_charge_of_support_card_le
2201 {A : Finset Point2} {E : Finset (Point2 × Point2)}
2202 (hcard : (unorderedEdgeSupport E).card ≤ A.card) :
2203 ∃ charge :
2204 {u : Sym2 Point2 // u ∈ unorderedEdgeSupport E} → {x : Point2 // x ∈ A},
2205 Function.Injective charge := by
2206 classical
2207 have hFintype :
2208 Fintype.card {u : Sym2 Point2 // u ∈ unorderedEdgeSupport E} ≤
2209 Fintype.card {x : Point2 // x ∈ A} := by
2210 simpa using hcard
2211 exact exists_injective_of_fintype_card_le hFintype
2212
2213/-- The pointwise support theorem and the endpoint-charging theorem are
2214equivalent over finite systems. This direction packages any cardinal proof as
2215an explicit charge. -/
2216theorem thrackle_endpoint_charging_from_pointwise_support
2217 (h : PointwiseUndirectedThrackleSupportBound) :
2218 ThrackleEndpointChargingCertificate := by
2219 intro A E hEdges hNoDisj
2220 exact endpoint_charge_of_support_card_le (h A E hEdges hNoDisj)
2221
2222/-- A directed edge set is a star about `v` when every ordered edge has `v` as
2223one endpoint. -/
2224def OrderedEdgesIncidentTo (v : Point2) (E : Finset (Point2 × Point2)) : Prop :=
2225 ∀ e ∈ E, e.1 = v ∨ e.2 = v
2226
2227/-- Three distinct points in a finite set force cardinality at least three. -/
2228theorem card_ge_three_of_three_mem_distinct
2229 {A : Finset Point2} {x y z : Point2}
2230 (hx : x ∈ A) (hy : y ∈ A) (hz : z ∈ A)
2231 (hxy : x ≠ y) (hxz : x ≠ z) (hyz : y ≠ z) :
2232 3 ≤ A.card := by
2233 classical
2234 let T : Finset Point2 := {x, y, z}
2235 have hsub : T ⊆ A := by
2236 intro w hw
2237 simp [T] at hw
2238 rcases hw with h | h | h
2239 · exact h ▸ hx
2240 · exact h ▸ hy
2241 · exact h ▸ hz
2242 have hT : T.card = 3 := by
2243 simp [T, hxy, hxz, hyz]
2244 exact hT ▸ Finset.card_le_card hsub
2245
2246/-- On at most two ambient points, every nonloop ordered edge system is a star.
2247The empty system is a star about `0`; a nonempty system is a star about the
2248first endpoint of any one edge. -/
2249theorem exists_incident_vertex_of_card_le_two
2250 {A : Finset Point2} {E : Finset (Point2 × Point2)}
2251 (hAcard : A.card ≤ 2)
2252 (hEdges : ∀ e ∈ E, e.1 ∈ A ∧ e.2 ∈ A ∧ e.1 ≠ e.2) :
2253 ∃ v : Point2, OrderedEdgesIncidentTo v E := by
2254 classical
2255 by_cases hE : E.Nonempty
2256 · rcases hE with ⟨e0, he0E⟩
2257 refine ⟨e0.1, ?_⟩
2258 intro e heE
2259 by_contra hnot
2260 have hn1 : e.1 ≠ e0.1 := by
2261 intro h
2262 exact hnot (Or.inl h)
2263 have hn2 : e.2 ≠ e0.1 := by
2264 intro h
2265 exact hnot (Or.inr h)
2266 have he0Data := hEdges e0 he0E
2267 have heData := hEdges e heE
2268 by_cases h_e1_eq_e02 : e.1 = e0.2
2269 · have hthree : 3 ≤ A.card :=
2270 card_ge_three_of_three_mem_distinct
2271 he0Data.1 he0Data.2.1 heData.2.1
2272 he0Data.2.2 hn2.symm (by
2273 intro h
2274 exact heData.2.2 (by
2275 rw [h_e1_eq_e02, h]))
2276 omega
2277 · have hthree : 3 ≤ A.card :=
2278 card_ge_three_of_three_mem_distinct
2279 he0Data.1 he0Data.2.1 heData.1
2280 he0Data.2.2 hn1.symm (by
2281 intro h
2282 exact h_e1_eq_e02 h.symm)
2283 omega
2284 · refine ⟨0, ?_⟩
2285 intro e he
2286 exact False.elim (hE ⟨e, he⟩)
2287
2288/-- On exactly three ambient points, the unordered nonloop support has at most
2289three edges. This closes the first non-star finite boundary case: the triangle
2290itself is maximal. -/
2291theorem unordered_support_card_le_of_card_eq_three
2292 {A : Finset Point2} {E : Finset (Point2 × Point2)}
2293 (hAcard : A.card = 3)
2294 (hEdges : ∀ e ∈ E, e.1 ∈ A ∧ e.2 ∈ A ∧ e.1 ≠ e.2) :
2295 (unorderedEdgeSupport E).card ≤ A.card := by
2296 classical
2297 rcases Finset.card_eq_three.mp hAcard with ⟨x, y, z, hxy, hxz, hyz, hAeq⟩
2298 let T : Finset (Sym2 Point2) :=
2299 {Sym2.mk (x, y), Sym2.mk (x, z), Sym2.mk (y, z)}
2300 have hsub : unorderedEdgeSupport E ⊆ T := by
2301 intro u hu
2302 unfold unorderedEdgeSupport at hu
2303 rw [Finset.mem_image] at hu
2304 rcases hu with ⟨e, heE, heu⟩
2305 have heData := hEdges e heE
2306 rw [hAeq] at heData
2307 cases e with
2308 | mk p q =>
2309 simp at heData heu
2310 have hp : p = x ∨ p = y ∨ p = z := by
2311 simpa using heData.1
2312 have hq : q = x ∨ q = y ∨ q = z := by
2313 simpa using heData.2.1
2314 have hpq : p ≠ q := heData.2.2
2315 rw [← heu]
2316 rcases hp with hp | hp | hp <;> rcases hq with hq | hq | hq
2317 · subst p; subst q; exact False.elim (hpq rfl)
2318 · subst p; subst q; simp [T, unorderedEdgeOfOrdered]
2319 · subst p; subst q; simp [T, unorderedEdgeOfOrdered]
2320 · subst p; subst q
2321 have hsym : Sym2.mk (y, x) = Sym2.mk (x, y) :=
2322 (Sym2.eq_iff).mpr (Or.inr ⟨rfl, rfl⟩)
2323 simp [T, unorderedEdgeOfOrdered, hsym]
2324 · subst p; subst q; exact False.elim (hpq rfl)
2325 · subst p; subst q; simp [T, unorderedEdgeOfOrdered]
2326 · subst p; subst q
2327 have hsym : Sym2.mk (z, x) = Sym2.mk (x, z) :=
2328 (Sym2.eq_iff).mpr (Or.inr ⟨rfl, rfl⟩)
2329 simp [T, unorderedEdgeOfOrdered, hsym]
2330 · subst p; subst q
2331 have hsym : Sym2.mk (z, y) = Sym2.mk (y, z) :=
2332 (Sym2.eq_iff).mpr (Or.inr ⟨rfl, rfl⟩)
2333 simp [T, unorderedEdgeOfOrdered, hsym]
2334 · subst p; subst q; exact False.elim (hpq rfl)
2335 calc
2336 (unorderedEdgeSupport E).card ≤ T.card := Finset.card_le_card hsub
2337 _ ≤ A.card := by
2338 have hT : T.card ≤ 3 := Finset.card_le_three
2339 omega
2340
2341
2342/-- If every unordered support edge is represented as `{v, x}` with `x ∈ A`,
2343then the support admits an injective endpoint charge into `A`. This is the
2344finite extraction step behind the star-case thrackle proof. -/
2345theorem endpoint_charge_of_support_subset_image
2346 {A : Finset Point2} {E : Finset (Point2 × Point2)} {v : Point2}
2347 (hsub :
2348 unorderedEdgeSupport E ⊆ A.image (fun x : Point2 => Sym2.mk (v, x))) :
2349 ∃ charge :
2350 {u : Sym2 Point2 // u ∈ unorderedEdgeSupport E} → {x : Point2 // x ∈ A},
2351 Function.Injective charge := by
2352 classical
2353 let f : Point2 → Sym2 Point2 := fun x => Sym2.mk (v, x)
2354 have hrep :
2355 ∀ u : {u : Sym2 Point2 // u ∈ unorderedEdgeSupport E},
2356 ∃ x : Point2, x ∈ A ∧ f x = u.1 := by
2357 intro u
2358 have hu : u.1 ∈ A.image f := hsub u.2
2359 rw [Finset.mem_image] at hu
2360 rcases hu with ⟨x, hxA, hxu⟩
2361 exact ⟨x, hxA, hxu⟩
2362 let charge :
2363 {u : Sym2 Point2 // u ∈ unorderedEdgeSupport E} → {x : Point2 // x ∈ A} :=
2364 fun u => ⟨Classical.choose (hrep u), (Classical.choose_spec (hrep u)).1⟩
2365 refine ⟨charge, ?_⟩
2366 intro u w huw
2367 apply Subtype.ext
2368 have hu_eq : f (charge u).1 = u.1 := (Classical.choose_spec (hrep u)).2
2369 have hw_eq : f (charge w).1 = w.1 := (Classical.choose_spec (hrep w)).2
2370 have hval : (charge u).1 = (charge w).1 := by
2371 exact congrArg Subtype.val huw
2372 calc
2373 u.1 = f (charge u).1 := hu_eq.symm
2374 _ = f (charge w).1 := by rw [hval]
2375 _ = w.1 := hw_eq
2376
2377/-- Star-case support bound for the thrackle certificate. If every edge is
2378incident to one vertex `v`, the unordered support injects into the ambient
2379point set by taking the other endpoint. -/
2380theorem unordered_support_card_le_of_incident_vertex
2381 {A : Finset Point2} {E : Finset (Point2 × Point2)} {v : Point2}
2382 (hEdges : ∀ e ∈ E, e.1 ∈ A ∧ e.2 ∈ A ∧ e.1 ≠ e.2)
2383 (hIncident : OrderedEdgesIncidentTo v E) :
2384 (unorderedEdgeSupport E).card ≤ A.card := by
2385 classical
2386 let f : Point2 → Sym2 Point2 := fun x => Sym2.mk (v, x)
2387 have hsub : unorderedEdgeSupport E ⊆ A.image f := by
2388 intro u hu
2389 unfold unorderedEdgeSupport at hu
2390 rw [Finset.mem_image] at hu
2391 rcases hu with ⟨e, heE, heu⟩
2392 have heData := hEdges e heE
2393 rcases hIncident e heE with hleft | hright
2394 · refine Finset.mem_image.mpr ⟨e.2, heData.2.1, ?_⟩
2395 rw [← heu]
2396 unfold f unorderedEdgeOfOrdered
2397 cases e with
2398 | mk p q =>
2399 simp at hleft ⊢
2400 subst p
2401 exact Or.inl rfl
2402 · refine Finset.mem_image.mpr ⟨e.1, heData.1, ?_⟩
2403 rw [← heu]
2404 unfold f unorderedEdgeOfOrdered
2405 cases e with
2406 | mk p q =>
2407 simp at hright ⊢
2408 subst q
2409 exact Or.inr rfl
2410 calc
2411 (unorderedEdgeSupport E).card ≤ (A.image f).card := Finset.card_le_card hsub
2412 _ ≤ A.card := Finset.card_image_le
2413
2414/-- Large non-star residual form of Conway's straight-line thrackle theorem.
2415The star systems and the `|A| ≤ 3` ambient cases are already finite
2416bookkeeping; this is the first genuinely large Conway counting target. -/
2417def LargeNonStarConwayThrackleSupportBound : Prop :=
2418 ∀ A : Finset Point2,
2419 ∀ E : Finset (Point2 × Point2),
2420 (∀ e ∈ E, e.1 ∈ A ∧ e.2 ∈ A ∧ e.1 ≠ e.2) →
2421 IsConwayThrackle E →
2422 4 ≤ A.card →
2423 (∀ v : Point2, ¬ OrderedEdgesIncidentTo v E) →
2424 (unorderedEdgeSupport E).card ≤ A.card
2425
2426/-- Star systems plus all ambient sets of size at most three are closed, so the
2427large non-star Conway residual implies the standard Conway support theorem. -/
2428theorem conway_support_bound_from_large_nonstar
2429 (hLarge : LargeNonStarConwayThrackleSupportBound) :
2430 ConwayThrackleSupportBound := by
2431 intro A E hEdges hConway
2432 by_cases hA2 : A.card ≤ 2
2433 · rcases exists_incident_vertex_of_card_le_two hA2 hEdges with ⟨v, hIncident⟩
2434 exact unordered_support_card_le_of_incident_vertex hEdges hIncident
2435 · by_cases hA3 : A.card = 3
2436 · exact unordered_support_card_le_of_card_eq_three hA3 hEdges
2437 · have hA4 : 4 ≤ A.card := by omega
2438 by_cases hStar : ∃ v : Point2, OrderedEdgesIncidentTo v E
2439 · rcases hStar with ⟨v, hIncident⟩
2440 exact unordered_support_card_le_of_incident_vertex hEdges hIncident
2441 · exact hLarge A E hEdges hConway hA4 (by
2442 intro v hIncident
2443 exact hStar ⟨v, hIncident⟩)
2444
2445/-- Star-case endpoint charge for the thrackle certificate. This strengthens
2446the star support bound by constructing the actual injective charge demanded by
2447`ThrackleEndpointChargingCertificate`. -/
2448theorem endpoint_charging_of_incident_vertex
2449 {A : Finset Point2} {E : Finset (Point2 × Point2)} {v : Point2}
2450 (hEdges : ∀ e ∈ E, e.1 ∈ A ∧ e.2 ∈ A ∧ e.1 ≠ e.2)
2451 (hIncident : OrderedEdgesIncidentTo v E) :
2452 ∃ charge :
2453 {u : Sym2 Point2 // u ∈ unorderedEdgeSupport E} → {x : Point2 // x ∈ A},
2454 Function.Injective charge := by
2455 classical
2456 let f : Point2 → Sym2 Point2 := fun x => Sym2.mk (v, x)
2457 have hsub : unorderedEdgeSupport E ⊆ A.image f := by
2458 intro u hu
2459 unfold unorderedEdgeSupport at hu
2460 rw [Finset.mem_image] at hu
2461 rcases hu with ⟨e, heE, heu⟩
2462 have heData := hEdges e heE
2463 rcases hIncident e heE with hleft | hright
2464 · refine Finset.mem_image.mpr ⟨e.2, heData.2.1, ?_⟩
2465 rw [← heu]
2466 unfold f unorderedEdgeOfOrdered
2467 cases e with
2468 | mk p q =>
2469 simp at hleft ⊢
2470 subst p
2471 exact Or.inl rfl
2472 · refine Finset.mem_image.mpr ⟨e.1, heData.1, ?_⟩
2473 rw [← heu]
2474 unfold f unorderedEdgeOfOrdered
2475 cases e with
2476 | mk p q =>
2477 simp at hright ⊢
2478 subst q
2479 exact Or.inr rfl
2480 exact endpoint_charge_of_support_subset_image hsub
2481
2482/-- Non-star residual form of the straight-line thrackle endpoint-charge
2483problem. Star systems are already charged by
2484`endpoint_charging_of_incident_vertex`; this certificate asks only for the
2485remaining pairwise-intersecting systems with no common incident vertex. -/
2486def NonStarThrackleEndpointChargingCertificate : Prop :=
2487 ∀ A : Finset Point2,
2488 ∀ E : Finset (Point2 × Point2),
2489 (∀ e ∈ E, e.1 ∈ A ∧ e.2 ∈ A ∧ e.1 ≠ e.2) →
2490 (∀ e ∈ E, ∀ f ∈ E, ¬ OrderedEdgesGeometricallyDisjoint e f) →
2491 (∀ v : Point2, ¬ OrderedEdgesIncidentTo v E) →
2492 ∃ charge :
2493 {u : Sym2 Point2 // u ∈ unorderedEdgeSupport E} → {x : Point2 // x ∈ A},
2494 Function.Injective charge
2495
2496/-- Large non-star residual form of the straight-line thrackle endpoint-charge
2497problem. The `|A| ≤ 2` cases are already stars, so the remaining non-star
2498certificate only has to start at three ambient points. -/
2499def LargeNonStarThrackleEndpointChargingCertificate : Prop :=
2500 ∀ A : Finset Point2,
2501 ∀ E : Finset (Point2 × Point2),
2502 (∀ e ∈ E, e.1 ∈ A ∧ e.2 ∈ A ∧ e.1 ≠ e.2) →
2503 (∀ e ∈ E, ∀ f ∈ E, ¬ OrderedEdgesGeometricallyDisjoint e f) →
2504 3 ≤ A.card →
2505 (∀ v : Point2, ¬ OrderedEdgesIncidentTo v E) →
2506 ∃ charge :
2507 {u : Sym2 Point2 // u ∈ unorderedEdgeSupport E} → {x : Point2 // x ∈ A},
2508 Function.Injective charge
2509
2510/-- Cardinal form of the large non-star thrackle residual. This is the weakest
2511finite statement needed on the thrackle side after star systems and `|A| ≤ 2`
2512systems have been closed. -/
2513def LargeNonStarThrackleSupportBoundCertificate : Prop :=
2514 ∀ A : Finset Point2,
2515 ∀ E : Finset (Point2 × Point2),
2516 (∀ e ∈ E, e.1 ∈ A ∧ e.2 ∈ A ∧ e.1 ≠ e.2) →
2517 (∀ e ∈ E, ∀ f ∈ E, ¬ OrderedEdgesGeometricallyDisjoint e f) →
2518 3 ≤ A.card →
2519 (∀ v : Point2, ¬ OrderedEdgesIncidentTo v E) →
2520 (unorderedEdgeSupport E).card ≤ A.card
2521
2522/-- Four-point-or-larger form of the non-star support residual. The exact
2523three-point boundary is already closed by
2524`unordered_support_card_le_of_card_eq_three`. -/
2525def FourPointNonStarThrackleSupportBoundCertificate : Prop :=
2526 ∀ A : Finset Point2,
2527 ∀ E : Finset (Point2 × Point2),
2528 (∀ e ∈ E, e.1 ∈ A ∧ e.2 ∈ A ∧ e.1 ≠ e.2) →
2529 (∀ e ∈ E, ∀ f ∈ E, ¬ OrderedEdgesGeometricallyDisjoint e f) →
2530 4 ≤ A.card →
2531 (∀ v : Point2, ¬ OrderedEdgesIncidentTo v E) →
2532 (unorderedEdgeSupport E).card ≤ A.card
2533
2534/-- Exact four-vertex non-star boundary certificate for straight-line thrackles.
2535This is the first genuinely geometric finite case after stars and triangles. -/
2536def ExactFourPointNonStarThrackleSupportBoundCertificate : Prop :=
2537 ∀ A : Finset Point2,
2538 ∀ E : Finset (Point2 × Point2),
2539 (∀ e ∈ E, e.1 ∈ A ∧ e.2 ∈ A ∧ e.1 ≠ e.2) →
2540 (∀ e ∈ E, ∀ f ∈ E, ¬ OrderedEdgesGeometricallyDisjoint e f) →
2541 A.card = 4 →
2542 (∀ v : Point2, ¬ OrderedEdgesIncidentTo v E) →
2543 (unorderedEdgeSupport E).card ≤ A.card
2544
2545/-- Geometric obstruction form of the exact four-vertex thrackle boundary. If a
2546non-star straight-line system on four ambient points has more than four
2547unordered support edges, then two represented ordered edges are geometrically
2548disjoint. This is the finite K4 obstruction left after pure counting closes
2549the triangle boundary. -/
2550def ExactFourPointK4ObstructionCertificate : Prop :=
2551 ∀ A : Finset Point2,
2552 ∀ E : Finset (Point2 × Point2),
2553 (∀ e ∈ E, e.1 ∈ A ∧ e.2 ∈ A ∧ e.1 ≠ e.2) →
2554 A.card = 4 →
2555 (∀ v : Point2, ¬ OrderedEdgesIncidentTo v E) →
2556 A.card < (unorderedEdgeSupport E).card →
2557 ∃ e ∈ E, ∃ f ∈ E, OrderedEdgesGeometricallyDisjoint e f
2558
2559/-- Support-level version of the exact four-vertex K4 obstruction. It asks for
2560two unordered support edges with geometrically disjoint representatives. This
2561is the natural next geometric target because the finite graph bookkeeping can
2562first find the two unordered candidates, and the segment geometry then supplies
2563the representatives. -/
2564def ExactFourPointSupportK4ObstructionCertificate : Prop :=
2565 ∀ A : Finset Point2,
2566 ∀ E : Finset (Point2 × Point2),
2567 (∀ e ∈ E, e.1 ∈ A ∧ e.2 ∈ A ∧ e.1 ≠ e.2) →
2568 A.card = 4 →
2569 (∀ v : Point2, ¬ OrderedEdgesIncidentTo v E) →
2570 A.card < (unorderedEdgeSupport E).card →
2571 ∃ u ∈ unorderedEdgeSupport E,
2572 ∃ v ∈ unorderedEdgeSupport E,
2573 SupportEdgesHaveDisjointRepresentatives E u v
2574
2575/-- The support-level K4 obstruction implies the ordered-representative K4
2576obstruction used by the final assembly. -/
2577theorem exact_fourpoint_k4_obstruction_from_support_obstruction
2578 (hSupportK4 : ExactFourPointSupportK4ObstructionCertificate) :
2579 ExactFourPointK4ObstructionCertificate := by
2580 intro A E hEdges hAcard hNonStar hgt
2581 rcases hSupportK4 A E hEdges hAcard hNonStar hgt with
2582 ⟨u, _hu, v, _hv, hDisjSupport⟩
2583 exact ordered_disjoint_pair_of_support_disjoint_pair hDisjSupport
2584
2585/-- The exact K4 obstruction proves the exact four-point support bound under
2586the pairwise-intersection hypothesis. -/
2587theorem exact_fourpoint_support_bound_from_k4_obstruction
2588 (hK4 : ExactFourPointK4ObstructionCertificate) :
2589 ExactFourPointNonStarThrackleSupportBoundCertificate := by
2590 intro A E hEdges hNoDisj hAcard hNonStar
2591 by_contra hnot
2592 have hgt : A.card < (unorderedEdgeSupport E).card := Nat.lt_of_not_ge hnot
2593 rcases hK4 A E hEdges hAcard hNonStar hgt with ⟨e, he, f, hf, hDisj⟩
2594 exact hNoDisj e he f hf hDisj
2595
2596/-! ### Plücker-based 4-point orientation dichotomy
2597
2598The Plücker identity (`orient2_alternating_sum_eq_zero`) plus a sum-of-squares
2599argument forces a sign pattern among the four triangle orientations of any four
2600points. This is the algebraic heart of the K4 obstruction: it routes every
2601non-degenerate 4-point configuration into at least one matching whose two
2602segments lie on the same strict side of a common line, which by
2603`same_side_segments_disjoint` makes them geometrically disjoint.
2604
2605The lemma is stated purely on four reals so it can be reused independently of
2606the geometric instantiation; the four reals will later be set to the four
2607`orient2`-values among `{a,b,c,d}`. -/
2608
2609/-- Sum-of-squares dichotomy. Given four reals satisfying the Plücker linear
2610relation `o₁ - o₂ + o₃ - o₄ = 0`, if all six bilinear sign witnesses
2611`o₃·o₄, o₁·o₂, -o₂·o₄, -o₁·o₃, o₂·o₃, o₁·o₄` are nonpositive, then all four
2612reals vanish.
2613
2614Proof: from `o₁ + o₃ = o₂ + o₄` we get
2615`(o₁+o₃)² = (o₁+o₃)(o₂+o₄) = o₁o₂ + o₁o₄ + o₂o₃ + o₃o₄ ≤ 0`,
2616so `o₁ + o₃ = 0`, hence `o₃ = -o₁` and `o₁o₃ = -o₁² ≤ 0`; combined with the
2617hypothesis `o₁o₃ ≥ 0` we get `o₁ = 0`, then `o₃ = 0`, and the symmetric step
2618gives `o₂ = o₄ = 0`. -/
2619theorem four_reals_orientation_dichotomy_alg
2620 {o₁ o₂ o₃ o₄ : ℝ}
2621 (hPluck : o₁ - o₂ + o₃ - o₄ = 0)
2622 (h₃₄ : o₃ * o₄ ≤ 0) (h₁₂ : o₁ * o₂ ≤ 0)
2623 (h₂₄ : 0 ≤ o₂ * o₄) (h₁₃ : 0 ≤ o₁ * o₃)
2624 (h₂₃ : o₂ * o₃ ≤ 0) (h₁₄ : o₁ * o₄ ≤ 0) :
2625 o₁ = 0 ∧ o₂ = 0 ∧ o₃ = 0 ∧ o₄ = 0 := by
2626 have hP : o₁ + o₃ = o₂ + o₄ := by linarith
2627 have hExpand : (o₁ + o₃) * (o₂ + o₄) ≤ 0 := by nlinarith
2628 have hSqLe : (o₁ + o₃) ^ 2 ≤ 0 := by
2629 have hRewrite : (o₁ + o₃) ^ 2 = (o₁ + o₃) * (o₂ + o₄) := by
2630 have : (o₁ + o₃) ^ 2 = (o₁ + o₃) * (o₁ + o₃) := by ring
2631 rw [this, hP]
2632 rw [hRewrite]; exact hExpand
2633 have hSqEq : (o₁ + o₃) ^ 2 = 0 :=
2634 le_antisymm hSqLe (sq_nonneg _)
2635 have hSum₁₃ : o₁ + o₃ = 0 := by
2636 have := sq_eq_zero_iff.mp hSqEq
2637 exact this
2638 have hSum₂₄ : o₂ + o₄ = 0 := by linarith
2639 have hO₃_eq : o₃ = -o₁ := by linarith
2640 have h_o1sq_le : o₁ ^ 2 ≤ 0 := by
2641 have hProd : o₁ * o₃ = -(o₁ ^ 2) := by
2642 rw [hO₃_eq]; ring
2643 linarith [h₁₃]
2644 have h_o1sq_eq : o₁ ^ 2 = 0 := le_antisymm h_o1sq_le (sq_nonneg _)
2645 have hO₁ : o₁ = 0 := sq_eq_zero_iff.mp h_o1sq_eq
2646 have hO₃ : o₃ = 0 := by linarith
2647 have hO₄_eq : o₄ = -o₂ := by linarith
2648 have h_o2sq_le : o₂ ^ 2 ≤ 0 := by
2649 have hProd : o₂ * o₄ = -(o₂ ^ 2) := by
2650 rw [hO₄_eq]; ring
2651 linarith [h₂₄]
2652 have h_o2sq_eq : o₂ ^ 2 = 0 := le_antisymm h_o2sq_le (sq_nonneg _)
2653 have hO₂ : o₂ = 0 := sq_eq_zero_iff.mp h_o2sq_eq
2654 have hO₄ : o₄ = 0 := by linarith
2655 exact ⟨hO₁, hO₂, hO₃, hO₄⟩
2656
2657/-- Geometric Plücker dichotomy for four points. If at least one of the four
2658triangle orientations among `{a,b,c,d}` is nonzero, then at least one of the
2659six same-side disjointness witnesses for the three perfect matchings of `K₄`
2660holds. Each witness, via `same_side_segments_disjoint`, certifies one
2661matching as geometrically disjoint.
2662
2663The six disjuncts are exactly the `0 < orient2 X Y P * orient2 X Y Q` hypotheses
2664of `same_side_segments_disjoint` for the lines and remaining points of the
2665three matchings `M₁ = {ab,cd}`, `M₂ = {ac,bd}`, `M₃ = {ad,bc}`. -/
2666theorem four_points_orientation_dichotomy
2667 (a b c d : Point2)
2668 (hNotAllCollinear :
2669 orient2 a b c ≠ 0 ∨ orient2 a b d ≠ 0 ∨
2670 orient2 a c d ≠ 0 ∨ orient2 b c d ≠ 0) :
2671 0 < orient2 a b c * orient2 a b d ∨
2672 0 < orient2 c d a * orient2 c d b ∨
2673 0 < orient2 a c b * orient2 a c d ∨
2674 0 < orient2 b d a * orient2 b d c ∨
2675 0 < orient2 a d b * orient2 a d c ∨
2676 0 < orient2 b c a * orient2 b c d := by
2677 -- Substitute the four `orient2` values as o₁, o₂, o₃, o₄.
2678 set o₁ := orient2 b c d with ho₁_def
2679 set o₂ := orient2 a c d with ho₂_def
2680 set o₃ := orient2 a b d with ho₃_def
2681 set o₄ := orient2 a b c with ho₄_def
2682 -- Plücker linear relation.
2683 have hPluck : o₁ - o₂ + o₃ - o₄ = 0 := by
2684 have h := orient2_alternating_sum_eq_zero a b c d
2685 linarith
2686 -- `orient2` swap/cyclic identities used below.
2687 have hcd_a : orient2 c d a = o₂ := by
2688 show orient2 c d a = orient2 a c d
2689 rw [orient2_cyclic, orient2_cyclic]
2690 have hcd_b : orient2 c d b = o₁ := by
2691 show orient2 c d b = orient2 b c d
2692 rw [orient2_cyclic, orient2_cyclic]
2693 have hacb : orient2 a c b = -o₄ := orient2_swap₂₃ a b c
2694 have hbda : orient2 b d a = o₃ := by
2695 show orient2 b d a = orient2 a b d
2696 rw [orient2_cyclic, orient2_cyclic]
2697 have hbdc : orient2 b d c = -o₁ := by
2698 have := orient2_swap₂₃ b c d
2699 -- orient2_swap₂₃ : orient2 b d c = - orient2 b c d
2700 linarith
2701 have hadb : orient2 a d b = -o₃ := orient2_swap₂₃ a b d
2702 have hadc : orient2 a d c = -o₂ := orient2_swap₂₃ a c d
2703 have hbca : orient2 b c a = o₄ := by
2704 show orient2 b c a = orient2 a b c
2705 rw [orient2_cyclic, orient2_cyclic]
2706 by_contra hAll
2707 push_neg at hAll
2708 obtain ⟨h1, h2, h3, h4, h5, h6⟩ := hAll
2709 -- Translate each negated witness into a sign condition on o₁, o₂, o₃, o₄.
2710 have h₃₄ : o₃ * o₄ ≤ 0 := by
2711 have h : o₄ * o₃ ≤ 0 := h1
2712 linarith [h, (by ring : o₃ * o₄ = o₄ * o₃)]
2713 have h₁₂ : o₁ * o₂ ≤ 0 := by
2714 rw [hcd_a, hcd_b] at h2
2715 linarith [h2, (by ring : o₁ * o₂ = o₂ * o₁)]
2716 -- h3 : (-o₄) * o₂ ≤ 0 ⇒ o₂ * o₄ ≥ 0.
2717 have h₂₄ : 0 ≤ o₂ * o₄ := by
2718 rw [hacb] at h3
2719 nlinarith [h3]
2720 -- h4 : o₃ * (-o₁) ≤ 0 ⇒ o₁ * o₃ ≥ 0.
2721 have h₁₃ : 0 ≤ o₁ * o₃ := by
2722 rw [hbda, hbdc] at h4
2723 nlinarith [h4]
2724 -- h5 : (-o₃)(-o₂) ≤ 0 ⇒ o₂ * o₃ ≤ 0.
2725 have h₂₃ : o₂ * o₃ ≤ 0 := by
2726 rw [hadb, hadc] at h5
2727 nlinarith [h5]
2728 -- h6 : o₄ * o₁ ≤ 0 ⇒ o₁ * o₄ ≤ 0.
2729 have h₁₄ : o₁ * o₄ ≤ 0 := by
2730 rw [hbca] at h6
2731 linarith [h6, (by ring : o₁ * o₄ = o₄ * o₁)]
2732 -- Apply the algebraic dichotomy.
2733 obtain ⟨hO₁, hO₂, hO₃, hO₄⟩ :=
2734 four_reals_orientation_dichotomy_alg hPluck h₃₄ h₁₂ h₂₄ h₁₃ h₂₃ h₁₄
2735 -- All four orientations vanish, contradicting `hNotAllCollinear`.
2736 rcases hNotAllCollinear with h | h | h | h
2737 · exact h hO₄
2738 · exact h hO₃
2739 · exact h hO₂
2740 · exact h hO₁
2741
2742/-- Symmetry of `OrderedEdgesGeometricallyDisjoint`. Two ordered edges are
2743geometrically disjoint regardless of which one is the first argument. -/
2744theorem ordered_edges_geometrically_disjoint_symm
2745 {e f : Point2 × Point2}
2746 (h : OrderedEdgesGeometricallyDisjoint e f) :
2747 OrderedEdgesGeometricallyDisjoint f e := by
2748 intro hmeet
2749 exact h (ordered_edges_meet_symm hmeet)
2750
2751/-- Geometric four-point matching dichotomy (noncollinear case). For any four
2752points `a, b, c, d` that are not all collinear (some `orient2` among triples
2753is nonzero), at least one of the three perfect matchings of `K₄` consists of
2754two geometrically disjoint segments. This is the heart of the Conway-K4
2755obstruction: it routes every non-degenerate 4-point configuration into a
2756disjoint matching using only `same_side_segments_disjoint` and the Plücker
2757orientation identity. -/
2758theorem four_distinct_points_one_matching_disjoint_noncollinear
2759 (a b c d : Point2)
2760 (hNotAllCollinear :
2761 orient2 a b c ≠ 0 ∨ orient2 a b d ≠ 0 ∨
2762 orient2 a c d ≠ 0 ∨ orient2 b c d ≠ 0) :
2763 OrderedEdgesGeometricallyDisjoint (a, b) (c, d) ∨
2764 OrderedEdgesGeometricallyDisjoint (a, c) (b, d) ∨
2765 OrderedEdgesGeometricallyDisjoint (a, d) (b, c) := by
2766 rcases four_points_orientation_dichotomy a b c d hNotAllCollinear with
2767 h | h | h | h | h | h
2768 · exact Or.inl (same_side_segments_disjoint h)
2769 · refine Or.inl ?_
2770 exact ordered_edges_geometrically_disjoint_symm (same_side_segments_disjoint h)
2771 · exact Or.inr (Or.inl (same_side_segments_disjoint h))
2772 · refine Or.inr (Or.inl ?_)
2773 exact ordered_edges_geometrically_disjoint_symm (same_side_segments_disjoint h)
2774 · exact Or.inr (Or.inr (same_side_segments_disjoint h))
2775 · refine Or.inr (Or.inr ?_)
2776 exact ordered_edges_geometrically_disjoint_symm (same_side_segments_disjoint h)
2777
2778/-! ### Conway-conditioned 4-point K4 obstruction
2779
2780The existing `ExactFourPointK4ObstructionCertificate` (above) asks for a
2781geometrically disjoint pair under the weak hypothesis "every pair of ordered
2782edges meets" (i.e., `¬ OrderedEdgesGeometricallyDisjoint`). That hypothesis
2783is too weak: with four collinear points, a five-edge non-star configuration
2784exists where every pair meets (some pairs overlap on a common sub-segment)
2785yet no disjoint pair can be extracted. The corresponding "intersecting
2786support bound" certificate `ExactFourPointNonStarThrackleSupportBoundCertificate`
2787is therefore false in general.
2788
2789Conway's actual theorem uses the *simple-meeting* condition
2790`OrderedEdgesMeetSimply` (exactly one common point), which excludes the
2791overlapping collinear pathology. Below we state and (mostly) discharge the
2792correct Conway-conditioned K4 obstruction: under simple-meeting, four ambient
2793points cannot host more than four unordered support edges. The noncollinear
2794case is closed by `four_distinct_points_one_matching_disjoint_noncollinear`;
2795the all-collinear case is the only remaining hand geometry (sorting on a
2796line). -/
2797
2798/-- Conway-conditioned exact four-point support bound. This is the correct
2799shape of the K4 boundary: a Conway thrackle on four points with no incident
2800vertex has at most four unordered support edges. -/
2801def ExactFourPointConwayThrackleSupportBoundCertificate : Prop :=
2802 ∀ A : Finset Point2,
2803 ∀ E : Finset (Point2 × Point2),
2804 (∀ e ∈ E, e.1 ∈ A ∧ e.2 ∈ A ∧ e.1 ≠ e.2) →
2805 IsConwayThrackle E →
2806 A.card = 4 →
2807 (∀ v : Point2, ¬ OrderedEdgesIncidentTo v E) →
2808 (unorderedEdgeSupport E).card ≤ A.card
2809
2810/-- All-collinear residual for the Conway K4 obstruction. If four distinct
2811collinear points host a Conway thrackle with no incident vertex, the unordered
2812support is bounded by 4. This is the only remaining hand geometry: in the
2813collinear case the algebraic dichotomy degenerates and we must sort by line
2814parameter. Stated separately so the noncollinear case can close immediately. -/
2815def CollinearFourPointConwayResidual : Prop :=
2816 ∀ A : Finset Point2,
2817 ∀ E : Finset (Point2 × Point2),
2818 (∀ e ∈ E, e.1 ∈ A ∧ e.2 ∈ A ∧ e.1 ≠ e.2) →
2819 IsConwayThrackle E →
2820 A.card = 4 →
2821 (∀ v : Point2, ¬ OrderedEdgesIncidentTo v E) →
2822 (∀ p ∈ A, ∀ q ∈ A, ∀ r ∈ A, orient2 p q r = 0) →
2823 (unorderedEdgeSupport E).card ≤ A.card
2824
2825/-! ### Pairwise strong dichotomy (algebraic + geometric)
2826
2827Three lemmas, one per pair `(M_i, M_j)` of matchings. If both matchings have
2828all their same-side disjointness witnesses fail (i.e., neither is "disjoint via
2829same-side"), then the SOS-Plücker argument forces a pair of zero `orient2`
2830values whose triples share two points; combined with the distinctness of the
2831four ambient points this forces all four points to be collinear. -/
2832
2833/-- Sum-of-squares pair lemma. For four reals satisfying Plücker and the four
2834sign-product conditions `o₃·o₄ ≤ 0`, `o₁·o₂ ≤ 0`, `o₂·o₃ ≤ 0`, `o₁·o₄ ≤ 0`
2835(the joint failure of the `M₁`/`M₃` same-side witnesses), the SOS expansion of
2836`(o₁+o₃)(o₂+o₄)` is nonpositive while equalling `(o₁+o₃)² ≥ 0`, so
2837`o₁ + o₃ = 0 = o₂ + o₄`, and one of `o₁·o₂ = 0` follows from the resulting
2838algebra. -/
2839theorem four_reals_M1_M3_pair_sos
2840 {o₁ o₂ o₃ o₄ : ℝ}
2841 (hPluck : o₁ - o₂ + o₃ - o₄ = 0)
2842 (h₃₄ : o₃ * o₄ ≤ 0) (h₁₂ : o₁ * o₂ ≤ 0)
2843 (h₂₃ : o₂ * o₃ ≤ 0) (h₁₄ : o₁ * o₄ ≤ 0) :
2844 (o₁ = 0 ∧ o₃ = 0) ∨ (o₂ = 0 ∧ o₄ = 0) := by
2845 have hP : o₁ + o₃ = o₂ + o₄ := by linarith
2846 have hExpand : (o₁ + o₃) * (o₂ + o₄) ≤ 0 := by nlinarith
2847 have hSqLe : (o₁ + o₃) ^ 2 ≤ 0 := by
2848 have hRewrite : (o₁ + o₃) ^ 2 = (o₁ + o₃) * (o₂ + o₄) := by
2849 have : (o₁ + o₃) ^ 2 = (o₁ + o₃) * (o₁ + o₃) := by ring
2850 rw [this, hP]
2851 rw [hRewrite]; exact hExpand
2852 have hSqEq : (o₁ + o₃) ^ 2 = 0 := le_antisymm hSqLe (sq_nonneg _)
2853 have hSum₁₃ : o₁ + o₃ = 0 := sq_eq_zero_iff.mp hSqEq
2854 have hSum₂₄ : o₂ + o₄ = 0 := by linarith
2855 have hO₃_eq : o₃ = -o₁ := by linarith
2856 have hO₄_eq : o₄ = -o₂ := by linarith
2857 -- o₂ * o₃ ≤ 0 with o₃ = -o₁ gives -o₁o₂ ≤ 0 i.e. o₁o₂ ≥ 0. Combined with h₁₂.
2858 have h_o₁o₂_zero : o₁ * o₂ = 0 := by
2859 have h1 : 0 ≤ o₁ * o₂ := by
2860 have hRw : o₂ * o₃ = -(o₁ * o₂) := by rw [hO₃_eq]; ring
2861 linarith [h₂₃, hRw]
2862 linarith [h₁₂]
2863 rcases mul_eq_zero.mp h_o₁o₂_zero with hO₁ | hO₂
2864 · left
2865 refine ⟨hO₁, ?_⟩
2866 rw [hO₃_eq, hO₁]; ring
2867 · right
2868 refine ⟨hO₂, ?_⟩
2869 rw [hO₄_eq, hO₂]; ring
2870
2871/-- Geometric two-zero collinearity. If `orient2 a b d = 0` and
2872`orient2 b c d = 0` with `b ≠ d`, then all four points `a, b, c, d` are
2873collinear: lines `bd` (from the first zero) and `bd` (from the second zero)
2874are the same line through `b, d`, and both `a` and `c` lie on it. The
2875conclusion is recorded as `orient2 a b c = 0` (since `a, b, c` collinear). -/
2876theorem orient2_zero_two_zeros_share_bd
2877 {a b c d : Point2} (hbd : b ≠ d)
2878 (h₃ : orient2 a b d = 0) (h₁ : orient2 b c d = 0) :
2879 orient2 a b c = 0 := by
2880 -- From `h₁ : orient2 b c d = 0` rewrite as `orient2 b d c = 0` via swap.
2881 have h_bd_c : orient2 b d c = 0 := by
2882 have hsw : orient2 b d c = -orient2 b c d := orient2_swap₂₃ b c d
2883 linarith
2884 -- Reorder `h₃` to use `b, d` as the "fixed line": `orient2 b d a = 0`.
2885 have h_bd_a : orient2 b d a = 0 := by
2886 have hc : orient2 a b d = orient2 b d a := orient2_cyclic a b d
2887 linarith
2888 -- Apply `orient2_zero_transitive` with `a := b`, `b := d`, `c := a`, `d := c`.
2889 have h_b_a_c : orient2 b a c = 0 :=
2890 orient2_zero_transitive hbd h_bd_a h_bd_c
2891 -- Convert to `orient2 a b c = 0` via swap.
2892 have hsw : orient2 b a c = -orient2 a b c := orient2_swap₁₂ a b c
2893 linarith
2894
2895/-- Pair `(M₁, M₂)`: both fail their same-side disjointness witnesses ⇒
2896either `o₁ = o₄ = 0` (collinearity of `{a,b,c}` and `{b,c,d}`, sharing `b, c`)
2897or `o₂ = o₃ = 0` (collinearity of `{a,c,d}` and `{a,b,d}`, sharing `a, d`).
2898Uses `(o₁ - o₄)(o₂ - o₃)` whose sign is forced to zero by Plücker
2899`o₁ - o₄ = o₂ - o₃` and the four sign hypotheses. -/
2900theorem four_reals_M1_M2_pair_sos
2901 {o₁ o₂ o₃ o₄ : ℝ}
2902 (hPluck : o₁ - o₂ + o₃ - o₄ = 0)
2903 (h₃₄ : o₃ * o₄ ≤ 0) (h₁₂ : o₁ * o₂ ≤ 0) -- M₁ fail
2904 (h₂₄ : 0 ≤ o₂ * o₄) (h₁₃ : 0 ≤ o₁ * o₃) : -- M₂ fail
2905 (o₁ = 0 ∧ o₄ = 0) ∨ (o₂ = 0 ∧ o₃ = 0) := by
2906 have hP : o₁ - o₄ = o₂ - o₃ := by linarith
2907 have hExpand : (o₁ - o₄) * (o₂ - o₃) ≤ 0 := by nlinarith
2908 have hSqLe : (o₁ - o₄) ^ 2 ≤ 0 := by
2909 have hRewrite : (o₁ - o₄) ^ 2 = (o₁ - o₄) * (o₂ - o₃) := by
2910 have : (o₁ - o₄) ^ 2 = (o₁ - o₄) * (o₁ - o₄) := by ring
2911 rw [this, hP]
2912 rw [hRewrite]; exact hExpand
2913 have hSqEq : (o₁ - o₄) ^ 2 = 0 := le_antisymm hSqLe (sq_nonneg _)
2914 have hDiff₁₄ : o₁ - o₄ = 0 := sq_eq_zero_iff.mp hSqEq
2915 have hO₄_eq : o₄ = o₁ := by linarith
2916 have hO₃_eq : o₃ = o₂ := by linarith
2917 -- o₂ * o₄ = o₁ * o₂, combine with h₁₂ : o₁ * o₂ ≤ 0 and h₂₄ : 0 ≤ o₂ * o₄.
2918 have h_o₁o₂_zero : o₁ * o₂ = 0 := by
2919 have hRw : o₂ * o₄ = o₁ * o₂ := by rw [hO₄_eq]; ring
2920 linarith [h₁₂, h₂₄, hRw]
2921 rcases mul_eq_zero.mp h_o₁o₂_zero with hO₁ | hO₂
2922 · left
2923 refine ⟨hO₁, ?_⟩
2924 linarith
2925 · right
2926 refine ⟨hO₂, ?_⟩
2927 linarith
2928
2929/-- Pair `(M₂, M₃)`: both fail their same-side disjointness witnesses ⇒
2930either `o₁ = o₂ = 0` (collinearity of `{b,c,d}` and `{a,c,d}`, sharing `c, d`)
2931or `o₃ = o₄ = 0` (collinearity of `{a,b,d}` and `{a,b,c}`, sharing `a, b`).
2932Uses `(o₁ - o₂)(o₃ - o₄) = -(o₁ - o₂)²` (after Plücker) plus the four sign
2933hypotheses. -/
2934theorem four_reals_M2_M3_pair_sos
2935 {o₁ o₂ o₃ o₄ : ℝ}
2936 (hPluck : o₁ - o₂ + o₃ - o₄ = 0)
2937 (h₂₄ : 0 ≤ o₂ * o₄) (h₁₃ : 0 ≤ o₁ * o₃) -- M₂ fail
2938 (h₂₃ : o₂ * o₃ ≤ 0) (h₁₄ : o₁ * o₄ ≤ 0) : -- M₃ fail
2939 (o₁ = 0 ∧ o₂ = 0) ∨ (o₃ = 0 ∧ o₄ = 0) := by
2940 have hP : o₁ - o₂ = -(o₃ - o₄) := by linarith
2941 have hExpand : 0 ≤ (o₁ - o₂) * (o₃ - o₄) := by nlinarith
2942 have hSqNeg : (o₁ - o₂) * (o₃ - o₄) = -(o₃ - o₄) ^ 2 := by
2943 have : (o₁ - o₂) * (o₃ - o₄) = -(o₃ - o₄) * (o₃ - o₄) := by
2944 rw [show o₁ - o₂ = -(o₃ - o₄) from hP]
2945 rw [this]; ring
2946 have hSqEq : (o₃ - o₄) ^ 2 = 0 := by
2947 have hSqLe : (o₃ - o₄) ^ 2 ≤ 0 := by
2948 have : -(o₃ - o₄) ^ 2 ≥ 0 := by linarith [hExpand, hSqNeg]
2949 linarith
2950 exact le_antisymm hSqLe (sq_nonneg _)
2951 have hDiff₃₄ : o₃ - o₄ = 0 := sq_eq_zero_iff.mp hSqEq
2952 have hO₄_eq : o₄ = o₃ := by linarith
2953 have hO₂_eq : o₂ = o₁ := by linarith
2954 -- o₂ * o₃ = o₁ * o₃, combine with h₂₃ ≤ 0 and h₁₃ ≥ 0.
2955 have h_o₁o₃_zero : o₁ * o₃ = 0 := by
2956 have hRw : o₂ * o₃ = o₁ * o₃ := by rw [hO₂_eq]
2957 linarith [h₂₃, h₁₃, hRw]
2958 rcases mul_eq_zero.mp h_o₁o₃_zero with hO₁ | hO₃
2959 · left
2960 refine ⟨hO₁, ?_⟩
2961 linarith
2962 · right
2963 refine ⟨hO₃, ?_⟩
2964 linarith
2965
2966/-! ### Geometric "all four collinear" closure from any shared pair of zeros
2967
2968For each of the six possible shared vertex pairs `{p, q} ⊂ {a, b, c, d}`, two
2969zero orientations whose underlying triples both contain `{p, q}` together
2970with `p ≠ q` force the remaining `orient2` values among `{a, b, c, d}` to
2971vanish, by `orient2_zero_transitive` plus the Plücker identity. -/
2972
2973/-- `o₁ = o₃ = 0` shared at `b, d` ⇒ all four orientations vanish. -/
2974theorem orient2_all_zero_of_o1_o3_zero
2975 {a b c d : Point2} (hbd : b ≠ d)
2976 (h₁ : orient2 b c d = 0) (h₃ : orient2 a b d = 0) :
2977 orient2 a b c = 0 ∧ orient2 a b d = 0 ∧
2978 orient2 a c d = 0 ∧ orient2 b c d = 0 := by
2979 have h₄ : orient2 a b c = 0 :=
2980 orient2_zero_two_zeros_share_bd hbd h₃ h₁
2981 have h₂ : orient2 a c d = 0 := by
2982 -- Plücker: o₁ - o₂ + o₃ - o₄ = 0 ⇒ o₂ = o₁ + o₃ - o₄ = 0.
2983 have hPl := orient2_alternating_sum_eq_zero a b c d
2984 linarith
2985 exact ⟨h₄, h₃, h₂, h₁⟩
2986
2987/-- `o₂ = o₄ = 0` shared at `a, c` ⇒ all four orientations vanish. -/
2988theorem orient2_all_zero_of_o2_o4_zero
2989 {a b c d : Point2} (hac : a ≠ c)
2990 (h₂ : orient2 a c d = 0) (h₄ : orient2 a b c = 0) :
2991 orient2 a b c = 0 ∧ orient2 a b d = 0 ∧
2992 orient2 a c d = 0 ∧ orient2 b c d = 0 := by
2993 -- Derive orient2 a b d = 0 using transitivity through line ac.
2994 have h_ac_b : orient2 a c b = 0 := by
2995 have := orient2_swap₂₃ a b c
2996 -- orient2 a c b = -orient2 a b c
2997 linarith
2998 have h_a_b_d : orient2 a b d = 0 := by
2999 -- Apply orient2_zero_transitive with line ac: get orient2 a b d.
3000 -- orient2_zero_transitive hac h_ac_b h₂ : orient2 a b d = 0.
3001 exact orient2_zero_transitive hac h_ac_b h₂
3002 have h_o1 : orient2 b c d = 0 := by
3003 have hPl := orient2_alternating_sum_eq_zero a b c d
3004 linarith
3005 exact ⟨h₄, h_a_b_d, h₂, h_o1⟩
3006
3007/-- `o₁ = o₄ = 0` shared at `b, c` ⇒ all four orientations vanish. -/
3008theorem orient2_all_zero_of_o1_o4_zero
3009 {a b c d : Point2} (hbc : b ≠ c)
3010 (h₁ : orient2 b c d = 0) (h₄ : orient2 a b c = 0) :
3011 orient2 a b c = 0 ∧ orient2 a b d = 0 ∧
3012 orient2 a c d = 0 ∧ orient2 b c d = 0 := by
3013 -- Apply orient2_zero_transitive with line bc.
3014 have h_bc_a : orient2 b c a = 0 := by
3015 have hcy : orient2 a b c = orient2 b c a := orient2_cyclic a b c
3016 linarith
3017 have h_b_a_d : orient2 b a d = 0 :=
3018 orient2_zero_transitive hbc h_bc_a h₁
3019 have h_a_b_d : orient2 a b d = 0 := by
3020 have := orient2_swap₁₂ a b d
3021 linarith
3022 have h_o2 : orient2 a c d = 0 := by
3023 have hPl := orient2_alternating_sum_eq_zero a b c d
3024 linarith
3025 exact ⟨h₄, h_a_b_d, h_o2, h₁⟩
3026
3027/-- `o₂ = o₃ = 0` shared at `a, d` ⇒ all four orientations vanish. -/
3028theorem orient2_all_zero_of_o2_o3_zero
3029 {a b c d : Point2} (had : a ≠ d)
3030 (h₂ : orient2 a c d = 0) (h₃ : orient2 a b d = 0) :
3031 orient2 a b c = 0 ∧ orient2 a b d = 0 ∧
3032 orient2 a c d = 0 ∧ orient2 b c d = 0 := by
3033 -- Apply orient2_zero_transitive with line ad.
3034 have h_ad_c : orient2 a d c = 0 := by
3035 have := orient2_swap₂₃ a c d
3036 linarith
3037 have h_ad_b : orient2 a d b = 0 := by
3038 have := orient2_swap₂₃ a b d
3039 linarith
3040 have h_a_c_b : orient2 a c b = 0 :=
3041 orient2_zero_transitive had h_ad_c h_ad_b
3042 have h_a_b_c : orient2 a b c = 0 := by
3043 have := orient2_swap₂₃ a b c
3044 linarith
3045 have h_o1 : orient2 b c d = 0 := by
3046 have hPl := orient2_alternating_sum_eq_zero a b c d
3047 linarith
3048 exact ⟨h_a_b_c, h₃, h₂, h_o1⟩
3049
3050/-- `o₁ = o₂ = 0` shared at `c, d` ⇒ all four orientations vanish. -/
3051theorem orient2_all_zero_of_o1_o2_zero
3052 {a b c d : Point2} (hcd : c ≠ d)
3053 (h₁ : orient2 b c d = 0) (h₂ : orient2 a c d = 0) :
3054 orient2 a b c = 0 ∧ orient2 a b d = 0 ∧
3055 orient2 a c d = 0 ∧ orient2 b c d = 0 := by
3056 -- Apply orient2_zero_transitive with line cd.
3057 have h_cd_a : orient2 c d a = 0 := by
3058 have hcy : orient2 a c d = orient2 c d a := by
3059 rw [orient2_cyclic, orient2_cyclic]
3060 linarith
3061 have h_cd_b : orient2 c d b = 0 := by
3062 have hcy : orient2 b c d = orient2 c d b := by
3063 rw [orient2_cyclic, orient2_cyclic]
3064 linarith
3065 have h_c_a_b : orient2 c a b = 0 :=
3066 orient2_zero_transitive hcd h_cd_a h_cd_b
3067 have h_a_b_c : orient2 a b c = 0 := by
3068 have hcy : orient2 c a b = orient2 a b c := by
3069 rw [orient2_cyclic, orient2_cyclic]
3070 linarith
3071 have h_o3 : orient2 a b d = 0 := by
3072 have hPl := orient2_alternating_sum_eq_zero a b c d
3073 linarith
3074 exact ⟨h_a_b_c, h_o3, h₂, h₁⟩
3075
3076/-- `o₃ = o₄ = 0` shared at `a, b` ⇒ all four orientations vanish. -/
3077theorem orient2_all_zero_of_o3_o4_zero
3078 {a b c d : Point2} (hab : a ≠ b)
3079 (h₃ : orient2 a b d = 0) (h₄ : orient2 a b c = 0) :
3080 orient2 a b c = 0 ∧ orient2 a b d = 0 ∧
3081 orient2 a c d = 0 ∧ orient2 b c d = 0 := by
3082 have h_o2 : orient2 a c d = 0 :=
3083 orient2_zero_transitive hab h₄ h₃
3084 have h_o1 : orient2 b c d = 0 := by
3085 have hPl := orient2_alternating_sum_eq_zero a b c d
3086 linarith
3087 exact ⟨h₄, h₃, h_o2, h_o1⟩
3088
3089/-! ### Pair-fail geometric closures (the three combined lemmas)
3090
3091Each "pair-fail" lemma combines an algebraic pair-SOS lemma with the
3092appropriate geometric `orient2_all_zero_of_*` closure to conclude that two
3093matchings failing all their same-side witnesses forces every triple of the
3094four ambient points to be collinear. -/
3095
3096/-- Pair `(M₁, M₃)`: if all four same-side witnesses fail (`M₁`'s two and
3097`M₃`'s two), all four `orient2` values among `{a, b, c, d}` vanish. -/
3098theorem orient2_M1_M3_pair_fail_all_collinear
3099 {a b c d : Point2}
3100 (hbd : b ≠ d) (hac : a ≠ c)
3101 (h_M1a : ¬ (0 < orient2 a b c * orient2 a b d))
3102 (h_M1b : ¬ (0 < orient2 c d a * orient2 c d b))
3103 (h_M3a : ¬ (0 < orient2 a d b * orient2 a d c))
3104 (h_M3b : ¬ (0 < orient2 b c a * orient2 b c d)) :
3105 orient2 a b c = 0 ∧ orient2 a b d = 0 ∧
3106 orient2 a c d = 0 ∧ orient2 b c d = 0 := by
3107 set o₁ := orient2 b c d with ho₁
3108 set o₂ := orient2 a c d with ho₂
3109 set o₃ := orient2 a b d with ho₃
3110 set o₄ := orient2 a b c with ho₄
3111 have hPluck : o₁ - o₂ + o₃ - o₄ = 0 := by
3112 have h := orient2_alternating_sum_eq_zero a b c d
3113 linarith
3114 have hcd_a : orient2 c d a = o₂ := by
3115 show orient2 c d a = orient2 a c d
3116 rw [orient2_cyclic, orient2_cyclic]
3117 have hcd_b : orient2 c d b = o₁ := by
3118 show orient2 c d b = orient2 b c d
3119 rw [orient2_cyclic, orient2_cyclic]
3120 have hadb : orient2 a d b = -o₃ := orient2_swap₂₃ a b d
3121 have hadc : orient2 a d c = -o₂ := orient2_swap₂₃ a c d
3122 have hbca : orient2 b c a = o₄ := by
3123 show orient2 b c a = orient2 a b c
3124 rw [orient2_cyclic, orient2_cyclic]
3125 have h₃₄ : o₃ * o₄ ≤ 0 := by
3126 have h : o₄ * o₃ ≤ 0 := not_lt.mp h_M1a
3127 linarith [(by ring : o₃ * o₄ = o₄ * o₃)]
3128 have h₁₂ : o₁ * o₂ ≤ 0 := by
3129 rw [hcd_a, hcd_b] at h_M1b
3130 have h := not_lt.mp h_M1b
3131 linarith [h, (by ring : o₁ * o₂ = o₂ * o₁)]
3132 have h₂₃ : o₂ * o₃ ≤ 0 := by
3133 rw [hadb, hadc] at h_M3a
3134 have h := not_lt.mp h_M3a
3135 nlinarith [h]
3136 have h₁₄ : o₁ * o₄ ≤ 0 := by
3137 rw [hbca] at h_M3b
3138 have h := not_lt.mp h_M3b
3139 linarith [h, (by ring : o₁ * o₄ = o₄ * o₁)]
3140 rcases four_reals_M1_M3_pair_sos hPluck h₃₄ h₁₂ h₂₃ h₁₄ with
3141 ⟨hO₁, hO₃⟩ | ⟨hO₂, hO₄⟩
3142 · exact orient2_all_zero_of_o1_o3_zero hbd hO₁ hO₃
3143 · exact orient2_all_zero_of_o2_o4_zero hac hO₂ hO₄
3144
3145/-- Pair `(M₁, M₂)`: if all four same-side witnesses fail, all `orient2`
3146values vanish. -/
3147theorem orient2_M1_M2_pair_fail_all_collinear
3148 {a b c d : Point2}
3149 (hbc : b ≠ c) (had : a ≠ d)
3150 (h_M1a : ¬ (0 < orient2 a b c * orient2 a b d))
3151 (h_M1b : ¬ (0 < orient2 c d a * orient2 c d b))
3152 (h_M2a : ¬ (0 < orient2 a c b * orient2 a c d))
3153 (h_M2b : ¬ (0 < orient2 b d a * orient2 b d c)) :
3154 orient2 a b c = 0 ∧ orient2 a b d = 0 ∧
3155 orient2 a c d = 0 ∧ orient2 b c d = 0 := by
3156 set o₁ := orient2 b c d with ho₁
3157 set o₂ := orient2 a c d with ho₂
3158 set o₃ := orient2 a b d with ho₃
3159 set o₄ := orient2 a b c with ho₄
3160 have hPluck : o₁ - o₂ + o₃ - o₄ = 0 := by
3161 have h := orient2_alternating_sum_eq_zero a b c d
3162 linarith
3163 have hcd_a : orient2 c d a = o₂ := by
3164 show orient2 c d a = orient2 a c d
3165 rw [orient2_cyclic, orient2_cyclic]
3166 have hcd_b : orient2 c d b = o₁ := by
3167 show orient2 c d b = orient2 b c d
3168 rw [orient2_cyclic, orient2_cyclic]
3169 have hacb : orient2 a c b = -o₄ := orient2_swap₂₃ a b c
3170 have hbda : orient2 b d a = o₃ := by
3171 show orient2 b d a = orient2 a b d
3172 rw [orient2_cyclic, orient2_cyclic]
3173 have hbdc : orient2 b d c = -o₁ := by
3174 have hsw : orient2 b d c = -orient2 b c d := orient2_swap₂₃ b c d
3175 linarith
3176 have h₃₄ : o₃ * o₄ ≤ 0 := by
3177 have h : o₄ * o₃ ≤ 0 := not_lt.mp h_M1a
3178 linarith [(by ring : o₃ * o₄ = o₄ * o₃)]
3179 have h₁₂ : o₁ * o₂ ≤ 0 := by
3180 rw [hcd_a, hcd_b] at h_M1b
3181 have h := not_lt.mp h_M1b
3182 linarith [h, (by ring : o₁ * o₂ = o₂ * o₁)]
3183 have h₂₄ : 0 ≤ o₂ * o₄ := by
3184 rw [hacb] at h_M2a
3185 have h := not_lt.mp h_M2a
3186 nlinarith [h]
3187 have h₁₃ : 0 ≤ o₁ * o₃ := by
3188 rw [hbda, hbdc] at h_M2b
3189 have h := not_lt.mp h_M2b
3190 nlinarith [h]
3191 rcases four_reals_M1_M2_pair_sos hPluck h₃₄ h₁₂ h₂₄ h₁₃ with
3192 ⟨hO₁, hO₄⟩ | ⟨hO₂, hO₃⟩
3193 · exact orient2_all_zero_of_o1_o4_zero hbc hO₁ hO₄
3194 · exact orient2_all_zero_of_o2_o3_zero had hO₂ hO₃
3195
3196/-- Pair `(M₂, M₃)`: if all four same-side witnesses fail, all `orient2`
3197values vanish. -/
3198theorem orient2_M2_M3_pair_fail_all_collinear
3199 {a b c d : Point2}
3200 (hcd : c ≠ d) (hab : a ≠ b)
3201 (h_M2a : ¬ (0 < orient2 a c b * orient2 a c d))
3202 (h_M2b : ¬ (0 < orient2 b d a * orient2 b d c))
3203 (h_M3a : ¬ (0 < orient2 a d b * orient2 a d c))
3204 (h_M3b : ¬ (0 < orient2 b c a * orient2 b c d)) :
3205 orient2 a b c = 0 ∧ orient2 a b d = 0 ∧
3206 orient2 a c d = 0 ∧ orient2 b c d = 0 := by
3207 set o₁ := orient2 b c d with ho₁
3208 set o₂ := orient2 a c d with ho₂
3209 set o₃ := orient2 a b d with ho₃
3210 set o₄ := orient2 a b c with ho₄
3211 have hPluck : o₁ - o₂ + o₃ - o₄ = 0 := by
3212 have h := orient2_alternating_sum_eq_zero a b c d
3213 linarith
3214 have hacb : orient2 a c b = -o₄ := orient2_swap₂₃ a b c
3215 have hbda : orient2 b d a = o₃ := by
3216 show orient2 b d a = orient2 a b d
3217 rw [orient2_cyclic, orient2_cyclic]
3218 have hbdc : orient2 b d c = -o₁ := by
3219 have hsw : orient2 b d c = -orient2 b c d := orient2_swap₂₃ b c d
3220 linarith
3221 have hadb : orient2 a d b = -o₃ := orient2_swap₂₃ a b d
3222 have hadc : orient2 a d c = -o₂ := orient2_swap₂₃ a c d
3223 have hbca : orient2 b c a = o₄ := by
3224 show orient2 b c a = orient2 a b c
3225 rw [orient2_cyclic, orient2_cyclic]
3226 have h₂₄ : 0 ≤ o₂ * o₄ := by
3227 rw [hacb] at h_M2a
3228 have h := not_lt.mp h_M2a
3229 nlinarith [h]
3230 have h₁₃ : 0 ≤ o₁ * o₃ := by
3231 rw [hbda, hbdc] at h_M2b
3232 have h := not_lt.mp h_M2b
3233 nlinarith [h]
3234 have h₂₃ : o₂ * o₃ ≤ 0 := by
3235 rw [hadb, hadc] at h_M3a
3236 have h := not_lt.mp h_M3a
3237 nlinarith [h]
3238 have h₁₄ : o₁ * o₄ ≤ 0 := by
3239 rw [hbca] at h_M3b
3240 have h := not_lt.mp h_M3b
3241 linarith [h, (by ring : o₁ * o₄ = o₄ * o₁)]
3242 rcases four_reals_M2_M3_pair_sos hPluck h₂₄ h₁₃ h₂₃ h₁₄ with
3243 ⟨hO₁, hO₂⟩ | ⟨hO₃, hO₄⟩
3244 · exact orient2_all_zero_of_o1_o2_zero hcd hO₁ hO₂
3245 · exact orient2_all_zero_of_o3_o4_zero hab hO₃ hO₄
3246
3247/-! ### Strong dichotomy: at least two matchings disjoint (noncollinear)
3248
3249Combining the three pair-fail-implies-all-collinear lemmas, in the
3250noncollinear case we get the strong dichotomy: at least two of the three
3251matchings are geometrically disjoint. Equivalently, the set of disjoint
3252matchings has cardinality at least two. -/
3253
3254/-- Pair "at-least-one-disjoint" for `(M₁, M₂)`. If the four points are not
3255all collinear, at least one of the matchings `(ab, cd)` or `(ac, bd)` is
3256geometrically disjoint. -/
3257theorem four_distinct_M1_or_M2_disjoint_noncollinear
3258 {a b c d : Point2}
3259 (hbc : b ≠ c) (had : a ≠ d)
3260 (hNotAllCollinear :
3261 orient2 a b c ≠ 0 ∨ orient2 a b d ≠ 0 ∨
3262 orient2 a c d ≠ 0 ∨ orient2 b c d ≠ 0) :
3263 OrderedEdgesGeometricallyDisjoint (a, b) (c, d) ∨
3264 OrderedEdgesGeometricallyDisjoint (a, c) (b, d) := by
3265 by_contra h
3266 push_neg at h
3267 obtain ⟨hN1, hN2⟩ := h
3268 -- ¬ disjoint M_1 ⇒ both same-side witnesses for M_1 fail.
3269 have hM1a : ¬ (0 < orient2 a b c * orient2 a b d) := by
3270 intro hwitness
3271 exact hN1 (same_side_segments_disjoint hwitness)
3272 have hM1b : ¬ (0 < orient2 c d a * orient2 c d b) := by
3273 intro hwitness
3274 exact hN1 (ordered_edges_geometrically_disjoint_symm (same_side_segments_disjoint hwitness))
3275 -- Similarly for M_2.
3276 have hM2a : ¬ (0 < orient2 a c b * orient2 a c d) := by
3277 intro hwitness
3278 exact hN2 (same_side_segments_disjoint hwitness)
3279 have hM2b : ¬ (0 < orient2 b d a * orient2 b d c) := by
3280 intro hwitness
3281 exact hN2 (ordered_edges_geometrically_disjoint_symm (same_side_segments_disjoint hwitness))
3282 -- Apply M₁/M₂ pair-fail lemma: all four orient2 vanish.
3283 obtain ⟨h₄, h₃, h₂, h₁⟩ :=
3284 orient2_M1_M2_pair_fail_all_collinear hbc had hM1a hM1b hM2a hM2b
3285 -- Contradiction with hNotAllCollinear.
3286 rcases hNotAllCollinear with h | h | h | h
3287 · exact h h₄
3288 · exact h h₃
3289 · exact h h₂
3290 · exact h h₁
3291
3292/-- Pair "at-least-one-disjoint" for `(M₁, M₃)`. -/
3293theorem four_distinct_M1_or_M3_disjoint_noncollinear
3294 {a b c d : Point2}
3295 (hbd : b ≠ d) (hac : a ≠ c)
3296 (hNotAllCollinear :
3297 orient2 a b c ≠ 0 ∨ orient2 a b d ≠ 0 ∨
3298 orient2 a c d ≠ 0 ∨ orient2 b c d ≠ 0) :
3299 OrderedEdgesGeometricallyDisjoint (a, b) (c, d) ∨
3300 OrderedEdgesGeometricallyDisjoint (a, d) (b, c) := by
3301 by_contra h
3302 push_neg at h
3303 obtain ⟨hN1, hN3⟩ := h
3304 have hM1a : ¬ (0 < orient2 a b c * orient2 a b d) := by
3305 intro hwitness
3306 exact hN1 (same_side_segments_disjoint hwitness)
3307 have hM1b : ¬ (0 < orient2 c d a * orient2 c d b) := by
3308 intro hwitness
3309 exact hN1 (ordered_edges_geometrically_disjoint_symm (same_side_segments_disjoint hwitness))
3310 have hM3a : ¬ (0 < orient2 a d b * orient2 a d c) := by
3311 intro hwitness
3312 exact hN3 (same_side_segments_disjoint hwitness)
3313 have hM3b : ¬ (0 < orient2 b c a * orient2 b c d) := by
3314 intro hwitness
3315 exact hN3 (ordered_edges_geometrically_disjoint_symm (same_side_segments_disjoint hwitness))
3316 obtain ⟨h₄, h₃, h₂, h₁⟩ :=
3317 orient2_M1_M3_pair_fail_all_collinear hbd hac hM1a hM1b hM3a hM3b
3318 rcases hNotAllCollinear with h | h | h | h
3319 · exact h h₄
3320 · exact h h₃
3321 · exact h h₂
3322 · exact h h₁
3323
3324/-- Pair "at-least-one-disjoint" for `(M₂, M₃)`. -/
3325theorem four_distinct_M2_or_M3_disjoint_noncollinear
3326 {a b c d : Point2}
3327 (hcd : c ≠ d) (hab : a ≠ b)
3328 (hNotAllCollinear :
3329 orient2 a b c ≠ 0 ∨ orient2 a b d ≠ 0 ∨
3330 orient2 a c d ≠ 0 ∨ orient2 b c d ≠ 0) :
3331 OrderedEdgesGeometricallyDisjoint (a, c) (b, d) ∨
3332 OrderedEdgesGeometricallyDisjoint (a, d) (b, c) := by
3333 by_contra h
3334 push_neg at h
3335 obtain ⟨hN2, hN3⟩ := h
3336 have hM2a : ¬ (0 < orient2 a c b * orient2 a c d) := by
3337 intro hwitness
3338 exact hN2 (same_side_segments_disjoint hwitness)
3339 have hM2b : ¬ (0 < orient2 b d a * orient2 b d c) := by
3340 intro hwitness
3341 exact hN2 (ordered_edges_geometrically_disjoint_symm (same_side_segments_disjoint hwitness))
3342 have hM3a : ¬ (0 < orient2 a d b * orient2 a d c) := by
3343 intro hwitness
3344 exact hN3 (same_side_segments_disjoint hwitness)
3345 have hM3b : ¬ (0 < orient2 b c a * orient2 b c d) := by
3346 intro hwitness
3347 exact hN3 (ordered_edges_geometrically_disjoint_symm (same_side_segments_disjoint hwitness))
3348 obtain ⟨h₄, h₃, h₂, h₁⟩ :=
3349 orient2_M2_M3_pair_fail_all_collinear hcd hab hM2a hM2b hM3a hM3b
3350 rcases hNotAllCollinear with h | h | h | h
3351 · exact h h₄
3352 · exact h h₃
3353 · exact h h₂
3354 · exact h h₁
3355
3356/-- Strong four-point dichotomy. For any four distinct points that are not
3357all collinear, at least two of the three perfect matchings of `K₄` are
3358geometrically disjoint. Stated as a disjunction of the three possible "two
3359disjoint" combinations. -/
3360theorem four_distinct_points_two_matchings_disjoint_noncollinear
3361 {a b c d : Point2}
3362 (hab : a ≠ b) (had : a ≠ d) (hac : a ≠ c)
3363 (hbc : b ≠ c) (hbd : b ≠ d) (hcd : c ≠ d)
3364 (hNotAllCollinear :
3365 orient2 a b c ≠ 0 ∨ orient2 a b d ≠ 0 ∨
3366 orient2 a c d ≠ 0 ∨ orient2 b c d ≠ 0) :
3367 (OrderedEdgesGeometricallyDisjoint (a, b) (c, d) ∧
3368 OrderedEdgesGeometricallyDisjoint (a, c) (b, d)) ∨
3369 (OrderedEdgesGeometricallyDisjoint (a, b) (c, d) ∧
3370 OrderedEdgesGeometricallyDisjoint (a, d) (b, c)) ∨
3371 (OrderedEdgesGeometricallyDisjoint (a, c) (b, d) ∧
3372 OrderedEdgesGeometricallyDisjoint (a, d) (b, c)) := by
3373 rcases four_distinct_M1_or_M2_disjoint_noncollinear hbc had hNotAllCollinear with
3374 hD1 | hD2
3375 · rcases four_distinct_M1_or_M3_disjoint_noncollinear hbd hac hNotAllCollinear with
3376 hD1' | hD3
3377 · -- D1 holds; need to find D2 or D3 also.
3378 rcases four_distinct_M2_or_M3_disjoint_noncollinear hcd hab hNotAllCollinear with
3379 hD2 | hD3
3380 · exact Or.inl ⟨hD1, hD2⟩
3381 · exact Or.inr (Or.inl ⟨hD1, hD3⟩)
3382 · exact Or.inr (Or.inl ⟨hD1, hD3⟩)
3383 · -- D2 holds.
3384 rcases four_distinct_M2_or_M3_disjoint_noncollinear hcd hab hNotAllCollinear with
3385 hD2' | hD3
3386 · -- D2 already from hD2. Need D1 or D3.
3387 rcases four_distinct_M1_or_M3_disjoint_noncollinear hbd hac hNotAllCollinear with
3388 hD1 | hD3
3389 · exact Or.inl ⟨hD1, hD2⟩
3390 · exact Or.inr (Or.inr ⟨hD2, hD3⟩)
3391 · exact Or.inr (Or.inr ⟨hD2, hD3⟩)
3392
3393/-! ### K4 wrap: missing-edge helper + noncollinear bound
3394
3395If two unordered edges have geometrically disjoint segments, then at least one
3396of them is missing from any Conway thrackle's unordered support. This is
3397the elementary lemma that converts the strong dichotomy into a missing-edge
3398count, which in turn bounds `unorderedEdgeSupport` cardinality. -/
3399
3400/-- If two unordered edges of an underlying point set have geometrically
3401disjoint segments (and the unordered edges themselves are distinct), then at
3402least one of them is missing from any Conway thrackle's unordered support. -/
3403theorem unordered_edge_missing_of_geometrically_disjoint
3404 {E : Finset (Point2 × Point2)} (hConway : IsConwayThrackle E)
3405 {p q r s : Point2}
3406 (hpq_rs : (Sym2.mk ((p, q) : Point2 × Point2)) ≠ Sym2.mk ((r, s) : Point2 × Point2))
3407 (hDisj : OrderedEdgesGeometricallyDisjoint (p, q) (r, s)) :
3408 (Sym2.mk ((p, q) : Point2 × Point2)) ∉ unorderedEdgeSupport E ∨
3409 (Sym2.mk ((r, s) : Point2 × Point2)) ∉ unorderedEdgeSupport E := by
3410 by_contra h
3411 push_neg at h
3412 obtain ⟨hu, hv⟩ := h
3413 rw [mem_unorderedEdgeSupport_iff] at hu hv
3414 obtain ⟨e, heE, hue⟩ := hu
3415 obtain ⟨f, hfE, hvf⟩ := hv
3416 have hef : e ≠ f := by
3417 intro habs
3418 apply hpq_rs
3419 rw [← hue, ← hvf, habs]
3420 have hSimple : OrderedEdgesMeetSimply e f := hConway e heE f hfE hef
3421 obtain ⟨x, hxef, _huniq⟩ := hSimple
3422 apply hDisj
3423 refine ⟨x, ?_, ?_⟩
3424 · have hueq := hue
3425 unfold unorderedEdgeOfOrdered at hueq
3426 rw [Sym2.mk_eq_mk_iff] at hueq
3427 rcases hueq with he_eq | he_eq
3428 · rw [he_eq] at hxef
3429 exact hxef.1
3430 · rw [he_eq] at hxef
3431 exact on_closed_segment_symm hxef.1
3432 · have hveq := hvf
3433 unfold unorderedEdgeOfOrdered at hveq
3434 rw [Sym2.mk_eq_mk_iff] at hveq
3435 rcases hveq with hf_eq | hf_eq
3436 · rw [hf_eq] at hxef
3437 exact hxef.2
3438 · rw [hf_eq] at hxef
3439 exact on_closed_segment_symm hxef.2
3440
3441/-- The standard six-pair Finset of unordered pairs from four points. -/
3442noncomputable def sixUnorderedPairs (a b c d : Point2) : Finset (Sym2 Point2) :=
3443 {Sym2.mk ((a, b) : Point2 × Point2), Sym2.mk ((a, c) : Point2 × Point2),
3444 Sym2.mk ((a, d) : Point2 × Point2), Sym2.mk ((b, c) : Point2 × Point2),
3445 Sym2.mk ((b, d) : Point2 × Point2), Sym2.mk ((c, d) : Point2 × Point2)}
3446
3447/-- Cardinality of the six-element set of unordered pairs from four distinct
3448points. This is the standard pigeonhole "container" for any unordered edge
3449support on a four-point ambient set. -/
3450theorem six_unordered_pairs_card_eq_six
3451 {a b c d : Point2}
3452 (hab : a ≠ b) (hac : a ≠ c) (had : a ≠ d)
3453 (hbc : b ≠ c) (hbd : b ≠ d) (hcd : c ≠ d) :
3454 (sixUnorderedPairs a b c d).card = 6 := by
3455 classical
3456 unfold sixUnorderedPairs
3457 -- The six `Sym2.mk` values are pairwise distinct via `Sym2.eq_iff`.
3458 have h_ab_ac : Sym2.mk ((a, b) : Point2 × Point2) ≠ Sym2.mk ((a, c) : Point2 × Point2) := by
3459 intro h; rw [Sym2.eq_iff] at h
3460 rcases h with ⟨_, h2⟩ | ⟨h1, _⟩
3461 · exact hbc h2
3462 · exact hac h1
3463 have h_ab_ad : Sym2.mk ((a, b) : Point2 × Point2) ≠ Sym2.mk ((a, d) : Point2 × Point2) := by
3464 intro h; rw [Sym2.eq_iff] at h
3465 rcases h with ⟨_, h2⟩ | ⟨h1, _⟩
3466 · exact hbd h2
3467 · exact had h1
3468 have h_ab_bc : Sym2.mk ((a, b) : Point2 × Point2) ≠ Sym2.mk ((b, c) : Point2 × Point2) := by
3469 intro h; rw [Sym2.eq_iff] at h
3470 rcases h with ⟨h1, _⟩ | ⟨h1, _⟩
3471 · exact hab h1
3472 · exact hac h1
3473 have h_ab_bd : Sym2.mk ((a, b) : Point2 × Point2) ≠ Sym2.mk ((b, d) : Point2 × Point2) := by
3474 intro h; rw [Sym2.eq_iff] at h
3475 rcases h with ⟨h1, _⟩ | ⟨h1, _⟩
3476 · exact hab h1
3477 · exact had h1
3478 have h_ab_cd : Sym2.mk ((a, b) : Point2 × Point2) ≠ Sym2.mk ((c, d) : Point2 × Point2) := by
3479 intro h; rw [Sym2.eq_iff] at h
3480 rcases h with ⟨h1, _⟩ | ⟨h1, _⟩
3481 · exact hac h1
3482 · exact had h1
3483 have h_ac_ad : Sym2.mk ((a, c) : Point2 × Point2) ≠ Sym2.mk ((a, d) : Point2 × Point2) := by
3484 intro h; rw [Sym2.eq_iff] at h
3485 rcases h with ⟨_, h2⟩ | ⟨h1, _⟩
3486 · exact hcd h2
3487 · exact had h1
3488 have h_ac_bc : Sym2.mk ((a, c) : Point2 × Point2) ≠ Sym2.mk ((b, c) : Point2 × Point2) := by
3489 intro h; rw [Sym2.eq_iff] at h
3490 rcases h with ⟨h1, _⟩ | ⟨h1, _⟩
3491 · exact hab h1
3492 · exact hac h1
3493 have h_ac_bd : Sym2.mk ((a, c) : Point2 × Point2) ≠ Sym2.mk ((b, d) : Point2 × Point2) := by
3494 intro h; rw [Sym2.eq_iff] at h
3495 rcases h with ⟨h1, _⟩ | ⟨h1, _⟩
3496 · exact hab h1
3497 · exact had h1
3498 have h_ac_cd : Sym2.mk ((a, c) : Point2 × Point2) ≠ Sym2.mk ((c, d) : Point2 × Point2) := by
3499 intro h; rw [Sym2.eq_iff] at h
3500 rcases h with ⟨h1, _⟩ | ⟨h1, _⟩
3501 · exact hac h1
3502 · exact had h1
3503 have h_ad_bc : Sym2.mk ((a, d) : Point2 × Point2) ≠ Sym2.mk ((b, c) : Point2 × Point2) := by
3504 intro h; rw [Sym2.eq_iff] at h
3505 rcases h with ⟨h1, _⟩ | ⟨h1, _⟩
3506 · exact hab h1
3507 · exact hac h1
3508 have h_ad_bd : Sym2.mk ((a, d) : Point2 × Point2) ≠ Sym2.mk ((b, d) : Point2 × Point2) := by
3509 intro h; rw [Sym2.eq_iff] at h
3510 rcases h with ⟨h1, _⟩ | ⟨h1, _⟩
3511 · exact hab h1
3512 · exact had h1
3513 have h_ad_cd : Sym2.mk ((a, d) : Point2 × Point2) ≠ Sym2.mk ((c, d) : Point2 × Point2) := by
3514 intro h; rw [Sym2.eq_iff] at h
3515 rcases h with ⟨h1, _⟩ | ⟨h1, _⟩
3516 · exact hac h1
3517 · exact had h1
3518 have h_bc_bd : Sym2.mk ((b, c) : Point2 × Point2) ≠ Sym2.mk ((b, d) : Point2 × Point2) := by
3519 intro h; rw [Sym2.eq_iff] at h
3520 rcases h with ⟨_, h2⟩ | ⟨h1, _⟩
3521 · exact hcd h2
3522 · exact hbd h1
3523 have h_bc_cd : Sym2.mk ((b, c) : Point2 × Point2) ≠ Sym2.mk ((c, d) : Point2 × Point2) := by
3524 intro h; rw [Sym2.eq_iff] at h
3525 rcases h with ⟨h1, _⟩ | ⟨h1, _⟩
3526 · exact hbc h1
3527 · exact hbd h1
3528 have h_bd_cd : Sym2.mk ((b, d) : Point2 × Point2) ≠ Sym2.mk ((c, d) : Point2 × Point2) := by
3529 intro h; rw [Sym2.eq_iff] at h
3530 rcases h with ⟨h1, _⟩ | ⟨h1, _⟩
3531 · exact hbc h1
3532 · exact hbd h1
3533 -- Now compute the cardinality using the distinctness facts.
3534 simp [h_ab_ac, h_ab_ad, h_ab_bc, h_ab_bd, h_ab_cd,
3535 h_ac_ad, h_ac_bc, h_ac_bd, h_ac_cd,
3536 h_ad_bc, h_ad_bd, h_ad_cd,
3537 h_bc_bd, h_bc_cd, h_bd_cd]
3538
3539/-- Counting helper: if `S` is contained in a six-element Finset `T`, and two
3540distinct elements `m₁, m₂ ∈ T` are not in `S`, then `|S| ≤ 4`. -/
3541theorem card_le_four_of_two_missing
3542 {S T : Finset (Sym2 Point2)}
3543 (hsub : S ⊆ T) (hTcard : T.card = 6)
3544 {m₁ m₂ : Sym2 Point2}
3545 (hm₁T : m₁ ∈ T) (hm₂T : m₂ ∈ T)
3546 (hm₁_ne : m₁ ≠ m₂)
3547 (hm₁_notS : m₁ ∉ S) (hm₂_notS : m₂ ∉ S) :
3548 S.card ≤ 4 := by
3549 classical
3550 have hSsub : S ⊆ T \ {m₁, m₂} := by
3551 intro x hxS
3552 refine Finset.mem_sdiff.mpr ⟨hsub hxS, ?_⟩
3553 intro hx_pair
3554 rcases Finset.mem_insert.mp hx_pair with hx | hx
3555 · exact hm₁_notS (hx ▸ hxS)
3556 · rw [Finset.mem_singleton] at hx
3557 exact hm₂_notS (hx ▸ hxS)
3558 have hPairCard : ({m₁, m₂} : Finset (Sym2 Point2)).card = 2 := by
3559 simp [hm₁_ne]
3560 have hPairSub : ({m₁, m₂} : Finset (Sym2 Point2)) ⊆ T := by
3561 intro x hx
3562 rcases Finset.mem_insert.mp hx with hx | hx
3563 · exact hx ▸ hm₁T
3564 · rw [Finset.mem_singleton] at hx
3565 exact hx ▸ hm₂T
3566 have hDiffCard : (T \ ({m₁, m₂} : Finset (Sym2 Point2))).card = 4 := by
3567 rw [Finset.card_sdiff_of_subset hPairSub, hTcard, hPairCard]
3568 have h := Finset.card_le_card hSsub
3569 rw [hDiffCard] at h
3570 exact h
3571
3572/-- Noncollinear Conway-conditioned K4 bound, conditional version. Assuming
3573the unordered edge support is contained in the standard six-pair Finset for
3574four ambient distinct points, and assuming not-all-collinear, we conclude
3575`|unorderedEdgeSupport E| ≤ 4`.
3576
3577The conditional shape lets us decouple the (long) casework for the
3578subset-inclusion hypothesis from the strong dichotomy + Conway argument.
3579The unconditional version follows once the subset inclusion is established
3580by enumeration on `A.card = 4`. -/
3581theorem exact_fourpoint_conway_thrackle_support_bound_conditional
3582 {a b c d : Point2}
3583 (hab : a ≠ b) (hac : a ≠ c) (had : a ≠ d)
3584 (hbc : b ≠ c) (hbd : b ≠ d) (hcd : c ≠ d)
3585 {E : Finset (Point2 × Point2)}
3586 (hConway : IsConwayThrackle E)
3587 (hsub : unorderedEdgeSupport E ⊆ sixUnorderedPairs a b c d)
3588 (hNotAllCol :
3589 orient2 a b c ≠ 0 ∨ orient2 a b d ≠ 0 ∨
3590 orient2 a c d ≠ 0 ∨ orient2 b c d ≠ 0) :
3591 (unorderedEdgeSupport E).card ≤ 4 := by
3592 classical
3593 have hTcard : (sixUnorderedPairs a b c d).card = 6 :=
3594 six_unordered_pairs_card_eq_six hab hac had hbc hbd hcd
3595 -- All six unordered pairs of {a, b, c, d} are members of sixUnorderedPairs.
3596 have hAB_mem : Sym2.mk ((a, b) : Point2 × Point2) ∈ sixUnorderedPairs a b c d := by
3597 simp [sixUnorderedPairs]
3598 have hAC_mem : Sym2.mk ((a, c) : Point2 × Point2) ∈ sixUnorderedPairs a b c d := by
3599 simp [sixUnorderedPairs]
3600 have hAD_mem : Sym2.mk ((a, d) : Point2 × Point2) ∈ sixUnorderedPairs a b c d := by
3601 simp [sixUnorderedPairs]
3602 have hBC_mem : Sym2.mk ((b, c) : Point2 × Point2) ∈ sixUnorderedPairs a b c d := by
3603 simp [sixUnorderedPairs]
3604 have hBD_mem : Sym2.mk ((b, d) : Point2 × Point2) ∈ sixUnorderedPairs a b c d := by
3605 simp [sixUnorderedPairs]
3606 have hCD_mem : Sym2.mk ((c, d) : Point2 × Point2) ∈ sixUnorderedPairs a b c d := by
3607 simp [sixUnorderedPairs]
3608 -- Inequalities between specific Sym2 pairs. Each is proved by unpacking
3609 -- `Sym2.eq_iff` and contradicting with one of the six distinctness facts.
3610 have h_AB_CD : Sym2.mk ((a, b) : Point2 × Point2) ≠ Sym2.mk ((c, d) : Point2 × Point2) := by
3611 intro h; rw [Sym2.eq_iff] at h
3612 rcases h with ⟨h1, _⟩ | ⟨h1, _⟩
3613 · exact hac h1
3614 · exact had h1
3615 have h_AC_BD : Sym2.mk ((a, c) : Point2 × Point2) ≠ Sym2.mk ((b, d) : Point2 × Point2) := by
3616 intro h; rw [Sym2.eq_iff] at h
3617 rcases h with ⟨h1, _⟩ | ⟨h1, _⟩
3618 · exact hab h1
3619 · exact had h1
3620 have h_AD_BC : Sym2.mk ((a, d) : Point2 × Point2) ≠ Sym2.mk ((b, c) : Point2 × Point2) := by
3621 intro h; rw [Sym2.eq_iff] at h
3622 rcases h with ⟨h1, _⟩ | ⟨h1, _⟩
3623 · exact hab h1
3624 · exact hac h1
3625 have h_AB_AC : Sym2.mk ((a, b) : Point2 × Point2) ≠ Sym2.mk ((a, c) : Point2 × Point2) := by
3626 intro h; rw [Sym2.eq_iff] at h
3627 rcases h with ⟨_, h2⟩ | ⟨h1, _⟩
3628 · exact hbc h2
3629 · exact hac h1
3630 have h_AB_AD : Sym2.mk ((a, b) : Point2 × Point2) ≠ Sym2.mk ((a, d) : Point2 × Point2) := by
3631 intro h; rw [Sym2.eq_iff] at h
3632 rcases h with ⟨_, h2⟩ | ⟨h1, _⟩
3633 · exact hbd h2
3634 · exact had h1
3635 have h_AB_BD : Sym2.mk ((a, b) : Point2 × Point2) ≠ Sym2.mk ((b, d) : Point2 × Point2) := by
3636 intro h; rw [Sym2.eq_iff] at h
3637 rcases h with ⟨h1, _⟩ | ⟨h1, _⟩
3638 · exact hab h1
3639 · exact had h1
3640 have h_AB_BC : Sym2.mk ((a, b) : Point2 × Point2) ≠ Sym2.mk ((b, c) : Point2 × Point2) := by
3641 intro h; rw [Sym2.eq_iff] at h
3642 rcases h with ⟨h1, _⟩ | ⟨h1, _⟩
3643 · exact hab h1
3644 · exact hac h1
3645 have h_CD_AC : Sym2.mk ((c, d) : Point2 × Point2) ≠ Sym2.mk ((a, c) : Point2 × Point2) := by
3646 intro h; rw [Sym2.eq_iff] at h
3647 rcases h with ⟨h1, _⟩ | ⟨_, h2⟩
3648 · exact hac h1.symm
3649 · exact had h2.symm
3650 have h_CD_BD : Sym2.mk ((c, d) : Point2 × Point2) ≠ Sym2.mk ((b, d) : Point2 × Point2) := by
3651 intro h; rw [Sym2.eq_iff] at h
3652 rcases h with ⟨h1, _⟩ | ⟨h1, _⟩
3653 · exact hbc h1.symm
3654 · exact hcd h1
3655 have h_CD_AD : Sym2.mk ((c, d) : Point2 × Point2) ≠ Sym2.mk ((a, d) : Point2 × Point2) := by
3656 intro h; rw [Sym2.eq_iff] at h
3657 rcases h with ⟨h1, _⟩ | ⟨h1, _⟩
3658 · exact hac h1.symm
3659 · exact hcd h1
3660 have h_CD_BC : Sym2.mk ((c, d) : Point2 × Point2) ≠ Sym2.mk ((b, c) : Point2 × Point2) := by
3661 intro h; rw [Sym2.eq_iff] at h
3662 rcases h with ⟨h1, _⟩ | ⟨_, h2⟩
3663 · exact hbc h1.symm
3664 · exact hbd h2.symm
3665 have h_AC_AD : Sym2.mk ((a, c) : Point2 × Point2) ≠ Sym2.mk ((a, d) : Point2 × Point2) := by
3666 intro h; rw [Sym2.eq_iff] at h
3667 rcases h with ⟨_, h2⟩ | ⟨h1, _⟩
3668 · exact hcd h2
3669 · exact had h1
3670 have h_AC_BC : Sym2.mk ((a, c) : Point2 × Point2) ≠ Sym2.mk ((b, c) : Point2 × Point2) := by
3671 intro h; rw [Sym2.eq_iff] at h
3672 rcases h with ⟨h1, _⟩ | ⟨h1, _⟩
3673 · exact hab h1
3674 · exact hac h1
3675 have h_BD_AD : Sym2.mk ((b, d) : Point2 × Point2) ≠ Sym2.mk ((a, d) : Point2 × Point2) := by
3676 intro h; rw [Sym2.eq_iff] at h
3677 rcases h with ⟨h1, _⟩ | ⟨h1, _⟩
3678 · exact hab h1.symm
3679 · exact hbd h1
3680 have h_BD_BC : Sym2.mk ((b, d) : Point2 × Point2) ≠ Sym2.mk ((b, c) : Point2 × Point2) := by
3681 intro h; rw [Sym2.eq_iff] at h
3682 rcases h with ⟨_, h2⟩ | ⟨h1, _⟩
3683 · exact hcd h2.symm
3684 · exact hbc h1
3685 -- Now the strong dichotomy.
3686 rcases four_distinct_points_two_matchings_disjoint_noncollinear hab had hac hbc hbd hcd hNotAllCol with
3687 ⟨hD1, hD2⟩ | ⟨hD1, hD3⟩ | ⟨hD2, hD3⟩
3688 -- For brevity we package each case below as a small "two missing edges" derivation.
3689 · -- M_1 and M_2 disjoint.
3690 rcases unordered_edge_missing_of_geometrically_disjoint hConway h_AB_CD hD1 with hMA | hMA
3691 · rcases unordered_edge_missing_of_geometrically_disjoint hConway h_AC_BD hD2 with hMB | hMB
3692 · exact card_le_four_of_two_missing hsub hTcard hAB_mem hAC_mem h_AB_AC hMA hMB
3693 · exact card_le_four_of_two_missing hsub hTcard hAB_mem hBD_mem h_AB_BD hMA hMB
3694 · rcases unordered_edge_missing_of_geometrically_disjoint hConway h_AC_BD hD2 with hMB | hMB
3695 · exact card_le_four_of_two_missing hsub hTcard hCD_mem hAC_mem h_CD_AC hMA hMB
3696 · exact card_le_four_of_two_missing hsub hTcard hCD_mem hBD_mem h_CD_BD hMA hMB
3697 · -- M_1 and M_3 disjoint.
3698 rcases unordered_edge_missing_of_geometrically_disjoint hConway h_AB_CD hD1 with hMA | hMA
3699 · rcases unordered_edge_missing_of_geometrically_disjoint hConway h_AD_BC hD3 with hMB | hMB
3700 · exact card_le_four_of_two_missing hsub hTcard hAB_mem hAD_mem h_AB_AD hMA hMB
3701 · exact card_le_four_of_two_missing hsub hTcard hAB_mem hBC_mem h_AB_BC hMA hMB
3702 · rcases unordered_edge_missing_of_geometrically_disjoint hConway h_AD_BC hD3 with hMB | hMB
3703 · exact card_le_four_of_two_missing hsub hTcard hCD_mem hAD_mem h_CD_AD hMA hMB
3704 · exact card_le_four_of_two_missing hsub hTcard hCD_mem hBC_mem h_CD_BC hMA hMB
3705 · -- M_2 and M_3 disjoint.
3706 rcases unordered_edge_missing_of_geometrically_disjoint hConway h_AC_BD hD2 with hMA | hMA
3707 · rcases unordered_edge_missing_of_geometrically_disjoint hConway h_AD_BC hD3 with hMB | hMB
3708 · exact card_le_four_of_two_missing hsub hTcard hAC_mem hAD_mem h_AC_AD hMA hMB
3709 · exact card_le_four_of_two_missing hsub hTcard hAC_mem hBC_mem h_AC_BC hMA hMB
3710 · rcases unordered_edge_missing_of_geometrically_disjoint hConway h_AD_BC hD3 with hMB | hMB
3711 · exact card_le_four_of_two_missing hsub hTcard hBD_mem hAD_mem h_BD_AD hMA hMB
3712 · exact card_le_four_of_two_missing hsub hTcard hBD_mem hBC_mem h_BD_BC hMA hMB
3713
3714/-- Subset-inclusion bookkeeping. For a four-point ambient set `A = {a,b,c,d}`
3715and an edge set `E` whose endpoints are in `A`, the unordered support of `E`
3716is contained in the standard six-pair `sixUnorderedPairs a b c d`. -/
3717theorem unorderedEdgeSupport_subset_sixUnorderedPairs_of_card_eq_four
3718 {A : Finset Point2} {E : Finset (Point2 × Point2)}
3719 (hEdges : ∀ e ∈ E, e.1 ∈ A ∧ e.2 ∈ A ∧ e.1 ≠ e.2)
3720 {a b c d : Point2}
3721 (hAeq : A = ({a, b, c, d} : Finset Point2)) :
3722 unorderedEdgeSupport E ⊆ sixUnorderedPairs a b c d := by
3723 classical
3724 intro u hu
3725 unfold unorderedEdgeSupport at hu
3726 rw [Finset.mem_image] at hu
3727 rcases hu with ⟨e, heE, heu⟩
3728 have heData := hEdges e heE
3729 rw [hAeq] at heData
3730 cases e with
3731 | mk p q =>
3732 simp at heData heu
3733 have hp : p = a ∨ p = b ∨ p = c ∨ p = d := by simpa using heData.1
3734 have hq : q = a ∨ q = b ∨ q = c ∨ q = d := by simpa using heData.2.1
3735 have hpq : p ≠ q := heData.2.2
3736 rw [← heu]
3737 rcases hp with hp | hp | hp | hp <;> rcases hq with hq | hq | hq | hq
3738 -- 16 cases. 4 diagonal collapse to False; 12 non-diagonal map to one
3739 -- of the six elements of sixUnorderedPairs (six direct, six via swap).
3740 all_goals (try (subst p; subst q; exact False.elim (hpq rfl)))
3741 all_goals (subst p; subst q)
3742 all_goals (simp [sixUnorderedPairs, unorderedEdgeOfOrdered])
3743
3744/-- Repeated-argument orientation vanishing. When two of the three arguments
3745of `orient2` are equal, the result is zero. -/
3746theorem orient2_eq_zero_of_two_eq_first
3747 (a b : Point2) : orient2 a a b = 0 := by
3748 unfold orient2; ring
3749
3750theorem orient2_eq_zero_of_two_eq_second
3751 (a b : Point2) : orient2 a b a = 0 := by
3752 unfold orient2; ring
3753
3754theorem orient2_eq_zero_of_two_eq_third
3755 (a b : Point2) : orient2 a b b = 0 := by
3756 unfold orient2; ring
3757
3758/-- If all four "canonical" orient2 values on `{a, b, c, d}` vanish, then
3759every triple `(p, q, r)` with `p, q, r ∈ {a, b, c, d}` has `orient2 p q r = 0`.
3760This is the key bridge between the 4-orient form of "noncollinear" and the
3761full "every triple from A is collinear" form. -/
3762theorem orient2_zero_of_quadruple_zero
3763 {a b c d : Point2}
3764 (h_abc : orient2 a b c = 0) (h_abd : orient2 a b d = 0)
3765 (h_acd : orient2 a c d = 0) (h_bcd : orient2 b c d = 0)
3766 {p q r : Point2}
3767 (hp : p = a ∨ p = b ∨ p = c ∨ p = d)
3768 (hq : q = a ∨ q = b ∨ q = c ∨ q = d)
3769 (hr : r = a ∨ r = b ∨ r = c ∨ r = d) :
3770 orient2 p q r = 0 := by
3771 -- Derive the additional orient2 zeros at every permutation by cyclic/swap.
3772 have h_acb : orient2 a c b = 0 := by
3773 have := orient2_swap₂₃ a b c; linarith
3774 have h_adb : orient2 a d b = 0 := by
3775 have := orient2_swap₂₃ a b d; linarith
3776 have h_adc : orient2 a d c = 0 := by
3777 have := orient2_swap₂₃ a c d; linarith
3778 have h_bdc : orient2 b d c = 0 := by
3779 have := orient2_swap₂₃ b c d; linarith
3780 have h_bac : orient2 b a c = 0 := by
3781 have := orient2_swap₁₂ a b c; linarith
3782 have h_bad : orient2 b a d = 0 := by
3783 have := orient2_swap₁₂ a b d; linarith
3784 have h_cab : orient2 c a b = 0 := by
3785 have := orient2_cyclic' a b c; linarith
3786 have h_cad : orient2 c a d = 0 := by
3787 have := orient2_swap₁₂ a c d; linarith
3788 have h_cba : orient2 c b a = 0 := by
3789 have := orient2_swap₁₃ a b c; linarith
3790 have h_cbd : orient2 c b d = 0 := by
3791 have := orient2_swap₁₂ b c d; linarith
3792 have h_cda : orient2 c d a = 0 := by
3793 have := orient2_cyclic a c d; linarith
3794 have h_cdb : orient2 c d b = 0 := by
3795 have := orient2_cyclic b c d; linarith
3796 have h_dab : orient2 d a b = 0 := by
3797 have := orient2_cyclic' a b d; linarith
3798 have h_dac : orient2 d a c = 0 := by
3799 have := orient2_cyclic' a c d; linarith
3800 have h_dba : orient2 d b a = 0 := by
3801 have := orient2_swap₁₃ a b d; linarith
3802 have h_dbc : orient2 d b c = 0 := by
3803 have := orient2_cyclic d b c; linarith
3804 have h_dca : orient2 d c a = 0 := by
3805 have := orient2_swap₁₃ a c d; linarith
3806 have h_dcb : orient2 d c b = 0 := by
3807 have := orient2_swap₁₃ b c d; linarith
3808 have h_bca : orient2 b c a = 0 := by
3809 have := orient2_cyclic a b c; linarith
3810 have h_bda : orient2 b d a = 0 := by
3811 have := orient2_cyclic a b d; linarith
3812 have h_acd' : orient2 a c d = 0 := h_acd
3813 -- Case-split on each of p, q, r.
3814 rcases hp with hp | hp | hp | hp <;>
3815 rcases hq with hq | hq | hq | hq <;>
3816 rcases hr with hr | hr | hr | hr <;>
3817 subst_vars
3818 all_goals
3819 first
3820 | exact h_abc | exact h_abd | exact h_acd | exact h_bcd
3821 | exact h_acb | exact h_adb | exact h_adc | exact h_bdc
3822 | exact h_bac | exact h_bad | exact h_cab | exact h_cad
3823 | exact h_cba | exact h_cbd | exact h_cda | exact h_cdb
3824 | exact h_dab | exact h_dac | exact h_dba | exact h_dbc
3825 | exact h_dca | exact h_dcb | exact h_bca | exact h_bda
3826 | exact orient2_eq_zero_of_two_eq_first _ _
3827 | exact orient2_eq_zero_of_two_eq_second _ _
3828 | exact orient2_eq_zero_of_two_eq_third _ _
3829
3830/-- Unconditional noncollinear Conway-conditioned K4 bound. Combines
3831`unorderedEdgeSupport_subset_sixUnorderedPairs_of_card_eq_four` with the
3832conditional version `exact_fourpoint_conway_thrackle_support_bound_conditional`. -/
3833theorem exact_fourpoint_conway_thrackle_support_bound_noncollinear_thm
3834 {A : Finset Point2} {E : Finset (Point2 × Point2)}
3835 (hEdges : ∀ e ∈ E, e.1 ∈ A ∧ e.2 ∈ A ∧ e.1 ≠ e.2)
3836 (hConway : IsConwayThrackle E)
3837 (hAcard : A.card = 4)
3838 (hNotAllCol : ¬ ∀ p ∈ A, ∀ q ∈ A, ∀ r ∈ A, orient2 p q r = 0) :
3839 (unorderedEdgeSupport E).card ≤ A.card := by
3840 classical
3841 rcases Finset.card_eq_four.mp hAcard with
3842 ⟨a, b, c, d, hab, hac, had, hbc, hbd, hcd, hAeq⟩
3843 have hsub : unorderedEdgeSupport E ⊆ sixUnorderedPairs a b c d :=
3844 unorderedEdgeSupport_subset_sixUnorderedPairs_of_card_eq_four hEdges hAeq
3845 have hNotAllCol4 :
3846 orient2 a b c ≠ 0 ∨ orient2 a b d ≠ 0 ∨
3847 orient2 a c d ≠ 0 ∨ orient2 b c d ≠ 0 := by
3848 by_contra h
3849 push_neg at h
3850 obtain ⟨h_abc, h_abd, h_acd, h_bcd⟩ := h
3851 apply hNotAllCol
3852 intro p hp q hq r hr
3853 rw [hAeq] at hp hq hr
3854 simp at hp hq hr
3855 exact orient2_zero_of_quadruple_zero h_abc h_abd h_acd h_bcd hp hq hr
3856 have hLE := exact_fourpoint_conway_thrackle_support_bound_conditional
3857 hab hac had hbc hbd hcd hConway hsub hNotAllCol4
3858 rw [hAcard]
3859 exact hLE
3860
3861/-! ### Bridge documentation (continued)
3862
3863For brevity we prove only the `M₁/M₃` algebraic pair lemma in this layer;
3864the symmetric `M₁/M₂` and `M₂/M₃` pair lemmas are scheduled for the next
3865tightening session. Each follows the same SOS-Plücker pattern with two
3866hypothesised sign-products from each matching's witnesses.
3867
3868### Session 2026-05-23 status (one-shot dichotomy attempt)
3869
3870This block delivers the algebraic + geometric *one-shot* foundation for the
3871Conway-conditioned 4-point K4 obstruction, replacing the existing
3872`ExactFourPointK4ObstructionCertificate` (which is provably false on
3873all-collinear 4-point configurations because overlap counts as "meeting"
3874under `OrderedEdgesGeometricallyDisjoint`, yet provides no disjoint pair).
3875
3876What is proved in this layer:
3877
3878* `four_reals_orientation_dichotomy_alg`: algebraic SOS dichotomy. Under
3879 Plücker on four reals, the six bilinear sign witnesses cannot all fail
3880 simultaneously unless all four reals vanish.
3881* `four_points_orientation_dichotomy`: geometric instantiation. For any
3882 four points not all collinear, at least one of the six `same_side`
3883 disjointness witnesses for the three perfect matchings holds.
3884* `four_distinct_points_one_matching_disjoint_noncollinear`: at least one
3885 matching is geometrically disjoint when the four points are noncollinear.
3886* `ExactFourPointConwayThrackleSupportBoundCertificate`: corrected target
3887 (Conway-conditioned).
3888* `CollinearFourPointConwayResidual`: all-collinear residual stated
3889 separately for follow-up.
3890* `four_reals_M1_M3_pair_sos`: algebraic pair lemma for the `M₁/M₃`
3891 matchings. Joint failure gives `o₁ = o₃ = 0` or `o₂ = o₄ = 0`.
3892* `orient2_zero_two_zeros_share_bd`: geometric closure. Two zero
3893 orientations sharing a `b, d` vertex pair with `b ≠ d` force a third
3894 zero orientation, hence all four points are collinear when distinct.
3895
3896What is pending for future sessions:
3897
38981. `four_reals_M1_M2_pair_sos` and `four_reals_M2_M3_pair_sos`: symmetric
3899 pair lemmas. Each follows the same SOS-with-Plücker pattern.
39002. `four_distinct_points_two_matchings_disjoint_noncollinear`: combine the
3901 three pair lemmas plus the original dichotomy to conclude at least two
3902 matchings disjoint.
39033. `exact_fourpoint_conway_thrackle_support_bound_noncollinear`: use the
3904 strong dichotomy to bound `|unorderedEdgeSupport E| ≤ 4` for noncollinear
3905 four-point Conway thrackles with no incident vertex.
39064. Discharge `CollinearFourPointConwayResidual` by sorting on the supporting
3907 line and counting which pairs of unordered edges can share at most one
3908 point.
39095. Combine 3 and 4 into `exact_fourpoint_conway_thrackle_support_bound_thm`,
3910 then lift through the existing `fivepoint`/`sixpoint` boundary chain to
3911 close `LargeNonStarConwayThrackleSupportBound` and ultimately
3912 `ConwayThrackleSupportBound`. -/
3913
3914/-- Five-point-or-larger non-star support certificate. This is the genuinely
3915large part of the remaining straight-line thrackle theorem after the exact
3916four-vertex boundary is separated. -/
3917def FivePointNonStarThrackleSupportBoundCertificate : Prop :=
3918 ∀ A : Finset Point2,
3919 ∀ E : Finset (Point2 × Point2),
3920 (∀ e ∈ E, e.1 ∈ A ∧ e.2 ∈ A ∧ e.1 ≠ e.2) →
3921 (∀ e ∈ E, ∀ f ∈ E, ¬ OrderedEdgesGeometricallyDisjoint e f) →
3922 5 ≤ A.card →
3923 (∀ v : Point2, ¬ OrderedEdgesIncidentTo v E) →
3924 (unorderedEdgeSupport E).card ≤ A.card
3925
3926/-- Exact five-vertex non-star support certificate. Kept separate from the
3927large theorem so finite boundary geometry can be attacked independently. -/
3928def ExactFivePointNonStarThrackleSupportBoundCertificate : Prop :=
3929 ∀ A : Finset Point2,
3930 ∀ E : Finset (Point2 × Point2),
3931 (∀ e ∈ E, e.1 ∈ A ∧ e.2 ∈ A ∧ e.1 ≠ e.2) →
3932 (∀ e ∈ E, ∀ f ∈ E, ¬ OrderedEdgesGeometricallyDisjoint e f) →
3933 A.card = 5 →
3934 (∀ v : Point2, ¬ OrderedEdgesIncidentTo v E) →
3935 (unorderedEdgeSupport E).card ≤ A.card
3936
3937/-- Six-point-or-larger non-star support certificate. -/
3938def SixPointNonStarThrackleSupportBoundCertificate : Prop :=
3939 ∀ A : Finset Point2,
3940 ∀ E : Finset (Point2 × Point2),
3941 (∀ e ∈ E, e.1 ∈ A ∧ e.2 ∈ A ∧ e.1 ≠ e.2) →
3942 (∀ e ∈ E, ∀ f ∈ E, ¬ OrderedEdgesGeometricallyDisjoint e f) →
3943 6 ≤ A.card →
3944 (∀ v : Point2, ¬ OrderedEdgesIncidentTo v E) →
3945 (unorderedEdgeSupport E).card ≤ A.card
3946
3947/-- Exact five-point support plus the six-point-or-larger residual supplies the
3948five-point-or-larger non-star support theorem. -/
3949theorem fivepoint_nonstar_support_bound_from_exact_five_and_six_residual
3950 (hExact5 : ExactFivePointNonStarThrackleSupportBoundCertificate)
3951 (hSix : SixPointNonStarThrackleSupportBoundCertificate) :
3952 FivePointNonStarThrackleSupportBoundCertificate := by
3953 intro A E hEdges hNoDisj hA5 hNonStar
3954 by_cases hEq5 : A.card = 5
3955 · exact hExact5 A E hEdges hNoDisj hEq5 hNonStar
3956 · have hA6 : 6 ≤ A.card := by omega
3957 exact hSix A E hEdges hNoDisj hA6 hNonStar
3958
3959/-- Exact four-vertex support plus the five-point-or-larger residual supplies
3960the four-point-or-larger non-star support theorem. -/
3961theorem fourpoint_nonstar_support_bound_from_exact_four_and_five_residual
3962 (hExact4 : ExactFourPointNonStarThrackleSupportBoundCertificate)
3963 (hFive : FivePointNonStarThrackleSupportBoundCertificate) :
3964 FourPointNonStarThrackleSupportBoundCertificate := by
3965 intro A E hEdges hNoDisj hA4 hNonStar
3966 by_cases hEq4 : A.card = 4
3967 · exact hExact4 A E hEdges hNoDisj hEq4 hNonStar
3968 · have hA5 : 5 ≤ A.card := by omega
3969 exact hFive A E hEdges hNoDisj hA5 hNonStar
3970
3971/-- Closing the four-point-or-larger residual closes the large non-star support
3972residual, because the three-point case is a finite triangle bound. -/
3973theorem large_nonstar_support_bound_from_fourpoint_residual
3974 (hFour : FourPointNonStarThrackleSupportBoundCertificate) :
3975 LargeNonStarThrackleSupportBoundCertificate := by
3976 intro A E hEdges hNoDisj hA3 hNonStar
3977 by_cases hAcard3 : A.card = 3
3978 · exact unordered_support_card_le_of_card_eq_three hAcard3 hEdges
3979 · have hA4 : 4 ≤ A.card := by omega
3980 exact hFour A E hEdges hNoDisj hA4 hNonStar
3981
3982/-- The cardinal large-non-star residual supplies the endpoint-charge residual,
3983because finite cardinal comparison produces an injection. -/
3984theorem large_nonstar_endpoint_charging_from_support_bound
3985 (hSupport : LargeNonStarThrackleSupportBoundCertificate) :
3986 LargeNonStarThrackleEndpointChargingCertificate := by
3987 intro A E hEdges hNoDisj hA3 hNonStar
3988 exact endpoint_charge_of_support_card_le
3989 (hSupport A E hEdges hNoDisj hA3 hNonStar)
3990
3991/-- Closing all large non-star systems closes the non-star residual, because the
3992small systems are automatically stars. -/
3993theorem nonstar_thrackle_endpoint_charging_from_large_residual
3994 (hLarge : LargeNonStarThrackleEndpointChargingCertificate) :
3995 NonStarThrackleEndpointChargingCertificate := by
3996 intro A E hEdges hNoDisj hNonStar
3997 by_cases hA2 : A.card ≤ 2
3998 · rcases exists_incident_vertex_of_card_le_two hA2 hEdges with ⟨v, hIncident⟩
3999 exact False.elim (hNonStar v hIncident)
4000 · have hA3 : 3 ≤ A.card := by omega
4001 exact hLarge A E hEdges hNoDisj hA3 hNonStar
4002
4003/-- Star closure plus the non-star residual certificate gives the full
4004endpoint-charging form of the straight-line thrackle theorem. -/
4005theorem thrackle_endpoint_charging_from_nonstar_residual
4006 (hNonStar : NonStarThrackleEndpointChargingCertificate) :
4007 ThrackleEndpointChargingCertificate := by
4008 intro A E hEdges hNoDisj
4009 by_cases hStar : ∃ v : Point2, OrderedEdgesIncidentTo v E
4010 · rcases hStar with ⟨v, hIncident⟩
4011 exact endpoint_charging_of_incident_vertex hEdges hIncident
4012 · exact hNonStar A E hEdges hNoDisj (by
4013 intro v hIncident
4014 exact hStar ⟨v, hIncident⟩)
4015
4016/-- Star systems and `|A| ≤ 2` systems are closed. Therefore a large non-star
4017endpoint-charge certificate is enough for the full straight-line thrackle
4018endpoint-charge theorem. -/
4019theorem thrackle_endpoint_charging_from_large_nonstar_residual
4020 (hLarge : LargeNonStarThrackleEndpointChargingCertificate) :
4021 ThrackleEndpointChargingCertificate :=
4022 thrackle_endpoint_charging_from_nonstar_residual
4023 (nonstar_thrackle_endpoint_charging_from_large_residual hLarge)
4024
4025/-- Cardinal support bound on large non-star systems is enough for the full
4026endpoint-charging form of straight-line thrackle. -/
4027theorem thrackle_endpoint_charging_from_large_nonstar_support_bound
4028 (hSupport : LargeNonStarThrackleSupportBoundCertificate) :
4029 ThrackleEndpointChargingCertificate :=
4030 thrackle_endpoint_charging_from_large_nonstar_residual
4031 (large_nonstar_endpoint_charging_from_support_bound hSupport)
4032
4033/-- A cardinal support bound for four-point-or-larger non-star systems is enough
4034for the full endpoint-charging form of straight-line thrackle. -/
4035theorem thrackle_endpoint_charging_from_fourpoint_nonstar_support_bound
4036 (hFour : FourPointNonStarThrackleSupportBoundCertificate) :
4037 ThrackleEndpointChargingCertificate :=
4038 thrackle_endpoint_charging_from_large_nonstar_support_bound
4039 (large_nonstar_support_bound_from_fourpoint_residual hFour)
4040
4041/-- The endpoint-charging certificate implies the pointwise undirected thrackle
4042support theorem by finite cardinality. This isolates the remaining geometric
4043content of the classical thrackle input. -/
4044theorem pointwise_thrackle_support_from_endpoint_charging
4045 (h : ThrackleEndpointChargingCertificate) :
4046 PointwiseUndirectedThrackleSupportBound := by
4047 intro A E hEdges hNoDisj
4048 obtain ⟨charge, hInjective⟩ := h A E hEdges hNoDisj
4049 have hcard := Fintype.card_le_of_injective charge hInjective
4050 simpa using hcard
4051
4052/-- The pointwise straight-line thrackle support theorem implies the eventual
4053form used by the Erdős #132 reduction. -/
4054theorem undirected_thrackle_support_from_pointwise
4055 (h : PointwiseUndirectedThrackleSupportBound) :
4056 UndirectedThrackleSupportBound := by
4057 filter_upwards with n
4058 intro A _hA E hEdges hNoDisj
4059 exact h A E hEdges hNoDisj
4060
4061/-- Orientation fibers are at most two for the edge sets relevant to the
4062thrackle bridge. Kept as a named finite bridge until the preferred unordered
4063edge API is expanded. -/
4064def OrderedOrientationFiberBound : Prop :=
4065 ∀ᶠ n in atTop,
4066 ∀ A : Finset Point2,
4067 A.card = n →
4068 ∀ E : Finset (Point2 × Point2),
4069 (∀ e ∈ E, e.1 ∈ A ∧ e.2 ∈ A ∧ e.1 ≠ e.2) →
4070 OrientationFiberAtMostTwo E
4071
4072/-- Undirected thrackle support plus orientation bookkeeping implies the
4073ordered thrackle bound used by the diameter shell proof. -/
4074theorem ordered_thrackle_bound_from_undirected_support
4075 (hSupport : UndirectedThrackleSupportBound)
4076 (hOrient : OrderedOrientationFiberBound) :
4077 OrderedThrackleBound := by
4078 filter_upwards [hSupport, hOrient] with n hSupportN hOrientN
4079 intro A hA E hEdges hNoDisj
4080 have hOrdered : E.card ≤ 2 * (unorderedEdgeSupport E).card :=
4081 ordered_card_le_two_mul_unordered_support E (hOrientN A hA E hEdges)
4082 have hSupportCard : (unorderedEdgeSupport E).card ≤ A.card :=
4083 hSupportN A hA E hEdges hNoDisj
4084 exact le_trans hOrdered (Nat.mul_le_mul_left 2 hSupportCard)
4085
4086/-- Since orientation fibers are universally bounded by two, the undirected
4087support theorem alone implies the ordered thrackle bound. -/
4088theorem ordered_thrackle_bound_from_undirected_support_only
4089 (hSupport : UndirectedThrackleSupportBound) :
4090 OrderedThrackleBound := by
4091 filter_upwards [hSupport] with n hSupportN
4092 intro A hA E hEdges hNoDisj
4093 have hOrdered : E.card ≤ 2 * (unorderedEdgeSupport E).card :=
4094 ordered_card_le_two_mul_unordered_support E (orientation_fiber_at_most_two E)
4095 have hSupportCard : (unorderedEdgeSupport E).card ≤ A.card :=
4096 hSupportN A hA E hEdges hNoDisj
4097 exact le_trans hOrdered (Nat.mul_le_mul_left 2 hSupportCard)
4098
4099/-- Hopf-Pannwitz ordered multiplicity follows from no-disjoint-diameter-edges
4100plus the ordered thrackle bound. -/
4101theorem diameter_ordered_bound_from_thrackle_components
4102 (hNoDisjoint : NoDisjointDiameterEdges)
4103 (hThrackle : OrderedThrackleBound) :
4104 DiameterShellOrderedMultiplicityBound := by
4105 filter_upwards [hNoDisjoint, hThrackle] with n hNoDisjointN hThrackleN
4106 intro A hA Δ hΔ
4107 have hEdges :
4108 ∀ e ∈ diameterOrderedEdges A Δ,
4109 e.1 ∈ A ∧ e.2 ∈ A ∧ e.1 ≠ e.2 := by
4110 intro e he
4111 unfold diameterOrderedEdges orderedPairEvents at he
4112 have he' := Finset.mem_filter.mp he
4113 have hp := Finset.mem_filter.mp he'.1
4114 have hprod := Finset.mem_product.mp hp.1
4115 exact ⟨hprod.1, hprod.2, hp.2⟩
4116 have hNoDisj :
4117 ∀ e ∈ diameterOrderedEdges A Δ,
4118 ∀ f ∈ diameterOrderedEdges A Δ,
4119 ¬ OrderedEdgesGeometricallyDisjoint e f :=
4120 hNoDisjointN A hA Δ hΔ
4121 simpa [orderedShellMultiplicity_eq_diameterOrderedEdges_card] using
4122 hThrackleN A hA (diameterOrderedEdges A Δ) hEdges hNoDisj
4123
4124/-- Hopf-Pannwitz diameter sparsity follows from the two thrackle components. -/
4125theorem diameter_shell_sparse_from_thrackle_components
4126 (hNoDisjoint : NoDisjointDiameterEdges)
4127 (hThrackle : OrderedThrackleBound) :
4128 DiameterShellSparseBound :=
4129 diameter_shell_sparse_from_ordered_bound
4130 (diameter_ordered_bound_from_thrackle_components hNoDisjoint hThrackle)
4131
4132/-- Diameter shell existence is finite bookkeeping: for all sufficiently large
4133cardinalities, a finite ordered distance spectrum is nonempty and therefore has
4134a maximum. -/
4135theorem diameter_shell_exists_eventually_holds :
4136 DiameterShellExistsEventually := by
4137 unfold DiameterShellExistsEventually
4138 rw [Filter.eventually_atTop]
4139 refine ⟨2, ?_⟩
4140 intro n hn A hA
4141 have hcard : 1 < A.card := by omega
4142 rcases Finset.one_lt_card.mp hcard with ⟨a, ha, b, hb, hne⟩
4143 have hpq : (a, b) ∈ orderedPairEvents A := by
4144 unfold orderedPairEvents
4145 simp [ha, hb, hne]
4146 have hspec_nonempty : (orderedDistanceSpectrum A).Nonempty := by
4147 unfold orderedDistanceSpectrum
4148 exact ⟨dist a b, Finset.mem_image.mpr ⟨(a, b), hpq, rfl⟩⟩
4149 let Δ := (orderedDistanceSpectrum A).max' hspec_nonempty
4150 refine ⟨Δ, ?_⟩
4151 exact ⟨Finset.max'_mem _ _, fun s hs => Finset.le_max' _ s hs⟩
4152
4153/-- Hopf-Pannwitz split into maximum-existence plus diameter sparsity. -/
4154structure HopfPannwitzComponentPack : Prop where
4155 diameter_exists : DiameterShellExistsEventually
4156 diameter_sparse : DiameterShellSparseBound
4157
4158/-- The component version of Hopf-Pannwitz supplies the current bridge. -/
4159theorem hopf_pannwitz_ordered_from_components
4160 (H : HopfPannwitzComponentPack) :
4161 HopfPannwitzOrderedDiameterBound := by
4162 filter_upwards [H.diameter_exists, H.diameter_sparse] with n hExists hSparse
4163 intro A hA
4164 rcases hExists A hA with ⟨Δ, hΔ⟩
4165 exact ⟨Δ, hΔ, hSparse A hA Δ hΔ⟩
4166
4167/-- Since diameter-shell existence is now proved, Hopf-Pannwitz reduces to the
4168diameter-sparsity theorem. -/
4169theorem hopf_pannwitz_ordered_from_diameter_sparsity
4170 (hSparse : DiameterShellSparseBound) :
4171 HopfPannwitzOrderedDiameterBound :=
4172 hopf_pannwitz_ordered_from_components
4173 ⟨diameter_shell_exists_eventually_holds, hSparse⟩
4174
4175theorem erdos132_from_hopf_pannwitz_and_flux
4176 (hHP : HopfPannwitzOrderedDiameterBound)
4177 (hFlux : SecondSparseShellFluxBridge) :
4178 Erdos132Ordered := by
4179 filter_upwards [hHP, hFlux] with n hHPn hFluxn
4180 intro A hA
4181 rcases hHPn A hA with ⟨Δ, hΔdiam, hΔsparse⟩
4182 rcases hFluxn A hA Δ hΔdiam with ⟨r, hr_ne, hr_sparse⟩
4183 exact ⟨Δ, r, hr_ne.symm, hΔsparse, hr_sparse⟩
4184
4185/-! ## Component bridge decomposition from the final reduction plan -/
4186
4187/-- Number of occupied shells in the ordered distance spectrum. -/
4188noncomputable def occupiedShellCount (A : Finset Point2) : ℕ :=
4189 (orderedDistanceSpectrum A).card
4190
4191/-- Total ordered two-body ledger capacity. -/
4192noncomputable def totalOrderedPairBudget (A : Finset Point2) : ℕ :=
4193 (orderedPairEvents A).card
4194
4195/-- The ordered event budget is bounded by all ordered pairs. -/
4196theorem totalOrderedPairBudget_le_all_pairs (A : Finset Point2) :
4197 totalOrderedPairBudget A ≤ A.card * A.card := by
4198 classical
4199 unfold totalOrderedPairBudget orderedPairEvents
4200 calc
4201 (((A.product A).filter (fun pq => pq.1 ≠ pq.2)).card) ≤
4202 (A.product A).card := Finset.card_filter_le _ _
4203 _ = A.card * A.card := by simp
4204
4205/-- A single shell cannot contain more ordered events than the whole ordered
4206pair budget. -/
4207theorem orderedShellMultiplicity_le_budget (A : Finset Point2) (r : ℝ) :
4208 orderedShellMultiplicity A r ≤ totalOrderedPairBudget A := by
4209 classical
4210 unfold orderedShellMultiplicity totalOrderedPairBudget
4211 exact Finset.card_filter_le _ _
4212
4213/-- If a shell lies in the spectrum, then it has positive ordered occupancy. -/
4214theorem orderedShellMultiplicity_pos_of_mem
4215 {A : Finset Point2} {r : ℝ}
4216 (hr : r ∈ orderedDistanceSpectrum A) :
4217 0 < orderedShellMultiplicity A r := by
4218 classical
4219 unfold orderedDistanceSpectrum orderedShellMultiplicity at *
4220 rw [Finset.mem_image] at hr
4221 rcases hr with ⟨pq, hpq, hpq_r⟩
4222 apply Finset.card_pos.mpr
4223 exact ⟨pq, by simp [hpq, hpq_r]⟩
4224
4225/-- An occupied shell that is not sparse is supercritical in the ordered
4226normalization. -/
4227theorem orderedShellMultiplicity_supercritical_of_not_sparse
4228 {A : Finset Point2} {r : ℝ}
4229 (hr : r ∈ orderedDistanceSpectrum A)
4230 (hnot : ¬ SparseShell A r) :
4231 2 * A.card < orderedShellMultiplicity A r := by
4232 classical
4233 unfold SparseShell at hnot
4234 exact Nat.not_le.mp (by intro hle; exact hnot ⟨hr, hle⟩)
4235
4236/-- The distance shells partition the ordered pair-event budget. -/
4237theorem sum_orderedShellMultiplicity_eq_budget (A : Finset Point2) :
4238 (∑ r ∈ orderedDistanceSpectrum A, orderedShellMultiplicity A r) =
4239 totalOrderedPairBudget A := by
4240 classical
4241 let f : Point2 × Point2 → ℝ := fun pq => dist pq.1 pq.2
4242 have hMaps :
4243 Set.MapsTo f ↑(orderedPairEvents A) ↑(orderedDistanceSpectrum A) := by
4244 intro pq hpq
4245 unfold orderedDistanceSpectrum
4246 exact Finset.mem_image.mpr ⟨pq, hpq, rfl⟩
4247 have h :=
4248 Finset.card_eq_sum_card_fiberwise
4249 (s := orderedPairEvents A)
4250 (t := orderedDistanceSpectrum A)
4251 (f := f) hMaps
4252 simpa [orderedShellMultiplicity, totalOrderedPairBudget, f] using h.symm
4253
4254/-- There is a second sparse shell after the diameter shell is removed. -/
4255def ExistsSecondSparseShell (A : Finset Point2) (Δ : ℝ) : Prop :=
4256 ∃ r : ℝ, r ≠ Δ ∧ SparseShell A r
4257
4258/-- A surviving deep-layer case: no non-diameter occupied shell has yet been
4259shown sparse. The later geometry bridge must rule these cases out. -/
4260structure DeepLayerCase (A : Finset Point2) (Δ : ℝ) : Prop where
4261 no_second_sparse :
4262 ∀ r : ℝ, r ∈ orderedDistanceSpectrum A → r ≠ Δ → ¬ SparseShell A r
4263
4264/-- In a deep-layer case, every occupied non-diameter shell is supercritical. -/
4265theorem DeepLayerCase.supercritical
4266 {A : Finset Point2} {Δ r : ℝ}
4267 (h : DeepLayerCase A Δ)
4268 (hr : r ∈ orderedDistanceSpectrum A)
4269 (hr_ne : r ≠ Δ) :
4270 2 * A.card < orderedShellMultiplicity A r :=
4271 orderedShellMultiplicity_supercritical_of_not_sparse hr
4272 (h.no_second_sparse r hr hr_ne)
4273
4274/-- Non-diameter occupied shells in a deep-layer case consume at least
4275`2|A|+1` ordered events each. This is the checked finite-counting pressure
4276behind the low-shell regime in the proof plan. -/
4277theorem non_diameter_shell_count_pressure
4278 {A : Finset Point2} {Δ : ℝ}
4279 (hDeep : DeepLayerCase A Δ) :
4280 (((orderedDistanceSpectrum A).filter (fun r => r ≠ Δ)).card) *
4281 (2 * A.card + 1) ≤ totalOrderedPairBudget A := by
4282 classical
4283 let S := (orderedDistanceSpectrum A).filter (fun r => r ≠ Δ)
4284 have h_each :
4285 ∀ r ∈ S, 2 * A.card + 1 ≤ orderedShellMultiplicity A r := by
4286 intro r hrS
4287 have hr : r ∈ orderedDistanceSpectrum A := by
4288 exact (Finset.mem_filter.mp hrS).1
4289 have hr_ne : r ≠ Δ := by
4290 exact (Finset.mem_filter.mp hrS).2
4291 exact Nat.succ_le_of_lt (hDeep.supercritical hr hr_ne)
4292 calc
4293 S.card * (2 * A.card + 1)
4294 = ∑ r ∈ S, (2 * A.card + 1) := by
4295 simp [Finset.sum_const]
4296 _ ≤ ∑ r ∈ S, orderedShellMultiplicity A r := by
4297 exact Finset.sum_le_sum h_each
4298 _ ≤ ∑ r ∈ orderedDistanceSpectrum A, orderedShellMultiplicity A r := by
4299 exact Finset.sum_le_sum_of_subset_of_nonneg
4300 (by
4301 intro r hr
4302 exact (Finset.mem_filter.mp hr).1)
4303 (by
4304 intro r _ _
4305 exact Nat.zero_le _)
4306 _ = totalOrderedPairBudget A := sum_orderedShellMultiplicity_eq_budget A
4307
4308/-- Arithmetic core of pair-budget pressure: if `k` classes each consume at
4309least `2n+1` ordered events inside an `n^2` budget, then `k ≤ n/2`. -/
4310theorem shell_pressure_arithmetic
4311 (k n : ℕ) (h : k * (2 * n + 1) ≤ n * n) :
4312 k ≤ n / 2 := by
4313 by_cases hn : n = 0
4314 · subst hn
4315 simp at h
4316 exact le_of_eq h
4317 by_contra hknot
4318 have hkgt : n / 2 < k := Nat.lt_of_not_ge hknot
4319 have hkle : n / 2 + 1 ≤ k := Nat.succ_le_of_lt hkgt
4320 have hpos : 0 < n := Nat.pos_of_ne_zero hn
4321 have hlt2 : n < 2 * (n / 2 + 1) := by omega
4322 have hltmul : n * n < (2 * (n / 2 + 1)) * n := by
4323 exact Nat.mul_lt_mul_of_pos_right hlt2 hpos
4324 have hle_rearr :
4325 (2 * (n / 2 + 1)) * n ≤ (n / 2 + 1) * (2 * n + 1) := by
4326 nlinarith
4327 have hstrict : n * n < (n / 2 + 1) * (2 * n + 1) :=
4328 lt_of_lt_of_le hltmul hle_rearr
4329 have hle2 :
4330 (n / 2 + 1) * (2 * n + 1) ≤ k * (2 * n + 1) :=
4331 Nat.mul_le_mul_right _ hkle
4332 have hcontr : n * n < k * (2 * n + 1) := lt_of_lt_of_le hstrict hle2
4333 exact (not_lt_of_ge h) hcontr
4334
4335/-- If the diameter shell is occupied, the occupied shell count is at most the
4336number of non-diameter shells plus one. -/
4337theorem occupiedShellCount_le_nonDiameter_add_one
4338 {A : Finset Point2} {Δ : ℝ}
4339 (hΔmem : Δ ∈ orderedDistanceSpectrum A) :
4340 occupiedShellCount A ≤
4341 ((orderedDistanceSpectrum A).filter (fun r => r ≠ Δ)).card + 1 := by
4342 classical
4343 unfold occupiedShellCount
4344 have hEq :
4345 ((orderedDistanceSpectrum A).filter (fun r => r ≠ Δ)).card + 1 =
4346 (orderedDistanceSpectrum A).card := by
4347 rw [Finset.filter_ne']
4348 exact Finset.card_erase_add_one hΔmem
4349 omega
4350
4351/-- Pair-budget pressure: if no second sparse shell has been found, then the
4352number of occupied shells is forced into the low-shell regime. -/
4353structure PairBudgetPressure (A : Finset Point2) (Δ : ℝ) : Prop where
4354 few_shells_if_deep :
4355 DeepLayerCase A Δ → occupiedShellCount A ≤ A.card / 2 + 2
4356
4357/-- The pair-budget component of the final plan is pure finite accounting:
4358in a deep-layer residual case, all non-diameter shells are supercritical, so
4359there can be at most `|A|/2` of them, and hence at most `|A|/2 + 1` occupied
4360shells. -/
4361theorem pair_budget_pressure_from_counting
4362 (A : Finset Point2) (Δ : ℝ)
4363 (hΔ : IsDiameterShell A Δ) :
4364 PairBudgetPressure A Δ where
4365 few_shells_if_deep := by
4366 intro hDeep
4367 let S := (orderedDistanceSpectrum A).filter (fun r => r ≠ Δ)
4368 have hPressure :
4369 S.card * (2 * A.card + 1) ≤ totalOrderedPairBudget A := by
4370 simpa [S] using non_diameter_shell_count_pressure (A := A) (Δ := Δ) hDeep
4371 have hBudget : totalOrderedPairBudget A ≤ A.card * A.card :=
4372 totalOrderedPairBudget_le_all_pairs A
4373 have hCombined : S.card * (2 * A.card + 1) ≤ A.card * A.card :=
4374 le_trans hPressure hBudget
4375 have hS : S.card ≤ A.card / 2 :=
4376 shell_pressure_arithmetic S.card A.card hCombined
4377 have hOcc :
4378 occupiedShellCount A ≤ S.card + 1 := by
4379 simpa [S] using occupiedShellCount_le_nonDiameter_add_one
4380 (A := A) (Δ := Δ) hΔ.1
4381 omega
4382
4383/-- Low-shell structure: the configuration has entered the small radial
4384spectrum regime where convex-layer analysis must take over. -/
4385structure LowShellStructure (A : Finset Point2) (Δ : ℝ) : Prop where
4386 few_shells : occupiedShellCount A ≤ A.card / 2 + 2
4387
4388/-- Layer-flux alternative: once in the low-shell regime, either the desired
4389second sparse shell is present, or the only remaining obstruction is a
4390deep-layer case. -/
4391structure LayerFluxAlternative (A : Finset Point2) (Δ : ℝ) : Prop where
4392 exits_or_deep : ExistsSecondSparseShell A Δ ∨ DeepLayerCase A Δ
4393
4394/-- The layer-flux alternative is a tautological split at the level of the
4395current definitions: either a second sparse shell exists, or we are in the
4396residual deep-layer case. The hard geometry is therefore not this split, but
4397screening the residual case. -/
4398theorem layer_flux_alternative_of_definitions
4399 (A : Finset Point2) (Δ : ℝ) :
4400 LayerFluxAlternative A Δ := by
4401 classical
4402 by_cases h : ExistsSecondSparseShell A Δ
4403 · exact ⟨Or.inl h⟩
4404 · refine ⟨Or.inr ?_⟩
4405 refine ⟨?_⟩
4406 intro r hr hr_ne hsparse
4407 exact h ⟨r, hr_ne, hsparse⟩
4408
4409/-- Deep-layer screening: the residual deep-layer cases cannot persist. -/
4410structure DeepLayerScreening (A : Finset Point2) (Δ : ℝ) : Prop where
4411 screen : DeepLayerCase A Δ → ExistsSecondSparseShell A Δ
4412
4413/-- The component package specified by the proof plan. Each field is a
4414standalone classical bridge target; together they close the shell-flux bridge.
4415-/
4416structure ShellFluxComponentPack : Prop where
4417 pair_budget_pressure :
4418 ∀ᶠ n in atTop,
4419 ∀ A : Finset Point2,
4420 A.card = n →
4421 ∀ Δ : ℝ, IsDiameterShell A Δ → PairBudgetPressure A Δ
4422 low_shell_structure :
4423 ∀ᶠ n in atTop,
4424 ∀ A : Finset Point2,
4425 A.card = n →
4426 ∀ Δ : ℝ,
4427 IsDiameterShell A Δ →
4428 PairBudgetPressure A Δ → LowShellStructure A Δ
4429 layer_flux_alternative :
4430 ∀ᶠ n in atTop,
4431 ∀ A : Finset Point2,
4432 A.card = n →
4433 ∀ Δ : ℝ,
4434 IsDiameterShell A Δ →
4435 LowShellStructure A Δ → LayerFluxAlternative A Δ
4436 deep_layer_screening :
4437 ∀ᶠ n in atTop,
4438 ∀ A : Finset Point2,
4439 A.card = n →
4440 ∀ Δ : ℝ,
4441 IsDiameterShell A Δ →
4442 LowShellStructure A Δ → DeepLayerScreening A Δ
4443
4444/-- Reduced component package after observing that `LayerFluxAlternative` is
4445just the definitional split "exit or residual case". This is the sharper
4446implementation target for the remaining proof. -/
4447structure ShellFluxReducedComponentPack : Prop where
4448 low_shell_structure :
4449 ∀ᶠ n in atTop,
4450 ∀ A : Finset Point2,
4451 A.card = n →
4452 ∀ Δ : ℝ,
4453 IsDiameterShell A Δ →
4454 PairBudgetPressure A Δ → LowShellStructure A Δ
4455 deep_layer_screening :
4456 ∀ᶠ n in atTop,
4457 ∀ A : Finset Point2,
4458 A.card = n →
4459 ∀ Δ : ℝ,
4460 IsDiameterShell A Δ →
4461 LowShellStructure A Δ → DeepLayerScreening A Δ
4462
4463/-- The reduced package supplies the full component package by the definitional
4464layer-flux split. -/
4465theorem shell_flux_component_pack_of_reduced
4466 (C : ShellFluxReducedComponentPack) :
4467 ShellFluxComponentPack where
4468 pair_budget_pressure := by
4469 filter_upwards with n
4470 intro A _ Δ hΔ
4471 exact pair_budget_pressure_from_counting A Δ hΔ
4472 low_shell_structure := C.low_shell_structure
4473 layer_flux_alternative := by
4474 filter_upwards with n
4475 intro A _ Δ _ _
4476 exact layer_flux_alternative_of_definitions A Δ
4477 deep_layer_screening := C.deep_layer_screening
4478
4479/-- The component package closes the missing shell-flux bridge. -/
4480theorem second_sparse_shell_flux_bridge_from_components
4481 (C : ShellFluxComponentPack) :
4482 SecondSparseShellFluxBridge := by
4483 filter_upwards
4484 [C.pair_budget_pressure,
4485 C.low_shell_structure,
4486 C.layer_flux_alternative,
4487 C.deep_layer_screening]
4488 with n hBudget hLow hLayer hScreen
4489 intro A hA Δ hΔ
4490 have hBudgetA : PairBudgetPressure A Δ := hBudget A hA Δ hΔ
4491 have hLowA : LowShellStructure A Δ := hLow A hA Δ hΔ hBudgetA
4492 have hLayerA : LayerFluxAlternative A Δ := hLayer A hA Δ hΔ hLowA
4493 have hScreenA : DeepLayerScreening A Δ := hScreen A hA Δ hΔ hLowA
4494 rcases hLayerA.exits_or_deep with hExit | hDeep
4495 · exact hExit
4496 · exact hScreenA.screen hDeep
4497
4498/-- Hopf-Pannwitz plus the component package proves the ordered form of
4499Erdős #132. This is the executable proof graph from the HTML plan. -/
4500theorem erdos132_from_hopf_pannwitz_and_components
4501 (hHP : HopfPannwitzOrderedDiameterBound)
4502 (C : ShellFluxComponentPack) :
4503 Erdos132Ordered :=
4504 erdos132_from_hopf_pannwitz_and_flux hHP
4505 (second_sparse_shell_flux_bridge_from_components C)
4506
4507/-- Final assembly from the sharper reduced component package. -/
4508theorem erdos132_from_hopf_pannwitz_and_reduced_components
4509 (hHP : HopfPannwitzOrderedDiameterBound)
4510 (C : ShellFluxReducedComponentPack) :
4511 Erdos132Ordered :=
4512 erdos132_from_hopf_pannwitz_and_components hHP
4513 (shell_flux_component_pack_of_reduced C)
4514
4515/-- Minimal remaining geometry package after implementing the finite
4516pair-budget pressure. The only nontrivial geometric work left is screening
4517the residual deep-layer case once its low-shell bound has been obtained from
4518finite counting. -/
4519structure ShellFluxMinimalGeometryPack : Prop where
4520 deep_layer_screening :
4521 ∀ᶠ n in atTop,
4522 ∀ A : Finset Point2,
4523 A.card = n →
4524 ∀ Δ : ℝ,
4525 IsDiameterShell A Δ →
4526 LowShellStructure A Δ → DeepLayerScreening A Δ
4527
4528/-- Exact final contradiction target: in the low-shell regime, the residual
4529deep-layer case cannot occur. This is the sharp geometric theorem left by the
4530finite accounting reductions. -/
4531def NoDeepLayerCaseInLowShellRegime : Prop :=
4532 ∀ᶠ n in atTop,
4533 ∀ A : Finset Point2,
4534 A.card = n →
4535 ∀ Δ : ℝ,
4536 IsDiameterShell A Δ →
4537 LowShellStructure A Δ →
4538 ¬ DeepLayerCase A Δ
4539
4540/-- Pointwise form of the low-shell no-deep-layer theorem. The Erdős #132
4541target only needs the eventual version, but this is the cleaner classical
4542geometric statement when small finite exceptions are not needed. -/
4543def PointwiseNoDeepLayerCaseInLowShellRegime : Prop :=
4544 ∀ A : Finset Point2,
4545 ∀ Δ : ℝ,
4546 IsDiameterShell A Δ →
4547 LowShellStructure A Δ →
4548 ¬ DeepLayerCase A Δ
4549
4550/-- Pointwise positive screening form of the layer residual. This matches the
4551proof plan's Deep-Layer Screening Lemma: under the low-shell hypotheses, any
4552residual deep-layer case produces the missing second sparse shell. -/
4553def PointwiseDeepLayerScreeningCertificate : Prop :=
4554 ∀ A : Finset Point2,
4555 ∀ Δ : ℝ,
4556 IsDiameterShell A Δ →
4557 LowShellStructure A Δ →
4558 DeepLayerScreening A Δ
4559
4560/-- Positive deep-layer screening rules out the residual deep-layer case,
4561because `DeepLayerCase` definitionally says no second sparse shell exists. -/
4562theorem pointwise_no_deep_layer_from_screening_certificate
4563 (hScreen : PointwiseDeepLayerScreeningCertificate) :
4564 PointwiseNoDeepLayerCaseInLowShellRegime := by
4565 intro A Δ hΔ hLow hDeep
4566 rcases (hScreen A Δ hΔ hLow).screen hDeep with ⟨r, hr_ne, hsparse⟩
4567 exact hDeep.no_second_sparse r hsparse.1 hr_ne hsparse
4568
4569/-- Conversely, pointwise no-deep-layer contradiction supplies the positive
4570screening certificate, by contradiction. Hence the residual can be stated in
4571either positive or negative form without changing mathematical content. -/
4572theorem pointwise_screening_certificate_from_no_deep_layer
4573 (hNoDeep : PointwiseNoDeepLayerCaseInLowShellRegime) :
4574 PointwiseDeepLayerScreeningCertificate := by
4575 intro A Δ hΔ hLow
4576 refine ⟨?_⟩
4577 intro hDeep
4578 exact False.elim (hNoDeep A Δ hΔ hLow hDeep)
4579
4580/-- The pointwise positive and negative layer residuals are equivalent. -/
4581theorem pointwise_deep_layer_screening_iff_no_deep_layer :
4582 PointwiseDeepLayerScreeningCertificate ↔
4583 PointwiseNoDeepLayerCaseInLowShellRegime :=
4584 ⟨pointwise_no_deep_layer_from_screening_certificate,
4585 pointwise_screening_certificate_from_no_deep_layer⟩
4586
4587/-- The pointwise no-deep-layer theorem implies the eventual theorem used in the
4588Erdős #132 assembly. -/
4589theorem no_deep_layer_from_pointwise
4590 (h : PointwiseNoDeepLayerCaseInLowShellRegime) :
4591 NoDeepLayerCaseInLowShellRegime := by
4592 filter_upwards with n
4593 intro A _hA Δ hΔ hLow
4594 exact h A Δ hΔ hLow
4595
4596/-- Pointwise positive screening supplies the eventual no-deep theorem used by
4597the Erdős #132 assembly. -/
4598theorem no_deep_layer_from_pointwise_screening_certificate
4599 (hScreen : PointwiseDeepLayerScreeningCertificate) :
4600 NoDeepLayerCaseInLowShellRegime :=
4601 no_deep_layer_from_pointwise
4602 (pointwise_no_deep_layer_from_screening_certificate hScreen)
4603
4604/-- Abstract first/second convex-layer package for a finite planar set. This
4605is intentionally structural: the detailed geometric construction of layers can
4606be supplied later, while the final shell-flux proof already knows exactly what
4607properties it needs. -/
4608structure ConvexLayerData (A : Finset Point2) where
4609 L1 : Finset Point2
4610 L2 : Finset Point2
4611 L1_subset : L1 ⊆ A
4612 L2_subset : L2 ⊆ A
4613
4614/-- A layer package is strong enough to screen the residual deep-layer case for
4615one chosen diameter shell. This is the local form of the Clemen-Dumitrescu-Liu
4616style convex-layer bridge in the plan. -/
4617def ConvexLayerScreensDeepCase
4618 (A : Finset Point2) (Δ : ℝ) (_L : ConvexLayerData A) : Prop :=
4619 LowShellStructure A Δ → ¬ DeepLayerCase A Δ
4620
4621/-- Global convex-layer screening theorem: every sufficiently large finite set
4622admits first/second layer data that screens the low-shell residual deep-layer
4623case. This is the exact remaining layer-flux theorem named by the plan. -/
4624def ConvexLayerScreeningBridge : Prop :=
4625 ∀ᶠ n in atTop,
4626 ∀ A : Finset Point2,
4627 A.card = n →
4628 ∀ Δ : ℝ,
4629 IsDiameterShell A Δ →
4630 ∃ L : ConvexLayerData A, ConvexLayerScreensDeepCase A Δ L
4631
4632/-- Thresholded form of convex-layer screening. This is the most concrete
4633statement of the remaining layer theorem: exhibit a finite `N` such that every
4634configuration with at least `N` points has first/second layer data screening the
4635low-shell residual deep-layer case. -/
4636def ConvexLayerScreeningThresholdCertificate : Prop :=
4637 ∃ N : ℕ,
4638 ∀ A : Finset Point2,
4639 N ≤ A.card →
4640 ∀ Δ : ℝ,
4641 IsDiameterShell A Δ →
4642 ∃ L : ConvexLayerData A, ConvexLayerScreensDeepCase A Δ L
4643
4644/-- A thresholded convex-layer certificate gives the eventual bridge. -/
4645theorem convex_layer_screening_from_threshold
4646 (h : ConvexLayerScreeningThresholdCertificate) :
4647 ConvexLayerScreeningBridge := by
4648 rcases h with ⟨N, hN⟩
4649 unfold ConvexLayerScreeningBridge
4650 rw [Filter.eventually_atTop]
4651 refine ⟨N, ?_⟩
4652 intro n hn A hA Δ hΔ
4653 exact hN A (by rw [hA]; exact hn) Δ hΔ
4654
4655/-- Conversely, the eventual bridge supplies some threshold. -/
4656theorem convex_layer_screening_threshold_from_bridge
4657 (h : ConvexLayerScreeningBridge) :
4658 ConvexLayerScreeningThresholdCertificate := by
4659 unfold ConvexLayerScreeningBridge at h
4660 rw [Filter.eventually_atTop] at h
4661 rcases h with ⟨N, hN⟩
4662 refine ⟨N, ?_⟩
4663 intro A hA Δ hΔ
4664 exact hN A.card hA A rfl Δ hΔ
4665
4666/-- The eventual and thresholded convex-layer formulations are equivalent. -/
4667theorem convex_layer_screening_iff_threshold :
4668 ConvexLayerScreeningBridge ↔ ConvexLayerScreeningThresholdCertificate :=
4669 ⟨convex_layer_screening_threshold_from_bridge,
4670 convex_layer_screening_from_threshold⟩
4671
4672/-- The convex-layer screening bridge implies the no-deep-layer target. -/
4673theorem no_deep_layer_from_convex_layer_screening
4674 (hLayer : ConvexLayerScreeningBridge) :
4675 NoDeepLayerCaseInLowShellRegime := by
4676 filter_upwards [hLayer] with n hLayerN
4677 intro A hA Δ hΔ hLow
4678 rcases hLayerN A hA Δ hΔ with ⟨L, hScreen⟩
4679 exact hScreen hLow
4680
4681/-- Conversely, the no-deep-layer target supplies the current structural
4682convex-layer bridge. The `ConvexLayerData` fields are only bookkeeping here;
4683the mathematical content is exactly `NoDeepLayerCaseInLowShellRegime`. This
4684keeps the final residual honest: the remaining layer theorem is the
4685low-shell/no-deep contradiction itself, not the choice of layer containers. -/
4686theorem convex_layer_screening_from_no_deep_layer
4687 (hNoDeep : NoDeepLayerCaseInLowShellRegime) :
4688 ConvexLayerScreeningBridge := by
4689 filter_upwards [hNoDeep] with n hNoDeepN
4690 intro A hA Δ hΔ
4691 refine ⟨{ L1 := ∅, L2 := ∅, L1_subset := ?_, L2_subset := ?_ }, ?_⟩
4692 · intro x hx
4693 simp at hx
4694 · intro x hx
4695 simp at hx
4696 · intro hLow hDeep
4697 exact hNoDeepN A hA Δ hΔ hLow hDeep
4698
4699/-- The structural convex-layer bridge is equivalent to the sharper low-shell
4700no-deep-layer target. -/
4701theorem convex_layer_screening_iff_no_deep_layer :
4702 ConvexLayerScreeningBridge ↔ NoDeepLayerCaseInLowShellRegime :=
4703 ⟨no_deep_layer_from_convex_layer_screening,
4704 convex_layer_screening_from_no_deep_layer⟩
4705
4706/-- The no-deep-layer contradiction target is exactly enough to screen the
4707residual case. -/
4708theorem minimal_geometry_pack_of_no_deep_layer
4709 (hNoDeep : NoDeepLayerCaseInLowShellRegime) :
4710 ShellFluxMinimalGeometryPack where
4711 deep_layer_screening := by
4712 filter_upwards [hNoDeep] with n hNoDeepN
4713 intro A hA Δ hΔ hLow
4714 refine ⟨?_⟩
4715 intro hDeep
4716 exact False.elim (hNoDeepN A hA Δ hΔ hLow hDeep)
4717
4718/-- The minimal geometry package closes the shell-flux bridge. The proof
4719splits definitionally into "a second sparse shell already exists" or "we are
4720in the residual deep-layer case"; in the residual case, finite pair-budget
4721pressure supplies the low-shell hypothesis needed by screening. -/
4722theorem second_sparse_shell_flux_bridge_from_minimal_geometry
4723 (G : ShellFluxMinimalGeometryPack) :
4724 SecondSparseShellFluxBridge := by
4725 filter_upwards [G.deep_layer_screening] with n hScreen
4726 intro A hA Δ hΔ
4727 by_cases hExit : ExistsSecondSparseShell A Δ
4728 · exact hExit
4729 · have hDeep : DeepLayerCase A Δ := by
4730 refine ⟨?_⟩
4731 intro r hr hr_ne hsparse
4732 exact hExit ⟨r, hr_ne, hsparse⟩
4733 have hBudget : PairBudgetPressure A Δ :=
4734 pair_budget_pressure_from_counting A Δ hΔ
4735 have hLow : LowShellStructure A Δ :=
4736 ⟨PairBudgetPressure.few_shells_if_deep hBudget hDeep⟩
4737 have hScreenA : DeepLayerScreening A Δ := hScreen A hA Δ hΔ hLow
4738 exact hScreenA.screen hDeep
4739
4740/-- Hopf-Pannwitz plus the single remaining deep-layer screening bridge proves
4741Erdős #132 in ordered-pair normalization. -/
4742theorem erdos132_from_hopf_pannwitz_and_minimal_geometry
4743 (hHP : HopfPannwitzOrderedDiameterBound)
4744 (G : ShellFluxMinimalGeometryPack) :
4745 Erdos132Ordered :=
4746 erdos132_from_hopf_pannwitz_and_flux hHP
4747 (second_sparse_shell_flux_bridge_from_minimal_geometry G)
4748
4749/-- Hopf-Pannwitz plus the exact no-deep-layer theorem proves Erdős #132.
4750This is the current sharp final assembly theorem: all finite counting has been
4751implemented, so the only remaining input is the geometric impossibility of the
4752low-shell residual case. -/
4753theorem erdos132_from_hopf_pannwitz_and_no_deep_layer
4754 (hHP : HopfPannwitzOrderedDiameterBound)
4755 (hNoDeep : NoDeepLayerCaseInLowShellRegime) :
4756 Erdos132Ordered :=
4757 erdos132_from_hopf_pannwitz_and_minimal_geometry hHP
4758 (minimal_geometry_pack_of_no_deep_layer hNoDeep)
4759
4760/-- Fully reduced final assembly theorem after implementing the proof-plan
4761bookkeeping. The remaining classical geometry inputs are exactly:
4762
47631. diameter shell existence,
47642. Hopf-Pannwitz diameter sparsity,
47653. no residual deep-layer case in the low-shell regime.
4766-/
4767theorem erdos132_from_final_components
4768 (H : HopfPannwitzComponentPack)
4769 (hNoDeep : NoDeepLayerCaseInLowShellRegime) :
4770 Erdos132Ordered :=
4771 erdos132_from_hopf_pannwitz_and_no_deep_layer
4772 (hopf_pannwitz_ordered_from_components H)
4773 hNoDeep
4774
4775/-- Diameter-sparsity assembly: diameter existence and finite bookkeeping are
4776proved, so this conditional theorem packages the older Hopf-Pannwitz sparsity
4777surface with the low-shell no-deep theorem. The current live endpoint is
4778`Erdos132CurrentLiveResidual`. -/
4779theorem erdos132_from_diameter_sparsity_and_no_deep_layer
4780 (hSparse : DiameterShellSparseBound)
4781 (hNoDeep : NoDeepLayerCaseInLowShellRegime) :
4782 Erdos132Ordered :=
4783 erdos132_from_hopf_pannwitz_and_no_deep_layer
4784 (hopf_pannwitz_ordered_from_diameter_sparsity hSparse)
4785 hNoDeep
4786
4787/-- Final assembly from the thrackle-level Hopf-Pannwitz components plus the
4788low-shell no-deep-layer theorem. -/
4789theorem erdos132_from_thrackle_and_no_deep_layer
4790 (hNoDisjoint : NoDisjointDiameterEdges)
4791 (hThrackle : OrderedThrackleBound)
4792 (hNoDeep : NoDeepLayerCaseInLowShellRegime) :
4793 Erdos132Ordered :=
4794 erdos132_from_diameter_sparsity_and_no_deep_layer
4795 (diameter_shell_sparse_from_thrackle_components hNoDisjoint hThrackle)
4796 hNoDeep
4797
4798/-- Legacy assembly from the older set-theoretic undirected thrackle
4799decomposition. This is kept as a conditional theorem, but the predicate
4800`UndirectedThrackleSupportBound` is too strong for arbitrary collinear edge
4801systems. Use the live Conway endpoint
4802`erdos132_from_ordered_conway_convex_layer_residual_pack` for the corrected
4803proof graph. -/
4804theorem erdos132_from_undirected_thrackle_and_no_deep_layer
4805 (hNoDisjoint : NoDisjointDiameterEdges)
4806 (hSupport : UndirectedThrackleSupportBound)
4807 (hOrient : OrderedOrientationFiberBound)
4808 (hNoDeep : NoDeepLayerCaseInLowShellRegime) :
4809 Erdos132Ordered :=
4810 erdos132_from_thrackle_and_no_deep_layer hNoDisjoint
4811 (ordered_thrackle_bound_from_undirected_support hSupport hOrient)
4812 hNoDeep
4813
4814/-- Legacy assembly through the deprecated set-theoretic undirected support
4815bound. Orientation bookkeeping is proved, but the support predicate is not the
4816correct Conway thrackle theorem. -/
4817theorem erdos132_from_undirected_thrackle_support_and_no_deep_layer
4818 (hNoDisjoint : NoDisjointDiameterEdges)
4819 (hSupport : UndirectedThrackleSupportBound)
4820 (hNoDeep : NoDeepLayerCaseInLowShellRegime) :
4821 Erdos132Ordered :=
4822 erdos132_from_thrackle_and_no_deep_layer hNoDisjoint
4823 (ordered_thrackle_bound_from_undirected_support_only hSupport)
4824 hNoDeep
4825
4826/-- Legacy assembly through local diameter meeting and the deprecated
4827set-theoretic undirected support bound. -/
4828theorem erdos132_from_local_diameter_meeting_thrackle_and_no_deep_layer
4829 (hMeet : DiameterSegmentsMeetLocally)
4830 (hSupport : UndirectedThrackleSupportBound)
4831 (hNoDeep : NoDeepLayerCaseInLowShellRegime) :
4832 Erdos132Ordered :=
4833 erdos132_from_undirected_thrackle_support_and_no_deep_layer
4834 (no_disjoint_diameter_edges_from_local_meeting hMeet)
4835 hSupport
4836 hNoDeep
4837
4838/-- Legacy assembly from the endpoint-disjoint local diameter geometry core and
4839the deprecated set-theoretic undirected support bound. -/
4840theorem erdos132_from_endpoint_disjoint_diameter_core_thrackle_and_no_deep_layer
4841 (hCore : EndpointDisjointDiameterSegmentsMeetLocally)
4842 (hSupport : UndirectedThrackleSupportBound)
4843 (hNoDeep : NoDeepLayerCaseInLowShellRegime) :
4844 Erdos132Ordered :=
4845 erdos132_from_local_diameter_meeting_thrackle_and_no_deep_layer
4846 (diameter_segments_meet_from_endpoint_disjoint_core hCore)
4847 hSupport
4848 hNoDeep
4849
4850/-- Legacy four-point assembly through the deprecated set-theoretic undirected
4851support bound. The four-point diameter geometry is live and proved; the
4852correct counting input is the Conway theorem used in the final endpoint below. -/
4853theorem erdos132_from_four_point_thrackle_and_no_deep_layer
4854 (h4 : FourPointDiameterCrossing)
4855 (hSupport : UndirectedThrackleSupportBound)
4856 (hNoDeep : NoDeepLayerCaseInLowShellRegime) :
4857 Erdos132Ordered :=
4858 erdos132_from_endpoint_disjoint_diameter_core_thrackle_and_no_deep_layer
4859 (endpoint_disjoint_local_meeting_from_four_point h4)
4860 hSupport
4861 hNoDeep
4862
4863/-- Legacy plan-language assembly before the Conway correction. It uses
4864`UndirectedThrackleSupportBound`, which permits overlapping collinear segments
4865and is not the correct global counting theorem. -/
4866theorem erdos132_from_four_point_thrackle_and_convex_layer_screening
4867 (h4 : FourPointDiameterCrossing)
4868 (hSupport : UndirectedThrackleSupportBound)
4869 (hLayer : ConvexLayerScreeningBridge) :
4870 Erdos132Ordered :=
4871 erdos132_from_four_point_thrackle_and_no_deep_layer h4 hSupport
4872 (no_deep_layer_from_convex_layer_screening hLayer)
4873
4874/-- Final assembly from the separated-segment bridge decomposition, undirected
4875thrackle support, and convex-layer screening. -/
4876theorem erdos132_from_separation_thrackle_and_convex_layer_screening
4877 (hSep : DisjointSegmentsHaveSeparation)
4878 (hProper : ProperSeparatedDiameterContradiction)
4879 (hCollinear : CollinearSeparatedDiameterContradiction)
4880 (hSupport : UndirectedThrackleSupportBound)
4881 (hLayer : ConvexLayerScreeningBridge) :
4882 Erdos132Ordered :=
4883 erdos132_from_four_point_thrackle_and_convex_layer_screening
4884 (four_point_diameter_crossing_from_separation_bridges hSep hProper hCollinear)
4885 hSupport
4886 hLayer
4887
4888/-- Final assembly using the unified separated-diameter contradiction. -/
4889theorem erdos132_from_unified_separation_thrackle_and_convex_layer_screening
4890 (hSep : DisjointSegmentsHaveSeparation)
4891 (hContr : SeparatedDiameterContradiction)
4892 (hSupport : UndirectedThrackleSupportBound)
4893 (hLayer : ConvexLayerScreeningBridge) :
4894 Erdos132Ordered :=
4895 erdos132_from_four_point_thrackle_and_convex_layer_screening
4896 (four_point_diameter_crossing_from_separated_diameter hSep hContr)
4897 hSupport
4898 hLayer
4899
4900/-- **Reduced assembly.** Because `CollinearSeparatedDiameterContradiction`
4901is now a Lean theorem (`collinearSeparatedDiameterContradiction`), the
4902collinear case is discharged automatically. Erdős #132 follows from just the
4903proper separated-diameter contradiction together with the segment-separation
4904case split, the undirected thrackle support bound, and convex-layer
4905screening. -/
4906theorem erdos132_from_proper_separation_thrackle_and_convex_layer_screening
4907 (hSep : DisjointSegmentsHaveSeparation)
4908 (hProper : ProperSeparatedDiameterContradiction)
4909 (hSupport : UndirectedThrackleSupportBound)
4910 (hLayer : ConvexLayerScreeningBridge) :
4911 Erdos132Ordered :=
4912 erdos132_from_separation_thrackle_and_convex_layer_screening
4913 hSep hProper collinearSeparatedDiameterContradiction
4914 hSupport hLayer
4915
4916/-- **Further-reduced assembly.** Because both
4917`CollinearSeparatedDiameterContradiction` and
4918`ProperSeparatedDiameterContradiction` are now Lean theorems
4919(`collinearSeparatedDiameterContradiction`,
4920`properSeparatedDiameterContradiction`), the four-point Hopf-Pannwitz lemma is
4921fully discharged. Erdős #132 follows from just the segment-separation case
4922split, undirected thrackle support, and convex-layer screening. -/
4923theorem erdos132_from_separation_thrackle_layer
4924 (hSep : DisjointSegmentsHaveSeparation)
4925 (hSupport : UndirectedThrackleSupportBound)
4926 (hLayer : ConvexLayerScreeningBridge) :
4927 Erdos132Ordered :=
4928 erdos132_from_proper_separation_thrackle_and_convex_layer_screening
4929 hSep properSeparatedDiameterContradiction hSupport hLayer
4930
4931/-- If `c` lies on the line through `a` and `b` and is in the closed lens
4932`D(a, Δ) ∩ D(b, Δ)` with `dist a b = Δ`, then `c` is on the closed segment
4933from `a` to `b`. -/
4934theorem onClosedSegment_of_orient2_zero_in_lens
4935 {a b c : Point2} {Δ : ℝ} (hΔ_pos : 0 < Δ)
4936 (hab : dist a b = Δ)
4937 (hac : dist a c ≤ Δ) (hbc : dist b c ≤ Δ)
4938 (h_orient : orient2 a b c = 0) :
4939 OnClosedSegment a b c := by
4940 have h_ab : a ≠ b := by
4941 intro he
4942 rw [he, dist_self] at hab
4943 linarith
4944 obtain ⟨t, ht⟩ := exists_scalar_of_orient2_zero h_ab h_orient
4945 have hac_eq : dist a c = |t| * Δ := by
4946 have := dist_from_diff_eq_smul ht
4947 rw [hab] at this
4948 exact this
4949 have hbc_param : ∀ i : Fin 2, c i - b i = (t - 1) * (b i - a i) := by
4950 intro i
4951 have := ht i
4952 linarith
4953 have hbc_eq : dist b c = |t - 1| * Δ := by
4954 have := dist_from_diff_eq_smul hbc_param
4955 rw [hab] at this
4956 exact this
4957 have habst : |t| ≤ 1 := by
4958 have h1 : |t| * Δ ≤ 1 * Δ := by
4959 rw [one_mul]
4960 linarith [hac_eq ▸ hac]
4961 exact le_of_mul_le_mul_right h1 hΔ_pos
4962 have habs1mt : |t - 1| ≤ 1 := by
4963 have h1 : |t - 1| * Δ ≤ 1 * Δ := by
4964 rw [one_mul]
4965 linarith [hbc_eq ▸ hbc]
4966 exact le_of_mul_le_mul_right h1 hΔ_pos
4967 have ht_le1 : t ≤ 1 := (abs_le.mp habst).2
4968 have hneg1mt : -(1:ℝ) ≤ t - 1 := (abs_le.mp habs1mt).1
4969 have ht_nn : 0 ≤ t := by linarith
4970 refine ⟨t, ht_nn, ht_le1, ?_⟩
4971 ext i
4972 have h := ht i
4973 show c i = ((1 - t) • a + t • b) i
4974 simp only [PiLp.add_apply, PiLp.smul_apply, smul_eq_mul]
4975 linarith
4976
4977/-- If `c` lies on line `ab` and is in the diameter lens, then the segment
4978`[a,b]` meets `[c,d]` at `c`. -/
4979theorem segments_meet_of_orient2_zero
4980 {a b c d : Point2} {Δ : ℝ} (hΔ_pos : 0 < Δ)
4981 (hab : dist a b = Δ)
4982 (hac : dist a c ≤ Δ) (hbc : dist b c ≤ Δ)
4983 (h_orient : orient2 a b c = 0) :
4984 OrderedEdgesMeetGeometrically (a, b) (c, d) := by
4985 refine ⟨c, ?_, left_endpoint_on_segment c d⟩
4986 exact onClosedSegment_of_orient2_zero_in_lens hΔ_pos hab hac hbc h_orient
4987
4988/-- Two distinct diameter representatives sharing their left endpoint meet
4989simply at that endpoint. A second intersection point would force the two
4990other endpoints to lie on the same diameter segment, hence coincide. -/
4991theorem shared_left_diameter_representatives_meet_simply
4992 {a b c : Point2} {Δ : ℝ}
4993 (hUne : unorderedEdgeOfOrdered (a, b) ≠ unorderedEdgeOfOrdered (a, c))
4994 (hab : dist a b = Δ) (hac : dist a c = Δ) (hbc : dist b c ≤ Δ) :
4995 OrderedEdgesMeetSimply (a, b) (a, c) := by
4996 have h_ab : a ≠ b := by
4997 intro h
4998 have hΔ0 : Δ = 0 := by
4999 rw [h, dist_self] at hab
5000 exact hab.symm
5001 have hac0 : dist a c = 0 := by rw [hac, hΔ0]
5002 have hca : c = a := (eq_of_dist_eq_zero hac0).symm
5003 apply hUne
5004 rw [h, hca, h]
5005 have hΔ_pos : 0 < Δ := by
5006 have hnn : 0 ≤ Δ := hab ▸ dist_nonneg
5007 have hne : Δ ≠ 0 := by
5008 intro hΔ0
5009 have hd : dist a b = 0 := by rw [hab, hΔ0]
5010 exact h_ab (eq_of_dist_eq_zero hd)
5011 exact lt_of_le_of_ne hnn (Ne.symm hne)
5012 refine ⟨a, ⟨left_endpoint_on_segment a b, left_endpoint_on_segment a c⟩, ?_⟩
5013 intro y hy
5014 by_contra hya
5015 have hay : a ≠ y := by exact fun h => hya h.symm
5016 have h_ab_y : orient2 a b y = 0 := orient2_eq_zero_of_on_closed_segment hy.1
5017 have h_ac_y : orient2 a c y = 0 := orient2_eq_zero_of_on_closed_segment hy.2
5018 have h_ayb : orient2 a y b = 0 := by
5019 rw [orient2_swap₂₃]
5020 simp [h_ab_y]
5021 have h_ayc : orient2 a y c = 0 := by
5022 rw [orient2_swap₂₃]
5023 simp [h_ac_y]
5024 have h_abc : orient2 a b c = 0 :=
5025 orient2_zero_transitive hay h_ayb h_ayc
5026 have hc_on_ab : OnClosedSegment a b c :=
5027 onClosedSegment_of_orient2_zero_in_lens hΔ_pos hab (by rw [hac]) hbc h_abc
5028 have hcb : c = b := by
5029 apply eq_right_of_on_closed_segment_of_dist_left_eq hc_on_ab
5030 rw [hac, hab]
5031 apply hUne
5032 rw [hcb]
5033
5034/-- Shared-endpoint diameter representatives of distinct unordered diameter
5035support edges meet simply. This discharges the endpoint-sharing half of the
5036diameter-support Conway condition. -/
5037theorem shared_endpoint_diameter_representatives_meet_simply :
5038 SharedEndpointDiameterRepresentativesMeetSimply := by
5039 intro A Δ hΔ e he f hf hUne hShare
5040 cases e with
5041 | mk a b =>
5042 cases f with
5043 | mk c d =>
5044 rcases diameter_ordered_edges_cross_distances_le hΔ he hf with
5045 ⟨hab, hcd, hac, had, hbc, hbd⟩
5046 unfold OrderedEdgesShareEndpoint at hShare
5047 simp at hShare hab hcd hac had hbc hbd
5048 rcases hShare with h_ac | h_ad | h_bc | h_bd
5049 · subst c
5050 exact shared_left_diameter_representatives_meet_simply hUne hab hcd hbd
5051 · subst d
5052 have hUne' :
5053 unorderedEdgeOfOrdered (a, b) ≠ unorderedEdgeOfOrdered (a, c) := by
5054 intro hEq
5055 apply hUne
5056 have hswap : unorderedEdgeOfOrdered (c, a) = unorderedEdgeOfOrdered (a, c) := by
5057 simpa using unorderedEdgeOfOrdered_swap (a, c)
5058 exact hEq.trans hswap.symm
5059 have hsimple :
5060 OrderedEdgesMeetSimply (a, b) (a, c) :=
5061 shared_left_diameter_representatives_meet_simply
5062 hUne' hab (by simpa [dist_comm] using hcd) hbc
5063 exact ordered_edges_meet_simply_swap_right hsimple
5064 · subst c
5065 have hUne' :
5066 unorderedEdgeOfOrdered (b, a) ≠ unorderedEdgeOfOrdered (b, d) := by
5067 intro hEq
5068 apply hUne
5069 have hswap : unorderedEdgeOfOrdered (b, a) = unorderedEdgeOfOrdered (a, b) := by
5070 simpa using unorderedEdgeOfOrdered_swap (a, b)
5071 exact hswap.symm.trans hEq
5072 have hsimple :
5073 OrderedEdgesMeetSimply (b, a) (b, d) :=
5074 shared_left_diameter_representatives_meet_simply
5075 hUne' (by simpa [dist_comm] using hab) hcd had
5076 exact ordered_edges_meet_simply_swap_left hsimple
5077 · subst d
5078 have hUne' :
5079 unorderedEdgeOfOrdered (b, a) ≠ unorderedEdgeOfOrdered (b, c) := by
5080 intro hEq
5081 apply hUne
5082 have hswap_e : unorderedEdgeOfOrdered (b, a) = unorderedEdgeOfOrdered (a, b) := by
5083 simpa using unorderedEdgeOfOrdered_swap (a, b)
5084 have hswap_f : unorderedEdgeOfOrdered (c, b) = unorderedEdgeOfOrdered (b, c) := by
5085 simpa using unorderedEdgeOfOrdered_swap (b, c)
5086 exact hswap_e.symm.trans (hEq.trans hswap_f.symm)
5087 have hsimple :
5088 OrderedEdgesMeetSimply (b, a) (b, c) :=
5089 shared_left_diameter_representatives_meet_simply
5090 hUne' (by simpa [dist_comm] using hab) (by simpa [dist_comm] using hcd) hac
5091 exact ordered_edges_meet_simply_swap_right
5092 (ordered_edges_meet_simply_swap_left hsimple)
5093
5094/-- A convex combination of two points in a closed ball is in the ball. -/
5095theorem dist_convex_combination_le
5096 {a c d : Point2} {Δ : ℝ} (t : ℝ) (ht0 : 0 ≤ t) (ht1 : t ≤ 1)
5097 (hac : dist a c ≤ Δ) (had : dist a d ≤ Δ) :
5098 dist a ((1 - t) • c + t • d) ≤ Δ := by
5099 have h_cvx : Convex ℝ (Metric.closedBall a Δ) := convex_closedBall a Δ
5100 have hc : c ∈ Metric.closedBall a Δ := by
5101 rw [Metric.mem_closedBall, dist_comm]
5102 exact hac
5103 have hd : d ∈ Metric.closedBall a Δ := by
5104 rw [Metric.mem_closedBall, dist_comm]
5105 exact had
5106 have h1mt : 0 ≤ 1 - t := by linarith
5107 have hsum : (1 - t) + t = 1 := by ring
5108 have h_in : (1 - t) • c + t • d ∈ Metric.closedBall a Δ :=
5109 h_cvx hc hd h1mt ht0 hsum
5110 rw [Metric.mem_closedBall, dist_comm] at h_in
5111 exact h_in
5112
5113/-- If `c` and `d` are on opposite strict sides of line `ab`, then under the
5114diameter cross-distance bounds the segments `[a,b]` and `[c,d]` meet. -/
5115theorem segments_meet_of_opposite_sides
5116 {a b c d : Point2} {Δ : ℝ} (hΔ_pos : 0 < Δ)
5117 (hab : dist a b = Δ)
5118 (hac : dist a c ≤ Δ) (had : dist a d ≤ Δ)
5119 (hbc : dist b c ≤ Δ) (hbd : dist b d ≤ Δ)
5120 (h_opp : orient2 a b c * orient2 a b d < 0) :
5121 OrderedEdgesMeetGeometrically (a, b) (c, d) := by
5122 have h_oc_ne : orient2 a b c ≠ 0 := by
5123 intro h
5124 rw [h, zero_mul] at h_opp
5125 linarith
5126 have h_od_ne : orient2 a b d ≠ 0 := by
5127 intro h
5128 rw [h, mul_zero] at h_opp
5129 linarith
5130 set u := orient2 a b c
5131 set v := orient2 a b d
5132 have huv : u * v < 0 := h_opp
5133 set t := u / (u - v) with ht_def
5134 have h_denom_ne : u - v ≠ 0 := by
5135 intro h
5136 have : u = v := by linarith
5137 rw [this] at huv
5138 have : v * v ≥ 0 := mul_self_nonneg v
5139 linarith
5140 have ht_pos : 0 < t := by
5141 rcases lt_trichotomy u 0 with hu | hu | hu
5142 · have hv : 0 < v := by
5143 rcases lt_trichotomy v 0 with h | h | h
5144 · have : 0 < u * v := mul_pos_of_neg_of_neg hu h
5145 linarith
5146 · rw [h] at huv
5147 linarith
5148 · exact h
5149 have hd_neg : u - v < 0 := by linarith
5150 exact div_pos_of_neg_of_neg hu hd_neg
5151 · rw [hu] at h_oc_ne
5152 exact absurd rfl h_oc_ne
5153 · have hv : v < 0 := by
5154 rcases lt_trichotomy v 0 with h | h | h
5155 · exact h
5156 · rw [h] at huv
5157 linarith
5158 · have : 0 < u * v := mul_pos hu h
5159 linarith
5160 have hd_pos : 0 < u - v := by linarith
5161 exact div_pos hu hd_pos
5162 have ht_lt : t < 1 := by
5163 have h_t_minus_1 : t - 1 = v / (u - v) := by
5164 rw [ht_def]
5165 field_simp
5166 ring
5167 rcases lt_trichotomy u 0 with hu | hu | hu
5168 · have hv : 0 < v := by
5169 rcases lt_trichotomy v 0 with h | h | h
5170 · have : 0 < u * v := mul_pos_of_neg_of_neg hu h
5171 linarith
5172 · rw [h] at huv
5173 linarith
5174 · exact h
5175 have hd_neg : u - v < 0 := by linarith
5176 have h_quot_neg : v / (u - v) < 0 := div_neg_of_pos_of_neg hv hd_neg
5177 linarith [h_t_minus_1, h_quot_neg]
5178 · rw [hu] at h_oc_ne
5179 exact absurd rfl h_oc_ne
5180 · have hv : v < 0 := by
5181 rcases lt_trichotomy v 0 with h | h | h
5182 · exact h
5183 · rw [h] at huv
5184 linarith
5185 · have : 0 < u * v := mul_pos hu h
5186 linarith
5187 have hd_pos : 0 < u - v := by linarith
5188 have h_quot_neg : v / (u - v) < 0 := div_neg_of_neg_of_pos hv hd_pos
5189 linarith [h_t_minus_1, h_quot_neg]
5190 set P := (1 - t) • c + t • d with hP_def
5191 have hP_on_cd : OnClosedSegment c d P := ⟨t, le_of_lt ht_pos, le_of_lt ht_lt, rfl⟩
5192 have h_orient_P : orient2 a b P = 0 := by
5193 have h_aff : orient2 a b P = (1 - t) * orient2 a b c + t * orient2 a b d := by
5194 rw [hP_def]
5195 exact orient2_affine_third a b c d t
5196 have h_aff' : orient2 a b P = (1 - t) * u + t * v := h_aff
5197 rw [h_aff', ht_def]
5198 field_simp
5199 ring
5200 have hP_aΔ : dist a P ≤ Δ := by
5201 exact dist_convex_combination_le t (le_of_lt ht_pos) (le_of_lt ht_lt) hac had
5202 have hP_bΔ : dist b P ≤ Δ := by
5203 exact dist_convex_combination_le t (le_of_lt ht_pos) (le_of_lt ht_lt) hbc hbd
5204 have hP_on_ab : OnClosedSegment a b P :=
5205 onClosedSegment_of_orient2_zero_in_lens hΔ_pos hab hP_aΔ hP_bΔ h_orient_P
5206 exact ⟨P, hP_on_ab, hP_on_cd⟩
5207
5208/-
5209The following same-side and crossing lemmas close the four-point
5210Hopf-Pannwitz geometry used by the live final assemblies below.
5211-/
5212
5213set_option maxHeartbeats 6400000 in
5214/-- **Sharper same-side bridge.** The proof of
5215`properSeparatedDiameterContradiction` only uses the first orientation
5216product condition of `ProperSegmentSeparation`, not the second. This
5217strengthens it: under the diameter conditions, having `c` and `d` strictly
5218on the same side of line `ab` (i.e., `orient2 a b c · orient2 a b d > 0`)
5219already gives a contradiction. -/
5220theorem sameSideDiameterContradiction
5221 (a b c d : Point2) (Δ : ℝ)
5222 (h_ac : a ≠ c) (_h_ad : a ≠ d) (_h_bc : b ≠ c) (_h_bd : b ≠ d)
5223 (hab : dist a b = Δ) (hcd : dist c d = Δ)
5224 (hac : dist a c ≤ Δ) (had : dist a d ≤ Δ) (hbc : dist b c ≤ Δ) (hbd : dist b d ≤ Δ)
5225 (h_same_side : 0 < orient2 a b c * orient2 a b d) :
5226 False := by
5227 by_cases hΔ : Δ = 0
5228 · subst hΔ
5229 have h : dist a c = 0 := le_antisymm hac dist_nonneg
5230 exact h_ac (eq_of_dist_eq_zero h)
5231 have hΔ_nn : 0 ≤ Δ := hab ▸ dist_nonneg
5232 have hΔ_pos : 0 < Δ := lt_of_le_of_ne hΔ_nn (Ne.symm hΔ)
5233 have hΔ_ne : Δ ≠ 0 := ne_of_gt hΔ_pos
5234 have hab_sq : Δ*Δ = (b 0 - a 0)^2 + (b 1 - a 1)^2 := by
5235 have h := dist_sq_unfold a b
5236 rw [hab] at h
5237 nlinarith [h]
5238 have hac_sq_le : (c 0 - a 0)^2 + (c 1 - a 1)^2 ≤ Δ*Δ := by
5239 have h := dist_sq_unfold a c
5240 have hac_nn : 0 ≤ dist a c := dist_nonneg
5241 have : (dist a c)^2 ≤ Δ^2 := by nlinarith [hac_nn, hac]
5242 nlinarith [h, this]
5243 have had_sq_le : (d 0 - a 0)^2 + (d 1 - a 1)^2 ≤ Δ*Δ := by
5244 have h := dist_sq_unfold a d
5245 have hd_nn : 0 ≤ dist a d := dist_nonneg
5246 have : (dist a d)^2 ≤ Δ^2 := by nlinarith [hd_nn, had]
5247 nlinarith [h, this]
5248 have hbc_sq_le : (b 0 - c 0)^2 + (b 1 - c 1)^2 ≤ Δ*Δ := by
5249 have h := dist_sq_unfold b c
5250 have hd_nn : 0 ≤ dist b c := dist_nonneg
5251 have : (dist b c)^2 ≤ Δ^2 := by nlinarith [hd_nn, hbc]
5252 nlinarith [h, this]
5253 have hbd_sq_le : (b 0 - d 0)^2 + (b 1 - d 1)^2 ≤ Δ*Δ := by
5254 have h := dist_sq_unfold b d
5255 have hd_nn : 0 ≤ dist b d := dist_nonneg
5256 have : (dist b d)^2 ≤ Δ^2 := by nlinarith [hd_nn, hbd]
5257 nlinarith [h, this]
5258 have hcd_sq_eq : (c 0 - d 0)^2 + (c 1 - d 1)^2 = Δ*Δ := by
5259 have h := dist_sq_unfold c d
5260 rw [hcd] at h
5261 nlinarith [h]
5262 have hLag_c : ((c 0 - a 0)*(b 0 - a 0) + (c 1 - a 1)*(b 1 - a 1))^2 +
5263 ((b 0 - a 0)*(c 1 - a 1) - (b 1 - a 1)*(c 0 - a 0))^2 =
5264 ((c 0 - a 0)^2 + (c 1 - a 1)^2) * ((b 0 - a 0)^2 + (b 1 - a 1)^2) :=
5265 lagrange_identity_2d a b c
5266 have hLag_d : ((d 0 - a 0)*(b 0 - a 0) + (d 1 - a 1)*(b 1 - a 1))^2 +
5267 ((b 0 - a 0)*(d 1 - a 1) - (b 1 - a 1)*(d 0 - a 0))^2 =
5268 ((d 0 - a 0)^2 + (d 1 - a 1)^2) * ((b 0 - a 0)^2 + (b 1 - a 1)^2) :=
5269 lagrange_identity_2d a b d
5270 have hLag_pol : ((c 0 - a 0)*(b 0 - a 0) + (c 1 - a 1)*(b 1 - a 1)) *
5271 ((d 0 - a 0)*(b 0 - a 0) + (d 1 - a 1)*(b 1 - a 1)) +
5272 ((b 0 - a 0)*(c 1 - a 1) - (b 1 - a 1)*(c 0 - a 0)) *
5273 ((b 0 - a 0)*(d 1 - a 1) - (b 1 - a 1)*(d 0 - a 0)) =
5274 ((c 0 - a 0)*(d 0 - a 0) + (c 1 - a 1)*(d 1 - a 1)) *
5275 ((b 0 - a 0)^2 + (b 1 - a 1)^2) :=
5276 lagrange_identity_polarized_2d a b c d
5277 set αc := ((c 0 - a 0)*(b 0 - a 0) + (c 1 - a 1)*(b 1 - a 1)) / Δ with hαc_def
5278 set βc := ((b 0 - a 0)*(c 1 - a 1) - (b 1 - a 1)*(c 0 - a 0)) / Δ with hβc_def
5279 set αd := ((d 0 - a 0)*(b 0 - a 0) + (d 1 - a 1)*(b 1 - a 1)) / Δ with hαd_def
5280 set βd := ((b 0 - a 0)*(d 1 - a 1) - (b 1 - a 1)*(d 0 - a 0)) / Δ with hβd_def
5281 have h_αcβc_eq_ac : αc*αc + βc*βc = (c 0 - a 0)^2 + (c 1 - a 1)^2 := by
5282 rw [hαc_def, hβc_def]; field_simp; nlinarith [hLag_c, hab_sq]
5283 have h_αdβd_eq_ad : αd*αd + βd*βd = (d 0 - a 0)^2 + (d 1 - a 1)^2 := by
5284 rw [hαd_def, hβd_def]; field_simp; nlinarith [hLag_d, hab_sq]
5285 have h_αcβc_eq_bc : (αc - Δ)*(αc - Δ) + βc*βc = (b 0 - c 0)^2 + (b 1 - c 1)^2 := by
5286 have e1 : αc * Δ = (c 0 - a 0)*(b 0 - a 0) + (c 1 - a 1)*(b 1 - a 1) := by
5287 rw [hαc_def]; field_simp
5288 have e2 : (αc - Δ)*(αc - Δ) + βc*βc = (αc*αc + βc*βc) - 2*(αc*Δ) + Δ*Δ := by ring
5289 rw [e2, h_αcβc_eq_ac, e1, hab_sq]; ring
5290 have h_αdβd_eq_bd : (αd - Δ)*(αd - Δ) + βd*βd = (b 0 - d 0)^2 + (b 1 - d 1)^2 := by
5291 have e1 : αd * Δ = (d 0 - a 0)*(b 0 - a 0) + (d 1 - a 1)*(b 1 - a 1) := by
5292 rw [hαd_def]; field_simp
5293 have e2 : (αd - Δ)*(αd - Δ) + βd*βd = (αd*αd + βd*βd) - 2*(αd*Δ) + Δ*Δ := by ring
5294 rw [e2, h_αdβd_eq_ad, e1, hab_sq]; ring
5295 have h_cd_eq : (αc - αd)*(αc - αd) + (βc - βd)*(βc - βd) = (c 0 - d 0)^2 + (c 1 - d 1)^2 := by
5296 have e1 : αc * αd + βc * βd = (c 0 - a 0)*(d 0 - a 0) + (c 1 - a 1)*(d 1 - a 1) := by
5297 have hΔΔ_pos : 0 < Δ*Δ := mul_pos hΔ_pos hΔ_pos
5298 have h1 : αc * αd = (((c 0 - a 0)*(b 0 - a 0) + (c 1 - a 1)*(b 1 - a 1)) *
5299 ((d 0 - a 0)*(b 0 - a 0) + (d 1 - a 1)*(b 1 - a 1))) / (Δ*Δ) := by
5300 rw [hαc_def, hαd_def]; field_simp
5301 have h2 : βc * βd = (((b 0 - a 0)*(c 1 - a 1) - (b 1 - a 1)*(c 0 - a 0)) *
5302 ((b 0 - a 0)*(d 1 - a 1) - (b 1 - a 1)*(d 0 - a 0))) / (Δ*Δ) := by
5303 rw [hβc_def, hβd_def]; field_simp
5304 rw [h1, h2, ← add_div]
5305 rw [hLag_pol, ← hab_sq]
5306 field_simp
5307 have e2 : (αc - αd)*(αc - αd) + (βc - βd)*(βc - βd) =
5308 (αc*αc + βc*βc) + (αd*αd + βd*βd) - 2*(αc*αd + βc*βd) := by ring
5309 rw [e2, h_αcβc_eq_ac, h_αdβd_eq_ad, e1]
5310 ring
5311 have hβc_orient : βc * Δ = orient2 a b c := by
5312 rw [hβc_def]; field_simp; unfold orient2; ring
5313 have hβd_orient : βd * Δ = orient2 a b d := by
5314 rw [hβd_def]; field_simp; unfold orient2; ring
5315 have hβ_prod : 0 < βc * βd := by
5316 have : 0 < (βc * Δ) * (βd * Δ) := by
5317 rw [hβc_orient, hβd_orient]; exact h_same_side
5318 have hΔΔ_pos : 0 < Δ*Δ := mul_pos hΔ_pos hΔ_pos
5319 nlinarith [this, hΔΔ_pos]
5320 have hi_lens : αc*αc + βc*βc ≤ Δ*Δ := by rw [h_αcβc_eq_ac]; exact hac_sq_le
5321 have hii_lens : (αc - Δ)*(αc - Δ) + βc*βc ≤ Δ*Δ := by rw [h_αcβc_eq_bc]; exact hbc_sq_le
5322 have hiii_lens : αd*αd + βd*βd ≤ Δ*Δ := by rw [h_αdβd_eq_ad]; exact had_sq_le
5323 have hiv_lens : (αd - Δ)*(αd - Δ) + βd*βd ≤ Δ*Δ := by rw [h_αdβd_eq_bd]; exact hbd_sq_le
5324 rcases lt_trichotomy βc 0 with hβc | hβc | hβc
5325 · have hβd : βd < 0 := by
5326 by_contra h
5327 push_neg at h
5328 rcases lt_or_eq_of_le h with hβd_pos | hβd_zero
5329 · have : βc * βd < 0 := mul_neg_of_neg_of_pos hβc hβd_pos
5330 linarith [hβ_prod, this]
5331 · rw [← hβd_zero] at hβ_prod; linarith
5332 have hp := hopf_pannwitz_strict_lens_coord_neg Δ αc βc αd βd hΔ_pos
5333 hi_lens hii_lens hiii_lens hiv_lens hβc hβd
5334 rw [h_cd_eq] at hp
5335 linarith [hp, hcd_sq_eq]
5336 · rw [hβc] at hβ_prod; linarith [hβ_prod]
5337 · have hβd : 0 < βd := by
5338 by_contra h
5339 push_neg at h
5340 rcases lt_or_eq_of_le h with hβd_neg | hβd_zero
5341 · have : βc * βd < 0 := mul_neg_of_pos_of_neg hβc hβd_neg
5342 linarith [hβ_prod, this]
5343 · rw [hβd_zero] at hβ_prod; linarith
5344 have hp := hopf_pannwitz_strict_lens_coord Δ αc βc αd βd hΔ_pos
5345 hi_lens hii_lens hiii_lens hiv_lens hβc hβd
5346 rw [h_cd_eq] at hp
5347 linarith [hp, hcd_sq_eq]
5348
5349
5350/-- **Four-point Hopf-Pannwitz crossing theorem, closed.** If
5351`dist a b = dist c d = Δ`, all four cross-distances are at most `Δ`, and the
5352four endpoints are pairwise distinct across the two segments, then the closed
5353segments `[a,b]` and `[c,d]` meet geometrically. -/
5354theorem fourPointDiameterCrossing_thm : FourPointDiameterCrossing := by
5355 intro a b c d Δ h_ac h_ad h_bc h_bd hab hcd hac had hbc hbd
5356 by_cases hΔ : Δ = 0
5357 · subst hΔ
5358 exact four_point_diameter_crossing_zero_case a b c d h_ac h_ad h_bc h_bd
5359 hab hcd hac had hbc hbd
5360 have hΔ_nn : 0 ≤ Δ := hab ▸ dist_nonneg
5361 have hΔ_pos : 0 < Δ := lt_of_le_of_ne hΔ_nn (Ne.symm hΔ)
5362 by_contra hnomeet
5363 have hdisj : OrderedEdgesGeometricallyDisjoint (a, b) (c, d) := hnomeet
5364 have meet_at_c : orient2 a b c = 0 → OrderedEdgesMeetGeometrically (a, b) (c, d) := by
5365 intro hc_z
5366 refine ⟨c,
5367 onClosedSegment_of_orient2_zero_in_lens hΔ_pos hab hac hbc hc_z,
5368 left_endpoint_on_segment c d⟩
5369 have meet_at_d : orient2 a b d = 0 → OrderedEdgesMeetGeometrically (a, b) (c, d) := by
5370 intro hd_z
5371 refine ⟨d,
5372 onClosedSegment_of_orient2_zero_in_lens hΔ_pos hab had hbd hd_z,
5373 right_endpoint_on_segment c d⟩
5374 rcases lt_trichotomy (orient2 a b c) 0 with hc_n | hc_z | hc_p
5375 · rcases lt_trichotomy (orient2 a b d) 0 with hd_n | hd_z | hd_p
5376 · have hprod : 0 < orient2 a b c * orient2 a b d :=
5377 mul_pos_of_neg_of_neg hc_n hd_n
5378 exact sameSideDiameterContradiction a b c d Δ h_ac h_ad h_bc h_bd
5379 hab hcd hac had hbc hbd hprod
5380 · exact hdisj (meet_at_d hd_z)
5381 · have hprod : orient2 a b c * orient2 a b d < 0 :=
5382 mul_neg_of_neg_of_pos hc_n hd_p
5383 exact hdisj (segments_meet_of_opposite_sides hΔ_pos hab hac had hbc hbd hprod)
5384 · rcases lt_trichotomy (orient2 a b d) 0 with hd_n | hd_z | hd_p
5385 · exact hdisj (meet_at_c hc_z)
5386 · exact collinearSeparatedDiameterContradiction a b c d Δ h_ac h_ad h_bc h_bd
5387 hab hcd hac had hbc hbd ⟨hc_z, hd_z, hdisj⟩
5388 · exact hdisj (meet_at_c hc_z)
5389 · rcases lt_trichotomy (orient2 a b d) 0 with hd_n | hd_z | hd_p
5390 · have hprod : orient2 a b c * orient2 a b d < 0 :=
5391 mul_neg_of_pos_of_neg hc_p hd_n
5392 exact hdisj (segments_meet_of_opposite_sides hΔ_pos hab hac had hbc hbd hprod)
5393 · exact hdisj (meet_at_d hd_z)
5394 · have hprod : 0 < orient2 a b c * orient2 a b d := mul_pos hc_p hd_p
5395 exact sameSideDiameterContradiction a b c d Δ h_ac h_ad h_bc h_bd
5396 hab hcd hac had hbc hbd hprod
5397
5398/-- Endpoint-disjoint diameter representative uniqueness, together with the
5399proved four-point diameter crossing theorem, gives simple meeting. -/
5400theorem endpoint_disjoint_diameter_representatives_meet_simply_from_unique_live
5401 (hUnique : EndpointDisjointDiameterIntersectionUniqueCertificate) :
5402 EndpointDisjointDiameterRepresentativesMeetSimply := by
5403 intro A Δ hΔ e he f hf hUne hNoShare
5404 classical
5405 rcases e with ⟨a, b⟩
5406 rcases f with ⟨c, d⟩
5407 have hNoShareOrig : ¬ OrderedEdgesShareEndpoint (a, b) (c, d) := hNoShare
5408 rcases diameter_ordered_edges_cross_distances_le hΔ he hf with
5409 ⟨hab, hcd, hac, had, hbc, hbd⟩
5410 unfold OrderedEdgesShareEndpoint at hNoShare
5411 simp at hNoShare
5412 have h_ac : a ≠ c := hNoShare.1
5413 have h_ad : a ≠ d := hNoShare.2.1
5414 have h_bc : b ≠ c := hNoShare.2.2.1
5415 have h_bd : b ≠ d := hNoShare.2.2.2
5416 have hMeet : OrderedEdgesMeetGeometrically (a, b) (c, d) :=
5417 fourPointDiameterCrossing_thm a b c d Δ h_ac h_ad h_bc h_bd
5418 hab hcd hac had hbc hbd
5419 rcases hMeet with ⟨x, hx⟩
5420 refine ⟨x, hx, ?_⟩
5421 intro y hy
5422 exact (hUnique A Δ hΔ (a, b) he (c, d) hf hUne hNoShareOrig x y hx hy).symm
5423
5424/-- Live corrected Conway-form final assembly: support-level Conway counting,
5425endpoint-disjoint diameter intersection uniqueness, and pointwise deep-layer
5426screening imply Erdős #132. The shared-endpoint diameter representative case is
5427already proved by `shared_endpoint_diameter_representatives_meet_simply`; the
5428endpoint-disjoint existence part is supplied by `fourPointDiameterCrossing_thm`.
5429-/
5430theorem erdos132_from_support_conway_endpoint_disjoint_uniqueness_and_deep_screening_live
5431 (hSupport : ConwayThrackleSupportBoundOnSupport)
5432 (hUnique : EndpointDisjointDiameterIntersectionUniqueCertificate)
5433 (hScreen : PointwiseDeepLayerScreeningCertificate) :
5434 Erdos132Ordered :=
5435 erdos132_from_diameter_sparsity_and_no_deep_layer
5436 (diameter_shell_sparse_from_diameter_conway_bound
5437 (diameter_conway_bound_from_support_conway hSupport
5438 (diameter_support_forms_conway_from_simple_representatives
5439 (diameter_support_simple_representatives_from_ordered_representatives
5440 (distinct_diameter_representatives_meet_simply_from_cases
5441 shared_endpoint_diameter_representatives_meet_simply
5442 (endpoint_disjoint_diameter_representatives_meet_simply_from_unique_live hUnique))))))
5443 (no_deep_layer_from_pointwise_screening_certificate hScreen)
5444
5445/-- Live residual package after closing the shared-endpoint diameter
5446representative case. -/
5447structure Erdos132ConwayEndpointDisjointUniquenessScreeningResidualPack : Prop where
5448 support_conway_thrackle_bound : ConwayThrackleSupportBoundOnSupport
5449 endpoint_disjoint_diameter_intersection_unique :
5450 EndpointDisjointDiameterIntersectionUniqueCertificate
5451 pointwise_deep_layer_screening : PointwiseDeepLayerScreeningCertificate
5452
5453/-- The live endpoint-disjoint uniqueness residual package proves Erdős #132. -/
5454theorem erdos132_from_conway_endpoint_disjoint_uniqueness_screening_residual_pack
5455 (P : Erdos132ConwayEndpointDisjointUniquenessScreeningResidualPack) :
5456 Erdos132Ordered :=
5457 erdos132_from_support_conway_endpoint_disjoint_uniqueness_and_deep_screening_live
5458 P.support_conway_thrackle_bound
5459 P.endpoint_disjoint_diameter_intersection_unique
5460 P.pointwise_deep_layer_screening
5461
5462/-- Live final assembly with endpoint-disjoint uniqueness reduced to the
5463two-common-points-force-collinearity certificate. -/
5464theorem erdos132_from_support_conway_endpoint_disjoint_collinear_and_deep_screening_live
5465 (hSupport : ConwayThrackleSupportBoundOnSupport)
5466 (hCol : EndpointDisjointTwoPointIntersectionForcesCollinear)
5467 (hScreen : PointwiseDeepLayerScreeningCertificate) :
5468 Erdos132Ordered :=
5469 erdos132_from_support_conway_endpoint_disjoint_uniqueness_and_deep_screening_live
5470 hSupport
5471 (endpoint_disjoint_diameter_intersection_unique_from_two_point_collinear hCol)
5472 hScreen
5473
5474/-- Live final assembly after closing all diameter-side local geometry. The
5475remaining inputs are exactly support-level Conway counting and pointwise
5476deep-layer screening. -/
5477theorem erdos132_from_support_conway_and_deep_screening_live
5478 (hSupport : ConwayThrackleSupportBoundOnSupport)
5479 (hScreen : PointwiseDeepLayerScreeningCertificate) :
5480 Erdos132Ordered :=
5481 erdos132_from_support_conway_endpoint_disjoint_collinear_and_deep_screening_live
5482 hSupport
5483 endpoint_disjoint_two_point_intersection_forces_collinear
5484 hScreen
5485
5486/-- Live final assembly with the remaining Conway input stated in the standard
5487ordered form. The support-level wrapper is derived by choosing one ordered
5488representative from each unordered support edge. -/
5489theorem erdos132_from_ordered_conway_and_deep_screening_live
5490 (hConway : ConwayThrackleSupportBound)
5491 (hScreen : PointwiseDeepLayerScreeningCertificate) :
5492 Erdos132Ordered :=
5493 erdos132_from_support_conway_and_deep_screening_live
5494 (conway_support_bound_on_support_from_ordered hConway)
5495 hScreen
5496
5497/-- Equivalent final assembly in the negative layer form: standard Conway
5498counting plus pointwise no-deep-layer contradiction proves Erdős #132. -/
5499theorem erdos132_from_ordered_conway_and_pointwise_no_deep_layer_live
5500 (hConway : ConwayThrackleSupportBound)
5501 (hNoDeep : PointwiseNoDeepLayerCaseInLowShellRegime) :
5502 Erdos132Ordered :=
5503 erdos132_from_ordered_conway_and_deep_screening_live
5504 hConway
5505 (pointwise_screening_certificate_from_no_deep_layer hNoDeep)
5506
5507/-- Honest eventual final assembly. The pointwise no-deep statement is too
5508strong for small finite sets; Erdős #132 only needs the eventual low-shell
5509no-deep theorem. -/
5510theorem erdos132_from_ordered_conway_and_eventual_no_deep_layer_live
5511 (hConway : ConwayThrackleSupportBound)
5512 (hNoDeep : NoDeepLayerCaseInLowShellRegime) :
5513 Erdos132Ordered :=
5514 erdos132_from_diameter_sparsity_and_no_deep_layer
5515 (diameter_shell_sparse_from_diameter_conway_bound
5516 (diameter_conway_bound_from_support_conway
5517 (conway_support_bound_on_support_from_ordered hConway)
5518 (diameter_support_forms_conway_from_simple_representatives
5519 (diameter_support_simple_representatives_from_ordered_representatives
5520 (distinct_diameter_representatives_meet_simply_from_cases
5521 shared_endpoint_diameter_representatives_meet_simply
5522 (endpoint_disjoint_diameter_representatives_meet_simply_from_unique_live
5523 (endpoint_disjoint_diameter_intersection_unique_from_two_point_collinear
5524 endpoint_disjoint_two_point_intersection_forces_collinear)))))))
5525 hNoDeep
5526
5527/-- Final assembly in the proof plan's current component language: standard
5528ordered Conway counting plus convex-layer screening proves Erdős #132. -/
5529theorem erdos132_from_ordered_conway_and_convex_layer_screening_live
5530 (hConway : ConwayThrackleSupportBound)
5531 (hLayer : ConvexLayerScreeningBridge) :
5532 Erdos132Ordered :=
5533 erdos132_from_ordered_conway_and_eventual_no_deep_layer_live
5534 hConway
5535 (no_deep_layer_from_convex_layer_screening hLayer)
5536
5537/-- Final assembly with the layer residual stated as an explicit threshold. -/
5538theorem erdos132_from_ordered_conway_and_threshold_convex_layer_screening_live
5539 (hConway : ConwayThrackleSupportBound)
5540 (hLayer : ConvexLayerScreeningThresholdCertificate) :
5541 Erdos132Ordered :=
5542 erdos132_from_ordered_conway_and_convex_layer_screening_live
5543 hConway
5544 (convex_layer_screening_from_threshold hLayer)
5545
5546/-- Current live residual package after reducing endpoint-disjoint uniqueness to
5547the two-point collinearity certificate. -/
5548structure Erdos132ConwayEndpointDisjointCollinearityScreeningResidualPack : Prop where
5549 support_conway_thrackle_bound : ConwayThrackleSupportBoundOnSupport
5550 endpoint_disjoint_two_point_intersection_forces_collinear :
5551 EndpointDisjointTwoPointIntersectionForcesCollinear
5552 pointwise_deep_layer_screening : PointwiseDeepLayerScreeningCertificate
5553
5554/-- The endpoint-disjoint collinearity residual package proves Erdős #132. -/
5555theorem erdos132_from_conway_endpoint_disjoint_collinearity_screening_residual_pack
5556 (P : Erdos132ConwayEndpointDisjointCollinearityScreeningResidualPack) :
5557 Erdos132Ordered :=
5558 erdos132_from_support_conway_endpoint_disjoint_collinear_and_deep_screening_live
5559 P.support_conway_thrackle_bound
5560 P.endpoint_disjoint_two_point_intersection_forces_collinear
5561 P.pointwise_deep_layer_screening
5562
5563/-- Current live residual package after closing the full diameter-side Conway
5564condition. -/
5565structure Erdos132ConwayCountingScreeningResidualPack : Prop where
5566 support_conway_thrackle_bound : ConwayThrackleSupportBoundOnSupport
5567 pointwise_deep_layer_screening : PointwiseDeepLayerScreeningCertificate
5568
5569/-- The Conway-counting plus deep-screening residual package proves Erdős #132. -/
5570theorem erdos132_from_conway_counting_screening_residual_pack
5571 (P : Erdos132ConwayCountingScreeningResidualPack) :
5572 Erdos132Ordered :=
5573 erdos132_from_support_conway_and_deep_screening_live
5574 P.support_conway_thrackle_bound
5575 P.pointwise_deep_layer_screening
5576
5577/-- Current live residual package in standard classical form: the standard
5578ordered Conway straight-line thrackle theorem plus pointwise deep-layer
5579screening. -/
5580structure Erdos132OrderedConwayScreeningResidualPack : Prop where
5581 ordered_conway_thrackle_bound : ConwayThrackleSupportBound
5582 pointwise_deep_layer_screening : PointwiseDeepLayerScreeningCertificate
5583
5584/-- The standard Conway-counting plus deep-screening residual package proves
5585Erdős #132. -/
5586theorem erdos132_from_ordered_conway_screening_residual_pack
5587 (P : Erdos132OrderedConwayScreeningResidualPack) :
5588 Erdos132Ordered :=
5589 erdos132_from_ordered_conway_and_deep_screening_live
5590 P.ordered_conway_thrackle_bound
5591 P.pointwise_deep_layer_screening
5592
5593/-- Final residual package in the cleanest negative layer form. -/
5594structure Erdos132OrderedConwayNoDeepResidualPack : Prop where
5595 ordered_conway_thrackle_bound : ConwayThrackleSupportBound
5596 pointwise_no_deep_layer : PointwiseNoDeepLayerCaseInLowShellRegime
5597
5598/-- The ordered Conway plus pointwise no-deep residual package proves Erdős #132. -/
5599theorem erdos132_from_ordered_conway_no_deep_residual_pack
5600 (P : Erdos132OrderedConwayNoDeepResidualPack) :
5601 Erdos132Ordered :=
5602 erdos132_from_ordered_conway_and_pointwise_no_deep_layer_live
5603 P.ordered_conway_thrackle_bound
5604 P.pointwise_no_deep_layer
5605
5606/-- Honest final residual package: standard ordered Conway counting plus the
5607eventual low-shell no-deep theorem. -/
5608structure Erdos132OrderedConwayEventualNoDeepResidualPack : Prop where
5609 ordered_conway_thrackle_bound : ConwayThrackleSupportBound
5610 eventual_no_deep_layer : NoDeepLayerCaseInLowShellRegime
5611
5612/-- The honest eventual residual package proves Erdős #132. -/
5613theorem erdos132_from_ordered_conway_eventual_no_deep_residual_pack
5614 (P : Erdos132OrderedConwayEventualNoDeepResidualPack) :
5615 Erdos132Ordered :=
5616 erdos132_from_ordered_conway_and_eventual_no_deep_layer_live
5617 P.ordered_conway_thrackle_bound
5618 P.eventual_no_deep_layer
5619
5620/-- Final residual package in the proof plan's component language: standard
5621ordered Conway counting plus convex-layer screening. -/
5622structure Erdos132OrderedConwayConvexLayerResidualPack : Prop where
5623 ordered_conway_thrackle_bound : ConwayThrackleSupportBound
5624 convex_layer_screening : ConvexLayerScreeningBridge
5625
5626/-- Ordered Conway counting plus convex-layer screening proves Erdős #132. -/
5627theorem erdos132_from_ordered_conway_convex_layer_residual_pack
5628 (P : Erdos132OrderedConwayConvexLayerResidualPack) :
5629 Erdos132Ordered :=
5630 erdos132_from_ordered_conway_and_convex_layer_screening_live
5631 P.ordered_conway_thrackle_bound
5632 P.convex_layer_screening
5633
5634/-- Final residual package with an explicit convex-layer threshold. -/
5635structure Erdos132OrderedConwayThresholdLayerResidualPack : Prop where
5636 ordered_conway_thrackle_bound : ConwayThrackleSupportBound
5637 convex_layer_screening_threshold : ConvexLayerScreeningThresholdCertificate
5638
5639/-- Ordered Conway counting plus thresholded convex-layer screening proves
5640Erdős #132. -/
5641theorem erdos132_from_ordered_conway_threshold_layer_residual_pack
5642 (P : Erdos132OrderedConwayThresholdLayerResidualPack) :
5643 Erdos132Ordered :=
5644 erdos132_from_ordered_conway_and_threshold_convex_layer_screening_live
5645 P.ordered_conway_thrackle_bound
5646 P.convex_layer_screening_threshold
5647
5648/-- The current live two-input endpoint for Erdős #132. All finite accounting,
5649diameter geometry, ordered/unordered representative bookkeeping, and the
5650support-level Conway correction have been discharged above. -/
5651def Erdos132CurrentLiveResidual : Prop :=
5652 ConwayThrackleSupportBound ∧ ConvexLayerScreeningBridge
5653
5654/-- The current live two-input residual proves Erdős #132. -/
5655theorem erdos132_from_current_live_residual
5656 (h : Erdos132CurrentLiveResidual) :
5657 Erdos132Ordered :=
5658 erdos132_from_ordered_conway_and_convex_layer_screening_live h.1 h.2
5659
5660/-- Constructive version of the current live residual: a Conway endpoint-charge
5661certificate plus convex-layer screening proves Erdős #132. -/
5662def Erdos132CurrentConstructiveResidual : Prop :=
5663 ConwayThrackleEndpointChargeCertificate ∧ ConvexLayerScreeningBridge
5664
5665/-- The constructive current residual proves Erdős #132. -/
5666theorem erdos132_from_current_constructive_residual
5667 (h : Erdos132CurrentConstructiveResidual) :
5668 Erdos132Ordered :=
5669 erdos132_from_ordered_conway_and_convex_layer_screening_live
5670 (conway_support_bound_from_endpoint_charge h.1)
5671 h.2
5672
5673/-- Large non-star version of the current live residual: all small and star
5674Conway cases are closed by finite bookkeeping, so only the large non-star
5675Conway theorem remains on the counting side. -/
5676def Erdos132CurrentLargeNonStarResidual : Prop :=
5677 LargeNonStarConwayThrackleSupportBound ∧ ConvexLayerScreeningBridge
5678
5679/-- The large non-star current residual proves Erdős #132. -/
5680theorem erdos132_from_current_large_nonstar_residual
5681 (h : Erdos132CurrentLargeNonStarResidual) :
5682 Erdos132Ordered :=
5683 erdos132_from_ordered_conway_and_convex_layer_screening_live
5684 (conway_support_bound_from_large_nonstar h.1)
5685 h.2
5686
5687/-- Legacy reduced assembly retained for comparison with the pre-Conway-correction
5688proof graph. The live final endpoint is
5689`erdos132_from_ordered_conway_convex_layer_residual_pack`. -/
5690theorem erdos132_from_thrackle_and_layer
5691 (hSupport : UndirectedThrackleSupportBound)
5692 (hLayer : ConvexLayerScreeningBridge) :
5693 Erdos132Ordered :=
5694 erdos132_from_four_point_thrackle_and_convex_layer_screening
5695 fourPointDiameterCrossing_thm hSupport hLayer
5696
5697end
5698end DistanceShellMultiplicity
5699end Mathematics
5700end IndisputableMonolith
5701