From dc57de22942673b45ce0a54c067255abbdefb47a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ya=C3=ABl=20Dillies?= Date: Thu, 23 Dec 2021 22:35:57 +0000 Subject: [PATCH] feat(logic/basic): When a dependent If-Then-Else is not one of its arguments (#10924) This is the dependent version of #10800. --- src/logic/basic.lean | 58 +++++++++++++++++++++++++++++++------------- 1 file changed, 41 insertions(+), 17 deletions(-) diff --git a/src/logic/basic.lean b/src/logic/basic.lean index 41894003118a4..2ee55e35b9e51 100644 --- a/src/logic/basic.lean +++ b/src/logic/basic.lean @@ -340,6 +340,8 @@ is classically true but not constructively. -/ theorem of_not_not : ¬¬a → a := by_contra +lemma not_ne_iff {α : Sort*} {a b : α} : ¬ a ≠ b ↔ a = b := not_not + -- See Note [decidable namespace] protected theorem decidable.of_not_imp [decidable a] (h : ¬ (a → b)) : a := decidable.by_contradiction (not_not_of_not_imp h) @@ -1087,6 +1089,9 @@ theorem forall_prop_of_true {p : Prop} {q : p → Prop} (h : p) : (∀ h' : p, q theorem exists_prop_of_true {p : Prop} {q : p → Prop} (h : p) : (∃ h' : p, q h') ↔ q h := @exists_const (q h) p ⟨h⟩ +lemma exists_iff_of_forall {p : Prop} {q : p → Prop} (h : ∀ h, q h) : (∃ h, q h) ↔ p := +⟨Exists.fst, λ H, ⟨H, h H⟩⟩ + theorem exists_unique_prop_of_true {p : Prop} {q : p → Prop} (h : p) : (∃! h' : p, q h') ↔ q h := @exists_unique_const (q h) p ⟨h⟩ _ @@ -1316,38 +1321,57 @@ end classical section ite variables {α β γ : Sort*} {σ : α → Sort*} (f : α → β) {P Q : Prop} [decidable P] [decidable Q] - {a b c : α} + {a b c : α} {A : P → α} {B : ¬ P → α} + +lemma dite_eq_iff : dite P A B = c ↔ (∃ h, A h = c) ∨ ∃ h, B h = c := by by_cases P; simp * +lemma ite_eq_iff : ite P a b = c ↔ P ∧ a = c ∨ ¬ P ∧ b = c := +dite_eq_iff.trans $ by rw [exists_prop, exists_prop] + +@[simp] lemma dite_eq_left_iff : dite P (λ _, a) B = a ↔ ∀ h, B h = a := by by_cases P; simp * +@[simp] lemma dite_eq_right_iff : dite P A (λ _, b) = b ↔ ∀ h, A h = b := by by_cases P; simp * +@[simp] lemma ite_eq_left_iff : ite P a b = a ↔ (¬ P → b = a) := dite_eq_left_iff +@[simp] lemma ite_eq_right_iff : ite P a b = b ↔ (P → a = b) := dite_eq_right_iff -lemma ite_eq_iff : ite P a b = c ↔ P ∧ a = c ∨ ¬ P ∧ b = c := by by_cases P; simp * +lemma dite_ne_left_iff : dite P (λ _, a) B ≠ a ↔ ∃ h, a ≠ B h := +by { rw [ne.def, dite_eq_left_iff, not_forall], exact exists_congr (λ h, by rw ne_comm) } -@[simp] lemma ite_eq_left_iff : ite P a b = a ↔ (¬ P → b = a) := by by_cases P; simp * -@[simp] lemma ite_eq_right_iff : ite P a b = b ↔ (P → a = b) := by by_cases P; simp * +lemma dite_ne_right_iff : dite P A (λ _, b) ≠ b ↔ ∃ h, A h ≠ b := +by simp only [ne.def, dite_eq_right_iff, not_forall] -lemma ite_ne_left_iff : ite P a b ≠ a ↔ ¬ P ∧ a ≠ b := -by rw [ne.def, ite_eq_left_iff, ne_comm, not_imp] +lemma ite_ne_left_iff : ite P a b ≠ a ↔ ¬ P ∧ a ≠ b := dite_ne_left_iff.trans $ by rw exists_prop +lemma ite_ne_right_iff : ite P a b ≠ b ↔ P ∧ a ≠ b := dite_ne_right_iff.trans $ by rw exists_prop -lemma ite_ne_right_iff : ite P a b ≠ b ↔ P ∧ a ≠ b := by rw [ne.def, ite_eq_right_iff, not_imp] +protected lemma ne.dite_eq_left_iff (h : ∀ h, a ≠ B h) : dite P (λ _, a) B = a ↔ P := +dite_eq_left_iff.trans $ ⟨λ H, of_not_not $ λ h', h h' (H h').symm, λ h H, (H h).elim⟩ -protected lemma ne.ite_eq_left_iff (h : a ≠ b) : ite P a b = a ↔ P := -ite_eq_left_iff.trans $ not_imp_comm.trans $ imp_iff_right h.symm +protected lemma ne.dite_eq_right_iff (h : ∀ h, A h ≠ b) : dite P A (λ _, b) = b ↔ ¬ P := +dite_eq_right_iff.trans $ ⟨λ H h', h h' (H h'), λ h' H, (h' H).elim⟩ +protected lemma ne.ite_eq_left_iff (h : a ≠ b) : ite P a b = a ↔ P := ne.dite_eq_left_iff $ λ _, h protected lemma ne.ite_eq_right_iff (h : a ≠ b) : ite P a b = b ↔ ¬ P := -ite_eq_right_iff.trans $ imp_iff_not h +ne.dite_eq_right_iff $ λ _, h -protected lemma ne.ite_ne_left_iff (h : a ≠ b) : ite P a b ≠ a ↔ ¬ P := -ite_ne_left_iff.trans $ and_iff_left h +protected lemma ne.dite_ne_left_iff (h : ∀ h, a ≠ B h) : dite P (λ _, a) B ≠ a ↔ ¬ P := +dite_ne_left_iff.trans $ exists_iff_of_forall h -protected lemma ne.ite_ne_right_iff (h : a ≠ b) : ite P a b ≠ b ↔ P := -ite_ne_right_iff.trans $ and_iff_left h +protected lemma ne.dite_ne_right_iff (h : ∀ h, A h ≠ b) : dite P A (λ _, b) ≠ b ↔ P := +dite_ne_right_iff.trans $ exists_iff_of_forall h -variables (P Q) (a b) +protected lemma ne.ite_ne_left_iff (h : a ≠ b) : ite P a b ≠ a ↔ ¬ P := ne.dite_ne_left_iff $ λ _, h -lemma ite_eq_or_eq : ite P a b = a ∨ ite P a b = b := -decidable.by_cases (λ h, or.inl (if_pos h)) (λ h, or.inr (if_neg h)) +protected lemma ne.ite_ne_right_iff (h : a ≠ b) : ite P a b ≠ b ↔ P := ne.dite_ne_right_iff $ λ _, h + +variables (P Q) (a b) /-- A `dite` whose results do not actually depend on the condition may be reduced to an `ite`. -/ @[simp] lemma dite_eq_ite : dite P (λ h, a) (λ h, b) = ite P a b := rfl +lemma dite_eq_or_eq : (∃ h, dite P A B = A h) ∨ ∃ h, dite P A B = B h := +decidable.by_cases (λ h, or.inl ⟨h, dif_pos h⟩) (λ h, or.inr ⟨h, dif_neg h⟩) + +lemma ite_eq_or_eq : ite P a b = a ∨ ite P a b = b := +decidable.by_cases (λ h, or.inl (if_pos h)) (λ h, or.inr (if_neg h)) + /-- A function applied to a `dite` is a `dite` of that function applied to each of the branches. -/ lemma apply_dite (x : P → α) (y : ¬P → α) : f (dite P x y) = dite P (λ h, f (x h)) (λ h, f (y h)) := by by_cases h : P; simp [h]