Set Theory
3

14module set

Set theory is almost the simplest possible first order logical system. It contains no formal terms and only a single binary predicate symbol: \in.

4syntax in
5    sentence (500) ::= term " ∈ " term
6end
8notation not_in
9    sentence (500) ::= term " ∉ " term
10end
12@[reducible]
13definition
14    a ∉ b := ¬a ∈ b
15end

The intended reading of xyx \in y is that yy is a set of which xx is an element. In our version of set theory, all objects are sets. Despite this simplicity, we can encode essentially all of mathematics using set theory. We will find ways to encode objects not traditionally thought of as sets using sets.

We have an intuitive notion of what a set is, but of course, we will need to provide axioms to make this understanding rigorous.

Axioms 3.1

27module set.axioms

The set of axioms we will be using for our set theory is called the Zermelo-Fraenkel axioms with Choice, abbreviated ZFC. There are other systems of axioms we could use, but ZFC is a commonly accepted set.

You may be hoping that \in will come with two axioms, an introduction and an elimination rule. Sadly this is not the case.

We do get an elimination rule. It says that two sets are equal if they contain exactly the same elements. This is traditionally known as extensionality.

11axiom zfc.extensionality :
12    |- ∀a, ∀b, (∀x, x ∈ a ↔ x ∈ b) → a = b
13end

We will be presenting the axioms as unschematized statements in first-order logic without using the iota operator. This is done to make clear the distinction between the axioms for which this can be done, and those for which it can't. We will state more natural forms of these axioms as theorems later.

Intuitively, a set is supposed to be a collection of all the objects with a certain property. Therefore, we might naturally expect to have an introduction rule similar to the following:

 axiom zfc.comprehension [p(_) : sentence(term)] :
    |- ∃x, ∀y, (y ∈ x ↔ p(y))
 end

However, such an axiom would be inconsistent. In particular, we would run into Russell's paradox: the axiom allows us to construct the set X={x  x∉x}X = \{x ~|~ x \not\in x\} which consists of all sets which do not contain themselves. Then we ask if XXX \in X. If it is then it should not be and if it isn't then it should be. We have a contradiction.

This leads us to the conclusion that not all properties can define sets. The remainder of the axioms of ZFC essentially define restricted forms of our idealized comprehension axiom which are believed not to lead to a contradiction. This will leave us with various operations which we can use to define our sets. In the end, almost all the sets we care about will be definable with these operations and so we will be able to act much as if we did have unrestricted comprehension.

The empty set axiom asserts the existence of a set with no elements.

46axiom zfc.empty_set :
47    |- ∃x, ∀y, y ∉ x 
48end

For any two sets we can form the set containing exactly those two sets.

52axiom zfc.pairing :
53    |- ∀a, ∀b, ∃x, ∀y, y ∈ x ↔ y = a ∨ y = b
54end

For any set we can take the union of all elements in the set.

58axiom zfc.union :
59    |- ∀a, ∃x, ∀y, y ∈ x ↔ (∃z, y ∈ z ∧ z ∈ a)
60end

For any set we can form the set of all subsets of the set (the powerset).

64axiom zfc.powerset :
65    |- ∀a, ∃x, ∀y, y ∈ x ↔ (∀z, z ∈ y → z ∈ a)
66end

There is a set containing the empty set with the property that for any xx in the set, the set also contains x{x}x \cup \{x\}. Such a set is called an inductive set and must be infinite. Without this axiom we would have no way to prove any infinite sets exist.

73axiom zfc.infinity :
74    |- ∃x, (∃y, y ∈ x ∧ ∀z, z ∉ y) 
75         ∧ (∀y, y ∈ x → ∃z, z ∈ x ∧ (∀w, w ∈ z ↔ w ∈ y ∨ w = y))
76end

Then we get the two axiom schemas. These are statements about all sentences which can't be stated using only quantifiers. The first says that for any set we can take the subset of all elements with a particular property. This is quite similar to the rejected comprehension axiom, but this one doesn't lead to contradictions (as far as we know). This is sometimes also called separation or restricted comprehension.

85axiom zfc.specification [p(_) : sentence(term)] :
86    |- ∀a, ∃x, ∀y, y ∈ x ↔ y ∈ a ∧ p(y)
87end

This axiom asserts that the image of any set under a function (implicitly defined by pp) exists. This is surprisingly rarely required.

92axiom zfc.replacement [p(_0, _1) : sentence(term, term)] :
93    |- ∀a, (∀x, x ∈ a → ∃!y, p(x, y)) → (∃x, ∀y, y ∈ x ↔ (∃z, z ∈ a ∧ p(z, y)))
94end

The final axiom has a formal statement that is somewhat difficult to parse. But the important point is that it guarantees that we do not get an infinite chain of descending sets x0x1x2x_0 \ni x_1 \ni x_2 \ni \dots. In other words, all sets are nested at a finite depth (despite the fact that some sets contain an infinite number of elements).

102axiom zfc.regularity :
103    |- ∀a, (∃x, x ∈ a) → (∃y, y ∈ a ∧ ¬∃z, (z ∈ y ∧ z ∈ a))
104end

The final axiom is the famed Axiom of Choice. It is the C in ZFC. However it has a much longer first order statement and it is generally considered more polite to be clear when one is using it. So we will postpone adding it until it becomes necessary.

Set Operations 3.2

30module set.operations

The fundamental operation over sets is forming the set of all elements with a certain property. We discussed previously that this set does not always exist, however the iota operator allows us to define notation for it which will have the expected properties if it does exist.

6notation comprehension
7    term ::= "{" x:@binding(term) " | " sentence(x) "}"
8end
10definition
11    {x | p(x)} := ℩y, ∀x, x ∈ y ↔ p(x)
12end

We want to prove that if the set {x  p(x)}\{x ~|~ p(x)\} exists, then the notation we have given for it will refer to that set. We need to invoke the iota axiom from the previous chapter.

18theorem uncomp.def [p(_) : sentence(term)] : (∃x, ∀y, y ∈ x ↔ p(y))
19    |- ∀y, y ∈ {x | p(x)} ↔ p(y) 
20proof
21    -- this property is essentially the definition of {x | p(x)} so we just
22    -- need to extract it using iota.unique. to do this we need that
23    -- the set is unique.
24    suffices ∃!x, ∀y, y ∈ x ↔ p(y) by iota.unique [∀y, y ∈ _ ↔ p(y)];
25
26    -- we can unwrap the definition of ∃!. this step is by definition.
27    suffices (∃x, ∀y, y ∈ x ↔ p(y)) ∧ (∃*x, ∀y, y ∈ x ↔ p(y));
28
29    -- we already have the lhs as a hypothesis.
30    suffices ∃*x, ∀y, y ∈ x ↔ p(y) by and.intro [∃x, ∀y, y ∈ x ↔ p(y)] [∃*x, ∀y, y ∈ x ↔ p(y)];
31
32    -- now we unwrap the definition of ∃*.
33    suffices ∀a, ∀b, (∀y, y ∈ a ↔ p(y)) ∧ (∀y, y ∈ b ↔ p(y)) → a = b;
34
35    -- let's extract all the pieces of this definition.
36    arbitrary a;
37    arbitrary b;
38    assume (∀y, y ∈ a ↔ p(y)) ∧ (∀y, y ∈ b ↔ p(y));
39    thus ∀y, y ∈ a ↔ p(y) by and.elim_left  [∀y, y ∈ a ↔ p(y)] [∀y, y ∈ b ↔ p(y)];
40    thus ∀y, y ∈ b ↔ p(y) by and.elim_right [∀y, y ∈ a ↔ p(y)] [∀y, y ∈ b ↔ p(y)];
41
42    -- now we can prove the equality using extensionality.
43    suffices ∀x, x ∈ a ↔ x ∈ b as
44        follows ∀a, ∀b, (∀x, x ∈ a ↔ x ∈ b) → a = b by zfc.extensionality;
45        thus ∀b, (∀x, x ∈ a ↔ x ∈ b) → a = b specializing ∀a, ∀b, (∀x, x ∈ a ↔ x ∈ b) → a = b;
46        thus (∀x, x ∈ a ↔ x ∈ b) → a = b     specializing ∀b, (∀x, x ∈ a ↔ x ∈ b) → a = b;
47        thus a = b by modus_ponens [∀x, x ∈ a ↔ x ∈ b] [a = b];
48    ;
49
50    arbitrary x;
51
52    -- We can use the transitivity of ↔ to finish the proof.
53    follows x ∈ a ↔ p(x) specializing ∀y, y ∈ a ↔ p(y);
54    follows x ∈ b ↔ p(x) specializing ∀y, y ∈ b ↔ p(y);
55    thus p(x) ↔ x ∈ b  by iff.symm [x ∈ b] [p(x)];
56    thus x ∈ a ↔ x ∈ b by iff.trans [x ∈ a] [p(x)] [x ∈ b];
57qed

Sorry, was that painful to read? It was painful to write. That proof wasn't actually very complicated but it was 40 lines long anyway. This is not sustainable. Lucky we have something to help. Vampire is an automated theorem prover. It will find proofs of mathematical facts automatically. We can make a new tactic that sends the current known facts and goal to Vampire to have it generate a proof. This proof is then translated for Watson to understand. This is a very complex but also very powerful tactic which eliminates the need for tedious manipulations.

68tactic justification.logically
69    justification ::= @kw"logically"
70end

At this point we are also going to start doing more complex mathematics so it will helpful to add a few more useful tactics.

Sometimes it is helpful to annotate exactly which hypotheses go into an application of a theorem. We will add given as a justification which uses Vampire like logically but also checks that Vampire uses the given hypotheses.

79grammar_category sentence_list
81tactic sentence_list.one sentence_list ::= sentence:@fragment(sentence) end
82tactic sentence_list.many sentence_list ::= sentence:@fragment(sentence) @kw"and" rest:sentence_list end
84grammar_category givens
86tactic givens.none givens ::= end
87tactic givens.some givens ::= @kw"given" sentences:sentence_list end
89tactic justification.given
90    justification ::= @kw"given" givens:sentence_list
91end

We will also extend the by tactic to use Vampire to apply the provided theorem. Note that Vampire can't do second order reasoning so this won't work with any theorems that contain templates more complex than unparameterized terms.

97grammar_category theorem_list
99tactic theorem_list.one theorem_list ::= thm:@name end
100tactic theorem_list.many theorem_list ::= thm:@name "," rest:theorem_list end
102tactic justification.by.vampire
103    -- bind stronger than the original to override it.
104    justification (600) ::= @kw"by" thms:theorem_list givens:givens
105end
107tactic justification.by_def
108    justification ::= @kw"by_def" sentence:@fragment(sentence)
109end

If we want to have Vampire use a theorem multiple times the recall tactic will add the statement of the theorem to the current proof state, making it so Vampire can use it in all future proofs.

115tactic tactic.recall
116    tactic ::= @kw"recall" thm:@name ";" next:tactic
117end

We will also add the done tactic which is just an alias for using a justification to prove the current goal instead of a tactic. This is equivalent to thus goal <just>.

123tactic tactic.done
124    tactic ::= @kw"done" just:justification
125end

We will also add a cases tactic. This is a little more complex then just splitting an or. By default, Vampire is used to prove this disjunction of all the case conditions. Or a separate justification can be provided for this purpose. Then the provided tactics are used to prove each case implies the original goal.

133grammar_category case_list
134grammar_category case
136tactic case_list.one  case_list ::= c:case end
137tactic case_list.many case_list ::= c:case rest:case_list end
139tactic case
140    case ::= "|" sentence:@fragment(sentence) @kw"then" tactic:tactic
141end
143tactic tactic.cases
144    tactic ::= @kw"cases" just:justification ":" cases:case_list
145end

The final new tactic we will add is the let tactic. This allows making new definitions inside a proof. These definitions will be invisible to Vampire so adding them won't effect reasoning at all.

151tactic tactic.let
152    tactic ::= @kw"let" name:@name ":=" frag:@fragment(term) ";" next:tactic
153end

The Subset Relation

The other fundamental relationship between sets, besides equality, is the subset relation.

161notation subset
162    sentence (500) ::= term " ⊆ " term
163end
165definition
166    a ⊆ b := ∀x, x ∈ a → x ∈ b
167end
169theorem sub.def [a b : term] :
170    |- a ⊆ b ↔ ∀x, x ∈ a → x ∈ b
171proof
172    done by iff.refl [a ⊆ b]
173qed

The subset relation is both reflexive and transitive.

177theorem sub.refl [a : term] :
178    |- a ⊆ a
179proof
180    suffices ∀x, x ∈ a → x ∈ a by sub.def;
181    done logically
182qed
184theorem sub.trans [a b c : term] : (a ⊆ b) (b ⊆ c)
185    |- a ⊆ c
186proof
187    follows ∀x, x ∈ a → x ∈ b by sub.def given a ⊆ b;
188    follows ∀x, x ∈ b → x ∈ c by sub.def given b ⊆ c;
189    thus    ∀x, x ∈ a → x ∈ c logically;
190    done by sub.def
191qed

We also have that if two sets are subsets of each other then they are equal. In fact, this is just a restatement of the extensionality axiom.

196theorem sub.sub_eq [a b : term] : (a ⊆ b) (b ⊆ a)
197    |- a = b
198proof
199    follows ∀x, x ∈ a → x ∈ b by sub.def given a ⊆ b;
200    follows ∀x, x ∈ b → x ∈ a by sub.def given b ⊆ a;
201    thus ∀x, x ∈ a ↔ x ∈ b logically;
202    thus a = b by zfc.extensionality;
203qed

We can also have the notion of a strict subset.

207notation strict_subset
208    sentence (500) ::= term " ⊂ " term
209end
211@[reducible]
212definition
213    a ⊂ b := a ⊆ b ∧ a ≠ b
214end
216theorem ssub.def [a b : term] :
217    |- a ⊂ b ↔ (a ⊆ b ∧ a ≠ b)
218proof
219    done by iff.refl [a ⊂ b]
220qed

Bounded Quantifiers

When defining the subset relation we wrote x,xaxb\forall x, x \in a \to x \in b. The xax \in a \to component makes the quantifier only meaningful for elements of the set aa. This is a very common pattern so we will define shorthand notation for it.

229notation forall.bounded
230    sentence (000) ::= "∀" x:@binding(term) " ∈ " term ", " sentence(x)
231end
233@[reducible]
234definition
235    ∀x ∈ X, p(x) := ∀x, x ∈ X → p(x)
236end

Note that for the existential quantifier we use \land instead of \to because we are looking for an element that is both in the set and satisfies the property.

242notation exists.bounded
243    sentence (000) ::= "∃" x:@binding(term) " ∈ " term ", " sentence(x)
244end
246@[reducible]
247definition
248    ∃x ∈ X, p(x) := ∃x, x ∈ X ∧ p(x)
249end

The Empty Set

Returning to mathematics, we can use the unrestricted comprehension syntax to define our first concrete set, the empty set.

256notation empty_set
257    term ::= "∅"
258end
260definition
261:= {x | ⊥}
262end

The empty set axiom tells us that this set actually exists.

266theorem empty.def :
267    |- ∀x, x ∉ ∅
268proof
269    -- expand the definition of ∅
270    suffices ∀x, x ∉ {x | ⊥};
271    -- existence from the axiom
272    follows ∃x, ∀y,  y ∉ x        by zfc.empty_set;
273    thus    ∃x, ∀y, (y ∈ x ↔ ⊥)   logically;     
274    -- and then set comprehension is always unique
275    thus    ∀y, (y ∈ {x | ⊥} ↔ ⊥) by uncomp.def [⊥];
276    thus    ∀y,  y ∉ {x | ⊥}      logically;
277qed

We can also characterize a non-empty set as one containing an element.

281theorem nonempty.has_element [a : term] :
282    |- a ≠ ∅ ↔ ∃x, x ∈ a
283proof
284    follows ∀x, x ∉ ∅          by empty.def;
285    follows a = ∅ ↔  ∀x, x ∉ a by zfc.extensionality; 
286    thus    a ≠ ∅ ↔ ¬∀x, x ∉ a logically;
287    thus    a ≠ ∅ ↔  ∃x, x ∈ a logically;
288qed

The empty set is a subset of any set.

292theorem empty.is_sub [a : term] :
293    |- ∅ ⊆ a
294proof
295    follows ∀x, x ∉ ∅         by empty.def;
296    thus    ∀x, x ∈ ∅ → x ∈ a logically;
297qed

Every subset of the empty set is the empty set.

301theorem empty.sub_is_empty [a : term] : (a ⊆ ∅)
302    |- a = ∅
303proof
304    follows ∀x, x ∈ a → x ∈ ∅ by sub.def;
305    follows ∀x,         x ∉ ∅ by empty.def;
306    thus   ¬∃x, x ∈ a         logically;
307    thus    a = ∅             by zfc.extensionality;
308qed

The Unordered Pair

We can develop the pair set in an essentially identical way.

314notation pair
315    term ::= "{" term ", " term "}"
316end
318definition 
319    {a, b} := {x | x = a ∨ x = b}
320end

This time it is the pairing axiom that tells us that this set exists.

324theorem pair.def [a b : term] :
325    |- ∀x, x ∈ {a, b} ↔ (x = a ∨ x = b)
326proof
327    suffices ∀x, x ∈ {y | y = a ∨ y = b} ↔ (x = a ∨ x = b);
328    follows ∃c, ∀x, x ∈ c ↔ (x = a ∨ x = b)               by zfc.pairing;
329    thus    ∀x, x ∈ {y | y = a ∨ y = b} ↔ (x = a ∨ x = b) by uncomp.def [_ = a ∨ _ = b];
330qed

The unordered pair is unordered. That is, it is symmetric.

334theorem pair.symm [a b : term] :
335    |- {a, b} = {b, a}
336proof
337    thus ∀x, x ∈ {a, b} ↔ x ∈ {b, a} by pair.def;
338    thus {a, b} = {b, a}             by zfc.extensionality;
339qed

The unordered pair being a subset is equivalent to both elements of the pair being members of the set.

