Zulip Chat Archive

Stream: new members

Topic: Rewrite inside BigOperators


Bernardo Borges (May 22 2024 at 02:33):

When manipulating proofs that involve BigOperators, such as , many of the terms will involve the index i. For example, I would like to understand how you would point the rw to the terms ys i and xs i, when we won't have i in the context:

import Mathlib.Data.Fin.Tuple.Reflection

open BigOperators

example
  (A : )
  (xs ys : Fin n  )
  (h : A  i,(xs i + ys i))
  : A  i,(ys i + xs i) := by
  rw [add_comm (ys i) (xs i)]
  -- unknown identifier 'i'
  assumption
  done

Should you intro? Declare a fun i =>? This is a more general question, because I will be manipulating Sums a lot. Thanks in advance!

Johan Commelin (May 22 2024 at 02:35):

You can use simp_rw. And just use an _ instead of the i.

Bernardo Borges (May 22 2024 at 02:38):

Oh. In this case the _ leaves a hole for Lean to complete?

Bernardo Borges (May 22 2024 at 02:41):

Looks good, thanks!

Notification Bot (May 22 2024 at 12:36):

Bernardo Borges has marked this topic as resolved.

Notification Bot (May 26 2024 at 10:32):

Ralf Stephan has marked this topic as unresolved.

Ralf Stephan (May 26 2024 at 10:38):

This works for me only up to the point, where properties of the bound variable come into play.

import Mathlib
set_option autoImplicit false
open Nat BigOperators Finset

