Zulip Chat Archive

Stream: new members

Topic: if a < b then a^3 < b^3


Lars Ericson (Jan 24 2021 at 21:58):

This is a tricky one:

import tactic
import tactic.slim_check
import algebra.ordered_ring
universe u

theorem ex_1_3_1_f (α: Type u) [linear_ordered_ring α]
   (a b : α) (h: a < b): a^3 < b^3 :=
begin
  have h1 := pow_two_nonneg a,
  have h2 := pow_two_nonneg b,
  rw (pow_succ a 2),
  rw (pow_succ b 2),
  sorry,
end

I just found some proofs over here, so I don't actually have a question. I don't see anything that fits for this in mathlib directly. I think I can adapt this proof which looks good:

If a > b then (a - b) > 0, and so (a - b)^3 > 0.

Thus (a - b)^3 = (a^3 - 3*a^2*b + 3a*b^2 - b^3) > 0, and so

(a^3 - b^3) > (3*a^2*b - 3a*b^2) = 3ab*(a - b).

Now we know that (a - b) > 0. So if either (i) both a and b are positive, or

(ii) both a and b are negative, then 3ab*(b - a) > 0, and so

(a^3 - b^3) > 0  ----->  a^3 > b^3.

If a > 0 and b < 0 then a^3 > 0 and b^3 < 0 so a^3 > b^3.