344theorem pair.sub [a b A : term] :
345    |- (a ∈ A ∧ b ∈ A) ↔ {a, b} ⊆ A
346proof
347    done by sub.def, pair.def
348qed

It is also non-empty.

352theorem pair.non_empty [a b : term] :
353    |- {a, b} ≠ ∅
354proof
355    follows a ∈ {a, b} by pair.def;
356    thus {a, b} ≠ ∅    by empty.def;
357qed

The Singleton Set

We can define the singleton set as the pair of the same element twice. We could define it as simply {a}={x  x=a}\{a\} = \{x ~|~ x = a\} but how would we prove this set exists? We would have to appeal to the pairing axiom anyway.

365notation singleton
366    term ::= "{" term "}"
367end
369definition
370    {a} := {a, a}
371end
373theorem singleton.def [a : term] :
374    |- ∀x, x ∈ {a} ↔ x = a
375proof
376    suffices ∀x, x ∈ {a, a} ↔ x = a;
377    thus ∀x, x ∈ {a, a} ↔ x = a by pair.def;
378qed

An element being in a set is equivalent to the singleton set being a subset.

382theorem singleton.sub [a A : term] :
383    |- a ∈ A ↔ {a} ⊆ A
384proof
385    follows a ∈ A → (∀x, x ∈ {a} → x ∈ A) by singleton.def;
386    follows (∀x, x ∈ {a} → x ∈ A) → a ∈ A by singleton.def;
387    done by sub.def
388qed

Restricted Comprehension

In contrast to unrestricted comprehensions, which are not always sets, a comprehension which is limited to be a subset of another set always exists. This is guaranteed by the specification axiom.

396notation restricted_comprehension
397    term ::= "{" x:@binding(term) " ∈ " term " | " sentence(x) "}"
398end
400definition
401    {x ∈ X | p(x)} := {x | x ∈ X ∧ p(x)}
402end

This proof follows from the specification axiom.

406theorem comp.def [p(_) : sentence(term)] [X : term] :
407    |- ∀y, y ∈ {x ∈ X | p(x)} ↔ (y ∈ X ∧ p(y))
408proof
409    suffices ∀y, y ∈ {x | x ∈ X ∧ p(x)} ↔ (y ∈ X ∧ p(y));
410    hence ∀a, ∃x, ∀y, y ∈ x ↔ (y ∈ a ∧ p(y)) by zfc.specification [p(_)];
411    follows ∃x, ∀y, y ∈ x ↔ (y ∈ X ∧ p(y))   logically;
412    thus ∀y, y ∈ {x | x ∈ X ∧ p(x)} ↔ (y ∈ X ∧ p(y)) by uncomp.def [_ ∈ X ∧ p(_)];
413qed

It easily follows from this definition that a restricted comprehension is always a subset of the original set.

418theorem comp.sub [p(_) : sentence(term)] [X : term] :
419    |- {x ∈ X | p(x)} ⊆ X
420proof
421    follows ∀y, y ∈ {x ∈ X | p(x)} ↔ (y ∈ X ∧ p(y)) by comp.def [p(_)] [X];
422    thus    ∀y, y ∈ {x ∈ X | p(x)} →  y ∈ X         logically;
423qed

Because comp.def is a second order theorem, that is it is schematized over all predicates pp, Vampire cannot reason with it automatically. This is why we had to manually provide the template instantiations when we invoked it. Restricted comprehension comes up so frequently and invoking second order theorems is so tedious that we are just going to hard code this theorem so that it is automatically given to Vampire any time a comprehension appears in the local context.

The Set Map

TODO

437notation term.with_term
438    term (1000) ::= @name "(" term ")"
439end
441notation set_map
442  term ::= "{" term(x) " | " x:@binding(term) " ∈ " term "}"
443end
445definition
446    {f(x) | x ∈ A} := {y | ∃x, x ∈ A ∧ y = f(x)}
447end

The proof follows from the replacement axiom and the definition of the set map.

451theorem set_map.def [f(_) : term(term)] [A : term] :
452    |- ∀y, y ∈ {f(x) | x ∈ A} ↔ (∃x, x ∈ A ∧ y = f(x))
453proof
454    suffices ∀y, y ∈ {z | ∃x, x ∈ A ∧ z = f(x)} ↔ (∃x, x ∈ A ∧ y = f(x));
455    suffices (∃x, ∀y, y ∈ x ↔ ∃x, x ∈ A ∧ y = f(x)) by uncomp.def [∃x, x ∈ A ∧ _ = f(x)];
456    hence ∀x ∈ A, ∃!y, y = f(x) logically;
457    follows ∀a, (∀x, x ∈ a → ∃!y, y = f(x)) → (∃x, ∀y, y ∈ x ↔ (∃z, z ∈ a ∧ y = f(z))) by zfc.replacement [_1 = f(_0)];
458    done logically
459qed

Unions

We can return to defining new sets with the union of a set.

465notation big_union
466    term (000) ::= "⋃" term
467end
469definition
470    ⋃a := {x | ∃y, x ∈ y ∧ y ∈ a}
471end

Once more the existence of this set is guaranteed by the union axiom of ZFC.

475theorem big_union.def [a : term] :
476    |- ∀x, x ∈ ⋃a ↔ (∃y, x ∈ y ∧ y ∈ a)
477proof
478    suffices ∀x, x ∈ {x | ∃y, x ∈ y ∧ y ∈ a} ↔ (∃y, x ∈ y ∧ y ∈ a);
479    follows ∃x, ∀y, y ∈ x ↔ (∃z, y ∈ z ∧ z ∈ a) by zfc.union;
480    follows ∀x, x ∈ {x | ∃y, x ∈ y ∧ y ∈ a} ↔ (∃y, x ∈ y ∧ y ∈ a) by uncomp.def [∃y, _ ∈ y ∧ y ∈ a];
481qed

Any element of a set is a subset of the union of that set.

485theorem big_union.super [a b : term] : (a ∈ b)
486    |- a ⊆ ⋃b
487proof
488    follows ∀x, (∃y, x ∈ y ∧ y ∈ b) ↔ x ∈ ⋃b by big_union.def;
489    thus    ∀x,      x ∈ a          → x ∈ ⋃b logically;
490qed

Next, we show that the union of a singleton is the element of the singleton.

494theorem big_union.singleton [a : term] :
495    |- ⋃{a} = a
496proof
497    follows ∀x, x ∈ {a} ↔ x = a by singleton.def;
498    hence ∀x, x ∈ ⋃{a} ↔ (∃y, x ∈ y ∧ y ∈ {a}) by big_union.def [{a}];
499    thus ∀x, x ∈ ⋃{a} ↔ (∃y, x ∈ y ∧ y = a) logically;
500    follows ∀x, x ∈ ⋃{a} ↔ (∃y, x ∈ a) logically;
501    follows ∀x, x ∈ ⋃{a} ↔ x ∈ a logically;
502    done by zfc.extensionality
503qed

We can define the regular union using the pair and the big union. Once again, although we could define this directly using unrestricted comprehension, it is easier to do it this way to avoid repeated proofs of existence.

508notation union
509    term (650>) ::= term " ∪ " term
510end
512definition
513    a ∪ b := ⋃{a, b}
514end

The definition of the union can be easily proved from the definitions of the big union and the pair.

519theorem union.def [a b : term] :
520    |- ∀x, x ∈ a ∪ b ↔ (x ∈ a ∨ x ∈ b)
521proof
522    suffices ∀x, x ∈ ⋃{a, b} ↔ (x ∈ a ∨ x ∈ b);
523    follows  ∀x, x ∈ ⋃{a, b} ↔ ∃y, x ∈ y ∧ y ∈ {a, b} by big_union.def;
524    follows  ∀y, y ∈  {a, b} ↔ (y = a ∨ y = b)        by pair.def;
525    done logically
526qed

The union operator is also symmetric. This follows either from the fact that the unordered pair is symmetric, or just the symmetry of or itself.

531theorem union.symm [a b : term] :
532    |- a ∪ b = b ∪ a
533proof
534    follows ∀x, x ∈ a ∪ b ↔ (x ∈ a ∨ x ∈ b) by union.def;
535    follows ∀x, x ∈ b ∪ a ↔ (x ∈ a ∨ x ∈ b) by union.def;
536    thus a ∪ b = b ∪ a                      by zfc.extensionality;
537qed

The union is also associative. This follows from the associativity of or.

541theorem union.assoc [a b c : term] :
542    |- a ∪ (b ∪ c) = (a ∪ b) ∪ c
543proof
544    follows ∀x, x ∈ a ∪ (b ∪ c) ↔ (x ∈ a ∨ (x ∈ b ∨ x ∈ c)) by union.def;
545    follows ∀x, x ∈ (a ∪ b) ∪ c ↔ ((x ∈ a ∨ x ∈ b) ∨ x ∈ c) by union.def;
546    thus a ∪ (b ∪ c) = (a ∪ b) ∪ c                          by zfc.extensionality;
547qed

Either set in the union is a subset of the union as a whole. These facts are really just simplifications of the defining fact.

552theorem union.left_sub [a b : term] :
553    |- a ⊆ a ∪ b
554proof
555    follows ∀x, (x ∈ a ∨ x ∈ b) ↔ x ∈ a ∪ b by union.def;
556    thus    ∀x,  x ∈ a          → x ∈ a ∪ b logically;
557qed
559theorem union.right_sub [a b : term] :
560    |- b ⊆ a ∪ b
561proof
562    follows ∀x, (x ∈ a ∨ x ∈ b) ↔ x ∈ a ∪ b by union.def;
563    thus    ∀x,          x ∈ b  → x ∈ a ∪ b logically;
564qed

Intersections

Instead of defining the big intersection with an unrestricted comprehension as we did for the big union, we will define it as a subset of the union. This makes it easier to prove existence.

572notation big_inter
573    term (000) ::= "⋂" term
574end
576definition
577    ⋂a := {x ∈ ⋃a | ∀y, y ∈ a → x ∈ y}
578end

This definition implies that the intersection of the empty set is the empty set. However, based on the defining property of the intersection, the intersection of the empty set should be the proper class of all sets, which isn't a set. So we restrict the definition theorem to only applying to non-empty sets.

585theorem big_inter.def [a : term] : (a ≠ ∅)
586    |- ∀x, x ∈ ⋂a ↔ (∀y, y ∈ a → x ∈ y)
587proof
588    arbitrary x;
589    suffices x ∈ {z ∈ ⋃a | ∀y, y ∈ a → z ∈ y} ↔ (∀y, y ∈ a → x ∈ y);
590
591    assume x ∈ {z ∈ ⋃a | ∀y, y ∈ a → z ∈ y} then ∀y, y ∈ a → x ∈ y logically;
592
593    assume ∀y, y ∈ a → x ∈ y then x ∈ {z ∈ ⋃a | ∀y, y ∈ a → z ∈ y} as
594        obtain y st y ∈ a  by nonempty.has_element;
595        follows     x ∈ y  logically;
596        thus        x ∈ ⋃a by big_union.def;
597        done logically
598    ;
599
600    done logically
601qed

The big intersection of a set is a subset of every element of the set.

605theorem big_inter.sub [a b : term] : (a ∈ b)
606    |- ⋂b ⊆ a
607proof
608    follows b ≠ ∅                            by nonempty.has_element;
609    follows ∀x, x ∈ ⋂b ↔ (∀y, y ∈ b → x ∈ y) by big_inter.def;
610    thus    ∀x, x ∈ ⋂b →              x ∈ a  logically;
611qed

We define the small intersection the same way we defined the small union.

615notation inter
616    term (700) ::= term " ∩ " term
617end
619definition
620    a ∩ b := ⋂{a, b}
621end

Since the pair set is always non-empty, the small intersection is always well defined.

626theorem inter.def [a b : term] :
627    |- ∀x, x ∈ a ∩ b ↔ (x ∈ a ∧ x ∈ b)
628proof
629    suffices ∀x, x ∈ ⋂{a, b} ↔ (x ∈ a ∧ x ∈ b);
630
631    -- we need that the pair set isn't empty to apply big_inter.def.
632    follows {a, b} ≠ ∅ by pair.non_empty; 
633    follows ∀x, x ∈ ⋂{a, b} ↔ (∀y, y ∈ {a, b} → x ∈ y) by big_inter.def;
634    follows ∀y, y ∈  {a, b} ↔ (y = a ∨ y = b)          by pair.def;
635    thus    ∀x, x ∈ ⋂{a, b} ↔ (x ∈ a ∧ x ∈ b)          logically;
636qed

Like the union, the intersection is symmetric and associative. The proofs are identical to those for union, just replacing every \lor with an \land.

641theorem inter.symm [a b : term] :
642    |- a ∩ b = b ∩ a
643proof
644    follows ∀x, x ∈ a ∩ b ↔ (x ∈ a ∧ x ∈ b) by inter.def;
645    follows ∀x, x ∈ b ∩ a ↔ (x ∈ a ∧ x ∈ b) by inter.def;
646    thus a ∩ b = b ∩ a                      by zfc.extensionality;
647qed
649theorem inter.assoc [a b c : term] :
650    |- a ∩ (b ∩ c) = (a ∩ b) ∩ c
651proof
652    follows ∀x, x ∈ a ∩ (b ∩ c) ↔ (x ∈ a ∧ (x ∈ b ∧ x ∈ c)) by inter.def;
653    follows ∀x, x ∈ (a ∩ b) ∩ c ↔ ((x ∈ a ∧ x ∈ b) ∧ x ∈ c) by inter.def;
654    thus a ∩ (b ∩ c) = (a ∩ b) ∩ c                          by zfc.extensionality;
655qed

The intersection of two sets is a subset of both of the original sets.

659theorem inter.sub_left [a b : term] :
660    |- a ∩ b ⊆ a
661proof
662    follows ∀x, x ∈ a ∩ b ↔ (x ∈ a ∧ x ∈ b) by inter.def;
663    thus    ∀x, x ∈ a ∩ b →  x ∈ a          logically;
664qed
666theorem inter.sub_right [a b : term] :
667    |- a ∩ b ⊆ b
668proof
669    follows ∀x, x ∈ a ∩ b ↔ (x ∈ a ∧ x ∈ b) by inter.def;
670    thus    ∀x, x ∈ a ∩ b →          x ∈ b  logically;
671qed
673theorem inter.left_sub [a b c : term] : (c ⊆ a ∩ b)
674    |- c ⊆ a
675proof
676    follows ∀x, x ∈ c → x ∈ a ∧ x ∈ b by inter.def, sub.def given c ⊆ a ∩ b;
677    follows ∀x, x ∈ c → x ∈ a         logically;
678qed
680theorem inter.right_sub [a b c : term] : (c ⊆ a ∩ b)
681    |- c ⊆ b
682proof
683    follows ∀x, x ∈ c → x ∈ a ∧ x ∈ b by inter.def, sub.def given c ⊆ a ∩ b;
684    follows ∀x, x ∈ c →         x ∈ b logically;
685qed
687theorem inter.both_sub [a b c : term] : (a ⊆ c) (b ⊆ c)
688    |- a ∩ b ⊆ c
689proof
690    suffices ∀x, x ∈ a ∧ x ∈ b → x ∈ c by inter.def, sub.def;
691    follows  ∀x, x ∈ a         → x ∈ c by sub.def given a ⊆ c;
692    follows  ∀x,         x ∈ b → x ∈ c by sub.def given b ⊆ c;
693    done logically
694qed
696theorem inter.sub_both [a b c : term] : (c ⊆ a) (c ⊆ b)
697    |- c ⊆ a ∩ b
698proof
699    suffices ∀x, x ∈ c → x ∈ a ∧ x ∈ b by inter.def, sub.def;
700    follows  ∀x, x ∈ c → x ∈ a         by sub.def given c ⊆ a;
701    follows  ∀x, x ∈ c →         x ∈ b by sub.def given c ⊆ b;
702    done logically
703qed

The Set Difference

We define the difference between two sets as the set of elements of the first set which are not in the second set.

709notation set_difference
710    term (700) ::= term " - " term
711end
713definition
714    a - b := {x ∈ a | x ∉ b}
715end

Since we used a restricted comprehension, the defining property follows directly without any more existence proofs.

720theorem set_diff.def [a b : term] :
721    |- ∀x, x ∈ a - b ↔ (x ∈ a ∧ x ∉ b)
722proof
723    suffices ∀x, x ∈ {y ∈ a | y ∉ b} ↔ (x ∈ a ∧ x ∉ b);
724    -- remember we gave Vampire the power to understand restricted comprehensions.
725    done logically 
726qed

The set difference is a subset of the first set. This follows from the fact that all restricted comprehensions are subsets.

731theorem set_diff.sub [a b : term] :
732    |- a - b ⊆ a
733proof
734    suffices {x ∈ a | x ∉ b} ⊆ a;
735    done by comp.sub [_ ∉ b] [a]
736qed

We can also characterize a non-empty difference.

740theorem set_diff.non_empty [a b : term] : (b ⊆ a)
741    |- a - b ≠ ∅ ↔ a ≠ b
742proof
743    assume a - b ≠ ∅ then a ≠ b as
744        obtain x st x ∈ a - b by nonempty.has_element;
745        thus x ∈ a ∧ x ∉ b    by set_diff.def;
746        thus a ≠ b            by zfc.extensionality;
747    ;
748
749    assume a ≠ b then a - b ≠ ∅ as
750        obtain x st (x ∈ a ∧ x ∉ b) ∨ (x ∈ b ∧ x ∉ a) by zfc.extensionality;
751        follows ¬(x ∈ b ∧ x ∉ a) by sub.def;
752        thus      x ∈ a ∧ x ∉ b  logically;
753        thus      x ∈ a - b      by set_diff.def;
754        thus      a - b ≠ ∅      by nonempty.has_element;
755    ;
756
757    done logically
758qed

The Powerset

We will define the powerset as the set of all subsets of a set.

764definition
765    𝒫(a) := {x | x ⊆ a}
766end

