342 lines
14 KiB
Text
342 lines
14 KiB
Text
/-
|
||
Copyright (c) 2014 Jeremy Avigad. All rights reserved.
|
||
Released under Apache 2.0 license as described in the file LICENSE.
|
||
|
||
Module: algebra.ordered_ring
|
||
Authors: Jeremy Avigad
|
||
|
||
Rather than multiply classes unnecessarily, we are aiming for the ones that are likely to be useful.
|
||
We can always split them apart later if necessary. Here an "ordered_ring" is partial ordered ring (which
|
||
is ordered with respect to both a weak order and an associated strict order). Our numeric structures will be
|
||
instances of "linear_ordered_comm_ring".
|
||
|
||
This development is modeled after Isabelle's library.
|
||
-/
|
||
|
||
import logic.eq data.unit data.sigma data.prod
|
||
import algebra.function algebra.binary algebra.ordered_group algebra.ring
|
||
|
||
open eq eq.ops
|
||
|
||
namespace algebra
|
||
|
||
variable {A : Type}
|
||
|
||
structure ordered_semiring [class] (A : Type) extends semiring A, ordered_cancel_comm_monoid A :=
|
||
(mul_le_mul_left: ∀a b c, le a b → le zero c → le (mul c a) (mul c b))
|
||
(mul_le_mul_right: ∀a b c, le a b → le zero c → le (mul a c) (mul b c))
|
||
(mul_lt_mul_left: ∀a b c, lt a b → lt zero c → lt (mul c a) (mul c b))
|
||
(mul_lt_mul_right: ∀a b c, lt a b → lt zero c → lt (mul a c) (mul b c))
|
||
|
||
section
|
||
|
||
variable [s : ordered_semiring A]
|
||
variables (a b c d e : A)
|
||
include s
|
||
|
||
-- TODO: remove after we short-circuit class-graph
|
||
definition ordered_semiring.to_mul [instance] [priority 100000] : has_mul A :=
|
||
has_mul.mk (@ordered_semiring.mul A s)
|
||
definition ordered_semiring.to_lt [instance] [priority 100000] : has_lt A :=
|
||
has_lt.mk (@ordered_semiring.lt A s)
|
||
definition ordered_semiring.to_zero [instance] [priority 100000] : has_zero A :=
|
||
has_zero.mk (@ordered_semiring.zero A s)
|
||
|
||
theorem mul_le_mul_of_nonneg_left {a b c : A} (Hab : a ≤ b) (Hc : 0 ≤ c) :
|
||
c * a ≤ c * b := !ordered_semiring.mul_le_mul_left Hab Hc
|
||
|
||
theorem mul_le_mul_of_nonneg_right {a b c : A} (Hab : a ≤ b) (Hc : 0 ≤ c) :
|
||
a * c ≤ b * c := !ordered_semiring.mul_le_mul_right Hab Hc
|
||
|
||
-- TODO: there are four variations, depending on which variables we assume to be nonneg
|
||
theorem mul_le_mul {a b c d : A} (Hac : a ≤ c) (Hbd : b ≤ d) (nn_b : 0 ≤ b) (nn_c : 0 ≤ c) :
|
||
a * b ≤ c * d :=
|
||
calc
|
||
a * b ≤ c * b : mul_le_mul_of_nonneg_right Hac nn_b
|
||
... ≤ c * d : mul_le_mul_of_nonneg_left Hbd nn_c
|
||
|
||
theorem mul_nonneg_of_nonneg_of_nonneg {a b : A} (Ha : a ≥ 0) (Hb : b ≥ 0) : a * b ≥ 0 :=
|
||
have H : 0 * b ≤ a * b, from mul_le_mul_of_nonneg_right Ha Hb,
|
||
!zero_mul_eq ▸ H
|
||
|
||
theorem mul_nonpos_of_nonneg_of_nonpos {a b : A} (Ha : a ≥ 0) (Hb : b ≤ 0) : a * b ≤ 0 :=
|
||
have H : a * b ≤ a * 0, from mul_le_mul_of_nonneg_left Hb Ha,
|
||
!mul_zero_eq ▸ H
|
||
|
||
theorem mul_nonpos_of_nonpos_of_nonneg {a b : A} (Ha : a ≤ 0) (Hb : b ≥ 0) : a * b ≤ 0 :=
|
||
have H : a * b ≤ 0 * b, from mul_le_mul_of_nonneg_right Ha Hb,
|
||
!zero_mul_eq ▸ H
|
||
|
||
theorem mul_lt_mul_of_pos_left {a b c : A} (Hab : a < b) (Hc : 0 < c) :
|
||
c * a < c * b := !ordered_semiring.mul_lt_mul_left Hab Hc
|
||
|
||
theorem mul_lt_mul_of_pos_right {a b c : A} (Hab : a < b) (Hc : 0 < c) :
|
||
a * c < b * c := !ordered_semiring.mul_lt_mul_right Hab Hc
|
||
|
||
-- TODO: once again, there are variations
|
||
theorem mul_lt_mul {a b c d : A} (Hac : a < c) (Hbd : b ≤ d) (pos_b : 0 < b) (nn_c : 0 ≤ c) :
|
||
a * b < c * d :=
|
||
calc
|
||
a * b < c * b : mul_lt_mul_of_pos_right Hac pos_b
|
||
... ≤ c * d : mul_le_mul_of_nonneg_left Hbd nn_c
|
||
|
||
theorem mul_pos_of_pos_of_pos {a b : A} (Ha : a > 0) (Hb : b > 0) : a * b > 0 :=
|
||
have H : 0 * b < a * b, from mul_lt_mul_of_pos_right Ha Hb,
|
||
!zero_mul_eq ▸ H
|
||
|
||
theorem mul_neg_of_pos_of_neg {a b : A} (Ha : a > 0) (Hb : b < 0) : a * b < 0 :=
|
||
have H : a * b < a * 0, from mul_lt_mul_of_pos_left Hb Ha,
|
||
!mul_zero_eq ▸ H
|
||
|
||
theorem mul_neg_of_neg_of_pos {a b : A} (Ha : a < 0) (Hb : b > 0) : a * b < 0 :=
|
||
have H : a * b < 0 * b, from mul_lt_mul_of_pos_right Ha Hb,
|
||
!zero_mul_eq ▸ H
|
||
|
||
end
|
||
|
||
structure linear_ordered_semiring [class] (A : Type)
|
||
extends ordered_semiring A, linear_strong_order_pair A
|
||
|
||
section
|
||
|
||
variable [s : linear_ordered_semiring A]
|
||
variables (a b c : A)
|
||
include s
|
||
|
||
-- TODO: remove after we short-circuit class-graph
|
||
definition linear_ordered_semiring.to_mul [instance] [priority 100000] : has_mul A :=
|
||
has_mul.mk (@linear_ordered_semiring.mul A s)
|
||
definition linear_ordered_semiring.to_lt [instance] [priority 100000] : has_lt A :=
|
||
has_lt.mk (@linear_ordered_semiring.lt A s)
|
||
definition linear_ordered_semiring.to_zero [instance] [priority 100000] : has_zero A :=
|
||
has_zero.mk (@linear_ordered_semiring.zero A s)
|
||
|
||
theorem lt_of_mul_lt_mul_left {a b c : A} (H : c * a < c * b) (Hc : c ≥ 0) : a < b :=
|
||
lt_of_not_le
|
||
(assume H1 : b ≤ a,
|
||
have H2 : c * b ≤ c * a, from mul_le_mul_of_nonneg_left H1 Hc,
|
||
not_lt_of_le H2 H)
|
||
|
||
theorem lt_of_mul_lt_mul_right {a b c : A} (H : a * c < b * c) (Hc : c ≥ 0) : a < b :=
|
||
lt_of_not_le
|
||
(assume H1 : b ≤ a,
|
||
have H2 : b * c ≤ a * c, from mul_le_mul_of_nonneg_right H1 Hc,
|
||
not_lt_of_le H2 H)
|
||
|
||
theorem le_of_mul_le_mul_left {a b c : A} (H : c * a ≤ c * b) (Hc : c > 0) : a ≤ b :=
|
||
le_of_not_lt
|
||
(assume H1 : b < a,
|
||
have H2 : c * b < c * a, from mul_lt_mul_of_pos_left H1 Hc,
|
||
not_le_of_lt H2 H)
|
||
|
||
theorem le_of_mul_le_mul_right {a b c : A} (H : a * c ≤ b * c) (Hc : c > 0) : a ≤ b :=
|
||
le_of_not_lt
|
||
(assume H1 : b < a,
|
||
have H2 : b * c < a * c, from mul_lt_mul_of_pos_right H1 Hc,
|
||
not_le_of_lt H2 H)
|
||
|
||
theorem pos_of_mul_pos_left (H : 0 < a * b) (H1 : 0 ≤ a) : 0 < b :=
|
||
lt_of_not_le
|
||
(assume H2 : b ≤ 0,
|
||
have H3 : a * b ≤ 0, from mul_nonpos_of_nonneg_of_nonpos H1 H2,
|
||
not_lt_of_le H3 H)
|
||
|
||
theorem pos_of_mul_pos_right (H : 0 < a * b) (H1 : 0 ≤ b) : 0 < a :=
|
||
lt_of_not_le
|
||
(assume H2 : a ≤ 0,
|
||
have H3 : a * b ≤ 0, from mul_nonpos_of_nonpos_of_nonneg H2 H1,
|
||
not_lt_of_le H3 H)
|
||
|
||
end
|
||
|
||
structure ordered_ring [class] (A : Type) extends ring A, ordered_comm_group A :=
|
||
(mul_nonneg_of_nonneg_of_nonneg : ∀a b, le zero a → le zero b → le zero (mul a b))
|
||
(mul_pos_of_pos_of_pos : ∀a b, lt zero a → lt zero b → lt zero (mul a b))
|
||
|
||
definition ordered_ring.to_ordered_semiring [instance] [s : ordered_ring A] : ordered_semiring A :=
|
||
ordered_semiring.mk ordered_ring.add ordered_ring.add_assoc !ordered_ring.zero
|
||
ordered_ring.add_left_id ordered_ring.add_right_id ordered_ring.add_comm ordered_ring.mul
|
||
ordered_ring.mul_assoc !ordered_ring.one ordered_ring.mul_left_id ordered_ring.mul_right_id
|
||
ordered_ring.left_distrib ordered_ring.right_distrib
|
||
zero_mul_eq mul_zero_eq !ordered_ring.zero_ne_one
|
||
(@add.left_cancel A _) (@add.right_cancel A _)
|
||
ordered_ring.le ordered_ring.le_refl ordered_ring.le_trans ordered_ring.le_antisym
|
||
ordered_ring.lt ordered_ring.lt_iff_le_ne ordered_ring.add_le_add_left
|
||
(@le_of_add_le_add_left A _)
|
||
(take a b c,
|
||
assume Hab : a ≤ b,
|
||
assume Hc : 0 ≤ c,
|
||
show c * a ≤ c * b,
|
||
proof
|
||
have H1 : 0 ≤ b - a, from iff.elim_right !sub_nonneg_iff_le Hab,
|
||
have H2 : 0 ≤ c * (b - a), from ordered_ring.mul_nonneg_of_nonneg_of_nonneg _ _ Hc H1,
|
||
iff.mp !sub_nonneg_iff_le (!mul_sub_left_distrib ▸ H2)
|
||
qed)
|
||
(take a b c,
|
||
assume Hab : a ≤ b,
|
||
assume Hc : 0 ≤ c,
|
||
show a * c ≤ b * c,
|
||
proof
|
||
have H1 : 0 ≤ b - a, from iff.elim_right !sub_nonneg_iff_le Hab,
|
||
have H2 : 0 ≤ (b - a) * c, from ordered_ring.mul_nonneg_of_nonneg_of_nonneg _ _ H1 Hc,
|
||
iff.mp !sub_nonneg_iff_le (!mul_sub_right_distrib ▸ H2)
|
||
qed)
|
||
(take a b c,
|
||
assume Hab : a < b,
|
||
assume Hc : 0 < c,
|
||
show c * a < c * b,
|
||
proof
|
||
have H1 : 0 < b - a, from iff.elim_right !sub_pos_iff_lt Hab,
|
||
have H2 : 0 < c * (b - a), from ordered_ring.mul_pos_of_pos_of_pos _ _ Hc H1,
|
||
iff.mp !sub_pos_iff_lt (!mul_sub_left_distrib ▸ H2)
|
||
qed)
|
||
(take a b c,
|
||
assume Hab : a < b,
|
||
assume Hc : 0 < c,
|
||
show a * c < b * c,
|
||
proof
|
||
have H1 : 0 < b - a, from iff.elim_right !sub_pos_iff_lt Hab,
|
||
have H2 : 0 < (b - a) * c, from ordered_ring.mul_pos_of_pos_of_pos _ _ H1 Hc,
|
||
iff.mp !sub_pos_iff_lt (!mul_sub_right_distrib ▸ H2)
|
||
qed)
|
||
|
||
section
|
||
|
||
variable [s : ordered_ring A]
|
||
variables (a b c : A)
|
||
include s
|
||
|
||
-- TODO: remove after we short-circuit class-graph
|
||
definition ordered_ring.to_mul [instance] [priority 100000] : has_mul A :=
|
||
has_mul.mk (@ordered_ring.mul A s)
|
||
definition ordered_ring.to_lt [instance] [priority 100000] : has_lt A :=
|
||
has_lt.mk (@ordered_ring.lt A s)
|
||
definition ordered_ring.to_zero [instance] [priority 100000] : has_zero A :=
|
||
has_zero.mk (@ordered_ring.zero A s)
|
||
|
||
theorem mul_le_mul_of_nonpos_left {a b c : A} (H : b ≤ a) (Hc : c ≤ 0) : c * a ≤ c * b :=
|
||
have Hc' : -c ≥ 0, from iff.mp' !neg_nonneg_iff_nonpos Hc,
|
||
have H1 : -c * b ≤ -c * a, from mul_le_mul_of_nonneg_left H Hc',
|
||
have H2 : -(c * b) ≤ -(c * a), from !neg_mul_eq_neg_mul⁻¹ ▸ !neg_mul_eq_neg_mul⁻¹ ▸ H1,
|
||
iff.mp !neg_le_neg_iff_le H2
|
||
|
||
theorem mul_le_mul_of_nonpos_right {a b c : A} (H : b ≤ a) (Hc : c ≤ 0) : a * c ≤ b * c :=
|
||
have Hc' : -c ≥ 0, from iff.mp' !neg_nonneg_iff_nonpos Hc,
|
||
have H1 : b * -c ≤ a * -c, from mul_le_mul_of_nonneg_right H Hc',
|
||
have H2 : -(b * c) ≤ -(a * c), from !neg_mul_eq_mul_neg⁻¹ ▸ !neg_mul_eq_mul_neg⁻¹ ▸ H1,
|
||
iff.mp !neg_le_neg_iff_le H2
|
||
|
||
theorem mul_nonneg_of_nonpos_of_nonpos {a b : A} (Ha : a ≤ 0) (Hb : b ≤ 0) : 0 ≤ a * b :=
|
||
!zero_mul_eq ▸ mul_le_mul_of_nonpos_right Ha Hb
|
||
|
||
theorem mul_lt_mul_of_neg_left {a b c : A} (H : b < a) (Hc : c < 0) : c * a < c * b :=
|
||
have Hc' : -c > 0, from iff.mp' !neg_pos_iff_neg Hc,
|
||
have H1 : -c * b < -c * a, from mul_lt_mul_of_pos_left H Hc',
|
||
have H2 : -(c * b) < -(c * a), from !neg_mul_eq_neg_mul⁻¹ ▸ !neg_mul_eq_neg_mul⁻¹ ▸ H1,
|
||
iff.mp !neg_lt_neg_iff_lt H2
|
||
|
||
theorem mul_lt_mul_of_neg_right {a b c : A} (H : b < a) (Hc : c < 0) : a * c < b * c :=
|
||
have Hc' : -c > 0, from iff.mp' !neg_pos_iff_neg Hc,
|
||
have H1 : b * -c < a * -c, from mul_lt_mul_of_pos_right H Hc',
|
||
have H2 : -(b * c) < -(a * c), from !neg_mul_eq_mul_neg⁻¹ ▸ !neg_mul_eq_mul_neg⁻¹ ▸ H1,
|
||
iff.mp !neg_lt_neg_iff_lt H2
|
||
|
||
theorem mul_pos_of_neg_of_neg {a b : A} (Ha : a < 0) (Hb : b < 0) : 0 < a * b :=
|
||
!zero_mul_eq ▸ mul_lt_mul_of_neg_right Ha Hb
|
||
|
||
end
|
||
|
||
-- TODO: we can eliminate mul_pos_of_pos, but now it is not worth the effort to redeclare the class instance
|
||
structure linear_ordered_ring [class] (A : Type) extends ordered_ring A, linear_strong_order_pair A
|
||
|
||
-- TODO: after we break out definition of divides, show that this is an instance of integral domain,
|
||
-- i.e no zero divisors
|
||
|
||
section
|
||
|
||
variable [s : linear_ordered_ring A]
|
||
variables (a b c : A)
|
||
include s
|
||
|
||
theorem mul_self_nonneg : a * a ≥ 0 :=
|
||
or.elim (le.total 0 a)
|
||
(assume H : a ≥ 0, mul_nonneg_of_nonneg_of_nonneg H H)
|
||
(assume H : a ≤ 0, mul_nonneg_of_nonpos_of_nonpos H H)
|
||
|
||
theorem zero_le_one : 0 ≤ 1 := mul.left_id 1 ▸ mul_self_nonneg 1
|
||
|
||
theorem zero_lt_one : 0 < 1 := lt_of_le_of_ne zero_le_one zero_ne_one
|
||
|
||
-- TODO: move these to ordered_group.lean
|
||
theorem lt_add_of_pos_right {a b : A} (H : b > 0) : a < a + b := !add.right_id ▸ add_lt_add_left H a
|
||
theorem lt_add_of_pos_left {a b : A} (H : b > 0) : a < b + a := !add.left_id ▸ add_lt_add_right H a
|
||
theorem le_add_of_nonneg_right {a b : A} (H : b ≥ 0) : a ≤ a + b := !add.right_id ▸ add_le_add_left H a
|
||
theorem le_add_of_nonneg_left {a b : A} (H : b ≥ 0) : a ≤ b + a := !add.left_id ▸ add_le_add_right H a
|
||
|
||
-- TODO: remove after we short-circuit class-graph
|
||
definition linear_ordered_ring.to_mul [instance] [priority 100000] : has_mul A :=
|
||
has_mul.mk (@linear_ordered_ring.mul A s)
|
||
definition linear_ordered_ring.to_lt [instance] [priority 100000] : has_lt A :=
|
||
has_lt.mk (@linear_ordered_ring.lt A s)
|
||
definition linear_ordered_ring.to_zero [instance] [priority 100000] : has_zero A :=
|
||
has_zero.mk (@linear_ordered_ring.zero A s)
|
||
|
||
/- TODO: a good example of a performance bottleneck.
|
||
|
||
Without any of the "proof ... qed" pairs, it exceeds the unifier maximum number of steps.
|
||
|
||
It works with at least one "proof ... qed", but takes about two seconds on my laptop. I do not
|
||
know where the bottleneck is.
|
||
|
||
Adding the explicit arguments to lt_or_eq_or_lt_cases does not seem to help at all. (The proof
|
||
still works if all the instances are replaced by "lt_or_eq_or_lt_cases" alone.)
|
||
|
||
Adding an extra "proof ... qed" around "!mul_zero_eq ▸ Hb⁻¹ ▸ Hab" fails with "value has
|
||
metavariables". I am not sure why.
|
||
-/
|
||
theorem pos_and_pos_or_neg_and_neg_of_mul_pos (Hab : a * b > 0) :
|
||
(a > 0 ∧ b > 0) ∨ (a < 0 ∧ b < 0) :=
|
||
lt_or_eq_or_lt_cases
|
||
(assume Ha : 0 < a,
|
||
lt_or_eq_or_lt_cases
|
||
(assume Hb : 0 < b, or.inl (and.intro Ha Hb))
|
||
(assume Hb : 0 = b,
|
||
absurd (!mul_zero_eq ▸ Hb⁻¹ ▸ Hab) (lt.irrefl 0))
|
||
(assume Hb : b < 0,
|
||
absurd Hab (not_lt_of_lt (mul_neg_of_pos_of_neg Ha Hb))))
|
||
(assume Ha : 0 = a,
|
||
absurd (!zero_mul_eq ▸ Ha⁻¹ ▸ Hab) (lt.irrefl 0))
|
||
(assume Ha : a < 0,
|
||
lt_or_eq_or_lt_cases
|
||
(assume Hb : 0 < b,
|
||
absurd Hab (not_lt_of_lt (mul_neg_of_neg_of_pos Ha Hb)))
|
||
(assume Hb : 0 = b,
|
||
absurd (!mul_zero_eq ▸ Hb⁻¹ ▸ Hab) (lt.irrefl 0))
|
||
(assume Hb : b < 0, or.inr (and.intro Ha Hb)))
|
||
|
||
set_option pp.coercions true
|
||
set_option pp.implicit true
|
||
set_option pp.notation false
|
||
-- print definition pos_and_pos_or_neg_and_neg_of_mul_pos
|
||
|
||
-- TODO: use previous and integral domain
|
||
theorem noneg_and_nonneg_or_nonpos_and_nonpos_of_mul_nonneg (Hab : a * b ≥ 0) :
|
||
(a ≥ 0 ∧ b ≥ 0) ∨ (a ≤ 0 ∧ b ≤ 0) :=
|
||
sorry
|
||
|
||
end
|
||
|
||
/-
|
||
Still left to do:
|
||
|
||
Isabelle's library has all kinds of cancelation rules for the simplifier, search on
|
||
mult_le_cancel_right1 in Rings.thy.
|
||
|
||
Properties of abs, sgn, and dvd.
|
||
|
||
Multiplication and one, starting with mult_right_le_one_le.
|
||
-/
|
||
|
||
structure linear_ordered_comm_ring [class] (A : Type) extends linear_ordered_ring A, comm_monoid A
|
||
|
||
end algebra
|