Skip to content

Commit 2b55585

Browse files
feat: to_dual attribute (#27887)
This PR defines the `to_dual` attribute for translating lemmas to their dual. This is useful in order theory and in category theory. It is built on top of the `to_additive` machinery. This PR only adds `@[to_dual]` tags in files that directly need to import `ToDual`, namely `Order/Defs/PartialOrder`, `Order/Notation` and `Combinatorics/Quiver/Basic`. Further tagging is left for (many) future PRs. This PR continues the work from #21719 Related (mathlib3) issues: - leanprover-community/mathlib3#13461 - leanprover-community/mathlib3#7691 Co-authored-by: @bryangingechen Co-authored-by: Bryan Gin-ge Chen <bryangingechen@gmail.com>
1 parent 8af997f commit 2b55585

File tree

18 files changed

+1153
-789
lines changed

18 files changed

+1153
-789
lines changed

Mathlib.lean

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6508,6 +6508,9 @@ import Mathlib.Tactic.TermCongr
65086508
import Mathlib.Tactic.ToAdditive
65096509
import Mathlib.Tactic.ToAdditive.Frontend
65106510
import Mathlib.Tactic.ToAdditive.GuessName
6511+
import Mathlib.Tactic.ToAdditive.ToAdditive
6512+
import Mathlib.Tactic.ToAdditive.ToDual
6513+
import Mathlib.Tactic.ToDual
65116514
import Mathlib.Tactic.ToExpr
65126515
import Mathlib.Tactic.ToLevel
65136516
import Mathlib.Tactic.Trace

Mathlib/Algebra/Order/Group/Defs.lean

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ but we still use the namespaces.
5959
6060
TODO: everything in these namespaces should be renamed; even if these typeclasses still existed,
6161
it's unconventional to put theorems in namespaces named after them. -/
62-
run_meta ToAdditive.insertTranslation `LinearOrderedCommGroup `LinearOrderedAddCommGroup
62+
insert_to_additive_translation LinearOrderedCommGroup LinearOrderedAddCommGroup
6363

6464
section LinearOrderedCommGroup
6565

Mathlib/Combinatorics/Quiver/Basic.lean

Lines changed: 31 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ Released under Apache 2.0 license as described in the file LICENSE.
44
Authors: David Wärn, Kim Morrison
55
-/
66
import Mathlib.Data.Opposite
7+
import Mathlib.Tactic.ToDual
78

89
/-!
910
# Quivers
@@ -41,6 +42,8 @@ class Quiver (V : Type u) where
4142
/-- The type of edges/arrows/morphisms between a given source and target. -/
4243
Hom : V → V → Sort v
4344

45+
attribute [to_dual self (reorder := 3 4)] Quiver.Hom
46+
4447
/--
4548
Notation for the type of edges/arrows/morphisms between a given source and target
4649
in a quiver or category.
@@ -54,13 +57,15 @@ instance opposite {V} [Quiver V] : Quiver Vᵒᵖ :=
5457
fun a b => (unop b ⟶ unop a)ᵒᵖ⟩
5558

5659
/-- The opposite of an arrow in `V`. -/
60+
@[to_dual self (reorder := 3 4)]
5761
def Hom.op {V} [Quiver V] {X Y : V} (f : X ⟶ Y) : op Y ⟶ op X := ⟨f⟩
5862

5963
/-- Given an arrow in `Vᵒᵖ`, we can take the "unopposite" back in `V`. -/
64+
@[to_dual self (reorder := 3 4)]
6065
def Hom.unop {V} [Quiver V] {X Y : Vᵒᵖ} (f : X ⟶ Y) : unop Y ⟶ unop X := Opposite.unop f
6166

6267
/-- The bijection `(X ⟶ Y) ≃ (op Y ⟶ op X)`. -/
63-
@[simps]
68+
@[simps, to_dual self (reorder := 3 4)]
6469
def Hom.opEquiv {V} [Quiver V] {X Y : V} :
6570
(X ⟶ Y) ≃ (Opposite.op Y ⟶ Opposite.op X) where
6671
toFun := Opposite.op
@@ -71,64 +76,70 @@ def Empty (V : Type u) : Type u := V
7176

7277
instance emptyQuiver (V : Type u) : Quiver.{u} (Empty V) := ⟨fun _ _ => PEmpty⟩
7378

74-
@[simp]
79+
@[simp, to_dual self (reorder := 2 3)]
7580
theorem empty_arrow {V : Type u} (a b : Empty V) : (a ⟶ b) = PEmpty := rfl
7681

7782
/-- A quiver is thin if it has no parallel arrows. -/
83+
@[to_dual IsThin' /-- `isThin'` is equivalent to `IsThin`.
84+
It is used by `@[to_dual]` to be able to translate `IsThin`. -/]
7885
abbrev IsThin (V : Type u) [Quiver V] : Prop := ∀ a b : V, Subsingleton (a ⟶ b)
7986

8087

8188
section
8289

83-
variable {V : Type*} [Quiver V]
90+
variable {V : Type*} [Quiver V] {X Y X' Y' : V}
8491

8592
/-- An arrow in a quiver can be transported across equalities between the source and target
8693
objects. -/
87-
def homOfEq {X Y : V} (f : X ⟶ Y) {X' Y' : V} (hX : X = X') (hY : Y = Y') : X' ⟶ Y' := by
94+
@[to_dual self (reorder := 3 4, 5 6, 8 9)]
95+
def homOfEq (f : X ⟶ Y) (hX : X = X') (hY : Y = Y') : X' ⟶ Y' := by
8896
subst hX hY
8997
exact f
9098

91-
@[simp]
92-
lemma homOfEq_trans {X Y : V} (f : X ⟶ Y) {X' Y' : V} (hX : X = X') (hY : Y = Y')
99+
@[simp, to_dual self (reorder := 3 4, 5 6, 8 9, 10 11, 12 13)]
100+
lemma homOfEq_trans (f : X ⟶ Y) (hX : X = X') (hY : Y = Y')
93101
{X'' Y'' : V} (hX' : X' = X'') (hY' : Y' = Y'') :
94102
homOfEq (homOfEq f hX hY) hX' hY' = homOfEq f (hX.trans hX') (hY.trans hY') := by
95103
subst hX hY hX' hY'
96104
rfl
97105

98-
lemma homOfEq_injective {X X' Y Y' : V} (hX : X = X') (hY : Y = Y')
106+
@[to_dual self (reorder := 3 4, 5 6, 7 8)]
107+
lemma homOfEq_injective (hX : X = X') (hY : Y = Y')
99108
{f g : X ⟶ Y} (h : Quiver.homOfEq f hX hY = Quiver.homOfEq g hX hY) : f = g := by
100109
subst hX hY
101110
exact h
102111

103-
@[simp]
104-
lemma homOfEq_rfl {X Y : V} (f : X ⟶ Y) : Quiver.homOfEq f rfl rfl = f := rfl
112+
@[simp, to_dual self (reorder := 3 4)]
113+
lemma homOfEq_rfl (f : X ⟶ Y) : Quiver.homOfEq f rfl rfl = f := rfl
105114

106-
lemma heq_of_homOfEq_ext {X Y X' Y' : V} (hX : X = X') (hY : Y = Y') {f : X ⟶ Y} {f' : X' ⟶ Y'}
115+
@[to_dual self (reorder := 3 4, 5 6, 7 8)]
116+
lemma heq_of_homOfEq_ext (hX : X = X') (hY : Y = Y') {f : X ⟶ Y} {f' : X' ⟶ Y'}
107117
(e : Quiver.homOfEq f hX hY = f') : f ≍ f' := by
108118
subst hX hY
109119
rw [Quiver.homOfEq_rfl] at e
110120
rw [e]
111121

112-
lemma homOfEq_eq_iff {X X' Y Y' : V} (f : X ⟶ Y) (g : X' ⟶ Y')
113-
(hX : X = X') (hY : Y = Y') :
122+
@[to_dual self (reorder := 3 4, 5 6, 9 10)]
123+
lemma homOfEq_eq_iff (f : X ⟶ Y) (g : X' ⟶ Y') (hX : X = X') (hY : Y = Y') :
114124
Quiver.homOfEq f hX hY = g ↔ f = Quiver.homOfEq g hX.symm hY.symm := by
115125
subst hX hY; simp
116126

117-
lemma eq_homOfEq_iff {X X' Y Y' : V} (f : X ⟶ Y) (g : X' ⟶ Y')
118-
(hX : X' = X) (hY : Y' = Y) :
127+
@[to_dual self (reorder := 3 4, 5 6, 9 10)]
128+
lemma eq_homOfEq_iff (f : X ⟶ Y) (g : X' ⟶ Y') (hX : X' = X) (hY : Y' = Y) :
119129
f = Quiver.homOfEq g hX hY ↔ Quiver.homOfEq f hX.symm hY.symm = g := by
120130
subst hX hY; simp
121131

122-
lemma homOfEq_heq {X Y X' Y' : V} (hX : X = X') (hY : Y = Y') (f : X ⟶ Y) :
123-
homOfEq f hX hY ≍ f := (heq_of_homOfEq_ext hX hY rfl).symm
132+
@[to_dual self (reorder := 3 4, 5 6, 7 8)]
133+
lemma homOfEq_heq (hX : X = X') (hY : Y = Y') (f : X ⟶ Y) : homOfEq f hX hY ≍ f :=
134+
(heq_of_homOfEq_ext hX hY rfl).symm
124135

125-
lemma homOfEq_heq_left_iff {X Y X' Y' : V} (f : X ⟶ Y) (g : X' ⟶ Y')
126-
(hX : X = X') (hY : Y = Y') :
136+
@[to_dual self (reorder := 3 4, 5 6, 9 10)]
137+
lemma homOfEq_heq_left_iff (f : X ⟶ Y) (g : X' ⟶ Y') (hX : X = X') (hY : Y = Y') :
127138
homOfEq f hX hY ≍ g ↔ f ≍ g := by
128139
cases hX; cases hY; rfl
129140

130-
lemma homOfEq_heq_right_iff {X Y X' Y' : V} (f : X ⟶ Y) (g : X' ⟶ Y')
131-
(hX : X' = X) (hY : Y' = Y) :
141+
@[to_dual self (reorder := 3 4, 5 6, 9 10)]
142+
lemma homOfEq_heq_right_iff (f : X ⟶ Y) (g : X' ⟶ Y') (hX : X' = X) (hY : Y' = Y) :
132143
f ≍ homOfEq g hX hY ↔ f ≍ g := by
133144
cases hX; cases hY; rfl
134145

Mathlib/GroupTheory/Coset/Defs.lean

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ open scoped Pointwise
4646
variable {α : Type*}
4747

4848
/- Ensure that `@[to_additive]` uses the right namespace. -/
49-
run_meta ToAdditive.insertTranslation `QuotientGroup `QuotientAddGroup
49+
insert_to_additive_translation QuotientGroup QuotientAddGroup
5050

5151
namespace QuotientGroup
5252

Mathlib/GroupTheory/FreeGroup/Basic.lean

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ variable {α : Type u}
5858
attribute [local simp] List.append_eq_has_append
5959

6060
/- Ensure that `@[to_additive]` uses the right namespace before the definition of `FreeGroup`. -/
61-
run_meta ToAdditive.insertTranslation `FreeGroup `FreeAddGroup
61+
insert_to_additive_translation FreeGroup FreeAddGroup
6262

6363
/-- Reduction step for the additive free group relation: `w + x + (-x) + v ~> w + v` -/
6464
inductive FreeAddGroup.Red.Step : List (α × Bool) → List (α × Bool) → Prop

Mathlib/GroupTheory/MonoidLocalization/Basic.lean

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -115,7 +115,7 @@ end Submonoid
115115
namespace Localization
116116

117117
/- Ensure that `@[to_additive]` uses the right namespace before the definition of `Localization`. -/
118-
run_meta ToAdditive.insertTranslation `Localization `AddLocalization
118+
insert_to_additive_translation Localization AddLocalization
119119

120120
/-- The congruence relation on `M × S`, `M` a `CommMonoid` and `S` a submonoid of `M`, whose
121121
quotient is the localization of `M` at `S`, defined as the unique congruence relation on

Mathlib/Order/Basic.lean

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -128,8 +128,6 @@ lemma not_lt_iff_le_imp_ge : ¬ a < b ↔ (a ≤ b → b ≤ a) := by
128128

129129
@[deprecated (since := "2025-05-11")] alias not_lt_iff_le_imp_le := not_lt_iff_le_imp_ge
130130

131-
lemma ge_of_eq (h : a = b) : b ≤ a := le_of_eq h.symm
132-
133131
@[simp] lemma lt_self_iff_false (x : α) : x < x ↔ False := ⟨lt_irrefl x, False.elim⟩
134132

135133
alias le_trans' := ge_trans
@@ -209,11 +207,6 @@ section PartialOrder
209207

210208
variable [PartialOrder α] {a b : α}
211209

212-
theorem ge_antisymm : a ≤ b → b ≤ a → b = a :=
213-
flip le_antisymm
214-
215-
theorem lt_of_le_of_ne' : a ≤ b → b ≠ a → a < b := fun h₁ h₂ ↦ lt_of_le_of_ne h₁ h₂.symm
216-
217210
theorem Ne.lt_of_le : a ≠ b → a ≤ b → a < b :=
218211
flip lt_of_le_of_ne
219212

@@ -293,7 +286,6 @@ protected theorem Decidable.eq_or_lt_of_le [DecidableLE α] (h : a ≤ b) : a =
293286

294287
theorem eq_or_lt_of_le (h : a ≤ b) : a = b ∨ a < b := (lt_or_eq_of_le h).symm
295288
theorem eq_or_lt_of_le' (h : a ≤ b) : b = a ∨ a < b := (eq_or_lt_of_le h).imp Eq.symm id
296-
theorem lt_or_eq_of_le' (h : a ≤ b) : a < b ∨ b = a := (eq_or_lt_of_le' h).symm
297289

298290
alias LE.le.lt_or_eq_dec := Decidable.lt_or_eq_of_le
299291
alias LE.le.eq_or_lt_dec := Decidable.eq_or_lt_of_le

Mathlib/Order/Defs/PartialOrder.lean

Lines changed: 50 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import Mathlib.Tactic.ExtendDoc
99
import Mathlib.Tactic.Lemma
1010
import Mathlib.Tactic.SplitIfs
1111
import Mathlib.Tactic.TypeStar
12+
import Mathlib.Tactic.ToDual
1213

1314
/-!
1415
# Orders
@@ -43,6 +44,9 @@ class Preorder (α : Type*) extends LE α, LT α where
4344
lt := fun a b => a ≤ b ∧ ¬b ≤ a
4445
lt_iff_le_not_ge : ∀ a b : α, a < b ↔ a ≤ b ∧ ¬b ≤ a := by intros; rfl
4546

47+
attribute [to_dual self (reorder := 3 5, 6 7)] Preorder.le_trans
48+
attribute [to_dual self (reorder := 3 4)] Preorder.lt_iff_le_not_ge
49+
4650
instance [Preorder α] : Std.LawfulOrderLT α where
4751
lt_iff := Preorder.lt_iff_le_not_ge
4852

@@ -61,79 +65,92 @@ variable [Preorder α] {a b c : α}
6165
lemma le_rfl : a ≤ a := le_refl a
6266

6367
/-- The relation `≤` on a preorder is transitive. -/
64-
lemma le_trans : a ≤ b → b ≤ c → a ≤ c := Preorder.le_trans _ _ _
68+
@[to_dual ge_trans] lemma le_trans : a ≤ b → b ≤ c → a ≤ c := Preorder.le_trans _ _ _
6569

70+
@[to_dual self (reorder := 3 4)]
6671
lemma lt_iff_le_not_ge : a < b ↔ a ≤ b ∧ ¬b ≤ a := Preorder.lt_iff_le_not_ge _ _
6772

6873
@[deprecated (since := "2025-05-11")] alias lt_iff_le_not_le := lt_iff_le_not_ge
6974

75+
@[to_dual self (reorder := 3 4)]
7076
lemma lt_of_le_not_ge (hab : a ≤ b) (hba : ¬ b ≤ a) : a < b := lt_iff_le_not_ge.2 ⟨hab, hba⟩
7177

7278
@[deprecated (since := "2025-05-11")] alias lt_of_le_not_le := lt_of_le_not_ge
7379

80+
@[to_dual ge_of_eq]
7481
lemma le_of_eq (hab : a = b) : a ≤ b := by rw [hab]
82+
@[to_dual self (reorder := 3 4)]
7583
lemma le_of_lt (hab : a < b) : a ≤ b := (lt_iff_le_not_ge.1 hab).1
84+
@[to_dual self (reorder := 3 4)]
7685
lemma not_le_of_gt (hab : a < b) : ¬ b ≤ a := (lt_iff_le_not_ge.1 hab).2
86+
@[to_dual self (reorder := 3 4)]
7787
lemma not_lt_of_ge (hab : a ≤ b) : ¬ b < a := imp_not_comm.1 not_le_of_gt hab
7888

7989
@[deprecated (since := "2025-05-11")] alias not_le_of_lt := not_le_of_gt
8090
@[deprecated (since := "2025-05-11")] alias not_lt_of_le := not_lt_of_ge
8191

82-
alias LT.lt.not_ge := not_le_of_gt
83-
alias LE.le.not_gt := not_lt_of_ge
92+
@[to_dual self (reorder := 3 4)] alias LT.lt.not_ge := not_le_of_gt
93+
@[to_dual self (reorder := 3 4)] alias LE.le.not_gt := not_lt_of_ge
8494

8595
@[deprecated (since := "2025-06-07")] alias LT.lt.not_le := LT.lt.not_ge
8696
@[deprecated (since := "2025-06-07")] alias LE.le.not_lt := LE.le.not_gt
8797

88-
89-
lemma ge_trans : b ≤ a → c ≤ b → c ≤ a := fun h₁ h₂ => le_trans h₂ h₁
90-
91-
lemma lt_irrefl (a : α) : ¬a < a := fun h ↦ not_le_of_gt h le_rfl
98+
@[to_dual self] lemma lt_irrefl (a : α) : ¬a < a := fun h ↦ not_le_of_gt h le_rfl
9299

93100
@[deprecated (since := "2025-06-07")] alias gt_irrefl := lt_irrefl
94101

102+
@[to_dual lt_of_lt_of_le']
95103
lemma lt_of_lt_of_le (hab : a < b) (hbc : b ≤ c) : a < c :=
96104
lt_of_le_not_ge (le_trans (le_of_lt hab) hbc) fun hca ↦ not_le_of_gt hab (le_trans hbc hca)
97105

106+
@[to_dual lt_of_le_of_lt']
98107
lemma lt_of_le_of_lt (hab : a ≤ b) (hbc : b < c) : a < c :=
99108
lt_of_le_not_ge (le_trans hab (le_of_lt hbc)) fun hca ↦ not_le_of_gt hbc (le_trans hca hab)
100109

101-
lemma lt_of_lt_of_le' : b < a → c ≤ b → c < a := flip lt_of_le_of_lt
102-
lemma lt_of_le_of_lt' : b ≤ a → c < b → c < a := flip lt_of_lt_of_le
103-
104110
@[deprecated (since := "2025-06-07")] alias gt_of_gt_of_ge := lt_of_lt_of_le'
105111
@[deprecated (since := "2025-06-07")] alias gt_of_ge_of_gt := lt_of_le_of_lt'
106112

113+
@[to_dual gt_trans]
107114
lemma lt_trans : a < b → b < c → a < c := fun h₁ h₂ => lt_of_lt_of_le h₁ (le_of_lt h₂)
108-
lemma gt_trans : b < a → c < b → c < a := flip lt_trans
109115

116+
@[to_dual ne_of_gt]
110117
lemma ne_of_lt (h : a < b) : a ≠ b := fun he => absurd h (he ▸ lt_irrefl a)
111-
lemma ne_of_gt (h : b < a) : a ≠ b := fun he => absurd h (he ▸ lt_irrefl a)
118+
@[to_dual self (reorder := 3 4)]
112119
lemma lt_asymm (h : a < b) : ¬b < a := fun h1 : b < a => lt_irrefl a (lt_trans h h1)
113120

121+
@[to_dual self (reorder := 3 4)]
114122
alias not_lt_of_gt := lt_asymm
115-
116123
@[deprecated (since := "2025-05-11")] alias not_lt_of_lt := not_lt_of_gt
117124

125+
@[to_dual le_of_lt_or_eq']
118126
lemma le_of_lt_or_eq (h : a < b ∨ a = b) : a ≤ b := h.elim le_of_lt le_of_eq
127+
@[to_dual le_of_eq_or_lt']
119128
lemma le_of_eq_or_lt (h : a = b ∨ a < b) : a ≤ b := h.elim le_of_eq le_of_lt
120129

121-
instance : @Trans α α α LE.le LE.le LE.le := ⟨le_trans⟩
122-
instance : @Trans α α α LT.lt LT.lt LT.lt := ⟨lt_trans⟩
123-
instance : @Trans α α α LT.lt LE.le LT.lt := ⟨lt_of_lt_of_le⟩
124-
instance : @Trans α α α LE.le LT.lt LT.lt := ⟨lt_of_le_of_lt⟩
125-
instance : @Trans α α α GE.ge GE.ge GE.ge := ⟨ge_trans⟩
126-
instance : @Trans α α α GT.gt GT.gt GT.gt := ⟨gt_trans⟩
127-
instance : @Trans α α α GT.gt GE.ge GT.gt := ⟨lt_of_lt_of_le'⟩
128-
instance : @Trans α α α GE.ge GT.gt GT.gt := ⟨lt_of_le_of_lt'⟩
130+
instance instTransLE : @Trans α α α LE.le LE.le LE.le := ⟨le_trans⟩
131+
instance instTransLT : @Trans α α α LT.lt LT.lt LT.lt := ⟨lt_trans⟩
132+
instance instTransLTLE : @Trans α α α LT.lt LE.le LT.lt := ⟨lt_of_lt_of_le⟩
133+
instance instTransLELT : @Trans α α α LE.le LT.lt LT.lt := ⟨lt_of_le_of_lt⟩
134+
-- we have to express the following 4 instances in terms of `≥` instead of flipping the arguments
135+
-- to `≤`, because otherwise `calc` gets confused.
136+
@[to_dual existing instTransLE]
137+
instance instTransGE : @Trans α α α GE.ge GE.ge GE.ge := ⟨ge_trans⟩
138+
@[to_dual existing instTransLT]
139+
instance instTransGT : @Trans α α α GT.gt GT.gt GT.gt := ⟨gt_trans⟩
140+
@[to_dual existing instTransLTLE]
141+
instance instTransGTGE : @Trans α α α GT.gt GE.ge GT.gt := ⟨lt_of_lt_of_le'⟩
142+
@[to_dual existing instTransLELT]
143+
instance instTransGEGT : @Trans α α α GE.ge GT.gt GT.gt := ⟨lt_of_le_of_lt'⟩
129144

130145
/-- `<` is decidable if `≤` is. -/
146+
@[to_dual decidableGTOfDecidableGE /-- `<` is decidable if `≤` is. -/]
131147
def decidableLTOfDecidableLE [DecidableLE α] : DecidableLT α :=
132148
fun _ _ => decidable_of_iff _ lt_iff_le_not_ge.symm
133149

134150
/-- `WCovBy a b` means that `a = b` or `b` covers `a`.
135151
This means that `a ≤ b` and there is no element in between. This is denoted `a ⩿ b`.
136152
-/
153+
@[to_dual self (reorder := 3 4)]
137154
def WCovBy (a b : α) : Prop :=
138155
a ≤ b ∧ ∀ ⦃c⦄, a < c → ¬c < b
139156

@@ -142,6 +159,7 @@ infixl:50 " ⩿ " => WCovBy
142159

143160
/-- `CovBy a b` means that `b` covers `a`. This means that `a < b` and there is no element in
144161
between. This is denoted `a ⋖ b`. -/
162+
@[to_dual self (reorder := 3 4)]
145163
def CovBy {α : Type*} [LT α] (a b : α) : Prop :=
146164
a < b ∧ ∀ ⦃c⦄, a < c → ¬c < b
147165

@@ -160,38 +178,49 @@ section PartialOrder
160178
class PartialOrder (α : Type*) extends Preorder α where
161179
le_antisymm : ∀ a b : α, a ≤ b → b ≤ a → a = b
162180

181+
attribute [to_dual self (reorder := 5 6)] PartialOrder.le_antisymm
182+
163183
instance [PartialOrder α] : Std.IsPartialOrder α where
164184
le_antisymm := PartialOrder.le_antisymm
165185

166186
variable [PartialOrder α] {a b : α}
167187

188+
@[to_dual ge_antisymm]
168189
lemma le_antisymm : a ≤ b → b ≤ a → a = b := PartialOrder.le_antisymm _ _
169190

191+
@[to_dual eq_of_ge_of_le]
170192
alias eq_of_le_of_ge := le_antisymm
171193

172194
@[deprecated (since := "2025-06-07")] alias eq_of_le_of_le := eq_of_le_of_ge
173195

196+
@[to_dual ge_antisymm_iff]
174197
lemma le_antisymm_iff : a = b ↔ a ≤ b ∧ b ≤ a :=
175198
fun e => ⟨le_of_eq e, le_of_eq e.symm⟩, fun ⟨h1, h2⟩ => le_antisymm h1 h2⟩
176199

200+
@[to_dual lt_of_le_of_ne']
177201
lemma lt_of_le_of_ne : a ≤ b → a ≠ b → a < b := fun h₁ h₂ =>
178202
lt_of_le_not_ge h₁ <| mt (le_antisymm h₁) h₂
179203

180204
/-- Equality is decidable if `≤` is. -/
205+
@[to_dual decidableEqofDecidableGE /-- Equality is decidable if `≤` is. -/]
181206
def decidableEqOfDecidableLE [DecidableLE α] : DecidableEq α
182207
| a, b =>
183208
if hab : a ≤ b then
184209
if hba : b ≤ a then isTrue (le_antisymm hab hba) else isFalse fun heq => hba (heq ▸ le_refl _)
185210
else isFalse fun heq => hab (heq ▸ le_refl _)
186211

187212
-- See Note [decidable namespace]
213+
@[to_dual Decidable.lt_or_eq_of_le']
188214
protected lemma Decidable.lt_or_eq_of_le [DecidableLE α] (hab : a ≤ b) : a < b ∨ a = b :=
189215
if hba : b ≤ a then Or.inr (le_antisymm hab hba) else Or.inl (lt_of_le_not_ge hab hba)
190216

217+
@[to_dual Decidable.le_iff_lt_or_eq']
191218
protected lemma Decidable.le_iff_lt_or_eq [DecidableLE α] : a ≤ b ↔ a < b ∨ a = b :=
192219
⟨Decidable.lt_or_eq_of_le, le_of_lt_or_eq⟩
193220

221+
@[to_dual lt_or_eq_of_le']
194222
lemma lt_or_eq_of_le : a ≤ b → a < b ∨ a = b := open scoped Classical in Decidable.lt_or_eq_of_le
223+
@[to_dual le_iff_lt_or_eq']
195224
lemma le_iff_lt_or_eq : a ≤ b ↔ a < b ∨ a = b := open scoped Classical in Decidable.le_iff_lt_or_eq
196225

197226
end PartialOrder

0 commit comments

Comments
 (0)