Imports
import Mathlib.Tactic
import Analysis.Section_3_1
import Analysis.Section_3_2
import Analysis.Section_3_4Analysis I, Section 3.5: Cartesian products
I have attempted to make the translation as faithful a paraphrasing as possible of the original text. When there is a choice between a more idiomatic Lean solution and a more faithful translation, I have generally chosen the latter. In particular, there will be places where the Lean code could be "golfed" to be more elegant and idiomatic, but I have consciously avoided doing so.
Main constructions and results of this section:
-
Ordered pairs and n-tuples.
-
Cartesian products and n-fold products.
-
Finite choice.
-
Connections with Mathlib counterparts such as
Set.piandSet.prod.
Tips from past users
Users of the companion who have completed the exercises in this section are welcome to send their tips for future users in this section as PRs.
-
(Add tip here)
-
Definition 3.5.1 (Ordered pair). One could also have used Object × Object to
define OrderedPair here.
#check OrderedPair.extDefinition 3.5.1 (Ordered pair)
@[simp]
theorem OrderedPair.eq (x y x' y' : Object) :
(⟨ x, y ⟩ : OrderedPair) = (⟨ x', y' ⟩ : OrderedPair) ↔ x = x' ∧ y = y' := inst✝:SetTheoryx:Objecty:Objectx':Objecty':Object⊢ { fst := x, snd := y } = { fst := x', snd := y' } ↔ x = x' ∧ y = y' All goals completed! 🐙Helper lemma for Exercise 3.5.1
lemma SetTheory.Set.pair_eq_singleton_iff {a b c: Object} : {a, b} = ({c}: Set) ↔
a = c ∧ b = c := inst✝:SetTheorya:Objectb:Objectc:Object⊢ {a, b} = {c} ↔ a = c ∧ b = c
All goals completed! 🐙Exercise 3.5.1, first part
def OrderedPair.toObject : OrderedPair ↪ Object where
toFun p := ({ (({p.fst}:Set):Object), (({p.fst, p.snd}:Set):Object) }:Set)
inj' := inst✝:SetTheory⊢ Function.Injective fun p ↦
SetTheory.set_to_object {SetTheory.set_to_object {p.fst}, SetTheory.set_to_object {p.fst, p.snd}} All goals completed! 🐙instance OrderedPair.inst_coeObject : Coe OrderedPair Object where
coe := toObject
A technical operation, turning a object x and a set Y to a set {x} × Y, needed to define
the full Cartesian product
abbrev SetTheory.Set.slice (x:Object) (Y:Set) : Set :=
Y.replace (P := fun y z ↦ z = (⟨x, y⟩:OrderedPair)) (inst✝:SetTheoryx:ObjectY:Set⊢ ∀ (x_1 : Y.toSubtype) (y y' : Object),
(fun y z ↦ z = OrderedPair.toObject { fst := x, snd := ↑y }) x_1 y ∧
(fun y z ↦ z = OrderedPair.toObject { fst := x, snd := ↑y }) x_1 y' →
y = y' All goals completed! 🐙)@[simp]
theorem SetTheory.Set.mem_slice (x z:Object) (Y:Set) :
z ∈ (SetTheory.Set.slice x Y) ↔ ∃ y:Y, z = (⟨x, y⟩:OrderedPair) := replacement_axiom _ _Definition 3.5.4 (Cartesian product)
abbrev SetTheory.Set.cartesian (X Y:Set) : Set :=
union (X.replace (P := fun x z ↦ z = slice x Y) (inst✝:SetTheoryX:SetY:Set⊢ ∀ (x : X.toSubtype) (y y' : Object),
(fun x z ↦ z = set_to_object (slice (↑x) Y)) x y ∧ (fun x z ↦ z = set_to_object (slice (↑x) Y)) x y' → y = y' intro _ inst✝:SetTheoryX:SetY:Setx✝:X.toSubtypey✝:Object⊢ ∀ (y' : Object),
(fun x z ↦ z = set_to_object (slice (↑x) Y)) x✝ y✝ ∧ (fun x z ↦ z = set_to_object (slice (↑x) Y)) x✝ y' → y✝ = y' inst✝:SetTheoryX:SetY:Setx✝:X.toSubtypey✝:Objecty'✝:Object⊢ (fun x z ↦ z = set_to_object (slice (↑x) Y)) x✝ y✝ ∧ (fun x z ↦ z = set_to_object (slice (↑x) Y)) x✝ y'✝ → y✝ = y'✝ inst✝:SetTheoryX:SetY:Setx✝:X.toSubtypey✝:Objecty'✝:Objecth1:(fun x z ↦ z = set_to_object (slice (↑x) Y)) x✝ y✝h2:(fun x z ↦ z = set_to_object (slice (↑x) Y)) x✝ y'✝⊢ y✝ = y'✝; All goals completed! 🐙))This instance enables the ×ˢ notation for Cartesian product.
example (X Y:Set) : X ×ˢ Y = SetTheory.Set.cartesian X Y := rfl@[simp]
theorem SetTheory.Set.mem_cartesian (z:Object) (X Y:Set) :
z ∈ X ×ˢ Y ↔ ∃ x:X, ∃ y:Y, z = (⟨x, y⟩:OrderedPair) := inst✝:SetTheoryz:ObjectX:SetY:Set⊢ z ∈ X ×ˢ Y ↔ ∃ x y, z = OrderedPair.toObject { fst := ↑x, snd := ↑y }
inst✝:SetTheoryz:ObjectX:SetY:Set⊢ (∃ S, z ∈ S ∧ set_to_object S ∈ X.replace ⋯) ↔ ∃ x y, z = OrderedPair.toObject { fst := ↑x, snd := ↑y }; inst✝:SetTheoryz:ObjectX:SetY:Set⊢ (∃ S, z ∈ S ∧ set_to_object S ∈ X.replace ⋯) → ∃ x y, z = OrderedPair.toObject { fst := ↑x, snd := ↑y }inst✝:SetTheoryz:ObjectX:SetY:Set⊢ (∃ x y, z = OrderedPair.toObject { fst := ↑x, snd := ↑y }) → ∃ S, z ∈ S ∧ set_to_object S ∈ X.replace ⋯
inst✝:SetTheoryz:ObjectX:SetY:Set⊢ (∃ S, z ∈ S ∧ set_to_object S ∈ X.replace ⋯) → ∃ x y, z = OrderedPair.toObject { fst := ↑x, snd := ↑y } inst✝:SetTheoryz:ObjectX:SetY:SetS:Sethz:z ∈ ShS:set_to_object S ∈ X.replace ⋯⊢ ∃ x y, z = OrderedPair.toObject { fst := ↑x, snd := ↑y }; inst✝:SetTheoryz:ObjectX:SetY:SetS:Sethz:z ∈ ShS:∃ x, set_to_object S = set_to_object (slice (↑x) Y)⊢ ∃ x y, z = OrderedPair.toObject { fst := ↑x, snd := ↑y }; inst✝:SetTheoryz:ObjectX:SetY:SetS:Sethz:z ∈ Sx:X.toSubtypehx:set_to_object S = set_to_object (slice (↑x) Y)⊢ ∃ x y, z = OrderedPair.toObject { fst := ↑x, snd := ↑y }
inst✝:SetTheoryz:ObjectX:SetY:SetS:Sethz:z ∈ Sx:X.toSubtypehx:set_to_object S = set_to_object (slice (↑x) Y)⊢ ∃ y, z = OrderedPair.toObject { fst := ↑x, snd := ↑y }; All goals completed! 🐙
inst✝:SetTheoryX:SetY:Setx:X.toSubtypey:Y.toSubtype⊢ ∃ S, OrderedPair.toObject { fst := ↑x, snd := ↑y } ∈ S ∧ set_to_object S ∈ X.replace ⋯; inst✝:SetTheoryX:SetY:Setx:X.toSubtypey:Y.toSubtype⊢ OrderedPair.toObject { fst := ↑x, snd := ↑y } ∈ slice (↑x) Y ∧ set_to_object (slice (↑x) Y) ∈ X.replace ⋯; refine ⟨ inst✝:SetTheoryX:SetY:Setx:X.toSubtypey:Y.toSubtype⊢ OrderedPair.toObject { fst := ↑x, snd := ↑y } ∈ slice (↑x) Y All goals completed! 🐙, ?_ ⟩
inst✝:SetTheoryX:SetY:Setx:X.toSubtypey:Y.toSubtype⊢ ∃ x_1, set_to_object (slice (↑x) Y) = set_to_object (slice (↑x_1) Y); All goals completed! 🐙noncomputable abbrev SetTheory.Set.fst {X Y:Set} (z:X ×ˢ Y) : X :=
((mem_cartesian _ _ _).mp z.property).choosenoncomputable abbrev SetTheory.Set.snd {X Y:Set} (z:X ×ˢ Y) : Y :=
(exists_comm.mp ((mem_cartesian _ _ _).mp z.property)).choosetheorem SetTheory.Set.pair_eq_fst_snd {X Y:Set} (z:X ×ˢ Y) :
z.val = (⟨ fst z, snd z ⟩:OrderedPair) := inst✝:SetTheoryX:SetY:Setz:(X ×ˢ Y).toSubtype⊢ ↑z = OrderedPair.toObject { fst := ↑(fst z), snd := ↑(snd z) }
inst✝:SetTheoryX:SetY:Setz:(X ×ˢ Y).toSubtypethis:∃ x y, ↑z = OrderedPair.toObject { fst := ↑x, snd := ↑y }⊢ ↑z = OrderedPair.toObject { fst := ↑(fst z), snd := ↑(snd z) }
inst✝:SetTheoryX:SetY:Setz:(X ×ˢ Y).toSubtypethis:∃ x y, ↑z = OrderedPair.toObject { fst := ↑x, snd := ↑y }y:Y.toSubtypehy:↑z = OrderedPair.toObject { fst := ↑(fst z), snd := ↑y }⊢ ↑z = OrderedPair.toObject { fst := ↑(fst z), snd := ↑(snd z) }
inst✝:SetTheoryX:SetY:Setz:(X ×ˢ Y).toSubtypethis:∃ x y, ↑z = OrderedPair.toObject { fst := ↑x, snd := ↑y }y:Y.toSubtypehy:↑z = OrderedPair.toObject { fst := ↑(fst z), snd := ↑y }x:X.toSubtypehx:↑z = OrderedPair.toObject { fst := ↑x, snd := ↑(snd z) }⊢ ↑z = OrderedPair.toObject { fst := ↑(fst z), snd := ↑(snd z) }
All goals completed! 🐙
This equips an OrderedPair with proofs that x ∈ X and y ∈ Y.
def SetTheory.Set.mk_cartesian {X Y:Set} (x:X) (y:Y) : X ×ˢ Y :=
⟨(⟨ x, y ⟩:OrderedPair), inst✝:SetTheoryX:SetY:Setx:X.toSubtypey:Y.toSubtype⊢ OrderedPair.toObject { fst := ↑x, snd := ↑y } ∈ X ×ˢ Y All goals completed! 🐙⟩@[simp]
theorem SetTheory.Set.fst_of_mk_cartesian {X Y:Set} (x:X) (y:Y) :
fst (mk_cartesian x y) = x := inst✝:SetTheoryX:SetY:Setx:X.toSubtypey:Y.toSubtype⊢ fst (mk_cartesian x y) = x
inst✝:SetTheoryX:SetY:Setx:X.toSubtypey:Y.toSubtypez:(X ×ˢ Y).toSubtype := mk_cartesian x y⊢ fst (mk_cartesian x y) = x; inst✝:SetTheoryX:SetY:Setx:X.toSubtypey:Y.toSubtypez:(X ×ˢ Y).toSubtype := mk_cartesian x ythis:∃ x y, ↑z = OrderedPair.toObject { fst := ↑x, snd := ↑y }⊢ fst (mk_cartesian x y) = x
inst✝:SetTheoryX:SetY:Setx:X.toSubtypey:Y.toSubtypez:(X ×ˢ Y).toSubtype := mk_cartesian x ythis:∃ x y, ↑z = OrderedPair.toObject { fst := ↑x, snd := ↑y }y':Y.toSubtypehy:↑z = OrderedPair.toObject { fst := ↑(fst z), snd := ↑y' }⊢ fst (mk_cartesian x y) = x
inst✝:SetTheoryX:SetY:Setx:X.toSubtypey:Y.toSubtypez:(X ×ˢ Y).toSubtype := mk_cartesian x yy':Y.toSubtypethis:Truehy:x = fst ⟨OrderedPair.toObject { fst := ↑x, snd := ↑y }, ⋯⟩ ∧ y = y'⊢ fst ⟨OrderedPair.toObject { fst := ↑x, snd := ↑y }, ⋯⟩ = x; All goals completed! 🐙@[simp]
theorem SetTheory.Set.snd_of_mk_cartesian {X Y:Set} (x:X) (y:Y) :
snd (mk_cartesian x y) = y := inst✝:SetTheoryX:SetY:Setx:X.toSubtypey:Y.toSubtype⊢ snd (mk_cartesian x y) = y
inst✝:SetTheoryX:SetY:Setx:X.toSubtypey:Y.toSubtypez:(X ×ˢ Y).toSubtype := mk_cartesian x y⊢ snd (mk_cartesian x y) = y; inst✝:SetTheoryX:SetY:Setx:X.toSubtypey:Y.toSubtypez:(X ×ˢ Y).toSubtype := mk_cartesian x ythis:∃ x y, ↑z = OrderedPair.toObject { fst := ↑x, snd := ↑y }⊢ snd (mk_cartesian x y) = y
inst✝:SetTheoryX:SetY:Setx:X.toSubtypey:Y.toSubtypez:(X ×ˢ Y).toSubtype := mk_cartesian x ythis:∃ x y, ↑z = OrderedPair.toObject { fst := ↑x, snd := ↑y }x':X.toSubtypehx:↑z = OrderedPair.toObject { fst := ↑x', snd := ↑(snd z) }⊢ snd (mk_cartesian x y) = y
inst✝:SetTheoryX:SetY:Setx:X.toSubtypey:Y.toSubtypez:(X ×ˢ Y).toSubtype := mk_cartesian x yx':X.toSubtypethis:Truehx:x = x' ∧ y = snd ⟨OrderedPair.toObject { fst := ↑x, snd := ↑y }, ⋯⟩⊢ snd ⟨OrderedPair.toObject { fst := ↑x, snd := ↑y }, ⋯⟩ = y; All goals completed! 🐙@[simp]
theorem SetTheory.Set.mk_cartesian_fst_snd_eq {X Y: Set} (z: X ×ˢ Y) :
(mk_cartesian (fst z) (snd z)) = z := inst✝:SetTheoryX:SetY:Setz:(X ×ˢ Y).toSubtype⊢ mk_cartesian (fst z) (snd z) = z
All goals completed! 🐙
Connections with the Mathlib set product, which consists of Lean pairs like (x, y)
equipped with a proof that x is in the left set, and y is in the right set.
Lean pairs like (x, y) are similar to our OrderedPair, but more general.
noncomputable abbrev SetTheory.Set.prod_equiv_prod (X Y:Set) :
((X ×ˢ Y):_root_.Set Object) ≃ (X:_root_.Set Object) ×ˢ (Y:_root_.Set Object) where
toFun z := ⟨(fst z, snd z), inst✝:SetTheoryX:SetY:Setz:↑{x | x ∈ X ×ˢ Y}⊢ (↑(fst z), ↑(snd z)) ∈ {x | x ∈ X} ×ˢ {x | x ∈ Y} All goals completed! 🐙⟩
invFun z := mk_cartesian ⟨z.val.1, z.prop.1⟩ ⟨z.val.2, z.prop.2⟩
left_inv _ := inst✝:SetTheoryX:SetY:Setx✝:↑{x | x ∈ X ×ˢ Y}⊢ (fun z ↦ mk_cartesian ⟨(↑z).1, ⋯⟩ ⟨(↑z).2, ⋯⟩) ((fun z ↦ ⟨(↑(fst z), ↑(snd z)), ⋯⟩) x✝) = x✝ All goals completed! 🐙
right_inv _ := inst✝:SetTheoryX:SetY:Setx✝:↑({x | x ∈ X} ×ˢ {x | x ∈ Y})⊢ (fun z ↦ ⟨(↑(fst z), ↑(snd z)), ⋯⟩) ((fun z ↦ mk_cartesian ⟨(↑z).1, ⋯⟩ ⟨(↑z).2, ⋯⟩) x✝) = x✝ All goals completed! 🐙/-- Example 3.5.5 -/
example : ({1, 2}: Set) ×ˢ ({3, 4, 5}: Set) = ({
((mk_cartesian (1: Nat) (3: Nat)): Object),
((mk_cartesian (1: Nat) (4: Nat)): Object),
((mk_cartesian (1: Nat) (5: Nat)): Object),
((mk_cartesian (2: Nat) (3: Nat)): Object),
((mk_cartesian (2: Nat) (4: Nat)): Object),
((mk_cartesian (2: Nat) (5: Nat)): Object)
}: Set) := inst✝:SetTheory⊢ {1, 2} ×ˢ {3, 4, 5} =
{↑(mk_cartesian 1 3), ↑(mk_cartesian 1 4), ↑(mk_cartesian 1 5), ↑(mk_cartesian 2 3), ↑(mk_cartesian 2 4),
↑(mk_cartesian 2 5)} inst✝:SetTheoryx✝:Object⊢ x✝ ∈ {1, 2} ×ˢ {3, 4, 5} ↔
x✝ ∈
{↑(mk_cartesian 1 3), ↑(mk_cartesian 1 4), ↑(mk_cartesian 1 5), ↑(mk_cartesian 2 3), ↑(mk_cartesian 2 4),
↑(mk_cartesian 2 5)}; All goals completed! 🐙
Example 3.5.5 / Exercise 3.6.5. There is a bijection between X ×ˢ Y and Y ×ˢ X.
noncomputable abbrev SetTheory.Set.prod_commutator (X Y:Set) : X ×ˢ Y ≃ Y ×ˢ X where
toFun := sorry
invFun := sorry
left_inv := sorry
right_inv := sorryExample 3.5.5. A function of two variables can be thought of as a function of a pair.
noncomputable abbrev SetTheory.Set.curry_equiv {X Y Z:Set} : (X → Y → Z) ≃ (X ×ˢ Y → Z) where
toFun f z := f (fst z) (snd z)
invFun f x y := f (mk_cartesian x y)
left_inv _ := inst✝:SetTheoryX:SetY:SetZ:Setx✝:X.toSubtype → Y.toSubtype → Z.toSubtype⊢ (fun f x y ↦ f (mk_cartesian x y)) ((fun f z ↦ f (fst z) (snd z)) x✝) = x✝ inst✝:SetTheoryX:SetY:SetZ:Setx✝²:X.toSubtype → Y.toSubtype → Z.toSubtypex✝¹:X.toSubtypex✝:Y.toSubtype⊢ ↑((fun f x y ↦ f (mk_cartesian x y)) ((fun f z ↦ f (fst z) (snd z)) x✝²) x✝¹ x✝) = ↑(x✝² x✝¹ x✝); All goals completed! 🐙
right_inv _ := inst✝:SetTheoryX:SetY:SetZ:Setx✝:(X ×ˢ Y).toSubtype → Z.toSubtype⊢ (fun f z ↦ f (fst z) (snd z)) ((fun f x y ↦ f (mk_cartesian x y)) x✝) = x✝ All goals completed! 🐙
Definition 3.5.6. The indexing set I plays the role of { i : 1 ≤ i ≤ n } in the text.
See Exercise 3.5.10 below for some connections betweeen this concept and the preceding notion
of Cartesian product and ordered pair.
abbrev SetTheory.Set.tuple {I:Set} {X: I → Set} (x: ∀ i, X i) : Object :=
((fun i ↦ ⟨ x i, inst✝:SetTheoryI:SetX:I.toSubtype → Setx:(i : I.toSubtype) → (X i).toSubtypei:I.toSubtype⊢ ↑(x i) ∈ I.iUnion X inst✝:SetTheoryI:SetX:I.toSubtype → Setx:(i : I.toSubtype) → (X i).toSubtypei:I.toSubtype⊢ ∃ α, ↑(x i) ∈ X α; inst✝:SetTheoryI:SetX:I.toSubtype → Setx:(i : I.toSubtype) → (X i).toSubtypei:I.toSubtype⊢ ↑(x i) ∈ X i; All goals completed! 🐙 ⟩):I → iUnion I X)Definition 3.5.6
abbrev SetTheory.Set.iProd {I: Set} (X: I → Set) : Set :=
((iUnion I X)^I).specify (fun t ↦ ∃ x : ∀ i, X i, t = tuple x)Definition 3.5.6
theorem SetTheory.Set.mem_iProd {I: Set} {X: I → Set} (t:Object) :
t ∈ iProd X ↔ ∃ x: ∀ i, X i, t = tuple x := inst✝:SetTheoryI:SetX:I.toSubtype → Sett:Object⊢ t ∈ iProd X ↔ ∃ x, t = tuple x
inst✝:SetTheoryI:SetX:I.toSubtype → Sett:Object⊢ (∃ (_ : t ∈ I.iUnion X ^ I), ∃ x, t = tuple x) ↔ ∃ x, t = tuple x; inst✝:SetTheoryI:SetX:I.toSubtype → Sett:Object⊢ (∃ (_ : t ∈ I.iUnion X ^ I), ∃ x, t = tuple x) → ∃ x, t = tuple xinst✝:SetTheoryI:SetX:I.toSubtype → Sett:Object⊢ (∃ x, t = tuple x) → ∃ (_ : t ∈ I.iUnion X ^ I), ∃ x, t = tuple x
inst✝:SetTheoryI:SetX:I.toSubtype → Sett:Object⊢ (∃ (_ : t ∈ I.iUnion X ^ I), ∃ x, t = tuple x) → ∃ x, t = tuple x inst✝:SetTheoryI:SetX:I.toSubtype → Sett:Objectht:t ∈ I.iUnion X ^ Ix:(i : I.toSubtype) → (X i).toSubtypeh:t = tuple x⊢ ∃ x, t = tuple x; All goals completed! 🐙
inst✝:SetTheoryI:SetX:I.toSubtype → Sett:Objectx:(i : I.toSubtype) → (X i).toSubtypehx:t = tuple x⊢ ∃ (_ : t ∈ I.iUnion X ^ I), ∃ x, t = tuple x
have h : t ∈ (I.iUnion X)^I := inst✝:SetTheoryI:SetX:I.toSubtype → Sett:Object⊢ t ∈ iProd X ↔ ∃ x, t = tuple x All goals completed! 🐙
All goals completed! 🐙theorem SetTheory.Set.tuple_mem_iProd {I: Set} {X: I → Set} (x: ∀ i, X i) :
tuple x ∈ iProd X := inst✝:SetTheoryI:SetX:I.toSubtype → Setx:(i : I.toSubtype) → (X i).toSubtype⊢ tuple x ∈ iProd X inst✝:SetTheoryI:SetX:I.toSubtype → Setx:(i : I.toSubtype) → (X i).toSubtype⊢ ∃ x_1, tuple x = tuple x_1; All goals completed! 🐙@[simp]
theorem SetTheory.Set.tuple_inj {I:Set} {X: I → Set} (x y: ∀ i, X i) :
tuple x = tuple y ↔ x = y := inst✝:SetTheoryI:SetX:I.toSubtype → Setx:(i : I.toSubtype) → (X i).toSubtypey:(i : I.toSubtype) → (X i).toSubtype⊢ tuple x = tuple y ↔ x = y All goals completed! 🐙
Example 3.5.8. There is a bijection between (X ×ˢ Y) ×ˢ Z and X ×ˢ (Y ×ˢ Z).
noncomputable abbrev SetTheory.Set.prod_associator (X Y Z:Set) : (X ×ˢ Y) ×ˢ Z ≃ X ×ˢ (Y ×ˢ Z) where
toFun p := mk_cartesian (fst (fst p)) (mk_cartesian (snd (fst p)) (snd p))
invFun p := mk_cartesian (mk_cartesian (fst p) (fst (snd p))) (snd (snd p))
left_inv _ := inst✝:SetTheoryX:SetY:SetZ:Setx✝:((X ×ˢ Y) ×ˢ Z).toSubtype⊢ (fun p ↦ mk_cartesian (mk_cartesian (fst p) (fst (snd p))) (snd (snd p)))
((fun p ↦ mk_cartesian (fst (fst p)) (mk_cartesian (snd (fst p)) (snd p))) x✝) =
x✝ All goals completed! 🐙
right_inv _ := inst✝:SetTheoryX:SetY:SetZ:Setx✝:(X ×ˢ Y ×ˢ Z).toSubtype⊢ (fun p ↦ mk_cartesian (fst (fst p)) (mk_cartesian (snd (fst p)) (snd p)))
((fun p ↦ mk_cartesian (mk_cartesian (fst p) (fst (snd p))) (snd (snd p))) x✝) =
x✝ All goals completed! 🐙Example 3.5.10. I suspect most of the equivalences will require classical reasoning and only be defined non-computably, but would be happy to learn of counterexamples.
noncomputable abbrev SetTheory.Set.singleton_iProd_equiv (i:Object) (X:Set) :
iProd (fun _:({i}:Set) ↦ X) ≃ X where
toFun := sorry
invFun := sorry
left_inv := sorry
right_inv := sorryExample 3.5.10
abbrev SetTheory.Set.empty_iProd_equiv (X: (∅:Set) → Set) : iProd X ≃ Unit where
toFun := sorry
invFun := sorry
left_inv := sorry
right_inv := sorryExample 3.5.10
noncomputable abbrev SetTheory.Set.iProd_of_const_equiv (I:Set) (X: Set) :
iProd (fun _:I ↦ X) ≃ (I → X) where
toFun := sorry
invFun := sorry
left_inv := sorry
right_inv := sorryExample 3.5.10
noncomputable abbrev SetTheory.Set.iProd_equiv_prod (X: ({0,1}:Set) → Set) :
iProd X ≃ (X ⟨ 0, inst✝:SetTheoryX:{0, 1}.toSubtype → Set⊢ 0 ∈ {0, 1} All goals completed! 🐙 ⟩) ×ˢ (X ⟨ 1, inst✝:SetTheoryX:{0, 1}.toSubtype → Set⊢ 1 ∈ {0, 1} All goals completed! 🐙 ⟩) where
toFun := sorry
invFun := sorry
left_inv := sorry
right_inv := sorryExample 3.5.10
noncomputable abbrev SetTheory.Set.iProd_equiv_prod_triple (X: ({0,1,2}:Set) → Set) :
iProd X ≃ (X ⟨ 0, inst✝:SetTheoryX:{0, 1, 2}.toSubtype → Set⊢ 0 ∈ {0, 1, 2} All goals completed! 🐙 ⟩) ×ˢ (X ⟨ 1, inst✝:SetTheoryX:{0, 1, 2}.toSubtype → Set⊢ 1 ∈ {0, 1, 2} All goals completed! 🐙 ⟩) ×ˢ (X ⟨ 2, inst✝:SetTheoryX:{0, 1, 2}.toSubtype → Set⊢ 2 ∈ {0, 1, 2} All goals completed! 🐙 ⟩) where
toFun := sorry
invFun := sorry
left_inv := sorry
right_inv := sorry
Connections with Mathlib's Set.pi
noncomputable abbrev SetTheory.Set.iProd_equiv_pi (I:Set) (X: I → Set) :
iProd X ≃ Set.pi .univ (fun i:I ↦ ((X i):_root_.Set Object)) where
toFun t := ⟨fun i ↦ ((mem_iProd _).mp t.property).choose i, inst✝:SetTheoryI:SetX:I.toSubtype → Sett:(iProd X).toSubtype⊢ (fun i ↦ ↑(⋯.choose i)) ∈ Set.univ.pi fun i ↦ {x | x ∈ X i} All goals completed! 🐙⟩
invFun x :=
⟨tuple fun i ↦ ⟨x.val i, inst✝:SetTheoryI:SetX:I.toSubtype → Setx:↑(Set.univ.pi fun i ↦ {x | x ∈ X i})i:I.toSubtype⊢ ↑x i ∈ ?m.43 x i inst✝:SetTheoryI:SetX:I.toSubtype → Setx:↑(Set.univ.pi fun i ↦ {x | x ∈ X i})i:I.toSubtypethis:i ∈ Set.univ → ↑x i ∈ (fun i ↦ {x | x ∈ X i}) i⊢ ↑x i ∈ ?m.43 x i; All goals completed! 🐙⟩, inst✝:SetTheoryI:SetX:I.toSubtype → Setx:↑(Set.univ.pi fun i ↦ {x | x ∈ X i})⊢ (tuple fun i ↦ ⟨↑x i, ⋯⟩) ∈ iProd X All goals completed! 🐙⟩
left_inv t := inst✝:SetTheoryI:SetX:I.toSubtype → Sett:(iProd X).toSubtype⊢ (fun x ↦ ⟨tuple fun i ↦ ⟨↑x i, ⋯⟩, ⋯⟩) ((fun t ↦ ⟨fun i ↦ ↑(⋯.choose i), ⋯⟩) t) = t inst✝:SetTheoryI:SetX:I.toSubtype → Sett:(iProd X).toSubtype⊢ ↑((fun x ↦ ⟨tuple fun i ↦ ⟨↑x i, ⋯⟩, ⋯⟩) ((fun t ↦ ⟨fun i ↦ ↑(⋯.choose i), ⋯⟩) t)) = ↑t; All goals completed! 🐙
right_inv x := inst✝:SetTheoryI:SetX:I.toSubtype → Setx:↑(Set.univ.pi fun i ↦ {x | x ∈ X i})⊢ (fun t ↦ ⟨fun i ↦ ↑(⋯.choose i), ⋯⟩) ((fun x ↦ ⟨tuple fun i ↦ ⟨↑x i, ⋯⟩, ⋯⟩) x) = x
inst✝:SetTheoryI:SetX:I.toSubtype → Setx:↑(Set.univ.pi fun i ↦ {x | x ∈ X i})x✝:I.toSubtype⊢ ↑((fun t ↦ ⟨fun i ↦ ↑(⋯.choose i), ⋯⟩) ((fun x ↦ ⟨tuple fun i ↦ ⟨↑x i, ⋯⟩, ⋯⟩) x)) x✝ = ↑x x✝; inst✝:SetTheoryI:SetX:I.toSubtype → Setx:↑(Set.univ.pi fun i ↦ {x | x ∈ X i})x✝:I.toSubtype⊢ ↑(⋯.choose x✝) = ↑x x✝
inst✝:SetTheoryI:SetX:I.toSubtype → Setx:↑(Set.univ.pi fun i ↦ {x | x ∈ X i})x✝:I.toSubtypepf✝:∀ (i : I.toSubtype), ↑x i ∈ X ih:∃ x_1, (tuple fun i ↦ ⟨↑x i, ⋯⟩) = tuple x_1⊢ ↑(h.choose x✝) = ↑x x✝
All goals completed! 🐙
Here we set up some an analogue of Mathlib Fin n types within the Chapter 3 Set Theory,
with rudimentary API.
/-
remark: there are also additional relations between these equivalences, but this begins to drift
into the field of higher order category theory, which we will not pursue here.
-/
abbrev SetTheory.Set.Fin (n:ℕ) : Set := nat.specify (fun m ↦ (m:ℕ) < n)theorem SetTheory.Set.mem_Fin (n:ℕ) (x:Object) : x ∈ Fin n ↔ ∃ m, m < n ∧ x = m := inst✝:SetTheoryn:ℕx:Object⊢ x ∈ Fin n ↔ ∃ m < n, x = ↑m
inst✝:SetTheoryn:ℕx:Object⊢ (∃ (h : x ∈ nat), nat_equiv.symm ⟨x, h⟩ < n) ↔ ∃ m < n, x = ↑m; inst✝:SetTheoryn:ℕx:Object⊢ (∃ (h : x ∈ nat), nat_equiv.symm ⟨x, h⟩ < n) → ∃ m < n, x = ↑minst✝:SetTheoryn:ℕx:Object⊢ (∃ m < n, x = ↑m) → ∃ (h : x ∈ nat), nat_equiv.symm ⟨x, h⟩ < n
inst✝:SetTheoryn:ℕx:Object⊢ (∃ (h : x ∈ nat), nat_equiv.symm ⟨x, h⟩ < n) → ∃ m < n, x = ↑m inst✝:SetTheoryn:ℕx:Objecth1:x ∈ nath2:nat_equiv.symm ⟨x, h1⟩ < n⊢ ∃ m < n, x = ↑m; inst✝:SetTheoryn:ℕx:Objecth1:x ∈ nath2:nat_equiv.symm ⟨x, h1⟩ < n⊢ nat_equiv.symm ⟨x, h1⟩ < n ∧ x = ↑(nat_equiv.symm ⟨x, h1⟩); All goals completed! 🐙
inst✝:SetTheoryn:ℕx:Objectm:ℕhm:m < nh:x = ↑m⊢ ∃ (h : x ∈ nat), nat_equiv.symm ⟨x, h⟩ < n
use (inst✝:SetTheoryn:ℕx:Objectm:ℕhm:m < nh:x = ↑m⊢ x ∈ nat inst✝:SetTheoryn:ℕx:Objectm:ℕhm:m < nh:x = ↑m⊢ ↑↑m ∈ nat; All goals completed! 🐙)
All goals completed! 🐙abbrev SetTheory.Set.Fin_mk (n m:ℕ) (h: m < n): Fin n := ⟨ m, inst✝:SetTheoryn:ℕm:ℕh:m < n⊢ ↑m ∈ Fin n inst✝:SetTheoryn:ℕm:ℕh:m < n⊢ ∃ m_1 < n, ↑m = ↑m_1; All goals completed! 🐙 ⟩theorem SetTheory.Set.mem_Fin' {n:ℕ} (x:Fin n) : ∃ m, ∃ h : m < n, x = Fin_mk n m h := inst✝:SetTheoryn:ℕx:(Fin n).toSubtype⊢ ∃ m, ∃ (h : m < n), x = Fin_mk n m h
inst✝:SetTheoryn:ℕx:(Fin n).toSubtypem:ℕhm:m < nthis:↑x = ↑m⊢ ∃ m, ∃ (h : m < n), x = Fin_mk n m h; inst✝:SetTheoryn:ℕx:(Fin n).toSubtypem:ℕhm:m < nthis:↑x = ↑m⊢ x = Fin_mk n m hm
All goals completed! 🐙@[coe]
noncomputable abbrev SetTheory.Set.Fin.toNat {n:ℕ} (i: Fin n) : ℕ := (mem_Fin' i).choosenoncomputable instance SetTheory.Set.Fin.inst_coeNat {n:ℕ} : CoeOut (Fin n) ℕ where
coe := toNattheorem SetTheory.Set.Fin.toNat_spec {n:ℕ} (i: Fin n) :
∃ h : i < n, i = Fin_mk n i h := (mem_Fin' i).choose_spectheorem SetTheory.Set.Fin.toNat_lt {n:ℕ} (i: Fin n) : i < n := (toNat_spec i).choose@[simp]
theorem SetTheory.Set.Fin.coe_toNat {n:ℕ} (i: Fin n) : ((i:ℕ):Object) = (i:Object) := inst✝:SetTheoryn:ℕi:(Fin n).toSubtype⊢ ↑↑i = ↑i
inst✝:SetTheoryn:ℕi:(Fin n).toSubtypej:ℕ := ↑i⊢ ↑j = ↑i; inst✝:SetTheoryn:ℕi:(Fin n).toSubtypej:ℕ := ↑ih:↑i < nh':i = Fin_mk n j h⊢ ↑j = ↑i; All goals completed! 🐙@[simp low]
lemma SetTheory.Set.Fin.coe_inj {n:ℕ} {i j: Fin n} : i = j ↔ (i:ℕ) = (j:ℕ) := inst✝:SetTheoryn:ℕi:(Fin n).toSubtypej:(Fin n).toSubtype⊢ i = j ↔ ↑i = ↑j
inst✝:SetTheoryn:ℕi:(Fin n).toSubtypej:(Fin n).toSubtype⊢ i = j → ↑i = ↑jinst✝:SetTheoryn:ℕi:(Fin n).toSubtypej:(Fin n).toSubtype⊢ ↑i = ↑j → i = j
inst✝:SetTheoryn:ℕi:(Fin n).toSubtypej:(Fin n).toSubtype⊢ i = j → ↑i = ↑j All goals completed! 🐙
inst✝:SetTheoryn:ℕi:(Fin n).toSubtypej:(Fin n).toSubtypew✝:↑i < nhi:i = Fin_mk n (↑i) w✝⊢ ↑i = ↑j → i = j
inst✝:SetTheoryn:ℕi:(Fin n).toSubtypej:(Fin n).toSubtypew✝¹:↑i < nhi:i = Fin_mk n (↑i) w✝w✝:↑j < nhj:j = Fin_mk n (↑j) w✝⊢ ↑i = ↑j → i = j
All goals completed! 🐙@[simp]
theorem SetTheory.Set.Fin.coe_eq_iff {n:ℕ} (i: Fin n) {j:ℕ} : (i:Object) = (j:Object) ↔ i = j := inst✝:SetTheoryn:ℕi:(Fin n).toSubtypej:ℕ⊢ ↑i = ↑j ↔ ↑i = j
inst✝:SetTheoryn:ℕi:(Fin n).toSubtypej:ℕ⊢ ↑i = ↑j → ↑i = jinst✝:SetTheoryn:ℕi:(Fin n).toSubtypej:ℕ⊢ ↑i = j → ↑i = ↑j
inst✝:SetTheoryn:ℕi:(Fin n).toSubtypej:ℕ⊢ ↑i = ↑j → ↑i = j inst✝:SetTheoryn:ℕi:(Fin n).toSubtypej:ℕh:↑i = ↑j⊢ ↑i = j
inst✝:SetTheoryn:ℕi:(Fin n).toSubtypej:ℕh:∃ (h : ↑j ∈ Fin n), i = ⟨↑j, h⟩⊢ ↑i = j
inst✝:SetTheoryn:ℕj:ℕw✝:↑j ∈ Fin n⊢ ↑⟨↑j, w✝⟩ = j
All goals completed! 🐙
All goals completed! 🐙@[simp]
theorem SetTheory.Set.Fin.coe_eq_iff' {n m:ℕ} (i: Fin n) (hi : ↑i ∈ Fin m) : ((⟨i, hi⟩ : Fin m):ℕ) = (i:ℕ) := inst✝:SetTheoryn:ℕm:ℕi:(Fin n).toSubtypehi:↑i ∈ Fin m⊢ ↑⟨↑i, hi⟩ = ↑i
inst✝:SetTheoryn:ℕm:ℕval:Objectproperty:val ∈ Fin nhi:↑⟨val, property⟩ ∈ Fin m⊢ ↑⟨↑⟨val, property⟩, hi⟩ = ↑⟨val, property⟩
inst✝:SetTheoryn:ℕm:ℕval:Objectproperty:val ∈ Fin nhi:↑⟨val, property⟩ ∈ Fin m⊢ ⋯.choose = ⋯.choose
inst✝:SetTheoryn:ℕm:ℕval:Objectproperty:val ∈ Fin nhi:↑⟨val, property⟩ ∈ Fin mh1:∃ m_1 < m, val = ↑m_1h2:∃ m < n, val = ↑m⊢ h1.choose = h2.choose
inst✝:SetTheoryn:ℕm:ℕval:Objectproperty:val ∈ Fin nhi:↑⟨val, property⟩ ∈ Fin mh1:∃ m_1 < m, val = ↑m_1h2:∃ m < n, val = ↑mthis:↑h1.choose = ↑h2.choose⊢ h1.choose = h2.chooseinst✝:SetTheoryn:ℕm:ℕval:Objectproperty:val ∈ Fin nhi:↑⟨val, property⟩ ∈ Fin mh1:∃ m_1 < m, val = ↑m_1h2:∃ m < n, val = ↑m⊢ ↑h1.choose = ↑h2.choose
inst✝:SetTheoryn:ℕm:ℕval:Objectproperty:val ∈ Fin nhi:↑⟨val, property⟩ ∈ Fin mh1:∃ m_1 < m, val = ↑m_1h2:∃ m < n, val = ↑mthis:↑h1.choose = ↑h2.choose⊢ h1.choose = h2.choose All goals completed! 🐙
inst✝:SetTheoryn:ℕm:ℕval:Objectproperty:val ∈ Fin nhi:↑⟨val, property⟩ ∈ Fin mh1:∃ m_1 < m, val = ↑m_1h2:∃ m < n, val = ↑mthis:h1.choose < m ∧ val = ↑h1.choose⊢ ↑h1.choose = ↑h2.choose
inst✝:SetTheoryn:ℕm:ℕval:Objectproperty:val ∈ Fin nhi:↑⟨val, property⟩ ∈ Fin mh1:∃ m_1 < m, val = ↑m_1h2:∃ m < n, val = ↑mthis✝:h1.choose < m ∧ val = ↑h1.choosethis:h2.choose < n ∧ val = ↑h2.choose⊢ ↑h1.choose = ↑h2.choose
All goals completed! 🐙@[simp]
theorem SetTheory.Set.Fin.toNat_mk {n:ℕ} (m:ℕ) (h: m < n) : (Fin_mk n m h : ℕ) = m := inst✝:SetTheoryn:ℕm:ℕh:m < n⊢ ↑(Fin_mk n m h) = m
inst✝:SetTheoryn:ℕm:ℕh:m < nthis:↑↑(Fin_mk n m h) = ↑(Fin_mk n m h)⊢ ↑(Fin_mk n m h) = m
rwa [Object.natCast_injinst✝:SetTheoryn:ℕm:ℕh:m < nthis:↑(Fin_mk n m h) = m⊢ ↑(Fin_mk n m h) = m at thisabbrev SetTheory.Set.Fin_embed (n N:ℕ) (h: n ≤ N) (i: Fin n) : Fin N := ⟨ i.val, inst✝:SetTheoryn:ℕN:ℕh:n ≤ Ni:(Fin n).toSubtype⊢ ↑i ∈ Fin N
inst✝:SetTheoryn:ℕN:ℕh:n ≤ Ni:(Fin n).toSubtypethis:↑i ∈ Fin n⊢ ↑i ∈ Fin N; inst✝:SetTheoryn:ℕN:ℕh:n ≤ Ni:(Fin n).toSubtypethis:∃ m < n, ↑i = ↑m⊢ ∃ m < N, ↑i = ↑m; All goals completed! 🐙
⟩
Connections with Mathlib's Fin n
noncomputable abbrev SetTheory.Set.Fin.Fin_equiv_Fin (n:ℕ) : Fin n ≃ _root_.Fin n where
toFun m := _root_.Fin.mk m (toNat_lt m)
invFun m := Fin_mk n m.val m.isLt
left_inv m := (toNat_spec m).2.symm
right_inv m := inst✝:SetTheoryn:ℕm:_root_.Fin n⊢ (fun m ↦ ⟨↑m, ⋯⟩) ((fun m ↦ Fin_mk n ↑m ⋯) m) = m All goals completed! 🐙Lemma 3.5.11 (finite choice)
theorem SetTheory.Set.finite_choice {n:ℕ} {X: Fin n → Set} (h: ∀ i, X i ≠ ∅) : iProd X ≠ ∅ := inst✝:SetTheoryn:ℕX:(Fin n).toSubtype → Seth:∀ (i : (Fin n).toSubtype), X i ≠ ∅⊢ iProd X ≠ ∅
-- This proof broadly follows the one in the text
-- (although it is more convenient to induct from 0 rather than 1)
inst✝:SetTheoryX:(Fin 0).toSubtype → Seth:∀ (i : (Fin 0).toSubtype), X i ≠ ∅⊢ iProd X ≠ ∅inst✝:SetTheoryn:ℕhn:∀ {X : (Fin n).toSubtype → Set}, (∀ (i : (Fin n).toSubtype), X i ≠ ∅) → iProd X ≠ ∅X:(Fin (n + 1)).toSubtype → Seth:∀ (i : (Fin (n + 1)).toSubtype), X i ≠ ∅⊢ iProd X ≠ ∅
inst✝:SetTheoryX:(Fin 0).toSubtype → Seth:∀ (i : (Fin 0).toSubtype), X i ≠ ∅⊢ iProd X ≠ ∅ have : Fin 0 = ∅ := inst✝:SetTheoryn:ℕX:(Fin n).toSubtype → Seth:∀ (i : (Fin n).toSubtype), X i ≠ ∅⊢ iProd X ≠ ∅
inst✝:SetTheoryX:(Fin 0).toSubtype → Seth:∀ (i : (Fin 0).toSubtype), X i ≠ ∅⊢ ∀ (x : Object), x ∉ Fin 0
All goals completed! 🐙
have empty (i:Fin 0) : X i := False.elim (inst✝:SetTheoryX:(Fin 0).toSubtype → Seth:∀ (i : (Fin 0).toSubtype), X i ≠ ∅this:Fin 0 = ∅i:(Fin 0).toSubtype⊢ False inst✝:SetTheoryX:(Fin 0).toSubtype → Seth:∀ (i : (Fin 0).toSubtype), X i ≠ ∅this:Fin 0 = ∅i:∅.toSubtype⊢ False; All goals completed! 🐙)
inst✝:SetTheoryX:(Fin 0).toSubtype → Seth:∀ (i : (Fin 0).toSubtype), X i ≠ ∅this:Fin 0 = ∅empty:(i : (Fin 0).toSubtype) → (X i).toSubtype⊢ tuple empty ∈ iProd X; inst✝:SetTheoryX:(Fin 0).toSubtype → Seth:∀ (i : (Fin 0).toSubtype), X i ≠ ∅this:Fin 0 = ∅empty:(i : (Fin 0).toSubtype) → (X i).toSubtype⊢ ∃ x, tuple empty = tuple x; All goals completed! 🐙
set X' : Fin n → Set := fun i ↦ X (Fin_embed n (n+1) (inst✝:SetTheoryn:ℕhn:∀ {X : (Fin n).toSubtype → Set}, (∀ (i : (Fin n).toSubtype), X i ≠ ∅) → iProd X ≠ ∅X:(Fin (n + 1)).toSubtype → Seth:∀ (i : (Fin (n + 1)).toSubtype), X i ≠ ∅i:(Fin n).toSubtype⊢ n ≤ n + 1 All goals completed! 🐙) i)
inst✝:SetTheoryn:ℕhn:∀ {X : (Fin n).toSubtype → Set}, (∀ (i : (Fin n).toSubtype), X i ≠ ∅) → iProd X ≠ ∅X:(Fin (n + 1)).toSubtype → Seth:∀ (i : (Fin (n + 1)).toSubtype), X i ≠ ∅X':(Fin n).toSubtype → Set := fun i ↦ X (Fin_embed n (n + 1) ⋯ i)hX':∀ (i : (Fin n).toSubtype), X' i ≠ ∅⊢ iProd X ≠ ∅
inst✝:SetTheoryn:ℕhn:∀ {X : (Fin n).toSubtype → Set}, (∀ (i : (Fin n).toSubtype), X i ≠ ∅) → iProd X ≠ ∅X:(Fin (n + 1)).toSubtype → Seth:∀ (i : (Fin (n + 1)).toSubtype), X i ≠ ∅X':(Fin n).toSubtype → Set := fun i ↦ X (Fin_embed n (n + 1) ⋯ i)hX':∀ (i : (Fin n).toSubtype), X' i ≠ ∅x'_obj:Objecthx':x'_obj ∈ iProd X'⊢ iProd X ≠ ∅
inst✝:SetTheoryn:ℕhn:∀ {X : (Fin n).toSubtype → Set}, (∀ (i : (Fin n).toSubtype), X i ≠ ∅) → iProd X ≠ ∅X:(Fin (n + 1)).toSubtype → Seth:∀ (i : (Fin (n + 1)).toSubtype), X i ≠ ∅X':(Fin n).toSubtype → Set := fun i ↦ X (Fin_embed n (n + 1) ⋯ i)hX':∀ (i : (Fin n).toSubtype), X' i ≠ ∅x'_obj:Objecthx':∃ x, x'_obj = tuple x⊢ iProd X ≠ ∅; inst✝:SetTheoryn:ℕhn:∀ {X : (Fin n).toSubtype → Set}, (∀ (i : (Fin n).toSubtype), X i ≠ ∅) → iProd X ≠ ∅X:(Fin (n + 1)).toSubtype → Seth:∀ (i : (Fin (n + 1)).toSubtype), X i ≠ ∅X':(Fin n).toSubtype → Set := fun i ↦ X (Fin_embed n (n + 1) ⋯ i)hX':∀ (i : (Fin n).toSubtype), X' i ≠ ∅x':(i : (Fin n).toSubtype) → (X' i).toSubtype⊢ iProd X ≠ ∅
set last : Fin (n+1) := Fin_mk (n+1) n (inst✝:SetTheoryn:ℕhn:∀ {X : (Fin n).toSubtype → Set}, (∀ (i : (Fin n).toSubtype), X i ≠ ∅) → iProd X ≠ ∅X:(Fin (n + 1)).toSubtype → Seth:∀ (i : (Fin (n + 1)).toSubtype), X i ≠ ∅X':(Fin n).toSubtype → Set := fun i ↦ X (Fin_embed n (n + 1) ⋯ i)hX':∀ (i : (Fin n).toSubtype), X' i ≠ ∅x':(i : (Fin n).toSubtype) → (X' i).toSubtype⊢ n < n + 1 All goals completed! 🐙)
inst✝:SetTheoryn:ℕhn:∀ {X : (Fin n).toSubtype → Set}, (∀ (i : (Fin n).toSubtype), X i ≠ ∅) → iProd X ≠ ∅X:(Fin (n + 1)).toSubtype → Seth:∀ (i : (Fin (n + 1)).toSubtype), X i ≠ ∅X':(Fin n).toSubtype → Set := fun i ↦ X (Fin_embed n (n + 1) ⋯ i)hX':∀ (i : (Fin n).toSubtype), X' i ≠ ∅x':(i : (Fin n).toSubtype) → (X' i).toSubtypelast:(Fin (n + 1)).toSubtype := Fin_mk (n + 1) n ⋯a:Objectha:a ∈ X last⊢ iProd X ≠ ∅
have x : ∀ i, X i := fun i =>
if h : i = n then
have : i = last := inst✝:SetTheoryn:ℕhn:∀ {X : (Fin n).toSubtype → Set}, (∀ (i : (Fin n).toSubtype), X i ≠ ∅) → iProd X ≠ ∅X:(Fin (n + 1)).toSubtype → Seth✝:∀ (i : (Fin (n + 1)).toSubtype), X i ≠ ∅X':(Fin n).toSubtype → Set := fun i ↦ X (Fin_embed n (n + 1) ⋯ i)hX':∀ (i : (Fin n).toSubtype), X' i ≠ ∅x':(i : (Fin n).toSubtype) → (X' i).toSubtypelast:(Fin (n + 1)).toSubtype := Fin_mk (n + 1) n ⋯a:Objectha:a ∈ X lasti:(Fin (n + 1)).toSubtypeh:↑i = n⊢ i = last inst✝:SetTheoryn:ℕhn:∀ {X : (Fin n).toSubtype → Set}, (∀ (i : (Fin n).toSubtype), X i ≠ ∅) → iProd X ≠ ∅X:(Fin (n + 1)).toSubtype → Seth✝:∀ (i : (Fin (n + 1)).toSubtype), X i ≠ ∅X':(Fin n).toSubtype → Set := fun i ↦ X (Fin_embed n (n + 1) ⋯ i)hX':∀ (i : (Fin n).toSubtype), X' i ≠ ∅x':(i : (Fin n).toSubtype) → (X' i).toSubtypelast:(Fin (n + 1)).toSubtype := Fin_mk (n + 1) n ⋯a:Objectha:a ∈ X lasti:(Fin (n + 1)).toSubtypeh:↑i = n⊢ ↑i = ↑last; All goals completed! 🐙
⟨a, inst✝:SetTheoryn:ℕhn:∀ {X : (Fin n).toSubtype → Set}, (∀ (i : (Fin n).toSubtype), X i ≠ ∅) → iProd X ≠ ∅X:(Fin (n + 1)).toSubtype → Seth✝:∀ (i : (Fin (n + 1)).toSubtype), X i ≠ ∅X':(Fin n).toSubtype → Set := fun i ↦ X (Fin_embed n (n + 1) ⋯ i)hX':∀ (i : (Fin n).toSubtype), X' i ≠ ∅x':(i : (Fin n).toSubtype) → (X' i).toSubtypelast:(Fin (n + 1)).toSubtype := Fin_mk (n + 1) n ⋯a:Objectha:a ∈ X lasti:(Fin (n + 1)).toSubtypeh:↑i = nthis:i = last⊢ a ∈ X i All goals completed! 🐙⟩
else
have : i < n := lt_of_le_of_ne (Nat.lt_succ_iff.mp (Fin.toNat_lt i)) h
let i' := Fin_mk n i this
have : X i = X' i' := inst✝:SetTheoryn:ℕhn:∀ {X : (Fin n).toSubtype → Set}, (∀ (i : (Fin n).toSubtype), X i ≠ ∅) → iProd X ≠ ∅X:(Fin (n + 1)).toSubtype → Seth✝:∀ (i : (Fin (n + 1)).toSubtype), X i ≠ ∅X':(Fin n).toSubtype → Set := fun i ↦ X (Fin_embed n (n + 1) ⋯ i)hX':∀ (i : (Fin n).toSubtype), X' i ≠ ∅x':(i : (Fin n).toSubtype) → (X' i).toSubtypelast:(Fin (n + 1)).toSubtype := Fin_mk (n + 1) n ⋯a:Objectha:a ∈ X lasti:(Fin (n + 1)).toSubtypeh:¬↑i = nthis:↑i < ni':(Fin n).toSubtype := Fin_mk n (↑i) this⊢ X i = X' i' All goals completed! 🐙
⟨x' i', inst✝:SetTheoryn:ℕhn:∀ {X : (Fin n).toSubtype → Set}, (∀ (i : (Fin n).toSubtype), X i ≠ ∅) → iProd X ≠ ∅X:(Fin (n + 1)).toSubtype → Seth✝:∀ (i : (Fin (n + 1)).toSubtype), X i ≠ ∅X':(Fin n).toSubtype → Set := fun i ↦ X (Fin_embed n (n + 1) ⋯ i)hX':∀ (i : (Fin n).toSubtype), X' i ≠ ∅x':(i : (Fin n).toSubtype) → (X' i).toSubtypelast:(Fin (n + 1)).toSubtype := Fin_mk (n + 1) n ⋯a:Objectha:a ∈ X lasti:(Fin (n + 1)).toSubtypeh:¬↑i = nthis✝:↑i < ni':(Fin n).toSubtype := Fin_mk n (↑i) thisthis:X i = X' i'⊢ ↑(x' i') ∈ X i All goals completed! 🐙⟩
All goals completed! 🐙Exercise 3.5.1, second part (requires axiom of regularity)
abbrev OrderedPair.toObject' : OrderedPair ↪ Object where
toFun p := ({ p.fst, (({p.fst, p.snd}:Set):Object) }:Set)
inj' := inst✝:SetTheory⊢ Function.Injective fun p ↦ SetTheory.set_to_object {p.fst, SetTheory.set_to_object {p.fst, p.snd}} All goals completed! 🐙An alternate definition of a tuple, used in Exercise 3.5.2
Custom extensionality lemma for Exercise 3.5.2.
Placing @[ext] on the structure would generate a lemma requiring proof of t.x = t'.x,
but these functions have different types when t.X ≠ t'.X. This lemma handles that part.
@[ext]
lemma SetTheory.Set.Tuple.ext {n:ℕ} {t t':Tuple n}
(hX : t.X = t'.X)
(hx : ∀ n : Fin n, ((t.x n):Object) = ((t'.x n):Object)) :
t = t' := inst✝:SetTheoryn:ℕt:Tuple nt':Tuple nhX:t.X = t'.Xhx:∀ (n_1 : (Fin n).toSubtype), ↑(t.x n_1) = ↑(t'.x n_1)⊢ t = t'
inst✝:SetTheoryn:ℕt:Tuple nt':Tuple nX✝:Setx✝:(Fin n).toSubtype → X✝.toSubtypesurj✝:Function.Surjective x✝hX:{ X := X✝, x := x✝, surj := surj✝ }.X = t'.Xhx:∀ (n_1 : (Fin n).toSubtype), ↑({ X := X✝, x := x✝, surj := surj✝ }.x n_1) = ↑(t'.x n_1)⊢ { X := X✝, x := x✝, surj := surj✝ } = t'; inst✝:SetTheoryn:ℕt:Tuple nt':Tuple nX✝¹:Setx✝¹:(Fin n).toSubtype → X✝.toSubtypesurj✝¹:Function.Surjective x✝X✝:Setx✝:(Fin n).toSubtype → X✝.toSubtypesurj✝:Function.Surjective x✝hX:{ X := X✝¹, x := x✝¹, surj := surj✝¹ }.X = { X := X✝, x := x✝, surj := surj✝ }.Xhx:∀ (n_1 : (Fin n).toSubtype),
↑({ X := X✝¹, x := x✝¹, surj := surj✝¹ }.x n_1) = ↑({ X := X✝, x := x✝, surj := surj✝ }.x n_1)⊢ { X := X✝¹, x := x✝¹, surj := surj✝¹ } = { X := X✝, x := x✝, surj := surj✝ }; inst✝:SetTheoryn:ℕt:Tuple nt':Tuple nX✝:Setx✝¹:(Fin n).toSubtype → X✝.toSubtypesurj✝¹:Function.Surjective x✝x✝:(Fin n).toSubtype → { X := X✝, x := x✝¹, surj := surj✝¹ }.X.toSubtypesurj✝:Function.Surjective x✝hx:∀ (n_1 : (Fin n).toSubtype),
↑({ X := X✝, x := x✝¹, surj := surj✝¹ }.x n_1) =
↑({ X := { X := X✝, x := x✝¹, surj := surj✝¹ }.X, x := x✝, surj := surj✝ }.x n_1)⊢ { X := X✝, x := x✝¹, surj := surj✝¹ } = { X := { X := X✝, x := x✝¹, surj := surj✝¹ }.X, x := x✝, surj := surj✝ }; inst✝:SetTheoryn:ℕt:Tuple nt':Tuple nX✝:Setx✝¹:(Fin n).toSubtype → X✝.toSubtypesurj✝¹:Function.Surjective x✝x✝:(Fin n).toSubtype → { X := X✝, x := x✝¹, surj := surj✝¹ }.X.toSubtypesurj✝:Function.Surjective x✝hx:∀ (n_1 : (Fin n).toSubtype),
↑({ X := X✝, x := x✝¹, surj := surj✝¹ }.x n_1) =
↑({ X := { X := X✝, x := x✝¹, surj := surj✝¹ }.X, x := x✝, surj := surj✝ }.x n_1)⊢ x✝¹ = x✝; inst✝:SetTheoryn:ℕt:Tuple nt':Tuple nX✝:Setx✝²:(Fin n).toSubtype → X✝.toSubtypesurj✝¹:Function.Surjective x✝x✝¹:(Fin n).toSubtype → { X := X✝, x := x✝¹, surj := surj✝¹ }.X.toSubtypesurj✝:Function.Surjective x✝hx:∀ (n_1 : (Fin n).toSubtype),
↑({ X := X✝, x := x✝¹, surj := surj✝¹ }.x n_1) =
↑({ X := { X := X✝, x := x✝¹, surj := surj✝¹ }.X, x := x✝, surj := surj✝ }.x n_1)x✝:(Fin n).toSubtype⊢ ↑(x✝² x✝) = ↑(x✝¹ x✝); All goals completed! 🐙Exercise 3.5.2
theorem SetTheory.Set.Tuple.eq {n:ℕ} (t t':Tuple n) :
t = t' ↔ ∀ n : Fin n, ((t.x n):Object) = ((t'.x n):Object) := inst✝:SetTheoryn:ℕt:Tuple nt':Tuple n⊢ t = t' ↔ ∀ (n_1 : (Fin n).toSubtype), ↑(t.x n_1) = ↑(t'.x n_1) All goals completed! 🐙noncomputable abbrev SetTheory.Set.iProd_equiv_tuples (n:ℕ) (X: Fin n → Set) :
iProd X ≃ { t:Tuple n // ∀ i, (t.x i:Object) ∈ X i } where
toFun := sorry
invFun := sorry
left_inv := sorry
right_inv := sorry
Exercise 3.5.3. The spirit here is to avoid direct rewrites (which make all of these claims
trivial), and instead use OrderedPair.eq or SetTheory.Set.tuple_inj
theorem OrderedPair.refl (p: OrderedPair) : p = p := inst✝:SetTheoryp:OrderedPair⊢ p = p All goals completed! 🐙theorem OrderedPair.symm (p q: OrderedPair) : p = q ↔ q = p := inst✝:SetTheoryp:OrderedPairq:OrderedPair⊢ p = q ↔ q = p All goals completed! 🐙theorem OrderedPair.trans {p q r: OrderedPair} (hpq: p=q) (hqr: q=r) : p=r := inst✝:SetTheoryp:OrderedPairq:OrderedPairr:OrderedPairhpq:p = qhqr:q = r⊢ p = r All goals completed! 🐙theorem SetTheory.Set.tuple_refl {I:Set} {X: I → Set} (a: ∀ i, X i) :
tuple a = tuple a := inst✝:SetTheoryI:SetX:I.toSubtype → Seta:(i : I.toSubtype) → (X i).toSubtype⊢ tuple a = tuple a All goals completed! 🐙theorem SetTheory.Set.tuple_symm {I:Set} {X: I → Set} (a b: ∀ i, X i) :
tuple a = tuple b ↔ tuple b = tuple a := inst✝:SetTheoryI:SetX:I.toSubtype → Seta:(i : I.toSubtype) → (X i).toSubtypeb:(i : I.toSubtype) → (X i).toSubtype⊢ tuple a = tuple b ↔ tuple b = tuple a All goals completed! 🐙theorem SetTheory.Set.tuple_trans {I:Set} {X: I → Set} {a b c: ∀ i, X i}
(hab: tuple a = tuple b) (hbc : tuple b = tuple c) :
tuple a = tuple c := inst✝:SetTheoryI:SetX:I.toSubtype → Seta:(i : I.toSubtype) → (X i).toSubtypeb:(i : I.toSubtype) → (X i).toSubtypec:(i : I.toSubtype) → (X i).toSubtypehab:tuple a = tuple bhbc:tuple b = tuple c⊢ tuple a = tuple c All goals completed! 🐙Exercise 3.5.4
theorem SetTheory.Set.prod_union (A B C:Set) : A ×ˢ (B ∪ C) = (A ×ˢ B) ∪ (A ×ˢ C) := inst✝:SetTheoryA:SetB:SetC:Set⊢ A ×ˢ (B ∪ C) = A ×ˢ B ∪ A ×ˢ C All goals completed! 🐙Exercise 3.5.4
theorem SetTheory.Set.prod_inter (A B C:Set) : A ×ˢ (B ∩ C) = (A ×ˢ B) ∩ (A ×ˢ C) := inst✝:SetTheoryA:SetB:SetC:Set⊢ A ×ˢ (B ∩ C) = A ×ˢ B ∩ A ×ˢ C All goals completed! 🐙Exercise 3.5.4
theorem SetTheory.Set.prod_diff (A B C:Set) : A ×ˢ (B \ C) = (A ×ˢ B) \ (A ×ˢ C) := inst✝:SetTheoryA:SetB:SetC:Set⊢ A ×ˢ (B \ C) = A ×ˢ B \ A ×ˢ C All goals completed! 🐙Exercise 3.5.4
theorem SetTheory.Set.union_prod (A B C:Set) : (A ∪ B) ×ˢ C = (A ×ˢ C) ∪ (B ×ˢ C) := inst✝:SetTheoryA:SetB:SetC:Set⊢ (A ∪ B) ×ˢ C = A ×ˢ C ∪ B ×ˢ C All goals completed! 🐙Exercise 3.5.4
theorem SetTheory.Set.inter_prod (A B C:Set) : (A ∩ B) ×ˢ C = (A ×ˢ C) ∩ (B ×ˢ C) := inst✝:SetTheoryA:SetB:SetC:Set⊢ (A ∩ B) ×ˢ C = A ×ˢ C ∩ B ×ˢ C All goals completed! 🐙Exercise 3.5.4
theorem SetTheory.Set.diff_prod (A B C:Set) : (A \ B) ×ˢ C = (A ×ˢ C) \ (B ×ˢ C) := inst✝:SetTheoryA:SetB:SetC:Set⊢ (A \ B) ×ˢ C = A ×ˢ C \ B ×ˢ C All goals completed! 🐙Exercise 3.5.5
theorem SetTheory.Set.inter_of_prod (A B C D:Set) :
(A ×ˢ B) ∩ (C ×ˢ D) = (A ∩ C) ×ˢ (B ∩ D) := inst✝:SetTheoryA:SetB:SetC:SetD:Set⊢ A ×ˢ B ∩ C ×ˢ D = (A ∩ C) ×ˢ (B ∩ D) All goals completed! 🐙/- Exercise 3.5.5 -/
def SetTheory.Set.union_of_prod :
Decidable (∀ (A B C D:Set), (A ×ˢ B) ∪ (C ×ˢ D) = (A ∪ C) ×ˢ (B ∪ D)) := inst✝:SetTheory⊢ Decidable (∀ (A B C D : Set), A ×ˢ B ∪ C ×ˢ D = (A ∪ C) ×ˢ (B ∪ D))
-- the first line of this construction should be `apply isTrue` or `apply isFalse`.
All goals completed! 🐙/- Exercise 3.5.5 -/
def SetTheory.Set.diff_of_prod :
Decidable (∀ (A B C D:Set), (A ×ˢ B) \ (C ×ˢ D) = (A \ C) ×ˢ (B \ D)) := inst✝:SetTheory⊢ Decidable (∀ (A B C D : Set), A ×ˢ B \ C ×ˢ D = (A \ C) ×ˢ (B \ D))
-- the first line of this construction should be `apply isTrue` or `apply isFalse`.
All goals completed! 🐙Exercise 3.5.6.
theorem SetTheory.Set.prod_subset_prod {A B C D:Set}
(hA: A ≠ ∅) (hB: B ≠ ∅) (hC: C ≠ ∅) (hD: D ≠ ∅) :
A ×ˢ B ⊆ C ×ˢ D ↔ A ⊆ C ∧ B ⊆ D := inst✝:SetTheoryA:SetB:SetC:SetD:SethA:A ≠ ∅hB:B ≠ ∅hC:C ≠ ∅hD:D ≠ ∅⊢ A ×ˢ B ⊆ C ×ˢ D ↔ A ⊆ C ∧ B ⊆ D All goals completed! 🐙def SetTheory.Set.prod_subset_prod' :
Decidable (∀ (A B C D:Set), A ×ˢ B ⊆ C ×ˢ D ↔ A ⊆ C ∧ B ⊆ D) := inst✝:SetTheory⊢ Decidable (∀ (A B C D : Set), A ×ˢ B ⊆ C ×ˢ D ↔ A ⊆ C ∧ B ⊆ D)
-- the first line of this construction should be `apply isTrue` or `apply isFalse`.
All goals completed! 🐙Exercise 3.5.7
theorem SetTheory.Set.direct_sum {X Y Z:Set} (f: Z → X) (g: Z → Y) :
∃! h: Z → X ×ˢ Y, fst ∘ h = f ∧ snd ∘ h = g := inst✝:SetTheoryX:SetY:SetZ:Setf:Z.toSubtype → X.toSubtypeg:Z.toSubtype → Y.toSubtype⊢ ∃! h, fst ∘ h = f ∧ snd ∘ h = g All goals completed! 🐙Exercise 3.5.8
@[simp]
theorem SetTheory.Set.iProd_empty_iff {n:ℕ} {X: Fin n → Set} :
iProd X = ∅ ↔ ∃ i, X i = ∅ := inst✝:SetTheoryn:ℕX:(Fin n).toSubtype → Set⊢ iProd X = ∅ ↔ ∃ i, X i = ∅ All goals completed! 🐙Exercise 3.5.9
theorem SetTheory.Set.iUnion_inter_iUnion {I J: Set} (A: I → Set) (B: J → Set) :
(iUnion I A) ∩ (iUnion J B) = iUnion (I ×ˢ J) (fun p ↦ (A (fst p)) ∩ (B (snd p))) := inst✝:SetTheoryI:SetJ:SetA:I.toSubtype → SetB:J.toSubtype → Set⊢ I.iUnion A ∩ J.iUnion B = (I ×ˢ J).iUnion fun p ↦ A (fst p) ∩ B (snd p) All goals completed! 🐙abbrev SetTheory.Set.graph {X Y:Set} (f: X → Y) : Set :=
(X ×ˢ Y).specify (fun p ↦ (f (fst p) = snd p))Exercise 3.5.10
theorem SetTheory.Set.graph_inj {X Y:Set} (f f': X → Y) :
graph f = graph f' ↔ f = f' := inst✝:SetTheoryX:SetY:Setf:X.toSubtype → Y.toSubtypef':X.toSubtype → Y.toSubtype⊢ graph f = graph f' ↔ f = f' All goals completed! 🐙theorem SetTheory.Set.is_graph {X Y G:Set} (hG: G ⊆ X ×ˢ Y)
(hvert: ∀ x:X, ∃! y:Y, ((⟨x,y⟩:OrderedPair):Object) ∈ G) :
∃! f: X → Y, G = graph f := inst✝:SetTheoryX:SetY:SetG:SethG:G ⊆ X ×ˢ Yhvert:∀ (x : X.toSubtype), ∃! y, OrderedPair.toObject { fst := ↑x, snd := ↑y } ∈ G⊢ ∃! f, G = graph f All goals completed! 🐙
Exercise 3.5.11. This trivially follows from SetTheory.Set.powerset_axiom, but the
exercise is to derive it from SetTheory.Set.exists_powerset instead.
theorem SetTheory.Set.powerset_axiom' (X Y:Set) :
∃! S:Set, ∀(F:Object), F ∈ S ↔ ∃ f: Y → X, f = F := sorryExercise 3.5.12, with errata from web site incorporated
theorem SetTheory.Set.recursion (X: Set) (f: nat → X → X) (c:X) :
∃! a: nat → X, a 0 = c ∧ ∀ n, a (n + 1:ℕ) = f n (a n) := inst✝:SetTheoryX:Setf:nat.toSubtype → X.toSubtype → X.toSubtypec:X.toSubtype⊢ ∃! a, a 0 = c ∧ ∀ (n : ℕ), a ↑(n + 1) = f (↑n) (a ↑n) All goals completed! 🐙Exercise 3.5.13
theorem SetTheory.Set.nat_unique (nat':Set) (zero:nat') (succ:nat' → nat')
(succ_ne: ∀ n:nat', succ n ≠ zero) (succ_of_ne: ∀ n m:nat', n ≠ m → succ n ≠ succ m)
(ind: ∀ P: nat' → Prop, P zero → (∀ n, P n → P (succ n)) → ∀ n, P n) :
∃! f : nat → nat', Function.Bijective f ∧ f 0 = zero
∧ ∀ (n:nat) (n':nat'), f n = n' ↔ f (n+1:ℕ) = succ n' := inst✝:SetTheorynat':Setzero:nat'.toSubtypesucc:nat'.toSubtype → nat'.toSubtypesucc_ne:∀ (n : nat'.toSubtype), succ n ≠ zerosucc_of_ne:∀ (n m : nat'.toSubtype), n ≠ m → succ n ≠ succ mind:∀ (P : nat'.toSubtype → Prop), P zero → (∀ (n : nat'.toSubtype), P n → P (succ n)) → ∀ (n : nat'.toSubtype), P n⊢ ∃! f,
Function.Bijective f ∧
f 0 = zero ∧ ∀ (n : nat.toSubtype) (n' : nat'.toSubtype), f n = n' ↔ f ↑(nat_equiv.symm n + 1) = succ n'
have nat_coe_eq {m:nat} {n} : (m:ℕ) = n → m = n := inst✝:SetTheorynat':Setzero:nat'.toSubtypesucc:nat'.toSubtype → nat'.toSubtypesucc_ne:∀ (n : nat'.toSubtype), succ n ≠ zerosucc_of_ne:∀ (n m : nat'.toSubtype), n ≠ m → succ n ≠ succ mind:∀ (P : nat'.toSubtype → Prop), P zero → (∀ (n : nat'.toSubtype), P n → P (succ n)) → ∀ (n : nat'.toSubtype), P n⊢ ∃! f,
Function.Bijective f ∧
f 0 = zero ∧ ∀ (n : nat.toSubtype) (n' : nat'.toSubtype), f n = n' ↔ f ↑(nat_equiv.symm n + 1) = succ n' All goals completed! 🐙
inst✝:SetTheorynat':Setzero:nat'.toSubtypesucc:nat'.toSubtype → nat'.toSubtypesucc_ne:∀ (n : nat'.toSubtype), succ n ≠ zerosucc_of_ne:∀ (n m : nat'.toSubtype), n ≠ m → succ n ≠ succ mind:∀ (P : nat'.toSubtype → Prop), P zero → (∀ (n : nat'.toSubtype), P n → P (succ n)) → ∀ (n : nat'.toSubtype), P nnat_coe_eq:∀ {m : nat.toSubtype} {n : ℕ}, nat_equiv.symm m = n → m = ↑nnat_coe_eq_zero:∀ {m : nat.toSubtype}, nat_equiv.symm m = 0 → m = 0⊢ ∃! f,
Function.Bijective f ∧
f 0 = zero ∧ ∀ (n : nat.toSubtype) (n' : nat'.toSubtype), f n = n' ↔ f ↑(nat_equiv.symm n + 1) = succ n'
inst✝:SetTheorynat':Setzero:nat'.toSubtypesucc:nat'.toSubtype → nat'.toSubtypesucc_ne:∀ (n : nat'.toSubtype), succ n ≠ zerosucc_of_ne:∀ (n m : nat'.toSubtype), n ≠ m → succ n ≠ succ mind:∀ (P : nat'.toSubtype → Prop), P zero → (∀ (n : nat'.toSubtype), P n → P (succ n)) → ∀ (n : nat'.toSubtype), P nnat_coe_eq:∀ {m : nat.toSubtype} {n : ℕ}, nat_equiv.symm m = n → m = ↑nnat_coe_eq_zero:∀ {m : nat.toSubtype}, nat_equiv.symm m = 0 → m = 0f:nat.toSubtype → nat'.toSubtypehf:(fun a ↦ a 0 = sorry ∧ ∀ (n : ℕ), a ↑(n + 1) = sorry (↑n) (a ↑n)) f ∧
∀ (y : nat.toSubtype → nat'.toSubtype), (fun a ↦ a 0 = sorry ∧ ∀ (n : ℕ), a ↑(n + 1) = sorry (↑n) (a ↑n)) y → y = f⊢ ∃! f,
Function.Bijective f ∧
f 0 = zero ∧ ∀ (n : nat.toSubtype) (n' : nat'.toSubtype), f n = n' ↔ f ↑(nat_equiv.symm n + 1) = succ n'
inst✝:SetTheorynat':Setzero:nat'.toSubtypesucc:nat'.toSubtype → nat'.toSubtypesucc_ne:∀ (n : nat'.toSubtype), succ n ≠ zerosucc_of_ne:∀ (n m : nat'.toSubtype), n ≠ m → succ n ≠ succ mind:∀ (P : nat'.toSubtype → Prop), P zero → (∀ (n : nat'.toSubtype), P n → P (succ n)) → ∀ (n : nat'.toSubtype), P nnat_coe_eq:∀ {m : nat.toSubtype} {n : ℕ}, nat_equiv.symm m = n → m = ↑nnat_coe_eq_zero:∀ {m : nat.toSubtype}, nat_equiv.symm m = 0 → m = 0f:nat.toSubtype → nat'.toSubtypehf:(fun a ↦ a 0 = sorry ∧ ∀ (n : ℕ), a ↑(n + 1) = sorry (↑n) (a ↑n)) f ∧
∀ (y : nat.toSubtype → nat'.toSubtype), (fun a ↦ a 0 = sorry ∧ ∀ (n : ℕ), a ↑(n + 1) = sorry (↑n) (a ↑n)) y → y = f⊢ ∃ x,
Function.Bijective x ∧
x 0 = zero ∧ ∀ (n : nat.toSubtype) (n' : nat'.toSubtype), x n = n' ↔ x ↑(nat_equiv.symm n + 1) = succ n'inst✝:SetTheorynat':Setzero:nat'.toSubtypesucc:nat'.toSubtype → nat'.toSubtypesucc_ne:∀ (n : nat'.toSubtype), succ n ≠ zerosucc_of_ne:∀ (n m : nat'.toSubtype), n ≠ m → succ n ≠ succ mind:∀ (P : nat'.toSubtype → Prop), P zero → (∀ (n : nat'.toSubtype), P n → P (succ n)) → ∀ (n : nat'.toSubtype), P nnat_coe_eq:∀ {m : nat.toSubtype} {n : ℕ}, nat_equiv.symm m = n → m = ↑nnat_coe_eq_zero:∀ {m : nat.toSubtype}, nat_equiv.symm m = 0 → m = 0f:nat.toSubtype → nat'.toSubtypehf:(fun a ↦ a 0 = sorry ∧ ∀ (n : ℕ), a ↑(n + 1) = sorry (↑n) (a ↑n)) f ∧
∀ (y : nat.toSubtype → nat'.toSubtype), (fun a ↦ a 0 = sorry ∧ ∀ (n : ℕ), a ↑(n + 1) = sorry (↑n) (a ↑n)) y → y = f⊢ ∀ (y₁ y₂ : nat.toSubtype → nat'.toSubtype),
(Function.Bijective y₁ ∧
y₁ 0 = zero ∧ ∀ (n : nat.toSubtype) (n' : nat'.toSubtype), y₁ n = n' ↔ y₁ ↑(nat_equiv.symm n + 1) = succ n') →
(Function.Bijective y₂ ∧
y₂ 0 = zero ∧ ∀ (n : nat.toSubtype) (n' : nat'.toSubtype), y₂ n = n' ↔ y₂ ↑(nat_equiv.symm n + 1) = succ n') →
y₁ = y₂
inst✝:SetTheorynat':Setzero:nat'.toSubtypesucc:nat'.toSubtype → nat'.toSubtypesucc_ne:∀ (n : nat'.toSubtype), succ n ≠ zerosucc_of_ne:∀ (n m : nat'.toSubtype), n ≠ m → succ n ≠ succ mind:∀ (P : nat'.toSubtype → Prop), P zero → (∀ (n : nat'.toSubtype), P n → P (succ n)) → ∀ (n : nat'.toSubtype), P nnat_coe_eq:∀ {m : nat.toSubtype} {n : ℕ}, nat_equiv.symm m = n → m = ↑nnat_coe_eq_zero:∀ {m : nat.toSubtype}, nat_equiv.symm m = 0 → m = 0f:nat.toSubtype → nat'.toSubtypehf:(fun a ↦ a 0 = sorry ∧ ∀ (n : ℕ), a ↑(n + 1) = sorry (↑n) (a ↑n)) f ∧
∀ (y : nat.toSubtype → nat'.toSubtype), (fun a ↦ a 0 = sorry ∧ ∀ (n : ℕ), a ↑(n + 1) = sorry (↑n) (a ↑n)) y → y = f⊢ ∃ x,
Function.Bijective x ∧
x 0 = zero ∧ ∀ (n : nat.toSubtype) (n' : nat'.toSubtype), x n = n' ↔ x ↑(nat_equiv.symm n + 1) = succ n' inst✝:SetTheorynat':Setzero:nat'.toSubtypesucc:nat'.toSubtype → nat'.toSubtypesucc_ne:∀ (n : nat'.toSubtype), succ n ≠ zerosucc_of_ne:∀ (n m : nat'.toSubtype), n ≠ m → succ n ≠ succ mind:∀ (P : nat'.toSubtype → Prop), P zero → (∀ (n : nat'.toSubtype), P n → P (succ n)) → ∀ (n : nat'.toSubtype), P nnat_coe_eq:∀ {m : nat.toSubtype} {n : ℕ}, nat_equiv.symm m = n → m = ↑nnat_coe_eq_zero:∀ {m : nat.toSubtype}, nat_equiv.symm m = 0 → m = 0f:nat.toSubtype → nat'.toSubtypehf:(fun a ↦ a 0 = sorry ∧ ∀ (n : ℕ), a ↑(n + 1) = sorry (↑n) (a ↑n)) f ∧
∀ (y : nat.toSubtype → nat'.toSubtype), (fun a ↦ a 0 = sorry ∧ ∀ (n : ℕ), a ↑(n + 1) = sorry (↑n) (a ↑n)) y → y = f⊢ Function.Bijective f ∧
f 0 = zero ∧ ∀ (n : nat.toSubtype) (n' : nat'.toSubtype), f n = n' ↔ f ↑(nat_equiv.symm n + 1) = succ n'
inst✝:SetTheorynat':Setzero:nat'.toSubtypesucc:nat'.toSubtype → nat'.toSubtypesucc_ne:∀ (n : nat'.toSubtype), succ n ≠ zerosucc_of_ne:∀ (n m : nat'.toSubtype), n ≠ m → succ n ≠ succ mind:∀ (P : nat'.toSubtype → Prop), P zero → (∀ (n : nat'.toSubtype), P n → P (succ n)) → ∀ (n : nat'.toSubtype), P nnat_coe_eq:∀ {m : nat.toSubtype} {n : ℕ}, nat_equiv.symm m = n → m = ↑nnat_coe_eq_zero:∀ {m : nat.toSubtype}, nat_equiv.symm m = 0 → m = 0f:nat.toSubtype → nat'.toSubtypehf:(fun a ↦ a 0 = sorry ∧ ∀ (n : ℕ), a ↑(n + 1) = sorry (↑n) (a ↑n)) f ∧
∀ (y : nat.toSubtype → nat'.toSubtype), (fun a ↦ a 0 = sorry ∧ ∀ (n : ℕ), a ↑(n + 1) = sorry (↑n) (a ↑n)) y → y = f⊢ Function.Bijective finst✝:SetTheorynat':Setzero:nat'.toSubtypesucc:nat'.toSubtype → nat'.toSubtypesucc_ne:∀ (n : nat'.toSubtype), succ n ≠ zerosucc_of_ne:∀ (n m : nat'.toSubtype), n ≠ m → succ n ≠ succ mind:∀ (P : nat'.toSubtype → Prop), P zero → (∀ (n : nat'.toSubtype), P n → P (succ n)) → ∀ (n : nat'.toSubtype), P nnat_coe_eq:∀ {m : nat.toSubtype} {n : ℕ}, nat_equiv.symm m = n → m = ↑nnat_coe_eq_zero:∀ {m : nat.toSubtype}, nat_equiv.symm m = 0 → m = 0f:nat.toSubtype → nat'.toSubtypehf:(fun a ↦ a 0 = sorry ∧ ∀ (n : ℕ), a ↑(n + 1) = sorry (↑n) (a ↑n)) f ∧
∀ (y : nat.toSubtype → nat'.toSubtype), (fun a ↦ a 0 = sorry ∧ ∀ (n : ℕ), a ↑(n + 1) = sorry (↑n) (a ↑n)) y → y = f⊢ f 0 = zero ∧ ∀ (n : nat.toSubtype) (n' : nat'.toSubtype), f n = n' ↔ f ↑(nat_equiv.symm n + 1) = succ n'
inst✝:SetTheorynat':Setzero:nat'.toSubtypesucc:nat'.toSubtype → nat'.toSubtypesucc_ne:∀ (n : nat'.toSubtype), succ n ≠ zerosucc_of_ne:∀ (n m : nat'.toSubtype), n ≠ m → succ n ≠ succ mind:∀ (P : nat'.toSubtype → Prop), P zero → (∀ (n : nat'.toSubtype), P n → P (succ n)) → ∀ (n : nat'.toSubtype), P nnat_coe_eq:∀ {m : nat.toSubtype} {n : ℕ}, nat_equiv.symm m = n → m = ↑nnat_coe_eq_zero:∀ {m : nat.toSubtype}, nat_equiv.symm m = 0 → m = 0f:nat.toSubtype → nat'.toSubtypehf:(fun a ↦ a 0 = sorry ∧ ∀ (n : ℕ), a ↑(n + 1) = sorry (↑n) (a ↑n)) f ∧
∀ (y : nat.toSubtype → nat'.toSubtype), (fun a ↦ a 0 = sorry ∧ ∀ (n : ℕ), a ↑(n + 1) = sorry (↑n) (a ↑n)) y → y = f⊢ Function.Bijective f inst✝:SetTheorynat':Setzero:nat'.toSubtypesucc:nat'.toSubtype → nat'.toSubtypesucc_ne:∀ (n : nat'.toSubtype), succ n ≠ zerosucc_of_ne:∀ (n m : nat'.toSubtype), n ≠ m → succ n ≠ succ mind:∀ (P : nat'.toSubtype → Prop), P zero → (∀ (n : nat'.toSubtype), P n → P (succ n)) → ∀ (n : nat'.toSubtype), P nnat_coe_eq:∀ {m : nat.toSubtype} {n : ℕ}, nat_equiv.symm m = n → m = ↑nnat_coe_eq_zero:∀ {m : nat.toSubtype}, nat_equiv.symm m = 0 → m = 0f:nat.toSubtype → nat'.toSubtypehf:(fun a ↦ a 0 = sorry ∧ ∀ (n : ℕ), a ↑(n + 1) = sorry (↑n) (a ↑n)) f ∧
∀ (y : nat.toSubtype → nat'.toSubtype), (fun a ↦ a 0 = sorry ∧ ∀ (n : ℕ), a ↑(n + 1) = sorry (↑n) (a ↑n)) y → y = f⊢ Function.Injective finst✝:SetTheorynat':Setzero:nat'.toSubtypesucc:nat'.toSubtype → nat'.toSubtypesucc_ne:∀ (n : nat'.toSubtype), succ n ≠ zerosucc_of_ne:∀ (n m : nat'.toSubtype), n ≠ m → succ n ≠ succ mind:∀ (P : nat'.toSubtype → Prop), P zero → (∀ (n : nat'.toSubtype), P n → P (succ n)) → ∀ (n : nat'.toSubtype), P nnat_coe_eq:∀ {m : nat.toSubtype} {n : ℕ}, nat_equiv.symm m = n → m = ↑nnat_coe_eq_zero:∀ {m : nat.toSubtype}, nat_equiv.symm m = 0 → m = 0f:nat.toSubtype → nat'.toSubtypehf:(fun a ↦ a 0 = sorry ∧ ∀ (n : ℕ), a ↑(n + 1) = sorry (↑n) (a ↑n)) f ∧
∀ (y : nat.toSubtype → nat'.toSubtype), (fun a ↦ a 0 = sorry ∧ ∀ (n : ℕ), a ↑(n + 1) = sorry (↑n) (a ↑n)) y → y = f⊢ Function.Surjective f
inst✝:SetTheorynat':Setzero:nat'.toSubtypesucc:nat'.toSubtype → nat'.toSubtypesucc_ne:∀ (n : nat'.toSubtype), succ n ≠ zerosucc_of_ne:∀ (n m : nat'.toSubtype), n ≠ m → succ n ≠ succ mind:∀ (P : nat'.toSubtype → Prop), P zero → (∀ (n : nat'.toSubtype), P n → P (succ n)) → ∀ (n : nat'.toSubtype), P nnat_coe_eq:∀ {m : nat.toSubtype} {n : ℕ}, nat_equiv.symm m = n → m = ↑nnat_coe_eq_zero:∀ {m : nat.toSubtype}, nat_equiv.symm m = 0 → m = 0f:nat.toSubtype → nat'.toSubtypehf:(fun a ↦ a 0 = sorry ∧ ∀ (n : ℕ), a ↑(n + 1) = sorry (↑n) (a ↑n)) f ∧
∀ (y : nat.toSubtype → nat'.toSubtype), (fun a ↦ a 0 = sorry ∧ ∀ (n : ℕ), a ↑(n + 1) = sorry (↑n) (a ↑n)) y → y = f⊢ Function.Injective f intro x1 inst✝:SetTheorynat':Setzero:nat'.toSubtypesucc:nat'.toSubtype → nat'.toSubtypesucc_ne:∀ (n : nat'.toSubtype), succ n ≠ zerosucc_of_ne:∀ (n m : nat'.toSubtype), n ≠ m → succ n ≠ succ mind:∀ (P : nat'.toSubtype → Prop), P zero → (∀ (n : nat'.toSubtype), P n → P (succ n)) → ∀ (n : nat'.toSubtype), P nnat_coe_eq:∀ {m : nat.toSubtype} {n : ℕ}, nat_equiv.symm m = n → m = ↑nnat_coe_eq_zero:∀ {m : nat.toSubtype}, nat_equiv.symm m = 0 → m = 0f:nat.toSubtype → nat'.toSubtypehf:(fun a ↦ a 0 = sorry ∧ ∀ (n : ℕ), a ↑(n + 1) = sorry (↑n) (a ↑n)) f ∧
∀ (y : nat.toSubtype → nat'.toSubtype), (fun a ↦ a 0 = sorry ∧ ∀ (n : ℕ), a ↑(n + 1) = sorry (↑n) (a ↑n)) y → y = fx1:nat.toSubtypex2:nat.toSubtype⊢ f x1 = f x2 → x1 = x2 inst✝:SetTheorynat':Setzero:nat'.toSubtypesucc:nat'.toSubtype → nat'.toSubtypesucc_ne:∀ (n : nat'.toSubtype), succ n ≠ zerosucc_of_ne:∀ (n m : nat'.toSubtype), n ≠ m → succ n ≠ succ mind:∀ (P : nat'.toSubtype → Prop), P zero → (∀ (n : nat'.toSubtype), P n → P (succ n)) → ∀ (n : nat'.toSubtype), P nnat_coe_eq:∀ {m : nat.toSubtype} {n : ℕ}, nat_equiv.symm m = n → m = ↑nnat_coe_eq_zero:∀ {m : nat.toSubtype}, nat_equiv.symm m = 0 → m = 0f:nat.toSubtype → nat'.toSubtypehf:(fun a ↦ a 0 = sorry ∧ ∀ (n : ℕ), a ↑(n + 1) = sorry (↑n) (a ↑n)) f ∧
∀ (y : nat.toSubtype → nat'.toSubtype), (fun a ↦ a 0 = sorry ∧ ∀ (n : ℕ), a ↑(n + 1) = sorry (↑n) (a ↑n)) y → y = fx1:nat.toSubtypex2:nat.toSubtypeheq:f x1 = f x2⊢ x1 = x2
inst✝:SetTheorynat':Setzero:nat'.toSubtypesucc:nat'.toSubtype → nat'.toSubtypesucc_ne:∀ (n : nat'.toSubtype), succ n ≠ zerosucc_of_ne:∀ (n m : nat'.toSubtype), n ≠ m → succ n ≠ succ mind:∀ (P : nat'.toSubtype → Prop), P zero → (∀ (n : nat'.toSubtype), P n → P (succ n)) → ∀ (n : nat'.toSubtype), P nnat_coe_eq:∀ {m : nat.toSubtype} {n : ℕ}, nat_equiv.symm m = n → m = ↑nnat_coe_eq_zero:∀ {m : nat.toSubtype}, nat_equiv.symm m = 0 → m = 0f:nat.toSubtype → nat'.toSubtypehf:(fun a ↦ a 0 = sorry ∧ ∀ (n : ℕ), a ↑(n + 1) = sorry (↑n) (a ↑n)) f ∧
∀ (y : nat.toSubtype → nat'.toSubtype), (fun a ↦ a 0 = sorry ∧ ∀ (n : ℕ), a ↑(n + 1) = sorry (↑n) (a ↑n)) y → y = fx1:nat.toSubtypex2:nat.toSubtypeheq:f x1 = f x2hx1:nat_equiv.symm x1 = 0⊢ x1 = x2inst✝:SetTheorynat':Setzero:nat'.toSubtypesucc:nat'.toSubtype → nat'.toSubtypesucc_ne:∀ (n : nat'.toSubtype), succ n ≠ zerosucc_of_ne:∀ (n m : nat'.toSubtype), n ≠ m → succ n ≠ succ mind:∀ (P : nat'.toSubtype → Prop), P zero → (∀ (n : nat'.toSubtype), P n → P (succ n)) → ∀ (n : nat'.toSubtype), P nnat_coe_eq:∀ {m : nat.toSubtype} {n : ℕ}, nat_equiv.symm m = n → m = ↑nnat_coe_eq_zero:∀ {m : nat.toSubtype}, nat_equiv.symm m = 0 → m = 0f:nat.toSubtype → nat'.toSubtypehf:(fun a ↦ a 0 = sorry ∧ ∀ (n : ℕ), a ↑(n + 1) = sorry (↑n) (a ↑n)) f ∧
∀ (y : nat.toSubtype → nat'.toSubtype), (fun a ↦ a 0 = sorry ∧ ∀ (n : ℕ), a ↑(n + 1) = sorry (↑n) (a ↑n)) y → y = fi:ℕih:∀ ⦃x1 x2 : nat.toSubtype⦄, f x1 = f x2 → nat_equiv.symm x1 = i → x1 = x2x1:nat.toSubtypex2:nat.toSubtypeheq:f x1 = f x2hx1:nat_equiv.symm x1 = i + 1⊢ x1 = x2
inst✝:SetTheorynat':Setzero:nat'.toSubtypesucc:nat'.toSubtype → nat'.toSubtypesucc_ne:∀ (n : nat'.toSubtype), succ n ≠ zerosucc_of_ne:∀ (n m : nat'.toSubtype), n ≠ m → succ n ≠ succ mind:∀ (P : nat'.toSubtype → Prop), P zero → (∀ (n : nat'.toSubtype), P n → P (succ n)) → ∀ (n : nat'.toSubtype), P nnat_coe_eq:∀ {m : nat.toSubtype} {n : ℕ}, nat_equiv.symm m = n → m = ↑nnat_coe_eq_zero:∀ {m : nat.toSubtype}, nat_equiv.symm m = 0 → m = 0f:nat.toSubtype → nat'.toSubtypehf:(fun a ↦ a 0 = sorry ∧ ∀ (n : ℕ), a ↑(n + 1) = sorry (↑n) (a ↑n)) f ∧
∀ (y : nat.toSubtype → nat'.toSubtype), (fun a ↦ a 0 = sorry ∧ ∀ (n : ℕ), a ↑(n + 1) = sorry (↑n) (a ↑n)) y → y = fx1:nat.toSubtypex2:nat.toSubtypeheq:f x1 = f x2hx1:nat_equiv.symm x1 = 0⊢ x1 = x2 All goals completed! 🐙
All goals completed! 🐙
All goals completed! 🐙
All goals completed! 🐙
All goals completed! 🐙end Chapter3