Declaratively define the maximum of a set of natural numbers.
This macro captures the mathematical notation
This macro introduces such a function,
from a user-supplied term that represents
Besides the function itself, this macro introduces auxiliary functions and theorems upon which the function definition is based, as well as theorems about the function. It also introduces theorems to help reason about the function, in particular to establish that the maximum exists without having to calculate it explicitly, and to establish that the maximum is a certain value.
See defmin-int for a related tool.
(defmax-nat f y (x1 ... xn) body :guard ... ; default t :verify-guards ... ; default t )
Name of the function to introduce.
Name of the variable to use as
y .This is the variable bound in the set comprehension of the mathematical notation shown above. Note that the syntax of
defmax-nat is similar to the syntax of defchoose in this respect.
List of the names of the zero or more variables to use as
x_1,\ldots,x_n .These are the formal parameters of
f .
Term to use as the formula
\psi[x_1,\ldots,x_n,y] .Its only free variables must be among
x1 , ...,xn , andy .We write this term as
body<x1,...,xn,y> , emphasizing its dependence on the variables.
Term to use as the guard of
f .Its only free variables must be among
x1 , ...,xn .Let
guard<x1,...,xn> be this term, emphasizing its dependence on the variables.
Determines whether the guards of
f , and of the auxiliary functions generated, should be verified or not.
The current implementation of this macro does not thoroughly validate its inputs, but errors caused by the generated functions and theorems should be relatively easy to debug, based on the documentation below, and possibly on the examination of the implementation, which uses a readable backquote notation. Nonetheless, the implementation of this macro may be improved in the future to validate its inputs more thoroughly.
See the file
Except for
Auxiliary function to test the membership of
y in the set defined byx1 , ...,xn .(defun f.elementp (x1 ... xn y) (declare (xargs :guard (and guard<x1,...,xn> (natp y)))) body<x1,...,xn,y>)
Auxiliary predicate asserting that
y is an upper bound of the set defined byx1 , ...,xn , along with associated theorems.(defun-sk f.uboundp (x1 ... xn y) (declare (xargs :guard (and guard<x1,...,xn> (natp y)))) (forall (y1) (impliez (and (natp y1) (f.elementp x1 ... xn y1)) (>= (nfix y) y1))) :rewrite (implies (and (f.uboundp x1 ... xn y) (natp y1) (f.elementp x1 ... xn y1)) (>= (nfix y) y1))) (defthm booleanp-of-f.uboundp (booleanp (f.uboundp x1 ... xn y)))
Auxiliary predicate asserting that the set defined by
x1 , ...,xn has a maximum, along with associated theorems.(defun-sk f.existsp (x1 ... xn) (declare (xargs :guard guard<x1,...,xn>)) (exists (y) (and (natp y) (f.elementp x1 ... xn y) (f.uboundp x1 ... xn y)))) (defthm booleanp-of-f.existsp (booleanp (f.existsp x1 ... xn)))
The function that returns the maximum if it exists (otherwise
nil ), along with associated theorems.(defun f (x1 ... xn) (declare (xargs :guard guard<x1,...,xn>)) (if (f.existsp x1 ... xn) (f.existsp-witness x1 ... xn) nil)) (defthm maybe-natp-of-f (maybe-natp (f x1 ... xn))) (defthm natp-of-f-equal-f.existsp (equal (natp (f x1 ... xn)) (f.existsp x1 ... xn))) (defthm natp-of-f-when-f.existsp (implies (f.existsp x1 ... xn) (natp (f x1 ... xn))) :rule-classes :type-prescription) (defthm f-iff-f.existsp (iff (f x1 ... xn) (f.existsp x1 ... xn))) (defthm not-f-when-not-f.existsp (implies (not (f.existsp x1 ... xn)) (not (f x1 ... xn))) :rule-classes :type-prescription) (defthm f.elementp-of-f-when-f.existsp (implies (f.existsp x1 ... xn) (f.elementp x1 ... xn (f x1 ... xn)))) (defthm f.uboundp-of-f-when-f.existsp (implies (f.existsp x1 ... xn) (f.uboundp x1 ... xn (f x1 ... xn)))) (defthm f-geq-when-f.existsp-linear (implies (and (f.existsp x1 ... xn) (f.elementp x1 ... xn y1) ;; bind free y1 (natp y1)) (>= (f x1 ... xn) y1)) :rule-classes :linear) (defthm f-geq-when-f.existsp-rewrite (implies (and (f.existsp x1 ... xn) (f.elementp x1 ... xn y1) (natp y1)) (>= (f x1 ... xn) y1)) (defthm f-leq-when-f.existsp-linear (implies (and (f.existsp x1 ... xn) (f.uboundp x1 ... xn y1) ;; bind free y1 (natp y1)) (<= (f x1 ... xn) y1)) :rule-classes :linear) (defthm f-leq-when-f.existsp-rewrite (implies (and (f.existsp x1 ... xn) (f.uboundp x1 ... xn y1) (natp y1)) (<= (f x1 ... xn) y1))
The helper theorem to establish that the maximum exists by exhibiting a member and a bound of the set.
(defthm f.existsp-when-nonempty-and-bounded (implies (and (natp y0) (f.elementp x1 ... xn y0) (natp y1) (f.uboundp x1 ... xn y1)) (f.existsp x1 ... xn)) :rule-classes nil)
The helper theorem to establish that the maximum has a certain value by showing that that value is both a member and an upper bound of the set.
(defthm f.equal-when-member-and-ubound (implies (and (natp y) (f.elementp x1 ... xn y) (f.uboundp x1 ... xn y)) (equal (f x) y)) :rule-classes nil)
The current implementation of this macro does not attempt to generate robust proofs. The generated proofs may implicitly rely on rules that, if disabled, may cause the proofs to fail. However, the generated theorems should be always provable. The implementation of this macro will be improved in the future to generate more robust proofs.
This macro may be generalized from natural numbers to integer numbers, or to other suitably ordered domains.
Besides maxima and minima (also see defmin-int), similar macros could be introduced to declaratively define suprema and infima.