summary |
shortlog |
changelog |
graph |
tags |
bookmarks |
branches |
files |
changeset |
file |
latest |
revisions |
annotate |
diff |
comparison |
raw |
help

doc-src/Logics/FOL.tex

author | clasohm |

Thu, 29 Jun 1995 12:28:27 +0200 | |

changeset 1163 | c080ff36d24e |

parent 874 | 2432820efbfe |

child 1388 | 7705e6211865 |

permissions | -rw-r--r-- |

changed 'chol' labels to 'hol'; added a few parentheses

%% $Id$ \chapter{First-Order Logic} \index{first-order logic|(} Isabelle implements Gentzen's natural deduction systems {\sc nj} and {\sc nk}. Intuitionistic first-order logic is defined first, as theory \thydx{IFOL}. Classical logic, theory \thydx{FOL}, is obtained by adding the double negation rule. Basic proof procedures are provided. The intuitionistic prover works with derived rules to simplify implications in the assumptions. Classical~{\tt FOL} employs Isabelle's classical reasoner, which simulates a sequent calculus. \section{Syntax and rules of inference} The logic is many-sorted, using Isabelle's type classes. The class of first-order terms is called \cldx{term} and is a subclass of {\tt logic}. No types of individuals are provided, but extensions can define types such as {\tt nat::term} and type constructors such as {\tt list::(term)term} (see the examples directory, {\tt FOL/ex}). Below, the type variable $\alpha$ ranges over class {\tt term}; the equality symbol and quantifiers are polymorphic (many-sorted). The type of formulae is~\tydx{o}, which belongs to class~\cldx{logic}. Figure~\ref{fol-syntax} gives the syntax. Note that $a$\verb|~=|$b$ is translated to $\neg(a=b)$. Figure~\ref{fol-rules} shows the inference rules with their~\ML\ names. Negation is defined in the usual way for intuitionistic logic; $\neg P$ abbreviates $P\imp\bot$. The biconditional~($\bimp$) is defined through $\conj$ and~$\imp$; introduction and elimination rules are derived for it. The unique existence quantifier, $\exists!x.P(x)$, is defined in terms of~$\exists$ and~$\forall$. An Isabelle binder, it admits nested quantifications. For instance, $\exists!x y.P(x,y)$ abbreviates $\exists!x. \exists!y.P(x,y)$; note that this does not mean that there exists a unique pair $(x,y)$ satisfying~$P(x,y)$. Some intuitionistic derived rules are shown in Fig.\ts\ref{fol-int-derived}, again with their \ML\ names. These include rules for the defined symbols $\neg$, $\bimp$ and $\exists!$. Natural deduction typically involves a combination of forward and backward reasoning, particularly with the destruction rules $(\conj E)$, $({\imp}E)$, and~$(\forall E)$. Isabelle's backward style handles these rules badly, so sequent-style rules are derived to eliminate conjunctions, implications, and universal quantifiers. Used with elim-resolution, \tdx{allE} eliminates a universal quantifier while \tdx{all_dupE} re-inserts the quantified formula for later use. The rules {\tt conj_impE}, etc., support the intuitionistic proof procedure (see~\S\ref{fol-int-prover}). See the files {\tt FOL/IFOL.thy}, {\tt FOL/IFOL.ML} and {\tt FOL/intprover.ML} for complete listings of the rules and derived rules. \begin{figure} \begin{center} \begin{tabular}{rrr} \it name &\it meta-type & \it description \\ \cdx{Trueprop}& $o\To prop$ & coercion to $prop$\\ \cdx{Not} & $o\To o$ & negation ($\neg$) \\ \cdx{True} & $o$ & tautology ($\top$) \\ \cdx{False} & $o$ & absurdity ($\bot$) \end{tabular} \end{center} \subcaption{Constants} \begin{center} \begin{tabular}{llrrr} \it symbol &\it name &\it meta-type & \it priority & \it description \\ \sdx{ALL} & \cdx{All} & $(\alpha\To o)\To o$ & 10 & universal quantifier ($\forall$) \\ \sdx{EX} & \cdx{Ex} & $(\alpha\To o)\To o$ & 10 & existential quantifier ($\exists$) \\ {\tt EX!} & \cdx{Ex1} & $(\alpha\To o)\To o$ & 10 & unique existence ($\exists!$) \end{tabular} \index{*"E"X"! symbol} \end{center} \subcaption{Binders} \begin{center} \index{*"= symbol} \index{&@{\tt\&} symbol} \index{*"| symbol} \index{*"-"-"> symbol} \index{*"<"-"> symbol} \begin{tabular}{rrrr} \it symbol & \it meta-type & \it priority & \it description \\ \tt = & $[\alpha,\alpha]\To o$ & Left 50 & equality ($=$) \\ \tt \& & $[o,o]\To o$ & Right 35 & conjunction ($\conj$) \\ \tt | & $[o,o]\To o$ & Right 30 & disjunction ($\disj$) \\ \tt --> & $[o,o]\To o$ & Right 25 & implication ($\imp$) \\ \tt <-> & $[o,o]\To o$ & Right 25 & biconditional ($\bimp$) \end{tabular} \end{center} \subcaption{Infixes} \dquotes \[\begin{array}{rcl} formula & = & \hbox{expression of type~$o$} \\ & | & term " = " term \\ & | & term " \ttilde= " term \\ & | & "\ttilde\ " formula \\ & | & formula " \& " formula \\ & | & formula " | " formula \\ & | & formula " --> " formula \\ & | & formula " <-> " formula \\ & | & "ALL~" id~id^* " . " formula \\ & | & "EX~~" id~id^* " . " formula \\ & | & "EX!~" id~id^* " . " formula \end{array} \] \subcaption{Grammar} \caption{Syntax of {\tt FOL}} \label{fol-syntax} \end{figure} \begin{figure} \begin{ttbox} \tdx{refl} a=a \tdx{subst} [| a=b; P(a) |] ==> P(b) \subcaption{Equality rules} \tdx{conjI} [| P; Q |] ==> P&Q \tdx{conjunct1} P&Q ==> P \tdx{conjunct2} P&Q ==> Q \tdx{disjI1} P ==> P|Q \tdx{disjI2} Q ==> P|Q \tdx{disjE} [| P|Q; P ==> R; Q ==> R |] ==> R \tdx{impI} (P ==> Q) ==> P-->Q \tdx{mp} [| P-->Q; P |] ==> Q \tdx{FalseE} False ==> P \subcaption{Propositional rules} \tdx{allI} (!!x. P(x)) ==> (ALL x.P(x)) \tdx{spec} (ALL x.P(x)) ==> P(x) \tdx{exI} P(x) ==> (EX x.P(x)) \tdx{exE} [| EX x.P(x); !!x. P(x) ==> R |] ==> R \subcaption{Quantifier rules} \tdx{True_def} True == False-->False \tdx{not_def} ~P == P-->False \tdx{iff_def} P<->Q == (P-->Q) & (Q-->P) \tdx{ex1_def} EX! x. P(x) == EX x. P(x) & (ALL y. P(y) --> y=x) \subcaption{Definitions} \end{ttbox} \caption{Rules of intuitionistic logic} \label{fol-rules} \end{figure} \begin{figure} \begin{ttbox} \tdx{sym} a=b ==> b=a \tdx{trans} [| a=b; b=c |] ==> a=c \tdx{ssubst} [| b=a; P(a) |] ==> P(b) \subcaption{Derived equality rules} \tdx{TrueI} True \tdx{notI} (P ==> False) ==> ~P \tdx{notE} [| ~P; P |] ==> R \tdx{iffI} [| P ==> Q; Q ==> P |] ==> P<->Q \tdx{iffE} [| P <-> Q; [| P-->Q; Q-->P |] ==> R |] ==> R \tdx{iffD1} [| P <-> Q; P |] ==> Q \tdx{iffD2} [| P <-> Q; Q |] ==> P \tdx{ex1I} [| P(a); !!x. P(x) ==> x=a |] ==> EX! x. P(x) \tdx{ex1E} [| EX! x.P(x); !!x.[| P(x); ALL y. P(y) --> y=x |] ==> R |] ==> R \subcaption{Derived rules for \(\top\), \(\neg\), \(\bimp\) and \(\exists!\)} \tdx{conjE} [| P&Q; [| P; Q |] ==> R |] ==> R \tdx{impE} [| P-->Q; P; Q ==> R |] ==> R \tdx{allE} [| ALL x.P(x); P(x) ==> R |] ==> R \tdx{all_dupE} [| ALL x.P(x); [| P(x); ALL x.P(x) |] ==> R |] ==> R \subcaption{Sequent-style elimination rules} \tdx{conj_impE} [| (P&Q)-->S; P-->(Q-->S) ==> R |] ==> R \tdx{disj_impE} [| (P|Q)-->S; [| P-->S; Q-->S |] ==> R |] ==> R \tdx{imp_impE} [| (P-->Q)-->S; [| P; Q-->S |] ==> Q; S ==> R |] ==> R \tdx{not_impE} [| ~P --> S; P ==> False; S ==> R |] ==> R \tdx{iff_impE} [| (P<->Q)-->S; [| P; Q-->S |] ==> Q; [| Q; P-->S |] ==> P; S ==> R |] ==> R \tdx{all_impE} [| (ALL x.P(x))-->S; !!x.P(x); S ==> R |] ==> R \tdx{ex_impE} [| (EX x.P(x))-->S; P(a)-->S ==> R |] ==> R \end{ttbox} \subcaption{Intuitionistic simplification of implication} \caption{Derived rules for intuitionistic logic} \label{fol-int-derived} \end{figure} \section{Generic packages} \FOL{} instantiates most of Isabelle's generic packages; see {\tt FOL/ROOT.ML} for details. \begin{itemize} \item Because it includes a general substitution rule, \FOL{} instantiates the tactic \ttindex{hyp_subst_tac}, which substitutes for an equality throughout a subgoal and its hypotheses. \item It instantiates the simplifier. \ttindexbold{IFOL_ss} is the simplification set for intuitionistic first-order logic, while \ttindexbold{FOL_ss} is the simplification set for classical logic. Both equality ($=$) and the biconditional ($\bimp$) may be used for rewriting. See the file {\tt FOL/simpdata.ML} for a complete listing of the simplification rules% \iflabelundefined{sec:setting-up-simp}{}% {, and \S\ref{sec:setting-up-simp} for discussion}. \item It instantiates the classical reasoner. See~\S\ref{fol-cla-prover} for details. \end{itemize} \section{Intuitionistic proof procedures} \label{fol-int-prover} Implication elimination (the rules~{\tt mp} and~{\tt impE}) pose difficulties for automated proof. In intuitionistic logic, the assumption $P\imp Q$ cannot be treated like $\neg P\disj Q$. Given $P\imp Q$, we may use~$Q$ provided we can prove~$P$; the proof of~$P$ may require repeated use of $P\imp Q$. If the proof of~$P$ fails then the whole branch of the proof must be abandoned. Thus intuitionistic propositional logic requires backtracking. For an elementary example, consider the intuitionistic proof of $Q$ from $P\imp Q$ and $(P\imp Q)\imp P$. The implication $P\imp Q$ is needed twice: \[ \infer[({\imp}E)]{Q}{P\imp Q & \infer[({\imp}E)]{P}{(P\imp Q)\imp P & P\imp Q}} \] The theorem prover for intuitionistic logic does not use~{\tt impE}.\@ Instead, it simplifies implications using derived rules (Fig.\ts\ref{fol-int-derived}). It reduces the antecedents of implications to atoms and then uses Modus Ponens: from $P\imp Q$ and~$P$ deduce~$Q$. The rules \tdx{conj_impE} and \tdx{disj_impE} are straightforward: $(P\conj Q)\imp S$ is equivalent to $P\imp (Q\imp S)$, and $(P\disj Q)\imp S$ is equivalent to the conjunction of $P\imp S$ and $Q\imp S$. The other \ldots{\tt_impE} rules are unsafe; the method requires backtracking. All the rules are derived in the same simple manner. Dyckhoff has independently discovered similar rules, and (more importantly) has demonstrated their completeness for propositional logic~\cite{dyckhoff}. However, the tactics given below are not complete for first-order logic because they discard universally quantified assumptions after a single use. \begin{ttbox} mp_tac : int -> tactic eq_mp_tac : int -> tactic Int.safe_step_tac : int -> tactic Int.safe_tac : tactic Int.inst_step_tac : int -> tactic Int.step_tac : int -> tactic Int.fast_tac : int -> tactic Int.best_tac : int -> tactic \end{ttbox} Most of these belong to the structure {\tt Int} and resemble the tactics of Isabelle's classical reasoner. \begin{ttdescription} \item[\ttindexbold{mp_tac} {\it i}] attempts to use \tdx{notE} or \tdx{impE} within the assumptions in subgoal $i$. For each assumption of the form $\neg P$ or $P\imp Q$, it searches for another assumption unifiable with~$P$. By contradiction with $\neg P$ it can solve the subgoal completely; by Modus Ponens it can replace the assumption $P\imp Q$ by $Q$. The tactic can produce multiple outcomes, enumerating all suitable pairs of assumptions. \item[\ttindexbold{eq_mp_tac} {\it i}] is like {\tt mp_tac} {\it i}, but may not instantiate unknowns --- thus, it is safe. \item[\ttindexbold{Int.safe_step_tac} $i$] performs a safe step on subgoal~$i$. This may include proof by assumption or Modus Ponens (taking care not to instantiate unknowns), or {\tt hyp_subst_tac}. \item[\ttindexbold{Int.safe_tac}] repeatedly performs safe steps on all subgoals. It is deterministic, with at most one outcome. \item[\ttindexbold{Int.inst_step_tac} $i$] is like {\tt safe_step_tac}, but allows unknowns to be instantiated. \item[\ttindexbold{Int.step_tac} $i$] tries {\tt safe_tac} or {\tt inst_step_tac}, or applies an unsafe rule. This is the basic step of the intuitionistic proof procedure. \item[\ttindexbold{Int.fast_tac} $i$] applies {\tt step_tac}, using depth-first search, to solve subgoal~$i$. \item[\ttindexbold{Int.best_tac} $i$] applies {\tt step_tac}, using best-first search (guided by the size of the proof state) to solve subgoal~$i$. \end{ttdescription} Here are some of the theorems that {\tt Int.fast_tac} proves automatically. The latter three date from {\it Principia Mathematica} (*11.53, *11.55, *11.61)~\cite{principia}. \begin{ttbox} ~~P & ~~(P --> Q) --> ~~Q (ALL x y. P(x) --> Q(y)) <-> ((EX x. P(x)) --> (ALL y. Q(y))) (EX x y. P(x) & Q(x,y)) <-> (EX x. P(x) & (EX y. Q(x,y))) (EX y. ALL x. P(x) --> Q(x,y)) --> (ALL x. P(x) --> (EX y. Q(x,y))) \end{ttbox} \begin{figure} \begin{ttbox} \tdx{excluded_middle} ~P | P \tdx{disjCI} (~Q ==> P) ==> P|Q \tdx{exCI} (ALL x. ~P(x) ==> P(a)) ==> EX x.P(x) \tdx{impCE} [| P-->Q; ~P ==> R; Q ==> R |] ==> R \tdx{iffCE} [| P<->Q; [| P; Q |] ==> R; [| ~P; ~Q |] ==> R |] ==> R \tdx{notnotD} ~~P ==> P \tdx{swap} ~P ==> (~Q ==> P) ==> Q \end{ttbox} \caption{Derived rules for classical logic} \label{fol-cla-derived} \end{figure} \section{Classical proof procedures} \label{fol-cla-prover} The classical theory, \thydx{FOL}, consists of intuitionistic logic plus the rule $$ \vcenter{\infer{P}{\infer*{P}{[\neg P]}}} \eqno(classical) $$ \noindent Natural deduction in classical logic is not really all that natural. {\FOL} derives classical introduction rules for $\disj$ and~$\exists$, as well as classical elimination rules for~$\imp$ and~$\bimp$, and the swap rule (see Fig.\ts\ref{fol-cla-derived}). The classical reasoner is set up for \FOL, as the structure~{\tt Cla}. This structure is open, so \ML{} identifiers such as {\tt step_tac}, {\tt fast_tac}, {\tt best_tac}, etc., refer to it. Single-step proofs can be performed, using \ttindex{swap_res_tac} to deal with negated assumptions.\index{assumptions!negated} {\FOL} defines the following classical rule sets: \begin{ttbox} prop_cs : claset FOL_cs : claset \end{ttbox} \begin{ttdescription} \item[\ttindexbold{prop_cs}] contains the propositional rules, namely those for~$\top$, $\bot$, $\conj$, $\disj$, $\neg$, $\imp$ and~$\bimp$, along with the rule~{\tt refl}. \item[\ttindexbold{FOL_cs}] extends {\tt prop_cs} with the safe rules {\tt allI} and~{\tt exE} and the unsafe rules {\tt allE} and~{\tt exI}, as well as rules for unique existence. Search using this is incomplete since quantified formulae are used at most once. \end{ttdescription} \noindent See the file {\tt FOL/FOL.ML} for derivations of the classical rules, and \iflabelundefined{chap:classical}{the {\em Reference Manual\/}}% {Chap.\ts\ref{chap:classical}} for more discussion of classical proof methods. \section{An intuitionistic example} Here is a session similar to one in {\em Logic and Computation} \cite[pages~222--3]{paulson87}. Isabelle treats quantifiers differently from {\sc lcf}-based theorem provers such as {\sc hol}. The proof begins by entering the goal in intuitionistic logic, then applying the rule $({\imp}I)$. \begin{ttbox} goal IFOL.thy "(EX y. ALL x. Q(x,y)) --> (ALL x. EX y. Q(x,y))"; {\out Level 0} {\out (EX y. ALL x. Q(x,y)) --> (ALL x. EX y. Q(x,y))} {\out 1. (EX y. ALL x. Q(x,y)) --> (ALL x. EX y. Q(x,y))} \ttbreak by (resolve_tac [impI] 1); {\out Level 1} {\out (EX y. ALL x. Q(x,y)) --> (ALL x. EX y. Q(x,y))} {\out 1. EX y. ALL x. Q(x,y) ==> ALL x. EX y. Q(x,y)} \end{ttbox} In this example, we shall never have more than one subgoal. Applying $({\imp}I)$ replaces~\verb|-->| by~\verb|==>|, making \(\ex{y}\all{x}Q(x,y)\) an assumption. We have the choice of $({\exists}E)$ and $({\forall}I)$; let us try the latter. \begin{ttbox} by (resolve_tac [allI] 1); {\out Level 2} {\out (EX y. ALL x. Q(x,y)) --> (ALL x. EX y. Q(x,y))} {\out 1. !!x. EX y. ALL x. Q(x,y) ==> EX y. Q(x,y)} \end{ttbox} Applying $({\forall}I)$ replaces the \hbox{\tt ALL x} by \hbox{\tt!!x}, changing the universal quantifier from object~($\forall$) to meta~($\Forall$). The bound variable is a {\bf parameter} of the subgoal. We now must choose between $({\exists}I)$ and $({\exists}E)$. What happens if the wrong rule is chosen? \begin{ttbox} by (resolve_tac [exI] 1); {\out Level 3} {\out (EX y. ALL x. Q(x,y)) --> (ALL x. EX y. Q(x,y))} {\out 1. !!x. EX y. ALL x. Q(x,y) ==> Q(x,?y2(x))} \end{ttbox} The new subgoal~1 contains the function variable {\tt?y2}. Instantiating {\tt?y2} can replace~{\tt?y2(x)} by a term containing~{\tt x}, even though~{\tt x} is a bound variable. Now we analyse the assumption \(\exists y.\forall x. Q(x,y)\) using elimination rules: \begin{ttbox} by (eresolve_tac [exE] 1); {\out Level 4} {\out (EX y. ALL x. Q(x,y)) --> (ALL x. EX y. Q(x,y))} {\out 1. !!x y. ALL x. Q(x,y) ==> Q(x,?y2(x))} \end{ttbox} Applying $(\exists E)$ has produced the parameter {\tt y} and stripped the existential quantifier from the assumption. But the subgoal is unprovable: there is no way to unify {\tt ?y2(x)} with the bound variable~{\tt y}. Using {\tt choplev} we can return to the critical point. This time we apply $({\exists}E)$: \begin{ttbox} choplev 2; {\out Level 2} {\out (EX y. ALL x. Q(x,y)) --> (ALL x. EX y. Q(x,y))} {\out 1. !!x. EX y. ALL x. Q(x,y) ==> EX y. Q(x,y)} \ttbreak by (eresolve_tac [exE] 1); {\out Level 3} {\out (EX y. ALL x. Q(x,y)) --> (ALL x. EX y. Q(x,y))} {\out 1. !!x y. ALL x. Q(x,y) ==> EX y. Q(x,y)} \end{ttbox} We now have two parameters and no scheme variables. Applying $({\exists}I)$ and $({\forall}E)$ produces two scheme variables, which are applied to those parameters. Parameters should be produced early, as this example demonstrates. \begin{ttbox} by (resolve_tac [exI] 1); {\out Level 4} {\out (EX y. ALL x. Q(x,y)) --> (ALL x. EX y. Q(x,y))} {\out 1. !!x y. ALL x. Q(x,y) ==> Q(x,?y3(x,y))} \ttbreak by (eresolve_tac [allE] 1); {\out Level 5} {\out (EX y. ALL x. Q(x,y)) --> (ALL x. EX y. Q(x,y))} {\out 1. !!x y. Q(?x4(x,y),y) ==> Q(x,?y3(x,y))} \end{ttbox} The subgoal has variables {\tt ?y3} and {\tt ?x4} applied to both parameters. The obvious projection functions unify {\tt?x4(x,y)} with~{\tt x} and \verb|?y3(x,y)| with~{\tt y}. \begin{ttbox} by (assume_tac 1); {\out Level 6} {\out (EX y. ALL x. Q(x,y)) --> (ALL x. EX y. Q(x,y))} {\out No subgoals!} \end{ttbox} The theorem was proved in six tactic steps, not counting the abandoned ones. But proof checking is tedious; \ttindex{Int.fast_tac} proves the theorem in one step. \begin{ttbox} goal IFOL.thy "(EX y. ALL x. Q(x,y)) --> (ALL x. EX y. Q(x,y))"; {\out Level 0} {\out (EX y. ALL x. Q(x,y)) --> (ALL x. EX y. Q(x,y))} {\out 1. (EX y. ALL x. Q(x,y)) --> (ALL x. EX y. Q(x,y))} by (Int.fast_tac 1); {\out Level 1} {\out (EX y. ALL x. Q(x,y)) --> (ALL x. EX y. Q(x,y))} {\out No subgoals!} \end{ttbox} \section{An example of intuitionistic negation} The following example demonstrates the specialized forms of implication elimination. Even propositional formulae can be difficult to prove from the basic rules; the specialized rules help considerably. Propositional examples are easy to invent. As Dummett notes~\cite[page 28]{dummett}, $\neg P$ is classically provable if and only if it is intuitionistically provable; therefore, $P$ is classically provable if and only if $\neg\neg P$ is intuitionistically provable.% \footnote{Of course this holds only for propositional logic, not if $P$ is allowed to contain quantifiers.} Proving $\neg\neg P$ intuitionistically is much harder than proving~$P$ classically. Our example is the double negation of the classical tautology $(P\imp Q)\disj (Q\imp P)$. When stating the goal, we command Isabelle to expand negations to implications using the definition $\neg P\equiv P\imp\bot$. This allows use of the special implication rules. \begin{ttbox} goalw IFOL.thy [not_def] "~ ~ ((P-->Q) | (Q-->P))"; {\out Level 0} {\out ~ ~ ((P --> Q) | (Q --> P))} {\out 1. ((P --> Q) | (Q --> P) --> False) --> False} \end{ttbox} The first step is trivial. \begin{ttbox} by (resolve_tac [impI] 1); {\out Level 1} {\out ~ ~ ((P --> Q) | (Q --> P))} {\out 1. (P --> Q) | (Q --> P) --> False ==> False} \end{ttbox} By $(\imp E)$ it would suffice to prove $(P\imp Q)\disj (Q\imp P)$, but that formula is not a theorem of intuitionistic logic. Instead we apply the specialized implication rule \tdx{disj_impE}. It splits the assumption into two assumptions, one for each disjunct. \begin{ttbox} by (eresolve_tac [disj_impE] 1); {\out Level 2} {\out ~ ~ ((P --> Q) | (Q --> P))} {\out 1. [| (P --> Q) --> False; (Q --> P) --> False |] ==> False} \end{ttbox} We cannot hope to prove $P\imp Q$ or $Q\imp P$ separately, but their negations are inconsistent. Applying \tdx{imp_impE} breaks down the assumption $\neg(P\imp Q)$, asking to show~$Q$ while providing new assumptions~$P$ and~$\neg Q$. \begin{ttbox} by (eresolve_tac [imp_impE] 1); {\out Level 3} {\out ~ ~ ((P --> Q) | (Q --> P))} {\out 1. [| (Q --> P) --> False; P; Q --> False |] ==> Q} {\out 2. [| (Q --> P) --> False; False |] ==> False} \end{ttbox} Subgoal~2 holds trivially; let us ignore it and continue working on subgoal~1. Thanks to the assumption~$P$, we could prove $Q\imp P$; applying \tdx{imp_impE} is simpler. \begin{ttbox} by (eresolve_tac [imp_impE] 1); {\out Level 4} {\out ~ ~ ((P --> Q) | (Q --> P))} {\out 1. [| P; Q --> False; Q; P --> False |] ==> P} {\out 2. [| P; Q --> False; False |] ==> Q} {\out 3. [| (Q --> P) --> False; False |] ==> False} \end{ttbox} The three subgoals are all trivial. \begin{ttbox} by (REPEAT (eresolve_tac [FalseE] 2)); {\out Level 5} {\out ~ ~ ((P --> Q) | (Q --> P))} {\out 1. [| P; Q --> False; Q; P --> False |] ==> P} \ttbreak by (assume_tac 1); {\out Level 6} {\out ~ ~ ((P --> Q) | (Q --> P))} {\out No subgoals!} \end{ttbox} This proof is also trivial for {\tt Int.fast_tac}. \section{A classical example} \label{fol-cla-example} To illustrate classical logic, we shall prove the theorem $\ex{y}\all{x}P(y)\imp P(x)$. Informally, the theorem can be proved as follows. Choose~$y$ such that~$\neg P(y)$, if such exists; otherwise $\all{x}P(x)$ is true. Either way the theorem holds. The formal proof does not conform in any obvious way to the sketch given above. The key inference is the first one, \tdx{exCI}; this classical version of~$(\exists I)$ allows multiple instantiation of the quantifier. \begin{ttbox} goal FOL.thy "EX y. ALL x. P(y)-->P(x)"; {\out Level 0} {\out EX y. ALL x. P(y) --> P(x)} {\out 1. EX y. ALL x. P(y) --> P(x)} \ttbreak by (resolve_tac [exCI] 1); {\out Level 1} {\out EX y. ALL x. P(y) --> P(x)} {\out 1. ALL y. ~ (ALL x. P(y) --> P(x)) ==> ALL x. P(?a) --> P(x)} \end{ttbox} We can either exhibit a term {\tt?a} to satisfy the conclusion of subgoal~1, or produce a contradiction from the assumption. The next steps are routine. \begin{ttbox} by (resolve_tac [allI] 1); {\out Level 2} {\out EX y. ALL x. P(y) --> P(x)} {\out 1. !!x. ALL y. ~ (ALL x. P(y) --> P(x)) ==> P(?a) --> P(x)} \ttbreak by (resolve_tac [impI] 1); {\out Level 3} {\out EX y. ALL x. P(y) --> P(x)} {\out 1. !!x. [| ALL y. ~ (ALL x. P(y) --> P(x)); P(?a) |] ==> P(x)} \end{ttbox} By the duality between $\exists$ and~$\forall$, applying~$(\forall E)$ in effect applies~$(\exists I)$ again. \begin{ttbox} by (eresolve_tac [allE] 1); {\out Level 4} {\out EX y. ALL x. P(y) --> P(x)} {\out 1. !!x. [| P(?a); ~ (ALL xa. P(?y3(x)) --> P(xa)) |] ==> P(x)} \end{ttbox} In classical logic, a negated assumption is equivalent to a conclusion. To get this effect, we create a swapped version of~$(\forall I)$ and apply it using \ttindex{eresolve_tac}; we could equivalently have applied~$(\forall I)$ using \ttindex{swap_res_tac}. \begin{ttbox} allI RSN (2,swap); {\out val it = "[| ~ (ALL x. ?P1(x)); !!x. ~ ?Q ==> ?P1(x) |] ==> ?Q" : thm} by (eresolve_tac [it] 1); {\out Level 5} {\out EX y. ALL x. P(y) --> P(x)} {\out 1. !!x xa. [| P(?a); ~ P(x) |] ==> P(?y3(x)) --> P(xa)} \end{ttbox} The previous conclusion, {\tt P(x)}, has become a negated assumption. \begin{ttbox} by (resolve_tac [impI] 1); {\out Level 6} {\out EX y. ALL x. P(y) --> P(x)} {\out 1. !!x xa. [| P(?a); ~ P(x); P(?y3(x)) |] ==> P(xa)} \end{ttbox} The subgoal has three assumptions. We produce a contradiction between the \index{assumptions!contradictory} assumptions~\verb|~P(x)| and~{\tt P(?y3(x))}. The proof never instantiates the unknown~{\tt?a}. \begin{ttbox} by (eresolve_tac [notE] 1); {\out Level 7} {\out EX y. ALL x. P(y) --> P(x)} {\out 1. !!x xa. [| P(?a); P(?y3(x)) |] ==> P(x)} \ttbreak by (assume_tac 1); {\out Level 8} {\out EX y. ALL x. P(y) --> P(x)} {\out No subgoals!} \end{ttbox} The civilised way to prove this theorem is through \ttindex{deepen_tac}, which automatically uses the classical version of~$(\exists I)$: \begin{ttbox} goal FOL.thy "EX y. ALL x. P(y)-->P(x)"; {\out Level 0} {\out EX y. ALL x. P(y) --> P(x)} {\out 1. EX y. ALL x. P(y) --> P(x)} by (deepen_tac FOL_cs 0 1); {\out Depth = 0} {\out Depth = 2} {\out Level 1} {\out EX y. ALL x. P(y) --> P(x)} {\out No subgoals!} \end{ttbox} If this theorem seems counterintuitive, then perhaps you are an intuitionist. In constructive logic, proving $\ex{y}\all{x}P(y)\imp P(x)$ requires exhibiting a particular term~$t$ such that $\all{x}P(t)\imp P(x)$, which we cannot do without further knowledge about~$P$. \section{Derived rules and the classical tactics} Classical first-order logic can be extended with the propositional connective $if(P,Q,R)$, where $$ if(P,Q,R) \equiv P\conj Q \disj \neg P \conj R. \eqno(if) $$ Theorems about $if$ can be proved by treating this as an abbreviation, replacing $if(P,Q,R)$ by $P\conj Q \disj \neg P \conj R$ in subgoals. But this duplicates~$P$, causing an exponential blowup and an unreadable formula. Introducing further abbreviations makes the problem worse. Natural deduction demands rules that introduce and eliminate $if(P,Q,R)$ directly, without reference to its definition. The simple identity \[ if(P,Q,R) \,\bimp\, (P\imp Q)\conj (\neg P\imp R) \] suggests that the $if$-introduction rule should be \[ \infer[({if}\,I)]{if(P,Q,R)}{\infer*{Q}{[P]} & \infer*{R}{[\neg P]}} \] The $if$-elimination rule reflects the definition of $if(P,Q,R)$ and the elimination rules for~$\disj$ and~$\conj$. \[ \infer[({if}\,E)]{S}{if(P,Q,R) & \infer*{S}{[P,Q]} & \infer*{S}{[\neg P,R]}} \] Having made these plans, we get down to work with Isabelle. The theory of classical logic, {\tt FOL}, is extended with the constant $if::[o,o,o]\To o$. The axiom \tdx{if_def} asserts the equation~$(if)$. \begin{ttbox} If = FOL + consts if :: "[o,o,o]=>o" rules if_def "if(P,Q,R) == P&Q | ~P&R" end \end{ttbox} The derivations of the introduction and elimination rules demonstrate the methods for rewriting with definitions. Classical reasoning is required, so we use {\tt fast_tac}. \subsection{Deriving the introduction rule} The introduction rule, given the premises $P\Imp Q$ and $\neg P\Imp R$, concludes $if(P,Q,R)$. We propose the conclusion as the main goal using~\ttindex{goalw}, which uses {\tt if_def} to rewrite occurrences of $if$ in the subgoal. \begin{ttbox} val prems = goalw If.thy [if_def] "[| P ==> Q; ~ P ==> R |] ==> if(P,Q,R)"; {\out Level 0} {\out if(P,Q,R)} {\out 1. P & Q | ~ P & R} \end{ttbox} The premises (bound to the {\ML} variable {\tt prems}) are passed as introduction rules to \ttindex{fast_tac}: \begin{ttbox} by (fast_tac (FOL_cs addIs prems) 1); {\out Level 1} {\out if(P,Q,R)} {\out No subgoals!} val ifI = result(); \end{ttbox} \subsection{Deriving the elimination rule} The elimination rule has three premises, two of which are themselves rules. The conclusion is simply $S$. \begin{ttbox} val major::prems = goalw If.thy [if_def] "[| if(P,Q,R); [| P; Q |] ==> S; [| ~ P; R |] ==> S |] ==> S"; {\out Level 0} {\out S} {\out 1. S} \end{ttbox} The major premise contains an occurrence of~$if$, but the version returned by \ttindex{goalw} (and bound to the {\ML} variable~{\tt major}) has the definition expanded. Now \ttindex{cut_facts_tac} inserts~{\tt major} as an assumption in the subgoal, so that \ttindex{fast_tac} can break it down. \begin{ttbox} by (cut_facts_tac [major] 1); {\out Level 1} {\out S} {\out 1. P & Q | ~ P & R ==> S} \ttbreak by (fast_tac (FOL_cs addIs prems) 1); {\out Level 2} {\out S} {\out No subgoals!} val ifE = result(); \end{ttbox} As you may recall from \iflabelundefined{definitions}{{\em Introduction to Isabelle}}% {\S\ref{definitions}}, there are other ways of treating definitions when deriving a rule. We can start the proof using {\tt goal}, which does not expand definitions, instead of {\tt goalw}. We can use \ttindex{rewrite_goals_tac} to expand definitions in the subgoals --- perhaps after calling \ttindex{cut_facts_tac} to insert the rule's premises. We can use \ttindex{rewrite_rule}, which is a meta-inference rule, to expand definitions in the premises directly. \subsection{Using the derived rules} The rules just derived have been saved with the {\ML} names \tdx{ifI} and~\tdx{ifE}. They permit natural proofs of theorems such as the following: \begin{eqnarray*} if(P, if(Q,A,B), if(Q,C,D)) & \bimp & if(Q,if(P,A,C),if(P,B,D)) \\ if(if(P,Q,R), A, B) & \bimp & if(P,if(Q,A,B),if(R,A,B)) \end{eqnarray*} Proofs also require the classical reasoning rules and the $\bimp$ introduction rule (called~\tdx{iffI}: do not confuse with~{\tt ifI}). To display the $if$-rules in action, let us analyse a proof step by step. \begin{ttbox} goal If.thy "if(P, if(Q,A,B), if(Q,C,D)) <-> if(Q, if(P,A,C), if(P,B,D))"; {\out Level 0} {\out if(P,if(Q,A,B),if(Q,C,D)) <-> if(Q,if(P,A,C),if(P,B,D))} {\out 1. if(P,if(Q,A,B),if(Q,C,D)) <-> if(Q,if(P,A,C),if(P,B,D))} \ttbreak by (resolve_tac [iffI] 1); {\out Level 1} {\out if(P,if(Q,A,B),if(Q,C,D)) <-> if(Q,if(P,A,C),if(P,B,D))} {\out 1. if(P,if(Q,A,B),if(Q,C,D)) ==> if(Q,if(P,A,C),if(P,B,D))} {\out 2. if(Q,if(P,A,C),if(P,B,D)) ==> if(P,if(Q,A,B),if(Q,C,D))} \end{ttbox} The $if$-elimination rule can be applied twice in succession. \begin{ttbox} by (eresolve_tac [ifE] 1); {\out Level 2} {\out if(P,if(Q,A,B),if(Q,C,D)) <-> if(Q,if(P,A,C),if(P,B,D))} {\out 1. [| P; if(Q,A,B) |] ==> if(Q,if(P,A,C),if(P,B,D))} {\out 2. [| ~ P; if(Q,C,D) |] ==> if(Q,if(P,A,C),if(P,B,D))} {\out 3. if(Q,if(P,A,C),if(P,B,D)) ==> if(P,if(Q,A,B),if(Q,C,D))} \ttbreak by (eresolve_tac [ifE] 1); {\out Level 3} {\out if(P,if(Q,A,B),if(Q,C,D)) <-> if(Q,if(P,A,C),if(P,B,D))} {\out 1. [| P; Q; A |] ==> if(Q,if(P,A,C),if(P,B,D))} {\out 2. [| P; ~ Q; B |] ==> if(Q,if(P,A,C),if(P,B,D))} {\out 3. [| ~ P; if(Q,C,D) |] ==> if(Q,if(P,A,C),if(P,B,D))} {\out 4. if(Q,if(P,A,C),if(P,B,D)) ==> if(P,if(Q,A,B),if(Q,C,D))} \end{ttbox} % In the first two subgoals, all assumptions have been reduced to atoms. Now $if$-introduction can be applied. Observe how the $if$-rules break down occurrences of $if$ when they become the outermost connective. \begin{ttbox} by (resolve_tac [ifI] 1); {\out Level 4} {\out if(P,if(Q,A,B),if(Q,C,D)) <-> if(Q,if(P,A,C),if(P,B,D))} {\out 1. [| P; Q; A; Q |] ==> if(P,A,C)} {\out 2. [| P; Q; A; ~ Q |] ==> if(P,B,D)} {\out 3. [| P; ~ Q; B |] ==> if(Q,if(P,A,C),if(P,B,D))} {\out 4. [| ~ P; if(Q,C,D) |] ==> if(Q,if(P,A,C),if(P,B,D))} {\out 5. if(Q,if(P,A,C),if(P,B,D)) ==> if(P,if(Q,A,B),if(Q,C,D))} \ttbreak by (resolve_tac [ifI] 1); {\out Level 5} {\out if(P,if(Q,A,B),if(Q,C,D)) <-> if(Q,if(P,A,C),if(P,B,D))} {\out 1. [| P; Q; A; Q; P |] ==> A} {\out 2. [| P; Q; A; Q; ~ P |] ==> C} {\out 3. [| P; Q; A; ~ Q |] ==> if(P,B,D)} {\out 4. [| P; ~ Q; B |] ==> if(Q,if(P,A,C),if(P,B,D))} {\out 5. [| ~ P; if(Q,C,D) |] ==> if(Q,if(P,A,C),if(P,B,D))} {\out 6. if(Q,if(P,A,C),if(P,B,D)) ==> if(P,if(Q,A,B),if(Q,C,D))} \end{ttbox} Where do we stand? The first subgoal holds by assumption; the second and third, by contradiction. This is getting tedious. Let us revert to the initial proof state and let \ttindex{fast_tac} solve it. The classical rule set {\tt if_cs} contains the rules of~{\FOL} plus the derived rules for~$if$. \begin{ttbox} choplev 0; {\out Level 0} {\out if(P,if(Q,A,B),if(Q,C,D)) <-> if(Q,if(P,A,C),if(P,B,D))} {\out 1. if(P,if(Q,A,B),if(Q,C,D)) <-> if(Q,if(P,A,C),if(P,B,D))} val if_cs = FOL_cs addSIs [ifI] addSEs[ifE]; by (fast_tac if_cs 1); {\out Level 1} {\out if(P,if(Q,A,B),if(Q,C,D)) <-> if(Q,if(P,A,C),if(P,B,D))} {\out No subgoals!} \end{ttbox} This tactic also solves the other example. \begin{ttbox} goal If.thy "if(if(P,Q,R), A, B) <-> if(P, if(Q,A,B), if(R,A,B))"; {\out Level 0} {\out if(if(P,Q,R),A,B) <-> if(P,if(Q,A,B),if(R,A,B))} {\out 1. if(if(P,Q,R),A,B) <-> if(P,if(Q,A,B),if(R,A,B))} \ttbreak by (fast_tac if_cs 1); {\out Level 1} {\out if(if(P,Q,R),A,B) <-> if(P,if(Q,A,B),if(R,A,B))} {\out No subgoals!} \end{ttbox} \subsection{Derived rules versus definitions} Dispensing with the derived rules, we can treat $if$ as an abbreviation, and let \ttindex{fast_tac} prove the expanded formula. Let us redo the previous proof: \begin{ttbox} choplev 0; {\out Level 0} {\out if(if(P,Q,R),A,B) <-> if(P,if(Q,A,B),if(R,A,B))} {\out 1. if(if(P,Q,R),A,B) <-> if(P,if(Q,A,B),if(R,A,B))} \end{ttbox} This time, simply unfold using the definition of $if$: \begin{ttbox} by (rewrite_goals_tac [if_def]); {\out Level 1} {\out if(if(P,Q,R),A,B) <-> if(P,if(Q,A,B),if(R,A,B))} {\out 1. (P & Q | ~ P & R) & A | ~ (P & Q | ~ P & R) & B <->} {\out P & (Q & A | ~ Q & B) | ~ P & (R & A | ~ R & B)} \end{ttbox} We are left with a subgoal in pure first-order logic: \begin{ttbox} by (fast_tac FOL_cs 1); {\out Level 2} {\out if(if(P,Q,R),A,B) <-> if(P,if(Q,A,B),if(R,A,B))} {\out No subgoals!} \end{ttbox} Expanding definitions reduces the extended logic to the base logic. This approach has its merits --- especially if the prover for the base logic is good --- but can be slow. In these examples, proofs using {\tt if_cs} (the derived rules) run about six times faster than proofs using {\tt FOL_cs}. Expanding definitions also complicates error diagnosis. Suppose we are having difficulties in proving some goal. If by expanding definitions we have made it unreadable, then we have little hope of diagnosing the problem. Attempts at program verification often yield invalid assertions. Let us try to prove one: \begin{ttbox} goal If.thy "if(if(P,Q,R), A, B) <-> if(P, if(Q,A,B), if(R,B,A))"; {\out Level 0} {\out if(if(P,Q,R),A,B) <-> if(P,if(Q,A,B),if(R,B,A))} {\out 1. if(if(P,Q,R),A,B) <-> if(P,if(Q,A,B),if(R,B,A))} by (fast_tac FOL_cs 1); {\out by: tactic failed} \end{ttbox} This failure message is uninformative, but we can get a closer look at the situation by applying \ttindex{step_tac}. \begin{ttbox} by (REPEAT (step_tac if_cs 1)); {\out Level 1} {\out if(if(P,Q,R),A,B) <-> if(P,if(Q,A,B),if(R,B,A))} {\out 1. [| A; ~ P; R; ~ P; R |] ==> B} {\out 2. [| B; ~ P; ~ R; ~ P; ~ R |] ==> A} {\out 3. [| ~ P; R; B; ~ P; R |] ==> A} {\out 4. [| ~ P; ~ R; A; ~ B; ~ P |] ==> R} \end{ttbox} Subgoal~1 is unprovable and yields a countermodel: $P$ and~$B$ are false while~$R$ and~$A$ are true. This truth assignment reduces the main goal to $true\bimp false$, which is of course invalid. We can repeat this analysis by expanding definitions, using just the rules of {\FOL}: \begin{ttbox} choplev 0; {\out Level 0} {\out if(if(P,Q,R),A,B) <-> if(P,if(Q,A,B),if(R,B,A))} {\out 1. if(if(P,Q,R),A,B) <-> if(P,if(Q,A,B),if(R,B,A))} \ttbreak by (rewrite_goals_tac [if_def]); {\out Level 1} {\out if(if(P,Q,R),A,B) <-> if(P,if(Q,A,B),if(R,B,A))} {\out 1. (P & Q | ~ P & R) & A | ~ (P & Q | ~ P & R) & B <->} {\out P & (Q & A | ~ Q & B) | ~ P & (R & B | ~ R & A)} by (fast_tac FOL_cs 1); {\out by: tactic failed} \end{ttbox} Again we apply \ttindex{step_tac}: \begin{ttbox} by (REPEAT (step_tac FOL_cs 1)); {\out Level 2} {\out if(if(P,Q,R),A,B) <-> if(P,if(Q,A,B),if(R,B,A))} {\out 1. [| A; ~ P; R; ~ P; R; ~ False |] ==> B} {\out 2. [| A; ~ P; R; R; ~ False; ~ B; ~ B |] ==> Q} {\out 3. [| B; ~ P; ~ R; ~ P; ~ A |] ==> R} {\out 4. [| B; ~ P; ~ R; ~ Q; ~ A |] ==> R} {\out 5. [| B; ~ R; ~ P; ~ A; ~ R; Q; ~ False |] ==> A} {\out 6. [| ~ P; R; B; ~ P; R; ~ False |] ==> A} {\out 7. [| ~ P; ~ R; A; ~ B; ~ R |] ==> P} {\out 8. [| ~ P; ~ R; A; ~ B; ~ R |] ==> Q} \end{ttbox} Subgoal~1 yields the same countermodel as before. But each proof step has taken six times as long, and the final result contains twice as many subgoals. Expanding definitions causes a great increase in complexity. This is why the classical prover has been designed to accept derived rules. \index{first-order logic|)}