The existence of this set is provided by one of the ZFC axioms in the same manner as before.

771theorem powset.def [a : term] :
772    |- ∀x, x ∈ 𝒫(a) ↔ x ⊆ a
773proof
774    suffices ∀x, x ∈ {y | y ⊆ a} ↔ x ⊆ a;
775    follows ∃b, ∀x, x ∈ b ↔ (∀y, y ∈ x → y ∈ a) by zfc.powerset;
776    thus    ∃b, ∀x, x ∈ b ↔ x ⊆ a;
777    thus    ∀x, x ∈ {y | y ⊆ a} ↔ x ⊆ a by uncomp.def [_ ⊆ a];
778qed

The singletons and pairs of elements from the original set are both examples of sets in the powerset.

783theorem powset.singleton_in [a A : term] : (a ∈ A)
784    |- {a} ∈ 𝒫(A)
785proof
786    follows {a} ⊆ A by singleton.sub;
787    thus {a} ∈ 𝒫(A) by powset.def;
788qed
790theorem powset.pair_in [a b A : term] : (a ∈ A) (b ∈ A)
791    |- {a, b} ∈ 𝒫(A)
792proof
793    follows {a, b} ⊆ A by pair.sub;
794    thus {a, b} ∈ 𝒫(A) by powset.def;
795qed

If

Using restricted comprehensions we can define the if then else operator. This will be useful for casewise definitions.

802notation if
803    term ::= "if " sentence " then " term " else " term
804end
806definition
807    if p then a else b := {x ∈ a | p} ∪ {x ∈ b | ¬p}
808end
810theorem union.empty [a : term] :
811    |- a ∪ ∅ = a
812proof
813    todo
814qed
816theorem empty.union [a : term] :
817    |- ∅ ∪ a = a
818proof
819    done by union.empty, union.symm
820qed
822theorem if.true [p : sentence] [a b : term] : (p)
823    |- if p then a else b = a
824proof
825    suffices {x ∈ a | p} ∪ {x ∈ b | ¬p} = a;
826    follows {x ∈ a |  p} = a given p;
827    follows {x ∈ b | ¬p} = ∅ by empty.def given p;
828    follows a ∪ ∅ = a        by union.empty;
829    done logically
830qed
832theorem if.false [p : sentence] [a b : term] : (¬p)
833    |- if p then a else b = b
834proof
835    suffices {x ∈ a | p} ∪ {x ∈ b | ¬p} = b;
836    follows {x ∈ a |  p} = ∅ by empty.def given ¬p;
837    follows {x ∈ b | ¬p} = b given ¬p;
838    follows ∅ ∪ b = b        by empty.union;
839    done logically
840qed
842theorem if.swap [p : sentence] [a b : term] :
843    |- if p then a else b = if ¬p then b else a
844proof
845    cases:
846    | p  then
847        follows if  p then a else b = a by if.true [p] [a] [b];
848        follows ¬¬p logically; -- TODO: use vampire for this.
849        follows if ¬p then b else a = a by if.false [¬p] [b] [a];
850        done logically
851    | ¬p then
852        follows if  p then a else b = b by if.false [p] [a] [b];
853        follows if ¬p then b else a = b by if.true [¬p] [b] [a];
854        done logically
855qed

Functions 3.3

33module set.fn

The Ordered Pair

An ordered pair (a, b) is a set composed of a singleton {a} and a pair {a, b}. We can use ordered pairs to enforce certain structure on sets.

4notation ordered_pair
5    term ::= "⟨" term ", " term "⟩"
6end
8definition
9    ⟨a, b⟩ := {{a}, {a, b}}
10end

The proof follows from the pairing axiom and the definition of the ordered pair.

15theorem opair.def [a b : term] :
16    |- ∀x, x ∈ ⟨a, b⟩ ↔ (x = {a} ∨ x = {a, b})
17proof
18    suffices ∀x, x ∈ {{a}, {a, b}} ↔ (x = {a} ∨ x = {a, b});
19    follows ∃c, ∀x, x ∈ c ↔ (x = {a} ∨ x = {a, b})      by zfc.pairing;
20    thus ∀x, x ∈ {{a}, {a, b}} ↔ (x = {a} ∨ x = {a, b}) by uncomp.def [_ = {a} ∨ _ = {a, b}];
21qed
23theorem opair.unfold [a b : term] :
24    |- ⟨a, b⟩ = {{a}, {a, b}}
25proof
26    done by eq.refl [⟨a, b⟩]
27qed

Lets prove some basic properties of ordered pairs

31theorem opair.union [a b : term] :
32    |- ⋃⟨a, b⟩ = {a, b}
33proof
34    suffices ⋃{{a}, {a, b}} = {a, b};
35    thus ∀x, x ∈ {a, b} ↔ (x = a ∨ x = b) by pair.def;
36    thus ∀x, x ∈ ⋃{{a}, {a, b}} ↔ (x ∈ {a} ∨ x ∈ {a, b}) by union.def [{a}] [{a, b}];
37    hence ∀x, (x = a ∨ (x = a ∨ x = b)) ↔ (x = a ∨ x = b) logically;
38    follows ∀x, (x ∈ {a} ∨ x ∈ {a, b}) ↔ (x = a ∨ (x = a ∨ x = b)) by singleton.def, pair.def;
39    done by zfc.extensionality
40qed
42theorem opair.inter [a b : term] :
43    |- ⋂⟨a, b⟩ = {a}
44proof
45    suffices ⋂{{a}, {a, b}} = {a};
46    thus ∀x, x ∈ {a} ↔ x = a by singleton.def;
47    thus ∀x, x ∈ {a, b} ↔ (x = a ∨ x = b) by pair.def;
48    thus ∀x, x ∈ ⋂{{a}, {a, b}} ↔ (x ∈ {a} ∧ x ∈ {a, b}) by inter.def [{a}] [{a, b}];
49    hence ∀x, (x = a ∧ (x = a ∨ x = b)) ↔ x = a logically;
50    thus ∀x, x ∈ ⋂{{a}, {a, b}} ↔ x ∈ {a} by singleton.def;
51    follows ⋂{{a}, {a, b}} = {a} by zfc.extensionality;
52qed

Next, we define a function which gives us the first element of an ordered pair. We define this function somewhat broadly, but it allows for an easy proof.

56definition
57    π₁(a) := ⋃⋂a
58end

The proof follows from the definition of the ordered pair and many of the intersection properties we've shown.

62theorem opair_first.def [a b : term] :
63    |- π₁(⟨a, b⟩) = a
64proof
65    hence ⋂⟨a, b⟩ = {a} by opair.inter;
66    thus ⋃{a} = a by big_union.singleton;
67    hence ⋃⋂⟨a, b⟩ = a logically;
68qed

Naturally, we now define the second element of an ordered pair.

72definition
73    π₂(a) := ⋃{x ∈ ⋃a | ⋃a ≠ ⋂a → x ∉ ⋂a}
74end

This proof follows simply from the definition of the ordered pair and the properties of unions and intersections.

78theorem opair_second.def [a b : term] :
79    |- π₂(⟨a, b⟩) = b
80proof
81    suffices ⋃{x ∈ ⋃⟨a, b⟩ | ⋃⟨a, b⟩ ≠ ⋂⟨a, b⟩ → x ∉ ⋂⟨a, b⟩} = b;
82    follows ⋃⟨a, b⟩ = {a, b} by opair.union;
83    follows ⋂⟨a, b⟩ = {a}    by opair.inter;
84    -- We can simplify our goal with our known facts for the union and intersection
85    hence ⋃{x ∈ ⋃⟨a, b⟩ | ⋃⟨a, b⟩ ≠ ⋂⟨a, b⟩ → x ∉ ⋂⟨a, b⟩}
86        = ⋃{x ∈ {a, b} | {a, b} ≠ {a} → x ∉ {a}} logically;
87    thus ∀x, x ∈ {a, b} ↔ (x = a ∨ x = b) by pair.def;
88    follows ∀x, x ∈ {a} ↔ x = a by singleton.def;
89    follows {a, b} ≠ {a} ↔ a ≠ b logically;
90    hence ∀x, ((x = a ∨ x = b) ∧ (a ≠ b → x ∉ {a})) ↔ x = b logically;
91    thus ∀x, x ∈ {x ∈ {a, b} | {a, b} ≠ {a} → x ∉ {a}} ↔ x = b by zfc.extensionality;
92    hence ∀x, x = b ↔ x ∈ {b} by singleton.def;
93    follows ∀x, x ∈ {x ∈ {a, b} | {a, b} ≠ {a} → x ∉ {a}} ↔ x ∈ {b} logically;
94    follows {x ∈ {a, b} | {a, b} ≠ {a} → x ∉ {a}} = {b} by zfc.extensionality;
95    -- so π₂(⟨a, b⟩) = ⋃{b} = b
96    hence ⋃{x ∈ {a, b} | {a, b} ≠ {a} → x ∉ {a}} = ⋃{b} logically;
97    done by big_union.singleton
98qed

Finally, we show that two ordered pairs are equal iff their first and second elements are equal.

102theorem opair.eq [a b c d : term] :
103    |- ⟨a, b⟩ = ⟨c, d⟩ ↔ (a = c ∧ b = d)
104proof
105    hence ⟨a, b⟩ = ⟨c, d⟩ → π₁(⟨a, b⟩) = π₁(⟨c, d⟩) by zfc.extensionality;
106    follows π₁(⟨a, b⟩) = π₁(⟨c, d⟩) ↔ a = c by opair_first.def;
107    follows ⟨a, b⟩ = ⟨c, d⟩ → π₂(⟨a, b⟩) = π₂(⟨c, d⟩) by zfc.extensionality;
108    follows π₂(⟨a, b⟩) = π₂(⟨c, d⟩) ↔ b = d by opair_second.def;
109    -- suffices ⟨a, b⟩ = ⟨c, d⟩ ↔ (a = c ∧ b = d);
110    hence ⟨a, b⟩ = ⟨c, d⟩ → (a = c ∧ b = d) logically;
111    hence (a = c ∧ b = d) → ⟨a, b⟩ = ⟨c, d⟩ logically;
112    done logically
113qed

The Cartesian Product

The Cartesian product of two sets is the set of all ordered pairs formed from the elements of those sets. A double powerset is sufficient to make a superset of the Cartesian product from which we can then restrict to get the required set.

122notation product
123    term (350) ::= term " × " term
124end
126definition
127    A × B := {x ∈ 𝒫(𝒫(A ∪ B)) | ∃a ∈ A, ∃b ∈ B, x = ⟨a, b⟩}
128end

The difficult task is to prove that this gives us every possible ordered pair.

132theorem cart_prod.def [A B : term] :
133    |- ∀x, x ∈ A × B ↔ ∃a ∈ A, ∃b ∈ B, x = ⟨a, b⟩
134proof
135    arbitrary x;
136
137    -- remember the definition of A × B. (specifically have Vampire remember it)
138    follows A × B = {x ∈ 𝒫(𝒫(A ∪ B)) | ∃a ∈ A, ∃b ∈ B, x = ⟨a, b⟩}
139        by eq.refl [A × B];
140
141    -- the forward direction is pretty simple. it just comes directly from the
142    -- definition of restricted comprehension.
143    assume x ∈ A × B then ∃a ∈ A, ∃b ∈ B, x = ⟨a, b⟩ logically;
144
145    -- the other direction is harder. it follows quickly that x satisfies the
146    -- comprehension condition, but it is a little more work to show it is in
147    -- the double powerset.
148    assume ∃a ∈ A, ∃b ∈ B, x = ⟨a, b⟩ then x ∈ A × B as
149        obtain a st a ∈ A and b st b ∈ B ∧ x = ⟨a, b⟩ logically;
150        follows x = {{a}, {a, b}} by_def x = ⟨a, b⟩;
151
152        -- we already have that x is a pair so we just need to prove it is in the powerset
153        suffices x ∈ 𝒫(𝒫(A ∪ B)) ∧ (∃a ∈ A, ∃b ∈ B, x = ⟨a, b⟩) logically;
154        suffices x ∈ 𝒫(𝒫(A ∪ B)) given x = ⟨a, b⟩;
155
156        follows a ∈ A ∪ B ∧ b ∈ A ∪ B    by union.def given a ∈ A and b ∈ B;
157        thus  {a}          ∈   𝒫(A ∪ B)  by powset.singleton_in;
158        thus       {a, b}  ∈   𝒫(A ∪ B)  by powset.pair_in;
159        thus {{a}, {a, b}} ∈ 𝒫(𝒫(A ∪ B)) by powset.pair_in;
160        thus             x ∈ 𝒫(𝒫(A ∪ B)) given x = {{a}, {a, b}};
161    ;
162
163    done logically
164qed

Next, we prove a useful result relating the cartesian product of sets to their subsets.

168lemma cart_prod.sub [A B C D : term] : (A ⊆ C) (B ⊆ D)
169    |- A × B ⊆ C × D
170proof
171    suffices ∀x ∈ A × B, x ∈ C × D;
172    arbitrary x;
173    assume x ∈ A × B then x ∈ C × D as
174        obtain a st a ∈ A and b st b ∈ B ∧ x = ⟨a, b⟩ by cart_prod.def;
175        follows a ∈ C by sub.def given A ⊆ C;
176        follows b ∈ D by sub.def given B ⊆ D;
177        done by cart_prod.def
178        ;
179    done logically
180qed

We can define the set of binary relations between two sets as the powerset of the Cartesian product of those two sets. Conceptually, if RR is a relation between AA and BB then it is the set of all pairs (a,b)(a, b) where aa and bb are related by RR.

188notation term.with_term_term
189    term (1000) ::= @name "(" term ", " term ")"
190end
192definition
193    Rel(A, B) := 𝒫(A × B)
194end
196theorem rel_on.def [A B : term] :
197    |- ∀R, R ∈ Rel(A, B) ↔ R ⊆ A × B
198proof
199    follows Rel(A, B) = 𝒫(A × B) by eq.refl [Rel(A, B)];
200    done by powset.def
201qed

For a relation we have the notions of the domain and range which are the sets of the first element of each pair and the second element of each pair, respectively.

207definition
208    dom(R) := {π₁(x) | x ∈ R}
209end
211definition
212    ran(R) := {π₂(x) | x ∈ R}
213end

We can prove the following using the set map definition.

217theorem dom.def [R : term] :
218    |- ∀x, x ∈ dom(R) ↔ ∃y ∈ R, x = π₁(y)
219proof
220    suffices ∀x, x ∈ {π₁(z) | z ∈ R} ↔ ∃y ∈ R, x = π₁(y);
221    thus ∀x, x ∈ {π₁(z) | z ∈ R} ↔ (∃z, z ∈ R ∧ x = π₁(z)) by set_map.def [π₁(_)] [R];
222    done logically
223qed
225theorem ran.def [R : term] :
226    |- ∀x, x ∈ ran(R) ↔ ∃y ∈ R, x = π₂(y)
227proof
228    suffices ∀x, x ∈ {π₂(z) | z ∈ R} ↔ ∃y ∈ R, x = π₂(y);
229    thus ∀x, x ∈ {π₂(z) | z ∈ R} ↔ (∃z, z ∈ R ∧ x = π₂(z)) by set_map.def [π₂(_)] [R];
230    done logically
231qed

We can also have the notion of being a relation without having to know the exact domain and range.

236notation postfix_pred
237    sentence ::= term " : " @name
238end
240definition
241    R : Rel := R ∈ Rel(dom(R), ran(R))
242end
244theorem rel.def [R : term] :
245    |- R : Rel ↔ R ∈ Rel(dom(R), ran(R))
246proof
247    done by iff.refl [R : Rel]
248qed

The following result can be proved using the different relation definitions as well as the definition of the domain and range.

252theorem rel.is_rel_on [R : term] :
253    |- R : Rel ↔ ∃A, ∃B, R ∈ Rel(A, B)
254proof
255    -- (→)
256    assume R : Rel then ∃A, ∃B, R ∈ Rel(A, B) as
257        follows R ∈ Rel(dom(R), ran(R)) by rel.def;
258        done logically;
259    -- (←)
260    assume ∃A, ∃B, R ∈ Rel(A, B) then R : Rel as
261        -- We can fix A and B with our assumption
262        obtain A st ∃B, R ∈ Rel(A, B) logically;
263        obtain B st R ∈ Rel(A, B) logically;
264        follows R ⊆ A × B by rel_on.def;
265        suffices R ∈ Rel(dom(R), ran(R)) by rel.def;
266        suffices R ⊆ dom(R) × ran(R) by rel_on.def;
267        suffices ∀x, x ∈ R → x ∈ dom(R) × ran(R) by sub.def;
268        arbitrary x;
269        assume x ∈ R then x ∈ dom(R) × ran(R) as
270            follows ∀y, y ∈ R → y ∈ A × B by sub.def given R ⊆ A × B;
271            follows x ∈ A × B logically;
272            -- As x is an ordered pair in A × B, we know specifically that there is an a and b which make up the ordered pair x
273            obtain a st a ∈ A and b st b ∈ B ∧ x = ⟨a, b⟩ by cart_prod.def;
274            -- TODO: This (2 next lines) should not be something we have to prove
275            follows π₁(x) = a by opair_first.def given x = ⟨a, b⟩;
276            follows π₂(x) = b by opair_second.def given x = ⟨a, b⟩;
277            -- The first and second coordinates of x are by definition in the domain and range of R
278            thus π₁(x) ∈ dom(R) by dom.def given x ∈ R;
279            thus π₂(x) ∈ ran(R) by ran.def given x ∈ R;
280            done by cart_prod.def;
281        ;
282    done logically
283qed

We can show this fact in a similar manner to the previous proof, additionally making use of our cartesian product subset lemma.

