Zulip Chat Archive

Stream: Is there code for X?

Topic: group sum/prod in pairs even and odd summands


Moritz Firsching (Oct 25 2023 at 14:02):

If I have a sum/prod over an even range or Ioc or Icc, is there some function to group it by pairs, each containing an odd an an evenly indexed summand/factor.

-- TODO: find good place and name and prove additive/multiplicative version in generality
theorem prod_even_odd (n : ) (f :   ) :
     x in Icc 1 (2 * n), f x =   x in Icc 1 (n), (f (2 * x)) * (f (2 * x - 1)) := by
  induction' n with n hn
  · rfl
  · have h : 2 * succ n = succ (succ (2 * n)) := by rfl
    rw [h,  Ico_succ_right, prod_Ico_succ_top <| le_add_left 1 (2 * n + 1),
        prod_Ico_succ_top <| le_add_left 1 (2 * n)]
    simp only [ Ico_succ_right, h] at hn
    rw [hn,  Ico_succ_right, prod_Ico_succ_top <| le_add_left 1 n, succ_eq_add_one, mul_add,
        mul_one, mul_comm (f (2 * n + 2)), mul_assoc]
    rfl

Is there already some theorem like that, I searched but couldn't find it? I think it could be useful in general, but maybe there is an even better generalization that is already there and I am not seeing.

Yaël Dillies (Oct 25 2023 at 14:09):

This is morally docs#Finset.prod_product, but we're missing some glue.

Moritz Firsching (Oct 25 2023 at 19:55):

