Module docstring
{"# ExistsUnique
This file defines the ExistsUnique predicate, notated as ∃!, and proves some of its
basic properties.
"}
{"# ExistsUnique
This file defines the ExistsUnique predicate, notated as ∃!, and proves some of its
basic properties.
"}
ExistsUnique
definition
(p : α → Prop)
/-- For `p : α → Prop`, `ExistsUnique p` means that there exists a unique `x : α` with `p x`. -/
def ExistsUnique (p : α → Prop) := ∃ x, p x ∧ ∀ y, p y → y = x
Mathlib.Notation.isExplicitBinderSingular
definition
(xs : TSyntax `` explicitBinders) : Bool
/-- Checks to see that `xs` has only one binder. -/
def isExplicitBinderSingular (xs : TSyntax ``explicitBinders) : Bool :=
match xs with
| `(explicitBinders| $_:binderIdent $[: $_]?) => true
| `(explicitBinders| ($_:binderIdent : $_)) => true
| _ => false
Mathlib.Notation.term∃!_,_
definition
: Lean.ParserDescr✝
macromacro "∃!" xs:explicitBinders ", " b:term : term => do
if !isExplicitBinderSingular xs then
Macro.throwErrorAt xs "\
The `ExistsUnique` notation should not be used with more than one binder.\n\
\n\
The reason for this is that `∃! (x : α), ∃! (y : β), p x y` has a completely different \
meaning from `∃! q : α × β, p q.1 q.2`. \
To prevent confusion, this notation requires that you be explicit \
and use one with the correct interpretation."
expandExplicitBinders ``ExistsUnique xs b
Mathlib.Notation.unexpandExistsUnique
definition
: Lean.PrettyPrinter.Unexpander
/--
Pretty-printing for `ExistsUnique`, following the same pattern as pretty printing for `Exists`.
However, it does *not* merge binders.
-/
@[app_unexpander ExistsUnique] def unexpandExistsUnique : Lean.PrettyPrinter.Unexpander
| `($(_) fun $x:ident ↦ $b) => `(∃! $x:ident, $b)
| `($(_) fun ($x:ident : $t) ↦ $b) => `(∃! $x:ident : $t, $b)
| _ => throw ()
Mathlib.Notation.term∃!__,_
definition
: Lean.ParserDescr✝
ExistsUnique.intro
theorem
{p : α → Prop} (w : α) (h₁ : p w) (h₂ : ∀ y, p y → y = w) : ∃! x, p x
theorem ExistsUnique.intro {p : α → Prop} (w : α)
(h₁ : p w) (h₂ : ∀ y, p y → y = w) : ∃! x, p x := ⟨w, h₁, h₂⟩
ExistsUnique.elim
theorem
{p : α → Prop} {b : Prop} (h₂ : ∃! x, p x) (h₁ : ∀ x, p x → (∀ y, p y → y = x) → b) : b
theorem ExistsUnique.elim {p : α → Prop} {b : Prop}
(h₂ : ∃! x, p x) (h₁ : ∀ x, p x → (∀ y, p y → y = x) → b) : b :=
Exists.elim h₂ (fun w hw ↦ h₁ w (And.left hw) (And.right hw))
existsUnique_of_exists_of_unique
theorem
{p : α → Prop} (hex : ∃ x, p x) (hunique : ∀ y₁ y₂, p y₁ → p y₂ → y₁ = y₂) : ∃! x, p x
theorem existsUnique_of_exists_of_unique {p : α → Prop}
(hex : ∃ x, p x) (hunique : ∀ y₁ y₂, p y₁ → p y₂ → y₁ = y₂) : ∃! x, p x :=
Exists.elim hex (fun x px ↦ ExistsUnique.intro x px (fun y (h : p y) ↦ hunique y x h px))
ExistsUnique.exists
theorem
{p : α → Prop} : (∃! x, p x) → ∃ x, p x
theorem ExistsUnique.exists {p : α → Prop} : (∃! x, p x) → ∃ x, p x | ⟨x, h, _⟩ => ⟨x, h⟩
ExistsUnique.unique
theorem
{p : α → Prop} (h : ∃! x, p x) {y₁ y₂ : α} (py₁ : p y₁) (py₂ : p y₂) : y₁ = y₂
theorem ExistsUnique.unique {p : α → Prop}
(h : ∃! x, p x) {y₁ y₂ : α} (py₁ : p y₁) (py₂ : p y₂) : y₁ = y₂ :=
let ⟨_, _, hy⟩ := h; (hy _ py₁).trans (hy _ py₂).symm
existsUnique_congr
theorem
{p q : α → Prop} (h : ∀ a, p a ↔ q a) : (∃! a, p a) ↔ ∃! a, q a
theorem existsUnique_congr {p q : α → Prop} (h : ∀ a, p a ↔ q a) : (∃! a, p a) ↔ ∃! a, q a :=
exists_congr fun _ ↦ and_congr (h _) <| forall_congr' fun _ ↦ imp_congr_left (h _)
existsUnique_iff_exists
theorem
[Subsingleton α] {p : α → Prop} : (∃! x, p x) ↔ ∃ x, p x
@[simp] theorem existsUnique_iff_exists [Subsingleton α] {p : α → Prop} :
(∃! x, p x) ↔ ∃ x, p x :=
⟨fun h ↦ h.exists, Exists.imp fun x hx ↦ ⟨hx, fun y _ ↦ Subsingleton.elim y x⟩⟩
existsUnique_const
theorem
{b : Prop} (α : Sort*) [i : Nonempty α] [Subsingleton α] : (∃! _ : α, b) ↔ b
theorem existsUnique_const {b : Prop} (α : Sort*) [i : Nonempty α] [Subsingleton α] :
(∃! _ : α, b) ↔ b := by simp
existsUnique_eq
theorem
{a' : α} : ∃! a, a = a'
@[simp] theorem existsUnique_eq {a' : α} : ∃! a, a = a' := by
simp only [eq_comm, ExistsUnique, and_self, forall_eq', exists_eq']
existsUnique_eq'
theorem
{a' : α} : ∃! a, a' = a
/-- The difference with `existsUnique_eq` is that the equality is reversed. -/
@[simp] theorem existsUnique_eq' {a' : α} : ∃! a, a' = a := by
simp only [ExistsUnique, and_self, forall_eq', exists_eq']
existsUnique_prop
theorem
{p q : Prop} : (∃! _ : p, q) ↔ p ∧ q
theorem existsUnique_prop {p q : Prop} : (∃! _ : p, q) ↔ p ∧ q := by simp
existsUnique_false
theorem
: ¬∃! _ : α, False
@[simp] theorem existsUnique_false : ¬∃! _ : α, False := fun ⟨_, h, _⟩ ↦ h
existsUnique_prop_of_true
theorem
{p : Prop} {q : p → Prop} (h : p) : (∃! h' : p, q h') ↔ q h
theorem existsUnique_prop_of_true {p : Prop} {q : p → Prop} (h : p) : (∃! h' : p, q h') ↔ q h :=
@existsUnique_const (q h) p ⟨h⟩ _
ExistsUnique.elim₂
theorem
{p : α → Sort*} [∀ x, Subsingleton (p x)] {q : ∀ (x) (_ : p x), Prop} {b : Prop} (h₂ : ∃! x, ∃! h : p x, q x h)
(h₁ : ∀ (x) (h : p x), q x h → (∀ (y) (hy : p y), q y hy → y = x) → b) : b
theorem ExistsUnique.elim₂ {p : α → Sort*} [∀ x, Subsingleton (p x)]
{q : ∀ (x) (_ : p x), Prop} {b : Prop} (h₂ : ∃! x, ∃! h : p x, q x h)
(h₁ : ∀ (x) (h : p x), q x h → (∀ (y) (hy : p y), q y hy → y = x) → b) : b := by
simp only [existsUnique_iff_exists] at h₂
apply h₂.elim
exact fun x ⟨hxp, hxq⟩ H ↦ h₁ x hxp hxq fun y hyp hyq ↦ H y ⟨hyp, hyq⟩
ExistsUnique.intro₂
theorem
{p : α → Sort*} [∀ x, Subsingleton (p x)] {q : ∀ (x : α) (_ : p x), Prop} (w : α) (hp : p w) (hq : q w hp)
(H : ∀ (y) (hy : p y), q y hy → y = w) : ∃! x, ∃! hx : p x, q x hx
theorem ExistsUnique.intro₂ {p : α → Sort*} [∀ x, Subsingleton (p x)]
{q : ∀ (x : α) (_ : p x), Prop} (w : α) (hp : p w) (hq : q w hp)
(H : ∀ (y) (hy : p y), q y hy → y = w) : ∃! x, ∃! hx : p x, q x hx := by
simp only [existsUnique_iff_exists]
exact ExistsUnique.intro w ⟨hp, hq⟩ fun y ⟨hyp, hyq⟩ ↦ H y hyp hyq
ExistsUnique.exists₂
theorem
{p : α → Sort*} {q : ∀ (x : α) (_ : p x), Prop} (h : ∃! x, ∃! hx : p x, q x hx) : ∃ (x : _) (hx : p x), q x hx
theorem ExistsUnique.exists₂ {p : α → Sort*} {q : ∀ (x : α) (_ : p x), Prop}
(h : ∃! x, ∃! hx : p x, q x hx) : ∃ (x : _) (hx : p x), q x hx :=
h.exists.imp fun _ hx ↦ hx.exists
ExistsUnique.unique₂
theorem
{p : α → Sort*} [∀ x, Subsingleton (p x)] {q : ∀ (x : α) (_ : p x), Prop} (h : ∃! x, ∃! hx : p x, q x hx) {y₁ y₂ : α}
(hpy₁ : p y₁) (hqy₁ : q y₁ hpy₁) (hpy₂ : p y₂) (hqy₂ : q y₂ hpy₂) : y₁ = y₂
theorem ExistsUnique.unique₂ {p : α → Sort*} [∀ x, Subsingleton (p x)]
{q : ∀ (x : α) (_ : p x), Prop} (h : ∃! x, ∃! hx : p x, q x hx) {y₁ y₂ : α}
(hpy₁ : p y₁) (hqy₁ : q y₁ hpy₁) (hpy₂ : p y₂) (hqy₂ : q y₂ hpy₂) : y₁ = y₂ := by
simp only [existsUnique_iff_exists] at h
exact h.unique ⟨hpy₁, hqy₁⟩ ⟨hpy₂, hqy₂⟩