Filtering...

defmax-nat

books/std/util/defmax-nat

Included Books

other
(in-package "ACL2")
include-book
(include-book "kestrel/error-checking/ensure-value-is-boolean" :dir :system)
include-book
(include-book "kestrel/error-checking/ensure-value-is-symbol" :dir :system)
include-book
(include-book "kestrel/error-checking/ensure-value-is-symbol-list" :dir :system)
include-book
(include-book "std/lists/rcons" :dir :system)
include-book
(include-book "xdoc/defxdoc-plus" :dir :system)
other
(defxdoc+ defmax-nat-implementation
  :parents (defmax-nat)
  :short "Implementation of @(tsee defmax-nat)."
  :long (topstring (p "The implementation functions have formal parameters
     consistently named as follows:")
    (ul (li "@('state') is the ACL2 @(see state).")
      (li "@('ctx') is the context used for errors.")
      (li "@('f'),
      @('y'),
      @('x1...xn'),
      @('body'),
      @('guard'), and
      @('verify-guards')
      are the honomynous inputs to @(tsee defmax-nat),
      where @('x1...xn') is shown as @('(x1 ... xn')) in the documentation.
      They have no types before being processed,
      then they acquire types implied by their validation.")))
  :order-subtopics t)
other
(defxdoc+ defmax-nat-input-processing
  :parents (defmax-nat-implementation)
  :short "Input processing performed by @(tsee defmax-nat)."
  :long (topstring-p "Currently this validates the inputs lightly.
    It should be improved to do a more thorough validation.")
  :order-subtopics t
  :default-parent t)
other
(define defmax-nat-process-inputs
  (f y x1...xn body guard verify-guards ctx state)
  :returns (mv erp (nothing null) state)
  :short "Process all the inputs."
  :long (topstring-p "We just check that the inputs have the right types.
    We do not check the @('body') and @('guard') inputs,
    since those are untranslated term,
    for which we do not quite have a ``type'' readily available.")
  (declare (ignore body guard))
  (b* (((er &) (ensure-value-is-symbol$ f "The first input" t nil)) ((er &) (ensure-value-is-symbol$ y "The second input" t nil))
      ((er &) (ensure-value-is-symbol-list$ x1...xn
          "The third input"
          t
          nil))
      ((er &) (ensure-value-is-boolean$ verify-guards
          "The :VERIFY-GUARDS input"
          t
          nil)))
    (value nil)))
other
(defxdoc+ defmax-nat-event-generation
  :parents (defmax-nat-implementation)
  :short "Event generation performed by @(tsee defmax-nat)."
  :order-subtopics t
  :default-parent t)
other
(define defmax-nat-gen-everything
  ((f symbolp) (y symbolp)
    (x1...xn symbol-listp)
    body
    guard
    (verify-guards booleanp))
  :returns (event "A @(tsee pseudo-event-formp).")
  :mode :program :short "Generate the top-level event."
  :long (topstring-p "The events are generated inside an @(tsee encapsulate).
    Some events are only local, just used to prove the first helper theorem
    @('f.existsp-when-nonempty-and-bounded').
    The exported theorems that have hints are generated
    first locally with the hints,
    then non-locally and redundantly without hints,
    to keep the history ``cleaner''.")
  (b* ((y0 (genvar y (symbol-name y) 0 (list* y x1...xn))) (y1 (genvar y (symbol-name y) 1 (list* y y0 x1...xn)))
      (x1...xn-y (rcons y x1...xn))
      (elementp (add-suffix-to-fn f ".ELEMENTP"))
      (uboundp (add-suffix-to-fn f ".UBOUNDP"))
      (existsp (add-suffix-to-fn f ".EXISTSP"))
      (existsp-witness (add-suffix-to-fn existsp "-WITNESS"))
      (uboundp-witness (add-suffix-to-fn uboundp "-WITNESS"))
      (uboundp-necc (add-suffix-to-fn uboundp "-NECC"))
      (existsp-suff (add-suffix-to-fn existsp "-SUFF"))
      (pkgwit (pkg-witness (symbol-package-name f)))
      (booleanp-of-uboundp (packn-pos (list 'booleanp-of uboundp) pkgwit))
      (booleanp-of-existsp (packn-pos (list 'booleanp-of existsp) pkgwit))
      (maybe-natp-of-f (packn-pos (list 'maybe-natp-of- f) pkgwit))
      (natp-of-f-equal-existsp (packn-pos (list 'natp-of- f '-equal- existsp) pkgwit))
      (natp-of-f-when-existsp (packn-pos (list 'natp-of- f '-when- existsp) pkgwit))
      (f-iff-existsp (packn-pos (list f '-iff- existsp) pkgwit))
      (not-f-when-not-existsp (packn-pos (list 'not- f '-when-not- existsp) pkgwit))
      (elementp-of-f-when-existsp (packn-pos (list elementp '-of- f '-when- existsp) pkgwit))
      (uboundp-of-f-when-existsp (packn-pos (list uboundp '-of- f '-when- 'existsp) pkgwit))
      (f-geq-when-existsp-linear (packn-pos (list f '-geq-when- existsp '-linear) pkgwit))
      (f-geq-when-existsp-rewrite (packn-pos (list f '-geq-when- existsp '-rewrite) pkgwit))
      (f-leq-when-existsp-linear (packn-pos (list f '-leq-when- existsp '-linear) pkgwit))
      (f-leq-when-existsp-rewrite (packn-pos (list f '-leq-when- existsp '-rewrite) pkgwit))
      (ubound-geq-member (packn-pos (list f '.ubound-geq-member) pkgwit))
      (ubound-nonmember-gt-member (packn-pos (list f '.ubound-nonmember-gt-member) pkgwit))
      (find-max (packn-pos (list f '.find-max) pkgwit))
      (find-max-uboundp-preservation (packn-pos (list f '.find-max-uboundp-preservation) pkgwit))
      (elementp-of-find-max (packn-pos (list f '.elementp-of-find-max) pkgwit))
      (uboundp-of-find-max (packn-pos (list f '.uboundp-of-find-max) pkgwit))
      (existsp-when-nonempty-and-bounded (packn-pos (list f '.existsp-when-nonempty-and-bounded)
          pkgwit))
      (equal-when-member-and-ubound (packn-pos (list f '.equal-when-member-and-ubound) pkgwit))
      (elementp-events `((defun ,ELEMENTP
           ,X1...XN-Y
           (declare (xargs :guard (and ,GUARD (natp ,Y))))
           ,BODY) ,@(AND VERIFY-GUARDS `((VERIFY-GUARDS ,ELEMENTP)))
          (in-theory (disable ,ELEMENTP))))
      (uboundp-events `((defun-sk ,UBOUNDP
           ,X1...XN-Y
           (declare (xargs :guard (and ,GUARD (natp ,Y)) :verify-guards nil))
           (forall (,Y1)
             (impliez (and (natp ,Y1) (,ELEMENTP ,@X1...XN ,Y1))
               (>= (nfix ,Y) ,Y1)))
           :rewrite (implies (and (,UBOUNDP ,@X1...XN-Y)
               (natp ,Y1)
               (,ELEMENTP ,@X1...XN ,Y1))
             (>= (nfix ,Y) ,Y1))) ,@(AND VERIFY-GUARDS `((VERIFY-GUARDS ,UBOUNDP)))
          (defthm ,BOOLEANP-OF-UBOUNDP
            (booleanp (,UBOUNDP ,@X1...XN-Y)))
          (in-theory (disable ,UBOUNDP ,UBOUNDP-NECC))))
      (existsp-events `((defun-sk ,EXISTSP
           ,X1...XN
           (declare (xargs :guard ,GUARD :verify-guards nil))
           (exists (,Y)
             (and (natp ,Y)
               (,ELEMENTP ,@X1...XN-Y)
               (,UBOUNDP ,@X1...XN-Y)))) ,@(AND VERIFY-GUARDS `((VERIFY-GUARDS ,EXISTSP)))
          (defthm ,BOOLEANP-OF-EXISTSP
            (booleanp (,EXISTSP ,@X1...XN)))
          (in-theory (disable ,EXISTSP ,EXISTSP-SUFF))))
      (f-events `((defun ,F
           ,X1...XN
           (declare (xargs :guard ,GUARD))
           (if (,EXISTSP ,@X1...XN)
             (,EXISTSP-WITNESS ,@X1...XN)
             nil)) ,@(AND VERIFY-GUARDS `((VERIFY-GUARDS ,F)))
          ,@(AND (NULL X1...XN) `((IN-THEORY (DISABLE (:E ,F)))))
          (local (defthm ,MAYBE-NATP-OF-F
              (maybe-natp (,F ,@X1...XN))
              :hints (("Goal" :in-theory (enable maybe-natp ,EXISTSP)))))
          (defthm ,MAYBE-NATP-OF-F (maybe-natp (,F ,@X1...XN)))
          (local (defthm ,NATP-OF-F-EQUAL-EXISTSP
              (equal (natp (,F ,@X1...XN)) (,EXISTSP ,@X1...XN))
              :hints (("Goal" :in-theory (enable ,EXISTSP)))))
          (defthm ,NATP-OF-F-EQUAL-EXISTSP
            (equal (natp (,F ,@X1...XN)) (,EXISTSP ,@X1...XN)))
          (defthm ,NATP-OF-F-WHEN-EXISTSP
            (implies (,EXISTSP ,@X1...XN) (natp (,F ,@X1...XN)))
            :rule-classes :type-prescription)
          (local (defthm ,F-IFF-EXISTSP
              (iff (,F ,@X1...XN) (,EXISTSP ,@X1...XN))
              :hints (("Goal" :in-theory (enable ,EXISTSP)))))
          (defthm ,F-IFF-EXISTSP
            (iff (,F ,@X1...XN) (,EXISTSP ,@X1...XN)))
          (defthm ,NOT-F-WHEN-NOT-EXISTSP
            (implies (not (,EXISTSP ,@X1...XN)) (not (,F ,@X1...XN)))
            :rule-classes :type-prescription)
          (local (defthm ,ELEMENTP-OF-F-WHEN-EXISTSP
              (implies (,EXISTSP ,@X1...XN)
                (,ELEMENTP ,@X1...XN (,F ,@X1...XN)))
              :hints (("Goal" :in-theory (enable ,EXISTSP)))))
          (defthm ,ELEMENTP-OF-F-WHEN-EXISTSP
            (implies (,EXISTSP ,@X1...XN)
              (,ELEMENTP ,@X1...XN (,F ,@X1...XN))))
          (local (defthm ,UBOUNDP-OF-F-WHEN-EXISTSP
              (implies (,EXISTSP ,@X1...XN)
                (,UBOUNDP ,@X1...XN (,F ,@X1...XN)))
              :hints (("Goal" :in-theory (enable ,EXISTSP)))))
          (defthm ,UBOUNDP-OF-F-WHEN-EXISTSP
            (implies (,EXISTSP ,@X1...XN)
              (,UBOUNDP ,@X1...XN (,F ,@X1...XN))))
          (local (defthm ,F-GEQ-WHEN-EXISTSP-LINEAR
              (implies (and (,EXISTSP ,@X1...XN)
                  (,ELEMENTP ,@X1...XN ,Y1)
                  (natp ,Y1))
                (>= (,F ,@X1...XN) ,Y1))
              :rule-classes :linear :hints (("Goal" :use (,UBOUNDP-OF-F-WHEN-EXISTSP (:instance ,UBOUNDP-NECC (,Y (,F ,@X1...XN))))))))
          (defthm ,F-GEQ-WHEN-EXISTSP-LINEAR
            (implies (and (,EXISTSP ,@X1...XN)
                (,ELEMENTP ,@X1...XN ,Y1)
                (natp ,Y1))
              (>= (,F ,@X1...XN) ,Y1))
            :rule-classes :linear)
          (local (defthm ,F-GEQ-WHEN-EXISTSP-REWRITE
              (implies (and (,EXISTSP ,@X1...XN)
                  (,ELEMENTP ,@X1...XN ,Y1)
                  (natp ,Y1))
                (>= (,F ,@X1...XN) ,Y1))
              :hints (("Goal" :by ,F-GEQ-WHEN-EXISTSP-LINEAR))))
          (defthm ,F-GEQ-WHEN-EXISTSP-REWRITE
            (implies (and (,EXISTSP ,@X1...XN)
                (,ELEMENTP ,@X1...XN ,Y1)
                (natp ,Y1))
              (>= (,F ,@X1...XN) ,Y1)))
          (local (defthm ,F-LEQ-WHEN-EXISTSP-LINEAR
              (implies (and (,EXISTSP ,@X1...XN)
                  (,UBOUNDP ,@X1...XN ,Y1)
                  (natp ,Y1))
                (<= (,F ,@X1...XN) ,Y1))
              :rule-classes :linear :hints (("Goal" :in-theory (disable ,F)
                 :use (:instance ,UBOUNDP-NECC (,Y1 (,F ,@X1...XN)) (,Y ,Y1))))))
          (defthm ,F-LEQ-WHEN-EXISTSP-LINEAR
            (implies (and (,EXISTSP ,@X1...XN)
                (,UBOUNDP ,@X1...XN ,Y1)
                (natp ,Y1))
              (<= (,F ,@X1...XN) ,Y1))
            :rule-classes :linear)
          (local (defthm ,F-LEQ-WHEN-EXISTSP-REWRITE
              (implies (and (,EXISTSP ,@X1...XN)
                  (,UBOUNDP ,@X1...XN ,Y1)
                  (natp ,Y1))
                (<= (,F ,@X1...XN) ,Y1))
              :hints (("Goal" :by ,F-LEQ-WHEN-EXISTSP-LINEAR))))
          (defthm ,F-LEQ-WHEN-EXISTSP-REWRITE
            (implies (and (,EXISTSP ,@X1...XN)
                (,UBOUNDP ,@X1...XN ,Y1)
                (natp ,Y1))
              (<= (,F ,@X1...XN) ,Y1)))
          (in-theory (disable ,F))))
      (existsp-when-non-empty-and-bounded-events `((local (defthm ,UBOUND-GEQ-MEMBER
             (implies (and (natp ,Y0)
                 (,ELEMENTP ,@X1...XN ,Y0)
                 (natp ,Y1)
                 (,UBOUNDP ,@X1...XN ,Y1))
               (>= ,Y1 ,Y0))
             :rule-classes nil
             :hints (("Goal" :use (:instance ,UBOUNDP-NECC (,Y ,Y1) (,Y1 ,Y0)))))) (local (defthm ,UBOUND-NONMEMBER-GT-MEMBER
              (implies (and (natp ,Y0)
                  (,ELEMENTP ,@X1...XN ,Y0)
                  (natp ,Y1)
                  (,UBOUNDP ,@X1...XN ,Y1)
                  (not (,ELEMENTP ,@X1...XN ,Y1)))
                (> ,Y1 ,Y0))
              :rule-classes nil
              :hints (("Goal" :use ,UBOUND-GEQ-MEMBER))))
          (local (defun ,FIND-MAX
              (,@X1...XN ,Y1 ,Y0)
              (declare (xargs :hints (("Goal" :use ,UBOUND-NONMEMBER-GT-MEMBER))))
              (if (and (natp ,Y0)
                  (,ELEMENTP ,@X1...XN ,Y0)
                  (natp ,Y1)
                  (,UBOUNDP ,@X1...XN ,Y1))
                (if (,ELEMENTP ,@X1...XN ,Y1)
                  ,Y1
                  (,FIND-MAX ,@X1...XN (1- ,Y1) ,Y0))
                0)))
          (local (defthm ,FIND-MAX-UBOUNDP-PRESERVATION
              (implies (and (natp ,Y0)
                  (,ELEMENTP ,@X1...XN ,Y0)
                  (natp ,Y1)
                  (,UBOUNDP ,@X1...XN ,Y1)
                  (not (,ELEMENTP ,@X1...XN ,Y1)))
                (,UBOUNDP ,@X1...XN (1- ,Y1)))
              :hints (("Goal" :expand ((,UBOUNDP ,@X1...XN (1- ,Y1)))
                 :use (:instance ,UBOUNDP-NECC
                   (,Y ,Y1)
                   (,Y1 (,UBOUNDP-WITNESS ,@X1...XN (1- ,Y1))))))))
          (local (defthm ,ELEMENTP-OF-FIND-MAX
              (implies (and (natp ,Y0)
                  (,ELEMENTP ,@X1...XN ,Y0)
                  (natp ,Y1)
                  (,UBOUNDP ,@X1...XN ,Y1))
                (,ELEMENTP ,@X1...XN (,FIND-MAX ,@X1...XN ,Y1 ,Y0)))
              :hints ('(:use (:instance ,UBOUNDP-NECC (,Y ,Y1) (,Y1 0))) '(:use (:instance ,UBOUNDP-NECC (,Y 0) (,Y1 ,Y0))))))
          (local (defthm ,UBOUNDP-OF-FIND-MAX
              (implies (and (natp ,Y0)
                  (,ELEMENTP ,@X1...XN ,Y0)
                  (natp ,Y1)
                  (,UBOUNDP ,@X1...XN ,Y1))
                (,UBOUNDP ,@X1...XN (,FIND-MAX ,@X1...XN ,Y1 ,Y0)))
              :hints ('(:use (:instance ,UBOUNDP-NECC (,Y ,Y1) (,Y1 0))) '(:use (:instance ,UBOUNDP-NECC (,Y 0) (,Y1 ,Y0))))))
          (local (defthm ,EXISTSP-WHEN-NONEMPTY-AND-BOUNDED
              (implies (and (natp ,Y0)
                  (,ELEMENTP ,@X1...XN ,Y0)
                  (natp ,Y1)
                  (,UBOUNDP ,@X1...XN ,Y1))
                (,EXISTSP ,@X1...XN))
              :rule-classes nil
              :hints (("Goal" :use (:instance ,EXISTSP-SUFF (,Y (,FIND-MAX ,@X1...XN ,Y1 ,Y0)))))))
          (defthm ,EXISTSP-WHEN-NONEMPTY-AND-BOUNDED
            (implies (and (natp ,Y0)
                (,ELEMENTP ,@X1...XN ,Y0)
                (natp ,Y1)
                (,UBOUNDP ,@X1...XN ,Y1))
              (,EXISTSP ,@X1...XN))
            :rule-classes nil)))
      (equal-when-member-and-bound `((local (defthm ,EQUAL-WHEN-MEMBER-AND-UBOUND
             (implies (and (natp ,Y)
                 (,ELEMENTP ,@X1...XN ,Y)
                 (,UBOUNDP ,@X1...XN ,Y))
               (equal (,F ,@X1...XN) ,Y))
             :rule-classes nil
             :hints (("Goal" :in-theory (disable ,F-GEQ-WHEN-EXISTSP-REWRITE)
                :use ((:instance ,EXISTSP-WHEN-NONEMPTY-AND-BOUNDED
                   (,Y0 ,Y)
                   (,Y1 ,Y)) (:instance ,F-GEQ-WHEN-EXISTSP-REWRITE (,Y1 ,Y))
                  (:instance ,UBOUNDP-NECC (,Y1 (,F ,@X1...XN)))))))) (defthm ,EQUAL-WHEN-MEMBER-AND-UBOUND
            (implies (and (natp ,Y)
                (,ELEMENTP ,@X1...XN ,Y)
                (,UBOUNDP ,@X1...XN ,Y))
              (equal (,F ,@X1...XN) ,Y))
            :rule-classes nil))))
    `(encapsulate nil
      (set-verify-guards-eagerness 0)
      ,@ELEMENTP-EVENTS
      ,@UBOUNDP-EVENTS
      ,@EXISTSP-EVENTS
      ,@F-EVENTS
      ,@EXISTSP-WHEN-NON-EMPTY-AND-BOUNDED-EVENTS
      ,@EQUAL-WHEN-MEMBER-AND-BOUND)))
other
(define defmax-nat-fn
  (f y x1...xn body guard verify-guards ctx state)
  :returns (mv erp (event "A @(tsee pseudo-event-formp).") state)
  :mode :program :parents (defmax-nat-implementation)
  :short "Process the inputs and generate the event to submit."
  (b* (((er &) (defmax-nat-process-inputs f
         y
         x1...xn
         body
         guard
         verify-guards
         ctx
         state)) (event (defmax-nat-gen-everything f
          y
          x1...xn
          body
          guard
          verify-guards)))
    (value event)))
other
(defsection defmax-nat-macro-definition
  :parents (defmax-nat-implementation)
  :short "Definition of the @(tsee defmax-nat) macro."
  :long (topstring (p "Submit the event generated by @(tsee defmax-nat-fn).")
    (@def "defmax-nat"))
  (defmacro defmax-nat
    (f y x1...xn body &key (guard 't) (verify-guards 't))
    `(make-event (defmax-nat-fn ',F
        ',Y
        ',X1...XN
        ',BODY
        ',GUARD
        ',VERIFY-GUARDS
        (cons 'defmax-nat ',F)
        state))))