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