]> matita.cs.unibo.it Git - helm.git/blob - weblib/tutorial/chapter2.ma
commit by user andrea
[helm.git] / weblib / tutorial / chapter2.ma
1 include "basics/logic.ma".
2
3 (* Most of the types we have seen so far are enumerated types, composed by a finite set of 
4 alternatives, and records, composed by tuples of heteregoneous elements. 
5 A more interesting case of type definition is when some of the rules defining its elements are 
6 recursive, i.e. they allow the formation of more elements of the type in terms of the already
7 defined ones. The most typical case is provided by the natural numbers, that can be defined as 
8 the smallest set generated by a constant 0 and a successor function from natural numbers to 
9 natural numbers *)
10
11 inductive nat : Type[0] ≝ 
12 | O :nat
13 | S: nat →nat.
14
15 (* The two terms O and S are called constructors: they define the signature of the type, whose 
16 objects are the elements freely generated by means of them. So, examples of natural numbers are 
17 O, S O, S (S O), S (S (S O)) and so on. 
18
19 The language of Matita allows the definition of well founded recursive functions over inductive 
20 types; in order to guarantee termination of recursion you are only allowed to make recursive 
21 calls on structurally smaller arguments than the ones you received in input. 
22 Most mathematical functions can be naturally defined in this way. For instance, the sum of two 
23 natural numbers can be defined as follows *)
24
25 let rec add n m ≝ 
26 match n with
27 [ O ⇒ m
28 | S a ⇒ \ 5a href="cic:/matita/tutorial/chapter2/nat.con(0,2,0)"\ 6S\ 5/a\ 6 (add a m)
29 ].
30
31 (* It is worth to observe that the previous algorithm works by recursion over the first 
32 argument. This means that, for instance, (add 0 x) will reduce to x, as expected, but (add x 0)
33 is stack. How can we prove that, for a generic x, (add x 0) = x? The mathematical tool do it is 
34 called induction. The induction principle states that, given a property P(n) over natural 
35 numbers, if we prove P(0) and prove that, for any m, P(m) implies P(S m), than we can conclude
36 P(n) for any n. 
37
38 The elim tactic, allow you to apply induction in a very simple way. If your goal is P(n), the 
39 invocation of
40   elim n
41 will break down your task to prove the two subgoals P(0) and ∀m.P(m) → P(S m).
42
43 Let us apply it to our case *)
44
45 lemma add_0: ∀a. \ 5a href="cic:/matita/tutorial/chapter2/add.fix(0,0,1)"\ 6add\ 5/a\ 6 a \ 5a href="cic:/matita/tutorial/chapter2/nat.con(0,1,0)"\ 6O\ 5/a\ 6 \ 5a title="leibnitz's equality" href="cic:/fakeuri.def(1)"\ 6=\ 5/a\ 6 a.
46 #a elim a
47
48 (* If you stop the computation here, you will see on the right the two subgoals 
49     - add O O = O
50     - ∀x. add x 0 = x → add (S x) O = S x
51 After normalization, both goals are trivial.
52 *)
53
54 normalize // qed.
55
56 (* In a similar way, it is convenient to state a lemma about the behaviour of add when the 
57 second argument is not zero. *)
58
59 lemma add_S : ∀a,b. \ 5a href="cic:/matita/tutorial/chapter2/add.fix(0,0,1)"\ 6add\ 5/a\ 6 a (\ 5a href="cic:/matita/tutorial/chapter2/nat.con(0,2,0)"\ 6S\ 5/a\ 6 b) \ 5a title="leibnitz's equality" href="cic:/fakeuri.def(1)"\ 6=\ 5/a\ 6 \ 5a href="cic:/matita/tutorial/chapter2/nat.con(0,2,0)"\ 6S\ 5/a\ 6 (\ 5a href="cic:/matita/tutorial/chapter2/add.fix(0,0,1)"\ 6add\ 5/a\ 6 a b).
60
61 (* In the same way as before, we proceed by induction over a. *)
62
63 #a #b elim a normalize //
64 qed. 
65
66 (* We are now in the position to prove the commutativity of the sum *)
67
68 theorem add_comm : ∀a,b. \ 5a href="cic:/matita/tutorial/chapter2/add.fix(0,0,1)"\ 6add\ 5/a\ 6 a b \ 5a title="leibnitz's equality" href="cic:/fakeuri.def(1)"\ 6=\ 5/a\ 6 \ 5a href="cic:/matita/tutorial/chapter2/add.fix(0,0,1)"\ 6add\ 5/a\ 6 b a.
69 #a elim a normalize
70
71 (* We have two sub goals:
72   G1: ∀b. b = add b O
73   G2: ∀x.(∀b. add x b = add b x) → ∀b. S (add x b) = add b (S x). 
74 G1 is just our lemma add_O. For G2, we start introducing x and the induction hypothesis IH; 
75 then, the goal is proved by rewriting using add_S and IH.
76 For Matita, the task is trivial and we can simply close the goal with // *)
77
78 // qed.
79
80 (* Let us now define the following function: *)
81
82 definition twice ≝ λn.\ 5a href="cic:/matita/tutorial/chapter2/add.fix(0,0,1)"\ 6add\ 5/a\ 6 n n. 
83
84 (* We are interested to prove that for any natural number m there exists a natural number m that 
85 is the integer half of m. This will give us the opportunity to introduce new connectives and 
86 quantifiers, and later on to make some interesting consideration on proofs and computations. *)
87
88 theorem ex_half: ∀n.\ 5a title="exists" href="cic:/fakeuri.def(1)"\ 6\ 5/a\ 6m. n \ 5a title="leibnitz's equality" href="cic:/fakeuri.def(1)"\ 6=\ 5/a\ 6 \ 5a href="cic:/matita/tutorial/chapter2/twice.def(2)"\ 6twice\ 5/a\ 6 m \ 5a title="logical or" href="cic:/fakeuri.def(1)"\ 6\ 5/a\ 6 n \ 5a title="leibnitz's equality" href="cic:/fakeuri.def(1)"\ 6=\ 5/a\ 6 \ 5a href="cic:/matita/tutorial/chapter2/nat.con(0,2,0)"\ 6S\ 5/a\ 6 (\ 5a href="cic:/matita/tutorial/chapter2/twice.def(2)"\ 6twice\ 5/a\ 6 m).
89 #n elim n normalize 
90
91 (* We proceed by induction on n, that breaks down to the following goals:
92   G1: ∃m.O = add O O ∨ O = S (add m m)
93   G2: ∀x.(∃m. x = add m m ∨ x = S (add m m))→ ∃m. S x = add m m ∨ S x = S (add m m)
94 The only way we have to prove an existential goal is by exhibiting the witness, that in the case 
95 of first goal is O. We do it by apply the term called ex_intro instantiated by the witness. 
96 Then, it is clear that we must follow the left branch of the disjunction. One way to do it is by 
97 applying the term or_introl, that is the first constructor of the disjunction. However, 
98 remembering the names of constructors can be annyoing: we can invoke the application of the n-th
99 constructor of an inductive type (inferred by the current goal) by typing %n. At this point 
100 we are left with the subgoal O = add O O, that is closed by computation.
101 It is worth to observe that invoking automation at depth /3/ would also automatically close G1.
102 *)
103   [@(\ 5a href="cic:/matita/basics/logic/ex.con(0,1,2)"\ 6ex_intro\ 5/a\ 6 … \ 5a href="cic:/matita/tutorial/chapter2/nat.con(0,1,0)"\ 6O\ 5/a\ 6) %1 //
104
105 (* The case of G2 is more complex. We should start introducing x and the inductive hypothesis
106      IH: ∃m. x = add m m ∨ x = S (add m m) 
107 At this point we should assume the existence of m enjoying the inductive hypothesis. To 
108 eliminate the existential from the context we can just use the case tactic. This situation where
109 we introduce something into the context and immediately eliminate it by case analysis is so 
110 frequent that Matita provides a convenient shorthand: you can just type a single "*". 
111 The star symbol should be reminiscent of an explosion: the idea is that you have a structured
112 hypothesis, and you ask to explode it into its constituents. In the case of the existential,
113 it allows to pass from a goal of the shape 
114     (∃x.P x) → Q
115 to a goal of the shape
116     ∀x.P x → Q
117 *)
118   |#x *
119 (* At this point we are left with a new goal with the following shape
120   G3: ∀m. x = add m m ∨ x = S (add m m) → ....  
121 We should introduce m, the hypothesis H: x = add m m ∨ x = S (add m m), and then reason by
122 cases on this hypothesis. It is the same situation as before: we explode the disjunctive 
123 hypothesis into its possible consituents. In the case of a disjunction, the * tactic allows
124 to pass from a goal of the form
125     A∨B → Q
126 to two subgoals of the form
127     A → Q  and  B → Q
128 *)
129   #m * #eqx
130 (* In the first subgoal, we are under the assumption that x = add m m. The half of (S x)
131 is hence m, and we have to prove the right branch of the disjunction. 
132 In the second subgoal, we are under the assumption that x = S (add m m). The halh of (S x)
133 is hence (S m), and have to follow the left branch of the disjunction.
134 *)
135   [@(\ 5a href="cic:/matita/basics/logic/ex.con(0,1,2)"\ 6ex_intro\ 5/a\ 6 … m) /2/ | @(\ 5a href="cic:/matita/basics/logic/ex.con(0,1,2)"\ 6ex_intro\ 5/a\ 6 … (\ 5a href="cic:/matita/tutorial/chapter2/nat.con(0,2,0)"\ 6S\ 5/a\ 6 m)) normalize /2/
136   ]
137 qed.