\documentclass[11pt]{article}
\usepackage{fullpage}
\usepackage{pslatex}
\usepackage{amsmath,proof,amsthm,amssymb}
%% part of a problem
\newcommand{\task}[2]
{\bigskip \noindent
{\bf Task #1} (#2 pts).}
\newcommand{\ectask}[1]
{\bigskip \noindent
{\bf Task #1} (Extra Credit).}
\newcommand{\dsd}[1]{\ensuremath{\mathsf{#1}}}
\newcommand{\irl}[1]{\texttt{#1}}
\newcommand{\ttt}[1]{\texttt{#1}}
\newcommand{\true}[1]{\ensuremath{#1 \, \dsd{true}}}
\newcommand{\even}[1]{\ensuremath{\dsd{even}(#1)}}
\newcommand{\odd}[1]{\ensuremath{\dsd{odd}(#1)}}
\newcommand{\suc}[1]{\ensuremath{\dsd{s} \: #1}}
\newcommand{\seq}[2]{\ensuremath{#1 \Longrightarrow #2}}
\newcommand{\csupset}[0]{\ensuremath{\mathord{\supset}}}
\title{Assignment 7: \\
Theorem Proving}
\author{15-317: Constructive Logic}
\date{Out: Thursday, October 23, 2008 \\
Due: Thursday, October 30, 2008, before class}
\begin{document}
\newtheorem{theorem}{Theorem}
\newtheorem{lemma}[theorem]{Lemma}
\maketitle
\section{Sequent Calculus}
\subsection{Rules}
\[
\begin{array}{c}
\infer[init]{\seq{\Gamma}{P}}{P \in \Gamma}
\end{array}
\]
\[
\begin{array}{cc}
\infer[\wedge R]{\seq{\Gamma}{A \wedge B}}
{\seq{\Gamma}{A} &
\seq{\Gamma}{B}}
&
\infer[\wedge L]{\seq{\Gamma,A \wedge B}{C}}
{\seq{\Gamma,A,B}{C}}
\\ \\
\infer[\top R]{\seq{\Gamma}{\top}}{}
&
\infer[\top L]{\seq{\Gamma,\top}{C}}{\seq{\Gamma}{C}}
\\ \\
\infer[\vee R_1]{\seq{\Gamma}{A \vee B}}{\seq{\Gamma}{A}}
\quad
\infer[\vee R_2]{\seq{\Gamma}{A \vee B}}{\seq{\Gamma}{B}}
&
\infer[\vee L]{\seq{\Gamma,A \vee B}{C}}
{\seq{\Gamma,A}{C} &
\seq{\Gamma,B}{C}}
\\ \\
\text{(no rule $\bot R$)}
&
\infer[\bot L]{\seq{\Gamma,\bot}{C}}{}
\\ \\
\infer[\csupset R]{\seq{\Gamma}{A \supset B}}{\seq{\Gamma,A}{B}}
&
\infer[\csupset L]{\seq{\Gamma,A \supset B}{C}}
{\seq{\Gamma,A \supset B}{A} &
\seq{\Gamma,B}{C}}
\end{array}
\]
Note that we treat $\Gamma$ as a set of hypotheses, so the notation
$\Gamma,A$ means that $A$ occurs somewhere in the set of hypotheses.
This sequent calculus satisfies weakening, identity, and cut:
\begin{itemize}
\item \textbf{Weakening:} If \seq{\Gamma}{C} then \seq{\Gamma,A}{C}.
\item \textbf{Identity:} For all $A$, \seq{\Gamma,A}{A}.
\item \textbf{Cut:} If \seq{\Gamma}{A} and \seq{\Gamma,A}{C} then
\seq{\Gamma}{C}.
\end{itemize}
\subsection{Differences with class}
This sequent calculus differs from the one presented in class on
Thursday, Oct. 23. in a few ways:
\begin{itemize}
\item Conjunction is given a single left rule, decomposing the
conjunction into two assumptions, rather than two left rules
corresponding to \ttt{fst} and \ttt{snd}.
\item The rules $\top L, \wedge L, \vee L, \mathord{\supset}L$ remove
the assumption you're using from the context (when going from the
conclusion of the rule to the premise). For example, in class, we
wrote:
\[
\infer[\vee L_{class}]{\seq{\Gamma,A \vee B}{C}}
{\seq{\Gamma,A \vee B,A}{C} &
\seq{\Gamma,A \vee B,B}{C}}
\]
which keeps the assumption $A \vee B$ in both premises. This is
problematic if you want to implement a theorem prover by typing the
rules into Prolog: you can apply the $\vee L_{class}$ rule again in the
premises, and again in their premises, etc., causing Prolog's proof
search to diverge.
\end{itemize}
However, the above sequent calculus is still correct, because neither of
these changes affects which sequents are provable. We ask you to show
one case:
\task{1}{5} Show that the rules $\vee L_{class}$ and $\vee L$
are equivalent by proving the following:
\begin{enumerate}
\item \seq{\Gamma,A \vee B,A}{C} iff \seq{\Gamma,A}{C}
\item \seq{\Gamma,A \vee B,B}{C} iff \seq{\Gamma,B}{C}
\end{enumerate}
Hint: use weakening, identity, and cut!
\subsection{Prolog Implementation}
In Figure~\ref{fig:seq-prolog}, we present a Prolog implementation of
these rules. The predicate \ttt{choose(G,A,G')} means that $A$ is in
$G$ and that removing $A$ from $G$ gives $G'$ (i.e., $G = (G',A)$, keeping
in mind that order doesn't matter). We'll use this predicate to write
the left rules, so they apply to any assumption in the context.
\task{2}{0} Read and understand this Prolog code.
\begin{figure}
\begin{verbatim}
choose([X|Xs],X,Xs).
choose([X|Xs],Y,[X|Ys]) :-
choose(Xs,Y,Ys).
% == initial ==
prove(G0,atom(P)) :- choose(G0,atom(P),_).
% == right rules ==
prove(_,top).
prove(G,and(A,B)) :- prove(G,A),prove(G,B).
%% no rule for bot
prove(G,or(A,_)) :- prove(G,A).
prove(G,or(_,B)) :- prove(G,B).
prove(G,implies(A,B)) :- prove([A|G],B).
% == left rules ==
prove(G0,C) :-
choose(G0,top,G),
prove(G,C).
prove(G0,C) :-
choose(G0,and(A,B),G),
prove([A,B|G],C).
prove(G0,_) :-
choose(G0,bot,_).
prove(G0,C) :-
choose(G0,or(A,B),G),
prove([A|G],C),
prove([B|G],C).
prove(G0,C) :-
choose(G0,implies(A,B),G),
prove(G0,A),
prove([B|G],C).
\end{verbatim}
\caption{Prolog code for sequent calculus rules}
\label{fig:seq-prolog}
\end{figure}
\section{Contraction-Free Sequent Calculus}
\subsection{The Problem}
Unfortunately, the above Prolog program does not always terminate. In
almost every rule, a connective is decomposed as you go from the
conclusion to the premises. However, this is not the case for the
implication left rule, where the assumption {$A \supset B$}
is copied to the first premise:
\[
\infer[\csupset L]
{\seq{\Gamma,A \supset B}{C}}
{\seq{\Gamma,\framebox{$A \supset B$}}{A} &
\seq{\Gamma,B}{C}}
\]
\task{1}{3} Explain why running the above Prolog program to \ttt{prove}
the sequent
\[
\seq{[]}{((P \vee (P \supset \bot)) \supset \bot) \supset \bot}
\]
%
loops: find a cycle in the series of goals that Prolog tries to prove.
(For example, if the rules were
\begin{verbatim}
foo(X) :- bar(s(X)).
bar(s(X)) :- foo(X).
\end{verbatim}
%
your answer would be ``When Prolog tries to prove \ttt{foo(z)} using the
first rule, it tries to prove \ttt{bar(s(z))}, but using the second rule
yields the subgoal \ttt{foo(z)}, so we've cycled back to where we
started.'')
\task{2}{2} Suppose we did not copy the implication to the first
premise:
\[
\infer[\csupset L']
{\seq{\Gamma,A \supset B}{C}}
{\seq{\Gamma}{A} &
\seq{\Gamma,B}{C}}
\]
%
Argue that this sequent calculus is not complete by explaining why the
following sequent is not provable:
\[
\seq{[]}{((P \vee (P \supset \bot)) \supset \bot) \supset \bot}
\]
\subsection{The Solution}
Thus, we need to keep the implication assumption in the first premise,
but the na\"ive way of doing this leads to non-termination. We can fix
this problem using \emph{Dyckhoff's contraction-free sequent calculus}.
The key idea is to replace the above implication left-rule with a set of
better-behaved rules. These rules break down the \emph{left-hand-side} of an
implication assumption, so something gets smaller every time a rule is
applied.
We will have one implication-left-rule for each possible left-hand-side.
Four of these rules are based on equivalences, many of which you have
proved over the course of the semester:
\begin{eqnarray*}
(\top \supset B) & \equiv & B \\
(A_1 \wedge A_2) \supset B & \equiv & A_1 \supset (A_2 \supset B) \\
(\bot \supset B) & \equiv & \top \\
(A_1 \vee A_2) \supset B & \equiv & (A_1 \supset B) \wedge (A_2 \supset B) \\
\end{eqnarray*}
%
Read left-to-right, these equivalences simplify the proposition to the
left of the $\supset$.
This gives the following four rules, which replace an assumption with an
equivalent but simpler one:
\[
\infer[\csupset L_\top]
{\seq{\Gamma,\top \supset B}{C}}
{\seq{\Gamma,B}{C}}
\quad
\infer[\csupset L_\wedge]
{\seq{\Gamma,(A_1 \wedge A_2) \supset B}{C}}
{\seq{\Gamma,A_1 \supset (A_2 \supset B)}{C}}
\quad
\infer[\csupset L_\bot]
{\seq{\Gamma,\bot \supset B}{C}}
{\seq{\Gamma}{C}}
\quad
\infer[\csupset L_\vee]
{\seq{\Gamma,(A_1 \vee A_2) \supset B}{C}}
{\seq{\Gamma,A_1 \supset B, A_2 \supset B}{C}}
\]
We need two additional rules, for atomic propositions and implications:
\[
\infer[\csupset L_P]
{\seq{\Gamma,P \supset B}{C}}
{P \in \Gamma &
\seq{\Gamma,B}{C}}
\quad
\infer[\csupset L_\supset]
{\seq{\Gamma,(A_1 \supset A_2) \supset B}{C}}
{\seq{\Gamma,(A_2 \supset B),A_1}{A_2} &
\seq{\Gamma,B}{C}}
\]
The first rule is the usual function application rule, but restricted to
atoms that are already in the context.
The second rule merits some explanation: if we were applying the
original implication left rule $\supset L$, the first premise would be:
\[
\seq{\Gamma,((A_1 \supset A_2) \supset B)}{A_1 \supset A_2}
\]
Because we can always introduce an implication on the right, it is
equivalent to prove
\[
\seq{\Gamma,((A_1 \supset A_2) \supset B),A_1}{A_2}
\]
But \emph{under the assumption of $A_1$}, $(A_1 \supset A_2) \equiv A_2$,
so we can simplify the assumption to $(A_2 \supset B)$.
We do not give a formal termination proof for running these rules, but
the idea is that each rule simplifies the implication assumption, so it
is no longer possible to loop.
\task{3}{15} Implement the contraction-free sequent calculus in Prolog:
\begin{itemize}
\item \textbf{Remove} the clause corresponding to $\csupset L$.
\item \textbf{Add} six new clauses for $\csupset L_\top, \csupset
L_\wedge, \csupset L_\bot, \csupset L_\vee, \csupset L_P, \csupset
L_\supset$.
\end{itemize}
Your implementation should work for the tests provided in the support
code, including the law-of-the-excluded-middle example that loops
above.
\section{Inversion}
\subsection{Invertible Left Rules}
Even though it is sound and complete, your implementation is inefficient
in a couple of ways. We will use the idea of \emph{invertibility} to
fix this. A rule is \emph{invertible} if the conclusion implies the
premise. Because the conclusion of an invertible rule is true iff the
premises are, one can eagerly apply such a rule whenever it applies,
without having to backtrack.
\task{1}{5} Determine whether each left rule is invertible (hand in only
your yes/no answers):
\begin{itemize}
\item [$\wedge L$]
If {\seq{\Gamma,A \wedge B}{C}}
then
{\seq{\Gamma,A,B}{C}}
\item [$\top L$] If {\seq{\Gamma,\top}{C}} then {\seq{\Gamma}{C}}.
\item [$\vee L$] If {\seq{\Gamma,A \vee B}{C}} then {\seq{\Gamma,A}{C}
and \seq{\Gamma,B}{C}}.
\item [$\bot L$] If {\seq{\Gamma,\bot}{C}} then true.
\item [$\csupset L_\top$]
If {\seq{\Gamma,\top \supset B}{C}}
then {\seq{\Gamma,B}{C}}.
\item [$\csupset L_\wedge$]
If {\seq{\Gamma,(A_1 \wedge A_2) \supset B}{C}}
then {\seq{\Gamma,A_1 \supset (A_2 \supset B)}{C}}.
\item [$\csupset L_\bot$]
If {\seq{\Gamma,\bot \supset B}{C}} then {\seq{\Gamma}{C}}.
\item [$\csupset L_\vee$]
If {\seq{\Gamma,(A_1 \vee A_2) \supset B}{C}}
then {\seq{\Gamma,A_1 \supset B, A_2 \supset B}{C}}.
\item [$\csupset L_P$]
If {\seq{\Gamma,P \supset B}{C}}
then {$P \in \Gamma$ and
\seq{\Gamma,B}{C}}.
\item [$\csupset L_\supset$]
If {\seq{\Gamma,(A_1 \supset A_2) \supset B}{C}}
then {\seq{\Gamma,(A_2 \supset B),A_1}{A_2} and
\seq{\Gamma,B}{C}}.
\end{itemize}
You should use weakening/cut/identity to try to prove these rules
invertible. When that fails, you should be able to construct a simple
counterexample. Hint: two rules are non-invertible, and the remainder
are invertible.
\subsection{Prolog Implementation}
We can use invertibility to make our theorem prover more efficient. The
idea is this: Whenever we add an assumption to the context, we
immediately apply all invertible left rules to it.
This solves two sources of inefficiency:
\begin{enumerate}
\item \textbf{Unnecessary backtracking:} The above Prolog code will try
applying the invertible left rules in many different orders, when in
fact one will suffice.
\item \textbf{Linear context lookups:} Because the above code uses the
\ttt{choose} relation to pick an assumption to work on, checking each
left rule to see whether it applies can take time linear in the length
of the context $\Gamma$. For example, to see if $\top L$ applies, you
have to look through all of the assumptions for an occurrence of
$\top$.
\end{enumerate}
\noindent
Here's how we will exploit invertibility:
\begin{itemize}
\item In \ttt{prove(G,A)}, restrict the context \ttt{G} to \emph{stable}
propositions, those whose left rules are \textbf{not} invertible.
\item Define an auxiliary relation \ttt{invert(G,D,A)}, where \ttt{D} is
a list of arbitrary propositions (some stable and some not).
\ttt{invert} should process each proposition in \ttt{D}:
\begin{itemize}
\item If its left-rule is invertible, apply it. For example, the case
of \ttt{invert} for $\wedge L$ looks like this:
\begin{verbatim}
invert(G,[and(A,B)|D],C) :-
invert(G,[A,B|D],C).
\end{verbatim}
\item If its left-rule is not invertible, move the proposition to
\ttt{G} and process the rest of \ttt{D}.
\end{itemize}
\item \ttt{prove} calls \ttt{invert} whenever it needs to add a
potentially-invertible proposition to the context. \ttt{invert} calls
prove when all propositions in \ttt{D} have been processed.
\item The non-invertible left rules are still applied
non-deterministically in \ttt{prove} to a proposition \ttt{choose}n
from \ttt{G}, as in the code above. (There are no clear rules about
when to use these non-invertible hypotheses.)
\end{itemize}
\task{2}{10} Revise your theorem prover to handle the left-invertible
rules in this manner.
\section{Handin Instructions}
\begin{itemize}
\item GNU Prolog is installed in
\begin{verbatim}
/afs/andrew/course/15/317/bin/gprolog
\end{verbatim}
To run it, you must have this \ttt{bin} directory in your path.
In \ttt{tcsh}, do this:
\begin{verbatim}
setenv PATH "/afs/andrew/course/15/317/bin:$PATH"
\end{verbatim}
In \ttt{bash}, do this:
\begin{verbatim}
export PATH="/afs/andrew/course/15/317/bin:$PATH"
\end{verbatim}
You may want to add this to your startup files so that you don't have to
reset your path every time you want to run Prolog.
Once you run Prolog, load your file using the \ttt{consult} command:
\begin{verbatim}
| ?- consult('yourfile.pl').
\end{verbatim}
\item To hand in your code, copy two files to your handin
directory:
Problem 2 (Dyckhoff):
\begin{verbatim}
/afs/andrew/course/15/317/submit//hw07-2.pl
\end{verbatim}
Problem 3 (Dyckhoff + inversion):
\begin{verbatim}
r/afs/andrew/course/15/317/submit//hw07-3.pl
\end{verbatim}
Submit the written problems in class or in \ttt{hw06.pdf}.
\end{itemize}
\end{document}