Filtering...

alist-equiv

books/std/alists/alist-equiv

Included Books

other
(in-package "ACL2")
include-book
(include-book "xdoc/top" :dir :system)
include-book
(include-book "alist-keys")
include-book
(include-book "alist-vals")
local
(local (encapsulate nil
    (in-theory (enable list-fix))
    (local (defthm l0 (implies (subsetp x (cdr y)) (subsetp x y))))
    (defthm subsetp-equal-reflexive (subsetp-equal x x))
    (defthm hons-assoc-equal-of-list-fix
      (equal (hons-assoc-equal key (list-fix alist))
        (hons-assoc-equal key alist)))
    (defthm hons-assoc-equal-of-list-fix
      (equal (hons-assoc-equal key (list-fix alist))
        (hons-assoc-equal key alist)))
    (defthm hons-assoc-equal-append
      (equal (hons-assoc-equal x (append a b))
        (or (hons-assoc-equal x a) (hons-assoc-equal x b))))
    (defthm alist-keys-of-list-fix
      (equal (alist-keys (list-fix x)) (alist-keys x)))))
other
(defsection alists-agree
  :parents (std/alists)
  :short "@(call alists-agree) determines if the alists @('al1') and @('al2')
agree on the value of every key in @('keys')."
  (defund alists-agree
    (keys al1 al2)
    (declare (xargs :guard t))
    (or (atom keys)
      (and (equal (hons-get (car keys) al1) (hons-get (car keys) al2))
        (alists-agree (cdr keys) al1 al2))))
  (local (in-theory (enable alists-agree)))
  (local (defthmd l0
      (equal (alists-agree (list-fix keys) al1 al2)
        (alists-agree keys al1 al2))))
  (defcong list-equiv
    equal
    (alists-agree keys al1 al2)
    1
    :hints (("Goal" :in-theory (enable list-equiv)
       :use ((:instance l0) (:instance l0 (keys keys-equiv))))))
  (defthmd alists-agree-hons-assoc-equal
    (implies (and (alists-agree keys a b) (member-equal x keys))
      (equal (hons-assoc-equal x b) (hons-assoc-equal x a))))
  (defthm alists-agree-self (alists-agree keys a a))
  (defthmd alists-agree-sym
    (implies (alists-agree keys a b) (alists-agree keys b a)))
  (defund alists-disagree-witness
    (keys al1 al2)
    (and (consp keys)
      (if (not (equal (hons-get (car keys) al1) (hons-get (car keys) al2)))
        (car keys)
        (alists-disagree-witness (cdr keys) al1 al2))))
  (defthmd alists-agree-iff-witness
    (iff (alists-agree keys al1 al2)
      (let ((x (alists-disagree-witness keys al1 al2)))
        (implies (member-equal x keys)
          (equal (hons-assoc-equal x al1) (hons-assoc-equal x al2)))))
    :hints (("goal" :in-theory (enable alists-disagree-witness))))
  (defthmd alists-agree-trans
    (implies (and (alists-agree keys x y) (alists-agree keys y z))
      (alists-agree keys x z))))
other
(defsection sub-alistp
  :parents (std/alists)
  :short "@(call sub-alistp) determines whether every @('key') bound in the
alist @('a') is also bound to the same value in the alist @('b')."
  (defund sub-alistp
    (a b)
    (declare (xargs :guard t))
    (mbe :logic (alists-agree (alist-keys a) a b)
      :exec (with-fast-alist a
        (with-fast-alist b (alists-agree (alist-keys a) a b)))))
  (local (in-theory (enable sub-alistp)))
  (defthm sub-alistp-self (sub-alistp x x))
  (defthmd sub-alistp-hons-assoc-equal
    (implies (and (sub-alistp a b) (hons-assoc-equal x a))
      (equal (hons-assoc-equal x a) (hons-assoc-equal x b)))
    :hints (("Goal" :in-theory (enable alists-agree-hons-assoc-equal))))
  (defun not-sub-alistp-witness
    (a b)
    (alists-disagree-witness (alist-keys a) a b))
  (defthmd sub-alistp-iff-witness
    (iff (sub-alistp a b)
      (let ((x (not-sub-alistp-witness a b)))
        (implies (hons-assoc-equal x a)
          (equal (hons-assoc-equal x a) (hons-assoc-equal x b)))))
    :hints (("Goal" :in-theory (e/d (alists-agree-iff-witness) (alists-agree)))))
  (defthmd sub-alistp-when-witness
    (implies (let ((x (not-sub-alistp-witness a b)))
        (implies (hons-assoc-equal x a)
          (equal (hons-assoc-equal x a) (hons-assoc-equal x b))))
      (sub-alistp a b))
    :hints (("goal" :use sub-alistp-iff-witness)))
  (defthmd sub-alistp-trans
    (implies (and (sub-alistp x y) (sub-alistp y z))
      (sub-alistp x z))
    :hints (("Goal" :in-theory (e/d (sub-alistp-when-witness)
         (sub-alistp not-sub-alistp-witness))
       :use ((:instance sub-alistp-hons-assoc-equal
          (x (not-sub-alistp-witness x z))
          (a x)
          (b y)) (:instance sub-alistp-hons-assoc-equal
           (x (not-sub-alistp-witness x z))
           (a y)
           (b z)))))))
