Module docstring
{"# The Following Are Equivalent
This file allows to state that all propositions in a list are equivalent. It is used by
Mathlib.Tactic.Tfae.
TFAE l means ∀ x ∈ l, ∀ y ∈ l, x ↔ y. This is equivalent to Pairwise (↔) l.
"}
{"# The Following Are Equivalent
This file allows to state that all propositions in a list are equivalent. It is used by
Mathlib.Tactic.Tfae.
TFAE l means ∀ x ∈ l, ∀ y ∈ l, x ↔ y. This is equivalent to Pairwise (↔) l.
"}
List.TFAE
definition
(l : List Prop) : Prop
/-- TFAE: The Following (propositions) Are Equivalent.
The `tfae_have` and `tfae_finish` tactics can be useful in proofs with `TFAE` goals.
-/
def TFAE (l : List Prop) : Prop :=
∀ x ∈ l, ∀ y ∈ l, x ↔ y
List.tfae_nil
theorem
: TFAE []
theorem tfae_nil : TFAE [] :=
forall_mem_nil _
List.tfae_singleton
theorem
(p) : TFAE [p]
@[simp]
theorem tfae_singleton (p) : TFAE [p] := by simp [TFAE, -eq_iff_iff]
List.tfae_cons_of_mem
theorem
{a b} {l : List Prop} (h : b ∈ l) : TFAE (a :: l) ↔ (a ↔ b) ∧ TFAE l
theorem tfae_cons_of_mem {a b} {l : List Prop} (h : b ∈ l) : TFAETFAE (a :: l) ↔ (a ↔ b) ∧ TFAE l :=
⟨fun H => ⟨H a (by simp) b (Mem.tail a h),
fun _ hp _ hq => H _ (Mem.tail a hp) _ (Mem.tail a hq)⟩,
by
rintro ⟨ab, H⟩ p (_ | ⟨_, hp⟩) q (_ | ⟨_, hq⟩)
· rfl
· exact ab.trans (H _ h _ hq)
· exact (ab.trans (H _ h _ hp)).symm
· exact H _ hp _ hq⟩
List.tfae_cons_cons
theorem
{a b} {l : List Prop} : TFAE (a :: b :: l) ↔ (a ↔ b) ∧ TFAE (b :: l)
theorem tfae_cons_cons {a b} {l : List Prop} : TFAETFAE (a :: b :: l) ↔ (a ↔ b) ∧ TFAE (b :: l) :=
tfae_cons_of_mem (Mem.head _)
List.tfae_cons_self
theorem
{a} {l : List Prop} : TFAE (a :: a :: l) ↔ TFAE (a :: l)
@[simp]
theorem tfae_cons_self {a} {l : List Prop} : TFAETFAE (a :: a :: l) ↔ TFAE (a :: l) := by
simp [tfae_cons_cons]
List.tfae_of_forall
theorem
(b : Prop) (l : List Prop) (h : ∀ a ∈ l, a ↔ b) : TFAE l
theorem tfae_of_forall (b : Prop) (l : List Prop) (h : ∀ a ∈ l, a ↔ b) : TFAE l :=
fun _a₁ h₁ _a₂ h₂ => (h _ h₁).trans (h _ h₂).symm
List.tfae_of_cycle
theorem
{a b} {l : List Prop} (h_chain : List.Chain (· → ·) a (b :: l)) (h_last : getLastD l b → a) : TFAE (a :: b :: l)
theorem tfae_of_cycle {a b} {l : List Prop} (h_chain : List.Chain (· → ·) a (b :: l))
(h_last : getLastD l b → a) : TFAE (a :: b :: l) := by
induction l generalizing a b with
| nil => simp_all [tfae_cons_cons, iff_def]
| cons c l IH =>
simp only [tfae_cons_cons, getLastD_cons, tfae_singleton, and_true, chain_cons, Chain.nil] at *
rcases h_chain with ⟨ab, ⟨bc, ch⟩⟩
have := IH ⟨bc, ch⟩ (ab ∘ h_last)
exact ⟨⟨ab, h_last ∘ (this.2 c (.head _) _ getLastD_mem_cons).1 ∘ bc⟩, this⟩
List.forall_tfae
theorem
{α : Type*} (l : List (α → Prop)) (H : ∀ a : α, (l.map (fun p ↦ p a)).TFAE) : (l.map (fun p ↦ ∀ a, p a)).TFAE
/-- If `P₁ x ↔ ... ↔ Pₙ x` for all `x`, then `(∀ x, P₁ x) ↔ ... ↔ (∀ x, Pₙ x)`.
Note: in concrete cases, Lean has trouble finding the list `[P₁, ..., Pₙ]` from the list
`[(∀ x, P₁ x), ..., (∀ x, Pₙ x)]`, but simply providing a list of underscores with the right
length makes it happier.
Example:
```lean
example (P₁ P₂ P₃ : ℕ → Prop) (H : ∀ n, [P₁ n, P₂ n, P₃ n].TFAE) :
[∀ n, P₁ n, ∀ n, P₂ n, ∀ n, P₃ n].TFAE :=
forall_tfae [_, _, _] H
```
-/
theorem forall_tfae {α : Type*} (l : List (α → Prop)) (H : ∀ a : α, (l.map (fun p ↦ p a)).TFAE) :
(l.map (fun p ↦ ∀ a, p a)).TFAE := by
simp only [TFAE, List.forall_mem_map]
intros p₁ hp₁ p₂ hp₂
exact forall_congr' fun a ↦ H a (p₁ a) (mem_map_of_mem hp₁)
(p₂ a) (mem_map_of_mem hp₂)
List.exists_tfae
theorem
{α : Type*} (l : List (α → Prop)) (H : ∀ a : α, (l.map (fun p ↦ p a)).TFAE) : (l.map (fun p ↦ ∃ a, p a)).TFAE
/-- If `P₁ x ↔ ... ↔ Pₙ x` for all `x`, then `(∃ x, P₁ x) ↔ ... ↔ (∃ x, Pₙ x)`.
Note: in concrete cases, Lean has trouble finding the list `[P₁, ..., Pₙ]` from the list
`[(∃ x, P₁ x), ..., (∃ x, Pₙ x)]`, but simply providing a list of underscores with the right
length makes it happier.
Example:
```lean
example (P₁ P₂ P₃ : ℕ → Prop) (H : ∀ n, [P₁ n, P₂ n, P₃ n].TFAE) :
[∃ n, P₁ n, ∃ n, P₂ n, ∃ n, P₃ n].TFAE :=
exists_tfae [_, _, _] H
```
-/
theorem exists_tfae {α : Type*} (l : List (α → Prop)) (H : ∀ a : α, (l.map (fun p ↦ p a)).TFAE) :
(l.map (fun p ↦ ∃ a, p a)).TFAE := by
simp only [TFAE, List.forall_mem_map]
intros p₁ hp₁ p₂ hp₂
exact exists_congr fun a ↦ H a (p₁ a) (mem_map_of_mem hp₁)
(p₂ a) (mem_map_of_mem hp₂)
List.tfae_not_iff
theorem
{l : List Prop} : TFAE (l.map Not) ↔ TFAE l
theorem tfae_not_iff {l : List Prop} : TFAETFAE (l.map Not) ↔ TFAE l := by
classical
simp only [TFAE, mem_map, forall_exists_index, and_imp, forall_apply_eq_imp_iff₂,
Decidable.not_iff_not]