|
| 1 | +/- |
| 2 | +Copyright (c) 2014 Jeremy Avigad. All rights reserved. |
| 3 | +Released under Apache 2.0 license as described in the file LICENSE. |
| 4 | +Authors: Jeremy Avigad, Yury Kudryashov, Yaël Dillies |
| 5 | +-/ |
| 6 | +import Mathlib.Order.Synonym |
| 7 | + |
| 8 | +/-! |
| 9 | +# Minimal/maximal and bottom/top elements |
| 10 | +
|
| 11 | +This file defines predicates for elements to be minimal/maximal or bottom/top and typeclasses |
| 12 | +saying that there are no such elements. |
| 13 | +
|
| 14 | +## Predicates |
| 15 | +
|
| 16 | +* `IsBot`: An element is *bottom* if all elements are greater than it. |
| 17 | +* `IsTop`: An element is *top* if all elements are less than it. |
| 18 | +* `IsMin`: An element is *minimal* if no element is strictly less than it. |
| 19 | +* `IsMax`: An element is *maximal* if no element is strictly greater than it. |
| 20 | +
|
| 21 | +See also `isBot_iff_isMin` and `isTop_iff_isMax` for the equivalences in a (co)directed order. |
| 22 | +
|
| 23 | +## Typeclasses |
| 24 | +
|
| 25 | +* `NoBotOrder`: An order without bottom elements. |
| 26 | +* `NoTopOrder`: An order without top elements. |
| 27 | +* `NoMinOrder`: An order without minimal elements. |
| 28 | +* `NoMaxOrder`: An order without maximal elements. |
| 29 | +-/ |
| 30 | + |
| 31 | + |
| 32 | +open OrderDual |
| 33 | + |
| 34 | +variable {α β : Type _} |
| 35 | + |
| 36 | +/-- Order without bottom elements. -/ |
| 37 | +class NoBotOrder (α : Type _) [LE α] : Prop where |
| 38 | + /-- For each term `a`, there is some `b` which is either incomparable or strictly smaller. -/ |
| 39 | + exists_not_ge (a : α) : ∃ b, ¬a ≤ b |
| 40 | + |
| 41 | +/-- Order without top elements. -/ |
| 42 | +class NoTopOrder (α : Type _) [LE α] : Prop where |
| 43 | + /-- For each term `a`, there is some `b` which is either incomparable or strictly larger. -/ |
| 44 | + exists_not_le (a : α) : ∃ b, ¬b ≤ a |
| 45 | + |
| 46 | +/-- Order without minimal elements. Sometimes called coinitial or dense. -/ |
| 47 | +class NoMinOrder (α : Type _) [LT α] : Prop where |
| 48 | + /-- For each term `a`, there is some strictly smaller `b`. -/ |
| 49 | + exists_lt (a : α) : ∃ b, b < a |
| 50 | + |
| 51 | +/-- Order without maximal elements. Sometimes called cofinal. -/ |
| 52 | +class NoMaxOrder (α : Type _) [LT α] : Prop where |
| 53 | + /-- For each term `a`, there is some strictly greater `b`. -/ |
| 54 | + exists_gt (a : α) : ∃ b, a < b |
| 55 | + |
| 56 | +export NoBotOrder (exists_not_ge) |
| 57 | + |
| 58 | +export NoTopOrder (exists_not_le) |
| 59 | + |
| 60 | +export NoMinOrder (exists_lt) |
| 61 | + |
| 62 | +export NoMaxOrder (exists_gt) |
| 63 | + |
| 64 | +instance [LT α] [NoMinOrder α] (a : α) : Nonempty { x // x < a } := |
| 65 | + nonempty_subtype.2 (exists_lt a) |
| 66 | + |
| 67 | +instance [LT α] [NoMaxOrder α] (a : α) : Nonempty { x // a < x } := |
| 68 | + nonempty_subtype.2 (exists_gt a) |
| 69 | + |
| 70 | +instance [LE α] [NoTopOrder α] : NoBotOrder αᵒᵈ := |
| 71 | + ⟨fun a => @exists_not_le α _ _ a⟩ |
| 72 | + |
| 73 | +instance [LE α] [NoBotOrder α] : NoTopOrder αᵒᵈ := |
| 74 | + ⟨fun a => @exists_not_ge α _ _ a⟩ |
| 75 | + |
| 76 | +instance [LT α] [NoMaxOrder α] : NoMinOrder αᵒᵈ := |
| 77 | + ⟨fun a => @exists_gt α _ _ a⟩ |
| 78 | + |
| 79 | +instance [LT α] [NoMinOrder α] : NoMaxOrder αᵒᵈ := |
| 80 | + ⟨fun a => @exists_lt α _ _ a⟩ |
| 81 | + |
| 82 | +-- See note [lower instance priority] |
| 83 | +instance (priority := 100) [Preorder α] [NoMinOrder α] : NoBotOrder α := |
| 84 | + ⟨fun a => (exists_lt a).imp fun _ => not_le_of_lt⟩ |
| 85 | + |
| 86 | +-- See note [lower instance priority] |
| 87 | +instance (priority := 100) [Preorder α] [NoMaxOrder α] : NoTopOrder α := |
| 88 | + ⟨fun a => (exists_gt a).imp fun _ => not_le_of_lt⟩ |
| 89 | + |
| 90 | +-- Porting note: mathlib3 proof uses `convert` |
| 91 | +theorem NoBotOrder.to_noMinOrder (α : Type _) [LinearOrder α] [NoBotOrder α] : NoMinOrder α := |
| 92 | + { exists_lt := fun a => by simpa [not_le] using exists_not_ge a } |
| 93 | +#align no_bot_order.to_no_min_order NoBotOrder.to_noMinOrder |
| 94 | + |
| 95 | +-- Porting note: mathlib3 proof uses `convert` |
| 96 | +theorem NoTopOrder.to_noMaxOrder (α : Type _) [LinearOrder α] [NoTopOrder α] : NoMaxOrder α := |
| 97 | + { exists_gt := fun a => by simpa [not_le] using exists_not_le a } |
| 98 | +#align no_top_order.to_no_max_order NoTopOrder.to_noMaxOrder |
| 99 | + |
| 100 | +theorem no_bot_order_iff_no_min_order (α : Type _) [LinearOrder α] : NoBotOrder α ↔ NoMinOrder α := |
| 101 | + ⟨fun h => |
| 102 | + haveI := h |
| 103 | + NoBotOrder.to_noMinOrder α, |
| 104 | + fun h => |
| 105 | + haveI := h |
| 106 | + inferInstance⟩ |
| 107 | + |
| 108 | +theorem no_top_order_iff_no_max_order (α : Type _) [LinearOrder α] : NoTopOrder α ↔ NoMaxOrder α := |
| 109 | + ⟨fun h => |
| 110 | + haveI := h |
| 111 | + NoTopOrder.to_noMaxOrder α, |
| 112 | + fun h => |
| 113 | + haveI := h |
| 114 | + inferInstance⟩ |
| 115 | + |
| 116 | +theorem NoMinOrder.not_acc [LT α] [NoMinOrder α] (a : α) : ¬Acc (· < ·) a := fun h => |
| 117 | + Acc.recOn h fun x _ => (exists_lt x).recOn |
| 118 | + |
| 119 | +theorem NoMaxOrder.not_acc [LT α] [NoMaxOrder α] (a : α) : ¬Acc (· > ·) a := fun h => |
| 120 | + Acc.recOn h fun x _ => (exists_gt x).recOn |
| 121 | + |
| 122 | +section LE |
| 123 | + |
| 124 | +variable [LE α] {a b : α} |
| 125 | + |
| 126 | +/-- `a : α` is a bottom element of `α` if it is less than or equal to any other element of `α`. |
| 127 | +This predicate is roughly an unbundled version of `OrderBot`, except that a preorder may have |
| 128 | +several bottom elements. When `α` is linear, this is useful to make a case disjunction on |
| 129 | +`NoMinOrder α` within a proof. -/ |
| 130 | +def IsBot (a : α) : Prop := |
| 131 | + ∀ b, a ≤ b |
| 132 | + |
| 133 | +/-- `a : α` is a top element of `α` if it is greater than or equal to any other element of `α`. |
| 134 | +This predicate is roughly an unbundled version of `OrderBot`, except that a preorder may have |
| 135 | +several top elements. When `α` is linear, this is useful to make a case disjunction on |
| 136 | +`NoMaxOrder α` within a proof. -/ |
| 137 | +def IsTop (a : α) : Prop := |
| 138 | + ∀ b, b ≤ a |
| 139 | + |
| 140 | +/-- `a` is a minimal element of `α` if no element is strictly less than it. We spell it without `<` |
| 141 | +to avoid having to convert between `≤` and `<`. Instead, `is_min_iff_forall_not_lt` does the |
| 142 | +conversion. -/ |
| 143 | +def IsMin (a : α) : Prop := |
| 144 | + ∀ ⦃b⦄, b ≤ a → a ≤ b |
| 145 | + |
| 146 | +/-- `a` is a maximal element of `α` if no element is strictly greater than it. We spell it without |
| 147 | +`<` to avoid having to convert between `≤` and `<`. Instead, `is_max_iff_forall_not_lt` does the |
| 148 | +conversion. -/ |
| 149 | +def IsMax (a : α) : Prop := |
| 150 | + ∀ ⦃b⦄, a ≤ b → b ≤ a |
| 151 | + |
| 152 | +@[simp] |
| 153 | +theorem not_is_bot [NoBotOrder α] (a : α) : ¬IsBot a := fun h => |
| 154 | + let ⟨_, hb⟩ := exists_not_ge a |
| 155 | + hb <| h _ |
| 156 | + |
| 157 | +@[simp] |
| 158 | +theorem not_is_top [NoTopOrder α] (a : α) : ¬IsTop a := fun h => |
| 159 | + let ⟨_, hb⟩ := exists_not_le a |
| 160 | + hb <| h _ |
| 161 | + |
| 162 | +protected theorem IsBot.is_min (h : IsBot a) : IsMin a := fun b _ => h b |
| 163 | + |
| 164 | +protected theorem IsTop.is_max (h : IsTop a) : IsMax a := fun b _ => h b |
| 165 | + |
| 166 | +@[simp] |
| 167 | +theorem is_bot_to_dual_iff : IsBot (toDual a) ↔ IsTop a := |
| 168 | + Iff.rfl |
| 169 | + |
| 170 | +@[simp] |
| 171 | +theorem is_top_to_dual_iff : IsTop (toDual a) ↔ IsBot a := |
| 172 | + Iff.rfl |
| 173 | + |
| 174 | +@[simp] |
| 175 | +theorem is_min_to_dual_iff : IsMin (toDual a) ↔ IsMax a := |
| 176 | + Iff.rfl |
| 177 | + |
| 178 | +@[simp] |
| 179 | +theorem is_max_to_dual_iff : IsMax (toDual a) ↔ IsMin a := |
| 180 | + Iff.rfl |
| 181 | + |
| 182 | +@[simp] |
| 183 | +theorem is_bot_of_dual_iff {a : αᵒᵈ} : IsBot (ofDual a) ↔ IsTop a := |
| 184 | + Iff.rfl |
| 185 | + |
| 186 | +@[simp] |
| 187 | +theorem is_top_of_dual_iff {a : αᵒᵈ} : IsTop (ofDual a) ↔ IsBot a := |
| 188 | + Iff.rfl |
| 189 | + |
| 190 | +@[simp] |
| 191 | +theorem is_min_of_dual_iff {a : αᵒᵈ} : IsMin (ofDual a) ↔ IsMax a := |
| 192 | + Iff.rfl |
| 193 | + |
| 194 | +@[simp] |
| 195 | +theorem is_max_of_dual_iff {a : αᵒᵈ} : IsMax (ofDual a) ↔ IsMin a := |
| 196 | + Iff.rfl |
| 197 | + |
| 198 | +alias is_bot_to_dual_iff ↔ _ IsTop.to_dual |
| 199 | + |
| 200 | +alias is_top_to_dual_iff ↔ _ IsBot.to_dual |
| 201 | + |
| 202 | +alias is_min_to_dual_iff ↔ _ IsMax.to_dual |
| 203 | + |
| 204 | +alias is_max_to_dual_iff ↔ _ IsMin.to_dual |
| 205 | + |
| 206 | +alias is_bot_of_dual_iff ↔ _ IsTop.of_dual |
| 207 | + |
| 208 | +alias is_top_of_dual_iff ↔ _ IsBot.of_dual |
| 209 | + |
| 210 | +alias is_min_of_dual_iff ↔ _ IsMax.of_dual |
| 211 | + |
| 212 | +alias is_max_of_dual_iff ↔ _ IsMin.of_dual |
| 213 | + |
| 214 | +end LE |
| 215 | + |
| 216 | +section Preorder |
| 217 | + |
| 218 | +variable [Preorder α] {a b : α} |
| 219 | + |
| 220 | +theorem IsBot.mono (ha : IsBot a) (h : b ≤ a) : IsBot b := fun _ => h.trans <| ha _ |
| 221 | + |
| 222 | +theorem IsTop.mono (ha : IsTop a) (h : a ≤ b) : IsTop b := fun _ => (ha _).trans h |
| 223 | + |
| 224 | +theorem IsMin.mono (ha : IsMin a) (h : b ≤ a) : IsMin b := fun _ hc => h.trans <| ha <| hc.trans h |
| 225 | + |
| 226 | +theorem IsMax.mono (ha : IsMax a) (h : a ≤ b) : IsMax b := fun _ hc => (ha <| h.trans hc).trans h |
| 227 | + |
| 228 | +theorem IsMin.not_lt (h : IsMin a) : ¬b < a := fun hb => hb.not_le <| h hb.le |
| 229 | + |
| 230 | +theorem IsMax.not_lt (h : IsMax a) : ¬a < b := fun hb => hb.not_le <| h hb.le |
| 231 | + |
| 232 | +@[simp] |
| 233 | +theorem not_is_min_of_lt (h : b < a) : ¬IsMin a := fun ha => ha.not_lt h |
| 234 | + |
| 235 | +@[simp] |
| 236 | +theorem not_is_max_of_lt (h : a < b) : ¬IsMax a := fun ha => ha.not_lt h |
| 237 | + |
| 238 | +alias not_is_min_of_lt ← LT.lt.not_is_min |
| 239 | + |
| 240 | +alias not_is_max_of_lt ← LT.lt.not_is_max |
| 241 | + |
| 242 | +theorem is_min_iff_forall_not_lt : IsMin a ↔ ∀ b, ¬b < a := |
| 243 | + ⟨fun h _ => h.not_lt, fun h _ hba => of_not_not fun hab => h _ <| hba.lt_of_not_le hab⟩ |
| 244 | + |
| 245 | +theorem is_max_iff_forall_not_lt : IsMax a ↔ ∀ b, ¬a < b := |
| 246 | + ⟨fun h _ => h.not_lt, fun h _ hba => of_not_not fun hab => h _ <| hba.lt_of_not_le hab⟩ |
| 247 | + |
| 248 | +@[simp] |
| 249 | +theorem not_is_min_iff : ¬IsMin a ↔ ∃ b, b < a := by |
| 250 | + simp [lt_iff_le_not_le, IsMin, not_forall, exists_prop] |
| 251 | + |
| 252 | +@[simp] |
| 253 | +theorem not_is_max_iff : ¬IsMax a ↔ ∃ b, a < b := by |
| 254 | + simp [lt_iff_le_not_le, IsMax, not_forall, exists_prop] |
| 255 | + |
| 256 | +@[simp] |
| 257 | +theorem not_is_min [NoMinOrder α] (a : α) : ¬IsMin a := |
| 258 | + not_is_min_iff.2 <| exists_lt a |
| 259 | + |
| 260 | +@[simp] |
| 261 | +theorem not_is_max [NoMaxOrder α] (a : α) : ¬IsMax a := |
| 262 | + not_is_max_iff.2 <| exists_gt a |
| 263 | + |
| 264 | +namespace Subsingleton |
| 265 | + |
| 266 | +variable [Subsingleton α] |
| 267 | + |
| 268 | +protected theorem is_bot (a : α) : IsBot a := fun _ => (Subsingleton.elim _ _).le |
| 269 | + |
| 270 | +protected theorem is_top (a : α) : IsTop a := fun _ => (Subsingleton.elim _ _).le |
| 271 | + |
| 272 | +protected theorem is_min (a : α) : IsMin a := |
| 273 | + (Subsingleton.is_bot _).is_min |
| 274 | + |
| 275 | +protected theorem is_max (a : α) : IsMax a := |
| 276 | + (Subsingleton.is_top _).is_max |
| 277 | + |
| 278 | +end Subsingleton |
| 279 | + |
| 280 | +end Preorder |
| 281 | + |
| 282 | +section PartialOrder |
| 283 | + |
| 284 | +variable [PartialOrder α] {a b : α} |
| 285 | + |
| 286 | +protected theorem IsMin.eq_of_le (ha : IsMin a) (h : b ≤ a) : b = a := |
| 287 | + h.antisymm <| ha h |
| 288 | + |
| 289 | +protected theorem IsMin.eq_of_ge (ha : IsMin a) (h : b ≤ a) : a = b := |
| 290 | + h.antisymm' <| ha h |
| 291 | + |
| 292 | +protected theorem IsMax.eq_of_le (ha : IsMax a) (h : a ≤ b) : a = b := |
| 293 | + h.antisymm <| ha h |
| 294 | + |
| 295 | +protected theorem IsMax.eq_of_ge (ha : IsMax a) (h : a ≤ b) : b = a := |
| 296 | + h.antisymm' <| ha h |
| 297 | + |
| 298 | +end PartialOrder |
| 299 | + |
| 300 | +section Prod |
| 301 | + |
| 302 | +variable [Preorder α] [Preorder β] {a a₁ a₂ : α} {b b₁ b₂ : β} {x y : α × β} |
| 303 | + |
| 304 | +theorem IsBot.prod_mk (ha : IsBot a) (hb : IsBot b) : IsBot (a, b) := fun _ => ⟨ha _, hb _⟩ |
| 305 | + |
| 306 | +theorem IsTop.prod_mk (ha : IsTop a) (hb : IsTop b) : IsTop (a, b) := fun _ => ⟨ha _, hb _⟩ |
| 307 | + |
| 308 | +theorem IsMin.prod_mk (ha : IsMin a) (hb : IsMin b) : IsMin (a, b) := fun _ hc => ⟨ha hc.1, hb hc.2⟩ |
| 309 | + |
| 310 | +theorem IsMax.prod_mk (ha : IsMax a) (hb : IsMax b) : IsMax (a, b) := fun _ hc => ⟨ha hc.1, hb hc.2⟩ |
| 311 | + |
| 312 | +theorem IsBot.fst (hx : IsBot x) : IsBot x.1 := fun c => (hx (c, x.2)).1 |
| 313 | + |
| 314 | +theorem IsBot.snd (hx : IsBot x) : IsBot x.2 := fun c => (hx (x.1, c)).2 |
| 315 | + |
| 316 | +theorem IsTop.fst (hx : IsTop x) : IsTop x.1 := fun c => (hx (c, x.2)).1 |
| 317 | + |
| 318 | +theorem IsTop.snd (hx : IsTop x) : IsTop x.2 := fun c => (hx (x.1, c)).2 |
| 319 | + |
| 320 | +theorem IsMin.fst (hx : IsMin x) : IsMin x.1 := |
| 321 | + fun c hc => (hx <| show (c, x.2) ≤ x from (and_iff_left le_rfl).2 hc).1 |
| 322 | + |
| 323 | +theorem IsMin.snd (hx : IsMin x) : IsMin x.2 := |
| 324 | + fun c hc => (hx <| show (x.1, c) ≤ x from (and_iff_right le_rfl).2 hc).2 |
| 325 | + |
| 326 | +theorem IsMax.fst (hx : IsMax x) : IsMax x.1 := |
| 327 | + fun c hc => (hx <| show x ≤ (c, x.2) from (and_iff_left le_rfl).2 hc).1 |
| 328 | + |
| 329 | +theorem IsMax.snd (hx : IsMax x) : IsMax x.2 := |
| 330 | + fun c hc => (hx <| show x ≤ (x.1, c) from (and_iff_right le_rfl).2 hc).2 |
| 331 | + |
| 332 | +theorem Prod.is_bot_iff : IsBot x ↔ IsBot x.1 ∧ IsBot x.2 := |
| 333 | + ⟨fun hx => ⟨hx.fst, hx.snd⟩, fun h => h.1.prod_mk h.2⟩ |
| 334 | + |
| 335 | +theorem Prod.is_top_iff : IsTop x ↔ IsTop x.1 ∧ IsTop x.2 := |
| 336 | + ⟨fun hx => ⟨hx.fst, hx.snd⟩, fun h => h.1.prod_mk h.2⟩ |
| 337 | + |
| 338 | +theorem Prod.is_min_iff : IsMin x ↔ IsMin x.1 ∧ IsMin x.2 := |
| 339 | + ⟨fun hx => ⟨hx.fst, hx.snd⟩, fun h => h.1.prod_mk h.2⟩ |
| 340 | + |
| 341 | +theorem Prod.is_max_iff : IsMax x ↔ IsMax x.1 ∧ IsMax x.2 := |
| 342 | + ⟨fun hx => ⟨hx.fst, hx.snd⟩, fun h => h.1.prod_mk h.2⟩ |
| 343 | + |
| 344 | +end Prod |
0 commit comments