other
(defsection alist-equiv
  :parents (std/alists)
  :short "@(call alist-equiv) determines whether the alists @('a') and @('b')
are equivalent up to @(see hons-assoc-equal), i.e., whether they bind the same
value to every key."
  :long "<p>This is a fundamental equivalence relation for alists.  It allows
you to consider the equivalence of alists regardless of the order of their
elements, the presence of shadowed elements, etc.</p>

<p>Note that @(see list-equiv) is a @(see refinement) of @(see
alist-equiv).</p>"
  (defund alist-equiv
    (a b)
    (declare (xargs :guard t))
    (mbe :logic (and (sub-alistp a b) (sub-alistp b a))
      :exec (with-fast-alist a
        (with-fast-alist b (and (sub-alistp a b) (sub-alistp b a))))))
  (local (in-theory (enable alist-equiv alists-agree)))
  (defequiv alist-equiv
    :hints (("Goal" :in-theory (enable sub-alistp-trans))))
  (encapsulate nil
    (local (defthm l0
        (implies (and (not (equal (hons-assoc-equal a x) (hons-assoc-equal a y)))
            (sub-alistp x y))
          (not (sub-alistp y x)))
        :hints (("Goal" :use ((:instance sub-alistp-hons-assoc-equal (x a) (a x) (b y)) (:instance sub-alistp-hons-assoc-equal (x a) (a y) (b x)))))))
    (defthmd alist-equiv-means-all-keys-agree
      (implies (alist-equiv x y) (alists-agree keys x y))))
  (defsection alist-equiv-refines-list-equiv
    (local (defthm l0
        (equal (alists-agree keys (list-fix al1) al2)
          (alists-agree keys al1 al2))
        :hints (("Goal" :in-theory (enable alists-agree)))))
    (local (defthm l1
        (equal (alists-agree keys al1 (list-fix al2))
          (alists-agree keys al1 al2))
        :hints (("Goal" :in-theory (enable alists-agree)))))
    (local (defthm l2
        (equal (sub-alistp (list-fix x) y) (sub-alistp x y))
        :hints (("Goal" :in-theory (enable sub-alistp)))))
    (local (defthm l3
        (equal (sub-alistp x (list-fix y)) (sub-alistp x y))
        :hints (("Goal" :in-theory (enable sub-alistp)))))
    (local (defcong list-equiv
        equal
        (sub-alistp x y)
        1
        :hints (("Goal" :in-theory (e/d (list-equiv) (l2))
           :use ((:instance l2 (x x)) (:instance l2 (x x-equiv)))))))
    (local (defcong list-equiv
        equal
        (sub-alistp x y)
        2
        :hints (("Goal" :in-theory (e/d (list-equiv) (l3))
           :use ((:instance l3 (y y)) (:instance l3 (y y-equiv)))))))
    (defrefinement list-equiv
      alist-equiv
      :hints (("Goal" :in-theory (enable alist-equiv))))))
other
(defsection basic-alist-equiv-congruences
  :parents (alist-equiv)
  :short "Some @(see congruence) rules about @(see alist-equiv) for basic alist
functions."
  (defcong alist-equiv
    equal
    (hons-assoc-equal x a)
    2
    :hints (("goal" :in-theory (enable alist-equiv alists-agree)
       :use ((:instance alist-equiv-means-all-keys-agree
          (keys (list x))
          (x a)
          (y a-equiv)))))))
