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
setoidinstance. - 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 asPSetquotiented 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 × ythat can be considered as a ZFC functionx → y. That is, each member ofxis 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 ofxhas 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
PSetfunction.- 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
fis 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.