]> matita.cs.unibo.it Git - helm.git/blobdiff - weblib/tutorial/chapter1.ma
commit by user ricciott
[helm.git] / weblib / tutorial / chapter1.ma
index 6598df5c14a13dede5438c154a5f2b398e853a7f..ef764ceae2aa5bff3b8e1375c6a9c84290d498c4 100644 (file)
@@ -1,4 +1,5 @@
-(*
+(* 
+\ 5h1\ 6Matita Interactive Tutorial\ 5/h1\ 6
 This is an interactive tutorial. To let you interact on line with the system, 
 you must first of all register yourself.
 
@@ -15,15 +16,20 @@ a file. The play button is meant to process the script up to a position
 previously selected by the user; the bottom button execute the whole script. 
 That's it: we are\ 5span style="font-family: Verdana,sans-serif;"\ 6 \ 5/span\ 6now ready to start.
 
-The first thing to say is that in a system like Matita's very few things are 
-built-in: not even booleans or logical connectives. The main philosophy of the 
-system is to let you define your own data-types and functions using a powerful 
-computational mechanism based on the declaration of inductive types. 
+\ 5h2 class="section"\ 6Data types, functions and theorems\ 5/h2\ 6
+Matita is both a programming language and a theorem proving environment:
+you define datatypes and programs, and then prove properties on them.
+Very few things are built-in: not even booleans or logical connectives
+(but you may of course use libraries, as in normal programming languages). 
+The main philosophy of the system is to let you define your own data-types 
+and functions using a powerful computational mechanism based on the 
+declaration of inductive types. 
 
 Let us start this tutorial with a simple example based on the following well 
 known problem.
 
-\ 5h2 class="section"\ 6The goat, the wolf and the cabbage\ 5/h2\ 6A farmer need to transfer a goat, a wolf and a cabbage across a river, but there
+\ 5b\ 6The goat, the wolf and the cabbage\ 5/b\ 6
+A farmer need to transfer a goat, a wolf and a cabbage across a river, but there
 is only one place available on his boat. Furthermore, the goat will eat the 
 cabbage if they are left alone on the same bank, and similarly the wolf will eat
 the goat. The problem consists in bringing all three items safely across the 
@@ -47,17 +53,19 @@ opposite one. *)
 
 definition opposite ≝ λs.
 match s with
-  [ east ⇒ \ 5a href="cic:/matita/tutorial/chapter1/bank.con(0,2,0)"\ 6west\ 5/a\ 6
-  | west ⇒ \ 5a href="cic:/matita/tutorial/chapter1/bank.con(0,1,0)"\ 6east\ 5/a\ 6
+  [ east ⇒ west
+  | west ⇒ east
   ].
 
 (* Functions are live entities, and can be actually computed. To check this, let
 us state the property that the opposite bank of east is west; every lemma needs a 
 name for further reference, and we call it "east_to_west". *)
  
-lemma east_to_west : \ 5a href="cic:/matita/tutorial/chapter1/opposite.def(1)"\ 6opposite\ 5/a\ 6 \ 5a href="cic:/matita/tutorial/chapter1/bank.con(0,1,0)"\ 6east\ 5/a\ 6 \ 5a title="leibnitz's equality" href="cic:/fakeuri.def(1)"\ 6=\ 5/a\ 6 \ 5a href="cic:/matita/tutorial/chapter1/bank.con(0,2,0)"\ 6west\ 5/a\ 6.
+lemma east_to_west : opposite east = west.
 
-(* If you stop the execution here you will see a new window on the  right side
+(* 
+\ 5h2 class="section"\ 6The goal window\ 5/h2\ 6
+If you stop the execution here you will see a new window on the  right side
 of the screen: it is the goal window, providing a sequent like representation of
 the form
 
@@ -94,13 +102,14 @@ lemma performing some book-keeping operations.
 In this case, we avoid the unnecessary simplification step: // will take care of 
 it. *) 
 
-lemma west_to_east : \ 5a href="cic:/matita/tutorial/chapter1/opposite.def(1)"\ 6opposite\ 5/a\ 6 \ 5a href="cic:/matita/tutorial/chapter1/bank.con(0,2,0)"\ 6west\ 5/a\ 6 \ 5a title="leibnitz's equality" href="cic:/fakeuri.def(1)"\ 6=\ 5/a\ 6 \ 5a href="cic:/matita/tutorial/chapter1/bank.con(0,1,0)"\ 6east\ 5/a\ 6.
+lemma west_to_east : opposite west = east.
 // qed.
 
-(* A slightly more complex problem consists in proving that opposite is 
-idempotent *)
+(*
+\ 5h2 class="section"\ 6Introduction\ 5/h2\ 6
+A slightly more complex problem consists in proving that opposite is idempotent *)
 
-lemma idempotent_opposite : ∀x. \ 5a href="cic:/matita/tutorial/chapter1/opposite.def(1)"\ 6opposite\ 5/a\ 6 (\ 5a href="cic:/matita/tutorial/chapter1/opposite.def(1)"\ 6opposite\ 5/a\ 6 x) \ 5a title="leibnitz's equality" href="cic:/fakeuri.def(1)"\ 6=\ 5/a\ 6 x.
+lemma idempotent_opposite : ∀x. opposite (opposite x) = x.
 
 (* we start the proof moving x from the conclusion into the context, that is a 
 (backward) introduction step. Matita syntax for an introduction step is simply 
@@ -113,7 +122,10 @@ wish to rename x into b (since it is a bank), we just type #b. *)
 (* See the effect of the execution in the goal window on the right: b has been 
 added to the context (replacing x in the conclusion); moreover its implicit type 
 "bank" has been made explicit. 
+*)
 
+(*
+\ 5h2 class="section"\ 6Case analysis\ 5/h2\ 6
 But how are we supposed to proceed, now? Simplification cannot help us, since b
 is a variable: just try to call normalize and you will see that it has no effect.
 The point is that we must proceed by cases according to the possible values of b,
@@ -134,27 +146,30 @@ them in turn, in a way that will be described at the end of this section.
 
 // qed.
 
-(* Instead of working with functions, it is sometimes convenient to work with
+(* 
+\ 5h2 class="section"\ 6Predicates\ 5/h2\ 6
+Instead of working with functions, it is sometimes convenient to work with
 predicates. For instance, instead of defining a function computing the opposite 
 bank, we could declare a predicate stating when two banks are opposite to each 
 other. Only two cases are possible, leading naturally to the following 
 definition:
 *)
 
-inductive opp : \ 5a href="cic:/matita/tutorial/chapter1/bank.ind(1,0,0)"\ 6bank\ 5/a\ 6 → \ 5a href="cic:/matita/tutorial/chapter1/bank.ind(1,0,0)"\ 6bank\ 5/a\ 6 → Prop ≝ 
-| east_west : opp \ 5a href="cic:/matita/tutorial/chapter1/bank.con(0,1,0)"\ 6east\ 5/a\ 6 \ 5a href="cic:/matita/tutorial/chapter1/bank.con(0,2,0)"\ 6west\ 5/a\ 6
-| west_east : opp \ 5a href="cic:/matita/tutorial/chapter1/bank.con(0,2,0)"\ 6west\ 5/a\ 6 \ 5a href="cic:/matita/tutorial/chapter1/bank.con(0,1,0)"\ 6east\ 5/a\ 6.
+inductive opp : bank → bank → Prop ≝ 
+| east_west : opp east west
+| west_east : opp west east.
 
 (* In precisely the same way as "bank" is the smallest type containing east and
 west, opp is the smallest predicate containing the two sub-cases east_west and
 weast_east. If you have some familiarity with Prolog, you may look at opp as the
-predicate definined by the two clauses - in this case, the two facts -
+predicate defined by the two clauses - in this case, the two facts - ast_west and
+west_east.
 
 Between opp and opposite we have the following relation:
     opp a b iff a = opposite b
 Let us prove it, starting from the left to right implication, first *)
 
-lemma opp_to_opposite: ∀a,b. \ 5a href="cic:/matita/tutorial/chapter1/opp.ind(1,0,0)"\ 6opp\ 5/a\ 6 a b → a \ 5a title="leibnitz's equality" href="cic:/fakeuri.def(1)"\ 6=\ 5/a\ 6 \ 5a href="cic:/matita/tutorial/chapter1/opposite.def(1)"\ 6opposite\ 5/a\ 6 b.
+lemma opp_to_opposite: ∀a,b. opp a b → a = opposite b.
  
 (* We start the proof introducing a, b and the hypothesis opp a b, that we
 call oppab. *)
@@ -167,9 +182,11 @@ automation *)
 
 cases oppab // qed.
 
-(* Let us come to the opposite direction. *)
+(* 
+\ 5h2 class="section"\ 6Rewriting\ 5/h2\ 6
+Let us come to the opposite direction. *)
 
-lemma opposite_to_opp: ∀a,b. a \ 5a title="leibnitz's equality" href="cic:/fakeuri.def(1)"\ 6=\ 5/a\ 6 \ 5a href="cic:/matita/tutorial/chapter1/opposite.def(1)"\ 6opposite\ 5/a\ 6 b → \ 5a href="cic:/matita/tutorial/chapter1/opp.ind(1,0,0)"\ 6opp\ 5/a\ 6 a b.
+lemma opposite_to_opp: ∀a,b. a = opposite b → opp a b.
 
 (* As usual, we start introducing a, b and the hypothesis (a = opposite b), 
 that we call eqa. *)
@@ -187,55 +204,55 @@ opposite b into a, we would have typed "<eqa". *)
 cases b // qed.
 
 (*
+\ 5h2 class="section"\ 6Records\ 5/h2\ 6
 It is time to proceed with our formalization of the farmer's problem. 
-A state of the system is defined by the position of four item: the goat, the 
+A state of the system is defined by the position of four items: the goat, the 
 wolf, the cabbage, and the boat. The simplest way to declare such a data type
 is to use a record.
 *)
 
 record state : Type[0] ≝
-  {goat_pos : \ 5a href="cic:/matita/tutorial/chapter1/bank.ind(1,0,0)"\ 6bank\ 5/a\ 6;
-   wolf_pos : \ 5a href="cic:/matita/tutorial/chapter1/bank.ind(1,0,0)"\ 6bank\ 5/a\ 6;
-   cabbage_pos: \ 5a href="cic:/matita/tutorial/chapter1/bank.ind(1,0,0)"\ 6bank\ 5/a\ 6;
-   boat_pos : \ 5a href="cic:/matita/tutorial/chapter1/bank.ind(1,0,0)"\ 6bank\ 5/a\ 6}.
+  {goat_pos : bank;
+   wolf_pos : bank;
+   cabbage_pos: bank;
+   boat_pos : bank}.
 
 (* When you define a record named foo, the system automatically defines a record 
 constructor named mk_foo. To construct a new record you pass as arguments to 
 mk_foo the values of the record fields *)
 
-definition start ≝ \ 5a href="cic:/matita/tutorial/chapter1/state.con(0,1,0)"\ 6mk_state\ 5/a\ 6 \ 5a href="cic:/matita/tutorial/chapter1/bank.con(0,1,0)"\ 6east\ 5/a\ 6 \ 5a href="cic:/matita/tutorial/chapter1/bank.con(0,1,0)"\ 6east\ 5/a\ 6 \ 5a href="cic:/matita/tutorial/chapter1/bank.con(0,1,0)"\ 6east\ 5/a\ 6 \ 5a href="cic:/matita/tutorial/chapter1/bank.con(0,1,0)"\ 6east\ 5/a\ 6.
-definition end ≝ \ 5a href="cic:/matita/tutorial/chapter1/state.con(0,1,0)"\ 6mk_state\ 5/a\ 6 \ 5a href="cic:/matita/tutorial/chapter1/bank.con(0,2,0)"\ 6west\ 5/a\ 6 \ 5a href="cic:/matita/tutorial/chapter1/bank.con(0,2,0)"\ 6west\ 5/a\ 6 \ 5a href="cic:/matita/tutorial/chapter1/bank.con(0,2,0)"\ 6west\ 5/a\ 6 \ 5a href="cic:/matita/tutorial/chapter1/bank.con(0,2,0)"\ 6west\ 5/a\ 6.
+definition start ≝ mk_state east east east east.
+definition end ≝ mk_state west west west west.
 
 (* We must now define the possible moves. A natural way to do it is in the form 
 of a relation (a binary predicate) over states. *)
 
-inductive move : \ 5a href="cic:/matita/tutorial/chapter1/state.ind(1,0,0)"\ 6state\ 5/a\ 6 → \ 5a href="cic:/matita/tutorial/chapter1/state.ind(1,0,0)"\ 6state\ 5/a\ 6 → Prop ≝
-| move_goat: ∀g,g1,w,c. \ 5a href="cic:/matita/tutorial/chapter1/opp.ind(1,0,0)"\ 6opp\ 5/a\ 6 g g1 → move (\ 5a href="cic:/matita/tutorial/chapter1/state.con(0,1,0)"\ 6mk_state\ 5/a\ 6 g w c g) (\ 5a href="cic:/matita/tutorial/chapter1/state.con(0,1,0)"\ 6mk_state\ 5/a\ 6 g1 w c g1)
-         (* Every time g and g1 are two opposite banks, it is legal to put
-                the state "\ 5a href="cic:/matita/tutorial/chapter1/state.con(0,1,0)"\ 6mk_state\ 5/a\ 6 g w c g", which says that goat and boat are on the same bank g,
-            and the state "\ 5a href="cic:/matita/tutorial/chapter1/state.con(0,1,0)"\ 6mk_state\ 5/a\ 6 g1 w c g1", which says that goat and boat are on the same bank g1
-            in the relation "move" because, for example, moving the goat from bank g to bank g1 requires
-            moving the boat as well. *) 
-| move_wolf: ∀g,w,w1,c. \ 5a href="cic:/matita/tutorial/chapter1/opp.ind(1,0,0)"\ 6opp\ 5/a\ 6 w w1 → move (\ 5a href="cic:/matita/tutorial/chapter1/state.con(0,1,0)"\ 6mk_state\ 5/a\ 6 g w c w) (\ 5a href="cic:/matita/tutorial/chapter1/state.con(0,1,0)"\ 6mk_state\ 5/a\ 6 g w1 c w1)
-| move_cabbage: ∀g,w,c,c1.\ 5a href="cic:/matita/tutorial/chapter1/opp.ind(1,0,0)"\ 6opp\ 5/a\ 6 c c1 → move (\ 5a href="cic:/matita/tutorial/chapter1/state.con(0,1,0)"\ 6mk_state\ 5/a\ 6 g w c c) (\ 5a href="cic:/matita/tutorial/chapter1/state.con(0,1,0)"\ 6mk_state\ 5/a\ 6 g w c1 c1)
-| move_boat: ∀g,w,c,b,b1. \ 5a href="cic:/matita/tutorial/chapter1/opp.ind(1,0,0)"\ 6opp\ 5/a\ 6 b b1 → move (\ 5a href="cic:/matita/tutorial/chapter1/state.con(0,1,0)"\ 6mk_state\ 5/a\ 6 g w c b) (\ 5a href="cic:/matita/tutorial/chapter1/state.con(0,1,0)"\ 6mk_state\ 5/a\ 6 g w c b1).
+inductive move : state → state → Prop ≝
+| move_goat: ∀g,g1,w,c. opp g g1 → move (mk_state g w c g) (mk_state g1 w c g1)
+  (* We can move the goat from a bank g to the opposite bank g1 if and only if the
+     boat is on the same bank g of the goat and we move the boat along with it. *)
+| move_wolf: ∀g,w,w1,c. opp w w1 → move (mk_state g w c w) (mk_state g w1 c w1)
+| move_cabbage: ∀g,w,c,c1.opp c c1 → move (mk_state g w c c) (mk_state g w c1 c1)
+| move_boat: ∀g,w,c,b,b1. opp b b1 → move (mk_state g w c b) (mk_state g w c b1).
 
 (* A state is safe if either the goat is on the same bank of the boat, or both 
 the wolf and the cabbage are on the opposite bank of the goat. *)
 
-inductive safe_state : \ 5a href="cic:/matita/tutorial/chapter1/state.ind(1,0,0)"\ 6state\ 5/a\ 6 → Prop ≝
-| with_boat : ∀g,w,c.safe_state (\ 5a href="cic:/matita/tutorial/chapter1/state.con(0,1,0)"\ 6mk_state\ 5/a\ 6 g w c g)
-| opposite_side : ∀g,g1,b.\ 5a href="cic:/matita/tutorial/chapter1/opp.ind(1,0,0)"\ 6opp\ 5/a\ 6 g g1 → safe_state (\ 5a href="cic:/matita/tutorial/chapter1/state.con(0,1,0)"\ 6mk_state\ 5/a\ 6 g g1 g1 b).
+inductive safe_state : state → Prop ≝
+| with_boat : ∀g,w,c.safe_state (mk_state g w c g)
+| opposite_side : ∀g,g1,b.opp g g1 → safe_state (mk_state g g1 g1 b).
 
 (* Finally, a state y is reachable from x if either there is a single move 
 leading from x to y, or there is a safe state z such that z is reachable from x 
 and there is a move leading from z to y *)
 
-inductive reachable : \ 5a href="cic:/matita/tutorial/chapter1/state.ind(1,0,0)"\ 6state\ 5/a\ 6 → \ 5a href="cic:/matita/tutorial/chapter1/state.ind(1,0,0)"\ 6state\ 5/a\ 6 → Prop ≝
-| one : ∀x,y.\ 5a href="cic:/matita/tutorial/chapter1/move.ind(1,0,0)"\ 6move\ 5/a\ 6 x y → reachable x y
-| more : ∀x,z,y. \ 5span style="text-decoration: underline;"\ 6\ 5/span\ 6reachable x z → \ 5a href="cic:/matita/tutorial/chapter1/safe_state.ind(1,0,0)"\ 6safe_state\ 5/a\ 6 z → \ 5span style="text-decoration: underline;"\ 6\ 5/span\ 6\ 5a href="cic:/matita/tutorial/chapter1/move.ind(1,0,0)"\ 6move\ 5/a\ 6 z y → reachable x y.
+inductive reachable : state → state → Prop ≝
+| one : ∀x,y.move x y → reachable x y
+| 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.
 
-(* Remarkably, Matita is now able to solve the problem by itslef, provided
+(* 
+\ 5h2 class="section"\ 6Automation\ 5/h2\ 6
+Remarkably, Matita is now able to solve the problem by itslef, provided
 you allow automation to exploit more resources. The command /n/ is similar to
 //, where n is a measure of this complexity: in particular it is a bound to
 the depth of the expected proof tree (more precisely, to the number of nested
@@ -243,18 +260,27 @@ applicative nodes). In this case, there is a solution in six moves, and we
 need a few more applications to handle reachability, and side conditions. 
 The magic number to let automation work is, in this case, 9.  *)
 
-lemma problem: \ 5a href="cic:/matita/tutorial/chapter1/reachable.ind(1,0,0)"\ 6reachable\ 5/a\ 6 \ 5a href="cic:/matita/tutorial/chapter1/start.def(1)"\ 6start\ 5/a\ 6 \ 5a href="cic:/matita/tutorial/chapter1/end.def(1)"\ 6end\ 5/a\ 6.
-normalize /9/ qed. 
+lemma problem: reachable start end.
+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. 
 
-(* Let us now try to derive the proof in a more interactive way. Of course, we
+(* 
+\ 5h2 class="section"\ 6Application\ 5/h2\ 6
+Let us now try to derive the proof in a more interactive way. Of course, we
 expect to need several moves to transfer all items from a bank to the other, so 
-we should start our proof by applying "more".
+we should start our proof by applying "more". Matita syntax for invoking the 
+application of a property named foo is to write "@foo". In general, the philosophy 
+of Matita is to describe each proof of a property P as a structured collection of 
+objects involved in the proof, prefixed by simple modalities (#,<,@,...) explaining 
+the way it is actually used (e.g. for introduction, rewriting, in an applicative 
+step, and so on).
 *)
 
-lemma problem1: \ 5a href="cic:/matita/tutorial/chapter1/reachable.ind(1,0,0)"\ 6reachable\ 5/a\ 6 \ 5a href="cic:/matita/tutorial/chapter1/start.def(1)"\ 6start\ 5/a\ 6 \ 5a href="cic:/matita/tutorial/chapter1/end.def(1)"\ 6end\ 5/a\ 6.
-normalize @\ 5a href="cic:/matita/tutorial/chapter1/reachable.con(0,2,0)"\ 6more\ 5/a\ 6
+lemma problem1: reachable start end.
+normalize @more
 
-(* We have now four open subgoals:
+(* 
+\ 5h2 class="section"\ 6Focusing\ 5/h2\ 6
+After performing the previous application, we have four open subgoals:
 
   X : STATE
   Y : reachable [east,east,east,east] X
@@ -288,7 +314,7 @@ We can now proceed in several possible ways. The most straightforward way is to
 provide the intermediate state, that is [east,west,west,east]. We can do it, by 
 just applying this term. *)
 
-   @(\ 5a href="cic:/matita/tutorial/chapter1/state.con(0,1,0)"\ 6mk_state\ 5/a\ 6 \ 5a href="cic:/matita/tutorial/chapter1/bank.con(0,1,0)"\ 6east\ 5/a\ 6 \ 5a href="cic:/matita/tutorial/chapter1/bank.con(0,2,0)"\ 6west\ 5/a\ 6 \ 5a href="cic:/matita/tutorial/chapter1/bank.con(0,2,0)"\ 6west\ 5/a\ 6 \ 5a href="cic:/matita/tutorial/chapter1/bank.con(0,1,0)"\ 6east\ 5/a\ 6
+   @(mk_state east west west east
 
 (* This application closes the goal; at present, no goal has the focus on.
 In order to act on the next goal, we must focus on it using the "|" operator. In
@@ -305,29 +331,31 @@ requires /2/ since move_goat opens an additional subgoal. By applying "]" we
 refocus on the skipped goal, going back to a situation similar to the one we
 started with. *)
 
-  | /2/ ] 
+  | /\ 5span class="autotactic"\ 62\ 5span class="autotrace"\ 6 trace move_goat, east_west\ 5/span\ 6\ 5/span\ 6/ ] 
 
-(* Let us perform the next step, namely moving back the boat, in a sligtly 
+(* 
+\ 5h2 class="section"\ 6Implicit arguments\ 5/h2\ 6
+Let us perform the next step, namely moving back the boat, in a sligtly 
 different way. The more operation expects as second argument the new 
 intermediate state, hence instead of applying more we can apply this term
 already instatated on the next intermediate state. As first argument, we
 type a question mark that stands for an implicit argument to be guessed by
 the system. *)
 
-@(\ 5a href="cic:/matita/tutorial/chapter1/reachable.con(0,2,0)"\ 6more\ 5/a\ 6 ? (\ 5a href="cic:/matita/tutorial/chapter1/state.con(0,1,0)"\ 6mk_state\ 5/a\ 6 \ 5a href="cic:/matita/tutorial/chapter1/bank.con(0,1,0)"\ 6east\ 5/a\ 6 \ 5a href="cic:/matita/tutorial/chapter1/bank.con(0,2,0)"\ 6west\ 5/a\ 6 \ 5a href="cic:/matita/tutorial/chapter1/bank.con(0,2,0)"\ 6west\ 5/a\ 6 \ 5a href="cic:/matita/tutorial/chapter1/bank.con(0,2,0)"\ 6west\ 5/a\ 6))
+@(more ? (mk_state east west west west))
 
 (* We now get three independent subgoals, all actives, and two of them are 
 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
 trivial goals. *)
 
-/2/
+/\ 5span class="autotactic"\ 62\ 5span class="autotrace"\ 6 trace opposite_side, move_boat, east_west, west_east\ 5/span\ 6\ 5/span\ 6/
 
 (* Let us come to the next step, that consists in moving the wolf. Suppose that 
 instead of specifying the next intermediate state, we prefer to specify the next 
 move. In the spirit of the previous example, we can do it in the following way 
 *)
 
-@(\ 5a href="cic:/matita/tutorial/chapter1/reachable.con(0,2,0)"\ 6more\ 5/a\ 6 … (\ 5a href="cic:/matita/tutorial/chapter1/move.con(0,2,0)"\ 6move_wolf\ 5/a\ 6 … ))
+@(more … (move_wolf … ))
 
 (* The dots stand here for an arbitrary number of implicit arguments, to be 
 guessed by the system. 
@@ -339,12 +367,12 @@ be arbitrary). The simplest way to proceed is to focus on the bank, that is
 the fourth subgoal, and explicitly instatiate it. Instead of repeatedly using "|",
 we can perform focusing by typing "4:" as described by the following command. *)
 
-[4: @\ 5a href="cic:/matita/tutorial/chapter1/bank.con(0,1,0)"\ 6east\ 5/a\ 6] /2/
+[4: @east] /\ 5span class="autotactic"\ 62\ 5span class="autotrace"\ 6 trace with_boat, east_west\ 5/span\ 6\ 5/span\ 6/
 
 (* Alternatively, we can directly instantiate the bank into the move. Let
 us complete the proof in this, very readable way. *)
 
-@(\ 5a href="cic:/matita/tutorial/chapter1/reachable.con(0,2,0)"\ 6more\ 5/a\ 6 … (\ 5a href="cic:/matita/tutorial/chapter1/move.con(0,1,0)"\ 6move_goat\ 5/a\ 6 \ 5a href="cic:/matita/tutorial/chapter1/bank.con(0,2,0)"\ 6west\ 5/a\ 6 … )) /2/
-@(\ 5a href="cic:/matita/tutorial/chapter1/reachable.con(0,2,0)"\ 6more\ 5/a\ 6 … (\ 5a href="cic:/matita/tutorial/chapter1/move.con(0,3,0)"\ 6move_cabbage\ 5/a\ 6 ?? \ 5a href="cic:/matita/tutorial/chapter1/bank.con(0,1,0)"\ 6east\ 5/a\ 6 … )) /2/
-@(\ 5a href="cic:/matita/tutorial/chapter1/reachable.con(0,2,0)"\ 6more\ 5/a\ 6 … (\ 5a href="cic:/matita/tutorial/chapter1/move.con(0,4,0)"\ 6move_boat\ 5/a\ 6 ??? \ 5a href="cic:/matita/tutorial/chapter1/bank.con(0,2,0)"\ 6west\ 5/a\ 6 … )) /2/
-@\ 5a href="cic:/matita/tutorial/chapter1/reachable.con(0,1,0)"\ 6one\ 5/a\ 6 /2/ qed.
\ No newline at end of file
+@(more … (move_goat west … )) /\ 5span class="autotactic"\ 62\ 5span class="autotrace"\ 6 trace with_boat, west_east\ 5/span\ 6\ 5/span\ 6/
+@(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/
+@(more … (move_boat ??? west … )) /\ 5span class="autotactic"\ 62\ 5span class="autotrace"\ 6 trace with_boat, west_east\ 5/span\ 6\ 5/span\ 6/
+@one /\ 5span class="autotactic"\ 62\ 5span class="autotrace"\ 6 trace move_goat, east_west\ 5/span\ 6\ 5/span\ 6/ qed.
\ No newline at end of file