286theorem rel_on.is_rel [R A B : term] :
287    |- R ∈ Rel(A, B) ↔ (R : Rel ∧ dom(R) ⊆ A ∧ ran(R) ⊆ B)
288proof
289    -- If R is a relation, then its a relation between sets
290    follows R : Rel ↔ ∃C, ∃D, R ∈ Rel(C, D) by rel.is_rel_on;
291    suffices R ∈ Rel(A, B) ↔ ((∃C, ∃D, R ∈ Rel(C, D)) ∧ dom(R) ⊆ A ∧ ran(R) ⊆ B) logically;
292    -- (→)
293    assume R ∈ Rel(A, B) then ((∃C, ∃D, R ∈ Rel(C, D)) ∧ dom(R) ⊆ A ∧ ran(R) ⊆ B) as
294        -- Really we just have to show that dom(R) ⊆ A and ran(R) ⊆ B as the first proposition is the same as our assumption
295        hence R ⊆ A × B by rel_on.def;
296        hence ∃C, ∃D, R ⊆ C × D logically;
297        follows ∃C, ∃D, R ∈ Rel(C, D) by rel_on.def;
298        suffices dom(R) ⊆ A ∧ ran(R) ⊆ B logically;
299        suffices (∀x ∈ dom(R), x ∈ A) ∧ (∀y ∈ ran(R), y ∈ B) by sub.def;
300        suffices (∀x, x ∈ dom(R) → x ∈ A) ∧ (∀y, y ∈ ran(R) → y ∈ B) logically;
301        -- Similarly to the last proof, we want to show the statement holds for an arbitrary element
302        hence (∀x, x ∈ dom(R) → x ∈ A) as
303            arbitrary x;
304            assume x ∈ dom(R) then x ∈ A as
305                obtain z st z ∈ R ∧ x = π₁(z) by dom.def;
306                follows z ∈ A × B by sub.def given R ⊆ A × B;
307                obtain a st a ∈ A and b st b ∈ B ∧ z = ⟨a, b⟩ by cart_prod.def;
308                follows π₁(z) = a by opair_first.def given z = ⟨a, b⟩;
309                done logically
310                ;
311            done logically
312            ;
313        hence (∀y, y ∈ ran(R) → y ∈ B) as
314            arbitrary y;
315            assume y ∈ ran(R) then y ∈ B as
316                obtain z st z ∈ R ∧ y = π₂(z) by ran.def;
317                follows z ∈ A × B by sub.def given R ⊆ A × B;
318                obtain b st b ∈ B and a st a ∈ A ∧ z = ⟨a, b⟩ by cart_prod.def;
319                follows π₂(z) = b by opair_second.def given z = ⟨a, b⟩;
320                done logically
321                ;
322            done logically
323            ;
324        done logically
325    ;
326    -- (←)
327    assume ((∃C, ∃D, R ∈ Rel(C, D)) ∧ dom(R) ⊆ A ∧ ran(R) ⊆ B) then R ∈ Rel(A, B) as
328        hence R : Rel by rel.is_rel_on;
329        follows R ∈ Rel(dom(R), ran(R)) by rel.def;
330        thus R ⊆ dom(R) × ran(R) by rel_on.def;
331        -- TODO: is this lemma useful?
332        follows dom(R) × ran(R) ⊆ A × B by cart_prod.sub;
333        hence R ⊆ A × B by sub.def given R ⊆ dom(R) × ran(R);
334        done by rel_on.def
335        ;
336    done logically
337qed

A functional relation is a particular kind of binary relation where the first element of each ordered pair in the relation is unique.

342notation functional_relation
343    term ::= term " → " term
344end
346definition
347    A → B := {f ∈ Rel(A, B) | ∀a ∈ A, ∃!b, ⟨a, b⟩ ∈ f}
348end
350theorem fn_on.def [A B : term] :
351    |- ∀f, f ∈ (A → B) ↔ f ∈ Rel(A, B) ∧ ∀a ∈ A, ∃!b, ⟨a, b⟩ ∈ f
352proof
353    suffices ∀f, f ∈ {f ∈ Rel(A, B) | ∀a ∈ A, ∃!b, ⟨a, b⟩ ∈ f} ↔ f ∈ Rel(A, B) ∧ ∀a ∈ A, ∃!b, ⟨a, b⟩ ∈ f;
354    done by zfc.extensionality
355qed

And once again we can define the notion of being a function independent of the domain and range.

360definition
361    f : Fn := f ∈ (dom(f) → ran(f))
362end
364theorem fn.def [f : term] :
365    |- f : Fn ↔ f ∈ (dom(f) → ran(f))
366proof
367    done by iff.refl [f : Fn]
368qed
370lemma fn.in_rel [A B : term] :
371    |- (A → B) ⊆ Rel(A, B)
372proof
373    thus {f ∈ Rel(A, B) | ∀a ∈ A, ∃!b, ⟨a, b⟩ ∈ f} ⊆ Rel(A, B)
374        by comp.sub [∀a ∈ A, ∃!b, ⟨a, b⟩ ∈ _] [Rel(A, B)];
375qed
377theorem fn.is_fn_on [f : term] :
378    |- f : Fn ↔ ∃A, ∃B, f ∈ (A → B)
379proof
380    suffices f ∈ (dom(f) → ran(f)) ↔ ∃A, ∃B, f ∈ (A → B);
381    assume f ∈ (dom(f) → ran(f)) then ∃A, ∃B, f ∈ (A → B) logically;
382    assume ∃A, ∃B, f ∈ (A → B) then f ∈ (dom(f) → ran(f)) as
383        obtain A st ∃B, f ∈ (A → B) logically;
384        obtain B st f ∈ (A → B) logically;
385        hence f ∈ Rel(A, B) ∧ ∀a ∈ A, ∃!b, ⟨a, b⟩ ∈ f by fn_on.def;
386        follows f : Rel by rel.is_rel_on;
387        follows f ∈ Rel(dom(f), ran(f)) by rel.def;
388        follows dom(f) ⊆ A by rel_on.is_rel;
389        follows ∀a, a ∈ dom(f) → a ∈ A by sub.def given dom(f) ⊆ A;
390        hence ∀a ∈ dom(f), ∃!b, ⟨a, b⟩ ∈ f logically;
391        done by fn_on.def
392        ;
393    done logically
394qed
396theorem fn_on.is_fn [f A B : term] :
397    |- f ∈ (A → B) ↔ (f : Fn ∧ dom(f) = A ∧ ran(f) ⊆ B)
398proof
399    hence f: Fn ↔ ∃C, ∃D, f ∈ (C → D) by fn.is_fn_on;
400    suffices f ∈ (A → B) ↔ (∃C, ∃D, f ∈ (C → D) ∧ dom(f) = A ∧ ran(f) ⊆ B) logically;
401    assume f ∈ (A → B) then (∃C, ∃D, f ∈ (C → D) ∧ dom(f) = A ∧ ran(f) ⊆ B) as
402        hence ∃C, ∃D, f ∈ (C → D) logically;
403        thus ∀x, x ∈ (A → B) → ∀a ∈ A, ∃!b, ⟨a, b⟩ ∈ x by fn_on.def;
404        follows ∀a ∈ A, ∃!b, ⟨a, b⟩ ∈ f logically;
405        suffices dom(f) = A ∧ ran(f) ⊆ B logically;
406        follows (A → B) ⊆ Rel(A, B) by fn.in_rel;
407        follows f ∈ Rel(A, B) by sub.def given (A → B) ⊆ Rel(A, B);
408        follows dom(f) ⊆ A ∧ ran(f) ⊆ B by rel_on.is_rel;
409        suffices A ⊆ dom(f) by sub.sub_eq;
410        suffices ∀a ∈ A, a ∈ dom(f) by sub.def;
411        arbitrary a;
412        assume a ∈ A then a ∈ dom(f) as
413            obtain b st ⟨a, b⟩ ∈ f logically;
414            thus a = π₁(⟨a, b⟩) by opair_first.def;
415            done by dom.def given ⟨a, b⟩ ∈ f
416            ;
417        done logically
418        ;
419    assume (∃C, ∃D, f ∈ (C → D) ∧ dom(f) = A ∧ ran(f) ⊆ B) then f ∈ (A → B) as
420        obtain C st ∃D, f ∈ (C → D) ∧ dom(f) = A ∧ ran(f) ⊆ B logically;
421        obtain D st f ∈ (C → D) ∧ dom(f) = A ∧ ran(f) ⊆ B logically;
422        follows f : Fn by fn.is_fn_on;
423        follows f ∈ (dom(f) → ran(f)) by fn.def;
424        follows ∀a ∈ dom(f), ∃!b, ⟨a, b⟩ ∈ f by fn_on.def;
425        hence ∀a ∈ A, ∃!b, ⟨a, b⟩ ∈ f logically;
426        follows (C → D) ⊆ Rel(C, D) by fn.in_rel;
427        follows f ∈ Rel(C, D) by sub.def given (C → D) ⊆ Rel(C, D);
428        follows f : Rel by rel.is_rel_on;
429        hence dom(f) = A logically;
430        follows dom(f) ⊆ dom(f) by sub.refl;
431        follows dom(f) ⊆ A by eq.subst [dom(f) ⊆ _] [dom(f)] [A];
432        follows f ∈ Rel(A, B) by rel_on.is_rel;
433        done by fn_on.def
434        ;
435    done logically
436qed

We define function application by extracting the second element of the unique ordered pair which has the argument as the first element. We can make this definition using the iota operator.

442notation function_application
443    term (1000) ::= term "(" term ")"
444end
446definition
447    f:term (a) := ℩b, ⟨a, b⟩ ∈ f
448end

This proof follows from our definition as well as the iota operator which lets us show unambiguity

452theorem fn_on.pairs [f A B : term] : (f ∈ (A → B))
453    |- f = {⟨a, f(a)⟩ | a ∈ A}
454proof
455    suffices f = {y | ∃a, a ∈ A ∧ y = ⟨a, f(a)⟩};
456    thus f ∈ Rel(A, B) ∧ ∀a ∈ A, ∃!b, ⟨a, b⟩ ∈ f by fn_on.def;
457    follows f ⊆ A × B by rel_on.def;
458    follows ∀a ∈ A, ∃!b, ⟨a, b⟩ ∈ f logically;
459    thus ∀x, x ∈ f ↔ (∃a, a ∈ A ∧ x = ⟨a, f(a)⟩) as
460        arbitrary x;
461        assume x ∈ f then ∃a, a ∈ A ∧ x = ⟨a, f(a)⟩ as
462            follows x ∈ A × B by sub.def given f ⊆ A × B;
463            obtain a st a ∈ A and b st b ∈ B ∧ x = ⟨a, b⟩ by cart_prod.def;
464            follows ⟨a, b⟩ ∈ f given x = ⟨a, b⟩;
465            follows ∃!b, ⟨a, b⟩ ∈ f logically;
466            follows ⟨a, f(a)⟩ ∈ f by iota.unique [⟨a, _⟩ ∈ f];
467            hence f(a) = b logically;
468            hence x = ⟨a, f(a)⟩ logically;
469            done logically
470            ;
471        assume ∃a, a ∈ A ∧ x = ⟨a, f(a)⟩ then x ∈ f as
472            obtain a st a ∈ A ∧ x = ⟨a, f(a)⟩ logically;
473            follows ∃!b, ⟨a, b⟩ ∈ f logically;
474            follows ⟨a, f(a)⟩ ∈ f by iota.unique [⟨a, _⟩ ∈ f];
475            done logically
476            ;
477        done logically
478        ;
479    -- f itself witnesses that the set exists, so the comprehension is well
480    -- defined and has the expected members.
481    follows ∃z, ∀x, x ∈ z ↔ (∃a, a ∈ A ∧ x = ⟨a, f(a)⟩) logically;
482    follows ∀x, x ∈ {y | ∃a, a ∈ A ∧ y = ⟨a, f(a)⟩} ↔ (∃a, a ∈ A ∧ x = ⟨a, f(a)⟩) by uncomp.def [∃a, a ∈ A ∧ _ = ⟨a, f(a)⟩];
483    follows ∀x, x ∈ f ↔ x ∈ {y | ∃a, a ∈ A ∧ y = ⟨a, f(a)⟩} logically;
484    done by zfc.extensionality
485qed
487theorem fn.pairs [f : term] : (f : Fn)
488    |- f = {⟨x, f(x)⟩ | x ∈ dom(f)}
489proof
490    follows f ∈ (dom(f) → ran(f)) by fn.def;
491    done by fn_on.pairs [f] [dom(f)] [ran(f)]
492qed

A useful lemma which lets us skip a lot of notation

496lemma fn.apply_iff [f a b : term] : (f : Fn) (a ∈ dom(f))
497    |- ⟨a, b⟩ ∈ f ↔ f(a) = b
498proof
499    follows f ∈ (dom(f) → ran(f)) by fn.def;
500    follows ∀a ∈ dom(f), ∃!b, ⟨a, b⟩ ∈ f by fn_on.def;
501    follows ∃!b, ⟨a, b⟩ ∈ f logically;
502    follows ⟨a, f(a)⟩ ∈ f by iota.unique [⟨a, _⟩ ∈ f];
503    done logically
504qed
507notation function_maps_to
508    term ::= x:@binding(term) " ∈ " term " ↦ " term(x)
509end
511definition
512    x ∈ X ↦ f(x) := {⟨x, f(x)⟩ | x ∈ X}
513end

This theorem follows from an ever-rare explicit use of the axiom of replacement as well as previously shown results for relations.

517theorem fun_map.is.rel [A B : term] [f(_) : term(term)]: (∀x ∈ A, f(x) ∈ B)
518    |- x ∈ A ↦ f(x) ∈ (A → B)
519proof
520    suffices {⟨x, f(x)⟩ | x ∈ A} ∈ (A → B);
521    suffices {y | ∃x, x ∈ A ∧ y = ⟨x, f(x)⟩} ∈ (A → B);
522    -- Using our replacement axiom to show that a functional mapping of a set defines its own set
523    follows ∀a, (∀x, x ∈ a → ∃!y, y = ⟨x, f(x)⟩) → (∃x, ∀y, y ∈ x ↔ (∃z, z ∈ a ∧ y = ⟨z, f(z)⟩))
524        by zfc.replacement [_1 = ⟨_0, f(_0)⟩];
525    -- Then we show the set that it defines
526    follows ∃z, ∀y, y ∈ z ↔ (∃x, x ∈ A ∧ y = ⟨x, f(x)⟩) logically;
527    thus ∀y, y ∈ {y | ∃x, x ∈ A ∧ y = ⟨x, f(x)⟩} ↔ (∃x, x ∈ A ∧ y = ⟨x, f(x)⟩)
528        by uncomp.def [∃x, x ∈ A ∧ _ = ⟨x, f(x)⟩];
529    suffices {y | ∃x, x ∈ A ∧ y = ⟨x, f(x)⟩} ∈ Rel(A, B)
530        ∧ ∀a ∈ A, ∃!b, ⟨a, b⟩ ∈ {y | ∃x, x ∈ A ∧ y = ⟨x, f(x)⟩} by fn_on.def;
531    -- Function mappings are subsets of all of the relations between two sets
532    thus {y | ∃x, x ∈ A ∧ y = ⟨x, f(x)⟩} ∈ Rel(A, B) as
533        suffices {y | ∃x, x ∈ A ∧ y = ⟨x, f(x)⟩} ⊆ A × B by rel_on.def;
534        suffices ∀w, w ∈ {y | ∃x, x ∈ A ∧ y = ⟨x, f(x)⟩} → w ∈ A × B by sub.def;
535        arbitrary w;
536        assume w ∈ {y | ∃x, x ∈ A ∧ y = ⟨x, f(x)⟩} then w ∈ A × B as
537            obtain a st a ∈ A ∧ w = ⟨a, f(a)⟩ logically;
538            follows f(a) ∈ B logically;
539            done by cart_prod.def
540            ;
541        done logically
542        ;
543    -- Showing function well-definedness, basically that every element a in A has a mapping, and that a = a → f(a) = f(a)
544    thus ∀a ∈ A, ∃!b, ⟨a, b⟩ ∈ {y | ∃x, x ∈ A ∧ y = ⟨x, f(x)⟩} as
545        arbitrary a;
546        assume a ∈ A then ∃!b, ⟨a, b⟩ ∈ {y | ∃x, x ∈ A ∧ y = ⟨x, f(x)⟩} as
547            thus ⟨a, f(a)⟩ ∈ {y | ∃x, x ∈ A ∧ y = ⟨x, f(x)⟩} logically;
548            thus ∀b, ⟨a, b⟩ ∈ {y | ∃x, x ∈ A ∧ y = ⟨x, f(x)⟩} → b = f(a) as
549                arbitrary b;
550                assume ⟨a, b⟩ ∈ {y | ∃x, x ∈ A ∧ y = ⟨x, f(x)⟩} then b = f(a) as
551                    obtain c st c ∈ A ∧ ⟨a, b⟩ = ⟨c, f(c)⟩ logically;
552                    follows a = c ∧ b = f(c) by opair.eq;
553                    done logically
554                    ;
555                done logically
556                ;
557            done logically
558            ;
559        done logically
560        ;
561
562    done logically
563qed

TODO:

