diff options
Diffstat (limited to 'doc/Program.tex')
-rw-r--r-- | doc/Program.tex | 850 |
1 files changed, 0 insertions, 850 deletions
diff --git a/doc/Program.tex b/doc/Program.tex deleted file mode 100644 index aa900ecb9..000000000 --- a/doc/Program.tex +++ /dev/null @@ -1,850 +0,0 @@ -\achapter{The Program Tactic} -\aauthor{Catherine Parent} -\label{Addoc-program} - -The facilities described in this document pertain to a special aspect of -the \Coq\ system: how to associate to a functional program, whose -specification is written in \gallina, a proof of its correctness. - -This methodology is based on the Curry-Howard isomorphism between -functional programs and constructive proofs. This isomorphism allows -the synthesis of a functional program from the constructive part of its -proof of correctness. That is, it is possible to analyze a \Coq\ proof, -to erase all its non-informative parts (roughly speaking, removing the -parts pertaining to sort \Prop, considered as comments, to keep only the -parts pertaining to sort \Set). - -This {\sl realizability interpretation} -was defined by Christine Paulin-Mohring in her PhD dissertation -\cite{Moh89b}, and -implemented as a {\sl program extraction} facility in previous versions of -\Coq~ by Benjamin Werner (see \cite{COQ93}). -However, the corresponding certified program -development methodology was very awkward: the user had to understand very -precisely the extraction mechanism in order to guide the proof construction -towards the desired algorithm. The facilities described in this chapter -attempt to do the reverse: i.e. to try and generate the proof of correctness -from the program itself, given as argument to a specialized tactic. -This work is based on the PhD dissertation of -Catherine Parent (see \cite{CPar95}) - -\asection{Developing certified programs: Motivations} -\label{program_proving} - -We want to develop certified programs automatically proved by the -system. That is to say, instead of giving a specification, an -interactive proof and then extracting a program, the user gives the -program he wants to prove and the corresponding specification. Using -this information, an automatic proof is developed which solves the -``informative'' goals without the help of the user. When the proof is -finished, the extracted program is guaranteed to be correct and -corresponds to the one given by the user. The tactic uses the fact -that the extracted program is a skeleton of its corresponding proof. - -\asection{Using {\tt Program}} -The user has to give two things: the specification (given as usual by -a goal) and the program (see section \ref{program-syntax}). Then, this program -is associated to the current goal (to know which specification it -corresponds to) and the user can use different tactics to develop an -automatic proof. - -\asubsection{\tt Realizer \term.} -\tacindex{Realizer} -\label{Realizer} -This command attaches a program {\term} to the current goal. This is a -necessary step before applying the first time the tactic {\tt -Program}. The syntax of programs is given in section \ref{program-syntax}. -If a program is already attached to the current subgoal, {\tt -Realizer} can be also used to change it. - -\asubsection{\tt Show Program.} -\comindex{Show Program}\label{Show Program} -The command \verb=Show Program= shows the program associated to the -current goal. The variant \verb=Show Program n= shows the program associated to -the nth subgoal. - -\asubsection{\tt Program.} -\tacindex{Program}\label{Program} -This tactics tries to build a proof of the current subgoal from the -program associated to the current goal. This tactic performs -\verb=Intros= then either one \verb=Apply= or one \verb=Elim= -depending on the syntax of the program. The \verb=Program= tactic -generates a list of subgoals which can be either logical or -informative. Subprograms are automatically attached to the informative -subgoals. - -When attached program are not automatically generated, an initial program -has to be given by {\tt Realizer}. - -\begin{ErrMsgs} -\item \errindex{No program associated to this subgoal}\\ -You need to attach a program to the current goal by using {\tt Realizer}. -Perhaps, you already attached a program but a {\tt Restart} or an -{\tt Undo} has removed it. -\item \errindex{Type of program and informative extraction of goal do not coincide} -\item \errindex{Cannot attach a realizer to a logical goal}\\ -The current goal is non informative (it lives in the world {\tt Prop} -of propositions or {\tt Type} of abstract sets) while it should lives -in the world {\tt Set} of computational objects. -\item \errindex{Perhaps a term of the Realizer is not an FW - term}\texttt{ and you then have to replace it by its extraction}\\ -Your program contains non informative subterms. -\end{ErrMsgs} - -\begin{Variants} -\item{\tt Program\_all.} - \tacindex{Program\_all}\label{Program_all}\\ - This tactic is equivalent to the composed tactic - \verb=Repeat (Program OrElse Auto)=. It repeats the \verb=Program= - tactic on every informative subgoal and tries the \verb=Auto= tactic - on the logical subgoals. Note that the work of the \verb=Program= - tactic is considered to be finished when all the informative subgoals - have been solved. This implies that logical lemmas can stay at the end - of the automatic proof which have to be solved by the user. -\item {\tt Program\_Expand} - \tacindex{Program\_Expand}\label{Program_Expand}\\ - The \verb=Program_Expand= tactic transforms the current program into - the same program with the head constant expanded. This tactic - particularly allows the user to force a program to be reduced before - each application of the \verb=Program= tactic. - - \begin{ErrMsgs} - \item \errindex{Not reducible}\\ - The head of the program is not a constant or is an opaque constant. - need to attach a program to the current goal by using {\tt Realizer}. - Perhaps, you already attached a program but a {\tt Restart} or an - {\tt Undo} has removed it. - \end{ErrMsgs} -\end{Variants} - -\asubsection{Hints for {\tt Program}} - -\begin{description} -\item[Mutual inductive types] The \verb=Program= tactic can deal with - mutual inductive types. But, this needs the use of - annotations. Indeed, when associating a mutual fixpoint program to a - specification, the specification is associated to the first (the - outermost) function defined by the fixpoint. But, the specifications - to be associated to the other functions cannot be automatically - derived. They have to be explicitly given by the user as - annotations. See section \ref{program-ex-mutual} for an example. - -\item[Constants] The \verb=Program= tactic is very sensitive to the - status of constants. Constants can be either opaque (their body - cannot be viewed) or transparent. The best of way of doing is to - leave constants opaque (this is the default). If it is needed after, - it is best to use the \verb=Transparent= command {\bf after} having - used the \verb=Program= tactic. -\end{description} - -\asection{Syntax for programs} -\label{program-syntax} -\asubsection{Pure programs} -The language to express programs is called \real\footnote{It - corresponds to \FW\ plus inductive definitions}. Programs are -explicitly typed\footnote{This information is not strictly needed but - was useful for type checking in a first experiment.} like terms -extracted from proofs. Some extra expressions have been added to have -a simpler syntax. - -This is the raw form of what we call pure programs. But, in fact, it -appeared that this simple type of programs is not sufficient. Indeed, -all the logical part useful for the proof is not contained in these -programs. That is why annotated programs are introduced. - -\asubsection{Annotated programs} -The notion of annotation introduces in a program a logical assertion -that will be used for the proof. The aim of the \verb=Program= tactic -is to start from a specification and a program and to generate -subgoals either logical or associated with programs. However, to find -the good specification for subprograms is not at all trivial in -general. For instance, if we have to find an invariant for a loop, or -a well founded order in a recursive call. - -So, annotations add in a program the logical part which is needed for -the proof and which cannot be automatically retrieved. This allows the -system to do proofs it could not do otherwise. - -For this, a particular syntax is needed which is the following: since -they are specifications, annotations follow the same internal syntax -as \Coq~terms. We indicate they are annotations by putting them -between \verb={= and \verb=}= and preceding them with \verb=:: ::=. -Since annotations are \Coq~terms, they can involve abstractions over -logical propositions that have to be declared. Annotated-$\lambda$ -have to be written between \verb=[{= and \verb=}]=. -Annotated-$\lambda$ can be seen like usual $\lambda$-bindings but -concerning just annotations and not \Coq~programs. - -\asubsection{Recursive Programs} -Programs can be recursively defined using the following syntax: \verb=<={\it - type-of-the-result}\verb=> rec= \index{rec@{\tt rec}} {\it - name-of-the-induction-hypothesis} \verb=:: :: {= {\it - well-founded-order-of-the-recursion} \verb=}= and then the body of -the program (see section \ref{program-examples}) which must always begin with -an abstraction [x:A] where A is the type of the arguments of the -function (also on which the ordering relation acts). - -\asubsection{Implicit arguments} - -A synthesis of implicit arguments has been added in order to -allow the user to write a minimum of types in a program. Then, it is -possible not to write a type inside a program term. This type has then -to be automatically synthesized. For this, it is necessary to indicate -where the implicit type to be synthesized appears. The syntax is the -current one of implicit arguments in \Coq: the question mark -\verb+?+. - -This synthesis of implicit arguments is not possible everywhere in a -program. In fact, the synthesis is only available inside a -\verb+Match+, a \verb+Cases+ or a \verb+Fix+ construction (where -\verb+Fix+ is a syntax for defining fixpoints). - -\asubsection{Grammar} -The grammar for programs is described in figure \ref{pgm-syntax}. - -\begin{figure} -\begin{tabular}{lcl} -{\pg} & ::= & {\ident}\\ - & $|$ & {\tt ?} \\ - & $|$ & {\tt [} {\ident} {\tt :} {\pg} {\tt ]} {\pg} \\ - & $|$ & {\tt [} {\ident} {\tt ]} {\pg} \\ - & $|$ & {\tt (} {\ident} {\tt :} {\pg} {\tt )} {\pg} \\ - & $|$ & {\tt (} {\pgs} {\tt )} \\ - & $|$ & {\tt Match} {\pg} {\tt with} {\pgs} {\tt end} \\ - & $|$ & \verb=<={\pg}\verb=>={\tt Match} {\pg} {\tt with} {\pgs} {\tt end} \\ - & $|$ & {\tt Cases} {\pg} {\tt of} \sequence{\eqn} {|} {\tt end} \\ - & $|$ & \verb=<={\pg}\verb=>={\tt Cases} {\pg} {\tt of} - \sequence{\eqn} {|} {\tt end} \\ - & $|$ & {\tt Fix} {\ident} \verb.{.\nelist{\fixpg}{with} \verb.}. \\ - & $|$ & {\tt Cofix} {\ident} \{{\ident} {\tt :} {\pg} {\tt :=} {\pg} - {\tt with} {\ldots} {\tt with} {\ident} {\tt :} {\pg} {\tt :=} {\pg}\} \\ - & $|$ & {\pg} {\tt ::} {\tt ::} \{ {\term} \} \\ - & $|$ & {\tt [\{} {\ident} {\tt :} {\term} {\tt \}]} {\pg} \\ - & $|$ & {\tt let} - {\tt (} {\ident} {\tt ,} {\ldots} {\tt ,} {\ident} {\tt ,} {\dots} - {\tt ,} {\ident} {\tt )} {\tt =} {\pg} {\tt in} {\pg} \\ -% & $|$ & \verb=<={\pg}\verb=>={\tt let} {\tt (} {\ident} {\tt ,} {\ldots} {\tt -% ,} {\ident} {\tt :} {\pg} {\tt ;} {\ldots} {\tt ;} {\ident} {\tt ,} -% {\ldots} {\tt ,} {\ident} {\tt :} {\pg} {\tt )} {\tt =} {\pg} {\tt -% in} {\pg} \\ - & $|$ & \verb=<={\pg}\verb=>={\tt let} {\tt (} {\ident} {\tt ,} - {\ldots} {\tt ,} {\ldots} {\tt ,} {\ident} {\tt )} {\tt =} {\pg} {\tt - in} {\pg} \\ - & $|$ & {\tt if} {\pg} {\tt then} {\pg} {\tt else} {\pg} \\ - & $|$ & \verb=<={\pg}\verb=>={\tt if} {\pg} {\tt then} {\pg} {\tt - else} {\pg} \\ - & $|$ & \verb=<={\pg}\verb=>={\tt rec} {\ident} {\tt ::} {\tt ::} \{ \term \} - {\tt [} {\ident} {\tt :} {\pg} {\tt ]} {\pg} \\ - {\pgs} & ::= & \pg \\ - & $|$ & {\pg} {\pgs}\\ -{\fixpg} & ::= & {\ident} {\tt [} \nelist{\typedidents}{;} {\tt ]} {\tt :} {\pg} {\tt :=} {\pg} \\ - & $|$ & {\ident} {\tt /} {\num} {\tt :} {\pg} {\tt :=} {\pg} {\tt ::} {\tt ::} \{ {\term} \} \\ -{\simplepattern} & ::= & {\ident} \\ - & $|$ & \verb!(! \nelist{\ident}{} \verb!)! \\ -{\eqn} & ::= & {\simplepattern} ~\verb!=>! ~\pg \\ -\end{tabular} -\caption{Syntax of annotated programs} -\label{pgm-syntax} -\end{figure} - -As for {\Coq} terms (see section \ref{term}), {\tt (}{\pgs}{\tt )} -associates to the left. The syntax of {\term} is the one in section. -The infix annotation operator \verb!:: ::! binds more than the -abstraction and product constructions. -\ref{term}. - -The reference to an identifier of the \Coq\ context (in particular a -constant) inside a program of the -language \real\ is a reference to its extracted contents. - -\asection{Examples} -\label{program-examples} -\asubsection{Ackermann Function} -Let us give the specification of Ackermann's function. We want to -prove that for every $n$ and $m$, there exists a $p$ such that -$ack(n,m)=p$ with: - -\begin{eqnarray*} -ack(0,n) & = & n+1 \\ -ack(n+1,0) & = & ack(n,1) \\ -ack(n+1,m+1) & = & ack(n,ack(n+1,m)) -\end{eqnarray*} - -An ML program following this specification can be: - -\begin{verbatim} -let rec ack = function - 0 -> (function m -> Sm) - | Sn -> (function 0 -> ack n 1 - | Sm -> ack n (ack Sn m)) -\end{verbatim} - -Suppose we give the following definition in \Coq~of a ternary relation -\verb=(Ack n m p)= in a Prolog like form representing $p=ack(n,m)$: - -\begin{coq_example*} -Inductive Ack : nat->nat->nat->Prop := - AckO : (n:nat)(Ack O n (S n)) - | AcknO : (n,p:nat)(Ack n (S O) p)->(Ack (S n) O p) - | AckSS : (n,m,p,q:nat)(Ack (S n) m q)->(Ack n q p) - ->(Ack (S n) (S m) p). -\end{coq_example*} -Then the goal is to prove that $\forall n,m .\exists p.(Ack~n~m~p)$, so -the specification is: - -\verb!(n,m:nat){p:nat|(Ack n m p)}!. -The associated {\real} program corresponding to the above ML program can be defined as a fixpoint: -\begin{coq_example*} -Fixpoint ack_func [n:nat] : nat -> nat := - Cases n of - O => [m:nat](S m) - | (S n') => Fix ack_func2 {ack_func2 [m:nat] : nat := - Cases m of - O => (ack_func n' (S O)) - | (S m') => (ack_func n' (ack_func2 m')) - end} - end. -\end{coq_example*} -The program is associated by using \verb=Realizer ack_func=. The -program is automatically expanded. Each realizer which is a constant -is automatically expanded. Then, by repeating the \verb=Program= -tactic, three logical lemmas are generated and are easily solved by -using the property Ack0, Ackn0 and AckSS. -\begin{coq_eval} -Goal (n,m:nat){p:nat|(Ack n m p)}. -Realizer ack_func. -\end{coq_eval} -\begin{coq_example} -Repeat Program. -\end{coq_example} - - -\asubsection{Euclidean Division} -This example shows the use of {\bf recursive programs}. Let us -give the specification of the euclidean division algorithm. We want to -prove that for $a$ and $b$ ($b>0$), there exist $q$ and $r$ such that -$a=b*q+r$ and $b>r$. - -An ML program following this specification can be: -\begin{verbatim} -let div b a = divrec a where rec divrec = function - if (b<=a) then let (q,r) = divrec (a-b) in (Sq,r) - else (0,a) -\end{verbatim} -Suppose we give the following definition in \Coq~which describes what -has to be proved, ie, $\exists q \exists r.~(a=b*q+r \wedge ~b>r)$: -\begin{coq_eval} -Abort. -Require Arith. -\end{coq_eval} -\begin{coq_example*} -Inductive diveucl [a,b:nat] : Set - := divex : (q,r:nat)(a=(plus (mult q b) r))->(gt b r) - ->(diveucl a b). -\end{coq_example*} -The decidability of the ordering relation has to be proved first, by -giving the associated function of type \verb!nat->nat->bool!: -\begin{coq_example*} -Theorem le_gt_dec : (n,m:nat){(le n m)}+{(gt n m)}. -Realizer Fix le_gt_bool {le_gt_bool [n:nat] : nat -> bool := - Cases n of - | O => [m:nat]true - | (S n') => [m:nat]Cases m of - | O => false - | (S m') => (le_gt_bool n' m') - end - end}. -Program_all. -Save. -\end{coq_example*} -Then the specification is \verb!(b:nat)(gt b O)->(a:nat)(diveucl a b)!. -The associated program corresponding to the ML program will be: -\begin{coq_eval} -Definition lt := [n,m:nat](gt m n). -Theorem eucl_dev : (b:nat)(gt b O)->(a:nat)(diveucl a b). -\end{coq_eval} -\begin{coq_example*} -Realizer - [b:nat](<nat*nat>rec div :: :: { lt } - [a:nat]if (le_gt_dec b a) - then let (q,r) = (div (minus a b)) - in ((S q),r) - else (O,a)). -\end{coq_example*} -Where \verb=lt= is the well-founded ordering relation defined by: -\begin{coq_example} -Print lt. -\end{coq_example} -Note the syntax for recursive programs as explained before. The -\verb=rec= construction needs 4 arguments: the type result of the -function (\verb=nat*nat= because it returns two natural numbers) -between \verb=<= and \verb=>=, the name of the induction hypothesis -(which can be used for recursive calls), the ordering relation -\verb=lt= (as an annotation because it is a specification), and the -program itself which must begin with a $\lambda$-abstraction. The -specification of \verb=le_gt_dec= is known because it is a previous -lemma. -The term \verb!(le_gt_dec b a)! is seen by the \verb!Program! tactic -as a term of type \verb!bool! which satisfies the specification -\verb!{(le a b)}+{(gt a b)}!. -The tactics \verb=Program_all= or \verb=Program= can be used, and the -following logical lemmas are obtained: -\begin{coq_example} -Repeat Program. -\end{coq_example} -The subgoals 4, 5 and 6 are resolved by \verb=Auto= (if you use -\verb=Program_all= they don't appear, because \verb=Program_all= tries -to apply \verb=Auto=). The other ones have to be solved by the user. - - -\asubsection{Insertion sort} -This example shows the use of {\bf annotations}. Let us give the -specification of a sorting algorithm. We want to prove that for a -sorted list of natural numbers $l$ and a natural number $a$, we can -build another sorted list $l'$, containing all the elements of $l$ -plus $a$. - -An ML program implementing the insertion sort and following this -specification can be: -\begin{verbatim} -let sort a l = sortrec l where rec sortrec = function - [] -> [a] - | b::l' -> if a<b then a::b::l' else b::(sortrec l') -\end{verbatim} -Suppose we give the following definitions in \Coq: - -First, the decidability of the ordering relation: -\begin{coq_eval} -Reset Initial. -Require Le. -Require Gt. -\end{coq_eval} -\begin{coq_example*} -Fixpoint inf_dec [n:nat] : nat -> bool := -[m:nat]Cases n of - O => true - | (S n') => Cases m of - O => false - | (S m') => (inf_dec n' m') - end - end. -\end{coq_example*} - -The definition of the type \verb=list=: -\begin{coq_example*} -Inductive list : Set := nil : list | cons : nat -> list -> list. -\end{coq_example*} - -We define the property for an element \verb=x= to be {\bf in} a list -\verb=l= as the smallest relation such that: $\forall a \forall -l~(In~x~l) \Ra (In~x~(a::l))$ and $\forall l~(In~x~(x::l))$. -\begin{coq_example*} -Inductive In [x:nat] : list->Prop - := Inl : (a:nat)(l:list)(In x l) -> (In x (cons a l)) - | Ineq : (l:list)(In x (cons x l)). -\end{coq_example*} - -A list \verb=t'= is equivalent to a list \verb=t= with one added -element \verb=y= iff: $(\forall x~(In~x~t) \Ra (In~x~t'))$ and -$(In~y~t')$ and $\forall x~(In~x~t') \Ra ((In~x~t) \vee y=x)$. The -following definition implements this ternary conjunction. -\begin{coq_example*} -Inductive equiv [y:nat;t,t':list]: Prop := - equiv_cons : - ((x:nat)(In x t)->(In x t')) - -> (In y t') - ->((x:nat)(In x t')->((In x t)\/y=x)) - -> (equiv y t t'). -\end{coq_example*} - -Definition of the property of list to be sorted, still defined -inductively: -\begin{coq_example*} -Inductive sorted : list->Prop - := sorted_nil : (sorted nil) - | sorted_trans : (a:nat)(sorted (cons a nil)) - | sorted_cons : (a,b:nat)(l:list)(sorted (cons b l)) -> (le a b) - -> (sorted (cons a (cons b l))). -\end{coq_example*} -Then the specification is:\\ -\verb!(a:nat)(l:list)(sorted l)->{l':list|(equiv a l l')&(sorted l')}!. - -The associated \real\ program corresponding to the ML program will be: -\begin{coq_eval} -Lemma toto : (a:nat)(l:list)(sorted l)->{l':list|(equiv a l l')&(sorted l')}. -\end{coq_eval} -\begin{coq_example*} -Realizer - Fix list_insert{list_insert [a:nat; l:list] : list := - Cases l of - | nil => (cons a nil) - | (cons b m) => - if (inf_dec b a) :: :: { {(le b a)}+{(gt b a)} } - then (cons b (list_insert a m)) - else (cons a (cons b m)) - end}. -\end{coq_example*} -% Realizer [a:nat][l:list] -% Match l with -% (cons a nil) -% [b,m,H]if (inf_dec b a) :: :: { {(le b a)}+{(gt b a)} } -% then (cons b H) -% else (cons a (cons b m)) -% end. -Note that we have defined \verb=inf_dec= as the program realizing the -decidability of the ordering relation on natural numbers. But, it has -no specification, so an annotation is needed to give this -specification. This specification is used and then the decidability of -the ordering relation on natural numbers has to be proved using the -index program. - -Suppose \verb=Program_all= is used, a few logical -lemmas are obtained (which have to be solved by the user): -\begin{coq_example} -Program_all. -\end{coq_example} - - -\asubsection{Quicksort} -This example shows the use of {\bf programs using previous -programs}. Let us give the specification of Quicksort. We want to -prove that for a list of natural numbers $l$, we can build a sorted -list $l'$, which is a permutation of the previous one. - -An ML program following this specification can be: -\begin{verbatim} -let rec quicksort l = function - [] -> [] - | a::m -> let (l1,l2) = splitting a m in - let m1 = quicksort l1 and - let m2 = quicksort l2 in m1@[a]@m2 -\end{verbatim} -Where \verb=splitting= is defined by: -\begin{verbatim} -let rec splitting a l = function - [] -> ([],[]) - | b::m -> let (l1,l2) = splitting a m in - if a<b then (l1,b::l2) - else (b::l1,l2) -\end{verbatim} -Suppose we give the following definitions in \Coq: - -Declaration of the ordering relation: -\begin{coq_eval} -Reset Initial. -Require List. -Require Gt. -\end{coq_eval} -\begin{coq_example*} -Variable inf : A -> A -> Prop. -Definition sup := [x,y:A]~(inf x y). -Hypothesis inf_sup : (x,y:A){(inf x y)}+{(sup x y)}. -\end{coq_example*} -Definition of the concatenation of two lists: -\begin{coq_eval} -Write State toto. -\end{coq_eval} -\begin{coq_example*} -Fixpoint app [l:list] : list -> list - := [m:list]Cases l of - nil => m - | (cons a l1) => (cons a (app l1 m)) end. -\end{coq_example*} -\begin{coq_eval} -Restore State toto. -\end{coq_eval} -Definition of the permutation of two lists: -\begin{coq_eval} -Definition mil := [a:A][l,m:list](app l (cons a m)) : A->list->list->list. -Lemma mil_app : (a:A)(l,m,n:list)(mil a l (app m n))=(app (mil a l m) n). - Intros. - Unfold mil. - Elim (ass_app l (cons a m) n). - Auto. -Save. -\end{coq_eval} -\begin{coq_example*} -Inductive permut : list->list->Prop := - permut_nil : (permut nil nil) - |permut_tran : (l,m,n:list)(permut l m)->(permut m n)->(permut l n) - |permut_cmil : (a:A)(l,m,n:list) - (permut l (app m n))->(permut (cons a l) (mil a m n)) - |permut_milc : (a:A)(l,m,n:list) - (permut (app m n) l)->(permut (mil a m n) (cons a l)). -\end{coq_example*} -\begin{coq_eval} -Hints Resolve permut_nil permut_cmil permut_milc. -Lemma permut_cons : (a:A)(l,m:list)(permut l m)->(permut (cons a l) (cons a m)). - Intros. - Change (permut (cons a l) (mil a nil m)). - Auto. -Save. -Hints Resolve permut_cons. -Lemma permut_refl : (l:list)(permut l l). - Induction l ; Auto. -Save. -Hints Resolve permut_refl. -Lemma permut_sym : (l,m:list)(permut l m)->(permut m l). - Intros l m h1 ; Elim h1 ; Auto. - Intros l0 m0 n h2 h3 h4 h5. - Apply permut_tran with m0 ; Auto. -Save. -Hints Immediate permut_sym. -Lemma permut_app1 : (m1,n1,l:list)(permut m1 n1)->(permut (app l m1) (app l n1)). - Intros ; Elim l ; Simpl ; Auto. -Save. -Hints Resolve permut_app1. -Lemma permut_app_mil : (a:A)(l1,m1,l2,m2,n2:list) - (permut (app l1 m1) (app (app l2 m2) n2)) - -> (permut (app (cons a l1) m1) (app (mil a l2 m2) n2)). - Intros ; Simpl. - Elim (mil_app a l2 m2 n2). - Apply permut_cmil. - Elim (app_ass l2 m2 n2) ; Auto. -Save. -Hints Resolve permut_app_mil. -Lemma permut_app_app : (m1,m2,n1,n2 :list) - (permut m1 n1)->(permut m2 n2)->(permut (app m1 m2) (app n1 n2)). - Intros m1 m2 n1 n2 h1 h2. - Elim h1 ; Intros. - exact h2. - Apply permut_tran with (app m n2) ; Auto. - Apply permut_tran with (app m m2) ; Auto. - Auto. - Apply permut_sym ; Auto. -Save. -Hints Resolve permut_app_app. -Lemma permut_app : (m,m1,m2,n1,n2 :list)(permut m1 n1)->(permut m2 n2)-> - (permut m (app m1 m2))->(permut m (app n1 n2)). - Intros. - Apply permut_tran with (app m1 m2) ; Auto. -Save. -\end{coq_eval} -The definitions \verb=inf_list= and \verb=sup_list= allow to know if -an element is lower or greater than all the elements of a list: -\begin{coq_example*} -Section Rlist_. -Variable R : A->Prop. -Inductive Rlist : list -> Prop := - Rnil : (Rlist nil) - | Rcons : (x:A)(l:list)(R x)->(Rlist l)->(Rlist (cons x l)). -\end{coq_example*} -\begin{coq_eval} -Hints Resolve Rnil Rcons. -Lemma Rlist_app : (m,n:list)(Rlist m)->(Rlist n)->(Rlist (app m n)). - Intros m n h1 h2 ; Elim h1 ; Simpl ; Auto. -Save. -Hints Resolve Rlist_app. -Section Rlist_cons_. -Variable a : A. -Variable l : list. -Hypothesis Rc : (Rlist (cons a l)). -Lemma Rlist_cons : (R a)/\(Rlist l). - Inversion_clear Rc; Auto. -Save. -End Rlist_cons_. -Section Rlist_append. -Variable n,m : list. -Lemma Rlist_appd : (Rlist (app n m))->((Rlist n)/\(Rlist m)). -Elim n ; Simpl; Auto. -Intros a y h1 h2. -Elim (Rlist_cons a (app y m)) ; Auto. -Intros h3 h4; Elim h1 ; Auto. -Save. -End Rlist_append. -Hints Resolve Rlist_appd. -Lemma Rpermut : (m,n:list)(permut m n)->(Rlist m)->(Rlist n). - Intros m n h1 ; Elim h1 ; Unfold mil ; Auto. - Intros a l m0 n0 h2 h3 h4. - Elim (Rlist_cons a l); Auto. - Intros h5 h6; Elim (Rlist_appd m0 n0); Auto. - Intros a l m0 n0 h2 h3 h4. - Elim (Rlist_appd m0 (cons a n0)) ; Auto. - Intros h5 h6; Elim (Rlist_cons a n0) ; Auto. -Save. -\end{coq_eval} -\begin{coq_example*} -End Rlist_. -Hints Resolve Rnil Rcons. -\end{coq_example*} -\begin{coq_eval} -Hints Resolve Rlist_app. -\end{coq_eval} -\begin{coq_example*} -Section Inf_Sup. -Hypothesis x : A. -Hypothesis l : list. -Definition inf_list := (Rlist (inf x) l). -Definition sup_list := (Rlist (sup x) l). -End Inf_Sup. -\end{coq_example*} -\begin{coq_eval} -Hints Unfold inf_list sup_list. -\end{coq_eval} -Definition of the property of a list to be sorted: -\begin{coq_example*} -Inductive sort : list->Prop := - sort_nil : (sort nil) - | sort_mil : (a:A)(l,m:list)(sup_list a l)->(inf_list a m) - ->(sort l)->(sort m)->(sort (mil a l m)). -\end{coq_example*} -\begin{coq_eval} -Hints Resolve sort_nil sort_mil. -Lemma permutapp : (a0:A)(y,l1,l2:list)(permut y (app l1 l2))->(permut (cons a0 y) (app l1 (cons a0 l2))). -Intros. -exact (permut_cmil a0 y l1 l2 H). -Save. -Hints Resolve permutapp. -Lemma sortmil : (a:A)(x,x0,l1,l2:list)(sup_list a l1)->(inf_list a l2)->(sort x)->(sort x0)->(permut l1 x)->(permut l2 x0)->(sort (mil a x x0)). -Intros. -Apply sort_mil ; Auto. -Unfold sup_list ; Apply Rpermut with l1 ; Auto. -Unfold inf_list ; Apply Rpermut with l2 ; Auto. -Save. -\end{coq_eval} - -\noindent Then the goal to prove is -$\forall l~\exists m~(sort~m) \wedge (permut~l~m)$ and the specification is - -\verb!(l:list){m:list|(sort m)&(permut l m)!. - -\noindent Let us first prove a preliminary lemma. Let us define \verb=ltl= a -well-founded ordering relation. - -\begin{coq_example*} -Definition ltl := [l,m:list](gt (length m) (length l)). -\end{coq_example*} -\begin{coq_eval} -Hints Unfold ltl. -Lemma ltl_cons : (a,a0:A)(l1,y:list)(ltl l1 (cons a y))->(ltl l1 (cons a (cons a0 y))). -Unfold ltl; Simpl; Auto. -Save. -Hints Resolve ltl_cons. -Lemma ltl_cons_cons : (a,a0:A)(l2,y:list)(ltl l2 (cons a y))->(ltl (cons a0 l2) (cons a (cons a0 y))). -Unfold ltl; Simpl; Auto with arith.. -Save. -Hints Resolve ltl_cons_cons. -Require Wf_nat. -\end{coq_eval} -Let us then give a definition of \verb=Splitting_spec= corresponding -to\\ -$\exists l_1 \exists l_2.~(sup\_list~a~l_1) \wedge (inf\_list~a~l_2) -\wedge (l \equiv l_1@l_2) \wedge (ltl~l_1~(a::l)) \wedge -(ltl~l2~(a::l))$ and a theorem on this definition. -\begin{coq_example*} -Inductive Splitting_spec [a:A; l:list] : Set := - Split_intro : (l1,l2:list)(sup_list a l1)->(inf_list a l2) - ->(permut l (app l1 l2)) - ->(ltl l1 (cons a l))->(ltl l2 (cons a l)) - ->(Splitting_spec a l). -\end{coq_example*} -\begin{coq_example*} -Theorem Splitting : (a:A)(l:list)(Splitting_spec a l). -Realizer - Fix split {split [a:A;l:list] : list*list := - Cases l of - | nil => (nil,nil) - | (cons b m) => let (l1,l2) = (split a m) in - if (inf_sup a b) - then (* inf a b *) (l1,(cons b l2)) - else (* sup a b *) ((cons b l1),l2) - end}. -Program_all. -Simpl; Auto. -Save. -\end{coq_example*} -% Realizer [a:A][l:list] -% Match l with -% (* nil *) (nil,nil) -% (* cons *) [b,m,ll]let (l1,l2) = ll in -% if (inf_sup a b) -% then (* inf a b *) (l1,(cons b l2)) -% else (* sup a b *) ((cons b l1),l2) -% end. - -The associated {\real} program to the specification we wanted to first -prove and corresponding to the ML program will be: -\begin{coq_example*} -Lemma Quicksort: (l:list){m:list|(sort m)&(permut l m)}. -Realizer <list>rec quick :: :: { ltl } - [l:list]Cases l of - nil => nil - | (cons a m) => let (l1,l2) = (Splitting a m) in - (mil a (quick l1) (quick l2)) - end. -\end{coq_example*} -Then \verb=Program_all= gives the following logical lemmas (they have -to be resolved by the user): -\begin{coq_example} -Program_all. -\end{coq_example} -\begin{coq_eval} -Abort. -\end{coq_eval} - -\asubsection{Mutual Inductive Types} -\label{program-ex-mutual} -This example shows the use of {\bf mutual inductive types} with -\verb=Program=. Let us give the specification of trees and forest, and -two predicate to say if a natural number is the size of a tree or a -forest. - -\begin{coq_example*} -Section TreeForest. - -Variable A : Set. - -Mutual Inductive - tree : Set := node : A -> forest -> tree -with forest : Set := empty : forest - | cons : tree -> forest -> forest. - -Mutual Inductive Tree_Size : tree -> nat -> Prop := - Node_Size : (n:nat)(a:A)(f:forest)(Forest_Size f n) - ->(Tree_Size (node a f) (S n)) -with Forest_Size : forest -> nat -> Prop := - Empty_Size : (Forest_Size empty O) -| Cons_Size : (n,m:nat)(t:tree)(f:forest) - (Tree_Size t n) - ->(Forest_Size f m) - ->(Forest_Size (cons t f) (plus n m)). - -Hints Resolve Node_Size Empty_Size Cons_Size. -\end{coq_example*} - -Then, let us associate the two mutually dependent functions to compute -the size of a forest and a tree to the the following specification: - -\begin{coq_example*} -Theorem tree_size_prog : (t:tree){n:nat | (Tree_Size t n)}. - -Realizer [t:tree] -(Fix tree_size{ - tree_size [t:tree] : nat := let (a,f) = t in (S (forest_size f)) - with forest_size /1 : forest -> nat - := ([f:forest]Cases f of - empty => O - | (cons t f') => (plus (tree_size t) (forest_size f')) - end) - :: :: {(f:forest) {n:nat | (Forest_Size f n)}}} - t). -\end{coq_example*} - -It is necessary to add an annotation for the \verb=forest_size= -function. Indeed, the global specification corresponds to the -specification of the \verb=tree_size= function and the specification -of \verb=forest_size= cannot be automatically inferred from the -initial one. - -Then, the \verb=Program_all= tactic can be applied: -\begin{coq_example} -Program_all. -Save. -\end{coq_example} - -% $Id$ - -%%% Local Variables: -%%% mode: latex -%%% TeX-master: "Reference-Manual" -%%% End: |