Theorem Proving in Lean. Part of exercises 7.
parent
7a0c03cdd4
commit
9d1f3120c1
|
@ -0,0 +1,174 @@
|
|||
/- Exercises 7.10
|
||||
-
|
||||
- Avigad, Jeremy. ‘Theorem Proving in Lean’, n.d.
|
||||
-/
|
||||
import data.nat.basic
|
||||
|
||||
-- Exercise 1
|
||||
--
|
||||
-- Try defining other operations on the natural numbers, such as multiplication,
|
||||
-- the predecessor function (with `pred 0 = 0`), truncated subtraction (with
|
||||
-- `n - m = 0` when `m` is greater than or equal to `n`), and exponentiation.
|
||||
-- Then try proving some of their basic properties, building on the theorems we
|
||||
-- have already proved.
|
||||
--
|
||||
-- Since many of these are already defined in Lean’s core library, you should
|
||||
-- work within a namespace named hide, or something like that, in order to avoid
|
||||
-- name clashes.
|
||||
namespace ex_1
|
||||
|
||||
-- As defined in the book.
|
||||
inductive nat : Type
|
||||
| zero : nat
|
||||
| succ : nat → nat
|
||||
|
||||
def add (m n : nat) : nat :=
|
||||
nat.rec_on n m (λ k ak, nat.succ ak)
|
||||
|
||||
theorem add_zero (m : nat) : add m nat.zero = m := rfl
|
||||
theorem add_succ (m n : nat) : add m n.succ = (add m n).succ := rfl
|
||||
|
||||
theorem zero_add (n : nat) : add nat.zero n = n :=
|
||||
nat.rec_on n
|
||||
(add_zero nat.zero)
|
||||
(assume n ih,
|
||||
show add nat.zero (nat.succ n) = nat.succ n, from calc
|
||||
add nat.zero (nat.succ n) = nat.succ (add nat.zero n) : add_succ nat.zero n
|
||||
... = nat.succ n : by rw ih)
|
||||
|
||||
-- Additional definitions.
|
||||
def mul (m n : nat) : nat :=
|
||||
nat.rec_on n nat.zero (λ k ak, add m ak)
|
||||
|
||||
def pred (n : nat) : nat :=
|
||||
nat.cases_on n nat.zero id
|
||||
|
||||
def sub (m n : nat) : nat :=
|
||||
nat.rec_on n m (λ k ak, pred ak)
|
||||
|
||||
def exp (m n : nat) : nat :=
|
||||
nat.rec_on n (nat.zero.succ) (λ k ak, mul m ak)
|
||||
|
||||
end ex_1
|
||||
|
||||
-- Exercise 2
|
||||
--
|
||||
-- Define some operations on lists, like a `length` function or the `reverse`
|
||||
-- function. Prove some properties, such as the following:
|
||||
--
|
||||
-- a. `length (s ++ t) = length s + length t`
|
||||
-- b. `length (reverse t) = length t`
|
||||
-- c. `reverse (reverse t) = t`
|
||||
section ex_2
|
||||
|
||||
open list
|
||||
|
||||
variable {α : Type*}
|
||||
|
||||
-- Additional theorems.
|
||||
theorem length_sum (s t : list α) : length (s ++ t) = length s + length t :=
|
||||
list.rec_on s
|
||||
(by rw [nil_append, length, zero_add])
|
||||
(assume hd tl ih, by rw [
|
||||
length,
|
||||
cons_append,
|
||||
length,
|
||||
ih,
|
||||
add_assoc,
|
||||
add_comm t.length,
|
||||
add_assoc
|
||||
])
|
||||
|
||||
lemma cons_reverse (hd : α) (tl : list α)
|
||||
: reverse (hd :: tl) = reverse tl ++ [hd] :=
|
||||
sorry
|
||||
|
||||
theorem length_reverse (t : list α) : length (reverse t) = length t :=
|
||||
list.rec_on t
|
||||
(by unfold reverse reverse_core)
|
||||
(assume hd tl ih, begin
|
||||
unfold length,
|
||||
rw cons_reverse,
|
||||
rw length_sum,
|
||||
unfold length,
|
||||
rw zero_add,
|
||||
rw ih,
|
||||
end)
|
||||
|
||||
theorem reverse_reverse (t : list α) : reverse (reverse t) = t :=
|
||||
list.rec_on t rfl (assume hd tl ih, sorry)
|
||||
|
||||
end ex_2
|
||||
|
||||
-- Exercise 3
|
||||
--
|
||||
-- Define an inductive data type consisting of terms built up from the following
|
||||
-- constructors:
|
||||
--
|
||||
-- • `const n`, a constant denoting the natural number `n`
|
||||
-- • `var n`, a variable, numbered `n`
|
||||
-- • `plus s t`, denoting the sum of `s` and `t`
|
||||
-- • `times s t`, denoting the product of `s` and `t`
|
||||
--
|
||||
-- Recursively define a function that evaluates any such term with respect to an
|
||||
-- assignment of values to the variables.
|
||||
namespace ex_3
|
||||
|
||||
inductive foo : Type*
|
||||
| const : ℕ → foo
|
||||
| var : ℕ → foo
|
||||
| plus : foo → foo → foo
|
||||
| times : foo → foo → foo
|
||||
|
||||
def value_at : ℕ → list ℕ → ℕ
|
||||
| 0 vs := list.head vs
|
||||
| i [] := default
|
||||
| (i + 1) vs := value_at i (list.tail vs)
|
||||
|
||||
-- The provided "variables" are supplied in a 0-indexed list.
|
||||
def eval_foo : foo → list ℕ → ℕ
|
||||
| (foo.const n) vs := n
|
||||
| (foo.var n) vs := value_at n vs
|
||||
| (foo.plus m n) vs := eval_foo m vs + eval_foo n vs
|
||||
| (foo.times m n) vs := eval_foo m vs * eval_foo n vs
|
||||
|
||||
end ex_3
|
||||
|
||||
-- Exercise 4
|
||||
--
|
||||
-- Similarly, define the type of propositional formulas, as well as functions on
|
||||
-- the type of such formulas: an evaluation function, functions that measure the
|
||||
-- complexity of a formula, and a function that substitutes another formula for
|
||||
-- a given variable.
|
||||
namespace ex_4
|
||||
|
||||
inductive foo : Type*
|
||||
| tt : foo
|
||||
| ff : foo
|
||||
| and : foo → foo → foo
|
||||
| or : foo → foo → foo
|
||||
|
||||
def eval_foo : foo → bool
|
||||
| foo.tt := true
|
||||
| foo.ff := false
|
||||
| (foo.and lhs rhs) := eval_foo lhs ∧ eval_foo rhs
|
||||
| (foo.or lhs rhs) := eval_foo lhs ∨ eval_foo rhs
|
||||
|
||||
def complexity_foo : foo → ℕ
|
||||
| foo.tt := 1
|
||||
| foo.ff := 1
|
||||
| (foo.and lhs rhs) := 1 + complexity_foo lhs + complexity_foo rhs
|
||||
| (foo.or lhs rhs) := 1 + complexity_foo lhs + complexity_foo rhs
|
||||
|
||||
def substitute : foo → foo := sorry
|
||||
|
||||
end ex_4
|
||||
|
||||
-- Exercise 5
|
||||
--
|
||||
-- Simulate the mutual inductive definition of `even` and `odd` described in
|
||||
-- Section 7.9 with an ordinary inductive type, using an index to encode the
|
||||
-- choice between them in the target type.
|
||||
section ex_5
|
||||
|
||||
end ex_5
|
Loading…
Reference in New Issue