example : ( p  Icc (1 : ) 5, (∑' k : , (p ^ k : )⁻¹)) =
    ( p  Icc (1 : ) 5, ((p : ) / (p - 1))) := by
  have h (p' : ) (hp : p'  Icc 1 5) : p'  0 := by sorry
  simp_rw [(inv_div (_ - 1 : ) (_ : )).symm, sub_div]
  simp_rw [div_self (h _)]
--  rw [one_div, ←tsum_geometric_of_lt_one]
  sorry

Here the first simp_rw is fine, but for the second, div_self needs a proof that _ is nonzero, which I tried to give with h. What mistake did I make? How can I refer to the fact that p was declared ∈ Icc 1 5 under the product?

Yaël Dillies (May 26 2024 at 10:56):

After #11563, you will be able to do ∏ hp : p ∈ Icc 1 5, .... Before that, you have to do ∑ p : Icc 1 5, ...

Michael Stoll (May 26 2024 at 11:14):

import Mathlib
set_option autoImplicit false
open Nat BigOperators Finset

example : ( p  Icc (1 : ) 5, (∑' k : , (p ^ k : )⁻¹)) =
    ( p  Icc (1 : ) 5, ((p : ) / (p - 1))) := by
  have h (p' : ) (hp : p'  Icc 1 5) : p'  0 := by sorry
  simp_rw [(inv_div (_ - 1 : ) (_ : )).symm, sub_div]
  have :  x  Icc (1 : ) 5, (x / x - 1 / x : )⁻¹ =  y  Icc (1 : ) 5, (1 - 1 / y : )⁻¹ := by
    refine Finset.prod_congr rfl fun x hx  ?_
    rw [div_self (by exact_mod_cast h x hx)]
  rw [this]
  sorry

is one possibility. The various ...congr lemmas allow you to use information like your variable is in the given (fin)set.

Alex Brodbelt (Aug 20 2024 at 17:06):

I'm struggling to rewrite within a sum and was wondering what other things can I try?

Before the sorry I want to convert
(1 / 2) ^ (x * 2) / (1 / 2) ^ (x + 1)
to
(1/2) ^(x - 1)

import Mathlib.Algebra.BigOperators.Group.Finset
import Mathlib.Algebra.Order.Field.Basic
import Mathlib.Data.Real.Basic

open Real BigOperators Finset Field

theorem part_b :  x :   , ( i, x i > 0)  ( i, x (i + 1)  x i)  (x 0 = 1)  ( N, ( n  range N, ((x n)^2 / (x (n + 1)))) < 4) := by
  let x :    := fun n => (1 / 2)^n
  use x
  constructor
  · intro i
    apply pow_pos (by norm_num) i
  constructor
  · intro i
    apply pow_le_pow_of_le_one
    · norm_num
    · rw [one_div_le (by norm_num) (by norm_num), div_one]; norm_num -- why does norm_num or linarith not work here?
    · apply Nat.le_succ
  constructor
  · rfl
  intro N
  dsimp [x]
  simp_rw [ pow_mul]
 -- simp_rw [div_eq_mul_inv ((1 / 2) ^ (x * 2)) _, ← pow_sub] --lean is not happy with these rewrites
  sorry

I was also trying to make a helper lemma

lemma helper {x : } (hx : 1  x): (1 / 2 : ) ^ (2 * x) / (1 / 2 : ) ^ (x + 1) = (1 / 2 : )^(2 * x - (x + 1)) := by
  calc (1 / 2 : ) ^ (2 * x) / (1 / 2 :   ) ^ (x + 1) = (1 / 2 : ) ^ (2 * x - (x + 1)) := by rw [div_eq_mul_inv,  pow_sub (a := (1 / 2)) (m := 2 * x) (n := x + 1)]

I have tried moogle and leansearch, but have had no success so far, I feel like it should be easy to do this computation and that there should be some tactic which I don't know how to use which should make this easy to do...

Kyle Miller (Aug 20 2024 at 17:08):

Re "why does norm_num not work here", you can use linarith, which knows how to prove inequalities. I think 1 / 2 ≤ 1 should be in the purview of norm_num though.

Kyle Miller (Aug 20 2024 at 17:11):

Here's some progress:

theorem part_b :  x :   , ( i, x i > 0)  ( i, x (i + 1)  x i)  (x 0 = 1)  ( N, ( n  range N, ((x n)^2 / (x (n + 1)))) < 4) := by
  let x :    := fun n => (1 / 2)^n
  use x
  constructor
  · intro i
    apply pow_pos (by norm_num) i
  constructor
  · intro i
    apply pow_le_pow_of_le_one
    · norm_num
    · linarith
    · apply Nat.le_succ
  constructor
  · rfl
  intro N
  dsimp [x]
  simp_rw [ pow_mul]
  convert_to ( x  range N, (1/2) ^(x - 1) : ) < 4 using 2
  rw [div_eq_mul_inv]
  -- ⊢ (1 / 2) ^ (x✝ * 2) * ((1 / 2) ^ (x✝ + 1))⁻¹ = (1 / 2) ^ (x✝ - 1)
  sorry

Kyle Miller (Aug 20 2024 at 17:12):

The convert_to tactic is useful for saying "I want to make the expression look like this; give me the difference". The using clause is to control how far to strip away like terms.

Kyle Miller (Aug 20 2024 at 17:13):

pow_sub doesn't apply here because it's for multiplicative groups, but the reals aren't a multiplicative group.

Kyle Miller (Aug 20 2024 at 17:13):

pow_sub₀ works though

Alex Brodbelt (Aug 20 2024 at 17:13):

Kyle Miller said:

Re "why does norm_num not work here", you can use linarith, which knows how to prove inequalities. I think 1 / 2 ≤ 1 should be in the purview of norm_num though.

I tried linarith as well and it fails too, which I thought was strange - but there could be something wrong with my version of lean. It has been acting up lately whenever I try start a new project using mathlib

Kyle Miller (Aug 20 2024 at 17:15):

Oh, you know what, norm_num works for me here. I didn't test it because I trusted the comment.

Kyle Miller (Aug 20 2024 at 17:15):

I'm on a version of mathlib from august 15, in case that helps.

Alex Brodbelt (Aug 20 2024 at 17:26):

Kyle Miller said:

Oh, you know what, norm_num works for me here. I didn't test it because I trusted the comment.

How can I check the version?
Something is weird, neither linarith or norm_num work for me there...

Kevin Buzzard (Aug 21 2024 at 08:52):

Are you working in mathlib itself or a project which has mathlib as a dependency?

Alex Brodbelt (Aug 21 2024 at 11:18):

Kevin Buzzard said:

Are you working in mathlib itself or a project which has mathlib as a dependency?

I'm working with mathlib as a dependency

Kevin Buzzard (Aug 21 2024 at 19:39):

Then you can look in your manifest file to see which mathlib commit you're using. Alternatively fire up a terminal, change directory to .lake/packages/mathlib and then do git log to see the date of the last commit.

Alex Brodbelt (Aug 22 2024 at 16:21):

I was working on part b for a q3 of the 1982 IMO (working on part a at the minute) and was wondering if there is a more idiomatic way to use sums over ranges or even Icc? what do more experienced users use when trying to formalise this sort of problem?
Once I have finished part a how can I add this to the archive of formalised IMO problems?

import Mathlib.Algebra.BigOperators.Group.Finset
import Mathlib.Algebra.Order.Field.Basic
import Mathlib.Data.Real.Basic
import Mathlib.Algebra.GeomSum

open Real BigOperators Finset Field Nat Preorder

theorem part_b :  x :   ,
                ( i, x i > 0) 
                ( i, x (i + 1)  x i)  (x 0 = 1) 
                ( N, ( n  range (N + 1), ((x n)^2 / (x (n + 1)))) < 4)
                := by
  let xₙ :    := fun n => (1/2)^n
  use xₙ
  constructor
  · intro i
    apply pow_pos (by norm_num) i
  constructor
  · intro i
    apply pow_le_pow_of_le_one (by norm_num)
    · rw [one_div_le (by norm_num) (by norm_num), div_one]; norm_num
    · apply Nat.le_succ
  constructor
  · rfl
  intro N
  dsimp [xₙ]
  rw [
    Finset.sum_eq_sum_diff_singleton_add (s := range (N + 1)) (i := 0) (Finset.mem_range.mpr (by linarith)),
    pow_zero, zero_add, one_pow, pow_one, one_div_one_div, add_comm
    ]
  convert_to (2 +  n  range (N), (1/2) ^ n : ) < 4 using 2
  induction' N with k hk
  case zero =>
    simp only [
      zero_add, range_one, sdiff_self, bot_eq_empty, one_div, inv_pow, div_inv_eq_mul,
      sum_empty, range_zero
      ]
  case succ =>
    rw [
      Finset.sum_range_succ,  hk, Finset.range_add_one
      ]
    simp only [
      one_div, inv_pow, div_inv_eq_mul, singleton_subset_iff, mem_insert, self_eq_add_left,
      AddLeftCancelMonoid.add_eq_zero, one_ne_zero, and_false, mem_range, lt_add_iff_pos_left,
      add_pos_iff, zero_lt_one, or_true, sum_sdiff_eq_sub, lt_self_iff_false, not_false_eq_true,
      sum_insert, sum_singleton, pow_zero, one_pow, inv_one, zero_add, pow_one, one_mul
      ]
    rw [
       pow_mul, mul_comm,  inv_pow
      ]
    nth_rewrite 1 [ inv_inv 2]
    rw [
      mul_comm, inv_pow 2⁻¹,  pow_sub₀ (a := 2⁻¹) (ha := by norm_num) (h := by linarith), add_mul,
      one_mul, add_assoc, one_add_one_eq_two, mul_comm k 2, two_mul, add_assoc,
      Nat.add_sub_assoc (by linarith), Nat.sub_self, add_zero, inv_pow, add_sub_assoc, add_comm
    ]
  rw [
    geom_sum_eq (by norm_num), half_sub, div_neg, div_eq_inv_mul, one_div, inv_inv,
    mul_comm,  neg_mul, neg_sub
    ]
  have h₀ : (1 - (2 : )⁻¹ ^ N) < 1 := by apply sub_lt_self; apply pow_pos (by norm_num)
  linarith [h₀]
  done

Kevin Buzzard (Aug 24 2024 at 17:45):

Once I have finished part a how can I add this to the archive of formalised IMO problems?

Just make a PR like you would for any changes to mathlib.


Last updated: May 02 2025 at 03:31 UTC