568grammar_category chain_list
570tactic tactic.chain
571    tactic ::= @kw"chain" term:@fragment(term) list:chain_list
572end
574tactic chain_list.one
575    chain_list ::= "=" term:@fragment(term) just:justification ";"
576end
577tactic chain_list.many
578    chain_list ::= "=" term:@fragment(term) just:justification ";" rest:chain_list
579end
582theorem fn.eq_on_dom.eq [f g : term] : (f : Fn) (g : Fn) (dom(f) = dom(g))
583    (∀x ∈ dom(f), f(x) = g(x))
584    |- f = g
585proof
586    -- chain f = {⟨x, f(x)⟩ | x ∈ dom(f)} by fn.pairs;
587    --         = {⟨x, g(x)⟩ | x ∈ dom(f)} given ∀x ∈ dom(f), f(x) = g(x);
588    --         = {⟨x, g(x)⟩ | x ∈ dom(g)} given dom(f) = dom(g);
589    --         = g                        by fn.pairs;
590    chain f = {⟨x, f(x)⟩ | x ∈ dom(f)} as todo;
591            = {⟨x, g(x)⟩ | x ∈ dom(f)} as todo;
592            = {⟨x, g(x)⟩ | x ∈ dom(g)} as todo;
593            = g                        as todo;
594qed
596notation fn_restriction
597    term ::= term " ↾ " term
598end
600definition
601    f ↾ A := {x ∈ f | π₁(x) ∈ A}
602end
604theorem fn.restriction.is [f X : term] : (f : Fn)
605    |- f ↾ X : Fn
606proof
607    todo
608qed
610theorem fn.restriction.pairs [f X : term] : (f : Fn)
611    |- f ↾ X = {⟨x, f(x)⟩ | x ∈ dom(f) ∩ X}
612proof
613    todo
614qed
616theorem fn.restriction.eq [f g X : term] : (f : Fn) (g : Fn) (dom(f) ∩ X = dom(g) ∩ X)
617    (∀x ∈ dom(f) ∩ X, f(x) = g(x))
618    |- f ↾ X = g ↾ X
619proof
620    -- chain f ↾ X 
621    --     = {⟨x, f(x)⟩ | x ∈ dom(f) ∩ X} by fn.restriction.pairs;
622    --     = {⟨x, g(x)⟩ | x ∈ dom(f) ∩ X} given ∀x ∈ X, f(x) = g(x);
623    --     = {⟨x, g(x)⟩ | x ∈ dom(g) ∩ X} given dom(f) ∩ X = dom(g) ∩ X;
624    --     = g ↾ X                        by fn.restriction.pairs;
625    chain f ↾ X 
626        = {⟨x, f(x)⟩ | x ∈ dom(f) ∩ X} as todo;
627        = {⟨x, g(x)⟩ | x ∈ dom(f) ∩ X} as todo;
628        = {⟨x, g(x)⟩ | x ∈ dom(g) ∩ X} as todo;
629        = g ↾ X                        as todo;
630qed

Function properties & Composition 3.4

The image of a function under a set is the set resulting from applying the function to every element of the set

636notation image_set
637    term (1000) ::= term "[" term "]"
638end
640definition
641    f:term [A] := {f(a) | a ∈ A}
642end
644theorem image.def [f A : term] :
645    |- ∀y, y ∈ f[A] ↔ ∃a ∈ A, y = f(a)
646proof
647    suffices ∀y, y ∈ {f(a) | a ∈ A} ↔ ∃a ∈ A, y = f(a);
648    thus ∀y, y ∈ {f(a) | a ∈ A} ↔ (∃a, a ∈ A ∧ y = f(a)) by set_map.def [f(_)] [A];
649    done logically
650qed

Trivially, the image of a subset of a domain is a subset of the range, with equality when finding the image of the domain

654theorem dom.is_ran_under_image [f A B : term] : (f ∈ (A → B))
655    |- f[A] = ran(f)
656proof
657    thus f : Fn by fn_on.is_fn;
658    suffices f[dom(f)] = ran(f) by fn_on.is_fn;
659    hence ∀y, y ∈ f[dom(f)] ↔ ∃a ∈ dom(f), y = f(a) by image.def;
660    furthermore ∀y, y ∈ ran(f) ↔ ∃z ∈ f, y = π₂(z) by ran.def;
661    indeed ∀y, y ∈ f[dom(f)] ↔ y ∈ ran(f) as
662        arbitrary y;
663        assume y ∈ f[dom(f)] then y ∈ ran(f) as
664            obtain a st a ∈ dom(f) ∧ y = f(a) logically;
665            hence ⟨a, f(a)⟩ ∈ f ↔ f(a) = f(a) by fn.apply_iff given a ∈ dom(f);
666            follows π₂(⟨a, f(a)⟩) = f(a) by opair_second.def;
667            done by ran.def given ⟨a, f(a)⟩ ∈ f
668            ;
669        assume y ∈ ran(f) then y ∈ f[dom(f)] as
670            follows f ⊆ A × B by rel_on.def, fn.in_rel, sub.def;
671            obtain b st b ∈ f ∧ y = π₂(b) logically;
672            hence b ∈ A × B by sub.def;
673            obtain a st a ∈ A and c st c ∈ B ∧ b = ⟨a, c⟩ by cart_prod.def;
674            furthermore π₂(b) = c by opair_second.def given b = ⟨a, c⟩;
675            thus a = π₁(⟨a, c⟩) by opair_first.def;
676            thus ⟨a, c⟩ ∈ f given b = ⟨a, c⟩;
677            hence a ∈ dom(f) by dom.def given ⟨a, c⟩ ∈ f;
678            follows ⟨a, c⟩ ∈ f ↔ f(a) = c by fn.apply_iff [f] [a] [c];
679            follows f(a) = y logically;
680            done by image.def given a ∈ dom(f)
681            ;
682        done logically
683        ;
684    done by zfc.extensionality
685qed

Importantly, every image has a preimage, which we'll have as the set of terms which are mapped to a specific set under a function

690notation preimage_set
691    term (1000) ::= term "⁻¹" "[" term "]"
692end
694definition
695    f:term⁻¹[A] := {x ∈ dom(f) | f(x) ∈ A}
696end
698theorem preimage.def [f A : term] :
699    |- ∀x, x ∈ f⁻¹[A] ↔ (x ∈ dom(f) ∧ f(x) ∈ A)
700proof
701    suffices ∀x, x ∈ {x ∈ dom(f) | f(x) ∈ A} ↔ (x ∈ dom(f) ∧ f(x) ∈ A);
702    done by zfc.extensionality
703qed

A surjection, also known as an onto function, between sets is a mapping where the range is the same as the codomain

707notation surjection
708    term ::= term " ↠ " term
709end
711definition
712    A ↠ B := {f ∈ (A → B) | ran(f) = B}
713end
715theorem surj_on.def [A B : term] :
716    |- ∀f, f ∈ (A ↠ B) ↔ (f ∈ (A → B) ∧ ran(f) = B)
717proof
718    suffices ∀f, f ∈ {f ∈ (A → B) | ran(f) = B} ↔ (f ∈ (A → B) ∧ ran(f) = B);
719    done by zfc.extensionality
720qed

An injection, a one-to-one function, between sets is one where every element of the domain is mapped to a unique element in the range

724notation injection
725    term ::= term " ↣ " term
726end
728definition
729    A ↣ B := {f ∈ (A → B) | ∀x, ∀y, x ∈ A ∧ y ∈ A ∧ f(x) = f(y) → x = y}
730end
732theorem inj_on.def [A B : term] :
733    |- ∀f, f ∈ (A ↣ B) ↔ (f ∈ (A → B) ∧ (∀x, ∀y, x ∈ A ∧ y ∈ A ∧ f(x) = f(y) → x = y))
734proof
735    suffices ∀f, f ∈ {f ∈ (A → B) | ∀x, ∀y, x ∈ A ∧ y ∈ A ∧ f(x) = f(y) → x = y} ↔ (f ∈ (A → B) ∧ (∀x, ∀y, x ∈ A ∧ y ∈ A ∧ f(x) = f(y) → x = y));
736    done by zfc.extensionality
737qed
739definition
740    f : Inj := f ∈ (dom(f) ↣ ran(f))
741end
743theorem inj.def [f : term] :
744    |- f : Inj ↔ f ∈ (dom(f) ↣ ran(f))
745proof
746    done by iff.refl [f : Inj]
747qed

A bijection between sets is a function that is both injective and surjective

751notation bijection
752    term ::= term " ↔ " term
753end
755definition
756    A ↔ B := {f ∈ (A ↣ B) | ran(f) = B}
757end
759theorem bij_on.def [A B : term] :
760    |- ∀f, f ∈ (A ↔ B) ↔ (f ∈ (A ↣ B) ∧ ran(f) = B)
761proof
762    suffices ∀f, f ∈ {f ∈ (A ↣ B) | ran(f) = B} ↔ (f ∈ (A ↣ B) ∧ ran(f) = B);
763    done by zfc.extensionality
764qed
766definition
767    f : Bij := f ∈ (dom(f) ↔ ran(f))
768end
770theorem bij.def [f : term] :
771    |- f : Bij ↔ f ∈ (dom(f) ↔ ran(f))
772proof
773    done by iff.refl [f : Bij]
774qed

This theorem follows cleanly from the definitions for injective, bijective, and surjective functions

778theorem bij_on.is_inj_and_surj [f A B : term] :
779    |- f ∈ (A ↔ B) ↔ (f ∈ (A ↣ B) ∧ f ∈ (A ↠ B))
780proof
781    follows f ∈ (A ↔ B) ↔ (f ∈ (A ↣ B) ∧ ran(f) = B) by bij_on.def;
782    follows f ∈ (A ↠ B) ↔ (f ∈ (A → B) ∧ ran(f) = B) by surj_on.def;
783    follows f ∈ (A ↣ B) → f ∈ (A → B) by inj_on.def;
784    done logically
785qed

We can define an inverse relation simply as the swapped coordinates of the relation

789notation inverse_relation
790    term (1000) ::= term "⁻¹"
791end
793definition
794    f:term⁻¹ := {⟨π₂(p), π₁(p)⟩ | p ∈ f}
795end

Swapping the components of every pair in f swaps the roles of the domain and the range.

799lemma inv.dom [f : term] :
800    |- dom(f⁻¹) = ran(f)
801proof
802    follows ∀x, x ∈ dom(f⁻¹) ↔ ∃y ∈ f⁻¹, x = π₁(y) by dom.def;
803    thus ∀y, y ∈ f⁻¹ ↔ ∃p ∈ f, y = ⟨π₂(p), π₁(p)⟩ by set_map.def [⟨π₂(_), π₁(_)⟩] [f];
804    follows ∀p, π₁(⟨π₂(p), π₁(p)⟩) = π₂(p) by opair_first.def;
805    follows ∀x, x ∈ ran(f) ↔ ∃p ∈ f, x = π₂(p) by ran.def;
806    hence ∀x, x ∈ dom(f⁻¹) ↔ x ∈ ran(f) logically;
807    done by zfc.extensionality
808qed
810lemma inv.ran [f : term] :
811    |- ran(f⁻¹) = dom(f)
812proof
813    follows ∀x, x ∈ ran(f⁻¹) ↔ ∃y ∈ f⁻¹, x = π₂(y) by ran.def;
814    thus ∀y, y ∈ f⁻¹ ↔ ∃p ∈ f, y = ⟨π₂(p), π₁(p)⟩ by set_map.def [⟨π₂(_), π₁(_)⟩] [f];
815    follows ∀p, π₂(⟨π₂(p), π₁(p)⟩) = π₁(p) by opair_second.def;
816    follows ∀x, x ∈ dom(f) ↔ ∃p ∈ f, x = π₁(p) by dom.def;
817    hence ∀x, x ∈ ran(f⁻¹) ↔ x ∈ dom(f) logically;
818    done by zfc.extensionality
819qed

The following proof gives us a way to reason with and construct what f⁻¹ looks like

823lemma inv.mem [f A B : term] : (f ∈ Rel(A, B))
824    |- ∀a, ∀b, ⟨a, b⟩ ∈ f⁻¹ ↔ ⟨b, a⟩ ∈ f
825proof
826    arbitrary a; arbitrary b;
827    follows f ⊆ A × B by rel_on.def;
828    thus ∀y, y ∈ f⁻¹ ↔ ∃p ∈ f, y = ⟨π₂(p), π₁(p)⟩ by set_map.def [⟨π₂(_), π₁(_)⟩] [f];
829    assume ⟨b, a⟩ ∈ f then ⟨a, b⟩ ∈ f⁻¹ as
830        follows π₁(⟨b, a⟩) = b by opair_first.def;
831        follows π₂(⟨b, a⟩) = a by opair_second.def;
832        hence ⟨a, b⟩ = ⟨π₂(⟨b, a⟩), π₁(⟨b, a⟩)⟩ logically;
833        done logically
834        ;
835    assume ⟨a, b⟩ ∈ f⁻¹ then ⟨b, a⟩ ∈ f as
836        obtain p st p ∈ f ∧ ⟨a, b⟩ = ⟨π₂(p), π₁(p)⟩ logically;
837        follows p ∈ A × B by sub.def given f ⊆ A × B;
838        obtain c st c ∈ A and d st d ∈ B ∧ p = ⟨c, d⟩ by cart_prod.def;
839        follows π₁(p) = c by opair_first.def given p = ⟨c, d⟩;
840        follows π₂(p) = d by opair_second.def given p = ⟨c, d⟩;
841        follows a = d ∧ b = c by opair.eq given ⟨a, b⟩ = ⟨π₂(p), π₁(p)⟩;
842        done logically
843        ;
844    done logically
845qed

The inverse of a relation between A and B is itself a relation, between B and A.

849lemma inv.rel [f A B : term] : (f ∈ Rel(A, B))
850    |- f⁻¹ ∈ Rel(B, A)
851proof
852    -- A relation is just some subset of the cartesian product
853    follows f ⊆ A × B by rel_on.def;
854    follows ∀a, ∀b, ⟨a, b⟩ ∈ f⁻¹ ↔ ⟨b, a⟩ ∈ f by inv.mem;
855    suffices ∀y, y ∈ f⁻¹ → y ∈ B × A by rel_on.def, sub.def;
856    arbitrary y;
857    assume y ∈ f⁻¹ then y ∈ B × A as
858        -- every element of f⁻¹ is a swapped pair from f
859        thus ∀z, z ∈ f⁻¹ ↔ ∃p ∈ f, z = ⟨π₂(p), π₁(p)⟩ by set_map.def [⟨π₂(_), π₁(_)⟩] [f];
860        obtain p st p ∈ f ∧ y = ⟨π₂(p), π₁(p)⟩ logically;
861        -- inv.mem swaps the pair back into f
862        follows ⟨π₁(p), π₂(p)⟩ ∈ f by inv.mem;
863        follows ⟨π₁(p), π₂(p)⟩ ∈ A × B by sub.def given f ⊆ A × B;
864        hence π₁(p) ∈ A ∧ π₂(p) ∈ B by cart_prod.def, opair.eq;
865        done by cart_prod.def
866        ;
867qed

When f is a bijection, its inverse is a function, every b ∈ B has a preimage because f is onto, and that preimage is unique because f is injective.

872lemma inv.is_fn_on [f A B : term] : (f ∈ (A ↔ B))
873    |- f⁻¹ ∈ (B → A)
874proof
875    indeed f ∈ (A ↣ B) ∧ ran(f) = B by bij_on.def;
876    hence f ∈ (A → B) ∧ f : Fn ∧ dom(f) = A by inj_on.def, fn_on.is_fn;
877    furthermore ∀a, ∀b, a ∈ A ∧ b ∈ A ∧ f(a) = f(b) → a = b by inj_on.def;
878    furthermore f ∈ Rel(A, B) by fn.in_rel, sub.def;
879    follows f⁻¹ ∈ Rel(B, A) by inv.rel given f ∈ Rel(A, B);
880    thus ∀a, ∀b, ⟨a, b⟩ ∈ f⁻¹ ↔ ⟨b, a⟩ ∈ f by inv.mem given f ∈ Rel(A, B);
881    suffices ∀b ∈ B, ∃!a, ⟨b, a⟩ ∈ f⁻¹ by fn_on.def;
882    arbitrary d;
883    assume d ∈ B then ∃!a, ⟨d, a⟩ ∈ f⁻¹ as
884        -- Every element of B is in the image of f[A] so a exists
885        obtain a₀ st a₀ ∈ A ∧ d = f(a₀) by image.def, dom.is_ran_under_image;
886        hence ⟨a₀, d⟩ ∈ f ∧ ⟨d, a₀⟩ ∈ f⁻¹ by fn.apply_iff given a₀ ∈ A;
887        -- any preimage of d is exactly a because f is injective
888        hence ∀a, ⟨d, a⟩ ∈ f⁻¹ → a ∈ dom(f) ∧ f(a) = d by dom.def, opair_first.def, fn.apply_iff;
889        done logically
890        ;
891    done logically
892qed

Next we show that bijections undo their inverse

896lemma inv.apply [f A B b : term] : (f ∈ (A ↔ B)) (b ∈ B)
897    |- f(f⁻¹(b)) = b
898proof
899    indeed f ∈ (A → B) ∧ f : Fn ∧ dom(f) = A by bij_on.def, inj_on.def, fn_on.is_fn;
900    furthermore f ∈ Rel(A, B) by fn.in_rel, sub.def;
901    hence ∀u, ∀v, ⟨u, v⟩ ∈ f⁻¹ ↔ ⟨v, u⟩ ∈ f by inv.mem;
902    follows f⁻¹ : Fn ∧ dom(f⁻¹) = B by inv.is_fn_on, fn_on.is_fn;
903    hence ⟨b, f⁻¹(b)⟩ ∈ f⁻¹ ∧ ⟨f⁻¹(b), b⟩ ∈ f by fn.apply_iff given b ∈ B;
904    follows f⁻¹(b) ∈ dom(f) by dom.def, opair_first.def given ⟨f⁻¹(b), b⟩ ∈ f;
905    done by fn.apply_iff given ⟨f⁻¹(b), b⟩ ∈ f and f⁻¹(b) ∈ dom(f)
906qed
908notation function_composition
909    term (400) ::= term " ∘ " term
910end
912definition
913    g ∘ f := {⟨x, g(f(x))⟩ | x ∈ {x ∈ dom(f) | f(x) ∈ dom(g)}}
914end
916theorem composition.def [f g : term] :
917    |- ∀y, y ∈ (g ∘ f) ↔ ∃x, (x ∈ dom(f) ∧ f(x) ∈ dom(g)) ∧ y = ⟨x, g(f(x))⟩
918proof
919    follows ∀y, y ∈ (g ∘ f) ↔ ∃x ∈ {x ∈ dom(f) | f(x) ∈ dom(g)}, y = ⟨x, g(f(x))⟩
920        by set_map.def [⟨_, g(f(_))⟩] [{x ∈ dom(f) | f(x) ∈ dom(g)}];
921    hence ∀x, x ∈ {x ∈ dom(f) | f(x) ∈ dom(g)} ↔ (x ∈ dom(f) ∧ f(x) ∈ dom(g))
922        by comp.def [f(_) ∈ dom(g)] [dom(f)];
923    done logically
924qed
926theorem composition.dom [f g : term] :
927    |- ∀x, x ∈ dom(g ∘ f) ↔ (x ∈ dom(f) ∧ f(x) ∈ dom(g))
928proof
929    follows ∀z, z ∈ dom(g ∘ f) ↔ ∃y ∈ (g ∘ f), z = π₁(y) by dom.def;
930    furthermore ∀y, y ∈ (g ∘ f) ↔ ∃x, (x ∈ dom(f) ∧ f(x) ∈ dom(g)) ∧ y = ⟨x, g(f(x))⟩ by composition.def;
931    indeed ∀x, π₁(⟨x, g(f(x))⟩) = x by opair_first.def;
932    done logically
933qed

