Fundamentals
Analysis I, Section 3.1: Fundamentals (of set theory)
In this section we set up a version of Zermelo-Frankel set theory (with atoms) that tries to be as faithful as possible to the original text of Analysis I, Section 3.1. All numbering refers to the original text.
I have attempted to make the translation as faithful a paraphrasing as possible of the original text. When there is a choice between a more idiomatic Lean solution and a more faithful translation, I have generally chosen the latter. In particular, there will be places where the Lean code could be "golfed" to be more elegant and idiomatic, but I have consciously avoided doing so.
Main constructions and results of this section:
-
A type
Chapter3.SetTheory.Setof sets -
A type
Chapter3.SetTheory.Objectof objects -
An axiom that every set is (or can be coerced into) an object
-
The empty set
∅, singletons{y}, and pairs{y,z}(and more general finite tuples), with their attendant axioms -
Pairwise union
X ∪ Y, and their attendant axioms -
Coercion of a set
Ato its associated typeA.toSubtype, which is a subtype ofObject, and basic API. (This is a technical construction needed to make the Zermelo-Frankel set theory compatible with the dependent type theory of Lean.) -
The specification
A.specify Pof a setAand a predicateto the subset of elements ofAobeyingP, and the axiom of specification. TODO: somehow implement set builder elaboration for this. -
The replacement
A.replace hPof a setAvia a predicateobeying a uniqueness condition∀ x y y', P x y ∧ P x y' → y = y', and the axiom of replacement. -
A bijective correspondence between the Mathlib natural numbers
ℕand a set(the axiom of infinity). -
Axioms of regularity, power set, and union (used in later sections of this chapter, but not required here)
-
Connections with Mathlib's notion of a set
The other axioms of Zermelo-Frankel set theory are discussed in later sections.
Some technical notes:
-
Mathlib of course has its own notion of a
Set(or more precisely, a typeSet Xassociated to each typeX), which is not compatible with the notionChapter3.Setdefined here, though we will try to make the notations match as much as possible. This causes some notational conflict: for instance, one may need to explicitly specify(∅:Chapter3.Set)instead of just∅to indicate that one is using theChapter3.Setversion of the empty set, rather than the Mathlib version of the empty set, and similarly for other notation defined here. -
In Analysis I, we chose to work with an "impure" set theory, in which there could be more
Objects than justSets. In the type theory of Lean, this requires treatingChapter3.SetandChapter3.Objectas distinct types. Occasionally this means we have to use a coercion(X: Chapter3.Object)of aChapter3.SetXto make into aChapter3.Object: this is mostly needed when manipulating sets of sets. -
Strictly speaking, a set
is not a type; however, we will coerce sets to types, and specifically to a subtype ofObject. A similar coercion is in place for Mathlib's formalization of sets. -
After this chapter is concluded, the notion of a
Chapter3.SetTheory.Setwill be deprecated in favor of the standard Mathlib notion of aSet(or more precisely of the typeSet Xof a set in a given typeX). However, due to various technical incompatibilities between set theory and type theory, we will not attempt to create a full equivalence between these two notions of sets. (As such, this makes this entire chapter optional from the point of view of the rest of the book, though we retain it for pedagogical purposes.)
Tips from past users
Users of the companion who have completed the exercises in this section are welcome to send their tips for future users in this section as PRs.
-
(Add tip here)
namespace Chapter3/- The ability to work in multiple universe is not relevant immediately, but
becomes relevant when constructing models of set theory in the Chapter 3 epilogue. -/
universe u vThe axioms of Zermelo-Frankel theory with atoms.
class SetTheory where
Set : Type u -- Axiom 3.1
Object : Type v -- Axiom 3.1
set_to_object : Set ↪ Object -- Axiom 3.1
mem : Object → Set → Prop -- Axiom 3.1
extensionality X Y : (∀ x, mem x X ↔ mem x Y) → X = Y -- Axiom 3.2
emptyset: Set -- Axiom 3.3
emptyset_mem x : ¬ mem x emptyset -- Axiom 3.3
singleton : Object → Set -- Axiom 3.4
singleton_axiom x y : mem x (singleton y) ↔ x = y -- Axiom 3.4
union_pair : Set → Set → Set -- Axiom 3.5
union_pair_axiom X Y x : mem x (union_pair X Y) ↔ (mem x X ∨ mem x Y) -- Axiom 3.5
specify A (P: Subtype (mem .A) → Prop) : Set -- Axiom 3.6
specification_axiom A (P: Subtype (mem .A) → Prop) :
(∀ x, mem x (specify A P) → mem x A) ∧ ∀ x, mem x.val (specify A P) ↔ P x -- Axiom 3.6
replace A (P: Subtype (mem .A) → Object → Prop)
(hP: ∀ x y y', P x y ∧ P x y' → y = y') : Set -- Axiom 3.7
replacement_axiom A (P: Subtype (mem .A) → Object → Prop)
(hP: ∀ x y y', P x y ∧ P x y' → y = y') : ∀ y, mem y (replace A P hP) ↔ ∃ x, P x y -- Axiom 3.7
nat : Set -- Axiom 3.8
nat_equiv : ℕ ≃ Subtype (mem .nat) -- Axiom 3.8
regularity_axiom A (hA : ∃ x, mem x A) :
∃ x, mem x A ∧ ∀ S, x = set_to_object S → ¬ ∃ y, mem y A ∧ mem y S -- Axiom 3.9
pow : Set → Set → Set -- Axiom 3.11
function_to_object (X: Set) (Y: Set) :
(Subtype (mem .X) → Subtype (mem .Y)) ↪ Object -- Axiom 3.11
powerset_axiom (X: Set) (Y: Set) (F:Object) :
mem F (pow X Y) ↔ ∃ f: Subtype (mem .Y) → Subtype (mem .X),
function_to_object Y X f = F -- Axiom 3.11
union : Set → Set -- Axiom 3.12
union_axiom A x : mem x (union A) ↔ ∃ S, mem x S ∧ mem (set_to_object S) A -- Axiom 3.12-- This enables one to use `Set` and `Object` instead of `SetTheory.Set` and `SetTheory.Object`.
export SetTheory (Set Object)-- This instance implicitly imposes the axioms of Zermelo-Frankel set theory with atoms.
variable [SetTheory]Definition 3.1.1 (objects can be elements of sets)
instance SetTheory.objects_mem_sets : Membership Object Set where
mem X x := mem x X-- Now we can use the `∈` notation between our `Object` and `Set`.
example (X: Set) (x: Object) : x ∈ X ↔ SetTheory.mem x X := inst✝:SetTheoryX:Setx:Object⊢ x ∈ X ↔ SetTheory.mem x X All goals completed! 🐙Axiom 3.1 (Sets are objects)
instance SetTheory.sets_are_objects : Coe Set Object where
coe X := set_to_object X-- Now we can treat a `Set` as an `Object` when needed.
example (X: Set) : (X: Object) = SetTheory.set_to_object X := rflAxiom 3.1 (Sets are objects)
theorem SetTheory.Set.coe_eq {X Y:Set} (h: (X: Object) = (Y: Object)) : X = Y :=
set_to_object.inj' hAxiom 3.1 (Sets are objects)
@[simp]
theorem SetTheory.Set.coe_eq_iff (X Y:Set) : (X: Object) = (Y: Object) ↔ X = Y :=
⟨ coe_eq, inst✝:SetTheoryX:SetY:Set⊢ X = Y → set_to_object X = set_to_object Y inst✝:SetTheoryX:Set⊢ set_to_object X = set_to_object X; All goals completed! 🐙 ⟩
Axiom 3.2 (Equality of sets). The [ext] tag allows the ext tactic to work for sets.
@[ext]
theorem SetTheory.Set.ext {X Y:Set} (h: ∀ x, x ∈ X ↔ x ∈ Y) : X = Y := extensionality _ _ hinstance SetTheory.Set.instEmpty : EmptyCollection Set where
emptyCollection := emptyset-- Now we can use the `∅` notation to refer to `SetTheory.emptyset`.
example : ∅ = SetTheory.emptyset := rfl-- Make everything we define in `SetTheory.Set.*` accessible directly.
open SetTheory.SetAxiom 3.3 (empty set). Note: in some applications one may have to explicitly cast ∅ to Set due to Mathlib's existing set theory notation.
@[simp]
theorem SetTheory.Set.not_mem_empty : ∀ x, x ∉ (∅:Set) := emptyset_memEmpty set has no elements
theorem SetTheory.Set.eq_empty_iff_forall_notMem {X:Set} : X = ∅ ↔ (∀ x, x ∉ X) := inst✝:SetTheoryX:Set⊢ X = ∅ ↔ ∀ (x : Object), x ∉ X
All goals completed! 🐙Empty set is unique
theorem SetTheory.Set.empty_unique : ∃! (X:Set), ∀ x, x ∉ X := inst✝:SetTheory⊢ ∃! X, ∀ (x : Object), x ∉ X
All goals completed! 🐙Lemma 3.1.5 (Single choice)
lemma SetTheory.Set.nonempty_def {X:Set} (h: X ≠ ∅) : ∃ x, x ∈ X := inst✝:SetTheoryX:Seth:X ≠ ∅⊢ ∃ x, x ∈ X
-- This proof is written to follow the structure of the original text.
inst✝:SetTheoryX:Seth:X ≠ ∅this:∀ (x : Object), x ∉ X⊢ False
have claim (x:Object) : x ∈ X ↔ x ∈ (∅:Set) := inst✝:SetTheoryX:Seth:X ≠ ∅⊢ ∃ x, x ∈ X All goals completed! 🐙
inst✝:SetTheoryX:Seth:X ≠ ∅this:∀ (x : Object), x ∉ Xclaim:X = ∅⊢ False
All goals completed! 🐙theorem SetTheory.Set.nonempty_of_inhabited {X:Set} {x:Object} (h:x ∈ X) : X ≠ ∅ := inst✝:SetTheoryX:Setx:Objecth:x ∈ X⊢ X ≠ ∅
inst✝:SetTheoryX:Setx:Objecth:X = ∅⊢ x ∉ X
inst✝:SetTheoryX:Setx:Objecth:∀ (x : Object), x ∉ X⊢ x ∉ X
All goals completed! 🐙instance SetTheory.Set.instSingleton : Singleton Object Set where
singleton := singleton-- Now we can use the `{x}` notation for a single element `Set`.
example (x: Object) : {x} = SetTheory.singleton x := rflAxiom 3.3(a) (singleton). Note: in some applications one may have to explicitly cast {a} to Set due to Mathlib's existing set theory notation.
@[simp]
theorem SetTheory.Set.mem_singleton (x a:Object) : x ∈ ({a}:Set) ↔ x = a := singleton_axiom x ainstance SetTheory.Set.instUnion : Union Set where
union := union_pair-- Now we can use the `X ∪ Y` notation for a union of two `Set`s.
example (X Y: Set) : X ∪ Y = SetTheory.union_pair X Y := rflAxiom 3.4 (Pairwise union)
@[simp]
theorem SetTheory.Set.mem_union (x:Object) (X Y:Set) : x ∈ (X ∪ Y) ↔ (x ∈ X ∨ x ∈ Y) :=
union_pair_axiom X Y xinstance SetTheory.Set.instInsert : Insert Object Set where
insert x X := {x} ∪ X@[simp]
theorem SetTheory.Set.mem_insert (a b: Object) (X: Set) : a ∈ insert b X ↔ a = b ∨ a ∈ X := inst✝:SetTheorya:Objectb:ObjectX:Set⊢ a ∈ insert b X ↔ a = b ∨ a ∈ X
All goals completed! 🐙Axiom 3.3(b) (pair). Note: in some applications one may have to cast {a,b} to Set.
theorem SetTheory.Set.pair_eq (a b:Object) : ({a,b}:Set) = {a} ∪ {b} := inst✝:SetTheorya:Objectb:Object⊢ {a, b} = {a} ∪ {b} All goals completed! 🐙Axiom 3.3(b) (pair). Note: in some applications one may have to cast {a,b} to Set.
@[simp]
theorem SetTheory.Set.mem_pair (x a b:Object) : x ∈ ({a,b}:Set) ↔ (x = a ∨ x = b) := inst✝:SetTheoryx:Objecta:Objectb:Object⊢ x ∈ {a, b} ↔ x = a ∨ x = b
All goals completed! 🐙@[simp]
theorem SetTheory.Set.mem_triple (x a b c:Object) : x ∈ ({a,b,c}:Set) ↔ (x = a ∨ x = b ∨ x = c) := inst✝:SetTheoryx:Objecta:Objectb:Objectc:Object⊢ x ∈ {a, b, c} ↔ x = a ∨ x = b ∨ x = c
All goals completed! 🐙Remark 3.1.9
theorem SetTheory.Set.singleton_uniq (a:Object) : ∃! (X:Set), ∀ x, x ∈ X ↔ x = a := inst✝:SetTheorya:Object⊢ ∃! X, ∀ (x : Object), x ∈ X ↔ x = a All goals completed! 🐙Remark 3.1.9
theorem SetTheory.Set.pair_uniq (a b:Object) : ∃! (X:Set), ∀ x, x ∈ X ↔ x = a ∨ x = b := inst✝:SetTheorya:Objectb:Object⊢ ∃! X, ∀ (x : Object), x ∈ X ↔ x = a ∨ x = b All goals completed! 🐙Remark 3.1.9
theorem SetTheory.Set.pair_comm (a b:Object) : ({a,b}:Set) = {b,a} := inst✝:SetTheorya:Objectb:Object⊢ {a, b} = {b, a} All goals completed! 🐙Remark 3.1.9
@[simp]
theorem SetTheory.Set.pair_self (a:Object) : ({a,a}:Set) = {a} := inst✝:SetTheorya:Object⊢ {a, a} = {a}
All goals completed! 🐙Exercise 3.1.1
theorem SetTheory.Set.pair_eq_pair {a b c d:Object} (h: ({a,b}:Set) = {c,d}) :
a = c ∧ b = d ∨ a = d ∧ b = c := inst✝:SetTheorya:Objectb:Objectc:Objectd:Objecth:{a, b} = {c, d}⊢ a = c ∧ b = d ∨ a = d ∧ b = c
All goals completed! 🐙abbrev SetTheory.Set.empty : Set := ∅abbrev SetTheory.Set.singleton_empty : Set := {(empty: Object)}abbrev SetTheory.Set.pair_empty : Set := {(empty: Object), (singleton_empty: Object)}Exercise 3.1.2
theorem SetTheory.Set.emptyset_neq_singleton : empty ≠ singleton_empty := inst✝:SetTheory⊢ empty ≠ singleton_empty
All goals completed! 🐙Exercise 3.1.2
theorem SetTheory.Set.emptyset_neq_pair : empty ≠ pair_empty := inst✝:SetTheory⊢ empty ≠ pair_empty All goals completed! 🐙Exercise 3.1.2
theorem SetTheory.Set.singleton_empty_neq_pair : singleton_empty ≠ pair_empty := inst✝:SetTheory⊢ singleton_empty ≠ pair_empty
All goals completed! 🐙Remark 3.1.11. (These results can be proven either by a direct rewrite, or by using extensionality.)
theorem SetTheory.Set.union_congr_left (A A' B:Set) (h: A = A') : A ∪ B = A' ∪ B := inst✝:SetTheoryA:SetA':SetB:Seth:A = A'⊢ A ∪ B = A' ∪ B All goals completed! 🐙Remark 3.1.11. (These results can be proven either by a direct rewrite, or by using extensionality.)
theorem SetTheory.Set.union_congr_right (A B B':Set) (h: B = B') : A ∪ B = A ∪ B' := inst✝:SetTheoryA:SetB:SetB':Seth:B = B'⊢ A ∪ B = A ∪ B' All goals completed! 🐙Lemma 3.1.12 (Basic properties of unions) / Exercise 3.1.3
theorem SetTheory.Set.singleton_union_singleton (a b:Object) :
({a}:Set) ∪ ({b}:Set) = {a,b} := inst✝:SetTheorya:Objectb:Object⊢ {a} ∪ {b} = {a, b}
All goals completed! 🐙Lemma 3.1.12 (Basic properties of unions) / Exercise 3.1.3
theorem SetTheory.Set.union_comm (A B:Set) : A ∪ B = B ∪ A := inst✝:SetTheoryA:SetB:Set⊢ A ∪ B = B ∪ A All goals completed! 🐙Lemma 3.1.12 (Basic properties of unions) / Exercise 3.1.3
theorem SetTheory.Set.union_assoc (A B C:Set) : (A ∪ B) ∪ C = A ∪ (B ∪ C) := inst✝:SetTheoryA:SetB:SetC:Set⊢ A ∪ B ∪ C = A ∪ (B ∪ C)
-- this proof is written to follow the structure of the original text.
inst✝:SetTheoryA:SetB:SetC:Setx:Object⊢ x ∈ A ∪ B ∪ C ↔ x ∈ A ∪ (B ∪ C)
inst✝:SetTheoryA:SetB:SetC:Setx:Object⊢ x ∈ A ∪ B ∪ C → x ∈ A ∪ (B ∪ C)inst✝:SetTheoryA:SetB:SetC:Setx:Object⊢ x ∈ A ∪ (B ∪ C) → x ∈ A ∪ B ∪ C
inst✝:SetTheoryA:SetB:SetC:Setx:Object⊢ x ∈ A ∪ B ∪ C → x ∈ A ∪ (B ∪ C) inst✝:SetTheoryA:SetB:SetC:Setx:Objecthx:x ∈ A ∪ B ∪ C⊢ x ∈ A ∪ (B ∪ C); inst✝:SetTheoryA:SetB:SetC:Setx:Objecthx:x ∈ A ∪ B ∨ x ∈ C⊢ x ∈ A ∪ (B ∪ C)
inst✝:SetTheoryA:SetB:SetC:Setx:Objectcase1:x ∈ A ∪ B⊢ x ∈ A ∪ (B ∪ C)inst✝:SetTheoryA:SetB:SetC:Setx:Objectcase2:x ∈ C⊢ x ∈ A ∪ (B ∪ C)
inst✝:SetTheoryA:SetB:SetC:Setx:Objectcase1:x ∈ A ∪ B⊢ x ∈ A ∪ (B ∪ C) inst✝:SetTheoryA:SetB:SetC:Setx:Objectcase1:x ∈ A ∨ x ∈ B⊢ x ∈ A ∪ (B ∪ C)
inst✝:SetTheoryA:SetB:SetC:Setx:Objectcase1a:x ∈ A⊢ x ∈ A ∪ (B ∪ C)inst✝:SetTheoryA:SetB:SetC:Setx:Objectcase1b:x ∈ B⊢ x ∈ A ∪ (B ∪ C)
inst✝:SetTheoryA:SetB:SetC:Setx:Objectcase1a:x ∈ A⊢ x ∈ A ∪ (B ∪ C) inst✝:SetTheoryA:SetB:SetC:Setx:Objectcase1a:x ∈ A⊢ x ∈ A ∨ x ∈ B ∪ C; All goals completed! 🐙
have : x ∈ B ∪ C := inst✝:SetTheoryA:SetB:SetC:Set⊢ A ∪ B ∪ C = A ∪ (B ∪ C) inst✝:SetTheoryA:SetB:SetC:Setx:Objectcase1b:x ∈ B⊢ x ∈ B ∨ x ∈ C; All goals completed! 🐙
inst✝:SetTheoryA:SetB:SetC:Setx:Objectcase1b:x ∈ Bthis:_fvar.11059 ∈ _fvar.11031 ∪ _fvar.11032 := ?_mvar.11638⊢ x ∈ A ∨ x ∈ B ∪ C; All goals completed! 🐙
have : x ∈ B ∪ C := inst✝:SetTheoryA:SetB:SetC:Set⊢ A ∪ B ∪ C = A ∪ (B ∪ C) inst✝:SetTheoryA:SetB:SetC:Setx:Objectcase2:x ∈ C⊢ x ∈ B ∨ x ∈ C; All goals completed! 🐙
inst✝:SetTheoryA:SetB:SetC:Setx:Objectcase2:x ∈ Cthis:_fvar.11059 ∈ _fvar.11031 ∪ _fvar.11032 := ?_mvar.12309⊢ x ∈ A ∨ x ∈ B ∪ C; All goals completed! 🐙
All goals completed! 🐙Proposition 3.1.27(c)
@[simp]
theorem SetTheory.Set.union_self (A:Set) : A ∪ A = A := inst✝:SetTheoryA:Set⊢ A ∪ A = A
All goals completed! 🐙Proposition 3.1.27(a)
@[simp]
theorem SetTheory.Set.union_empty (A:Set) : A ∪ ∅ = A := inst✝:SetTheoryA:Set⊢ A ∪ ∅ = A
All goals completed! 🐙Proposition 3.1.27(a)
@[simp]
theorem SetTheory.Set.empty_union (A:Set) : ∅ ∪ A = A := inst✝:SetTheoryA:Set⊢ ∅ ∪ A = A
All goals completed! 🐙theorem SetTheory.Set.triple_eq (a b c:Object) : {a,b,c} = ({a}:Set) ∪ {b,c} := inst✝:SetTheorya:Objectb:Objectc:Object⊢ {a, b, c} = {a} ∪ {b, c}
All goals completed! 🐙Example 3.1.10
theorem SetTheory.Set.pair_union_pair (a b c:Object) :
({a,b}:Set) ∪ {b,c} = {a,b,c} := inst✝:SetTheorya:Objectb:Objectc:Object⊢ {a, b} ∪ {b, c} = {a, b, c}
inst✝:SetTheorya:Objectb:Objectc:Objectx✝:Object⊢ x✝ ∈ {a, b} ∪ {b, c} ↔ x✝ ∈ {a, b, c}; inst✝:SetTheorya:Objectb:Objectc:Objectx✝:Object⊢ (x✝ = a ∨ x✝ = b) ∨ x✝ = b ∨ x✝ = c ↔ x✝ = a ∨ x✝ = b ∨ x✝ = c; All goals completed! 🐙Definition 3.1.14.
instance SetTheory.Set.instSubset : HasSubset Set where
Subset X Y := ∀ x, x ∈ X → x ∈ Y-- Now we can use `⊆` for a subset relationship between two `Set`s.
example (X Y: Set) : X ⊆ Y ↔ ∀ x, x ∈ X → x ∈ Y := inst✝:SetTheoryX:SetY:Set⊢ X ⊆ Y ↔ ∀ x ∈ X, x ∈ Y All goals completed! 🐙
Definition 3.1.14.
Note that the strict subset operation in Mathlib is denoted rather than .
instance SetTheory.Set.instSSubset : HasSSubset Set where
SSubset X Y := X ⊆ Y ∧ X ≠ Y-- Now we can use `⊂` for a strict subset relationship between two `Set`s.
example (X Y: Set) : X ⊂ Y ↔ X ⊆ Y ∧ X ≠ Y := inst✝:SetTheoryX:SetY:Set⊢ X ⊂ Y ↔ X ⊆ Y ∧ X ≠ Y All goals completed! 🐙Definition 3.1.14.
theorem SetTheory.Set.subset_def (X Y:Set) : X ⊆ Y ↔ ∀ x, x ∈ X → x ∈ Y := inst✝:SetTheoryX:SetY:Set⊢ X ⊆ Y ↔ ∀ x ∈ X, x ∈ Y All goals completed! 🐙
Definition 3.1.14.
Note that the strict subset operation in Mathlib is denoted rather than .
theorem SetTheory.Set.ssubset_def (X Y:Set) : X ⊂ Y ↔ (X ⊆ Y ∧ X ≠ Y) := inst✝:SetTheoryX:SetY:Set⊢ X ⊂ Y ↔ X ⊆ Y ∧ X ≠ Y All goals completed! 🐙Remark 3.1.15
theorem SetTheory.Set.subset_congr_left {A A' B:Set} (hAA':A = A') (hAB: A ⊆ B) : A' ⊆ B := inst✝:SetTheoryA:SetA':SetB:SethAA':A = A'hAB:A ⊆ B⊢ A' ⊆ B All goals completed! 🐙Examples 3.1.16
@[simp, refl]
theorem SetTheory.Set.subset_self (A:Set) : A ⊆ A := inst✝:SetTheoryA:Set⊢ A ⊆ A All goals completed! 🐙Examples 3.1.16
@[simp]
theorem SetTheory.Set.empty_subset (A:Set) : ∅ ⊆ A := inst✝:SetTheoryA:Set⊢ ∅ ⊆ A All goals completed! 🐙Proposition 3.1.17 (Partial ordering by set inclusion)
theorem SetTheory.Set.subset_trans {A B C:Set} (hAB:A ⊆ B) (hBC:B ⊆ C) : A ⊆ C := inst✝:SetTheoryA:SetB:SetC:SethAB:A ⊆ BhBC:B ⊆ C⊢ A ⊆ C
-- This proof is written to follow the structure of the original text.
inst✝:SetTheoryA:SetB:SetC:SethAB:A ⊆ BhBC:B ⊆ C⊢ ∀ x ∈ A, x ∈ C
inst✝:SetTheoryA:SetB:SetC:SethAB:A ⊆ BhBC:B ⊆ Cx:Objecthx:x ∈ A⊢ x ∈ C
inst✝:SetTheoryA:SetB:SetC:SethAB:∀ x ∈ A, x ∈ BhBC:B ⊆ Cx:Objecthx:x ∈ A⊢ x ∈ C
inst✝:SetTheoryA:SetB:SetC:SethAB:∀ x ∈ A, x ∈ BhBC:B ⊆ Cx:Objecthx:x ∈ B⊢ x ∈ C
inst✝:SetTheoryA:SetB:SetC:SethAB:∀ x ∈ A, x ∈ BhBC:B ⊆ Cx:Objecthx:x ∈ C⊢ x ∈ C
All goals completed! 🐙Proposition 3.1.17 (Partial ordering by set inclusion)
theorem SetTheory.Set.subset_antisymm (A B:Set) (hAB:A ⊆ B) (hBA:B ⊆ A) : A = B := inst✝:SetTheoryA:SetB:SethAB:A ⊆ BhBA:B ⊆ A⊢ A = B
All goals completed! 🐙Proposition 3.1.17 (Partial ordering by set inclusion)
theorem SetTheory.Set.ssubset_trans (A B C:Set) (hAB:A ⊂ B) (hBC:B ⊂ C) : A ⊂ C := inst✝:SetTheoryA:SetB:SetC:SethAB:A ⊂ BhBC:B ⊂ C⊢ A ⊂ C
All goals completed! 🐙
This defines the subtype A.toSubtype for any .
Note that A.toSubtype gives you a type, similar to how Object or Set are types.
A value x' of type A.toSubtype combines some with a proof that .
To produce an element x' of this subtype, use ⟨ x, hx ⟩, where and .
The object x associated to a subtype element x' is recovered as x'.val, and
the property hx that x belongs to A is recovered as x'.property.
abbrev SetTheory.Set.toSubtype (A:Set) := Subtype (fun x ↦ x ∈ A)example (A: Set) (x: Object) (hx: x ∈ A) : A.toSubtype := ⟨x, hx⟩example (A: Set) (x': A.toSubtype) : Object := x'.valexample (A: Set) (x': A.toSubtype) : x'.val ∈ A := x'.property-- In practice, a subtype lets us carry an object with a membership proof as a single value.
-- Compare these two proofs. They are equivalent, but the latter packs `x` and `hx` into `x'`.
example (A B: Set) (x: Object) (hx: x ∈ A) : x ∈ A ∪ B := inst✝:SetTheoryA:SetB:Setx:Objecthx:x ∈ A⊢ x ∈ A ∪ B inst✝:SetTheoryA:SetB:Setx:Objecthx:x ∈ A⊢ x ∈ A ∨ x ∈ B; inst✝:SetTheoryA:SetB:Setx:Objecthx:x ∈ A⊢ x ∈ A; All goals completed! 🐙example (A B: Set) (x': A.toSubtype) : x'.val ∈ A ∪ B := inst✝:SetTheoryA:SetB:Setx':A.toSubtype⊢ ↑x' ∈ A ∪ B inst✝:SetTheoryA:SetB:Setx':A.toSubtype⊢ ↑x' ∈ A ∨ ↑x' ∈ B; inst✝:SetTheoryA:SetB:Setx':A.toSubtype⊢ ↑x' ∈ A; All goals completed! 🐙instance : CoeSort (Set) (Type v) where
coe A := A.toSubtype-- Now instead of writing `x': A.toSubtype`, we can just write `x': A`.
-- Compare these three proofs. They are equivalent, but the last one reads most concisely.
example (A B: Set) (x: Object) (hx: x ∈ A) : x ∈ A ∪ B := inst✝:SetTheoryA:SetB:Setx:Objecthx:x ∈ A⊢ x ∈ A ∪ B inst✝:SetTheoryA:SetB:Setx:Objecthx:x ∈ A⊢ x ∈ A ∨ x ∈ B; inst✝:SetTheoryA:SetB:Setx:Objecthx:x ∈ A⊢ x ∈ A; All goals completed! 🐙example (A B: Set) (x': A.toSubtype) : x'.val ∈ A ∪ B := inst✝:SetTheoryA:SetB:Setx':A.toSubtype⊢ ↑x' ∈ A ∪ B inst✝:SetTheoryA:SetB:Setx':A.toSubtype⊢ ↑x' ∈ A ∨ ↑x' ∈ B; inst✝:SetTheoryA:SetB:Setx':A.toSubtype⊢ ↑x' ∈ A; All goals completed! 🐙example (A B: Set) (x': A) : x'.val ∈ A ∪ B := inst✝:SetTheoryA:SetB:Setx':A.toSubtype⊢ ↑x' ∈ A ∪ B inst✝:SetTheoryA:SetB:Setx':A.toSubtype⊢ ↑x' ∈ A ∨ ↑x' ∈ B; inst✝:SetTheoryA:SetB:Setx':A.toSubtype⊢ ↑x' ∈ A; All goals completed! 🐙Elements of a set (implicitly coerced to a subtype) are also elements of the set (with respect to the membership operation of the set theory).
lemma SetTheory.Set.subtype_property (A:Set) (x:A) : x.val ∈ A := x.propertylemma SetTheory.Set.subtype_coe (A:Set) (x:A) : x.val = x := rfllemma SetTheory.Set.coe_inj (A:Set) (x y:A) : x.val = y.val ↔ x = y := Subtype.coe_inj
If one has a proof hx of x ∈ A, then A.subtype_mk hx will then make the element of A
(viewed as a subtype) corresponding to x.
def SetTheory.Set.subtype_mk (A:Set) {x:Object} (hx:x ∈ A) : A := ⟨ x, hx ⟩@[simp]
lemma SetTheory.Set.subtype_mk_coe {A:Set} {x:Object} (hx:x ∈ A) : A.subtype_mk hx = x := inst✝:SetTheoryA:Setx:Objecthx:x ∈ A⊢ ↑(A.subtype_mk hx) = x All goals completed! 🐙abbrev SetTheory.Set.specify (A:Set) (P: A → Prop) : Set := SetTheory.specify A PAxiom 3.6 (axiom of specification)
theorem SetTheory.Set.specification_axiom {A:Set} {P: A → Prop} {x:Object} (h: x ∈ A.specify P) :
x ∈ A :=
(SetTheory.specification_axiom A P).1 x hAxiom 3.6 (axiom of specification)
theorem SetTheory.Set.specification_axiom' {A:Set} (P: A → Prop) (x:A) :
x.val ∈ A.specify P ↔ P x :=
(SetTheory.specification_axiom A P).2 xAxiom 3.6 (axiom of specification)
@[simp]
theorem SetTheory.Set.specification_axiom'' {A:Set} (P: A → Prop) (x:Object) :
x ∈ A.specify P ↔ ∃ h:x ∈ A, P ⟨ x, h ⟩ := inst✝:SetTheoryA:SetP:A.toSubtype → Propx:Object⊢ x ∈ A.specify P ↔ ∃ (h : x ∈ A), P ⟨x, h⟩
inst✝:SetTheoryA:SetP:A.toSubtype → Propx:Object⊢ x ∈ A.specify P → ∃ (h : x ∈ A), P ⟨x, h⟩inst✝:SetTheoryA:SetP:A.toSubtype → Propx:Object⊢ (∃ (h : x ∈ A), P ⟨x, h⟩) → x ∈ A.specify P
inst✝:SetTheoryA:SetP:A.toSubtype → Propx:Object⊢ x ∈ A.specify P → ∃ (h : x ∈ A), P ⟨x, h⟩ inst✝:SetTheoryA:SetP:A.toSubtype → Propx:Objecth:x ∈ A.specify P⊢ ∃ (h : x ∈ A), P ⟨x, h⟩; inst✝:SetTheoryA:SetP:A.toSubtype → Propx:Objecth:x ∈ A.specify P⊢ P ⟨x, ⋯⟩
All goals completed! 🐙
inst✝:SetTheoryA:SetP:A.toSubtype → Propx:Objecth:x ∈ AhP:P ⟨x, h⟩⊢ x ∈ A.specify P
All goals completed! 🐙theorem SetTheory.Set.specify_subset {A:Set} (P: A → Prop) : A.specify P ⊆ A := inst✝:SetTheoryA:SetP:A.toSubtype → Prop⊢ A.specify P ⊆ A All goals completed! 🐙This exercise may require some understanding of how subtypes are implemented in Lean.
theorem SetTheory.Set.specify_congr {A A':Set} (hAA':A = A') {P: A → Prop} {P': A' → Prop}
(hPP': (x:Object) → (h:x ∈ A) → (h':x ∈ A') → P ⟨ x, h⟩ ↔ P' ⟨ x, h'⟩ ) :
A.specify P = A'.specify P' := inst✝:SetTheoryA:SetA':SethAA':A = A'P:A.toSubtype → PropP':A'.toSubtype → ProphPP':∀ (x : Object) (h : x ∈ A) (h' : x ∈ A'), P ⟨x, h⟩ ↔ P' ⟨x, h'⟩⊢ A.specify P = A'.specify P' All goals completed! 🐙instance SetTheory.Set.instIntersection : Inter Set where
inter X Y := X.specify (fun x ↦ x.val ∈ Y)-- Now we can use the `X ∩ Y` notation for an intersection of two `Set`s.
example (X Y: Set) : X ∩ Y = X.specify (fun x ↦ x.val ∈ Y) := rflDefinition 3.1.22 (Intersections)
@[simp]
theorem SetTheory.Set.mem_inter (x:Object) (X Y:Set) : x ∈ (X ∩ Y) ↔ (x ∈ X ∧ x ∈ Y) := inst✝:SetTheoryx:ObjectX:SetY:Set⊢ x ∈ X ∩ Y ↔ x ∈ X ∧ x ∈ Y
inst✝:SetTheoryx:ObjectX:SetY:Set⊢ x ∈ X ∩ Y → x ∈ X ∧ x ∈ Yinst✝:SetTheoryx:ObjectX:SetY:Set⊢ x ∈ X ∧ x ∈ Y → x ∈ X ∩ Y
inst✝:SetTheoryx:ObjectX:SetY:Set⊢ x ∈ X ∩ Y → x ∈ X ∧ x ∈ Y inst✝:SetTheoryx:ObjectX:SetY:Seth:x ∈ X ∩ Y⊢ x ∈ X ∧ x ∈ Y; inst✝:SetTheoryx:ObjectX:SetY:Seth:x ∈ X ∩ Yh':?_mvar.29648 := Chapter3.SetTheory.Set.specification_axiom _fvar.29644⊢ x ∈ X ∧ x ∈ Y; inst✝:SetTheoryx:ObjectX:SetY:Seth:x ∈ X ∩ Yh':?_mvar.29648 := Chapter3.SetTheory.Set.specification_axiom _fvar.29644⊢ x ∈ Y
All goals completed! 🐙
inst✝:SetTheoryx:ObjectX:SetY:SethX:x ∈ XhY:x ∈ Y⊢ x ∈ X ∩ Y; All goals completed! 🐙instance SetTheory.Set.instSDiff : SDiff Set where
sdiff X Y := X.specify (fun x ↦ x.val ∉ Y)-- Now we can use the `X \ Y` notation for a difference of two `Set`s.
example (X Y: Set) : X \ Y = X.specify (fun x ↦ x.val ∉ Y) := rflDefinition 3.1.26 (Difference sets)
@[simp]
theorem SetTheory.Set.mem_sdiff (x:Object) (X Y:Set) : x ∈ (X \ Y) ↔ (x ∈ X ∧ x ∉ Y) := inst✝:SetTheoryx:ObjectX:SetY:Set⊢ x ∈ X \ Y ↔ x ∈ X ∧ x ∉ Y
inst✝:SetTheoryx:ObjectX:SetY:Set⊢ x ∈ X \ Y → x ∈ X ∧ x ∉ Yinst✝:SetTheoryx:ObjectX:SetY:Set⊢ x ∈ X ∧ x ∉ Y → x ∈ X \ Y
inst✝:SetTheoryx:ObjectX:SetY:Set⊢ x ∈ X \ Y → x ∈ X ∧ x ∉ Y inst✝:SetTheoryx:ObjectX:SetY:Seth:x ∈ X \ Y⊢ x ∈ X ∧ x ∉ Y; inst✝:SetTheoryx:ObjectX:SetY:Seth:x ∈ X \ Yh':?_mvar.30370 := Chapter3.SetTheory.Set.specification_axiom _fvar.30366⊢ x ∈ X ∧ x ∉ Y; inst✝:SetTheoryx:ObjectX:SetY:Seth:x ∈ X \ Yh':?_mvar.30370 := Chapter3.SetTheory.Set.specification_axiom _fvar.30366⊢ x ∉ Y
All goals completed! 🐙
inst✝:SetTheoryx:ObjectX:SetY:SethX:x ∈ XhY:x ∉ Y⊢ x ∈ X \ Y; All goals completed! 🐙Proposition 3.1.27(d) / Exercise 3.1.6
theorem SetTheory.Set.inter_comm (A B:Set) : A ∩ B = B ∩ A := inst✝:SetTheoryA:SetB:Set⊢ A ∩ B = B ∩ A All goals completed! 🐙Proposition 3.1.27(b)
theorem SetTheory.Set.subset_union {A X: Set} (hAX: A ⊆ X) : A ∪ X = X := inst✝:SetTheoryA:SetX:SethAX:A ⊆ X⊢ A ∪ X = X All goals completed! 🐙Proposition 3.1.27(b)
theorem SetTheory.Set.union_subset {A X: Set} (hAX: A ⊆ X) : X ∪ A = X := inst✝:SetTheoryA:SetX:SethAX:A ⊆ X⊢ X ∪ A = X All goals completed! 🐙Proposition 3.1.27(c)
@[simp]
theorem SetTheory.Set.inter_self (A:Set) : A ∩ A = A := inst✝:SetTheoryA:Set⊢ A ∩ A = A
All goals completed! 🐙Proposition 3.1.27(e)
theorem SetTheory.Set.inter_assoc (A B C:Set) : (A ∩ B) ∩ C = A ∩ (B ∩ C) := inst✝:SetTheoryA:SetB:SetC:Set⊢ A ∩ B ∩ C = A ∩ (B ∩ C) All goals completed! 🐙Proposition 3.1.27(f)
theorem SetTheory.Set.inter_union_distrib_left (A B C:Set) :
A ∩ (B ∪ C) = (A ∩ B) ∪ (A ∩ C) := inst✝:SetTheoryA:SetB:SetC:Set⊢ A ∩ (B ∪ C) = A ∩ B ∪ A ∩ C
All goals completed! 🐙Proposition 3.1.27(f)
theorem SetTheory.Set.union_inter_distrib_left (A B C:Set) :
A ∪ (B ∩ C) = (A ∪ B) ∩ (A ∪ C) := inst✝:SetTheoryA:SetB:SetC:Set⊢ A ∪ B ∩ C = (A ∪ B) ∩ (A ∪ C)
All goals completed! 🐙Proposition 3.1.27(f)
theorem SetTheory.Set.union_compl {A X:Set} (hAX: A ⊆ X) : A ∪ (X \ A) = X := inst✝:SetTheoryA:SetX:SethAX:A ⊆ X⊢ A ∪ X \ A = X All goals completed! 🐙Proposition 3.1.27(f)
theorem SetTheory.Set.inter_compl {A X:Set} : A ∩ (X \ A) = ∅ := inst✝:SetTheoryA:SetX:Set⊢ A ∩ (X \ A) = ∅ All goals completed! 🐙Proposition 3.1.27(g)
theorem SetTheory.Set.compl_union {A B X:Set} : X \ (A ∪ B) = (X \ A) ∩ (X \ B) := inst✝:SetTheoryA:SetB:SetX:Set⊢ X \ (A ∪ B) = X \ A ∩ (X \ B) All goals completed! 🐙Proposition 3.1.27(g)
theorem SetTheory.Set.compl_inter {A B X:Set} : X \ (A ∩ B) = (X \ A) ∪ (X \ B) := inst✝:SetTheoryA:SetB:SetX:Set⊢ X \ (A ∩ B) = X \ A ∪ X \ B All goals completed! 🐙Not from textbook: sets form a distributive lattice.
instance SetTheory.Set.instDistribLattice : DistribLattice Set where
le := (·⊆ ·)
le_refl := subset_self
le_trans := fun _ _ _ ↦ subset_trans
le_antisymm := subset_antisymm
inf := (·∩ ·)
sup := (·∪ ·)
le_sup_left := inst✝:SetTheory⊢ ∀ (a b : Set), a ⊆ a ∪ b All goals completed! 🐙
le_sup_right := inst✝:SetTheory⊢ ∀ (a b : Set), b ⊆ a ∪ b All goals completed! 🐙
sup_le := inst✝:SetTheory⊢ ∀ (a b c : Set), a ⊆ c → b ⊆ c → a ∪ b ⊆ c All goals completed! 🐙
inf_le_left := inst✝:SetTheory⊢ ∀ (a b : Set), a ∩ b ⊆ a All goals completed! 🐙
inf_le_right := inst✝:SetTheory⊢ ∀ (a b : Set), a ∩ b ⊆ b All goals completed! 🐙
le_inf := inst✝:SetTheory⊢ ∀ (a b c : Set), a ⊆ b → a ⊆ c → a ⊆ b ∩ c All goals completed! 🐙
le_sup_inf := inst✝:SetTheory⊢ ∀ (x y z : Set), (x ⊔ y) ⊓ (x ⊔ z) ⊆ x ⊔ y ⊓ z
inst✝:SetTheoryX:SetY:SetZ:Set⊢ (X ⊔ Y) ⊓ (X ⊔ Z) ⊆ X ⊔ Y ⊓ Z; inst✝:SetTheoryX:SetY:SetZ:Set⊢ (X ∪ Y) ∩ (X ∪ Z) ⊆ X ∪ Y ∩ Z
All goals completed! 🐙Sets have a minimal element.
instance SetTheory.Set.instOrderBot : OrderBot Set where
bot := ∅
bot_le := empty_subset-- Now we've defined `A ≤ B` to mean `A ⊆ B`, and set `⊥` to `∅`.
-- This makes the `Disjoint` definition from Mathlib work with our `Set`.
example (A B: Set) : (A ≤ B) ↔ (A ⊆ B) := inst✝:SetTheoryA:SetB:Set⊢ A ≤ B ↔ A ⊆ B All goals completed! 🐙example : ⊥ = (∅: Set) := inst✝:SetTheory⊢ ⊥ = ∅ All goals completed! 🐙example (A B: Set) : Prop := Disjoint A BDefinition of disjointness (using the previous instances)
theorem SetTheory.Set.disjoint_iff (A B:Set) : Disjoint A B ↔ A ∩ B = ∅ := inst✝:SetTheoryA:SetB:Set⊢ Disjoint A B ↔ A ∩ B = ∅
All goals completed! 🐙abbrev SetTheory.Set.replace (A:Set) {P: A → Object → Prop}
(hP : ∀ x y y', P x y ∧ P x y' → y = y') : Set := SetTheory.replace A P hPAxiom 3.7 (Axiom of replacement)
@[simp]
theorem SetTheory.Set.replacement_axiom {A:Set} {P: A → Object → Prop}
(hP: ∀ x y y', P x y ∧ P x y' → y = y') (y:Object) :
y ∈ A.replace hP ↔ ∃ x, P x y := SetTheory.replacement_axiom A P hP yabbrev Nat := SetTheory.nat-- Going forward, we'll use `Nat` as a type.
-- However, notice we've set `Nat` to `SetTheory.nat` which is a `Set` and not a type.
-- The only reason we can write `x: Nat` is because we've previously defined a `CoeSort`
-- coercion that lets us write `x: A` (when `A` is a `Set`) as a shortcut for `x: A.toSubtype`.
-- This is why, whenever you see `x: Nat`, you're really looking at `x: Nat.toSubtype`.
example (x: Nat) : Nat.toSubtype := xexample (x: Nat) : Object := x.valexample (x: Nat) : (x.val ∈ Nat) := x.propertyexample (o: Object) (ho: o ∈ Nat) : Nat := ⟨o, ho⟩
-- Below are some API for handling coercions. This may not be the optimal way to set things up.
instance SetTheory.Set.instOfNat {n:ℕ} : OfNat Nat n where
ofNat := nat_equiv n-- Now we can define `Nat` with a natural literal.
example : Nat := 5example : (5 : Nat).val ∈ Nat := (5 : Nat).propertyinstance SetTheory.Set.instNatCast : NatCast Nat where
natCast n := nat_equiv n-- Now we can turn `ℕ` into `Nat`.
example (n : ℕ) : Nat := nexample (n : ℕ) : (n : Nat).val ∈ Nat := (n : Nat).propertyinstance SetTheory.Set.toNat : Coe Nat ℕ where
coe n := nat_equiv.symm n-- Now we can turn `Nat` into `ℕ`.
example (n : Nat) : ℕ := ninstance SetTheory.Object.instNatCast : NatCast Object where
natCast n := (n:Nat).val-- Now we can turn `ℕ` into an `Object`.
example (n: ℕ) : Object := nexample (n: ℕ) : Set := {(n: Object)}instance SetTheory.Object.instOfNat {n:ℕ} : OfNat Object n where
ofNat := ((n:Nat):Object)-- Now we can define `Object` with a natural literal.
example : Object := 1example : Set := {1, 2, 3}@[simp]
lemma SetTheory.Object.ofnat_eq {n:ℕ} : ((n:Nat):Object) = (n:Object) := rfllemma SetTheory.Object.ofnat_eq' {n:ℕ} : (ofNat(n):Object) = (n:Object) := rfl@[simp]
lemma SetTheory.Object.ofnat_eq'' {n:Nat} : ((n:ℕ):Object) = (n: Object) := inst✝:SetTheoryn:Nat.toSubtype⊢ ↑(Set.nat_equiv.symm n) = ↑n
All goals completed! 🐙@[simp]
lemma SetTheory.Object.ofnat_eq''' {n:ℕ} {hn} : ((⟨(n:Object), hn⟩: nat): ℕ) = n := inst✝:SetTheoryn:ℕhn:↑n ∈ nat⊢ Set.nat_equiv.symm ⟨↑n, hn⟩ = n
All goals completed! 🐙lemma SetTheory.Set.nat_coe_eq {n:ℕ} : (n:Nat) = OfNat.ofNat n := rfl@[simp]
lemma SetTheory.Set.nat_equiv_inj (n m:ℕ) : (n:Nat) = (m:Nat) ↔ n=m :=
Equiv.apply_eq_iff_eq nat_equiv@[simp]
lemma SetTheory.Set.nat_equiv_symm_inj (n m:Nat) : (n:ℕ) = (m:ℕ) ↔ n = m :=
Equiv.apply_eq_iff_eq nat_equiv.symm@[simp]
theorem SetTheory.Set.ofNat_inj (n m:ℕ) :
(ofNat(n) : Nat) = (ofNat(m) : Nat) ↔ ofNat(n) = ofNat(m) := inst✝:SetTheoryn:ℕm:ℕ⊢ OfNat.ofNat n = OfNat.ofNat m ↔ OfNat.ofNat n = OfNat.ofNat m
All goals completed! 🐙example : (5:Nat) ≠ (3:Nat) := inst✝:SetTheory⊢ 5 ≠ 3
All goals completed! 🐙@[simp]
theorem SetTheory.Set.ofNat_inj' (n m:ℕ) :
(ofNat(n) : Object) = (ofNat(m) : Object) ↔ ofNat(n) = ofNat(m) := inst✝:SetTheoryn:ℕm:ℕ⊢ OfNat.ofNat n = OfNat.ofNat m ↔ OfNat.ofNat n = OfNat.ofNat m
inst✝:SetTheoryn:ℕm:ℕ⊢ n = m ↔ OfNat.ofNat n = OfNat.ofNat m
All goals completed! 🐙example : (5:Object) ≠ (3:Object) := inst✝:SetTheory⊢ 5 ≠ 3
All goals completed! 🐙@[simp]
lemma SetTheory.Set.nat_coe_eq_iff {m n : ℕ} : (m:Object) = ofNat(n) ↔ m = n := inst✝:SetTheorym:ℕn:ℕ⊢ ↑m = OfNat.ofNat n ↔ m = n All goals completed! 🐙example (n: ℕ) : (n: Object) = 2 ↔ n = 2 := inst✝:SetTheoryn:ℕ⊢ ↑n = 2 ↔ n = 2
All goals completed! 🐙@[simp]
theorem SetTheory.Object.natCast_inj (n m:ℕ) :
(n : Object) = (m : Object) ↔ n = m := inst✝:SetTheoryn:ℕm:ℕ⊢ ↑n = ↑m ↔ n = m
All goals completed! 🐙@[simp]
lemma SetTheory.Set.nat_equiv_coe_of_coe (n:ℕ) : ((n:Nat):ℕ) = n :=
Equiv.symm_apply_apply nat_equiv n@[simp]
lemma SetTheory.Set.nat_equiv_coe_of_coe' (n:Nat) : ((n:ℕ):Nat) = n :=
Equiv.symm_apply_apply nat_equiv.symm n@[simp]
lemma SetTheory.Set.nat_equiv_coe_of_coe'' (n:ℕ) : ((ofNat(n):Nat):ℕ) = n :=
nat_equiv_coe_of_coe n@[simp]
lemma SetTheory.Set.nat_coe_eq_iff' {m: Nat} {n : ℕ} : (m:Object) = (ofNat(n):Object) ↔ (m:ℕ) = ofNat(n) := inst✝:SetTheorym:Nat.toSubtypen:ℕ⊢ ↑m = OfNat.ofNat n ↔ nat_equiv.symm m = OfNat.ofNat n
inst✝:SetTheorym:Nat.toSubtypen:ℕ⊢ ↑m = OfNat.ofNat n → nat_equiv.symm m = OfNat.ofNat ninst✝:SetTheorym:Nat.toSubtypen:ℕ⊢ nat_equiv.symm m = OfNat.ofNat n → ↑m = OfNat.ofNat n inst✝:SetTheorym:Nat.toSubtypen:ℕ⊢ ↑m = OfNat.ofNat n → nat_equiv.symm m = OfNat.ofNat ninst✝:SetTheorym:Nat.toSubtypen:ℕ⊢ nat_equiv.symm m = OfNat.ofNat n → ↑m = OfNat.ofNat n inst✝:SetTheorym:Nat.toSubtypen:ℕh:nat_equiv.symm m = OfNat.ofNat n⊢ ↑m = OfNat.ofNat n inst✝:SetTheorym:Nat.toSubtypen:ℕh:↑m = OfNat.ofNat n⊢ nat_equiv.symm m = OfNat.ofNat ninst✝:SetTheorym:Nat.toSubtypen:ℕh:nat_equiv.symm m = OfNat.ofNat n⊢ ↑m = OfNat.ofNat n inst✝:SetTheorym:Nat.toSubtypen:ℕh:nat_equiv.symm m = OfNat.ofNat n⊢ ↑↑n = OfNat.ofNat n
inst✝:SetTheorym:Nat.toSubtypen:ℕh:nat_equiv.symm m = OfNat.ofNat n⊢ ↑↑n = OfNat.ofNat n; All goals completed! 🐙Example 3.1.16 (simplified).
example : ({3, 5}:Set) ⊆ {1, 3, 5} := inst✝:SetTheory⊢ {3, 5} ⊆ {1, 3, 5}
inst✝:SetTheory⊢ ∀ (x : Object), x = 3 ∨ x = 5 → x = 1 ∨ x = 3 ∨ x = 5; All goals completed! 🐙Example 3.1.17 (simplified).
example : ({3, 5}:Set).specify (fun x ↦ x.val ≠ 3) = ({5}:Set) := inst✝:SetTheory⊢ ({3, 5}.specify fun x => ↑x ≠ 3) = {5}
inst✝:SetTheoryx✝:Object⊢ (x✝ ∈ {3, 5}.specify fun x => ↑x ≠ 3) ↔ x✝ ∈ {5}
inst✝:SetTheoryx✝:Object⊢ (∃ (_ : x✝ ∈ {3, 5}), x✝ ≠ 3) ↔ x✝ = 5
inst✝:SetTheoryx✝:Object⊢ (∃ (_ : x✝ ∈ {3, 5}), x✝ ≠ 3) → x✝ = 5inst✝:SetTheoryx✝:Object⊢ x✝ = 5 → ∃ (_ : x✝ ∈ {3, 5}), x✝ ≠ 3
inst✝:SetTheoryx✝:Object⊢ (∃ (_ : x✝ ∈ {3, 5}), x✝ ≠ 3) → x✝ = 5 inst✝:SetTheoryx✝:Objecth1:x✝ ∈ {3, 5}h2:x✝ ≠ 3⊢ x✝ = 5; inst✝:SetTheoryx✝:Objecth2:x✝ ≠ 3h1:x✝ = 3 ∨ x✝ = 5⊢ x✝ = 5; All goals completed! 🐙
inst✝:SetTheory⊢ ∃ (_ : 5 ∈ {3, 5}), 5 ≠ 3; All goals completed! 🐙Example 3.1.24
example : ({1, 2, 4}:Set) ∩ {2,3,4} = {2, 4} := inst✝:SetTheory⊢ {1, 2, 4} ∩ {2, 3, 4} = {2, 4}
inst✝:SetTheoryx:Object⊢ x ∈ {1, 2, 4} ∩ {2, 3, 4} ↔ x ∈ {2, 4}
-- Instead of unfolding repetitive branches by hand like earlier,
-- you can use the `aesop` tactic which does this automatically.
All goals completed! 🐙Example 3.1.24
example : ({1, 2}:Set) ∩ {3,4} = ∅ := inst✝:SetTheory⊢ {1, 2} ∩ {3, 4} = ∅
inst✝:SetTheory⊢ ∀ (x : Object), x ∉ {1, 2} ∩ {3, 4}
All goals completed! 🐙example : ¬ Disjoint ({1, 2, 3}:Set) {2,3,4} := inst✝:SetTheory⊢ ¬Disjoint {1, 2, 3} {2, 3, 4}
inst✝:SetTheory⊢ ¬{1, 2, 3} ∩ {2, 3, 4} = ∅
inst✝:SetTheoryh:{1, 2, 3} ∩ {2, 3, 4} = ∅⊢ False
inst✝:SetTheoryh:{1, 2, 3} ∩ {2, 3, 4} = ∅⊢ False
inst✝:SetTheoryh:∀ (x : Object), x ∉ {1, 2, 3} ∩ {2, 3, 4}⊢ False
All goals completed! 🐙example : Disjoint (∅:Set) ∅ := inst✝:SetTheory⊢ Disjoint ∅ ∅ All goals completed! 🐙Definition 3.1.26 example
example : ({1, 2, 3, 4}:Set) \ {2,4,6} = {1, 3} := inst✝:SetTheory⊢ {1, 2, 3, 4} \ {2, 4, 6} = {1, 3}
inst✝:SetTheory⊢ ∀ (x : Object), x ∈ {1, 2, 3, 4} \ {2, 4, 6} ↔ x ∈ {1, 3}; All goals completed! 🐙Example 3.1.30
example : ({3,5,9}:Set).replace (P := fun x y ↦ ∃ (n:ℕ), x.val = n ∧ y = (n+1:ℕ)) (inst✝:SetTheory⊢ ∀ (x : {3, 5, 9}.toSubtype) (y y' : Object),
(fun x y => ∃ n, ↑x = ↑n ∧ y = ↑(n + 1)) x y ∧ (fun x y => ∃ n, ↑x = ↑n ∧ y = ↑(n + 1)) x y' → y = y' All goals completed! 🐙)
= {4,6,10} := inst✝:SetTheory⊢ {3, 5, 9}.replace ⋯ = {4, 6, 10} All goals completed! 🐙Example 3.1.31
example : ({3,5,9}:Set).replace (P := fun _ y ↦ y=1) (inst✝:SetTheory⊢ ∀ (x : {3, 5, 9}.toSubtype) (y y' : Object), (fun x y => y = 1) x y ∧ (fun x y => y = 1) x y' → y = y' All goals completed! 🐙) = {1} := inst✝:SetTheory⊢ {3, 5, 9}.replace ⋯ = {1}
inst✝:SetTheoryx✝:Object⊢ x✝ ∈ {3, 5, 9}.replace ⋯ ↔ x✝ ∈ {1}; inst✝:SetTheoryx✝:Object⊢ (∃ x, x✝ = 1) ↔ x✝ ∈ {1}; All goals completed! 🐙
Exercise 3.1.5. One can use the tfae_have and tfae_finish tactics here.
theorem SetTheory.Set.subset_tfae (A B:Set) : [A ⊆ B, A ∪ B = B, A ∩ B = A].TFAE := inst✝:SetTheoryA:SetB:Set⊢ [A ⊆ B, A ∪ B = B, A ∩ B = A].TFAE All goals completed! 🐙Exercise 3.1.7
theorem SetTheory.Set.inter_subset_left (A B:Set) : A ∩ B ⊆ A := inst✝:SetTheoryA:SetB:Set⊢ A ∩ B ⊆ A
All goals completed! 🐙Exercise 3.1.7
theorem SetTheory.Set.inter_subset_right (A B:Set) : A ∩ B ⊆ B := inst✝:SetTheoryA:SetB:Set⊢ A ∩ B ⊆ B
All goals completed! 🐙Exercise 3.1.7
@[simp]
theorem SetTheory.Set.subset_inter_iff (A B C:Set) : C ⊆ A ∩ B ↔ C ⊆ A ∧ C ⊆ B := inst✝:SetTheoryA:SetB:SetC:Set⊢ C ⊆ A ∩ B ↔ C ⊆ A ∧ C ⊆ B
All goals completed! 🐙Exercise 3.1.7
theorem SetTheory.Set.subset_union_left (A B:Set) : A ⊆ A ∪ B := inst✝:SetTheoryA:SetB:Set⊢ A ⊆ A ∪ B
All goals completed! 🐙Exercise 3.1.7
theorem SetTheory.Set.subset_union_right (A B:Set) : B ⊆ A ∪ B := inst✝:SetTheoryA:SetB:Set⊢ B ⊆ A ∪ B
All goals completed! 🐙Exercise 3.1.7
@[simp]
theorem SetTheory.Set.union_subset_iff (A B C:Set) : A ∪ B ⊆ C ↔ A ⊆ C ∧ B ⊆ C := inst✝:SetTheoryA:SetB:SetC:Set⊢ A ∪ B ⊆ C ↔ A ⊆ C ∧ B ⊆ C
All goals completed! 🐙Exercise 3.1.8
@[simp]
theorem SetTheory.Set.inter_union_cancel (A B:Set) : A ∩ (A ∪ B) = A := inst✝:SetTheoryA:SetB:Set⊢ A ∩ (A ∪ B) = A All goals completed! 🐙Exercise 3.1.8
@[simp]
theorem SetTheory.Set.union_inter_cancel (A B:Set) : A ∪ (A ∩ B) = A := inst✝:SetTheoryA:SetB:Set⊢ A ∪ A ∩ B = A All goals completed! 🐙Exercise 3.1.9
theorem SetTheory.Set.partition_left {A B X:Set} (h_union: A ∪ B = X) (h_inter: A ∩ B = ∅) :
A = X \ B := inst✝:SetTheoryA:SetB:SetX:Seth_union:A ∪ B = Xh_inter:A ∩ B = ∅⊢ A = X \ B All goals completed! 🐙Exercise 3.1.9
theorem SetTheory.Set.partition_right {A B X:Set} (h_union: A ∪ B = X) (h_inter: A ∩ B = ∅) :
B = X \ A := inst✝:SetTheoryA:SetB:SetX:Seth_union:A ∪ B = Xh_inter:A ∩ B = ∅⊢ B = X \ A
All goals completed! 🐙
Exercise 3.1.10.
You may find Function.onFun_apply and the fin_cases tactic useful.
theorem SetTheory.Set.pairwise_disjoint (A B:Set) :
Pairwise (Function.onFun Disjoint ![A \ B, A ∩ B, B \ A]) := inst✝:SetTheoryA:SetB:Set⊢ Pairwise (Function.onFun Disjoint ![A \ B, A ∩ B, B \ A]) All goals completed! 🐙Exercise 3.1.10
theorem SetTheory.Set.union_eq_partition (A B:Set) : A ∪ B = (A \ B) ∪ (A ∩ B) ∪ (B \ A) := inst✝:SetTheoryA:SetB:Set⊢ A ∪ B = A \ B ∪ A ∩ B ∪ B \ A
All goals completed! 🐙
Exercise 3.1.11.
The challenge is to prove this without using Set.specify, Set.specification_axiom,
Set.specification_axiom', or anything built from them (like differences and intersections).
theorem SetTheory.Set.specification_from_replacement {A:Set} {P: A → Prop} :
∃ B, B ⊆ A ∧ ∀ x, x.val ∈ B ↔ P x := inst✝:SetTheoryA:SetP:A.toSubtype → Prop⊢ ∃ B ⊆ A, ∀ (x : A.toSubtype), ↑x ∈ B ↔ P x All goals completed! 🐙Exercise 3.1.12.
theorem SetTheory.Set.subset_union_subset {A B A' B':Set} (hA'A: A' ⊆ A) (hB'B: B' ⊆ B) :
A' ∪ B' ⊆ A ∪ B := inst✝:SetTheoryA:SetB:SetA':SetB':SethA'A:A' ⊆ AhB'B:B' ⊆ B⊢ A' ∪ B' ⊆ A ∪ B All goals completed! 🐙Exercise 3.1.12.
theorem SetTheory.Set.subset_inter_subset {A B A' B':Set} (hA'A: A' ⊆ A) (hB'B: B' ⊆ B) :
A' ∩ B' ⊆ A ∩ B := inst✝:SetTheoryA:SetB:SetA':SetB':SethA'A:A' ⊆ AhB'B:B' ⊆ B⊢ A' ∩ B' ⊆ A ∩ B All goals completed! 🐙Exercise 3.1.12.
theorem SetTheory.Set.subset_diff_subset_counter :
∃ (A B A' B':Set), (A' ⊆ A) ∧ (B' ⊆ B) ∧ ¬ (A' \ B') ⊆ (A \ B) := inst✝:SetTheory⊢ ∃ A B A' B', A' ⊆ A ∧ B' ⊆ B ∧ ¬A' \ B' ⊆ A \ B All goals completed! 🐙/-
Final part of Exercise 3.1.12: state and prove a reasonable substitute positive result for the
above theorem that involves set differences.
-/Exercise 3.1.13
theorem SetTheory.Set.singleton_iff (A:Set) (hA: A ≠ ∅) : (¬∃ B ⊂ A, B ≠ ∅) ↔ ∃ x, A = {x} := inst✝:SetTheoryA:SethA:A ≠ ∅⊢ (¬∃ B ⊂ A, B ≠ ∅) ↔ ∃ x, A = {x} All goals completed! 🐙/-
Now we introduce connections between this notion of a set, and Mathlib's notion.
The exercise below will acquiant you with the API for Mathlib's sets.
-/
instance SetTheory.Set.inst_coe_set : Coe Set (_root_.Set Object) where
coe X := { x | x ∈ X }-- Now we can convert our `Set` into a Mathlib `_root_.Set`.
-- Notice that Mathlib sets are parameterized by the element type, in our case `Object`.
example (X: Set) : _root_.Set Object := XInjectivity of the coercion. Note however that we do NOT assert that the coercion is surjective (and indeed Russell's paradox prevents this)
@[simp]
theorem SetTheory.Set.coe_inj' (X Y:Set) :
(X : _root_.Set Object) = (Y : _root_.Set Object) ↔ X = Y := inst✝:SetTheoryX:SetY:Set⊢ {x | x ∈ X} = {x | x ∈ Y} ↔ X = Y
inst✝:SetTheoryX:SetY:Set⊢ {x | x ∈ X} = {x | x ∈ Y} → X = Yinst✝:SetTheoryX:SetY:Set⊢ X = Y → {x | x ∈ X} = {x | x ∈ Y}
inst✝:SetTheoryX:SetY:Set⊢ {x | x ∈ X} = {x | x ∈ Y} → X = Y inst✝:SetTheoryX:SetY:Seth:{x | x ∈ X} = {x | x ∈ Y}⊢ X = Y; inst✝:SetTheoryX:SetY:Seth:{x | x ∈ X} = {x | x ∈ Y}⊢ ∀ (x : Object), x ∈ X ↔ x ∈ Y; inst✝:SetTheoryX:SetY:Seth:{x | x ∈ X} = {x | x ∈ Y}x:Object⊢ x ∈ X ↔ x ∈ Y
inst✝:SetTheoryX:SetY:Setx:Objecth:?_mvar.127178 := id (congrArg (fun x => _fvar.127174 ∈ x) _fvar.127156)⊢ x ∈ X ↔ x ∈ Y; All goals completed! 🐙
inst✝:SetTheoryX:Set⊢ {x | x ∈ X} = {x | x ∈ X}; All goals completed! 🐙Compatibility of the membership operation ∈
theorem SetTheory.Set.mem_coe (X:Set) (x:Object) : x ∈ (X : _root_.Set Object) ↔ x ∈ X := inst✝:SetTheoryX:Setx:Object⊢ x ∈ {x | x ∈ X} ↔ x ∈ X
All goals completed! 🐙Compatibility of the emptyset
theorem SetTheory.Set.coe_empty : ((∅:Set) : _root_.Set Object) = ∅ := inst✝:SetTheory⊢ {x | x ∈ ∅} = ∅ All goals completed! 🐙Compatibility of subset
theorem SetTheory.Set.coe_subset (X Y:Set) :
(X : _root_.Set Object) ⊆ (Y : _root_.Set Object) ↔ X ⊆ Y := inst✝:SetTheoryX:SetY:Set⊢ {x | x ∈ X} ⊆ {x | x ∈ Y} ↔ X ⊆ Y All goals completed! 🐙theorem SetTheory.Set.coe_ssubset (X Y:Set) :
(X : _root_.Set Object) ⊂ (Y : _root_.Set Object) ↔ X ⊂ Y := inst✝:SetTheoryX:SetY:Set⊢ {x | x ∈ X} ⊂ {x | x ∈ Y} ↔ X ⊂ Y All goals completed! 🐙Compatibility of singleton
theorem SetTheory.Set.coe_singleton (x: Object) : ({x} : _root_.Set Object) = {x} := inst✝:SetTheoryx:Object⊢ {x} = {x} All goals completed! 🐙Compatibility of union
theorem SetTheory.Set.coe_union (X Y: Set) :
(X ∪ Y : _root_.Set Object) = (X : _root_.Set Object) ∪ (Y : _root_.Set Object) := inst✝:SetTheoryX:SetY:Set⊢ {x | x ∈ X} ∪ {x | x ∈ Y} = {x | x ∈ X} ∪ {x | x ∈ Y} All goals completed! 🐙Compatibility of pair
theorem SetTheory.Set.coe_pair (x y: Object) : ({x, y} : _root_.Set Object) = {x, y} := inst✝:SetTheoryx:Objecty:Object⊢ {x, y} = {x, y} All goals completed! 🐙Compatibility of subtype
theorem SetTheory.Set.coe_subtype (X: Set) : (X : _root_.Set Object) = X.toSubtype := inst✝:SetTheoryX:Set⊢ ↑{x | x ∈ X} = X.toSubtype All goals completed! 🐙Compatibility of intersection
theorem SetTheory.Set.coe_intersection (X Y: Set) :
(X ∩ Y : _root_.Set Object) = (X : _root_.Set Object) ∩ (Y : _root_.Set Object) := inst✝:SetTheoryX:SetY:Set⊢ {x | x ∈ X} ∩ {x | x ∈ Y} = {x | x ∈ X} ∩ {x | x ∈ Y} All goals completed! 🐙Compatibility of set difference
theorem SetTheory.Set.coe_diff (X Y: Set) :
(X \ Y : _root_.Set Object) = (X : _root_.Set Object) \ (Y : _root_.Set Object) := inst✝:SetTheoryX:SetY:Set⊢ {x | x ∈ X} \ {x | x ∈ Y} = {x | x ∈ X} \ {x | x ∈ Y} All goals completed! 🐙Compatibility of disjointness
theorem SetTheory.Set.coe_Disjoint (X Y: Set) :
Disjoint (X : _root_.Set Object) (Y : _root_.Set Object) ↔ Disjoint X Y := inst✝:SetTheoryX:SetY:Set⊢ Disjoint {x | x ∈ X} {x | x ∈ Y} ↔ Disjoint X Y All goals completed! 🐙end Chapter3