A model of ZFC #
In this file, we model Zermelo-Fraenkel set theory (+ Choice) using Lean's underlying type theory. We do this in four main steps:
- Define pre-sets inductively.
- Define extensional equivalence on pre-sets and give it a
setoid
instance. - Define ZFC sets by quotienting pre-sets by extensional equivalence.
- Define classes as sets of ZFC sets. Then the rest is usual set theory.
The model #
PSet
: Pre-set. A pre-set is inductively defined by its indexing type and its members, which are themselves pre-sets.ZFSet
: ZFC set. Defined asPSet
quotiented byPSet.Equiv
, the extensional equivalence.Class
: Class. Defined asSet ZFSet
.ZFSet.choice
: Axiom of choice. Proved from Lean's axiom of choice.
Other definitions #
PSet.Type
: Underlying type of a pre-set.PSet.Func
: Underlying family of pre-sets of a pre-set.PSet.Equiv
: Extensional equivalence of pre-sets. Defined inductively.PSet.omega
,ZFSet.omega
: The von Neumann ordinalω
as aPSet
, as aSet
.Classical.allZFSetDefinable
: All functions are classically definable.ZFSet.IsFunc
: Predicate that a ZFC set is a subset ofx × y
that can be considered as a ZFC functionx → y
. That is, each member ofx
is related by the ZFC set to exactly one member ofy
.ZFSet.funs
: ZFC set of ZFC functionsx → y
.ZFSet.Hereditarily p x
: Predicate that every set in the transitive closure ofx
has propertyp
.Class.iota
: Definite description operator.
Notes #
To avoid confusion between the Lean Set
and the ZFC Set
, docstrings in this file refer to them
respectively as "Set
" and "ZFC set".
The underlying pre-set family of a pre-set
Instances For
Two pre-sets are extensionally equivalent if every element of the first family is extensionally equivalent to some element of the second family and vice-versa.
Equations
Instances For
Equations
- PSet.setoid = { r := PSet.Equiv, iseqv := PSet.setoid.proof_1 }
A pre-set is a subset of another pre-set if every element of the first family is extensionally equivalent to some element of the second family.
Equations
- x.Subset y = ∀ (a : x.Type), ∃ (b : y.Type), (x.Func a).Equiv (y.Func b)
Instances For
Equations
- PSet.instHasSubset = { Subset := PSet.Subset }
Equations
- PSet.instMembership = { mem := PSet.Mem }
Equations
- PSet.instWellFoundedRelation = { rel := fun (x1 x2 : PSet.{?u.5}) => x1 ∈ x2, wf := PSet.mem_wf }
A nonempty set is one that contains some element.
Equations
- u.Nonempty = u.toSet.Nonempty
Instances For
Two pre-sets are equivalent iff they have the same members.
Equations
- PSet.instCoeSet = { coe := PSet.toSet }
Equations
- PSet.instEmptyCollection = { emptyCollection := PSet.empty }
Equations
- PSet.instInhabited = { default := ∅ }
Insert an element into a pre-set
Equations
- x.insert y = PSet.mk (Option y.Type) fun (o : Option y.Type) => Option.casesOn o x y.Func
Instances For
Equations
- PSet.instInsert = { insert := PSet.insert }
Equations
- PSet.instSingleton = { singleton := fun (s : PSet.{?u.4}) => insert s ∅ }
Equations
- x.instInhabitedTypeInsert y = inferInstanceAs (Inhabited (Option y.Type))
The n-th von Neumann ordinal
Equations
- PSet.ofNat 0 = ∅
- PSet.ofNat n.succ = insert (PSet.ofNat n) (PSet.ofNat n)
Instances For
The von Neumann ordinal ω
Equations
- PSet.omega = PSet.mk (ULift.{?u.4, 0} ℕ) fun (n : ULift.{?u.4, 0} ℕ) => PSet.ofNat n.down
Instances For
The pre-set separation operation {x ∈ a | p x}
Equations
Instances For
The pre-set powerset operator
Equations
Instances For
The pre-set union operator
Equations
Instances For
The pre-set union operator
Equations
- PSet.«term⋃₀_» = Lean.ParserDescr.node `PSet.«term⋃₀_» 110 (Lean.ParserDescr.binary `andthen (Lean.ParserDescr.symbol "⋃₀ ") (Lean.ParserDescr.cat `term 110))
Instances For
The image of a function from pre-sets to pre-sets.
Equations
- PSet.image f x = PSet.mk x.Type (f ∘ x.Func)
Instances For
Universe lift operation
Equations
- (PSet.mk α A).Lift = PSet.mk (ULift.{?u.122, ?u.123} α) fun (x : ULift.{?u.122, ?u.123} α) => match x with | { down := x } => (A x).Lift
Instances For
Embedding of one universe in another
Equations
- PSet.embed = PSet.mk (ULift.{?u.6, ?u.7 + 1} PSet.{?u.7}) fun (x : ULift.{?u.6, ?u.7 + 1} PSet.{?u.7}) => match x with | { down := x } => x.Lift
Instances For
Function equivalence is defined so that f ~ g
iff ∀ x y, x ~ y → f x ~ g y
. This extends to
equivalence of n
-ary functions.
Equations
- PSet.Arity.Equiv a b = PSet.Equiv a b
- PSet.Arity.Equiv a b = ∀ (x y : PSet.{?u.606}), x.Equiv y → PSet.Arity.Equiv (a x) (b y)
Instances For
resp n
is the collection of n-ary functions on PSet
that respect
equivalence, i.e. when the inputs are equivalent the output is as well.
Equations
- PSet.Resp n = { x : Function.OfArity PSet.{?u.11} PSet.{?u.11} n // PSet.Arity.Equiv x x }
Instances For
Equations
- PSet.Resp.inhabited = { default := ⟨Function.OfArity.const PSet.{?u.12} default n, ⋯⟩ }
The n
-ary image of a (n + 1)
-ary function respecting equivalence as a function respecting
equivalence.
Equations
- f.f x = ⟨↑f x, ⋯⟩
Instances For
Function equivalence for functions respecting equivalence. See PSet.Arity.Equiv
.
Equations
- a.Equiv b = PSet.Arity.Equiv ↑a ↑b
Instances For
The ZFC universe of sets consists of the type of pre-sets, quotiented by extensional equivalence.
Equations
Instances For
Turns a pre-set into a ZFC set.
Instances For
A set function is "definable" if it is the image of some n-ary PSet
function. This isn't exactly definability, but is useful as a sufficient
condition for functions that have a computable image.
Turns a definable function into an n-ary
PSet
function.- mk_out (xs : Fin n → PSet.{u}) : ZFSet.mk (ZFSet.Definable.out f xs) = f fun (x : Fin n) => ZFSet.mk (xs x)
A set function
f
is the image ofDefinable.out f
.
Instances
An abbrev of ZFSet.Definable
for unary functions.
Equations
- ZFSet.Definable₁ f = ZFSet.Definable 1 fun (s : Fin 1 → ZFSet.{?u.16}) => f (s 0)
Instances For
A simpler constructor for ZFSet.Definable₁
.
Equations
- ZFSet.Definable₁.mk out mk_out = { out := fun (xs : Fin 1 → PSet.{?u.32}) => out (xs 0), mk_out := ⋯ }
Instances For
Turns a unary definable function into a unary PSet
function.
Equations
- ZFSet.Definable₁.out f x = ZFSet.Definable.out (fun (s : Fin (Nat.succ 0) → ZFSet.{?u.29}) => f (s 0)) ![x]
Instances For
An abbrev of ZFSet.Definable
for binary functions.
Equations
- ZFSet.Definable₂ f = ZFSet.Definable 2 fun (s : Fin 2 → ZFSet.{?u.21}) => f (s 0) (s 1)
Instances For
A simpler constructor for ZFSet.Definable₂
.
Equations
- ZFSet.Definable₂.mk out mk_out = { out := fun (xs : Fin 2 → PSet.{?u.42}) => out (xs 0) (xs 1), mk_out := ⋯ }
Instances For
Turns a binary definable function into a binary PSet
function.
Equations
- ZFSet.Definable₂.out f x y = ZFSet.Definable.out (fun (s : Fin (Nat.succ 0).succ → ZFSet.{?u.42}) => f (s 0) (s 1)) ![x, y]
Instances For
Equations
- ZFSet.instDefinableOfDefinable₁ f n g = { out := fun (xs : Fin n → PSet.{?u.55}) => ZFSet.Definable₁.out f (ZFSet.Definable.out g xs), mk_out := ⋯ }
Equations
- ZFSet.instDefinableOfDefinable₂ f n g₁ g₂ = { out := fun (xs : Fin n → PSet.{?u.77}) => ZFSet.Definable₂.out f (ZFSet.Definable.out g₁ xs) (ZFSet.Definable.out g₂ xs), mk_out := ⋯ }
Equations
- ZFSet.instDefinable n i = { out := fun (s : Fin n → PSet.{?u.27}) => s i, mk_out := ⋯ }
Helper function for PSet.eval
.
Equations
- PSet.Resp.evalAux = ⟨fun (a : PSet.Resp 0) => ⟦↑a⟧, PSet.Resp.evalAux.proof_4⟩
- PSet.Resp.evalAux = ⟨fun (a : PSet.Resp (n + 1)) => Quotient.lift (fun (x : PSet.{?u.352}) => ↑PSet.Resp.evalAux (a.f x)) ⋯, ⋯⟩
Instances For
An equivalence-respecting function yields an n-ary ZFC set function.
Equations
- PSet.Resp.eval n = ↑PSet.Resp.evalAux
Instances For
A set function is "definable" if it is the image of some n-ary pre-set function. This isn't exactly definability, but is useful as a sufficient condition for functions that have a computable image.
- mk {n : ℕ} (f : PSet.Resp n) : PSet.Definable n (PSet.Resp.eval n f)
Instances
The evaluation of a function respecting equivalence is definable, by that same function.
Equations
Instances For
Turns a definable function into a function that respects equivalence.
Equations
- PSet.Definable.Resp (PSet.Resp.eval n f) = f
Instances For
All functions are classically definable.
Equations
- Classical.allDefinable F = PSet.Definable.EqMk ⟨Classical.choose ⋯, ⋯⟩ ⋯
- Classical.allDefinable F = PSet.Definable.EqMk ⟨fun (x : PSet.{?u.562}) => ↑(PSet.Definable.Resp (F ⟦x⟧)), ⋯⟩ ⋯
Instances For
All functions are classically definable.
Equations
- Classical.allZFSetDefinable F = { out := fun (xs : Fin n → PSet.{?u.27}) => Quotient.out (F fun (x : Fin n) => ZFSet.mk (xs x)), mk_out := ⋯ }
Instances For
The membership relation for ZFC sets is inherited from the membership relation for pre-sets.
Equations
- ZFSet.Mem = Quotient.lift₂ (fun (x1 x2 : PSet.{?u.17}) => x1 ∈ x2) ZFSet.Mem.proof_1
Instances For
Equations
- ZFSet.instMembership = { mem := fun (t s : ZFSet.{?u.5}) => s.Mem t }
A nonempty set is one that contains some element.
Equations
- u.Nonempty = u.toSet.Nonempty
Instances For
x ⊆ y
as ZFC sets means that all members of x
are members of y
.
Equations
- x.Subset y = ∀ ⦃z : ZFSet.{?u.17}⦄, z ∈ x → z ∈ y
Instances For
Equations
- ZFSet.hasSubset = { Subset := ZFSet.Subset }
Equations
- ZFSet.instEmptyCollection = { emptyCollection := ZFSet.empty }
Equations
- ZFSet.instInhabited = { default := ∅ }
Insert x y
is the set {x} ∪ y
Instances For
Equations
- ZFSet.instInsert = { insert := ZFSet.Insert }
Equations
- ZFSet.instSingleton = { singleton := fun (x : ZFSet.{?u.4}) => insert x ∅ }
{x ∈ a | p x}
is the set of elements in a
satisfying p
Equations
- ZFSet.sep p = Quotient.map (PSet.sep fun (y : PSet.{?u.16}) => p (ZFSet.mk y)) ⋯
Instances For
Equations
- ZFSet.instSep = { sep := ZFSet.sep }
The powerset operation, the collection of subsets of a ZFC set
Instances For
The union operator, the collection of elements of elements of a ZFC set
Instances For
The union operator, the collection of elements of elements of a ZFC set
Equations
- ZFSet.«term⋃₀_» = Lean.ParserDescr.node `ZFSet.«term⋃₀_» 110 (Lean.ParserDescr.binary `andthen (Lean.ParserDescr.symbol "⋃₀ ") (Lean.ParserDescr.cat `term 110))
Instances For
The intersection operator, the collection of elements in all of the elements of a ZFC set. We
define ⋂₀ ∅ = ∅
.
Instances For
The intersection operator, the collection of elements in all of the elements of a ZFC set. We
define ⋂₀ ∅ = ∅
.
Equations
- ZFSet.«term⋂₀_» = Lean.ParserDescr.node `ZFSet.«term⋂₀_» 110 (Lean.ParserDescr.binary `andthen (Lean.ParserDescr.symbol "⋂₀ ") (Lean.ParserDescr.cat `term 110))
Instances For
The binary intersection operation
Equations
- x.inter y = ZFSet.sep (fun (z : ZFSet.{?u.16}) => z ∈ y) x
Instances For
The set difference operation
Equations
- x.diff y = ZFSet.sep (fun (z : ZFSet.{?u.16}) => z ∉ y) x
Instances For
Equations
- ZFSet.instUnion = { union := ZFSet.union }
Equations
- ZFSet.instInter = { inter := ZFSet.inter }
Induction on the ∈
relation.
Equations
- ZFSet.instWellFoundedRelation = { rel := fun (x1 x2 : ZFSet.{?u.5}) => x1 ∈ x2, wf := ZFSet.mem_wf }
The image of a (definable) ZFC set function
Equations
- ZFSet.image f = Quotient.map (PSet.image (ZFSet.Definable₁.out f)) ⋯
Instances For
The range of a type-indexed family of sets.
Equations
- ZFSet.range f = ⟦PSet.mk (Shrink.{?u.26, ?u.25} α) (Quotient.out ∘ f ∘ ⇑(equivShrink α).symm)⟧
Instances For
A subset of pairs {(a, b) ∈ x × y | p a b}
Equations
- ZFSet.pairSep p x y = ZFSet.sep (fun (z : ZFSet.{?u.26}) => ∃ a ∈ x, ∃ b ∈ y, z = a.pair b ∧ p a b) (x ∪ y).powerset.powerset
Instances For
The cartesian product, {(a, b) | a ∈ x, b ∈ y}
Equations
- ZFSet.prod = ZFSet.pairSep fun (x x : ZFSet.{?u.6}) => True
Instances For
Equations
Equations
- ZFSet.instDefinable₂Pair = id inferInstance
Graph of a function: map f x
is the ZFC function which maps a ∈ x
to f a
Equations
- ZFSet.map f = ZFSet.image fun (y : ZFSet.{?u.29}) => y.pair (f y)
Instances For
Given a predicate p
on ZFC sets. Hereditarily p x
means that x
has property p
and the
members of x
are all Hereditarily p
.
Equations
- ZFSet.Hereditarily p x = (p x ∧ ∀ y ∈ x, ZFSet.Hereditarily p y)
Instances For
Alias of the forward direction of ZFSet.hereditarily_iff
.
The collection of all classes.
We define Class
as Set ZFSet
, as this allows us to get many instances automatically. However, in
practice, we treat it as (the definitionally equal) ZFSet → Prop
. This means, the preferred way to
state that x : ZFSet
belongs to A : Class
is to write A x
.
Equations
Instances For
Equations
- instClassHasSubset = Set.instHasSubset
Equations
- instClassEmptyCollection = Set.instEmptyCollection
Equations
- instInsertZFSetClass = { insert := Set.insert }
{x ∈ A | p x}
is the class of elements in A
satisfying p
Equations
- Class.sep p A = {y : ZFSet.{?u.17} | A y ∧ p y}
Instances For
Equations
- Class.instCoeZFSet = { coe := Class.ofSet }
Assert that A
is a ZFC set satisfying B
Equations
- B.ToSet A = ∃ (x : ZFSet.{?u.16}), ↑x = A ∧ B x
Instances For
Equations
- Class.instMembership = { mem := Class.Mem }
Equations
- Class.instWellFoundedRelation = { rel := fun (x1 x2 : Class.{?u.5}) => x1 ∈ x2, wf := Class.mem_wf }
Convert a conglomerate (a collection of classes) into a class
Equations
- Class.congToClass x = {y : ZFSet.{?u.2} | ↑y ∈ x}
Instances For
Convert a class into a conglomerate (a collection of classes)
Equations
- x.classToCong = {y : Class.{?u.2} | y ∈ x}
Instances For
The power class of a class is the class of all subclasses that are ZFC sets
Equations
- x.powerset = Class.congToClass (𝒫 x)
Instances For
The union of a class is the class of all members of ZFC sets in the class
Instances For
The union of a class is the class of all members of ZFC sets in the class
Equations
- Class.«term⋃₀_» = Lean.ParserDescr.node `Class.«term⋃₀_» 110 (Lean.ParserDescr.binary `andthen (Lean.ParserDescr.symbol "⋃₀ ") (Lean.ParserDescr.cat `term 110))
Instances For
The intersection of a class is the class of all members of ZFC sets in the class
Instances For
The intersection of a class is the class of all members of ZFC sets in the class
Equations
- Class.«term⋂₀_» = Lean.ParserDescr.node `Class.«term⋂₀_» 110 (Lean.ParserDescr.binary `andthen (Lean.ParserDescr.symbol "⋂₀ ") (Lean.ParserDescr.cat `term 110))
Instances For
An induction principle for sets. If every subset of a class is a member, then the class is universal.
The definite description operator, which is {x}
if {y | A y} = {x}
and ∅
otherwise.
Equations
- A.iota = ⋃₀ {x : ZFSet.{?u.12} | ∀ (y : ZFSet.{?u.12}), A y ↔ y = x}
Instances For
Function value
Equations
- F ′ A = Class.iota fun (y : ZFSet.{?u.17}) => Class.ToSet (fun (x : ZFSet.{?u.17}) => F (x.pair y)) A
Instances For
Function value
Equations
- Class.«term_′_» = Lean.ParserDescr.trailingNode `Class.«term_′_» 100 100 (Lean.ParserDescr.binary `andthen (Lean.ParserDescr.symbol " ′ ") (Lean.ParserDescr.cat `term 101))
Instances For
A choice function on the class of nonempty ZFC sets.
Equations
- x.choice = ZFSet.map (fun (y : ZFSet.{?u.14}) => Classical.epsilon fun (z : ZFSet.{?u.14}) => z ∈ y) x
Instances For
ZFSet.toSet
as an equivalence.
Equations
- One or more equations did not get rendered due to their size.