Theory Up

section ‹ Up Part ›

theory Up
imports UpDown_Scheme Triangular_Function
begin

lemma up'_inplace:
  assumes p'_in: "p'  grid p ds" and "d  ds"
  shows "snd (up' d l p α) p' = α p'"
  using p'_in
proof (induct l arbitrary: p α)
  case (Suc l)
  let "?ch dir" = "child p dir d"
  let "?up dir α" = "up' d l (?ch dir) α"
  let "?upl" = "snd (?up left α)"

  from contrapos_nn[OF p'  grid p ds grid_child[OF d  ds]]
  have left: "p'  grid (?ch left) ds" and
       right: "p'  grid (?ch right) ds" by auto

  have "p  p'" using grid.Start Suc.prems by auto
  with Suc.hyps[OF left, of α] Suc.hyps[OF right, of ?upl]
  show ?case
    by (cases "?up left α", cases "?up right ?upl", auto simp add: Let_def)
qed auto

lemma up'_fl_fr:
      " d < length p ; p = (child p_r right d) ; p = (child p_l left d) 
        fst (up' d lm p α) =
              ( p'  lgrid p {d} (lm + level p). (α p') * l2_φ (p' ! d) (p_r ! d),
                p'  lgrid p {d} (lm + level p). (α p') * l2_φ (p' ! d) (p_l ! d))"
proof (induct lm arbitrary: p p_l p_r α)
  case (Suc lm)
  note d < length p[simp]

  from child_ex_neighbour
  obtain pc_r pc_l
    where pc_r_def: "child p right d = child pc_r (inv right) d"
    and pc_l_def: "child p left d = child pc_l (inv left) d" by blast

  define pc where "pc dir = (case dir of right  pc_r | left  pc_l)" for dir
  { fix dir have "child p (inv dir) d = child (pc (inv dir)) dir d"
      by (cases dir, auto simp add: pc_def pc_r_def pc_l_def) } note pc_child = this
  { fix dir have "child p dir d = child (pc dir) (inv dir) d"
      by (cases dir, auto simp add: pc_def pc_r_def pc_l_def) } note pc_child_inv = this
  hence "!! dir. length (child p dir d) = length (child (pc dir) (inv dir) d)" by auto
  hence "!! dir. length p = length (pc dir)" by auto
  hence [simp]: "!! dir. d < length (pc dir)" by auto

  let ?l = "λs. lm + level s"
  let ?C = "λp p'. (α p) * l2_φ (p ! d) (p' ! d)"
  let ?sum' = "λs p''.  p'  lgrid s {d} (Suc lm + level p). ?C p' p''"
  let ?sum = "λs dir p.  p'  lgrid (child s dir d) {d} (?l (child s dir d)). ?C p' p"
  let ?ch = "λdir. child p dir d"
  let ?f = "λdir. ?sum p dir (pc dir)"
  let ?fm = "λdir. ?sum p dir p"
  let ?result = "(?fm left + ?fm right + (α p) / 2 ^ (lv p d) / 2) / 2"
  let ?up = "λlm p α. up' d lm p α"

  define βl where "βl = snd (?up lm (?ch left) α)"
  define βr where "βr = snd (?up lm (?ch right) βl)"

  define p_d where "p_d dir = (case dir of right  p_r | left  p_l)" for dir
  have p_d_child: "p = child (p_d dir) dir d" for dir
    using Suc.prems p_d_def by (cases dir) auto
  hence " dir. length p = length (child (p_d dir) dir d)" by auto
  hence " dir. d < length (p_d dir)" by auto

  { fix dir

    { fix p' assume "p'  lgrid (?ch (inv dir)) {d} (?l (?ch (inv dir))) "
      hence "?C p' (pc (inv dir)) + (?C p' p) / 2 = ?C p' (p_d dir)"
        using l2_zigzag[OF _ p_d_child[of dir] _ pc_child[of dir]]
        by (cases dir) (auto simp add: algebra_simps) }
    hence inv_dir_sum: "?sum p (inv dir) (pc (inv dir)) + (?sum p (inv dir) p) / 2
      = ?sum p (inv dir) (p_d dir)"
      by (auto simp add: sum.distrib[symmetric] sum_divide_distrib)

    have "?sum p dir p / 2 = ?sum p dir (p_d dir)"
      using l2_down2[OF _ _ p = child (p_d dir) dir d]
      by (force intro!: sum.cong simp add: sum_divide_distrib)
    moreover
    have "?C p (p_d dir) = (α p) / 2 ^ (lv p d) / 4"
      using l2_child[OF d < length (p_d dir), of p dir "{d}"] p_d_child[of dir]
      d < length (p_d dir) child_lv child_ix grid.Start[of p "{d}"]
      by (cases dir) (auto simp add: add_divide_distrib field_simps)
    ultimately
    have "?sum' p (p_d dir) =
      ?sum p (inv dir) (pc (inv dir)) +
      (?sum p (inv dir) p) / 2 + ?sum p dir p / 2 + (α p) / 2 ^ (lv p d) / 4"
      using lgrid_sum[where b=p] and child_level and inv_dir_sum
      by (cases dir) auto
    hence "?sum p (inv dir) (pc (inv dir)) + ?result = ?sum' p (p_d dir)"
      by (cases dir) auto }
  note this[of left] this[of right]
  moreover
  note eq = up'_inplace[OF grid_not_child[OF d < length p], of d "{d}" lm]
  { fix p' assume "p'  lgrid (?ch right) {d} (lm + level (?ch right))"
    with grid_disjunct[of d p] up'_inplace[of p' "?ch left" "{d}" d lm α] βl_def
    have "βl p' = α p'" by auto }
  hence "fst (?up (Suc lm) p α) = (?f left + ?result, ?f right + ?result)"
    using βl_def pc_child_inv[of left] pc_child_inv[of right]
      Suc.hyps[of "?ch left" "pc left" p α] eq[of left α]
      Suc.hyps[of "?ch right" p "pc right" βl] eq[of right βl]
    by (cases "?up lm (?ch left) α", cases "?up lm (?ch right) βl") (simp add: Let_def)
  ultimately show ?case by (auto simp add: p_d_def)
next
  case 0
  show ?case by simp
qed

lemma up'_β:
  " d < length b ; l + level b = lm ; b  sparsegrid' dm ; p  sparsegrid' dm 
   
   (snd (up' d l b α)) p =
     (if p  lgrid b {d} lm
      then  p'  (lgrid p {d} lm) - {p}. α p' * l2_φ (p' ! d) (p ! d)
      else α p)"
  (is " _ ; _ ; _ ; _   (?goal l b p α)")
proof (induct l arbitrary: b p α)
  case (Suc l)

  let ?l = "child b left d" and ?r = "child b right d"
  obtain p_l where p_l_def: "?r = child p_l left d" using child_ex_neighbour[where dir=right] by auto
  obtain p_r where p_r_def: "?l = child p_r right d" using child_ex_neighbour[where dir=left] by auto

  let ?ul = "up' d l ?l α"
  let ?ur = "up' d l ?r (snd ?ul)"

  let "?C p'" = "α p' * l2_φ (p' ! d) (p ! d)"
  let "?s s" = " p'  (lgrid s {d} lm). ?C p'"

  from b  sparsegrid' dm have "length b = dm" unfolding sparsegrid'_def start_def
    by auto
  hence "d < dm" using d < length b by auto

  { fix p' assume "p'  grid ?r {d}"
    hence "p'  grid ?l {d}"
      using grid_disjunct[OF d < length b] by auto
    hence "snd ?ul p' = α p'" using up'_inplace by auto
  } note eq = this

  show "?goal (Suc l) b p α"
  proof (cases "p = b")
    case True

    let "?C p'" = "α p' * l2_φ (p' ! d) (b ! d)"
    let "?s s" = " p'  (lgrid s {d} lm). ?C p'"

    have "d < length ?l" using d < length b by auto
    from up'_fl_fr[OF this p_r_def]
    have fml: "snd (fst ?ul) = ( p'  lgrid ?l {d} (l + level ?l). ?C p')" by simp

    have "d < length ?r" using d < length b by auto
    from up'_fl_fr[OF this _ p_l_def, where α="snd ?ul"]
    have fmr: "fst (fst ?ur) = ( p'  lgrid ?r {d} (l + level ?r).
                                ((snd ?ul) p') * l2_φ (p' ! d) (b ! d))" by simp

    have "level b < lm" using Suc l + level b = lm by auto
    hence "{ b }  lgrid b {d} lm" unfolding lgrid_def by auto
    from sum_diff[OF lgrid_finite this]
    have "( p'  (lgrid b {d} lm) - {b}. ?C p') = ?s b - ?C b" by simp
    also have " = ?s ?l + ?s ?r"
      using lgrid_sum and level b < lm and d < length b by auto
    also have " = snd (fst ?ul) + fst (fst ?ur)" using fml and fmr
      and Suc l + level b = lm and child_level[OF d < length b]
      using eq unfolding True lgrid_def by auto

    finally show ?thesis unfolding up'.simps Let_def and fun_upd_def lgrid_def
      using p = b and level b < lm
      by (cases ?ul, cases ?ur, auto)
  next
    case False

    have "?r  sparsegrid' dm" and "?l  sparsegrid' dm"
      using b  sparsegrid' dm and d < dm unfolding sparsegrid'_def by auto
    from Suc.hyps[OF _ _ this(1)] Suc.hyps[OF _ _ this(2)]
    have "?goal l ?l p α" and "?goal l ?r p (snd ?ul)"
      using d < length b and Suc l + level b = lm and p  sparsegrid' dm by auto

    show ?thesis
    proof (cases "p  lgrid b {d} lm")
      case True
      hence "level p < lm" and "p  grid b {d}" unfolding lgrid_def by auto
      hence "p  grid ?l {d}  p  grid ?r {d}"
        unfolding grid_partition[of b] using p  b by auto
      thus ?thesis
      proof (rule disjE)
        assume "p  grid (child b left d) {d}"
        hence "p  grid (child b right d) {d}"
          using grid_disjunct[OF d < length b] by auto
        thus ?thesis
          using ?goal l ?l p α and ?goal l ?r p (snd ?ul)
          using p  b p  lgrid b {d} lm
          unfolding lgrid_def grid_partition[of b]
          by (cases ?ul, cases ?ur, auto simp add: Let_def)
      next
        assume *: "p  grid (child b right d) {d}"
        hence "p  grid (child b left d) {d}"
          using grid_disjunct[OF d < length b] by auto
        moreover
        { fix p' assume "p'  grid p {d}"
          from grid_transitive[OF this *] eq[of p']
          have "snd ?ul p' = α p'" by simp
        }
        ultimately show ?thesis
          using ?goal l ?l p α and ?goal l ?r p (snd ?ul)
          using p  b p  lgrid b {d} lm *
          unfolding lgrid_def
          by (cases ?ul, cases ?ur, auto simp add: Let_def)
  qed
next
      case False
      then have "p  lgrid ?l {d} lm" and "p  lgrid ?r {d} lm"
        unfolding lgrid_def and grid_partition[where p=b] by auto
      with False show ?thesis using ?goal l ?l p α and ?goal l ?r p (snd ?ul)
        using p  b p  lgrid b {d} lm
        unfolding lgrid_def
        by (cases ?ul, cases ?ur, auto simp add: Let_def)
    qed
  qed
next
  case 0
  then have "lgrid b {d} lm = {}"
    using lgrid_empty'[where p=b and lm=lm and ds="{d}"] by auto
  with 0 show ?case unfolding up'.simps by auto
qed

lemma up:
  assumes "d < dm" and "p  sparsegrid dm lm"
  shows "(up dm lm d α) p = ( p'  (lgrid p {d} lm) - {p}. α p' * l2_φ (p' ! d) (p ! d))"
proof -
  let ?S = "λ x p p'. if p'  grid p {d} - {p} then x * l2_φ (p'!d) (p!d) else 0"
  let ?F = "λ d lm p α. snd (up' d lm p α)"

  { fix p b assume "p  grid b {d}"
    from grid_transitive[OF _ this subset_refl subset_refl]
    have "lgrid b {d} lm  (grid p {d} - {p}) = lgrid p {d} lm - {p}"
      unfolding lgrid_def by auto
  } note lgrid_eq = this

  { fix l b p α
    assume b: "b  lgrid (start dm) ({0..<dm} - {d}) lm"
    hence "b  sparsegrid' dm" and "d < length b" using sparsegrid'_start d < dm by auto
    assume l: "l + level b = lm" and p: "p  sparsegrid dm lm"
    note sparsegridE[OF p]

    note up' = up'_β[OF d < length b l b  sparsegrid' dm p  sparsegrid' dm]

    have "?F d l b α p =
          (if b = base {d} p then (p'lgrid b {d} lm. ?S (α p') p p') else α p)"
    proof (cases "b = base {d} p")
      case True with baseE(2)[OF p  sparsegrid' dm] level p < lm
      have "p  lgrid b {d} lm" and "p  grid b {d}" by auto
      show ?thesis
        using lgrid_eq[OF p  grid b {d}]
        unfolding up' if_P[OF True] if_P[OF p  lgrid b {d} lm]
        by (intro sum.mono_neutral_cong_left lgrid_finite) auto
    next
      case False
      moreover have "p  lgrid b {d} lm"
      proof (rule ccontr)
        assume "¬ ?thesis"
        hence "base {d} p = b" using b by (auto intro!: baseI)
        thus False using False by auto
      qed
      ultimately show ?thesis unfolding up' by auto
    qed }
  with lift[where F = ?F, OF d < dm p  sparsegrid dm lm]
  have lift_eq: "lift ?F dm lm d α p =
         (p'lgrid (base {d} p) {d} lm. ?S (α p') p p')" by auto
  from lgrid_eq[OF baseE(2)[OF sparsegrid_subset[OF p  sparsegrid dm lm]]]
  show ?thesis
    unfolding up_def lift_eq by (intro sum.mono_neutral_cong_right lgrid_finite) auto
qed

end