import Erdos1135.Tao.Section5.NoHitRate
import Erdos1135.Tao.Syracuse.TimeBounded

/-!
# Section 5 scheduled no-hit estimate

The existing no-hit proof is driven by deterministic descent at the literal
time `taoSection5N0 B`.  This leaf retains that witness and proves the same
polynomial error for failure to hit by the scheduled time.
-/

namespace Erdos1135
namespace Tao

noncomputable section

open Filter

/-- Probability that a source in one odd logarithmic window has not hit `B`
within `T` Syracuse steps. -/
noncomputable def syracuseNoHitWithinWindowProb
    (B T lo hi : ℕ)
    (hmass : 0 < logFinsetMass (oddLogWindow lo hi)) : ℝ :=
  pmfProb (oddLogWindowPMF lo hi hmass)
    {N : {n : ℕ // n ∈ oddLogWindow lo hi} |
      ¬ syracuseHitsAtMostWithin (N : ℕ) B T}

theorem syracuseNoHitWithinWindowProb_eq_logFinsetProb
    (B T lo hi : ℕ)
    (hmass : 0 < logFinsetMass (oddLogWindow lo hi)) :
    syracuseNoHitWithinWindowProb B T lo hi hmass =
      logFinsetProb (oddLogWindow lo hi)
        {N : ℕ | ¬ syracuseHitsAtMostWithin N B T} := by
  unfold syracuseNoHitWithinWindowProb
  simpa using pmfProb_oddLogWindowPMF lo hi hmass
    {N : ℕ | ¬ syracuseHitsAtMostWithin N B T}

theorem syracuseNoHitWithinWindowProb_le_one
    (B T lo hi : ℕ)
    (hmass : 0 < logFinsetMass (oddLogWindow lo hi)) :
    syracuseNoHitWithinWindowProb B T lo hi hmass ≤ 1 := by
  unfold syracuseNoHitWithinWindowProb
  calc
    pmfProb (oddLogWindowPMF lo hi hmass)
        {N : {N : ℕ // N ∈ oddLogWindow lo hi} |
          ¬ syracuseHitsAtMostWithin (N : ℕ) B T} ≤
      pmfProb (oddLogWindowPMF lo hi hmass) Set.univ :=
        pmfProb_mono _ (Set.subset_univ _)
    _ = 1 := pmfProb_univ _

/-- A pointwise scheduled-failure-to-valuation-event implication transports
the finite source probability into the actual valuation-law event mass. -/
theorem syracuseNoHitWithinWindowProb_le_actualValuationLaw_event
    (B T lo hi n : ℕ)
    (hmass : 0 < logFinsetMass (oddLogWindow lo hi))
    (E : Set (List ℕ+))
    (hpoint : ∀ N : {N : ℕ // N ∈ oddLogWindow lo hi},
      ¬ syracuseHitsAtMostWithin (N : ℕ) B T →
        syracuseValuationPNatList n
          (oddLogWindowValueToOddNat N).1
          (oddLogWindowValueToOddNat N).2 ∈ E) :
    syracuseNoHitWithinWindowProb B T lo hi hmass ≤
      ((taoProp19ActualValuationLaw
        (oddLogWindowOddNatPMF lo hi hmass) n).toOuterMeasure E).toReal := by
  unfold syracuseNoHitWithinWindowProb
  calc
    pmfProb (oddLogWindowPMF lo hi hmass)
        {N : {N : ℕ // N ∈ oddLogWindow lo hi} |
          ¬ syracuseHitsAtMostWithin (N : ℕ) B T} ≤
      pmfProb (oddLogWindowPMF lo hi hmass)
        {N : {N : ℕ // N ∈ oddLogWindow lo hi} |
          syracuseValuationPNatList n
            (oddLogWindowValueToOddNat N).1
            (oddLogWindowValueToOddNat N).2 ∈ E} := by
      exact pmfProb_mono (oddLogWindowPMF lo hi hmass) hpoint
    _ = ((taoProp19ActualValuationLaw
          (oddLogWindowOddNatPMF lo hi hmass) n).toOuterMeasure E).toReal := by
      rw [pmfProb_eq_toOuterMeasure_toReal]
      unfold taoProp19ActualValuationLaw oddLogWindowOddNatPMF
      rw [PMF.toOuterMeasure_map_apply, PMF.toOuterMeasure_map_apply]
      apply congrArg ENNReal.toReal
      apply congrArg (oddLogWindowPMF lo hi hmass).toOuterMeasure
      ext N
      rfl

/-- Failure to hit by the literal Section 5 time forces the same strict
low-valuation event used by the eventual no-hit proof. -/
theorem TaoSection5DescentScaleFacts.actualValuations_mem_low_of_not_hitsWithin
    {B : ℕ} (facts : TaoSection5DescentScaleFacts B)
    {N : {N : ℕ // Odd N}} {branch : TaoSection5SourceBranch}
    (hmem : N.1 ∈ oddLogWindow
      (taoSection5SourceLo B branch) (taoSection5SourceHi B branch))
    (hno : ¬ syracuseHitsAtMostWithin N.1 B (taoSection5N0 B)) :
    syracuseValuationPNatList (taoSection5N0 B) N.1 N.2 ∈
      taoLowValuationWeightEvent (taoSection5N0 B) := by
  change
    10 * taoTupleWeight
        (syracuseValuationPNatList (taoSection5N0 B) N.1 N.2) <
      19 * taoSection5N0 B
  by_contra hlow
  have hweight :
      19 * taoSection5N0 B ≤
        10 * taoTupleWeight
          (syracuseValuationPNatList (taoSection5N0 B) N.1 N.2) := by
    omega
  apply hno
  exact ⟨taoSection5N0 B, le_rfl,
    facts.iterate_le_threshold hmem hweight⟩

/-- The native Section 5 comparison gives the original error bound for
failure to hit by the scheduled time. -/
theorem taoSection5_noHitWithinScheduleWindowProb_le_error_of_inputs
    {B : ℕ} (descent : TaoSection5DescentScaleFacts B)
    (prop19 : TaoSection5LogWindowProp19Output B)
    (branch : TaoSection5SourceBranch)
    (hmass : 0 < logFinsetMass
      (oddLogWindow (taoSection5SourceLo B branch)
        (taoSection5SourceHi B branch))) :
    syracuseNoHitWithinWindowProb B (taoSection5N0 B)
        (taoSection5SourceLo B branch)
        (taoSection5SourceHi B branch) hmass ≤
      taoSection5NoHitError B := by
  have hmassEq : hmass = prop19.schedule.mass_pos branch :=
    Subsingleton.elim _ _
  subst hmass
  let lo := taoSection5SourceLo B branch
  let hi := taoSection5SourceHi B branch
  let n := taoSection5N0 B
  let source := oddLogWindowOddNatPMF lo hi (prop19.schedule.mass_pos branch)
  let E := taoLowValuationWeightEvent n
  have hmap :
      syracuseNoHitWithinWindowProb B n lo hi
          (prop19.schedule.mass_pos branch) ≤
        ((taoProp19ActualValuationLaw source n).toOuterMeasure E).toReal := by
    apply syracuseNoHitWithinWindowProb_le_actualValuationLaw_event
    intro N hno
    apply descent.actualValuations_mem_low_of_not_hitsWithin
      (N := oddLogWindowValueToOddNat N)
    · exact N.property
    · simpa only [n, lo, hi] using hno
  have hvaluation := prop19.valuationBound branch
  unfold taoProp19ValuationTV at hvaluation
  have hcompare :
      ((taoProp19ActualValuationLaw source n).toOuterMeasure E).toReal ≤
        ((geom2PNatListPMF n).toOuterMeasure E).toReal +
          4 * (2 : ℝ) ^ (-((1 / 128 : ℝ) * (n : ℝ))) := by
    apply pmfOuterMass_le_add_of_taoPMFFullL1_le
    simpa only [source, n, lo, hi] using hvaluation
  have hideal := geom2PNatListPMF_lowWeightEvent_le_exp n
  calc
    syracuseNoHitWithinWindowProb B n lo hi
        (prop19.schedule.mass_pos branch) ≤
      ((taoProp19ActualValuationLaw source n).toOuterMeasure E).toReal := hmap
    _ ≤ ((geom2PNatListPMF n).toOuterMeasure E).toReal +
        4 * (2 : ℝ) ^ (-((1 / 128 : ℝ) * (n : ℝ))) := hcompare
    _ ≤ Real.exp (-((n : ℝ) / 3200)) +
        4 * (2 : ℝ) ^ (-((1 / 128 : ℝ) * (n : ℝ))) := by
      exact add_le_add (by simpa only [E] using hideal) le_rfl
    _ = taoSection5NoHitError B := by
      rfl

/-- Scheduled failure has the same explicit polynomial rate as the checked
eventual no-hit output. -/
theorem TaoSection5NoHitRateOutput.noHitWithinSchedule_le
    {B : ℕ} (rate : TaoSection5NoHitRateOutput B)
    (branch : TaoSection5SourceBranch)
    (hmass : 0 < logFinsetMass
      (oddLogWindow (taoSection5SourceLo B branch)
        (taoSection5SourceHi B branch))) :
    syracuseNoHitWithinWindowProb B (taoSection5N0 B)
        (taoSection5SourceLo B branch)
        (taoSection5SourceHi B branch) hmass ≤
      10 * (B : ℝ) ^ (-(1 / 32000 : ℝ)) := by
  exact (taoSection5_noHitWithinScheduleWindowProb_le_error_of_inputs
    rate.output.descent rate.output.prop19 branch hmass).trans rate.error_le

/-- Both canonical source branches satisfy the scheduled polynomial no-hit
rate for all sufficiently large thresholds. -/
theorem eventually_taoSection5_noHitWithinSchedule_le :
    ∀ᶠ B : ℕ in atTop,
      ∀ branch : TaoSection5SourceBranch,
        ∀ hmass : 0 < logFinsetMass
          (oddLogWindow (taoSection5SourceLo B branch)
            (taoSection5SourceHi B branch)),
          syracuseNoHitWithinWindowProb B (taoSection5N0 B)
              (taoSection5SourceLo B branch)
              (taoSection5SourceHi B branch) hmass ≤
            10 * (B : ℝ) ^ (-(1 / 32000 : ℝ)) := by
  filter_upwards [eventually_taoSection5NoHitRateOutput] with B rate
  intro branch hmass
  exact rate.noHitWithinSchedule_le branch hmass

end

end Tao
end Erdos1135
