\documentclass{article}

\usepackage[T1]{fontenc}
\usepackage{xcolor}
\usepackage[french]{babel}
\usepackage{syntax}
\usepackage{listings}
\usepackage{amsmath}
\lstset{
 language=caml,
 columns=[c]fixed,
 basicstyle=\small\ttfamily,
 keywordstyle=\bfseries,
 upquote=true,
 commentstyle=,
 breaklines=true,
 showstringspaces=false}
%% installer texlive-lang-french pour cela

% ci-dessous: commenté car non offert sur les machines libre-service.
% décommentez si vous le souhaitez.
%\usepackage[french]{babel}

% pour compiler: 

% faire    pdflatex ex-rapport
% (si les references aux numeros de parties apparaissent comme des
% "?", recompiler une fois)

% la compilation de la bibliographie est davantage une "incantation":
% faire     bibtex ex-biblio
% puis      pdflatex ex-rapport (un nombre premier de fois)


% vous pouvez ensuite ouvrir le fichier ex-rapport.pdf




% elements du titre
\title{Pieuvre: le mini assitant de preuve}
\author{Marwan et Augustin}
\date{}

% definition de quelques macros, pour les maths
\newcommand{\litt}{\alpha}
\newcommand{\non}[1]{\overline{#1}}
\newcommand{\TODO}[1]{\textbf{\color{red}#1}}
\begin{document}

\maketitle

\section{Présentation}

Nous avons programmé \textbf{Pieuvre}, un assistant de preuve
pour la logique intuitionniste en \textbf{OCaml}.
Il permet, à l'aide d'une boucle interactive, de prouver des
prédicats simples.

Nous indiquons dans la partie~\ref{s:opt} comment compiler,
lancer et utiliser notre programme.
Nous exposons ensuite à la partie~\ref{s:orga} comment notre
programme est structuré.
Nous présentons enfin dans la partie~\ref{s:stlc} notre
implémentation du $\lambda$-calcul simplement typé puis dans
les parties~\ref{s:proof} et~\ref{s:tactic} notre
implémentation des preuves et des tactiques.

\section{Compiler et exécuter}
\label{s:opt}
Pour compiler : \lstinline{make pieuvre}

Pour exécuter \textbf{Pieuvre} et entrer dans la boucle
interactive de l'assistant de preuve, il suffit d'entrer la
commande \lstinline{./pieuvre}.
Sinon, on peut spécifier un des modes suivants:
\begin{itemize}
	\item \texttt{-alpha}

		qui vérifie l'$\alpha$-équivalence
		de deux $\lambda$-termes séparés par \lstinline{&}.

	\item \texttt{-reduce}

		qui affiche les $\beta$-réduction
		successives du $\lambda$-terme.
\end{itemize}
\section{Organisation du code}
\label{s:orga}

Le code est structuré de la manière suivante~:
\begin{itemize}
\item \lstinline{parser.mly} et \lstinline{lexel.mll}
	qui définissent l'analyse
	syntaxique du $\lambda$-calcul simplément typé
	ainsi que des tactiques.

\item \lstinline{lam.ml} qui contient notre implémentation
	du $\lambda$-calcul simplement typé.

\item \lstinline{types.ml} qui contient la définition
	des \lstinline{types} et \lstinline{typing.ml}
	qui implémente l'algorithme de vérification de type.
\item \lstinline{hlam.ml} qui décrit les~$\lambda$-termes creux,
	utilisés dans les preuves.
\item \lstinline{proof.ml} qui définit la structure d'une preuve
	et implémente les tactiques.

\item \lstinline{main.ml} le point d'entrée de notre programme
	qui fait l'interface avec l'utilisateur.
\end{itemize}

\section{$\lambda$-calcul simplement typé}
\label{s:stlc}
Avant de pouvoir réaliser des preuves, il faut pouvoir les encoder.
On utilise le $\lambda$-calcul simplement typé.
Dans notre programme, on utilise la syntaxe suivante
pour les types et pour les termes:


\begin{grammar}
	<A, B> ::= \lstinline{X}
	\alt \lstinline{A -> B}
	\alt \lstinline{A /\ B}
	\alt \lstinline{A \/ B}
	\alt \lstinline{false}
\end{grammar}

\begin{grammar}
	<M, N> ::= x
	  \alt \lstinline{fun (x : A)  => M}
	  \alt \lstinline{M N}
	  \alt \lstinline{exf (M : A)}
	  \alt \lstinline{l(M : A \/ B)}
	  \alt \lstinline{r(M : A \/ B)}
	  \alt \lstinline{(M, N)}
\end{grammar}
Les termes ainsi définis se réduisent à l'aide des règles de
$\beta$-réduction rappelées dans les notes de
Selinger~\cite{SelingerNotes}.
Avant d'être $\beta$-réduit par \lstinline{betastep},
les termes sont d'abord
$\alpha$-convertis avec \lstinline{alpha_convert} afin d'éviter
les problèmes de substitution.

On remarque que l'on impose d'annoter le type de l'argument
d'une $\lambda$-abstraction, des constructeurs de termes somme
et produit.
On peut alors vérifier le type de tous les termes de manière
déterministe avec les règles rappelées dans
le livre de S. Mimram~\cite{SMIM} et \textit{très} brièvement dans le livre de
Landin~\cite{PJL700}.

L'implémentation du~\textit{OU} et du~\textit{ET} est incomplète.
Nous n'avons pas eu le temps d'implémenter les déconstructeurs associés
(les projecteurs et le \verb|match|).

\section{Preuves}
\label{s:proof}

Pour construire la preuve d'une proposition,
on se base sur la correspondance de
Curry-Howard :
ainsi, construire une preuve correspond à créer
un~$\lambda$-terme dont le type correspond à la proposition.

Les~$\lambda$-termes de preuves sont des~$\lambda$-termes
particuliers au sens où ils sont \textbf{creux}.
Intuitivement, les~$\lambda$-termes creux, ou~\lstinline{hlam},
sont des termes avec des trous.
Compléter la preuve correspond
à remplir ces trous à l'aide de tactique.


Lorsqu'on déclare un but, on lui assigne donc :
\begin{itemize}
    \item un lambda terme creux (\verb|Ref (ref Hole)|) que 
	l'on construit petit à petit à l'aide des tactiques.
    \item le type associé à ce que l'on souhaite prouver
    \item son contexte, c'est à dire un liste d'hypothèses
		(nom de l'hypothèse, type, $\lambda$-terme possiblement encore creux qui sera mis à jour facilement grâce aux \verb|ref|s)
\end{itemize}
Au moment du \verb|Qed|, ce $\lambda$-terme de preuve qui a
été gardé de côté est $\beta$-réduit puis typé contre le type
du but définit au moment de \verb|Goal|.


\section{Tactiques}
\label{s:tactic}

Dans le mode générique, le programme démarre un assistant de preuve interactif semblable à Coq.
Voici les commandes et tactiques implémentées:

\begin{itemize}
    \item \verb|Goal| pour émettre un nouveau but
    \item \verb|Undo| pour annuler la dernière tactique.
	Son implémentation est très brutale, on se contente de maintenir une pile des états
	du terme de preuve. Appliquer cette tactique revient à dépiler l'état courant et à
	revenir au précédent. L'implémentation pourrait être plus judicieuse.
    \item \verb|Qed| pour clore la preuve d'un but
	\item \verb|Check| construit le fichier \lstinline{checker.v} qui contient
	le but courant ainsi qu'un \lstinline{exact} du terme de preuve.
	Ce fichier est envoyé au top-level de Coq afin d'être vérifié.
    \item \verb|exact| si une hypothèse correspond parfaitement à notre but courant
    \item \verb|assumption| recherche automatique d'une hypothèse correspondant au but courant
    \item \verb|intro| pour défaire une implication
    \item \verb|intros| pour répéter \verb|intro| autant que possible
    \item \verb|cut| permet de faire une élimination
		de la coupure.
    \item \verb|apply H| où \verb|H| est une implication
		avec le but courant en conclusion permet de prouver
		directement les prémisses de l'implication.
    \item \verb|split| permet de prouver un côté puis l'autre
		d'une conjonction
    \item \verb|left| et \verb|right| permettent de choisir
		quel côté de la conjonction prouver
	\item \verb|try| pour essayer une tactique. Si elle échoue,
		rien ne se passe.
\end{itemize}


Là encore, il manque la tactique~\lstinline|destruct|.

On peut prouver~\lstinline{A -> A /\ A} mais pas l'implication inverse.

\section{Conlusion}
Nous avons présenté notre assistant de preuve \textbf{Pieuvre}.
Il permet de prouver des prédicats logiques simples.
Plusieurs extensions (et améliorations) sont envisageables.

Tout d'abord, on pourrait évidemment enrichir la grammaire
et les tactiques pour avoir un langage plus expressif.
On pourrait également laisser la possibilité à l'utilisateur
de prouver des \verb|lemmes| et des \verb|théorèmes| pour les
sauvegarder et les réutiliser plus tard.
Il faudrait alors également proposer les types dépendants.

Enfin, il faut se poser la question de la fiabilité de notre
assistant de preuve. Il serait difficile de prouver formellement
toutes les composantes du programme (la~$\beta$-réduction,
l'~$\alpha$-conversion, le \verb|typecheck|, etc.).
Ainsi, on propose de sauvegarder les termes de preuves
puis de les envoyer à Coq pour valider la preuve.
Cette approche est assez satisfaisante dans la mesure où
la construction du terme de preuve repose uniquement sur les tactiques
et pas sur notre implémentation du~$\lambda$-calcul.
Ainsi, on peut supposer qu'on n'a jamais de faux-positif:
si Check valide notre preuve, c'est quelle est valide.


\section{Répartition du travail}
\begin{itemize}
	\item parser et lexer pour le~$\lambda$-calcul et les tactiques (Marwan)
	\item exfalso et typage bidirectionnel (Marwan)
	\item $\beta$-réduction (Marwan)
	\item système de preuve (définition des \verb|hlam|,
		des contextes, des buts, etc.) (Marwan)
	\item les tactiques exact, assumption, intro, intros,
		cut, apply et try (Marwan)
	\item $\alpha$-équivalence / renommage (Augustin)
	\item fonctionnement du \verb|main| (options, arguments, etc.)
		(Augustin)
	\item boucle interactive et interface utilisateur
		(Augustin)
	\item les tactiques Goal, Qed, left, right et split (Augustin)
	\item Undo (Augustin)
\end{itemize}


\bibliographystyle{plain}
\bibliography{ex-biblio}

\end{document}
