]> matita.cs.unibo.it Git - helm.git/blob - weblib/lroversi/2009-Andrea-tutorial.ma
commit by user lroversi
[helm.git] / weblib / lroversi / 2009-Andrea-tutorial.ma
1 (**************************************************************************)
2 (*       ___                                                              *)
3 (*      ||M||                                                             *)
4 (*      ||A||       A project by Andrea Asperti                           *)
5 (*      ||T||                                                             *)
6 (*      ||I||       Developers:                                           *)
7 (*      ||T||         The HELM team.                                      *)
8 (*      ||A||         http://helm.cs.unibo.it                             *)
9 (*      \   /                                                             *)
10 (*       \ /        This file is distributed under the terms of the       *)
11 (*        v         GNU General Public License Version 2                  *)
12 (*                                                                        *)
13 (**************************************************************************)
14 (**** 
15 After some experience in the use of Matita I could realize how
16 useful Andrea's tutorial:
17 http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.149.7928
18 can be, since it is compact, and allows to focus on the esssential
19 aspects for a fruitful approach to Matita.
20 So, I decided to start converting it for the current (23rd 
21 of February 2013) version of Matita. The reason I like to have it
22 available via web browser is that, quite often, I access
23 Matita by my tablet.
24
25 For the moment I am very interested to the more 'advanced' parts,
26 i.e. those ones that start after double induction.
27 Initially, I will introduce the least amount of code which is
28 essential to have the advanced part working. Gradually, I plan to
29 include the whole text as comments to the code.
30
31 DISCLAIMER: 
32 Until not explicitly otherwise written, every part of the content
33 is due to Andrea.*)
34
35 include "basics/relations.ma".
36
37 (*****************************************************************)
38 (**************** Chapter 1. Getting started *********************)
39 (*****************************************************************)
40 (* Natural numbers are the smallest set generated by a constant O 
41 and a successor function S. Sets of this kind, freely generated by
42 a finite number of constructors, are known as inductive types.
43 The definition of natural numbers in Matita reads as follows: *)
44
45 inductive nat : Type[0] ≝
46   | O : nat
47   | S : nat → nat.
48 interpretation "Natural numbers" 'N = nat.
49 alias num (instance 0) = "natural number".
50
51 (* By this syntax, we declare we are defining an inductive type of 
52 name nat (which is a Type[0]), built up from the two constructors O 
53 of type nat and S of type nat → nat.
54 Let us now define a simple function over natural numbers. 
55 The sum of two natural numbers n and m may be defined as follows: 
56 if n is O then the sum is m, otherwise, if n is the successor of 
57 some natural number p, then the sum of n and m is equal to the 
58 successor of the sum of p and m. In this way, we have reduced the 
59 computation of the sum of two natural numbers to a similar problem, 
60 but on smaller input values. This is an example of a recursive 
61 definition, that is a definition of a function in terms of the 
62 function itself. In Matita, the previous definition of the sum 
63 over natural numbers would be written in the following way: *)
64
65 let rec plus n m ≝ 
66  match n with [ O ⇒ m | S p ⇒ S (plus p m) ].
67 interpretation "natural plus" 'plus x y = (plus x y).
68
69 (* Equalities ***************************************************************)
70
71 theorem plus_O_n: ∀n:nat. n = O + n.
72 #n normalize @refl qed.
73
74 theorem plus_n_O: ∀n:nat. n = n + O.
75 #n (elim n) normalize 
76 [ @refl | #n #H <H @eq_f @refl ] qed.
77
78 theorem plus_n_Sm : ∀n,m:nat. S (n+m) = n + S m.
79 #n (elim n) normalize 
80 [#m @eq_f @refl 
81 |#m #H #p @eq_f <(H p) @eq_f @eq_f2 
82  [@refl|@refl]] qed.
83  
84 (* The monotonicity of plus is not in the original
85 Apserti's tutorial but, as far as I could understand
86 the way the current version of Matita works, requires
87 it to prove the equivalence of the two equivalence
88 relations le2 and le we shall see later. *)
89 theorem plus_monotone:∀n,m:nat. n=m → (S n) = (S m).
90 #n elim n  
91 [#m #Om <Om @eq_f @refl 
92 |#m #H #p #Smp >Smp @eq_f @refl] qed.
93
94 theorem plus_sym: ∀ n,m:nat. n+m = m+n.
95 #n #m elim n normalize
96 [ @plus_n_O
97 | #p #H >H @(plus_n_Sm m p)] qed.
98
99 (* Exercise: 
100 lemma not_eq_plus_S_m_O: ∀ n,m:nat. Not ((S n)+m = O).
101 #n #m @nmk >(plus_sym (S n) m) <(plus_n_Sm m n) #abs destruct qed .*)
102
103 (**************** Section 1.2 Double induction ***************)
104 theorem nat_elim2 :
105  ∀R:nat → nat → Prop.
106   (∀n:nat. R O n) 
107   → (∀n:nat. R (S n) O)
108   → (∀n,m:nat. R n m → R (S n) (S m))
109   → ∀n,m:nat. R n m.
110 #R #ROn #RSO #RSS #n (elim n) 
111 [ @ROn
112 | #Pred_n #RPred_nm
113   #m cases m
114     [@(RSO Pred_n)
115     |#m' @(RSS Pred_n m') @(RPred_nm m')]
116 ] qed.
117
118 (**************** Section 1.3 Negation and Discrimination ***)
119 (* Two major axioms of Peano axiomatization of naturals are:
120 1) the inequality between O and S x, for any x, and
121 2) the injectivity of S. 
122 More generally, given any inductive type, we expect to be 
123 able to prove that all constructors are injective and 
124 distinguishable each from the other.
125
126 The statement ∀x. Not (O = (Sx)) is our first example 
127 involving negation.
128
129 In the logical framework of Matita, negation is not 
130 considered as a primitive connective, but is instead defined 
131 in terms of the absurdity proposition False. Explicitly, we 
132 may conclude Not P, if and only if assuming P leads 
133 to an asburdity, that is P → False.
134
135 What about False? The only logical principle related to 
136 False is the ancient property expressed by the latin motto 
137 'ex falso quodlibet', that is, everything may be deduced 
138 under a false assumption. 
139
140 Formally, this is expressed by the following property that, 
141 for the moment, we may assume to be a primitive constant 
142 of the system:
143
144 False_ind : ∀P:Prop. False → P
145
146 [Ndr: In fact, False_ind *is* a primitive in Matita as it 
147 is used in many points when building libraries! ]
148
149 Concerning injectivity (or separability) of constructors, 
150 Matita provides the tactic destruct. The tactic expects in 
151 input a term of type e1 = e2. It recursively compares e1 
152 and e2, skipping common constructors (injectivity) and halts
153 on subexpressions differing on their leftmost outermost 
154 symbols. If any of these correponding symbols are two 
155 different constructors the tactics automatically closes the 
156 goal [Ndr: that depends on them] having obtained a 
157 contradiction. Otherwise, destruct adds to the context all 
158 new equalities between the different subformulae in 
159 corresponding positions. Luckily, the tactic is much simpler
160 to use than to explain. Let us see a couple of examples. *)
161
162 theorem not_eq_O_S: ∀ n:nat. Not (O = S n).
163 #n (* apply the definition of Not *) @nmk #Habs destruct qed.
164
165 (* Exercise:
166 lemma not_eq_S_O: ∀ n:nat. Not (S n = O).
167 #n (* apply the definition of Not *) @nmk #Habs destruct qed. *)
168
169 theorem S_inj: ∀ n,m:nat. S n = S m → n = m.
170 #n #m #Hinj destruct @refl qed .
171
172 (*****************************************************************)
173 (**************** Chapter 2. Defining properties *****************)
174 (*****************************************************************)
175 (* So far, the only property we have been dealing with has 
176 been equality that we have essentially assumed as a 
177 primitive notion of Matita, governed via rewriting and 
178 reflexivity. As an exercise one can prove simmetry and 
179 transitivity of the equality, as follows: *)
180
181 lemma eq_sym: ∀A:Type[0]. ∀x,y:A. x=y → y=x.
182 #A #x #y #eqxy <eqxy @refl qed .
183
184 lemma eq_tran: ∀A:Type[0]. ∀x,y,z:A. x=y → y=z → x=z.
185 #A #x #y #z #eqxy #eqyz >eqxy @eqyz qed .
186
187 (* The next step is to define a binary predicate 
188 le n m 
189 asserting that n is less or equal to m. As we shall see, 
190 we have some alternatives.
191
192 We start with a natural mathematical definition: 
193 n is less or equal to m 
194   if and only if it exists p such n + p = m. 
195
196 We have essentially two different, almost equivalent, ways
197 to encode such a predicate in Matita: 
198 1) as a definition, or 
199 2) as an inductive type.
200
201 As a definition it is: *)
202
203 definition le1: nat → nat → Prop ≝
204                        λn,m.∃p:nat.n+p = m.
205
206 (* However, an experienced Matita user would probably prefer
207 to transform the previous definition of le into the smallest
208 property induced by *an integer p and a proof of n+p=m * 
209 as follows:*)
210
211 inductive le2 (n,m:nat) : Prop ≝
212 le_witness : ∀p:nat.n+p = m → le2 n m.
213
214 (* The constructor le_witness is a user-defined name that
215 can bw chosen arbitrarily and which idetifies a proof of:
216     
217     ∀n,m,p:nat.n + p = m → le2 n m
218
219 Namely, the two parameters n and m are also parameters 
220 for the constructor whose fully blown type is exactly:
221
222      le_witness: ∀n,m,p:nat.n + p = m → le2 n m
223
224 We formally prove the equivalence between the two
225 previous definitions. 
226
227 We start proving that the first definition implies the
228 second one: *)
229
230 lemma le1_to_le2: ∀n,m:nat.le1 n m → le2 n m.
231 (* This is the proof pattern we shall follow: 
232 --------------------------------------------------- @npeqm
233 n:nat,m:nat,∃p:nat.n+p=m,
234 p:nat,npeqm:n+p=m  ⊢ n+p=m
235 ----------------------------------------------- @(le_witness n m p)
236 n:nat,m:nat,∃p:nat.n+p=m,
237 p:nat,npeqm:n+p=m  ⊢ n+p=m→le2 n m
238 ----------------------------------------------- #p #npeqm
239 n:nat,m:nat,∃p:nat.n+p=m 
240                    ⊢ ∀x:ℕ.n+x=m→le2 n m
241 ----------------------------------------------- elim le1
242 n:nat,m:nat,∃p:nat.n+p=m 
243                    ⊢ le2 n m
244 ----------------------------------- normalize in le1;
245 n:nat,m:nat,le1 n m ⊢ le2 n m
246 ------------------------------- #n #m #le1
247 ∀n,m:nat.le1 n m → le2 n m                    *)
248 #n #m #le1 
249 normalize in le1; elim le1 (* (0) *)
250 #p #npeqm @(le_witness n m p) @npeqm qed .
251
252 (* Then, the second definition implies the first one: *)
253 lemma le2_to_le1: ∀n,m:nat.le2 n m → le1 n m.
254 (* This is the proof pattern we shall follow: 
255 ---------- (ex_intro nat (λp:ℕ.n+p=m)) ---------
256 n:ℕ,m:ℕ,le2:le2 n m ⊢ ∀p:ℕ.n+p=m → ∃p0:ℕ.n+p0=m
257 ------------------------------------------------ normalize
258 n:ℕ,m:ℕ,le2:le2 n m ⊢ ∀p:ℕ.n+p=m → le1 n m
259 ------------------------------------------- elim le2
260 n:ℕ,m:ℕ,le2:le2 n m ⊢ le1 n m
261 -------------------------------- #n #m #le2
262 ∀n:ℕ.∀m:ℕ.le2 n m→le1 n m                      *)
263 #n #m #le2 elim le2 normalize (* (1) *)
264 (* (* One may *) check  (ex_intro nat (λp:ℕ.n+p=m)) *)
265 @(ex_intro nat (λp:ℕ.n+p=m)) (* (2) *) 
266 qed .
267
268 (* In the previous proof we do not follow  original Asperti's
269 proof pattern. We directly exploit ex_intro, defined in 
270 lib/basics/logic.ma whose type is:
271
272      eq_intro: ∀A:Type.∀P:A→Prop.∀x:A.Px→∃x:A.Px
273
274 I have do guess the two arguments of ex_intro. In fact,
275 I have experimented with the original Asperti's proof pattern
276 which, keep going from (1) above, must develop as follows:
277
278     #p #npeqm  @(ex_intro ? ? p npeqm))
279
280 Specifically,
281     check (ex_intro ? ? p npeqm)) 
282 lets Matita to automatically build:
283     (ex_intro ℕ (λ_:ℕ.n+__1=m) p npeqm:∃_:ℕ.n+__1=m)
284 from which one can synthesize (2).
285
286 We remark that the proof of le2_to_le1 is slightly more 
287 compact than the proof of le1_to_le2. The reason is that
288 le2_to_le1 does not require the normalization of the 
289 definition of le2 before eliminating it as in (0) above. 
290 This is one of the practical reason for preferring le2 over 
291 le1. More generally, the existential quantifier is just a 
292 particular case of inductive type, and the direct definition 
293 of a property as an inductive types usually allows a simpler
294 and more direct destructuration of the corresponding 
295 definition. *)
296
297 (**************** Section 2.1 Recursive properties ***)
298 (* The previous definition of le relies on the definition of 
299 the sum, that is not very elegant. An alternative way to look 
300 at the less or equal relation is as the smallest relation R 
301 being reflexive and such that R n m implies R n (S m). This 
302 notion is precisely captured by the following inductive type: *)
303 inductive le (n:nat) : nat → Prop ≝
304 | le_n : le n n
305 | le_S : ∀ m:nat. le n m → le n (S m).
306
307 (* Again, let us prove the equivalence between this definition 
308 and the definition of le2. As suggested by the original
309 tutorial, we start showing why the tactics we learned so far
310 are not enough. To experiment it, just uncomment in the
311 right way. *)
312 (* <-- Erase this....
313 lemma le2_to_le_not_general_enough: ∀ n,m:nat. le2 n m → le n m.
314 (*  As suggested, one can start as follows: *)
315 #n #m #le2 elim le2 #p 
316 (* We get to: 
317    n:ℕ,m:ℕ,le2:le2 n m,p:ℕ ⊢ n+p=m→le n m
318 At this point, we can try to proceed by induction on p: *) 
319 elim p
320 [ (* We can prove the base case *)
321   normalize <(plus_n_O n) #nm <nm @le_n 
322 | (* However the assumptions are too weak 
323      and we get stuck.  *)
324   #x #ind #H 
325 ] .... and erase this --> *)
326  
327 (* In fact, in the course of the proof of le_to_le2
328 instead of getting to the point where the goal is
329            n+p=m→le n m
330 we need to arrive to the stronger goal:
331            ∀m:ℕ.n+p=m→le n m
332 The tactic we need is 
333      generalize in match m; 
334 The working proof follows.  *)
335
336 lemma le2_to_le: ∀ n,m:nat. le2 n m → le n m .
337 (* 
338 The following proof can be seen as split into two
339 phases. The first one aims at getting to the goal
340    n:nat,p:ℕ ⊢ ∀m:nat.n+p=m → le n m (1)
341 which we shall prove by inducton on 
342
343 The goal (1) here above needs the introduction to
344 the right of ∀m, after m has been moved among the
345 assumptions to discharge all the other assumptions
346 as required:
347
348 n:nat,p:ℕ ⊢ ∀m:nat.n+p=m → le n m
349 ------------------------------------ generalize in match m;
350 n:nat,m:nat,p:ℕ ⊢ n+p=m → le n m
351 ------------------------------------ #p
352 n:nat,m:nat ⊢ ∀p:ℕ.n+p=m→le n m
353 ------------------------------------ elim le2 -le2
354 n:nat,m:nat,le2 n m ⊢ le n m
355 ------------------------------------ #n #m #le2 
356 ∀n,m:nat.le2 n m → le n m         *)
357 #n #m #le2 elim le2 -le2
358 #p generalize in match m;
359 (* The second part proves (1) by induction on p: *)
360 elim p
361 [ <(plus_n_O n) #n' #neqn' <neqn' @le_n 
362 | #x #Hind #y #nSxeqy <nSxeqy <(plus_n_Sm) @(le_S)
363   @(Hind (n+x)) 
364   (* eq_f2 is in lib/basics/logic.ma *)
365   @eq_f2 @refl @refl
366 ] qed .
367
368 (* The converse holds as well: *)
369 lemma le_to_le2: ∀ n,m:nat. le n m → le2 n m .
370 #n #m #le elim le -le
371 [ @(le_witness n n O) <(plus_n_O n) @refl
372 | (* 
373   *)
374   #x #H -H 
375   #le2 elim le2 -le2
376   #p 
377   (* The coming steps have n,m,x,p as global assumptions and essentially
378      build the following proof:
379      
380       plus_monotone
381     ----------------- -------------
382     ⊢ n+p=x→S(n+p)=Sx n+p=x ⊢ n+p=x   plus_n_Sm      
383  →E--------------------------------  -------------   
384          n+p=x ⊢ S(n+p)=Sx          ⊢ S(n+p)=n+Sp   ∀n,m,p.n+p=m->le2 n (S x) 
385       eq ----------------------------------------   -------------------------
386                         n+p=x ⊢ n+Sp=Sx              ⊢ n+Sp=Sx → le2 n (S x) 
387                      →E-----------------------------------------------------
388                                   n+p=x ⊢ le2 n (S x)
389                              →I-----------------------
390                                  ⊢ n+p=x → le2 n (S x)                  *)
391   #npeqx
392   (* check (plus_monotone (n+p) x npeqx) *) 
393   lapply (plus_monotone (n+p) x npeqx) -npeqx
394   >(plus_n_Sm)
395   (* check (le_witness n (S x) (S p)) *)
396   @(le_witness n (S x) (S p))
397   ] qed .
398
399 (**************** Section 2.2 Prop vs. Bool ***)
400 (* The definition of le of the previous section does not give an 
401 effective way to decide if n is less or equal to m. What we are looking 
402 for is a binary boolean function returning true if n ≤ m, and f alse 
403 otherwise. Such a computable function is usually called a decision 
404 procedure. A property admitting a decision procedure is called recursive,
405 or decidable. We start defining the type of booleans as the smallest type
406 containing the two elements true and false: *)
407 inductive bool : Type[0] ≝
408 | true : bool
409 | false : bool.
410
411 (* Then, we define a decision procedure for the less or equal relation: *)
412 let rec leb n m ≝ 
413   match n with
414   [ O ⇒ true | (S p) ⇒ match m with
415                        [ O ⇒ false | (S q) ⇒ leb p q]].
416                              
417 (* Once given a decision procedure, it is convenient to define a
418 corresponding elimination principle, which relates in a very general
419 way the boolean function to its propositional counterpart (le). In our 
420 case the boolean function is leb, and its propositional counterpart 
421 is le. The elimination principle says that:
422 for all natural numbers n and m, and any proposition P over booleans, 
423 provided we may prove (P true) under the assumption (le n m), and 
424 (P false) under the assumption ¬(le n m), then we can conclude 
425 (P (leb n m)). Namely:
426
427   (n ≤ m → (P true)) → (n ≰ m → (P false)) → P (leb n m)
428
429 The proof requires preliminary steps: 
430 1) the proof of lemmas le_O_n, not_le_Sn_O, le_S_S, 
431 2) the definition of pred
432 3) the proof the pred is monotonic
433 4) the proof of le_S_S_to_le.
434 5) the proof of contraposition, called not_to_not in
435 lib/basics/logic.ma. Tuttavia, si potrebbe immaginare
436 di spostare contraposition nella sezione relativa alle
437 dimostrazioni per assurdo, visto il modo di dimostrarla. *)
438
439 lemma le_O_n : ∀n:nat. le O n.
440 #n (elim n) [@le_n | #x @le_S ] qed.
441
442 lemma not_le_Sn_O: ∀ n:nat. Not (le (S n) O).
443 #n @nmk #abs 
444 lapply ((le_to_le2 (S n) O) abs) -abs #le2 elim le2 -le2 #p
445 >(plus_sym (S n) p) <(plus_n_Sm p n) #abs destruct qed .
446  
447 lemma le_S_S: ∀n,m:nat. (le n m) → (le (S n) (S m)).
448 #n #m #lenm elim lenm -lenm
449 [ @le_n | #x #H -H @(le_S) ] qed .
450
451 definition pred ≝
452  λn. match n with [ O ⇒ O | S p ⇒ p].
453
454 theorem pred_monotonic: 
455    ∀n,m:nat. le n m → le (pred n) (pred m).
456 #n #m #lenm (elim lenm)
457 [ @le_n 
458 | #x normalize in match (pred (S x)); 
459   cases x normalize in match (pred O);
460   [ #dummy #H @H 
461   | #y normalize in match (pred (S y)); 
462     #dummy @le_S ] qed.
463
464 lemma le_S_S_to_le: ∀n,m:nat. (le (S n) (S m)) → (le n m).
465 #n #m #leSnSn 
466 (* check ((pred_monotonic (S n) (S m)) leSnSn) *)
467 lapply ((pred_monotonic (S n) (S m)) leSnSn) 
468 normalize in match (pred (S n));
469 normalize in match (pred (S m)); #H @H qed .
470
471 theorem contraposition : ∀A,B:Prop. (A → B) → ¬B →¬A.
472 #A #B #AB #nB @nmk #A lapply nB lapply (AB A) @absurd qed .
473
474 theorem leb_elim: ∀n,m:nat. ∀P:bool → Prop.
475 (le n m → P true) → (Not (le n m) → P false) → P (leb n m).
476 @nat_elim2 
477   [normalize #n #P #Pt #Pf @Pt @(le_O_n)
478   |normalize #n #P #Pt #Pf @Pf @(not_le_Sn_O)
479   |normalize #n #m #Hind #P #Pt #Pf @Hind
480     [#lenm @Pt @le_S_S @lenm 
481     |#nlenm @Pf lapply nlenm  @contraposition @le_S_S_to_le ]
482 qed.
483
484 (* Le seguenti prorietà che si trovano anche in 
485 lib/arithmetics/nat.ma ma sinora non mi paiono necessarie
486 per questo tutorial, quindi le commento. 
487
488
489 lemma le_n_Sn : ∀n:nat. le n (S n).
490 #n @le_S @le_n qed.
491
492 lemma le_tran : ∀n,m,o:nat. le n m → le m o → le n o.
493 #n #m #o #lenm #lemo (elim lemo) 
494 [@lenm | #x #dummy @le_S ]   qed. 
495
496 lemma  le_pred_n : ∀n:nat. le (pred n) n.
497 #n (elim n) 
498 [ normalize @le_n 
499 | #m #H normalize @(le_S) @le_n] qed . *)
500
501
502 (* Le seguenti proprietà sfruttano pesantemente leb_elim e sono
503 un esempio fondamentale.*)
504 theorem leb_true_to_le:∀n,m.leb n m = true → (le n m).
505 #n #m 
506 (* check (λb:bool. b=true→le n m)) *)
507 check (∀b:bool. b=true→le n m)
508 (* check ((λb:bool. b=true→le n m) (leb n m)) *)
509 @(leb_elim n m (λb:bool. b=true→le n m))
510
511 (* DA QUI !!!!!!!!!!!!!!!!!*)
512
513 @leb_elim // #_ #abs @False_ind /2/ qed.
514
515 theorem leb_false_to_not_le:∀n,m.
516   leb n m = false → n ≰ m.
517 #n #m @leb_elim // #_ #abs @False_ind /2/ qed.
518
519 theorem le_to_leb_true: ∀n,m. n ≤ m → leb n m = true.
520 #n #m @leb_elim // #H #H1 @False_ind /2/ qed.
521
522 theorem not_le_to_leb_false: ∀n,m. n ≰ m → leb n m = false.
523 #n #m @leb_elim // #H #H1 @False_ind /2/ qed.
524
525 theorem lt_to_leb_false: ∀n,m. m < n → leb n m = false.
526 /3/ qed.
527
528
529 (*****************************************************************)
530 (**************** Chapter 3. A non trivial example ***************)
531 (*****************************************************************)
532 (* In a way similar to plus we may define the product of two natural 
533 numbers: *)
534
535
536 let rec times n m ≝ 
537  match n with [ O ⇒ 0 | S p ⇒ m + (times p m) ].
538
539 interpretation "natural times" 'times x y = (times x y).
540
541 definition divides1: nat \to nat \to Prop \def
542 \lambda n,m.\exist p:nat.m = times n p.
543
544 (* However, as we have seen, it is preferable to define divides as
545 the smallest property induced by a 'witness' p and a proof that 
546 m = np, namely: *)
547
548 inductive divides (n,m:nat) : Prop \def
549 witness : \forall p:nat.m = times n p \to divides n m.
550
551
552 (* Let us now address the decidability of divides, i.e. the problem
553 to define an algorithmic boolean function that taken in input two 
554 integers n and m returns true if n divides m, and f alse otherwise.
555 A convenient way to proceed is to address the slightly more general
556 problem to compute the modulus (mod) of two numbers (i.e. the rest
557 of an integewr division); obviously n divides m if and only if 
558 m mod n = 0. The natural way to define mod as a recursive function 
559 would look something like the following: *)
560
561 let rec mod m n: nat \def
562 match (leb (S m) n) with
563 [ true \Rightarrow m
564 | false \Rightarrow mod (m-n) n
565 ]
566
567 (* The problem with this definition is that the calculus is based on 
568 a particular kind or recursion that must be guaranteed to be 
569 well-founded (never diverge) . This is typically the case when the 
570 recursive parameter 'decreases' in the recursive call. Unfortunately,
571 there is no trivial way, for the system, to understand that m − n is 
572 'smaller' than m w.r.t. some well founded ordering
573 (minus is a user defined operation!). What the system is able to 
574 understand is essentially a syntactic ordering, based on the structure
575 of inductive data: for instance n is 'smaller' of S n.
576 A simple but effective approach to this problem is that of defining 
577 an auxiliary function accepting in input an extra-parameter t 
578 providing an upper bound to the complexity of the function, and then 
579 recurring on such an argument. For instance, in the case of the 
580 modulus, we may eventually complete the computation of mod m n in 
581 less than m steps. So, we define: *)
582
583 let rec mod_aux t m n: nat \def
584 match (leb (S m) n) with
585 [ true \Rightarrow m
586 | false \Rightarrow
587 match t with
588 [O \Rightarrow m
589 (* if t is large enough this case never happens *)
590 |(S t1) \Rightarrow mod_aux t1 (m-n) n
591 ]
592 ].
593
594 definition mod : nat \to nat \to nat \def
595 \lambda m,n.mod_aux m m n.
596
597 (* When we define a function having several cases as the previous 
598 one, it is good practice to specify the behavour with a distinct 
599 lemma for each possible branch. In the case of the previous function,
600 we have the following relevant cases, whose proof is more or less 
601 straightforward. The only novelty is the use of the change tactic, 
602 that allows to replace a goal with an equivalent one (up to 
603 convertibility). Sometimes, the heuristic used by the simplify 
604 tactic simplifies too much, and it turns out to be convenient to 
605 give the system the expected transformation in an explicit way. *)
606
607 lemma O_to_mod_aux: \forall m,n. mod_aux O m n = m.
608 intros.
609 simplify.elim (leb (S m) n);reflexivity.
610 qed.
611
612 lemma lt_to_mod_aux:
613 \forall t,m,n. m < n \to mod_aux (S t) m n = m.
614 intros.
615 change with
616 ( match (leb (S m) n) with
617 [ true \Rightarrow m
618 | false \Rightarrow mod_aux t (m-n) n] = m).
619 rewrite > (le_to_leb_true ? ? H).
620 reflexivity.
621 qed.
622
623 lemma le_to_mod_aux:
624 \forall t,m,n.
625 n \le m \to mod_aux (S t) m n = mod_aux t (m-n) n.
626 intros.
627 change with
628 (match (leb (S m) n) with
629 [ true \Rightarrow m
630 | false \Rightarrow mod_aux t (m-n) n] = mod_aux t (m-n) n).
631 apply (leb_elim (S m) n);intro
632 [apply False_ind.apply (le_to_not_lt ? ? H).apply H1
633 |reflexivity
634 ]
635 qed.
636
637 (* In order to understand the use of the previous lemmas, let us 
638 try to prove a simple property of the modulus operation, namely that
639 for any positive n, m mod n < n. The proof has the following 
640 structure: *)
641
642 theorem lt_mod_aux_m_m:
643 \forall n. O < n \to
644 \forall t,m. m \leq t \to (mod_aux t m n) < n.
645 intros 3.
646 elim t
647 [rewrite > O_to_mod_aux.
648 apply (le_n_O_elim ? H1).
649 assumption
650 |elim (decidable_lt m n)
651 [rewrite > lt_to_mod_aux[assumption|assumption]
652 |rewrite > le_to_mod_aux
653 [apply H1.
654 ...
655 |apply not_lt_to_le.
656 assumption
657 ]
658 ]
659 ]
660 qed.
661
662 (* Mimicking the definition of mod_aux, the proof proceeds by 
663 induction on the recursive parameter t. The case t = 0 is closed 
664 by O_to_mod_aux; in case t = Sn1, we distinguish two more cases 
665 according the situations m < n or m ≥ n. In the former case, we use 
666 lt_to_mod_aux while in the latter we use le_to_mod_aux
667 and the inductive hypothesis H1. The dots correspond to a trivial 
668 but formally cumbersome fragment of the proof. Indeed, after 
669 applying the inductive hypothesis H1 we are left with the following 
670 goal: *)
671
672
673 (* Very likely here it will benecessary to expand what 
674 Andrea writes .... *)
675
676 (* The proof requires several elementary arithmetical results, 
677 but is not particualry informative, so we shall skip it here.
678 Having defined the modulus, we define: *)
679
680 definition divides_b : nat \to nat \to bool \def
681 \lambda n,m :nat. (eqb (m \mod n) O).
682