summaryrefslogtreecommitdiff
path: root/books/workshops/2004/sumners-ray/support
diff options
context:
space:
mode:
Diffstat (limited to 'books/workshops/2004/sumners-ray/support')
-rw-r--r--books/workshops/2004/sumners-ray/support/.gitignore5
-rw-r--r--books/workshops/2004/sumners-ray/support/Makefile49
-rw-r--r--books/workshops/2004/sumners-ray/support/basis.lisp295
-rw-r--r--books/workshops/2004/sumners-ray/support/cert_pl_exclude2
-rw-r--r--books/workshops/2004/sumners-ray/support/crit.lisp125
-rwxr-xr-xbooks/workshops/2004/sumners-ray/support/invp.lsp1660
-rw-r--r--books/workshops/2004/sumners-ray/support/mesi.lisp227
-rw-r--r--books/workshops/2004/sumners-ray/support/records.lisp644
-rw-r--r--books/workshops/2004/sumners-ray/support/sets.lisp1220
-rw-r--r--books/workshops/2004/sumners-ray/support/total-order.lisp30
10 files changed, 4257 insertions, 0 deletions
diff --git a/books/workshops/2004/sumners-ray/support/.gitignore b/books/workshops/2004/sumners-ray/support/.gitignore
new file mode 100644
index 0000000..844dd58
--- /dev/null
+++ b/books/workshops/2004/sumners-ray/support/.gitignore
@@ -0,0 +1,5 @@
+*.rpt
+run.date
+run.err
+run.log
+success.txt
diff --git a/books/workshops/2004/sumners-ray/support/Makefile b/books/workshops/2004/sumners-ray/support/Makefile
new file mode 100644
index 0000000..4c174c4
--- /dev/null
+++ b/books/workshops/2004/sumners-ray/support/Makefile
@@ -0,0 +1,49 @@
+# Instructions:
+
+# Before starting, see "Dependencies" below.
+
+# In the shell, execute
+# make
+# to certify all books.
+# To clean up (removing files *.cert, *.o, *.fasl, etc.), in the shell execute
+# make clean
+
+top1:
+ @echo "Using ACL2=$(ACL2)"
+ @$(MAKE) top
+
+top: success.txt
+
+success.txt: mesi.cert crit.cert invp.lsp
+ @echo "Making `pwd`/success.txt on `date`"
+ @rm -f success.txt workxxx
+ @date > run.date
+ @echo '(value :q)' > workxxx
+ @echo '(acl2::lp)' >> workxxx
+ @echo '(acl2::ld "invp.lsp")' >> workxxx
+ @echo '(value :q)' >> workxxx
+ @echo '(acl2::good-bye)' >> workxxx
+ @$(ACL2) < workxxx > run.log 2> run.err
+ @rm -f workxxx TMP*
+ @if [ ! -f success.txt ]; then \
+ echo "**CERTIFICATION FAILED**"; \
+ exit 1 ; \
+ else \
+ ls -al success.txt ; \
+ fi
+
+include ../../../../Makefile-generic
+
+# Need to omit invp from BOOKS because targets like all-fas would try to
+# include invp as a book:
+BOOKS = basis crit mesi records sets total-order
+
+
+clean: clean-more
+
+clean-more:
+ rm -f *.rpt
+ rm -f success.txt
+ rm -f run.date run.log run.err
+
+-include Makefile-deps
diff --git a/books/workshops/2004/sumners-ray/support/basis.lisp b/books/workshops/2004/sumners-ray/support/basis.lisp
new file mode 100644
index 0000000..b9ccacf
--- /dev/null
+++ b/books/workshops/2004/sumners-ray/support/basis.lisp
@@ -0,0 +1,295 @@
+(in-package "ACL2")
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;;;;;;;;;; definitions and rules for time operators ;;;;;;;;;;;;;;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+;; Even though the invariant prover proves invariants by an induction over time
+;; (where time is understood to be natural number), we prefer to use our own
+;; operators t+, t-, t0, and tzp to define the behavior of the time
+;; parameter. This avoids issues which may arise with the aliasing of ACL2
+;; arithmetic and allows us to define time in a manner which avoids the need to
+;; introduce natp hypothesis.
+
+(encapsulate
+ (((t- *) => *)
+ ((t0) => *)
+ ((tzp *) => *)
+ ((tmsr *) => *))
+
+(local (defun tzp (n) (or (atom n) (car n))))
+(local (defun t- (n) (if (tzp n) n (cdr n))))
+(local (defun t0 () nil))
+(local (defun tmsr (n) (if (tzp n) 0 (1+ (tmsr (cdr n))))))
+
+(defthm tzp-t0redux (equal (tzp (t0)) t))
+(defthm tmsr-ordinal (o-p (tmsr n)))
+(defthm tzp-tmsr-o< (implies (not (tzp n)) (o< (tmsr (t- n)) (tmsr n))))
+
+;; The following definition and theorems are not exported because we do not
+;; want any user functions which are defined in terms of t+, so it is built in
+;; directly in the rewriter. We prove these theorems here to demonstrate that
+;; the built-in rules in the rewriter are valid.
+
+(local (defun t+ (n) (cons nil n)))
+
+;; The following theorem is included to demonstrate that every object in the
+;; ACL2 universe is either tzp or equal to (t+ n) for some n. This also means
+;; that if a theorem is proven for (t0) and (t+ n) for every n, then it is true
+;; for all n since the only property that we export about (t0) is (tzp (t0)).
+
+(local (defthm time-totality (implies (not (tzp n)) (equal (t+ (t- n)) n))))
+(local (defthm tzp-t+redux (equal (tzp (t+ n)) nil)))
+(local (defthm t--t+-redux (equal (t- (t+ n)) n))))
+
+
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;;;;;;;;;;;;;;;;; auxiliary helper functions ;;;;;;;;;;;;;;;;;;;;;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+(defmacro char-in-range (c x y)
+ `(let ((a (char-code ,c)))
+ (and (>= a (char-code ,x))
+ (<= a (char-code ,y)))))
+
+(defun str-to-number1 (str i n acc)
+ (declare (xargs :measure (nfix n)))
+ (cond ((zp n) acc)
+ ((char-in-range (char str i) #\0 #\9)
+ (str-to-number1 str (1+ i) (1- n)
+ (+ (* acc 10)
+ (- (char-code (char str i))
+ (char-code #\0)))))
+ (t (er hard 'str-to-number
+ "ill-formed token encountered: ~x0"
+ str))))
+
+(defun str-to-number (str)
+ (str-to-number1 str 0 (length str) 0))
+
+(defun digit-to-str (dig)
+ (string (code-char (+ dig (char-code #\0)))))
+
+(defun number-to-str1 (num d)
+ (declare (xargs :measure (nfix d)))
+ (cond ((zp d)
+ (er hard 'number-2-str
+ "attempt to print too large natural: ~x0" num))
+ ((not (and (integerp num) (>= num 0)))
+ (er hard 'number-2-str
+ "attempt to print non-natural: ~x0" num))
+ ((< num 10) (digit-to-str num))
+ (t (string-append (number-to-str1 (floor num 10) (1- d))
+ (digit-to-str (mod num 10))))))
+
+(defun number-to-str (num)
+ (number-to-str1 num 1000000))
+
+(defun pos-of-char1 (ch str i n)
+ (declare (xargs :measure (nfix n)))
+ (cond ((zp n) nil)
+ ((>= i (length str)) nil)
+ ((eql (char str i) ch) i)
+
+ (t (pos-of-char1 ch str (1+ i) (1- n)))))
+
+(defun pos-of-char (ch str)
+ (pos-of-char1 ch str 0 (length str)))
+
+(defun to-string (obj)
+ (cond ((stringp obj) obj)
+ ((characterp obj) (string obj))
+ ((symbolp obj) (string-downcase (symbol-name obj)))
+ ((natp obj) (number-to-str obj))
+ (t (er hard 'to-string
+ "don't know how to convert to string: ~x0" obj))))
+
+(defun snap-objs (objs)
+ (if (endp objs) ""
+ (string-append (to-string (first objs))
+ (snap-objs (rest objs)))))
+
+(defmacro snap (&rest objs)
+ `(snap-objs (list ,@objs)))
+
+(defmacro snap-sym (&rest objs)
+ `(intern (string-upcase (snap ,@objs)) "ACL2"))
+
+(defmacro snap-key (&rest objs)
+ `(intern (string-upcase (snap ,@objs)) "KEYWORD"))
+
+
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;;;;;;;;;; macro for generating if-lifting rules ;;;;;;;;;;;;;;;;;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+(defun replace-arg (call arg term)
+ (cond ((endp call)
+ (er hard 'replace-arg "did not find arg"))
+ ((eq arg (first call))
+ (cons term (rest call)))
+ (t
+ (cons (first call)
+ (replace-arg (rest call) arg term)))))
+
+(defun if-lift-call (arg call)
+ `(defthm ,(snap-sym 'if-lift- (first call) '- arg)
+ (equal ,(replace-arg call arg '(if tst tbr fbr))
+ (if tst ,(replace-arg call arg 'tbr) ,(replace-arg call arg 'fbr)))))
+
+(defun if-lifts-call (args call)
+ (if (endp args) ()
+ (cons (if-lift-call (first args) call)
+ (if-lifts-call (rest args) call))))
+
+(defun if-lifts-calls (calls)
+ (if (endp calls) ()
+ (append (if-lifts-call (rest (first calls)) (first calls))
+ (if-lifts-calls (rest calls)))))
+
+(defmacro if-lift-rules (&rest calls)
+ (cons 'progn (if-lifts-calls calls)))
+
+
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;;;;;;;;;; macro for generating abstraction rules ;;;;;;;;;;;;;;;;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+(defun abs-termp (x)
+ (and (consp x)
+ (not (quotep x))
+ (pseudo-termp x)))
+
+(defun abs-term-listp (x)
+ (or (null x)
+ (and (consp x)
+ (abs-termp (first x))
+ (abs-term-listp (rest x)))))
+
+(defun make-abs-thm (trm n)
+ `(defthm ,(snap-sym 'abstract- (first trm) '- n)
+ (equal ,trm (hide ,trm))
+ :hints (("Goal" :expand (hide ,trm)))))
+
+(defun make-abs-thms (trms n)
+ (if (endp trms) ()
+ (cons (make-abs-thm (first trms) n)
+ (make-abs-thms (rest trms) (1+ n)))))
+
+(defmacro abstract-terms (&rest trms)
+ (declare (xargs :guard (abs-term-listp trms)))
+ `(progn ,@(make-abs-thms trms 0)))
+
+
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;;;;;;;;;; macro for generating finite case-splits ;;;;;;;;;;;;;;;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+(defun finite-case-term (tgt cases)
+ (if (endp cases) tgt
+ (let ((c (first cases)))
+ `(if (equal ,tgt ,c) ,c ,(finite-case-term tgt (rest cases))))))
+
+(defmacro finite-cases (name class target cases)
+ (declare (xargs :guard (and (symbolp name)
+ (member class '(:state :input))
+ (consp target)
+ (symbol-listp target)
+ (true-listp cases))))
+ (let ((op! (snap-sym (first target) '!)))
+ `(encapsulate
+ ()
+ (defun ,op! ,(rest target) ,target)
+ (defthm ,(snap-sym name '-finite-cases)
+ (implies (syntaxp (equal n (quote ,(if (eq class :input) '(t+ n) 'n))))
+ (equal ,target ,(finite-case-term (cons op! (rest target)) cases))))
+ ,@(and (eq class :state)
+ `((defthm ,(snap-sym name '-unwrap-cases)
+ (implies (syntaxp (or (equal n '(t0)) (equal n '(t+ n))))
+ (equal ,(cons op! (rest target)) ,target)))))
+ (in-theory (disable ,op!)))))
+
+
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;;;;;;;;;;;;;;;;; basic rules for equal and if ;;;;;;;;;;;;;;;;;;;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+;; We use if* here to avoid ACL2 restriction on if lhs rewrite rules. The
+;; invariant prover will read any lhs if* rules as if rules and so the user is
+;; encouraged to make use of this bypass around ACL2 when they wish to have
+;; rules which have 'if as the outermost lhs operator.
+
+(defthm if-if-lift-rule
+ (equal (if* (if x y z) a b)
+ (if x (if y a b) (if z a b))))
+
+(defthm equal-if-lift-lhs
+ (equal (equal (if x y z) a)
+ (if x (equal y a) (equal z a))))
+
+(defthm equal-if-lift-rhs
+ (equal (equal a (if x y z))
+ (if x (equal a y) (equal a z))))
+
+(defthm equal-orient-rule
+ (implies (syntaxp (term-order x y))
+ (equal (equal x y) (equal y x)))
+ ;; I have to add the following to keep ACL2 from adding
+ ;; a loop stopper by default :(
+ :rule-classes ((:rewrite :loop-stopper ())))
+
+
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;;;;;;;;;;;;;;;;;;;;;; define-system macro ;;;;;;;;;;;;;;;;;;;;;;;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+(defun reg-declp (reg)
+ (and (true-listp reg)
+ (equal (length reg) 4)
+ (symbolp (first reg))
+ (symbol-listp (second reg))))
+
+(defun reg-declsp (regs)
+ (or (null regs)
+ (and (consp regs)
+ (reg-declp (first regs))
+ (reg-declsp (rest regs)))))
+
+(defun reg-fn (reg)
+ (list `(defun ,(first reg) ,(second reg)
+ (declare (xargs :measure (tmsr n)))
+ (if (tzp n) ,(third reg) (let ((n- (t- n))) ,(fourth reg))))))
+
+(defun reg-thm (reg)
+ (list `(if-lift-rules (,(first reg) ,@(second reg)))
+ `(defthm ,(snap-sym (first reg) '-tzp)
+ (implies (tzp n)
+ (equal (,(first reg) ,@(second reg))
+ ,(third reg))))
+ `(defthm ,(snap-sym (first reg) '-t+)
+ (implies (not (tzp n))
+ (equal (,(first reg) ,@(second reg))
+ (let ((n- (t- n))) ,(fourth reg)))))))
+
+(defun reg-fns (regs)
+ (if (endp regs) ()
+ (append (reg-fn (first regs))
+ (reg-fns (rest regs)))))
+
+(defun reg-thms (regs)
+ (if (endp regs) ()
+ (append (reg-thm (first regs))
+ (reg-thms (rest regs)))))
+
+(defmacro define-system (name &rest regs)
+ (declare (xargs :guard (and (symbolp name) (reg-declsp regs)))
+ (ignore name))
+ (list* 'progn
+ (cons 'mutual-recursion (reg-fns regs))
+ (reg-thms regs)))
diff --git a/books/workshops/2004/sumners-ray/support/cert_pl_exclude b/books/workshops/2004/sumners-ray/support/cert_pl_exclude
new file mode 100644
index 0000000..833501d
--- /dev/null
+++ b/books/workshops/2004/sumners-ray/support/cert_pl_exclude
@@ -0,0 +1,2 @@
+This directory has a custom Makefile, so it is excluded from
+certification based on cert.pl.
diff --git a/books/workshops/2004/sumners-ray/support/crit.lisp b/books/workshops/2004/sumners-ray/support/crit.lisp
new file mode 100644
index 0000000..03a1864
--- /dev/null
+++ b/books/workshops/2004/sumners-ray/support/crit.lisp
@@ -0,0 +1,125 @@
+(in-package "ACL2")
+(include-book "basis")
+
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;;;;;;; definitions for example critical section system ;;;;;;;;;;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+(encapsulate (((i *) => *)) (local (defun i (n) n)))
+
+(define-system critical
+ (in-critical (n) nil
+ (if (in-critical n-)
+ (/= (i n) (critical-id n-))
+ (= (status (i n) n-) :try)))
+
+ (critical-id (n) nil
+ (if (and (not (in-critical n-))
+ (= (status (i n) n-) :try))
+ (i n)
+ (critical-id n-)))
+
+ (status (p n) :idle
+ (if (/= (i n) p) (status p n-)
+ (case (status p n-)
+ (:try (if (in-critical n-) :try :critical))
+ (:critical :idle)
+ (t :try)))))
+
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;;;;;;; definitions for example critical section system ;;;;;;;;;;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+(encapsulate (((a) => *) ((b) => *))
+ (local (defun a () 1)) (local (defun b () 2))
+ (defthm a-/=-b (not (equal (a) (b))))
+ (defthm a-non-nil (not (equal (a) nil)))
+ (defthm b-non-nil (not (equal (b) nil))))
+
+; Added after v7-2 by Matt K. since the define-system just below introduces a
+; non-recursive definition with a measure.
+(set-bogus-measure-ok t)
+
+(define-system critical-spec
+ (ok (n) t
+ (not (and (= (status (a) n-) :critical)
+ (= (status (b) n-) :critical)))))
+
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;;;;;;;; proof of invariant ok via inductive invariant ;;;;;;;;;;;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+; we have to use a different versions of the above functions which are
+; defined on natural time rather than the abstracted t+,t-,tzp time
+; defined in basis.lisp.
+
+(mutual-recursion
+ (defun in-critical* (n)
+ (declare (xargs :measure (nfix n)))
+ (if (zp n) nil
+ (let ((n- (1- n)))
+ (if (in-critical* n-)
+ (/= (i n) (critical-id* n-))
+ (= (status* (i n) n-) :try)))))
+
+ (defun critical-id* (n)
+ (declare (xargs :measure (nfix n)))
+ (if (zp n) nil
+ (let ((n- (1- n)))
+ (if (and (not (in-critical* n-))
+ (= (status* (i n) n-) :try))
+ (i n)
+ (critical-id* n-)))))
+
+ (defun status* (p n)
+ (declare (xargs :measure (nfix n)))
+ (if (zp n) :idle
+ (let ((n- (1- n)))
+ (if (/= (i n) p) (status* p n-)
+ (case (status* p n-)
+ (:try (if (in-critical* n-) :try :critical))
+ (:critical :idle)
+ (t :try))))))
+
+ (defun ok* (n)
+ (declare (xargs :measure (nfix n)))
+ (if (zp n) t
+ (let ((n- (1- n)))
+ (not (and (= (status* (a) n-) :critical)
+ (= (status* (b) n-) :critical)))))))
+
+(defun ii-ok-for1 (n i)
+ (iff (= (status* i n) :critical)
+ (and (in-critical* n) (= (critical-id* n) i))))
+
+(defun ii-ok (n)
+ (and (ii-ok-for1 n (a)) (ii-ok-for1 n (b))))
+
+(defthm bogus-linear
+ (implies (integerp n)
+ (equal (+ (- x) x n) n)))
+
+(defthm ok-is-invariant
+ (and (ii-ok 0) (ok* 0)
+ (implies (and (natp n) (ii-ok n))
+ (and (ok* (1+ n)) (ii-ok (1+ n)))))
+ :hints (("Goal" :in-theory (disable (ii-ok) (ok*)))))
+
+
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;;;;;;;; a few auxiliary rules for the invariant prover ;;;;;;;;;;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+; we will need if-lifting for equal rules in the invariant prover:
+(if-lift-rules (equal x y))
+
+; we also need to force a case-split on (i n) and (critical-id n)
+; the need for a case-split on critical-id is unfortunate and is
+; due to some weakness in the prover which needs to be resolved.
+(finite-cases process-id :input (i n) ((a) (b)))
+(finite-cases critical-id :state (critical-id n) ((a) (b)))
+
diff --git a/books/workshops/2004/sumners-ray/support/invp.lsp b/books/workshops/2004/sumners-ray/support/invp.lsp
new file mode 100755
index 0000000..0254447
--- /dev/null
+++ b/books/workshops/2004/sumners-ray/support/invp.lsp
@@ -0,0 +1,1660 @@
+#| (ld "invp.lisp") |#
+
+(in-package "ACL2")
+
+#|
+
+ invp.lisp
+ ~~~~~~~~~
+
+CODE SECTIONS
+-------------
+
+1. include the basis book which defines numerous operators
+2. definition and initialization of ic$ stobj
+3. inside-out conditional term rewriter
+4. extended rewriting and propagating rep-step
+5. invariant checker implementation
+6. top-level algorithm and interface
+7. some simple test examples
+
+
+TODO LIST
+---------
+
+1. Add translation of model to Verilog and interface to VIS model checker.
+
+2. Add deep if-lifting to rewrite-step
+
+3. Add some tagging of terms to declare the term to be in normal-form to
+ avoid rewriting terms which are in normal-form.
+
+
+NOTES/ISSUES
+------------
+
+1. Why do we need to set the translate-flg in the calls of simplify-term??
+
+2. Need to write-up arguments for the correctness of all of the reductions
+ supported in this tool.
+
+|#
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+#| <SECTION> 1. include the basis book which defines numerous operators |#
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+(include-book "basis")
+
+(defun zip-fms (chars lst)
+ (cond ((endp lst) ())
+ ((endp chars)
+ (er hard 'zip-fms "too many args to detail!"))
+ (t (acons (car chars) (car lst)
+ (zip-fms (cdr chars) (cdr lst))))))
+
+(defconst *fms-chars*
+ '(#\0 #\1 #\2 #\3 #\4 #\5 #\6 #\7 #\8 #\9))
+
+(program)
+
+(defun detail-fn (fmt-str lst chan state)
+ (declare (xargs :stobjs state))
+ (if (not chan) state
+ (fms fmt-str (zip-fms *fms-chars* lst) chan state nil)))
+
+(defmacro detail (&rest r)
+ `(let ((state (detail-fn ,(first r)
+ ,(cons 'list (rest (butlast r 1)))
+ (detail-channel ic$) state)))
+ ,(car (last r))))
+
+(defmacro report (&rest r)
+ `(prog2$ (cw ,@(butlast r 1))
+ (detail ,(string-append "REPORT:" (first r))
+ ,@(rest r))))
+
+(defmacro bozo (&rest r)
+ `(prog2$ (cw ,@(butlast r 1))
+ ,(car (last r))))
+
+(defmacro seq (&rest bind)
+ (cond ((endp bind)
+ (er hard 'seq
+ "no body/result expression in seq form"))
+ ((endp (cdr bind))
+ (car bind))
+ ((atom (caar bind))
+ `(let ((,(caar bind) ,(cadar bind)))
+ (seq ,@(cdr bind))))
+ (t
+ `(mv-let ,(caar bind) ,(cadar bind)
+ (seq ,@(cdr bind))))))
+
+(defmacro die (&rest r)
+ `(prog2$ (er hard ,@(butlast r 1))
+ ,(car (last r))))
+
+(logic)
+
+(defabbrev bnil () 0)
+(defabbrev bnth (i x) (logbitp i x))
+
+(defun blist-length (x)
+ (cond ((atom x)
+ (er hard 'blist-length "ill-formed"))
+ ((eq (first x) 'bnil) 0)
+ ((eq (first x) 'bcons)
+ (1+ (blist-length (third x))))
+ (t (er hard 'blist-length "ill-formed"))))
+
+(defmacro bcons (b x)
+ (let ((size (1+ (blist-length x))))
+ `(the (unsigned-byte ,size)
+ (let ((b ,b)
+ (x (the (unsigned-byte ,size) (* ,x 2))))
+ (declare (type (unsigned-byte ,size) x))
+ (if b (the (unsigned-byte ,size) (1+ x)) x)))))
+
+(local ; ACL2 primitive
+ (defmacro 1+f (x)
+ `(the-fixnum (1+ (the-fixnum ,x)))))
+
+(local ; ACL2 primitive
+ (defmacro 1-f (x)
+ `(the-fixnum (1- (the-fixnum ,x)))))
+
+(defmacro modf (x y)
+ `(the-fixnum (mod (the-fixnum ,x) (the-fixnum ,y))))
+
+(defmacro fzp (x)
+ `(let ((x ,x))
+ (declare (type (signed-byte 29) x))
+ (or (not (integerp x))
+ (<= x 0))))
+
+(in-theory (disable ash logbitp))
+
+;; We need to get some properties of the functions we deal with from the
+;; current ACL2 world. We define the macro fn-prop below for that purpose.
+(defabbrev fn-prop (fn prop)
+ (getprop fn prop nil 'current-acl2-world (w state)))
+
+;; and more precisely, we will have the unnormalized-body and the formals.
+(defabbrev get-formals (fn)
+ (fn-prop fn 'formals))
+
+(defabbrev get-body (fn)
+ (fn-prop fn 'unnormalized-body))
+
+(defabbrev get-normal-body (fn)
+ (fn-prop fn 'body))
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+#| <SECTION> 2. definition and initialization of ic$ stobj |#
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+(program)
+
+;; we now define a stobj which we use to hold much of the state which
+;; we use as a holding area for various parameters and variables which
+;; are updated throughout the invariant proof
+(defstobj ic$
+ (reduce-contexts :type T)
+ (jump-bound :type T)
+ (check-bound :type T)
+ (refine-bound :type T)
+ (inputs-bound :type T)
+ (fast-search :type T)
+ (detail-channel :type T)
+ (always-check :type T)
+ (disable-exec :type T)
+ (num-rep-bits :type T)
+ (inv-check-result :type T)
+ ;; the following are merely in the stobj instead of being parameters to dfs
+ (search-bound :type (signed-byte 29)
+ :initially 0)
+ (num-states :type (signed-byte 29)
+ :initially 0)
+ (num-inputs :type (signed-byte 29)
+ :initially 0)
+ (input-vec :type (array T (0))
+ :resizable T)
+ (inv-bit :type T)
+ (st-hashtbl :type (array T (0))
+ :resizable T))
+
+(defun is-prime-number (x y)
+ (cond ((or (zp x) (= x 1)) t)
+ ((eql (mod y x) 0) nil)
+ (t (is-prime-number (1- x) y))))
+
+(defun prev-prime-number (x)
+ (cond ((zp x) 1)
+ ((is-prime-number x x) x)
+ (t (prev-prime-number (1- x)))))
+
+(defun clear-ic$-for-inv-check (ic$)
+ (declare (xargs :stobjs ic$))
+ (seq
+ (ic$ (resize-st-hashtbl 0 ic$)) ;; this will clear the st-hashtbl
+ (ic$ (resize-st-hashtbl (prev-prime-number (check-bound ic$)) ic$))
+ (ic$ (update-inv-check-result nil ic$))
+ ic$))
+
+;; we initialize the inv-checker stobj ic$ for the book-keeping we need.
+(defun initialize-ic$ (jump-bound
+ check-bound
+ refine-bound
+ inputs-bound
+ fast-search
+ detail-file
+ always-check
+ disable-exec
+ reduce-contexts
+ ic$
+ state)
+ (declare (xargs :stobjs (ic$ state)))
+ (seq
+ (ic$ (update-jump-bound jump-bound ic$))
+ (ic$ (update-check-bound check-bound ic$))
+ (ic$ (update-refine-bound refine-bound ic$))
+ (ic$ (update-inputs-bound inputs-bound ic$))
+ (ic$ (update-fast-search fast-search ic$))
+ (ic$ (update-always-check always-check ic$))
+ (ic$ (update-disable-exec disable-exec ic$))
+ (ic$ (update-reduce-contexts reduce-contexts ic$))
+ (ic$ (clear-ic$-for-inv-check ic$))
+ ((channel state)
+ (if detail-file
+ (open-output-channel detail-file :character state)
+ (mv nil state)))
+ (ic$ (update-detail-channel channel ic$))
+ (mv ic$ state)))
+
+(defun cleanup-ic$ (ic$ state)
+ (declare (xargs :stobjs (ic$ state)))
+ (seq
+ (state (close-output-channel (detail-channel ic$) state))
+ (mv ic$ state)))
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+#| <SECTION> 3. iterative inside-out conditional term rewriter |#
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+(program)
+
+(defabbrev equiv-ops (a b)
+ (let ((op-a (if (atom a) a (car a)))
+ (op-b (if (atom b) b (car b))))
+ (and (not (eq op-a 'lambda))
+ (eq op-a op-b))))
+
+(defabbrev hidep (x)
+ (and (consp x) (eq (first x) 'hide)))
+
+(defun equiv-terms1 (x y is-lst)
+ (cond ((and is-lst (endp x)) (endp y))
+ (is-lst (and (equiv-terms1 (first x) (first y) nil)
+ (equiv-terms1 (rest x) (rest y) t)))
+ ((hidep x) (equiv-terms1 (second x) y nil))
+ ((hidep y) (equiv-terms1 x (second y) nil))
+ ((atom x) (eq x y))
+ ((atom y) nil)
+ (t (and (equiv-ops (first x) (first y))
+ (equiv-terms1 (rest x) (rest y) t)))))
+
+(defabbrev equiv-terms (x y) (equiv-terms1 x y nil))
+
+(defun bind-args* (vars args rslt)
+ (if (endp vars) rslt
+ (bind-args* (rest vars) (rest args)
+ (cons (cons (first vars)
+ (first args))
+ rslt))))
+
+(defabbrev bind-args (vars args)
+ (bind-args* vars args ()))
+
+(defun subst-term* (trm alst is-lst in-synp ctx)
+ (cond
+ ((and is-lst (endp trm)) ())
+ (is-lst (cons (subst-term* (first trm) alst nil in-synp ctx)
+ (subst-term* (rest trm) alst t in-synp ctx)))
+ ((atom trm)
+ (let* ((mtch (assoc-eq trm alst))
+ (val (if mtch (cdr mtch) trm)))
+ (if (not in-synp) val
+ (list 'quote (if (and (not mtch) (eq trm 'ctx)) ctx val)))))
+ (t
+ (let ((op (first trm)))
+ (cond
+ ((eq op 'quote) trm)
+ ((eq op 'synp) (subst-term* (second (fourth trm)) alst nil t ctx))
+ (t (cons (if (atom op) (list op) op)
+ (subst-term* (rest trm) alst t in-synp ctx))))))))
+
+(defabbrev subst-term-ctx (trm alst ctx)
+ (subst-term* trm alst nil nil ctx))
+
+(defabbrev subst-term (trm alst)
+ (subst-term* trm alst nil nil nil))
+
+(defabbrev st-phase (st) (car st))
+(defabbrev st-wrld (st) (cadr st))
+(defabbrev st-ens (st) (caddr st))
+(defabbrev st-rew-ctx (st) (cadddr st))
+(defabbrev st-depth (st) (cddddr st))
+
+(defun make-init-st (wrld ens rew-ctx depth)
+ (list* nil wrld ens rew-ctx depth))
+
+(defabbrev in-hyps (st)
+ (if (st-phase st) st (cons t (cdr st))))
+
+(defabbrev match-ctx-elem (trm ctx iff)
+ (cond
+ ((and iff (equiv-terms trm ctx)) ''t)
+ ((let ((op (first ctx)))
+ (or (eq op 'equal)
+ (and (eq op 'iff) iff)))
+ (and (equiv-terms trm (second ctx))
+ (third ctx)))))
+
+(defun match-in-ctx* (trm ctx iff)
+ (and (not (endp ctx))
+ (or (match-ctx-elem trm (first ctx) iff)
+ (match-in-ctx* trm (rest ctx) iff))))
+
+(defun match-in-ctx (trm ctx iff)
+ (if (quotep trm) nil (match-in-ctx* trm ctx iff)))
+
+(defmacro gprop (name prop)
+ `(getprop ,name ,prop nil 'current-acl2-world wrld))
+
+(defun quoted-args (args)
+ (or (endp args)
+ (and (quotep (first args))
+ (quoted-args (rest args)))))
+
+(defun fncall-args (args)
+ (if (endp args) ()
+ (cons (second (first args))
+ (fncall-args (rest args)))))
+
+(defun merge-alsts (new alst)
+ (if (endp new) alst
+ (merge-alsts (cdr new)
+ (let ((mtch (assoc-eq (caar new) alst)))
+ (if mtch alst (cons (car new) alst))))))
+
+(defun find-nume (pairs rune)
+ (cond ((endp pairs) nil)
+ ((equal rune (cdar pairs))
+ (caar pairs))
+ (t (find-nume (cdr pairs) rune))))
+
+(defun rewrt-built-in (op args)
+ (cond
+ ((eq op 'if)
+ (let ((tst (first args))
+ (tbr (second args))
+ (fbr (third args)))
+ (cond
+ ((quotep tst) (if (second tst) tbr fbr))
+ ((equal tbr fbr) tbr))))
+ ((eq op 'equal)
+ (let ((lhs (first args))
+ (rhs (second args)))
+ (cond
+ ((equal lhs rhs) ''t)
+ ((and (quotep lhs) (quotep rhs)) ''nil))))
+ (t
+ (let ((n (first args)))
+ (cond
+ ((and (consp n) (eq (first n) 't+))
+ (cond ((eq op 'tzp) ''nil)
+ ((eq op 't-) (second n)))))))))
+
+(defun all-vars-bound* (trm alst is-lst)
+ (cond
+ ((and is-lst (endp trm)) t)
+ (is-lst (and (all-vars-bound* (first trm) alst nil)
+ (all-vars-bound* (rest trm) alst t)))
+ ((atom trm) (assoc-eq trm alst))
+ ((eq (first trm) 'quote) t)
+ (t (all-vars-bound* (rest trm) alst t))))
+
+(defabbrev all-vars-bound (trm alst)
+ (all-vars-bound* trm alst nil))
+
+(defun subtermp1 (x y is-lst)
+ (cond ((and is-lst (endp y)) nil)
+ (is-lst (or (subtermp1 x (first y) nil)
+ (subtermp1 x (rest y) t)))
+ ((equiv-terms x y) t)
+ ((atom y) nil)
+ ((eq (first y) 'quote) nil)
+ (t (subtermp1 x (rest y) t))))
+
+(defun subtermp (x y) (subtermp1 x y nil))
+
+(defun subterm-ctx (lhs ctx)
+ (and (not (endp ctx))
+ (or (subtermp lhs (first ctx))
+ (subterm-ctx lhs (rest ctx)))))
+
+(defabbrev func-symb (term)
+ (let ((op (car term))) (if (atom op) op (car op))))
+
+(mutual-recursion
+(defun unify-1way1 (pat term alist)
+ (cond
+ ((variablep pat)
+ (let ((pair (assoc-eq pat alist)))
+ (cond (pair (cond ((equiv-terms (cdr pair) term)
+ (mv t alist))
+ (t (mv nil alist))))
+ (t (mv t (cons (cons pat term) alist))))))
+ ((fquotep pat)
+ (cond ((equal pat term) (mv t alist))
+ (t (mv nil alist))))
+ ((variablep term) (mv nil alist))
+ ((fquotep term)
+ (let ((func-symb (func-symb pat)))
+ (cond
+ ((acl2-numberp (cadr term))
+ (case func-symb
+ (binary-+
+ (cond
+ ((quotep (fargn pat 1))
+ (unify-1way1 (fargn pat 2) (kwote (- (cadr term) (fix (cadr (fargn pat 1))))) alist))
+ ((quotep (fargn pat 2))
+ (unify-1way1 (fargn pat 1) (kwote (- (cadr term) (fix (cadr (fargn pat 2))))) alist))
+ (t (mv nil alist))))
+ (binary-*
+ (cond
+ ((and (quotep (fargn pat 1))
+ (integerp (cadr (fargn pat 1)))
+ (> (abs (cadr (fargn pat 1))) 1))
+ (unify-1way1 (fargn pat 2) (kwote (/ (cadr term) (cadr (fargn pat 1)))) alist))
+ ((and (quotep (fargn pat 2))
+ (integerp (cadr (fargn pat 2)))
+ (> (abs (cadr (fargn pat 2))) 1))
+ (unify-1way1 (fargn pat 1) (kwote (/ (cadr term) (cadr (fargn pat 2)))) alist))
+ (t (mv nil alist))))
+ (unary--
+ (cond
+ ((>= (+ (realpart (cadr term)) (imagpart (cadr term))) 0)
+ (mv nil alist))
+ (t (unify-1way1 (fargn pat 1) (kwote (- (cadr term))) alist))))
+ (unary-/
+ (cond
+ ((or (>= (* (cadr term) (conjugate (cadr term))) 1) (eql 0 (cadr term)))
+ (mv nil alist))
+ (t (unify-1way1 (fargn pat 1) (kwote (/ (cadr term))) alist))))
+ (otherwise (mv nil alist))))
+ ((symbolp (cadr term))
+ (cond
+ ((eq func-symb 'intern-in-package-of-symbol)
+ (let ((pkg (symbol-package-name (cadr term)))
+ (name (symbol-name (cadr term))))
+ (mv-let (ans alist1)
+ (unify-1way1 (fargn pat 1) (kwote name) alist)
+ (if ans
+ (if (and (nvariablep (fargn pat 2))
+ (fquotep (fargn pat 2)))
+ (if (not (symbolp (cadr (fargn pat 2))))
+ (mv (if (equal term *nil*) ans nil) alist)
+ (if (equal pkg (symbol-package-name (cadr (fargn pat 2))))
+ (mv ans alist1)
+ (mv nil alist)))
+ (mv-let (ans alist2)
+ (unify-1way1 (fargn pat 2) term alist1)
+ (if ans (mv ans alist2) (mv nil alist))))
+ (mv nil alist)))))
+ (t (mv nil alist))))
+ ((stringp (cadr term))
+ (cond
+ ((and (eq func-symb 'coerce) (equal (fargn pat 2) ''string))
+ (unify-1way1 (fargn pat 1) (kwote (coerce (cadr term) 'list)) alist))
+ (t (mv nil alist))))
+ ((consp (cadr term))
+ (cond
+ ((eq func-symb 'cons)
+ (mv-let (ans alist1)
+ (unify-1way1 (fargn pat 1) (kwote (car (cadr term))) alist)
+ (if ans
+ (mv-let (ans alist2)
+ (unify-1way1 (fargn pat 2) (kwote (cdr (cadr term))) alist1)
+ (if ans (mv ans alist2) (mv nil alist)))
+ (mv nil alist))))
+ (t (mv nil alist))))
+ (t (mv nil alist)))))
+ (t
+ (let ((pat-fn (func-symb pat))
+ (term-fn (func-symb term)))
+ (cond
+ ((or (not (eq pat-fn term-fn)) (eq pat-fn 'lambda))
+ (mv nil alist))
+ ((eq pat-fn 'equal)
+ (unify-1way1-equal (fargn pat 1) (fargn pat 2)
+ (fargn term 1) (fargn term 2)
+ alist))
+ (t (mv-let (ans alist1)
+ (unify-1way1-lst (fargs pat) (fargs term) alist)
+ (if ans (mv ans alist1) (mv nil alist)))))))))
+
+(defun unify-1way1-lst (pl tl alist)
+ (if (endp pl) (mv t alist)
+ (mv-let (ans alist)
+ (unify-1way1 (car pl) (car tl) alist)
+ (if (not ans) (mv nil alist)
+ (unify-1way1-lst (cdr pl) (cdr tl) alist)))))
+
+(defun unify-1way1-equal1 (pat1 pat2 term1 term2 alist)
+ (mv-let (ans alist1)
+ (unify-1way1 pat1 term1 alist)
+ (if (not ans) (mv nil alist)
+ (mv-let (ans alist2)
+ (unify-1way1 pat2 term2 alist1)
+ (if ans (mv ans alist2) (mv nil alist))))))
+
+(defun unify-1way1-equal (pat1 pat2 term1 term2 alist)
+ (mv-let (ans alist)
+ (unify-1way1-equal1 pat1 pat2 term1 term2 alist)
+ (if ans (mv ans alist)
+ (unify-1way1-equal1 pat2 pat1 term1 term2 alist))))
+)
+
+(defun unify-1way (pat term) (unify-1way1 pat term nil))
+
+(defun ctx-lhs (trm)
+ (if (and (consp trm) (member-eq (first trm) '(equal iff))) (second trm) trm))
+
+(defabbrev already-reduced (op op! go)
+ (or (eq op! 'quote)
+ (eq op! 'hide)
+ (and (eq op op!) (not go))))
+
+(mutual-recursion
+(defun prune-trm1 (trm)
+ (if (atom trm) trm
+ (let* ((op (first trm))
+ (op! (if (atom op) op (first op))))
+ (cond ((eq op op!) trm)
+ ((eq op! 'quote) (cons 'quote (rest trm)))
+ (t (cons op! (prune-args (rest trm))))))))
+
+(defun prune-args (args)
+ (if (endp args) ()
+ (cons (prune-trm1 (first args))
+ (prune-args (rest args)))))
+)
+
+(defabbrev prune-trm (op op! trm)
+ (cond ((eq op op!) trm)
+ ((eq op! 'hide) (prune-trm1 trm))
+ (t (cons op! (rest trm)))))
+
+(mutual-recursion
+(defun rewrt-hyp (hyp alst dp ctx st)
+ (if (not (all-vars-bound hyp alst)) :fail
+ (let ((rew (rewrt-trm (subst-term-ctx hyp alst ctx)
+ nil (1- dp) ctx t (in-hyps st))))
+ (if (and (consp hyp) (eq (first hyp) 'synp))
+ (cond
+ ((not (quotep rew))
+ (er hard 'rewrt-hyp "illegal synp rewrite"))
+ ((eq (second rew) t) alst)
+ ((consp (second rew)) (merge-alsts rew alst))
+ (t :fail))
+ (if (equal rew ''t) alst :fail)))))
+
+(defun rewrt-hyps (hyps alst dp ctx st)
+ (if (endp hyps) alst
+ (let ((alst (rewrt-hyp (first hyps) alst dp ctx st)))
+ (if (eq alst :fail) alst
+ (rewrt-hyps (rest hyps) alst dp ctx st)))))
+
+(defun rewrt-rule (r recp ens trm dp ctx iff st)
+ (let ((subc (access rewrite-rule r :subclass))
+ (lhs (access rewrite-rule r :lhs))
+ (rhs (access rewrite-rule r :rhs))
+ (hyps (access rewrite-rule r :hyps))
+ (equiv (access rewrite-rule r :equiv))
+ (hinfo (access rewrite-rule r :heuristic-info))
+ (nume (access rewrite-rule r :nume)))
+ (and (not (and recp (eq subc 'definition)))
+ (member-eq subc '(definition abbreviation backchain))
+ (enabled-numep nume ens)
+ (consp lhs)
+ (implies (eq subc 'backchain) (null hinfo))
+ (or (eq equiv 'equal) (and iff (eq equiv 'iff)))
+ (consp trm)
+ (implies (eq (car trm) 'if*) (not (eq subc 'definition)))
+ (mv-let (mtch alst) (unify-1way lhs trm)
+ (and mtch
+ (let ((alst (if (st-phase st) (if hyps :fail alst)
+ (rewrt-hyps hyps alst dp ctx st))))
+ (and (not (eq alst :fail))
+ (subst-term rhs alst))))))))
+
+(defun rewrt-rules (lemmas recp ens trm dp ctx iff st)
+ (and (not (endp lemmas))
+ (or (rewrt-rule (first lemmas) recp ens trm dp ctx iff st)
+ (rewrt-rules (rest lemmas) recp ens trm dp ctx iff st))))
+
+(defun rewrt-step (trm dp ctx iff st)
+ (let* ((wrld (st-wrld st))
+ (ens (st-ens st))
+ (op (first trm))
+ (args (rest trm))
+ (op* (if (eq op 'if) 'if* op))
+ (op-ok (not (eq op 't+)))
+ (lemmas (and op-ok (gprop op* 'lemmas)))
+ (recp (and op-ok (gprop op* 'recursivep)))
+ (trm* (if (eq op 'if) (cons 'if* args) trm)))
+ (or (rewrt-built-in op args)
+ (rewrt-rules lemmas recp ens trm* dp ctx iff st)
+ (and op-ok (quoted-args args)
+ (or (eq (gprop op 'symbol-class) :program) ;; could only occur in synp
+ (let ((nume (find-nume (gprop op 'runic-mapping-pairs)
+ (list :executable-counterpart op))))
+ (and nume (enabled-numep nume ens))))
+ (mv-let (erp val)
+ (ev-fncall-w op (fncall-args args) wrld nil nil t nil nil)
+ (and (not erp) (list 'quote val))))
+ trm)))
+
+(defun redux-ctx (lst ctx go dp st)
+ (cond
+ ((eq ctx :fail) :fail)
+ ((eq lst :fail) :fail)
+ ((endp lst) ctx)
+ (t
+ (let* ((trm (rewrt-trm (first lst) go dp ctx t st))
+ (ctx+ (if (quotep trm) (if (second trm) ctx :fail) (cons trm ctx))))
+ (redux-ctx (rest lst) ctx+ go dp st)))))
+
+(defun rewrt-ctx (ctx go dp st)
+ (let ((ctx+ (redux-ctx (redux-ctx ctx () go dp st) () go dp st)))
+ (if (or (eq ctx+ :fail) (equal ctx ctx+)) ctx (rewrt-ctx ctx+ go (1- dp) st))))
+
+(defun extend-ctx (trm ctx go dp st)
+ (cond
+ ((quotep trm)
+ (if (second trm) () :fail))
+ ((not (st-rew-ctx st))
+ (cons trm ctx))
+ ((subterm-ctx (ctx-lhs trm) ctx)
+ (rewrt-ctx (cons trm ctx) go dp st))
+ (t (cons trm ctx))))
+
+(defun rewrt-if-args (args go dp ctx iff st)
+ (let* ((tst (rewrt-trm (first args) go dp ctx t st))
+ (tbr (second args))
+ (fbr (third args))
+ (t-ctx (extend-ctx tst ctx go dp st)))
+ (cond
+ ((eq t-ctx :fail)
+ (list ''nil tbr (rewrt-trm fbr go dp ctx iff st)))
+ ((endp t-ctx)
+ (list ''t (rewrt-trm tbr go dp ctx iff st) fbr))
+ (t
+ (let ((f-ctx (extend-ctx (list 'equal tst ''nil) ctx go dp st)))
+ (cond
+ ((eq f-ctx :fail)
+ (list ''t (rewrt-trm tbr go dp ctx iff st) fbr))
+ ((endp f-ctx)
+ (list ''nil tbr (rewrt-trm fbr go dp ctx iff st)))
+ (t
+ (list tst
+ (rewrt-trm tbr t dp t-ctx iff st)
+ (rewrt-trm fbr t dp f-ctx iff st)))))))))
+
+(defun rewrt-args* (args go dp ctx st)
+ (if (endp args) ()
+ (cons (rewrt-trm (first args) go dp ctx nil st)
+ (rewrt-args* (rest args) go dp ctx st))))
+
+(defun rewrt-args (args op go dp ctx iff st)
+ (if (eq op 'if)
+ (rewrt-if-args args go dp ctx iff st)
+ (rewrt-args* args go dp ctx st)))
+
+(defun rewrt-trm (trm go dp ctx iff st)
+ (if (zp dp) (list 'hide trm)
+ (let ((mtch (match-in-ctx trm ctx iff)))
+ (cond
+ (mtch (rewrt-trm mtch go (1- dp) ctx iff st))
+ ((atom trm) trm)
+ (t
+ (let* ((op (first trm))
+ (op! (if (atom op) op (car op))))
+ (if (already-reduced op op! go) (prune-trm op op! trm)
+ (let ((args (rewrt-args (rest trm) op! go dp ctx iff st)))
+ (if (eq op! 'lambda)
+ (let ((trm+ (subst-term (third op) (bind-args (second op) args))))
+ (rewrt-trm trm+ go dp ctx iff st))
+ (let ((trm+ (rewrt-step (cons op! args) (1- dp) ctx iff st)))
+ (rewrt-trm trm+ nil (1- dp) ctx iff st)))))))))))
+)
+
+(defconst *rewrt-trm-depth* 100)
+
+(defun rewrt-term (trm ctx iff rew-ctx state)
+ (declare (xargs :stobjs state))
+ (let ((st (make-init-st (w state) (ens state) rew-ctx *rewrt-trm-depth*)))
+ (rewrt-trm trm t (st-depth st) ctx iff st)))
+
+(defabbrev rewrt-pure (trm) (rewrt-term trm () nil t state))
+(defabbrev rewrt-rep (trm rew-ctx) (rewrt-term trm () t rew-ctx state))
+(defabbrev rewrt-in-ctx (trm ctx) (rewrt-term trm ctx t nil state))
+
+(mutual-recursion
+(defun term-contains-force (trm)
+ (and (consp trm)
+ (or (eq (first trm) 'force)
+ (args-contain-force (rest trm)))))
+
+(defun args-contain-force (args)
+ (and (not (endp args))
+ (or (term-contains-force (first args))
+ (args-contain-force (rest args)))))
+)
+
+(mutual-recursion
+(defun strip-forces-term (trm hyps)
+ (if (atom trm) (mv trm hyps)
+ (case (first trm)
+ ((quote hide) (mv trm hyps))
+ (force (mv ''t (cons trm hyps)))
+ (t (mv-let (args hyps)
+ (strip-forces-args (rest trm) hyps)
+ (mv (cons (first trm) args) hyps))))))
+
+(defun strip-forces-args (args hyps)
+ (if (endp args) (mv () hyps)
+ (mv-let (fst hyps)
+ (strip-forces-term (first args) hyps)
+ (mv-let (rst hyps)
+ (strip-forces-args (rest args) hyps)
+ (mv (cons fst rst) hyps)))))
+)
+
+(defun rewrt-rep-loop* (term hyps ic$ state)
+ (declare (xargs :stobjs (ic$ state)))
+ (let ((nterm (rewrt-rep term (reduce-contexts ic$))))
+ (if (not (term-contains-force nterm)) (mv nterm hyps)
+ (mv-let (nterm nhyps) (strip-forces-term nterm ())
+ (rewrt-rep-loop* nterm (append nhyps hyps) ic$ state)))))
+
+(defabbrev rewrt-rep-loop (term)
+ (rewrt-rep-loop* term () ic$ state))
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+#| <SECTION> 4. extended rewriting and propagating rep-step |#
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+(defun rewrite-rep-step (rep ic$ state)
+ (declare (xargs :stobjs (ic$ state)))
+ (mv-let (term hyps) (rewrt-rep-loop `((lambda (n) ,rep) (t+ n)))
+ (detail "assuming rep hyps: ~p0 ~%" hyps (mv term hyps ic$ state))))
+
+(mutual-recursion
+(defun is-rep-term (term)
+ (if (atom term) (eq term 'n)
+ (let ((op (first term)))
+ (or (eq op 'quote)
+ (and (not (eq op 't+))
+ (not (eq op 'hide))
+ (are-rep-args (rest term)))))))
+
+(defun are-rep-args (args)
+ (or (endp args)
+ (and (is-rep-term (first args))
+ (are-rep-args (rest args)))))
+)
+
+(defmacro union-terms (x &rest y)
+ (if (endp y) x `(union-equal ,x (union-terms ,(car y) ,@(cdr y)))))
+
+(defun extract-rep-subterms (term)
+ (cond ((atom term) ())
+ ((eq (first term) 'quote) ())
+ ((eq (first term) 'if)
+ (union-terms (extract-rep-subterms (second term))
+ (extract-rep-subterms (third term))
+ (extract-rep-subterms (fourth term))))
+ ((is-rep-term term) (list term))
+ (t ())))
+
+(defun extract-non-rep-subterms (term)
+ (cond ((atom term) (list term))
+ ((eq (first term) 'quote) ())
+ ((eq (first term) 'if)
+ (union-terms (extract-non-rep-subterms (second term))
+ (extract-non-rep-subterms (third term))
+ (extract-non-rep-subterms (fourth term))))
+ ((is-rep-term term) ())
+ (t (list term))))
+
+(defun compute-rep-prime (reps step-alist ic$ state)
+ (declare (xargs :stobjs (ic$ state)))
+ (if (endp reps)
+ (mv nil nil step-alist nil ic$ state)
+ (seq
+ (current-rep (first reps))
+ ((term fst-hyps ic$ state)
+ (rewrite-rep-step current-rep ic$ state))
+ ((rst-reps rst-hyps step-alist rst-ins ic$ state)
+ (compute-rep-prime (rest reps) step-alist ic$ state))
+ (fst-reps (extract-rep-subterms term))
+ (reps (union-equal fst-reps rst-reps))
+ (hyps (union-equal fst-hyps rst-hyps))
+ (fst-ins (extract-non-rep-subterms term))
+ (ins (union-equal fst-ins rst-ins))
+ (step-alist (acons current-rep term step-alist))
+ (mv reps hyps step-alist ins ic$ state))))
+
+(defun compute-step-prime (reps step-alist ic$ state)
+ (declare (xargs :stobjs (ic$ state)))
+ (if (endp reps)
+ (mv (list 'bnil) ic$ state)
+ (seq
+ ((rest-step ic$ state)
+ (compute-step-prime (rest reps) step-alist ic$ state))
+ (first-step
+ (cdr (assoc-equal (first reps) step-alist)))
+ (mv (list 'bcons first-step rest-step) ic$ state))))
+
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+#| <SECTION> 5. invariant checker implementation |#
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+(defun clear-st-hashtbl (ndx ic$)
+ (declare (xargs :stobjs ic$))
+ (if (zp ndx) ic$
+ (let* ((ndx (1- ndx))
+ (ic$ (update-st-hashtbli ndx nil ic$)))
+ (clear-st-hashtbl ndx ic$))))
+
+(defun clear-seen-states (ic$)
+ (declare (xargs :stobjs ic$))
+ (clear-st-hashtbl (st-hashtbl-length ic$) ic$))
+
+(defconst *hex-digits*
+ '("0" "1" "2" "3" "4" "5" "6" "7" "8" "9" "A" "B" "C" "D" "E" "F"))
+
+(defun st-str (n st)
+ (if (zp n) ""
+ (string-append (st-str (- n 1) (floor st 16))
+ (nth (mod st 16) *hex-digits*))))
+
+(defmacro the-max-fix-st () (expt 2 28))
+
+(defmacro with-st-hash (st rslt)
+ `(let ((hash (let ((st ,st)
+ (len (the-fixnum (st-hashtbl-length ic$))))
+ (declare (type (signed-byte 29) len))
+ (the-fixnum (if (< st (the-max-fix-st))
+ (the-fixnum (mod (the-fixnum st) len))
+ (the-fixnum (mod st len)))))))
+ (declare (type (signed-byte 29) hash))
+ ,rslt))
+
+(defun legal-bnth (term)
+ (and (consp term)
+ (eq (first term) 'bnth)
+ (integerp (second term))
+ (>= (second term) 0)
+ (member (third term) '(s i))))
+
+(defun legal-singl (term)
+ (or (legal-bnth term)
+ (and (consp term)
+ (case (first term)
+ (quote t)
+ (if (and (legal-bnth (second term))
+ (legal-singl (third term))
+ (legal-singl (fourth term))))))))
+
+(defun legal-step (term)
+ (and (consp term)
+ (case (first term)
+ (bcons (and (legal-singl (second term))
+ (legal-step (third term))))
+ (bnil t))))
+
+(defmacro state-report-interval () 1000)
+
+(defun check-and-add-seen-state (st ic$)
+ (declare (xargs :stobjs ic$))
+ (with-st-hash
+ st
+ (let* ((entry (st-hashtbli hash ic$))
+ (seen (cond ((eq entry nil) nil)
+ ((eq entry t) t)
+ ((consp entry) (member st entry))
+ (t (eql st entry)))))
+ (if seen
+ (mv t ic$)
+ (let ((num-states (num-states ic$)))
+ (declare (type (signed-byte 29) num-states))
+ (prog2$
+ (and (eql (modf num-states (state-report-interval)) 0)
+ (> num-states 0)
+ (cw "num. abstract states visited: ~x0 ~%" num-states))
+ (let* ((ic$ (update-num-states (1+f num-states) ic$))
+ (ic$ (update-search-bound (1-f (search-bound ic$)) ic$))
+ (entry (cond ((eq entry nil) st)
+ ((fast-search ic$) t)
+ ((consp entry) (cons st entry))
+ (t (list st entry))))
+ (ic$ (update-st-hashtbli hash entry ic$)))
+ (mv nil ic$))))))))
+
+(defun mk-not-term (x)
+ (cond ((atom x) (list 'not x))
+ ((not (eq (first x) 'equal)) (list 'not x))
+ ((equal (second x) ''nil) (third x))
+ ((equal (third x) ''nil) (second x))
+ (t (list 'not x))))
+
+(defun map-rep-vector (mask reps st)
+ (if (endp mask) ()
+ (let ((n (first mask)))
+ (cons (if (bnth n st) (nth n reps) (mk-not-term (nth n reps)))
+ (map-rep-vector (rest mask) reps st)))))
+
+(defun mk-and-term (lst)
+ (cond ((endp lst) t)
+ ((endp (rest lst)) (first lst))
+ (t (cons 'and lst))))
+
+(defun map-counter-example (reps inputs path mask)
+ (if (endp path) ()
+ (cons (list (mk-and-term (map-rep-vector (caar mask) reps (caar path)))
+ (mk-and-term (map-rep-vector (cdar mask) inputs (cdar path))))
+ (map-counter-example reps inputs (rest path) (rest mask)))))
+
+(defun get-mask-terms (step tgt n)
+ (if (atom step)
+ (er hard 'get-mask-terms "illegal step")
+ (case (first step)
+ (bnil ())
+ (bcons
+ (if (member n tgt)
+ (cons (second step)
+ (get-mask-terms (third step) tgt (1+ n)))
+ (get-mask-terms (third step) tgt (1+ n))))
+ (t (er hard 'get-mask-terms "illegal step")))))
+
+(defun compute-ev (trm st in)
+ (if (atom trm)
+ (er hard 'compute-ev "illegal term")
+ (case (first trm)
+ (quote (second trm))
+ (bnth (bnth (second trm)
+ (if (eq (third trm) 's) st in)))
+ (if (if (compute-ev (second trm) st in)
+ (compute-ev (third trm) st in)
+ (compute-ev (fourth trm) st in)))
+ (t (er hard 'compute-ev "illegal trm")))))
+
+(defun compute-mask (term st in)
+ (if (atom term)
+ (er hard 'compute-mask "illegal term")
+ (case (first term)
+ (quote ())
+ (bnth (list term))
+ (if (let* ((tst (second term))
+ (tbr (third term))
+ (fbr (fourth term))
+ (tst-v (compute-ev tst st in))
+ (br (if tst-v tbr fbr))
+ (rst (compute-mask br st in)))
+ (if (or (quotep tst)
+ (iff (compute-ev tbr st in)
+ (compute-ev fbr st in)))
+ rst
+ (cons tst rst))))
+ (t (er hard 'compute-mask "illegal term")))))
+
+(defun add-mask-bits (mask var rslt)
+ (if (endp mask) rslt
+ (add-mask-bits (rest mask) var
+ (if (eq var (third (first mask)))
+ (add-to-set-eql (second (first mask)) rslt)
+ rslt))))
+
+(defun compute-masks (trms st in smsk imsk)
+ (if (endp trms) (mv smsk imsk)
+ (let ((mask (compute-mask (first trms) st in)))
+ (compute-masks (rest trms) st in
+ (add-mask-bits mask 's smsk)
+ (add-mask-bits mask 'i imsk)))))
+
+(defun compute-step-masks (step tgt st in)
+ (compute-masks (get-mask-terms step tgt 0) st in () ()))
+
+(defun compute-example-mask (path step tgt)
+ (if (endp path) ()
+ (seq
+ ((st-mask in-mask)
+ (compute-step-masks step tgt (caar path) (cdar path)))
+ (acons st-mask in-mask
+ (compute-example-mask (cdr path) step st-mask)))))
+
+(defun transform-rslt-path (path)
+ (if (endp (cdr path)) ()
+ (seq
+ (in (caar path))
+ (st (cdadr path))
+ (acons st in (transform-rslt-path (cdr path))))))
+
+(defun load-input-vec (input-set ndx ic$)
+ (declare (xargs :stobjs ic$))
+ (if (endp input-set) ic$
+ (let ((ic$ (update-input-veci ndx (first input-set) ic$)))
+ (load-input-vec (rest input-set) (1+ ndx) ic$))))
+
+(defun ivarp (x)
+ (and (consp x)
+ (eq (first x) 'if)
+ (natp (second x))
+ (eq (third x) t)
+ (eq (fourth x) nil)))
+
+(defun input-set-template (term)
+ (if (atom term)
+ (er hard 'input-set-template "illegal atom term")
+ (case (first term)
+ (quote (if (second term) t nil))
+ (bcons (list 'or
+ (input-set-template (second term))
+ (input-set-template (third term))))
+ (bnil :x)
+ (bnth (let ((ndx (second term))
+ (var (third term)))
+ (cond ((not (and (natp ndx)
+ (member var '(s i))))
+ (er hard 'input-set-template "illegal bnth term"))
+ ((eq var 'i) (list 'if ndx t nil))
+ (t :x))))
+ (if (let* ((tst (input-set-template (second term)))
+ (tbr (input-set-template (third term)))
+ (fbr (input-set-template (fourth term)))
+ (tst (if (ivarp tst) (second tst) tst)))
+ (cond ((natp tst) (list 'if tst tbr fbr))
+ ((eq tst t) tbr)
+ ((eq tst nil) fbr)
+ ((eq tst :x) (list 'or tbr fbr))
+ (t (er hard 'input-set-template "illegal if term")))))
+ (t (er hard 'input-set-template "illegal op term")))))
+
+(defun fully-defined (tmpl)
+ (cond ((eq tmpl :x) nil)
+ ((atom tmpl) t)
+ ((eq (first tmpl) 'or)
+ (and (fully-defined (second tmpl))
+ (fully-defined (third tmpl))))
+ (t
+ (and (fully-defined (third tmpl))
+ (fully-defined (fourth tmpl))))))
+
+(defun reduce-template (tmpl var valu)
+ (cond ((eql tmpl var) valu)
+ ((atom tmpl) tmpl)
+ ((eq (first tmpl) 'or)
+ (let ((a (reduce-template (second tmpl) var valu))
+ (b (reduce-template (third tmpl) var valu)))
+ (cond ((equal a b) a)
+ ((and (atom a) (atom b)) :x)
+ (t (list 'or a b)))))
+ (t
+ (let ((tst (reduce-template (second tmpl) var valu)))
+ (cond ((eq tst t)
+ (reduce-template (third tmpl) var valu))
+ ((eq tst nil)
+ (reduce-template (fourth tmpl) var valu))
+ (t
+ (let ((tbr (reduce-template (third tmpl) var valu))
+ (fbr (reduce-template (fourth tmpl) var valu)))
+ (cond ((and (equal tbr fbr) (fully-defined tbr)) tbr)
+ ((not (eq tst :x)) (list 'if tst tbr fbr))
+ ((and (atom tbr) (atom fbr)) :x)
+ (t (list 'or tbr fbr))))))))))
+
+(defun first-tmpl-var (tmpl)
+ (cond ((natp tmpl) tmpl)
+ ((atom tmpl) nil)
+ (t
+ (or (first-tmpl-var (second tmpl))
+ (first-tmpl-var (third tmpl))
+ (and (eq (first tmpl) 'if)
+ (first-tmpl-var (fourth tmpl)))))))
+
+(defabbrev set-bnth (i v x)
+ (if v (logior x (ash 1 i)) (logand x (lognot (ash 1 i)))))
+
+(defun add-input-set (tmpl in rslt)
+ (if (atom tmpl) (cons in rslt)
+ (let ((var (first-tmpl-var tmpl)))
+ (add-input-set (reduce-template tmpl var t)
+ (set-bnth var t in)
+ (add-input-set (reduce-template tmpl var nil)
+ (set-bnth var nil in)
+ rslt)))))
+
+(defun compute-input-set (step-term)
+ (add-input-set (input-set-template step-term) 0 ()))
+
+(defun construct-input-vec (step-term inputs state ic$)
+ (declare (xargs :stobjs (state ic$)))
+ (seq
+ (input-set (compute-input-set step-term))
+ (num-inputs (length input-set))
+ (ic$ (update-num-inputs num-inputs ic$))
+ (ic$ (resize-input-vec num-inputs ic$))
+ (ic$ (load-input-vec input-set 0 ic$))
+ (report "number of input bits: ~p0 number of inputs: ~p1 ~%"
+ (length inputs) num-inputs
+ (detail "inputs: ~p0 ~%" inputs
+ (mv ic$ state)))))
+
+(defun format-counter-example1 (path n)
+ (if (endp path) ()
+ (cons (list :step n
+ :state (first (first path))
+ :input (second (first path)))
+ (format-counter-example1 (rest path) (1+ n)))))
+
+(defun format-counter-example (path)
+ (format-counter-example1 (reverse path) 1))
+
+(defconst *invariant-checker-functions-and-compile* (quote (
+(defun visit-next-states (st in acc ic$)
+ (declare (xargs :stobjs ic$
+ :mode :program)
+ (type (signed-byte 29) in))
+ (if (fzp in)
+ (mv acc ic$)
+ (let ((in (1-f in)))
+ (declare (type (signed-byte 29) in))
+ (seq
+ (next-in (input-veci in ic$))
+ (next-st (step-prime st next-in))
+ ((seen ic$) (check-and-add-seen-state next-st ic$))
+ (acc (if seen acc (cons (cons next-in next-st) acc)))
+ (visit-next-states st in acc ic$)))))
+
+(defun bfs (visiting alst next-wave path ic$)
+ (declare (xargs :stobjs ic$
+ :mode :program))
+ (cond
+ ((endp visiting)
+ (cond
+ ((not (endp alst))
+ (bfs (cdar alst) (cdr alst) next-wave (caar alst) ic$))
+ ((endp next-wave)
+ (mv :passed ic$))
+ (t
+ (bfs () next-wave () path ic$))))
+ ((fzp (search-bound ic$))
+ (mv :bound-fail ic$))
+ (t
+ (seq
+ (pair (car visiting))
+ (st (cdr pair))
+ (path+ (cons pair path))
+ (if (not (bnth (inv-bit ic$) st))
+ (mv path+ ic$)
+ (seq
+ ((next ic$) (visit-next-states st (num-inputs ic$) () ic$))
+ (next-wave (cons (cons path+ next) next-wave))
+ (bfs (cdr visiting) alst next-wave path ic$)))))))
+
+(defun invariant-checker (reps inputs inv-term step-term ic$ state)
+ (declare (xargs :stobjs (ic$ state)
+ :mode :program))
+ (if (not (legal-step step-term))
+ (detail "illegal step term: ~p0 ~%" step-term
+ (seq
+ (ic$ (update-inv-check-result :bad-step ic$))
+ (mv ic$ state)))
+ (seq
+ (term (rewrt-pure '(rep-prime (t0))))
+ (if (not (quotep term))
+ (detail "init term rewrote to: ~p0 ~%" term
+ (seq
+ (ic$ (update-inv-check-result :bad-init ic$))
+ (mv ic$ state)))
+ (seq
+ (init-abs (second term))
+ ((ic$ state)
+ (construct-input-vec step-term inputs state ic$))
+ (ic$ (clear-seen-states ic$))
+ (ic$ (update-inv-bit (position-equal inv-term reps) ic$))
+ (ic$ (update-search-bound (check-bound ic$) ic$))
+ (ic$ (update-num-states 0 ic$))
+ (ic$ (update-num-rep-bits (length reps) ic$))
+ ((rslt ic$)
+ (if (inv-bit ic$)
+ (bfs (list (cons 0 init-abs)) () () () ic$)
+ (die :model-check-inv
+ "unexpectedly did not find inv-term in list of reps"
+ (mv nil ic$))))
+ (rslt (if (atom rslt) rslt
+ (seq
+ (rslt (transform-rslt-path rslt))
+ (tgt (list (inv-bit ic$)))
+ (mask (compute-example-mask rslt step-term tgt))
+ (rslt (map-counter-example reps inputs rslt mask))
+ rslt)))
+ (ic$ (update-inv-check-result rslt ic$))
+ (mv ic$ state))))))
+
+(comp (quote (step-prime visit-next-states bfs invariant-checker)))
+)))
+
+(defun bogus-function-denoting-invariant-checker-side-effect (ic$)
+ (declare (xargs :stobjs ic$))
+ ic$)
+
+(defun check-invariant (step-body rep-body reps inputs inv ic$ state)
+ (declare (xargs :stobjs (ic$ state)))
+ (mv-let (erp val state)
+ (ld (append (list (list 'defun 'step-prime (list 's 'i)
+ '(declare (xargs :mode :program))
+ step-body)
+ (list 'defun 'rep-prime (list 'n)
+ '(declare (xargs :mode :logic))
+ rep-body))
+ (and (disable-exec ic$)
+ (list (list 'in-theory (list 'disable (list 'rep-prime)))))
+ *invariant-checker-functions-and-compile*
+ (list (list 'invariant-checker
+ (list 'quote reps)
+ (list 'quote inputs)
+ (list 'quote inv)
+ (list 'quote step-body)
+ 'ic$ 'state)
+ (list 'ubt! (list 'quote 'step-prime)))))
+ (let ((ic$ (bogus-function-denoting-invariant-checker-side-effect ic$)))
+ (if erp (die :check-invariant
+ "Unexpected error ~p0" val
+ (mv nil ic$ state))
+ (mv (inv-check-result ic$) ic$ state)))))
+
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+#| <SECTION> 6. top-level algorithm and interface |#
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+(defun build-rep-body (reps)
+ (if (endp reps)
+ (list 'bnil)
+ (list 'bcons (first reps)
+ (build-rep-body (rest reps)))))
+
+(defun snoc (e x)
+ (if (endp x) (list e)
+ (cons (first x) (snoc e (rest x)))))
+
+(defun match-rep-or-input (term reps inputs)
+ (let ((pos (position-equal term reps)))
+ (if pos
+ (mv (list 'bnth pos 's) inputs)
+ (let ((pos (position-equal term inputs)))
+ (if pos
+ (mv (list 'bnth pos 'i) inputs)
+ (mv (list 'bnth (length inputs) 'i)
+ (snoc term inputs)))))))
+
+(defun final-step-redux (term)
+ (cond ((or (atom term)
+ (not (eq (car term) 'if)))
+ term)
+ ((quotep (second term))
+ (if (second (second term))
+ (third term)
+ (fourth term)))
+ ((equal (third term) (fourth term))
+ (third term))
+ ((and (equal (third term) ''t)
+ (equal (fourth term) ''nil))
+ (second term))
+ ((and (equal (third term) ''t)
+ (term-order (fourth term) (second term)))
+ (list 'if (fourth term) ''t (second term)))
+ ((and (equal (fourth term) ''nil)
+ (term-order (third term) (second term)))
+ (list 'if (third term) (second term) ''nil))
+ (t term)))
+
+(defconst *step-prime-ops*
+ '(bcons bnil if))
+
+(mutual-recursion
+(defun build-step-body (term reps inputs ic$)
+ (declare (xargs :stobjs ic$))
+ (cond ((atom term)
+ (match-rep-or-input term reps inputs))
+ ((eq (car term) 'quote)
+ (mv (if (cadr term) ''t ''nil) inputs))
+ ((member (car term) *step-prime-ops*)
+ (mv-let (args inputs)
+ (build-step-args (rest term) reps inputs ic$)
+ (mv (final-step-redux (cons (car term) args)) inputs)))
+ (t
+ (match-rep-or-input term reps inputs))))
+
+(defun build-step-args (args reps inputs ic$)
+ (declare (xargs :stobjs ic$))
+ (if (endp args)
+ (mv () inputs)
+ (mv-let (fst inputs)
+ (build-step-body (first args) reps inputs ic$)
+ (mv-let (rst inputs)
+ (build-step-args (rest args) reps inputs ic$)
+ (mv (cons fst rst) inputs)))))
+)
+
+(defun compute-reps (bound new reps hyps step-alist ic$ state)
+ (declare (xargs :stobjs (ic$ state)))
+ (cond
+ ((endp new)
+ (report "converged on reps! ~%"
+ (mv t reps hyps step-alist ic$ state)))
+ ((zp bound)
+ (report "exceeded refine bound! ~%"
+ (mv nil reps hyps step-alist ic$ state)))
+ (t
+ (seq
+ ((new-new new-hyps step-alist new-ins ic$ state)
+ (compute-rep-prime new step-alist ic$ state))
+ (bound (- bound (len new)))
+ (reps (union-equal new reps))
+ (new (set-difference-equal new-new reps))
+ (hyps (union-equal new-hyps hyps))
+ (detail "new reps: ~p0 ~%" new
+ (detail "new ins: ~p0 ~%" new-ins
+ (compute-reps bound new reps hyps step-alist ic$ state)))))))
+
+(defun get-prods (term)
+ (cond ((eq term t) ())
+ ((and (consp term) (eq (first term) 'and))
+ (rest term))
+ (t (list term))))
+
+(defun drop-nots (terms)
+ (cond ((endp terms) ())
+ ((and (consp (first terms))
+ (eq (first (first terms)) 'not))
+ (cons (second (first terms))
+ (drop-nots (rest terms))))
+ (t
+ (cons (first terms)
+ (drop-nots (rest terms))))))
+
+(defun new-reps-in (prods)
+ (cond ((endp prods) ())
+ ((is-rep-term (first prods)) (list (first prods)))
+ (t (new-reps-in (rest prods)))))
+
+(defun find-new-reps (path)
+ (and (consp path)
+ (or (new-reps-in (drop-nots (get-prods (second (first path)))))
+ (find-new-reps (rest path)))))
+
+(defun check-abstraction (reps step-alist inv ic$ state)
+ (declare (xargs :stobjs (ic$ state)))
+ (detail "check-reps: ~p0 ~%" reps
+ (seq
+ ((step-term ic$ state)
+ (compute-step-prime reps step-alist ic$ state))
+ ((step-body inputs)
+ (build-step-body step-term reps () ic$))
+ (rep-body (build-rep-body reps))
+ (ic$ (clear-ic$-for-inv-check ic$))
+ ((result ic$ state)
+ (detail "step-term: ~p0 ~%" step-term
+ (check-invariant step-body rep-body reps inputs inv ic$ state)))
+ (detail "number of abstract states visited: ~p0~%" (num-states ic$)
+ (cond
+ ((eq result :passed)
+ (mv t () ic$ state))
+ ((eq result :bound-fail)
+ (report "exceeded bound on number of states!~%"
+ (mv nil () ic$ state)))
+ ((eq result :bad-init)
+ (report "could not rewrite (rep-prime (t0)) to constant!~%"
+ (mv nil () ic$ state)))
+ (t
+ (report "failed-inv-check!~%"
+ (detail "failed-path:~p0~%" (format-counter-example result)
+ (mv nil (find-new-reps result) ic$ state)))))))))
+
+(defun prove-inv-single (bound inv-term new-reps curr-reps curr-hyps curr-step ic$ state)
+ (declare (xargs :stobjs (ic$ state)))
+ (seq
+ ((ok reps hyps step-alist ic$ state)
+ (compute-reps (refine-bound ic$) new-reps curr-reps
+ curr-hyps curr-step ic$ state))
+ (if (or ok (always-check ic$))
+ (seq
+ ((ok new-reps ic$ state)
+ (check-abstraction reps step-alist inv-term ic$ state))
+ (cond
+ (ok (mv t hyps ic$ state))
+ ((or (endp new-reps) (zp bound)) (mv nil hyps ic$ state))
+ (t (prove-inv-single (1- bound) inv-term new-reps
+ reps hyps step-alist ic$ state))))
+ (mv nil hyps ic$ state))))
+
+(defun prove-inv-loop (to-prove proven proofs-bound ic$ state)
+ (declare (xargs :stobjs (ic$ state)))
+ (cond
+ ((endp to-prove)
+ (mv t ic$ state))
+ ((member-equal (first to-prove) proven)
+ (prove-inv-loop (rest to-prove) proven proofs-bound ic$ state))
+ ((zp proofs-bound)
+ (report "exceeded bound on number of proofs!~%"
+ (mv nil ic$ state)))
+ (t
+ (seq
+ ((ok hyps ic$ state)
+ (prove-inv-single (jump-bound ic$) (first to-prove) (list (first to-prove))
+ () () () ic$ state))
+ (if (not ok)
+ (mv nil ic$ state)
+ (prove-inv-loop (append hyps (rest to-prove))
+ (cons (first to-prove) proven)
+ (1- proofs-bound) ic$ state))))))
+
+(defun definv-fn (inv-name
+ inv-form
+ jump-bound
+ check-bound
+ refine-bound
+ proofs-bound
+ inputs-bound
+ fast-search
+ detail-file
+ always-check
+ disable-exec
+ reduce-contexts
+ expected-result
+ ic$
+ state)
+ (declare (xargs :stobjs (ic$ state)))
+ (seq
+ ((erp inv-term bindings state)
+ (translate1 inv-form :stobjs-out '((:stobjs-out . :stobjs-out))
+ t 'top-level (w state) state))
+ (state
+ (if (or erp
+
+; Change by Matt K., 10/17/2013: When testing a tentative fix for a soundness
+; bug, I found a guard violation below because EQ was being called instead of
+; EQUAL; so I changed EQ to EQUAL. (Implementation details: That bug involved
+; doing extra guard-checking for certain :program mode functions in order to
+; avoid violating stobj recognizers. In this case definv-fn was marked as such
+; a function because it depended on ld-fn, which had been marked as such a
+; function because it took state. The ultimate fix didn't give this special
+; treatment for state, so the change from EQ to EQUAL below is no longer
+; necessary. But it seems that since the call of EQ was ill-guarded, it is
+; still good to fix.)
+
+ (not (equal bindings bindings)))
+ (die :illegal-term
+ "Error in macro-expansion: ~p0" inv-form
+ state)
+ state))
+ ((ic$ state)
+ (initialize-ic$ jump-bound
+ check-bound
+ refine-bound
+ inputs-bound
+ fast-search
+ detail-file
+ always-check
+ disable-exec
+ reduce-contexts
+ ic$
+ state))
+ (state
+ (detail "**************** begin ~s0 **************** ~%" detail-file
+ state))
+ ((ok ic$ state)
+ (prove-inv-loop (list inv-term) () proofs-bound ic$ state))
+ (result (if ok :qed :failed))
+ (state
+ (report "~x0~%" (list result inv-name result)
+ (detail "**************** end ~s0 **************** ~%~%" detail-file
+ state)))
+ ((ic$ state)
+ (cleanup-ic$ ic$ state))
+ (state
+ (if (implies expected-result (equal result expected-result))
+ state
+ (die :unexpected-result-for-inv-proof
+ "encountered unexpected result for invariant proof~%"
+ state)))
+ (mv state ic$)))
+
+(defmacro definv (inv-name
+ inv-term
+ &key
+ (file '"invp.rpt")
+ (jump-bound '1)
+ (check-bound '4000)
+ (refine-bound '8)
+ (proofs-bound '10)
+ (inputs-bound '1000)
+ (fast-search 'nil)
+ (disable-exec 't)
+ (always-check 'nil)
+ (reduce-contexts 'nil)
+ (expected-result 'nil))
+ (declare (xargs :guard (and (symbolp inv-name)
+ (integerp check-bound)
+ (>= check-bound 0)
+ (integerp inputs-bound)
+ (>= inputs-bound 0)
+ (integerp refine-bound)
+ (>= refine-bound 0)
+ (integerp proofs-bound)
+ (>= proofs-bound 0)
+ (or (stringp file) (not file))
+ (booleanp fast-search)
+ (booleanp always-check)
+ (booleanp disable-exec)
+ (booleanp reduce-contexts)
+ (member-eq expected-result '(:qed :failed nil)))))
+ `(definv-fn
+ (quote ,inv-name)
+ (quote ,inv-term)
+ (quote ,jump-bound)
+ (quote ,check-bound)
+ (quote ,refine-bound)
+ (quote ,proofs-bound)
+ (quote ,inputs-bound)
+ (quote ,fast-search)
+ (quote ,file)
+ (quote ,always-check)
+ (quote ,disable-exec)
+ (quote ,reduce-contexts)
+ (quote ,expected-result)
+ ic$
+ state))
+
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+#| <SECTION> 7. various test examples |#
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+;; compile the invariant prover:
+(comp t)
+
+(set-ignore-ok t)
+(set-irrelevant-formals-ok t)
+(set-match-free-error nil)
+
+(logic)
+
+;; Simple Example: A simple pair of integers
+;; -----------------------------------------
+
+(progn
+(defun next (s i)
+ (cons (if (car i) (if (cdr s) 1 (ifix (cdr i))) (cdr s))
+ (if (cdr i) (ifix (car i)) (cdr s))))
+
+(defun init ()
+ (cons 1 2))
+
+(in-theory (disable natp))
+
+;; environment input function
+(encapsulate (((i *) => *)) (local (defun i (n) n)))
+
+(defun x (n)
+ (declare (xargs :measure (tmsr n)))
+ (if (tzp n) (init) (next (x (t- n)) (i n))))
+
+(in-theory (disable (x)))
+
+(if-lift-rules
+ (integerp x)
+ (natp x)
+ (equal x y)
+ (car x)
+ (cdr x))
+
+(defthm x-of-t+
+ (implies (not (tzp n))
+ (equal (x n) (next (x (t- n)) (i n))))
+ :hints (("Goal" :in-theory (disable next))))
+
+(defthm x-of-t0
+ (equal (x (t0)) (init)))
+)
+
+(definv simple-pass-inv
+ (integerp (car (x n)))
+ :file "simp1.rpt"
+ :expected-result :qed)
+
+(definv simple-fail-inv
+ (natp (car (x n)))
+ :file "simp2.rpt"
+ :expected-result :failed)
+
+(u)
+
+;; Another Simple Example: A mutual exclusion model
+;; -------------------------------------------------
+
+(include-book "crit")
+
+(definv crit-inv
+ (ok n)
+ :file "crit.rpt"
+ :expected-result :qed)
+
+(u)
+
+;; A slightly more complex example: A MESI cache model
+;; -------------------------------------------------
+
+(include-book "mesi")
+
+(definv mesi-inv
+ (ok n)
+ :file "mesi.rpt"
+ :expected-result :qed)
+
+(u)
+
+;; go ahead and write to success.txt in order to signal that we have succeeded
+;; in proving all of the example invariants:
+
+(defun mark-successful-run (state)
+ (declare (xargs :stobjs state
+ :mode :program))
+ (mv-let (channel state)
+ (open-output-channel "success.txt" :character state)
+ (let ((state (fms "invariant prover successfully completed proofs!!" () channel state nil)))
+ (let ((state (close-output-channel channel state)))
+ state))))
+
+(mark-successful-run state)
+
+
+
+
diff --git a/books/workshops/2004/sumners-ray/support/mesi.lisp b/books/workshops/2004/sumners-ray/support/mesi.lisp
new file mode 100644
index 0000000..70583a0
--- /dev/null
+++ b/books/workshops/2004/sumners-ray/support/mesi.lisp
@@ -0,0 +1,227 @@
+(in-package "ACL2")
+(include-book "basis")
+(include-book "records")
+
+#|
+
+We define a cache-coherence memory-ordering protocol at a pretty high-level of
+abstraction. This is loosely based on the MESI protocol.
+
+The property we want to prove is the following:
+
+Forall p,q,a,d: if (q completed the last write to address a with data d) and
+ p reads address a and gets value d.
+
+Well, it is easier to leave the specific q and d out of the equation and only
+introduce p and a as skolem constants. We add appropriate auxiliary variables
+to track this.
+
+|#
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;;;;;;;;;; definitions for example mesi cache system ;;;;;;;;;;;;;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+(encapsulate (((proc *) => *) ((op *) => *)
+ ((addr *) => *) ((data *) => *))
+ (local (defun proc (n) n)) (local (defun op (n) n))
+ (local (defun addr (n) n)) (local (defun data (n) n)))
+
+(encapsulate (((c-l *) => *)) (local (defun c-l (a) a)))
+
+(define-system mesi-cache
+ (mem (c n) nil
+ (cond ((/= (c-l (addr n)) c) (mem c n-))
+ ((and (= (op n) :flush)
+ (in (proc n) (excl c n-)))
+ (cache (proc n) c n-))
+ (t (mem c n-))))
+
+ (cache (p c n) nil
+ (cond ((/= (c-l (addr n)) c) (cache p c n-))
+ ((/= (proc n) p) (cache p c n-))
+ ((or (and (= (op n) :fill) (not (excl c n-)))
+ (and (= (op n) :fille) (not (valid c n-))))
+ (mem c n-))
+ ((and (= (op n) :store) (in p (excl c n-)))
+ (s (addr n) (data n) (cache p c n-)))
+ (t (cache p c n-))))
+
+ (excl (c n) nil
+ (cond ((/= (c-l (addr n)) c) (excl c n-))
+ ((and (= (op n) :flush)
+ (implies (excl c n-)
+ (in (proc n) (excl c n-))))
+ (sdrop (proc n) (excl c n-)))
+ ((and (= (op n) :fille) (not (valid c n-)))
+ (sadd (proc n) (excl c n-)))
+ (t (excl c n-))))
+
+ (valid (c n) nil
+ (cond ((/= (c-l (addr n)) c) (valid c n-))
+ ((and (= (op n) :flush)
+ (implies (excl c n-)
+ (in (proc n) (excl c n-))))
+ (sdrop (proc n) (valid c n-)))
+ ((or (and (= (op n) :fill) (not (excl c n-)))
+ (and (= (op n) :fille) (not (valid c n-))))
+ (sadd (proc n) (valid c n-)))
+ (t (valid c n-)))))
+
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;;;;;;;;;; definitions for mesi system specification ;;;;;;;;;;;;;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+(encapsulate (((p) => *) ((a) => *))
+ (local (defun p () t)) (local (defun a () t))
+ (defthm a-not-nil (equal (equal (a) nil) nil))
+ (defthm p-not-nil (equal (equal (p) nil) nil)))
+
+(define-system mesi-specification
+ (a-dat (n) nil
+ (if (and (equal (addr n) (a))
+ (equal (op n) :store)
+ (in (proc n) (excl (c-l (addr n)) n-)))
+ (list (data n))
+ (a-dat n-)))
+
+ (ok (n) t
+ (if (and (a-dat n-)
+ (equal (proc n) (p))
+ (equal (addr n) (a))
+ (equal (op n) :load)
+ (in (p) (valid (c-l (addr n)) n-)))
+ (equal (g (a) (cache (p) (c-l (a)) n-))
+ (car (a-dat n-)))
+ (ok n-))))
+
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;;;;;;;;;;; various auxiliary rules and definitions ;;;;;;;;;;;;;;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+
+;; For the (proc n), (addr n), and (op n) inputs, we want to force
+;; case-splits using the finite-cases macro from basis.lisp:
+
+(finite-cases process-id :input (proc n) ((p) (scar (excl (c-l (a)) (t- n)))))
+(finite-cases address :input (addr n) ((a)))
+(finite-cases operation :input (op n) (:store :fille :fill :flush :load))
+
+
+;; We do want the following rewrite rule from the records book enabled:
+
+(in-theory (enable g-of-s-redux))
+
+
+;; The following function is only used as shorthand in provide a precise
+;; case-split in rewrite rules below:
+
+(defun <<s (e x) (implies x (<< e (scar x))))
+
+
+;; These could probably be moved into the sets and records books, but it is
+;; easy enough to include all of the if-lifting rules in one form:
+
+(if-lift-rules
+ (<<s x y)
+ (car x)
+ (cons x y)
+ (g a r)
+ (s a v r)
+ (c1 r)
+ (equal x y)
+ (sdiff x y)
+ (isect x y)
+ (unite x y)
+ (in e x)
+ (subset x y)
+ (scar a)
+ (s1 a)
+ (c-l a))
+
+
+;; The following is an unfortunate rule that we need to add because the
+;; rewriter does not handle equality reasoning across predicate
+;; evaluations. This might be a worthwhile addition, but it could also be an
+;; expensive proposition, so I need to continue working on this.
+
+(defthm bogus-equality1
+ (implies (not (equal (proc! a) (p)))
+ (equal (equal (scar (excl (c-l (a)) n)) (proc! a))
+ (if (equal (scar (excl (c-l (a)) n)) (p)) nil
+ (hide (equal (scar (excl (c-l (a)) n)) (proc! a))))))
+ :hints (("Goal" :expand (hide (equal (scar (excl (c-l (a)) n)) (proc! a))))))
+
+
+;; The next set of rules are simply reorganized versions of rules from the sets
+;; book which we need in order to introduce certain abstractions and/or force
+;; certain case splits:
+
+(defthm c1-of-sdrop-hide
+ (equal (c1 (sdrop e x))
+ (if (in e x) (if (c1 x) nil (hide (c1 (sdrop e x)))) (c1 x)))
+ :hints (("Goal" :expand (hide (c1 (sdrop e x))))))
+
+(defthm scar-of-sdrop-hide
+ (equal (scar (sdrop e x))
+ (if (in e x) (hide (scar (sdrop e x))) (scar x)))
+ :hints (("Goal" :expand (hide (scar (sdrop e x))))))
+
+(defthm scar-of-sadd
+ (equal (scar (sadd e x))
+ (if (<<s e x) e (scar x)))
+ :hints (("Goal" :cases (x (not x)))))
+
+(defthm drop-in-test-when-equal-scar
+ (implies (and s (equal (scar s) e))
+ (in e s)))
+
+(defthm rename-of-wrap-up-s1
+ (equal (equal s (s1 a))
+ (and (c1 s) (equal (scar s) a))))
+
+
+;; We will only use the following predicate in syntaxp tests below...
+
+(defun st-predp (x)
+ (declare (xargs :mode :program))
+ (not (intersectp-eq '(t+ hide) (all-fnnames x))))
+
+
+;; Ok, the key insight to this invariant proof is to case-split the test of a
+;; node in an :excl set by testing if the :excl set is empty, a singleton of
+;; the last guy to be added to the :excl set, or abstracted (we don't care
+;; because we don't expect this case to ever occur -- or at least not
+;; matter). We need the syntaxp test to make sure we only apply this in cases
+;; where we are trying to case-split out a selected input, but also we must
+;; ensure that the resulting tests and cases will in fact be rep terms.
+
+(defthm in-excl-rdx
+ (implies (syntaxp (not (st-predp e)))
+ (equal (in e (excl c n))
+ (cond ((not (excl c n)) nil)
+ ((c1 (excl c n)) (equal e (scar (excl c n))))
+ (t (hide (in e (excl c n)))))))
+ :hints (("Goal" :expand (hide (in e (excl c n))))))
+
+
+;; And now we abstract the terms which we do not wish to include in state
+;; information for the MESI model:
+
+(abstract-terms (in 'nil (excl (c-l (a)) n))
+ (equal (scar (excl (c-l (a)) n)) 'nil)
+ (equal (g (a) (cache 'nil (c-l (a)) n)) (car (a-dat n)))
+ (equal (scar (valid c n)) e)
+ (c1 (valid c n)))
+
+
+;; This final theorem basically defines the only case of <<s we care about:
+
+(defthm <<s-of-nil
+ (equal (<<s e x) (if x (hide (<<s e x)) t))
+ :hints (("Goal" :expand (hide (<<s e x)))))
+
+(in-theory (disable <<s))
+
diff --git a/books/workshops/2004/sumners-ray/support/records.lisp b/books/workshops/2004/sumners-ray/support/records.lisp
new file mode 100644
index 0000000..57b406d
--- /dev/null
+++ b/books/workshops/2004/sumners-ray/support/records.lisp
@@ -0,0 +1,644 @@
+;; maps.lisp
+
+(in-package "ACL2")
+
+(set-match-free-default :all)
+
+#|
+
+We define properties of a generic map or record accessor function and updater
+function. The basic functions are (g a r) and (s a v r) where a is an
+address/key, v is a value, r is a record, and (g a r) returns the value set to
+address a in record r, and (s a v r) returns a new record with address a set to
+value v in record r.
+
+The following main lemmas are "exported" about record (g)et and (s)et:
+
+(defthm g-same-s
+ (equal (g a (s a v r))
+ v))
+
+(defthm g-diff-s
+ (implies (not (equal a b))
+ (equal (g a (s b v r))
+ (g a r))))
+
+(defthm s-same-g
+ (equal (s a (g a r) r)
+ r))
+
+(defthm s-same-s
+ (equal (s a y (s a x r))
+ (s a y r)))
+
+(defthm s-diff-s
+ (implies (not (equal a b))
+ (equal (s b y (s a x r))
+ (s a x (s b y r))))
+ :rule-classes ((:rewrite :loop-stopper ((b a s)))))
+
+We also include some auxiliary lemmas which have proven useful.
+
+(defthm access-of-nil-is-nil
+ (not (g a nil)))
+
+(defthm record-set-cannot-be-nil
+ (implies v (s a v r)))
+
+(defthm record-get-non-nil-cannot-be-nil
+ (implies (g a r) r))
+
+We also include some additional functions and lemmas for defining functions
+which recur through a record. The function 'dom takes a record and returns the
+set of "keys" or "fields" in the record. We prove the following properties of
+'dom with respect 's and 'g.
+
+(defthm dom-of-s
+ (equal (dom (s a v r))
+ (if v
+ (sadd a (dom r))
+ (sdrop a (dom r)))))
+
+(defthm in-dom-iff-g
+ (iff (in a (dom r))
+ (g a r)))
+
+We normalize the record structures (which allows the 'equal-ity based rewrite
+rules) as alists where the keys (cars) are ordered using the total-order added
+to ACL2 and defined in the included book. We define a set of "-aux" functions
+which assume well-formed records -- defined by rcdp -- and then prove the
+desired properties using hypothesis assuming well-formed records.
+
+We then remove these well-formed record hypothesis by defining an invertible
+mapping (acl2->rcd) taking any ACL2 object and returning a well-formed
+record. We then prove the desired properties using the proper translations of
+the -aux functions to the acl2 objects, and subsequently remove the
+well-formed record hypothesis.
+
+|#
+
+(include-book "sets")
+
+;; BEGIN records definitions.
+
+(verify-guards <<)
+
+(defun ill-formed-key ()
+ (declare (xargs :guard t))
+ "unlikely-we-should-ever-encounter-this-particular-string-as-a-key!?!?!?!")
+
+(defun wf-keyp (x)
+ (declare (xargs :guard t))
+ (not (equal x (ill-formed-key))))
+
+(defun rcdp (x)
+ (declare (xargs :guard t))
+ (or (null x)
+ (and (consp x)
+ (consp (car x))
+ (rcdp (cdr x))
+ (cdar x)
+ (or (null (cdr x))
+ (<< (caar x) (caadr x))))))
+
+(defthm rcdp-implies-alistp
+ (implies (rcdp x) (alistp x)))
+
+(defun ifrp (x) ;; ill-formed rcdp
+ (declare (xargs :guard t))
+ (or (not (rcdp x))
+ (and (consp x)
+ (null (cdr x))
+ (consp (car x))
+ (equal (caar x) (ill-formed-key))
+ (ifrp (cdar x)))))
+
+(defun acl2->rcd (x) ;; function mapping acl2 objects to well-formed records.
+ (declare (xargs :guard t))
+ (if (ifrp x) (list (cons (ill-formed-key) x)) x))
+
+(defun rcd->acl2 (x) ;; inverse of acl2->rcd.
+ (declare (xargs :guard t))
+ (if (ifrp x) (and (consp x) (consp (car x)) (cdar x)) x))
+
+(defun g-aux (a x) ;; record g(et) when x is a well-formed record.
+ (declare (xargs :guard (rcdp x)))
+ (cond ((or (endp x)
+ (<< a (caar x)))
+ nil)
+ ((equal a (caar x))
+ (cdar x))
+ (t
+ (g-aux a (cdr x)))))
+
+(defun g (a x) ;; the generic record g(et) which works on any ACL2 object.
+ (declare (xargs :guard t))
+ (g-aux a (acl2->rcd x)))
+
+(defabbrev acons-if (a v x)
+ (if v (cons (cons a v) x) x))
+
+(defun s-aux (a v r) ;; record s(et) when x is a well-formed record.
+ (declare (xargs :guard (rcdp r)))
+ (cond ((or (endp r)
+ (<< a (caar r)))
+ (acons-if a v r))
+ ((equal a (caar r))
+ (acons-if a v (cdr r)))
+ (t
+ (cons (car r) (s-aux a v (cdr r))))))
+
+(defun s (a v x) ;; the generic record s(et) which works on any ACL2 object.
+ (declare (xargs :guard t))
+ (rcd->acl2 (s-aux a v (acl2->rcd x))))
+
+(defun dom-aux (x)
+;; (declare (xargs :guard (rcdp x)))
+ (if (endp x) ()
+ (sadd (caar x) (dom-aux (cdr x)))))
+
+(defun dom (x)
+ (dom-aux (acl2->rcd x)))
+
+
+;; We now provide "faster" versions of the above record operations. The bodies
+;; of these "f" functions should rewrite immediately to the nicer logic
+;; functions.
+
+(defun wf-rcdp (x)
+ (declare (xargs :guard t))
+ (or (null x)
+ (and (consp x)
+ (consp (car x))
+ (wf-rcdp (cdr x))
+ (cdar x)
+ (wf-keyp (caar x))
+ (or (null (cdr x))
+ (<< (caar x) (caadr x))))))
+
+(local
+(defthm wf-rcdp-implies-rcdp
+ (implies (wf-rcdp x)
+ (rcdp x))))
+
+(local
+(defthm wf-rcdp-implies-not-ifrp
+ (implies (wf-rcdp x)
+ (not (ifrp x)))))
+
+(defun fast-g (a r)
+ (declare (xargs :guard (wf-rcdp r)))
+ (cond ((endp r) nil)
+ ((equal a (caar r)) (cdar r))
+ (t (fast-g a (cdr r)))))
+
+(local
+(defthm fast-g-equals-g-aux
+ (implies (wf-rcdp r)
+ (equal (fast-g a r)
+ (g-aux a r)))))
+
+(defun fg (a r)
+ (declare (xargs :guard (wf-rcdp r)))
+ (mbe :logic (g a r)
+ :exec (fast-g a r)))
+
+(local
+(defthm s-aux-is-bounded
+ (implies (and (rcdp r)
+ (s-aux a v r)
+ (<< e a)
+ (<< e (caar r)))
+ (<< e (caar (s-aux a v r))))))
+
+(local
+(defthm s-aux-preserves-wf-rcdp
+ (implies (and (wf-rcdp r)
+ (wf-keyp a))
+ (wf-rcdp (s-aux a v r)))))
+
+(defun fast-s (a v r)
+ (declare (xargs :guard (wf-rcdp r)))
+ (cond ((endp r)
+ (acons-if a v ()))
+ ((equal a (caar r))
+ (acons-if a v (cdr r)))
+ ((<< a (caar r))
+ (acons-if a v r))
+ (t
+ (cons (car r) (fast-s a v (cdr r))))))
+
+(local
+(defthm fast-s-equals-s-aux
+ (implies (wf-rcdp r)
+ (equal (fast-s a v r)
+ (s-aux a v r)))))
+
+(defun fs (a v r)
+ (declare (xargs :guard (and (wf-keyp a) (wf-rcdp r))))
+ (mbe :logic (s a v r)
+ :exec (fast-s a v r)))
+
+;; we will need the following theorem in order to prove guards in functions
+;; which use fs:
+
+(defthm s-preserves-wf-rcdp
+ (implies (and (wf-rcdp r)
+ (wf-keyp a))
+ (wf-rcdp (s a v r))))
+
+
+;;;; basic property of records ;;;;
+
+(local
+(defthm rcdp-implies-true-listp
+ (implies (rcdp x)
+ (true-listp x))
+ :rule-classes (:forward-chaining
+ :rewrite)))
+
+
+;;;; initial properties of s-aux and g-aux ;;;;
+
+(local
+(defthm s-aux-preserves-rcdp
+ (implies (rcdp r)
+ (rcdp (s-aux a v r)))))
+
+(local
+(defthm g-aux-same-s-aux
+ (implies (rcdp r)
+ (equal (g-aux a (s-aux a v r))
+ v))))
+
+(local
+(defthm g-aux-diff-s-aux
+ (implies (and (rcdp r)
+ (not (equal a b)))
+ (equal (g-aux a (s-aux b v r))
+ (g-aux a r)))))
+
+(local
+(defthm s-aux-same-g-aux
+ (implies (rcdp r)
+ (equal (s-aux a (g-aux a r) r)
+ r))))
+
+(local
+(defthm s-aux-same-s-aux
+ (implies (rcdp r)
+ (equal (s-aux a y (s-aux a x r))
+ (s-aux a y r)))))
+
+(local
+(defthm s-aux-diff-s-aux
+ (implies (and (rcdp r)
+ (not (equal a b)))
+ (equal (s-aux b y (s-aux a x r))
+ (s-aux a x (s-aux b y r))))
+ :rule-classes ((:rewrite :loop-stopper ((b a s))))))
+
+(local
+(defthm s-aux-non-nil-cannot-be-nil
+ (implies (and v (rcdp r))
+ (s-aux a v r))))
+
+(local
+(defthm g-aux-is-nil-for-<<
+ (implies (and (rcdp r)
+ (<< a (caar r)))
+ (not (g-aux a r)))))
+
+(local
+(defthm dom-aux-of-s-aux
+ (implies (rcdp r)
+ (equal (dom-aux (s-aux a v r))
+ (if v
+ (sadd a (dom-aux r))
+ (sdrop a (dom-aux r)))))))
+
+(local
+(defthm in-dom-aux-iff-g-aux
+ (implies (rcdp r)
+ (iff (g-aux a r)
+ (in a (dom-aux r))))))
+
+(defun induct-two-records (r1 r2)
+ (declare (xargs :measure (+ (len r1) (len r2))))
+ (cond ((endp r1) r2)
+ ((endp r2) r1)
+ ((<< (caar r1) (caar r2))
+ (induct-two-records (cdr r1) r2))
+ ((<< (caar r2) (caar r1))
+ (induct-two-records r1 (cdr r2)))
+ ((equal (caar r1) (caar r2))
+ (induct-two-records (cdr r1) (cdr r2)))
+ (t nil)))
+
+;;;; The output from the following theorems is voluminous,
+;;;; and it is pretty impressive that ACL2 can get through
+;;;; this proof without any help other than the induction
+;;;; scheme. Cool.
+
+(local
+(defthm equal-s-aux-redux-1
+ (implies (and (rcdp r1)
+ (rcdp r2)
+ (equal (s-aux a v1 r1) (s-aux a v2 r2)))
+ (equal (equal v1 v2) t))
+ :hints (("Goal" :induct (induct-two-records r1 r2)))))
+
+(local
+(defthm equal-s-aux-redux-2
+ (implies (and (rcdp r1)
+ (rcdp r2)
+ (equal (s-aux a v1 r1) (s-aux a v2 r2)))
+ (equal (equal (s-aux a v r1) (s-aux a v r2))
+ t))
+ :hints (("Goal" :induct (induct-two-records r1 r2)))))
+
+;;;; properties of acl2->rcd and rcd->acl2 ;;;;
+
+(local
+(defthm acl2->rcd-rcd->acl2-of-rcdp
+ (implies (rcdp x)
+ (equal (acl2->rcd (rcd->acl2 x))
+ x))))
+
+(local
+(defthm acl2->rcd-returns-rcdp
+ (rcdp (acl2->rcd x))))
+
+(local
+(defthm acl2->rcd-preserves-equality
+ (iff (equal (acl2->rcd x) (acl2->rcd y))
+ (equal x y))))
+
+(local
+(defthm rcd->acl2-acl2->rcd-inverse
+ (equal (rcd->acl2 (acl2->rcd x)) x)))
+
+(local
+(defthm rcd->acl2-of-record-non-nil
+ (implies (and r (rcdp r))
+ (rcd->acl2 r))))
+
+(local
+(defthm rcd->acl2-preserves-equality-on-rcds
+ (implies (and (rcdp x) (rcdp y))
+ (iff (equal (rcd->acl2 x) (rcd->acl2 y))
+ (equal x y)))))
+
+(in-theory (disable acl2->rcd rcd->acl2))
+
+
+;;;; final (exported) properties of record g(et) and s(et) ;;;;
+
+(defthm dom-of-s
+ (equal (dom (s a v r))
+ (if v
+ (sadd a (dom r))
+ (sdrop a (dom r)))))
+
+(defthm in-dom-iff-g
+ (iff (g a r)
+ (in a (dom r))))
+
+;; We disable this rule because it may introduce "dom" into contexts where it
+;; is not wanted.
+(in-theory (disable in-dom-iff-g))
+
+(local
+(defthm dom-aux-empty-iff-empty
+ (implies (rcdp r)
+ (iff (dom-aux r) r))))
+
+(defthm dom-empty-iff-empty
+ (iff (dom x) x))
+
+;; NOTE that these theorems basically follow from the "equivalent" properties
+;; for s-aux and g-aux with rcdp hypothesis, and the lemmas about the acl2->rcd
+;; and its inverse rcd->acl2. If the user wanted to add to the following set of
+;; exported theorems, they should add the corresponding lemma about s-aux and
+;; g-aux using rcdp hypothesis and then add the theorem here about the generic
+;; s(et) and g(et) they wish to export from the book.
+
+(defthm g-same-s
+ (equal (g a (s a v r))
+ v))
+
+(defthm g-diff-s
+ (implies (not (equal a b))
+ (equal (g a (s b v r))
+ (g a r))))
+
+;;;; NOTE: The following can be used instead of the above rules to force ACL2
+;;;; to do a case-split. We disable this rule by default since it can lead to
+;;;; an expensive case explosion, but in many cases, this rule may be more
+;;;; effective than two rules above and should be enabled.
+
+(defthm g-of-s-redux
+ (equal (g a (s b v r))
+ (if (equal a b) v (g a r))))
+
+(in-theory (disable g-of-s-redux))
+
+(defthm s-same-g
+ (equal (s a (g a r) r)
+ r))
+
+(defthm s-same-s
+ (equal (s a y (s a x r))
+ (s a y r)))
+
+(defthm s-diff-s
+ (implies (not (equal a b))
+ (equal (s b y (s a x r))
+ (s a x (s b y r))))
+ :rule-classes ((:rewrite :loop-stopper ((b a s)))))
+
+;; the following theorems are less relevant but have been useful in dealing
+;; with a default record of NIL.
+
+(defthm g-of-nil-is-nil
+ (not (g a nil)))
+
+(defthm s-non-nil-cannot-be-nil
+ (implies v (s a v r))
+ :hints (("Goal"
+ :in-theory (disable rcd->acl2-of-record-non-nil)
+ :use (:instance rcd->acl2-of-record-non-nil
+ (r (s-aux a v (acl2->rcd r)))))))
+
+(defthm non-nil-if-g-non-nil
+ (implies (g a r) r)
+ :rule-classes :forward-chaining)
+
+(defthm equal-s-redux-1
+ (implies (equal (s a v1 r1) (s a v2 r2))
+ (equal (equal v1 v2) t))
+ :hints (("Goal"
+ :use ((:instance equal-s-aux-redux-1
+ (r1 (acl2->rcd r1))
+ (r2 (acl2->rcd r2))))
+ :in-theory (disable equal-s-aux-redux-1))))
+
+(defthm equal-s-redux-2
+ (implies (equal (s a v1 r1) (s a v2 r2))
+ (equal (equal (s a v r1) (s a v r2)) t)))
+
+;; Finally, we prove some "constructive" properties about records. In
+;; particular, we want to show the following property:
+;;
+;; (not (equal (g a x) x))
+;;
+;; unfortunately, the above is not true when x is NIL, and may not be true when
+;; a is NIL, so we will have a weaker form of the above property:
+;;
+;; (implies (and x a) (not (equal (g a x) x)))
+;;
+;; further, we would like to generalize this to any nesting of g(et)s Well,
+;; what we can show is the following property:
+;;
+;; (implies (and x a) (< (rcd-count (g a x)) (rcd-count x)))
+;;
+;; where rcd-count is a natural number measure function.
+
+(defun rcount-msr (r)
+ (cond ((null r) 0)
+ ((endp r) 1)
+ (t (+ 1
+ (rcount-msr (car r))
+ (rcount-msr (cdr r))))))
+
+(defun rcount (r)
+ (declare (xargs :measure (rcount-msr r)))
+ (if (null r) 0
+ (+ 1
+ (rcount (cdar r))
+ (rcount (cdr r)))))
+
+(defthm rcount-g-aux-<
+ (implies r
+ (< (rcount (g-aux a r))
+ (rcount r))))
+
+(defthm rcount-g-<
+ (implies (and x (wf-keyp a))
+ (< (rcount (g a x))
+ (rcount x)))
+ :hints (("Goal" :in-theory (enable acl2->rcd))))
+
+;; We disable s, g, and dom assuming the rules proven in this book are
+;; sufficient to manipulate record terms which are encountered.
+
+(in-theory (disable s g dom))
+
+;; in order to facilitate debugging of proofs which involve (equal (s .) (s .))
+;; terms, we include some additional definitions and rules in terms of s and g.
+
+(defun s-clr (a r) (s a nil r))
+
+(defthm equal-s-destruct
+ (equal (equal (s a v1 r1) (s a v2 r2))
+ (and (equal v1 v2)
+ (equal (s-clr a r1) (s-clr a r2)))))
+
+;; we no longer desire to have the parent theorems enabled
+(in-theory (disable equal-s-redux-1 equal-s-redux-2))
+
+(defthm g-same-s-clr
+ (equal (g a (s-clr a r))
+ nil))
+
+(defthm g-diff-s-clr
+ (implies (not (equal a b))
+ (equal (g a (s-clr b r))
+ (g a r))))
+
+(defthm s-same-s-clr
+ (equal (s-clr a (s a v r))
+ (s-clr a r)))
+
+(defthm s-diff-s-clr
+ (implies (not (equal a b))
+ (equal (s-clr b (s a v r))
+ (s a v (s-clr b r)))))
+
+(defthm dom-s-clr
+ (equal (dom (s-clr a r))
+ (sdrop a (dom r))))
+
+;; we add some rules for dealing with the case where records are collapsed as
+;; quoted constants. Some normalization may not occur in this case unless one
+;; "cleans" up the quoted constant records.
+
+(defun quoted-rcd-with-non-nil-field (a r)
+ (or (and (quotep r)
+ (g a (second r)))
+ (and (consp r)
+ (eq (first r) 's)
+ (quoted-rcd-with-non-nil-field a (fourth r)))))
+
+(defthm s-clean-up-rcd
+ (implies (syntaxp (and (quotep a)
+ (quoted-rcd-with-non-nil-field (second a) r)))
+ (equal (s a v r)
+ (s a v (s-clr a r)))))
+
+(in-theory (disable s-clr))
+
+;; equal-s-destruct may be too aggressive and possibly, the following rules are
+;; more appropriate candidates for use (maybe together):
+
+(defthm equal-s-key
+ (equal (equal (s a v1 r) (s a v2 r))
+ (equal v1 v2)))
+
+(defthm equal-s-rcd
+ (equal (equal (s a v r1) (s a v r2))
+ (equal (s-clr a r1) (s-clr a r2))))
+
+(in-theory (disable equal-s-destruct equal-s-key equal-s-rcd))
+
+;; we conclude with some useful macros for defining functions which recur
+;; through records (for functions of this ilk, use (xargs :measure (rmsr r)) on
+;; the record parameter)
+
+(defmacro rempty (r)
+ `(not (dom ,r)))
+
+(defmacro rcar (r)
+ `(scar (dom ,r)))
+
+(defmacro rcdr (r)
+ `(s-clr (rcar ,r) ,r))
+
+(defmacro rmsr (r)
+ `(card (dom ,r)))
+
+(in-theory (disable s g))
+
+(defun rts (n r)
+ (declare (xargs :guard (and (integerp n) (>= n 0)
+ (wf-rcdp r))))
+ (if (zp n) r
+ (let ((k (- (nfix (g :b r))
+ (nfix (g :b r)))))
+ (rts (1- n) (s :b (1+ k) r)))))
+
+(defun frts (n r)
+ (declare (xargs :guard (and (integerp n) (>= n 0)
+ (wf-rcdp r))))
+ (if (zp n) r
+ (let ((k (- (nfix (fg :b r))
+ (nfix (fg :b r)))))
+ (frts (1- n) (fs :b (1+ k) r)))))
+
+(defun arts (n r)
+ (declare (xargs :guard (and (integerp n) (>= n 0)
+ (alistp r))))
+ (if (zp n) r
+ (let ((k (nfix (cdr (assoc-eq :a r)))))
+ (arts (1- n) (acons :a (1+ k) r)))))
+
diff --git a/books/workshops/2004/sumners-ray/support/sets.lisp b/books/workshops/2004/sumners-ray/support/sets.lisp
new file mode 100644
index 0000000..951d261
--- /dev/null
+++ b/books/workshops/2004/sumners-ray/support/sets.lisp
@@ -0,0 +1,1220 @@
+;; sets.lisp
+
+(in-package "ACL2")
+
+(set-match-free-default :all)
+
+#|
+
+We define the common boolean operations (and a few other common useful notions)
+on sets canonicalized as ordered lists using Pete's total ordering of all ACL2
+objects. Further, the functions have been defined with a normalization of all
+ACL2 objects as appropriate sets (we define a 1-1 function which maps any ACL2
+object to a corresponding well-formed set) and using this normal (and its
+inverse), we can prove properties about normalized set operations which use
+equal-ity instead of set-equality and require no backtracking to relieve
+well-formed set hypotheses.
+
+EXPORTED logic functions:
+
+ (in e x) -- set membership predicate, is element e a member of set x
+ (subset x y) -- subset predicate, is set x a subset of set y
+ (isect x y) -- the set intersection of set x and set y
+ (unite x y) -- the set union of set x and set y
+ (sdiff x y) -- the set of elements in set x but not in set y
+ (card x) -- returns the number of objects in the set x
+ (s1 e) -- the singleton set consisting only of the element e
+ (scar x) -- the least (by <<) element in the set x, nil if x is empty
+ () -- NIL is unique representative value for empty set,
+ so use NULL or NOT to test a set for emptiness
+ (c1 x) -- test which returns true if x is a singleton set
+
+EXPORTED theorems provided at the end of this file.
+
+I have removed all of the subgoal hints except for those introduced by the
+macro defthm-ternary-sets. These subgoal hints are reasonable since they are
+introduced in the context of a provided induction scheme and they help speed
+the proofs through considerably by avoiding the problem in ACL2 of
+free-variable matching in the application of <<-transitive.
+
+|#
+
+(include-book "total-order")
+
+;; i needed to add the following forward-chaining rule to make better use
+;; of <<-trichotomy from the included order book.
+
+(local
+(defthm <<-trichotomy-forward-chain1
+ (implies (and (not (<< x y))
+ (not (equal x y)))
+ (<< y x))
+ :rule-classes :forward-chaining))
+
+(defun setp (x)
+ (or (null x)
+ (and (consp x)
+ (setp (rest x))
+ (or (null (rest x))
+ (<< (first x) (second x))))))
+
+(defun ifsp (x) ;; ill-formed setp
+ (or (not (setp x))
+ (and (consp x)
+ (null (cdr x))
+ (ifsp (car x)))))
+
+(defun norm->set (x)
+ (if (ifsp x) (list x) x))
+
+(defun set->norm (x)
+ (if (ifsp x) (first x) x))
+
+(defun in-aux (e x)
+ (and (not (endp x))
+ (or (equal e (first x))
+ (and (<< (first x) e)
+ (in-aux e (rest x))))))
+
+(defun in (e x)
+ (in-aux e (norm->set x)))
+
+(defun subset-aux (x y)
+ (or (endp x)
+ (and (not (endp y))
+ (cond ((equal (first x) (first y))
+ (subset-aux (rest x) (rest y)))
+ ((<< (first y) (first x))
+ (subset-aux x (rest y)))
+ (t nil)))))
+
+(defun subset (x y)
+ (subset-aux (norm->set x) (norm->set y)))
+
+(defun isect-aux (x y)
+ (declare (xargs :measure (+ (acl2-count x)
+ (acl2-count y))))
+ (cond ((endp x) ())
+ ((endp y) ())
+ ((equal (first x) (first y))
+ (cons (first x)
+ (isect-aux (rest x) (rest y))))
+ ((<< (first x) (first y))
+ (isect-aux (rest x) y))
+ (t
+ (isect-aux x (rest y)))))
+
+(defun isect (x y)
+ (set->norm (isect-aux (norm->set x) (norm->set y))))
+
+(defun unite-aux (x y)
+ (declare (xargs :measure (+ (acl2-count x)
+ (acl2-count y))))
+ (cond ((endp x) y)
+ ((endp y) x)
+ ((equal (first x) (first y))
+ (cons (first x)
+ (unite-aux (rest x) (rest y))))
+ ((<< (first x) (first y))
+ (cons (first x)
+ (unite-aux (rest x) y)))
+ (t
+ (cons (first y)
+ (unite-aux x (rest y))))))
+
+(defun unite (x y)
+ (set->norm (unite-aux (norm->set x) (norm->set y))))
+
+(defun sdiff-aux (x y)
+ (declare (xargs :measure (+ (acl2-count x)
+ (acl2-count y))))
+ (cond ((endp x) ())
+ ((endp y) x)
+ ((equal (first x) (first y))
+ (sdiff-aux (rest x) (rest y)))
+ ((<< (first x) (first y))
+ (cons (first x)
+ (sdiff-aux (rest x) y)))
+ (t
+ (sdiff-aux x (rest y)))))
+
+(defun sdiff (x y)
+ (set->norm (sdiff-aux (norm->set x) (norm->set y))))
+
+(defun s1 (e)
+ (set->norm (list e)))
+
+(defun card (x)
+ (len (norm->set x)))
+
+(defun scar (x)
+ (if (ifsp x) x (first x)))
+
+(defmacro empty-set ()
+ `())
+
+(defun c1 (x)
+ (let ((x (norm->set x))) (and (consp x) (not (cdr x)))))
+
+
+
+;;; some useful auxiliary macros which could be removed if
+;;; needed (e.g. if the names conflict with existing fns)
+
+(defmacro sadd (e x)
+ `(unite (s1 ,e) ,x))
+
+(defmacro sdrop (e x)
+ `(sdiff ,x (s1 ,e)))
+
+(defmacro scdr (x)
+ `(sdrop (scar ,x) ,x))
+
+(defmacro satom (x)
+ `(not ,x))
+
+(defmacro common (x y)
+ `(not (satom (isect ,x ,y))))
+
+
+;;;; properties of setp ;;;;
+
+(local
+(defthm setp-implies-true-listp
+ (implies (setp x)
+ (true-listp x))
+ :rule-classes (:forward-chaining
+ :rewrite)))
+
+
+;;;; properties of norm->set and set->norm ;;;;
+
+(local
+(defthm norm->set-set->norm-of-setp
+ (implies (setp x)
+ (equal (norm->set (set->norm x))
+ x))))
+
+(local
+(defthm norm->set-of-wf-setp
+ (implies (not (ifsp x))
+ (equal (norm->set x) x))))
+
+(local
+(defthm norm->set-of-if-setp
+ (implies (ifsp x)
+ (equal (norm->set x) (list x)))))
+
+(local
+(defthm norm->set-returns-setp
+ (setp (norm->set x))))
+
+(local
+(defthm norm->set-preserves-equality
+ (iff (equal (norm->set x) (norm->set y))
+ (equal x y))))
+
+(local
+(defthm set->norm-norm->set-inverse
+ (equal (set->norm (norm->set x)) x)))
+
+(local
+(defthm set->norm-nil-iff-passed-nil
+ (implies (setp x)
+ (iff (set->norm x) x))))
+
+(local
+(defthm norm->set-of-x-is-consp-or-not-x
+ (iff (consp (norm->set x)) x)
+ :rule-classes nil))
+
+(local
+(defthm norm->set-is-true-listp
+ (true-listp (norm->set x))
+ :rule-classes :type-prescription))
+
+(in-theory (disable set->norm norm->set))
+
+
+;;;; bounded properties ;;;;
+
+(local
+(defthm unite-aux-bounded-<<
+ (implies (and (<< a (first x))
+ (<< a (first y)))
+ (<< a (first (unite-aux x y))))))
+
+(local
+(defthm isect-aux-bounded-<<
+ (implies (and (or (<< a (first x))
+ (<< a (first y)))
+ (isect-aux x y))
+ (<< a (first (isect-aux x y))))))
+
+(local
+(defthm sdiff-aux-bounded-<<
+ (implies (and (setp x)
+ (<< a (first x))
+ (sdiff-aux x y))
+ (<< a (first (sdiff-aux x y))))))
+
+
+;;;; type-correctness properties ;;;;
+
+(local
+(defthm unite-aux-preserves-setp
+ (implies (and (setp x) (setp y))
+ (setp (unite-aux x y)))
+ :rule-classes ((:forward-chaining
+ :trigger-terms ((unite-aux x y)))
+ :rewrite)))
+
+(local
+(defthm isect-aux-preserves-setp
+ (implies (and (setp x) (setp y))
+ (setp (isect-aux x y)))
+ :rule-classes ((:forward-chaining
+ :trigger-terms ((isect-aux x y)))
+ :rewrite)))
+
+(local
+(defthm sdiff-aux-preserves-setp
+ (implies (setp x)
+ (setp (sdiff-aux x y)))
+ :rule-classes ((:forward-chaining
+ :trigger-terms ((sdiff-aux x y)))
+ :rewrite)))
+
+
+;;;; properties of membership-aux ;;;;
+
+(local
+(defthm in-aux-isect-aux-reduce
+ (equal (in-aux e (isect-aux x y))
+ (and (in-aux e x) (in-aux e y)))))
+
+(local
+(defthm in-aux-unite-aux-reduce
+ (equal (in-aux e (unite-aux x y))
+ (or (in-aux e x) (in-aux e y)))))
+
+(local
+(defthm in-aux-implies-bounded
+ (implies (and (setp x)
+ (<< a (first x)))
+ (not (in-aux a x)))))
+
+(local
+(defthm in-aux-sdiff-aux-reduce
+ (implies (setp x)
+ (equal (in-aux e (sdiff-aux x y))
+ (and (in-aux e x) (not (in-aux e y)))))))
+
+(local
+(defthm in-aux-subset-aux-transits
+ (implies (and (in-aux e x)
+ (subset-aux x y))
+ (in-aux e y))))
+
+
+;;;; ternary variable induction scheme and strategy ;;;;
+
+;; the following function defines an induction scheme used in theorems
+;; involving three free variables (like associativity proofs).
+
+(local
+(defun ternary-induct (x y z)
+ (declare (xargs :measure (+ (acl2-count x)
+ (acl2-count y)
+ (acl2-count z))))
+ (if (or (endp x)
+ (endp y)
+ (endp z))
+ ; The following was changed to avoid SBCL warning, "Asserted type NUMBER
+ ; conflicts with derived type (VALUES LIST &OPTIONAL)."
+ (list x y z)
+ (cond ((<< (first x) (first y))
+ (cond ((<< (first x) (first z))
+ (ternary-induct (rest x) y z))
+ ((equal (first x) (first z))
+ (ternary-induct (rest x) y (rest z)))
+ ((and (<< (first z) (first x))
+ (<< (first z) (first y)))
+ (ternary-induct x y (rest z)))))
+ ((equal (first x) (first y))
+ (cond ((<< (first x) (first z))
+ (ternary-induct (rest x) (rest y) z))
+ ((equal (first x) (first z))
+ (ternary-induct (rest x) (rest y) (rest z)))
+ ((<< (first z) (first x))
+ (ternary-induct x y (rest z)))))
+ ((<< (first y) (first x))
+ (cond ((<< (first y) (first z))
+ (ternary-induct x (rest y) z))
+ ((equal (first y) (first z))
+ (ternary-induct x (rest y) (rest z)))
+ ((and (<< (first z) (first y))
+ (<< (first z) (first x)))
+ (ternary-induct x y (rest z)))))))))
+
+;; the following macro defines an effective strategy for inducting based on the
+;; scheme ternary-induct.
+
+(defmacro defthm-ternary-sets (name body)
+ `(defthm ,name ,body
+ :hints (("Goal"
+ :induct (ternary-induct x y z)
+ :in-theory (disable <<-transitive))
+ ("Subgoal *1/13"
+ :in-theory (enable <<-transitive))
+ ("Subgoal *1/5"
+ :in-theory (enable <<-transitive)))))
+
+
+;;;; properties of subset-aux ;;;;
+
+(local
+(defthm unite-aux-x<y-expansion
+ (implies (and (consp x)
+ (consp y)
+ (<< (car x) (car y)))
+ (equal (unite-aux x y)
+ (cons (car x)
+ (unite-aux (cdr x) y))))))
+
+(local
+(defthm subset-aux-x<y-reduces-nil
+ (implies (and (consp x)
+ (consp y)
+ (<< (car x) (car y)))
+ (equal (subset-aux x y)
+ nil))))
+
+(local
+(defthm atom-unite-aux-implies-atom-params
+ (implies (not (consp (unite-aux x y)))
+ (and (not (consp x))
+ (not (consp y))))))
+
+(local
+(defthm-ternary-sets subset-aux-unite-aux-reduction
+ (equal (subset-aux (unite-aux x y) z)
+ (and (subset-aux x z)
+ (subset-aux y z)))))
+
+(local
+(in-theory (disable unite-aux-x<y-expansion)))
+
+(local
+(defthm subset-aux-is-reflexive
+ (subset-aux x x)))
+
+(local
+(defthm subset-aux-unite-aux-property
+ (implies (setp x)
+ (subset-aux x (unite-aux x y)))))
+
+(local
+(defthm <<-irreflexive-rewrite
+ (implies (<< x y)
+ (not (equal x y)))))
+
+(local
+(defthm-ternary-sets subset-aux-isect-aux-reduction
+ (equal (subset-aux x (isect-aux y z))
+ (and (subset-aux x y)
+ (subset-aux x z)))))
+
+(local
+(defthm subset-aux-isect-aux-property
+ (implies (setp x)
+ (subset-aux (isect-aux x y) x))))
+
+(local
+(defthm subset-aux-sdiff-aux-property
+ (implies (setp x)
+ (subset-aux (sdiff-aux x y) x))))
+
+(local
+(defthm-ternary-sets subset-aux-is-transitive
+ (implies (and (subset-aux x y)
+ (subset-aux y z))
+ (subset-aux x z))))
+
+(local
+(defthm subset-aux-is-total-on-sets
+ (implies (and (setp x) (setp y)
+ (subset-aux x y))
+ (equal (subset-aux y x)
+ (equal x y)))))
+
+(local
+(defthm subset-length-property
+ (implies (and (setp x)
+ (setp y)
+ (subset-aux x y))
+ (<= (len x) (len y)))))
+
+(local
+(defthm len<-reduce-when-subset
+ (implies (and (setp x)
+ (setp y)
+ (subset-aux x y))
+ (equal (< (len x) (len y))
+ (not (equal x y))))))
+
+
+;;;; properties of unite-aux ;;;;
+
+(local
+(defthm unite-aux-implied-by-and
+ (implies (and (setp x)
+ (setp y)
+ x y)
+ (unite-aux x y))))
+
+(local
+(defthm unite-aux-reflexes
+ (implies (setp x)
+ (equal (unite-aux x x) x))))
+
+(local
+(defthm unite-aux-commutes
+ (implies (and (setp x) (setp y))
+ (equal (unite-aux x y)
+ (unite-aux y x)))))
+
+(local
+(defthm unite-aux-x<y-expansion-flip
+ (implies (and (consp x)
+ (consp y)
+ (<< (car x) (car y)))
+ (equal (unite-aux y x)
+ (cons (car x)
+ (unite-aux y (cdr x)))))))
+
+(local
+(in-theory (enable unite-aux-x<y-expansion)))
+
+(local
+(defthm-ternary-sets unite-aux-associates
+ (implies (and (setp x) (setp y) (setp z))
+ (equal (unite-aux (unite-aux x y) z)
+ (unite-aux x (unite-aux y z))))))
+
+(local
+(in-theory (disable unite-aux-x<y-expansion-flip
+ unite-aux-x<y-expansion)))
+
+(local
+(defthm unite-aux-subset-aux-property
+ (equal (equal (unite-aux x y) y)
+ (subset-aux x y))))
+
+(local
+(defthm length-of-unite-aux-property
+ (implies (and (setp x) (setp y))
+ (equal (len (unite-aux x y))
+ (+ (len x)
+ (len (sdiff-aux y x)))))))
+
+(local
+(defthm set-norm-equality-transfer
+ (implies (setp x)
+ (equal (equal (set->norm x) y)
+ (equal x (norm->set y))))))
+
+
+;;;; properties of isect-aux ;;;;
+
+(local
+(defthm isect-aux-reflexes
+ (implies (setp x)
+ (equal (isect-aux x x) x))))
+
+(local
+(defthm isect-aux-commutes
+ (implies (and (setp x) (setp y))
+ (equal (isect-aux x y) (isect-aux y x)))))
+
+(local
+(defthm isect-aux-x<y-expansion
+ (implies (and (consp x)
+ (consp y)
+ (<< (car x) (car y)))
+ (equal (isect-aux y x)
+ (isect-aux y (cdr x))))))
+
+(local
+(defthm-ternary-sets isect-aux-associates
+ (implies (and (setp x) (setp y) (setp z))
+ (equal (isect-aux (isect-aux x y) z)
+ (isect-aux x (isect-aux y z))))))
+
+(local
+(in-theory (disable isect-aux-commutes
+ unite-aux-commutes)))
+
+(local
+(defthm isect-aux-bounded-then-not-equal
+ (implies (and (consp z)
+ (or (<< (car z) (car x))
+ (<< (car z) (car y))))
+ (not (equal (isect-aux x y) z)))))
+
+(local
+(defthm isect-aux-subset-aux-property
+ (implies (and (setp x) (setp y))
+ (equal (equal (isect-aux x y) x)
+ (subset-aux x y)))))
+
+(local
+(defthm <<-irreflexive-rewrite-flip
+ (implies (<< x y)
+ (not (equal y x)))))
+
+(local
+(defthm-ternary-sets isect-aux-unite-aux-distributes
+ (implies (and (setp x) (setp y) (setp z))
+ (equal (isect-aux (unite-aux x y) z)
+ (unite-aux (isect-aux x z)
+ (isect-aux y z))))))
+
+(local
+(defthm-ternary-sets isect-aux-sdiff-aux-distributes
+ (implies (and (setp x) (setp y) (setp z))
+ (equal (isect-aux (sdiff-aux x y) z)
+ (sdiff-aux (isect-aux x z) y)))))
+
+
+;;;; properties of sdiff-aux ;;;;
+
+(local
+(defthm sdiff-aux-subset-aux-property
+ (implies (and (setp x) (setp y))
+ (iff (sdiff-aux x y)
+ (not (subset-aux x y))))))
+
+(local
+(defthm length-of-sdiff-aux-property
+ (implies (and (setp x) (setp y))
+ (equal (len (sdiff-aux x y))
+ (- (len x)
+ (len (isect-aux x y)))))))
+
+(local
+(defthm-ternary-sets sdiff-aux-unite-aux-distributes
+ (implies (and (setp x) (setp y) (setp z))
+ (equal (sdiff-aux (unite-aux x y) z)
+ (unite-aux (sdiff-aux x z)
+ (sdiff-aux y z))))))
+
+(local
+(defthm-ternary-sets sdiff-aux-unite-aux-reduction
+ (implies (and (setp x) (setp y) (setp z))
+ (equal (sdiff-aux x (unite-aux y z))
+ (sdiff-aux (sdiff-aux x y) z)))))
+
+(local
+(defthm sdiff-aux-reduce-no-isect-aux
+ (implies (and (setp x) (setp y) (not (isect-aux x y)))
+ (equal (sdiff-aux x y) x))))
+
+
+;;;; properties of s1-aux -- i.e. list ;;;;
+
+(local
+(defthm subset-aux-reduces-to-membership
+ (implies (setp x)
+ (equal (subset-aux (list e) x)
+ (in-aux e x)))))
+
+(local
+(defthm subset-aux-of-singleton
+ (implies (and (setp x) x
+ (subset-aux x (list e)))
+ (equal (equal x (list e)) t))))
+
+(local
+(defthm isect-aux-of-singleton
+ (implies (setp x)
+ (equal (isect-aux (list e) x)
+ (if (in-aux e x) (list e) ())))))
+
+(local
+(defthm sdiff-aux-of-singleton
+ (implies (setp x)
+ (equal (sdiff-aux (list e) x)
+ (if (in-aux e x) () (list e))))))
+
+
+;;;; EXPORTED THEOREMS ;;;;
+;; Note, the order of the these theorems below is relevant for the
+;; order in which ACL2 applies them (later ones first). This is why
+;; the associativity and commutativity theorems are first since
+;; restructuring unite and isect can have the detrimental effect of
+;; disabling the application of other rules.
+
+(local
+(in-theory (enable unite-aux-commutes
+ isect-aux-commutes)))
+
+
+;;;; EXPORTED associative and commutative properties ;;;;
+
+(defthm unite-implied-by-and
+ (implies (and x y)
+ (unite x y)))
+
+(defthm unite-reflexes
+ (equal (unite x x) x))
+
+(defthm unite-commutes
+ (equal (unite x y)
+ (unite y x)))
+
+(defthm unite-associates
+ (equal (unite (unite x y) z)
+ (unite x (unite y z))))
+
+(defthm unite-associate-2
+ (equal (unite x (unite y z))
+ (unite y (unite x z)))
+ :hints (("Goal"
+ :in-theory (disable unite-commutes)
+ :use ((:instance unite-commutes
+ (x x) (y (unite y z)))
+ (:instance unite-commutes
+ (x x) (y z))))))
+
+(defthm isect-reflexes
+ (equal (isect x x) x))
+
+(defthm isect-commutes
+ (equal (isect x y)
+ (isect y x)))
+
+(defthm isect-associates
+ (equal (isect (isect x y) z)
+ (isect x (isect y z))))
+
+(defthm isect-associate-2
+ (equal (isect x (isect y z))
+ (isect y (isect x z)))
+ :hints (("Goal"
+ :in-theory (disable isect-commutes)
+ :use ((:instance isect-commutes
+ (x x) (y (isect y z)))
+ (:instance isect-commutes
+ (x x) (y z))))))
+
+;;;; EXPORTED properties of membership ;;;;
+
+(defthm in-isect-reduce
+ (equal (in e (isect x y))
+ (and (in e x) (in e y))))
+
+(defthm in-unite-reduce
+ (equal (in e (unite x y))
+ (or (in e x) (in e y))))
+
+(defthm in-sdiff-reduce
+ (equal (in e (sdiff x y))
+ (and (in e x) (not (in e y)))))
+
+(defthm in-subset-transits
+ (implies (and (in e x)
+ (subset x y))
+ (in e y)))
+
+
+;;;; EXPORTED properties of susbet ;;;;
+
+(defthm subset-unite-reduction
+ (equal (subset (unite x y) z)
+ (and (subset x z)
+ (subset y z))))
+
+(defthm subset-unite-property
+ (subset x (unite x y)))
+
+(defthm subset-isect-reduction
+ (equal (subset x (isect y z))
+ (and (subset x y)
+ (subset x z))))
+
+(defthm subset-isect-property
+ (subset (isect x y) x))
+
+(defthm subset-sdiff-property
+ (subset (sdiff x y) x))
+
+(defthm subset-is-reflexive
+ (subset x x))
+
+(defthm subset-is-transitive
+ (implies (and (subset x y)
+ (subset y z))
+ (subset x z)))
+
+(defthm subset-is-total-order
+ (implies (subset x y)
+ (equal (subset y x)
+ (equal x y))))
+
+(defthm subset-card-property
+ (implies (subset x y)
+ (<= (card x) (card y))))
+
+(defthm card<-reduce-when-subset
+ (implies (subset x y)
+ (equal (< (card x) (card y))
+ (not (equal x y)))))
+
+
+;;;; EXPORTED reductions of unite ;;;;
+
+(defthm unite-subset-property
+ (equal (equal (unite x y) y)
+ (subset x y)))
+
+(defthm unite-subset-property-2
+ (equal (equal (unite y x) y)
+ (subset x y)))
+
+(defthm unite-card-property
+ (equal (card (unite x y))
+ (+ (card x)
+ (card (sdiff y x)))))
+
+
+;;;; EXPORTED reductions of isect ;;;;
+
+(defthm isect-subset-property
+ (equal (equal (isect x y) x)
+ (subset x y)))
+
+(defthm isect-unite-distributes-1
+ (equal (isect (unite x y) z)
+ (unite (isect x z)
+ (isect y z))))
+
+(defthm isect-unite-distributes-2
+ (equal (isect z (unite x y))
+ (unite (isect x z)
+ (isect y z)))
+ :hints (("Goal" :in-theory (disable isect-aux-commutes)
+ :use (:instance isect-aux-commutes
+ (x (norm->set z))
+ (y (unite-aux (norm->set x)
+ (norm->set y)))))))
+
+(defthm isect-sdiff-distributes-1
+ (equal (isect (sdiff x y) z)
+ (sdiff (isect x z) y)))
+
+(defthm isect-sdiff-distributes-2
+ (equal (isect z (sdiff x y))
+ (sdiff (isect x z) y))
+ :hints (("Goal" :in-theory (disable isect-aux-commutes)
+ :use (:instance isect-aux-commutes
+ (x (norm->set z))
+ (y (sdiff-aux (norm->set x)
+ (norm->set y)))))))
+
+
+;;;; EXPORTED reductions of sdiff ;;;;
+
+(defthm sdiff-subset-property
+ (iff (sdiff x y)
+ (not (subset x y))))
+
+(defthm sdiff-card-property
+ (equal (card (sdiff x y))
+ (- (card x)
+ (card (isect x y)))))
+
+(defthm sdiff-unite-distributes
+ (equal (sdiff (unite x y) z)
+ (unite (sdiff x z)
+ (sdiff y z))))
+
+(defthm sdiff-unite-reduction
+ (equal (sdiff x (unite y z))
+ (sdiff (sdiff x y) z)))
+
+(defthm sdiff-reduce-no-isect
+ (implies (not (isect x y))
+ (equal (sdiff x y) x)))
+
+
+;;;; EXPORTED reductions of s1 ;;;;
+
+(defthm s1-membership-property
+ (equal (in a (s1 b))
+ (equal a b)))
+
+(defthm s1-subset-property-1
+ (equal (subset (s1 e) x)
+ (in e x)))
+
+(defthm s1-subset-property-2
+ (implies (and (subset x (s1 e)) x)
+ (equal x (s1 e)))
+ :hints (("Goal" :use
+ (:instance norm->set-of-x-is-consp-or-not-x)))
+ :rule-classes :forward-chaining)
+
+(defthm s1-isect-property-1
+ (equal (isect (s1 e) x)
+ (if (in e x) (s1 e) ())))
+
+(defthm s1-isect-property-2
+ (equal (isect x (s1 e))
+ (if (in e x) (s1 e) ()))
+ :hints (("Goal" :in-theory (disable isect-aux-commutes)
+ :use (:instance isect-aux-commutes
+ (x (norm->set x))
+ (y (list e))))))
+
+(defthm s1-sdiff-property
+ (equal (sdiff (s1 e) x)
+ (if (in e x) () (s1 e))))
+
+(defthm s1-card-property
+ (equal (card (s1 e)) 1))
+
+(defthm s1-iff-t (iff (s1 e) t))
+
+(defthm s1-equal-nil
+ (equal (equal (s1 e) nil) nil))
+
+(defthm subset-s1-redux
+ (equal (subset a (s1 e))
+ (if a (equal a (s1 e)) t)))
+
+
+
+;;;; EXPORTED properties of empty-set ;;;;
+
+(defthm membership-empty-set
+ (not (in e (empty-set))))
+
+(defthm empty-set-is-subset
+ (subset (empty-set) x))
+
+(defthm empty-set-is-only-superset-self
+ (equal (subset x (empty-set))
+ (not x)))
+
+(defthm unite-empty-set-property-1
+ (equal (unite x (empty-set)) x))
+
+(defthm unite-empty-set-property-2
+ (equal (unite (empty-set) x) x))
+
+(defthm isect-empty-set-property-1
+ (equal (isect (empty-set) x) (empty-set)))
+
+(defthm isect-empty-set-property-2
+ (equal (isect x (empty-set)) (empty-set)))
+
+(defthm sdiff-of-empty-set-1
+ (equal (sdiff (empty-set) x) (empty-set)))
+
+(defthm sdiff-of-empty-set-2
+ (equal (sdiff x (empty-set)) x))
+
+(defthm s1-is-not-empty-set
+ (s1 e)
+ :hints (("Goal" :in-theory (enable set->norm)))
+ :rule-classes :type-prescription)
+
+(defthm card-of-empty-set
+ (iff (not x)
+ (equal (card x) 0))
+ :hints (("Goal" :in-theory (enable norm->set)))
+ :rule-classes :type-prescription)
+
+
+;;;; EXPORTED properties of scar ;;;;
+
+(defthm scar-membership-property
+ (iff (in (scar x) x) x))
+
+(defthm scar-is-least-member
+ (implies (and (in e x)
+ (not (equal e (scar x))))
+ (<< (scar x) e)))
+
+(defthm scar-returns-nil-for-empty-set
+ (equal (scar (empty-set)) nil))
+
+(defthm scar-of-s1
+ (equal (scar (s1 e)) e)
+ :hints (("Goal" :in-theory (enable set->norm))))
+
+(defthm scar-of-unite
+ (implies (and x y)
+ (equal (scar (unite x y))
+ (if (<< (scar x) (scar y)) (scar x) (scar y))))
+ :hints (("Goal" :in-theory (enable norm->set set->norm))))
+
+(defthm scar-of-sdiff
+ (implies (<< (scar x) (scar y))
+ (equal (scar (sdiff x y)) (scar x)))
+ :hints (("Goal" :in-theory (enable norm->set set->norm))))
+
+
+;;;; EXPORTED properties of c1 ;;;;
+
+(defthm c1-of-s1
+ (equal (c1 (s1 e)) t))
+
+(defthm c1-of-nil
+ (equal (c1 ()) nil))
+
+(defthm c1-of-unite
+ (equal (c1 (unite x y))
+ (if (c1 x) (implies y (equal x y)) (and (not x) (c1 y))))
+ :hints (("Goal" :in-theory (enable norm->set set->norm)
+ :expand ((unite-aux (list x) y) (unite-aux x y)))))
+
+(defthm isect-aux-sdiff-aux-prop1
+ (implies (and (setp x) x
+ (not (isect-aux x y)))
+ (sdiff-aux x y)))
+
+(defthm isect-aux-sdiff-aux-prop2
+ (implies (and (consp x)
+ (setp x)
+ (not (isect-aux x y))
+ (not (cdr (sdiff-aux x y))))
+ (not (cdr x))))
+
+(defthm c1-of-sdiff
+ (implies (not (isect x y))
+ (equal (c1 (sdiff x y)) (c1 x)))
+ :hints (("Goal" :in-theory (enable norm->set set->norm)
+ :expand ((:free (x) (sdiff-aux (list x) y))
+ (:free (x z) (sdiff-aux (list x z) y))
+ (:free (x a b) (sdiff-aux (list* x a b) y))))))
+
+(defthm c1-not-sdiff
+ (implies (and (isect x y) (c1 x))
+ (not (sdiff x y)))
+ :hints (("Goal" :in-theory (enable norm->set set->norm)
+ :expand (:free (x) (sdiff-aux (list x) y)))))
+
+
+;; we now disable the top-level functions to keep their
+;; definitions from being expanded
+
+(in-theory (disable in subset isect unite sdiff card s1 scar c1))
+
+;; the following macro will enable/disable the executable-counterparts
+
+(defmacro ec-sets (x)
+ `(in-theory (,(if x 'enable 'disable)
+ (in) (subset) (isect) (unite)
+ (sdiff) (card) (s1) (scar) (c1))))
+
+;; we will begin with the executable-counterparts disabled
+
+(ec-sets nil)
+
+;; the following macro is a convenient way to define constants, it is similar
+;; to the 'list macro
+
+(defmacro make-set (&rest elems)
+ (if (endp elems) '(emptyset)
+ `(sadd ,(first elems) (make-set ,@(rest elems)))))
+
+
+
+;; we conclude with a few corollaries
+
+(defthm unite-iff-or
+ (iff (unite x y) (or x y))
+ :hints (("Goal" :cases ((not x) (not y)))))
+
+(defthm unite-x-absorption
+ (equal (unite x (unite x y)) (unite x y)))
+
+(defthm c1-of-sadd
+ (equal (c1 (sadd e x)) (if (c1 x) (equal x (s1 e)) (not x))))
+
+(defthm equal-s1-redux
+ (equal (equal (s1 a) (s1 b)) (equal a b))
+ :hints (("Goal" :in-theory (enable s1))))
+
+(defthm wrap-up-s1-equal-to-c1
+ (equal (equal (s1 (scar s)) s) (c1 s))
+ :hints (("Goal" :in-theory (enable s1 scar c1))))
+
+(defthm c1-in-redux-scar
+ (implies (c1 s) (equal (in e s) (equal e (scar s))))
+ :hints (("Goal" :in-theory (enable in c1 scar))))
+
+(local
+(defthm setp-cons-redux
+ (equal (setp (cons x y))
+ (and (setp y) (implies y (<< x (car y)))))))
+
+(defthm equal-sadd-s1-redux
+ (equal (equal (sadd e x) (s1 a))
+ (and (equal e a) (implies x (equal x (s1 e)))))
+ :hints (("Goal" :in-theory (enable s1 unite norm->set set->norm)
+ :expand ((unite-aux (list e) x)))))
+
+
+
+
+#|
+
+
+
+> I propose the following additions to the sets book:
+>
+> (defthm sdiff-x-x
+> (equal (sdiff x x)
+> (empty-set)))
+
+The following rule subsumes yours and I think would be
+a better addition:
+
+(defthm sdiff-superset
+ (implies (subset x y)
+ (equal (sdiff x y)
+ (empty-set))))
+
+> ;(add similar lemmas about other functions than unite
+> (e.g., isect)?
+> (defthm unite-reflexes-2
+> (equal (unite x (unite x y))
+> (unite x y)))
+>
+> ;and can you prove this one for me?
+> (defthm sdiff-sdiff
+> (equal (sdiff (sdiff x y) y)
+> (sdiff x y))
+> )
+
+absorption rules for unite, isect, and sdiff (on the right)
+would be good. I have no idea why I had not considered adding
+these before. I will probably generalize them to have subset
+hypothesis.
+
+> BTW, what's the status of the sets book? Will it be
+> released with ACL2?
+
+It is in one of the workshops, although I am uncertain if it
+is updated. I will probably get Matt to add it to the misc
+directory (especially with some of the recent additions to
+the records book which make use of the sets book).
+
+> I also need:
+>
+> (defthm unite-sdiff-hack
+> (equal (unite x (sdiff y x))
+> (unite x y)))
+
+Hmmm. I am uncertain if this is a proper reduction. Intuitively,
+while the lhs is a bigger term, it is smaller in terms of
+cardinality. I will need to think about this case, but offhand,
+I don't see this as an obviously good addition to the sets book.
+
+> (BTW, I'm assuming its okay to ask you to prove these
+> since they'd make good additions to the sets book,
+> which you are developing. If you'd rather not be
+> bothered with this, let me know.)
+
+Please feel free to make suggestions (just don't expect that I
+will always be quick in handling the suggestions). I like using
+the sets book and would like to see others use it as well. (I am
+generally an advocate of having books with rewrite rules which
+are "context-free" -- well as context-free as possible).
+
+ -Rob
+
+
+> i talked with Matt (the other "old-timer") and we
+> are
+> in tacit agreement that we should change
+> "records.lisp"
+> to "maps.lisp" (the new version with all of the
+> various
+> improvements and which includes the sets book). But,
+> I want to wait ask about this at the next ACL2
+> meeting
+> to get an idea of how many people (if any) are using
+> the
+> records book.
+
+Excellent.
+
+My sense is that people aren't using the records/maps
+book enough (and that, in general, people don't
+appreciate the importance of the tricks done to make
+the records book clean). Did anyone ever give a talk
+on records/maps at the ACL2 seminar?
+
+I'm changing my copy of the "M5" JVM model to use
+records, and I think this is clearly the way to go.
+(There are some subtleties, but I now have a fairly
+clean algebra for the heap.) If J's folks keep
+hearing about this from enough people, maybe they'll
+use records for M6. Hanbing seems to be in charge of
+M6.
+
+> > BTW, are there easy proofs for either of the
+> following
+> > (which I've left as axioms in order to get on with
+> my
+> > JVM proofs)? I'm not terribly familiar with the
+> sets
+> > book, and I didn't find an easy proof for these.
+> >
+> > (defaxiom sdiff-sdiff
+> > (equal (ACL2::SDIFF (ACL2::SDIFF Z X) X)
+> > (ACL2::SDIFF Z X)))
+> >
+> > (defaxiom unite-hack
+> > (equal (acl2::unite x (acl2::sdiff z x))
+> > (acl2::unite x z)))
+>
+> I believe these are provable, but not easily proven
+> in
+> terms of the existing rules.
+>
+> I am planning on doing some work with the records (I
+> mean
+> "maps") and sets books this weekend. The updates
+> should
+> cover these theorems (and many others). I will send
+> them
+> to you on Monday.
+
+That would be great! Thanks. I've been spending a
+lot of time making changes to M5 and thinking about
+sets, maps, and other implementation details, instead
+of actually doing the proofs I'm supposed to be doing
+(about java.util.linkedlist). Even so, Dill seems
+satisfied with my progress. Once we get the JVM model
+(and the sets and maps books) stabilized, I should be
+much more productive and should be able to totally
+impress him.
+
+Thanks,
+-Eric
+
+
+__________________________________________________
+Do you Yahoo!?
+Yahoo! Tax Center - forms, calculators, tips, more
+http://taxes.yahoo.com/
+
+
+
+
+|#
diff --git a/books/workshops/2004/sumners-ray/support/total-order.lisp b/books/workshops/2004/sumners-ray/support/total-order.lisp
new file mode 100644
index 0000000..519325a
--- /dev/null
+++ b/books/workshops/2004/sumners-ray/support/total-order.lisp
@@ -0,0 +1,30 @@
+;; total-order.lisp
+
+(in-package "ACL2")
+
+(defun << (x y)
+ (and (lexorder x y)
+ (not (equal x y))))
+
+(defthm <<-irreflexive
+ (not (<< x x)))
+
+(defthm <<-transitive
+ (implies (and (<< x y)
+ (<< y z))
+ (<< x z)))
+
+(defthm <<-asymmetric
+ (implies (<< x y)
+ (not (<< y x))))
+
+(defthm <<-trichotomy
+ (implies (and (not (<< y x))
+ (not (equal x y)))
+ (<< x y)))
+
+(defthm <<-implies-lexorder
+ (implies (<< x y)
+ (lexorder x y)))
+
+(in-theory (disable <<))