import Erdos1135.ND.Density.NatDilate

/-!
# Natural Density From Varying Odd Two-Adic Layers

This file closes the generic density-assembly part of the P4 hard-interface
pilot.  The source set may vary with the two-adic exponent, as required by
the frozen ND-1.6 to ND-1.3 transfer.
-/

namespace Erdos1135
namespace ND

open Filter
open scoped BigOperators Topology

private theorem half_div_natCast_powTwo (a : ℕ) :
    (1 / 2 : ℝ) / (((2 : ℕ) ^ a : ℕ) : ℝ) =
      (1 / 2 : ℝ) ^ (a + 1) := by
  simp only [Nat.cast_pow, Nat.cast_ofNat, pow_succ, div_eq_mul_inv,
    one_mul, inv_pow]
  exact mul_comm _ _

private theorem sum_half_pow_succ (K : ℕ) :
    (∑ a ∈ Finset.range K, (1 / 2 : ℝ) ^ (a + 1)) =
      1 - (1 / 2 : ℝ) ^ K := by
  induction K with
  | zero => simp
  | succ K ih =>
      rw [Finset.sum_range_succ, ih, pow_succ]
      ring

private theorem disjoint_powTwo_natDilate_of_odd
    (G : ℕ → Set ℕ) (hodd : ∀ a {M : ℕ}, M ∈ G a → Odd M)
    {a b : ℕ} (hab : a ≠ b) :
    Disjoint
      (Tao.natDilate ((2 : ℕ) ^ a) (G a))
      (Tao.natDilate ((2 : ℕ) ^ b) (G b)) := by
  rw [Set.disjoint_left]
  intro N hNa hNb
  rcases (Tao.mem_natDilate_iff_exists_mul
      (Nat.pow_pos (by norm_num : 0 < (2 : ℕ)))).mp hNa with
    ⟨Ma, hMa, rfl⟩
  rcases (Tao.mem_natDilate_iff_exists_mul
      (Nat.pow_pos (by norm_num : 0 < (2 : ℕ)))).mp hNb with
    ⟨Mb, hMb, hEq⟩
  apply hab
  calc
    a = Terras.twoAdicExponent ((2 : ℕ) ^ a * Ma) :=
      (Tao.twoAdicExponent_pow_mul_odd (hodd a hMa)).symm
    _ = Terras.twoAdicExponent ((2 : ℕ) ^ b * Mb) :=
      congrArg Terras.twoAdicExponent hEq
    _ = b := Tao.twoAdicExponent_pow_mul_odd (hodd b hMb)

private theorem hasNatDensity_finite_powTwo_odd_dilates
    (G : ℕ → Set ℕ)
    (hodd : ∀ a {M : ℕ}, M ∈ G a → Odd M)
    (hdens : ∀ a, Terras.HasNatDensity (G a) (1 / 2 : ℝ))
    (K : ℕ) :
    Terras.HasNatDensity
      (Terras.finsetSetUnion (Finset.range K)
        (fun a => Tao.natDilate ((2 : ℕ) ^ a) (G a)))
      (1 - (1 / 2 : ℝ) ^ K) := by
  have hlayer (a : ℕ) :
      Terras.HasNatDensity
        (Tao.natDilate ((2 : ℕ) ^ a) (G a))
        ((1 / 2 : ℝ) ^ (a + 1)) := by
    rw [← half_div_natCast_powTwo a]
    exact hasNatDensity_natDilate (hdens a) ((2 : ℕ) ^ a)
      (Nat.pow_pos (by norm_num : 0 < (2 : ℕ)))
  have hfinite :=
    Terras.HasNatDensity.finsetSetUnion_of_pairwise_disjoint
      (Finset.range K)
      (fun a => Tao.natDilate ((2 : ℕ) ^ a) (G a))
      (fun a => (1 / 2 : ℝ) ^ (a + 1))
      (by
        intro a _ha
        exact hlayer a)
      (by
        intro a _ha b _hb hab
        exact disjoint_powTwo_natDilate_of_odd G hodd hab)
  rw [sum_half_pow_succ K] at hfinite
  exact hfinite

/-- If every varying odd source fiber has ambient density `1/2`, and all of
its power-of-two dilates lie in `A`, then `A` has natural density one.

For a fixed cutoff `K`, the first `K` dilates are disjoint and have total
density `1 - (1/2)^K`.  These finite lower approximations tend to density one;
no countable-union closure for natural density is used.
-/
theorem hasNatDensity_one_of_powTwo_odd_dilates
    {A : Set ℕ} (G : ℕ → Set ℕ)
    (hodd : ∀ a {M : ℕ}, M ∈ G a → Odd M)
    (hdens : ∀ a, Terras.HasNatDensity (G a) (1 / 2 : ℝ))
    (hsub : ∀ a, Tao.natDilate ((2 : ℕ) ^ a) (G a) ⊆ A) :
    Terras.HasNatDensity A 1 := by
  refine Terras.HasNatDensity.of_superset_of_tendsto_one
    (A := fun K =>
      Terras.finsetSetUnion (Finset.range K)
        (fun a => Tao.natDilate ((2 : ℕ) ^ a) (G a)))
    (S := A) (d := fun K => 1 - (1 / 2 : ℝ) ^ K) ?_ ?_ ?_
  · intro K N hN
    rcases hN with ⟨a, _ha, hNa⟩
    exact hsub a hNa
  · intro K
    exact hasNatDensity_finite_powTwo_odd_dilates G hodd hdens K
  · have hpow :
        Tendsto (fun K : ℕ => (1 / 2 : ℝ) ^ K) atTop (nhds 0) :=
      tendsto_pow_atTop_nhds_zero_of_lt_one (by norm_num) (by norm_num)
    have hlimit :
        Tendsto (fun K : ℕ => (1 : ℝ) - (1 / 2 : ℝ) ^ K)
          atTop (nhds ((1 : ℝ) - 0)) :=
      tendsto_const_nhds.sub hpow
    simpa using hlimit

end ND
end Erdos1135
