Skip to content

Commit

Permalink
feat: Bool lemmas (#183)
Browse files Browse the repository at this point in the history
This migrates a large selection of Mathlib theorems on Booleans to std.
  • Loading branch information
fgdorais authored Oct 27, 2023
1 parent bd60d93 commit 65544c3
Show file tree
Hide file tree
Showing 3 changed files with 286 additions and 3 deletions.
1 change: 1 addition & 0 deletions Std.lean
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ import Std.Data.BinomialHeap.Basic
import Std.Data.BinomialHeap.Lemmas
import Std.Data.BitVec
import Std.Data.BitVec.Basic
import Std.Data.Bool
import Std.Data.Char
import Std.Data.DList
import Std.Data.Fin.Basic
Expand Down
256 changes: 256 additions & 0 deletions Std/Data/Bool.lean
Original file line number Diff line number Diff line change
@@ -0,0 +1,256 @@
/-
Copyright (c) 2023 F. G. Dorais. No rights reserved.
Released under Apache 2.0 license as described in the file LICENSE.
Authors: F. G. Dorais
-/

import Std.Tactic.Alias

/-- Boolean exclusive or -/
abbrev xor : Bool → Bool → Bool := bne

namespace Bool

/- Namespaced versions that can be used instead of prefixing `_root_` -/
@[inherit_doc not] protected abbrev not := not
@[inherit_doc or] protected abbrev or := or
@[inherit_doc and] protected abbrev and := and
@[inherit_doc xor] protected abbrev xor := xor

instance (p : Bool → Prop) [inst : DecidablePred p] : Decidable (∀ x, p x) :=
match inst true, inst false with
| isFalse ht, _ => isFalse fun h => absurd (h _) ht
| _, isFalse hf => isFalse fun h => absurd (h _) hf
| isTrue ht, isTrue hf => isTrue fun | true => ht | false => hf

instance (p : Bool → Prop) [inst : DecidablePred p] : Decidable (∃ x, p x) :=
match inst true, inst false with
| isTrue ht, _ => isTrue ⟨_, ht⟩
| _, isTrue hf => isTrue ⟨_, hf⟩
| isFalse ht, isFalse hf => isFalse fun | ⟨true, h⟩ => absurd h ht | ⟨false, h⟩ => absurd h hf

instance : LE Bool := leOfOrd
instance : LT Bool := ltOfOrd
instance : Max Bool := maxOfLe
instance : Min Bool := minOfLe

/-! ### and -/

@[simp] theorem and_not_self_left : ∀ (x : Bool), (!x && x) = false := by
decide

@[simp] theorem and_not_self_right : ∀ (x : Bool), (x && !x) = false := by
decide

theorem and_comm : ∀ (x y : Bool), (x && y) = (y && x) := by
decide

theorem and_left_comm : ∀ (x y z : Bool), (x && (y && z)) = (y && (x && z)) := by
decide

theorem and_right_comm : ∀ (x y z : Bool), ((x && y) && z) = ((x && z) && y) := by
decide

theorem and_or_distrib_left : ∀ (x y z : Bool), (x && (y || z)) = ((x && y) || (x && z)) := by
decide

theorem and_or_distrib_right : ∀ (x y z : Bool), ((x || y) && z) = ((x && z) || (y && z)) := by
decide

theorem and_xor_distrib_left : ∀ (x y z : Bool), (x && xor y z) = xor (x && y) (x && z) := by
decide

theorem and_xor_distrib_right : ∀ (x y z : Bool), (xor x y && z) = xor (x && z) (y && z) := by
decide

theorem and_deMorgan : ∀ (x y : Bool), (!(x && y)) = (!x || !y) := by
decide

theorem and_eq_true_iff : ∀ (x y : Bool), (x && y) = true ↔ x = true ∧ y = true := by
decide

theorem and_eq_false_iff : ∀ (x y : Bool), (x && y) = false ↔ x = false ∨ y = false := by
decide

alias and_false_left := Bool.false_and
alias and_false_right := Bool.and_false
alias and_true_left := Bool.true_and
alias and_true_right := Bool.and_true
alias not_and := Bool.and_deMorgan

/-! ### or -/

@[simp] theorem or_not_self_left : ∀ (x : Bool), (!x || x) = true := by
decide

@[simp] theorem or_not_self_right : ∀ (x : Bool), (x || !x) = true := by
decide

theorem or_comm : ∀ (x y : Bool), (x || y) = (y || x) := by
decide

theorem or_left_comm : ∀ (x y z : Bool), (x || (y || z)) = (y || (x || z)) := by
decide

theorem or_right_comm : ∀ (x y z : Bool), ((x || y) || z) = ((x || z) || y) := by
decide

theorem or_and_distrib_left : ∀ (x y z : Bool), (x || (y && z)) = ((x || y) && (x || z)) := by
decide

theorem or_and_distrib_right : ∀ (x y z : Bool), ((x && y) || z) = ((x || z) && (y || z)) := by
decide

theorem or_deMorgan : ∀ (x y : Bool), (!(x || y)) = (!x && !y) := by
decide

theorem or_eq_true_iff : ∀ (x y : Bool), (x || y) = true ↔ x = true ∨ y = true := by
decide

theorem or_eq_false_iff : ∀ (x y : Bool), (x || y) = false ↔ x = false ∧ y = false := by
decide

alias or_false_left := Bool.false_or
alias or_false_right := Bool.or_false
alias or_true_left := Bool.true_or
alias or_true_right := Bool.or_true
alias not_or := Bool.or_deMorgan

/-! ### xor -/

@[simp] theorem xor_false_left : ∀ (x : Bool), xor false x = x := by
decide

@[simp] theorem xor_false_right : ∀ (x : Bool), xor x false = x := by
decide

@[simp] theorem xor_true_left : ∀ (x : Bool), xor true x = !x := by
decide

@[simp] theorem xor_true_right : ∀ (x : Bool), xor x true = !x := by
decide

@[simp] theorem xor_not_self_left : ∀ (x : Bool), xor (!x) x = true := by
decide

@[simp] theorem xor_not_self_right : ∀ (x : Bool), xor x (!x) = true := by
decide

@[simp] theorem xor_not_left : ∀ (x y : Bool), xor (!x) y = !(xor x y) := by
decide

@[simp] theorem xor_not_right : ∀ (x y : Bool), xor x (!y) = !(xor x y) := by
decide

theorem xor_not_not : ∀ (x y : Bool), xor (!x) (!y) = (xor x y) := by
decide

theorem xor_self : ∀ (x : Bool), xor x x = false := by
decide

theorem xor_comm : ∀ (x y : Bool), xor x y = xor y x := by
decide

theorem xor_left_comm : ∀ (x y z : Bool), xor x (xor y z) = xor y (xor x z) := by
decide

theorem xor_right_comm : ∀ (x y z : Bool), xor (xor x y) z = xor (xor x z) y := by
decide

theorem xor_assoc : ∀ (x y z : Bool), xor (xor x y) z = xor x (xor y z) := by
decide

/-! ### le/lt -/

@[simp] protected theorem le_true : ∀ (x : Bool), x ≤ true := by
decide

@[simp] protected theorem false_le : ∀ (x : Bool), false ≤ x := by
decide

@[simp] protected theorem le_refl : ∀ (x : Bool), x ≤ x := by
decide

@[simp] protected theorem lt_irrefl : ∀ (x : Bool), ¬ x < x := by
decide

protected theorem le_trans : ∀ {x y z : Bool}, x ≤ y → y ≤ z → x ≤ z := by
decide

protected theorem le_antisymm : ∀ {x y : Bool}, x ≤ y → y ≤ x → x = y := by
decide

protected theorem le_total : ∀ (x y : Bool), x ≤ y ∨ y ≤ x := by
decide

protected theorem lt_asymm : ∀ {x y : Bool}, x < y → ¬ y < x := by
decide

protected theorem lt_trans : ∀ {x y z : Bool}, x < y → y < z → x < z := by
decide

protected theorem lt_iff_le_not_le : ∀ {x y : Bool}, x < y ↔ x ≤ y ∧ ¬ y ≤ x := by
decide

protected theorem lt_of_le_of_lt : ∀ {x y z : Bool}, x ≤ y → y < z → x < z := by
decide

protected theorem lt_of_lt_of_le : ∀ {x y z : Bool}, x < y → y ≤ z → x < z := by
decide

protected theorem le_of_lt : ∀ {x y : Bool}, x < y → x ≤ y := by
decide

protected theorem le_of_eq : ∀ {x y : Bool}, x = y → x ≤ y := by
decide

protected theorem ne_of_lt : ∀ {x y : Bool}, x < y → x ≠ y := by
decide

protected theorem lt_of_le_of_ne : ∀ {x y : Bool}, x ≤ y → x ≠ y → x < y := by
decide

protected theorem le_of_lt_or_eq : ∀ {x y : Bool}, x < y ∨ x = y → x ≤ y := by
decide

protected theorem eq_true_of_true_le : ∀ {x : Bool}, true ≤ x → x = true := by
decide

protected theorem eq_false_of_le_false : ∀ {x : Bool}, x ≤ false → x = false := by
decide

/-! ### min/max -/

protected theorem max_eq_or : ∀ (x y : Bool), max x y = (x || y) := by
decide

protected theorem min_eq_and : ∀ (x y : Bool), min x y = (x && y) := by
decide

/-! ### injectivity lemmas -/

theorem not_inj : ∀ {x y : Bool}, (!x) = (!y) → x = y := by
decide

theorem not_inj_iff : ∀ {x y : Bool}, (!x) = (!y) ↔ x = y := by
decide

theorem and_or_inj_right : ∀ {m x y : Bool}, (x && m) = (y && m) → (x || m) = (y || m) → x = y := by
decide

theorem and_or_inj_right_iff :
∀ {m x y : Bool}, (x && m) = (y && m) ∧ (x || m) = (y || m) ↔ x = y := by
decide

theorem and_or_inj_left : ∀ {m x y : Bool}, (m && x) = (m && y) → (m || x) = (m || y) → x = y := by
decide

theorem and_or_inj_left_iff :
∀ {m x y : Bool}, (m && x) = (m && y) ∧ (m || x) = (m || y) ↔ x = y := by
decide

/-! ### deprecated -/

@[deprecated] alias not_inj' := not_inj_iff
@[deprecated] alias and_or_inj_left' := and_or_inj_left_iff
@[deprecated] alias and_or_inj_right' := and_or_inj_right_iff
32 changes: 29 additions & 3 deletions Std/Data/List/Lemmas.lean
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ Released under Apache 2.0 license as described in the file LICENSE.
Authors: Parikshit Khanna, Jeremy Avigad, Leonardo de Moura, Floris van Doorn, Mario Carneiro
-/
import Std.Control.ForInStep.Lemmas
import Std.Data.Bool
import Std.Data.Nat.Lemmas
import Std.Data.List.Basic
import Std.Data.Option.Lemmas
Expand Down Expand Up @@ -987,9 +988,6 @@ theorem length_removeNth : ∀ {l i}, i < length l → length (@removeNth α l i

@[simp] theorem any_eq_true {l : List α} : l.any p ↔ ∃ x ∈ l, p x := by induction l <;> simp [*]

theorem all_eq_not_any_not (l : List α) (p : α → Bool) : l.all p = !l.any (fun c => !p c) := by
rw [Bool.eq_iff_iff]; simp; rw [← Bool.not_eq_true, List.any_eq_true]; simp

@[simp] theorem contains_nil [BEq α] : ([] : List α).contains a = false := rfl

@[simp] theorem contains_cons [BEq α] :
Expand All @@ -1000,6 +998,34 @@ theorem all_eq_not_any_not (l : List α) (p : α → Bool) : l.all p = !l.any (f
theorem contains_eq_any_beq [BEq α] (l : List α) (a : α) : l.contains a = l.any (a == ·) := by
induction l with simp | cons b l => cases a == b <;> simp [*]

theorem not_all_eq_any_not (l : List α) (p : α → Bool) : (!l.all p) = l.any fun a => !p a := by
induction l with simp | cons _ _ ih => rw [Bool.not_and, ih]

theorem not_any_eq_all_not (l : List α) (p : α → Bool) : (!l.any p) = l.all fun a => !p a := by
induction l with simp | cons _ _ ih => rw [Bool.not_or, ih]

theorem or_all_distrib_left (l : List α) (p : α → Bool) (q : Bool) :
(q || l.all p) = l.all fun a => q || p a := by
induction l with simp | cons _ _ ih => rw [Bool.or_and_distrib_left, ih]

theorem or_all_distrib_right (l : List α) (p : α → Bool) (q : Bool) :
(l.all p || q) = l.all fun a => p a || q := by
induction l with simp | cons _ _ ih => rw [Bool.or_and_distrib_right, ih]

theorem and_any_distrib_left (l : List α) (p : α → Bool) (q : Bool) :
(q && l.any p) = l.any fun a => q && p a := by
induction l with simp | cons _ _ ih => rw [Bool.and_or_distrib_left, ih]

theorem and_any_distrib_right (l : List α) (p : α → Bool) (q : Bool) :
(l.any p && q) = l.any fun a => p a && q := by
induction l with simp | cons _ _ ih => rw [Bool.and_or_distrib_right, ih]

theorem any_eq_not_all_not (l : List α) (p : α → Bool) : l.any p = !l.all (!p .) := by
simp only [not_all_eq_any_not, Bool.not_not]

theorem all_eq_not_any_not (l : List α) (p : α → Bool) : l.all p = !l.any (!p .) := by
simp only [not_any_eq_all_not, Bool.not_not]

/-! ### reverse -/

@[simp] theorem mem_reverseAux {x : α} : ∀ {as bs}, x ∈ reverseAux as bs ↔ x ∈ as ∨ x ∈ bs
Expand Down

0 comments on commit 65544c3

Please sign in to comment.