This PR adds useful declarations to the `LawfulOrderMin/Max` and `LawfulOrderLeftLeaningMin/Max` API. In particular, it introduces `.leftLeaningOfLE` factories for `Min` and `Max`. It also renames `LawfulOrderMin/Max.of_le` to .of_le_min_iff` and `.of_max_le_iff` and introduces a second variant with different arguments.
305 lines
11 KiB
Text
305 lines
11 KiB
Text
/-
|
||
Copyright (c) 2025 Lean FRO, LLC. All rights reserved.
|
||
Released under Apache 2.0 license as described in the file LICENSE.
|
||
Authors: Paul Reichert
|
||
-/
|
||
module
|
||
|
||
prelude
|
||
public import Init.Data.Order.Classes
|
||
import Init.Classical
|
||
|
||
namespace Std
|
||
|
||
/-!
|
||
This module provides utilities for the creation of order-related typeclass instances.
|
||
-/
|
||
|
||
section OfLE
|
||
|
||
/--
|
||
Creates a `Min α` instance from `LE α` and `DecidableLE α` so that `min a b` is either `a` or `b`,
|
||
preferring `a` over `b` when in doubt.
|
||
|
||
Has a `LawfulOrderLeftLeaningMin α` instance.
|
||
-/
|
||
@[inline]
|
||
public def _root_.Min.leftLeaningOfLE (α : Type u) [LE α] [DecidableLE α] : Min α where
|
||
min a b := if a ≤ b then a else b
|
||
|
||
/--
|
||
Creates a `Max α` instance from `LE α` and `DecidableLE α` so that `max a b` is either `a` or `b`,
|
||
preferring `a` over `b` when in doubt.
|
||
|
||
Has a `LawfulOrderLeftLeaningMax α` instance.
|
||
-/
|
||
@[inline]
|
||
public def _root_.Max.leftLeaningOfLE (α : Type u) [LE α] [DecidableLE α] : Max α where
|
||
max a b := if b ≤ a then a else b
|
||
|
||
/--
|
||
This instance is only publicly defined in `Init.Data.Order.Lemmas`.
|
||
-/
|
||
instance {r : α → α → Prop} [Total r] : Refl r where
|
||
refl a := by simpa using Total.total a a
|
||
|
||
/--
|
||
If an `LE α` instance is reflexive and transitive, then it represents a preorder.
|
||
-/
|
||
public theorem IsPreorder.of_le {α : Type u} [LE α]
|
||
(le_refl : Std.Refl (α := α) (· ≤ ·) := by exact inferInstance)
|
||
(le_trans : Trans (α := α) (· ≤ ·) (· ≤ ·) (· ≤ ·) := by exact inferInstance) :
|
||
IsPreorder α where
|
||
le_refl := le_refl.refl
|
||
le_trans _ _ _ := le_trans.trans
|
||
|
||
/--
|
||
If an `LE α` instance is transitive and total, then it represents a linear preorder.
|
||
-/
|
||
public theorem IsLinearPreorder.of_le {α : Type u} [LE α]
|
||
(le_trans : Trans (α := α) (· ≤ ·) (· ≤ ·) (· ≤ ·) := by exact inferInstance)
|
||
(le_total : Total (α := α) (· ≤ ·) := by exact inferInstance) :
|
||
IsLinearPreorder α where
|
||
toIsPreorder := .of_le
|
||
le_total := le_total.total
|
||
|
||
/--
|
||
If an `LE α` is reflexive, antisymmetric and transitive, then it represents a partial order.
|
||
-/
|
||
public theorem IsPartialOrder.of_le {α : Type u} [LE α]
|
||
(le_refl : Std.Refl (α := α) (· ≤ ·) := by exact inferInstance)
|
||
(le_antisymm : Std.Antisymm (α := α) (· ≤ ·) := by exact inferInstance)
|
||
(le_trans : Trans (α := α) (· ≤ ·) (· ≤ ·) (· ≤ ·) := by exact inferInstance) :
|
||
IsPartialOrder α where
|
||
toIsPreorder := .of_le
|
||
le_antisymm := le_antisymm.antisymm
|
||
|
||
/--
|
||
If an `LE α` instance is antisymmetric, transitive and total, then it represents a linear order.
|
||
-/
|
||
public theorem IsLinearOrder.of_le {α : Type u} [LE α]
|
||
(le_antisymm : Std.Antisymm (α := α) (· ≤ ·) := by exact inferInstance)
|
||
(le_trans : Trans (α := α) (· ≤ ·) (· ≤ ·) (· ≤ ·) := by exact inferInstance)
|
||
(le_total : Total (α := α) (· ≤ ·) := by exact inferInstance) :
|
||
IsLinearOrder α where
|
||
toIsLinearPreorder := .of_le
|
||
le_antisymm := le_antisymm.antisymm
|
||
|
||
/--
|
||
This lemma derives a `LawfulOrderLT α` instance from a property involving an `LE α` instance.
|
||
-/
|
||
public theorem LawfulOrderLT.of_le {α : Type u} [LT α] [LE α]
|
||
(lt_iff : ∀ a b : α, a < b ↔ a ≤ b ∧ ¬ b ≤ a) : LawfulOrderLT α where
|
||
lt_iff := lt_iff
|
||
|
||
/--
|
||
This lemma derives a `LawfulOrderBEq α` instance from a property involving an `LE α` instance.
|
||
-/
|
||
public theorem LawfulOrderBEq.of_le {α : Type u} [BEq α] [LE α]
|
||
(beq_iff : ∀ a b : α, a == b ↔ a ≤ b ∧ b ≤ a) : LawfulOrderBEq α where
|
||
beq_iff_le_and_ge := by simp [beq_iff]
|
||
|
||
/--
|
||
This lemma characterizes in terms of `LE α` when a `Min α` instance "behaves like an infimum
|
||
operator".
|
||
-/
|
||
public theorem LawfulOrderInf.of_le {α : Type u} [Min α] [LE α]
|
||
(le_min_iff : ∀ a b c : α, a ≤ min b c ↔ a ≤ b ∧ a ≤ c) : LawfulOrderInf α where
|
||
le_min_iff := le_min_iff
|
||
|
||
/--
|
||
Returns a `LawfulOrderMin α` instance given certain properties.
|
||
|
||
This lemma derives a `LawfulOrderMin α` instance from two properties involving `LE α` and `Min α`
|
||
instances.
|
||
|
||
The produced instance entails `LawfulOrderInf α` and `MinEqOr α`.
|
||
-/
|
||
public theorem LawfulOrderMin.of_le_min_iff {α : Type u} [Min α] [LE α]
|
||
(le_min_iff : ∀ a b c : α, a ≤ min b c ↔ a ≤ b ∧ a ≤ c := by exact LawfulOrderInf.le_min_iff)
|
||
(min_eq_or : ∀ a b : α, min a b = a ∨ min a b = b := by exact MinEqOr.min_eq_or) :
|
||
LawfulOrderMin α where
|
||
toLawfulOrderInf := .of_le le_min_iff
|
||
toMinEqOr := ⟨min_eq_or⟩
|
||
|
||
/--
|
||
Returns a `LawfulOrderMin α` instance given that `max a b` returns either `a` or `b` and that
|
||
it is less than or equal to both of them. The `≤` relation needs to be transitive.
|
||
|
||
The produced instance entails `LawfulOrderInf α` and `MinEqOr α`.
|
||
-/
|
||
public theorem LawfulOrderMin.of_min_le {α : Type u} [Min α] [LE α]
|
||
[i : Trans (α := α) (· ≤ ·) (· ≤ ·) (· ≤ ·)]
|
||
(min_le_left : ∀ a b : α, min a b ≤ a) (min_le_right : ∀ a b : α, min a b ≤ b)
|
||
(min_eq_or : ∀ a b : α, min a b = a ∨ min a b = b := by exact MinEqOr.min_eq_or) :
|
||
LawfulOrderMin α := by
|
||
apply LawfulOrderMin.of_le_min_iff
|
||
· simp [autoParam]
|
||
intro a b c
|
||
constructor
|
||
· intro h
|
||
exact ⟨i.trans h (min_le_left b c), i.trans h (min_le_right b c)⟩
|
||
· intro h
|
||
cases min_eq_or b c <;> simp [*]
|
||
· exact min_eq_or
|
||
|
||
/--
|
||
This lemma characterizes in terms of `LE α` when a `Max α` instance "behaves like a supremum
|
||
operator".
|
||
-/
|
||
public def LawfulOrderSup.of_le {α : Type u} [Max α] [LE α]
|
||
(max_le_iff : ∀ a b c : α, max a b ≤ c ↔ a ≤ c ∧ b ≤ c) : LawfulOrderSup α where
|
||
max_le_iff := max_le_iff
|
||
|
||
/--
|
||
Returns a `LawfulOrderMax α` instance given certain properties.
|
||
|
||
This lemma derives a `LawfulOrderMax α` instance from two properties involving `LE α` and `Max α`
|
||
instances.
|
||
|
||
The produced instance entails `LawfulOrderSup α` and `MaxEqOr α`.
|
||
-/
|
||
public def LawfulOrderMax.of_max_le_iff {α : Type u} [Max α] [LE α]
|
||
(max_le_iff : ∀ a b c : α, max a b ≤ c ↔ a ≤ c ∧ b ≤ c := by exact LawfulOrderInf.le_min_iff)
|
||
(max_eq_or : ∀ a b : α, max a b = a ∨ max a b = b := by exact MaxEqOr.max_eq_or) :
|
||
LawfulOrderMax α where
|
||
toLawfulOrderSup := .of_le max_le_iff
|
||
toMaxEqOr := ⟨max_eq_or⟩
|
||
|
||
/--
|
||
Returns a `LawfulOrderMax α` instance given that `max a b` returns either `a` or `b` and that
|
||
it is larger than or equal to both of them. The `≤` relation needs to be transitive.
|
||
|
||
The produced instance entails `LawfulOrderSup α` and `MaxEqOr α`.
|
||
-/
|
||
public theorem LawfulOrderMax.of_le_max {α : Type u} [Max α] [LE α]
|
||
[i : Trans (α := α) (· ≤ ·) (· ≤ ·) (· ≤ ·)]
|
||
(left_le_max : ∀ a b : α, a ≤ max a b) (right_le_max : ∀ a b : α, b ≤ max a b)
|
||
(max_eq_or : ∀ a b : α, max a b = a ∨ max a b = b := by exact MaxEqOr.max_eq_or) :
|
||
LawfulOrderMax α := by
|
||
apply LawfulOrderMax.of_max_le_iff
|
||
· simp [autoParam]
|
||
intro a b c
|
||
constructor
|
||
· intro h
|
||
exact ⟨i.trans (left_le_max a b) h, i.trans (right_le_max a b) h⟩
|
||
· intro h
|
||
cases max_eq_or a b <;> simp [*]
|
||
· exact max_eq_or
|
||
|
||
end OfLE
|
||
|
||
section OfLT
|
||
|
||
/--
|
||
Creates a *total* `LE α` instance from an `LT α` instance.
|
||
|
||
This only makes sense for asymmetric `LT α` instances (see `Std.Asymm`).
|
||
-/
|
||
@[inline]
|
||
public def _root_.LE.ofLT (α : Type u) [LT α] : LE α where
|
||
le a b := ¬ b < a
|
||
|
||
/--
|
||
The `LE α` instance obtained from an asymmetric `LT α` instance is compatible with said
|
||
`LT α` instance.
|
||
-/
|
||
public instance LawfulOrderLT.of_lt {α : Type u} [LT α] [i : Asymm (α := α) (· < ·)] :
|
||
haveI := LE.ofLT α
|
||
LawfulOrderLT α :=
|
||
letI := LE.ofLT α
|
||
{ lt_iff a b := by simpa [LE.ofLT, Classical.not_not] using i.asymm a b }
|
||
|
||
/--
|
||
If an `LT α` instance is asymmetric and its negation is transitive, then `LE.ofLT α` represents a
|
||
linear preorder.
|
||
-/
|
||
public theorem IsLinearPreorder.of_lt {α : Type u} [LT α]
|
||
(lt_asymm : Asymm (α := α) (· < ·) := by exact inferInstance)
|
||
(not_lt_trans : Trans (α := α) (¬ · < ·) (¬ · < ·) (¬ · < ·) := by exact inferInstance) :
|
||
haveI := LE.ofLT α
|
||
IsLinearPreorder α :=
|
||
letI := LE.ofLT α
|
||
{ le_trans := by simpa [LE.ofLT] using fun a b c hab hbc => not_lt_trans.trans hbc hab
|
||
le_total a b := by
|
||
apply Or.symm
|
||
open Classical in simpa [LE.ofLT, Decidable.imp_iff_not_or] using lt_asymm.asymm a b
|
||
le_refl a := by
|
||
open Classical in simpa [LE.ofLT] using lt_asymm.asymm a a }
|
||
|
||
/--
|
||
If an `LT α` instance is asymmetric and its negation is transitive and antisymmetric, then
|
||
`LE.ofLT α` represents a linear order.
|
||
-/
|
||
public theorem IsLinearOrder.of_lt {α : Type u} [LT α]
|
||
(lt_asymm : Asymm (α := α) (· < ·) := by exact inferInstance)
|
||
(not_lt_trans : Trans (α := α) (¬ · < ·) (¬ · < ·) (¬ · < ·) := by exact inferInstance)
|
||
(not_lt_antisymm : Antisymm (α := α) (¬ · < ·) := by exact inferInstance) :
|
||
haveI := LE.ofLT α
|
||
IsLinearOrder α :=
|
||
letI := LE.ofLT α
|
||
haveI : IsLinearPreorder α := .of_lt
|
||
{ le_antisymm := by
|
||
simpa [LE.ofLT] using fun a b hab hba => not_lt_antisymm.antisymm a b hba hab }
|
||
|
||
/--
|
||
This lemma characterizes in terms of `LT α` when a `Min α` instance
|
||
"behaves like an infimum operator" with respect to `LE.ofLT α`.
|
||
-/
|
||
public theorem LawfulOrderInf.of_lt {α : Type u} [Min α] [LT α]
|
||
(min_lt_iff : ∀ a b c : α, min b c < a ↔ b < a ∨ c < a) :
|
||
haveI := LE.ofLT α
|
||
LawfulOrderInf α :=
|
||
letI := LE.ofLT α
|
||
{ le_min_iff a b c := by
|
||
open Classical in
|
||
simp only [LE.ofLT, ← Decidable.not_iff_not (a := ¬ min b c < a)]
|
||
simpa [Decidable.imp_iff_not_or] using min_lt_iff a b c }
|
||
|
||
/--
|
||
Derives a `LawfulOrderMin α` instance for `LE.ofLT` from two properties involving
|
||
`LT α` and `Min α` instances.
|
||
|
||
The produced instance entails `LawfulOrderInf α` and `MinEqOr α`.
|
||
-/
|
||
public theorem LawfulOrderMin.of_lt {α : Type u} [Min α] [LT α]
|
||
(min_lt_iff : ∀ a b c : α, min b c < a ↔ b < a ∨ c < a)
|
||
(min_eq_or : ∀ a b : α, min a b = a ∨ min a b = b) :
|
||
haveI := LE.ofLT α
|
||
LawfulOrderMin α :=
|
||
letI := LE.ofLT α
|
||
{ toLawfulOrderInf := .of_lt min_lt_iff
|
||
toMinEqOr := ⟨min_eq_or⟩ }
|
||
|
||
/--
|
||
This lemma characterizes in terms of `LT α` when a `Max α` instance
|
||
"behaves like an supremum operator" with respect to `LE.ofLT α`.
|
||
-/
|
||
public def LawfulOrderSup.of_lt {α : Type u} [Max α] [LT α]
|
||
(lt_max_iff : ∀ a b c : α, c < max a b ↔ c < a ∨ c < b) :
|
||
haveI := LE.ofLT α
|
||
LawfulOrderSup α :=
|
||
letI := LE.ofLT α
|
||
{ max_le_iff a b c := by
|
||
open Classical in
|
||
simp only [LE.ofLT, ← Decidable.not_iff_not ( a := ¬ c < max a b)]
|
||
simpa [Decidable.imp_iff_not_or] using lt_max_iff a b c }
|
||
|
||
/--
|
||
Derives a `LawfulOrderMax α` instance for `LE.ofLT` from two properties involving `LT α` and
|
||
`Max α` instances.
|
||
|
||
The produced instance entails `LawfulOrderSup α` and `MaxEqOr α`.
|
||
-/
|
||
public def LawfulOrderMax.of_lt {α : Type u} [Max α] [LT α]
|
||
(lt_max_iff : ∀ a b c : α, c < max a b ↔ c < a ∨ c < b)
|
||
(max_eq_or : ∀ a b : α, max a b = a ∨ max a b = b) :
|
||
haveI := LE.ofLT α
|
||
LawfulOrderMax α :=
|
||
letI := LE.ofLT α
|
||
{ toLawfulOrderSup := .of_lt lt_max_iff
|
||
toMaxEqOr := ⟨max_eq_or⟩ }
|
||
|
||
end OfLT
|
||
|
||
end Std
|