(credits: Assia Mahboubi and Yves Bertot)
Now : We will see how to write
specifications of programs written in Coq
and how to prove them.
4
Coq
programs can be seen as models of realistic programs and its formal proof as a
dynamic documentation.
4 Coq programs can be translated
(extracted) to realistic programming languages.
4 Coq programs can be executed
efficiently, and this is a proof automation technique.
And there exist tools too to prove even imperative programs but it is
much more intricate a problem.
Proofs
about computation
4 Reason about
functional correctness
4 State properties
about computation results
4 Show
consistency between several computations
4 Use the same
tactics as for usual logical connectives
4 Add tactics to
control computations and observation of data
4 Follow the
structure of functions
4 Proving is akin
to symbolic debugging
4 A proof is a
guarantee that all cases have been covered
4 It is much
stronger than a test!
First
examples
Controlling
execution
4 Replace formulas
containing functions with other formulas
4 Manually with
direct Coq control:
4change f1 with f2
4 Really checks
that f1 and f2 are the same modulo computation
4 Manually with
indirect control
4replace f1 with f2
4 Produces a side
goal with the equality f1 = f2
4 Simply expand
definitions
4unfold f, unfold f at 2
Functions
and specifications
4 Each function
should come with theorems about it.
4 In this course,
sometimes called companion theorems.
4 They should be usable directly
through apply when the conclusion of the goal fits.
4 Otherwise, they can be brought in
the context using assert
Reasoning
about pattern-matching constructs
4 Pattern-matching
typically describes alternative behaviors.
4 Reasoning on
these functions goes by covering all cases.
4 Companion
theorems describe the non trivial identities.
Examples
with natural numbers
Tools
4 case is the basic constructs
4 generates one
goal per constructor
4 the expression is replaced by
constructor-values, in the conclusion
4 the argument to S becomes a universally quantified variable
4 destruct is more advanced and covers the
context
4 like case, but nesting is
authorized
4 the context is
also modified
4 case_eq remembers in which case we are
4 the context is
not modified (as in case)
4 remembering can
be crucial
How
to find Companion theorems
4 Search is your friend.
4 In general Search commands are your friends.
4
Search: use a
predicate name
Search le.
4 SearchRewrite: use
patterns of expressions searchRewrite (_ + 0).
4
SearchPattern: use a pattern of the conclusion of the theorem
(type Prop,
usually)
SearchPattern (_ * _ <= _ * _).
Recursive
functions and induction
4 When a function is recursive, calls
are usually made on direct subterms.
4 Companion theorems do not already
exist, but have to be stated and proved by the user.
4 Induction
hypotheses make up for the missing theorems.
4 The structure
of the proof is imposed by the data-type.
Examples
on recursive functions
Proofs
on functions on lists
4 Tactics case, destruct, case_eq also work
4 Induction on
lists works like induction on natural numbers
4 nil
plays the same role as 0: base case of proofs by induction
4 a::tl plays the same role as S
4 Induction
hypothesis on tl
4 Fits with
recursive calls on tl
A
trick to control recursion
4 Add one-step
unfolding theorems to recursive functions
4 Associate any
definition
Fixpoint f x1 ...xn := body
with a (trivial)
theorem f_step
forall x1 ...xn, f x1 ...xn =body
4 Use rewrite f_step instead of change, replace, or simpl
4 This provides a
better control than simpl.
4 More concise
than replace or change.
4 Note that unfold is not well-suited for recursive functions.