Here we show that function composition is itself a function

937theorem composition.is_fn [f g : term] : (f : Fn) (g : Fn)
938    |- g ∘ f : Fn
939proof
940    -- We want to show that the composition is some functional relation between two sets
941    suffices ∃A, ∃B, g ∘ f ∈ (A → B) by fn.is_fn_on;
942    thus ∀x ∈ {x ∈ dom(f) | f(x) ∈ dom(g)}, g(f(x)) ∈ ran(g) as
943        -- The construction here is simple as we only pick x where f(x) is in dom(g), because
944        -- g(dom(g)) being in ran(g) falls out of the definition
945        arbitrary c st c ∈ {x ∈ dom(f) | f(x) ∈ dom(g)};
946        follows g(f(c)) ∈ ran(g) as
947            follows ∀x, x ∈ {x ∈ dom(f) | f(x) ∈ dom(g)} ↔ (x ∈ dom(f) ∧ f(x) ∈ dom(g))
948                by comp.def [f(_) ∈ dom(g)] [dom(f)];
949            thus f(c) ∈ dom(g) logically;
950            hence ⟨f(c), g(f(c))⟩ ∈ g ↔ g(f(c)) = g(f(c)) by fn.apply_iff [g] [f(c)] [g(f(c))];
951            hence ⟨f(c), g(f(c))⟩ ∈ g logically;
952            follows π₂(⟨f(c), g(f(c))⟩) = g(f(c)) by opair_second.def;
953            done by ran.def given ⟨f(c), g(f(c))⟩ ∈ g
954            ;
955        done logically
956        ;
957    -- g ∘ f is a functional mapping from dom(g ∘ f) to ran(g)
958    follows g ∘ f ∈ ({x ∈ dom(f) | f(x) ∈ dom(g)} → ran(g))
959        by fun_map.is.rel [{x ∈ dom(f) | f(x) ∈ dom(g)}] [ran(g)] [g(f(_))];
960    done logically
961qed

This theorem follows cleanly from the above facts.

965theorem composition.apply [f g a : term] : (f : Fn) (g : Fn) (a ∈ dom(g ∘ f))
966    |- (g ∘ f)(a) = g(f(a))
967proof
968    hence a ∈ dom(f) ∧ f(a) ∈ dom(g) by composition.dom;
969    furthermore ∀y, y ∈ (g ∘ f) ↔ ∃x, (x ∈ dom(f) ∧ f(x) ∈ dom(g)) ∧ y = ⟨x, g(f(x))⟩ by composition.def;
970    furthermore ⟨a, g(f(a))⟩ ∈ (g ∘ f) logically;
971    indeed g ∘ f : Fn by composition.is_fn;
972    furthermore ⟨a, g(f(a))⟩ ∈ (g ∘ f) ↔ (g ∘ f)(a) = g(f(a)) by fn.apply_iff [g ∘ f] [a] [g(f(a))];
973    done logically
974qed
976theorem composition.is_fn_on [f g A B C : term] : (f ∈ (A → B)) (g ∈ (B → C))
977    |- g ∘ f ∈ (A → C)
978proof
979    hence g ∘ f : Fn by composition.is_fn, fn.is_fn_on;
980    hence ∀x, x ∈ dom(g ∘ f) ↔ (x ∈ dom(f) ∧ f(x) ∈ dom(g)) by composition.dom;
981    follows f ∈ (A → B) → dom(f) = A ∧ ran(f) ⊆ B by fn_on.is_fn;
982    follows g ∈ (B → C) → dom(g) = B ∧ ran(g) ⊆ C by fn_on.is_fn;
983    indeed ∀x, x ∈ dom(g ∘ f) ↔ (x ∈ A ∧ f(x) ∈ B) logically;
984    hence ∀x, x ∈ A → f(x) ∈ B as
985        arbitrary c st c ∈ A;
986        follows f(c) ∈ B as
987            indeed c ∈ dom(f) logically;
988            hence ⟨c, f(c)⟩ ∈ f as
989                indeed f : Fn by fn.is_fn_on;
990                thus ⟨c, f(c)⟩ ∈ f ↔ f(c) = f(c) by fn.apply_iff [f] [c] [f(c)];
991                done logically
992                ;
993            follows f(c) ∈ ran(f) by opair_second.def, ran.def given ⟨c, f(c)⟩ ∈ f;
994            done by sub.def given ran(f) ⊆ B
995            ;
996        ;
997    hence ∀x, x ∈ dom(g ∘ f) ↔ x ∈ A logically;
998    hence dom(g ∘ f) = A by zfc.extensionality;
999    thus ran(g ∘ f) ⊆ C as
1000        suffices ∀y, y ∈ ran(g ∘ f) → y ∈ C by sub.def;
1001        arbitrary y;
1002        assume y ∈ ran(g ∘ f) then y ∈ C as
1003            obtain p st p ∈ (g ∘ f) ∧ y = π₂(p) by ran.def;
1004            obtain x st (x ∈ dom(f) ∧ f(x) ∈ dom(g)) ∧ p = ⟨x, g(f(x))⟩ by composition.def;
1005            indeed g : Fn by fn.is_fn_on;
1006            furthermore f(x) ∈ dom(g) logically;
1007            follows ⟨f(x), g(f(x))⟩ ∈ g ↔ g(f(x)) = g(f(x)) by fn.apply_iff [g] [f(x)] [g(f(x))];
1008            hence ⟨f(x), g(f(x))⟩ ∈ g logically;
1009            follows g(f(x)) ∈ ran(g) by ran.def, opair_second.def given ⟨f(x), g(f(x))⟩ ∈ g;
1010            done by opair_second.def, sub.def given ran(g) ⊆ C
1011            ;
1012        done logically
1013        ;
1014    done by fn_on.is_fn
1015qed

A function composed of two injective functions is itself injective. This is a standard injectivity proof where we reason that g(f(x)) = g(f(y)) implies f(x) = f(y) which impliex x = y

1020theorem comp_inj.is_inj [f g A B C : term] : (f ∈ (A ↣ B)) (g ∈ (B ↣ C))
1021    |- g ∘ f ∈ (A ↣ C)
1022proof
1023    follows g ∘ f ∈ (A → C) by composition.is_fn_on, inj_on.def;
1024    suffices ∀x, ∀y, x ∈ A ∧ y ∈ A ∧ (g ∘ f)(x) = (g ∘ f)(y) → x = y by inj_on.def;
1025    arbitrary x; arbitrary y;
1026    assume x ∈ A ∧ y ∈ A ∧ (g ∘ f)(x) = (g ∘ f)(y) then x = y as
1027        follows f ∈ (A → B) ∧ g ∈ (B → C) by inj_on.def;
1028        indeed (∀a, ∀b, a ∈ A ∧ b ∈ A ∧ f(a) = f(b) → a = b)
1029              ∧ (∀a, ∀b, a ∈ B ∧ b ∈ B ∧ g(a) = g(b) → a = b) by inj_on.def;
1030        indeed f : Fn ∧ g : Fn by fn.is_fn_on;
1031        thus dom(g ∘ f) = A ∧ dom(g) = B by fn_on.is_fn;
1032        hence x ∈ dom(g ∘ f) ∧ y ∈ dom(g ∘ f) logically;
1033        follows g(f(x)) = g(f(y)) by composition.apply;
1034        furthermore f(x) ∈ B ∧ f(y) ∈ B by composition.dom;
1035        thus f(x) = f(y) logically;
1036        done logically
1037        ;
1038    done logically
1039qed

The following proof where we show composition of surjective functions is surjective takes a different shape. We want to show that some c in ran(g) has a preimage in dom(g) and then that dom(g) = ran(f).

1044theorem comp_surj.is_surj [f g A B C : term] : (f ∈ (A ↠ B)) (g ∈ (B ↠ C))
1045    |- g ∘ f ∈ (A ↠ C)
1046proof
1047    follows g ∘ f ∈ (A → C) by composition.is_fn_on, surj_on.def;
1048    suffices ran(g ∘ f) = C by surj_on.def;
1049    follows f ∈ (A → B) ∧ ran(f) = B ∧ g ∈ (B → C) ∧ ran(g) = C by surj_on.def;
1050    hence f : Fn ∧ g : Fn by fn_on.is_fn;
1051    thus dom(f) = A ∧ dom(g) = B ∧ ran(g ∘ f) ⊆ C by fn_on.is_fn;
1052    thus f[A] = ran(f) ∧ g[B] = ran(g) ∧ (g ∘ f)[A] = ran(g ∘ f) by dom.is_ran_under_image;
1053    furthermore ∀y, y ∈ f[A] ↔ ∃z ∈ A, y = f(z) by image.def;
1054    follows ∀y, y ∈ g[B] ↔ ∃z ∈ B, y = g(z) by image.def;
1055    suffices C ⊆ ran(g ∘ f) by sub.sub_eq;
1056    suffices ∀c, c ∈ C → c ∈ ran(g ∘ f) by sub.def;
1057    arbitrary c;
1058    assume c ∈ C then c ∈ ran(g ∘ f) as
1059        obtain b st b ∈ B ∧ c = g(b) logically;
1060        obtain a st a ∈ A ∧ b = f(a) logically;
1061        thus a ∈ dom(g ∘ f) by composition.dom;
1062        follows (g ∘ f)(a) = c by composition.apply;
1063        done by image.def given a ∈ A
1064        ;
1065    done logically
1066qed

This lemma looks a bit weird, but the idea is that we want to be able to reason about where in B f has an inverse

1070lemma inj.is_bij_to_ran [f A B : term] : (f ∈ (A ↣ B))
1071    |- f ∈ (A ↔ ran(f))
1072proof
1073    suffices f ∈ (A ↣ ran(f)) by bij_on.def;
1074    suffices (f ∈ (A → ran(f))) ∧ (∀x, ∀y, x ∈ A ∧ y ∈ A ∧ f(x) = f(y) → x = y) by inj_on.def;
1075    hence f : Fn ∧ dom(f) = A by fn_on.is_fn, inj_on.def;
1076    follows ran(f) ⊆ ran(f) by sub.refl;
1077    indeed f ∈ (A → ran(f)) by fn_on.is_fn;
1078    done by inj_on.def
1079qed
1081lemma sub.has_surj [S B : term]: (S ⊆ B) (S ≠ ∅)
1082    |- ∃h, h ∈ (B ↠ S)
1083proof
1084    todo
1085qed

One of the most important properties of a bijective function is that it defines a unique bijective inverse. The proof follows cleanly from the previous inverse theorems.

1090theorem bij.has_inverse [f A B : term] : (f ∈ (A ↔ B))
1091    |- f⁻¹ ∈ (B ↔ A)
1092proof
1093    follows f⁻¹ ∈ (B → A) by inv.is_fn_on;
1094    follows dom(f) = A by bij_on.def, inj_on.def, fn_on.is_fn;
1095    follows ran(f⁻¹) = A by inv.ran given dom(f) = A;
1096    thus ∀x, ∀y, x ∈ B ∧ y ∈ B ∧ f⁻¹(x) = f⁻¹(y) → x = y as
1097        arbitrary x; arbitrary y;
1098        assume x ∈ B ∧ y ∈ B ∧ f⁻¹(x) = f⁻¹(y) then x = y as
1099            follows f(f⁻¹(x)) = x ∧ f(f⁻¹(y)) = y by inv.apply;
1100            done logically
1101            ;
1102        done logically
1103        ;
1104    follows f⁻¹ ∈ (B ↣ A) by inj_on.def;
1105    done by bij_on.def
1106qed

Here we have that an injection between sets implies the existence of a surjection the other way. We'll use this lemma later to explicitly construct this surjection. This lemma follows from the previous few where we show a surjection from B to ran(f) via sub.has_surj and ran(f) to A via bij.has_inverse as inj.is_bij_to_ran gives us a bijection between A and ran(f)

1112lemma inj.is_inv_srj [f g A B : term] : (f ∈ (A ↣ B)) (A ≠ ∅)
1113    |- ∃g, g ∈ (B ↠ A)
1114proof
1115    follows f ∈ (A → B) by inj_on.def;
1116    hence f[A] = ran(f) by dom.is_ran_under_image;
1117    suffices ∃h, ∃w, h ∈ (B ↠ ran(f)) ∧ w ∈ (ran(f) ↠ A) by comp_surj.is_surj;
1118    hence ∃w, w ∈ (ran(f) ↠ A) as
1119        follows f ∈ (A ↔ ran(f)) by inj.is_bij_to_ran;
1120        furthermore ∃w₀, w₀ ∈ (ran(f) ↔ A) by bij.has_inverse;
1121        done by bij_on.is_inj_and_surj
1122        ;
1123    furthermore ran(f) ⊆ B by fn_on.is_fn;
1124    follows ran(f) ≠ ∅ by image.def, nonempty.has_element;
1125    hence ∃h, h ∈ (B ↠ ran(f)) by sub.has_surj;
1126    done by comp_surj.is_surj
1127qed
1129theorem shroeder_bernstein [A B : term] : (∃f, f ∈ (A ↣ B)) (∃g, g ∈ (B ↣ A))
1130    |- ∃h, h ∈ (A ↔ B)
1131proof
1132    todo
1133qed

The Ordinals 3.5

36module set.ordinal

Definitions

2module set.ordinal.def

Our first goal upon the completion of our development of set theory will be to define the natural numbers. We will not develop the natural numbers directly but we will instead consider them to be certain "ordinal" numbers. So we will start by developing the ordinals.

The intuitive definition of the ordinal numbers is as follows: The empty set is an ordinal number and any set which contains every previously defined ordinal is an ordinal number. The goal is to produce a canonical set with each "number" of elements. The problem is that this definition is recursive and we will need ordinals before we can define recursion. Luckily, the ordinals admit an alternate definition. We define an ordinal as a transitive set that is well ordered by \in.

A transitive set is one where every element is also a subset.

16definition 
17    transitive(α) := ∀x ∈ α, x ⊆ α
18end
20theorem transitive.def [α : term] :
21    |- transitive(α) ↔ ∀x ∈ α, x ⊆ α
22proof
23    done by iff.refl [transitive(α)]
24qed

A well ordered set is one where every non-empty subset has a least element.

28definition
29    is_least(α, β) := α ∈ β ∧ (∀γ ∈ β, γ ≠ α → α ∈ γ)
30end
32theorem is_least.def [α β : term] :
33    |- is_least(α, β) ↔ α ∈ β ∧ (∀γ ∈ β, γ ≠ α → α ∈ γ)
34proof
35    done by iff.refl [is_least(α, β)]
36qed
38definition
39    well_ordered(α) := ∀β, β ⊆ α ∧ β ≠ ∅ → ∃γ, is_least(γ, β)
40end
42theorem well_ordered.def [α : term] :
43    |- well_ordered(α) ↔ ∀β, β ⊆ α ∧ β ≠ ∅ → ∃γ, is_least(γ, β)
44proof
45    done by iff.refl [well_ordered(α)]
46qed

The combination of these two properties is what defines an ordinal.

50definition
51    α : Ord := transitive(α) ∧ well_ordered(α)
52end
54theorem ordinal.def [α : term] :
55    |- α : Ord ↔ transitive(α) ∧ well_ordered(α)
56proof
57    done by iff.refl [α : Ord]
58qed

Since \in well orders an ordinal, we can think of \in as being << for ordinals. It would be helpful, then, to know that \in is anti-reflexive and anti-symmetric. These two properties follows by classic proofs from the axiom of regularity.

65lemma mem.irrefl [a : term] : 
66    |- a ∉ a
67proof
68    follows ∃x, x ∈ {a} by singleton.def;
69    obtain y st y ∈ {a} ∧ ¬∃z, (z ∈ y ∧ z ∈ {a}) by zfc.regularity;
70    done by singleton.def
71qed
73lemma mem.no_loop [a b : term] :
74    |- ¬(a ∈ b ∧ b ∈ a)
75proof
76    follows ∃x, x ∈ {a, b} by pair.def;
77    obtain y st y ∈ {a, b} ∧ ¬∃z, (z ∈ y ∧ z ∈ {a, b}) by zfc.regularity;
78    -- if y = a then b ∈ a ∧ b ∈ {a, b} would lead to a contradiction and 
79    -- vice versa. just let vampire work it out.
80    done by pair.def
81qed

Our First Ordinals

5module set.ordinal.basic

We are now ready for our first proof about ordinals. Recall from our intuative definition that we wanted \empty to be the first ordinal number. Another way of thinking about this is that α<β\alpha < \beta can be thought of as αβ\alpha \in \beta and any ordinal is the set of every previous ordinal. Thus, it stands to reason that the first ordinal is \empty. The proof that \empty satisfies our definition is easy; the two required properties are vacuous when applied to the empty set.

9theorem ordinal.empty.is :
10    |- ∅ : Ord
11proof
12    follows transitive(∅) as
13        suffices ∀x ∈ ∅, x ⊆ ∅ by transitive.def;
14        follows ∀x, x ∉ ∅ by empty.def;
15        done logically
16    ;
17
18    follows well_ordered(∅) as
19        suffices ∀β, β ⊆ ∅ ∧ β ≠ ∅ → ∃γ, is_least(γ, β) by well_ordered.def;
20        follows  ∀β, β ⊆ ∅ → β = ∅ by empty.sub_is_empty;
21        done logically
22    ;
23
24    thus ∅ : Ord by ordinal.def given transitive(∅) and well_ordered(∅);
25qed

