; lists-defthms.lisp -- theorems about functions in the theory of lists ; Copyright (C) 1997 Computational Logic, Inc. ; This book is free software; you can redistribute it and/or modify ; it under the terms of the GNU General Public License as published by ; the Free Software Foundation; either version 2 of the License, or ; (at your option) any later version. ; This book is distributed in the hope that it will be useful, ; but WITHOUT ANY WARRANTY; without even the implied warranty of ; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ; GNU General Public License for more details. ; You should have received a copy of the GNU General Public License ; along with this book; if not, write to the Free Software ; Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. ; Written by: Bill Bevier (bevier@cli.com) ; Computational Logic, Inc. ; 1717 West Sixth Street, Suite 290 ; Austin, TX 78703-4776 U.S.A. (in-package "ACL2") (include-book "list-defuns") ;; We need this much arithmetic to get some of the following ;; theorems proved, e.g., put-seg-non-recursive, len-nthcdr. (local (include-book "../arithmetic/equalities")) ; ------------------------------------------------------------ ; Equality Trichotomy ; ------------------------------------------------------------ ; Rewrite the EQL and EQ versions of various functions to ; the EQUAL version. This way, we can build one set of rules about ; the EQUAL functions. (defthm member->member-equal (equal (member x l) (member-equal x l))) (defthm member-eq->member-equal (equal (member-eq x l) (member-equal x l))) (defthm remove->remove-equal (equal (remove x l) (remove-equal x l))) (defthm remove-eq->remove-equal (equal (remove-eq x l) (remove-equal x l))) (defthm remove-duplicates-eql->remove-duplicates-equal (equal (remove-duplicates-eql l) (remove-duplicates-equal l))) (defthm remove-duplicates->remove-duplicates-equal (implies (true-listp l) (equal (remove-duplicates l) (remove-duplicates-equal l)))) (defthm remove-duplicates-eq->remove-duplicates-equal (equal (remove-duplicates-eq l) (remove-duplicates-equal l))) (defthm initial-sublistp->initial-sublistp-equal (equal (initial-sublistp a b) (initial-sublistp-equal a b))) (defthm initial-sublistp-eq->initial-sublistp-equal (equal (initial-sublistp-eq a b) (initial-sublistp-equal a b))) (defthm memberp->memberp-equal (equal (memberp x l) (memberp-equal x l))) (defthm memberp-eq->memberp-equal (equal (memberp-eq x l) (memberp-equal x l))) (defthm no-duplicatesp->no-duplicatesp-equal (iff (no-duplicatesp l) (no-duplicatesp-equal l))) (defthm no-duplicatesp-eq->no-duplicatesp-equal (iff (no-duplicatesp-eq l) (no-duplicatesp-equal l))) (local (defthm occurrences-ac->occurrences-equal-ac (equal (occurrences-ac x l ac) (occurrences-equal-ac x l ac)))) (defthm occurrences->occurrences-equal (equal (occurrences x l) (occurrences-equal x l))) (local (defthm occurrences-eq-ac->occurrences-equal-ac (equal (occurrences-eq-ac x l ac) (occurrences-equal-ac x l ac)))) (defthm occurrences-eq->occurrences-equal (equal (occurrences-eq x l) (occurrences-equal x l))) (local (defthm position-ac->position-equal-ac (equal (position-ac x l ac) (position-equal-ac x l ac)))) (defthm position->position-equal (equal (position x l) (position-equal x l))) (local (defthm position-eq-ac->position-equal-ac (equal (position-eq-ac x l ac) (position-equal-ac x l ac)))) (defthm position-eq->position-equal (implies (true-listp l) (equal (position-eq x l) (position-equal x l)))) ; ------------------------------------------------------------ ; CONSP type prescription and rewrite lemmas ; ------------------------------------------------------------ (defthm consp-append (equal (consp (append a b)) (or (consp a) (consp b))) :rule-classes ((:rewrite) (:type-prescription :corollary (implies (consp a) (consp (append a b)))) (:type-prescription :corollary (implies (consp b) (consp (append a b)))))) (defthm consp-revappend (equal (consp (revappend a b)) (or (consp a) (consp b))) :rule-classes ((:rewrite) (:type-prescription :corollary (implies (consp a) (consp (revappend a b)))) (:type-prescription :corollary (implies (consp b) (consp (revappend a b)))))) (defthm consp-reverse (equal (consp (reverse a)) (consp a)) :rule-classes ((:rewrite) (:type-prescription :corollary (implies (consp a) (consp (reverse a)))))) (local (defthm consp-first-n-ac (equal (consp (first-n-ac i l ac)) (if (zp i) (consp ac) t)) :rule-classes ((:rewrite) (:type-prescription :corollary (implies (or (not (zp i)) (consp ac)) (consp (first-n-ac i l ac))))) :hints (("Goal" :induct (first-n-ac i l ac))))) (local (defthm consp-take (equal (consp (take n l)) (not (zp n))) :rule-classes ((:rewrite) (:type-prescription :corollary (implies (not (zp n)) (consp (take n l))))) :hints (("Goal" :do-not-induct t)))) (defthm consp-butlast (equal (consp (butlast lst n)) (not (zp (- (len lst) n)))) :rule-classes ((:rewrite) (:type-prescription :corollary (implies (not (zp (- (len lst) n))) (consp (butlast lst n))))) :hints (("Goal" :do-not-induct t))) (defthm consp-firstn (equal (consp (firstn n l)) (and (not (zp n)) (consp l))) :hints (("Goal" :expand (firstn n l))) :rule-classes ((:rewrite) (:type-prescription :corollary (implies (and (not (zp n)) (consp l)) (consp (firstn n l)))))) (defthm consp-last (equal (consp (last l)) (consp l)) :rule-classes ((:rewrite) (:type-prescription :corollary (implies (consp l) (consp (last l)))))) (defthm consp-make-list-ac (equal (consp (make-list-ac n val ac)) (or (not (zp n)) (consp ac))) :hints (("Goal" :expand (make-list-ac n val ac))) :rule-classes ((:rewrite) (:type-prescription :corollary (implies (and (not (zp n)) (consp ac)) (consp (make-list-ac n val ac)))))) (defthm consp-member-equal (or (consp (member-equal x l)) (equal (member-equal x l) nil)) :rule-classes ((:type-prescription) (:rewrite :corollary (iff (not (consp (member-equal x l))) (equal (member-equal x l) nil))))) (local (defthm nthcdr-nil (implies (and (integerp n) (<= 0 n)) (not (nthcdr n nil))))) (defthm consp-nthcdr (iff (consp (nthcdr n l)) (< (nfix n) (len l))) :rule-classes ((:rewrite) (:type-prescription :corollary (implies (< (nfix n) (len l)) (consp (nthcdr n l)))))) (defthm consp-nth-seg (implies (<= (+ i j) (len l)) (equal (consp (nth-seg i j l)) (and (consp l) (not (zp j))))) :rule-classes ((:rewrite) (:type-prescription :corollary (implies (and (consp l) (not (zp j)) (<= (+ i j) (len l))) (consp (nth-seg i j l)))))) (defthm consp-put-nth (equal (consp (put-nth n v l)) (consp l)) :rule-classes ((:rewrite) (:type-prescription :corollary (implies (consp l) (consp (put-nth n v l)))))) (defthm consp-put-seg (equal (consp (put-seg i seg l)) (consp l)) :rule-classes ((:rewrite) (:type-prescription :corollary (implies (consp l) (consp (put-seg i seg l)))))) (defthm consp-subseq (implies (and (true-listp list) (integerp start) (<= 0 start) (or (null end) (and (integerp end) (<= 0 end)))) (iff (consp (subseq list start end)) (< start (if (null end) (len list) end)))) :hints (("Goal" :do-not-induct t :in-theory (disable take)))) ;; UPDATE-NTH is always a CONS ; ------------------------------------------------------------ ; TRUE-LISTP type prescription and rewrite rules ; ------------------------------------------------------------ (defthm true-listp-append (equal (true-listp (append a b)) (true-listp b)) :rule-classes ((:rewrite) (:type-prescription :corollary (implies (true-listp b) (true-listp (append a b)))))) (defthm true-listp-revappend (equal (true-listp (revappend a b)) (true-listp b)) :rule-classes ((:rewrite) (:type-prescription :corollary (implies (true-listp b) (true-listp (revappend a b)))))) (defthm true-listp-reverse (implies (listp a) (true-listp (reverse a))) :rule-classes (:type-prescription)) (local (defthm true-listp-first-n-ac (implies (true-listp ac) (true-listp (first-n-ac i l ac))) :rule-classes (:rewrite :type-prescription) :hints (("Goal" :induct (first-n-ac i l ac))))) (local (defthm true-listp-take (true-listp (take n l)) :rule-classes (:rewrite :type-prescription))) (defthm true-listp-butlast (true-listp (butlast lst n)) :rule-classes (:rewrite :type-prescription)) ; FIRSTN is always a true list (defthm true-listp-last (equal (true-listp (last l)) (true-listp l)) :rule-classes ((:rewrite) (:type-prescription :corollary (implies (true-listp l) (true-listp (last l)))))) (defthm true-listp-make-list-ac (equal (true-listp (make-list-ac n val ac)) (true-listp ac)) :rule-classes ((:rewrite) (:type-prescription :corollary (implies (true-listp ac) (true-listp (make-list-ac n val ac)))))) (defthm true-listp-member-equal (implies (true-listp l) (true-listp (member-equal x l))) :rule-classes (:rewrite :type-prescription)) (defthm true-listp-nthcdr (implies (true-listp l) (true-listp (nthcdr n l))) :hints (("Goal" :induct (nthcdr n l))) :rule-classes (:rewrite :type-prescription)) (defthm true-listp-put-nth (implies (true-listp l) (true-listp (put-nth n v l))) :rule-classes (:rewrite :type-prescription)) (defthm true-listp-put-seg (implies (true-listp l) (true-listp (put-seg i seg l))) :rule-classes (:rewrite :type-prescription)) (local (defthm true-listp-subseq-list (true-listp (subseq-list lst start end)) :hints (("Goal" :do-not-induct t :in-theory (disable take))) :rule-classes (:rewrite :type-prescription))) (defthm true-listp-subseq (implies (true-listp seq) (true-listp (subseq seq start end))) :hints (("Goal" :do-not-induct t :in-theory (disable subseq-list))) :rule-classes (:rewrite :type-prescription)) ;; true-listp-update-nth already exists ; ------------------------------------------------------------ ; NATURALP type prescription rules ; ------------------------------------------------------------ (local (defthm naturalp-occurrences-equal-ac (implies (and (integerp acc) (<= 0 acc)) (and (integerp (occurrences-equal-ac item lst acc)) (<= 0 (occurrences-equal-ac item lst acc)))))) (defthm naturalp-occurrences-equal (and (integerp (occurrences-equal item lst)) (<= 0 (occurrences-equal item lst))) :rule-classes (:rewrite :type-prescription)) (local (defthm naturalp-position-equal-ac (implies (and (integerp acc) (<= 0 acc) (member-equal item lst)) (and (integerp (position-equal-ac item lst acc)) (<= 0 (position-equal-ac item lst acc)))))) (defthm naturalp-position-equal (implies (member-equal item lst) (and (integerp (position-equal item lst)) (<= 0 (position-equal item lst)))) :rule-classes (:rewrite :type-prescription)) ; ------------------------------------------------------------ ; Some support lemmas ; We use these lemmas to define non-recursive forms for some ; recursive functions. These non-recursive forms are easier to ; reason about at times. ; ; ------------------------------------------------------------ (local (defthm nth-seg-non-recursive (equal (nth-seg i j l) (firstn j (nthcdr i l))))) (local (defthm put-seg-non-recursive (implies (and (true-listp l) (integerp i) (>= i 0)) (equal (put-seg i seg l) (append (firstn i l) (firstn (nfix (- (len l) i)) seg) (nthcdr (+ i (min (nfix (- (len l) i)) (len seg))) l)))) :hints (("Goal" :induct (put-seg i seg l))))) (local (in-theory (disable nth-seg-non-recursive put-seg-non-recursive))) ; ------------------------------------------------------------ ; LEN ; ------------------------------------------------------------ (defthm positive-len-fwd-to-consp (implies (< 0 (len l)) (consp l)) :rule-classes :forward-chaining) (defthm len-append (equal (len (append a b)) (+ (len a) (len b)))) (defthm len-revappend (equal (len (revappend a b)) (+ (len a) (len b)))) (defthm len-reverse (equal (len (reverse a)) (len a))) (local (defthm len-first-n-ac (equal (len (first-n-ac n l ac)) (+ (nfix n) (len ac))) :hints (("Goal" :induct (first-n-ac n l ac))))) (local (defthm len-take (equal (len (take n l)) (nfix n)))) (defthm len-butlast (implies (and (integerp n) (<= 0 n)) (equal (len (butlast lst n)) (if (<= (len lst) n) 0 (- (len lst) n)))) :hints (("Goal" :do-not-induct t :in-theory (disable take)))) (defthm len-firstn (equal (len (firstn n l)) (if (<= (nfix n) (len l)) (nfix n) (len l))) :hints (("Goal" :induct (firstn n l)))) (defthm len-last (equal (len (last l)) (if (consp l) 1 0)) :hints (("Goal" :induct (last l)))) (defthm len-make-list-ac (equal (len (make-list-ac n val ac)) (+ (nfix n) (len ac))) :hints (("Goal" :induct (make-list-ac n val ac)))) (defthm len-member-equal (not (< (len l) (len (member-equal x l)))) :rule-classes (:rewrite :linear)) (defthm len-nthcdr (equal (len (nthcdr n l)) (if (<= (nfix n) (len l)) (- (len l) (nfix n)) 0)) :hints (("Goal" :induct (nthcdr n l)))) (defthm len-nth-seg (implies (<= (+ i j) (len l)) (equal (len (nth-seg i j l)) (min (nfix j) (max (- (len l) (nfix i)) 0)))) :hints (("Goal" :do-not-induct t :in-theory (union-theories (set-difference-theories (current-theory :here) '((:definition nth-seg))) '(nth-seg-non-recursive))))) (defthm len-put-nth (equal (len (put-nth n v l)) (len l))) (defthm len-put-seg (implies (and (true-listp l) (integerp i) (not (< i 0))) (equal (len (put-seg i seg l)) (len l))) :hints (("Goal" :do-not-induct t :in-theory (union-theories (set-difference-theories (current-theory :here) '((:definition put-seg))) '(put-seg-non-recursive))))) (local (defthm occurrences-equal-ac+1 (implies (acl2-numberp ac) (equal (occurrences-equal-ac x l (+ 1 ac)) (+ 1 (occurrences-equal-ac x l ac)))))) (local (in-theory (disable occurrences-equal-ac+1))) (local (defthm len-remove-equal-ac (implies (acl2-numberp ac) (equal (len (remove-equal x l)) (+ ac (- (len l) (occurrences-equal-ac x l ac))))) :rule-classes nil :hints (("Goal" :induct (remove-equal x l) :in-theory (enable occurrences-equal-ac+1)) ("Subgoal *1/2'''" :expand ((OCCURRENCES-EQUAL-AC L1 (CONS L1 L2) AC)))))) (defthm len-remove-equal (equal (len (remove-equal x l)) (- (len l) (occurrences-equal x l))) :hints (("Goal" :do-not-induct t :use ((:instance len-remove-equal-ac (ac 0)))))) (defthm len-subseq (implies (and (true-listp l) (integerp start) (<= 0 start) (or (and (integerp end) (<= start end)) (null end))) (equal (len (subseq l start end)) (if (null end) (len (nthcdr start l)) (- (Nfix end) (nfix start))))) :hints (("Goal" :do-not-induct t :in-theory (disable take)))) (defthm len-update-nth1 (equal (len (update-nth n val l)) (if (< (nfix n) (len l)) (len l) (+ 1 (nfix n)))) :hints (("Goal" :induct (update-nth n val l)))) ; ------------------------------------------------------------ ; LEN inequalities ; ------------------------------------------------------------ (local (defthm leq-occurrences-equal-ac-len (implies (acl2-numberp ac) (not (< (+ (len l) ac) (occurrences-equal-ac x l ac)))) :rule-classes nil)) (defthm leq-occurrences-equal-len (not (< (len l) (occurrences-equal x l))) :rule-classes (:rewrite :linear) :hints (("Goal" :do-not-induct t :use ((:instance leq-occurrences-equal-ac-len (ac 0)))))) (local (defthm leq-position-equal-ac-len (implies (and (acl2-numberp ac) (member-equal x l)) (not (< (+ (len l) ac) (position-equal-ac x l ac)))) :rule-classes nil)) (defthm leq-position-equal-len (implies (member-equal x l) (not (< (len l) (position-equal x l)))) :rule-classes (:rewrite :linear) :hints (("Goal" :do-not-induct t :use ((:instance leq-position-equal-ac-len (ac 0)))))) ; ------------------------------------------------------------ ; APPEND facts ; ------------------------------------------------------------ ; The normal rewriting strategy is to pull APPEND outside of other ; list operations. So we don't have many rules for dealing with other ; operations are args to append. (defthm append-right-id (implies (true-listp a) (equal (append a nil) a))) (defthm associativity-of-append (equal (append (append a b) c) (append a (append b c)))) (defthm append-firstn-nthcdr (implies (true-listp l) (equal (append (firstn n l) (nthcdr n l)) l))) ; ------------------------------------------------------------ ; REVAPPEND, REVERSE ; ------------------------------------------------------------ (defthm revappend-binary-append (equal (revappend (binary-append a b) c) (revappend b (revappend a c)))) (defthm binary-append-revappend (equal (binary-append (revappend a b) c) (revappend a (binary-append b c)))) (defthm reverse-append (implies (and (listp a) (listp b)) (equal (reverse (append a b)) (append (reverse b) (reverse a)))) :hints (("Goal" :do-not-induct t))) (defthm revappend-revappend (equal (revappend (revappend a b) c) (revappend b (binary-append a c)))) (defthm reverse-reverse (implies (true-listp l) (equal (reverse (reverse l)) l)) :hints (("Goal" :do-not-induct t))) ; ------------------------------------------------------------ ; BUTLAST ; ------------------------------------------------------------ (local (defthm first-n-ac-len (implies (and (true-listp ac) (true-listp l) (eql (len l) n)) (equal (first-n-ac n l ac) (revappend ac l))) :hints (("Goal" :induct t)))) (local (defthm take-len (implies (true-listp l) (equal (take (len l) l) l)))) (local (defthm first-n-ac-append1 (implies (<= n (len a)) (equal (first-n-ac n (append a b) ac) (first-n-ac n a ac))) :hints (("Goal" :induct (first-n-ac n a ac)))) ) (local (defthm take-append1 (implies (<= n (len a)) (equal (take n (append a b)) (take n a))) :hints (("Goal" :do-not-induct t)))) (defthm butlast-append1-crock (IMPLIES (and (TRUE-LISTP A) (<= (+ (LEN A) i) i)) (EQUAL NIL A)) :rule-classes nil) (defthm butlast-append1 (implies (and (true-listp a) (true-listp b)) (equal (butlast (append a b) (len b)) a)) :hints (("Goal" :do-not-induct t :use ((:instance butlast-append1-crock (i (len b)))) :in-theory (disable take)))) ; ------------------------------------------------------------ ; FIRSTN ; ------------------------------------------------------------ (defthm firstn-with-large-index (implies (and (<= (len l) (nfix n)) (true-listp l)) (equal (firstn n l) l))) (defthm firstn-append (equal (firstn n (append a b)) (if (<= (nfix n) (len a)) (firstn n a) (append a (firstn (- n (len a)) b))))) (defthm firstn-firstn (equal (firstn i (firstn j l)) (if (< (nfix i) (nfix j)) (firstn i l) (firstn j l)))) (defthm firstn-make-list-ac (equal (firstn i (make-list-ac j v ac)) (if (< (nfix i) (nfix j)) (make-list-ac i v nil) (make-list-ac j v (firstn (- i (nfix j)) ac))))) (local (defthm firstn-cons (equal (firstn n (cons a l)) (if (zp n) nil (cons a (firstn (1- n) l)))))) (defthm firstn-put-nth (equal (firstn i (put-nth j v l)) (if (<= (nfix i) (nfix j)) (firstn i l) (put-nth j v (firstn i l)))) :rule-classes ((:rewrite :corollary (implies (<= (nfix i) (nfix j)) (equal (firstn i (put-nth j v l)) (firstn i l)))))) ; ------------------------------------------------------------ ; MEMBER ; ------------------------------------------------------------ (defthm member-equal-append (iff (member-equal x (append a b)) (or (member-equal x a) (member-equal x b)))) (defthm member-equal-make-list-ac-instance (implies (not (zp n)) (member-equal x (make-list-ac n x ac))) :hints (("Goal" :induct (make-list-ac n x ac)))) (defthm consp-member-equal-make-list-ac (implies (not (zp n)) (consp (member-equal x (make-list-ac n x ac)))) :hints (("Goal" :induct (make-list-ac n x ac)))) (defthm member-equal-make-list-ac (implies (not (member-equal x ac)) (iff (member-equal x (make-list-ac n y ac)) (and (not (zp n)) (equal x y))))) (defthm member-equal-car-last (implies (consp l) (member-equal (car (last l)) l))) (defthm member-equal-nth (implies (< (nfix n) (len l)) (member-equal (nth n l) l)) :hints (("Goal" :in-theory (enable nth)))) (defthm member-equal-put-nth (implies (< (nfix n) (len l)) (member-equal x (put-nth n x l)))) (defthm consp-member-equal-remove-equal (iff (consp (member-equal x (remove-equal y l))) (if (equal x y) nil (consp (member-equal x l)))) :hints (("Goal" :induct (remove-equal y l)))) (defthm member-equal-remove-equal (iff (member-equal x (remove-equal y l)) (if (equal x y) nil (member-equal x l)))) (defthm consp-member-equal-remove-duplicates-equal (iff (consp(member-equal x (remove-duplicates-equal l))) (consp(member-equal x l))) :hints (("Goal" :induct (remove-duplicates-equal l)))) (defthm member-equal-remove-duplicates-equal (iff (member-equal x (remove-duplicates-equal l)) (member-equal x l))) (defthm member-equal-revappend (iff (member-equal x (revappend a b)) (or (member-equal x a) (member-equal x b))) :hints (("Goal" :induct (revappend a b)))) (defthm member-equal-reverse (iff (member-equal x (reverse l)) (member-equal x l))) (defthm member-equal-update-nth (member-equal x (update-nth n x l))) ; ------------------------------------------------------------ ; MEMBERP ; ------------------------------------------------------------ (defthm memberp-equal-append (iff (memberp-equal x (append a b)) (or (memberp-equal x a) (memberp-equal x b)))) (defthm memberp-equal-make-list-ac (implies (not (memberp-equal x ac)) (iff (memberp-equal x (make-list-ac n y ac)) (and (not (zp n)) (equal x y))))) (defthm memberp-equal-car-last (implies (consp l) (memberp-equal (car (last l)) l))) (defthm memberp-equal-nth (implies (< (nfix n) (len l)) (memberp-equal (nth n l) l)) :hints (("Goal" :in-theory (enable nth)))) (defthm memberp-equal-put-nth (implies (< (nfix n) (len l)) (memberp-equal x (put-nth n x l)))) (defthm memberp-equal-remove-equal (iff (memberp-equal x (remove-equal y l)) (if (equal x y) nil (memberp-equal x l)))) (defthm memberp-equal-remove-duplicates-equal (iff (memberp-equal x (remove-duplicates-equal l)) (memberp-equal x l))) (defthm memberp-equal-revappend (iff (memberp-equal x (revappend a b)) (or (memberp-equal x a) (memberp-equal x b))) :hints (("Goal" :induct (revappend a b)))) (defthm consp-member-equal-revappend (iff (consp (member-equal x (revappend a b))) (or (consp (member-equal x a)) (consp (member-equal x b)))) :hints (("Goal" :induct (revappend a b)))) (defthm memberp-equal-reverse (iff (memberp-equal x (reverse l)) (memberp-equal x l)) :hints (("Goal" :do-not-induct t))) (defthm memberp-equal-update-nth (memberp-equal x (update-nth n x l))) ; ------------------------------------------------------------ ; INITIAL-SUBLISTP-EQUAL ; ------------------------------------------------------------ (defthm initial-sublistp-equal-reflexive (implies (true-listp l) (initial-sublistp-equal l l))) (defthm initial-sublistp-equal-nil (implies (true-listp l) (initial-sublistp-equal nil l))) ; ------------------------------------------------------------ ; NO-DUPLICATESP-EQUAL ; ------------------------------------------------------------ (defthm no-duplicatesp-equal-remove-duplicates-equal (no-duplicatesp-equal (remove-duplicates-equal l)) :hints (("Goal" :induct (remove-duplicates-equal l)))) ; ------------------------------------------------------------ ; NTH ; ------------------------------------------------------------ (defthm nth-with-large-index (implies (and (<= (len l) (nfix n)) (true-listp l)) (equal (nth n l) nil))) (defthm nth-append (equal (nth n (append a b)) (if (< (nfix n) (len a)) (nth n a) (nth (- (nfix n) (len a)) b)))) (defthm nth-revappend (implies (and (integerp n) (<= 0 n)) (equal (nth n (revappend a b)) (if (< n (len a)) (nth (- (len a) (1+ n)) a) (nth (- n (len a)) b)))) :hints (("Goal" :induct (revappend a b)))) (defthm nth-reverse (implies (and (integerp n) (<= 0 n)) (equal (nth n (reverse a)) (if (< n (len a)) (nth (- (len a) (1+ n)) a) nil)))) ;; In the following event we show how NTH interacts with TAKE, BUTLAST ;; and SUBSEQ. The proof strategy is to rewrite the basic FIRST-N-AC ;; term into one involving REVAPPEND and a version of firstn called ;; XFIRSTN. (local (defun xfirstn (n l) (declare (xargs :guard (and (integerp n) (<= 0 n) (true-listp l)))) (cond ((zp n) nil) (t (cons (car l) (xfirstn (1- n) (cdr l))))))) (local (defthm nth-xfirstn (implies (and (integerp i) (<= 0 i) (integerp n) (<= 0 n)) (equal (nth i (xfirstn n l)) (if (<= n (len l)) (if (< i n) (nth i l) nil) (if (< i (len l)) (nth i l) nil)))))) (local (defthm first-n-ac-non-recursive (implies (and (true-listp ac) (integerp n) (<= 0 n)) (equal (first-n-ac n l ac) (revappend ac (xfirstn n l)))))) (local (defthm nth-take (implies (and (integerp i) (<= 0 i) (integerp n) (<= 0 n)) (equal (nth i (take n l)) (if (<= n (len l)) (if (< i n) (nth i l) nil) (if (< i (len l)) (nth i l) nil)))) :hints (("Goal" :do-not-induct t)))) (defthm nth-butlast (implies (and (integerp i) (<= 0 i) (integerp n) (<= 0 n)) (equal (nth i (butlast l n)) (if (< i (- (len l) n)) (nth i l) nil))) :hints (("Goal" :do-not-induct t ; Apologia: The following hint was not necessary until we fixed the ; controller-alist problem in Version 2.4. The author of this book ; has the lemma nth-revappend just waiting for the unexpanded version ; of (revappend (list ...) ...) but because of the controller-alist ; fix, we now open that revappend up. :in-theory (disable revappend)))) (local (defthm car-nthcdr (implies (and (true-listp l) (integerp n) (<= 0 n)) (equal (car (nthcdr n l)) (nth n l))))) (local (defthm cdr-nthcdr (implies (and (integerp n) (<= 0 n)) (equal (cdr (nthcdr n l)) (nthcdr (1+ n) l))))) (defthm nth-subseq (implies (and (true-listp l) (integerp start) (<= 0 start) (or (and (integerp end) (<= start end)) (null end)) (integerp n) (<= 0 n)) (equal (nth n (subseq l start end)) (if (null end) (nth n (nthcdr start l)) (nth n (take (- end start) (nthcdr start l)))))) :hints (("Goal" :do-not-induct t ; Apologia: See nth-butlast. :in-theory (disable revappend)))) (defthm nth-firstn (equal (nth i (firstn j l)) (if (< (nfix i) (nfix j)) (nth i l) nil)) :hints (("Goal" :induct (and (nth i (firstn j l)) (nth i l) (firstn j l))))) (defthm nth-make-list-ac (equal (nth i (make-list-ac j val ac)) (if (< (nfix i) (nfix j)) val (nth (- i (nfix j)) ac))) :hints (("Goal" :induct (make-list-ac j val ac)))) (defthm nth-nthcdr (equal (nth i (nthcdr j l)) (nth (+ (nfix j) (nfix i)) l))) (defthm nth-nth-seg (equal (nth n (nth-seg i j l)) (if (< (nfix n) (nfix j)) (nth (+ (nfix i) (nfix n)) l) nil)) :hints (("Goal" :do-not-induct t :in-theory (union-theories (set-difference-theories (current-theory :here) '((:definition nth-seg))) '(nth-seg-non-recursive))))) (defthm nth-put-nth (equal (nth i (put-nth j v l)) (if (< (nfix i) (len l)) (if (equal (nfix i) (nfix j)) v (nth i l)) (nth i l)))) (local (defthm nth-put-seg-helper-1 (implies (and (true-listp l) (integerp i) (integerp n) (< (len l) i) (not (< n (len l)))) (not (nth (+ i n (- (len l))) l))) :hints (("Goal" :use (:instance nth-with-large-index (l l) (n (+ i n (- (len l))))) :in-theory (disable nth-with-large-index))))) (defthm nth-put-seg (implies (and (true-listp l) (integerp i) (not (< i 0))) (equal (nth n (put-seg i seg l)) (if (< (nfix n) i) (nth n l) (if (< (nfix n) (+ i (min (max (- (len l) i) 0) (len seg)))) (nth (- (nfix n) i) seg) (nth n l))))) :hints (("Goal" :do-not-induct t :in-theory (union-theories (set-difference-theories (current-theory :here) '((:definition put-seg))) '(put-seg-non-recursive))))) (local (defthm nth-position-equal-ac (implies (member-equal x l) (equal (nth (- (position-equal-ac x l ac) ac) l) x)) :rule-classes nil)) (defthm nth-position-equal (implies (member-equal x l) (equal (nth (position-equal x l) l) x)) :hints (("Goal" :use ((:instance nth-position-equal-ac (ac 0)))))) ; There's an NTH-UPDATE-NTH in the base ACL2 theory. ; ------------------------------------------------------------ ; NTHCDR ; ------------------------------------------------------------ (defthm nthcdr-with-large-index (implies (and (<= (len l) (nfix n)) (true-listp l)) (equal (nthcdr n l) nil))) (defthm nthcdr-append (equal (nthcdr n (append a b)) (if (<= (nfix n) (len a)) (append (nthcdr n a) b) (nthcdr (- n (len a)) b)))) (defthm nthcdr-firstn (equal (nthcdr i (firstn j l)) (if (<= (nfix j) (nfix i)) nil (firstn (- (nfix j) (nfix i)) (nthcdr i l)))) :hints (("Goal" :induct t))) (defthm nthcdr-make-list-ac (equal (nthcdr i (make-list-ac j v ac)) (if (<= (nfix j) (nfix i)) (nthcdr (- (nfix i) (nfix j)) ac) (make-list-ac (- (nfix j) (nfix i)) v ac))) :hints (("Goal" :induct t :expand (make-list-ac (+ (- i) j) v ac)))) (defthm nthcdr-nthcdr (equal (nthcdr i (nthcdr j l)) (nthcdr (+ (nfix j) (nfix i)) l))) (defthm nthcdr-nth-seg (equal (nthcdr n (nth-seg i j l)) (nth-seg (+ (nfix i) (nfix n)) (max (- (nfix j) (nfix n)) 0) l)) :hints (("Goal" :do-not-induct t :in-theory (union-theories (set-difference-theories (current-theory :here) '((:definition nth-seg))) '(nth-seg-non-recursive))))) (defthm nthcdr-put-nth (equal (nthcdr i (put-nth j v l)) (if (< (nfix j) (nfix i)) (nthcdr i l) (put-nth (- (nfix j) (nfix i)) v (nthcdr i l)))) :hints (("Goal" :induct t)) :rule-classes ((:rewrite :corollary (implies (< (nfix j) (nfix i)) (equal (nthcdr i (put-nth j v l)) (nthcdr i l)))))) ; ------------------------------------------------------------ ; OCCURRENCES and POSITION helper lemmas ; ------------------------------------------------------------ ;; Throughout the rest of this script, we'll take the strategy of ;; proving facts about OCCURRENCES by first proving the fact about XOCCURRENCES. (local (defun xoccurrences-equal (x l) (declare (xargs :guard (and (true-listp l) (or (symbolp x) (symbol-listp l))))) (cond ((endp l) 0) ((eql x (car l)) (1+ (xoccurrences-equal x (cdr l)))) (t (xoccurrences-equal x (cdr l)))))) (local (defthm occurrences-equal-ac-equals-xoccurrences-equal (implies (integerp ac) (equal (occurrences-equal-ac x l ac) (+ (xoccurrences-equal x l) ac))))) ;; Throughout the rest of this script, we'll take the strategy of ;; proving facts about POSITION by first proving the fact about XPOSITION. (local (defun xposition-equal (x l) (declare (xargs :guard (and (true-listp l) (or (symbolp x) (symbol-listp l))))) (cond ((endp l) nil) ((eq x (car l)) 0) (t (let ((N (xposition-equal x (cdr l)))) (and n (1+ n))))))) (local (defthm position-equal-ac-equals-xposition-equal1 (implies (integerp ac) (iff (position-equal-ac x l ac) (xposition-equal x l))))) (local (defthm position-equal-ac-equals-xposition-equal2 (implies (and (integerp ac) (position-equal-ac x l ac)) (equal (position-equal-ac x l ac) (+ (xposition-equal x l) ac))))) (local (defthm position-equal-ac-iff-member-equal (implies (integerp ac) (iff (position-equal-ac x l ac) (member-equal x l))))) ; ------------------------------------------------------------ ; OCCURRENCES ; ------------------------------------------------------------ (local (defthm equal-occurrences-equal-ac-zero (implies (and (not (member-equal x l)) (integerp acc)) (equal (occurrences-equal-ac x l acc) acc)))) (defthm equal-occurrences-equal-zero (implies (not (member-equal x l)) (equal (occurrences-equal x l) 0))) (local (defthm equal-occurrences-equal-ac-one (implies (and (member-equal x l) (no-duplicatesp-equal l) (integerp acc)) (equal (occurrences-equal-ac x l acc) (+ acc 1))))) (defthm equal-occurrences-equal-one (implies (and (member-equal x l) (no-duplicatesp-equal l)) (equal (occurrences-equal x l) 1))) (local (defthm xoccurrences-equal-append (implies (integerp ac) (equal (xoccurrences-equal x (append a b)) (+ (xoccurrences-equal x a) (xoccurrences-equal x b)))))) (defthm occurrences-equal-append (equal (occurrences-equal x (append a b)) (+ (occurrences-equal x a) (occurrences-equal x b)))) (local (defthm xoccurrences-equal-revappend (equal (xoccurrences-equal x (revappend a b)) (+ (xoccurrences-equal x a) (xoccurrences-equal x b))))) (defthm occurrences-equal-reverse (equal (occurrences-equal x (reverse a)) (occurrences-equal x a))) (local (defthm leq-xoccurrences-equal-firstn (<= (xoccurrences-equal x (firstn n l)) (xoccurrences-equal x l)))) (defthm occurrences-equal-firstn (<= (occurrences-equal x (firstn n l)) (occurrences-equal x l)) :rule-classes :linear) (local (defthm xoccurrences-equal-firstn-xposition-equal (implies (member-equal x l) (equal (xoccurrences-equal x (firstn (xposition-equal x l) l)) 0)))) (defthm occurrences-equal-firstn-position-equal (implies (member-equal x l) (equal (occurrences-equal x (firstn (position-equal x l) l)) 0)) :hints (("Goal" :do-not-induct t))) (local (defthm xoccurrences-equal-make-list-ac (equal (xoccurrences-equal x (make-list-ac n val ac)) (if (eql x val) (+ (nfix n) (xoccurrences-equal x ac)) (xoccurrences-equal x ac))) :hints (("Goal" :induct (make-list-ac n val ac))))) (defthm occurrences-equal-make-list-ac (equal (occurrences-equal x (make-list-ac n val ac)) (if (eql x val) (+ (nfix n) (occurrences-equal x ac)) (occurrences-equal x ac))) :hints (("Goal" :do-not-induct t))) (local (defthm xoccurrences-equal-member-equal (implies (member-equal x l) (equal (xoccurrences-equal x (member-equal x l)) (xoccurrences-equal x l))))) (defthm occurrences-equal-member-equal (implies (member-equal x l) (equal (occurrences-equal x (member-equal x l)) (occurrences-equal x l)))) (local (defthm leq-xoccurrences-equal-nthcdr (<= (xoccurrences-equal x (nthcdr n l)) (xoccurrences-equal x l)))) (defthm occurrences-equal-nthcdr (<= (occurrences-equal x (nthcdr n l)) (occurrences-equal x l)) :rule-classes :linear) (local (defthm xoccurrences-equal-nthcdr-xposition-equal (implies (member-equal x l) (equal (xoccurrences-equal x (nthcdr (xposition-equal x l) l)) (xoccurrences-equal x l))))) (defthm occurrences-equal-nthcdr-position-equal (implies (member-equal x l) (equal (occurrences-equal x (nthcdr (position-equal x l) l)) (occurrences-equal x l)))) (local (defthm xoccurrences-equal-put-nth (equal (xoccurrences-equal x (put-nth n v l)) (if (< (nfix n) (len l)) (if (equal x v) (if (equal x (nth n l)) (xoccurrences-equal x l) (1+ (xoccurrences-equal x l))) (if (equal x (nth n l)) (1- (xoccurrences-equal x l)) (xoccurrences-equal x l))) (xoccurrences-equal x l))) :hints (("Goal" :induct (put-nth n v l) :in-theory (enable nth))))) (defthm occurrences-equal-put-nth (equal (occurrences-equal x (put-nth n v l)) (if (< (nfix n) (len l)) (if (equal x v) (if (equal x (nth n l)) (occurrences-equal x l) (1+ (occurrences-equal x l))) (if (equal x (nth n l)) (1- (occurrences-equal x l)) (occurrences-equal x l))) (occurrences-equal x l))) :hints (("Goal" :do-not-induct t))) (local (defthm xoccurrences-equal-remove-equal (equal (xoccurrences-equal x (remove-equal y l)) (if (equal x y) 0 (xoccurrences-equal x l))) :hints (("Goal" :induct (remove-equal y l))))) (defthm occurrences-equal-remove-equal (equal (occurrences-equal x (remove-equal y l)) (if (equal x y) 0 (occurrences-equal x l))) :hints (("Goal" :do-not-induct t))) (local (defthm xoccurrences-equal-remove-duplicates-equal (<= (xoccurrences-equal x (remove-duplicates-equal l)) 1))) (defthm occurrences-equal-remove-duplicates-equal (implies (true-listp l) (<= (occurrences-equal x (remove-duplicates-equal l)) 1)) :rule-classes (:rewrite :linear)) ; ------------------------------------------------------------ ; POSITION ; ------------------------------------------------------------ (defthm position-equal-iff-member-equal (implies (not (stringp lst)) (iff (position-equal item lst) (member-equal item lst))) :hints (("Goal" :do-not-induct t))) (local (defthm xposition-equal-append (equal (xposition-equal x (append a b)) (if (member-equal x a) (xposition-equal x a) (if (member-equal x b) (+ (len a) (xposition-equal x b)) nil))))) (defthm position-equal-append (implies (not (stringp b)) (equal (position-equal x (append a b)) (if (member-equal x a) (position-equal x a) (if (member-equal x b) (+ (len a) (position-equal x b)) nil)))) :hints (("Goal" :do-not-induct t))) ; ------------------------------------------------------------ ; PUT-NTH ; ------------------------------------------------------------ (defthm put-nth-with-large-index (implies (and (true-listp l) (<= (len l) (nfix n))) (equal (put-nth n v l) l))) (defthm put-nth-append (equal (put-nth n v (append a b)) (if (< (nfix n) (len a)) (append (put-nth n v a) b) (append a (put-nth (- n (len a)) v b))))) (local (defun put-nth-firstn-induction (i j l) (declare (xargs :guard (and (true-listp l) (integerp i) (<= 0 i) (integerp j) (<= 0 j)))) (cond ((endp (firstn j l)) 0) ((zp i) 0) (t (put-nth-firstn-induction (1- i) (1- j) (cdr l)))))) (defthm put-nth-firstn (equal (put-nth i v (firstn j l)) (if (< (nfix i) (nfix j)) (firstn j (put-nth i v l)) (firstn j l))) :hints (("Goal" :induct (put-nth-firstn-induction i j l)))) (defthm put-nth-nthcdr (equal (put-nth i v (nthcdr j l)) (nthcdr j (put-nth (+ (nfix j) (nfix i)) v l))) :hints (("Goal" :induct t))) (defthm put-nth-nth (implies (true-listp l) (equal (put-nth i (nth i l) l) l))) (defthm put-nth-put-nth (equal (put-nth j b (put-nth i a l)) (if (= (nfix i) (nfix j)) (put-nth j b l) (put-nth i a (put-nth j b l)))) :rule-classes ((:rewrite :corollary (implies (= (nfix i) (nfix j)) (equal (put-nth j b (put-nth i a l)) (put-nth j b l)))) (:rewrite :corollary (implies (< (nfix i) (nfix j)) (equal (put-nth j b (put-nth i a l)) (put-nth i a (put-nth j b l))))))) ; ------------------------------------------------------------ ; REMOVE ; ------------------------------------------------------------ (defthm remove-equal-non-member-equal (implies (and (true-listp l) (not (member-equal x l))) (equal (remove-equal x l) l))) (defthm remove-equal-append (equal (remove-equal x (append a b)) (append (remove-equal x a) (remove-equal x b)))) (defthm remove-equal-remove-equal (equal (remove-equal y (remove-equal x l)) (if (equal x y) (remove-equal x l) (remove-equal x (remove-equal y l)))) :rule-classes ((:rewrite :corollary (equal (remove-equal x (remove-equal x l)) (remove-equal x l))))) ; ------------------------------------------------------------ ; UPDATE-NTH ; ------------------------------------------------------------ (defthm update-nth-append (equal (update-nth n v (append a b)) (if (< (nfix n) (len a)) (append (update-nth n v a) b) (append a (update-nth (- n (len a)) v b))))) (defthm update-nth-nth (implies (and (true-listp l) (integerp n) (<= 0 n) (< n (len l))) (equal (update-nth n (nth n l) l) l))) (defthm update-nth-update-nth (equal (update-nth j b (update-nth i a l)) (if (= (nfix i) (nfix j)) (update-nth j b l) (update-nth i a (update-nth j b l)))) :rule-classes ((:rewrite :corollary (implies (= (nfix i) (nfix j)) (equal (update-nth j b (update-nth i a l)) (update-nth j b l)))) (:rewrite :corollary (implies (< (nfix i) (nfix j)) (equal (update-nth j b (update-nth i a l)) (update-nth i a (update-nth j b l))))))) (in-theory (disable butlast position position-eq position-equal occurrences occurrences-eq occurrences-equal))