other
(defsection alist-equiv-bad-guy
  :parents (alist-equiv)
  :short "@(call alist-equiv-bad-guy) finds some key, if one exists, that
differs between the alists @('al1') and @('al2')."
  :long "<p>This is generally useful for doing pick-a-point style reasoning
about alist equivalence.</p>"
  (defchoose alist-equiv-bad-guy
    (bg)
    (al1 al2)
    (not (equal (hons-assoc-equal bg al1) (hons-assoc-equal bg al2))))
  (local (in-theory (enable alist-equiv alists-agree)))
  (local (defthm l0
      (implies (and (equal (hons-assoc-equal (alist-equiv-bad-guy al1 al2) al1)
            (hons-assoc-equal (alist-equiv-bad-guy al1 al2) al2)))
        (equal (hons-assoc-equal a al1) (hons-assoc-equal a al2)))
      :hints (("goal" :use ((:instance alist-equiv-bad-guy (bg a)))))))
  (defthmd alists-agree-when-agree-on-alist-equiv-bad-guy
    (implies (let ((bg (alist-equiv-bad-guy al1 al2)))
        (equal (hons-assoc-equal bg al1) (hons-assoc-equal bg al2)))
      (alists-agree keys al1 al2))
    :hints (("Goal" :induct (len keys))))
  (defthmd alists-agree-when-agree-on-alist-equiv-bad-guy1
    (implies (let ((bg (alist-equiv-bad-guy al1 al2)))
        (equal (hons-assoc-equal bg al1) (hons-assoc-equal bg al2)))
      (alists-agree keys al2 al1))
    :hints (("Goal" :induct (len keys))))
  (defthmd sub-alistp-when-agree-on-alist-equiv-bad-guy
    (implies (let ((bg (alist-equiv-bad-guy al1 al2)))
        (equal (hons-assoc-equal bg al1) (hons-assoc-equal bg al2)))
      (sub-alistp al1 al2))
    :hints (("Goal" :in-theory (enable alists-agree-when-agree-on-alist-equiv-bad-guy
         sub-alistp))))
  (defthmd sub-alistp-when-agree-on-alist-equiv-bad-guy1
    (implies (let ((bg (alist-equiv-bad-guy al2 al1)))
        (equal (hons-assoc-equal bg al1) (hons-assoc-equal bg al2)))
      (sub-alistp al1 al2))
    :hints (("Goal" :in-theory (enable alists-agree-when-agree-on-alist-equiv-bad-guy1
         sub-alistp))))
  (defthmd alist-equiv-when-agree-on-bad-guy
    (implies (let ((bg (alist-equiv-bad-guy al1 al2)))
        (equal (hons-assoc-equal bg al1) (hons-assoc-equal bg al2)))
      (equal (alist-equiv al1 al2) t))
    :hints (("Goal" :in-theory (enable sub-alistp-when-agree-on-alist-equiv-bad-guy
         sub-alistp-when-agree-on-alist-equiv-bad-guy1))))
  (defthmd alist-equiv-iff-agree-on-bad-guy
    (iff (alist-equiv al1 al2)
      (let ((bg (alist-equiv-bad-guy al1 al2)))
        (equal (hons-assoc-equal bg al1) (hons-assoc-equal bg al2))))
    :hints (("goal" :in-theory (e/d (alist-equiv-when-agree-on-bad-guy sub-alistp-hons-assoc-equal)
         (alist-equiv))))))
other
(defsection more-congruences
  :extension basic-alist-equiv-congruences
  (defcong alist-equiv
    equal
    (alists-agree keys a b)
    2
    :hints (("goal" :in-theory (enable alists-agree))))
  (defcong alist-equiv
    equal
    (alists-agree keys a b)
    3
    :hints (("goal" :in-theory (enable alists-agree))))
  (defcong alist-equiv
    equal
    (sub-alistp x y)
    1
    :hints (("Goal" :in-theory (enable alist-equiv sub-alistp-trans)
       :cases ((sub-alistp x y)))))
  (defcong alist-equiv
    equal
    (sub-alistp x y)
    2
    :hints (("Goal" :in-theory (enable alist-equiv sub-alistp-trans)
       :cases ((sub-alistp x y)))))
  (encapsulate nil
    (local (in-theory (e/d (member alist-keys)
          (alist-keys-member-hons-assoc-equal))))
    (local (defthm l0
        (implies (member (cons a b) x) (member a (alist-keys x)))))
    (local (defthm l1
        (implies (and (subsetp x y) (member a (alist-keys x)))
          (member a (alist-keys y)))))
    (local (defthm l2
        (implies (subsetp x y)
          (subsetp (alist-keys x) (alist-keys y)))))
    (defcong set-equiv
      set-equiv
      (alist-keys x)
      1
      :hints (("Goal" :in-theory (enable set-equiv)))))
  (encapsulate nil
    (local (in-theory (enable member alist-vals)))
    (local (defthm l0
        (implies (member (cons a b) x) (member b (alist-vals x)))))
    (local (defthm l1
        (implies (and (subsetp x y) (member a (alist-vals x)))
          (member a (alist-vals y)))))
    (local (defthm l2
        (implies (subsetp x y)
          (subsetp (alist-vals x) (alist-vals y)))))
    (defcong set-equiv
      set-equiv
      (alist-vals x)
      1
      :hints (("Goal" :in-theory (enable set-equiv)))))
  (defsection alist-keys-set-equivalence
    (local (defthm l1
        (implies (and (subsetp keys (alist-keys x)) (alist-equiv x y))
          (subsetp keys (alist-keys y)))
        :hints (("Goal" :induct (len keys)))))
    (local (defthm l2
        (implies (alist-equiv x y)
          (subsetp (alist-keys x) (alist-keys y)))
        :hints (("Goal" :in-theory (disable l1)
           :use ((:instance l1 (keys (alist-keys x))))))))
    (defcong alist-equiv
      set-equiv
      (alist-keys x)
      1
      :hints (("Goal" :in-theory (enable set-equiv)))))
  (defcong alist-equiv
    alist-equiv
    (cons a b)
    2
    :hints (("goal" :in-theory (enable alist-equiv-when-agree-on-bad-guy))))
  (defcong alist-equiv
    alist-equiv
    (append a b)
    1
    :hints (("Goal" :in-theory (enable alist-equiv-when-agree-on-bad-guy))))
  (defcong alist-equiv
    alist-equiv
    (append a b)
    2
    :hints (("Goal" :in-theory (enable alist-equiv-when-agree-on-bad-guy)))))