LP works efficiently on large problems, has many important user amenities, and can be used by relatively naive users. It was developed by Stephen J. Garland and John V. Guttag at the MIT Laboratory for Computer Science. It is currently maintained by Stephen J. Garland.
For a general introduction to LP, see the following topics.
The entire set of pages describing LP is also available as a single, printable document.
LP works efficiently on large problems, has many important user amenities, and can be used by relatively naive users. It was developed by Stephen J. Garland and John V. Guttag at the MIT Laboratory for Computer Science. It is currently maintained by Stephen J. Garland.
For a general introduction to LP, see the following topics.
The entire set of pages describing LP is also available as a single, printable document.
Because conjectures are often flawed, LP is not designed to find difficult proofs automatically. For example, LP does not use heuristics to formulate additional conjectures that might be useful in a proof. Instead, LP makes it easy for users to employ standard techniques such as simplification and proofs by cases, induction, and contradiction, either to construct proofs or to understand why they have failed.
LP also provides support for rechecking proofs following changes in axioms, conjectures, or proof strategies. This support assists users in regression testing during proof construction: when users discover they must change a formalization in order to establish some conjecture, regression testing ensures that the change does not invalidate previously constructed proofs. This support also promotes proof re-use: users can edit old proofs to prove new conjectures, and LP will check that the progress of the proof stays ``in sync'' with the users' intentions.
LP is a command-driven system. The last line of LP's welcoming message, LP1:, is a prompt for the first command. LP prompts users to enter subsequent commands with LP2:, LP3:, ...Welcome to LP (the Larch Prover), Release 3.1 (94/12/30). Copyright (C) 1994, S. J. Garland and J. V. Guttag Type `help lp' (followed by a carriage return) for help. LP1:
You can type input directly in response to LP's prompts, or you can create a file of LP commands (e.g., set1.lp) and then use LP's execute command to cause LP to execute the commands in that file as if you had typed them directly. Here's the start of a session in which commands are executed from the file set1.lp:
The first command, execute set1, was typed by the user. The second was obtained from the file set1.lp. This command is a comment: LP ignores all input following a percent sign. The prompts LP1.1: and LP1.2: indicate that LP is taking input from the file being executed as a result of the command entered in response to the prompt LP1:.LP1: execute set1 LP1.1: % Some simple theorems about finite sets LP1.2:
declare sorts E, S
declare variables e, e1, e2: E, x, y, z: S
declare operators
{}: -> S
{__}: E -> S
insert: E, S -> S
__ \union __: S, S -> S
__ \in __: E, S -> Bool
__ \subseteq __: S, S -> Bool
..
The first declare command introduces names for two sorts,
E and S. LP predefines the boolean sort Bool.
The second command introduces variables ranging over E and S. These variables will be used when stating axioms and conjectures.
The third command introduces symbols for the operators whose properties we will axiomatize. This command uses LP's multi-line input convention: if the arguments for a command do not fit on the line containing the command, they can be given on subsequent lines. Two periods (..) mark the end of the command.
The declaration for each operator specifies sorts for the operator's arguments and the sort of its result. Operators like {} with no arguments are constants. Operators like insert are used in functional notations like insert(e, x). The placeholders in operators like {__} and __\in__ indicate where their arguments belong in notations like {e} and e \in x.
set name setAxioms
assert
sort S generated by {}, insert;
{e} = insert(e, {});
~(e \in {});
e \in insert(e1, x) <=> e = e1 \/ e \in x;
{} \subseteq x;
insert(e, x) \subseteq y <=> e \in y /\ x \subseteq y;
e \in (x \union y) <=> e \in x \/ e \in y
..
set name extensionality
assert \A e (e \in x <=> e \in y) => x = y
The set command directs LP to assign the names
setAxioms.1, setAxioms.2, ... to the axioms introduced by the
subsequent assert commands. When multiple axioms are asserted in a
single command, they are separated by semicolons.
The axioms are formulated using declared symbols (for sorts, variables, and operators) together with logical symbols for equality (=), negation (~), conjunction (/\), disjunction (\/), implication (=>), logical equivalence (<=>), and universal quantification (\A). LP also provides a symbol for existential quantification (\E). LP uses a limited amount of \llink{precedence} when parsing formulas: for example, the logical operator <=> binds less tightly than the other logical operators, which bind less tightly than the equality operator, which bind less tightly than declared operators like \in and \union.
The axioms in set1.lp fall into several categories:
set name setTheorems
prove e \in {e}
prove \E x \A e (e \in x <=> e = e1 \/ e = e2)
prove x \union {} = x
prove x \union insert(e, y) = insert(e, x \union y)
prove ac \union
prove e \in x /\ x \subseteq y => e \in y
prove x \subseteq y /\ y \subseteq x => x = y
prove (x \union y) \subseteq z <=> x \subseteq z /\ y \subseteq z
prove sort S generated by {}, {__}, \union
prove x \subseteq (x \union y)
prove x \subseteq x
Except for the fourth, the sample conjectures are like the sample axioms: they
are either formulas or induction rules. The fourth, ac \union, is an
abbreviation for the conjunction of the
associative and commutative laws for the \union
operator. It provides LP with useful operational information. For example, it
allows LP to conclude that {} \union x is the same set as x \union {};
hence the third conjecture shows that both of these sets are the same as x.
The order in which we have stated these conjectures is not completely arbitrary. As we shall see, some of them are used to prove conjectures appearing later in the list.
set name setTheorems
prove e \in {e}
qed
The prove command directs LP to initiate the proof of a conjecture, and
the qed command directs LP to confirm that its proof is complete. LP
proves this conjecture automatically by using the user-supplied axioms as
rewrite rules. When using a formula as a rewrite rule,
either LP rewrites terms matching the entire formula to
true or, when the principal connective of the formula is = (equals)
or <=> (if and only if), LP rewrites terms matching the left side of the
formula to terms matching the right. Occasionally LP will reverse the order of
terms in an equality to ensure that the resulting set of rewrite rules does not
produce nonterminating (i.e., infinite) rewriting sequences. Here's how LP
proves the first conjecture:
e \in {e} ~> e \in insert(e, {}) by setAxioms.2
~> e = e \/ e \in {} by setAxioms.4
~> true \/ e \in {} by a hardwired axiom for =
~> true by a hardwired axiom for \/
Most proofs require user guidance. For example, to prove that for any two
elements e1 and e2, there is a set that contains exactly these two
elements, the user must provide a ``witness'' for the existential quantifier in
the second conjecture:
prove \E x \A e (e \in x <=> e = e1 \/ e = e2)
resume by specializing x to insert(e2, {e1})
qed
Users can specify a proof method for a conjecture either as
part of the prove command or in a separate resume command,
which continues the proof of the conjecture.
prove x \union {} = x
instantiate y by x \union {} in extensionality
qed
The instantiate command directs LP to form the substitution instance
\A e (e \in x <=> e \in x \union {}) => x = x \union {}
of the fact name extensionality. LP rewrites this formula automatically
to
\A e (e \in x <=> e \in x \/ e \in {}) => x = x \union {}
using the definition of \union, then to
\A e (e \in x <=> e \in x \/ false) => x = x \union {}
using the definition of \in, and then successively to
\A e (e \in x <=> e \in x) => x = x \union {}
\A e (true) => x = x \union {}
true => x = x \union {}
x = x \union {}
using LP's hardwired axioms. LP orients this final simplification into the
rewrite rule x \union {} -> x, which it uses to simplify the conjecture to
true.
Two other theorems about union can also be proved by instantiating the extensionality axiom. Both proofs are left as exercises to the reader.
prove x \union insert(e, y) = insert(e, x \union y) prove ac \union
prove x \union {} = x by contradiction
critical-pairs *Hyp with extensionality
qed
The prove command directs LP to begin an attempt to prove the
conjecture by contradiction. LP does this by adding the negation,
~(xc \union {} = xc), of the conjecture as a hypothesis to its logical
system. It replaces the variable x in the conjecture by the constant
xc, because the negation of a conjecture about all sets x is a
statement about some particular set xc. LP also orients this new
hypothesis into a rewrite rule, xc \union {} = xc -> false.
The critical-pairs command directs LP to use the rewrite rule obtained from this new hypothesis, whose name setTheoremsContraHyp.1 matches the pattern *Hyp, together with that obtained from the fact whose name matches extensionality, to enlarge its set of rewrite rules. LP does this by finding a term that can be rewritten in two different ways by the two rewrite rules and then asserting that these two terms must be equal. LP finds such a term by unifying the left side of one rewrite rule with a subterm of the left side of the other. Here, LP unifies the left side of the hypothesized rewrite rule with a subterm of the extensionality principle (by mapping x to xc \union {} and y to xc) to obtain the formula
\A e (e \in (xc \union {}) <=> e \in xc) => xc \union {} = xc
The extensionality axiom rewrites this formula to true, whereas the
hypothesized rewrite rule rewrites it to
\A e (e \in (xc \union {}) <=> e \in xc) => false
Hence these two results must be equivalent:
\A e (e \in (xc \union {}) <=> e \in xc) => false <=> true
As in our first proof of the conjecture, this formula rewrites to
true => false <=> true, which rewrites to false using LP's hardwired
axioms. This inconsistency finishes the proof by
contradiction.
The file set1.lp uses this technique to prove the second and third theorems about union.
set proof-methods normalization, =>
prove e \in x /\ x \subseteq y => e \in y by induction on x
resume by case ec = e1c
complete
qed
The set command directs LP to use an automatic proof technique whenever
the user does not specify one explicitly. Here, it directs LP to try to prove
conjectures first by rewriting, and then to assume the hypotheses of
implications and try again. This setting for proof-methods is a good
alternative to the standard setting, which consists of normalization
alone.
Creating subgoals for proof by structural induction on `x'
Basis subgoal:
Subgoal 1: e \in {} /\ {} \subseteq y => e \in y
Induction constant: xc
Induction hypothesis:
setTheoremsInductHyp.1: e \in xc /\ xc \subseteq y => e \in y
Induction subgoal:
Subgoal 2: e \in insert(e1, xc) /\ insert(e1, xc) \subseteq y => e \in y
LP proves the basis subgoal automatically by rewriting the term e \in {} to
false, but it needs further guidance to prove the induction subgoal.
Creating subgoals for proof of =>
New constants: e1c, ec, yc
Hypothesis:
setTheoremsImpliesHyp.1:
(ec = e1c \/ ec \in xc) /\ e1c \in yc /\ xc \subseteq yc
Subgoal:
ec \in yc
The hypothesis for this subgoal is the result of reducing the hypothesis of the
implication in the induction subgoal, after replacing its variables by new
constants.
LP finishes the first case by using the case hypothesis to rewrite the subterm ec of the subgoal ec \in yc to e1c; then it rewrites e1c \in yc to true using the second conjunct of the implication hypothesis.Creating subgoals for proof by cases Case hypotheses: setTheoremsCaseHyp.1.1: ec = e1c setTheoremsCaseHyp.1.2: ~(ec = e1c) Same subgoal for all cases: ec \in yc
In the second case, LP uses the case hypothesis and its hardwired rules to rewrite the first conjunct of the implication hypothesis to ec \in xc, at which point it gets stuck. The complete command directs LP to use what it knows to finish the proof by deriving a few critical-pair equations. First, LP derives xc \subseteq y => ec \in y as critical pair between ec \in xc and the induction hypothesis . Then it obtains ec \in yc as a critical pair between this fact and the last conjunct of the implication hypothesis. This finishes the proof by cases, the proof of the implication for the induction step of the conjecture, and the proof of the conjecture itself.
prove x \subseteq y /\ y \subseteq x => x = y
prove e \in xc <=> e \in yc by <=>
complete
complete
instantiate x by xc, y by yc in extensionality
qed
In the second, LP fills in all the details in a proof by induction without
requiring further guidance from the user.
prove (x \union y) \subseteq z <=> x \subseteq z /\ y \subseteq z by induction on x qed
prove sort S generated by {}, {__}, \union
resume by induction
set name lemma
critical-pairs *GenHyp with *GenHyp
critical-pairs *InductHyp with lemma
qed
LP formulates an appropriate subgoal for the proof of this conjecture, together
with additional hypotheses to be used in the proof, using a new operator
isGenerated:
Creating subgoals for proof of induction rule
Induction subgoal hypotheses:
setTheoremsGenHyp.1: isGenerated({})
setTheoremsGenHyp.2: isGenerated({e})
setTheoremsGenHyp.3:
isGenerated(s) /\ isGenerated(s1) => isGenerated(s \union s1)
Induction subgoal:
isGenerated(s)
The user then directs LP to attempt to prove isGenerated(s) by induction
(on s) using the asserted induction rule. LP proves the basis subgoal
automatically using the hypothesis isGenerated({}). The user guides the
proof of the induction subgoal by causing LP to compute critical pairs. The
first critical-pairs command causes LP to derive
as a critical pair between the second and third isGenerated hypotheses. The second critical-pairs command causes LP to derive the induction subgoal, isGenerated(insert(e, sc)), as a critical pair between this lemma and the induction hypothesis. This finishes the proof of the induction rule.lemma.1: isGenerated(s) => isGenerated(insert(e, s))
The prove command directs LP to use the induction rule just proved to formulate subgoals for the proof by induction using the generators {}, {__}, and \union instead of the generators {} and insert:prove x \subseteq (x \union y) by induction on x using setTheorems qed
Creating subgoals for proof by structural induction on `x'
Basis subgoals:
Subgoal 1: {} \subseteq ({} \union y)
Subgoal 2: {e} \subseteq ({e} \union y)
Induction constants: xc, xc1
Induction hypotheses:
setTheoremsInductHyp.1: xc \subseteq (xc \union y)
setTheoremsInductHyp.2: xc1 \subseteq (xc1 \union y)
Induction subgoal:
Subgoal 3: (xc \union xc1) \subseteq (xc1 \union xc \union y)
LP establishes all three subgoals automatically.
Finally, we prove the last theorem by directing LP to compute a critical pair between the theorem just established and an earlier theorem, x \union {} = x.
prove x \subseteq x critical-pairs setTheorems with setTheorems qed
display proof to see the current subgoal display *Hyp to see the current hypotheses display to see all facts history to see how you got where you are
<term> ::= <simpleId> | <simpleId> "(" <term>+, ")"
that are interpreted according to the following conventions to mean that a
<term> is either a simple identifier or a simple identifier followed by
a parenthesized list of terms separated by commas.
A <number> is a <simpleId> consisting entirely of digits. See also keyword.
The keywords to and with cannot be used as names for facts, or as components of a name pattern.
LP reserves other words (ac, commutative, depth, on, sort, using and well) in certain contexts within facts and conjectures, but does not prohibit their use as identifiers.
in response to LP's command prompt, or you can type an abbreviation of the command without any arguments and await a further prompt:set display-mode
In response to this prompt, you can typeLP1: set display The current display-mode is `unambiguous'. New display-mode:
Legal display modes: qualified unambiguous unqualified
Commands that require a possibly lengthy argument allow you to enter it on more than one line. To do this, don't type the argument on the command line; instead, type it on the following lines, terminating your input with a line consisting of two periods (..). For example,
If you need help in the middle of typing a lengthy argument, type a question mark on a line by itself.LP1: declare sort Nat LP2: declare operators Please enter operator declarations, terminated with a `..' line, or `?' for help: 0: -> Nat s: Nat -> Nat ..
LP also allows users to abbreviate certain command arguments with unambiguous prefixes. When the argument can be a hyphenated word, it is enough to supply unambiguous prefixes of the hyphenated components. Examples:
When an argument to a command can contain reserved words (such as formulas) and names of facts, abbreviations used for reserved words must not conflict with any name-prefix established by the set command. For example, disp form is a legal abbreviation for the command display formulas unless the user has previously entered the command set name form, in which case LP interprets disp form as a request to display all facts whose name begins with the prefix form rather than to display all facts that are formulas.Command Abbreviation ------- ------------ declare operators 0, 1: -> Nat dec op 0, 1: -> Nat display rewrite-rules dis r-r
<sort> ::= <simple-sort> | <compound-sort> <simple-sort> ::= <simpleId> <compound-sort> ::= <simpleId> "[" <sort>+, "]"
Nat Set[Nat] Map[Set[A],A]
All sorts other than Bool must be declared in a declare sorts command. Except for Bool and bool, which denote the same sort, case is significant in sort identifiers. Thus Nat and nat are different sorts.
Since distinct sorts represent disjoint sets of objects, users who want to consider one ``sort'' (e.g., Nat) as a subset of another (e.g., Int) must resort to one of two devices. They can define the larger as a sort and the smaller by means of a unary predicate (e.g., isNat:Int->Bool). Alternatively, they can define both as sorts and introduce a mapping from one into the other (e.g., asInt:Nat->Int).
<variable> ::= <variableId> [ : <sort> ] <variableId> ::= <simpleId>
x x:Int committee: Set[Person]
The same <variableId> can be overloaded to name two different variables, that is, two variables with different sorts. It can also be used to name a variable and an operator, provided the operator is not a constant of the same sort. LP uses context to disambiguate overloaded identifiers.
At times (e.g., when computing critical pairs or when proving an induction rule), LP creates variables, the identifiers for which consist of the first letter of the sort of the variable, followed by digits if necessary to avoid conflicts with constants and with other variables in the same term or formula.
<operator> ::= <opForm> [ : <signature> ]
<opForm> ::= <functionId> | <simpleOpForm> | <bracketedOp> | <ifOp>
<functionId> ::= <simpleId>
<simpleOpForm> ::= [ __ ] <simpleOp> [ __ ] | [ __ ] . <simpleId>
<simpleOp> ::= <opId> | <escapedId>
<bracketedOp> ::= [ __ ] <openSym> __*, <closeSym> [ __ ]
<openSym> ::= { | "[" | \( | \<
<closeSym> ::= } | "]" | \) | \>
<ifOp> ::= if __ then __ else __
Note: All markers (__) may be omitted from a <simpleOpForm> when there
is exactly one declared operator (with the indicated signature) that can be
formed by adding some number of markers to the <simpleOpForm>.
<functionId> f 0 gcd
<simpleOpForm> -__ __<=>__ __\in__ __\Post __.first
<simpleOp> - <=> \in \Post
<bracketedOp> __[__] {}
Identifiers for most operators can be overloaded, that is, they can be used to represent operators with different signatures or with markers in different places. LP uses context to disambiguate overloaded identifiers.
The arity of an operator is the number of its arguments, that is, the number of sorts in its domain. A unary operator has arity 1, a binary operator has arity 2, and a constant has arity 0.
<signature> ::= <domain> -> <range> <domain> ::= <sort>*, <range> ::= <sort>
- ->Nat
- Signature for a nullary operator (constant) of sort Nat
- Bool->Bool
- Signature for a unary operator from sort Bool to sort Bool
- Nat,Nat->Nat
- Signature for a binary operator from sort Nat to sort Nat
- Element,Set->Set
- Signature for a binary operator from sorts Element and Set to sort Set
The same identifier can be overloaded to name two different constants, that is, two constants with different sorts. A <simpleId> can also be used to name a variable and a constant, provided the variable does not have the same sort as the constant.
When LP formulates hypotheses for use in proving subgoals in a proof, it generally replaces all free variables in the hypotheses by constants. LP creates identifiers for these constants by appending the letter c and, if necessary, further digits to obtain an identifier that is not already in use. Thus LP may replace the variable x by the constants xc, xc1, ...
Operationally, LP uses equational term-rewriting to reduce a term t to a normal form t' such that the formula t = t' is true. For this purpose, LP:
The meaning of the logical operators is given by the following hardwired rewrite rules.
~true -> false true => p -> p
~false -> true false => p -> true
p => true -> true
p /\ true -> p p => false -> ~p
p /\ false -> false
p \/ true -> true p <=> false -> ~p
p \/ false -> p p <=> true -> p
LP uses these rewrite rules, together with the following, to simplify terms
containing logical operators.
~(~p) -> p p => p -> true
p => ~p -> ~p
p /\ p -> p ~p => p -> p
p /\ ~p -> false
p <=> p -> true
p \/ p -> p p <=> ~p -> false
p \/ ~p -> true ~p <=> ~q -> p <=> q
These rewrite rules are not sufficient to reduce all boolean tautologies to
true. There are sets of rewrite rules that are complete in this sense,
but they require exponential time and space, and they can expand rather than
simplify expressions that do not reduce to true or false. Hence they
are not hardwired into LP. Users wishing to use such a set can execute the
file ~lp/boolequiv.lp or the file ~lp/boolxor.lp.
To assist in orienting formulas into rewrite rules, LP places true and false at the bottom of the registry, and it registers /\, \/, and <=> as having multiset status.
LP several additional hardwired rewrite rules to simplify terms containing conditional operators. It always uses the following two rules:if true then x else y -> x if false then x else y -> y
Unless the hardwired-usage setting dictates otherwise, it also uses the following rewrite rules:if x then y else y -> y if ~x then y else z -> if x then z else y
Likewise, unless the hardwired-usage setting dictates otherwise, LP uses the if-simplification metaruleif x then true else y -> x \/ y if x then false else y -> ~x /\ y if x then y else true -> x => y if x then y else false -> x /\ y
to reduce terms when t1 occurs as a subterm of t2 or t3; here t2[true] is the result of substituting true for every occurrence of t1 as a subterm of t2, and t3[false] is defined similarly.if t1 then t2[t1] else t3[t1] -> if t1 then t2[true] else t3[false]
declare operators
{}: -> Set
{__}: Nat -> Set
__[__]: Array, Nat -> Nat
__[__,__]: Matrix, Nat, Nat -> Nat
[__]__: Nat, Matrix -> Array
..
enable the following notations:
allow the use of infix (e.g., (x + 1) \mod n), prefix (e.g., ~p and -x), and postfix (e.g., 3!) notations. Users can also declare a selection operator for use in postfix notations. For example, the declarationdeclare operators __+__, __\mod__: Nat, Nat -> Nat % infix operators -__: Nat -> Nat % prefix operator __!: Nat -> Nat % postfix operator ..
allows the use of postfix notations such as q.first. See operator.declare operator __.first: Queue -> Element
The existential quantifier \E x is pronounced ``there exists an x''. The universal quantifier \A x is pronounced ``for all x''.\A x \E y (x < y) x < y => \E z (x < z /\ z < y)
<quantifier> ::= <quantifierSym> <variable> <quantifierSym> ::= \A | \E
\A x \E i: Nat
The standard quantifier scope rules (from first-order logic) apply within terms and formulas. The scope of the leading quantifier in the terms \A x t and \E x t is the term t. An occurrence of a variable in a term is bound if it is in the scope of a quantifier over that variable; otherwise it is free. The free variables in a formula, rewrite rule, or deduction rule are understood to be quantified universally. LP suppresses the display of leading universal quantifiers.
LP uses the following hardwired rewrite rules to reduce terms containing quantifiers.
Here P(x) and Q(x) are arbitrary terms, t is a term with no free occurrences of x, and P(t) and Q(t) are the results of substituting t for x in P(x) and Q(x) with appropriate changes of bound variables to prevent a quantifier in P or Q from capturing a variable in t.\A x t -> t \E x t -> t \E x \E x1 ... xn (x = t /\ P(x)) -> \E x1 ... \E xn P(t) \A x \A x1 ... xn (~(x = t) \/ Q(x)) -> \A x1 ... xn Q(t) \A x \A x1 ... xn (x = t /\ P(x) => Q(x)) -> \A x1 ... xn (P(t) => Q(t)) \A x \A x1 ... xn (P(x) => ~(x = t) \/ Q(x)) -> \A x1 ... xn (P(t) => Q(t))
The fix and instantiate commands, together with the generalization and specialization proof methods, enable users to eliminate quantifiers from facts and conjectures.
See also prenex form.
Every quantifier in a formula can be classified as a prenex-universal, a prenex-existential quantifier, or neither depending on whether it corresponds to a universal (\A) quantifier, an existential (\E) quantifier, or more than one quantifier in a systematically derived logically equivalent prenex formula. The leading quantifiers in \A x P and \E x P are prenex-universal and prenex-existential quantifiers, respectively. If a quantifier is prenex-universal (prenex-existential) in P, then it is the same in P /\ Q, P \/ Q, Q => P, \A y P, and \E y P; it is prenex-existential (prenex-universal) in ~P and P => Q; and it is neither in any other formula, e.g., in P <=> Q.\E w \A x P(w, x) => \A y \E z P(z, y) \A w \A y \E x \E z (P(w, x) => P(z, y)) \A w \A y \E x (P(w, x) => P(x, y))
Formulas can be transformed systematically into prenex formulas using changes of bound variables and the following logical validities.
\A x P <=> P (x not free in P)
\E x P <=> P (x not free in P)
\A x ~P <=> ~\E x P
\E x ~P <=> ~\A x P
\A x (P /\ Q) <=> \A x P /\ \A x Q
\E x (P /\ Q) <=> \E x P /\ Q (x not free in Q)
\A x (P \/ Q) <=> \A x P \/ Q (x not free in Q)
\E x (P \/ Q) <=> \E x P \/ \E x Q
\A x (P => Q) <=> \E x P) => Q (x not free in Q)
\A x (P => Q) <=> P => \A x Q (x not free in P)
\E x (P => Q) <=> \A x P => \E x Q
F(\A x P) <=> (F(true) /\ \A x P)
\/ (F(false) /\ ~\A x P)
The instantiate and fix commands enable users to eliminate certain prenex-universal and prenex-existential quantifiers from facts. The generalization and specialization proof methods provide the corresponding functionality for conjectures.
For this reason, LP automatically changes bound variables to avoid captures during rewriting, in response to the fix and instantiate commands, and in response to the generalization and specialization proof methods.
<term> ::= if <term> then <term> else <term>
| <subterm>
<subterm> ::= <subterm> ( <simpleOp> <subterm> )+
| ( <simpleOp> | <quantifier> )* <simpleOp> <secondary>
| ( <simpleOp> | <quantifier> )* <quantifier> <primary>
| <secondary> <simpleOp>*
<secondary> ::= <primary>
| [ <bracketPre> ] <bracketed> [ <bracketPost> ]
<primary> ::= <primaryHead> <primaryTail>*
<primaryHead> ::= <simpleId> [ "(" <term>+, ")" ]
| "(" <term> ")"
<primaryTail> ::= "." <primaryHead> | <qualification>
<qualification> ::= ":" <sort>
<bracketPre> ::= <primaryHead> | <primary> . <primaryHead>
<bracketed> ::= <openSym> <term>*, <closeSym> [ <qualification> ]
<bracketPost> ::= <primary> | . <primaryHead> <primaryTail>*
Restrictions: Terms must type-check, that is, all operators must be
applied to arguments with sorts in the operator's signature.
The following combinations of <simpleOp>s cannot appear in a <subterm>
unless they are separated by <simpleOp>s that bind less
tightly:
the terms x = z and x = w are unambiguous, but the term x = y is ambiguous. It can be disambiguated in several ways, for example, as x:Nat = y or as x = y:Bool. Given the additional declarationsdeclare variables x, y, z: Bool, x, y, w: Nat
the term f(z) is unambiguous, but the term f(w) needs to be disambiguated as either f(w):Nat or f(w):Bool, and the term f(x) needs to be disambiguated as one of f(x:Bool), f(x:Nat):Nat, or f(x:Nat):Bool.declare operators f:Nat->Nat, f:Nat->Bool, f:Bool->Bool
Another potential ambiguity in terms arises from the treatment LP accords to the period symbol (.). For example, given the declarations
the terms a.size and a.1 are unambiguous, but a.min could represent an application of either the infix operator . or the postfix operator .min. In such cases, LP disambiguates a.min as containing a postfix operator; users who want . to refer to the infix operator can write a.(min).declare operators 1, min: -> Nat a: -> Array __.__: Array, Nat -> Nat __ .size, __ .min: Array -> Nat ..
Quantifiers bind more tightly than all operators.
Unparenthesized version Interpretation ---------------------- -------------- a < b + c Error p /\ q \/ r Error p => q => r Error x - y - z (x - y) - z a = b + c => b < s(a) (a = (b + c)) => (b < s(a)) a.b.c! ((a.b).c)! ~p /\ ~x.pre (~p) /\ (~(x.pre)) \E x (x < c) => c > 0 (\E x (x < c)) => (c > 0) \A x \E y x < y (\A x \E y x) < y
Restriction: the sort of the <term> must be Bool.<formula> ::= <term>
x + s(y) = s(x + y) x | y <=> \E z (y = x * z) x < y \/ x = y \/ y < x x < y => \E z (x < z /\ z < y)
Operationally, LP uses formulas by orienting them (if possible) into a terminating set of rewrite rules. LP also automatically reduces all nonimmune formulas to normal form.
LP automatically rewrites formulas of the form ~p to p = false and formulas of the form ~p = false to p. Furthermore, it uses the following hardwired deduction rules to derive new formulas from existing formulas and rewrite rules.
LP uses the names of these deduction rules when it reports their application, but they cannot be entered by the user when naming objects.lp_and_is_true: when p /\ q yield p, q lp_or_is_false: when ~(p \/ q) yield ~p, ~q
To display the formulas that LP has not converted into rewrite rules, type display formulas (or dis fo for short).
Restriction: The two <term>s in an equation must have the same sort. This sort must be Bool if the equality operator is <=>.<equation> ::= <term> (= | <=>) <term>
x + 0 = x x <= y <=> x < y \/ x = y x | y <=> \E z (y = x*z)
The facts in a logical system have both semantic content (expressed by formulas in first-order logic) and operational content. For more information about this operational content, see:
LP automatically recognizes the formula x ~= t, where t is a term not involving the variable x, as inconsistent. Thus, LP rules out empty sorts. It also recognizes the formulas false and b = t, where t is a term not involving the boolean variable b, as inconsistent. Thus, the boolean sort contains two distinct values.
If an inconsistency arises during a proof by contradiction, that proof succeeds. If it arises during a proof by cases, the current case is deemed impossible.
Restrictions: The two <term>s in a rewrite rule must have the same sort. The left side of the rule must not be a variable, the logical constant true, or the logical constant false. Every free variable in the right side must also occur free in left side.<rewrite-rule> ::= <term> -> <term>
x + 0 -> x x <= y -> x < y \/ x = y x | y -> \E z (y = x*z) 0 < 1 -> true
LP maintains the invariant that all active rewrite rules have been applied to all nonimmune formulas, rewrite rules, and deduction rules in the system.
Some rewrite rules are hardwired into LP to define properties of the logical connectives, the conditional and equality operators, and the quantifiers.
The restriction that the left side of a rewrite rule not be a variable prevents ``rules'' like x -> f(x) from leading to a nonterminating rewriting sequence such as x -> f(x) -> f(f(x)) -> .... The restriction that it not be true or false preserves the meaning of those logical constants. The restriction that the right side not introduce a free variable is more technical. It prevents logically equivalent ``rules'' such as f(x) -> f(y) and f(u) -> f(v) from producing different results when applied to terms like y + f(x).
<operator-theory> ::= (ac | commutative) <operator>
ac + commutative gcd
LP hardwires the logical connectives /\, \/, and <=> as associative-commutative operators. It hardwires the equality operator =:S,S->Bool as a commutative operator when the sort S is not Bool.
The fact ac op normalizes the fact commutative op to true.
To display the operator theories in LP's logical system, type display operator-theories (or disp o-t for short).
<induction-rule> ::= sort <sort> generated [ freely ] by <operator>+,
| well founded <operator>
sort Nat generated freely by 0, s
sort Set generated by {}, insert
sort Set generated by {}, {__}, \U
well founded <
Assertions like sort Nat generated by 0, s specify sets of generators for use in proofs by structural induction. The listed operators (e.g, 0 and s) must have the named sort (e.g., Nat) as their range. If none of the domain sorts of an operator is the same as its range sort, the operator is a basis generator (e.g., 0); otherwise, it is an inductive generator (e.g, s). Structural induction rules are logically equivalent to infinite sets of first-order formulas of the form
where P is an arbitrary first-order formula.P(0) /\ \A x (P(x) => P(s(x))) => \A x P(x)
The use of freely supplements a structural induction rule with a set of formulas asserting that the named operators are one-to-one and have disjoint ranges. For example, sort Nat generated freely by 0, s gives rise to the formulas s(x) = s(y) <=> x = y and 0 ~= s(x).
Assertions like well founded < specify a binary relation for use in proofs by well-founded induction. The listed operator must have a signature of the form S,S->Bool for some sort S. Well-founded induction rules are logically equivalent to infinite sets of first-order formulas of the form
where P is an arbitrary first-order formula.\A x (\A y (y < x => P(y)) => P(x)) => \A x P(x)
To display the induction rules that LP currently has available for use, type display induction-rules (or disp i-r for short).
<deduction-rule> ::= when <hypothesis>+, yield <conclusion>+, <hypothesis> ::= <formula> <conclusion> ::= <formula>
when x < y, y < z yield x < z when p /\ q yield p, q when \A e (e \in s1 <=> e \in s2) yield s1 = s2
A deduction rule can be applied to a formula or rewrite rule if there is a substitution that matches the first hypothesis of the deduction rule to the formula or rewrite rule. The result of applying a deduction rule with one hypothesis is the set of formulas obtained by applying the substitution(s) that matched its hypothesis to each of its conclusions. For example, applying the second example to 1 < f(x) /\ f(x) < 2 yields two formulas, 1 < f(x) and f(x) < 2. Likewise, applying the third example to x \in s <=> x \in (s \U s) yields the formula s = s \U s.
The result of applying a deduction rule with more than one hypothesis is the set of deduction rules obtained by deleting its first hypothesis (i.e., the one that was matched) and applying the substitution(s) that matched this hypothesis to the remainder of the deduction rule. For example, applying the first example to the formula a < b yields the deduction rule
On the other hand, applying the logically equivalent deduction rulewhen b < z yield a < z
to the same formula yields a different result, namely,when y < z, x < y yield x < z
when x < a yield x < b
When applying deduction rules, LP produces the strongest valid conclusions by changing, when appropriate, variables in the conclusions that do not occur freely in the hypotheses. For example, applying the deduction rule
to the formula P(f(y)) yields the result Q(f(y), y1) and not the weaker result Q(f(y), y).when P(x) yield Q(x, y)
The results of applying a deduction rule are given the default activity and immunity, as established by the set command.
LP maintains the invariant that all active deduction rules have been applied to all nonimmune formulas and rewrite rules in the system.
To display the deduction rules that LP currently has available for use, type display deduction-rules (or disp d-r for short).
See formulas for a list of deduction rules that are hardwired into LP. See also partitioned-by.
Restriction: Each of the <operator>s must have <sort> in its domain.<partitioned-by> ::= sort <sort> partitioned by <operator>+,
sort Set partitioned by \in sort Stack partitioned by isEmpty, top, pop
In general, LP translates a statement likewhen \A e (e \in s = e \in s1) yield s = s1 when isEmpty(s) = isEmpty(s1), top(s) = top(s1), pop(s) = pop(s1) yield s = s1
into to the deduction rulesort E partitioned by op1:E->R, op2:E,A->R, op3:E,E,A->R
when op1(e1) = op1(e2),
\A a (op2(e1, a) = op2(e2, a)),
\A a \A e3 (op3(e1, e3, a) = op3(e2, e3, a)),
\A a \A e3 (op3(e3, e1, a) = op3(e3, e2, a))
yield e1 = e2
which uses auxiliary variables e1, e2, and e3 of sort E and
a and a1 of sort A.
<name> ::= <simpleId> <extension>* <extension> ::= . <number>
arith.1 set.2.3
Normalization, ordering, unordering, and proofs preserve the names of formulas, rewrite rules, and deduction rules. LP assigns subnames (i.e., names with an additional <extension>) to instantiations of formulas, rewrite rules, and deduction rules, to the results of applying deduction rules, and to hypotheses introduced during the proof of a conjecture. The names of the results of applying a deduction rule to a formula extend the name of the deduction rule if the deduction rule has more than one hypothesis; otherwise they extend the name of the formula.
One fact is called a descendant of another (and the latter is called an ancestor of the former) if the name of the first extends, by zero or more <extension>s, the name of the second. A proper ancestor (or descendant) of a fact is an ancestor (or descendant) with a different name.
The names of the hardwired deduction rules for formulas begin with lp_. The hardwired rewrite rules for the logical connectives, the conditional and equality operators, and the quantifiers do not have names, nor do conjectures introduced as subgoals in proofs.
<names> ::= <name-primary>+,
| <name-primary> ("/" <name-primary>)+
| <name-primary> ("~" <name-primary>)+
<name-primary> ::= <name-pattern> | <class> | "(" [ <names> ] ")"
<name-pattern> ::= <prefix-pattern> [ . ]
| <prefix-pattern> <extension>+ [ : <last> ] [ ! ]
<prefix-pattern> ::= ( <simpleId> | "*" )+
<last> ::= <number> | last
arith, set.2:last *Hyp * ~ (nat, set)
Primitive <names> include <name>s (e.g., set.2) and <name-pattern>s of the following forms, where N is a <name> that may have asterisks embedded in its alphanumeric prefix (e.g., * and *Hyp.1), and where m and n are positive integers.
Pattern Facts denoted by pattern
------- ------------------------
N! those with names that can be obtained from N by replacing the
asterisks in N by alphanumeric characters
N those denoted by N! and all their descendents
N.m:n! those denoted by N.m!, N.m+1!, ..., N.n!
N.m:n those denoted by N.m, N.m+1, ..., N.n
N.m:last! those denoted N.m!, N.m+1!, ...
N.m:last those denoted N.m, N.m+1, ...
See also <class>.
<class> ::= <class-name> | <class-constant>
| <class-function> "(" <names> ")"
| contains-operator "(" <operator> ")"
| contains-variable "(" <variable> ")"
| copy "(" <class-name> ")"
<class-name> ::= $ <simpleId>
<class-constant> ::= deduction-rules | formulas | induction-rules
| operator-theories | rewrite-rules | active | passive
| immune | nonimmune | ancestor-immune
<class-function> ::= ancestors | proper-ancestors | descendants
| proper-descendants | eval
$facts contains-operator(+) eval(* ~ $old)
A <class-name> (or <class>) appearing in an argument to a command other than define-class is replaced by its definition (or evaluated) when the command is executed. Evaluation in the define-class command can be forced using one of the following operators:
<assert-command> ::= assert <assertion>;+ [;]
<assertion> ::= [:<simpleId>:] <fact>
<fact> ::= <formula> | <deduction-rule> | <induction-rule>
| <operator-theory> | <partitioned-by>
assert
e1 \in insert(e2, s) <=> e1 = e2 \/ e1 \in s;
when \A e (e \in s1 <=> e \in s2) yield s1 = s2;
Set generated by {}, insert;
ac \U;
Set partitioned by \in
..
LP takes certain default actions when it adds assertions to its logical system.
Restrictions: There must be at least one marker in each <opForm> that contains a <simpleOpForm>. The number of marker symbols in any <opForm> not containing a <functionId> must equal the number of sorts in the domain of the operator's signature. A period (.) can be declared as an infix operator, but not as a prefix or a postfix operator. The predefined operators cannot be overloaded with user-defined signatures.<declare-command> ::= declare ( <sortDecs> | <varDecs> | <opDecs> ) <sortDecs> ::= sorts <sort>+, <varDecs> ::= variables <varDec>+[,] <varDec> ::= <variableId>+, : <sort> <opDecs> ::= operators <opDec>+[,] <opDec> ::= <opForm>+, : <signature>
Notes: The words sorts, operators, and variables can be abbreviated by any prefix, as well as by ops and vars.
declare sorts Nat, Set
declare variables i, j: Nat, s: Set
declare operators
0: -> Nat
s, __!: Nat -> Nat
__+__, __*__: Nat, Nat -> Nat
{}: -> Set
{__}: Nat -> Set
__\U__: Set, Set -> Set
~__: Set -> Set
..
The declare variables command introduces variables with the indicated sorts.
The declare operators commands introduces operators with the indicated signatures. Marker symbols (__) in an <opForm> indicate where the arguments of the operator are placed when it is used in a term.
LP at times creates variables and operators in response to user commands. To avoid problems, it is a good idea for users to declare the identifiers they need before issuing commands (such as prove) that may cause LP to appropriate an identifier for its own use (e.g., by creating a variable s1 of sort Set and thereby preventing the user from later using s1 as a constant of sort Set).
The display symbols command produces a list of all declared identifiers.
Note: The <fact-status> can be abbreviated.<make_command> ::= make <fact-status> ( <names> | conjecture ) <fact-status> ::= active | passive | immune | nonimmune | ancestor-immune
make inactive rewrite-rules make immune conjecture
LP automatically normalizes any rewrite rules and deduction rules made nonimmune by the make command, and it applies all active deduction rules to these deimmunized rules.
See the activity and immunity settings.
<order-command> ::= order [ <names> ]
order order nat
When a formula is an equation t1 = t2 or t1 <=> t2, LP uses the current ordering-method, if possible, to orient it into the rewrite rule t1 -> t2 or into the rewrite rule t2 -> t1. When a formula f is not an equation (i.e., when its principal operator is neither = nor <=>), LP orients it into the rewrite rule f -> true (or into the rewrite rule f1 -> false, if f has the form ~f1).
If the current ordering method is a registered or polynomial ordering, the order command also attempts to orient the formulas into a provably terminating set of rewrite rules. If the current ordering method is a brute-force ordering, the order command may orient the formulas into a nonterminating set of rewrite rules.
Users can interrupt and resume the operation of the order command.
Registered orderings use information in a registry to orient formulas into rewrite rules. There are two kinds of information in a registry: height information and status information.
When the current registry does not contain enough information to orient a formula, LP will generate minimal sets of extensions to the registry, called suggestions, that permit the formula to be oriented. If the automatic-registry setting is on, LP picks one of these extensions to orient a formula without user interaction; it does not try all extensions. If the setting is off, LP will interact with the user, who must pick the desired extension.
The dsmpos ordering computes complete sets of minimal extensions to LP's registry when necessary to orient a formula. The noeq-dsmpos is the same ordering, except that it does not suggest assigning equal heights to two operators; as a result, it is faster, but less powerful than dsmpos.
Let s and t be two terms, with s = f(s1, ..., sm) and t = g(t1, ..., tn). Then s >= t in the dsmpos ordering iff
The dsmpos ordering is based on the recursive path ordering with status due to Dershowitz, Kamin, and Levy. The definition of the ordering >= is due to Forgaard. The generation of suggestions is due to Detlefs and Forgaard.
LP uses the following modification of the dsmpos ordering to orient equations that contain quantifiers. It replaces each quantifier (over a sort S) in an equation by a pseudo-operator with signature S, Bool -> Bool, and it replaces each bound variable by the constant true; in this way, it converts each subterm of the form \E x P(x) or \A x P(x) in an equation into a subterm \E(true, P(true)) or \A(true, P(true)). (In general, the resulting term does not sort check.) Then LP tries to orient the transformed equation with the aid of registry suggestions for the pseudo-operators. It it succeeds, it orients the original equation in the same direction as its transformation.
<polynomial-constraint> ::= polynomials <operator> <polynomial>*[,]
<polynomial> ::= <polynomial-term> ( "+" <polynomial-term> )*
<polynomial-term> ::= <polynomial-factor> ( "*" <polynomial-factor> )*
<polynomial-factor> ::= <polynomial-primary> [ "^" <number> ]
<polynomial-primary> ::= <variable> | <number> | "(" <polynomial> ")"
polynomials + x + y + 1, x + 2
The command set ordering polynomial n sets the current ordering-method to a polynomial ordering based on sequences of length n; the default value of n is 1.
The command register polynomial op p1, ..., pn assigns the sequence p1, ..., pn of polynomials as the polynomial interpretation of the operator op. If no polynomials are specified, LP prompts the user to enter them on the following lines. The polynomials are entered like standard LP terms, using the binary operators +, *, \and fq{^} (for exponentiation), the variables in the prompt, and positive integer coefficients. LP understands operator precedence for terms representing polynomials, so these terms need not be fully parenthesized..
If the sequence of polynomials associated with an operator is longer than the length of the current polynomial ordering, the extra polynomials are ignored. If it is shorter, it is extended by replicating its last element.
Each operator has a default interpretation. Suggestions for assigning polynomials:
(1) f nullary I[f] = 2
(2) f(x1,...,xn) -> t [f not in t] I[f] = I[t] + 1
(3) h(f(t1,...,tn)) -> I[h] = a*(x^i) with i > 1
f(h(t1),...,h(tn)) I[f] = x1 + ... + xn
(4) f associative I.1[f] = (a*x*y) + x with a > 0
f(f(x,y),z) -> f(x,f(y,z)) I.2[f] = (a*(x^i)) + y with a, i > 0
(5) f associative I.1[f] = (a*x*y) + y with a > 0
f(x,f(y,z)) -> f(f(x,y),z) I.2[f] = x + (a*(y^i)) with a, i > 0
(6) f associative-commutative I[f] = (a*x*y) + (b*(x+y)) + c
with ac + b - b^2 = 0
(7) f, g associative-commutative I[f] = a*x*y with a > 0
g distributive over f I[g] = x + y
or I[f] as in (6) with a > 0
I[g] = x+y+d with d = b/a
(8) f should be rewritten to g degree(I.1[f]) > degree(I.1[g])
The following sets of suggestions will allow the equation to be oriented into
a rewrite rule:
Direction Suggestions
--------- -----------
1. -> a > b
2. <- b > a
What do you want to do with the formula?
users can type ? to see a menu such as
of possible responses, which have the following effects.Enter one of the following, or type < ret > to exit. accept[1..2] interrupt left-to-right postpone suggestions divide kill ordering right-to-left
<register-command> ::= register <ordering-constraint>
<ordering-constraint> ::= <height-constraint> | <status-constraint>
| <polynomial-constraint>
Note: The first word in the <ordering-constraint> can be
abbreviated.
register height f > g register status multiset + register polynomials + x + y + 1, x + 2
When the automatic-registry setting is on and the ordering-method setting is a registered ordering, LP automatically adds height and status constraints to the registry, as necessary, to orient equations in order to ensure that the resulting set of rewrite rules is terminating.
The display ordering command displays the constraints in the registry. Ordering constraints can be removed from the registry with the unregister command.
<height-constraint> ::= height <operator-set> ( <height> <operator-set> )+
| ( bottom | top ) <operator>+[,]
<height> ::= > | = | >=
<operator-set> ::= <operator> | "(" <operator>+[,] ")"
Note: The first word in a <height-constraint> can be
abbreviated.
height f > g height => > (/\, \/) > true = false bottom f
The transitive closure of the height constraints in LP's registry defines a partial order on operators, which is used by the dsmpos ordering. The register command will reject any height constraint that is not a consistent extension to its registry.
The bottom (top) constraints suggest that LP extend its registry when it needs information about a listed operator by giving that operator a lower (higher) height than any non-bottom (non-top) operator. LP does not actually extend its registry until it needs this information. In general, putting operators at the bottom (top) of the registry causes terms to be reduced toward (away from) ones made out of these operators.
Note: The word status and the <status> can be abbreviated.<status-constraint> ::= status <status> <operator>+[,] <status> ::= left-to-right | right-to-left | multiset
status left-to-right f, g status multiset +
The left-to-right and right-to-left statuses are called lexicographic statuses. The assign more weight, respectively, to the leftmost or rightmost arguments of an operator. They are useful when orienting the associativity equation f(f(x,y),z) = f(x,f(y,z)). If f has left-to-right, this equation would be oriented from left to right. If f has right-to-left status, it would be would be oriented from right to left.
The multiset status is appropriate for ac and commutative operators, because it gives all arguments equal weight.
The dsmpos ordering is defined on terms containing an operator without a defined status if the ordering would produce the same results no matter what status was given to that operator. This property allows LP or the user to define the status of an operator without invalidating the proof of termination for previously oriented rewrite rules.
<unorder-command> ::= unorder [ <names> ]
unorder unorder nat
Even if the automatic-ordering setting is on, the unordered formulas are not immediately reordered into rewrite rules. This gives users an opportunity to change the ordering-method or the registry. The formulas will be oriented into rewrite rules in response to an explicit order command or in response to some other command that would invoke LP's automatic ordering (for example, the assert command).
Note: The first word in the <ordering-information> can be abbreviated.<unregister-command> ::= unregister <ordering-information> <ordering-information> ::= registry | ( bottom | top ) <operator>+[,]
unregister bottom succ unregister registry
The unregister top and unregister bottom commands remove the listed operators from the top and bottom of the registry used by the registered orderings.
Users can make formulas, rewrite rules, and deduction rules immune or ancestor-immune to protect them from automatic normalization, both to enhance the performance of LP and to preserve particular forms for use in a proof. Users can also deactivate rewrite rules to prevent them from being applied automatically. The normalize and rewrite commands explicitly apply rewrite rules (whether or not active) to facts (whether or not immune).
Inactive deduction rules are not used for automatic deduction, and immune formulas and rewrite rules are not subject to automatic deduction. Users can also apply deduction rules explicitly, for example, to immune formulas.
<apply-command> ::= apply <names> to <target> <target> ::= <names> | conjecture
apply passive / deduction-rules to * apply setExtensionality to conjecture
The second version attempts to prove the current conjecture by explicit deduction using the named deduction rules. The attempt succeeds if the current conjecture matches a conclusion of a named deduction rule and the hypotheses of that deduction rule, under the matching substitution, reduce to true. For example, if LP's logical system contains the axioms
then the command apply setExtensionality to conjecture finishes the proof of the conjecture x \U x = x.setAxioms.1: e \in (x \U y) -> e \in x \/ e \in y setExtensionality.1: when \A e (e \in s1 <=> e \in s2) yield s1 = s2
<complete-command> ::= complete
complete
When LP's logical system consists solely of active, nonimmune, quantifier-free equations and rewrite rules, the complete command attempts to transform the logical system into a convergent set of rewrite rules that has the same equational theory. The completion procedure is based on the Peterson and Stickle extension of the Knuth-Bendix completion procedure.
LP terminates the completion procedure if the current conjecture reduces to true.
A convergent rewriting system can be used to prove theorems by normalization using the prove command or to reduce terms to a canonical form using the show normal-form command. The completion-mode setting controls the operation of the completion procedure. You can interrupt and resume the operation of the completion procedure.
See also proofs by consistency.
<critical-pairs-command> ::= critical-pairs <names> with <names>
critical-pairs *Hyp with *
LP also computes critical pairs in response to the complete command. LP keeps track of which rewrite rules have had their critical pairs computed, and does not recompute critical pairs between those rules. See also the forget command.
Critical pair equations between two rewrite rules result from using them to rewrite a common term in two different ways. Suppose that R1 is the rewrite rule l1 -> r1 and R2 is l2 -> r2. Suppose also that R1 and R2 have no variables in common (LP ensures that this is the case by substituting fresh variables for those in R2). If l2 can be unified with a nonvariable subterm of l1, then both R1 and R2 can be used to rewrite some substitution instance of l1. A critical pair equation between R1 and R2 is an equation relating the results of these two rewritings.
More precisely, if s1 is a nonvariable subterm of l1 that does not contain any variables bound by outer quantifiers in l1, if sigma is a substitution that unifies l2 with s1 and that does not introduce any variables bound by outer quantifiers in l1, and if l1' is the result of substituting r2 for s2 in l1, then sigma(l1') = sigma(r1) is a critical pair equation between R1 and R2.
Examples:
Rewrite rules Critical pair equations
1. f(x) * f(y) -> f(x * y) b * f(y) = f(a * y)
f(a) -> b f(x) * b = f(x * a)
2. P(x) => Q(x) -> true true => Q(c) <=> true
P(c) -> true ... which reduces to Q(c)
3. \E x (f(x) = g(y)) -> true \E x (f(x) = c)
g(c) -> c
When the principal operator of l1 or l2 is an
ac operator, say *, LP generalizes the
critical pair computation by computing Petersen-Stickel extensions
Ri' having the form li*x -> ri*x of R1 and R2, and then by
computing critical pair equations between {R1, R1'} and {R2,
R2'}. Thus, i(x) * x -> e has three nontrivial critical pair
equations with itself when * is ac:
<fix-command> ::= fix <variable> as <term> in <names>
fix x as s(0) in *Hyp
the commands fix x as c in user and fix z as bigger(x) in user produce the resultsuser.1: \E x \A y (f(y) = x) user.2: \E z (x < z)
user.1.1: f(y) = c user.2.1: x < bigger(x)
LP will reject a fix command unless the following conditions are satisfied.
<instantiate-command> ::= instantiate (<variable> by <term>)+, in <names>
instantiate s2 by s1 \U s1 in setExtensionality instantiate x by 0, y by 1 in lemmas
LP normalizes any nonimmune results from an instantiation, discarding those that normalize to true and orienting any resulting formulas into rewrite rules if the automatic-ordering setting is on. The activity and immunity of the results are determined by the current values of the activity and immunity settings. When instantiating a rewrite rule, LP does not use that rule in normalizing the result.
<normalize-command> ::= normalize <target> [ with [ reversed ] <names> ] <target> ::= <names> | conjecture
normalize immune / lemmas with * normalize conjecture with distributiveLaws
If reversed is present, all named formulas and rewrite rules, whether or not they are active, that can be oriented from right to left into legal rewrite rules are used with that orientation. If reversed is not present, all named rewrite rules and formulas, whether or not they are active, that can be oriented from left to right are used with that orientation. If no <names> are given, all rewrite rules and left-to-right orientable formulas are used.
The second version of the normalize command normalizes the current conjecture using the rewrite rules obtained as just described.
The normalize command is typically used to ``open up'' definitions using a set of passive rewrite rules. When reversed is present, the named rewrite rules should ordinarily be passive to prevent them from immediately undoing the result of the normalize command. See also the rewrite command.
<rewrite-command> ::= rewrite <target> [ with [ reversed ] <names> ]
rewrite immune / lemmas with * rewrite conjecture with distributiveLaws
If reversed is present, all named formulas and rewrite rules, whether or not they are active, that can be oriented from right to left into legal rewrite rules are used with that orientation. If reversed is not present, all named rewrite rules and formulas, whether or not they are active, that can be oriented from left to right are used with that orientation. If no <names> are given, all rewrite rules and left-to-right orientable formulas are used.
The second version of the rewrite command rewrites some term in the current conjecture using the rewrite rules obtained as just described.
The rewrite command is typically used to ``open up'' definitions using a set of passive rewrite rules or to undo an application of a rewrite rule. When reversed is present, the named rewrite rules should ordinarily be passive to prevent them from immediately undoing the result of the rewrite command. See also the normalize command.
A proof by consistency proceeds by adding an equation to a complete system and running the completion procedure. If that procedure terminates without generating an inconsistency, then the equation is valid in the initial model; if it terminates with an inconsistency, the equation is not valid; if it does not terminate, the equation may or may not be valid.
<proof-method> ::= <default-proof-method> | cases <term>+,
| contradiction | default
| generalizing <variable> from <term>
| induction [ [ on <variable> ]
[ depth <number> ] [ [ using ] <names> ]
| specializing ( <variable> to <term> ) +,
<default-proof-method> ::= /\-method | =>-method | <=>-method | if-method
| explicit-commands | normalization
Note: The first word of the <proof-method> can be
abbreviated.
=> cases x < 0, x = 0, x > 0 induction on x
The default method specifies the use of the first applicable proof method in the value of the proof-methods setting. See the individual descriptions of the other proof methods for information about their use.
{e} \subseteq insert(e, s)
from the axioms
{e} = insert(e, {})
e \in insert(e1, x) <=> e = e1 \/ e \in s
{} \subseteq s
insert(e, x) \subseteq y <=> e \in y /\ x \subseteq y
by using them to reduce it to true. But the conjecture x \subseteq x
is irreducible, and LP treats it as a subgoal to be proved by some other proof
method.
Passive rewrite rules can be applied explicitly to a conjecture by the normalize and rewrite commands. These commands can be used to control when definitions are expanded, or when nonsimplifying rewrite rules (such as distributivity) are applied.
The command prove F by cases F1, ..., Fn directs LP to prove a formula F by division into n cases defined by the formulas F1, ..., Fn (or into two cases, F1 and ~F1 if n = 1). The command resume by cases F1, ..., Fn directs LP to resume the proof of the current conjecture by division into cases.
A proof by cases involves n+1 subgoals. If n > 1, the first subgoal involves proving F1 \/ ... \/ Fn to show that the cases exhaust all possibilities. If n = 1, LP generates a default second case of ~F1, but does not generate a disjunction as the first subgoal. Then, for each case i, LP generates a subgoal F' and an additional hypothesis Fi' by substituting new constants for the free variables of Fi in both F and Fi. If an inconsistency results from adding a case hypothesis, that case is impossible and the subgoal is vacuously true. Otherwise the subgoal must be shown to follow from the axioms supplemented by the case hypothesis. The names of the case hypotheses have the form <simpleId>CaseHyp.<number>, where <simpleId> is the current value of the name-prefix setting.
In each case of a proof by cases, LP first adds the case hypothesis without using it to reduce the other rewrite rules in the system. Only if this action fails to reduce the desired conclusion to true does LP use the case hypothesis to reduce the other rewrite rules.
The command resume by contradiction directs LP to resume the proof of the current conjecture by contradiction.
The command resume by induction directs LP to resume the proof of the current conjecture by induction.
LP supports proofs both by structural and well-founded induction. Induction rules beginning with generated by provide the basis for proofs by structural induction. Induction rules beginning with well founded provide the basis for proofs by well-founded induction.
LP generates appropriate subgoals for each kind of proof by induction. Some of those subgoals introduce additional hypotheses, known as induction hypotheses. The names of the induction hypotheses have the form <simpleId>InductHyp.<number>, where <simpleId> is the current value of the name-prefix setting.
assert sort Nat generated by 0, s prove 0 + x = x by induction Basis subgoal: 0 + 0 = 0 New constant: xc Induction hypothesis: 0 + xc = xc Induction subgoal: 0 + s(xc) = s(xc)
assert sort Set generated by {}, {__}, \U
prove x \subseteq x by induction
Basis subgoals: {} \subseteq {}, {e} \subseteq {e}
New constants: xc, xc1
Induction hypotheses: xc \subseteq xc, xc1 \subseteq xc1
Induction subgoal: (xc \U xc1) \subseteq (xc \U xc1)
In general, LP constructs the basis and induction steps using the set G of generators for the sort S of x specified by the induction rule IR, as follows.
Definition 1. A (G,F,C)-ground term, where C is a set of constants of sort S, is a quantifier-free term of sort S in which all operators are either in C or are inductive generators in G, no variable has sort S, no variable occurs more than once, and no variable also occurs in F.
Definition 2. A (G,F)-ground term is a (G,F,B)-ground term, where B is the set of basis generators in G.
Definition 3. The depth of a quantifier-free term is 0 if the term consists of a variable; otherwise it is one more than the maximum depth of its arguments.
Definition 4. A (G,F,{c1,...,cm})-ground term is canonical if it contains exactly one occurrence of each of c1, ..., ck for some k <= m.
The basis step involves proving all formulas of the form F(x gets t) where t is an (G,F,B)-ground term of depth at most n.
The induction step introduces a set C = {c1,...,cm} of new constants of sort S, where m is the maximum number of arguments of sort S in a generator in G raised to the power n. The induction step involves proving all formulas of the form F(x gets t), where t is a canonical (G,F,C)-ground term of depth n+1. The induction hypotheses available in the induction step consist of all formulas of the form F(x gets t), where t is a (G,F,C)-ground term of depth at most n.
When n is 1, the induction hypotheses consist of all formulas of the form F(x gets c), where c is in C; and the induction step involves proving all formulas of the form F(x gets t), where t is a canonical (G,F,C)-ground term of depth 2.
Examples:
Gener- Level Basis Induction Induction
ators Subgoals Hypotheses Subgoals
0, s 1 f(0) f(c) f(s(c))
0, s 2 f(0) f(c) f(s(s(c)))
f(s(0)) f(s(c))
0, 1, + 1 f(0) f(c1) f(c1+c2)
f(1) f(c2)
0, 1, + 2 f(0) f(c1), f(c2) f(c1+(c2+c3)
f(1) f(c3), f(c4) f((c1+c2)+c3)
f(0+0) f(c1+c1), f(c1+c2), ... f((c1+c2)+(c3+c4))
f(0+1) f(c2+c1), f(c2+c2), ...
f(1+0) f(c3+c1), f(c3+c2), ...
f(1+1) f(c4+c1), f(c4+c2), ...
nil 1 f(nil) f(c) f(cons(x, c))
cons
nil 2 f(nil) f(c) f(cons(x,cons(y,c))
cons f(cons(x,nil)) f(cons(x,c))
assert well founded < prove 0 + x = x by induction New constant: xc Induction subgoal: 0 + xc = xc Induction hypothesis: x < xc => 0 + x = x
The command resume by generalizing x from t directs LP to resume the proof of the current conjecture by this method.
This proof method, which eliminates a universal quantifier from a conjecture, is the dual of the fix command, which eliminates an existential quantifier from a fact. It is subject to restrictions on x and t as for the fix command.
This command is unlikely to be used when F contains free variables other than x. When x is the only free variable in F, the only restriction is that t be a constant that does not occur in F or in any fact in LP's logical system. For example, the command
is allowed when d is a new constant and reduces the proof of the conjecture to establishing the subgoal f(d) = c. See Skolem-constant.prove \A x (f(x) = c) by generalizing x from d
The command resume by generalizing x from t directs LP to resume the proof of the current conjecture by this method.
This proof method, which eliminates existential quantifiers from a conjecture, is the dual of the instantiate command, which eliminates universal quantifiers from facts.
For example, the command
reduces the proof of the conjecture to establishing the subgoal x < s(x).prove \A x \E y (x < y) by specializing y to s(x)
The command resume by /\ directs LP to resume the proof of the current conjecture using this method. It is applicable only when the current conjecture has been reduced to a conjunction.
Users should beware that employing this method too early in a proof can result in lengthening the proof considerably, for example, when the same sequence of commands or the same lemma is needed to prove more than one conjunct.
directs LP to prove the subgoal t2' using the hypothesis t1', where t1' and t2' are obtained as in a proof by cases, that is, by substituting new constants for the free variables of t1 in both t1 and t2. The name of the hypothesis has the form <simpleId>ImpliesHyp.<number>, where <simpleId> is the current value of the name-prefix setting.prove t1 => t2 by =>
For example, given the axioms a => b and b => c, the command prove a => c by => orients the hypothesis a into a rewrite rule a -> true and attempts to prove c as a subgoal. The proof succeeds automatically: LP orients the hypothesis into a rewrite rule a -> true, uses it to normalize the first axiom to b, orients the result into a rewrite rule b -> true, and uses it to normalize the second axiom to c, which establishes the subgoal.
The command resume by => directs LP to resume the proof of the current conjecture using this method. It is applicable only when the current conjecture has been reduced to an implication.
Users should beware of using the => proof method prematurely, because it causes LP to replace all free variables in the conjecture by constants, which makes it impossible to continue the proof by induction on one of those variables.
The command resume by <=> directs LP to resume the proof of the current conjecture using this method. It is applicable only when the current conjecture has been reduced to a formula of the form t1 <=> t2 or of the form t1 = t2 when t1 and t2 are boolean-valued terms.
direct LP to prove the conjectures by division into two cases, t1 and ~t1. LP substitutes new constants for the free variables of t1 in all terms ti to obtain terms ti'. In the first case, it assumes t1' as an additional hypothesis and attempts to prove t2' (or t2' = t4') as a subgoal. In the second case, it assumes t1' = false as an additional hypothesis and attempts to prove t3' (or t3' = t4'). The names of the hypotheses have the form <simpleId>IfHyp.<number>, where <simpleId> is the current value of the name-prefix setting.prove if t1 then t2 else t3 by if-method prove (if t1 then t2 else t3) = t4 by if-method
The command resume by if-method directs LP to resume the proof of the current conjecture using this method. It is applicable only when the current conjecture has been reduced to a formula of the form if t1 then t2 else t3 or of the form (if t1 then t2 else t3) = t4, where t4 does not begin with if.
For example, the command
causes LP to generate a single subgoal which involves proving the formulaprove when \A x:Elem (x \in s:Set <=> x \in t:Set) yield s = t
\A x:Elem (x \in s:Set <=> x \in t:Set) => s = t
LP also generates a single subgoal when asked to initiate a proof of a partitioned-by. This subgoal is the one associated with the translation of the partitioned-by into a deduction rule.
sort Set generated by {}, {__}, \U
LP creates a single subgoal that involves proving the formula
isGenerated(x) using the hypotheses
isGenerated({})
isGenerated({e})
isGenerated(s1) /\ isGenerated(s2) => isGenerated(s1 /\ s2)
where isGenerated is a new operator with signature Set->Bool. The
names of the hypotheses have the form <simpleId>GenHyp.<number>, where
<simpleId> is the current value of the name-prefix setting. User
guidance is generally required to finish the proof, for example, by using the
induction rule sort Set generated by {}, insert.
To prove a structural induction rule such as
LP also attempts to prove the subgoalssort Nat generated freely by 0:->Nat, f:Nat->Nat, g:Nat->Nat
in addition to the subgoal isGenerated(n).f(n) ~= 0 f(n) = f(n1) <=> n = n1 f(n) ~= g(n1) g(n) ~= 0 g(n) = g(n1) <=> n = n1
To prove a well-founded induction rule such as well founded <, LP creates a single subgoal that involves proving the formula isGenerated(x) using the hypothesis
\A n1 (n1 < n => isGenerated(n1)) => isGenerated(n)
<apply-command> ::= apply <names> to <target> <target> ::= <names> | conjecture
apply passive / deduction-rules to * apply setExtensionality to conjecture
The second version attempts to prove the current conjecture by explicit deduction using the named deduction rules. The attempt succeeds if the current conjecture matches a conclusion of a named deduction rule and the hypotheses of that deduction rule, under the matching substitution, reduce to true. For example, if LP's logical system contains the axioms
then the command apply setExtensionality to conjecture finishes the proof of the conjecture x \U x = x.setAxioms.1: e \in (x \U y) -> e \in x \/ e \in y setExtensionality.1: when \A e (e \in s1 <=> e \in s2) yield s1 = s2
<cancel-command> ::= cancel [ all | lemma ]
cancel cancel all cancel lemma
The command cancel all cancels the proofs of all conjectures.
The command cancel lemma cancels the proof of the conjecture introduced by the last prove command, together with the proofs of all subgoals introduced by LP during the proof of that conjecture.
<normalize-command> ::= normalize <target> [ with [ reversed ] <names> ] <target> ::= <names> | conjecture
normalize immune / lemmas with * normalize conjecture with distributiveLaws
If reversed is present, all named formulas and rewrite rules, whether or not they are active, that can be oriented from right to left into legal rewrite rules are used with that orientation. If reversed is not present, all named rewrite rules and formulas, whether or not they are active, that can be oriented from left to right are used with that orientation. If no <names> are given, all rewrite rules and left-to-right orientable formulas are used.
The second version of the normalize command normalizes the current conjecture using the rewrite rules obtained as just described.
The normalize command is typically used to ``open up'' definitions using a set of passive rewrite rules. When reversed is present, the named rewrite rules should ordinarily be passive to prevent them from immediately undoing the result of the normalize command. See also the rewrite command.
<prove-command> ::= prove <assertion> [ by <proof-method> ]
prove e \in {e}
prove i * (j + k) = (i * j) + (i * k) by induction on i
prove sort Set generated by {}, insert
LP maintains a stack of proof contexts for conjectures whose proofs are not yet complete. Each proof context consists of a conjecture, a logical system of facts available for the proof, and values for the local settings that govern the proof. The conjecture in the topmost proof context on the stack is known as the current conjecture.
The prove command pushes a new proof context on top of the stack. Certain proof methods create subgoals for proving a conjecture. LP associates a separate proof context with each subgoal, and it adds appropriate additional facts, called hypotheses, to the logical system in that proof context.
The user can cancel the proof of a conjecture with the cancel command, which pops the stack of proof contexts. Or the user can resume the proof of the current conjecture with the resume command (for example, to specify a new method of proof or after proving a lemma). Whenever a proof succeeds or is canceled, LP pops the stack of proof contexts, restores its logical system and settings to those in effect before work began on the conjecture (thereby discarding any lemmas proved while working on the conjecture), adds the conjecture to the system if it was proved, and resumes work on the new current conjecture. As soon as LP can establish the current conjecture, it terminates any forward inference mechanisms (such as internormalization of the rewriting system or the computation of critical-pair equations) that may be in progress.
<qed-command> ::= qed
qed
<presume-command> ::= resume [ by <proof-method> ]
resume by induction on i resume by cases x < 0, x = 0, x > 0
<rewrite-command> ::= rewrite <target> [ with [ reversed ] <names> ]
rewrite immune / lemmas with * rewrite conjecture with distributiveLaws
If reversed is present, all named formulas and rewrite rules, whether or not they are active, that can be oriented from right to left into legal rewrite rules are used with that orientation. If reversed is not present, all named rewrite rules and formulas, whether or not they are active, that can be oriented from left to right are used with that orientation. If no <names> are given, all rewrite rules and left-to-right orientable formulas are used.
The second version of the rewrite command rewrites some term in the current conjecture using the rewrite rules obtained as just described.
The rewrite command is typically used to ``open up'' definitions using a set of passive rewrite rules or to undo an application of a rewrite rule. When reversed is present, the named rewrite rules should ordinarily be passive to prevent them from immediately undoing the result of the rewrite command. See also the normalize command.
<diamond-command> ::= <> <character>* <box-command> ::= [] <character>*
<> induction step [] induction step
LP checks <>'s and []'s when it executes commands from a .lp file and the box-checking setting is on. Whenever it generates a <> or a [], LP checks that the next nonblank line in the .lp file contains a corresponding <> or [] command. The special LP prompts <>? and []? indicate that LP expects a confirming <> or [] in the .lp file. LP prints an error message if the confirming <> or [] is missing, or if an unexpected <> or [] appears in the .lp file.
Regardless of whether box-checking is on or off, LP does not copy <> and [] commands from its input to the history or to a script file. Instead, it puts into the history and script file the <> and [] commands that it produces as it creates and discharges subgoals. Thus, the history and the script file will be annotated in a way that correctly reflects the actual progress of the proof.
See also the qed command.
<clear-command> ::= clear
clear
<comment-command> ::= % <string>
% Axioms for finite sets
<define-class-command> ::= define-class <class-name> [ <names> ]
define-class $facts nat, set define-class $facts1 copy($facts) define-class $old eval(*)
<delete-command> ::= delete <names>
delete rewrite-rules delete myLemma, junk
<display-command> ::= display [ <information-type> ] [ <names> ]
<information-type> ::= classes | conjectures | facts | names
| ordering-constraints | proof-status | symbols
display display *Hyp display ordering-constraints contains-operator(+)
<execute-command> ::= ( execute | execute-silently ) <file> <file> ::= <blank-free-string>
execute myProof
Further execute commands may occur in .lp files, but recursive .lp files are not allowed. Once a .lp file has been exhausted, LP resumes accepting input from the previous .lp file or from the user if no other file is being executed. If LP encounters an error while executing a file, or if the user interrupts LP, LP takes subsequent input from the terminal.
The execute-silently command is just like execute, except that it produces no output.
Note: The argument of the forget command can be abbreviated.<forget-command> ::= forget [ pairs ]
forget
The forget command can save significant space when there are many rewrite rules. It is useful when we are interested proving conjectures without appealing to the critical-pairs or complete commands.
<freeze-command> ::= (freeze | freeze-current) <file> <thaw-command> ::= thaw <file>
freeze case1 thaw case1
The freeze-current command does the same, except that it only saves the state of the current proof context. This command is faster and uses less disk space than the freeze command. It is useful primarily for trying different strategies for proving the current conjecture.
The thaw command restores the state of LP from that saved previously using the freeze command in the file named <file>.lpfrz (unless <file> contains a period, in which case LP does not supply the suffix .lpfrz) on the current LP search path. The thaw command will not thaw files that were frozen using an out-of-date version of LP.
These commands are useful for checkpointing attempted proofs. They are also useful for saving and restoring completed or partially-completed systems.
<help-command> ::= help <topic> <topic> ::= <blank-free-string>
help ? help commands
If you don't get information on the topic you expected after typing a command like help rewrite, try typing help rewrite- to see if there is further information about related topics (e.g., rewrite-command or rewrite-rule).
<history-command> ::= history [ <number> | all ]
history history 10 history all
LP annotates the history by commenting out erroneous commands, by marking the beginning and end of executed files, by marking the creation of subgoals and the completion of proofs, and by indenting the history to reveal its proof structure.
After a thaw command, LP's current history is replaced by the history that led to the corresponding freeze. Thus a script file provides a record of the commands executed during the current LP session, and the history provides a record of commands that will recreate LP's current state.
Users who want a script that will recreate LP's current state, but who have forgotten to issue a set script command, can issue a set log command instead followed by a history all command to capture the script in the log file.
<push-settings-command> ::= push-settings <pop-settings-command> ::= pop-settings
push-settings pop-settings
The write command places the push-settings and pop-settings commands in .lp files so that named axioms can be loaded from these files without affecting the current name-prefix, activity, and immunity settings.
<quit-command> ::= quit | q
quit
<set-command> ::= set [ <setting-name> [ <setting-value> ] ]
<setting-name> ::= activity | automatic-ordering | automatic-registry
| box-checking | completion-mode | directory
| display-mode | hardwired-usage | immunity
| log-file | lp-path | name-prefix | ordering-method
| page-mode | prompt | proof-methods
| reduction-strategy | rewriting-limit | script-file
| statistics-level | trace-level | write-mode
<setting-value> ::= <string>
Note: The setting-name can be abbreviated.
set set proof-methods set script session
Settings marked with (L) are local to the current proof context. If such a setting is changed, for example, during the proof of one case in a proof by cases it reverts to its previous value upon termination of that case in the proof. Settings marked with G are global and remain in effect until changed by the user. All settings have default values, which can be restored by the unset command.
<set-activity-command> ::= set activity ( on | off )
set activity off
LP automatically uses all active rewrite rules to reduce terms to normal form, and it automatically uses all active deduction rules to deduce consequences from formulas and rewrite rules. LP does not make automatic use of passive facts. Instead, LP applies passive rewrite rules only in response to the normalize or rewrite commands, and it applies passive deduction rules only in response to the apply command.
Facts retain their activity or passivity when they are normalized, and formulas retain their activity or passivity when oriented into rewrite rules. Likewise, passive conjectures remain passive when proved.
There are two main uses for passive facts in LP.
<set-automatic-ordering-command> ::= set automatic-ordering ( on | off )
set auto-ord off
<set-automatic-registry-command> ::= set automatic-registry ( on | off )
set auto-reg off
<set-box-checking-command> ::= set box-checking ( on | off )
set box on
See the box and diamond commands for details.
Note: The <completion-mode> can be abbreviated.<set-completion-mode-command> ::= set completion-mode <completion-mode> <completion-mode> ::= standard | expert | big
set completion-mode expert
<set-directory-command> ::= set directory <file>
set directory ~/proofs
The default working directory is the directory in which LP was invoked. The set directory command changes the working directory in all proof contexts.
Note: The <qualification-mode> can be abbreviated.<set-display-command> ::= set display-mode <qualification-mode> <qualification-mode> ::= qualified | unambiguous | unqualified
set display-mode qualified
The default display-mode is unambiguous.display-mode effect ------------ ------ qualified print qualifications for all subterms, identifiers unqualified print no qualifications unambiguous print enough qualifications to enable reparsing
<set-hardwired-usage-command> ::= set hardwired-usage <number>
set hardwired-usage 8
Note: The immunity setting can be abbreviated.<set-immunity-command> ::= set immunity ( on | off | ancestor )
set immunity on
LP automatically reduces all terms in nonimmune formulas, rewrite rules, and deduction rules to normal form, and it automatically applies all active deduction rules to all nonimmune formulas and rewrite rules. LP behaves differently, however, with respect to immune and ancestor-immune facts.
There are several reasons to make facts immune or ancestor-immune in LP.
However, there are also disadvantages to making too many rules immune.
<set-log-file-command> ::= set log-file <file>
set log session
<set-lp-path-command> ::= set lp-path <string>
set lp-path . ~/myAxioms ~lp
<set-name-prefix-command> ::= set name-prefix <simpleId>
set name nat
<set-ordering-method-command> ::= set ordering-method <ordering>
<ordering> ::= <registered-ordering>
| either-way | left-to-right
| manual | polynomial [ <number> ]
<registered-ordering> ::= dsmpos | noeq-dsmpos
Note: The <ordering> can be abbreviated.
set ordering dsmpos set ordering polynomial 2
When a set of rewrite rules is known to terminate (because of the ordering used to orient them), but the new ordering does not establish termination, LP issues a warning that the termination proof will be lost when the next rewrite rule is added to the system.
<set-page-mode-command> ::= set page-mode ( on | off )
set page-mode on
Most Unix systems also allow users to control output is by using the ^S and ^Q keys; ^S stops output, and ^Q resumes printing.Response Action -------- ------ space display next screenful return display next line digit display next digit lines d display next half screenful u display continuously until next user interaction q display nothing until next user interaction ? display this menu
<set-prompt-command> ::= set prompt <prompt> <prompt> ::= <blank-free-string> | ` <string> '
set prompt `[!] ' set prompt `>> '
LP replaces the first exclamation mark (!) in <prompt>, if any, by the number of the next command. LP numbers commands entered from the terminal by consecutive integers. It numbers commands obtained during execution of a script (.lp) file by appending a period followed by consecutive integers to the number of the execute command; thus command 5.2.3 is the third command in the script file executed in response to the second command in the script file executed in response to the fifth command typed by the user.
Note: Each <default-proof-method> can be abbreviated.<set-proof-methods-command> ::= set proof-methods <default-proof-method>+[,]
set proof =>, normalization
<set-reduction-strategy-command> ::= set reduction-strategy
( inside-out | outside-in )
Note: The reduction-strategy can be
abbreviated.
set reduction in
The reduction-strategy is local to the current proof context.
<set-rewriting-limit-command> ::= set rewriting-limit <number>
set rewriting-limit 50
If LP exceeds the rewriting limit when normalizing a formula, rewrite rule, or deduction rule, it immunizes that fact. If it exceeds the rewriting limit when attempting to prove a conjecture by normalization or rewriting, the user can continue normalizing the conjecture by typing resume (after raising the rewriting limit, if desired).
<set-script-file-command> ::= set script-file <file>
set script session
LP annotates the script file by commenting out erroneous commands, by substituting the text of the executed file for an execute command, by marking the creation of subgoals and the completion of proofs, and by indenting the script to reveal its proof structure.
Script files can be replayed using the execute command, and they can be edited before being replayed. Although a script file can be replayed directly using the command execute fileName.lpscr, it is generally advisable to rename the script file to fileName.lp and then replay it using the command execute fileName (lest a set script command cause LP to overwrite the command file being executed).
<set-statistics-level-command> ::= set statistics-level <number>
set statistics-level 3
<set-trace-level-command> ::= set trace-level <number>
set trace-level 3
Also, the size of the system at regular intervals, and when a critical pair computation is abandoned because a theorem has been proved.
Also, the size of the system at more frequent intervals.
Also, the accumulated running time at periodic intervals.
<set-write-mode-command> ::= set write-mode <qualification-mode>
set write-mode qualified
The default write-mode is qualified, which guarantees that the output can be reparsed even in the presence of additional overloadings for identifiers. It is often desirable, however, to set the write-mode to unambiguous to shorten and improve the readability of .lp files. If a problem arises in executing a .lp file produced in this fashion (because it is being executed in a context that overloads one of its operators), the problem can be solved by starting a new copy of LP, executing the .lp file, and writing it out again in qualified mode.write-mode effect ---------- ------ qualified print qualifications for all subterms, identifiers unqualified print no qualifications unambiguous print enough qualifications to enable reparsing
<show-command> ::= show normal-form <term>
| show unifiers <term>, <term>
Note: The first argument of the show command can be
abbreviated.
show n-f e \in (s \U s) show unifiers e*x, i(y)*y
The show unifiers command displays a complete set of most general unifiers of two terms. It displays the unifying substitutions along with the unifications of the terms, and it uses unification algorithms appropriate to the theories associated with the operators in the terms.
Note: The first word of the <statistics-option> command can be abbreviated.<statistics-command> ::= statistics [ <statistics-option> ] <statistics-option> ::= time | usage [ <names> ]
statistics stat usage nat
The usage option displays information about the use of the rewrite and deduction rules matched by <names>, which defaults to "*". For rewrite rules, the information includes the number of successful applications, the number of attempted applications, and the number of nontrivial critical pairs computed from the rule. For deduction rules, the information includes the number of successful applications. In the display, each name is preceded by (rr) or (dr) to indicate whether the named fact is a rewrite rule or a deduction rule. If two or more facts had the same name, then the display show separate statistics for each incarnation of the name (for example, if two theorems, thm.1 and thm.2, were proved by cases, then two separate rewrite rules would have received the name thmCaseHyp1.1).
<stop-command> ::= stop
stop
Note: The argument to the unset command can be abbreviated.<unset-command> ::= unset ( <setting-name> | all )
The unset command sets the value of <setting-name> to its default value. In particular, unset script stops recording user input in a script file and unset log stops recording the session in a log file. The unset all command sets the value of all settings to their defaults.unset script unset all
<version-command> ::= version
version
<write-command> ::= write <file> [ <names> ]
write axioms write intSet int, set
Unlike the freeze command, the write command does not save information about the state of uncompleted proofs. But unlike thawing a frozen file, which replaces all of LP's logical system, executing a written file adds information to the current system. Hence it can be used to combine axiomatizations.
Rewrite rules written by the write command are asserted as formulas. The numeric extensions in the names assigned to facts may change when the .lp file is executed; hence facts that are ancestor-immune may behave differently when the system is recreated.
Put all the declarations you expect to need at the beginning of your command file. This allows LP to check your declarations before beginning any time consuming tasks.
Although proofs are usually constructed interactively, successful proofs should be recorded in cleaned-up command files. Structure your proofs using a sequence of execute commands.
Freeze LP's state often. This makes it easier to try different alternatives when looking for a proof.
Always set scripting and logging on at the start of an LP session. If you realize that you are not recording a session, start logging and then execute a history all command to get LP to print the commands already executed. After executing a step of a proof, enter a comment recording information that may be helpful in cleaning up the LP-produced .lpscr file. If, for example, a critical-pairs command produced no useful critical pairs, record that fact in a comment.
Keep in mind that LP automatically indents and annotates .lpscr files. It is often useful to use an editor to replace parts of human-generated .lp files with material extracted from .lpscr files.
Be careful about the use of free variables in formulas. The formula x = {} => subset(x, y) correctly (albeit awkwardly) expresses the fact that the empty set is a subset of any set. However, its converse, subset(x, y) => x = {}, does not express the fact that any set that is a subset of all sets must be the empty set. That fact is expressed by the equivalent formulas \A x (\A y subset(x, y) => x = {}) and \A x \E y (subset(x, y) => x = {}).
An axiom or conjecture of the form when A yield B has the same logical content as one of the form A => B, but different operational content. Given the axiomization
LP will automatically derive the fact g(a) from f(a) by applying the deduction rule, but it will not derive h(a) from g(a) unless it is instructed to compute critical-pairs.declare variable x: Bool declare operators a: -> Bool f, g, h: Bool -> Bool .. assert when f(x) yield g(x); g(x) => h(x); f(a) ..
A multiple-hypothesis deduction rule of the form when A, B yield C has the same logical content as a single-hypothesis rule of the form when A /\ B yield C. They differ operationally in that, if the user asserts or proves two formulas that are matched by A and B, LP will apply the multiple-hypothesis rule but not the single-hypothesis rule.
When a proof fails unexpectedly, look at the rewrite rules to see if any are oriented in surprising directions. If so, there are several potentially useful things to try.
Be careful not to let variables disappear too quickly in a proof. Once they are gone, you cannot do a proof by induction. Start your inductions before starting proofs by cases, the => method, the <=> method, or the if method.
Splitting a conjecture into separate conjuncts (using the /\ proof method) early in a proof often leads to repeating work on multiple conjuncts, for example, doing the same case analysis several times.
To keep lemmas and theorems from disappearing (because they normalize to true), make them immune. Typing either of the commands
when you begin the proof of a conjecture immunizes that conjecture (i.e., causes it to be immune once it becomes a theorem), but nothing else. Similarly, the commandsset immunity on prove ... by explicit-commands prove ... by explicit-commands make immune conjecture set immunity off resume by ... resume by ...
help keep instantiations from disappearing when they are special cases of other facts.set immunity ancestor instantiate ... in ... set immunity off
When a proof gets stuck:
Because LP automatically internormalizes facts, you may find that what you consider to be the information content of some user-supplied assertion has been ``spread out'' over several facts in the current logical system in a way that may not be easy to understand, particularly if the system contains dozens or hundreds of facts. Similarly, you may sometimes notice that LP is reducing (or has reduced) some expression in some way that you don't understand. The command show normal-form E, where E is the expression being mysteriously reduced, or where E is the original form of one side of a formula, will often be enlightening in such cases. Setting the trace-level up to 6 will show which rewrite rules are applied in the normalization.
If unification or critical pairing is costly, try to use smaller rule lists as arguments to the critical-pairs command. Also, try to avoid computing critical pairs between rewrite rules that contain subterms such as t1 /\ t2 /\ ... /\ t5, with multiple occurrences of the same associative-commutative operator.
lp-linux.gz Intel workstation running Linux lp-solaris.gz Sparcstation running SunOS 4.1 or Solaris 5.3 lp-solaris-5_8.gz Sparcstation running Solaris 5.8
The source code for LP is also available in the file lp-code.tar.gz. LP is written in CLU, a language developed by Barbara Liskov at MIT in the 1970s to provide direct linquistic support for data abstraction. PCLU, a portable CLU compiler, is available from ftp.lcs.mit.edu:/pub/pclu. See alsocsh> ftp ftp.sds.lcs.mit.edu Name: anonymous Password: your_email_address ftp> cd pub/Larch/LP ftp> bin ftp> get lp-lib.tar.gz ftp> get lp-platform.gz ftp> quit
Name: _______________________________ Date: __________________
E-mail address: _________________________
Version: ___ [Type lp to find out.]
Hardware: ___ Sparc ___ DECmips ___ Alpha
___ Other: __________________________
Operating System and Version: _____________________________
Which of the following symptoms occurred (check all that apply):
__ system level error (OS crashes or hangs, unrelated data is lost)
__ program crashes (segmentation fault, core dump, etc.)
__ program reports a fatal error
__ program hangs
__ program exhibits __ incorrect, __ mysterious, or __ unfriendly behavior
__ program destroys data
__ poor or incorrect error messages
__ incorrect or missing documentation
__ missing feature (please elaborate)
__ other (please elaborate)
Problem description (please append a stand-alone command file that we can
execute to reproduce the bug):
Old: declare sort Nat New: declare sort Nat
declare operator 0: -> nat declare operator 0: -> Nat
(Fewer parentheses are needed now because the boolean operators /\ and \/ bind more tightly than =>, which binds more tightly than <=>.)Old: not, &, | New: ~, /\, \/
Old: x + 0 == x New: x + 0 = x
init(x) == x = 0 init(x) <=> x = 0
init(x) == x = 0 init(x) = (x = 0)
Old: declare op +: N, N -> N New: declare op __+__: N, N -> N
Old: assert ac + New: assert
assert ac +;
1 = s(0) 1 = s(0);
x + 0 = x x + 0 = x
.. ..
Old: assert Nat generated by 0, s New: assert sort Nat generated by 0, s
assert Set parititioned by /in assert sort Set partitioned by \in
Old: assert a.b:S = 2 New: assert a.(b:S) = 2
assert a:S[n] assert (a:S)[n]
Old: resume by case a b not(a | b) New: resume by case a, b, ~(a \/ b)
Old: when h1 h2 yield c1 c2 New: when h1, h2 yield c1, c2
Old: when forall x p(x) q(x) New: when \A x p(x), \A x q(x) yield c
yield c
Old: display d-r nat set New: display d-r / (nat, set)
Old: prove P(x) by case x = 0 New: prove P(x) by case x = 0
<> 2 subgoals for proof <> case xc = 0
... commands ... ... commands ...
[] case 0 = xc [] case xc = 0
... commands ... <> case ~(xc = 0)
[] case not(0 = xc) ... commands ...
[] conjecture [] case ~(xc = 0)
[] conjecture
A set E of equations defines an equational theory, which is the set of equations that can be derived from E by substituting equals for equals. More generally, a set of equations and rewrite rules defines an equational theory, which is that obtained by considering the rewrite rules as equations. A major purpose of the Knuth-Bendix completion procedure is to provide a decision procedure (reduction to normal form) for the question of whether equations are in the equational theory of a given system of equations and rewrite rules.
When an argument of an ac operator has that operator as its principal operator, LP replaces it by its arguments. For example, when + is ac, (a + b) + (c + d) flattens to a + b + c + d.
Furthermore, when a flattened term involving an ac operator has more than two arguments, LP sorts the arguments lexicographically; for example, when + is ac, (c + b) + a flattens to a + b + c.
Two-argument terms such as q <=> p, where <=> is the hardwired ac operator for boolean equivalence, are not flattened to p <=> q. This enables LP to orient them into rewrite rules in the direction the user (may have) intended.
If the rewriting system is not guaranteed to terminate (e.g., if the user oriented an equation into a rewrite rule manually), the normal form computation may not terminate. When the rewriting system is not known to terminate, LP stops the rewriting process and issues a warning after a very large number of rewrites during a normal form computation. See the rewriting-limit setting.
If the rewriting system is not confluent, a term may have more than one normal form.
LP uses normalization as a method of forward and backward inference.
For another example, the conjecture \A x (f(x) = 0) can be proved from the subgoal f(c) = 0, where c is a Skolem constant. As long as c is new, the proof is sound.
When an existential quantifier is being eliminated from a fact that contains free variables, or when the existential quantifier occurs in the scope of a universal quantifier, the quantified variable must be replaced by a term involving a Skolem function applied to the free and universally quantified variables. For example, the fact \A x (x < bigger(x)) can be obtained by eliminating the existential quantifier from \A x \E y (x < y) and replacing y by bigger(x). See the fix command and the generalization proof method.
A substitution sigma is an instance of a substitution sigma1 if there is a substitution sigma2 such that sigma(t) = sigma2(sigma1(t)).sigma(f(t1, ..., tn)) = f(sigma(t1), ..., sigma(tn))
See also captured.
A set of unifiers for two terms is complete if every unifier of the two terms is a substitution instance of some unifier in the set. A unifier of two terms is a most general unifier if, whenever it is (equivalent to) a substitution instance of another unifier, that other unifier is also (equivalent to) a substitution instance of it. For any two unifiable terms containing ac and/or commutative operators, there is a finite set of most general unifiers that is complete.