import Option
import Base
union Nat {
zero
suc(Nat)
}
recursive operator +(Nat,Nat) -> Nat {
operator +(0, m) = m
operator +(suc(n), m) = suc(n + m)
}
recursive operator *(Nat,Nat) -> Nat {
operator *(0, m) = 0
operator *(suc(n), m) = m + (n * m)
}
recursive expt(Nat, Nat) -> Nat {
expt(0, n) = 1
expt(suc(p), n) = n * expt(p, n)
}
fun operator ^(a : Nat, b : Nat) {
expt(b, a)
}
recursive max(Nat,Nat) -> Nat {
max(zero, n) = n
max(suc(m'), n) =
switch n {
case zero { suc(m') }
case suc(n') { suc(max(m',n')) }
}
}
recursive min(Nat,Nat) -> Nat {
min(zero, n) = zero
min(suc(m'), n) =
switch n {
case zero { zero }
case suc(n') { suc(min(m',n')) }
}
}
fun pred(n : Nat) {
switch n {
case 0 { 0 }
case suc(n') { n' }
}
}
recursive operator -(Nat,Nat) -> Nat {
operator -(0, m) = 0
operator -(suc(n), m) =
switch m {
case 0 { suc(n) }
case suc(m') { n - m' }
}
}
recursive operator ≤(Nat,Nat) -> bool {
operator ≤(0, m) = true
operator ≤(suc(n'), m) =
switch m {
case 0 { false }
case suc(m') { n' ≤ m' }
}
}
fun operator < (x:Nat, y:Nat) {
suc(x) ≤ y
}
fun operator > (x:Nat, y:Nat) {
y < x
}
fun operator ≥ (x:Nat, y:Nat) {
y ≤ x
}
recursive summation(Nat, Nat, fn Nat->Nat) -> Nat {
summation(0, begin, f) = 0
summation(suc(k), begin, f) = f(begin) + summation(k, suc(begin), f)
}
recursive iterate<T>(Nat, T, fn T -> T) -> T {
iterate(0, init, f) = init
iterate(suc(n), init, f) = f(iterate(n, init, f))
}
recursive pow2(Nat) -> Nat {
pow2(0) = 1
pow2(suc(n')) = 2 * pow2(n')
}
private recursive div2_helper(Nat, bool) -> Nat {
div2_helper(0, b) = 0
div2_helper(suc(n'), b) =
if b then div2_helper(n', not b)
else suc(div2_helper(n', not b))
}
private fun div2(n : Nat) {
div2_helper(n, true)
}
private fun div2_aux(n : Nat) {
div2_helper(n, false)
}
recursive equal(Nat, Nat) -> bool {
equal(0, n) =
switch n {
case 0 { true }
case suc(n') { false }
}
equal(suc(m'), n) =
switch n {
case 0 { false }
case suc(n') { equal(m', n') }
}
}
recursive dist(Nat, Nat) -> Nat {
dist(0, n) = n
dist(suc(m), n) =
switch n {
case 0 {
suc(m)
}
case suc(n') {
dist(m, n')
}
}
}
theorem zero_add: all n:Nat.
0 + n = n
proof
arbitrary n:Nat
conclude 0 + n = n by definition operator+
end
theorem add_zero: all n:Nat.
n + 0 = n
proof
induction Nat
case 0 {
conclude 0 + 0 = 0 by definition operator+
}
case suc(n') suppose IH: n' + 0 = n' {
equations
suc(n') + 0 = suc(n' + 0) by definition operator+
... = suc(n') by replace IH
}
end
theorem suc_add: all m:Nat, n:Nat.
suc(m) + n = suc(m + n)
proof
arbitrary m:Nat, n:Nat
definition operator+
end
theorem suc_one_add: all n:Nat.
suc(n) = 1 + n
proof
arbitrary n:Nat
equations
suc(n) =# suc(0 + n) # by definition operator+
... = suc(0) + n by symmetric suc_add[0, n]
end
theorem one_add_suc: all n:Nat.
1 + n = suc(n)
proof
arbitrary n:Nat
symmetric suc_one_add[n]
end
theorem not_one_add_zero: all n:Nat.
not (1 + n = 0)
proof
arbitrary n:Nat
definition operator+
end
theorem add_suc: all m:Nat. all n:Nat.
m + suc(n) = suc(m + n)
proof
induction Nat
case 0 {
arbitrary n : Nat
conclude 0 + suc(n) = suc(0 + n) by evaluate
}
case suc(n') suppose IH {
arbitrary n : Nat
equations
suc(n') + suc(n) = suc(n' + suc(n)) by evaluate
... = suc(suc(n' + n)) by replace IH
... = suc(suc(n') + n) by evaluate
}
end
theorem add_commute: all n:Nat. all m:Nat. n + m = m + n
proof
induction Nat
case 0 {
arbitrary m : Nat
equations 0 + m = m by evaluate
... = m + 0 by symmetric add_zero[m]
}
case suc(n') suppose IH {
arbitrary m : Nat
equations suc(n') + m = suc(n' + m) by evaluate
... = suc(m + n') by replace IH
... = # m + suc(n') # by replace add_suc
}
end
theorem one_add: all m:Nat. 1 + m = suc(m)
proof
arbitrary m:Nat
definition 2 * operator+
end
theorem add_one: all m:Nat. m + 1 = suc(m)
proof
arbitrary m:Nat
equations
m + 1 = 1 + m by add_commute[m][1]
... = suc(m) by one_add[m]
end
theorem add_assoc: all m:Nat, n:Nat, o:Nat.
(m + n) + o = m + (n + o)
proof
induction Nat
case 0 {
arbitrary n:Nat, o:Nat
conclude (0 + n) + o = 0 + (n + o) by evaluate
}
case suc(m') suppose IH {
arbitrary n:Nat, o:Nat
equations
(suc(m') + n) + o = suc((m' + n) + o) by evaluate
... = suc(m' + (n + o)) by replace IH
... = suc(m') + (n + o) by evaluate
}
end
associative operator+ in Nat
theorem assoc_add: all m:Nat, n:Nat, o:Nat.
m + (n + o) = (m + n) + o
proof
arbitrary m:Nat, n:Nat, o:Nat
symmetric add_assoc
end
theorem add_both_sides_of_equal: all x:Nat. all y:Nat, z:Nat.
x + y = x + z ⇔ y = z
proof
induction Nat
case 0 {
arbitrary y:Nat, z:Nat
evaluate
}
case suc(x') suppose IH {
arbitrary y:Nat, z:Nat
suffices __ by definition operator+
have A: suc(x' + y) = suc(x' + z) ⇔ (x' + y = x' + z)
by { assume seq injective suc seq } , { assume eq replace eq }
have B: ((x' + y = x' + z) ⇔ (y = z)) by IH[y,z]
conclude ((suc(x' + y) = suc(x' + z)) ⇔ (y = z))
by apply iff_trans[suc(x' + y) = suc(x' + z), x' + y = x' + z, y = z]
to A, B
}
end
theorem left_cancel: all x:Nat. all y:Nat, z:Nat.
if x + y = x + z then y = z
proof
induction Nat
case 0 {
arbitrary y:Nat, z:Nat
suppose prem: 0 + y = 0 + z
equations y = 0 + y by evaluate
... = 0 + z by prem
... = z by evaluate
}
case suc(x') suppose IH: all y:Nat, z:Nat. if x' + y = x' + z then y = z {
arbitrary y:Nat, z:Nat
suppose prem: suc(x') + y = suc(x') + z
suffices y = z by .
apply IH[y,z] to {
suffices x' + y = x' + z by .
injective suc
conclude suc(x' + y) = suc(x' + z) by evaluate in prem
}
}
end
theorem add_to_zero: all n:Nat. all m:Nat.
if n + m = 0
then n = 0 and m = 0
proof
induction Nat
case 0 {
arbitrary m:Nat
suppose zmz
have: m = 0
by definition operator + in zmz
replace (recall m = 0)
}
case suc(n') suppose IH {
arbitrary m:Nat
suppose snmz: suc(n') + m = 0
conclude false
by definition operator + in snmz
}
end
theorem zero_sub: all x:Nat. 0 - x = 0
proof
evaluate
end
theorem sub_cancel: all n:Nat. n - n = 0
proof
induction Nat
case 0 {
conclude 0 - 0 = 0 by definition operator-
}
case suc(n') assume IH: n' - n' = 0 {
equations
suc(n') - suc(n') = n' - n' by definition operator-
... = 0 by IH
}
end
theorem sub_zero: all n:Nat.
n - 0 = n
proof
induction Nat
case 0 {
conclude 0 - 0 = 0 by definition operator-
}
case suc(n') suppose IH {
conclude suc(n') - 0 = suc(n') by definition operator-
}
end
theorem pred_one: pred(suc(0)) = 0
proof
definition pred
end
theorem pred_suc_n: all n:Nat. pred(suc(n)) = n
proof
evaluate
end
theorem sub_one_pred : all x : Nat. x - 1 = pred(x)
proof
induction Nat
case zero {
definition {pred, operator-}
}
case suc(x') {
definition { pred, operator- }
and replace sub_zero
}
end
theorem add_sub_identity: all m:Nat. all n:Nat.
(m + n) - m = n
proof
induction Nat
case 0 {
arbitrary n:Nat
equations (0 + n) - 0 = n - 0 by replace zero_add
... = n by sub_zero[n]
}
case suc(m') suppose IH {
arbitrary n:Nat
equations (suc(m') + n) - suc(m')
= suc(m' + n) - suc(m') by replace suc_add
... = (m' + n) - m' by definition operator-
... = n by IH[n]
}
end
theorem sub_sub_eq_sub_add : all x : Nat. all y:Nat. all z:Nat.
(x - y) - z = x - (y + z)
proof
induction Nat
case zero { definition operator- }
case suc(x') suppose IH{
arbitrary y :Nat
switch y {
case zero {
arbitrary z : Nat
replace sub_zero | zero_add
}
case suc(y') {
arbitrary x : Nat
switch x {
case zero {
replace sub_zero | add_zero
}
case suc(z') {
suffices (x' - y') - suc(z') = x' - (y' + suc(z'))
by definition { operator+, operator- }
IH[y'][suc(z')]
}
}
}
}
}
end
theorem sub_order : all x : Nat, y : Nat, z : Nat.
(x - y) - z = (x - z) - y
proof
arbitrary x : Nat, y : Nat, z : Nat
equations (x - y) - z = x - (y + z) by sub_sub_eq_sub_add
... = x - (z + y) by replace add_commute
... = #(x - z) - y# by replace sub_sub_eq_sub_add
end
theorem zero_mult: all n:Nat.
0 * n = 0
proof
arbitrary n:Nat
definition operator*
end
theorem mult_zero: all n:Nat.
n * 0 = 0
proof
induction Nat
case 0 {
conclude 0 * 0 = 0 by definition operator*
}
case suc(n') suppose IH {
equations suc(n') * 0 = 0 + n' * 0 by definition operator*
... = n' * 0 by zero_add[n'*0]
... = 0 by IH
}
end
theorem suc_mult: all m:Nat, n:Nat.
suc(m) * n = n + m * n
proof
arbitrary m:Nat, n:Nat
definition operator*
end
theorem mult_suc: all m:Nat. all n:Nat.
m * suc(n) = m + m * n
proof
induction Nat
case 0 {
arbitrary n:Nat
equations 0 * suc(n) = 0 by zero_mult[suc(n)]
... = 0 * n by symmetric zero_mult[n]
... = 0 + 0 * n by symmetric zero_add[0*n]
}
case suc(m') suppose IH: all n:Nat. m' * suc(n) = m' + m' * n {
arbitrary n:Nat
suffices suc(n + m' * suc(n)) = suc(m' + (n + m' * n))
by definition operator* | 2*operator+
equations suc(n + m' * suc(n))
= suc(n + m' + m' * n) by replace IH
... = suc(m' + n + m' * n) by replace add_commute[n][m']
}
end
theorem mult_commute: all m:Nat. all n:Nat.
m * n = n * m
proof
induction Nat
case 0 {
arbitrary n:Nat
equations 0 * n = 0 by zero_mult[n]
... = n * 0 by symmetric mult_zero[n]
}
case suc(m') suppose IH: all n:Nat. m' * n = n * m' {
arbitrary n:Nat
equations suc(m') * n
= n + m' * n by definition operator*
... = n + (n * m') by replace IH
... = n * suc(m') by symmetric mult_suc[n][m']
}
end
theorem one_mult: all n:Nat.
1 * n = n
proof
arbitrary n:Nat
equations 1 * n = n + 0 * n by suc_mult[0,n]
... = n + 0 by replace zero_mult
... = n by add_zero[n]
end
theorem mult_one: all n:Nat.
n * 1 = n
proof
arbitrary n:Nat
equations n * 1 = 1 * n by mult_commute[n][1]
... = n by one_mult[n]
end
theorem mult_to_zero : all n :Nat, m : Nat.
if m * n = 0 then m = 0 or n = 0
proof
arbitrary n : Nat, m :Nat
switch n {
case 0 { . }
case suc(n') assume eq_sn_t {
switch m {
case 0 { . }
case suc(m') assume eq_sm_t {
evaluate
}
}
}
}
end
theorem one_mult_one : all x : Nat, y : Nat.
if x * y = 1 then x = 1 and y = 1
proof
arbitrary x : Nat, y : Nat
switch x {
case 0 {
definition operator*
}
case suc(x') suppose IH {
switch y {
case 0 {
rewrite mult_zero[suc(x')]
}
case suc(y') {
suffices (if suc(y' + x' * suc(y')) = 1 then (suc(x') = 1 and suc(y') = 1))
by definition { operator*, operator+ }
suppose prem
have blah : y' + x' * suc(y') = 0
by injective suc
prem
have y'_zero : y' = 0 by apply add_to_zero to blah
have x'sy'_zero : x' * suc(y') = 0 by apply add_to_zero to blah
have x'_zero : x' = 0
by switch x' {case 0 {
.
}
case suc(n') suppose x_sn' {
definition { operator*, operator+ } in rewrite x_sn' in x'sy'_zero
}}
rewrite x'_zero | y'_zero
}}
}}
end
theorem two_mult: all n:Nat.
2 * n = n + n
proof
arbitrary n:Nat
equations 2 * n = n + 1 * n by suc_mult[1,n]
... = n + n by replace one_mult
end
theorem dist_mult_add:
all a:Nat, x:Nat, y:Nat.
a * (x + y) = a * x + a * y
proof
induction Nat
case zero {
arbitrary x:Nat, y:Nat
equations 0 * (x + y)
= 0 by zero_mult[x+y]
... = 0 + 0 by symmetric add_zero[0]
... =# 0 * x + 0 * y # by replace zero_mult
}
case suc(a') suppose IH {
arbitrary x:Nat, y:Nat
suffices (x + y) + a' * (x + y) = (x + a' * x) + (y + a' * y)
by definition operator *
equations
(x + y) + a' * (x + y)
= x + y + a'*x + a'*y by replace IH
... = x + a'*x + y + a'*y by replace add_commute[y, a'*x]
}
end
theorem dist_mult_add_right:
all x:Nat, y:Nat, a:Nat.
(x + y) * a = x * a + y * a
proof
arbitrary x:Nat, y:Nat, a:Nat
equations
(x + y) * a = a * (x + y) by replace mult_commute
... = a * x + a * y by dist_mult_add[a][x,y]
... = x * a + y * a by replace mult_commute
end
theorem mult_assoc: all m:Nat. all n:Nat, o:Nat.
(m * n) * o = m * (n * o)
proof
induction Nat
case 0 {
arbitrary n:Nat, o:Nat
equations (0 * n) * o = 0 * o by replace zero_mult
... = 0 by zero_mult[o]
... = 0 * (n * o) by symmetric zero_mult[n*o]
}
case suc(m') suppose IH: all n:Nat, o:Nat. (m' * n) * o = m' * (n * o) {
arbitrary n:Nat, o:Nat
equations
(suc(m') * n) * o
= (n + m' * n) * o by definition operator*
... = n * o + (m' * n) * o by dist_mult_add_right[n, m'*n, o]
... = n * o + m' * (n * o) by replace IH
... =# suc(m') * (n * o) # by definition operator*
}
end
associative operator* in Nat
theorem mult_right_cancel : all m : Nat, n : Nat, o : Nat.
if m * suc(o) = n * suc(o) then m = n
proof
induction Nat
case 0 {
arbitrary n:Nat, o:Nat
switch n {
case 0 { . }
case suc(n') {
assume contra: 0 * suc(o) = suc(n') * suc(o)
conclude false by evaluate in contra
}
}
}
case suc(m') assume IH {
arbitrary n:Nat, o:Nat
switch n {
case 0 {
assume contra: suc(m') * suc(o) = 0 * suc(o)
conclude false by evaluate in contra
}
case suc(n') {
assume prem: suc(m') * suc(o) = suc(n') * suc(o)
have prem2: suc(o) + m' * suc(o) = suc(o) + n' * suc(o)
by definition operator* in prem
have prem3: m' * suc(o) = n' * suc(o)
by apply left_cancel to prem2
have: m' = n' by apply IH to prem3
conclude suc(m') = suc(n') by replace recall m' = n'
}
}
}
end
theorem mult_left_cancel : all m : Nat, a : Nat, b : Nat.
if suc(m) * a = suc(m) * b then a = b
proof
arbitrary m:Nat, a:Nat, b:Nat
assume prem: suc(m) * a = suc(m) * b
have prem2: a * suc(m) = b * suc(m) by rewrite mult_commute in prem
conclude a = b by apply mult_right_cancel to prem2
end
theorem suc_less_equal_iff_less_equal_suc: all x:Nat, y:Nat.
x ≤ y ⇔ suc(x) ≤ suc(y)
proof
arbitrary x:Nat, y:Nat
have sle : if x ≤ y then suc(x) ≤ suc(y)
by suppose prem
suffices x ≤ y by definition operator≤
prem
have els : if suc(x) ≤ suc(y) then x ≤ y
by suppose prem
definition operator≤ in prem
sle, els
end
theorem less_suc_iff_suc_less: all x:Nat, y:Nat.
x < y ⇔ suc(x) < suc(y)
proof
arbitrary x:Nat, y:Nat
have ls : if x < y then suc(x) < suc(y)
by suppose x_l_y
suffices suc(x) ≤ y by definition {operator<, operator≤}
definition operator< in x_l_y
have sl : if suc(x) < suc(y) then x < y
by suppose sx_l_sy
suffices suc(x) ≤ y by definition operator<
apply suc_less_equal_iff_less_equal_suc[suc(x), y]
to definition operator< in sx_l_sy
ls, sl
end
theorem not_less_zero:
all x:Nat. not (x < 0)
proof
definition {operator<, operator≤}
end
theorem less_equal_implies_less_or_equal:
all x:Nat. all y:Nat.
if x ≤ y then x < y or x = y
proof
induction Nat
case 0 {
arbitrary y:Nat
switch y {
case 0 {
.
}
case suc(y') {
suppose _
suffices suc(0) ≤ suc(y') by definition operator<
suffices 0 ≤ y' by definition operator≤
definition operator≤
}
}
}
case suc(x') suppose IH {
arbitrary y:Nat
suppose sx_le_y
switch y {
case 0 suppose yz {
conclude false by definition operator≤ in replace yz in sx_le_y
}
case suc(y') suppose y_sy {
have: x' ≤ y'
by definition operator≤ in replace y_sy in sx_le_y
have: x' < y' or x' = y'
by IH[y'], recall x' ≤ y'
cases (recall x' < y' or x' = y')
case x_l_y {
have sx_l_sy: suc(x') < suc(y')
by apply less_suc_iff_suc_less to x_l_y
conclude (suc(x') < suc(y') or suc(x') = suc(y'))
by sx_l_sy
}
case x_y {
have sx_sy: suc(x') = suc(y')
by replace x_y
conclude (suc(x') < suc(y') or suc(x') = suc(y'))
by sx_sy
}
}
}
}
end
theorem less_equal_not_equal_implies_less:
all x:Nat, y:Nat.
if x ≤ y and not (x = y) then x < y
proof
arbitrary x:Nat, y:Nat
assume prem: x ≤ y and not (x = y)
have LE: x < y or x = y by apply less_equal_implies_less_or_equal[x,y] to prem
cases LE
case less { less }
case eq { conclude false by apply prem to eq }
end
theorem less_implies_less_equal:
all x:Nat. all y:Nat.
if x < y then x ≤ y
proof
induction Nat
case zero {
arbitrary y:Nat
suppose _
conclude 0 ≤ y by definition operator ≤
}
case suc(x') suppose IH {
arbitrary y:Nat
suppose sx_y: suc(x') < y
have ssx_y: suc(suc(x')) ≤ y by definition operator < in sx_y
switch y {
case zero suppose yz {
conclude false by definition operator ≤ in (replace yz in ssx_y)
}
case suc(y') suppose EQ : y = suc(y') {
have ssx_sy: suc(suc(x')) ≤ suc(y') by replace EQ in ssx_y
have: x' < y'
by suffices suc(x') ≤ y' by definition operator <
definition operator ≤ in ssx_sy
suffices suc(x') ≤ suc(y') by .
suffices x' ≤ y' by definition operator ≤
IH[y'], recall x' < y'
}
}
}
end
theorem less_equal_refl: all n:Nat. n ≤ n
proof
induction Nat
case 0 { conclude 0 ≤ 0 by evaluate }
case suc(n') suppose IH {
suffices n' ≤ n' by evaluate
IH
}
end
theorem equal_implies_less_equal: all x:Nat, y:Nat.
if x = y then x ≤ y
proof
arbitrary x:Nat, y:Nat
suppose x_y
suffices y ≤ y by replace x_y
less_equal_refl[y]
end
theorem less_equal_antisymmetric:
all x:Nat. all y:Nat.
if x ≤ y and y ≤ x
then x = y
proof
induction Nat
case zero {
arbitrary y:Nat
suppose zy_yz: 0 ≤ y and y ≤ 0
switch y {
case zero { . }
case suc(y') suppose y_suc {
have sy_z: suc(y') ≤ 0 by replace y_suc in zy_yz
conclude false by definition operator ≤ in sy_z
}
}
}
case suc(x') suppose IH {
arbitrary y:Nat
suppose sxy_ysx: suc(x') ≤ y and y ≤ suc(x')
switch y {
case zero suppose y_z {
have: suc(x') ≤ 0 by replace y_z in sxy_ysx
conclude false by definition operator ≤ in (recall suc(x') ≤ 0)
}
case suc(y') suppose y_suc {
have: x' ≤ y' by evaluate in replace y_suc in sxy_ysx
have: y' ≤ x' by evaluate in replace y_suc in sxy_ysx
have: x' = y' by IH[y'], (recall x' ≤ y', y' ≤ x')
conclude suc(x') = suc(y') by replace (recall x' = y')
}
}
}
end
theorem less_equal_trans: all m:Nat. all n:Nat, o:Nat.
if m ≤ n and n ≤ o then m ≤ o
proof
induction Nat
case 0 {
arbitrary n:Nat, o:Nat
suppose _
conclude 0 ≤ o by evaluate
}
case suc(m') suppose IH {
arbitrary n:Nat, o:Nat
suppose Prem: suc(m') ≤ n and n ≤ o
have: suc(m') ≤ n by Prem
have: n ≤ o by Prem
switch n {
case 0 suppose nz {
have: suc(m') ≤ 0 by replace nz in (recall suc(m') ≤ n)
conclude false by evaluate in recall suc(m') ≤ 0
}
case suc(n') suppose: n = suc(n') {
have sm_sn: suc(m') ≤ suc(n')
by replace (recall n = suc(n')) in (recall suc(m') ≤ n)
have: m' ≤ n' by evaluate in sm_sn
have: suc(n') ≤ o by replace (recall n = suc(n')) in (recall n ≤ o)
switch o {
case 0 suppose: o = 0 {
have: suc(n') ≤ 0 by replace (recall o = 0) in (recall suc(n') ≤ o)
conclude false by evaluate in recall suc(n') ≤ 0
}
case suc(o') suppose os {
have: suc(n') ≤ suc(o') by replace os in (recall suc(n') ≤ o)
have: n' ≤ o' by evaluate in recall suc(n') ≤ suc(o')
suffices m' ≤ o' by evaluate
IH[n',o'], recall m' ≤ n', n' ≤ o'
}
}
}
}
}
end
theorem not_less_implies_less_equal:
all x: Nat. all y: Nat.
if not (x < y) then y ≤ x
proof
induction Nat
case zero {
arbitrary y: Nat
suppose not_0_y: not (0 < y)
switch y {
case zero { definition operator ≤ }
case suc(y') suppose ys {
conclude false by apply (replace ys in not_0_y)
to (suffices 1 ≤ suc(y') by definition operator <
definition {operator ≤,operator ≤})
}
}
}
case suc(x') suppose IH {
arbitrary y: Nat
suppose not_sx_y: not (suc(x') < y)
switch y {
case zero { definition operator ≤ }
case suc(y') suppose ys {
have not_x_y: not (x' < y')
by (suppose x_y: x' < y'
have sx_sy: suc(x') < suc(y')
by suffices suc(suc(x')) ≤ suc(y') by definition operator <
suffices suc(x') ≤ y' by definition operator ≤
(definition operator < in x_y)
have sx_y: suc(x') < y by (suffices suc(x') < suc(y') by replace ys
sx_sy)
apply not_sx_y to sx_y)
suffices y' ≤ x' by definition operator ≤
apply IH[y'] to not_x_y
}
}
}
end
theorem less_irreflexive: all x:Nat. not (x < x)
proof
induction Nat
case zero {
suppose z_l_z: 0 < 0
conclude false by evaluate in z_l_z
}
case suc(x') suppose IH: not (x' < x') {
suppose sx_l_sx: suc(x') < suc(x')
have x_l_x: x' < x' by apply less_suc_iff_suc_less to sx_l_sx
conclude false by apply IH to x_l_x
}
end
theorem less_not_equal: all x:Nat, y:Nat.
if x < y then not (x = y)
proof
arbitrary x:Nat, y:Nat
suppose: x < y
suppose: x = y
have: y < y by replace (recall x = y) in recall x < y
have: not (y < y) by less_irreflexive
conclude false by recall y < y, not (y < y)
end
theorem greater_not_equal: all x:Nat, y:Nat.
if x > y then not (x = y)
proof
arbitrary x:Nat, y:Nat
suppose: x > y
suppose: x = y
have: y > y by replace (recall x = y) in (recall x > y)
have: y < y by definition operator> in recall y > y
have: not (y < y) by less_irreflexive
conclude false by recall y < y, not (y < y)
end
theorem trichotomy:
all x:Nat. all y:Nat.
x < y or x = y or y < x
proof
induction Nat
case zero {
arbitrary y:Nat
switch y {
case zero { conclude 0 = 0 by . }
case suc(y') {
conclude 0 < suc(y') by definition operator < | 2 * operator ≤
}
}
}
case suc(x') suppose IH {
arbitrary y:Nat
switch y {
case zero {
conclude 0 < suc(x')
by definition operator< | 2 * operator≤
}
case suc(y') {
have IH': (x' < y' or x' = y' or y' < x') by IH[y']
cases IH'
case less { conclude suc(x') < suc(y')
by suffices suc(suc(x')) ≤ suc(y') by definition operator <
suffices suc(x') ≤ y' by definition operator ≤
definition operator < in less
}
case x_eq_y { conclude suc(x') = suc(y') by replace x_eq_y }
case greater {
conclude suc(y') < suc(x')
by suffices suc(suc(y')) ≤ suc(x') by definition operator <
suffices suc(y') ≤ x' by definition operator ≤
definition operator < in greater
}
}
}
}
end
theorem trichotomy2:
all y:Nat, x:Nat.
if not (x = y) and not (x < y)
then y < x
proof
arbitrary y:Nat, x:Nat
suppose prem: not (x = y) and not (x < y)
cases trichotomy[x][y]
case less: x < y {
have not_less: not (x < y) by prem
conclude false by apply not_less to less
}
case x_eq_y: x = y {
have not_equal: not (x = y) by prem
conclude false by apply not_equal to x_eq_y
}
case greater: y < x {
conclude y < x by greater
}
end
lemma positive_1_and_2: 0 ≤ 1 and 0 ≤ 2
proof
have one_pos: 0 ≤ 1 by definition operator ≤
have two_pos: 0 ≤ 2 by definition operator ≤
conclude 0 ≤ 1 and 0 ≤ 2 by one_pos, two_pos
end
lemma positive_2: 0 ≤ 2
proof
conclude 0 ≤ 2 by positive_1_and_2
end
theorem dichotomy: all x:Nat, y:Nat. x ≤ y or y < x
proof
arbitrary x:Nat, y:Nat
have tri: x < y or x = y or y < x by trichotomy[x][y]
cases tri
case x_l_y: x < y {
have x_le_y: x ≤ y by apply less_implies_less_equal[x][y] to x_l_y
conclude x ≤ y or y < x by x_le_y
}
case x_eq_y: x = y {
have x_le_y: x ≤ y by suffices y ≤ y by replace x_eq_y
less_equal_refl[y]
conclude x ≤ y or y < x by x_le_y
}
case y_l_x: y < x {
conclude x ≤ y or y < x by y_l_x
}
end
theorem zero_or_positive: all x:Nat. x = 0 or 0 < x
proof
arbitrary x:Nat
switch x {
case zero {
conclude true or 0 < 0 by .
}
case suc(x') {
have z_l_sx: 0 < suc(x')
by definition operator < | 2 * operator ≤
conclude suc(x') = 0 or 0 < suc(x') by z_l_sx
}
}
end
theorem zero_le_zero: all x:Nat. if x ≤ 0 then x = 0
proof
induction Nat
case zero {
suppose _
.
}
case suc(x') {
suppose prem: suc(x') ≤ 0
conclude false by definition operator ≤ in prem
}
end
theorem not_less_equal_iff_greater:
all x:Nat, y:Nat.
not (x ≤ y) ⇔ (y < x)
proof
arbitrary x:Nat, y:Nat
have nle_g : if not (x ≤ y) then y < x
by suppose not_xy
cases dichotomy[x,y]
case x_le_y { apply not_xy to x_le_y }
case y_l_x { y_l_x }
have g_nle : if y < x then not (x ≤ y)
by suppose ylx
have y_le_x : y ≤ x by apply less_implies_less_equal to ylx
suppose label : x ≤ y
have xy_a_yx : x ≤ y and y ≤ x by y_le_x, label
have y_e_x: y=x by symmetric (apply less_equal_antisymmetric to xy_a_yx)
have x_ne_y: not (y = x) by apply less_not_equal to ylx
replace y_e_x in x_ne_y
nle_g, g_nle
end
theorem less_implies_not_greater:
all x:Nat. all y:Nat.
if x < y then not (y < x)
proof
induction Nat
case zero {
arbitrary y:Nat
suppose zero_less_y
suppose y_less_zero
conclude false by (definition {operator <, operator ≤} in y_less_zero)
}
case suc(x') suppose IH {
arbitrary y:Nat
suppose sx_less_y: suc(x') < y
suppose y_less_sx: y < suc(x')
switch y {
case zero suppose y_eq_zero {
conclude false by (definition {operator <, operator ≤} in
(replace y_eq_zero in sx_less_y))
}
case suc(y') suppose ys {
have x_less_y: x' < y' by {
suffices __ by evaluate
evaluate in replace ys in sx_less_y
}
have y_less_x: y' < x' by {
suffices __ by evaluate
evaluate in replace ys in y_less_sx
}
conclude false by apply (apply IH[y'] to x_less_y) to y_less_x
}
}
}
end
theorem not_less_equal_less_equal:
all x:Nat, y:Nat.
if not (x ≤ y) then y ≤ x
proof
arbitrary x:Nat, y:Nat
suppose not_xy
have y_l_x: y < x by apply not_less_equal_iff_greater to not_xy
apply less_implies_less_equal to y_l_x
end
theorem not_zero_suc: all n:Nat.
if not (n = 0)
then some n':Nat. n = suc(n')
proof
arbitrary n:Nat
switch n {
case 0 { . }
case suc(n') {
choose n'.
}
}
end
theorem positive_suc: all n:Nat.
if 0 < n
then some n':Nat. n = suc(n')
proof
arbitrary n:Nat
switch n {
case 0 {
suppose z_l_z: 0 < 0
conclude false by definition {operator<, operator≤} in z_l_z
}
case suc(n') {
suppose z_l_sn: 0 < suc(n')
choose n'.
}
}
end
theorem less_equal_add: all x:Nat. all y:Nat.
x ≤ x + y
proof
induction Nat
case 0 {
arbitrary y:Nat
conclude 0 ≤ 0 + y by definition operator ≤
}
case suc(x') suppose IH {
arbitrary y:Nat
suffices x' ≤ x' + y by definition {operator +, operator ≤}
IH[y]
}
end
theorem less_equal_add_left: all x:Nat, y:Nat.
y ≤ x + y
proof
arbitrary x:Nat, y:Nat
suffices y ≤ y + x by replace add_commute
less_equal_add[y][x]
end
theorem less_equal_suc: all n:Nat.
n ≤ suc(n)
proof
arbitrary n:Nat
definition 2 * operator+ in
replace add_commute in
less_equal_add[n][1]
end
theorem add_mono: all a:Nat, b:Nat, c:Nat, d:Nat.
if a ≤ c and b ≤ d
then a + b ≤ c + d
proof
induction Nat
case 0 {
arbitrary b:Nat, c:Nat, d:Nat
assume prem
suffices __ by replace zero_add
have bd: b ≤ d by prem
have d_dc: d ≤ d + c by less_equal_add
have d_cd: d ≤ c + d by replace add_commute in d_dc
conclude b ≤ c + d by apply less_equal_trans to bd, d_cd
}
case suc(a') assume IH {
arbitrary b:Nat, c:Nat, d:Nat
assume prem
have b_d: b ≤ d by prem
switch c {
case 0 assume cz {
conclude false by evaluate in replace cz in prem
}
case suc(c') assume cs {
have a_c: a' ≤ c' by evaluate in replace cs in prem
suffices __ by definition operator+ | operator≤
conclude a' + b ≤ c' + d by apply IH to a_c, b_d
}
}
}
end
theorem add_pos_nonneg : all a : Nat, b : Nat.
if 0 < a then 0 < a + b
proof
arbitrary a : Nat, b : Nat
assume prem
switch b {
case 0 assume eq_z_t {
suffices 0 < a by rewrite add_zero
prem
}
case suc(b') assume eq_sn_t {
suffices 0 < suc(a + b') by rewrite add_suc
evaluate
}
}
end
theorem less_one_add: all n:Nat.
0 < 1 + n
proof
arbitrary n:Nat
definition {operator<, operator≤, operator+, operator≤}
end
theorem add_both_sides_of_less_equal: all x:Nat. all y:Nat, z:Nat.
x + y ≤ x + z ⇔ y ≤ z
proof
induction Nat
case 0 {
definition operator+
}
case suc(x') suppose IH {
suffices (all y:Nat, z:Nat. (x' + y ≤ x' + z ⇔ y ≤ z))
by definition {operator+, operator≤}
IH
}
end
theorem add_both_sides_of_less: all x:Nat, y:Nat, z:Nat.
x + y < x + z ⇔ y < z
proof
arbitrary x:Nat, y:Nat, z:Nat
suffices suc(x + y) ≤ x + z ⇔ suc(y) ≤ z by definition operator<
suffices (x + suc(y) ≤ x + z ⇔ suc(y) ≤ z)
by replace add_commute[x][y]
| symmetric (definition operator+ in add_commute[x][suc(y)])
add_both_sides_of_less_equal[x][suc(y), z]
end
theorem mult_mono_le : all n : Nat. all x : Nat, y : Nat.
if x ≤ y then n * x ≤ n * y
proof
induction Nat
case zero {
definition {operator*, operator≤}
}
case suc(n') suppose IH {
arbitrary x:Nat, y:Nat
suppose prem : x ≤ y
suffices x + n' * x ≤ y + n' * y by definition operator*
have nx_le_ny : n' * x ≤ n' * y by apply IH to prem
have nyx_le_nyy : n' * y + x ≤ n' * y + y
by apply add_both_sides_of_less_equal[n'*y][x, y] to prem
have xny_le_yny : x + n' * y ≤ y + n' * y
by replace add_commute[n'*y][x]
| add_commute[n'*y][y]
in nyx_le_nyy
have xnx_le_xny : x + n' * x ≤ x + n' * y
by apply add_both_sides_of_less_equal[x][n'*x, n'*y] to nx_le_ny
apply less_equal_trans to xnx_le_xny, xny_le_yny
}
end
theorem mult_mono_le_r : all n : Nat. all x : Nat, y : Nat.
if x ≤ y then x * n ≤ y * n
proof
arbitrary n : Nat, x : Nat, y : Nat
rewrite mult_commute[n, x] | mult_commute[n, y] in mult_mono_le[n, x, y]
end
theorem sub_add_assoc: all n:Nat. all l:Nat,m:Nat.
if m ≤ n
then l + (n - m) = (l + n) - m
proof
induction Nat
case 0 {
arbitrary l:Nat, m:Nat
suppose m_le_z: m ≤ 0
suffices l + 0 = (l + 0) - m by definition operator-
suffices l = l - m by replace add_zero
have m_z: m = 0 by apply zero_le_zero to m_le_z
replace m_z | sub_zero[l]
}
case suc(n') suppose IH {
arbitrary l:Nat, m:Nat
suppose m_le_sn
switch m {
case 0 {
suffices l + suc(n') = (l + suc(n')) - 0 by definition {operator-}
replace sub_zero
}
case suc(m') suppose m_sm {
suffices l + (n' - m') = (l + suc(n')) - suc(m')
by definition {operator-}
suffices l + (n' - m') = suc(l + n') - suc(m')
by replace add_suc
suffices l + (n' - m') = (l + n') - m'
by definition operator-
have m_n: m' ≤ n'
by definition operator ≤ in replace m_sm in m_le_sn
apply IH[l, m'] to m_n
}
}
}
end
theorem sub_suc_identity: all n:Nat.
if 0 < n then suc(n - 1) = n
proof
arbitrary n:Nat
assume: 0 < n
have X: 1 + (n - 1) = (1 + n) - 1 by apply sub_add_assoc[n,1,1] to definition operator< in recall 0 < n
have Y: (1 + n) - 1 = n by add_sub_identity
equations
suc(n - 1) = #1 + (n - 1)# by definition 2*operator+
... = (1 + n) - 1 by apply sub_add_assoc[n,1,1] to definition operator< in recall 0 < n
... = n by add_sub_identity
end
theorem sub_add_identity: all n:Nat. all m:Nat.
if m ≤ n
then m + (n - m) = n
proof
induction Nat
case 0 {
arbitrary m:Nat
suppose m_le_z
suffices m + (0 - m) = 0 by .
have m_z: m = 0 by apply zero_le_zero to m_le_z
suffices 0 + (0 - 0) = 0 by replace m_z
definition {operator-, operator+}
}
case suc(n') suppose IH {
arbitrary m:Nat
suppose m_le_sn
suffices m + (suc(n') - m) = suc(n') by .
switch m {
case 0 {
conclude 0 + (suc(n') - 0) = suc(n') by definition {operator-,operator+}
}
case suc(m') suppose m_sm {
suffices suc(m') + (suc(n') - suc(m')) = suc(n') by .
suffices suc(m' + (n' - m')) = suc(n')
by definition {operator-,operator+}
have m_n: m' ≤ n' by definition operator≤ in replace m_sm in m_le_sn
have IH_m: m' + (n' - m') = n' by apply IH[m'] to m_n
replace IH_m
}
}
}
end
theorem sub_right_cancel: all x:Nat, y:Nat, a:Nat.
if x - a = y - a and a ≤ x and a ≤ y
then x = y
proof
arbitrary x:Nat, y:Nat, a:Nat
assume prem
have eq1: x - a = y - a by prem
have eq2: (x - a) + a = (y - a) + a by replace eq1
have eq3: a + (x - a) = a + (y - a) by replace add_commute in eq2
conclude x = y by replace (apply sub_add_identity[x,a] to prem)
| (apply sub_add_identity[y,a] to prem) in eq3
end
theorem less_equal_add_sub: all m:Nat. all n:Nat, o:Nat.
if n ≤ m and m ≤ n + o
then m - n ≤ o
proof
induction Nat
case 0 {
arbitrary n:Nat, o:Nat
suppose prem
definition {operator -, operator ≤}
}
case suc(m') suppose IH {
arbitrary n:Nat, o:Nat
suppose prem
switch n {
case 0 suppose n_z {
suffices suc(m') ≤ o by definition operator -
conclude suc(m') ≤ o
by definition operator+ in replace n_z in prem
}
case suc(n') suppose n_sn {
suffices m' - n' ≤ o by definition operator-
have n_m: n' ≤ m'
by definition operator ≤ in replace n_sn
in conjunct 0 of prem
have m_no: m' ≤ n' + o
by definition {operator ≤, operator +} in replace n_sn in
conjunct 1 of prem
conclude m' - n' ≤ o by apply IH[n',o] to n_m, m_no
}
}
}
end
theorem sub_zero_iff_less_eq : all x : Nat, y : Nat. x ≤ y ⇔ x - y = 0
proof
induction Nat
case 0 {
conclude all y : Nat. 0 ≤ y ⇔ 0 - y = 0
by definition {operator≤, operator-}
}
case suc(x') suppose IH {
arbitrary y : Nat
switch y {
case 0 {
suffices not (suc(x') ≤ 0) by definition operator-
assume sx_le_z
apply zero_le_zero[suc(x')] to sx_le_z
}
case suc(y') {
suffices x' ≤ y' ⇔ x' - y' = 0
by definition {operator≤, operator-}
IH[y']
}
}
}
end
theorem sub_pos_iff_less: all x: Nat, y:Nat. y < x ⇔ 0 < x - y
proof
induction Nat
case 0 {
arbitrary y:Nat
have fwd: if y < 0 then 0 < 0 - y by
definition {operator<, operator≤}
have bkwd: if 0 < 0 - y then y < 0 by
definition {operator-, operator<, operator≤}
fwd, bkwd
}
case suc(x') assume IH {
arbitrary y:Nat
switch y {
case 0 {
have fwd: if 0 < suc(x') then 0 < suc(x') - 0
by assume _ definition operator- | operator< | 2* operator≤
have bkwd: if 0 < suc(x') - 0 then 0 < suc(x')
by assume _ definition operator< | 2*operator≤
fwd, bkwd
}
case suc(y') {
have IH': y' < x' ⇔ 0 < x' - y' by IH[y']
suffices suc(y') < suc(x') ⇔ 0 < x' - y' by definition operator-
have syx_yx: suc(y') < suc(x') ⇔ y' < x'
by apply iff_symm to less_suc_iff_suc_less[y',x']
apply iff_trans[suc(y') < suc(x'), y' < x', 0 < x' - y']
to syx_yx, IH'
}
}
}
end
theorem le_exists_sub : all n : Nat, m : Nat.
if n <= m then some x : Nat. m = n + x
proof
arbitrary n : Nat, m :Nat
assume prem
choose m - n
symmetric apply sub_add_identity[m, n] to prem
end
theorem less_trans: all m:Nat, n:Nat, o:Nat.
if m < n and n < o then m < o
proof
arbitrary m:Nat, n:Nat, o:Nat
suppose prem
suffices suc(m) ≤ o by definition operator <
have _5: suc(m) ≤ suc(suc(m))
by less_equal_suc[suc(m)]
have _3: suc(suc(m)) ≤ suc(n) by
suffices suc(m) ≤ n by definition operator≤
definition operator < in prem
have _2: suc(n) ≤ o by definition operator < in prem
have _4: suc(suc(m)) ≤ o
by apply less_equal_trans to (_3, _2)
conclude suc(m) ≤ o
by apply less_equal_trans to (_5, _4)
end
theorem greater_any_zero: all x:Nat, y:Nat.
if x < y
then 0 < y
proof
arbitrary x:Nat, y:Nat
suppose x_l_y
suffices 1 ≤ y by definition operator<
have sx_le_y: 1 + x ≤ y by
suffices suc(x) ≤ y by definition 2*operator+
definition operator< in x_l_y
have one_le_sx: 1 ≤ 1 + x
by less_equal_add[1][x]
apply less_equal_trans to (one_le_sx, sx_le_y)
end
theorem dist_mult_sub : all x : Nat. all y : Nat, z : Nat.
x * (y - z) = x * y - x * z
proof
induction Nat
case zero {
arbitrary y:Nat, z:Nat
suffices 0 = 0 - 0 by replace zero_mult
definition operator-
}
case suc(n') suppose IH {
arbitrary y:Nat, z:Nat
suffices (n' * y - n' * z) + (y - z) = (y + n' * y) - (z + n' * z)
by definition operator*
and replace IH | add_commute[(y - z)][(n' * y - n' * z)]
cases dichotomy[z, y]
case z_le_y: z ≤ y {
have nz_le_ny : n'*z ≤n' * y
by apply mult_mono_le[n', z, y] to z_le_y
replace apply sub_add_assoc[y, (n' * y - n' * z) ,z] to z_le_y
| add_commute[(n' * y - n' * z), y]
| apply sub_add_assoc[n'*y, y, n'*z] to nz_le_ny
| sub_sub_eq_sub_add[(y + n' * y), n' * z, z]
| add_commute[n' * z, z]
}
case ylz: y < z {
have y_le_z: y ≤ z by apply less_implies_less_equal[y, z] to ylz
have ny_le_nz: n' * y ≤ n' * z by apply mult_mono_le[n', y, z] to y_le_z
have zny_le_znz : z + n' * y ≤ z + n' * z
by apply add_both_sides_of_less_equal[z, n'*y, n'*z] to ny_le_nz
have nyy_le_nyz: n' * y + y ≤ n' * y + z
by apply add_both_sides_of_less_equal[n'*y, y, z] to y_le_z
have yny_le_zny : y + n' * y ≤ z + n' * y
by replace add_commute in nyy_le_nyz
have yny_le_znz: y + n'*y ≤ z + n'*z
by apply less_equal_trans to yny_le_zny, zny_le_znz
suffices 0+0=0
by replace apply sub_zero_iff_less_eq to y_le_z
| apply sub_zero_iff_less_eq to ny_le_nz
| apply sub_zero_iff_less_eq to yny_le_znz
add_zero[0]
}
}
end
theorem mult_pos_nonneg : all a : Nat, b : Nat.
if 0 < a and 0 < b then 0 < a * b
proof
arbitrary a : Nat, b : Nat
switch a {
case 0 {
evaluate
}
case suc(a') {
assume prem
suffices 0 < b + a' * b by definition operator*
apply add_pos_nonneg[b, a'*b] to conjunct 1 of prem
}
}
end
theorem mult_lt_mono_l : all c : Nat, a : Nat, b : Nat.
if c > 0 then (if a < b then a * c < b * c)
proof
induction Nat
case 0 {
evaluate
}
case suc(c') assume IH {
arbitrary a : Nat, b : Nat
suppose sc_g_z
suppose alb
suffices a + a * c' < b + b * c' by rewrite mult_suc | mult_suc
switch c' > 0 {
case true assume prop_t {
have ac_l_bc : a * c' < b * c' by apply (rewrite prop_t in IH) to alb
have step1 : a + a * c' < a + b * c' by apply add_both_sides_of_less[a, a*c'] to ac_l_bc
have step2 : a + b * c' < b + b * c' by
suffices b * c' + a < b * c' + b
by rewrite add_commute[a, b * c'] | add_commute[b, b * c']
apply add_both_sides_of_less[b * c'] to alb
apply less_trans to step1, step2
}
case false assume prop_f {
have cz : c' = 0 by rewrite (definition operator > in prop_f) in zero_or_positive[c']
suffices a<b by rewrite cz | mult_zero | add_zero
alb
}
}
}
end
theorem mult_lt_mono_r : all c : Nat, a : Nat, b : Nat.
if 0 < c then (if a * c < b * c then a < b)
proof
arbitrary c : Nat, a : Nat, b : Nat
assume zlc
assume ac_l_bc
have cgz : c > 0 by
suffices __ by definition operator>
zlc
cases trichotomy[a, b]
case : a < b {
recall a < b
}
case aeb : a = b {
apply less_irreflexive to rewrite aeb in ac_l_bc
}
case : b < a {
have contra : b * c < a * c by
apply (apply mult_lt_mono_l[c, b, a] to cgz) to (recall b < a)
apply (apply less_implies_not_greater[b*c, a*c] to contra) to ac_l_bc
}
end
lemma max_same: all x:Nat. max(x,x) = x
proof
induction Nat
case 0 {
conclude max(0, 0) = 0 by definition max
}
case suc(x') suppose IH {
suffices suc(max(x', x')) = suc(x')
by definition max
conclude suc(max(x', x')) = suc(x') by replace IH
}
end
lemma max_suc: all x:Nat. max(suc(x), x) = suc(max(x,x))
proof
induction Nat
case zero {
conclude max(suc(0), 0) = suc(max(0,0)) by definition max
}
case suc(x') suppose IH {
equations
# max(suc(suc(x')),suc(x')) #= suc(max(suc(x'),x'))
by definition max
... = suc(suc(max(x',x'))) by replace IH
... =# suc(max(suc(x'),suc(x'))) # by definition max
}
end
lemma max_suc2: all x:Nat, y:Nat. max(suc(x), suc(y)) = suc(max(x,y))
proof
arbitrary x:Nat, y:Nat
switch x {
case 0 {
conclude max(1,suc(y)) = suc(max(0,y)) by definition 2*max
}
case suc(x') {
switch y {
case 0 {
definition 2*max
}
case suc(y') {
definition 2*max
}
}
}
}
end
theorem max_greater_right: all y:Nat, x:Nat.
y ≤ max(x, y)
proof
induction Nat
case 0 {
arbitrary x:Nat
definition operator ≤
}
case suc(y') suppose IH {
arbitrary x:Nat
switch x {
case 0 {
suffices suc(y') ≤ suc(y') by definition max
less_equal_refl[suc(y')]
}
case suc(x') {
suffices suc(y') ≤ suc(max(x',y')) by replace max_suc2
suffices y' ≤ max(x',y') by definition operator ≤
IH[x']
}
}
}
end
theorem max_greater_left: all x:Nat, y:Nat.
x ≤ max(x, y)
proof
induction Nat
case 0 {
arbitrary y:Nat
definition operator ≤
}
case suc(x') suppose IH {
arbitrary y:Nat
switch y {
case 0 {
suffices suc(x') ≤ suc(x') by definition max
conclude suc(x') ≤ suc(x') by less_equal_refl[suc(x')]
}
case suc(y') {
suffices x' ≤ max(x',y') by definition max | operator ≤
IH[y']
}
}
}
end
theorem max_is_left_or_right: all x:Nat, y:Nat.
max(x, y) = x or max( x
,y)=y
proofinduction Natcase0
{arbitraryy:Nat
definition max
}
case suc(x') suppose IH {
arbitrary y:Nat
switch y {
case 0 {
definition max
}
case suc(y') {
cases IH[y']
case m_x: max(x',y') = x' {
suffices suc(max(x',y')) = suc(x') by definition max
replace m_x
}
case m_y: max(x',y') = y' {
suffices suc(max(x',y')) = suc(y') by definition max
replace m_y
}
}
}
}
end
theorem zero_max: all x:Nat.
max(0, x) = x
proof
definition max
end
theorem max_zero: all x:Nat.
max(x, 0) = x
proof
induction Nat
case 0 {
conclude max(0, 0) = 0 by definition max
}
case suc(x') suppose IH {
conclude max(suc(x'), 0) = suc(x') by definition max
}
end
theorem max_symmetric: all x:Nat, y:Nat.
max(x,y) = max(y,x)
proof
induction Nat
case 0 {
arbitrary y:Nat
suffices y = max(y, 0) by definition max
replace max_zero
}
case suc(x') suppose IH {
arbitrary y:Nat
switch y {
case 0 {
conclude max(suc(x'), 0) = max(0, suc(x'))
by definition max
}
case suc(y') suppose y_suc {
suffices suc(max(x', y')) = suc(max(y', x'))
by replace max_suc2
replace IH
}
}
}
end
theorem max_assoc: all x:Nat, y:Nat,z:Nat.
max(max(x, y), z) = max(x, max(y, z))
proof
induction Nat
case 0 {
arbitrary y:Nat,z:Nat
conclude max(max(0, y), z) = max(0, max(y, z))
by definition max
}
case suc(x') suppose IH {
arbitrary y:Nat,z:Nat
switch y {
case 0 {
conclude max(max(suc(x'), 0), z) = max(suc(x'), max(0, z))
by definition max
}
case suc(y') suppose y_suc {
switch z {
case 0 {
conclude max(max(suc(x'), suc(y')), 0) = max(suc(x'), max(suc(y'), 0))
by definition max
}
case suc(z') suppose z_suc {
suffices suc(max(max(x', y'), z')) = suc(max(x', max(y', z')))
by definition max
replace IH
}
}
}
}
}
end
theorem max_equal_greater_right: all x:Nat, y:Nat.
if x ≤ y
then max(x, y) = y
proof
induction Nat
case 0 {
arbitrary y:Nat
suppose _
conclude max(0, y) = y by definition max
}
case suc(x') suppose IH {
arbitrary y:Nat
suppose sx_le_y
switch y for max {
case 0 suppose y_z {
conclude false by definition operator≤ in
replace y_z in sx_le_y
}
case suc(y') suppose y_suc {
have x_l_y: x' ≤ y'
by definition operator≤ in replace y_suc in sx_le_y
conclude suc(max(x', y')) = suc(y')
by replace apply IH to x_l_y
}
}
}
end
theorem max_equal_greater_left: all x:Nat, y:Nat.
if y ≤ x
then max(x, y) = x
proof
arbitrary x:Nat
arbitrary y:Nat
suppose prem
suffices max(y, x) = x by replace max_symmetric
apply max_equal_greater_right to prem
end
theorem max_less_equal: all x:Nat, y:Nat, z:Nat.
if x ≤ z
and y ≤ z
then max(x, y) ≤ z
proof
induction Nat
case 0 {
arbitrary y:Nat, z:Nat
suppose prem
suffices y ≤ z by definition max
prem
}
case suc(x') suppose IH {
arbitrary y:Nat, z:Nat
suppose prem
switch y for max {
case 0 {
conclude suc(x') ≤ z by prem
}
case suc(y') suppose y_suc {
suffices suc(max(x', y')) ≤ z by .
switch z {
case 0 suppose z_zero {
conclude false
by definition operator≤ in
replace z_zero in prem
}
case suc(z') suppose z_suc {
suffices max(x', y') ≤ z' by definition operator≤
have x_le_z: x' ≤ z' by
definition operator≤ in replace z_suc in prem
have y_le_z: y' ≤ z' by
definition operator≤ in
replace y_suc | z_suc in prem
apply IH to x_le_z, y_le_z
}
}
}
}
}
end
recursive parity(Nat, bool) -> bool {
parity(0, b) = b
parity(suc(n'), b) = parity(n', not b)
}
fun is_even(n : Nat) {
parity(n, true)
}
fun is_odd(n : Nat) {
parity(n, false)
}
fun Even(n : Nat) {
some m:Nat. n = 2 * m
}
fun Odd(n : Nat) {
some m:Nat. n = suc (2 * m)
}
theorem two_even: all n:Nat. Even(2*n)
proof
arbitrary n:Nat
suffices __ by definition Even
choose n
.
end
theorem one_two_odd: all n:Nat. Odd(1 + 2*n)
proof
arbitrary n:Nat
suffices __ by definition Odd
choose n
evaluate
end
theorem even_or_odd: all n:Nat. is_even(n) or is_odd(n)
proof
induction Nat
case 0 {
conclude is_even(0) by definition {is_even, parity}
}
case suc(n') assume IH {
cases IH
case even {
conclude is_odd(suc(n')) by
suffices parity(n', true) by definition {is_odd, parity}
definition is_even in even
}
case odd {
conclude is_even(suc(n')) by
suffices parity(n', false) by definition {is_even, parity}
definition is_odd in odd
}
}
end
theorem addition_of_evens:
all x:Nat, y:Nat.
if Even(x) and Even(y) then Even(x + y)
proof
arbitrary x:Nat, y:Nat
suppose even_xy: Even(x) and Even(y)
have even_x: some m:Nat. x = 2 * m by definition Even in even_xy
have even_y: some m:Nat. y = 2 * m by definition Even in even_xy
obtain a where x_2a: x = 2*a from even_x
obtain b where y_2b: y = 2*b from even_y
suffices some m:Nat. x + y = 2 * m by definition Even
choose a + b
equations
x + y
= 2*a + 2*b by replace x_2a | y_2b
... = #2 * (a + b)# by replace dist_mult_add
end
theorem is_even_odd:
all n:Nat.
(if is_even(n) then Even(n))
and (if is_odd(n) then Odd(n))
proof
induction Nat
case zero {
have part1: if is_even(0) then Even(0)
by suppose _
conclude Even(0)
by suffices some m:Nat. 0 = 2 * m by definition Even
choose 0
evaluate
have part2: if is_odd(0) then Odd(0)
by suppose zero_odd
conclude false by definition {is_odd, parity} in zero_odd
part1, part2
}
case suc(n') suppose IH {
have part1: (if is_even(suc(n')) then Even(suc(n'))) by
(suppose suc_even: is_even(suc(n'))
have odd_n: is_odd(n') by {
suffices parity(n', false) by definition {is_odd}
definition {is_even, parity} in suc_even
}
have Odd_n: Odd(n') by apply (conjunct 1 of IH) to odd_n
obtain m where n_2m from definition Odd in Odd_n
suffices some m':Nat. suc(n') = 2 * m' by definition Even
choose suc(m)
suffices suc(suc(2 * m)) = 2 * suc(m) by replace n_2m
suffices suc(suc(m + (m + 0))) = suc(m + suc(m + 0))
by definition 3 * operator* | 3 * operator+
replace add_zero | add_suc)
have part2: (if is_odd(suc(n')) then Odd(suc(n'))) by
(suppose suc_odd: is_odd(suc(n'))
have even_n: is_even(n') by {
suffices parity(n', true) by definition is_even
definition {is_odd, parity} in suc_odd
}
have Even_n: Even(n') by apply (conjunct 0 of IH) to even_n
obtain m where n_2m from definition Even in Even_n
suffices some m':Nat. suc(n') = suc(2 * m') by definition Odd
choose m
replace n_2m)
part1, part2
}
end
theorem Even_or_Odd: all n:Nat. Even(n) or Odd(n)
proof
arbitrary n:Nat
cases even_or_odd[n]
case even {
conclude Even(n) by apply is_even_odd to even
}
case odd {
conclude Odd(n) by apply is_even_odd to odd
}
end
theorem odd_one_even: all n:Nat. if Odd(1 + n) then Even(n)
proof
arbitrary n:Nat
assume n1_odd
obtain k where nk: 1 + n = suc(2 * k) from definition Odd in n1_odd
have n2k: n = 2*k
by apply add_both_sides_of_equal[1, n, 2*k] to (replace suc_one_add | add_zero in nk)
suffices __ by definition Even
choose k
n2k
end
theorem even_one_odd: all n:Nat. if Even(1 + n) then Odd(n)
proof
arbitrary n:Nat
assume n1_even
obtain k where nk: 1 + n = 2 * k from definition Even in n1_even
suffices __ by definition Odd
switch k {
case 0 assume kz {
conclude false by evaluate in replace kz in nk
}
case suc(k') assume ksk {
have eq1: 1 + n = 1 + (1 + k' * 2) by {
suffices __ by evaluate
evaluate in definition operator* in replace ksk | mult_commute in nk
}
have n_eq: n = 1 + k' * 2 by apply add_both_sides_of_equal to eq1
suffices __ by replace n_eq | suc_one_add | dist_mult_add | mult_one | add_zero
choose k'
replace two_mult
}
}
end
theorem Even_not_Odd: all n:Nat. Even(n) ⇔ not Odd(n)
proof
induction Nat
case 0 {
suffices some m:Nat. 0 = 2 * m by definition Even | Odd
choose 0
conclude 0 = 2 * 0 by evaluate
}
case suc(n') assume IH {
have fwd: if Even(suc(n')) then not Odd(suc(n')) by {
assume prem: Even(suc(n'))
assume contra: Odd(suc(n'))
have en: Even(n') by apply odd_one_even to (replace suc_one_add in contra)
have not_on: not Odd(n') by apply IH to en
have on: Odd(n') by apply even_one_odd to (replace suc_one_add in prem)
conclude false by apply not_on to on
}
have bkwd: if not Odd(suc(n')) then Even(suc(n')) by {
assume prem: not Odd(suc(n'))
have nen: not Even(n') by {
assume en: Even(n')
obtain k where n2k: n' = 2*k from definition Even in en
have sn2k: suc(n') = suc(2*k) by replace n2k
have osn: Odd(suc(n')) by {
suffices __ by definition Odd
choose k
sn2k
}
conclude false by apply prem to osn
}
have nnon: not (not Odd(n'))
by apply contrapositive[not Odd(n'), Even(n')] to IH, nen
have on: Odd(n') by replace double_neg in nnon
obtain k where ns2k: n' = suc (2 * k) from definition Odd in on
suffices __ by definition Even and replace ns2k
choose 1+k
suffices __ by replace dist_mult_add | mult_one
evaluate
}
fwd, bkwd
}
end
theorem summation_cong: all k : Nat. all f : fn Nat->Nat, g : fn Nat->Nat, s : Nat, t : Nat.
if (all i:Nat. if i < k then f(s + i) = g(t + i))
then summation(k, s, f) = summation(k, t, g)
proof
induction Nat
case zero {
arbitrary f:fn(Nat) -> Nat,g:fn(Nat) -> Nat,s:Nat,t:Nat
suppose f_g
definition summation
}
case suc(k') suppose IH {
arbitrary f:fn(Nat) -> Nat,g:fn(Nat) -> Nat,s:Nat,t:Nat
suppose f_g
suffices summation(suc(k'),s,f) = summation(suc(k'),t,g) by .
suffices f(s) + summation(k',suc(s),f) = g(t) + summation(k',suc(t),g)
by definition summation
have f_g_s: f(s) = g(t) by
replace add_zero in
(apply f_g[0] to definition operator < | 2* operator ≤)
have IH': summation(k',suc(s),f) = summation(k',suc(t),g)
by apply IH[f,g,suc(s),suc(t)]
to arbitrary i:Nat suppose i_k: i < k'
suffices f(suc(s + i)) = g(suc(t + i)) by evaluate
have fsi_gtsi: f(s + suc(i)) = g(t + suc(i))
by suffices suc(i) < suc(k') by f_g[suc(i)]
apply less_suc_iff_suc_less to i_k
replace add_suc in fsi_gtsi
replace f_g_s | IH'
}
end
lemma summation_cong4: all k:Nat. all f : fn Nat->Nat, g : fn Nat->Nat, s :Nat.
if (all i:Nat. if s ≤ i and i < s + k then f(i) = g(i))
then summation(k, s, f) = summation(k, s, g)
proof
induction Nat
case zero {
arbitrary f : fn Nat->Nat, g : fn Nat->Nat, s :Nat
suppose _
definition summation
}
case suc(k') suppose IH {
arbitrary f : fn Nat->Nat, g : fn Nat->Nat, s :Nat
suppose f_g: all i:Nat. if s ≤ i and i < s + suc(k') then f(i) = g(i)
suffices f(s) + summation(k',suc(s),f) = g(s) + summation(k',suc(s),g)
by definition summation
have f_g_s: f(s) = g(s) by {
have s_s: s ≤ s by less_equal_refl[s]
have s_sk: s < s + suc(k') by {
suffices s ≤ s + k' by definition operator < | operator ≤ and replace add_suc
less_equal_add[s][k']
}
apply f_g[s] to s_s, s_sk
}
have IH': summation(k',suc(s),f) = summation(k',suc(s),g) by {
have IH_prem: all i:Nat. if (suc(s) ≤ i and i < suc(s) + k')
then f(i) = g(i) by
{
arbitrary i:Nat
suppose ss_i_and_i_ss_k
have s_i: s ≤ i by {
apply less_implies_less_equal[s][i]
to suffices suc(s) ≤ i by definition operator <
ss_i_and_i_ss_k
}
have i_s_k: i < s + suc(k') by {
suffices suc(i) ≤ suc(s + k') by {
suffices __ by evaluate
replace add_suc
}
suffices i ≤ s + k' by evaluate
evaluate in (conjunct 1 of ss_i_and_i_ss_k)
}
conclude f(i) = g(i) by apply f_g[i] to s_i, i_s_k
}
apply IH[f,g,suc(s)] to IH_prem
}
replace f_g_s | IH'
}
end
theorem summation_suc: all k:Nat. all f : fn Nat->Nat, g : fn Nat->Nat, s :Nat.
if (all i:Nat. f(i) = g(suc(i)))
then summation(k, s, f) = summation(k, suc(s), g)
proof
arbitrary k:Nat
arbitrary f : fn Nat->Nat, g : fn Nat->Nat, s :Nat
suppose prem
have sum_prem: (all i:Nat. (if i < k then f(s + i) = g(suc(s) + i))) by
arbitrary i:Nat
suppose i_less_k
suffices f(s+i) = g(suc(s+i)) by definition operator+
prem[s+i]
apply summation_cong[k][f, g, s, suc(s)] to sum_prem
end
lemma summation_cong3: all k:Nat. all f : fn Nat->Nat, g : fn Nat->Nat, s :Nat, t :Nat.
if (all i:Nat. f(s + i) = g(t + i))
then summation(k, s, f) = summation(k, t, g)
proof
induction Nat
case zero {
arbitrary f : fn Nat->Nat, g : fn Nat->Nat, s :Nat, t :Nat
suppose _
definition summation
}
case suc(k') suppose IH {
arbitrary f : fn Nat->Nat, g : fn Nat->Nat, s :Nat, t :Nat
suppose f_g: all i:Nat. f(s + i) = g(t + i)
suffices f(s) + summation(k',suc(s),f) = g(t) + summation(k',suc(t),g) by definition summation
have fs_gt: f(s) = g(t) by replace add_zero in f_g[0]
have all_f_g: all i:Nat. f(suc(s) + i) = g(suc(t) + i)
by arbitrary i:Nat
suffices f(suc(s + i)) = g(suc(t + i)) by definition operator +
replace add_suc in f_g[suc(i)]
equations
f(s) + summation(k',suc(s),f)
= g(t) + summation(k',suc(s),f) by replace fs_gt
... = g(t) + summation(k',suc(t),g) by replace (apply IH[f,g,suc(s),suc(t)] to all_f_g)
}
end
theorem summation_add:
all a:Nat. all b:Nat, s:Nat, t:Nat, f:fn Nat->Nat, g:fn Nat->Nat, h:fn Nat->Nat.
if (all i:Nat. if i < a then g(s + i) = f(s + i))
and (all i:Nat. if i < b then h(t + i) = f(s + a + i))
then summation(a + b, s, f) = summation(a, s, g) + summation(b, t, h)
proof
induction Nat
case zero {
arbitrary b:Nat, s:Nat, t:Nat, f:fn Nat->Nat, g:fn Nat->Nat, h:fn Nat->Nat
suppose g_f_and_h_f
suffices summation(b,s,f) = summation(b,t,h) by definition { operator+, summation }
apply summation_cong[b][f,h,s,t]
to arbitrary i:Nat
suppose i_b: i < b
conclude f(s + i) = h(t + i)
by definition operator+ in symmetric (apply (conjunct 1 of g_f_and_h_f)[i] to i_b)
}
case suc(a') suppose IH {
arbitrary b:Nat, s:Nat, t:Nat, f:fn Nat->Nat, g:fn Nat->Nat, h:fn Nat->Nat
suppose g_f_and_h_f
suffices f(s) + summation(a' + b,suc(s),f) = (g(s) + summation(a',suc(s),g)) + summation(b,t,h)
by definition {operator +, summation}
have fs_gs: f(s) = g(s) by symmetric
replace add_zero
in apply (conjunct 0 of g_f_and_h_f)[0]
to definition operator < | 2* operator ≤
have IH': summation(a' + b,suc(s),f)
= summation(a',suc(s),g) + summation(b,t,h)
by have p1: all i:Nat. (if i < a' then g(suc(s) + i) = f(suc(s) + i))
by arbitrary i:Nat suppose i_a: i < a'
have i_sa : suc(i) < suc(a') by
apply less_suc_iff_suc_less to i_a
replace add_suc | symmetric suc_add[s, i]
in apply (conjunct 0 of g_f_and_h_f)[suc(i)] to i_sa
have p2: all i:Nat. (if i < b then h(t + i) = f(suc(s) + (a' + i)))
by arbitrary i:Nat suppose i_b: i < b
suffices __ by definition 2*operator+
definition operator+ in
replace add_suc in
apply (conjunct 1 of g_f_and_h_f)[i] to i_b
apply IH[b,suc(s),t,f,g,h] to p1, p2
replace fs_gs | IH'
}
end
theorem summation_next: all n:Nat, s:Nat, f:fn Nat->Nat.
summation(1 + n, s, f) = summation(n, s, f) + f(s + n)
proof
arbitrary n:Nat, s:Nat, f:fn Nat->Nat
have A: (all i:Nat. (if i < n then f(s + i) = f(s + i))) by {
arbitrary i:Nat assume: i < n .
}
have B: (all i:Nat. (if i < 1 then f((s + n) + i) = f(s + (n + i)))) by {
arbitrary i:Nat assume: i < 1 .
}
have C: summation(n + 1, s, f) = summation(n, s, f) + summation(1, s+n, f)
by apply summation_add[n,1,s,s+n,f,f,f] to A,B
have D: summation(1, s + n, f) = f(s + n)
by definition 2*summation and replace add_zero
replace add_commute[1,n] | C | D
end
theorem equal_refl: all n:Nat. equal(n,n)
proof
induction Nat
case 0 {
definition equal
}
case suc(n') suppose IH {
suffices equal(n',n') by definition equal
IH
}
end
theorem equal_complete_sound : all m:Nat. all n:Nat.
m = n ⇔ equal(m, n)
proof
induction Nat
case 0 {
arbitrary n:Nat
switch n {
case 0 { definition equal }
case suc(n') { definition equal }
}
}
case suc(m') suppose IH {
arbitrary n:Nat
switch n {
case 0 { definition equal }
case suc(n') {
have right : (if suc(m') = suc(n') then equal(suc(m'), suc(n')))
by suppose sm_sn: suc(m') = suc(n')
suffices equal(m', n') by definition equal
have m_n: m' = n' by injective suc sm_sn
suffices equal(n', n') by replace m_n
equal_refl[n']
have left : (if equal(suc(m'), suc(n')) then suc(m') = suc(n'))
by suppose sm_sn : equal(suc(m'), suc(n'))
have e_m_n : equal(m', n') by definition equal in sm_sn
have m_n : m' = n' by apply IH to e_m_n
replace m_n
right, left
}
}
}
end
theorem not_equal_not_eq: all m:Nat, n:Nat.
if not equal(m, n) then not (m = n)
proof
arbitrary m:Nat, n:Nat
suppose not_m_n
suppose m_n
have eq_m_n: equal(m, n) by suffices equal(n,n) by replace m_n
equal_refl[n]
apply not_m_n to eq_m_n
end
lemma div2_zero: div2(0) = 0
proof
evaluate
end
lemma div2_add_2: all n:Nat. div2(suc(suc(n))) = suc(div2(n))
proof
arbitrary n:Nat
definition {div2, div2_helper, div2_helper}
end
lemma div2_double: all n:Nat.
div2(n + n) = n
proof
induction Nat
case 0 {
definition {operator+, div2, div2_helper}
}
case suc(n') suppose IH {
suffices div2(suc(n' + suc(n'))) = suc(n') by definition operator+
suffices div2(suc(suc(n' + n'))) = suc(n') by replace add_suc
suffices suc(div2(n' + n')) = suc(n') by replace div2_add_2
replace IH
}
end
lemma div2_times2: all n:Nat.
div2(2 * n) = n
proof
arbitrary n:Nat
suffices div2(n + (n + 0)) = n by definition {operator*,operator*,operator*}
suffices div2(n + n) = n by replace add_zero
div2_double[n]
end
lemma div2_suc_double: all n:Nat.
div2(suc(n + n)) = n
proof
induction Nat
case 0 {
definition {operator+, div2, div2_helper, div2_helper}
}
case suc(n') suppose IH {
suffices suc(div2_helper(suc(n' + n'), true)) = suc(n')
by definition {div2, div2_helper, operator+, div2_helper} and replace add_suc
suffices suc(div2_helper(n' + n', false)) = suc(n')
by definition div2_helper
replace (definition {div2, div2_helper} in IH)
}
end
lemma div2_suc_times2: all n:Nat.
div2(suc(2 * n)) = n
proof
arbitrary n:Nat
suffices div2(suc(n + (n + 0))) = n by definition {operator*,operator*,operator*}
suffices div2(suc(n + n)) = n by replace add_zero
div2_suc_double[n]
end
lemma sub_div2: all n:Nat. n - div2(n) ≤ suc(div2(n))
proof
arbitrary n:Nat
cases Even_or_Odd[n]
case even {
obtain k where n_2k: n = 2 * k from definition Even in even
suffices k ≤ suc(k) by replace n_2k | div2_times2[k] | two_mult[k] | add_sub_identity[k,k]
less_equal_suc
}
case odd {
obtain k where n_s2k: n = suc(2 * k) from definition Odd in odd
suffices suc(k + k) - k ≤ suc(k) by replace n_s2k | div2_suc_times2[k] | two_mult[k]
have eq_1: suc(k + k) = 1 + (k + k) by definition {operator+, operator+}
suffices (1 + (k + k)) - k ≤ suc(k) by replace eq_1
have k_kk: k ≤ k + k by less_equal_add
have eq_2: (1 + (k + k)) - k = 1 + ((k + k) - k) by symmetric apply sub_add_assoc[k + k, 1, k] to k_kk
suffices 1 + ((k + k) - k) ≤ suc(k) by replace eq_2
suffices ((k + k) - k) ≤ k by definition {operator+, operator+, operator≤}
suffices k ≤ k by replace add_sub_identity[k,k]
less_equal_refl
}
end
lemma sub_div2_pos: all n:Nat. if 0 < n then 0 < n - div2(n)
proof
arbitrary n:Nat
cases Even_or_Odd[n]
case even {
obtain k where n_2k: n = 2 * k from definition Even in even
suffices if 0 < k + k then 0 < k by replace n_2k | div2_times2[k] | two_mult[k] | add_sub_identity[k,k]
switch k {
case 0 {
conclude if 0 < 0 + 0 then 0 < 0
by definition {operator +}
}
case suc(k') {
assume _
definition {operator<, operator≤, operator≤}
}
}
}
case odd {
obtain k where n_s2k: n = suc(2 * k) from definition Odd in odd
suffices if 0 < suc(k + k) then 0 < suc(k + k) - k by replace n_s2k | div2_suc_times2[k] | two_mult[k]
assume _
have eq_1: suc(k + k) = 1 + (k + k) by definition {operator+, operator+}
suffices 0 < (1 + (k + k)) - k by replace eq_1
have k_kk: k ≤ k + k by less_equal_add
have eq_2: (1 + (k + k)) - k = 1 + ((k + k) - k) by symmetric apply sub_add_assoc[k + k, 1, k] to k_kk
suffices 0 < 1 + ((k + k) - k) by replace eq_2
definition {operator+, operator<, operator≤, operator≤}
}
end
lemma div2_aux_pos_less: all n:Nat. if 0 < n then div2(n) < n and div2_aux(n) ≤ n
proof
induction Nat
case 0 {
assume: 0 < 0
conclude false by apply less_irreflexive to recall 0 < 0
}
case suc(n') assume IH {
assume: 0 < suc(n')
switch n' {
case 0 {
definition {div2, div2_aux, operator<, operator≤, div2_helper, div2_helper, operator≤}
}
case suc(n'') assume np_eq {
have: 0 < n' by {
suffices 0 < suc(n'') by replace np_eq
definition {operator<, operator≤, operator≤}
}
have IH': div2(n') < n' and div2_aux(n') ≤ n' by apply IH to (recall 0 < n')
suffices (div2_helper(n'', true) ≤ n'' and div2_helper(n'', false) ≤ suc(n''))
by definition {div2, div2_aux, div2_helper, div2_helper, operator<, operator≤, operator≤}
have _1: div2_helper(n'', true) ≤ n'' by {
definition {div2_aux, div2_helper, operator≤} in
replace np_eq in
conjunct 1 of IH'
}
have _2: div2_helper(n'', false) ≤ suc(n'') by {
have lt1: div2_helper(n'', false) ≤ n'' by {
definition {div2, div2_helper, operator<, operator≤} in
replace np_eq in
conjunct 0 of IH'
}
have lt2: n'' ≤ suc(n'') by less_equal_suc
apply less_equal_trans to lt1, lt2
}
_1, _2
}
}
}
end
lemma div2_pos_less: all n:Nat. if 0 < n then div2(n) < n
proof
div2_aux_pos_less
end
lemma div2_aux_mono: all x:Nat, y:Nat.
if x ≤ y then div2(x) ≤ div2(y) and div2_aux(x) ≤ div2_aux(y)
proof
induction Nat
case 0 {
arbitrary y:Nat
assume _
conclude div2(0) ≤ div2(y) and div2_aux(0) ≤ div2_aux(y)
by definition {div2, div2_aux, div2_helper, operator≤}
}
case suc(x') assume IH {
arbitrary y:Nat
assume sx_y
switch y {
case 0 assume y_eq {
conclude false by definition operator≤ in replace y_eq in sx_y
}
case suc(y') assume y_eq {
suffices div2_helper(x', false) ≤ div2_helper(y', false)
and div2_helper(x', true) ≤ div2_helper(y', true)
by definition {div2, div2_aux, div2_helper, operator≤}
have xy: x' ≤ y' by apply suc_less_equal_iff_less_equal_suc to replace y_eq in sx_y
definition {div2, div2_aux} in apply IH[y'] to xy
}
}
}
end
lemma div2_mono: all x:Nat, y:Nat.
if x ≤ y then div2(x) ≤ div2(y)
proof
div2_aux_mono
end
theorem pow_positive: all n:Nat. 0 < pow2(n)
proof
induction Nat
case 0 {
definition {pow2, operator<, operator≤, operator≤}
}
case suc(n') suppose IH {
suffices 0 < 2 * pow2(n') by definition pow2
obtain pn' where pn_s: pow2(n') = suc(pn')
from apply positive_suc[pow2(n')] to IH
suffices 0 < 2 * suc(pn') by replace pn_s
suffices 0 < suc(pn') + (suc(pn') + 0) by definition {operator*,operator*,operator*}
suffices 0 < suc(pn') + suc(pn') by replace add_zero[suc(pn')]
suffices 0 < suc(pn' + suc(pn')) by definition operator+
suffices 0 < suc(suc(pn' + pn')) by replace add_suc[pn'][pn']
definition {operator<, operator≤, operator≤}
}
end
recfun operator /(n : Nat, m : Nat) -> Nat
measure n
{
if n < m then 0
else if m = 0 then 0
else 1 + (n - m) / m
}
terminates {
arbitrary n:Nat, m:Nat
assume cond: not (n < m) and not (m = 0)
suffices m + (n - m) < m + n by add_both_sides_of_less[m,n-m,n]
suffices n < m + n by {
have m_n: m ≤ n by apply not_less_implies_less_equal to conjunct 0 of cond
replace apply sub_add_identity[n,m] to m_n
}
obtain m' where m_sm: m = suc(m') from apply not_zero_suc to conjunct 1 of cond
suffices n < suc(m') + n by replace m_sm
suffices n ≤ m' + n by definition operator+ | operator< | operator≤
suffices n ≤ n + m' by replace add_commute
less_equal_add
}
fun operator % (n:Nat, m:Nat) {
n - (n / m) * m
}
lemma strong_induction_aux: all P: fn Nat -> bool.
if (all n:Nat. if (all k:Nat. if k < n then P(k)) then P(n))
then (all j:Nat, k:Nat. if k < j then P(k))
proof
arbitrary P: fn Nat -> bool
assume H
induction Nat
case 0 {
arbitrary k:Nat
assume neg_k
conclude false by apply not_less_zero to neg_k
}
case suc(j') assume IH {
arbitrary k:Nat
assume: k < suc(j')
have: k ≤ j' by evaluate in recall k < suc(j')
cases (apply less_equal_implies_less_or_equal to recall k ≤ j')
case: k < j' {
conclude P(k) by apply IH to recall k < j'
}
case: k = j' {
have A: all m:Nat. if m < j' then P(m) by {
arbitrary m:Nat
assume: m < j'
have B: all k':Nat. (if k' < m then P(k')) by {
arbitrary k':Nat
assume: k' < m
have: k' < j' by apply less_trans to (recall k' < m), (recall m < j')
conclude P(k') by apply IH to recall k' < j'
}
conclude P(m) by apply H[m] to B
}
have: P(j') by apply H[j'] to A
conclude P(k) by replace symmetric (recall k = j') in recall P(j')
}
}
end
theorem strong_induction: all P: fn Nat -> bool, n:Nat.
if (all j:Nat. if (all i:Nat. if i < j then P(i)) then P(j))
then P(n)
proof
arbitrary P: fn Nat -> bool, n:Nat
assume prem
have X: all j:Nat, k:Nat. if k < j then P(k)
by apply strong_induction_aux[P] to prem
have: n < suc(n) by {
suffices n ≤ n by evaluate
less_equal_refl
}
conclude P(n) by apply X[suc(n),n] to recall n < suc(n)
end
private fun DivPred(n:Nat) {
all m:Nat. if 0 < m then some r:Nat. (n / m) * m + r = n and r < m
}
lemma division: all n:Nat, m:Nat.
if 0 < m
then some r:Nat. (n/m)*m + r = n and r < m
proof
arbitrary n:Nat
have SI: all j:Nat. if (all i:Nat. if i < j then DivPred(i)) then DivPred(j) by {
arbitrary j:Nat
assume prem: all i:Nat. if i < j then DivPred(i)
suffices all m:Nat. if 0 < m then some r:Nat. ((j / m) * m + r = j and r < m)
by definition DivPred
arbitrary m:Nat
assume m_pos
switch j < m {
case true assume j_m_true {
suffices some r:Nat. r = j and r < m
by definition operator / and replace j_m_true | zero_mult | zero_add
choose j
conclude j = j and j < m
by replace j_m_true
}
case false assume j_m_false {
switch m = 0 {
case true assume m_z_true {
have: m = 0 by replace m_z_true
conclude false by apply less_irreflexive to replace (recall m = 0) in m_pos
}
case false assume m_z_false {
have not_m_z: not (m = 0) by replace m_z_false
have not_j_m: not (j < m) by replace j_m_false
have m_j: m ≤ j by apply not_less_implies_less_equal to not_j_m
obtain m' where m_sm: m = suc(m') from apply not_zero_suc to not_m_z
suffices some r:Nat. ((1 + (j - m) / m) * m + r = j and r < m)
by definition operator / and replace j_m_false | m_z_false
suffices some r:Nat. (m + ((j - m) / m) * m + r = j and r < m)
by replace dist_mult_add_right | one_mult
have jm_j: j - m < j by {
suffices m + (j - m) < m + j by add_both_sides_of_less[m,j-m,j]
suffices j < m + j by replace apply sub_add_identity[j,m] to m_j
suffices __ by replace m_sm
suffices j ≤ m' + j by definition operator+ | operator< | operator≤
suffices __ by replace add_commute
less_equal_add
}
have div_mp: DivPred(j - m) by apply prem[j - m] to jm_j
obtain r where div_jm: ((j - m) / m) * m + r = j - m and r < m
from apply (definition DivPred in div_mp)[m] to m_pos
choose r
suffices (m + (j - m) = j and r < m) by replace conjunct 0 of div_jm
have mjm_j: m + (j - m) = j by apply sub_add_identity[j, m] to m_j
mjm_j, conjunct 1 of div_jm
}
}
}
}
}
have: DivPred(n) by apply strong_induction[DivPred, n] to SI
definition DivPred in recall DivPred(n)
end
theorem div_mod: all n:Nat, m:Nat.
if 0 < m
then (n / m) * m + (n % m) = n
proof
arbitrary n:Nat, m:Nat
assume m_pos: 0 < m
have p1: 0 * m ≤ n by evaluate
have p2: n < (1 + (0 + (1 + n) * m)) * m by {
obtain m' where m_sm: m = suc(m') from apply positive_suc to m_pos
suffices __ by replace m_sm | zero_add | dist_mult_add_right[1,n] | mult_commute[n]
| suc_one_add[m'] | dist_mult_add_right[1,m',n] | one_mult | dist_mult_add | mult_one
| add_commute[m',n] | add_commute[1,n]
suffices __ by definition operator< and replace suc_one_add[n]
less_equal_add[1+n]
}
have ex: some r:Nat. (n/m)*m + r = n and r < m
by apply division[n,m] to m_pos
obtain r where R: (n/m)*m + r = n and r < m from ex
suffices __ by definition operator%
define a = (n / m) * m
have ar_n: a + r = n by R
have a_le_a_r: a ≤ a + r by less_equal_add
have n_eq_a_r: n = a + r by symmetric (conjunct 0 of R)
have a_le_n: a ≤ n by {
suffices a ≤ a + r by replace n_eq_a_r
a_le_a_r
}
conclude a + (n - a) = n
by apply sub_add_identity to a_le_n
end
theorem mod_less_divisor: all n:Nat, m:Nat. if 0 < m then n % m < m
proof
arbitrary n:Nat, m:Nat
assume m_pos: 0 < m
suffices __ by definition operator%
obtain r where R: (n / m) * m + r = n and r < m
from apply division[n, m] to m_pos
define a = (n / m)*m
have ar_n: a + r = n by R
have ar_a_a: (a + r) - a = r by add_sub_identity[a][r]
have r_na: r = n - a by {
suffices __ by replace symmetric ar_n
symmetric ar_a_a
}
suffices r < m by replace symmetric r_na
conjunct 1 of R
end
lemma mult_div_mod_self: all y:Nat.
if 0 < y
then y / y = 1 and y % y = 0
proof
arbitrary y:Nat
assume y_pos: 0 < y
have div_rem: (y / y) * y + (y % y) = y
by apply div_mod[y,y] to y_pos
have rem_less: y % y < y
by apply mod_less_divisor[y, y] to y_pos
switch (y / y) {
case 0 assume yyz {
have rem_eq: y % y = y by replace yyz | zero_mult | zero_add in div_rem
conclude false by apply (apply less_not_equal to rem_less) to rem_eq
}
case suc(y') assume ysy {
have eq1: y + (y' * y + y % y) = y + 0 by {
suffices __ by replace add_zero
definition operator* in replace ysy in div_rem
}
have eq2: y' * y + y%y = 0 by apply left_cancel to eq1
have rem_zero: y % y = 0 by apply add_to_zero to eq2
suffices suc(y') = 1 by replace rem_zero | ysy
have yz: y' = 0 by {
have yyz: y' * y = 0 by apply add_to_zero to eq2
obtain y'' where ysy2: y = suc(y'') from apply positive_suc to y_pos
have eq3: y' + y'' * y' = 0 by {
definition operator* in
replace ysy2 | mult_commute in yyz
}
conclude y' = 0 by apply add_to_zero to eq3
}
conclude suc(y') = 1 by replace yz
}
}
end
theorem div_cancel: all y:Nat. if 0 < y then y / y = 1
proof
arbitrary y:Nat
assume y_pos: 0 < y
apply mult_div_mod_self[y] to y_pos
end
theorem mod_self_zero: all y:Nat. y % y = 0
proof
arbitrary y:Nat
switch y {
case 0 {
suffices __ by definition operator%
zero_sub
}
case suc(y') assume y_sy {
have y_pos: 0 < y by {
suffices __ by replace y_sy
evaluate
}
suffices y % y = 0 by replace symmetric y_sy
apply mult_div_mod_self[y] to y_pos
}
}
end
theorem zero_mod: all x:Nat. 0 % x = 0
proof
arbitrary x:Nat
suffices __ by definition operator%
zero_sub
end
theorem zero_div: all x:Nat. if 0 < x then 0 / x = 0
proof
arbitrary x:Nat
assume xpos
have eq1: (0/x)*x + (0 % x) = 0 by apply div_mod[0,x] to xpos
have eq2: (0/x)*x = 0 by apply add_to_zero to eq1
switch x {
case 0 assume xz {
conclude false by apply (apply less_not_equal to xpos) to rewrite xz
}
case suc(x') assume xsx {
have eq3: 0 / suc(x') + x' * (0 / suc(x')) = 0
by definition operator* in rewrite xsx | mult_commute in eq2
conclude 0 / suc(x') = 0 by apply add_to_zero to eq3
}
}
end
theorem mod_one: all n:Nat. n % 1 = 0
proof
arbitrary n:Nat
have one_pos: 0 < 1 by evaluate
have n1_1: n % 1 < 1 by apply mod_less_divisor[n,1] to one_pos
switch n % 1 {
case 0 assume n1z { n1z }
case suc(n') assume n1_sn {
conclude false by evaluate in replace n1_sn in n1_1
}
}
end
theorem div_one: all n:Nat. n / 1 = n
proof
arbitrary n:Nat
have one_pos: 0 < 1 by evaluate
have eq1: (n / 1) * 1 + (n % 1) = n by apply div_mod[n,1] to one_pos
have eq2: (n / 1) + (n % 1) = n by replace mult_one in eq1
replace mod_one | add_zero in eq2
end
theorem add_div_one: all n:Nat, m:Nat.
if 0 < m
then (n + m) / m = 1 + n / m
proof
arbitrary n:Nat, m:Nat
assume m_pos
have not_nm_m: not (n + m < m) by {
assume nm_m: n + m < m
have not_m_nm: not (m ≤ n + m) by apply not_less_equal_iff_greater to nm_m
have: m ≤ m + n by less_equal_add
have m_nm: m ≤ n + m by replace add_commute in recall m ≤ m + n
conclude false by apply not_m_nm to m_nm
}
have m_nz: not (m = 0) by {
assume: m = 0
conclude false by evaluate in replace (recall m = 0) in m_pos
}
equations
(n + m) / m = 1 + ((n + m) - m) / m by definition operator/
and replace (apply eq_false to not_nm_m)
| (apply eq_false to m_nz)
... = 1 + n / m by replace add_commute[n,m]
| add_sub_identity
end
theorem mult_div_inverse: all n:Nat, m:Nat.
if 0 < m then (n * m) / m = n
proof
induction Nat
case 0 {
arbitrary m:Nat
assume prem
suffices 0 / m = 0 by replace zero_mult
apply zero_div to prem
}
case suc(n') assume IH {
arbitrary m:Nat
assume prem
suffices (n' * m + m) / m = suc(n') by definition operator* and replace add_commute
equations
(n' * m + m) / m = 1 + (n' * m) / m by apply add_div_one[n'*m, m] to prem
... = 1 + n' by replace apply IH to prem
... = suc(n') by evaluate
}
end
theorem expt_one : all n : Nat.
n ^ 1 = n
proof
arbitrary n : Nat
suffices n * 1 = n by evaluate
mult_one
end
theorem one_expt : all n : Nat.
1 ^ n = 1
proof
induction Nat
case 0 {
evaluate
}
case suc(n') assume IH {
have IH' : expt(n', 1) = 1 by definition operator^ in IH
suffices 1 * expt(n', 1) = 1 by definition operator^ | expt
rewrite IH' | one_mult
}
end
theorem pow_add_r : all n : Nat, m : Nat, o : Nat.
m ^ (n + o) = m ^ n * m ^ o
proof
induction Nat
case zero {
arbitrary m : Nat, o : Nat
suffices expt(o, m) = expt(o, m) + 0 by evaluate
replace add_zero
}
case suc(n') assume IH {
arbitrary m : Nat, o : Nat
have IH' : (all m':Nat, o':Nat. expt(n' + o', m') = expt(n', m') * expt(o', m'))
by definition operator^ in IH
suffices m * expt(n' + o, m) = m * expt(n', m) * expt(o, m)
by definition operator^ | operator+ | expt
replace IH'
}
end
theorem pow_mul_l : all o : Nat, m : Nat, n : Nat.
(m * n) ^ o = m ^ o * n ^ o
proof
induction Nat
case 0 {
evaluate
}
case suc(o') assume IH {
arbitrary m : Nat, n : Nat
have IH' : (all m':Nat, n':Nat. expt(o', m' * n') = expt(o', m') * expt(o', n'))
by evaluate in IH
suffices m * n * expt(o', m * n) = m * expt(o', m) * n * expt(o', n) by evaluate
rewrite IH' | mult_commute[n, expt(o', m)]
}
end
theorem pow_mul_r : all o : Nat, m : Nat, n : Nat.
(m ^ n) ^ o = m ^ (n * o)
proof
induction Nat
case 0 {
arbitrary m : Nat, n : Nat
suffices (m ^ n) ^ 0 = m ^ 0 by replace mult_zero
evaluate
}
case suc(o') assume IH {
arbitrary m : Nat, n : Nat
have IH' : (all m':Nat, n':Nat. expt(o', expt(n', m')) = expt(n' * o', m'))
by definition operator^ in IH
suffices expt(n, m) * expt(n * o', m) = expt(n + n * o', m)
by definition operator^ | expt
and rewrite mult_suc[n, o'] | IH'
symmetric definition operator^ in pow_add_r[n, m, n * o']
}
end
theorem pow_pos_nonneg : all b : Nat, a : Nat.
if 0<a then 0<a^b
proof
induction Nat
case 0 {
evaluate
}
case suc(b') assume IH {
arbitrary a : Nat
assume prem
suffices 0 < a * expt(b', a) by definition operator^ | expt
have exp_nz : 0 < expt(b', a) by definition operator^ in apply IH to prem
apply mult_pos_nonneg to prem, exp_nz
}
end
theorem pow_0_l : all a : Nat. if 0<a then 0^a = 0
proof
arbitrary a : Nat
switch a {
case 0 {
evaluate
}
case suc(n') {
evaluate
}
}
end
theorem pow_eq_0 : all n : Nat, m : Nat.
if m ^ n = 0 then m = 0
proof
induction Nat
case 0 {
evaluate
}
case suc(n') assume IH {
arbitrary m : Nat
switch m {
case 0 assume eq_z_t {
evaluate
}
case suc(m') assume eq_sn_t {
assume contra
have contra' : suc(m') * expt(n', suc(m')) = 0
by definition operator^ | expt in contra
have e_n_sm_z : expt(n', suc(m')) = 0 by apply mult_to_zero to contra'
have IH' : all m'':Nat. if expt(n', m'') = 0 then m'' = 0
by definition operator^ in IH
conclude false by apply IH'[suc(m')] to e_n_sm_z
}
}
}
end
theorem exp_one_implies_zero_or_one : all m : Nat, n : Nat.
if m ^ n = 1 then n = 0 or m = 1
proof
arbitrary m : Nat, n : Nat
switch n {
case 0 {
.
}
case suc(n') {
suffices (if m * expt(n', m) = 1 then m = 1) by evaluate
assume prem
apply one_mult_one to prem
}
}
end
theorem pow_lt_mono_l : all c : Nat, a : Nat, b : Nat.
if 0 < c then if a < b then a ^ c < b ^ c
proof
induction Nat
case 0 {
evaluate
}
case suc(n') assume IH {
arbitrary a : Nat, b : Nat
assume z_l_sc
assume alb
switch 0 < n' {
case true assume prop_t {
suffices a * expt(n', a) < b * expt(n', b)
by definition operator^ | expt
have ena_l_enb : expt(n', a) < expt(n', b)
by definition operator^ in apply (rewrite prop_t in IH) to alb
have enb_nz : expt(n', b) > 0
by suffices __ by definition operator >
apply greater_any_zero to ena_l_enb
have bnz : 0 < b
by apply greater_any_zero to alb
have step1 : a * expt(n', a) <= a * expt(n', b)
by apply mult_mono_le[a, expt(n', a), expt(n', b)] to
(apply less_implies_less_equal to ena_l_enb)
have step2 : a * (expt(n',b)) < b * expt(n', b)
by apply (apply mult_lt_mono_l[expt(n', b), a, b] to enb_nz) to alb
cases (apply less_equal_implies_less_or_equal to step1)
case step1': a * expt(n', a) < a * expt(n', b) {
apply less_trans[a * expt(n', a), a * expt(n', b)] to step1', step2
}
case step1'': a * expt(n', a) = a * expt(n', b) {
replace symmetric step1'' in step2
}
}
case false assume prop_f {
have nz : n' = 0 by rewrite prop_f in zero_or_positive[n']
suffices a < b by rewrite nz | expt_one
alb
}
}
}
end
theorem pow_gt_1 : all n : Nat, m : Nat.
if 1 < n then (0 < m <=> 1 < n ^ m)
proof
arbitrary n : Nat, m : Nat
assume prem
have l : if 0 < m then 1 < n ^ m
by assume zlm
suffices 1^m < n^m by rewrite symmetric one_expt[m]
suffices 1 < n by apply pow_lt_mono_l[m, 1, n] to zlm
prem
have r : if 1 < n ^ m then 0 < m
by assume nm_g1
cases zero_or_positive[m]
case zm : m = 0 {
evaluate in rewrite zm in nm_g1
}
case : 0 < m { recall 0 < m }
r, l
end
theorem pow_le_mono_l : all c : Nat, a : Nat, b : Nat.
if a <= b then a ^ c <= b ^ c
proof
induction Nat
case 0 {
evaluate
}
case suc(n') assume IH {
arbitrary a : Nat, b : Nat
assume a_le_b
suffices a * expt(n', a) ≤ b * expt(n', b)
by definition operator^ | expt
have step : expt(n', a) <= expt(n', b)
by definition operator^ in (apply IH to a_le_b)
have step1 : a * expt(n', a) <= a * expt(n', b)
by apply mult_mono_le[a, expt(n', a), expt(n', b)] to step
have step2 : a * expt(n', b) <= b * expt(n', b)
by apply mult_mono_le_r[expt(n', b), a, b] to a_le_b
apply less_equal_trans[a * expt(n', a), a * expt(n', b)] to step1, step2
}
end
theorem pow_lt_mono_r : all c : Nat, a : Nat, b : Nat.
if 1 < a then if b < c then a^b < a^c
proof
arbitrary c : Nat, a : Nat, b : Nat
assume prem
assume blc
have blec : b <= c by apply less_implies_less_equal to blc
obtain x where step from apply le_exists_sub to blec
suffices a ^ b < a ^ b * a ^ x
by rewrite step | pow_add_r
suffices 1 * a ^ b < a ^ x * 1 * a ^ b
by rewrite mult_commute[a^b, a^x] | symmetric one_mult[a^b]
have zla : 0 < a by
have zl1 : 0 < 1 by evaluate
apply less_trans[0, 1, a] to zl1, prem
have : a ^ b > 0 by
suffices __ by definition operator>
apply pow_pos_nonneg[b, a] to zla
suffices 1 < a^x * 1
by (apply mult_lt_mono_l[a^b, 1, a^x * 1] to recall a^b > 0)
have zlx : 0 < x
by cases zero_or_positive[x]
case xz : x = 0 {
have cb : c = b by rewrite xz | add_zero in step
apply less_irreflexive to rewrite cb in blc
}
case : 0 < x { recall 0 < x }
rewrite symmetric mult_one[a^x] in apply (apply pow_gt_1[a, x] to prem) to zlx
end
theorem pow_inj_l : all a : Nat, b : Nat, c : Nat.
if 0 < c then (if a^c = b^c then a = b)
proof
arbitrary a : Nat, b : Nat, c : Nat
assume zlc
assume ac_eq_bc
cases trichotomy[a, b]
case : a < b {
have contra : a^c < b^c by apply (apply pow_lt_mono_l[c, a, b] to zlc) to (recall a < b)
apply less_irreflexive to rewrite ac_eq_bc in contra
}
case : a = b { recall a = b }
case : b < a {
have contra : b^c < a^c by apply (apply pow_lt_mono_l[c, b, a] to zlc) to (recall b < a)
apply less_irreflexive to rewrite ac_eq_bc in contra
}
end
theorem pow_inj_r : all a : Nat, b : Nat, c : Nat.
if 1 < a then if a^b = a ^ c then b = c
proof
arbitrary a : Nat, b : Nat, c : Nat
assume ola
assume ab_eq_ac
cases trichotomy[b, c]
case : b < c {
apply less_irreflexive to
rewrite ab_eq_ac in
apply apply pow_lt_mono_r[c,a,b] to ola to recall b < c
}
case : b = c { recall b = c }
case : c < b {
apply less_irreflexive to
rewrite ab_eq_ac in
apply apply pow_lt_mono_r[b,a,c] to ola to recall c < b
}
end