(We can't have a < 0 and b > 0 since a > b.)

So in all cases we have that a > b implies that a^3 > b^3.

Alex J. Best (Jan 24 2021 at 22:04):

A linear ordered ring isn't commutative and it looks like your proof uses commutativity of multiplication to say that (a - b)^3 = (a^3 - 3*a^2*b + 3a*b^2 - b^3)

Alex J. Best (Jan 24 2021 at 22:11):

That proof looks quite a lot of algebraic manipulations to me though, I'd be inclined to just use facts like
0 < b \to a < b \to a * b < b *b which should be in the library, and split into cases based on whether a and b are positive or negative and build the proof that way.

Kevin Buzzard (Jan 24 2021 at 22:34):

If your ring is commutative then you can use that a^2+ab+b^2>=0 by completing the square

Lars Ericson (Jan 25 2021 at 01:53):

The setting is "ordered domain" which I've taken up to now to be integral_domain with linear_ordered_ring. It's described more here.

I just figured out how to prove a polynomial so I think I can grind through this now:

import tactic
import tactic.slim_check
import algebra.ordered_ring
universe u

lemma expand_mult (α: Type u) [integral_domain α] [linear_ordered_ring α]
   (a b : α) (h: 0 < a):
   (b-a)^3 = b^3-3*a*b^2+3*a^2*b-a^3 :=
begin
  rw pow_succ (b-a) 2,
  rw pow_succ (b-a) 1,
  simp,
  rw sub_eq_add_neg,
  repeat { rw left_distrib, rw right_distrib, },
  ring,
end

It would be nice if Lean were hybridized a bit with some kind of self-validating pre-theorem-proving-style computer algebra so I could do stuff like this:

>>> import sympy as sp
>>> a,b=sp.symbols('a,b')
>>> sp.expand((b-a)**3)
-a**3 + 3*a**2*b - 3*a*b**2 + b**3

Yakov Pechersky (Jan 25 2021 at 01:55):

That does not compile for me, because you have two conflicting ring on α

Yakov Pechersky (Jan 25 2021 at 01:56):

For me, this works instead: [integral_domain α] [linear_order α]. Perhaps I'm on an old mathlib

Yakov Pechersky (Jan 25 2021 at 01:56):

import tactic

lemma expand_mult (α : Type*) [integral_domain α] [linear_order α]
   (a b : α) :
   (b-a)^3 = b^3-3*a*b^2+3*a^2*b-a^3 :=
by ring_exp

Yakov Pechersky (Jan 25 2021 at 01:57):

No need for the positivity constraint

Lars Ericson (Jan 25 2021 at 01:57):

Great, thanks! ring_exp is nice. I will update my mathlib now to make sure I am in sync with latest.

Lars Ericson (Jan 25 2021 at 02:08):

OK so after doing leanproject upgrade-mathlib, your version works fine. My version breaks in a weird way on the ring command. It is both happy and sad. It says "goals accomplished" but also complains about ring horners:

type mismatch at application
  norm_num.subst_into_mul b (b * b) (tactic.ring.horner 1 b 1 0) (tactic.ring.horner 1 b 2 0)
    (tactic.ring.horner 1 b 3 0)
    (tactic.ring.horner_atom b)
term
  tactic.ring.horner_atom b
has type
  b = tactic.ring.horner 1 b 1 0
but is expected to have type
  b = tactic.ring.horner 1 b 1 0

on input

import tactic
import tactic.slim_check
import algebra.ordered_ring
universe u

lemma expand_mult (α: Type u) [integral_domain α] [linear_ordered_ring α]
   (a b : α) (h: 0 < a):
   (b-a)^3 = b^3-3*a*b^2+3*a^2*b-a^3 :=
begin
  rw pow_succ (b-a) 2,
  rw pow_succ (b-a) 1,
  simp,
  rw sub_eq_add_neg,
  repeat { rw left_distrib, rw right_distrib, },
  ring,
end

Lars Ericson (Jan 25 2021 at 02:08):

Screenshot-from-2021-01-24-21-08-38.png

Yakov Pechersky (Jan 25 2021 at 02:12):

You'd have to do a lot of inspection of intermediate terms, but what you'd find is that by saying [integral_domain α] [linear_ordered_ring α], you're invoking two separate, non-identical [ring α]. That means that ring is trying to bring both sides of the equation to the same terms, but is running into the problem that it doesn't know which of the two (now completely independent) inferred definitions of (+) it should be using. That's my understanding of that error.

Bryan Gin-ge Chen (Jan 25 2021 at 02:13):

ring should probably throw an error there instead of clearing the goal. cc: @Mario Carneiro

Mario Carneiro (Jan 25 2021 at 02:16):

Oh I see, yeah ring isn't very defensive against weird multiplications on the type. simp I think has the same problem

Mario Carneiro (Jan 25 2021 at 02:17):

I'm not sure it's worth the expense

Lars Ericson (Jan 25 2021 at 02:18):

This is a bit sad because if I switch from linear_ordered_ring to linear_order I lose sub_pos and probably other stuff in my theorem ex_1_3_1_f :

import tactic
import tactic.slim_check
import algebra.ordered_ring
universe u
/-
lemma expand_mult (α: Type u) [integral_domain α] [linear_ordered_ring α]
   (a b : α) (h: 0 < a):
   (b-a)^3 = b^3-3*a*b^2+3*a^2*b-a^3 :=
begin
  rw pow_succ (b-a) 2,
  rw pow_succ (b-a) 1,
  simp,
  rw sub_eq_add_neg,
  repeat { rw left_distrib, rw right_distrib, },
  ring,
end -/

lemma expand_mult (α : Type*) [integral_domain α] [linear_order α]
   (a b : α) :
   (b-a)^3 = b^3-3*a*b^2+3*a^2*b-a^3 :=
by ring_exp

theorem ex_1_3_1_f (α: Type u) [integral_domain α] [linear_order α]
   (a b : α) (h: a < b): a^3 < b^3 :=
begin
  by_cases ha : a > 0,
  by_cases hb : b > 0,
  have h1 := sub_pos.2 h,
  have h2 := pow_pos h1 3,
  have h3 := expand_mult,
  sorry,
  sorry,
  sorry,
end

I haven't actually needed integral_domain up to now, just ordered_ring or linear_ordered_ring for these:

import tactic
import tactic.slim_check
import algebra.ordered_ring
universe u

theorem ex_1_3_1_a (α: Type u) [ordered_ring α]
   (a b c : α) (h: a < b): a + c < b + c :=
  add_lt_add_right h c

theorem ex_1_3_1_b (α: Type u) [ordered_ring α]
   (a x y : α): a-x < a-y  x > y := sub_lt_sub_iff_left a

lemma lt0_lt_flip (α: Type*) [linear_ordered_ring α] -- Ruben Van de Velde
   (a x : α) (hx: a * x < 0) (ha: a < 0) : 0 < x :=
  pos_of_mul_neg_right hx ha.le

theorem ex_1_3_1_c (α: Type u) [linear_ordered_ring α]
   (a x y : α) (h: a < 0): a*x > a* y  x < y :=
begin
  split,
  {
    intro h0,
    have h1 := sub_lt_zero.mpr h0,
    apply sub_lt_zero.1,
    rw  mul_sub at h1,
    have h2 := lt0_lt_flip α a (y-x) h1 h,
    rw (neg_sub x y).symm at h2,
    exact neg_pos.1 h2,
  },
  {
    intro h0,
    apply sub_lt_zero.1,
    rw  mul_sub,
    have h1 := sub_pos.2 h0,
    exact mul_neg_of_neg_of_pos h h1,
  }
end

theorem ex_1_3_1_d (α: Type u) [linear_ordered_ring α]
   (a b c : α) (ha: 0 < c) (hacbc: a*c < b*c): a < b :=
  (mul_lt_mul_right ha).mp hacbc

theorem ex_1_3_1_e (α: Type u) [linear_ordered_ring α]
   (x : α) (h: x + x + x + x = 0) : x = 0 :=
begin
  rw (add_assoc (x+x) x x) at h,
  exact bit0_eq_zero.mp (bit0_eq_zero.mp h),
end

I'm not sure at this point exactly what combination of Lean structures equals Birkhoff and Mac Lane's notion of ordered domain.

It's more confusing because it seems from above I have to make sure my inheritance hierarchy is a tree, not a lattice, i.e. no two classes with a common superclass.

Bryan Gin-ge Chen (Jan 25 2021 at 02:20):

Mario Carneiro said:

I'm not sure it's worth the expense

Fair enough. Might be worth documenting these cases somewhere.

Mario Carneiro (Jan 25 2021 at 02:22):

@Lars Ericson The theorem should hold for a linear_ordered_ring without the integral domain part

Mario Carneiro (Jan 25 2021 at 02:23):

actually linear_ordered_comm_ring

Mario Carneiro (Jan 25 2021 at 02:23):

which is implied by the conjunction of linear_ordered_ring and integral_domain

Lars Ericson (Jan 25 2021 at 04:24):

Thanks Mario, all of the exercises are happy with linear_ordered_comm_ring.

Lars Ericson (Jan 29 2021 at 02:31):

Done, finally. I found this to be incredibly hard. I expect a one-line version from Mario soon:

import tactic
import algebra.ordered_ring
universe u

lemma together  (α: Type u) [linear_ordered_comm_ring α] (a b: α) (h: a-b = 0)  : a = b :=
  sub_eq_zero.mp h

lemma factor_expr (α: Type u) [linear_ordered_comm_ring α] (a b : α) :
  a * (b ^ 2 * -3) + (a ^ 2 * (b * 3)) = 3*a*b*(a - b) :=
begin
  apply (together α (a * (b ^ 2 * -3) + (a ^ 2 * (b * 3))) (3*a*b*(a - b))),
  ring,
end

lemma move_cubes_left (α: Type u) [linear_ordered_comm_ring α]
   (a b : α) (h: 0 < a * (b ^ 2 * -3) + (a ^ 2 * (b * 3) + (-a ^ 3 + b ^ 3))) :
   a^3- b^3 < a * (b ^ 2 * -3) + (a ^ 2 * (b * 3)) :=
begin
  linarith,
end

lemma negneg (α: Type u) [linear_ordered_comm_ring α] (a b : α): a - b = - (b - a):=
begin
  linarith,
end

lemma this_is_negative (α: Type u) [linear_ordered_comm_ring α] (a b : α)
      (h1: 0 < b - a)
      (hha: a > 0)
      (hhb: b > 0) : 3 * a * b * (a - b) < 0 :=
begin
  rw negneg α a b,
  have h3 := zero_lt_three,
  have h4 := mul_pos h3 hha,
  have h5 := mul_pos h4 hhb,
  simp,
  have h6 := neg_lt_zero.mpr h1,
  have h7 := neg_sub b  a,
  rw h7 at h6,
  exact linarith.mul_neg h6 h5,
  exact nontrivial_of_lt 0 (b - a) h1,
end

lemma this_is_positive (α: Type u) [linear_ordered_comm_ring α] (a b : α)
      (h1: 0 < b - a) (hb: b > 0) (alt0: a < 0) : 0 < 3 * a * b * (a - b) :=
begin
  have h3 := zero_lt_three,
  have h4 := mul_neg_of_pos_of_neg h3 alt0,
  have h5 := mul_neg_of_neg_of_pos h4 hb,
  have h6 := neg_lt_zero.mpr h1,
  have h7 := mul_pos_of_neg_of_neg h5 h6,
  have h8 := neg_sub b a,
  rw h8 at h7,
  exact h7,
  exact nontrivial_of_lt 0 (b - a) h1,
end

lemma simp_pow (α: Type u) [linear_ordered_comm_ring α]: (0:α)^3 = 0 :=
  tactic.ring_exp.pow_p_pf_zero rfl rfl

lemma is_lt_0 (α: Type u) [linear_ordered_comm_ring α] (b : α)
      (hb: ¬b > 0) (hb0: ¬b = 0): b < 0 :=
  (ne.le_iff_lt hb0).mp (not_lt.mp hb)

lemma odd_pos_neg_neg (α: Type u) [linear_ordered_comm_ring α] (a : α)
        (h: a < 0) : a^3 < 0 :=
  pow_bit1_neg_iff.mpr h

lemma this_be_negative (α: Type u) [linear_ordered_comm_ring α] (a b : α)
      (h1: a < b)
      (halt0: a < 0)
      (hblt0: b < 0) :
      3 * a * b * (a - b) < 0 :=
begin
  have h3 := zero_lt_three,
  have h4 := sub_lt_zero.mpr h1,
  have h5 := mul_pos_of_neg_of_neg  halt0 hblt0,
  have h6 := mul_pos h3 h5,
  have h7 := sub_lt_zero.mpr h1,
  have h8 := linarith.mul_neg h7 h6,
  finish,
  exact nontrivial_of_lt a b h1,
end

theorem ex_1_3_1_f (α: Type u) [linear_ordered_comm_ring α]
   (a b : α) (h: a < b): a^3 < b^3 :=
begin
  have h1 := sub_pos.2 h,
  have h2 := pow_pos h1 3,
  repeat { rw pow_succ' at h2, },
  simp at h2,
  rw sub_eq_neg_add at h2,
  repeat { rw right_distrib at h2, rw left_distrib at h2, },
  ring_exp at h2,
  have h3 := move_cubes_left α a b h2,
  rw factor_expr α a b at h3,
  by_cases ha : a > 0,
  {
    by_cases hb : b > 0,
    {
      have h4 := this_is_negative α a b h1 ha hb,
      have h5 := lt_trans h3 h4,
      exact sub_lt_zero.1 h5,
    },
    {
      exfalso,
      exact hb (lt_trans ha h),
    },
  },
  by_cases ha0: a = 0,
  {
    rw ha0 at *,
    simp at *,
    assumption,
  },
  {
    have halt0 := is_lt_0 α a ha ha0,
    have h3alt0 := odd_pos_neg_neg α a halt0,
    by_cases hb : b > 0,
    {
      have h3bgt0 := pow_pos hb 3,
      exact lt_trans h3alt0 h3bgt0,
    },
    by_cases hb0 : b = 0,
    {
      rw hb0,
      rw simp_pow,
      assumption,
    },
    {
      have hblt0 := is_lt_0 α b hb hb0,
      have hf := this_be_negative α a b h halt0 hblt0,
      have hf1 := lt_trans h3 hf,
      finish,
    }
  }
end

Lars Ericson (Jan 29 2021 at 02:38):

On the other hand, this one took 30 seconds:

import tactic
import algebra.ordered_ring
universe u

theorem ex_1_3_1_g (α: Type u) [linear_ordered_comm_ring α]
   (a b c : α) (hc: 0  c) (ha: b  a): b * c  a * c :=
  mul_mono_nonneg hc ha

Lars Ericson (Jan 29 2021 at 02:46):

This one also pretty easy except I have no idea what just happened at the end:

import tactic
import algebra.ordered_ring
universe u

theorem ex_1_3_2 (α: Type u) [linear_ordered_comm_ring α] (x:α): ¬  x:α, x^2 + 1 = 0 :=
begin
  intro h,
  cases h with x hx,
  rw (pow_two x) at hx,
  nlinarith,
end

Lars Ericson (Jan 29 2021 at 02:51):

This one is also free out of the box:

theorem ex_1_3_4 (α: Type u) [linear_ordered_comm_ring α] (a b:α):
  abs (abs a - abs b)  abs(a-b) :=
  abs_abs_sub_abs_le_abs_sub a b

Mario Carneiro (Jan 29 2021 at 18:50):

theorem ex_1_3_1_f (α: Type u) [linear_ordered_comm_ring α]
   (a b : α) (h: a < b): a^3 < b^3 :=
strict_mono_pow_bit1 1 h

one line version delivered

Lars Ericson (Feb 02 2021 at 04:41):

Thanks @Mario Carneiro that's great! What's a bit0 and a bit1? I've seen these around but I don't know what to make of this:

def bit0 {α : Type u} [s  : has_add α] (a  : α)                 : α := a + a
def bit1 {α : Type u} [s₁ : has_one α] [s₂ : has_add α] (a : α) : α := (bit0 a) + 1

Mario Carneiro (Feb 02 2021 at 05:06):

it is what it says. bit0 n is the function 2*n and bit1 n is 2*n+1

Kyle Miller (Feb 02 2021 at 05:09):

and 37 is the number bit1 (bit0 (bit1 (bit0 (bit0 has_one.one))))

Lars Ericson (Feb 02 2021 at 12:43):

Thanks. I get it now. It's a way of spelling out natural numbers in base 2. There are 18 docs#bit0 theorems and 19 docs#bit1 theorems in mathlib. I didn't find any commentary. The application above was powerful. It would be nice to have an article on https://leanprover-community.github.io/ exploring the power of bit and how those 37 theorems relate.


Last updated: Dec 20 2023 at 11:08 UTC