The empty set is the zero of the ordinal numbers. We can get the next ordinal from any previous ordinal number by applying the successor operation. If nn is an ordinal then it is the set of all previous ordinals. So the next ordinal after nn should include all the ordinals in nn and nn itself. Hence the definition.

33definition
34    succ(n) := n ∪ {n}
35end
37theorem ordinal.succ.def [n : term] :
38    |- succ(n) = n ∪ {n}
39proof
40    done by eq.refl [succ(n)]
41qed

We can prove now that the result we get is still an ordinal. This proof isn't conceptually complicated but it has a few things to check.

46theorem ordinal.succ.is [α : term] : (α : Ord)
47    |- succ(α) : Ord
48proof
49    follows succ(α) = α ∪ {α} by ordinal.succ.def;
50    
51    follows transitive(succ(α)) as
52        suffices ∀x ∈ succ(α), x ⊆ succ(α) by transitive.def;
53        arbitrary x st x ∈ succ(α);
54
55        -- x is either from α or is α. split on which case we are in.
56        follows x ∈ α ∨ x = α by union.def, singleton.def given succ(α) = α ∪ {α};
57
58        cases:
59        | x ∈ α then
60            follows transitive(α) by ordinal.def given α : Ord;
61            thus x ⊆ α by transitive.def;
62            follows α ⊆ succ(α) by union.left_sub;
63            done by sub.trans
64        | x = α then 
65            done by union.left_sub given succ(α) = α ∪ {α}
66    ;
67
68    follows well_ordered(succ(α)) as
69        suffices ∀β, β ⊆ succ(α) ∧ β ≠ ∅ → ∃γ, is_least(γ, β) by well_ordered.def;
70        arbitrary β st β ⊆ succ(α) ∧ β ≠ ∅;
71
72        -- there are two cases. either β = {α} in which case α is the least
73        -- element or β ∩ α ≠ ∅ in which case we can use the well orderedness of
74        -- α to get a least element from it.
75        assume β = {α} then is_least(α, β) as
76            suffices α ∈ β ∧ (∀γ ∈ β, γ ≠ α → α ∈ γ);
77            follows α ∈ β          by singleton.def given β = {α};
78            follows ¬∃γ ∈ β, γ ≠ α by singleton.def;
79            done logically
80        ;
81
82        assume β ≠ {α} then ∃γ, is_least(γ, β) as
83            -- consider only the subset of β in α
84            let β' := β ∩ α;
85            follows β' ⊆ α ∧ β' ⊆ β by inter.sub_right, inter.sub_left;
86            follows β' ≠ ∅ as 
87                obtain x st x ∈ β ∧ x ≠ α as
88                    suffices ¬∀x ∈ β, x = α logically;
89                    assume ∀x ∈ β, x = α for_contra;
90                    thus β = {α} by singleton.def, nonempty.has_element, zfc.extensionality;
91                    contradiction
92                ;
93                follows x ∈ succ(α) by sub.def given β ⊆ succ(α) and x ∈ β;
94                follows x ∈ α       by ordinal.succ.def, union.def, singleton.def;
95                thus    x ∈ β'      by inter.def given x ∈ α and x ∈ β;
96                thus    β' ≠ ∅      by nonempty.has_element;
97            ;
98            -- we get the minimal element of this subset by the well ordering of α
99            follows well_ordered(α) by ordinal.def given α : Ord;
100            obtain γ st is_least(γ, β') by well_ordered.def;
101            thus γ ∈ β' ∧ (∀δ ∈ β', δ ≠ γ → γ ∈ δ) by is_least.def;
102            -- we want that this is still the least element of β
103            suffices is_least(γ, β) logically;
104            suffices γ ∈ β ∧ (∀δ ∈ β, δ ≠ γ → γ ∈ δ) by is_least.def;
105            -- it's in β just because β' ⊆ β
106            follows γ ∈ β by sub.def given γ ∈ β' and β' ⊆ β;
107            follows ∀δ ∈ β, δ ≠ γ → γ ∈ δ as
108                arbitrary δ st δ ∈ β; assume δ ≠ γ;
109                -- any element of β is either in α or is α. split on which case.
110                follows δ ∈ α ∨ δ = α by union.def, singleton.def, sub.def
111                    given δ ∈ β and β ⊆ succ(α) and succ(α) = α ∪ {α};
112
113                cases:
114                | δ ∈ α then
115                    follows δ ∈ β' by inter.def given δ ∈ β and δ ∈ α;
116                    done given ∀δ ∈ β, δ ≠ γ → γ ∈ δ
117                | δ = α then done by sub.def given γ ∈ β' and β' ⊆ α
118            ;
119
120            done logically
121        ;
122
123        done logically
124    ;
125
126    thus succ(α) : Ord by ordinal.def given transitive(succ(α)) and well_ordered(succ(α));
127qed

Properties

8module set.ordinal.props

Returning to our characterization of ordinals as sets containing every previous ordinal, we want to prove that every element of an ordinal is an ordinal. Doing this will require several new lemmas.

First we will prove that we have the trichotomy property for members of an ordinal. We will have a stronger trichotomy on all ordinals later but since we do not yet know that the elements of an ordinal are still ordinals, we cannot apply it.

10lemma ordinal.internal_trichotomy [α β γ : term] : (α : Ord) (β ∈ α) (γ ∈ α)
11    |- γ ∈ β ∨ γ = β ∨ β ∈ γ
12proof
13    follows transitive(α) ∧ well_ordered(α) by ordinal.def;
14
15    -- The idea here is that {β, γ} ⊆ α so it must have a least element.
16    follows {β, γ} ⊆ α by pair.def, sub.def given β ∈ α and γ ∈ α;
17    follows {β, γ} ≠ ∅ by pair.non_empty;
18
19    -- the least element δ must be either β or γ
20    obtain  δ st is_least(δ, {β, γ}) by well_ordered.def given well_ordered(α);
21    follows δ ∈ {β, γ}    by is_least.def given is_least(δ, {β, γ});
22    follows δ = β ∨ δ = γ by pair.def;
23
24    -- whichever one δ is it must be either equal to or in the other
25    follows ∀η ∈ {β, γ}, η ≠ δ → δ ∈ η by is_least.def given is_least(δ, {β, γ});
26    follows ∀η ∈ {β, γ}, η = δ ∨ δ ∈ η logically;
27    follows β = δ ∨ δ ∈ β by pair.def;
28    follows γ = δ ∨ δ ∈ γ by pair.def;
29
30    -- which suffices. you can check the cases on δ = β ∨ δ = γ
31    done logically
32qed

We will also need the fact that \in is transitive inside an ordinal. Again, we will have a stronger, non-internal version of this later.

37lemma ordinal.internal_trans [α β γ δ : term] : (α : Ord) (β ∈ α) (γ ∈ α) (δ ∈ α)
38    (β ∈ γ) (γ ∈ δ)
39    |- β ∈ δ
40proof
41    -- the idea here is to use the well ordering of α to find a minimal element
42    -- in {β, γ, δ}. If it is β we are happy. If it is γ we have a contradiction
43    -- from β ∈ γ and γ ∈ β. If it is δ then we have one from γ ∈ δ and δ ∈ γ.
44    let S := {β} ∪ {γ} ∪ {δ};
45    follows ∀x, x ∈ S ↔ x = β ∨ x = γ ∨ x = δ by singleton.def, union.def;
46
47    -- obtain the least element of S
48    thus S ⊆ α ∧ S ≠ ∅ by sub.def, empty.def;
49    follows well_ordered(α) by ordinal.def;
50    obtain η st is_least(η, S) by well_ordered.def;
51    thus η ∈ S by is_least.def;
52
53    cases:
54    | η = γ then 
55        follows γ ∈ β by is_least.def;
56        contradiction by mem.no_loop given β ∈ γ
57    | η = δ then 
58        follows δ ∈ γ by is_least.def;
59        contradiction by mem.no_loop given γ ∈ δ
60    | η = β then 
61        follows β ∈ δ by is_least.def;
62qed

Now we are ready for the theorem itself.

66theorem ordinal.mem.is [α β : term] : (α ∈ β) (β : Ord)
67    |- α : Ord
68proof
69    follows well_ordered(β) ∧ transitive(β) by ordinal.def;
70
71    follows transitive(α) as
72        suffices ∀x ∈ α, x ⊆ α by transitive.def;
73        arbitrary x st x ∈ α;
74        suffices ∀y ∈ x, y ∈ α by sub.def;
75        arbitrary y st y ∈ x;
76
77        follows α ⊆ β by transitive.def given transitive(β) and α ∈ β;
78        thus    x ∈ β by sub.def given x ∈ α;
79        thus    x ⊆ β by transitive.def;
80        thus    y ∈ β by sub.def;
81
82        cases by ordinal.internal_trichotomy:
83        | y ∈ α then 
84            done
85        | y = α then
86            -- we have y ∈ x ∈ α so we get α ∈ x ∈ α, a contradiction.
87            follows α ∈ x given y ∈ x;
88            contradiction by mem.no_loop given x ∈ α
89        | α ∈ y then
90            -- α ∈ y ∈ x ∈ α, also a contradiction.
91            follows α ∈ x by ordinal.internal_trans given α ∈ y and y ∈ x;
92            contradiction by mem.no_loop given x ∈ α
93    ;
94
95    follows well_ordered(α) as
96        suffices ∀δ, δ ⊆ α ∧ δ ≠ ∅ → ∃γ, is_least(γ, δ) by well_ordered.def;
97        arbitrary δ st δ ⊆ α ∧ δ ≠ ∅;
98
99        -- by the transitivity of β, α ⊆ β, so δ ⊆ β as well. and then we use
100        -- the well ordering of β. 
101        follows α ⊆ β by transitive.def given α ∈ β and transitive(β);
102        thus    δ ⊆ β by sub.trans given δ ⊆ α;
103        thus ∃γ, is_least(γ, δ) by well_ordered.def given well_ordered(β) and δ ⊆ α ∧ δ ≠ ∅;
104    ;
105
106    done by ordinal.def
107qed

With this theorem we can now make proper use of the full ordinal trichotomy, although the proof of the trichotomy does not actually rely on the members of an ordinal being in ordinal. It will, however, need two more lemmas. First, the intersection of two ordinals is an ordinal. Intuitively, the intersection is just the smaller ordinal.

115theorem ordinal.inter.is [α β : term] : (α : Ord) (β : Ord)
116    |- α ∩ β : Ord
117proof
118    follows transitive(α ∩ β) as
119        suffices ∀γ ∈ α ∩ β, γ ⊆ α ∩ β by transitive.def;
120        arbitrary γ st γ ∈ α ∩ β;
121        follows γ ∈ α ∧ γ ∈ β by inter.def;
122
123        follows γ ⊆ α by ordinal.def, transitive.def given α : Ord;
124        follows γ ⊆ β by ordinal.def, transitive.def given β : Ord;
125        thus γ ⊆ α ∩ β by inter.sub_both;
126    ;
127
128    follows well_ordered(α ∩ β) as
129        suffices ∀δ, δ ⊆ α ∩ β ∧ δ ≠ ∅ → ∃γ, is_least(γ, δ);
130        arbitrary δ st δ ⊆ α ∩ β ∧ δ ≠ ∅;
131        follows δ ⊆ α by inter.left_sub;
132        obtain γ st is_least(γ, δ) by ordinal.def, well_ordered.def;
133        done logically
134    ;
135
136    done by ordinal.def
137qed

Ordinals are transitive but they also have the inverse property: any subset is a member. Unless the subset is just the original set.

142theorem ordinal.sub_mem [α β : term] : (α : Ord) (β : Ord) (β ⊆ α)
143    |- β ∈ α ∨ β = α
144proof
145    -- we just need to show β ∈ α if β ≠ α
146    suffices β ≠ α → β ∈ α logically; assume β ≠ α;
147    
148    -- construct α - β which is a non-empty subset of α.
149    let S := α - β;
150    follows S ⊆ α by set_diff.sub;
151    follows S ≠ ∅ by set_diff.non_empty given β ≠ α;
152
153    -- we claim that the least element in S is β which suffices.
154    obtain μ st is_least(μ, S) by ordinal.def, well_ordered.def given α : Ord;
155    follows  μ ∈ S by is_least.def;
156    follows  μ ∈ α by set_diff.def;
157    follows  μ ∉ β by set_diff.def;
158    follows  μ ⊆ α by ordinal.def, transitive.def given α : Ord;
159    suffices μ = β logically;
160
161    follows μ ⊆ β as
162        suffices ∀δ ∈ μ, δ ∈ β by sub.def;
163        arbitrary δ st δ ∈ μ;
164
165        -- idea: δ must be in β because otherwise it would be in S and then we
166        -- would have μ ∈ δ and δ ∈ μ
167        assume  δ ∉ β for_contra;
168        follows δ ∈ α by sub.def given δ ∈ μ and μ ⊆ α;
169        thus    δ ∈ S by set_diff.def;
170
171        follows δ ≠ μ by mem.irrefl given δ ∈ μ;
172        thus    μ ∈ δ by is_least.def given δ ∈ S and is_least(μ, S);
173        contradiction by mem.no_loop given δ ∈ μ and μ ∈ δ
174    ;
175
176    follows β ⊆ μ as
177        suffices ∀δ ∈ β, δ ∈ μ by sub.def;
178        arbitrary δ st δ ∈ β;
179
180        -- the idea here is that μ ∉ δ because if it was then μ would be in δ
181        -- by transitivity. so then it must be that δ ∈ μ by transitivity in α
182        follows δ ≠ μ given δ ∈ β and μ ∉ β;
183        follows μ ∉ δ as
184            assume  μ ∈ δ for_contra;
185            follows δ ⊆ β by ordinal.def, transitive.def given β : Ord and δ ∈ β;
186            follows μ ∈ β by sub.def;
187            contradiction
188        ;
189
190        follows δ ∈ α by sub.def given β ⊆ α and δ ∈ β;
191        thus    δ ∈ μ by ordinal.internal_trichotomy given δ ≠ μ and μ ∉ δ;
192    ;
193
194    thus μ = β by sub.sub_eq;
195qed

With these facts we can prove the full trichotomy theorem.

199theorem ordinal.trichotomy [α β : term] : (α : Ord) (β : Ord)
200    |- α ∈ β ∨ α = β ∨ β ∈ α
201proof
202    let γ := α ∩ β;
203    follows γ : Ord by ordinal.inter.is;
204
205    -- since γ is a subset of both α and β we have that it either is or 
206    -- is a member of each
207    follows γ ⊆ α by inter.sub_left;
208    follows γ ∈ α ∨ γ = α by ordinal.sub_mem;
209    follows γ ⊆ β by inter.sub_right;
210    follows γ ∈ β ∨ γ = β by ordinal.sub_mem;
211
212    -- but it can't be a member of both because then it would be a member of itself.
213    follows ¬(γ ∈ α ∧ γ ∈ β) as
214        assume  γ ∈ α ∧ γ ∈ β for_contra;
215        thus    γ ∈ γ by inter.def;
216        contradiction by mem.irrefl
217    ;
218
219    -- so γ must be one of α and β. split on which case we are in.
220    follows γ = α ∨ γ = β logically;
221
222    cases:
223    | γ = α ∧ γ = β then 
224        follows α = β logically; 
225        done logically
226    | γ = α ∧ γ ≠ β then 
227        follows γ ∈ β given γ ∈ β ∨ γ = β;
228        thus    α ∈ β logically;
229        done logically
230    | γ ≠ α ∧ γ = β then 
231        follows γ ∈ α given γ ∈ α ∨ γ = α;
232        thus    β ∈ α logically;
233        done logically
234qed

We can also write down the full transitivity property. This is really just a restatement of transitivity.

239theorem ordinal.trans [α β γ : term] : (γ : Ord) (α ∈ β) (β ∈ γ)
240    |- α ∈ γ
241proof
242    follows β ⊆ γ by ordinal.def, transitive.def;
243    thus    α ∈ γ by sub.def;
244qed

Induction

11module set.ordinal.induction

We now arrive at one of the most important facts about ordinals. Just like the natural numbers, ordinals satisfy strong induction. (In fact, the naturals are just a special case of the ordinals). In some ways, induction is definitional. It is just another way of stating the well ordering property.

6theorem ordinal.induction [p(_) : sentence(term)] : (∀α, (α : Ord ∧ ∀β ∈ α, p(β)) → p(α))
7    |- ∀α, α : Ord → p(α)
8proof
9    -- suppose we have an ordinal such that ¬p
10    assume ¬(∀α, α : Ord → p(α)) for_contra;
11    obtain α st α : Ord ∧ ¬p(α) logically;
12
13    let s := {δ ∈ succ(α) | ¬p(δ)};
14
15    -- s is a non-empty subset of succ(α)
16    follows s ⊆ succ(α) by sub.def;
17    follows α ∈ succ(α) by ordinal.succ.def, union.def, singleton.def;
18    follows s ≠ ∅       by empty.def;
19
20    -- thus, since succ(α) is well ordered, we can find the least element.
21    follows succ(α) : Ord         by ordinal.succ.is;
22    thus    well_ordered(succ(α)) by ordinal.def;
23    obtain  μ st is_least(μ, s)   by well_ordered.def;
24
25    -- μ is an ordinal since it is in succ(α)
26    follows μ ∈ s       by is_least.def;
27    follows μ ∈ succ(α) logically;
28    follows μ : Ord     by ordinal.mem.is;
29
30    -- every member β of μ satisfies p because otherwise it would be in s.
31    follows ∀β ∈ μ, p(β) as
32        arbitrary β st β ∈ μ;
33        assume ¬p(β) for_contra;
34
35        -- we get that β is in s
36        follows μ ⊆ succ(α) by ordinal.def, transitive.def given μ ∈ succ(α);
37        thus    β ∈ succ(α) by sub.def given β ∈ μ;
38        thus    β ∈ s       given ¬p(β) and β ∈ succ(α);
39        
40        -- but then it can't be the case that β ∈ μ since μ is least in s
41        follows β ≠ μ by mem.irrefl   given β ∈ μ;
42        thus    μ ∈ β by is_least.def given β ∈ s and is_least(μ, s);
43        contradiction by mem.no_loop  given β ∈ μ and μ ∈ β
44    ;
45
46    thus     p(μ) logically;
47    follows ¬p(μ) given μ ∈ s;
48    contradiction
49qed

