The rationals

Analysis I, Section 4.2

This file is a translation of Section 4.2 of Analysis I to Lean 4. All numbering refers to the original text.

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:

  • Definition of the "Section 4.2" rationals, Section_4_2.Rat : TypeSection_4_2.Rat, as formal quotients Unknown identifier `a`sorry // sorry : Section_4_2.Rata // Unknown identifier `b`b of integers , up to equivalence. (This is a quotient of a scaffolding type Section_4_2.PreRat : TypeSection_4_2.PreRat, which consists of formal quotients without any equivalence imposed.)

  • Field operations and order on these rationals, as well as an embedding of ℕ and ℤ.

  • Equivalence with the Mathlib rationals Rat : Type_root_.Rat (or : Type), which we will use going forward.

Note: here (and in the sequel) we use Mathlib's natural numbers : Type and integers : Type rather than the Chapter 2 natural numbers and Section 4.1 integers.

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)

namespace Section_4_2structure PreRat where numerator : denominator : nonzero : denominator 0

Exercise 4.2.1

instance declaration uses 'sorry'PreRat.instSetoid : Setoid PreRat where r a b := a.numerator * b.denominator = b.numerator * a.denominator iseqv := { refl := (x : PreRat), x.numerator * x.denominator = x.numerator * x.denominator All goals completed! 🐙 symm := {x y : PreRat}, x.numerator * y.denominator = y.numerator * x.denominator y.numerator * x.denominator = x.numerator * y.denominator All goals completed! 🐙 trans := {x y z : PreRat}, x.numerator * y.denominator = y.numerator * x.denominator y.numerator * z.denominator = z.numerator * y.denominator x.numerator * z.denominator = z.numerator * x.denominator All goals completed! 🐙 }
@[simp] theorem PreRat.eq (a b c d:) (hb: b 0) (hd: d 0) : ( a,b,hb : PreRat) c,d,hd a * d = c * b := a:b:c:d:hb:b 0hd:d 0{ numerator := a, denominator := b, nonzero := hb } { numerator := c, denominator := d, nonzero := hd } a * d = c * b All goals completed! 🐙abbrev Rat := Quotient PreRat.instSetoid

We give division a "junk" value of 0//1 if the denominator is zero

abbrev Rat.formalDiv (a b:) : Rat := Quotient.mk PreRat.instSetoid (if h:b 0 then a,b,h else 0, 1, a:b:h:¬b 01 0 All goals completed! 🐙 )
infix:100 " // " => Rat.formalDiv

Definition 4.2.1 (Rationals)

theorem Rat.eq (a c:) {b d:} (hb: b 0) (hd: d 0): a // b = c // d a * d = c * b := a:c:b:d:hb:b 0hd:d 0a // b = c // d a * d = c * b All goals completed! 🐙

Definition 4.2.1 (Rationals)

theorem Rat.eq_diff (n:Rat) : a b, b 0 n = a // b := n:Rat a b, b 0 n = a // b n:Rat (a : PreRat), a_1 b, b 0 a = a_1 // b; n:Rata:b:h:b 0 a_1 b_1, b_1 0 { numerator := a, denominator := b, nonzero := h } = a_1 // b_1 n:Rata:b:h:b 0{ numerator := a, denominator := b, nonzero := h } = a // b All goals completed! 🐙

Decidability of equality. Hint: modify the proof of DecidableEq : TypeDecidableEq Int from the previous section. However, because formal division handles the case of zero denominator separately, it may be more convenient to avoid that operation and work directly with the Quotient.{u} {α : Sort u} (s : Setoid α) : Sort uQuotient API.

instance declaration uses 'sorry'Rat.decidableEq : DecidableEq Rat := DecidableEq Rat All goals completed! 🐙

Lemma 4.2.3 (Addition well-defined)

