]> matita.cs.unibo.it Git - helm.git/blob - weblib/tutorial/chapter1.ma
- update in basic_2
[helm.git] / weblib / tutorial / chapter1.ma
1 (* 
2 \ 5h1\ 6Matita Interactive Tutorial\ 5/h1\ 6
3 This is an interactive tutorial. To let you interact on line with the system, 
4 you must first of all register yourself.
5
6 Before starting, let us briefly explain the meaning of the menu buttons. 
7 With the Advance and Retract buttons you respectively perform and undo single 
8 computational steps. Each step consists in reading a user command, and processing
9 it. The part of the user input file (called script) already executed by the 
10 system will be colored, and will not be editable any more. The advance bottom 
11 will also automatically advance the focus of the window, but you can inspect the 
12 whole file using the scroll bars, as usual. Comments are skipped.
13 Try to advance and retract a few steps, to get the feeling of the system. You can 
14 also come back here by using the top button, that takes you at the beginning of 
15 a file. The play button is meant to process the script up to a position 
16 previously selected by the user; the bottom button execute the whole script. 
17 That's it: we are\ 5span style="font-family: Verdana,sans-serif;"\ 6 \ 5/span\ 6now ready to start.
18
19 \ 5h2 class="section"\ 6Data types, functions and theorems\ 5/h2\ 6
20 Matita is both a programming language and a theorem proving environment:
21 you define datatypes and programs, and then prove properties on them.
22 Very few things are built-in: not even booleans or logical connectives
23 (but you may of course use libraries, as in normal programming languages). 
24 The main philosophy of the system is to let you define your own data-types 
25 and functions using a powerful computational mechanism based on the 
26 declaration of inductive types. 
27
28 Let us start this tutorial with a simple example based on the following well 
29 known problem.
30
31 \ 5b\ 6The goat, the wolf and the cabbage\ 5/b\ 6
32 A farmer need to transfer a goat, a wolf and a cabbage across a river, but there
33 is only one place available on his boat. Furthermore, the goat will eat the 
34 cabbage if they are left alone on the same bank, and similarly the wolf will eat
35 the goat. The problem consists in bringing all three items safely across the 
36 river. 
37
38 Our first data type defines the two banks of the river, which will be named east
39 and west. It is a simple example of enumerated type, defined by explicitly 
40 declaring all its elements. The type itself is called "bank".
41 Before giving its definition we "include" the file "logic.ma" that contains a 
42 few preliminary notions not worth discussing for the moment.
43 *)
44
45 include "basics/logic.ma".
46
47 inductive bank: Type[0] ≝
48 | east : bank 
49 | west : bank.
50
51 (* We can now define a simple function computing, for each bank of the river, the
52 opposite one. *)
53
54 definition opposite ≝ λs.
55 match s with
56   [ east ⇒ west
57   | west ⇒ east
58   ].
59
60 (* Functions are live entities, and can be actually computed. To check this, let
61 us state the property that the opposite bank of east is west; every lemma needs a 
62 name for further reference, and we call it "east_to_west". *)
63  
64 lemma east_to_west : opposite east = west.
65
66 (* 
67 \ 5h2 class="section"\ 6The goal window\ 5/h2\ 6
68 If you stop the execution here you will see a new window on the  right side
69 of the screen: it is the goal window, providing a sequent like representation of
70 the form
71
72 B1
73 B2
74 ....
75 Bk
76 -----------------------
77 A
78
79 for each open goal remaining to be solved. A is the conclusion of the goal and 
80 B1, ..., Bk is its context, that is the set of current hypothesis and type 
81 declarations. In this case, we have only one goal, and its context is empty. 
82 The proof proceeds by typing commands to the system. In this case, we
83 want to evaluate the function, that can be done by invoking the  "normalize"
84 command:
85 *)
86
87 normalize
88
89 (* By executing it - just type the advance command - you will see that the goal
90 has changed to west = west, by reducing the subexpression (opposite east). 
91 You may use the retract bottom to undo the step, if you wish. 
92
93 The new goal west = west is trivial: it is just a consequence of reflexivity.
94 Such trivial steps can be just closed in Matita by typing a double slash. 
95 We complete the proof by the qed command, that instructs the system to store the
96 lemma performing some book-keeping operations. 
97 *)
98
99 // qed.
100
101 (* In exactly the same way, we can prove that the opposite side of west is east.
102 In this case, we avoid the unnecessary simplification step: // will take care of 
103 it. *) 
104
105 lemma west_to_east : opposite west = east.
106 // qed.
107
108 (*
109 \ 5h2 class="section"\ 6Introduction\ 5/h2\ 6
110 A slightly more complex problem consists in proving that opposite is idempotent *)
111
112 lemma idempotent_opposite : ∀x. opposite (opposite x) = x.
113
114 (* we start the proof moving x from the conclusion into the context, that is a 
115 (backward) introduction step. Matita syntax for an introduction step is simply 
116 the sharp character followed by the name of the item to be moved into the 
117 context. This also allows us to rename the item, if needed: for instance if we 
118 wish to rename x into b (since it is a bank), we just type #b. *)
119
120 #b
121
122 (* See the effect of the execution in the goal window on the right: b has been 
123 added to the context (replacing x in the conclusion); moreover its implicit type 
124 "bank" has been made explicit. 
125 *)
126
127 (*
128 \ 5h2 class="section"\ 6Case analysis\ 5/h2\ 6
129 But how are we supposed to proceed, now? Simplification cannot help us, since b
130 is a variable: just try to call normalize and you will see that it has no effect.
131 The point is that we must proceed by cases according to the possible values of b,
132 namely east and west. To this aim, you must invoke the cases command, followed by
133 the name of the hypothesis (more generally, an arbitrary expression) that must be
134 the object of the case analysis (in our case, b).
135 *)
136
137 cases b
138
139 (* Executing the previous command has the effect of opening two subgoals, 
140 corresponding to the two cases b=east and b=west: you may switch from one to the 
141 other by using the hyperlinks over the top of the goal window. 
142 Both goals can be closed by trivial computations, so we may use // as usual.
143 If we had to treat each subgoal in a different way, we should focus on each of 
144 them in turn, in a way that will be described at the end of this section.
145 *)
146
147 // qed.
148
149 (* 
150 \ 5h2 class="section"\ 6Predicates\ 5/h2\ 6
151 Instead of working with functions, it is sometimes convenient to work with
152 predicates. For instance, instead of defining a function computing the opposite 
153 bank, we could declare a predicate stating when two banks are opposite to each 
154 other. Only two cases are possible, leading naturally to the following 
155 definition:
156 *)
157
158 inductive opp : bank → bank → Prop ≝ 
159 | east_west : opp east west
160 | west_east : opp west east.
161
162 (* In precisely the same way as "bank" is the smallest type containing east and
163 west, opp is the smallest predicate containing the two sub-cases east_west and
164 weast_east. If you have some familiarity with Prolog, you may look at opp as the
165 predicate defined by the two clauses - in this case, the two facts - ast_west and
166 west_east.
167
168 Between opp and opposite we have the following relation:
169     opp a b iff a = opposite b
170 Let us prove it, starting from the left to right implication, first *)
171
172 lemma opp_to_opposite: ∀a,b. opp a b → a = opposite b.
173  
174 (* We start the proof introducing a, b and the hypothesis opp a b, that we
175 call oppab. *)
176 #a #b #oppab
177
178 (* Now we proceed by cases on the possible proofs of (opp a b), that is on the 
179 possible shapes of oppab. By definition, there are only two possibilities, 
180 namely east_west or west_east. Both subcases are trivial, and can be closed by
181 automation *)
182
183 cases oppab // qed.
184
185 (* 
186 \ 5h2 class="section"\ 6Rewriting\ 5/h2\ 6
187 Let us come to the opposite direction. *)
188
189 lemma opposite_to_opp: ∀a,b. a = opposite b → opp a b.
190
191 (* As usual, we start introducing a, b and the hypothesis (a = opposite b), 
192 that we call eqa. *)
193
194 #a #b #eqa
195
196 (* The right way to proceed, now, is by rewriting a into (opposite b). We do
197 this by typing ">eqa". If we wished to rewrite in the opposite direction, namely
198 opposite b into a, we would have typed "<eqa". *)
199
200 >eqa
201
202 (* We conclude the proof by cases on b. *)
203
204 cases b // qed.
205
206 (*
207 \ 5h2 class="section"\ 6Records\ 5/h2\ 6
208 It is time to proceed with our formalization of the farmer's problem. 
209 A state of the system is defined by the position of four items: the goat, the 
210 wolf, the cabbage, and the boat. The simplest way to declare such a data type
211 is to use a record.
212 *)
213
214 record state : Type[0] ≝
215   {goat_pos : bank;
216    wolf_pos : bank;
217    cabbage_pos: bank;
218    boat_pos : bank}.
219
220 (* When you define a record named foo, the system automatically defines a record 
221 constructor named mk_foo. To construct a new record you pass as arguments to 
222 mk_foo the values of the record fields *)
223
224 definition start ≝ mk_state east east east east.
225 definition end ≝ mk_state west west west west.
226
227 (* We must now define the possible moves. A natural way to do it is in the form 
228 of a relation (a binary predicate) over states. *)
229
230 inductive move : state → state → Prop ≝
231 | move_goat: ∀g,g1,w,c. opp g g1 → move (mk_state g w c g) (mk_state g1 w c g1)
232   (* We can move the goat from a bank g to the opposite bank g1 if and only if the
233      boat is on the same bank g of the goat and we move the boat along with it. *)
234 | move_wolf: ∀g,w,w1,c. opp w w1 → move (mk_state g w c w) (mk_state g w1 c w1)
235 | move_cabbage: ∀g,w,c,c1.opp c c1 → move (mk_state g w c c) (mk_state g w c1 c1)
236 | move_boat: ∀g,w,c,b,b1. opp b b1 → move (mk_state g w c b) (mk_state g w c b1).
237
238 (* A state is safe if either the goat is on the same bank of the boat, or both 
239 the wolf and the cabbage are on the opposite bank of the goat. *)
240
241 inductive safe_state : state → Prop ≝
242 | with_boat : ∀g,w,c.safe_state (mk_state g w c g)
243 | opposite_side : ∀g,g1,b.opp g g1 → safe_state (mk_state g g1 g1 b).
244
245 (* Finally, a state y is reachable from x if either there is a single move 
246 leading from x to y, or there is a safe state z such that z is reachable from x 
247 and there is a move leading from z to y *)
248
249 inductive reachable : state → state → Prop ≝
250 | one : ∀x,y.move x y → reachable x y
251 | more : ∀x,z,y. \ 5span style="text-decoration: underline;"\ 6\ 5/span\ 6reachable x z → safe_state z → \ 5span style="text-decoration: underline;"\ 6\ 5/span\ 6move z y → reachable x y.
252
253 (* 
254 \ 5h2 class="section"\ 6Automation\ 5/h2\ 6
255 Remarkably, Matita is now able to solve the problem by itslef, provided
256 you allow automation to exploit more resources. The command /n/ is similar to
257 //, where n is a measure of this complexity: in particular it is a bound to
258 the depth of the expected proof tree (more precisely, to the number of nested
259 applicative nodes). In this case, there is a solution in six moves, and we
260 need a few more applications to handle reachability, and side conditions. 
261 The magic number to let automation work is, in this case, 9.  *)
262
263 lemma problem: reachable start end.
264 normalize /\ 5span class="autotactic"\ 69\ 5span class="autotrace"\ 6 trace one, more, with_boat, opposite_side, move_goat, move_wolf, move_cabbage, move_boat, east_west, west_east\ 5/span\ 6\ 5/span\ 6/ qed. 
265
266 (* 
267 \ 5h2 class="section"\ 6Application\ 5/h2\ 6
268 Let us now try to derive the proof in a more interactive way. Of course, we
269 expect to need several moves to transfer all items from a bank to the other, so 
270 we should start our proof by applying "more". Matita syntax for invoking the 
271 application of a property named foo is to write "@foo". In general, the philosophy 
272 of Matita is to describe each proof of a property P as a structured collection of 
273 objects involved in the proof, prefixed by simple modalities (#,<,@,...) explaining 
274 the way it is actually used (e.g. for introduction, rewriting, in an applicative 
275 step, and so on).
276 *)
277
278 lemma problem1: reachable start end.
279 normalize @more
280
281 (* 
282 \ 5h2 class="section"\ 6Focusing\ 5/h2\ 6
283 After performing the previous application, we have four open subgoals:
284
285   X : STATE
286   Y : reachable [east,east,east,east] X
287   W : safe_state X
288   Z : move X [west,west,west,west]
289  
290 That is, we must guess a state X, such that this is reachable from start, it is 
291 safe, and there is a move leading from X to end. All goals are active, that is
292 emphasized by the fact that they are all red. Any command typed by the user is
293 normally applied in parallel to all active goals, but clearly we must proceed 
294 here is a different way for each of them. The way to do it, is by structuring
295 the script using the following syntax: [...|... |...|...] where we typically have
296 as many cells inside the brackets as the number of the active subgoals. The
297 interesting point is that we can associate with the three symbol "[", "|" and
298 "]" a small-step semantics that allow to execute them individually. In particular
299
300 - the operator "[" opens a new focusing section for the currently active goals,
301   and focus on the first of them
302 - the operator "|" shift the focus to the next goal
303 - the operator "]" close the focusing section, falling back to the previous level
304   and adding to it all remaining goals not yet closed
305
306 Let us see the effect of the "[" on our proof:
307 *)
308
309   [  
310
311 (* As you see, only the first goal has now the focus on. Moreover, all goals got
312 a progressive numerical label, to help designating them, if needed. 
313 We can now proceed in several possible ways. The most straightforward way is to 
314 provide the intermediate state, that is [east,west,west,east]. We can do it, by 
315 just applying this term. *)
316
317    @(mk_state east west west east) 
318
319 (* This application closes the goal; at present, no goal has the focus on.
320 In order to act on the next goal, we must focus on it using the "|" operator. In
321 this case, we would like to skip the next goal, and focus on the trivial third 
322 subgoal: a simple way to do it, is by retyping "|". The proof that 
323 [east,west,west,east] is safe is trivial and can be done with //.*)
324
325   || //
326
327 (*
328 We then advance to the next goal, namely the fact that there is a move from 
329 [east,west,west,east] to [west,west,west,west]; this is trivial too, but it 
330 requires /2/ since move_goat opens an additional subgoal. By applying "]" we
331 refocus on the skipped goal, going back to a situation similar to the one we
332 started with. *)
333
334   | /\ 5span class="autotactic"\ 62\ 5span class="autotrace"\ 6 trace move_goat, east_west\ 5/span\ 6\ 5/span\ 6/ ] 
335
336 (* 
337 \ 5h2 class="section"\ 6Implicit arguments\ 5/h2\ 6
338 Let us perform the next step, namely moving back the boat, in a sligtly 
339 different way. The more operation expects as second argument the new 
340 intermediate state, hence instead of applying more we can apply this term
341 already instatated on the next intermediate state. As first argument, we
342 type a question mark that stands for an implicit argument to be guessed by
343 the system. *)
344
345 @(more ? (mk_state east west west west))
346
347 (* We now get three independent subgoals, all actives, and two of them are 
348 trivial. We\ 5span style="font-family: Verdana,sans-serif;"\ 6 \ 5/span\ 6can just apply automation to all of them, and it will close the two
349 trivial goals. *)
350
351 /\ 5span class="autotactic"\ 62\ 5span class="autotrace"\ 6 trace opposite_side, move_boat, east_west, west_east\ 5/span\ 6\ 5/span\ 6/
352
353 (* Let us come to the next step, that consists in moving the wolf. Suppose that 
354 instead of specifying the next intermediate state, we prefer to specify the next 
355 move. In the spirit of the previous example, we can do it in the following way 
356 *)
357
358 @(more … (move_wolf … ))
359
360 (* The dots stand here for an arbitrary number of implicit arguments, to be 
361 guessed by the system. 
362 Unfortunately, the previous move is not enough to fully instantiate the new 
363 intermediate state: a bank B remains unknown. Automation cannot help here,
364 since all goals depend from this bank and automation refuses to close some
365 subgoals instantiating other subgoals remaining open (the instantiation could
366 be arbitrary). The simplest way to proceed is to focus on the bank, that is
367 the fourth subgoal, and explicitly instatiate it. Instead of repeatedly using "|",
368 we can perform focusing by typing "4:" as described by the following command. *)
369
370 [4: @east] /\ 5span class="autotactic"\ 62\ 5span class="autotrace"\ 6 trace with_boat, east_west\ 5/span\ 6\ 5/span\ 6/
371
372 (* Alternatively, we can directly instantiate the bank into the move. Let
373 us complete the proof in this, very readable way. *)
374
375 @(more … (move_goat west … )) /\ 5span class="autotactic"\ 62\ 5span class="autotrace"\ 6 trace with_boat, west_east\ 5/span\ 6\ 5/span\ 6/
376 @(more … (move_cabbage ?? east … )) /\ 5span class="autotactic"\ 62\ 5span class="autotrace"\ 6 trace opposite_side, east_west, west_east\ 5/span\ 6\ 5/span\ 6/
377 @(more … (move_boat ??? west … )) /\ 5span class="autotactic"\ 62\ 5span class="autotrace"\ 6 trace with_boat, west_east\ 5/span\ 6\ 5/span\ 6/
378 @one /\ 5span class="autotactic"\ 62\ 5span class="autotrace"\ 6 trace move_goat, east_west\ 5/span\ 6\ 5/span\ 6/ qed.