summaryrefslogtreecommitdiff
path: root/books/workshops/2007/cowles-et-al/support/greve/defminterm.lisp
diff options
context:
space:
mode:
Diffstat (limited to 'books/workshops/2007/cowles-et-al/support/greve/defminterm.lisp')
-rw-r--r--books/workshops/2007/cowles-et-al/support/greve/defminterm.lisp1459
1 files changed, 1459 insertions, 0 deletions
diff --git a/books/workshops/2007/cowles-et-al/support/greve/defminterm.lisp b/books/workshops/2007/cowles-et-al/support/greve/defminterm.lisp
new file mode 100644
index 0000000..3c06cd7
--- /dev/null
+++ b/books/workshops/2007/cowles-et-al/support/greve/defminterm.lisp
@@ -0,0 +1,1459 @@
+#|-*-Lisp-*-=================================================================|#
+#| |#
+#| Copyright © 2005-7 Rockwell Collins, Inc. All Rights Reserved. |#
+#| |#
+#|===========================================================================|#
+(in-package "ACL2")
+
+(include-book "defxch")
+(include-book "defpun")
+
+(defun o () 1)
+(defun inx (x m)
+ (declare (ignore x))
+ (+ 1 (nfix m)))
+
+(defmacro defminterm-1-arg (fn fn-test fn-base fn-step)
+
+ (let ((fn-minterm (packn-pos (list fn "_MINTERM") fn))
+ (fn-minterm-term (packn-pos (list fn "_MINTERM_TERM") fn))
+ (fn-measure (packn-pos (list fn "_MEASURE") fn))
+ (fn-terminates (packn-pos (list fn "_TERMINATES") fn))
+ )
+
+ `(encapsulate
+ ()
+
+ (set-ignore-ok t)
+ (set-irrelevant-formals-ok t)
+
+ (defxch-aux ,fn-minterm inx o natp ,fn-test ,fn-base ,fn-step)
+
+ (defun ,fn-measure (x)
+ (nfix (,fn-minterm x)))
+
+ (defun ,fn-terminates (x)
+ (,fn-minterm-term x))
+
+ (in-theory
+ (disable
+ (,fn-terminates)
+ (,fn-measure)
+ ))
+
+ (defthm ,(packn-pos (list "OPEN_" fn "_MEASURE") fn)
+ (implies (,fn-terminates kst)
+ (and
+ (implies
+ (not (,fn-test kst))
+ (equal (,fn-measure kst)
+ (+ 1 (,fn-measure (,fn-step kst)))))
+ (implies
+ (,fn-test kst)
+ (equal (,fn-measure kst) (o)))))
+ :hints (("Goal" :in-theory (disable ,(packn-pos (list fn-minterm "_TERM_PROP") fn-minterm)))))
+
+ (defthm ,(packn-pos (list "OPEN_" fn "_TERMINATES") fn)
+ (and (implies (not (,fn-test kst))
+ (iff (,fn-terminates kst)
+ (,fn-terminates (,fn-step kst))))
+ (implies (,fn-test kst)
+ (,fn-terminates kst)))
+ :hints (("Goal" :in-theory '(,(packn-pos (list fn-minterm "_TERM_PROP") fn-minterm)
+ ,fn-terminates))))
+
+ (in-theory (disable ,fn-measure ,fn-terminates))
+
+ )
+ ))
+
+(defmacro minterm (fn type &rest args)
+ (declare (ignore type args)
+ (xargs :guard (equal (len args) 1)))
+ (let ((fn-test (packn-pos (list fn "_TEST") fn))
+ (fn-base (packn-pos (list fn "_BASE") fn))
+ (fn-step (packn-pos (list fn "_STEP1") fn)))
+ `(defminterm-1-arg ,fn ,fn-test ,fn-base ,fn-step)))
+
+(defun unbundle (args list)
+ (if (consp args)
+ (cons `(,(car args) (car ,list))
+ (unbundle (cdr args) `(cdr ,list)))
+ nil))
+
+(defun args-syntax-guard (args)
+ (if (consp args)
+ (cons `(or (symbolp ,(car args)) (quotep ,(car args)))
+ (args-syntax-guard (cdr args)))
+ nil))
+
+(defun generate-open-theorems (fn fn-test fn-terminates fn-step-1 args head tail)
+ (declare (xargs :mode :program))
+ (if (consp head)
+ (let ((arg (car head)))
+ (cons
+ `(defthmd ,(packn-pos (list "OPEN_" fn "_TERMINATES_" arg) fn)
+ (implies
+ (syntaxp (and ,@(args-syntax-guard (append (cdr head) tail))))
+ (and (implies (not (,fn-test ,@args))
+ (iff (,fn-terminates ,@args)
+ (let ,(unbundle args `(,fn-step-1 (list ,@args)))
+ (,fn-terminates ,@args))))
+ (implies (,fn-test ,@args)
+ (,fn-terminates ,@args)))))
+ (generate-open-theorems fn fn-test fn-terminates fn-step-1 args (cdr head) (cons arg tail))))
+ nil))
+
+(defmacro defminterm-n-args (fn args test base step)
+
+ (let* ((fn-test (packn-pos (list fn "TEST_BODY") fn))
+ (fn-base (packn-pos (list fn "BASE_BODY") fn))
+ (fn-step (packn-pos (list fn "STEP_BODY") fn))
+ (fn-1 (packn-pos (list fn "_1") fn))
+ (fn-test-1 (packn-pos (list fn-test "_1") fn))
+ (fn-base-1 (packn-pos (list fn-base "_1") fn))
+ (fn-step-1 (packn-pos (list fn-step "_1") fn))
+ (fn-measure (packn-pos (list fn "_MEASURE") fn))
+ (fn-1-measure (packn-pos (list fn "_1_MEASURE") fn))
+ (fn-terminates (packn-pos (list fn "_TERMINATES") fn))
+ (fn-1-terminates (packn-pos (list fn "_1_TERMINATES") fn))
+ )
+
+ `(encapsulate
+ ()
+
+ (set-ignore-ok t)
+ (set-irrelevant-formals-ok t)
+
+ (defun ,fn-base-1 (list)
+ (let ,(unbundle args 'list)
+ ,base))
+
+ (defun ,fn-test-1 (list)
+ (let ,(unbundle args 'list)
+ ,test))
+
+ (defun ,fn-step-1 (list)
+ (let ,(unbundle args 'list)
+ ,step))
+
+ (defun ,fn-base (,@args)
+ (,fn-base-1 (list ,@args)))
+
+ (defun ,fn-test (,@args)
+ (,fn-test-1 (list ,@args)))
+
+ (defun ,fn-step (,@args)
+ (,fn-step-1 (list ,@args)))
+
+ (defminterm-1-arg ,fn-1 ,fn-test-1 ,fn-base-1 ,fn-step-1)
+
+ (defun ,fn-measure (,@args)
+ (,fn-1-measure (list ,@args)))
+
+ (defun ,fn-terminates (,@args)
+ (,fn-1-terminates (list ,@args)))
+
+ (defthm ,(packn-pos (list "OPEN_" fn "_MEASURE") fn)
+ (implies (,fn-terminates ,@args)
+ (and
+ (implies
+ (not (,fn-test ,@args))
+ (equal (,fn-measure ,@args)
+ (let ,(unbundle args `(,fn-step-1 (list ,@args)))
+ (+ 1 (,fn-measure ,@args)))))
+ (implies
+ (,fn-test ,@args)
+ (equal (,fn-measure ,@args) (o))))))
+
+ (defthm ,(packn-pos (list "OPEN_" fn "_TERMINATES") fn)
+ (implies
+ (syntaxp (and ,@(args-syntax-guard args)))
+ (and (implies (not (,fn-test ,@args))
+ (iff (,fn-terminates ,@args)
+ (let ,(unbundle args `(,fn-step-1 (list ,@args)))
+ (,fn-terminates ,@args))))
+ (implies (,fn-test ,@args)
+ (,fn-terminates ,@args)))))
+
+ ,@(if (< 1 (len args))
+ (generate-open-theorems fn fn-test fn-terminates fn-step-1 args args nil)
+ nil)
+
+ (defthmd ,(packn-pos (list "OPEN_" fn "_TERMINATES!") fn)
+ (and (implies (not (,fn-test ,@args))
+ (iff (,fn-terminates ,@args)
+ (let ,(unbundle args `(,fn-step-1 (list ,@args)))
+ (,fn-terminates ,@args))))
+ (implies (,fn-test ,@args)
+ (,fn-terminates ,@args))))
+
+ (in-theory (disable ,fn-measure ,fn-terminates))
+
+ )))
+
+(defun if-formp (form)
+ (declare (type t form))
+ (if (consp form)
+ (if (equal (car form) 'if)
+ (and (consp (cdr form))
+ (consp (cddr form))
+ (consp (cdddr form))
+ (null (cddddr form)))
+ (if (equal (car form) 'let)
+ (and (consp (cdr form))
+ (consp (cddr form))
+ (null (cdddr form))
+ (if-formp (caddr form)))
+ t))
+ nil))
+
+;;
+;; Some number of let's followed by an "if"
+;;
+
+(defun if-test (form)
+ (declare (type (satisfies if-formp) form))
+ (if (consp form)
+ (if (equal (car form) 'if)
+ (cadr form)
+ (if (equal (car form) 'let)
+ `(let ,(cadr form)
+ ,(if-test (caddr form)))
+ nil))
+ nil))
+
+(defun if-base (form)
+ (declare (type (satisfies if-formp) form))
+ (if (consp form)
+ (if (equal (car form) 'if)
+ (caddr form)
+ (if (equal (car form) 'let)
+ `(let ,(cadr form)
+ ,(if-base (caddr form)))
+ nil))
+ nil))
+
+(defun if-body (form)
+ (declare (type (satisfies if-formp) form))
+ (if (consp form)
+ (if (equal (car form) 'if)
+ (cadddr form)
+ (if (equal (car form) 'let)
+ `(let ,(cadr form)
+ ,(if-body (caddr form)))
+ nil))
+ nil))
+
+(defun contains-fapp-rec (fn args form)
+ (declare (type t form))
+ (if (consp form)
+ (if args
+ (or (contains-fapp-rec fn nil (car form))
+ (contains-fapp-rec fn t (cdr form)))
+ (or (equal fn (car form))
+ (contains-fapp-rec fn t (cdr form))))
+ nil))
+
+(defmacro contains-fapp (fn form)
+ `(contains-fapp-rec ,fn nil ,form))
+
+(defun wf-measure-body (fn form)
+ (declare (type t form))
+ (and (if-formp form)
+ (not (iff (contains-fapp fn (if-base form))
+ (contains-fapp fn (if-body form))))))
+
+(defun remap-fn-rec (fn fn* args form)
+ (declare (type (satisfies true-listp) fn*))
+ (if (consp form)
+ (if args
+ (cons (remap-fn-rec fn fn* nil (car form))
+ (remap-fn-rec fn fn* t (cdr form)))
+ (if (equal fn (car form))
+ (append fn* (remap-fn-rec fn fn* t (cdr form)))
+ (cons (car form) (remap-fn-rec fn fn* t (cdr form)))))
+ form))
+
+(defmacro remap-fn (fn fn* form)
+ `(remap-fn-rec ,fn ,fn* nil ,form))
+
+(defun replace-fn-rec (fn term args form)
+ (declare (type t form))
+ (if (consp form)
+ (if args
+ (cons (replace-fn-rec fn term nil (car form))
+ (replace-fn-rec fn term t (cdr form)))
+ (if (equal fn (car form))
+ term
+ (cons (car form) (replace-fn-rec fn term t (cdr form)))))
+ form))
+
+(defmacro replace-fn (fn term form)
+ `(replace-fn-rec ,fn ,term nil ,form))
+
+(defun map-replace-fn (fn list body)
+ (declare (type t fn list body))
+ (if (consp list)
+ (cons
+ (replace-fn fn (car list) body)
+ (map-replace-fn fn (cdr list) body))
+ nil))
+
+(defthm true-listp-map-replace-fn
+ (true-listp (map-replace-fn fn list body)))
+
+(defun extract-fn (fn args form)
+ (declare (type t form))
+ (if (consp form)
+ (if args
+ (or (extract-fn fn nil (car form))
+ (extract-fn fn t (cdr form)))
+ (if (equal fn (car form)) form
+ (extract-fn fn t (cdr form))))
+ form))
+
+(defun push-lets (fn body)
+ (declare (type t fn body))
+ (let ((fcall (extract-fn fn nil body)))
+ (if (consp fcall)
+ `(,fn ,@(map-replace-fn fn (cdr fcall) body))
+ `(,fn))))
+
+(defun test-base-body (fn form)
+ (declare (type (satisfies if-formp) form))
+ (let ((body (if-body form)))
+ (if (contains-fapp fn body)
+ (mv (if-test form) (if-base form) body)
+ (mv `(not ,(if-test form)) body (if-base form)))))
+
+(defun pun-form (fn form)
+ (declare (type (satisfies if-formp) form))
+ (let ((body (if-body form)))
+ (if (contains-fapp fn body)
+ (let ((test (if-test form))
+ (base (if-base form))
+ (body (push-lets fn body)))
+ `(if ,test ,base ,body))
+ (let ((test `(not ,(if-test form)))
+ (base body)
+ (body (push-lets fn (if-base form))))
+ `(if ,test ,base ,body)))))
+
+(defun first-list (list)
+ (declare (type t list))
+ (if (consp list)
+ (if (consp (cdr list))
+ (cons (car list) (first-list (cdr list)))
+ nil)
+ nil))
+
+; (declare (xargs :guard (wf-measure-body fn form)))
+
+(defun contains-guard-declaration-rec (decl)
+ (declare (type t decl))
+ (if (consp decl)
+ (if (consp (car decl))
+ (or (equal (caar decl) 'type)
+ (contains-guard-declaration-rec (cdr decl)))
+ (contains-guard-declaration-rec (cdr decl)))
+ nil))
+
+(defun contains-guard-declaration (decl)
+ (declare (type t decl))
+ (and (consp decl)
+ (equal (car decl) 'declare)
+ (contains-guard-declaration-rec (cdr decl))))
+
+(defun contain-guard-declarations (decls)
+ (declare (type t decls))
+ (if (consp decls)
+ (or (contains-guard-declaration (car decls))
+ (contain-guard-declarations (cdr decls)))
+ nil))
+
+(defmacro defminterm (fn args &rest term)
+ (let ((form (car (last term)))
+ (decls (first-list term)))
+ (let ((guards (contain-guard-declarations decls)))
+ (mv-let (test base body) (test-base-body fn form)
+ (let ((step (remap-fn fn `(list) body)))
+ (let ((fn-terminates (packn-pos (list fn "_TERMINATES") fn))
+ (fn-measure (packn-pos (list fn "_MEASURE") fn))
+ ;(fn-step-1 (packn-pos (list fn "STEP_BODY_1") fn))
+ (fn-x (packn-pos (list fn "_EXECUTION") fn))
+ (fn-x-nt (packn-pos (list fn "_EXECUTION_NON_TERMINATING") fn))
+ (fn-x-to-fn (packn-pos (list fn "_EXECUTION_TO_" fn) fn))
+ (open-fn-terminates (packn-pos (list "OPEN_" fn "_TERMINATES") fn))
+ (open-fn-rec-term (packn-pos (list "OPEN_" fn "_REC_TERM") fn))
+ )
+ (let ((body-x (remap-fn fn `(,fn-x _base_case_) body)))
+ `(encapsulate
+ ()
+
+ (set-ignore-ok t)
+ (set-irrelevant-formals-ok t)
+
+ (defminterm-n-args ,fn ,args ,test ,base ,step)
+
+ ,@(and
+ guards
+ `(
+ (defun ,fn-x (_base_case_ ,@args)
+ ,@decls
+ (declare (xargs :verify-guards nil
+ :measure (,fn-measure ,@args)))
+ (mbe :logic (if (,fn-terminates ,@args)
+ (if ,test ,base ,body-x)
+ _base_case_)
+ :exec (if ,test ,base ,body-x)))
+
+ (defthm ,fn-x-nt
+ (implies
+ (not (,fn-terminates ,@args))
+ (equal (,fn-x _base_case_ ,@args) _base_case_)))
+
+ (verify-guards
+ ,fn-x
+ :hints (("goal" :in-theory (disable ,open-fn-terminates))
+ (and acl2::stable-under-simplificationp
+ `(:in-theory (current-theory :here)))))))
+
+ (defun ,fn (,@args)
+ ,@decls
+ (declare (xargs :verify-guards nil
+ :measure (,fn-measure ,@args)))
+ ,(let ((logic `(if (and (,fn-terminates ,@args) (not ,test))
+ ,body
+ ,base)))
+ (if guards
+ `(mbe :logic ,logic
+ :exec (,fn-x ,base ,@args))
+ logic)))
+
+ (defthmd ,open-fn-rec-term
+ (implies (and (,fn-terminates ,@args) (not ,test))
+ (equal (,fn ,@args) ,body)))
+
+ ,@(if guards
+ `(
+ (defthm ,fn-x-to-fn
+ (implies
+ (,fn-terminates ,@args)
+ (equal (,fn-x _base_case_ ,@args)
+ (,fn ,@args))))
+
+ (verify-guards
+ ,fn
+ :hints (("goal" :in-theory (disable ,open-fn-terminates))))
+ )
+ `(
+ (in-theory
+ (disable
+ (,fn)
+ ))))
+
+ )
+ )))))))
+
+(encapsulate
+ ()
+
+ (local
+ (encapsulate
+ ()
+
+ (defund inca (a) (1+ (ifix a)))
+
+ (defstub some-test (a) nil)
+ (defund test-a (a) (some-test a))
+
+ (defminterm foo (a)
+ (let ((a (inca a)))
+ (if (test-a a) (inca a)
+ (foo (inca a)))))
+
+ (defthm integerp-foo
+ (integerp (foo a))
+ :hints (("Subgoal *1/2" :expand (inca a))))
+
+ (defthm foo-prop
+ (implies
+ (integerp a)
+ (< a (foo a)))
+ :hints (("Goal" :induct (foo a))
+ (and acl2::stable-under-simplificationp
+ '(:in-theory (enable inca)))))
+
+ )))
+
+(encapsulate
+ ()
+
+ (local
+ (encapsulate
+ ()
+
+ (defund foo_test (x) x)
+ (defund foo_base (x) x)
+ (defund foo_step1 (x) x)
+
+ (minterm foo state (x state))
+
+ )))
+
+(encapsulate
+ (
+ (defxch_measure (x) t)
+ (defxch_terminates (x) t)
+ (defxch_test (x) t)
+ (defxch_base (r x) t)
+ (defxch_r0 () t)
+ (defxch_steps (x) t)
+ (defxch_fn_pun (r x) t)
+ (defxch_inc (x r) t)
+ (defxch_hyps (x) t)
+ (defxch_type (x) t)
+ (defxch_default () t)
+ )
+
+ (local
+ (encapsulate ()
+
+ (defstub defxch_r0 () nil)
+ (defstub defxch_default () nil)
+ (defstub defxch_test (x) nil)
+ (defund defxch_steps (x) x)
+
+ (defun defxch_hyps (x)
+ (declare (ignore x)) t)
+
+ (defun defxch_type (x)
+ (declare (ignore x)) t)
+
+ (defun defxch_inc (x r)
+ (declare (ignore x)) r)
+
+ (defun defxch_base (r x)
+ (declare (ignore x)) r)
+
+ (defminterm defxch (x)
+ (if (defxch_test x) x
+ (defxch (defxch_steps x))))
+
+ (defpun defxch_fn_pun (r x)
+ (if (defxch_test x) (defxch_base r x)
+ (defxch_fn_pun (defxch_inc x r) (defxch_steps x))))
+
+ ))
+
+ (defthm defxch_base_defxch_inc_commute
+ (equal (defxch_base (defxch_inc a r) x)
+ (defxch_inc a (defxch_base r x))))
+
+ (defthm defxch_type_defxch_r0
+ (defxch_type (defxch_r0)))
+
+ (defthm defxch_type_defxch_base
+ (implies
+ (and
+ (defxch_hyps x)
+ (defxch_type r))
+ (defxch_type (defxch_base r x))))
+
+ (defthm defxch_type_defxch_default
+ (defxch_type (defxch_default)))
+
+ (defthm defxch_inc_preserves_type
+ (implies
+ (and
+ (defxch_hyps x)
+ (defxch_type r))
+ (defxch_type (defxch_inc x r))))
+
+ (defthm defxch_steps_preserves_hyps
+ (implies
+ (defxch_hyps x)
+ (defxch_hyps (defxch_steps x)))
+ :hints (("Goal" :in-theory (enable defxch_steps))))
+
+ (defthm natp-defxch_measure
+ (natp (defxch_measure x))
+ :rule-classes (:rewrite :type-prescription))
+
+ (defthm defxch_measure_property
+ (implies
+ (and
+ (defxch_terminates x)
+ (not (defxch_test x)))
+ (< (defxch_measure (defxch_steps x)) (defxch_measure x)))
+ :rule-classes (:rewrite :linear))
+
+ (defthm defxch_terminates_property
+ (and
+ (implies
+ (and
+ (defxch_hyps x)
+ (defxch_test x))
+ (iff (defxch_terminates x) t))
+ (implies
+ (and
+ (defxch_hyps x)
+ (not (defxch_test x)))
+ (iff (defxch_terminates x) (defxch_terminates (defxch_steps x))))))
+
+ (defthm defxch_fn_pun_prop
+ (implies
+ (and
+ (defxch_hyps x)
+ (defxch_type r))
+ (equal (defxch_fn_pun r x)
+ (if (defxch_test x) (defxch_base r x)
+ (defxch_fn_pun (defxch_inc x r) (defxch_steps x)))))
+ :rule-classes (:definition))
+
+ (defthm defxch_inc_of-inc
+ (implies
+ (and
+ (defxch_hyps x)
+ (defxch_hyps a)
+ (defxch_type r))
+ (equal (defxch_inc a (defxch_inc x r))
+ (defxch_inc x (defxch_inc a r)))))
+
+ )
+
+(encapsulate
+ ()
+
+ (local
+ (encapsulate
+ ()
+
+ (defun defxch_inductshun (r x)
+ (declare (xargs :measure (defxch_measure x)))
+ (if (or (not (defxch_hyps x)) (not (defxch_type r)) (defxch_test x) (not (defxch_terminates x))) r
+ (defxch_inductshun (defxch_inc x r) (defxch_steps x))))
+
+ (defthm open_defxch_fn_pun
+ (and
+ (implies
+ (and
+ (defxch_hyps x)
+ (defxch_type r)
+ (defxch_test x))
+ (equal (defxch_fn_pun r x) (defxch_base r x)))
+ (implies
+ (and
+ (defxch_hyps x)
+ (defxch_type r)
+ (not (defxch_test x)))
+ (equal (defxch_fn_pun r x)
+ (defxch_fn_pun (defxch_inc x r) (defxch_steps x))))))
+
+ (defthm foo-over-defxch_inc
+ (implies
+ (and
+ (defxch_hyps x)
+ (defxch_type r)
+ (defxch_hyps a)
+ (defxch_terminates x))
+ (equal (defxch_fn_pun (defxch_inc a r) x)
+ (defxch_inc a (defxch_fn_pun r x))))
+ :hints (("goal" :induct (defxch_inductshun r x))
+ ("Subgoal *1/1" :cases ((defxch_test x)))))
+
+ (defthm terminal_prop
+ (implies
+ (and
+ (defxch_hyps x)
+ (defxch_type r)
+ (defxch_terminates x))
+ (equal (defxch_fn_pun r x)
+ (if (defxch_test x) (defxch_base r x)
+ (defxch_inc x (defxch_fn_pun r (defxch_steps x))))))
+ :rule-classes nil
+ :hints (("Goal" :induct (defxch_inductshun r x))))
+
+ ))
+
+ (defun defxch_fn (x)
+ (declare (xargs :measure (defxch_measure x)))
+ (if (defxch_terminates x)
+ (if (defxch_test x) (defxch_base (defxch_r0) x)
+ (defxch_inc x (defxch_fn (defxch_steps x))))
+ (defxch_default)))
+
+ (local
+ (encapsulate
+ ()
+
+ (defun defxch_aux (x)
+ (defxch_fn_pun (defxch_r0) x))
+
+ (defthm open_defxch_aux
+ (implies
+ (and
+ (defxch_hyps x)
+ (defxch_terminates x))
+ (equal (defxch_aux x)
+ (if (defxch_test x) (defxch_base (defxch_r0) x)
+ (defxch_inc x (defxch_aux (defxch_steps x))))))
+ :hints (("Goal" :use (:instance terminal_prop (r (defxch_r0))))))
+
+ (defthm defxch_fn_to_aux
+ (implies
+ (and
+ (defxch_hyps x)
+ (defxch_terminates x))
+ (equal (defxch_fn x) (defxch_aux x)))
+ :hints (("Goal" :induct (defxch_fn x))))
+
+ ))
+
+ (defthm defxch_fn_to_fn_pun
+ (implies
+ (and
+ (defxch_hyps x)
+ (defxch_terminates x))
+ (equal (defxch_fn x) (defxch_fn_pun (defxch_r0) x))))
+
+ )
+
+(local
+ (encapsulate
+ ()
+
+ (defstub test (x) nil)
+ (defstub steq (x) nil)
+
+ (defminterm foo_induction (x)
+ (if (test x) x
+ (foo_induction (steq x))))
+
+ ;;
+ ;; Here is a template for how to use this theorem ..
+ ;;
+
+ (defpun foo_pun (r x)
+ (if (test x) r
+ (foo_pun (+ 1 r) (steq x))))
+
+ #+joe
+ (defthm open_foo_pun
+ (implies
+ (in-conclusion (foo_pun r x))
+ (equal (foo_pun r x)
+ (if (test x) r
+ (foo_pun (+ 1 r) (steq x)))))
+ :hints (("Goal" :in-theory (enable open-foo_pun))))
+
+ (defun foo (x)
+ (declare (xargs :measure (foo_induction_measure x)))
+ (if (foo_induction_terminates x)
+ (if (test x) 0
+ (+ 1 (foo (steq x))))
+ 0))
+
+ (defthm foo_to_foo_pun
+ (implies
+ (foo_induction_terminates x)
+ (equal (foo x) (foo_pun 0 x)))
+ :hints (("Goal" :use (:functional-instance defxch_fn_to_fn_pun
+ (defxch_type (lambda (r) t))
+ (defxch_hyps (lambda (x) t))
+ (defxch_fn foo)
+ (defxch_fn_pun foo_pun)
+ (defxch_test test)
+ (defxch_r0 (lambda () 0))
+ (defxch_base (lambda (r x) r))
+ (defxch_default (lambda () 0))
+ (defxch_steps steq)
+ (defxch_measure foo_induction_measure)
+ (defxch_terminates foo_induction_terminates)
+ (defxch_inc (lambda (x r) (+ 1 r)))
+ ))))
+
+
+ ))
+
+(defmacro defxch-1 (fn fn_test r0 fn_base fn_step fn_inc &key (measure 'nil) (terminates 'nil))
+ (declare (xargs :guard (iff measure terminates)))
+ (let ((fn_induction (packn-pos (list fn "_INDUCTION") fn))
+ (fn_induction_measure (or measure (packn-pos (list fn "_INDUCTION_MEASURE") fn)))
+ (fn_induction_terminates (or terminates (packn-pos (list fn "_INDUCTION_TERMINATES") fn)))
+ (measure-required (not measure))
+ (fn_pun (packn-pos (list fn "_PUN") fn))
+ (open-fn_pun (packn-pos (list "OPEN-" fn "_PUN") fn))
+ (fn_to_fn_pun (packn-pos (list fn "_TO_" fn "_PUN") fn))
+ )
+
+ `(encapsulate
+ ()
+
+ ,@(and measure-required
+ `((defminterm ,fn_induction (x)
+ (if (,fn_test x) x
+ (,fn_induction (,fn_step x))))))
+
+ (defpun ,fn_pun (r x)
+ (if (,fn_test x) (,fn_base r x)
+ (,fn_pun (,fn_inc x r) (,fn_step x))))
+
+ (in-theory (enable ,open-fn_pun))
+
+ (defun ,fn (x)
+ (declare (xargs :measure (,fn_induction_measure x)))
+ (if (,fn_induction_terminates x)
+ (if (,fn_test x) (,fn_base ,r0 x)
+ (,fn_inc x (,fn (,fn_step x))))
+ ,r0))
+
+ (defthmd ,fn_to_fn_pun
+ (implies
+ (,fn_induction_terminates x)
+ (equal (,fn x) (,fn_pun ,r0 x)))
+ :hints (("Goal" :use (:functional-instance defxch_fn_to_fn_pun
+ (defxch_type (lambda (r) t))
+ (defxch_hyps (lambda (x) t))
+ (defxch_test ,fn_test)
+ (defxch_r0 (lambda () ,r0))
+ (defxch_base ,fn_base)
+ (defxch_default (lambda () ,r0))
+ (defxch_steps ,fn_step)
+ (defxch_fn ,fn)
+ (defxch_fn_pun ,fn_pun)
+ (defxch_measure ,fn_induction_measure)
+ (defxch_terminates ,fn_induction_terminates)
+ (defxch_inc ,fn_inc)
+ ))))
+
+
+ )))
+
+(local
+ (encapsulate
+ ()
+ (defstub goo_test (x) nil)
+ (defstub goo_step (x) nil)
+ (defstub goo_pred (x) nil)
+
+ (defun goo_base (r x)
+ (declare (ignore x))
+ r)
+
+ (defun goo_inc (x r)
+ (and (goo_pred x) r))
+
+ (defxch-1 goo goo_test 't goo_base goo_step goo_inc)
+
+ ))
+
+(defun just-body (fn term)
+ (declare (type t fn term))
+ (if (consp term)
+ (if (consp (car term))
+ (if (equal (caar term) fn)
+ (car term)
+ (just-body fn (cdr term)))
+ (just-body fn (cdr term)))
+ nil))
+
+(defun tail-body (fn form)
+ (declare (type (satisfies if-formp) form))
+ (if (consp form)
+ (if (equal (car form) 'let)
+ `(let ,(cadr form)
+ ,(tail-body fn (caddr form)))
+ (just-body fn form))
+ nil))
+
+;; For efficiency we may want to witness a 2 argument example that we can
+;; functionally instantiate over and over in vfaat .. rather than doing a
+;; complete defxch each time.
+
+(defmacro defxch (fn args form &key (defpun 'nil) (measure 'nil) (terminates 'nil) (induction 'nil))
+ (declare (xargs :guard (and (iff measure terminates) (implies defpun measure))))
+ (let ((fn_pun (or defpun (packn-pos (list fn "_PUN") fn)))
+ (fn_pun_induction (packn-pos (list fn "_PUN_INDUCTION") fn))
+ (fn_induction (or induction (if measure fn (packn-pos (list fn "_INDUCTION") fn))))
+ (fn_induction_terminates (or terminates (packn-pos (list fn "_INDUCTION_TERMINATES") fn)))
+ (fn_induction_measure (or measure (packn-pos (list fn "_INDUCTION_MEASURE") fn)))
+ (defmeasure (not measure))
+ (open-fn_pun (packn-pos (list "OPEN-" fn "_PUN") fn))
+ (fn-1 (packn-pos (list fn "-1") fn))
+ (fn-1-pun (packn-pos (list fn "-1_PUN") fn))
+ (fn-inc-1 (packn-pos (list fn "-inc-1") fn))
+ (fn-test-1 (packn-pos (list fn "-test-1") fn))
+ (fn-step-1 (packn-pos (list fn "-step-1") fn))
+ (fn-measure-1 (packn-pos (list fn "-measure-1") fn))
+ (fn-terminates-1 (packn-pos (list fn "-terminates-1") fn))
+ (fn-1-reduction (packn-pos (list fn "-1-reduction") fn))
+ (fn-1-pun-reduction (packn-pos (list fn "-1-pun-reduction") fn))
+ (fn-to-fn-pun (packn-pos (list fn "_to_" fn "_pun") fn))
+ (fn-1-to-fn-1-pun (packn-pos (list fn "-1_TO_" fn "-1_PUN") fn))
+ )
+ (mv-let (test base body) (test-base-body fn form)
+ (let ((tbody (tail-body fn body)))
+ (let ((fn-inc (replace-fn fn `xarg body)))
+ (let ((pun-body (remap-fn fn `(,fn_pun ,fn-inc) (push-lets fn tbody))))
+ `(encapsulate
+ ()
+
+ (set-ignore-ok t)
+ (set-irrelevant-formals-ok t)
+
+ ,@(and defmeasure
+ `((defminterm ,fn_induction ,args
+ (if ,test (list ,@args) ,(remap-fn fn `(,fn_induction) tbody)))))
+
+ ,@(and (not defpun)
+ `(
+ (defpun ,fn_pun (xarg ,@args)
+ (if ,test xarg ,pun-body))
+
+ (in-theory (enable ,open-fn_pun))
+
+ (defun ,fn ,args
+ (declare (xargs :measure (,fn_induction_measure ,@args)))
+ (if (,fn_induction_terminates ,@args)
+ ,form
+ ,base))
+ ))
+
+ (local
+ (encapsulate
+ ()
+
+ (defun ,fn-test-1 (list)
+ (let ,(unbundle args 'list)
+ ,test))
+
+ (defun ,fn-step-1 (list)
+ (let ,(unbundle args 'list)
+ ,(remap-fn fn `(list) tbody)))
+
+ (defun ,fn-inc-1 (list xarg)
+ (let ,(unbundle args 'list)
+ ,fn-inc))
+
+ (defun ,fn-measure-1 (list)
+ (let ,(unbundle args 'list)
+ (,fn_induction_measure ,@args)))
+
+ (defun ,fn-terminates-1 (list)
+ (let ,(unbundle args 'list)
+ (,fn_induction_terminates ,@args)))
+
+ (defxch-1 ,fn-1 ,fn-test-1 ,base (lambda (r x) r) ,fn-step-1 ,fn-inc-1
+ :measure ,fn-measure-1
+ :terminates ,fn-terminates-1
+ )
+
+ (defthm ,fn-1-reduction
+ (equal (,fn ,@args)
+ (,fn-1 (list ,@args)))
+ :hints (("Goal" :induct (,fn_induction ,@args))))
+
+ (defun ,fn_pun_induction (xarg ,@args)
+ (declare (xargs :measure (,fn_induction_measure ,@args)))
+ (if (,fn_induction_terminates ,@args)
+ (if ,test xarg ,(remap-fn fn_pun `(,fn_pun_induction) pun-body))
+ xarg))
+
+ (defthm ,fn-1-pun-reduction
+ (implies
+ (,fn_induction_terminates ,@args)
+ (equal (,fn_pun xarg ,@args)
+ (,fn-1-pun xarg (list ,@args))))
+ :hints (("Goal" :induct (,fn_pun_induction xarg ,@args))))
+
+ ))
+
+ (defthmd ,fn-to-fn-pun
+ (implies
+ (,fn_induction_terminates ,@args)
+ (equal (,fn ,@args) (,fn_pun ,base ,@args)))
+ :hints (("Goal" :in-theory (enable ,fn-1-to-fn-1-pun))))
+
+ )))))))
+
+(encapsulate
+ ()
+ (local
+ (encapsulate
+ ()
+
+ (SET-IGNORE-OK T)
+ (SET-IRRELEVANT-FORMALS-OK T)
+ (defstub text (x y) nil)
+ (defstub hoot (x y) nil)
+ (defstub stx (x y) nil)
+ (defstub sty (x y) nil)
+ (defun inxx (x r) (+ 1 r))
+ (defxch goop (x y)
+ (if (text x y) (r0)
+ (inxx x (goop (stx x y) (sty x y)))))
+
+ ))
+ )
+
+(encapsulate
+ ()
+ (local
+ (encapsulate
+ ()
+
+ (SET-IGNORE-OK T)
+ (SET-IRRELEVANT-FORMALS-OK T)
+ (defstub text (x y) nil)
+ (defstub hoot (x y) nil)
+ (defstub stx (x y) nil)
+ (defstub sty (x y) nil)
+ (defun inxx (x r) (+ 1 r))
+ (defminterm goop_induction (x y)
+ (if (text x y) (list x y)
+ (goop_induction (stx x y) (sty x y))))
+ (defxch goop (x y)
+ (if (text x y) (r0)
+ (inxx x (goop (stx x y) (sty x y))))
+ :measure goop_induction_measure
+ :terminates goop_induction_terminates)
+
+ ))
+ )
+
+(encapsulate
+ ()
+ (local
+ (encapsulate
+ ()
+
+ (SET-IGNORE-OK T)
+ (SET-IRRELEVANT-FORMALS-OK T)
+ (defstub text (x y) nil)
+ (defstub hoot (x y) nil)
+ (defstub stx (x y) nil)
+ (defstub sty (x y) nil)
+ (defun inxx (x r) (+ 1 r))
+ (defminterm goop_induction (x y)
+ (if (text x y) (list x y)
+ (goop_induction (stx x y) (sty x y))))
+ (defun goop (x y)
+ (declare (xargs :measure (goop_induction_measure x y)))
+ (if (goop_induction_terminates x y)
+ (if (text x y) (r0)
+ (inxx x (goop (stx x y) (sty x y))))
+ (r0)))
+ (defpun goop_pun (xarg x y)
+ (if (text x y) xarg
+ (goop_pun (inxx x xarg) (stx x y) (sty x y))))
+ (in-theory (enable open-goop_pun))
+ (defxch goop (x y)
+ (if (text x y) (r0)
+ (inxx x (goop (stx x y) (sty x y))))
+ :defpun goop_pun
+ :measure goop_induction_measure
+ :terminates goop_induction_terminates)
+
+ ))
+ )
+
+(defmacro vfaat_fn_hyps (k st)
+ `(and (vfaat_fn_hyp1 ,k)
+ (vfaat_fn_hyp2 ,st)))
+
+(encapsulate
+ (
+ (vfaat_fn_hyp1 (k) t)
+ (vfaat_fn_hyp2 (st) t)
+ (vfaat_fn_type (r) t)
+ (vfaat_fn (k st) t)
+ (vfaat_fn_pun (r k st) t)
+ (vfaat_fn_induction_measure (k st) t)
+ (vfaat_fn_induction_terminates (k st) t)
+ (vfaat_fn_test (k) t)
+ (vfaat_fn_base () t)
+ (vfaat_fn_default () t)
+ (vfaat_fn_branch (k st) t)
+ (vfaat_fn_comp (k st) t)
+ (vfaat_fn_inc (k st r) t)
+ )
+
+ (local
+ (encapsulate ()
+
+ (defstub vfaat_fn_test (k) nil)
+ (defstub vfaat_fn_base () nil)
+ (defstub vfaat_fn_default () nil)
+ (defstub vfaat_fn_branch (k st) nil)
+ (defstub vfaat_fn_comp (k st) nil)
+
+ (defun vfaat_fn_hyp1 (k)
+ (declare (ignore k))
+ t)
+
+ (defun vfaat_fn_hyp2 (st)
+ (declare (ignore st))
+ t)
+
+ (defun vfaat_fn_type (r)
+ (declare (ignore r))
+ t)
+
+ (defun vfaat_fn_inc (k st r)
+ (declare (ignore k st)) r)
+
+ (defminterm vfaat_fn_induction (k st)
+ (if (vfaat_fn_test k) (list k st)
+ (vfaat_fn_induction (vfaat_fn_branch k st) (vfaat_fn_comp k st))))
+
+ (defun vfaat_fn (k st)
+ (declare (xargs :measure (vfaat_fn_induction_measure k st)))
+ (if (vfaat_fn_induction_terminates k st)
+ (if (vfaat_fn_test k) (vfaat_fn_base)
+ (vfaat_fn_inc k st (vfaat_fn (vfaat_fn_branch k st) (vfaat_fn_comp k st))))
+ (vfaat_fn_default)))
+
+ (defpun vfaat_fn_pun (r k st)
+ (if (vfaat_fn_test k) r
+ (vfaat_fn_pun (vfaat_fn_inc k st r) (vfaat_fn_branch k st) (vfaat_fn_comp k st))))
+
+ ))
+
+ (defthm vfaat_fn_step_preserves_vfaat_fn_hyps
+ (implies
+ (and
+ (vfaat_fn_hyp1 k)
+ (vfaat_fn_hyp2 st))
+ (and (vfaat_fn_hyp1 (vfaat_fn_branch k st))
+ (vfaat_fn_hyp2 (vfaat_fn_comp k st)))))
+
+ (defthm vfaat_fn_type_vfaat_fn_base
+ (vfaat_fn_type (vfaat_fn_base)))
+
+ (defthm vfaat_fn_type_vfaat_fn_default
+ (vfaat_fn_type (vfaat_fn_default)))
+
+ (defthm vfaat_fn_type_vfaat_fn_inc
+ (implies
+ (and
+ (vfaat_fn_hyp1 k)
+ (vfaat_fn_hyp2 st)
+ (vfaat_fn_type r))
+ (vfaat_fn_type (vfaat_fn_inc k st r))))
+
+ (defthm natp-vfaat_fn_induction_measure
+ (natp (vfaat_fn_induction_measure k st))
+ :rule-classes (:rewrite :type-prescription))
+
+ (defthm vfaat_fn_induction_measure_property
+ (implies
+ (and
+ (vfaat_fn_induction_terminates k st)
+ (not (vfaat_fn_test k)))
+ (< (vfaat_fn_induction_measure (vfaat_fn_branch k st) (vfaat_fn_comp k st)) (vfaat_fn_induction_measure k st)))
+ :rule-classes (:rewrite :linear))
+
+ (defthm vfaat_fn_induction_terminates_property
+ (and
+ (implies
+ (and
+ (vfaat_fn_hyps k st)
+ (vfaat_fn_test k))
+ (iff (vfaat_fn_induction_terminates k st) t))
+ (implies
+ (and
+ (vfaat_fn_hyps k st)
+ (not (vfaat_fn_test k)))
+ (iff (vfaat_fn_induction_terminates k st) (vfaat_fn_induction_terminates (vfaat_fn_branch k st) (vfaat_fn_comp k st))))))
+
+ (defthm vfaat_fn_pun_prop
+ (implies
+ (and
+ (vfaat_fn_hyps k st)
+ (vfaat_fn_type r))
+ (equal (vfaat_fn_pun r k st)
+ (if (vfaat_fn_test k) r ;; (vfaat_fn_base r)
+ (vfaat_fn_pun (vfaat_fn_inc k st r) (vfaat_fn_branch k st) (vfaat_fn_comp k st)))))
+ :rule-classes (:definition))
+
+ (defthm vfaat_fn_inc_of-inc
+ (implies
+ (and
+ (vfaat_fn_type r)
+ (vfaat_fn_hyps a b)
+ (vfaat_fn_hyps k st))
+ (equal (vfaat_fn_inc a b (vfaat_fn_inc k st r))
+ (vfaat_fn_inc k st (vfaat_fn_inc a b r)))))
+
+ (defthm vfaat_fn_property
+ (equal (vfaat_fn k st)
+ (if (vfaat_fn_induction_terminates k st)
+ (if (vfaat_fn_test k) (vfaat_fn_base)
+ (vfaat_fn_inc k st (vfaat_fn (vfaat_fn_branch k st) (vfaat_fn_comp k st))))
+ (vfaat_fn_default)))
+ :rule-classes (:definition))
+
+ )
+
+(defthm vfaat_fn_to_fn_pun
+ (implies
+ (and
+ (vfaat_fn_hyps k st)
+ (vfaat_fn_induction_terminates k st))
+ (equal (vfaat_fn k st)
+ (vfaat_fn_pun (vfaat_fn_base) k st)))
+ :rule-classes nil
+ :hints (("Goal" :use (:functional-instance
+ (:instance defxch_fn_to_fn_pun (x (list k st)))
+ (defxch_hyps (lambda (list) (vfaat_fn_hyps (car list) (cadr list))))
+ (defxch_type vfaat_fn_type)
+ (defxch_fn (lambda (list) (vfaat_fn (car list) (cadr list))))
+ (defxch_fn_pun (lambda (x list) (vfaat_fn_pun x (car list) (cadr list))))
+ (defxch_test (lambda (list) (vfaat_fn_test (car list))))
+ (defxch_base (lambda (r x) r))
+ (defxch_r0 vfaat_fn_base)
+ (defxch_default vfaat_fn_default)
+ (defxch_steps (lambda (list) (list (vfaat_fn_branch (car list) (cadr list))
+ (vfaat_fn_comp (car list) (cadr list)))))
+ (defxch_measure (lambda (list) (vfaat_fn_induction_measure (car list) (cadr list))))
+ (defxch_terminates (lambda (list) (vfaat_fn_induction_terminates (car list) (cadr list))))
+ (defxch_inc (lambda (list r) (vfaat_fn_inc (car list) (cadr list) r)))
+ ))))
+
+(defmacro vfaat_fnx_hyps (k st)
+ `(and (vfaat_fnx_hyp1 ,k)
+ (vfaat_fnx_hyp2 ,st)))
+
+(encapsulate
+ (
+ (vfaat_fnx_hyp1 (k) t)
+ (vfaat_fnx_hyp2 (st) t)
+ (vfaat_fnx_type (r) t)
+ (vfaat_fnx (k st) t)
+ (vfaat_fnx_pun (r k st) t)
+ (vfaat_fnx_induction_measure (k st) t)
+ (vfaat_fnx_induction_terminates (k st) t)
+ (vfaat_fnx_test (k) t)
+ (vfaat_fnx_r0 () t)
+ (vfaat_fnx_base (r k st) t)
+ (vfaat_fnx_default () t)
+ (vfaat_fnx_branch (k st) t)
+ (vfaat_fnx_comp (k st) t)
+ (vfaat_fnx_inc (k st r) t)
+ )
+
+ (local
+ (encapsulate ()
+
+ (defstub vfaat_fnx_test (k) nil)
+ (defstub vfaat_fnx_r0 () nil)
+ (defstub vfaat_fnx_default () nil)
+ (defstub vfaat_fnx_branch (k st) nil)
+ (defstub vfaat_fnx_comp (k st) nil)
+
+ (defun vfaat_fnx_base (r k st)
+ (declare (ignore k st))
+ r)
+
+ (defun vfaat_fnx_hyp1 (k)
+ (declare (ignore k))
+ t)
+
+ (defun vfaat_fnx_hyp2 (st)
+ (declare (ignore st))
+ t)
+
+ (defun vfaat_fnx_type (r)
+ (declare (ignore r))
+ t)
+
+ (defun vfaat_fnx_inc (k st r)
+ (declare (ignore k st)) r)
+
+ (defminterm vfaat_fnx_induction (k st)
+ (if (vfaat_fnx_test k) (list k st)
+ (vfaat_fnx_induction (vfaat_fnx_branch k st) (vfaat_fnx_comp k st))))
+
+ (defun vfaat_fnx (k st)
+ (declare (xargs :measure (vfaat_fnx_induction_measure k st)))
+ (if (vfaat_fnx_induction_terminates k st)
+ (if (vfaat_fnx_test k) (vfaat_fnx_base (vfaat_fnx_r0) k st)
+ (vfaat_fnx_inc k st (vfaat_fnx (vfaat_fnx_branch k st) (vfaat_fnx_comp k st))))
+ (vfaat_fnx_default)))
+
+ (defpun vfaat_fnx_pun (r k st)
+ (if (vfaat_fnx_test k) (vfaat_fnx_base r k st)
+ (vfaat_fnx_pun (vfaat_fnx_inc k st r) (vfaat_fnx_branch k st) (vfaat_fnx_comp k st))))
+
+ ))
+
+ (defthm vfaat_fnx_step_preserves_vfaat_fnx_hyps
+ (implies
+ (and
+ (vfaat_fnx_hyp1 k)
+ (vfaat_fnx_hyp2 st))
+ (and (vfaat_fnx_hyp1 (vfaat_fnx_branch k st))
+ (vfaat_fnx_hyp2 (vfaat_fnx_comp k st)))))
+
+ (defthm vfaat_fnx_type_vfaat_fnx_base
+ (implies
+ (and
+ (vfaat_fnx_hyp1 k)
+ (vfaat_fnx_hyp2 st)
+ (vfaat_fnx_type r))
+ (vfaat_fnx_type (vfaat_fnx_base r k st))))
+
+ (defthm vfaat_fnx_base_vfaat_fnx_inc_commute
+ (equal (vfaat_fnx_base (vfaat_fnx_inc k1 st1 r) k2 st2)
+ (vfaat_fnx_inc k1 st1 (vfaat_fnx_base r k2 st2))))
+
+ (defthm vfaat_fnx_type_vfaat_fnx_r0
+ (vfaat_fnx_type (vfaat_fnx_r0)))
+
+ (defthm vfaat_fnx_type_vfaat_fnx_default
+ (vfaat_fnx_type (vfaat_fnx_default)))
+
+ (defthm vfaat_fnx_type_vfaat_fnx_inc
+ (implies
+ (and
+ (vfaat_fnx_hyp1 k)
+ (vfaat_fnx_hyp2 st)
+ (vfaat_fnx_type r))
+ (vfaat_fnx_type (vfaat_fnx_inc k st r))))
+
+ (defthm natp-vfaat_fnx_induction_measure
+ (natp (vfaat_fnx_induction_measure k st))
+ :rule-classes (:rewrite :type-prescription))
+
+ (defthm vfaat_fnx_induction_measure_property
+ (implies
+ (and
+ (vfaat_fnx_induction_terminates k st)
+ (not (vfaat_fnx_test k)))
+ (< (vfaat_fnx_induction_measure (vfaat_fnx_branch k st) (vfaat_fnx_comp k st)) (vfaat_fnx_induction_measure k st)))
+ :rule-classes (:rewrite :linear))
+
+ (defthm vfaat_fnx_induction_terminates_property
+ (and
+ (implies
+ (and
+ (vfaat_fnx_hyp1 k)
+ (vfaat_fnx_hyp2 st)
+ (vfaat_fnx_test k))
+ (iff (vfaat_fnx_induction_terminates k st) t))
+ (implies
+ (and
+ (vfaat_fnx_hyp1 k)
+ (vfaat_fnx_hyp2 st)
+ (not (vfaat_fnx_test k)))
+ (iff (vfaat_fnx_induction_terminates k st) (vfaat_fnx_induction_terminates (vfaat_fnx_branch k st) (vfaat_fnx_comp k st))))))
+
+ (defthm vfaat_fnx_pun_prop
+ (implies
+ (and
+ (vfaat_fnx_hyp1 k)
+ (vfaat_fnx_hyp2 st)
+ (vfaat_fnx_type r))
+ (equal (vfaat_fnx_pun r k st)
+ (if (vfaat_fnx_test k) (vfaat_fnx_base r k st)
+ (vfaat_fnx_pun (vfaat_fnx_inc k st r) (vfaat_fnx_branch k st) (vfaat_fnx_comp k st)))))
+ :rule-classes (:definition))
+
+ (defthm vfaat_fnx_inc_of-inc
+ (implies
+ (and
+ (vfaat_fnx_type r)
+ (vfaat_fnx_hyps a b)
+ (vfaat_fnx_hyps k st))
+ (equal (vfaat_fnx_inc a b (vfaat_fnx_inc k st r))
+ (vfaat_fnx_inc k st (vfaat_fnx_inc a b r)))))
+
+ (defthm vfaat_fnx_property
+ (equal (vfaat_fnx k st)
+ (if (vfaat_fnx_induction_terminates k st)
+ (if (vfaat_fnx_test k) (vfaat_fnx_base (vfaat_fnx_r0) k st)
+ (vfaat_fnx_inc k st (vfaat_fnx (vfaat_fnx_branch k st) (vfaat_fnx_comp k st))))
+ (vfaat_fnx_default)))
+ :rule-classes (:definition))
+
+ )
+
+(defthm vfaat_fnx_to_fn_pun
+ (implies
+ (and
+ (vfaat_fnx_hyps k st)
+ (vfaat_fnx_induction_terminates k st))
+ (equal (vfaat_fnx k st)
+ (vfaat_fnx_pun (vfaat_fnx_r0) k st)))
+ :rule-classes nil
+ :hints (("Goal" :use (:functional-instance
+ (:instance defxch_fn_to_fn_pun (x (list k st)))
+ (defxch_hyps (lambda (list) (vfaat_fnx_hyps (car list) (cadr list))))
+ (defxch_type vfaat_fnx_type)
+ (defxch_fn (lambda (list) (vfaat_fnx (car list) (cadr list))))
+ (defxch_fn_pun (lambda (x list) (vfaat_fnx_pun x (car list) (cadr list))))
+ (defxch_test (lambda (list) (vfaat_fnx_test (car list))))
+ (defxch_base (lambda (r list) (vfaat_fnx_base r (car list) (cadr list))))
+ (defxch_r0 vfaat_fnx_r0)
+ (defxch_default vfaat_fnx_default)
+ (defxch_steps (lambda (list) (list (vfaat_fnx_branch (car list) (cadr list))
+ (vfaat_fnx_comp (car list) (cadr list)))))
+ (defxch_measure (lambda (list) (vfaat_fnx_induction_measure (car list) (cadr list))))
+ (defxch_terminates (lambda (list) (vfaat_fnx_induction_terminates (car list) (cadr list))))
+ (defxch_inc (lambda (list r) (vfaat_fnx_inc (car list) (cadr list) r)))
+ ))))
+
+#|
+ACL2:
+
+(defthm <NAME>_to_<NAME>_pun
+ (implies
+ (<TERMINATES> k st)
+ (equal (<NAME> k st)
+ (<NAME>_pun <BASE> k st)))
+ :hints (("Goal" :use (:functional-instance
+ vfaat_fn_to_fn_pun
+ (vfaat_fn_hyp1 kstate-p)
+ (vfaat_fn_hyp2 st-p)
+ (vfaat_fn_type <TYPE3>)
+ (vfaat_fn <NAME>)
+ (vfaat_fn_pun <NAME>_pun)
+ (vfaat_fn_induction_measure <MEASURE>)
+ (vfaat_fn_induction_terminates <TERMINATES>)
+ (vfaat_fn_test <EXIT>)
+ (vfaat_fn_base (lambda () <BASE>))
+ (vfaat_fn_default (lambda () <DEFAULT>))
+ (vfaat_fn_branch <BRANCH>)
+ (vfaat_fn_comp <COMP>)
+ (vfaat_fn_inc <NAME>_inc)
+ ))))
+
+PVS:
+
+ IMPORTING defxch[
+ <TYPE1>, <TYPE2>, <TYPE3>,
+ <NAME>,
+ <NAME>_pun,
+ <NAME>_inc,
+ <EXIT>,
+ <BASE>,
+ <DEFAULT>,
+ <BRANCH>,
+ <COMP>,
+ <MEASURE>,
+ <TERMINATES>
+ ] as <NAME>_xch
+
+ <NAME>_to_<NAME>_pun: LEMMA
+ FORALL (k: <TYPE1>, st:<TYPE2>):
+ <TERMINATES> =>
+ <NAME>(k,st) =
+ <NAME>_pun(<BASE>,k,st)
+%|- <NAME>_to_<NAME>_pun: PROOF
+%|- (auto-rewrite "<NAME>_xch.fn_to_fn_pun") (skosimp) (assert)
+%|- QED
+
+
+|#