Filtering...

pigeonhole

books/misc/pigeonhole
other
(in-package "PIGEONHOLE")
other
(include-book "xdoc/top" :dir :system)
other
(encapsulate (((fn *) => *) ((n) => *))
  (local (defun fn
      (x)
      (declare (ignore x))
      0))
  (local (defun n nil 10))
  (defthm n-type
    (posp (n))
    :rule-classes (:type-prescription :rewrite))
  (defthm fn-type
    (integerp (fn x))
    :rule-classes (:type-prescription :rewrite))
  (defthm fn-bound
    (and (<= 0 (fn x))
      (< (fn x) (n)))
    :rule-classes (:linear (:forward-chaining :trigger-terms ((fn x))))))
other
(local (encapsulate nil
    (defun duplicate-values
      (args available used)
      (if (not (consp args))
        (mv 0 0)
        (let ((value (fn (car args))))
          (if (assoc value used)
            (mv (car args)
              (cdr (assoc value used)))
            (if (member value available)
              (duplicate-values (cdr args)
                (remove value available)
                (acons value
                  (car args)
                  used))
              (mv 0 0))))))
    (defun range-invariant
      (n available used)
      (if (zp n)
        t
        (let ((n (1- n)))
          (and (iff (assoc n used)
              (not (member n available)))
            (range-invariant n
              available
              used)))))
    (defun unique-count
      (list)
      (if (not (consp list))
        0
        (1+ (unique-count (remove (car list) (cdr list))))))
    (encapsulate nil
      (local (encapsulate nil
          (defthm member-remove
            (iff (member-equal x
                (remove-equal y list))
              (if (equal x y)
                nil
                (member-equal x list))))
          (defthm remove-remove
            (equal (remove-equal x
                (remove-equal x z))
              (remove-equal x z)))
          (defthm remove-commute
            (equal (remove-equal x
                (remove-equal y z))
              (remove-equal y
                (remove-equal x z))))
          (defthm open-unique-count-remove
            (implies (consp available)
              (equal (unique-count (remove-equal v
                    available))
                (if (equal v (car available))
                  (unique-count (remove-equal (car available)
                      (cdr available)))
                  (1+ (unique-count (remove-equal v
                        (remove-equal (car available)
                          (cdr available))))))))
            :hints (("Goal" :do-not-induct t
               :expand ((remove-equal v
                  available) (:free (a z)
                   (unique-count (cons a z)))))))
          (defthm open-unique-count-member
            (implies (member-equal v
                available)
              (equal (unique-count available)
                (1+ (unique-count (remove-equal v
                      available)))))
            :hints (("Goal" :in-theory (disable remove-equal))))))
      (defthm unique-count-remove
        (implies (member-equal v
            available)
          (equal (unique-count (remove-equal v
                available))
            (1- (unique-count available))))
        :hints (("Goal" :in-theory (disable remove-equal)))))
    (defun fn-alistp
      (alist)
      (if (not (consp alist))
        t
        (let ((entry (car alist)))
          (and (equal (car entry)
              (fn (cdr entry)))
            (fn-alistp (cdr alist))))))
    (defthm fn-assoc-fn-alistp
      (implies (and (fn-alistp used)
          (assoc-equal v used))
        (equal (fn (cdr (assoc-equal v used)))
          v)))
    (defthm member-remove
      (iff (member-equal x
          (remove-equal y list))
        (if (equal x y)
          nil
          (member-equal x list))))
    (defthm range-invariant-step
      (implies (range-invariant n
          available
          used)
        (range-invariant n
          (remove-equal (fn x)
            available)
          (cons (cons (fn x) x)
            used))))
    (defun bound-p
      (n x)
      (< (nfix x)
        (nfix n)))
    (defun enumerate-n
      (n)
      (if (zp n)
        nil
        (let ((n (1- n)))
          (cons n (enumerate-n n)))))
    (defthm bound-p-reduction
      (iff (bound-p n x)
        (member (nfix x)
          (enumerate-n n))))
    (defthm remove-enumerate-n
      (implies (<= (nfix m)
          (nfix n))
        (equal (remove-equal n
            (enumerate-n m))
          (enumerate-n m))))
    (defthm unique-count-enumerate-n
      (equal (unique-count (enumerate-n n))
        (nfix n))
      :hints (("Goal" :induct (enumerate-n n)
         :do-not-induct t
         :expand (:free (a x)
           (unique-count (cons a x))))))
    (defun range-invariant-1
      (n available)
      (if (zp n)
        t
        (let ((n (1- n)))
          (and (member n available)
            (range-invariant-1 n
              available)))))
    (defthm range-invariant-reduction
      (iff (range-invariant n
          available
          nil)
        (range-invariant-1 n
          available)))
    (defthm range-invariant-cons
      (implies (and (natp n)
          (natp a)
          (<= n a))
        (equal (range-invariant-1 n
            (cons a b))
          (range-invariant-1 n b))))
    (defthm range-invariant-1-enumerate-n
      (range-invariant-1 n
        (enumerate-n n)))
    (defun alist-values
      (used)
      (if (not (consp used))
        nil
        (let ((entry (car used)))
          (cons (cdr entry)
            (alist-values (cdr used))))))
    (defun disjoint-from-domain
      (args used)
      (if (not (consp args))
        t
        (and (not (member (car args)
              (alist-values used)))
          (disjoint-from-domain (cdr args)
            used))))
    (defun no-duplicates
      (args)
      (if (not (consp args))
        t
        (and (not (member (car args) (cdr args)))
          (no-duplicates (cdr args)))))
    (defthm disjoint-from-domain-invariant
      (implies (and (disjoint-from-domain args
            used)
          (not (member arg args)))
        (disjoint-from-domain args
          (cons (cons val arg)
            used))))
    (defthmd range-invariant-assoc-reduction
      (implies (and (natp v)
          (range-invariant n
            available
            used)
          (< v (nfix n)))
        (iff (assoc-equal v used)
          (not (member v available)))))
    (defthm not-member-values-not-equal-cdr-assoc
      (implies (and (not (member-equal arg
              (alist-values used)))
          (assoc-equal z used))
        (not (equal arg
            (cdr (assoc-equal z used))))))
    (defthm member-alist-values
      (implies (assoc-equal v used)
        (member-equal (cdr (assoc v used))
          (alist-values used))))
    (in-theory (disable mv-nth))
    (defthm general-property
      (implies (and (fn-alistp used)
          (range-invariant (n)
            available
            used)
          (no-duplicates args)
          (disjoint-from-domain args
            used)
          (< (unique-count available)
            (len args)))
        (mv-let (a b)
          (duplicate-values args
            available
            used)
          (and (or (member a args)
              (member a
                (alist-values used)))
            (or (member b args)
              (member b
                (alist-values used)))
            (not (equal a b))
            (equal (fn a)
              (fn b)))))
      :rule-classes nil
      :hints (("Goal" :do-not-induct t
         :induct (duplicate-values args
           available
           used)
         :expand (disjoint-from-domain args
           used)) (and stable-under-simplificationp
          '(:in-theory (enable range-invariant-assoc-reduction)))))
    (defthm disjoint-from-domain-nil
      (disjoint-from-domain args nil))
    (defthmd property-instance
      (implies (and (no-duplicates args)
          (< (n) (len args)))
        (mv-let (a b)
          (duplicate-values args
            (enumerate-n (n))
            nil)
          (and (member a args)
            (member b args)
            (not (equal a b))
            (equal (fn a)
              (fn b)))))
      :hints (("Goal" :do-not-induct t
         :use (:instance general-property
           (used nil)
           (available (enumerate-n (n)))))))
    (defthm not-member-enumerate-n
      (implies (and (natp m)
          (natp n)
          (<= n m))
        (not (member-equal m
            (enumerate-n n)))))
    (defthm no-duplicates-enumerate-n
      (no-duplicates (enumerate-n m)))
    (defthm len-enumerate-n
      (equal (len (enumerate-n m))
        (nfix m)))
    (defthm nat-listp-enumerate-n
      (nat-listp (enumerate-n n))
      :rule-classes ((:forward-chaining :trigger-terms ((enumerate-n n)))))
    (defthm natp-member-nat-listp
      (implies (and (member-equal x list)
          (nat-listp list))
        (natp x))
      :rule-classes :forward-chaining)
    (defthm natp-implies
      (implies (natp x)
        (and (integerp x) (<= 0 x)))
      :rule-classes :forward-chaining)
    (defthmd numeric-property-instance
      (implies (and (natp m)
          (< (n) m))
        (mv-let (a b)
          (duplicate-values (enumerate-n (1+ m))
            (enumerate-n (n))
            nil)
          (and (natp a)
            (natp b)
            (bound-p (1+ m) a)
            (bound-p (1+ m) b)
            (not (equal a b))
            (equal (fn a)
              (fn b)))))
      :hints (("Goal" :do-not-induct t
         :in-theory (disable enumerate-n
           duplicate-values)
         :use (:instance property-instance
           (args (enumerate-n (1+ m)))))))))
other
(defun-sk exists-duplicates
  (m)
  (exists (a b)
    (and (natp a)
      (natp b)
      (<= a m)
      (<= b m)
      (not (equal a b))
      (equal (fn a)
        (fn b)))))
other
(defthmd numeric-pigeonhole-property
  (implies (and (natp m)
      (< (n) m))
    (exists-duplicates m))
  :hints (("Goal" :do-not-induct t
     :in-theory (e/d (bound-p)
       (bound-p-reduction exists-duplicates))
     :use (numeric-property-instance))))
proofmacro
(defmacro proof
  (fn n &key (function 'nil))
  (let ((pkg (or function
         (if (symbolp fn)
           fn
           'hole-proof))) (function (or function fn)))
    (let ((exists-fn-duplicates (packn-pos (list 'exists-
             function
             '-duplicates)
           pkg)) (exists-fn-duplicates-witness (packn-pos (list 'exists-
              function
              '-duplicates-witness)
            pkg))
        (fn-pigeonhole-property (packn-pos (list function '-pigeonhole-property)
            pkg)))
      `(encapsulate nil
        (defun-sk ,PIGEONHOLE::EXISTS-FN-DUPLICATES
          (m)
          (exists (a b)
            (and (natp a)
              (natp b)
              (<= a m)
              (<= b m)
              (not (equal a b))
              (equal (,PIGEONHOLE::FN a)
                (,PIGEONHOLE::FN b)))))
        (defthm ,PIGEONHOLE::FN-PIGEONHOLE-PROPERTY
          (implies (and (natp m)
              (< ,PIGEONHOLE::N m))
            (,PIGEONHOLE::EXISTS-FN-DUPLICATES m))
          :hints (("Goal" :do-not-induct t
             :use (:functional-instance numeric-pigeonhole-property
               (fn ,PIGEONHOLE::FN)
               (n (lambda nil ,PIGEONHOLE::N))
               (exists-duplicates ,PIGEONHOLE::EXISTS-FN-DUPLICATES)
               (exists-duplicates-witness ,PIGEONHOLE::EXISTS-FN-DUPLICATES-WITNESS)))))))))
other
(local (encapsulate nil
    (encapsulate (((zed *) => *))
      (local (defun zed
          (x)
          (declare (ignore x))
          10))
      (defthm integerp-zed
        (integerp (zed x)))
      (defthm zed-bound
        (and (<= 0 (zed x))
          (< (zed x) 100))))
    (proof zed 100)
    (defthm zed-pigeonhole-property-lemma
      (implies (and (natp m) (< 100 m))
        (exists-zed-duplicates m)))))
other
(defxdoc proof
  :short "A macro that proves the pigeonhole principle for functions with finite ranges"
  :parents (proof-automation)
  :long "
<p>
The pigeonhole book defines a simple macro @('pigeonhole::proof') that can
be used to prove the pigeonhole principle for functions with finite ranges.
The pigeonhole principle says that, given a function with k elements in
its range, among k+1 or more invocations of that function at least two will
generate identical outputs.
</p>
<p>Usage:</p>
@({
   (include-book "misc/pigeonhole" :dir :system)

   (encapsulate
       (
        ((zed *) => *)
        )

     (local (defun zed (x) (declare (ignore x)) 10))

     (defthm integerp-zed
       (integerp (zed x)))

     (defthm zed-bound
       (and (<= 0 (zed x))
            (< (zed x) 100)))
     
     )

   ;;        
   ;; This macro invocation:
   ;;
   (pigeonhole::proof zed 100)
   ;;
   ;; admits the form:
   ;;
   ;; (defun-sk exists-zed-duplicates (m)
   ;;   (exists (a b) (and (natp a)
   ;;                      (natp b)
   ;;                      (<= a m)
   ;;                      (<= b m)
   ;;                      (not (equal a b))
   ;;                      (equal (zed a) (zed b)))))
   ;;
   ;; And proves ..
   ;;
   (defthm zed-pigeonhole-property-lemma
     (implies
      (and
       (natp m)
       (< 100 m))
      (exists-zed-duplicates m)))

 })
")