mathlib documentation

lean_problem_sheets / 2020.integers.int_def_solns

def nat2.R (a b : × ) :
Prop

The equivalence relation on ℕ² such that equivalence classes are ℤ

Equations
@[protected, instance]
Equations
@[simp]
theorem nat2.R.equiv_def {i j k l : } :
(i, j) (k, l) i + l = k + j
theorem nat2.R.practice  :
(3, 5) (4, 6)
theorem nat2.R.reflexive (x : × ) :
x x
theorem nat2.R.symmetric (x y : × ) :
x yy x
theorem nat2.R.transitive (x y z : × ) :
x yy zx z
@[protected, instance]
Equations
def myint  :
Type

The integers are the equivalence classes of the equivalence relation we just defined on ℕ²

Equations

zero #

@[protected, instance]
Equations
theorem myint.zero_def  :
0 = (0, 0)

negation (additive inverse) #

def myint.neg_aux (x : × ) :
Equations
theorem myint.neg_aux_def (i j : ) :
myint.neg_aux (i, j) = (j, i)

Well-definedness #

OK now here's the concrete problem. We would like to define a negation map ℤ → ℤ sending z to -z. We want to do this in the following way: Say z ∈ ℤ. Choose a=(i,j) ∈ ℕ² representing z (i.e. such that cl(i,j) = ⟦(i,j)⟧ = z) Now apply neg_aux to a, and define -z to be the result.

The problem with this is that what if b is a different element of the equivalence class? Then we also want -z to be neg_aux b.

Indeed, in Lean this construction is called quotient.lift, and if you uncomment the below code

def myint.neg  :

Negation on on the integers. The function sending z to -z.

Equations
@[protected, instance]
Equations
theorem myint.neg_def (i j : ) :
-(i, j) = (j, i)

addition #

Our final construction: we want to define addition on myint. Here we have the same problem. Say z₁ and z₂ are integers. Choose elements a₁=(i,j) and a₂=(k,l) in ℕ². We want to define z₁ + z₂ to be ⟦(i+k,j+l)⟧, the equivalence class of a₁ + a₂. Let's make this definition now.

def myint.add_aux (x y : × ) :

An auxiliary function taking two elements of ℕ² and returning the equivalence class of their sum.

Equations
theorem myint.add_aux_def (i j k l : ) :
myint.add_aux (i, j) (k, l) = (i + k, j + l)
theorem myint.add_aux_lemma (x₁ x₂ y₁ y₂ : × ) :
x₁ y₁x₂ y₂myint.add_aux x₁ x₂ = myint.add_aux y₁ y₂
def myint.add  :
myintmyintmyint

Addition on the integers

Equations
@[protected, instance]
Equations
theorem myint.add_def (i j k l : ) :
(i, j) + (k, l) = (i + k, j + l)
theorem myint.zero_add (x : myint) :
0 + x = x
theorem myint.add_zero (x : myint) :
x + 0 = x
theorem myint.add_left_neg (x : myint) :
-x + x = 0
theorem myint.add_comm (x y : myint) :
x + y = y + x
theorem myint.add_assoc (x y z : myint) :
x + y + z = x + (y + z)
@[protected, instance]
Equations

multiplication #

What's left to define is 1 and multiplication (note that we don't need multiplicative inverses -- if a is a non-zero integer then a⁻¹ is typially not an integer)

def myint.mul_aux (x y : × ) :
Equations
theorem myint.mul_aux_def (i j k l : ) :
myint.mul_aux (i, j) (k, l) = (i * k + j * l, i * l + j * k)
theorem myint.mul_aux_lemma (x₁ x₂ y₁ y₂ : × ) :
x₁ y₁x₂ y₂myint.mul_aux x₁ x₂ = myint.mul_aux y₁ y₂
@[protected, instance]
Equations
theorem myint.mul_def (i j k l : ) :
(i, j) * (k, l) = (i * k + j * l, i * l + j * k)
theorem myint.mul_assoc (x y z : myint) :
(x * y) * z = x * y * z
def myint.one  :
Equations
@[protected, instance]
Equations
theorem myint.one_def  :
1 = (37, 36)
theorem myint.one_mul (x : myint) :
1 * x = x
theorem myint.mul_one (x : myint) :
x * 1 = x
theorem myint.mul_comm (x y : myint) :
x * y = y * x
theorem myint.mul_add (x y z : myint) :
x * (y + z) = x * y + x * z
theorem myint.add_mul (x y z : myint) :
(x + y) * z = x * z + y * z