+ =====================================================================	+
| LIBRARY	: decision						|
|									|
| DESCRIPTION   : Co-operating decision procedures.			|
|									|
| AUTHOR	: R.J.Boulton						|
| DATE		: 1995							|
|									|
| MODIFIED      : R.J.Boulton						|
| DATE		: 3 September 1996					|
+ =====================================================================	+

The decision library contains co-operating decision procedures for
quantifier-free formulas built up from linear natural number arithmetic,
propositional logic, and the equational theories of pairs, recursive types,
and uninterpreted function symbols. Subterms from other theories may also
be accepted if they do not contribute to the truth of the formula. Formulas
that when placed in prenex normal form contain only universal quantifiers
are accepted in addition to quantifier-free formulas. The procedure is
based on the approach of Nelson and Oppen:

   G. Nelson and D. C. Oppen
   "Simplification by Cooperating Decision Procedures"
   ACM Transactions on Programming Languages and Systems, 1(2):245-257,
   October 1979.

The procedure either proves that the formula is equal to false or raises an
exception. There is some incompleteness in the procedures. Properties of
the natural numbers that depend fundamentally on the discreteness of the
naturals are not proved. Nor are acyclicity properties of recursive types
(e.g. lists). There is also much scope for improvements to the efficiency.

The most important ML structure for the procedure is DecisionUser which
contains the following identifiers:

   DECIDE_CONV : conv
   DECIDE : term -> thm
   DECIDE_TAC : tactic
   DECISION_TAC : conv -> (term -> bool) -> tactic
   show_proving : bool ref

(The type `conv' is an abbreviation for `term -> thm'.)

DECIDE_CONV is the main decision procedure. It takes a term t and attempts
to prove the theorem |- t = T, where T is the truth value true. DECIDE is a
variant of DECIDE_CONV that proves |- t instead of |- t = T.

DECIDE_TAC is a tactic that uses DECIDE_CONV to attempt to prove the
conclusion of the current goal in the context of any assumptions that are
free of lambda abstractions (and hence of quantifiers). To select different
assumptions use `DECISION_TAC DECIDE_CONV p' where p is a predicate that
returns true when applied to the required assumptions.

The procedure normalizes the negation of the formula to be proved and then
attempts to prove that the result is false. To see the formulas the
procedure is trying to refute and the equations between variables that are
exchanged by the component procedures, set the reference variable
show_proving to true.

Initially lists are the only recursive type handled by the procedure, but
it may be extended to handle the equational theories of types defined using
the HOL define_type function, including selectors (e.g. HD and TL for lists)
and discriminators (e.g. NULL) defined for such types. Amongst others, the
structure DecideTypes contains the following identifiers:

   add_type : thm HOLTypeInfo.hol_type_info -> unit
   delete_type : string -> unit

The function add_type extends the decision procedure with a new type. The
function delete_type removes the named type from the procedure. The type
information required by add_type can be obtained using the following
function in the structure HOLTypeInfo:

   define_type_info : {name : string,
                       type_spec : term frag list,
                       fixities : fixity list,
                       selectors : (string * string list) list,
                       discriminators : (string * string) list}
                      -> thm hol_type_info

The fields `name', `type_spec', and `fixities' of the argument are identical
to those of the HOL define_type function. The other fields specify the names
of the selector and discriminator functions. Each is a list of pairs in
which the first component should be the name of one of the constructors.

The function assumes that there are no selectors for a constructor that
doesn't appear in the list, so it is not necessary to include an entry for
a nullary constructor. For other constructors there must be one selector
name for each argument and they should be given in the correct order. The
function ignores any item in the list with a constructor name that does not
belong to the type. The discriminators are optional. The constructor,
selector and discriminator names must all be distinct.

Here is an example, a type of Lisp s-expressions:

   define_type_info
      {name = "sexp",
       type_spec = `sexp = Nil | Atom of 'a | Cons of sexp => sexp`,
       fixities = [Prefix,Prefix,Prefix],
       selectors = [("Atom",["Tok"]),("Cons",["Car","Cdr"])],
       discriminators = [("Nil","Nilp"),("Atom","Atomp"),("Cons","Consp")]};

Ideally, define_type_info should be used in place of define_type. It then
defines the type and the selectors and discriminators, and returns the type
information required by the decision procedure. However, if the type has
already been defined, define_type_info attempts to extract the type
information from the current theory hierarchy.

For details of the implementation of the decision procedure, see the
following paper:

   R. J. Boulton
   "Combining Decision Procedures in the HOL System"
   In E. T. Schubert, P. J. Windley and J. Alves-Foss (editors),
   "Proceedings of the 8th International Workshop on Higher Order Logic
    Theorem Proving and Its Applications", Aspen Grove, UT, USA,
   September 1995, pages 75-89. Volume 971 of Lecture Notes in Computer
   Science, Springer-Verlag.

Some examples can be found in the file examples.sml in this directory.

