@@ -107,6 +107,22 @@ theorem embedSum_succ_zero {n : Fin (m + 1) → ℕ} {j : Fin (n 0)} :
107107theorem embedSum_succ_succ {n : Fin (m + 1 ) → ℕ} {i : Fin m} (j : Fin (n i.succ)) :
108108 embedSum (i.succ) j = Fin.natAdd _ (embedSum i j) := rfl
109109
110+ /-- The underlying value of `embedSum i j` is the sum of `n` over all indices before `i`,
111+ plus the value of `j`. -/
112+ theorem val_embedSum {m : ℕ} {n : Fin m → ℕ} (i : Fin m) (j : Fin (n i)) :
113+ (embedSum i j).val = (∑ i' : Fin i.val, n (castLE i.isLt.le i')) + j.val := by
114+ induction m with
115+ | zero => exact Fin.elim0 i
116+ | succ m ih =>
117+ induction i using Fin.cases with
118+ | zero => simp
119+ | succ i =>
120+ have key : (∑ i' : Fin i.succ.val, n (castLE i.succ.isLt.le i'))
121+ = n 0 + ∑ i' : Fin i.val, n ((castLE i.isLt.le i').succ) :=
122+ Fin.sum_univ_succ (fun i' : Fin (i.val + 1 ) => n (castLE i.succ.isLt.le i'))
123+ rw [embedSum_succ_succ, val_natAdd, ih (n := fun i => n i.succ) i j]
124+ omega
125+
110126/-- Split a vector sum index `k : Fin (vsum n)` into nested indices `(i : Fin m) × Fin (n i)`.
111127This converts from indexing into the vector sum back to nested indexing, inverse of `embedSum`. -/
112128def splitSum {m : ℕ} {n : Fin m → ℕ} (k : Fin (vsum n)) : (i : Fin m) × Fin (n i) := match m with
@@ -253,16 +269,6 @@ theorem vflatten_one {n : Fin 1 → ℕ} {v : (i : Fin 1) → Fin (n i) → α}
253269theorem vflatten_two_eq_append {n : Fin 2 → ℕ} {v : (i : Fin 2 ) → Fin (n i) → α} :
254270 vflatten v = vappend (v 0 ) (v 1 ) := rfl
255271
256- theorem vflatten_eq_vappend_last {m : ℕ} {n : Fin (m + 1 ) → ℕ}
257- {v : (i : Fin (m + 1 )) → Fin (n i) → α} :
258- vflatten v =
259- vappend (vflatten (fun i => v i.castSucc)) (v (last _)) ∘ Fin.cast vsum_castSucc := by
260- induction m with
261- | zero => ext i; simp
262- | succ m ih =>
263- rw [vflatten_succ, ih, vflatten_succ]
264- sorry
265-
266272@[simp]
267273theorem vflatten_splitSum {m : ℕ} {n : Fin m → ℕ} (v : (k : Fin (vsum n)) → α) (k : Fin (vsum n)) :
268274 vflatten (fun i j => v (embedSum i j)) k = v k :=
@@ -273,6 +279,33 @@ theorem vflatten_embedSum {m : ℕ} {n : Fin m → ℕ} (v : (i : Fin m) → Fin
273279 (j : Fin (n i)) : vflatten v (embedSum i j) = v i j :=
274280 dflatten_embedSum (motive := fun _ => α) v i j
275281
282+ theorem vflatten_eq_vappend_last {m : ℕ} {n : Fin (m + 1 ) → ℕ}
283+ {v : (i : Fin (m + 1 )) → Fin (n i) → α} :
284+ vflatten v =
285+ vappend (vflatten (fun i => v i.castSucc)) (v (last _)) ∘ Fin.cast vsum_castSucc := by
286+ funext k
287+ have hk : embedSum (splitSum k).1 (splitSum k).2 = k := embedSum_splitSum k
288+ rcases hs : splitSum k with ⟨i, j⟩
289+ rw [hs] at hk
290+ clear hs
291+ subst hk
292+ dsimp only
293+ rw [vflatten_embedSum, Function.comp_apply]
294+ induction i using Fin.lastCases with
295+ | last =>
296+ refine (vappend_right (vflatten fun i => v i.castSucc) (v (last m)) j).symm.trans ?_
297+ congr 1
298+ apply Fin.ext
299+ simp only [Fin.val_natAdd, Fin.val_cast, val_embedSum, Fin.val_last, vsum_eq_univ_sum]
300+ rfl
301+ | cast i =>
302+ refine (vflatten_embedSum (fun i => v i.castSucc) i j).symm.trans ?_
303+ rw [← vappend_left (vflatten fun i => v i.castSucc) (v (last m)) (embedSum i j)]
304+ congr 1
305+ apply Fin.ext
306+ simp only [Fin.val_castAdd, Fin.val_cast, val_embedSum, Fin.val_castSucc]
307+ rfl
308+
276309/-- Functorial flatten: flattens a nested heterogeneous tuple
277310`(i : Fin m) → (j : Fin (n i)) → F (α i j)` into a single heterogeneous tuple with type
278311`(k : Fin (vsum n)) → F (vflatten α k)` where `vflatten` operates on the vector of types `α`.
@@ -309,13 +342,6 @@ theorem fflatten_two_eq_append {A : Sort u} {F : A → Sort v} {n : Fin 2 →
309342 {v : (i : Fin 2 ) → (j : Fin (n i)) → F (α i j)} :
310343 fflatten v = fappend (F := F) (v 0 ) (v 1 ) := rfl
311344
312- @[simp]
313- theorem fflatten_splitSum {A : Sort u} {F : A → Sort v} {m : ℕ} {n : Fin m → ℕ}
314- {α : (i : Fin (vsum n)) → A}
315- (v : (k : Fin (vsum n)) → F (α k)) (k : Fin (vsum n)) :
316- fflatten (fun i j => v (embedSum i j)) k = cast (by simp) (v k) := by
317- sorry
318-
319345@[simp]
320346theorem fflatten_embedSum {A : Sort u} {F : A → Sort v} {m : ℕ} {n : Fin m → ℕ}
321347 {α : (i : Fin m) → (j : Fin (n i)) → A}
@@ -334,6 +360,18 @@ theorem fflatten_embedSum {A : Sort u} {F : A → Sort v} {m : ℕ} {n : Fin m
334360 erw [fappend_right, ih (fun i => v i.succ) i j, _root_.cast_cast]
335361 rfl
336362
363+ @[simp]
364+ theorem fflatten_splitSum {A : Sort u} {F : A → Sort v} {m : ℕ} {n : Fin m → ℕ}
365+ {α : (i : Fin (vsum n)) → A}
366+ (v : (k : Fin (vsum n)) → F (α k)) (k : Fin (vsum n)) :
367+ fflatten (fun i j => v (embedSum i j)) k = cast (by simp) (v k) := by
368+ have hk : embedSum (splitSum k).1 (splitSum k).2 = k := embedSum_splitSum k
369+ rcases hs : splitSum k with ⟨i, j⟩
370+ rw [hs] at hk
371+ clear hs
372+ subst hk
373+ exact fflatten_embedSum _ i j
374+
337375/-- Functorial flatten with two arguments: flattens two nested heterogeneous tuple
338376`(i : Fin m) → (j : Fin (n i)) → F (α i j)` into a single heterogeneous tuple with type
339377`(k : Fin (vsum n)) → F (vflatten α k)` where `vflatten` operates on the vector of types `α`.
@@ -375,14 +413,6 @@ theorem fflatten₂_two_eq_append {A : Sort u} {B : Sort v} {F : A → B → Sor
375413 {v : (i : Fin 2 ) → (j : Fin (n i)) → F (α i j) (β i j)} :
376414 fflatten₂ v = fappend₂ (F := F) (v 0 ) (v 1 ) := rfl
377415
378- @[simp]
379- theorem fflatten₂_splitSum {A : Sort u} {B : Sort v} {F : A → B → Sort w} {m : ℕ} {n : Fin m → ℕ}
380- {α : (i : Fin m) → (j : Fin (n i)) → A}
381- {β : (i : Fin m) → (j : Fin (n i)) → B}
382- (v : (k : Fin (vsum n)) → F (vflatten α k) (vflatten β k)) (k : Fin (vsum n)) :
383- fflatten₂ (fun i j => v (embedSum i j)) k = cast (by simp) (v k) := by
384- sorry
385-
386416@[simp]
387417theorem fflatten₂_embedSum {A : Sort u} {B : Sort v} {F : A → B → Sort w} {m : ℕ} {n : Fin m → ℕ}
388418 {α : (i : Fin m) → (j : Fin (n i)) → A}
@@ -402,6 +432,19 @@ theorem fflatten₂_embedSum {A : Sort u} {B : Sort v} {F : A → B → Sort w}
402432 erw [fappend₂_right, ih (fun i => v i.succ) i j, _root_.cast_cast]
403433 rfl
404434
435+ @[simp]
436+ theorem fflatten₂_splitSum {A : Sort u} {B : Sort v} {F : A → B → Sort w} {m : ℕ} {n : Fin m → ℕ}
437+ {α : (i : Fin m) → (j : Fin (n i)) → A}
438+ {β : (i : Fin m) → (j : Fin (n i)) → B}
439+ (v : (k : Fin (vsum n)) → F (vflatten α k) (vflatten β k)) (k : Fin (vsum n)) :
440+ fflatten₂ (fun i j => v (embedSum i j)) k = cast (by simp) (v k) := by
441+ have hk : embedSum (splitSum k).1 (splitSum k).2 = k := embedSum_splitSum k
442+ rcases hs : splitSum k with ⟨i, j⟩
443+ rw [hs] at hk
444+ clear hs
445+ subst hk
446+ exact fflatten₂_embedSum _ i j
447+
405448/-- Heterogeneous flatten: flattens a nested heterogeneous tuple
406449`(i : Fin m) → (j : Fin (n i)) → α i j` into a single heterogeneous tuple with type
407450`(k : Fin (vsum n)) → vflatten α k` where `vflatten` operates on the vector of types `α`.
@@ -478,9 +521,30 @@ def ranges {n : ℕ} (a : Fin n → ℕ) : (i : Fin n) → Fin (a i) → ℕ :=
478521def divSum? {m : ℕ} (n : Fin m → ℕ) (k : ℕ) : Option (Fin m) :=
479522 Fin.find? (fun i => k < ∑ j, n (castLE i.isLt j))
480523
524+ /-- The sum of `n` over the first `i + 1` indices is at most the total sum. -/
525+ theorem partialSum_le_sum {m : ℕ} (n : Fin m → ℕ) (i : Fin m) :
526+ ∑ j : Fin (i.val + 1 ), n (castLE i.isLt j) ≤ ∑ j, n j := by
527+ have h : (i.val + 1 ) + (m - i.val - 1 ) = m := by omega
528+ conv_rhs => rw [← Fin.sum_congr' n h, Fin.sum_univ_add]
529+ refine le_of_eq_of_le (Finset.sum_congr rfl fun j _ => ?_) (Nat.le_add_right _ _)
530+ rfl
531+
481532theorem divSum?_is_some_iff_lt_sum {m : ℕ} {n : Fin m → ℕ} {k : ℕ} :
482533 (divSum? n k).isSome ↔ k < ∑ i, n i := by
483- sorry
534+ rw [divSum?, Fin.isSome_find?_iff]
535+ constructor
536+ · rintro ⟨i, hi⟩
537+ rw [decide_eq_true_eq] at hi
538+ exact lt_of_lt_of_le hi (partialSum_le_sum n i)
539+ · intro hk
540+ obtain ⟨m', rfl⟩ : ∃ m', m = m' + 1 := by
541+ cases m with
542+ | zero => simp at hk
543+ | succ m' => exact ⟨m', rfl⟩
544+ refine ⟨Fin.last m', ?_⟩
545+ rw [decide_eq_true_eq]
546+ refine lt_of_lt_of_le hk (le_of_eq (Finset.sum_congr rfl fun j _ => ?_))
547+ rfl
484548 -- constructor
485549 -- · intro h
486550 -- simp only [divSum?, Nat.succ_eq_add_one, castLE, isSome_find_iff] at h
@@ -505,20 +569,26 @@ theorem sum_le_of_divSum?_eq_some {m : ℕ} {n : Fin m → ℕ} {k : Fin (∑ j,
505569 by_cases hi' : 0 = i.val
506570 · rw [← Fin.sum_congr' _ hi']
507571 simp only [Finset.univ_eq_empty, Finset.sum_empty, _root_.zero_le]
508- · have : (i.val - 1 ) + 1 = i.val := by omega
509- rw [← Fin.sum_congr' _ this]
510- sorry
572+ · have hone : (i.val - 1 ) + 1 = i.val := by omega
573+ rw [← Fin.sum_congr' _ hone]
574+ have hj : (decide (↑k < ∑ j, n (castLE (Fin.mk (i.val - 1 ) (by omega) : Fin m).isLt j)))
575+ = false :=
576+ Fin.eq_false_of_find?_eq_some_of_lt hi ⟨i.val - 1 , by omega⟩ (by simp [Fin.lt_def]; omega)
577+ rw [decide_eq_false_iff_not, not_lt] at hj
578+ refine le_trans (le_of_eq (Finset.sum_congr rfl fun j _ => ?_)) hj
579+ rfl
511580 -- have := Fin.find_min (Option.mem_def.mp hi) (j := ⟨i.val - 1, by omega⟩) <| Fin.lt_def.mpr
512581 -- (by simp only; omega)
513582 -- exact not_lt.mp this
514583
515584def modSum {m : ℕ} {n : Fin m → ℕ} (k : Fin (∑ j, n j)) : Fin (n (divSum k)) :=
516585 ⟨k - ∑ j, n (Fin.castLE (divSum k).isLt.le j), by
517- -- sorry
518586 have divSum_mem : divSum k ∈ divSum? n k := by
519587 simp only [divSum, divSum?, Option.mem_def, Option.some_get]
520- have hk : k < ∑ j, n (Fin.castLE (divSum k).isLt j) := by
521- sorry --Fin.find_spec _ divSum_mem
588+ have hk : (k : ℕ) < ∑ j, n (Fin.castLE (divSum k).isLt j) := by
589+ have := Fin.eq_true_of_find?_eq_some (p := fun i => decide ((k : ℕ) <
590+ ∑ j, n (castLE i.isLt j))) divSum_mem
591+ simpa using this
522592 simp only [Fin.sum_univ_succAbove _ (Fin.last (divSum k)), succAbove_last] at hk
523593 rw [Nat.sub_lt_iff_lt_add' (sum_le_of_divSum?_eq_some divSum_mem)]
524594 rw [add_comm]
0 commit comments