Zulip Chat Archive

Stream: Is there code for X?

Topic: tactic for rearrange terms?


Casavaca (Mar 24 2024 at 08:34):

I want to proof something like a b c d e p q s : R, a * b * c * d * e < p * q * e * d * s. Suppose I want to apply

theorem mul_lt_mul_of_pos_left [...] (bc : b < c) (a0 : 0 < a) :
a * b < a * c

and transform the goal into a * b * c * d < p * q * d * s and 0 < e.

Then apply again on d to turn the goal into a * b * c < p * q * s and 0 < d

Is there a tactic to free me from always reorder the terms manually?

Thanks.

Yaël Dillies (Mar 24 2024 at 08:35):

Try gcongr _ * _ * _ * ?_ * ?_

Kevin Buzzard (Mar 24 2024 at 08:36):

What is R? Can you write a #mwe if Yael's suggestion doesn't answer your question?

Kyle Miller (Mar 24 2024 at 08:38):

There's also convert_to to create equalities that you could prove with ring. The using clause tells convert_to the depth at which it should stop trying to pull things apart.

example (a b c d e p q s : ) :
    a * b * c * d * e < p * q * e * d * s := by
  convert_to e * (a * b * c * d) < e * (p * q * d * s) using 1
  · ring
  · ring
  apply mul_lt_mul_of_pos_left
  /-
  case bc
  a b c d e p q s : ℝ
  ⊢ a * b * c * d < p * q * d * s

  case a0
  a b c d e p q s : ℝ
  ⊢ 0 < e
  -/

Damiano Testa (Mar 24 2024 at 09:34):

move_mul [e] should also move e to the far right (and using ←e moves it to the far left).

Damiano Testa (Mar 24 2024 at 09:45):

E.g.

import Mathlib

example (a b c d e p q s : ) :
    a * b * c * d * e < p * q * e * d * s := by
  move_mul [e]   -- ⊢ a * b * c * d * e < p * q * d * s * e
  apply mul_lt_mul_of_pos_right
  /-
  case bc
  a b c d e p q s : ℝ
  ⊢ a * b * c * d < p * q * d * s

  case a0
  a b c d e p q s : ℝ
  ⊢ 0 < e
  -/

Casavaca (Mar 24 2024 at 17:29):

Thank you all. I meant "ℝ" when I typed R. move_mul is very useful because I don't have to manually locate the term by "gcongr _ * _ * _ * ?_ * ?_" or manually rewrite all the terms by "convert_to e * (a * b * c * d) < e * (p * q * d * s)".

Casavaca (Apr 03 2024 at 06:04):

I got another question:

How do I do this? Basically I want to make Lean merge the constants.

example {a b c d : } (h : (2 : ) * a * ((2 : ) * b) * ((2 : ) * c) = d) : True := by
  -- h : 2 * a * (2 * b) * (2 * c) = d
  magic_norm_num at h
  -- h : (8 : ℝ) * (a * b * c) = d

Damiano Testa (Apr 03 2024 at 06:14):

Oh, I did not implement move_mul at? I think that I did in lean3.

Otherwise, maybe move_mul [a, b, c] at h; rw [show (2 : ℝ) * 2 * 2 = 8 by norm_num] at h would work?

(Even if it did, I agree that it is not ideal.)

Damiano Testa (Apr 03 2024 at 06:15):

There was a recent thread about a tactic for "collecting terms", but I'm on mobile now.

Casavaca (Apr 03 2024 at 06:17):

You're right. "collecting terms" wanted to achieve similar goal.
You did implement move_mul. In this case, it can be weird because if goal is "2 * a * 2 * a * 2 * a", you can't apply move_mul, it would say that 2 is already left_most, and a is already right most

Damiano Testa (Apr 03 2024 at 06:19):

Repetitions should be allowed and respected: move_mul [a, a, a] should do what you want.

Damiano Testa (Apr 03 2024 at 06:20):

(And it is a bug if it does not work: there is some care taken in "uniquifing" the input, to preserve multiplicities.)

Damiano Testa (Apr 03 2024 at 06:22):

I.e. move_mul [a, a] should not be the same as move_mul [a]; move_mul [a].

Casavaca (Apr 03 2024 at 06:28):

Thanks. move_mul [2, 2] worked, but we don't have move_mul ... at ... yet. It would be nice if we can have something like move_combine_constant.

Damiano Testa (Apr 03 2024 at 06:33):

Ok, I had at in Lean 3, but did not port it. The "combine constants" part I think that has never part of any tactic, though maybe it is part of the specs for ring. However, also ring does not support the at ... syntax.

Damiano Testa (Apr 03 2024 at 06:34):

import Mathlib

example {a b c d : } : (2 : ) * a * ((2 : ) * b) * ((2 : ) * c) = d := by
  ring
  -- ⊢ a * b * c * 8 = d

Last updated: May 02 2025 at 03:31 UTC