Pith. sign in

IndisputableMonolith.Mathematics.DistanceShellMultiplicity

IndisputableMonolith/Mathematics/DistanceShellMultiplicity.lean · 5701 lines · 337 declarations

show as:
view math explainer →

open module explainer GitHub source

Explainer status: ready · generated 2026-08-13 22:44:17.967415+00:00

   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

source mirrored from github.com/jonwashburn/shape-of-logic