Thanks @Yaël Dillies, I see why this is related.
I tried deducing the result from docs#Finset.prod_product, but it turned out to be quite cumbersome, especially because of the use of docs#Finset.prod_bij' afterwards.
What is the glue that we missing precisely (I'm happy to produce it!). Do you have some canonical way in mind to write Icc 1 (2 * n) as a cartesian product?

theorem prod_even_odd (n : ) (f :   ) :
     x in Icc 1 (2 * n), f x =   x in Icc 1 (n), (f (2 * x)) * (f (2 * x - 1)) := by
  set i :  ×    := fun a => 2 * a.1 - a.2
  set g :  ×    := fun a => f (i a)
  have := @Finset.prod_product _ _ _ _ ((Icc 1 n)) ({0, 1}) g
  convert this
  · refine' prod_bij' _ _ _ _ _ _ _
    · intro a ha
      exact 1 + (a - 1) / 2, a % 2
    · intros a ha
      simp only [mem_singleton, mem_product, mem_Icc, mem_insert]
      constructor
      · simp at ha
        constructor
        · exact le_add_right 1 ((a - 1) / 2)
        · have := ha.2
          by_cases Even a
          · sorry
          · sorry
      · exact mod_two_eq_zero_or_one a
    · intros a ha
      simp only
      congr
      by_cases Even a
      · sorry
      · sorry
    · intro a ha
      exact i a
    · intro a ha
      simp only [mem_singleton, mem_product, mem_Icc, mem_insert] at ha
      cases' ha with ha_left ha_right
      simp only [_root_.mul_eq_zero, false_or, mem_Icc, tsub_le_iff_right]
      constructor
      · have : 2  2 * a.1 := by simp [ha_left.1]
        by_cases a.2 = 1
        · rw [h]
          exact le_pred_of_lt this
        · have h : a.2 = 0 := by tauto
          rw [h]
          exact one_le_of_lt this
      · by_cases a.2 = 1
        have := ha_left.2
        · rw [h]
          linarith
        · have h : a.2 = 0 := by tauto
          rw [h]
          linarith
    · intro a ha
      dsimp only
      by_cases Even a
      · sorry
      · sorry
    · intro a ha
      dsimp only
      congr
      · sorry
      · sorry
  · simp

Yaël Dillies (Oct 25 2023 at 20:41):

Will have a look tomorrow morning, but does docs#finProdFinEquiv help?

Moritz Firsching (Oct 26 2023 at 08:36):

This is starting to make sense. I suppose one missing potentially useful theorem is prod_finProd as an analogue to docs#Finset.prod_product, what do you think?

@[to_additive]
theorem prod_finProd {n : } {m : } {f : Fin n × Fin m  } :
     x : Fin n × Fin m, f x =  x : Fin n,  y : Fin m, f (x, y) := by
  refine prod_finset_product univ univ (fun _  univ) ?h
  exact fun p => fun _ => mem_univ p.1, mem_univ p.2⟩, fun _ => mem_univ p

theorem prod_even_odd (n : ) (f :   ) :
     x : Fin (n * 2), f x =   x : Fin n, (f (2 * x)) * (f (1 + 2 * x)) := by
  let g x := (f (2 * x)) * (f (1 + 2 * x))
  have :  x : Fin n, f (2 * x) * f (1 + 2 * x ) =  x : Fin n, g x := by rfl
  rw [this]
  have :  x : Fin (n * 2), f x =   y : (Fin n) × (Fin 2), f (finProdFinEquiv y) := by
    exact
      (Equiv.prod_comp' finProdFinEquiv (fun i  f (finProdFinEquiv i)) (fun i  f i)
          (congrFun rfl)).symm
  rw [this, prod_finProd]
  simp

Moritz Firsching (Oct 26 2023 at 11:43):

I suggest to add prod_finProd and friends here: #7955

Yaël Dillies (Oct 26 2023 at 13:52):

Uh, your prod_finProd is defeq to docs#Finset.prod_product.

Moritz Firsching (Oct 27 2023 at 11:53):

I see.
Is this

def  range_product_rangeEquiv {m n : } : (range m) ×ˢ (range n)  range (m * n) where

also defeq to something in the library?

Eric Wieser (Oct 27 2023 at 12:05):

That should be very close to docs#finProdFinEquiv

Moritz Firsching (Nov 01 2023 at 01:25):

Thanks!
When using this, I made up two more lemmas:

def rangeFinEquiv {n : } : range n  Fin n where
  toFun := fun x => x, List.mem_range.mp x.2
  invFun := fun x => x.1, mem_range.mpr x.2
  left_inv := congrFun rfl
  right_inv := congrFun rfl

def range_prod_rangeEquiv {m n : } : (range m) × (range n)  range (m * n) :=
  Equiv.trans (Equiv.prodCongr rangeFinEquiv rangeFinEquiv)
  <| (finProdFinEquiv ).trans (rangeFinEquiv).symm

def range_sprod_rangeEquiv {m n : } : (range m) ×ˢ (range n)  range (m * n) := by
  refine' Equiv.trans _ range_prod_rangeEquiv
  convert Equiv.subtypeProdEquivProd
  simp only [mem_product, mem_range]

I feel like rangeFinEquiv surely should be already there somewhere, but I couldn't find it. If not, should any of those be added to mathlib?

Even without those lemmas, I was able to change use docs#Finset.prod_product for a version of the statement that I actually need in #7924

theorem prod_even_odd (n : ) (f :   ) :
     x : Fin (n * 2), f x =   x : Fin n, (f (2 * x)) * (f (1 + 2 * x)) := by
  rw [(Equiv.prod_comp' finProdFinEquiv (fun i  f (finProdFinEquiv i)) (fun i  f i)
          (congrFun rfl)).symm, Fintype.prod_prod_type]
  simp only [finProdFinEquiv_apply_val]
  congr
  ext x
  rw [Fin.prod_univ_eq_prod_range (fun x_1 => f (x_1 + 2 * x)) 2, Finset.prod_range_succ]
  simp

Eric Wieser (Nov 01 2023 at 01:39):

Can you make those mwes, with imports?

Eric Wieser (Nov 01 2023 at 01:40):

In particular, which range is that?

Eric Wieser (Nov 01 2023 at 01:42):

If it's Finset.range, then this works for the first one:

def rangeFinEquiv {n : } : Finset.range n  Fin n :=
  (Equiv.subtypeEquivProp <| by simp).trans Fin.equivSubtype.symm

Moritz Firsching (Nov 01 2023 at 10:53):

sure, as mwe:

import Mathlib.Logic.Equiv.Fin
import Mathlib.Logic.Equiv.Basic
import Mathlib.Data.Fintype.BigOperators
import Mathlib.Algebra.BigOperators.Intervals

open Finset

def rangeFinEquiv {n : } : range n  Fin n :=
  (Equiv.subtypeEquivProp <| by simp).trans Fin.equivSubtype.symm

def range_prod_rangeEquiv {m n : } : (range m) × (range n)  range (m * n) :=
  Equiv.trans (Equiv.prodCongr rangeFinEquiv rangeFinEquiv)
  <| (finProdFinEquiv ).trans (rangeFinEquiv).symm

def range_sprod_rangeEquiv {m n : } : (range m) ×ˢ (range n)  range (m * n) := by
  refine' Equiv.trans _ range_prod_rangeEquiv
  convert Equiv.subtypeProdEquivProd
  simp only [mem_product, mem_range]

open BigOperators Nat

theorem prod_even_odd (n : ) (f :   ) :
     x : Fin (n * 2), f x =   x : Fin n, (f (2 * x)) * (f (1 + 2 * x)) := by
  rw [(Equiv.prod_comp' finProdFinEquiv (fun i  f (finProdFinEquiv i)) (fun i  f i)
          (congrFun rfl)).symm, Fintype.prod_prod_type]
  simp only [finProdFinEquiv_apply_val]
  congr
  ext x
  rw [Fin.prod_univ_eq_prod_range (fun x_1 => f (x_1 + 2 * x)) 2, Finset.prod_range_succ]
  simp

Last updated: Dec 20 2023 at 11:08 UTC