CubicPathwidth.EndpointTransfer

Source file CubicPathwidth/EndpointTransfer.lean of the Lean project (how it is built).

import CubicPathwidth.Completion

/-!
# Separate cut and distinct-endpoint coefficients (T18-F)

The proved cut gluing `pathwidth_of_cut_endpoint_bounds` uses, on each side,
the set of DISTINCT boundary endpoints `(edges G A).image Prod.fst` (resp.
`Prod.snd`), and the cut size only as the connector width.  The existing
coefficient step bounds the endpoint counts by the cut size.  Here the two
are controlled by separate coefficients `κ` (cut) and `ξ` (endpoints per side).

Main results:
* `endpoint_coefficient_step`: from a uniform pathwidth coefficient `b < 1/3`
  and a `(κ, ξ)` partition family, the coefficient `max κ (ξ + (1/2 - 3ξ) b)`.
* `endpoint_transfer`: for `0 ≤ κ < 1/6`, `0 ≤ ξ ≤ 1/6`, the coefficient
  `max κ (2ξ/(1+6ξ))`.
* `bisection_transfer`: for every `0 ≤ c < 1/6`, a uniform bisection
  coefficient `c` gives the pathwidth coefficient `2c/(1+6c)` (the general
  parameter version of the project's coefficient step).
-/

noncomputable section
namespace CubicPathwidth
open CutConnector SectionDecomposition

/-- A uniform family of bisections with cut coefficient `κ` and at most
`(ξ+ε)n` distinct boundary endpoints on EACH side. -/
def UniformEndpointPartitionBound (κ ξ : ℝ) : Prop :=
  ∀ ε : ℝ, 0 < ε → ∃ N : ℕ, ∀ n : ℕ, N ≤ n →
    ∀ G : SimpleGraph (Fin n), IsSubcubic G →
      ∃ A : Finset (Fin n), IsBisection A ∧
        (crossingEdges G A : ℝ) ≤ (κ + ε) * (n : ℝ) ∧
        ((((edges G A).image Prod.fst).card : ℕ) : ℝ) ≤ (ξ + ε) * (n : ℝ) ∧
        ((((edges G A).image Prod.snd).card : ℕ) : ℝ) ≤ (ξ + ε) * (n : ℝ)

theorem uniformBisection_of_partition {κ ξ : ℝ} (h : UniformEndpointPartitionBound κ ξ) :
    UniformBisectionBound κ := by
  intro ε hε
  obtain ⟨N, hN⟩ := h ε hε
  refine ⟨N, fun n hn G hG => ?_⟩
  obtain ⟨A, hA, hc, -, -⟩ := hN n hn G hG
  exact ⟨A, hA, hc⟩

/-- Distinct endpoints never exceed the cut size, so a bisection coefficient
`c` gives a partition family with `κ = ξ = c`. -/
theorem partition_of_bisection {c : ℝ} (h : UniformBisectionBound c) :
    UniformEndpointPartitionBound c c := by
  classical
  intro ε hε
  obtain ⟨N, hN⟩ := h ε hε
  refine ⟨N, fun n hn G hG => ?_⟩
  obtain ⟨A, hA, hc⟩ := hN n hn G hG
  have hX : (((edges G A).image Prod.fst).card : ℝ) ≤ crossingEdges G A := by
    exact_mod_cast (Finset.card_image_le).trans_eq (edges_card G A)
  have hY : (((edges G A).image Prod.snd).card : ℝ) ≤ crossingEdges G A := by
    exact_mod_cast (Finset.card_image_le).trans_eq (edges_card G A)
  exact ⟨A, hA, hc, hX.trans hc, hY.trans hc⟩

private theorem side_estimate_xi (b ξ ε n m x : ℝ)
    (hb : 0 ≤ b) (hb' : b ≤ 1 / 3) (_hξ0 : 0 ≤ ξ) (hξ : ξ ≤ 1 / 6)
    (hε : 0 < ε) (hn : 0 ≤ n)
    (hm : m ≤ n) (hhalf : 2 * m ≤ n + 1)
    (hx : x ≤ (ξ + ε / 4) * n) (hlarge : 1 ≤ ε * n) :
    max x (b * m + (1 - 3 * b) * x) + (ε / 4) * m ≤
      (ξ + (1 / 2 - 3 * ξ) * b + ε) * n := by
  have hd : 0 ≤ 1 - 3 * b := by linarith
  have hxm := mul_le_mul_of_nonneg_left hx hd
  have hbm := mul_le_mul_of_nonneg_left hhalf hb
  have hem := mul_le_mul_of_nonneg_left hm (by linarith : 0 ≤ ε / 4)
  have hlam : 0 ≤ (1 / 2 - 3 * ξ) * b := mul_nonneg (by linarith) hb
  have hlamn : 0 ≤ (1 / 2 - 3 * ξ) * b * n := mul_nonneg hlam hn
  have hbe : 0 ≤ b * (ε * n) := mul_nonneg hb (by nlinarith)
  have hen : 0 ≤ ε * n := by nlinarith
  apply (le_sub_iff_add_le).mp
  apply max_le
  · nlinarith
  · nlinarith

/-- One coefficient step with separate cut and endpoint coefficients. -/
theorem endpoint_coefficient_step (κ ξ b : ℝ) (hξ0 : 0 ≤ ξ) (hξ : ξ ≤ 1 / 6)
    (hb : 0 ≤ b) (hb' : b < 1 / 3)
    (hpart : UniformEndpointPartitionBound κ ξ) (hpw : UniformPathwidthBound b) :
    UniformPathwidthBound (max κ (ξ + (1 / 2 - 3 * ξ) * b)) := by
  classical
  have hend : UniformEndpointBound b := boundaryTransfer b hb hb' hpw
  intro ε hε
  have hε4 : 0 < ε / 4 := by linarith
  obtain ⟨Nc, hNc⟩ := hpart (ε / 4) hε4
  obtain ⟨Ne, hNe⟩ := hend (ε / 4) hε4
  obtain ⟨M, hM⟩ := exists_nat_ge (1 / ε)
  refine ⟨max Nc (max (2 * Ne + 2) M), ?_⟩
  intro n hn G hG
  have hnC : Nc ≤ n := (le_max_left _ _).trans hn
  have hnE : 2 * Ne + 2 ≤ n := (le_trans (le_max_left _ _) (le_max_right _ _)).trans hn
  have hnM : M ≤ n := (le_trans (le_max_right _ _) (le_max_right _ _)).trans hn
  have hlarge : (1 : ℝ) ≤ ε * (n : ℝ) := by
    have hmn : (M : ℝ) ≤ n := by exact_mod_cast hnM
    have h := (div_le_iff₀ hε).mp (hM.trans hmn)
    nlinarith
  obtain ⟨A, hbal, hcut, hXreal, hYreal⟩ := hNc n hnC G hG
  let B := Finset.univ \ A
  let X := (edges G A).image Prod.fst
  let Y := (edges G A).image Prod.snd
  have hBcard : B.card = n - A.card := by
    simpa [B] using Finset.card_sdiff_of_subset (Finset.subset_univ A)
  have hsum : A.card + B.card = n := by
    simpa [B, Nat.add_comm] using Finset.card_sdiff_add_card_eq_card (Finset.subset_univ A)
  have hbalanced : A.card ≤ B.card + 1 ∧ B.card ≤ A.card + 1 := by
    simpa only [IsBisection, ← hBcard] using hbal
  have hAmin : Ne ≤ A.card := by omega
  have hBmin : Ne ≤ B.card := by omega
  have hAn : A.card ≤ n := by omega
  have hBn : B.card ≤ n := by omega
  have hAhalf : 2 * A.card ≤ n + 1 := by omega
  have hBhalf : 2 * B.card ≤ n + 1 := by omega
  have hXsub : X ⊆ A := left_subset G A
  have hYsub : Y ⊆ B := by
    intro v hv
    exact Finset.mem_sdiff.mpr ⟨Finset.mem_univ _, right_not_mem G A hv⟩
  have hleft := hNe A.card hAmin (inducedOnFin G A) (inducedOnFin_subcubic hG A)
    (boundaryPreimage A X)
  have hright := hNe B.card hBmin (inducedOnFin G B) (inducedOnFin_subcubic hG B)
    (boundaryPreimage B Y)
  rw [boundaryPreimage_card A X hXsub] at hleft
  rw [boundaryPreimage_card B Y hYsub] at hright
  have hglue := pathwidth_of_cut_endpoint_bounds G A hleft hright
  apply hglue.mono
  have hSA := side_estimate_xi b ξ ε n A.card X.card hb hb'.le hξ0 hξ hε (Nat.cast_nonneg n)
    (by exact_mod_cast hAn) (by exact_mod_cast hAhalf) hXreal hlarge
  have hSB := side_estimate_xi b ξ ε n B.card Y.card hb hb'.le hξ0 hξ hε (Nat.cast_nonneg n)
    (by exact_mod_cast hBn) (by exact_mod_cast hBhalf) hYreal hlarge
  have hmaxR : (ξ + (1 / 2 - 3 * ξ) * b + ε) * (n : ℝ) ≤
      (max κ (ξ + (1 / 2 - 3 * ξ) * b) + ε) * (n : ℝ) := by
    apply mul_le_mul_of_nonneg_right _ (Nat.cast_nonneg n)
    linarith [le_max_right κ (ξ + (1 / 2 - 3 * ξ) * b)]
  have hmaxK : (κ + ε / 4) * (n : ℝ) ≤ (max κ (ξ + (1 / 2 - 3 * ξ) * b) + ε) * (n : ℝ) := by
    apply mul_le_mul_of_nonneg_right _ (Nat.cast_nonneg n)
    linarith [le_max_left κ (ξ + (1 / 2 - 3 * ξ) * b)]
  apply max_le
  · apply max_le
    · exact hSA.trans hmaxR
    · exact hSB.trans hmaxR
  · exact hcut.trans hmaxK

/-- The contraction map of the transfer. -/
def endpointMap (κ ξ b : ℝ) : ℝ := max κ (ξ + (1 / 2 - 3 * ξ) * b)

/-- Iterates of the transfer from the start value `b0`. -/
def endpointIter (κ ξ b0 : ℝ) : ℕ → ℝ
  | 0 => b0
  | j + 1 => endpointMap κ ξ (endpointIter κ ξ b0 j)

/-- The fixed point `max κ (2ξ/(1+6ξ))`. -/
def endpointFixed (κ ξ : ℝ) : ℝ := max κ (2 * ξ / (1 + 6 * ξ))

theorem endpointMap_range (κ ξ b : ℝ) (hκ0 : 0 ≤ κ) (hκ : κ < 1 / 3)
    (_hξ0 : 0 ≤ ξ) (hξ : ξ ≤ 1 / 6) (_hb : 0 ≤ b) (hb' : b < 1 / 3) :
    0 ≤ endpointMap κ ξ b ∧ endpointMap κ ξ b < 1 / 3 := by
  unfold endpointMap
  constructor
  · exact le_trans hκ0 (le_max_left _ _)
  · apply max_lt hκ
    have hl : 0 ≤ 1 / 2 - 3 * ξ := by linarith
    have := mul_le_mul_of_nonneg_left hb'.le hl
    nlinarith

theorem endpointIter_range (κ ξ b0 : ℝ) (hκ0 : 0 ≤ κ) (hκ : κ < 1 / 3)
    (hξ0 : 0 ≤ ξ) (hξ : ξ ≤ 1 / 6) (hb0 : 0 ≤ b0) (hb0' : b0 < 1 / 3) :
    ∀ j, 0 ≤ endpointIter κ ξ b0 j ∧ endpointIter κ ξ b0 j < 1 / 3 := by
  intro j
  induction j with
  | zero => exact ⟨hb0, hb0'⟩
  | succ j ih => exact endpointMap_range κ ξ _ hκ0 hκ hξ0 hξ ih.1 ih.2

theorem endpointFixed_isFixed (κ ξ : ℝ) (hξ0 : 0 ≤ ξ) (hξ : ξ ≤ 1 / 6) :
    endpointMap κ ξ (endpointFixed κ ξ) = endpointFixed κ ξ := by
  unfold endpointMap endpointFixed
  have hpos : 0 < 1 + 6 * ξ := by linarith
  set β := 2 * ξ / (1 + 6 * ξ) with hβ
  have hβeq : ξ + (1 / 2 - 3 * ξ) * β = β := by
    rw [hβ]; field_simp; ring
  rcases le_total κ β with h | h
  · rw [max_eq_right h, hβeq, max_eq_right h]
  · rw [max_eq_left h]
    have hl : 0 ≤ 1 / 2 - 3 * ξ := by linarith
    have hle : ξ + (1 / 2 - 3 * ξ) * κ ≤ κ := by
      have h1 : (1 / 2 - 3 * ξ) * β ≤ (1 / 2 - 3 * ξ) * κ := mul_le_mul_of_nonneg_left h hl
      -- ξ = β - λβ = (1-λ)β ≤ (1-λ)κ
      nlinarith [hβeq]
    exact max_eq_left hle

theorem endpointMap_lipschitz (κ ξ a b : ℝ) (_hξ0 : 0 ≤ ξ) (hξ : ξ ≤ 1 / 6) :
    |endpointMap κ ξ a - endpointMap κ ξ b| ≤ (1 / 2 - 3 * ξ) * |a - b| := by
  unfold endpointMap
  have hl : 0 ≤ 1 / 2 - 3 * ξ := by linarith
  have key : |max κ (ξ + (1 / 2 - 3 * ξ) * a) - max κ (ξ + (1 / 2 - 3 * ξ) * b)| ≤
      |(ξ + (1 / 2 - 3 * ξ) * a) - (ξ + (1 / 2 - 3 * ξ) * b)| := by
    rw [max_comm κ (ξ + (1 / 2 - 3 * ξ) * a), max_comm κ (ξ + (1 / 2 - 3 * ξ) * b)]
    exact abs_max_sub_max_le_abs _ _ κ
  calc |max κ (ξ + (1 / 2 - 3 * ξ) * a) - max κ (ξ + (1 / 2 - 3 * ξ) * b)|
      ≤ |(ξ + (1 / 2 - 3 * ξ) * a) - (ξ + (1 / 2 - 3 * ξ) * b)| := key
    _ = (1 / 2 - 3 * ξ) * |a - b| := by
        rw [show (ξ + (1 / 2 - 3 * ξ) * a) - (ξ + (1 / 2 - 3 * ξ) * b) =
          (1 / 2 - 3 * ξ) * (a - b) by ring, abs_mul, abs_of_nonneg hl]

theorem endpointIter_close (κ ξ b0 : ℝ) (hξ0 : 0 ≤ ξ) (hξ : ξ ≤ 1 / 6) :
    ∀ j, |endpointIter κ ξ b0 j - endpointFixed κ ξ| ≤
      (1 / 2 - 3 * ξ) ^ j * |b0 - endpointFixed κ ξ| := by
  intro j
  induction j with
  | zero => simp [endpointIter]
  | succ j ih =>
    have hl : 0 ≤ 1 / 2 - 3 * ξ := by linarith
    calc |endpointIter κ ξ b0 (j + 1) - endpointFixed κ ξ|
        = |endpointMap κ ξ (endpointIter κ ξ b0 j) -
            endpointMap κ ξ (endpointFixed κ ξ)| := by
          rw [endpointFixed_isFixed κ ξ hξ0 hξ]; rfl
      _ ≤ (1 / 2 - 3 * ξ) * |endpointIter κ ξ b0 j - endpointFixed κ ξ| :=
          endpointMap_lipschitz κ ξ _ _ hξ0 hξ
      _ ≤ (1 / 2 - 3 * ξ) * ((1 / 2 - 3 * ξ) ^ j * |b0 - endpointFixed κ ξ|) :=
          mul_le_mul_of_nonneg_left ih hl
      _ = (1 / 2 - 3 * ξ) ^ (j + 1) * |b0 - endpointFixed κ ξ| := by ring

/-- Main transfer: a `(κ, ξ)` partition family gives the pathwidth coefficient
`max κ (2ξ/(1+6ξ))`.  The start value `2κ` comes from the proved bootstrap. -/
theorem endpoint_transfer (κ ξ : ℝ) (hκ0 : 0 ≤ κ) (hκ : κ < 1 / 6)
    (hξ0 : 0 ≤ ξ) (hξ : ξ ≤ 1 / 6) (hpart : UniformEndpointPartitionBound κ ξ) :
    UniformPathwidthBound (endpointFixed κ ξ) := by
  have hstart : UniformPathwidthBound (2 * κ) :=
    uniformPathwidthBound_twice_of_bisection hκ0 (uniformBisection_of_partition hpart)
  have hb0 : 0 ≤ 2 * κ := by linarith
  have hb0' : 2 * κ < 1 / 3 := by linarith
  have hrange := endpointIter_range κ ξ (2 * κ) hκ0 (by linarith) hξ0 hξ hb0 hb0'
  have hiter : ∀ j, UniformPathwidthBound (endpointIter κ ξ (2 * κ) j) := by
    intro j
    induction j with
    | zero => simpa [endpointIter] using hstart
    | succ j ih =>
      exact endpoint_coefficient_step κ ξ _ hξ0 hξ (hrange j).1 (hrange j).2 hpart ih
  apply uniformPathwidthBound_of_approximations
  intro η hη
  have hl0 : 0 ≤ 1 / 2 - 3 * ξ := by linarith
  have hl1 : 1 / 2 - 3 * ξ < 1 := by linarith
  set D := |2 * κ - endpointFixed κ ξ| with hD
  have hDpos : 0 < D + 1 := by positivity
  obtain ⟨j, hj⟩ := exists_pow_lt_of_lt_one (div_pos hη hDpos) hl1
  refine ⟨endpointIter κ ξ (2 * κ) j, ?_, hiter j⟩
  have hc := endpointIter_close κ ξ (2 * κ) hξ0 hξ j
  have hpowle : (1 / 2 - 3 * ξ) ^ j * D ≤ (1 / 2 - 3 * ξ) ^ j * (D + 1) := by
    have : 0 ≤ (1 / 2 - 3 * ξ) ^ j := pow_nonneg hl0 j
    nlinarith
  have hlt : (1 / 2 - 3 * ξ) ^ j * (D + 1) < η := by
    have := (lt_div_iff₀ hDpos).mp hj
    linarith
  have habs := (abs_le.mp (hc.trans (hpowle.trans hlt.le))).2
  have : endpointIter κ ξ (2 * κ) j - endpointFixed κ ξ < η := by
    have h2 := hc.trans_lt (lt_of_le_of_lt hpowle hlt)
    exact lt_of_le_of_lt (le_abs_self _) h2
  linarith

/-- General-parameter version of the project's coefficient step: every uniform
bisection coefficient `0 ≤ c < 1/6` gives the pathwidth coefficient `2c/(1+6c)`. -/
theorem bisection_transfer (c : ℝ) (hc0 : 0 ≤ c) (hc : c < 1 / 6)
    (hbis : UniformBisectionBound c) :
    UniformPathwidthBound (2 * c / (1 + 6 * c)) := by
  have h := endpoint_transfer c c hc0 hc hc0 hc.le (partition_of_bisection hbis)
  have hfix : endpointFixed c c = 2 * c / (1 + 6 * c) := by
    unfold endpointFixed
    apply max_eq_right
    have hpos : 0 < 1 + 6 * c := by linarith
    rw [le_div_iff₀ hpos]
    nlinarith
  rw [hfix] at h
  exact h

end CubicPathwidth

#print axioms CubicPathwidth.endpoint_coefficient_step
#print axioms CubicPathwidth.endpoint_transfer
#print axioms CubicPathwidth.bisection_transfer
Back to top