This problem set includes several problems that test your
understanding of the proofs that ACL2 does. You are expected to do
these proofs by hand, not use the theorem prover. Your exam may
contain problems like this.
These problems are for your practice. You do not need to submit your
solutions. But we urge you to do them, to get a sense of what it
takes to do formal proofs. We will post our solutions on the Web in a
couple of weeks. But we do urge you to not look at the posted
solutions unless you are irrepairably stuck and do not find a way to
make progress. Looking at our solutions will not help you do the
reasoning --- the best way to understand how to do formal proofs is to
*do* it. However, we do hope that the experience will teach you the
need for mechanized tools like ACL2 to help you in doing proofs.
In doing the hand proofs, you can make use of (1) substitution of
equals by equals, (2) propositional reasoning, and (3) induction. You
can also prove a lemma and use any instance of that proven lemma in a
subsequent theorem. When you do propositional reasoning, remember
that the functions and, or, etc. in ACL2, are not exactly Boolean.
For instance, the ACL2 definition of AND is: (and x y) = (if x y NIL).
You can also use any standard arithmetic facts when reasoning about
numbers, but remember that the arithmetic operators (+, *, etc.) have
completion axioms that state what their values will be for non-numeric
inputs.
If you are unsure what the relevant axioms about a function are,
consult the paper "M. Kaufmann and J S. Moore: A Precise Description
of the ACL2 Logic". Feel free to ask the instructors in case you get
stuck.
The problems specifications below are often provided as informal
English text. In such cases, the first job is to formalize them,
convert them into a term that you can start proving. Note that it is
*not* sufficient to just argue the correctness of the statement
informally, --- you will need to produce a formula that you believe is
a reflection of the statement in the logic.
We understand that there may be several ways to formalize a problem.
In some cases, the problem descriptions may even be (deliberately)
ambiguous. A key skill that you need to learn in applying formal
methods is to translate informal English statements to a formal form,
and this skill can be learnt only out of practice. If for some
English statement, it is not clear what the intended formalization is,
please feel free to ask the instructors.
Problem 1: This is a warm-up, and asks you to reason about factorial.
(a) Recall the definition of factorial shown in class
(defun fact (n)
(if (zp n)
1
(* n (fact (- n 1)))))
Prove that this function always returns a natural number greater than
0.
(b) Consider the following definition:
(defun trfact (n a)
(if (zp n) a
(trfact (- n 1) (* n a))))
(defun trfact1 (n)
(trfact n 1))
Prove that trfact1 returns the factorial of a number.
Problem 2: This problem asks you to think about reversing lists.
Prove the statement that reversing a list twice returns the original
list. (Hint: You can use the rev function shown in class.)
Problem 3: This problem considers list sorting.
(a) Consider the functions orderedp and insert below.
(defun orderedp (x)
(if (endp x) t
(if (endp (cdr x)) t
(if (<= (car x) (car (cdr x)))
(orderedp (cdr x))
nil))))
(defun insert (e x)
(if (endp x) (list e)
(if (< e (car x))
(cons e x)
(cons (car x) (insert e (cdr x))))))
Prove the following statement: Suppose we insert an element e into
a ordered list x of natural numbers. Then the result is ordered.
(b) Consider the following definition of the insertion-sort function.
(defun isort (x)
(if (endp x) nil
(insert (car x) (isort (cdr x)))))
Prove that isort produces an ordered list.
Problem 4: This problem deals with trees.
(a) Consider the following definition, which swaps the elements in a tree.
(defun swap-tree (x)
(if (atom x) x
(cons (swap-tree (cdr x))
(swap-tree (car x)))))
Prove that doing swap-tree and then doing it again returns the original tree.
(b) Consider the following function fringe that creates a list out of
the leaves of a tree. Here app is the function we showed in
class.
(defun fringe (x)
(if (atom x)
(cons x nil)
(app (fringe (car x))
(fringe (cdr x)))))
Prove that the fringe of the tree obtained after the swap-tree
operation is the reverse of the fringe of the original tree.
Problem 5: This problem deals with bit vectors, and is a bit more
elaborate. You should try this problem only after you have done all
the previous ones. Also, it may be worth-while to first do this proof
in ACL2 before embarking on a proof by hand.
We will consider modeling bit vectors as lists of Booleans (that is, T
and NIL). Thus, '(T NIL) is a bit vector which you might have
conventionally written as the binary string 10. The decimal value of
this bit vector is 3.
(a) Define a function bit-vectorp that returns T if its argument is a
bit vector.
(b) Define a function bv-add which takes two bit vectors and returns
the bit-vector which represents their sum. (Note: the lengths of
the bit vectors may vary, and the length of the sum can be at most
one more than the length of the larger bit-vector.
(c) Define functions bv-to-nat and nat-to-bv to convert a bit vector
to a natural number and back. Function bv-to-nat takes a
bit-vector b and returns a natural number. Function nat-to-bv
takes a natural number n and length l and returns a bit vector of
length l whose value is the same n. If l is too small nat-to-bv
you can decide yourself what to do, for example throw an error or
truncate the result, or something else. Do whatever you feel is
natural.
(d) Formalize and state the following theorem. "Suppose we have two
bit vectors x and y, and we add them to get the bit vector z.
Convert z to a natural number. The result is the same as first
converting x and y to natural numbers and then computing their
sum.
(e) Prove the theorem above.
(f) State the other side of the theorem. That is, suppose you want to
take two arbitrary natural numbers a and b, convert them to
appropriate bit vectors and compute bit-vector sum. Then the
result should be the same as first summing a and b and then
converting the result to a bit vector. Can you state this
theorem? (Note: This statement is a bit more subtle, since you
need to produce bit vectors of appropriate lengths.)