Sometimes we don't want something for all ordinals but just for all ordinals up to some ceiling. That version is a simple corollary.

54corollary ordinal.induction.up_to [p(_) : sentence(term)] [α : term] : (α : Ord)
55    (∀β ∈ α, (∀γ ∈ β, p(γ)) → p(β))
56    |- ∀β ∈ α, p(β)
57proof
58    suffices ∀β, β ∈ α → p(β);
59    suffices ∀β, β : Ord → (β ∈ α → p(β)) by ordinal.mem.is;
60    suffices ∀β, (β : Ord ∧ (∀γ ∈ β, γ ∈ α → p(γ))) → (β ∈ α → p(β))
61        by ordinal.induction [_ ∈ α → p(_)];
62
63    arbitrary β; 
64    assume β : Ord ∧ (∀γ ∈ β, γ ∈ α → p(γ));
65    assume β ∈ α;
66
67    follows ∀γ ∈ β, γ ∈ α by ordinal.trans;
68    follows ∀γ ∈ β, p(γ) logically;
69    thus p(β) given ∀β ∈ α, (∀γ ∈ β, p(γ)) → p(β) and β ∈ α;
70qed

Omega

14module set.ordinal.omega

As mentioned a few times, the natural numbers are a particular subset of the ordinals. Specifically, they are the ordinals that can be made by starting with the empty set and repeatedly applying the successor operation. It may not be obvious that this isn't just all the ordinals. In, fact, if we did not have the axiom of infinity this would be all the ordinals! But with the axiom of infinity we can prove the existence of a the set containing all the natural numbers. We call this set ω\omega and it is actually an ordinal itself, since it contains all previous ordinals. Since we cannot reach ω\omega using the successor operation from previous ordinals, we call it a limit ordinals.

The defining property of ω\omega is that it is the smallest set which contains \emptyset and is closed under the successor operation. We will call this closure property inductivity.

15definition
16    inductive(α) := ∅ ∈ α ∧ (∀n ∈ α, succ(n) ∈ α)
17end
19theorem inductive.def [α : term] :
20    |- inductive(α) ↔ ∅ ∈ α ∧ (∀n ∈ α, succ(n) ∈ α)
21proof
22    done by iff.refl [inductive(α)]
23qed

By the smallest set we mean that ω\omega is a subset of any inductive set. Put another way, ω\omega is the intersection of the proper class of all inductive sets. However, our theory does not contain proper classes so we cannot use the intersection operator developed previously. We can instead define ω\omega using an unrestricted comprehension.

31definition
32    ω := {x | ∀α, inductive(α) → x ∈ α}
33end

The ZF axiom of infinity guarantees that at least one inductive set exists, which is what will let us conclude that ω\omega is well defined.

38lemma inductive.exists :
39    |- ∃α, inductive(α)
40proof
41    suffices ∃α, ∅ ∈ α ∧ ∀n ∈ α, n ∪ {n} ∈ α;
42
43    -- the object whose existence is guaranteed by the axiom of infinity is the
44    -- α that we want.
45    obtain x st (∃y, y ∈ x ∧ ∀z, z ∉ y) ∧ (∀y ∈ x, ∃z ∈ x, ∀w, w ∈ z ↔ w ∈ y ∨ w = y)
46        by zfc.infinity;
47
48    -- the ∃y, y ∈ x ∧ ∀z, z ∉ y tells us that x contains ∅
49    follows ∅ ∈ x by empty.def, zfc.extensionality;
50
51    -- now we need to show that x is closed under the successor operation
52    follows ∀n ∈ x, n ∪ {n} ∈ x as
53        arbitrary n st n ∈ x;
54        obtain z st z ∈ x ∧ (∀w, w ∈ z ↔ w ∈ n ∨ w = n) logically;
55        follows ∀w, w ∈ n ∪ {n} ↔ (w ∈ n ∨ w = n) by singleton.def, union.def;
56        follows z = n ∪ {n} by zfc.extensionality;
57        thus    n ∪ {n} ∈ x logically;
58    ;
59
60    done logically
61qed

From this lemma we can deduce that ω\omega will be well defined, as it is a subset of that inductive set.

66theorem omega.def :
67    |- ∀x, x ∈ ω ↔ (∀α, inductive(α) → x ∈ α)
68proof
69    -- we have at least one inductive set. since ω is an infinite intersection
70    -- restricting the comprehension doesn't change anything. so ω' = ω.
71    obtain α st inductive(α) by inductive.exists;
72    let ω' := {x ∈ α | ∀β, inductive(β) → x ∈ β};
73
74    -- we prove that ω' has the defining property of ω
75    follows ∀y, y ∈ ω' ↔ (∀β, inductive(β) → y ∈ β) as
76        arbitrary y;
77        suffices y ∈ {x ∈ α | ∀β, inductive(β) → x ∈ β} ↔ (∀β, inductive(β) → y ∈ β);
78        assume y ∈ {x ∈ α | ∀β, inductive(β) → x ∈ β} then ∀β, inductive(β) → y ∈ β logically;
79        assume ∀β, inductive(β) → y ∈ β then y ∈ {x ∈ α | ∀β, inductive(β) → x ∈ β} as
80            follows y ∈ α given inductive(α);
81            follows y ∈ α ∧ (∀β, inductive(β) → y ∈ β) logically;
82            done logically
83        ;
84        done logically
85    ;
86
87    -- ω' proves that the infinite intersection exists, so ω is well defined
88    -- and thus has the desired property.
89    thus ∃w, ∀x, x ∈ w ↔ (∀β, inductive(β) → x ∈ β) logically;
90    thus ∀x, x ∈ ω ↔ (∀β, inductive(β) → x ∈ β) by uncomp.def [∀β, inductive(β) → _ ∈ β];
91qed

Since ω\omega is a subset of all inductive sets, it is itself inductive.

95corollary omega.sub_inductive [a : term] : (inductive(a))
96    |- ω ⊆ a
97proof
98    done by omega.def, sub.def
99qed
101corollary omega.inductive :
102    |- inductive(ω)
103proof
104    follows ∀α, inductive(α) → ∅ ∈ α by inductive.def;
105    thus                       ∅ ∈ ω by omega.def;
106
107    follows ∀n ∈ ω, succ(n) ∈ ω as
108        arbitrary n st n ∈ ω;
109        follows ∀α, inductive(α) → n ∈ α by omega.def;
110        follows ∀α, inductive(α) → succ(n) ∈ α by inductive.def;
111        thus succ(n) ∈ ω by omega.def;
112    ;
113
114    done by inductive.def
115qed

The proof that ω\omega is an ordinal is rather complex. We will observe first, as a lemma, that all the elements in ω\omega are ordinals.

120lemma omega.mem.is_ordinal [n : term] : (n ∈ ω)
121    |- n : Ord
122proof
123    let T := {n ∈ ω | n : Ord};
124    follows T ⊆ ω by comp.sub [_ : Ord] [ω];
125
126    follows ∅ : Ord by ordinal.empty.is;
127    follows ∅ ∈ ω   by omega.inductive, inductive.def;
128    thus    ∅ ∈ T   logically;
129
130    follows ∀n ∈ T, succ(n) ∈ T as
131        arbitrary n st n ∈ T;
132
133        follows n : Ord logically;
134        thus succ(n) : Ord by ordinal.succ.is;
135
136        follows n ∈ ω logically;
137        follows succ(n) ∈ ω by omega.inductive, inductive.def;
138
139        thus succ(n) ∈ T logically;
140    ;
141
142    -- thus T is inductive so ω = T and every element of T is an ordinal,
143    -- by definition, so we are done.
144    thus inductive(T) by inductive.def;
145    thus ω ⊆ T by omega.sub_inductive;
146    thus ω = T by sub.sub_eq;
147    done logically
148qed

It requires a few careful arguments to see that ω\omega is transitive and well ordered.

153theorem ordinal.omega.is :
154    |- ω : Ord
155proof
156    follows transitive(ω) as 
157        -- define the set of elements of ω that are subsets of ω. We will show
158        -- that T is inductive, thus T ⊆ ω, thus T = ω, thus ω is transitive.
159        let T := {n ∈ ω | n ⊆ ω};
160        follows T ⊆ ω by comp.sub [_ ⊆ ω] [ω];
161
162        -- T is inductive
163        follows ∅ ∈ T as
164            follows ∅ ∈ ω by omega.inductive, inductive.def;
165            follows ∅ ⊆ ω by empty.is_sub;
166            thus ∅ ∈ T logically;
167        ;
168        follows ∀n ∈ T, succ(n) ∈ T as
169            arbitrary n st n ∈ T;
170            thus n ∈ ω ∧ n ⊆ ω logically;
171            thus succ(n) ∈ ω by omega.inductive, inductive.def;
172            follows n ∪ {n} ⊆ ω as
173                suffices ∀x, x ∈ n ∪ {n} → x ∈ ω;
174                arbitrary x st x ∈ n ∪ {n};
175                follows x = n ∨ x ∈ n by union.def, singleton.def;
176                thus x ∈ ω by sub.def given n ⊆ ω and n ∈ ω;
177            ;
178            thus succ(n) ⊆ ω by ordinal.succ.def;
179            thus succ(n) ∈ T given succ(n) ∈ ω and succ(n) ⊆ ω;
180        ;
181
182        -- T = ω
183        thus inductive(T) by inductive.def;
184        thus ω ⊆ T by omega.sub_inductive;
185        thus ω = T by sub.sub_eq given T ⊆ ω and ω ⊆ T;
186
187        -- T is transitive
188        thus ∀x ∈ ω, x ⊆ ω given ω = T;
189        thus transitive(ω) by transitive.def;
190    ;
191
192    follows well_ordered(ω) as
193        suffices ∀β, β ⊆ ω ∧ β ≠ ∅ → ∃γ, is_least(γ, β) by well_ordered.def;
194        arbitrary β st β ⊆ ω ∧ β ≠ ∅;
195
196        -- idea: we restrict β to a subset of one of it's elements. we know δ+
197        -- is an ordinal so we get a least element in β ∩ δ+ ⊆ δ+ which will 
198        -- also be least in β.
199        obtain δ st δ ∈ β by nonempty.has_element;
200        let β' := β ∩ succ(δ);
201
202        -- β' is a non-empty subset of succ(δ)
203        follows β' ⊆ succ(δ) by inter.sub_right;
204        follows δ ∈ succ(δ)  by ordinal.succ.def, union.def, singleton.def;
205        thus    δ ∈ β'       by inter.def;
206        thus    β' ≠ ∅       by nonempty.has_element;
207
208        -- it follows that succ(δ) is an ordinal
209        follows β ⊆ ω given transitive(ω);
210        thus δ ∈ ω by sub.def given δ ∈ β;
211        thus δ : Ord by omega.mem.is_ordinal;
212        thus succ(δ) : Ord by ordinal.succ.is;
213
214        -- therefore can obtain a least element in β'
215        thus well_ordered(succ(δ)) by ordinal.def;
216        obtain γ st is_least(γ, β') by well_ordered.def;
217        
218        -- we want to claim γ is also least in β.
219        suffices is_least(γ, β) logically;
220
221        follows γ ∈ β' by is_least.def given is_least(γ, β');
222        follows γ ∈ β  by inter.def;
223        suffices ∀η ∈ β, η ≠ γ → γ ∈ η by is_least.def;
224
225        -- assume there was some smaller element η ∈ β.
226        arbitrary η st η ∈ β; assume η ≠ γ;
227        assume γ ∉ η for_contra;
228        follows η ∈ γ as
229            follows η ∈ ω by sub.def given η ∈ β and β ⊆ ω;
230            follows γ ∈ ω by sub.def given γ ∈ β and β ⊆ ω;
231            thus η : Ord ∧ γ : Ord by omega.mem.is_ordinal;
232            thus η ∈ γ by ordinal.trichotomy given η ≠ γ and γ ∉ η;
233        ;
234
235        -- that η would also have to be in β' since succ(δ) is transitive.
236        follows γ ∈ succ(δ) by inter.def given γ ∈ β';
237        follows γ ⊆ succ(δ) by ordinal.def, transitive.def given succ(δ) : Ord;
238        thus    η ∈ succ(δ) by sub.def given η ∈ γ;
239        thus    η ∈ β' by inter.def given η ∈ β and η ∈ succ(δ);
240
241        -- but then we have both η ∈ γ and γ ∈ η.
242        thus γ ∈ η by is_least.def given is_least(γ, β');
243        contradiction by mem.no_loop given η ∈ γ and γ ∈ η
244    ;
245
246    done by ordinal.def
247qed

Since ω\omega is an ordinal induction holds inside of it. From this we get induction on the natural numbers!

252corollary omega.induction [p(_) : sentence(term)] : (∀n ∈ ω, (∀m ∈ n, p(m)) → p(n))
253    |- ∀n ∈ ω, p(n)
254proof
255    follows ω : Ord by ordinal.omega.is;
256    done by ordinal.induction.up_to [p(_)] [ω]
257qed

Recursion

17module set.ordinal.recursion

The next thing we want to do is define operations on ordinals. In order to do this we will need recursion. It isn't obvious a priori that recursive operations are well defined. In fact, every recursive definition needs a proof to go with it. For example, f(0)=1f(0) = 1 and f(n)=nf(n1)f(n) = n \cdot f(n-1) is clearly well defined, it is the factorial function. Whereas g(0)=1g(0) = 1 and g(n)=ng(n+1)g(n) = n \cdot g(n+1) is nonsense, despite just changing a - to a ++.

In order to define a recursive function f:OrdAf : \text{Ord} \to A, we will make use of an auxiliary function g:{αOrd  αA}Ag : \{\alpha \in \text{Ord} ~|~ \alpha \to A\} \to A. The idea is that gg has the property that, for all ordinals α\alpha, f(α)=g(fα)f(\alpha) = g(f \upharpoonright \alpha), i.e. that gg produces the next value of ff given the partial function of all previous values of ff. Except, we will define gg instead of ff and use it to produce ff.

The key fact we will prove, is that if f:αAf' : \alpha \to A satisfies the property f(β)=g(fβ)f'(\beta) = g(f \upharpoonright \beta) for all βα\beta \in \alpha, then ff' is a restriction of ff. In particular f=fαf' = f \upharpoonright \alpha. Thus, we only have to find some way of identifying functions with that property, and then ff is easily defined via the union of all such functions.

We will call a function with the given property coherent (not a standard term). This property is relative to gg. Note that, since gg is a function over the whole class of ordinals, it is not a set, so we need to be slightly more verbose.

25notation sentence.with_term_of_term_and_term
26    sentence ::= @name "(" x:@binding(term) "↦" term(x) "," term ")"
27end
29definition
30    coherent(f' ↦ g(f'), f) := ∀β ∈ dom(f), f(β) = g(f ↾ β)
31end

And the theorem is that all coherent functions with the same domain are equal.

35theorem coherent.unique [g(_) : term(term)] [f₁ f₂ : term] : (f₁ : Fn) (f₂ : Fn)
36    (dom(f₁) = dom(f₂)) (dom(f₁) : Ord) (coherent(f' ↦ g(f'), f₁)) 
37    (coherent(f' ↦ g(f'), f₂))
38    |- f₁ = f₂
39proof
40    let α := dom(f₁);
41    -- to prove two functions are equal, we show they are equal on their domains.
42    suffices ∀β ∈ α, f₁(β) = f₂(β) as todo;
43    -- we can complete the proof by induction.
44    suffices ∀β ∈ α, (∀γ ∈ β, f₁(γ) = f₂(γ)) → f₁(β) = f₂(β) 
45        by ordinal.induction.up_to [f₁(_) = f₂(_)] [α]; -- todo: induction tactic
46
47    arbitrary β st β ∈ α;
48    assume ∀γ ∈ β, f₁(γ) = f₂(γ);
49
50    -- since f₁ is coherent, f₁(β) = g(f₁ ↾ β). And the same for f₂
51    follows f₁(β) = g(f₁ ↾ β) as todo;
52    follows f₂(β) = g(f₂ ↾ β) as todo;
53
54    -- but f₁ ↾ β = f₂ ↾ β so we are done.
55    follows f₁ ↾ β = f₂ ↾ β as todo; -- by fn.restriction.eq;
56    done as todo
57qed

And for each ordinal there exists a coherent function with that ordinal as its domain. This is a simple inductive argument.

62theorem coherent.exists [g(_) : term(term)] [α : term] : (α : Ord)
63    |- ∃f, dom(f) = α ∧ coherent(f' ↦ g(f'), f)
64proof
65    todo
66qed

Together, these facts let us pick the coherent function with each length. We will call this the recursive partial function with domain α\alpha.

71notation term.with_term_of_term_and_term
72    term ::= @name "(" x:@binding(term) "↦" term(x) "," term ")"
73end
75definition
76    rec.partial(f' ↦ g(f'), α) := ℩f, dom(f) = α ∧ coherent(f' ↦ g(f'), f)
77end

And this allows us to define the recursive function itself simply as the value returned by each of these partial functions.

82definition
83    rec(f' ↦ g(f'), α) := rec.partial(f' ↦ g(f'), α)(α)
84end

And we need to prove that this definition produces a recursive function with the desired property.

89theorem recursion.def [g(_) : term(term)] [α : term] : (α : Ord)
90    |- rec(f' ↦ g(f'), α) = g(β ∈ α ↦ rec(f' ↦ g(f'), β))
91proof
92    todo
93qed