summaryrefslogtreecommitdiff
path: root/books/workshops/2002/cowles-flat/support/flat-ackermann.lisp
diff options
context:
space:
mode:
Diffstat (limited to 'books/workshops/2002/cowles-flat/support/flat-ackermann.lisp')
-rw-r--r--books/workshops/2002/cowles-flat/support/flat-ackermann.lisp465
1 files changed, 465 insertions, 0 deletions
diff --git a/books/workshops/2002/cowles-flat/support/flat-ackermann.lisp b/books/workshops/2002/cowles-flat/support/flat-ackermann.lisp
new file mode 100644
index 0000000..e56036d
--- /dev/null
+++ b/books/workshops/2002/cowles-flat/support/flat-ackermann.lisp
@@ -0,0 +1,465 @@
+; Introduction of a function satisfying a slightly altered version
+; of the Ackermann recursive equation.
+; Copyright (C) 2001 John R. Cowles, University of Wyoming
+
+; Original Peter version of the Ackermann recursive equation:
+
+; (equal (f x1 x2)
+; (if (equal x1 0)
+; (+ x2 1)
+; (if (equal x2 0)
+; (f (- x1 1) 1)
+; (f (- x1 1)(f x1 (- x2 1))))))
+
+; Construction based on flat domains in ACL2.
+
+; This book is free software; you can redistribute it and/or modify
+; it under the terms of the GNU General Public License as published by
+; the Free Software Foundation; either version 2 of the License, or
+; (at your option) any later version.
+
+; This book is distributed in the hope that it will be useful,
+; but WITHOUT ANY WARRANTY; without even the implied warranty of
+; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+; GNU General Public License for more details.
+
+; You should have received a copy of the GNU General Public License
+; along with this book; if not, write to the Free Software
+; Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+; Written by:
+; John Cowles
+; Department of Computer Science
+; University of Wyoming
+; Laramie, WY 82071-3682 U.S.A.
+
+; Fall 2001.
+; Modified 28 December 2001.
+; Last modified 2 March 2002.
+
+#|
+ To certify (originally in ACL2 Version 2.6):
+ (defpkg
+ "FLAT" (union-eq
+ *acl2-exports*
+ *common-lisp-symbols-from-main-lisp-package*))
+
+ (certify-book "flat-ackermann" 1 nil ; compile-flg
+ :defaxioms-okp nil
+ :skip-proofs-okp nil)
+|#
+(in-package "FLAT")
+(include-book "flat")
+
+#| We want a function that satisfies the original Peter version of
+ the Ackermann recursive equation:
+(equal (f x1 x2)
+ (if (equal x1 0)
+ (+ x2 1)
+ (if (equal x2 0)
+ (f (- x1 1) 1)
+ (f (- x1 1)(f x1 (- x2 1))))))
+|#
+
+(defun
+ <def= (x y)
+ (or (eq x 'undef$)
+ (equal x y)))
+
+(defmacro
+ sq-if (test then else)
+ "Sequential version of IF."
+ `(if (eq ,test 'undef$)
+ 'undef$
+ (if ,test ,then ,else)))
+
+(defmacro
+ lt-st-equal (x y)
+ "Left-strict version of equal."
+ `(if (eq ,x 'undef$)
+ 'undef$
+ (equal ,x ,y)))
+
+(defmacro
+ lt-st-+ (x y)
+ "Left-strict version of (binary) +."
+ `(if (eq ,x 'undef$)
+ 'undef$
+ (+ ,x ,y)))
+
+#| Our heuristics say it should be possible to get this:
+(equal (f x1 x2)
+ (if (equal x1 0)
+ (+ x2 1)
+ (sq-if (lt-st-equal x2 0)
+ (f (- x1 1) 1)
+ (f (- x1 1)(f x1 (- x2 1))))))
+|#
+#| Our heuristics are too primitive:
+ In fact we can get define a function f that satisfies:
+(equal (f x1 x2)
+ (if (equal x1 0)
+ (lt-st-+ x2 1)
+ (sq-if (lt-st-equal x2 0)
+ (f (- x1 1) 1)
+ (f (- x1 1)(f x1 (- x2 1))))))
+
+ Recall that we wanted a function that satisfies the original
+ Peter version of the Ackermann recursive equation:
+(equal (f x1 x2)
+ (if (equal x1 0)
+ (+ x2 1)
+ (if (equal x2 0)
+ (f (- x1 1) 1)
+ (f (- x1 1)(f x1 (- x2 1))))))
+
+ ACL2 can then prove the following, which is close to what we
+ had hoped for:
+
+(implies (not (equal x2 'undef$))
+ (equal (f x1 x2)
+ (if (equal x1 0)
+ (+ x2 1)
+ (if (equal x2 0)
+ (f (- x1 1) 1)
+ (f (- x1 1)(f x1 (- x2 1)))))))
+|#
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; Add some basic arithmetic facts:
+
+(local
+ (defthm
+ commutativity-2-of-+
+ (equal (+ x y z)
+ (+ y x z))))
+
+(local
+ (defthm
+ associate-constants-left-+
+ (implies (and (syntaxp (quotep x))
+ (syntaxp (quotep y)))
+ (equal (+ x (+ y z))
+ (+ (+ x y) z)))))
+
+(local
+ (defthm
+ minus-inverse-+-a
+ (implies (acl2-numberp y)
+ (equal (+ (- x) x y)
+ y))))
+
+(local
+ (defthm
+ minus-inverse-+-b
+ (implies (acl2-numberp y)
+ (equal (+ x (- x) y)
+ y))))
+
+#| Preliminary test for suitability of definition:
+(defun
+ f21-chain (i x1 x2)
+ (if (zp i)
+ 'undef$
+ (if (equal x1 0)
+ (lt-st-+ x2 1)
+ (sq-if (lt-st-equal x2 0)
+ (f21-chain (- i 1)(- x1 1) 1)
+ (f21-chain (- i 1)(- x1 1)
+ (f21-chain (- i 1) x1
+ (- x2 1)))))))
+
+(thm
+ (<def= (f21-chain i x1 x2)
+ (f21-chain (+ 1 i) x1 x2)))
+|#
+#| Unary version of what we want:
+(equal f1 (x)
+ (let ((x1 (car x))
+ (x2 (cadr x)))
+ (if (equal x1 0)
+ (lt-st-+ x2 1)
+ (sq-if (lt-st-equal x2 0)
+ (f1 (list (- x1 1) 1))
+ (f1 (list (- x1 1)
+ (f1 (list x1 (- x2 1)))))))))
+
+Heuristics suggest that second list should be right strict.
+|#
+
+(defmacro
+ rt-st-list (x y)
+ "Right-strict version of (binary) list."
+ `(if (eq ,y 'undef$)
+ 'undef$
+ (list ,x ,y)))
+
+(defun
+ f1-chain (i x)
+ (if (zp i)
+ 'undef$
+ (if (eq x 'undef$) ;; Ensure f1 is strict and
+ 'undef$ ;; thus a monotonic function.
+ (let ((x1 (car x))
+ (x2 (cadr x)))
+ (if (equal x1 0)
+ (lt-st-+ x2 1)
+ (sq-if (lt-st-equal x2 0)
+ (f1-chain (- i 1)
+ (list (- x1 1) 1))
+ (f1-chain
+ (- i 1)
+ (rt-st-list (- x1 1)
+ (f1-chain (- i 1)
+ (list
+ x1
+ (- x2 1))))
+ )))))))
+
+(defthm
+ base-of-f1-chain=undef$
+ (implies (zp i)
+ (equal (f1-chain i x)
+ 'undef$)))
+
+(defthm
+ f1-chain-is-<def=-chain
+ (implies (and (integerp i)
+ (>= i 0))
+ (<def= (f1-chain i x)
+ (f1-chain (+ 1 i) x))))
+
+;; Choose an ``index'' for definition of lub of f1-chain:
+
+(defchoose
+ lub-f1-chain-i i (x)
+ (not (equal (f1-chain i x)
+ 'undef$)))
+
+(defthm
+ lub-f1-chain-i-rewrite
+ (implies (equal (f1-chain (lub-f1-chain-i x) x)
+ 'undef$)
+ (equal (f1-chain i x) 'undef$))
+ :hints (("Goal"
+ :use lub-f1-chain-i)))
+
+;; Make sure the chosen index is a nonneg. integer:
+
+(defun
+ lub-f1-chain-nat-i (x)
+ (nfix (lub-f1-chain-i x)))
+
+(in-theory (disable (:executable-counterpart
+ lub-f1-chain-nat-i)))
+
+;; Define the least upper bound of f-chain:
+
+(defun
+ lub-f1-chain (x)
+ (f1-chain (lub-f1-chain-nat-i x) x))
+
+(in-theory (disable (:executable-counterpart
+ lub-f1-chain)))
+
+(defthm
+ lub-f1-chain-is-upper-bound
+ (<def= (f1-chain i x)
+ (lub-f1-chain x))
+ :hints (("Goal"
+ :by
+ (:functional-instance
+ lub-$bottom$-based-chain-is-upper-bound
+ ($<=$ <def=)
+ ($bottom$ (lambda () 'undef$))
+ ($bottom$-based-chain f1-chain)
+ (lub-$bottom$-based-chain lub-f1-chain)
+ (lub-$bottom$-based-chain-nat-i lub-f1-chain-nat-i)
+ (lub-$bottom$-based-chain-i lub-f1-chain-i)))
+ ("Subgoal 2" ; changed after v4-3 from "Subgoal 3", for tau system
+ :use f1-chain-is-<def=-chain)))
+
+(defthm
+ f1-chain-is-<def=-chain-f
+ (implies (and (>= i (lub-f1-chain-nat-i x))
+ (integerp i))
+ (equal (lub-f1-chain x)
+ (f1-chain i x)))
+ :hints (("Goal"
+ :by
+ (:functional-instance
+ $bottom$-based-chain-is-$<=$-chain-f
+ ($<=$ <def=)
+ ($bottom$ (lambda () 'undef$))
+ ($bottom$-based-chain f1-chain)
+ (lub-$bottom$-based-chain lub-f1-chain)
+ (lub-$bottom$-based-chain-nat-i lub-f1-chain-nat-i)
+ (lub-$bottom$-based-chain-i lub-f1-chain-i)))))
+
+(defun
+ f1 (x)
+ (lub-f1-chain x))
+
+(in-theory (disable (:executable-counterpart f1)))
+
+(defthm
+ f1-is-strict
+ (equal (f1 'undef$) 'undef$))
+
+(defun
+ g1-chain (i x)
+ (f1-chain (+ 1 i) x))
+
+(defun
+ ub-g1-chain (x)
+ (if (eq x 'undef$)
+ 'undef$
+ (let ((x1 (car x))
+ (x2 (cadr x)))
+ (if (equal x1 0)
+ (lt-st-+ x2 1)
+ (sq-if (lt-st-equal x2 0)
+ (f1 (list (- x1 1) 1))
+ (f1 (rt-st-list (- x1 1)
+ (f1 (list x1 (- x2 1))))
+ ))))))
+
+(defthm
+ g1-chain-<def=-ub-g1-chain
+ (implies (and (integerp i)
+ (>= i 0))
+ (<def= (g1-chain i x)
+ (ub-g1-chain x)))
+; fcd/Satriani v3.7 Moore - used to be Subgoal 8
+ :hints (("Subgoal 2"
+ :in-theory (disable lub-f1-chain-is-upper-bound)
+ :use (:instance
+ lub-f1-chain-is-upper-bound
+ (x (list (- (car x) 1) 1))))
+; fcd/Satriani v3.7 Moore - used to be Subgoal 3
+ ("Subgoal 6"
+ :in-theory (disable lub-f1-chain-is-upper-bound)
+ :use ((:instance
+ lub-f1-chain-is-upper-bound
+ (x (list (car x)(- (cadr x) 1))))
+ (:instance
+ lub-f1-chain-is-upper-bound
+ (x (list (- (car x) 1)
+ (f1-chain i (list (car x)
+ (- (cadr x) 1)))))
+ )))))
+
+(defun
+ Skolem-f1 (x)
+ (max (lub-f1-chain-nat-i (list (- (car x) 1) 1))
+ (max (lub-f1-chain-nat-i (list (car x)(- (cadr x) 1)))
+ (lub-f1-chain-nat-i (rt-st-list (- (car x) 1)
+ (f1 (list
+ (car x)
+ (- (cadr x) 1)))
+ )))))
+
+(defthm
+ ub-g1-chain-=-g1-chain-Skolem-f1
+ (equal (ub-g1-chain x)
+ (g1-chain (Skolem-f1 x) x))
+ :hints (("Goal"
+ :use ((:instance
+ f1-chain-is-<def=-chain-f
+ (x (list (- (car x) 1) 1))
+ (i (Skolem-f1 x)))
+ (:instance
+ f1-chain-is-<def=-chain-f
+ (x (list (car x)(- (cadr x) 1)))
+ (i (Skolem-f1 x)))
+ (:instance
+ f1-chain-is-<def=-chain-f
+ (x (rt-st-list (- (car x) 1)
+ (f1 (list
+ (car x)
+ (- (cadr x) 1)))))
+ (i (Skolem-f1 x)))))))
+
+(defthm
+ lub-f1-chain=ub-g1-chain
+ (equal (lub-f1-chain x)(ub-g1-chain x))
+ :rule-classes nil
+ :hints (("Goal"
+ :by
+ (:functional-instance
+ lub-$chain$=ub-shifted-$chain$
+ ($<=$ <def=)
+ ($bottom$ (lambda () 'undef$))
+ ($chain$ f1-chain)
+ (lub-$chain$ lub-f1-chain)
+ (lub-$chain$-i lub-f1-chain-i)
+ (lub-$chain$-nat-i lub-f1-chain-nat-i)
+ ($f$ Skolem-f1)
+ (shifted-$chain$ g1-chain)
+ (ub-shifted-$chain$ ub-g1-chain)))
+ ("Subgoal 4" ; changed after v4-3 from "Subgoal 5", for tau system
+ :use g1-chain-<def=-ub-g1-chain)
+ ("Subgoal 3" ; changed after v4-3 from "Subgoal 4", for tau system
+ :use f1-chain-is-<def=-chain)
+ ))
+
+(defthm
+ f1-def
+ (equal (f1 x)
+ (if (eq x 'undef$)
+ 'undef$
+ (let ((x1 (car x))
+ (x2 (cadr x)))
+ (if (equal x1 0)
+ (lt-st-+ x2 1)
+ (sq-if (lt-st-equal x2 0)
+ (f1 (list (- x1 1) 1))
+ (f1 (rt-st-list (- x1 1)
+ (f1 (list x1
+ (- x2 1))
+ ))
+ ))))))
+ :hints (("Goal"
+ :in-theory (disable ;;lub-f1-chain
+ ub-g1-chain-=-g1-chain-Skolem-f1)
+ :use lub-f1-chain=ub-g1-chain)))
+
+(defun
+ f (x1 x2)
+ (f1 (list x1 x2)))
+
+(defthm
+ f-def
+ (equal (f x1 x2)
+ (if (equal x1 0)
+ (lt-st-+ x2 1)
+ (sq-if (lt-st-equal x2 0)
+ (f (- x1 1) 1)
+ (f (- x1 1)(f x1 (- x2 1))))))
+ :hints (("Goal"
+ :use (:instance
+ f1-def
+ (x (list x1 x2))))))
+
+; Recall the original Peter version of the Ackermann recursive
+; equation:
+
+; (equal (f x1 x2)
+; (if (equal x1 0)
+; (+ x2 1)
+; (if (equal x2 0)
+; (f (- x1 1) 1)
+; (f (- x1 1)(f x1 (- x2 1))))))
+
+(in-theory (disable f f-def))
+
+(defthm
+ Peter-version-f-def
+ (implies (not (equal x2 'undef$))
+ (equal (f x1 x2)
+ (if (equal x1 0)
+ (+ x2 1)
+ (if (equal x2 0)
+ (f (- x1 1) 1)
+ (f (- x1 1)(f x1 (- x2 1)))))))
+ :hints (("Goal"
+ :use f-def)))