instance Rat.add_inst : Add Rat where add := Quotient.lift₂ (fun a, b, h1 c, d, h2 (a*d+b*c) // (b*d)) ( (a₁ b₁ a₂ b₂ : PreRat), a₁ a₂ b₁ b₂ (fun x x_1 => match x with | { numerator := a, denominator := b, nonzero := h1 } => match x_1 with | { numerator := c, denominator := d, nonzero := h2 } => (a * d + b * c) // (b * d)) a₁ b₁ = (fun x x_1 => match x with | { numerator := a, denominator := b, nonzero := h1 } => match x_1 with | { numerator := c, denominator := d, nonzero := h2 } => (a * d + b * c) // (b * d)) a₂ b₂ a:b:h1:b 0c:d:h2:d 0a':b':h1':b' 0c':d':h2':d' 0h3:{ numerator := a, denominator := b, nonzero := h1 } { numerator := a', denominator := b', nonzero := h1' }h4:{ numerator := c, denominator := d, nonzero := h2 } { numerator := c', denominator := d', nonzero := h2' }(fun x x_1 => match x with | { numerator := a, denominator := b, nonzero := h1 } => match x_1 with | { numerator := c, denominator := d, nonzero := h2 } => (a * d + b * c) // (b * d)) { numerator := a, denominator := b, nonzero := h1 } { numerator := c, denominator := d, nonzero := h2 } = (fun x x_1 => match x with | { numerator := a, denominator := b, nonzero := h1 } => match x_1 with | { numerator := c, denominator := d, nonzero := h2 } => (a * d + b * c) // (b * d)) { numerator := a', denominator := b', nonzero := h1' } { numerator := c', denominator := d', nonzero := h2' } a:b:h1:b 0c:d:h2:d 0a':b':h1':b' 0c':d':h2':d' 0h3:a * b' = a' * bh4:c * d' = c' * d(a * d + b * c) * (b' * d') = (a' * d' + b' * c') * (b * d) calc _ = (a*b')*d*d' + b*b'*(c*d') := a:b:h1:b 0c:d:h2:d 0a':b':h1':b' 0c':d':h2':d' 0h3:a * b' = a' * bh4:c * d' = c' * d(a * d + b * c) * (b' * d') = a * b' * d * d' + b * b' * (c * d') All goals completed! 🐙 _ = (a'*b)*d*d' + b*b'*(c'*d) := a:b:h1:b 0c:d:h2:d 0a':b':h1':b' 0c':d':h2':d' 0h3:a * b' = a' * bh4:c * d' = c' * da * b' * d * d' + b * b' * (c * d') = a' * b * d * d' + b * b' * (c' * d) All goals completed! 🐙 _ = _ := a:b:h1:b 0c:d:h2:d 0a':b':h1':b' 0c':d':h2':d' 0h3:a * b' = a' * bh4:c * d' = c' * da' * b * d * d' + b * b' * (c' * d) = (a' * d' + b' * c') * (b * d) All goals completed! 🐙 )

Definition 4.2.2 (Addition of rationals)

theorem Rat.add_eq (a c:) {b d:} (hb: b 0) (hd: d 0) : (a // b) + (c // d) = (a*d + b*c) // (b*d) := a:c:b:d:hb:b 0hd:d 0a // b + c // d = (a * d + b * c) // (b * d) a:c:b:d:hb:b 0hd:d 0a = (if h : b 0 then { numerator := a, denominator := b, nonzero := h } else { numerator := 0, denominator := 1, nonzero := formalDiv._proof_1 }).numeratora:c:b:d:hb:b 0hd:d 0d = (if h : d 0 then { numerator := c, denominator := d, nonzero := h } else { numerator := 0, denominator := 1, nonzero := formalDiv._proof_1 }).denominatora:c:b:d:hb:b 0hd:d 0b = (if h : b 0 then { numerator := a, denominator := b, nonzero := h } else { numerator := 0, denominator := 1, nonzero := formalDiv._proof_1 }).denominatora:c:b:d:hb:b 0hd:d 0c = (if h : d 0 then { numerator := c, denominator := d, nonzero := h } else { numerator := 0, denominator := 1, nonzero := formalDiv._proof_1 }).numeratora:c:b:d:hb:b 0hd:d 0b = (if h : b 0 then { numerator := a, denominator := b, nonzero := h } else { numerator := 0, denominator := 1, nonzero := formalDiv._proof_1 }).denominatora:c:b:d:hb:b 0hd:d 0d = (if h : d 0 then { numerator := c, denominator := d, nonzero := h } else { numerator := 0, denominator := 1, nonzero := formalDiv._proof_1 }).denominator a:c:b:d:hb:b 0hd:d 0a = (if h : b 0 then { numerator := a, denominator := b, nonzero := h } else { numerator := 0, denominator := 1, nonzero := formalDiv._proof_1 }).numeratora:c:b:d:hb:b 0hd:d 0d = (if h : d 0 then { numerator := c, denominator := d, nonzero := h } else { numerator := 0, denominator := 1, nonzero := formalDiv._proof_1 }).denominatora:c:b:d:hb:b 0hd:d 0b = (if h : b 0 then { numerator := a, denominator := b, nonzero := h } else { numerator := 0, denominator := 1, nonzero := formalDiv._proof_1 }).denominatora:c:b:d:hb:b 0hd:d 0c = (if h : d 0 then { numerator := c, denominator := d, nonzero := h } else { numerator := 0, denominator := 1, nonzero := formalDiv._proof_1 }).numeratora:c:b:d:hb:b 0hd:d 0b = (if h : b 0 then { numerator := a, denominator := b, nonzero := h } else { numerator := 0, denominator := 1, nonzero := formalDiv._proof_1 }).denominatora:c:b:d:hb:b 0hd:d 0d = (if h : d 0 then { numerator := c, denominator := d, nonzero := h } else { numerator := 0, denominator := 1, nonzero := formalDiv._proof_1 }).denominator All goals completed! 🐙

Lemma 4.2.3 (Multiplication well-defined)

instance declaration uses 'sorry'Rat.mul_inst : Mul Rat where mul := Quotient.lift₂ (fun a, b, h1 c, d, h2 (a*c) // (b*d)) ( (a₁ b₁ a₂ b₂ : PreRat), a₁ a₂ b₁ b₂ (fun x x_1 => match x with | { numerator := a, denominator := b, nonzero := h1 } => match x_1 with | { numerator := c, denominator := d, nonzero := h2 } => (a * c) // (b * d)) a₁ b₁ = (fun x x_1 => match x with | { numerator := a, denominator := b, nonzero := h1 } => match x_1 with | { numerator := c, denominator := d, nonzero := h2 } => (a * c) // (b * d)) a₂ b₂ All goals completed! 🐙)

Definition 4.2.2 (Multiplication of rationals)

theorem Rat.mul_eq (a c:) {b d:} (hb: b 0) (hd: d 0) : (a // b) * (c // d) = (a*c) // (b*d) := a:c:b:d:hb:b 0hd:d 0a // b * c // d = (a * c) // (b * d) a:c:b:d:hb:b 0hd:d 0a = (if h : b 0 then { numerator := a, denominator := b, nonzero := h } else { numerator := 0, denominator := 1, nonzero := formalDiv._proof_1 }).numeratora:c:b:d:hb:b 0hd:d 0c = (if h : d 0 then { numerator := c, denominator := d, nonzero := h } else { numerator := 0, denominator := 1, nonzero := formalDiv._proof_1 }).numeratora:c:b:d:hb:b 0hd:d 0b = (if h : b 0 then { numerator := a, denominator := b, nonzero := h } else { numerator := 0, denominator := 1, nonzero := formalDiv._proof_1 }).denominatora:c:b:d:hb:b 0hd:d 0d = (if h : d 0 then { numerator := c, denominator := d, nonzero := h } else { numerator := 0, denominator := 1, nonzero := formalDiv._proof_1 }).denominator a:c:b:d:hb:b 0hd:d 0a = (if h : b 0 then { numerator := a, denominator := b, nonzero := h } else { numerator := 0, denominator := 1, nonzero := formalDiv._proof_1 }).numeratora:c:b:d:hb:b 0hd:d 0c = (if h : d 0 then { numerator := c, denominator := d, nonzero := h } else { numerator := 0, denominator := 1, nonzero := formalDiv._proof_1 }).numeratora:c:b:d:hb:b 0hd:d 0b = (if h : b 0 then { numerator := a, denominator := b, nonzero := h } else { numerator := 0, denominator := 1, nonzero := formalDiv._proof_1 }).denominatora:c:b:d:hb:b 0hd:d 0d = (if h : d 0 then { numerator := c, denominator := d, nonzero := h } else { numerator := 0, denominator := 1, nonzero := formalDiv._proof_1 }).denominator All goals completed! 🐙

Lemma 4.2.3 (Negation well-defined)

instance declaration uses 'sorry'Rat.neg_inst : Neg Rat where neg := Quotient.lift (fun a, b, h1 (-a) // b) ( (a b : PreRat), a b (fun x => match x with | { numerator := a, denominator := b, nonzero := h1 } => (-a) // b) a = (fun x => match x with | { numerator := a, denominator := b, nonzero := h1 } => (-a) // b) b All goals completed! 🐙)

Definition 4.2.2 (Negation of rationals)

theorem Rat.neg_eq (a:) {b:} (hb: b 0) : - (a // b) = (-a) // b := a:b:hb:b 0-a // b = (-a) // b a:b:hb:b 0a = (if h : b 0 then { numerator := a, denominator := b, nonzero := h } else { numerator := 0, denominator := 1, nonzero := formalDiv._proof_1 }).numeratora:b:hb:b 0b = (if h : b 0 then { numerator := a, denominator := b, nonzero := h } else { numerator := 0, denominator := 1, nonzero := formalDiv._proof_1 }).denominator a:b:hb:b 0a = (if h : b 0 then { numerator := a, denominator := b, nonzero := h } else { numerator := 0, denominator := 1, nonzero := formalDiv._proof_1 }).numeratora:b:hb:b 0b = (if h : b 0 then { numerator := a, denominator := b, nonzero := h } else { numerator := 0, denominator := 1, nonzero := formalDiv._proof_1 }).denominator All goals completed! 🐙

Embedding the integers in the rationals

instance Rat.instIntCast : IntCast Rat where intCast a := a // 1
instance Rat.instNatCast : NatCast Rat where natCast n := (n:) // 1instance Rat.instOfNat {n:} : OfNat Rat n where ofNat := (n:) // 1theorem Rat.coe_Int_eq (a:) : (a:Rat) = a // 1 := rfltheorem Rat.coe_Nat_eq (n:) : (n:Rat) = n // 1 := rfltheorem Rat.of_Nat_eq (n:) : (ofNat(n):Rat) = (ofNat(n):Nat) // 1 := rfl

natCast distributes over successor

theorem declaration uses 'sorry'Rat.natCast_succ (n: ) : ((n + 1: ): Rat) = (n: Rat) + 1 := n:(n + 1) = n + 1 All goals completed! 🐙

intCast distributes over addition

lemma declaration uses 'sorry'Rat.intCast_add (a b:) : (a:Rat) + (b:Rat) = (a+b:) := a:b:a + b = (a + b) All goals completed! 🐙

intCast distributes over multiplication

lemma declaration uses 'sorry'Rat.intCast_mul (a b:) : (a:Rat) * (b:Rat) = (a*b:) := a:b:a * b = (a * b) All goals completed! 🐙

intCast commutes with negation

lemma Rat.intCast_neg (a:) : - (a:Rat) = (-a:) := rfl
theorem declaration uses 'sorry'Rat.coe_Int_inj : Function.Injective (fun n: (n:Rat)) := Function.Injective fun n => n All goals completed! 🐙

Whereas the book leaves the inverse of 0 undefined, it is more convenient in Lean to assign a "junk" value to this inverse; we arbitrarily choose this junk value to be 0.

instance declaration uses 'sorry'Rat.instInv : Inv Rat where inv := Quotient.lift (fun a, b, h1 b // a) ( (a b : PreRat), a b (fun x => match x with | { numerator := a, denominator := b, nonzero := h1 } => b // a) a = (fun x => match x with | { numerator := a, denominator := b, nonzero := h1 } => b // a) b All goals completed! 🐙 -- hint: split into the `a=0` and `a≠0` cases )
lemma Rat.inv_eq (a:) {b:} (hb: b 0) : (a // b)⁻¹ = b // a := a:b:hb:b 0(a // b)⁻¹ = b // a a:b:hb:b 0b = (if h : b 0 then { numerator := a, denominator := b, nonzero := h } else { numerator := 0, denominator := 1, nonzero := formalDiv._proof_1 }).denominatora:b:hb:b 0a = (if h : b 0 then { numerator := a, denominator := b, nonzero := h } else { numerator := 0, denominator := 1, nonzero := formalDiv._proof_1 }).numerator a:b:hb:b 0b = (if h : b 0 then { numerator := a, denominator := b, nonzero := h } else { numerator := 0, denominator := 1, nonzero := formalDiv._proof_1 }).denominatora:b:hb:b 0a = (if h : b 0 then { numerator := a, denominator := b, nonzero := h } else { numerator := 0, denominator := 1, nonzero := formalDiv._proof_1 }).numerator All goals completed! 🐙@[simp] theorem Rat.inv_zero : (0:Rat)⁻¹ = 0 := rfl

Proposition 4.2.4 (laws of algebra) / Exercise 4.2.3

instance declaration uses 'sorry'declaration uses 'sorry'Rat.addGroup_inst : AddGroup Rat := AddGroup.ofLeftAxioms ( (a b c : Rat), a + b + c = a + (b + c) -- this proof is written to follow the structure of the original text. x:Raty:Ratz:Ratx + y + z = x + (y + z) y:Ratz:Rata:b:hb:b 0a // b + y + z = a // b + (y + z) z:Rata:b:hb:b 0c:d:hd:d 0a // b + c // d + z = a // b + (c // d + z) a:b:hb:b 0c:d:hd:d 0e:f:hf:f 0a // b + c // d + e // f = a // b + (c // d + e // f) a:b:hb:b 0c:d:hd:d 0e:f:hf:f 0hbd:_fvar.38578 * _fvar.38654 0 := Int.mul_ne_zero _fvar.38600 _fvar.38672a // b + c // d + e // f = a // b + (c // d + e // f) -- can also use `observe hbd : b*d ≠ 0` here a:b:hb:b 0c:d:hd:d 0e:f:hf:f 0hbd:_fvar.38578 * _fvar.38654 0 := Int.mul_ne_zero _fvar.38600 _fvar.38672hdf:_fvar.38654 * _fvar.38726 0 := Int.mul_ne_zero _fvar.38672 _fvar.38744a // b + c // d + e // f = a // b + (c // d + e // f) -- can also use `observe hdf : d*f ≠ 0` here a:b:hb:b 0c:d:hd:d 0e:f:hf:f 0hbd:_fvar.38578 * _fvar.38654 0 := Int.mul_ne_zero _fvar.38600 _fvar.38672hdf:_fvar.38654 * _fvar.38726 0 := Int.mul_ne_zero _fvar.38672 _fvar.38744hbdf:_fvar.38578 * _fvar.38654 * _fvar.38726 0 := Int.mul_ne_zero _fvar.38859 _fvar.38744a // b + c // d + e // f = a // b + (c // d + e // f) -- can also use `observe hbdf : b*d*f ≠ 0` here a:b:hb:b 0c:d:hd:d 0e:f:hf:f 0hbd:_fvar.38578 * _fvar.38654 0 := Int.mul_ne_zero _fvar.38600 _fvar.38672hdf:_fvar.38654 * _fvar.38726 0 := Int.mul_ne_zero _fvar.38672 _fvar.38744hbdf:_fvar.38578 * _fvar.38654 * _fvar.38726 0 := Int.mul_ne_zero _fvar.38859 _fvar.38744((a * d + b * c) * f + b * d * e) * (b * d * f) = (a * (d * f) + b * (c * f + d * e)) * (b * d * f) All goals completed! 🐙 ) ( (a : Rat), 0 + a = a All goals completed! 🐙) ( (a : Rat), -a + a = 0 All goals completed! 🐙)

Proposition 4.2.4 (laws of algebra) / Exercise 4.2.3

instance declaration uses 'sorry'Rat.instAddCommGroup : AddCommGroup Rat where add_comm := (a b : Rat), a + b = b + a All goals completed! 🐙

Proposition 4.2.4 (laws of algebra) / Exercise 4.2.3

instance declaration uses 'sorry'declaration uses 'sorry'declaration uses 'sorry'declaration uses 'sorry'declaration uses 'sorry'declaration uses 'sorry'Rat.instCommMonoid : CommMonoid Rat where mul_comm := (a b : Rat), a * b = b * a All goals completed! 🐙 mul_assoc := (a b c : Rat), a * b * c = a * (b * c) All goals completed! 🐙 one_mul := (a : Rat), 1 * a = a All goals completed! 🐙 mul_one := (a : Rat), a * 1 = a All goals completed! 🐙

Proposition 4.2.4 (laws of algebra) / Exercise 4.2.3

instance declaration uses 'sorry'declaration uses 'sorry'declaration uses 'sorry'declaration uses 'sorry'declaration uses 'sorry'declaration uses 'sorry'declaration uses 'sorry'Rat.instCommRing : CommRing Rat where left_distrib := (a b c : Rat), a * (b + c) = a * b + a * c All goals completed! 🐙 right_distrib := (a b c : Rat), (a + b) * c = a * c + b * c All goals completed! 🐙 zero_mul := (a : Rat), 0 * a = 0 All goals completed! 🐙 mul_zero := (a : Rat), a * 0 = 0 All goals completed! 🐙 mul_assoc := (a b c : Rat), a * b * c = a * (b * c) All goals completed! 🐙 -- Usually CommRing will generate a natCast instance and a proof for this. -- However, we are using a custom natCast for which `natCast_succ` cannot -- be proven automatically by `rfl`. Luckily we have proven it already. natCast_succ := natCast_succ
instance Rat.instRatCast : RatCast Rat where ratCast q := q.num // q.dentheorem declaration uses 'sorry'Rat.ratCast_inj : Function.Injective (fun n: (n:Rat)) := Function.Injective fun n => n All goals completed! 🐙theorem Rat.coe_Rat_eq (a:) {b:} (hb: b 0) : (a/b:) = a // b := a:b:hb:b 0(a / b) = a // b a:b:hb:b 0q: := _fvar.43387 / _fvar.43388q = a // b a:b:hb:b 0q: := _fvar.43387 / _fvar.43388num: := failed to pretty print expression (use 'set_option pp.rawOnError true' for raw representation)q = a // b a:b:hb:b 0q: := _fvar.43387 / _fvar.43388num: := failed to pretty print expression (use 'set_option pp.rawOnError true' for raw representation)den: := failed to pretty print expression (use 'set_option pp.rawOnError true' for raw representation)q = a // b have hden : den 0 := a:b:hb:b 0(a / b) = a // b All goals completed! 🐙 a:b:hb:b 0q: := _fvar.43387 / _fvar.43388num: := failed to pretty print expression (use 'set_option pp.rawOnError true' for raw representation)den: := failed to pretty print expression (use 'set_option pp.rawOnError true' for raw representation)hden:_fvar.43699 0 := ?_mvar.43808num // den = a // b a:b:hb:b 0q: := _fvar.43387 / _fvar.43388num: := failed to pretty print expression (use 'set_option pp.rawOnError true' for raw representation)den: := failed to pretty print expression (use 'set_option pp.rawOnError true' for raw representation)hden:_fvar.43699 0 := ?_mvar.43808num * b = a * den a:b:hb:b 0q: := _fvar.43387 / _fvar.43388num: := failed to pretty print expression (use 'set_option pp.rawOnError true' for raw representation)den: := failed to pretty print expression (use 'set_option pp.rawOnError true' for raw representation)hden:_fvar.43699 0 := ?_mvar.43808num * b = a * den a:b:hb:b 0q: := _fvar.43387 / _fvar.43388num: := failed to pretty print expression (use 'set_option pp.rawOnError true' for raw representation)den: := failed to pretty print expression (use 'set_option pp.rawOnError true' for raw representation)hden:_fvar.43699 0 := ?_mvar.43808hq:_fvar.43609 / _fvar.43699 = _fvar.43551 := Rat.num_div_den _fvar.43551num * b = a * den rwa [div_eq_div_iffa:b:hb:b 0q: := _fvar.43387 / _fvar.43388num: := failed to pretty print expression (use 'set_option pp.rawOnError true' for raw representation)den: := failed to pretty print expression (use 'set_option pp.rawOnError true' for raw representation)hden:_fvar.43699 0 := ?_mvar.43808hq:num * b = a * dennum * b = a * dena:b:hb:b 0q: := _fvar.43387 / _fvar.43388num: := failed to pretty print expression (use 'set_option pp.rawOnError true' for raw representation)den: := failed to pretty print expression (use 'set_option pp.rawOnError true' for raw representation)hden:_fvar.43699 0 := ?_mvar.43808hq:_fvar.43609 / _fvar.43699 = _fvar.43551 := Rat.num_div_den _fvar.43551den 0a:b:hb:b 0q: := _fvar.43387 / _fvar.43388num: := failed to pretty print expression (use 'set_option pp.rawOnError true' for raw representation)den: := failed to pretty print expression (use 'set_option pp.rawOnError true' for raw representation)hden:_fvar.43699 0 := ?_mvar.43808hq:_fvar.43609 / _fvar.43699 = _fvar.43551 := Rat.num_div_den _fvar.43551b 0 at hq a:b:hb:b 0q: := _fvar.43387 / _fvar.43388num: := failed to pretty print expression (use 'set_option pp.rawOnError true' for raw representation)den: := failed to pretty print expression (use 'set_option pp.rawOnError true' for raw representation)hden:_fvar.43699 0 := ?_mvar.43808hq:_fvar.43609 / _fvar.43699 = _fvar.43551 := Rat.num_div_den _fvar.43551den 0a:b:hb:b 0q: := _fvar.43387 / _fvar.43388num: := failed to pretty print expression (use 'set_option pp.rawOnError true' for raw representation)den: := failed to pretty print expression (use 'set_option pp.rawOnError true' for raw representation)hden:_fvar.43699 0 := ?_mvar.43808hq:_fvar.43609 / _fvar.43699 = _fvar.43551 := Rat.num_div_den _fvar.43551b 0 All goals completed! 🐙

Default definition of division

instance Rat.instDivInvMonoid : DivInvMonoid Rat where
theorem Rat.div_eq (q r:Rat) : q/r = q * r⁻¹ := q:Ratr:Ratq / r = q * r⁻¹ All goals completed! 🐙

Proposition 4.2.4 (laws of algebra) / Exercise 4.2.3

instance declaration uses 'sorry'declaration uses 'sorry'Rat.instField : Field Rat where exists_pair_ne := x y, x y All goals completed! 🐙 mul_inv_cancel := (a : Rat), a 0 a * a⁻¹ = 1 All goals completed! 🐙 inv_zero := rfl ratCast_def := (q : ), q = q.num / q.den q:q = q.num / q.den q:num: := failed to pretty print expression (use 'set_option pp.rawOnError true' for raw representation)q = num / q.den q:num: := failed to pretty print expression (use 'set_option pp.rawOnError true' for raw representation)den: := failed to pretty print expression (use 'set_option pp.rawOnError true' for raw representation)q = num / den have hden : (den:) 0 := (q : ), q = q.num / q.den All goals completed! 🐙 q:num: := failed to pretty print expression (use 'set_option pp.rawOnError true' for raw representation)den: := failed to pretty print expression (use 'set_option pp.rawOnError true' for raw representation)hden:_fvar.47889 0 := ?_mvar.48005(q.num / q.den) = num / den q:num: := failed to pretty print expression (use 'set_option pp.rawOnError true' for raw representation)den: := failed to pretty print expression (use 'set_option pp.rawOnError true' for raw representation)hden:_fvar.47889 0 := ?_mvar.48005num / den = q.num // den q:num: := failed to pretty print expression (use 'set_option pp.rawOnError true' for raw representation)den: := failed to pretty print expression (use 'set_option pp.rawOnError true' for raw representation)hden:_fvar.47889 0 := ?_mvar.48005num * 1 * den = q.num * (1 * den)q:num: := failed to pretty print expression (use 'set_option pp.rawOnError true' for raw representation)den: := failed to pretty print expression (use 'set_option pp.rawOnError true' for raw representation)hden:_fvar.47889 0 := ?_mvar.480051 * den 0q:num: := failed to pretty print expression (use 'set_option pp.rawOnError true' for raw representation)den: := failed to pretty print expression (use 'set_option pp.rawOnError true' for raw representation)hden:_fvar.47889 0 := ?_mvar.48005den 0q:num: := failed to pretty print expression (use 'set_option pp.rawOnError true' for raw representation)den: := failed to pretty print expression (use 'set_option pp.rawOnError true' for raw representation)hden:_fvar.47889 0 := ?_mvar.480051 0q:num: := failed to pretty print expression (use 'set_option pp.rawOnError true' for raw representation)den: := failed to pretty print expression (use 'set_option pp.rawOnError true' for raw representation)hden:_fvar.47889 0 := ?_mvar.48005den 0q:num: := failed to pretty print expression (use 'set_option pp.rawOnError true' for raw representation)den: := failed to pretty print expression (use 'set_option pp.rawOnError true' for raw representation)hden:_fvar.47889 0 := ?_mvar.480051 0 q:num: := failed to pretty print expression (use 'set_option pp.rawOnError true' for raw representation)den: := failed to pretty print expression (use 'set_option pp.rawOnError true' for raw representation)hden:_fvar.47889 0 := ?_mvar.48005num * 1 * den = q.num * (1 * den)q:num: := failed to pretty print expression (use 'set_option pp.rawOnError true' for raw representation)den: := failed to pretty print expression (use 'set_option pp.rawOnError true' for raw representation)hden:_fvar.47889 0 := ?_mvar.480051 * den 0q:num: := failed to pretty print expression (use 'set_option pp.rawOnError true' for raw representation)den: := failed to pretty print expression (use 'set_option pp.rawOnError true' for raw representation)hden:_fvar.47889 0 := ?_mvar.48005den 0q:num: := failed to pretty print expression (use 'set_option pp.rawOnError true' for raw representation)den: := failed to pretty print expression (use 'set_option pp.rawOnError true' for raw representation)hden:_fvar.47889 0 := ?_mvar.480051 0q:num: := failed to pretty print expression (use 'set_option pp.rawOnError true' for raw representation)den: := failed to pretty print expression (use 'set_option pp.rawOnError true' for raw representation)hden:_fvar.47889 0 := ?_mvar.48005den 0q:num: := failed to pretty print expression (use 'set_option pp.rawOnError true' for raw representation)den: := failed to pretty print expression (use 'set_option pp.rawOnError true' for raw representation)hden:_fvar.47889 0 := ?_mvar.480051 0 All goals completed! 🐙 qsmul := _ nnqsmul := _
declaration uses 'sorry'example : (3//4) / (5//6) = 9 // 10 := 3 // 4 / 5 // 6 = 9 // 10 All goals completed! 🐙def declaration uses 'sorry'declaration uses 'sorry'Rat.coe_int_hom : →+* Rat where toFun n := (n:Rat) map_zero' := rfl map_one' := rfl map_add' := (x y : ), (x + y) = x + y All goals completed! 🐙 map_mul' := (x y : ), (x * y) = x * y All goals completed! 🐙

Definition 4.2.6 (positivity)

def Rat.isPos (q:Rat) : Prop := a b:, a > 0 b > 0 q = a/b

Definition 4.2.6 (negativity)

def Rat.isNeg (q:Rat) : Prop := r:Rat, r.isPos q = -r

Lemma 4.2.7 (trichotomy of rationals) / Exercise 4.2.4

theorem declaration uses 'sorry'Rat.trichotomous (x:Rat) : x = 0 x.isPos x.isNeg := x:Ratx = 0 x.isPos x.isNeg All goals completed! 🐙

Lemma 4.2.7 (trichotomy of rationals) / Exercise 4.2.4

theorem declaration uses 'sorry'Rat.not_zero_and_pos (x:Rat) : ¬(x = 0 x.isPos) := x:Rat¬(x = 0 x.isPos) All goals completed! 🐙

Lemma 4.2.7 (trichotomy of rationals) / Exercise 4.2.4

theorem declaration uses 'sorry'Rat.not_zero_and_neg (x:Rat) : ¬(x = 0 x.isNeg) := x:Rat¬(x = 0 x.isNeg) All goals completed! 🐙

Lemma 4.2.7 (trichotomy of rationals) / Exercise 4.2.4

theorem declaration uses 'sorry'Rat.not_pos_and_neg (x:Rat) : ¬(x.isPos x.isNeg) := x:Rat¬(x.isPos x.isNeg) All goals completed! 🐙

Definition 4.2.8 (Ordering of the rationals)

instance Rat.instLT : LT Rat where lt x y := (x-y).isNeg

Definition 4.2.8 (Ordering of the rationals)

instance Rat.instLE : LE Rat where le x y := (x < y) (x = y)
theorem Rat.lt_iff (x y:Rat) : x < y (x-y).isNeg := x:Raty:Ratx < y (x - y).isNeg All goals completed! 🐙theorem Rat.le_iff (x y:Rat) : x y (x < y) (x = y) := x:Raty:Ratx y x < y x = y All goals completed! 🐙theorem declaration uses 'sorry'Rat.gt_iff (x y:Rat) : x > y (x-y).isPos := x:Raty:Ratx > y (x - y).isPos All goals completed! 🐙theorem declaration uses 'sorry'Rat.ge_iff (x y:Rat) : x y (x > y) (x = y) := x:Raty:Ratx y x > y x = y All goals completed! 🐙

Proposition 4.2.9(a) (order trichotomy) / Exercise 4.2.5

theorem declaration uses 'sorry'Rat.trichotomous' (x y:Rat) : x > y x < y x = y := x:Raty:Ratx > y x < y x = y All goals completed! 🐙

Proposition 4.2.9(a) (order trichotomy) / Exercise 4.2.5

theorem declaration uses 'sorry'Rat.not_gt_and_lt (x y:Rat) : ¬ (x > y x < y):= x:Raty:Rat¬(x > y x < y) All goals completed! 🐙

Proposition 4.2.9(a) (order trichotomy) / Exercise 4.2.5

theorem declaration uses 'sorry'Rat.not_gt_and_eq (x y:Rat) : ¬ (x > y x = y):= x:Raty:Rat¬(x > y x = y) All goals completed! 🐙

Proposition 4.2.9(a) (order trichotomy) / Exercise 4.2.5

theorem declaration uses 'sorry'Rat.not_lt_and_eq (x y:Rat) : ¬ (x < y x = y):= x:Raty:Rat¬(x < y x = y) All goals completed! 🐙

Proposition 4.2.9(b) (order is anti-symmetric) / Exercise 4.2.5

theorem declaration uses 'sorry'Rat.antisymm (x y:Rat) : x < y y > x := x:Raty:Ratx < y y > x All goals completed! 🐙

Proposition 4.2.9(c) (order is transitive) / Exercise 4.2.5

theorem declaration uses 'sorry'Rat.lt_trans {x y z:Rat} (hxy: x < y) (hyz: y < z) : x < z := x:Raty:Ratz:Rathxy:x < yhyz:y < zx < z All goals completed! 🐙

Proposition 4.2.9(d) (addition preserves order) / Exercise 4.2.5

theorem declaration uses 'sorry'Rat.add_lt_add_right {x y:Rat} (z:Rat) (hxy: x < y) : x + z < y + z := x:Raty:Ratz:Rathxy:x < yx + z < y + z All goals completed! 🐙

Proposition 4.2.9(e) (positive multiplication preserves order) / Exercise 4.2.5

theorem declaration uses 'sorry'Rat.mul_lt_mul_right {x y z:Rat} (hxy: x < y) (hz: z.isPos) : x * z < y * z := x:Raty:Ratz:Rathxy:x < yhz:z.isPosx * z < y * z All goals completed! 🐙

(Not from textbook) Establish the decidability of this order.

instance declaration uses 'sorry'declaration uses 'sorry'Rat.decidableRel : DecidableRel (· ·: Rat Rat Prop) := DecidableRel fun x1 x2 => x1 x2 n:Ratm:RatDecidable ((fun x1 x2 => x1 x2) n m) have : (n:PreRat) (m: PreRat), Decidable (Quotient.mk PreRat.instSetoid n Quotient.mk PreRat.instSetoid m) := DecidableRel fun x1 x2 => x1 x2 n:Ratm:Rata:b:hb:b 0c:d:hd:d 0Decidable ({ numerator := a, denominator := b, nonzero := hb } { numerator := c, denominator := d, nonzero := hd }) -- at this point, the goal is morally `Decidable(a//b ≤ c//d)`, but there are technical -- issues due to the junk value of formal division when the denominator vanishes. -- It may be more convenient to avoid formal division and work directly with `Quotient.mk`. cases (0:).decLe (b*d) with n:Ratm:Rata:b:hb:b 0c:d:hd:d 0hbd:0 b * dDecidable ({ numerator := a, denominator := b, nonzero := hb } { numerator := c, denominator := d, nonzero := hd }) cases (a * d).decLe (b * c) with n:Ratm:Rata:b:hb:b 0c:d:hd:d 0hbd:0 b * dh:a * d b * cDecidable ({ numerator := a, denominator := b, nonzero := hb } { numerator := c, denominator := d, nonzero := hd }) n:Ratm:Rata:b:hb:b 0c:d:hd:d 0hbd:0 b * dh:a * d b * c{ numerator := a, denominator := b, nonzero := hb } { numerator := c, denominator := d, nonzero := hd } All goals completed! 🐙 n:Ratm:Rata:b:hb:b 0c:d:hd:d 0hbd:0 b * dh:¬a * d b * cDecidable ({ numerator := a, denominator := b, nonzero := hb } { numerator := c, denominator := d, nonzero := hd }) n:Ratm:Rata:b:hb:b 0c:d:hd:d 0hbd:0 b * dh:¬a * d b * c¬{ numerator := a, denominator := b, nonzero := hb } { numerator := c, denominator := d, nonzero := hd } All goals completed! 🐙 n:Ratm:Rata:b:hb:b 0c:d:hd:d 0hbd:¬0 b * dDecidable ({ numerator := a, denominator := b, nonzero := hb } { numerator := c, denominator := d, nonzero := hd }) cases (b * c).decLe (a * d) with n:Ratm:Rata:b:hb:b 0c:d:hd:d 0hbd:¬0 b * dh:b * c a * dDecidable ({ numerator := a, denominator := b, nonzero := hb } { numerator := c, denominator := d, nonzero := hd }) n:Ratm:Rata:b:hb:b 0c:d:hd:d 0hbd:¬0 b * dh:b * c a * d{ numerator := a, denominator := b, nonzero := hb } { numerator := c, denominator := d, nonzero := hd } All goals completed! 🐙 n:Ratm:Rata:b:hb:b 0c:d:hd:d 0hbd:¬0 b * dh:¬b * c a * dDecidable ({ numerator := a, denominator := b, nonzero := hb } { numerator := c, denominator := d, nonzero := hd }) n:Ratm:Rata:b:hb:b 0c:d:hd:d 0hbd:¬0 b * dh:¬b * c a * d¬{ numerator := a, denominator := b, nonzero := hb } { numerator := c, denominator := d, nonzero := hd } All goals completed! 🐙 All goals completed! 🐙

(Not from textbook) Rat has the structure of a linear ordering.

instance declaration uses 'sorry'declaration uses 'sorry'declaration uses 'sorry'declaration uses 'sorry'declaration uses 'sorry'declaration uses 'sorry'Rat.instLinearOrder : LinearOrder Rat where le_refl := sorry le_trans := sorry lt_iff_le_not_ge := sorry le_antisymm := sorry le_total := sorry toDecidableLE := decidableRel

(Not from textbook) Rat has the structure of a strict ordered ring.

instance declaration uses 'sorry'Rat.instIsStrictOrderedRing : IsStrictOrderedRing Rat where add_le_add_left := (a b : Rat), a b (c : Rat), c + a c + b All goals completed! 🐙 add_le_add_right := (a b : Rat), a b (c : Rat), a + c b + c All goals completed! 🐙 mul_lt_mul_of_pos_left := (a b c : Rat), a < b 0 < c c * a < c * b All goals completed! 🐙 mul_lt_mul_of_pos_right := (a b c : Rat), a < b 0 < c a * c < b * c All goals completed! 🐙 le_of_add_le_add_left := (a b c : Rat), a + b a + c b c All goals completed! 🐙 zero_le_one := 0 1 All goals completed! 🐙

Exercise 4.2.6

theorem declaration uses 'sorry'Rat.mul_lt_mul_right_of_neg (x y z:Rat) (hxy: x < y) (hz: z.isNeg) : x * z > y * z := x:Raty:Ratz:Rathxy:x < yhz:z.isNegx * z > y * z All goals completed! 🐙

Not in textbook: create an equivalence between Rat and ℚ. This requires some familiarity with the API for Mathlib's version of the rationals.

abbrev declaration uses 'sorry'declaration uses 'sorry'declaration uses 'sorry'Rat.equivRat : Rat where toFun := Quotient.lift (fun a, b, h a / b) ( (a b : PreRat), a b (fun x => match x with | { numerator := a, denominator := b, nonzero := h } => a / b) a = (fun x => match x with | { numerator := a, denominator := b, nonzero := h } => a / b) b All goals completed! 🐙) invFun := fun n: (n:Rat) left_inv n := sorry right_inv n := sorry

Not in textbook: equivalence preserves order

abbrev declaration uses 'sorry'Rat.equivRat_order : Rat ≃o where toEquiv := equivRat map_rel_iff' := {a b : Rat}, equivRat a equivRat b a b All goals completed! 🐙

Not in textbook: equivalence preserves ring operations

abbrev declaration uses 'sorry'declaration uses 'sorry'Rat.equivRat_ring : Rat ≃+* where toEquiv := equivRat map_add' := (x y : Rat), equivRat.toFun (x + y) = equivRat.toFun x + equivRat.toFun y All goals completed! 🐙 map_mul' := (x y : Rat), equivRat.toFun (x * y) = equivRat.toFun x * equivRat.toFun y All goals completed! 🐙

(Not from textbook) The textbook rationals are isomorphic (as a field) to the Mathlib rationals.

def Rat.equivRat_ring_symm : ≃+* Rat := Rat.equivRat_ring.symm
end Section_4_2