1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738
|
\newcommand{\AVM}[1]{\mbox{\em AVM--#1}}
\newcommand{\vb}[1]{\mbox{\tt #1}}
\chapter{The {\tt abs\_theory} Library}
A theory is a set of types, definitions, constants, axioms and parent
theories. Logics are extended by defining new theories. An abstract
theory is parameterized so that some of the types and constants in the
theory are undefined inside the theory except for their syntax and an
algebraic specification of their semantics. Group theory provides an
example of a abstract theory: the multiplication operator is undefined
except for its syntax (a binary operator on type \vb{:group}) and a
semantics given by the axioms of group theory.
Abstract theories are useful because they provide proofs about abstract
structures which can then be used to reason about specific instances of
those structures. In groups, for example, after showing that addition over
the integers satisfies the axioms of group theory, we can use the theorems
from group theory to reason about addition on the integers.
This report describes the use of abstract theories in the HOL theorem
prover~\cite{gordon1}. The current version of the abstract theory package
has evolved greatly since the original report was
published~\cite{windley:abs-old}.
\section{Abstract Theories.}
There are two key components of an abstract theory: (1) the {\em abstract
representation} and (2) the {\em theory obligations}. The {\em abstract
representation} is a set of abstract objects and a set of abstract
operations. The operations are unspecified; that is, we don't know (inside
the theory) what the objects and operations mean. Their meaning is
specified through the theory obligations: a set of predicates that define
relationships among members of the abstract representation. The abstract
theory describes a model. Any structure with objects and operations that
satisfy the predicates is a homomorphism of that model.
The theory obligations axiomatize the theory. Using the obligations as
axioms, we prove theorems of interest about the abstract objects and
operations. The goal is to use the abstract theory to reason about
specific objects by instantiating the abstract theory with a concrete
representation which has been shown to meet the obligations. The
instantiation specializes the abstract theorems, producing a set of
theorems about the concrete representation. The concrete representation is
an instance of the abstract theory and represents a {\em member} of the
class of abstract objects that it describes.
HOL, the verification environment used in the research reported here, does
not explicitly support abstract theories; however, HOL's metalanguage, ML,
combined with higher--order logic, provides a framework sufficient for
implementing abstract theories. Several specification and verification
systems, such as OBJ and EHDM, offer explicit support for abstract
theories. We briefly describe them for comparison.
\paragraph{OBJ.}
OBJ is a specification and programming language developed by Joseph
Goguen~\etal\ that has most recently been described in~\cite{obj-ref-man}.
OBJ is widely known and the semantics of its theories and views match our
use of abstract theories. OBJ is based on a many--sorted (or typed)
algebraic semantics and supports parameterized specification and
programming \cite{obj-param-prog}. OBJ has three kinds of entities:
\begin{enumerate}
\item
{\bf Objects}, which are concrete modules that encapsulate executable code,
\item
{\bf Theories}, which are parameterized modules that correspond to abstract
theories as used in this report, and
\item
{\bf Views}, which bind objects and theories to parameters in another
theory.
\end{enumerate}
Objects are said to contain executable code because the expressions in an
object module give the initial algebraic semantics of the sorts and
operations being defined. The fact that their semantics is initial implies
that they describe just one model (up to isomorphism). Theories, on the
other hand, are said to have a ``loose'' semantics since they define a
variety of models. A loose semantics describes a class of objects; any
member of that class will satisfy the theory.
A view is {\em not} an instantiation. Instantiation is done using a
special command, {\bf make}, after the view has been established. A view
can be seen as a mapping of the operators and objects from one module onto
a theory, as well as a declaration of intent that the module meets the
obligations set forth in the equations of the theory module. OBJ does not
require that the user prove that the obligations are met---a simple
declaration is sufficient. Of course, if the view is not proper, then the
OBJ program will not operate as intended.
\paragraph{EHDM.}
EHDM is a specification and verification system developed by SRI
International~\cite{ehdm:manual}. The language of EHDM is based on
first--order predicate logic, but includes some elements of higher--order
logic as well. For example, variables can range over functions, functions
can return other functions, and functions can appear in quantifications.
Parameterized modules are an important part of the EHDM language where they
are used to organize specifications. Modules can be parameterized with
types, constants, and functions. The module parameters can have
constraints placed on them that must be met before the module can be
instantiated.
In EHDM, a parameterized module is called a {\em generic module} and an
instantiation is called a {\em module instance}. EHDM module declarations
give the uninterpreted types, constants, and functions over which the
module is parameterized. This declaration is analogous to our abstract
representation.
The module body contains (among other things) an {\bf ASSUMING} clause that
gives the properties of the module parameters. The formulae in the {\bf
ASSUMING} clause are analogous to our theory obligations.
The module can also contain declarations of concrete types, constants, and
functions that define the theory associated with the module and proofs of
theorems about the abstract operations in the theory. These proofs may
rely on the formulae in the {\bf ASSUMING} clause.
\section{Using the Abstract Theory Package.}
This section briefly describes the major functions in the abstract theory
package. The following section provides an example of its use. Complete
descriptions of all the commands are given in the next chapter. For an
example of how abstract theories can be used in computer system
specification and verification see~\cite{windley:ah,windley:git}.
Before beginning an abstract theory, the ML file \vb{abs\_theory} must be
loaded. This defines the commands in the abstract package and modifies
some of the standard HOL commands to support its operation.
One declares a new abstract theory in the same way that one declares a
standard theory, using \vb{new\_theory}. One is free to use any of the
standard HOL commands for manipulating a draft theory in their usual
manner. For example, definitions are made in the usual way using
\vb{new\_definition}.
\subsection{Abstract Representations.}
The abstract representation describes the abstract objects and operators in
the abstract theory. The abstract theory package defines
\vb{new\_abstract\_representation} for declaring the abstract representation.
The function is applied to a string representing the name of the abstract
object and a list of string--type pairs. The first member of the pair
gives the name of the abstract operator and the second member of the pair
is the its type. Any number of abstract operators can be defined in an
abstract representation. One can use \vb{new\_abstract\_representation}
more than once in a single theory defining more than one abstract object.
The system does not require that abstract objects be specifically declared.
We represent abstract objects as type variables in HOL (denoted by a
prepended asterisk). Since HOL does not require that type variables be
declared, we are free to use them wherever we wish. The declaration of
abstract objects is implicit, being the set of type variables
occurring in the abstract representation.
The result of declaring a new abstract representation is a theorem that can
be saved to use with \vb{abs\_type\_info} to retrieve the type of the
abstract object when this is difficult to otherwise discern.
When one defines a constant in the abstract theory, by convention, the
first argument to the constant will be a variable with the same type as the
abstract representation. This variable must, in turn be the first argument
to any of the abstract constants from the abstract representation used in
the definition. Later, during instantiation, the definition will be
applied to a concrete representation and the instantiation functions will
replace the abstract constants with the appropriate concrete constants in
the instantiation.
\subsection{Theory Obligations.}
The theory obligations are declared using the ML function
\vb{new\_theory\_obligations}. The function takes a string--term
pair as its sole argument. The pair represents a theory obligation, giving
the name and the predicate defining the theory obligation. The pair can be
thought of as an axiom defining the semantics of the abstract objects.
The predicate is usually a conjunction of obligations. These obligations
will be available for use in the draft theory. The system will
automatically add them to the assumption list when the HOL commands for
declaring abstract goals and proving abstract theorems, such as
{\vb{set\_abs\_goal}} and \vb{prove\_abs\_thm}, are used. The HOL command
{\vb{close\_theory}} closes the current draft and flushes the theory
obligations.
\subsection{Instantiating Theories.}
One makes use of an abstract theory by instantiating it. The first step is
to make the abstract theory a parent of the draft theory using the ML
function \vb{new\_abstract\_parent}.
HOL theories differentiate between definitions and theorems and so there
is an ML function for instantiating each. Instantiating any abstract
object requires that we create a concrete representation. Concrete
representations are created by applying the name of the abstract object to
the concrete objects that are to be used for the instantiation.
\paragraph{Abstract Definitions.}
Abstract definitions are definitions which use the abstract objects from
the abstract representation. By convention, the first variable in an
abstract definition is the representation variable and has the same type as
the abstract representation. Creating a concrete definition from an
abstract one requires two steps:
\begin{enumerate}
\item
Make an auxiliary definition that uses the abstract definition and applies
it to a concrete representation.
\item
Use the ML function \vb{instantiate\_abstract\_definition} to produce a
concrete instance of the abstract definition from the auxiliary definition.
\end{enumerate}
The result of this instantiation is a theorem that defines a concrete
instance of the abstract definition and makes no reference to the abstract
definition.
\paragraph{Abstract Theorems.}
In drafting an abstract theory, one normally proves theorems about the
abstract representation using the theory obligations as axioms. When the
abstract theory is used, we instantiate the theorems in it so that the
theory obligations are discharged and the new concrete theorems stand on
their own.
The ML function \vb{instantiate\_abstract\_theorem} instantiates one
abstract theorem. The function takes four arguments:
\begin{enumerate}
\item
The name of the abstract theory where theorem reside.
\item
The name of the abstract theorem to instantiate.
\item
A list of term pairs that instantiate variables with concrete
representations. The first term in the pair is the variable to instantiate
and the second is the concrete representation.
\item
A list of theorems that satisfy the theory obligations in the subject
abstract theorem. These theorems discharge the antecedents of the abstract
theorems.
\end{enumerate}
The new theorem resulting from the instantiation is {\em not} automatically
saved in the current theory, but must be explicitly saved using
\vb{save\_thm}.
\section{Example: Group Theory}
This section demonstrates the major features of the abstract theory
package. We begin by defining an abstract theory for {\em monoids}. The
following section uses the theory of monoids to create a theory of {\em
groups}. The last section instantiates the theory of groups using
exclusive--or as the group operator.
\subsection{Defining Monoids}
A monoid is an algebra with a binary operator and an identity element. The
operator is associative and operating on the identity element with any
object in the algebra, $x$ yields that same object, $x$.
We begin the the session by loading the abstract theory package and
entering draft mode:
\begin{boxed}\begin{hol}\begin{alltt}
loadf `abs_theory`;;
new_theory `monoid_def`;;
\end{alltt}\end{hol}\end{boxed}
The abstract representation is declared using
{\vb{new\_abstract\_representation}}. We declare the binary operator,
{\vb{op}}, and an identity element, \vb{e}:
\begin{boxed}\begin{hol}\begin{alltt}\holthm{
let MONOID = new_abstract_representation `monoid`
[
(`op`,":* -> * -> *")
;
(`e`,":*")
];;
}\end{alltt}\end{hol}\end{boxed}
The abstract representation gives only the name and type of the operators.
A declaration of an abstract representation will almost always be followed
immediately by a declaration of the theory obligation since the abstract
representation introduces the structure of the abstract entity, but not the
semantics. The theory obligations declare the semantics (or axioms) for the
abstract entity. The theory obligations are contained in a predicate that
states the required properties of \vb{op} and \vb{e}:
\begin{boxed}\begin{hol}\begin{alltt}\holthm{
new_theory_obligations
(`IS_MONOID`,
"!m:(*)monoid . IS_MONOID m =
(!x:* .op m x (e m) = x) /\
(!x:* .op m (e m) x = x) /\
(! x y z:*. (op m x (op m y z)) = (op m (op m x y) z))");;
}
\end{alltt}\end{hol}\end{boxed}
Note that when \vb{op} and \vb{e} are used in a term, they always take as
their first argument a variable with the type of the abstract object.
While this is an implementational requirement, one can think of it as
identifying \vb{op} and \vb{e} as abstract operators and giving the
specific abstract object of which they are part. This last point is
important since some theorems may use more than one abstract object and the
abstract operators are differentiated by their argument (as shown in the
example below).
We will begin with an interactive proof that the identity element is
unique. We place the goal on the goal stack in the usual manner:
\begin{boxed}\begin{hol}\begin{alltt}\holthm{
g
"! (m:(*)monoid) (f:*) .
(!(a:*) .(op m a f = a) /\ (op m f a = a)) ==> (f = (e m))";;
}
\end{alltt}\end{hol}\end{boxed}
HOL responds with the goal. Note that the theory obligations are
automatically placed on the assumption list.
\begin{boxed}\begin{hol}\begin{alltt}\holthm{
"!f. (!a. (op m a f = a) /\ (op m f a = a)) ==> (f = e m)"
[ "!x y z. op m x(op m y z) = op m(op m x y)z" ]
[ "!x. op m(e m)x = x" ]
[ "!x. op m x(e m) = x" ]
}
\end{alltt}\end{hol}\end{boxed}
We begin by stripping the universally quantified variables and the
antecedent of the implication:
\begin{boxed}\begin{hol}\begin{alltt}\holthm{
e(
REPEAT STRIP_TAC
);;
OK..
"f = e m"
[ "!x y z. op m x(op m y z) = op m(op m x y)z" ]
[ "!x. op m(e m)x = x" ]
[ "!x. op m x(e m) = x" ]
[ "!a. (op m a f = a) /\ (op m f a = a)" ]
}
\end{alltt}\end{hol}\end{boxed}
We can specialize the antecedent that we just placed on the assumption list
with the identity element. Either conjunct can be used to solve the goal,
we'll use the first.\footnote{\vb{SYM\_RULE} is implemented as
\vb{CONV\_RULE SYM\_CONV}.}
\begin{boxed}\begin{hol}\begin{alltt}\holthm{
e(
ASSUME_TAC (
SYM_RULE (
CONJUNCT1 (
SPEC "e (m:(*)monoid)" (
ASSUME "!a. (op m a f = a) /\ (op m f a = a)"))))
);;
OK..
"f = e m"
[ "!x y z. op m x(op m y z) = op m(op m x y)z" ]
[ "!x. op m(e m)x = x" ]
[ "!x. op m x(e m) = x" ]
[ "!a. (op m a f = a) /\ (op m f a = a)" ]
[ "e m = op m(e m)f" ]
}
\end{alltt}\end{hol}\end{boxed}
The result of the last step can be substituted into the goal:
\begin{boxed}\begin{hol}\begin{alltt}\holthm{
e(
SUBST1_TAC ASSUME "e m = op m(e m)f"
);;
OK..
"f = op m(e m)f"
[ "!x y z. op m x(op m y z) = op m(op m x y)z" ]
[ "!x. op m(e m)x = x" ]
[ "!x. op m x(e m) = x" ]
[ "!a. (op m a f = a) /\ (op m f a = a)" ]
[ "e m = op m(e m)f" ]
}
\end{alltt}\end{hol}\end{boxed}
The result can be rewritten with the assumptions to solve the goal:
\begin{boxed}\begin{hol}\begin{alltt}\holthm{
e(
ASM_REWRITE_TAC []
);;
OK..
goal proved
. |- f = op m(e m)f
.. |- f = e m
.. |- f = e m
. |- !f. (!a. (op m a f = a) /\ (op m f a = a)) ==> (f = e m)
Previous subproof:
goal proved
}
\end{alltt}\end{hol}\end{boxed}
The interactive proof can be packaged up as a proof script:
\begin{boxed}\begin{hol}\begin{alltt}\holthm{
let IDENTITY_UNIQUE = ABS_TAC_PROOF
(([],"! (m:(*)monoid) (f:*) .
(!(a:*) .(op m a f = a) /\ (op m f a = a)) ==> (f = (e m))"),
REPEAT GEN_TAC
THEN STRIP_GOAL_THEN (\.thm .
SUBST1_TAC (
SYM_RULE (
CONJUNCT1 (
SPEC "e (m:(*)monoid)" thm))))
THEN ASM_REWRITE_TAC []
);;
}
\holthm{
IDENTITY_UNIQUE =
. |- !f. (!a. (op m a f = a) /\ (op m f a = a)) ==> (f = e m)
}
\end{alltt}\end{hol}\end{boxed}
The function \vb{ABS\_TAC\_PROOF} is like \vb{TAC\_PROOF} except that when
used on a goal with an abstract variable, the theory obligations are added
to the assumption list before the proof is started. If there is more than
one abstract variable the theory obligations are added to the assumption
list for each. The fact that the theory obligations are needed to
establish the theorem and are on the assumption list obviously influences
the style of proof. An example in the next section demonstrates how to
explicitly declare the obligations.
The next theorem gives an example that uses two abstract objects. The
theorem proves that if the operations for two monoids are the same then
their identity elements must be the same as well.
\begin{boxed}\begin{hol}\begin{alltt}\holthm{
let OP_DETERMINES_IDENTITY = ABS_TAC_PROOF
(([],
"! m1 (m2:(*)monoid) . (op m1 = (op m2)) ==> (e m1 = (e m2))"),
REPEAT STRIP_TAC
THEN let t1 = ASSUME "!x:*. op m1 (e m1) x = x" in
SUBST_TAC (map SYM_RULE [SPEC "e m2:*" t1])
THEN let t2 = ASSUME "!x:*. op m2 x (e m2) = x" in
SUBST_TAC (map SYM_RULE [SPEC "e m1:*" t2])
THEN ASM_REWRITE_TAC []
);;
}
\holthm{
OP_DETERMINES_IDENTITY = .. |- (op m1 = op m2) ==> (e m1 = e m2)
}
\end{alltt}\end{hol}\end{boxed}
In this example \vb{m1} and \vb{m2} are two distinct abstract objects. The
term \vb{(op m1)} represents the binary operation of monoid \vb{m1} and the
term \vb{(op m2)} represents the binary operation of monoid \vb{m2}. When
there is more than one abstract object in a goal, the abstract theory
package places theory obligations on the assumption list for each. Note
that the style of proof in this example is more goal oriented than the last
example even though, as in the last example, the goal is proven using the
assumptions.
\subsection{Defining Groups}
A group is a monoid extended with an inverse operator defined such that
when the binary operator is applied to any element and its inverse, the
identity element is the result.
To define a theory of groups, we take care of the usual front matter and
also declare \vb{monoids\_def} to be an abstract parent since we are going
to establish some properties of groups from our theory of monoids.
\begin{boxed}\begin{hol}\begin{alltt}
loadf `abs_theory`;;
new_theory `group_def`;;
new_abstract_parent `monoid_def`;;
\end{alltt}\end{hol}\end{boxed}
The call to \vb{new\_theory} clears the global theory obligation list.
\vb{new\_abstract\_parent} puts the theory obligations from
{\vb{monoid\_def}} on the theory obligation list.
The next step is to define the abstract representation:
\begin{boxed}\begin{hol}\begin{alltt}\holthm{
let GROUP = new_abstract_representation `group`
[
(`fn`,":* -> * -> *")
;
(`id`,":*")
;
(`inv`,":* -> *")
];;
}
\end{alltt}\end{hol}\end{boxed}
Note that we do not simply define the abstract representation for groups as
an extension to the representation for monoids. Without subtypes, the
implementation and use of extensions becomes too unwieldy. Also, since HOL
does not allow operator overloading, we had to give the operator and
identity element for groups different names from the operator and identity
element for monoids.
The theory obligations are those for monoids extended with two additional
facts for the inverse function:
\begin{boxed}\begin{hol}\begin{alltt}\holthm{
new_theory_obligations
(`IS_GROUP`,
"!g:(*)group . IS_GROUP g =
(!x:* .fn g x (id g) = x) /\
(!x:* .fn g (id g) x = x) /\
(!x:* .fn g x (inv g x) = (id g)) /\
(!x:* .fn g (inv g x) x = (id g)) /\
(! x y z:*. (fn g x (fn g y z)) = (fn g (fn g x y) z))");;
}\end{alltt}\end{hol}\end{boxed}
Again, because HOL does not have a notion of subtypes, we do not define the
theory obligations for groups in terms of the theory obligations for
monoids.
The connection between groups and monoids is established by the following
trivial theorem:
\begin{boxed}\begin{hol}\begin{alltt}\holthm{
let GROUP_EXTENDS_MONOID = ABS_TAC_PROOF
(([],
"! g:(*)group . IS_MONOID(monoid (fn g) (id g))"),
EXPAND_THOBS_TAC `monoid_def`
THEN ASM_REWRITE_TAC []
);;
}\holthm{
GROUP_EXTENDS_MONOID = ... |- IS_MONOID(monoid(fn g)(id g))
}
\end{alltt}\end{hol}\end{boxed}
The theorem states that the operator and identity element for groups can be
used in place of the operator and identity element for monoids. The tactic
{\vb{EXPAND\_THOBS\_TAC}} is used to expand the theory obligations for
monoids as the first step of the proof. The result is an abstract theorem
since it relies on the theory obligations of \vb{group\_def}.
We can make use of the fact that a group is a monoid by instantiating the
theorem that the identity is unique from \vb{monoid\_def}:
\begin{boxed}\begin{hol}\begin{alltt}\holthm{
let IDENTITY_UNIQUE =
instantiate_abstract_theorem `monoid_def` `IDENTITY_UNIQUE`
["m","monoid (fn (g:(*)group)) (id (g:(*)group))"]
[GROUP_EXTENDS_MONOID];;
}\holthm{
IDENTITY_UNIQUE =
... |- !f. (!a. (fn g a f = a) /\ (fn g f a = a)) ==> (f = id g)
}
\end{alltt}\end{hol}\end{boxed}
We instantiate the abstract representation variable \vb{"m"} with a
concrete (from the standpoint of \vb{monoid\_def}) representation made from
the operator and identity element of \vb{group\_def}. The theorem that a
group extends a monoid is used to discharge the theory obligations for
monoids. Note that the instantiated theorem must be explicitly saved on
the current theory.
The resulting theorem is really a theory about groups, not monoids, as can
be seen from the following check of the type of the abstract representation
variable \vb{"g"} in \vb{IDENTITY\_UNIQUE}:
\begin{boxed}\begin{hol}\begin{alltt}\holthm{
(type_of o hd o frees o concl o DISCH_ALL) IDENTITY_UNIQUE;;
":(*)group" : type
}\end{alltt}\end{hol}\end{boxed}
In addition to instantiating theorems from \vb{monoid\_def}, we can prove
theorems about groups directly. For example, we can prove that left
cancellation holds for groups:
\begin{boxed}\begin{hol}\begin{alltt}\holthm{
let LEFT_CANCELLATION = prove_abs_thm
(`LEFT_CANCELLATION`,
"! (g:(*)group) (x y a:*) .
((fn g) a x = ((fn g) a y)) ==> (x = y)",
REPEAT STRIP_TAC
THEN ACCEPT_TAC (
let t1 = (ASSUME "!x y z. fn g x(fn g y z) = fn g(fn g x y)z") and
t2 = (ASSUME "!x. fn g(inv g x)x = id g") and
t3 = (ASSUME "!x. fn g(id g) x = x") and
t4 = (ASSUME "fn g a x = fn g a y") in
SYM_RULE (
REWRITE_RULE [t1;t2;t3] (
REWRITE_RULE [t2;t3;t4] (
ISPECL ["(inv g a)";"a";"x"] t1))))
);;
}\holthm{
LEFT_CANCELLATION = ... |- !x y a. (fn g a x = fn g a y) ==> (x = y)
}
\end{alltt}\end{hol}\end{boxed}
In this case, we used \vb{prove\_abs\_thm}, so the the resulting theorem is
explicitly saved in the current theory.
Because some people may be uncomfortable with implicit theory obligations
and their automatic inclusion in the assumptions, the abstract theory
package supports explicit theory obligations as well. For example,
consider the following proof that the inverse function is reversible (that
is that the inverse operator applied twice is the identity function):
\begin{boxed}\begin{hol}\begin{alltt}\holthm{
let INVERSE_INVERSE_LEMMA = prove_thm
(`INVERSE_INVERSE_LEMMA`,
"!(g:(*)group) . IS_GROUP(g) ==> !a .(((inv g) ((inv g) a)) = a)",
STRIP_THOBS_TAC
THEN GEN_TAC
THEN ACCEPT_TAC (
let t1 = ASSUME "!x. fn g x(inv g x) = id g" and
t2 = ASSUME "!x. fn g (inv g x)x = id g" in
let LC_LEMMA =
ISPECL ["inv g (inv g a)";"a";"inv g a"] LEFT_CANCELLATION in
MATCH_MP LC_LEMMA
(TRANS (ISPEC "(inv g) a" t1)
(SYM_RULE (ISPEC "a" t2))))
);;
}\holthm{
INVERSE_INVERSE_LEMMA = |- !g. IS_GROUP g ==> (!a. inv g(inv g a) = a)
}
\end{alltt}\end{hol}\end{boxed}
In this case, we use the standard \vb{prove\_thm} function and so the
theory obligations were not automatically added to the assumption list.
The theory obligation are given explicitly as the antecedent to an
implication. The tactic {\vb{STRIP\_THOBS\_TAC}} is a convenient way to
strip explicit theory obligations from the goal and expand them on the
assumption list.
We can use a different proof style using the theorem continuation
{\vb{STRIP\_THOBS\_THEN}} for the same theorem:
\begin{boxed}\begin{hol}\begin{alltt}\holthm{
let ALTERNATE_INVERSE_INVERSE_LEMMA = TAC_PROOF
(([],
"!(g:(*)group) . IS_GROUP(g) ==> ! a .(((inv g) ((inv g) a)) = a)"),
STRIP_THOBS_THEN (\. thm .
let thl = CONJUNCTS thm in
MAP_EVERY ASSUME_TAC thl THEN
GEN_TAC THEN
MATCH_MP_TAC
(ISPECL ["inv g (inv g a)";"a";"inv g a"]
LEFT_CANCELLATION) THEN
REWRITE_TAC thl)
);;
}\holthm{
ALTERNATE_INVERSE_INVERSE_LEMMA =
|- !g. IS_GROUP g ==> (!a. inv g(inv g a) = a)
}\end{alltt}\end{hol}\end{boxed}
The only caveat to using {\vb{STRIP\_THOBS\_THEN}} is that the accompanying
theorem--tactic must put the theory obligations on the assumption list if
any other abstract theories are to be used. In this case, we use
{\vb{LEFT\_CANCELLATION}} and so the tactic {\vb{MAP\_EVERY ASSUME\_TAC
thl}} is used to add the theory obligations to the assumption list.
\subsection{Using Groups}
We can instantiate the theory of groups using exclusive--or as the
operator, false as the identity element, and the identity function as the
inverse operator. As usual, we load the abstract theory package, enter
draft mode, and declare \vb{groups\_def} an abstract parent.
\begin{boxed}\begin{hol}\begin{alltt}
loadf `abs_theory`;;
new_theory `example`;;
load_library `taut`;;
new_abstract_parent `group_def`;;
\end{alltt}\end{hol}\end{boxed}
Before we can instantiate the theorems of \vb{group\_def} we must show that
our proposed instantiation discharges the theory obligations:
\begin{boxed}\begin{hol}\begin{alltt}\holthm{
let GROUP_THOBS = TAC_PROOF
(([],"IS_GROUP(group (\.x y.~(x=y)) F I)"),
EXPAND_THOBS_TAC `group_def`
THEN BETA_TAC
THEN REWRITE_TAC [I_THM]
THEN TAUT_TAC
);;
}\end{alltt}\end{hol}\end{boxed}
Note that we have created our concrete representation using
{\vb{(group (\(\lambda\) x y. \(\lnot\)(x=y)) F I)}}.
Using {\vb{instantiate\_abstract\_theorem}}, we can instantiate the theorem
of group theory for our concrete representation. The abstract variable
{\vb{"g"}} is instantiated with our concrete representation.
\begin{boxed}\begin{hol}\begin{alltt}\holthm{
instantiate_abstract_theorem `group_def` `IDENTITY_UNIQUE`
["g","group (\.x y.~(x=y)) F I"]
[GROUP_THOBS];;
|- !f. (!a. (~(a = f) = a) /\ (~(f = a) = a)) ==> ~f
instantiate_abstract_theorem `group_def` `LEFT_CANCELLATION`
["g","group (\.x y.~(x=y)) F I"]
[GROUP_THOBS];;
|- !x y a. (~(a = x) = ~(a = y)) ==> (x = y)
instantiate_abstract_theorem `group_def` `INVERSE_INVERSE_LEMMA`
["g","group (\.x y.~(x=y)) F I"]
[GROUP_THOBS];;
|- !a. I(I a) = a
}
\end{alltt}\end{hol}\end{boxed}
The instantiation is done in the same way regardless of whether the theory
obligations for the abstract theorems were explicitly stated or not.
\begin{thebibliography}{EHD88}
\bibitem[EHD88]{ehdm:manual}
SRI International Computer Science Laboratory.
\newblock {\em {EHDM} Specification and Verification System: User's Guide, {\rm
Version 4.1}}, 1988.
\bibitem[Gog84]{obj-param-prog}
J.~Goguen.
\newblock Parameterized programming.
\newblock {\em IEEE Transactions on Software Engineering}, SE-10(5):528--543,
September 1984.
\bibitem[Gor88]{gordon1}
Michael~J.C. Gordon.
\newblock {HOL}: A proof generating system for higher-order logic.
\newblock In G.~Birtwhistle and P.A Subrahmanyam, editors, {\em {VLSI}
Specification,Verification, and Synthesis}. Kluwer Academic Press, 1988.
\bibitem[GW88]{obj-ref-man}
J.~Goguen and T.~Winkler.
\newblock Introducing \mbox{OBJ3}.
\newblock Technical Report SRI-CSL-88-9, SRI International, August 1988.
\bibitem[Win90]{windley:abs-old}
Phillip~J. Windley.
\newblock A poor man's implementation of abstract theories.
\newblock Technical Report CSE-90-06, University of California, Davis, Division
of Computer Science, 1990.
\bibitem[Win91]{windley:ah}
Phillip~J. Windley.
\newblock Abstract hardware.
\newblock In {\em Proceedings of the {ACM/SIGDA} International Workshop in
Formal Methods in {VLSI} Design}, January 1991.
\bibitem[Win92]{windley:git}
Phillip~J. Windley.
\newblock A theory of generic interpreters.
\newblock Technical Report LAL-92-06, University of Idaho, Laboratory for
Applied Logic, April 1992.
\end{thebibliography}
|