A Lean Companion to Conceptual Mathematics

Session 4: Division of maps: Isomorphisms

2. Inverses versus reciprocals

Definition: Inverse, Isomorphism (p. 61)

If {A \xrightarrow{f} B}, an inverse for f is a map {B \xrightarrow{g} A} satisfying both g \circ f = 1_A \quad\text{and}\quad f \circ g = 1_B. If f has an inverse, we say that f is an isomorphism or invertible map.

See the original presentation of these definitions at the beginning of Article II.

Theorem (uniqueness of inverses) (p. 61)

Any map f has at most one inverse.

Proof (p. 61)

Say {A \xrightarrow{f} B}, and suppose that both {B \xrightarrow{g} A} and {B \xrightarrow{h} A} are inverses for f; so g \circ f = 1_A \quad\text{and}\quad f \circ g = 1_B,\\\ h \circ f = 1_A \quad\text{and}\quad f \circ h = 1_B. We only need two of these equations to prove that g and h are the same: g = 1_A \circ g = (h \circ f) \circ g = h \circ (f \circ g) = h \circ 1_B = h.

See the Lean implementation uniqueness_of_inverses under the original presentation of this theorem in Article II.

4. A small zoo of isomorphisms in other categories

In some of the Exercises that follow, we start to make use of mathlib's implementation of the Category class (see the definition of category at the end of Article I) ahead of our more extensive reliance on it in later Articles and Sessions.

Exercise 1 (p. 66)

Finish checking that d is an isomorphism in our category by showing that {h \circ d} and {d \circ h} are indeed identity maps.

Solution: Exercise 1

To begin tackling this Exercise, we first define an abstract algebraic object as a type equipped with a carrier set and a 'combining-rule', which operates on elements of the carrier set (and which has the closure property).

structure AlgebraicObj where t : Type carrier : Set t oper : t t t oper_mem {a b} : a carrier b carrier oper a b carrier

Next we register a Category instance for our algebraic object, defining maps/morphisms between algebraic objects as morphisms between their underlying types that map elements of the domain carrier set to elements of the codomain carrier set and that respect the combining-rules.

instance : Category AlgebraicObj where Hom X Y := { f : X.t Y.t // ( x X.carrier, f x Y.carrier) -- maps to codomain ( x₁ X.carrier, -- respects combining-rules x₂ X.carrier, f (X.oper x₁ x₂) = Y.oper (f x₁) (f x₂)) } id X := 𝟙 X.t, X:AlgebraicObj(∀ x X.carrier, 𝟙 X.t x X.carrier) x₁ X.carrier, x₂ X.carrier, 𝟙 X.t (X.oper x₁ x₂) = X.oper (𝟙 X.t x₁) (𝟙 X.t x₂) X:AlgebraicObj x X.carrier, 𝟙 X.t x X.carrierX:AlgebraicObj x₁ X.carrier, x₂ X.carrier, 𝟙 X.t (X.oper x₁ x₂) = X.oper (𝟙 X.t x₁) (𝟙 X.t x₂) X:AlgebraicObj x X.carrier, 𝟙 X.t x X.carrier intro _ X:AlgebraicObjx✝:X.thx:x✝ X.carrier𝟙 X.t x✝ X.carrier All goals completed! 🐙 X:AlgebraicObj x₁ X.carrier, x₂ X.carrier, 𝟙 X.t (X.oper x₁ x₂) = X.oper (𝟙 X.t x₁) (𝟙 X.t x₂) X:AlgebraicObjx₁✝:X.ta✝¹:x₁✝ X.carrierx₂✝:X.ta✝:x₂✝ X.carrier𝟙 X.t (X.oper x₁✝ x₂✝) = X.oper (𝟙 X.t x₁✝) (𝟙 X.t x₂✝) All goals completed! 🐙 comp := {X Y Z : AlgebraicObj} { f // (∀ x X.carrier, f x Y.carrier) x₁ X.carrier, x₂ X.carrier, f (X.oper x₁ x₂) = Y.oper (f x₁) (f x₂) } { f // (∀ x Y.carrier, f x Z.carrier) x₁ Y.carrier, x₂ Y.carrier, f (Y.oper x₁ x₂) = Z.oper (f x₁) (f x₂) } { f // (∀ x X.carrier, f x Z.carrier) x₁ X.carrier, x₂ X.carrier, f (X.oper x₁ x₂) = Z.oper (f x₁) (f x₂) } X✝:AlgebraicObjY✝:AlgebraicObjZ✝:AlgebraicObjf:X✝.t Y✝.thf:(∀ x X✝.carrier, f x Y✝.carrier) x₁ X✝.carrier, x₂ X✝.carrier, f (X✝.oper x₁ x₂) = Y✝.oper (f x₁) (f x₂)g:Y✝.t Z✝.thg:(∀ x Y✝.carrier, g x Z✝.carrier) x₁ Y✝.carrier, x₂ Y✝.carrier, g (Y✝.oper x₁ x₂) = Z✝.oper (g x₁) (g x₂){ f // (∀ x X✝.carrier, f x Z✝.carrier) x₁ X✝.carrier, x₂ X✝.carrier, f (X✝.oper x₁ x₂) = Z✝.oper (f x₁) (f x₂) } exact g f, X✝:AlgebraicObjY✝:AlgebraicObjZ✝:AlgebraicObjf:X✝.t Y✝.thf:(∀ x X✝.carrier, f x Y✝.carrier) x₁ X✝.carrier, x₂ X✝.carrier, f (X✝.oper x₁ x₂) = Y✝.oper (f x₁) (f x₂)g:Y✝.t Z✝.thg:(∀ x Y✝.carrier, g x Z✝.carrier) x₁ Y✝.carrier, x₂ Y✝.carrier, g (Y✝.oper x₁ x₂) = Z✝.oper (g x₁) (g x₂)(∀ x X✝.carrier, (g f) x Z✝.carrier) x₁ X✝.carrier, x₂ X✝.carrier, (g f) (X✝.oper x₁ x₂) = Z✝.oper ((g f) x₁) ((g f) x₂) X✝:AlgebraicObjY✝:AlgebraicObjZ✝:AlgebraicObjf:X✝.t Y✝.tg:Y✝.t Z✝.thg:(∀ x Y✝.carrier, g x Z✝.carrier) x₁ Y✝.carrier, x₂ Y✝.carrier, g (Y✝.oper x₁ x₂) = Z✝.oper (g x₁) (g x₂)hf_mtc: x X✝.carrier, f x Y✝.carrierhf_comb: x₁ X✝.carrier, x₂ X✝.carrier, f (X✝.oper x₁ x₂) = Y✝.oper (f x₁) (f x₂)(∀ x X✝.carrier, (g f) x Z✝.carrier) x₁ X✝.carrier, x₂ X✝.carrier, (g f) (X✝.oper x₁ x₂) = Z✝.oper ((g f) x₁) ((g f) x₂) X✝:AlgebraicObjY✝:AlgebraicObjZ✝:AlgebraicObjf:X✝.t Y✝.tg:Y✝.t Z✝.thf_mtc: x X✝.carrier, f x Y✝.carrierhf_comb: x₁ X✝.carrier, x₂ X✝.carrier, f (X✝.oper x₁ x₂) = Y✝.oper (f x₁) (f x₂)hg_mtc: x Y✝.carrier, g x Z✝.carrierhg_comb: x₁ Y✝.carrier, x₂ Y✝.carrier, g (Y✝.oper x₁ x₂) = Z✝.oper (g x₁) (g x₂)(∀ x X✝.carrier, (g f) x Z✝.carrier) x₁ X✝.carrier, x₂ X✝.carrier, (g f) (X✝.oper x₁ x₂) = Z✝.oper ((g f) x₁) ((g f) x₂) X✝:AlgebraicObjY✝:AlgebraicObjZ✝:AlgebraicObjf:X✝.t Y✝.tg:Y✝.t Z✝.thf_mtc: x X✝.carrier, f x Y✝.carrierhf_comb: x₁ X✝.carrier, x₂ X✝.carrier, f (X✝.oper x₁ x₂) = Y✝.oper (f x₁) (f x₂)hg_mtc: x Y✝.carrier, g x Z✝.carrierhg_comb: x₁ Y✝.carrier, x₂ Y✝.carrier, g (Y✝.oper x₁ x₂) = Z✝.oper (g x₁) (g x₂) x X✝.carrier, (g f) x Z✝.carrierX✝:AlgebraicObjY✝:AlgebraicObjZ✝:AlgebraicObjf:X✝.t Y✝.tg:Y✝.t Z✝.thf_mtc: x X✝.carrier, f x Y✝.carrierhf_comb: x₁ X✝.carrier, x₂ X✝.carrier, f (X✝.oper x₁ x₂) = Y✝.oper (f x₁) (f x₂)hg_mtc: x Y✝.carrier, g x Z✝.carrierhg_comb: x₁ Y✝.carrier, x₂ Y✝.carrier, g (Y✝.oper x₁ x₂) = Z✝.oper (g x₁) (g x₂) x₁ X✝.carrier, x₂ X✝.carrier, (g f) (X✝.oper x₁ x₂) = Z✝.oper ((g f) x₁) ((g f) x₂) X✝:AlgebraicObjY✝:AlgebraicObjZ✝:AlgebraicObjf:X✝.t Y✝.tg:Y✝.t Z✝.thf_mtc: x X✝.carrier, f x Y✝.carrierhf_comb: x₁ X✝.carrier, x₂ X✝.carrier, f (X✝.oper x₁ x₂) = Y✝.oper (f x₁) (f x₂)hg_mtc: x Y✝.carrier, g x Z✝.carrierhg_comb: x₁ Y✝.carrier, x₂ Y✝.carrier, g (Y✝.oper x₁ x₂) = Z✝.oper (g x₁) (g x₂) x X✝.carrier, (g f) x Z✝.carrier intro x X✝:AlgebraicObjY✝:AlgebraicObjZ✝:AlgebraicObjf:X✝.t Y✝.tg:Y✝.t Z✝.thf_mtc: x X✝.carrier, f x Y✝.carrierhf_comb: x₁ X✝.carrier, x₂ X✝.carrier, f (X✝.oper x₁ x₂) = Y✝.oper (f x₁) (f x₂)hg_mtc: x Y✝.carrier, g x Z✝.carrierhg_comb: x₁ Y✝.carrier, x₂ Y✝.carrier, g (Y✝.oper x₁ x₂) = Z✝.oper (g x₁) (g x₂)x:X✝.thx:x X✝.carrier(g f) x Z✝.carrier All goals completed! 🐙 X✝:AlgebraicObjY✝:AlgebraicObjZ✝:AlgebraicObjf:X✝.t Y✝.tg:Y✝.t Z✝.thf_mtc: x X✝.carrier, f x Y✝.carrierhf_comb: x₁ X✝.carrier, x₂ X✝.carrier, f (X✝.oper x₁ x₂) = Y✝.oper (f x₁) (f x₂)hg_mtc: x Y✝.carrier, g x Z✝.carrierhg_comb: x₁ Y✝.carrier, x₂ Y✝.carrier, g (Y✝.oper x₁ x₂) = Z✝.oper (g x₁) (g x₂) x₁ X✝.carrier, x₂ X✝.carrier, (g f) (X✝.oper x₁ x₂) = Z✝.oper ((g f) x₁) ((g f) x₂) intro x₁ X✝:AlgebraicObjY✝:AlgebraicObjZ✝:AlgebraicObjf:X✝.t Y✝.tg:Y✝.t Z✝.thf_mtc: x X✝.carrier, f x Y✝.carrierhf_comb: x₁ X✝.carrier, x₂ X✝.carrier, f (X✝.oper x₁ x₂) = Y✝.oper (f x₁) (f x₂)hg_mtc: x Y✝.carrier, g x Z✝.carrierhg_comb: x₁ Y✝.carrier, x₂ Y✝.carrier, g (Y✝.oper x₁ x₂) = Z✝.oper (g x₁) (g x₂)x₁:X✝.thx₁:x₁ X✝.carrier x₂ X✝.carrier, (g f) (X✝.oper x₁ x₂) = Z✝.oper ((g f) x₁) ((g f) x₂) X✝:AlgebraicObjY✝:AlgebraicObjZ✝:AlgebraicObjf:X✝.t Y✝.tg:Y✝.t Z✝.thf_mtc: x X✝.carrier, f x Y✝.carrierhf_comb: x₁ X✝.carrier, x₂ X✝.carrier, f (X✝.oper x₁ x₂) = Y✝.oper (f x₁) (f x₂)hg_mtc: x Y✝.carrier, g x Z✝.carrierhg_comb: x₁ Y✝.carrier, x₂ Y✝.carrier, g (Y✝.oper x₁ x₂) = Z✝.oper (g x₁) (g x₂)x₁:X✝.thx₁:x₁ X✝.carrierx₂:X✝.tx₂ X✝.carrier (g f) (X✝.oper x₁ x₂) = Z✝.oper ((g f) x₁) ((g f) x₂) X✝:AlgebraicObjY✝:AlgebraicObjZ✝:AlgebraicObjf:X✝.t Y✝.tg:Y✝.t Z✝.thf_mtc: x X✝.carrier, f x Y✝.carrierhf_comb: x₁ X✝.carrier, x₂ X✝.carrier, f (X✝.oper x₁ x₂) = Y✝.oper (f x₁) (f x₂)hg_mtc: x Y✝.carrier, g x Z✝.carrierhg_comb: x₁ Y✝.carrier, x₂ Y✝.carrier, g (Y✝.oper x₁ x₂) = Z✝.oper (g x₁) (g x₂)x₁:X✝.thx₁:x₁ X✝.carrierx₂:X✝.thx₂:x₂ X✝.carrier(g f) (X✝.oper x₁ x₂) = Z✝.oper ((g f) x₁) ((g f) x₂) X✝:AlgebraicObjY✝:AlgebraicObjZ✝:AlgebraicObjf:X✝.t Y✝.tg:Y✝.t Z✝.thf_mtc: x X✝.carrier, f x Y✝.carrierhf_comb: x₁ X✝.carrier, x₂ X✝.carrier, f (X✝.oper x₁ x₂) = Y✝.oper (f x₁) (f x₂)hg_mtc: x Y✝.carrier, g x Z✝.carrierhg_comb: x₁ Y✝.carrier, x₂ Y✝.carrier, g (Y✝.oper x₁ x₂) = Z✝.oper (g x₁) (g x₂)x₁:X✝.thx₁:x₁ X✝.carrierx₂:X✝.thx₂:x₂ X✝.carrierg (f (X✝.oper x₁ x₂)) = Z✝.oper (g (f x₁)) (g (f x₂)) X✝:AlgebraicObjY✝:AlgebraicObjZ✝:AlgebraicObjf:X✝.t Y✝.tg:Y✝.t Z✝.thf_mtc: x X✝.carrier, f x Y✝.carrierhf_comb: x₁ X✝.carrier, x₂ X✝.carrier, f (X✝.oper x₁ x₂) = Y✝.oper (f x₁) (f x₂)hg_mtc: x Y✝.carrier, g x Z✝.carrierhg_comb: x₁ Y✝.carrier, x₂ Y✝.carrier, g (Y✝.oper x₁ x₂) = Z✝.oper (g x₁) (g x₂)x₁:X✝.thx₁:x₁ X✝.carrierx₂:X✝.thx₂:x₂ X✝.carrierh₁:f (X✝.oper x₁ x₂) = Y✝.oper (f x₁) (f x₂) := hf_comb x₁ hx₁ x₂ hx₂g (f (X✝.oper x₁ x₂)) = Z✝.oper (g (f x₁)) (g (f x₂)) X✝:AlgebraicObjY✝:AlgebraicObjZ✝:AlgebraicObjf:X✝.t Y✝.tg:Y✝.t Z✝.thf_mtc: x X✝.carrier, f x Y✝.carrierhf_comb: x₁ X✝.carrier, x₂ X✝.carrier, f (X✝.oper x₁ x₂) = Y✝.oper (f x₁) (f x₂)hg_mtc: x Y✝.carrier, g x Z✝.carrierhg_comb: x₁ Y✝.carrier, x₂ Y✝.carrier, g (Y✝.oper x₁ x₂) = Z✝.oper (g x₁) (g x₂)x₁:X✝.thx₁:x₁ X✝.carrierx₂:X✝.thx₂:x₂ X✝.carrierh₁:f (X✝.oper x₁ x₂) = Y✝.oper (f x₁) (f x₂) := hf_comb x₁ hx₁ x₂ hx₂g (Y✝.oper (f x₁) (f x₂)) = Z✝.oper (g (f x₁)) (g (f x₂)) X✝:AlgebraicObjY✝:AlgebraicObjZ✝:AlgebraicObjf:X✝.t Y✝.tg:Y✝.t Z✝.thf_mtc: x X✝.carrier, f x Y✝.carrierhf_comb: x₁ X✝.carrier, x₂ X✝.carrier, f (X✝.oper x₁ x₂) = Y✝.oper (f x₁) (f x₂)hg_mtc: x Y✝.carrier, g x Z✝.carrierhg_comb: x₁ Y✝.carrier, x₂ Y✝.carrier, g (Y✝.oper x₁ x₂) = Z✝.oper (g x₁) (g x₂)x₁:X✝.thx₁:x₁ X✝.carrierx₂:X✝.thx₂:x₂ X✝.carrierh₁:f (X✝.oper x₁ x₂) = Y✝.oper (f x₁) (f x₂) := hf_comb x₁ hx₁ x₂ hx₂h₂:g (Y✝.oper (f x₁) (f x₂)) = Z✝.oper (g (f x₁)) (g (f x₂)) := hg_comb (f x₁) (hf_mtc x₁ hx₁) (f x₂) (hf_mtc x₂ hx₂)g (Y✝.oper (f x₁) (f x₂)) = Z✝.oper (g (f x₁)) (g (f x₂)) All goals completed! 🐙

Lastly we define the concrete algebraic object of real numbers with addition as the combining-rule.

def RealAdd : AlgebraicObj := { t := carrier := Set.univ oper := (· + ·) oper_mem := fun _ _ Set.mem_univ _ }

We are now ready to complete the Exercise by defining d and h as morphisms in our category and showing that they are inverses.

def d : RealAdd RealAdd := fun (x : ) 2 * x, (∀ x RealAdd.carrier, (fun x 2 * x) x RealAdd.carrier) x₁ RealAdd.carrier, x₂ RealAdd.carrier, (fun x 2 * x) (RealAdd.oper x₁ x₂) = RealAdd.oper ((fun x 2 * x) x₁) ((fun x 2 * x) x₂) x RealAdd.carrier, (fun x 2 * x) x RealAdd.carrier x₁ RealAdd.carrier, x₂ RealAdd.carrier, (fun x 2 * x) (RealAdd.oper x₁ x₂) = RealAdd.oper ((fun x 2 * x) x₁) ((fun x 2 * x) x₂) x RealAdd.carrier, (fun x 2 * x) x RealAdd.carrier All goals completed! 🐙 x₁ RealAdd.carrier, x₂ RealAdd.carrier, (fun x 2 * x) (RealAdd.oper x₁ x₂) = RealAdd.oper ((fun x 2 * x) x₁) ((fun x 2 * x) x₂) x₁✝:RealAdd.ta✝¹:x₁✝ RealAdd.carrierx₂✝:RealAdd.ta✝:x₂✝ RealAdd.carrier(fun x 2 * x) (RealAdd.oper x₁✝ x₂✝) = RealAdd.oper ((fun x 2 * x) x₁✝) ((fun x 2 * x) x₂✝) x₁✝:RealAdd.ta✝¹:x₁✝ RealAdd.carrierx₂✝:RealAdd.ta✝:x₂✝ RealAdd.carrier2 * (x₁✝ + x₂✝) = 2 * x₁✝ + 2 * x₂✝ All goals completed! 🐙 noncomputable def h : RealAdd RealAdd := fun (x : ) x / 2, (∀ x RealAdd.carrier, (fun x x / 2) x RealAdd.carrier) x₁ RealAdd.carrier, x₂ RealAdd.carrier, (fun x x / 2) (RealAdd.oper x₁ x₂) = RealAdd.oper ((fun x x / 2) x₁) ((fun x x / 2) x₂) x RealAdd.carrier, (fun x x / 2) x RealAdd.carrier x₁ RealAdd.carrier, x₂ RealAdd.carrier, (fun x x / 2) (RealAdd.oper x₁ x₂) = RealAdd.oper ((fun x x / 2) x₁) ((fun x x / 2) x₂) x RealAdd.carrier, (fun x x / 2) x RealAdd.carrier All goals completed! 🐙 x₁ RealAdd.carrier, x₂ RealAdd.carrier, (fun x x / 2) (RealAdd.oper x₁ x₂) = RealAdd.oper ((fun x x / 2) x₁) ((fun x x / 2) x₂) x₁✝:RealAdd.ta✝¹:x₁✝ RealAdd.carrierx₂✝:RealAdd.ta✝:x₂✝ RealAdd.carrier(fun x x / 2) (RealAdd.oper x₁✝ x₂✝) = RealAdd.oper ((fun x x / 2) x₁✝) ((fun x x / 2) x₂✝) x₁✝:RealAdd.ta✝¹:x₁✝ RealAdd.carrierx₂✝:RealAdd.ta✝:x₂✝ RealAdd.carrier(x₁✝ + x₂✝) / 2 = x₁✝ / 2 + x₂✝ / 2 All goals completed! 🐙 example : IsIso d := { out := inv, inv d = 𝟙 RealAdd d inv = 𝟙 RealAdd h d = 𝟙 RealAdd d h = 𝟙 RealAdd h d = 𝟙 RealAddd h = 𝟙 RealAdd h d = 𝟙 RealAdd h d = 𝟙 RealAdd have h₀ : h.val d.val = id := inv, inv d = 𝟙 RealAdd d inv = 𝟙 RealAdd x:RealAdd.t(h d) x = id x x:RealAdd.t2 * x / 2 = x All goals completed! 🐙 All goals completed! 🐙 d h = 𝟙 RealAdd d h = 𝟙 RealAdd have h₀ : d.val h.val = id := inv, inv d = 𝟙 RealAdd d inv = 𝟙 RealAdd x:RealAdd.t(d h) x = id x x:RealAdd.t2 * (x / 2) = x All goals completed! 🐙 All goals completed! 🐙 }
Exercise 2 (p. 66)

Find an isomorphism (\{\textit{odd}, \textit{even}\}, +) \xrightarrow{f} (\{\textit{positive}, \textit{negative}\}, \times). Hint: There are only two invertible maps of sets from {\{\textit{odd}, \textit{even}\}} to {\{\textit{pos.}, \textit{neg.}\}}. One of them 'respects the combining rules', but the other doesn't.

Solution: Exercise 2

For this Exercise, we continue to use the category of algebraic objects we defined in Exercise 1.

Define addition for parity and multiplication for sign, and allow use of + and * notation.

inductive Parity | odd | even def add : Parity Parity Parity | Parity.odd, Parity.odd => Parity.even | Parity.odd, Parity.even => Parity.odd | Parity.even, Parity.odd => Parity.odd | Parity.even, Parity.even => Parity.even instance : Add Parity where add := add inductive Sign | pos | neg def mul : Sign Sign Sign | Sign.pos, Sign.pos => Sign.pos | Sign.pos, Sign.neg => Sign.neg | Sign.neg, Sign.pos => Sign.neg | Sign.neg, Sign.neg => Sign.pos instance : Mul Sign where mul := mul

Create algebraic objects for parity with addition and sign with multiplication.

def parityAdd : AlgebraicObj := { t := Parity carrier := Set.univ oper := (· + ·) oper_mem := fun _ _ Set.mem_univ _ } def signMul : AlgebraicObj := { t := Sign carrier := Set.univ oper := (· * ·) oper_mem := fun _ _ Set.mem_univ _ }

Propose a map f from parity to sign, and its inverse, and form the corresponding morphisms between algebraic objects.

def f' : Parity Sign | Parity.odd => Sign.neg | Parity.even => Sign.pos def finv' : Sign Parity | Sign.pos => Parity.even | Sign.neg => Parity.odd def f : parityAdd signMul := f', (∀ x parityAdd.carrier, f' x signMul.carrier) x₁ parityAdd.carrier, x₂ parityAdd.carrier, f' (parityAdd.oper x₁ x₂) = signMul.oper (f' x₁) (f' x₂) x parityAdd.carrier, f' x signMul.carrier x₁ parityAdd.carrier, x₂ parityAdd.carrier, f' (parityAdd.oper x₁ x₂) = signMul.oper (f' x₁) (f' x₂) x parityAdd.carrier, f' x signMul.carrier All goals completed! 🐙 x₁ parityAdd.carrier, x₂ parityAdd.carrier, f' (parityAdd.oper x₁ x₂) = signMul.oper (f' x₁) (f' x₂) intro a a:parityAdd.ta✝:a parityAdd.carrier x₂ parityAdd.carrier, f' (parityAdd.oper a x₂) = signMul.oper (f' a) (f' x₂) a:parityAdd.ta✝:a parityAdd.carrierb:parityAdd.tb parityAdd.carrier f' (parityAdd.oper a b) = signMul.oper (f' a) (f' b) a:parityAdd.ta✝¹:a parityAdd.carrierb:parityAdd.ta✝:b parityAdd.carrierf' (parityAdd.oper a b) = signMul.oper (f' a) (f' b) b:parityAdd.ta✝¹:b parityAdd.carriera✝:Parity.odd parityAdd.carrierf' (parityAdd.oper Parity.odd b) = signMul.oper (f' Parity.odd) (f' b)b:parityAdd.ta✝¹:b parityAdd.carriera✝:Parity.even parityAdd.carrierf' (parityAdd.oper Parity.even b) = signMul.oper (f' Parity.even) (f' b) b:parityAdd.ta✝¹:b parityAdd.carriera✝:Parity.odd parityAdd.carrierf' (parityAdd.oper Parity.odd b) = signMul.oper (f' Parity.odd) (f' b)b:parityAdd.ta✝¹:b parityAdd.carriera✝:Parity.even parityAdd.carrierf' (parityAdd.oper Parity.even b) = signMul.oper (f' Parity.even) (f' b) a✝¹:Parity.even parityAdd.carriera✝:Parity.odd parityAdd.carrierf' (parityAdd.oper Parity.even Parity.odd) = signMul.oper (f' Parity.even) (f' Parity.odd)a✝¹:Parity.even parityAdd.carriera✝:Parity.even parityAdd.carrierf' (parityAdd.oper Parity.even Parity.even) = signMul.oper (f' Parity.even) (f' Parity.even) a✝¹:Parity.odd parityAdd.carriera✝:Parity.odd parityAdd.carrierf' (parityAdd.oper Parity.odd Parity.odd) = signMul.oper (f' Parity.odd) (f' Parity.odd)a✝¹:Parity.odd parityAdd.carriera✝:Parity.even parityAdd.carrierf' (parityAdd.oper Parity.odd Parity.even) = signMul.oper (f' Parity.odd) (f' Parity.even)a✝¹:Parity.even parityAdd.carriera✝:Parity.odd parityAdd.carrierf' (parityAdd.oper Parity.even Parity.odd) = signMul.oper (f' Parity.even) (f' Parity.odd)a✝¹:Parity.even parityAdd.carriera✝:Parity.even parityAdd.carrierf' (parityAdd.oper Parity.even Parity.even) = signMul.oper (f' Parity.even) (f' Parity.even) All goals completed! 🐙 def finv : signMul parityAdd := finv', (∀ x signMul.carrier, finv' x parityAdd.carrier) x₁ signMul.carrier, x₂ signMul.carrier, finv' (signMul.oper x₁ x₂) = parityAdd.oper (finv' x₁) (finv' x₂) x signMul.carrier, finv' x parityAdd.carrier x₁ signMul.carrier, x₂ signMul.carrier, finv' (signMul.oper x₁ x₂) = parityAdd.oper (finv' x₁) (finv' x₂) x signMul.carrier, finv' x parityAdd.carrier All goals completed! 🐙 x₁ signMul.carrier, x₂ signMul.carrier, finv' (signMul.oper x₁ x₂) = parityAdd.oper (finv' x₁) (finv' x₂) intro a a:signMul.ta✝:a signMul.carrier x₂ signMul.carrier, finv' (signMul.oper a x₂) = parityAdd.oper (finv' a) (finv' x₂) a:signMul.ta✝:a signMul.carrierb:signMul.tb signMul.carrier finv' (signMul.oper a b) = parityAdd.oper (finv' a) (finv' b) a:signMul.ta✝¹:a signMul.carrierb:signMul.ta✝:b signMul.carrierfinv' (signMul.oper a b) = parityAdd.oper (finv' a) (finv' b) b:signMul.ta✝¹:b signMul.carriera✝:Sign.pos signMul.carrierfinv' (signMul.oper Sign.pos b) = parityAdd.oper (finv' Sign.pos) (finv' b)b:signMul.ta✝¹:b signMul.carriera✝:Sign.neg signMul.carrierfinv' (signMul.oper Sign.neg b) = parityAdd.oper (finv' Sign.neg) (finv' b) b:signMul.ta✝¹:b signMul.carriera✝:Sign.pos signMul.carrierfinv' (signMul.oper Sign.pos b) = parityAdd.oper (finv' Sign.pos) (finv' b)b:signMul.ta✝¹:b signMul.carriera✝:Sign.neg signMul.carrierfinv' (signMul.oper Sign.neg b) = parityAdd.oper (finv' Sign.neg) (finv' b) a✝¹:Sign.neg signMul.carriera✝:Sign.pos signMul.carrierfinv' (signMul.oper Sign.neg Sign.pos) = parityAdd.oper (finv' Sign.neg) (finv' Sign.pos)a✝¹:Sign.neg signMul.carriera✝:Sign.neg signMul.carrierfinv' (signMul.oper Sign.neg Sign.neg) = parityAdd.oper (finv' Sign.neg) (finv' Sign.neg) a✝¹:Sign.pos signMul.carriera✝:Sign.pos signMul.carrierfinv' (signMul.oper Sign.pos Sign.pos) = parityAdd.oper (finv' Sign.pos) (finv' Sign.pos)a✝¹:Sign.pos signMul.carriera✝:Sign.neg signMul.carrierfinv' (signMul.oper Sign.pos Sign.neg) = parityAdd.oper (finv' Sign.pos) (finv' Sign.neg)a✝¹:Sign.neg signMul.carriera✝:Sign.pos signMul.carrierfinv' (signMul.oper Sign.neg Sign.pos) = parityAdd.oper (finv' Sign.neg) (finv' Sign.pos)a✝¹:Sign.neg signMul.carriera✝:Sign.neg signMul.carrierfinv' (signMul.oper Sign.neg Sign.neg) = parityAdd.oper (finv' Sign.neg) (finv' Sign.neg) All goals completed! 🐙

Give a proof that our proposed map f is indeed an isomorphism.

example : IsIso f := { out := inv, inv f = 𝟙 parityAdd f inv = 𝟙 signMul finv f = 𝟙 parityAdd f finv = 𝟙 signMul finv f = 𝟙 parityAddf finv = 𝟙 signMul finv f = 𝟙 parityAdd have h₀ : finv.val f.val = id := inv, inv f = 𝟙 parityAdd f inv = 𝟙 signMul x:parityAdd.t(finv f) x = id x (finv f) Parity.odd = id Parity.odd(finv f) Parity.even = id Parity.even (finv f) Parity.odd = id Parity.odd(finv f) Parity.even = id Parity.even All goals completed! 🐙 All goals completed! 🐙 f finv = 𝟙 signMul have h₀ : f.val finv.val = id := inv, inv f = 𝟙 parityAdd f inv = 𝟙 signMul x:signMul.t(f finv) x = id x (f finv) Sign.pos = id Sign.pos(f finv) Sign.neg = id Sign.neg (f finv) Sign.pos = id Sign.pos(f finv) Sign.neg = id Sign.neg All goals completed! 🐙 All goals completed! 🐙 }
Exercise 3 (p. 66)

An unscrupulous importer has sold to the algebraic category section of our zoo some creatures which are not isomorphisms. Unmask the impostors.

(a) {(\mathbb{R}, +) \xrightarrow{p} (\mathbb{R}, +)} by 'plus 1': {p\:x = x + 1}.

(b) {(\mathbb{R}, \times) \xrightarrow{\mathit{sq}} (\mathbb{R}, \times)} by 'squaring': {\mathit{sq}\:x = x^2}.

(c) {(\mathbb{R}, \times) \xrightarrow{\mathit{sq}} (\mathbb{R}_{\ge 0}, \times)} by 'squaring': {\mathit{sq}\:x = x^2}.

(d) {(\mathbb{R}, +) \xrightarrow{m} (\mathbb{R}, +)} by 'minus': {m\:x = -x}.

(e) {(\mathbb{R}, \times) \xrightarrow{m} (\mathbb{R}, \times)} by 'minus': {m\:x = -x}.

(f) {(\mathbb{R}, \times) \xrightarrow{c} (\mathbb{R}_{>0}, \times)} by 'cubing': {c\:x = x^3}.

Hints: Exactly one is genuine. Some of the cruder impostors fail to be maps in our category, i.e. don't respect the combining-rules. The crudest is not even a map of sets with the indicated domain and codomain.

Solution: Exercise 3

For clarity of presentation here, we restrict our use of the category of algebraic objects we defined in Exercise 1 to the one genuine case of (d).

(a) p fails to respect the combining-rules.

example {p : } (hp : x : , p x = x + 1) : ¬( a b : , p (a + b) = p a + p b) := p: hp: (x : ), p x = x + 1¬ (a b : ), p (a + b) = p a + p b p: hp: (x : ), p x = x + 1 a b, p (a + b) p a + p b p: hp: (x : ), p x = x + 1p (0 + 0) p 0 + p 0 p: hp: (x : ), p x = x + 1¬0 + 1 = 0 All goals completed! 🐙

(b) \mathit{sq} has no retraction.

example {sq : } (hsq : x : , sq x = x ^ 2) : ¬( r : , ( x : , r (sq x) = x)) := sq: hsq: (x : ), sq x = x ^ 2¬ r, (x : ), r (sq x) = x sq: hsq: (x : ), sq x = x ^ 2h: r, (x : ), r (sq x) = xFalse sq: hsq: (x : ), sq x = x ^ 2r: h: (x : ), r (sq x) = xFalse sq: hsq: (x : ), sq x = x ^ 2r: h: (x : ), r (sq x) = xhpos:r (sq 1) = 1 := h 1False sq: hsq: (x : ), sq x = x ^ 2r: h: (x : ), r (sq x) = xhpos:r (sq 1) = 1 := h 1hneg:r (sq (-1)) = -1 := h (-1)False sq: hsq: (x : ), sq x = x ^ 2r: h: (x : ), r (sq x) = xhpos:r (1 ^ 2) = 1hneg:r ((-1) ^ 2) = -1False sq: hsq: (x : ), sq x = x ^ 2r: h: (x : ), r (sq x) = xhpos:r (1 ^ 2) = 1hneg:1 = -1False All goals completed! 🐙

(c) \mathit{sq} has no retraction.

open NNReal in example {sq : ℝ≥0} (hsq : x : , sq x = x ^ 2) : ¬( r : , ( x : , r (sq x) = x)) := sq: ℝ≥0hsq: (x : ), (sq x) = x ^ 2¬ r, (x : ), r (sq x) = x sq: ℝ≥0hsq: (x : ), (sq x) = x ^ 2h: r, (x : ), r (sq x) = xFalse sq: ℝ≥0hsq: (x : ), (sq x) = x ^ 2r: h: (x : ), r (sq x) = xFalse sq: ℝ≥0hsq: (x : ), (sq x) = x ^ 2r: h: (x : ), r (sq x) = xhpos:r (sq 1) = 1 := h 1False sq: ℝ≥0hsq: (x : ), (sq x) = x ^ 2r: h: (x : ), r (sq x) = xhpos:r (sq 1) = 1 := h 1hneg:r (sq (-1)) = -1 := h (-1)False sq: ℝ≥0hsq: (x : ), (sq x) = x ^ 2r: h: (x : ), r (sq x) = xhpos:r (1 ^ 2) = 1hneg:r ((-1) ^ 2) = -1False sq: ℝ≥0hsq: (x : ), (sq x) = x ^ 2r: h: (x : ), r (sq x) = xhpos:r (1 ^ 2) = 1hneg:1 = -1False All goals completed! 🐙

(d) m is genuine.

def m : RealAdd RealAdd := fun (x : ) -x, (∀ x RealAdd.carrier, (fun x -x) x RealAdd.carrier) x₁ RealAdd.carrier, x₂ RealAdd.carrier, (fun x -x) (RealAdd.oper x₁ x₂) = RealAdd.oper ((fun x -x) x₁) ((fun x -x) x₂) x RealAdd.carrier, (fun x -x) x RealAdd.carrier x₁ RealAdd.carrier, x₂ RealAdd.carrier, (fun x -x) (RealAdd.oper x₁ x₂) = RealAdd.oper ((fun x -x) x₁) ((fun x -x) x₂) x RealAdd.carrier, (fun x -x) x RealAdd.carrier All goals completed! 🐙 x₁ RealAdd.carrier, x₂ RealAdd.carrier, (fun x -x) (RealAdd.oper x₁ x₂) = RealAdd.oper ((fun x -x) x₁) ((fun x -x) x₂) x₁✝:RealAdd.ta✝¹:x₁✝ RealAdd.carrierx₂✝:RealAdd.ta✝:x₂✝ RealAdd.carrier(fun x -x) (RealAdd.oper x₁✝ x₂✝) = RealAdd.oper ((fun x -x) x₁✝) ((fun x -x) x₂✝) x₁✝:RealAdd.ta✝¹:x₁✝ RealAdd.carrierx₂✝:RealAdd.ta✝:x₂✝ RealAdd.carrier-(x₁✝ + x₂✝) = -x₁✝ + -x₂✝ All goals completed! 🐙 def minv := m example : IsIso m := { out := inv, inv m = 𝟙 RealAdd m inv = 𝟙 RealAdd minv m = 𝟙 RealAdd m minv = 𝟙 RealAdd minv m = 𝟙 RealAddm minv = 𝟙 RealAdd minv m = 𝟙 RealAdd have h₀ : minv.val m.val = id := inv, inv m = 𝟙 RealAdd m inv = 𝟙 RealAdd x:RealAdd.t(minv m) x = id x x:RealAdd.t- -x = x Try this: [apply] ring_nf The `ring` tactic failed to close the goal. Use `ring_nf` to obtain a normal form. Note that `ring` works primarily in *commutative* rings. If you have a noncommutative ring, abelian group or module, consider using `noncomm_ring`, `abel` or `module` instead.All goals completed! 🐙 All goals completed! 🐙 m minv = 𝟙 RealAdd have h₀ : m.val minv.val = id := inv, inv m = 𝟙 RealAdd m inv = 𝟙 RealAdd x:RealAdd.t(m minv) x = id x x:RealAdd.t- -x = x Try this: [apply] ring_nf The `ring` tactic failed to close the goal. Use `ring_nf` to obtain a normal form. Note that `ring` works primarily in *commutative* rings. If you have a noncommutative ring, abelian group or module, consider using `noncomm_ring`, `abel` or `module` instead.All goals completed! 🐙 All goals completed! 🐙 }

(e) m fails to respect the combining-rules.

example {m : } (hm : x : , m x = -x) : ¬( a b : , m (a * b) = m a * m b) := m: hm: (x : ), m x = -x¬ (a b : ), m (a * b) = m a * m b m: hm: (x : ), m x = -x a b, m (a * b) m a * m b m: hm: (x : ), m x = -xm (1 * 1) m 1 * m 1 m: hm: (x : ), m x = -x¬-1 = -1 * -1 All goals completed! 🐙

(f) c has an invalid codomain.

abbrev ℝpos := { x : // x > 0 } example {c : ℝpos} (hc : x : , c x = x ^ 3) : x : , ¬( y : ℝpos, y.val = c x) := c: ℝposhc: (x : ), (c x) = x ^ 3 x, ¬ y, y = (c x) c: ℝposhc: (x : ), (c x) = x ^ 3 x, (y : ℝpos), y (c x) c: ℝposhc: (x : ), (c x) = x ^ 3 (y : ℝpos), y (c (-1)) c: ℝposhc: (x : ), (c x) = x ^ 3 (y : ℝpos), y (-1) ^ 3 c: ℝposhc: (x : ), (c x) = x ^ 3 (a : ), 0 < a ¬a = -1 c: ℝposhc: (x : ), (c x) = x ^ 3a✝:b✝:0 < a✝¬a✝ = -1 All goals completed! 🐙