X-Git-Url: http://matita.cs.unibo.it/gitweb/?a=blobdiff_plain;f=weblib%2Ftutorial%2Fchapter1.ma;h=4cf145d60f53f72c70b08846444700cd9b1afc7e;hb=a82d87a4c2ff9f518385fba7357dafb632a22882;hp=c2523f38c803f8472106b853b6d6e4e1d4d0d565;hpb=3476afc7e71ac34beec061b94cf712e5ff85802f;p=helm.git diff --git a/weblib/tutorial/chapter1.ma b/weblib/tutorial/chapter1.ma index c2523f38c..4cf145d60 100644 --- a/weblib/tutorial/chapter1.ma +++ b/weblib/tutorial/chapter1.ma @@ -1,35 +1,57 @@ - -(* -In a system like Matita's very few things are built-in: not even booleans or -logical connectives. The main philosophy od 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. - -h2 class="section"The goat, the wolf and the cabbage/h2div class="paragraph"/divA farmer need to tranfer 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 item safely across the river. - -Our first data type defines the two banks of the river, which we will call east and -west. It is a simple example of enumerated type, defined by explicitly declaring all -its elements. The type itself is called "bank". -Before giving its definition we "include" the file "logic.ma" that contains a a few -preliminary notions not worth discussing here. +(* +h1Matita Interactive Tutorial/h1 +This is an interactive tutorial. To let you interact on line with the system, +you must first of all register yourself. + +Before starting, let us briefly explain the meaning of the menu buttons. +With the Advance and Retract buttons you respectively perform and undo single +computational steps. Each step consists in reading a user command, and processing +it. The part of the user input file (called script) already executed by the +system will be colored, and will not be editable any more. The advance bottom +will also automatically advance the focus of the window, but you can inspect the +whole file using the scroll bars, as usual. Comments are skipped. +Try to advance and retract a few steps, to get the feeling of the system. You can +also come back here by using the top button, that takes you at the beginning of +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 arespan style="font-family: Verdana,sans-serif;" /spannow ready to start. + +h2 class="section"Data types, functions and theorems/h2 +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. + +bThe goat, the wolf and the cabbage/b +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 +river. + +Our first data type defines the two banks of the river, which will be named east +and west. It is a simple example of enumerated type, defined by explicitly +declaring all its elements. The type itself is called "bank". +Before giving its definition we "include" the file "logic.ma" that contains a +few preliminary notions not worth discussing for the moment. *) include "basics/logic.ma". -inductive bank: Type[0] ≝ +img class="anchor" src="icons/tick.png" id="bank"inductive bank: Type[0] ≝ | east : bank | west : bank. -(* We can now define a simple function computing, for each bank of the river, -the opposite one. *) +(* We can now define a simple function computing, for each bank of the river, the +opposite one. *) -definition opposite ≝ λs. +img class="anchor" src="icons/tick.png" id="opposite"definition opposite ≝ λs. match s with [ east ⇒ a href="cic:/matita/tutorial/chapter1/bank.con(0,2,0)"west/a | west ⇒ a href="cic:/matita/tutorial/chapter1/bank.con(0,1,0)"east/a @@ -39,9 +61,11 @@ match s with 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 : a href="cic:/matita/tutorial/chapter1/opposite.def(1)"opposite/a a href="cic:/matita/tutorial/chapter1/bank.con(0,1,0)"east/a a title="leibnitz's equality" href="cic:/fakeuri.def(1)"=/a a href="cic:/matita/tutorial/chapter1/bank.con(0,2,0)"west/a. +img class="anchor" src="icons/tick.png" id="east_to_west"lemma east_to_west : a href="cic:/matita/tutorial/chapter1/opposite.def(1)"opposite/a a href="cic:/matita/tutorial/chapter1/bank.con(0,1,0)"east/a a title="leibnitz's equality" href="cic:/fakeuri.def(1)"=/a a href="cic:/matita/tutorial/chapter1/bank.con(0,2,0)"west/a. -(* If you stop the execution here you will see a new window on the right side +(* +h2 class="section"The goal window/h2 +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 @@ -69,170 +93,286 @@ You may use the retract bottom to undo the step, if you wish. The new goal west = west is trivial: it is just a consequence of reflexivity. Such trivial steps can be just closed in Matita by typing a double slash. We complete the proof by the qed command, that instructs the system to store the -lemma performing some bookkeeping operations. +lemma performing some book-keeping operations. *) // qed. -lemma west_to_east : change_side west = east. +(* In exactly the same way, we can prove that the opposite side of west is east. +In this case, we avoid the unnecessary simplification step: // will take care of +it. *) + +img class="anchor" src="icons/tick.png" id="west_to_east"lemma west_to_east : a href="cic:/matita/tutorial/chapter1/opposite.def(1)"opposite/a a href="cic:/matita/tutorial/chapter1/bank.con(0,2,0)"west/a a title="leibnitz's equality" href="cic:/fakeuri.def(1)"=/a a href="cic:/matita/tutorial/chapter1/bank.con(0,1,0)"east/a. // qed. -lemma change_twice : ∀x. change_side (change_side x) = x. -* // -qed. +(* +h2 class="section"Introduction/h2 +A slightly more complex problem consists in proving that opposite is idempotent *) -inductive item: Type[0] ≝ -| goat : item -| wolf : item -| cabbage: item -| boat : item. +img class="anchor" src="icons/tick.png" id="idempotent_opposite"lemma idempotent_opposite : ∀x. a href="cic:/matita/tutorial/chapter1/opposite.def(1)"opposite/a (a href="cic:/matita/tutorial/chapter1/opposite.def(1)"opposite/a x) a title="leibnitz's equality" href="cic:/fakeuri.def(1)"=/a x. -(* definition state ≝ item → side. *) +(* 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 +the sharp character followed by the name of the item to be moved into the +context. This also allows us to rename the item, if needed: for instance if we +wish to rename x into b (since it is a bank), we just type #b. *) -record state : Type[0] ≝ - {goat_pos : side; - wolf_pos : side; - cabbage_pos: side; - boat_pos : side}. +#b -definition state_of_item ≝ λs,i. -match i with -[ goat ⇒ goat_pos s -| wolf ⇒ wolf_pos s -| cabbage ⇒ cabbage_pos s -| boat ⇒ boat_pos s]. +(* 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. +*) (* -definition is_movable ≝ λs,i. - state_of_item s i = state_of_item s boat. - -record movable_item (s:state) : Type[0] ≝ - {elem : item; - mov : is_movable s elem}. *) - -definition start :state ≝ - mk_state east east east east. - -(* slow -inductive move : state → state → Type[0] ≝ -| move_goat: ∀g,w,c. - move (mk_state (change_side g) w c (change_side g)) (mk_state g w c g) -| move_wolf: ∀g,w,c. - move (mk_state g (change_side w) c (change_side w)) (mk_state g w c w) -| move_cabbage: ∀g,w,c. - move (mk_state g w (change_side c) (change_side c)) (mk_state g w c c) -| move_boat: ∀g,w,c,b. - move (mk_state g w c (change_side b)) (mk_state g w c b). +h2 class="section"Case analysis/h2 +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, +namely east and west. To this aim, you must invoke the cases command, followed by +the name of the hypothesis (more generally, an arbitrary expression) that must be +the object of the case analysis (in our case, b). +*) + +cases b + +(* Executing the previous command has the effect of opening two subgoals, +corresponding to the two cases b=east and b=west: you may switch from one to the +other by using the hyperlinks over the top of the goal window. +Both goals can be closed by trivial computations, so we may use // as usual. +If we had to treat each subgoal in a different way, we should focus on each of +them in turn, in a way that will be described at the end of this section. +*) + +// qed. + +(* +h2 class="section"Predicates/h2 +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: *) -(* this is working well *) -inductive move : state → state → Type[0] ≝ -| move_goat: ∀g,w,c. - move (mk_state g w c g) (mk_state (change_side g) w c (change_side g)) -| move_wolf: ∀g,w,c. - move (mk_state g w c w) (mk_state g (change_side w) c (change_side w)) -| move_cabbage: ∀g,w,c. - move (mk_state g w c c) (mk_state g w (change_side c) (change_side c)) -| move_boat: ∀g,w,c,b. - move (mk_state g w c b) (mk_state g w c (change_side b)). +img class="anchor" src="icons/tick.png" id="opp"inductive opp : a href="cic:/matita/tutorial/chapter1/bank.ind(1,0,0)"bank/a → a href="cic:/matita/tutorial/chapter1/bank.ind(1,0,0)"bank/a → Prop ≝ +| east_west : opp a href="cic:/matita/tutorial/chapter1/bank.con(0,1,0)"east/a a href="cic:/matita/tutorial/chapter1/bank.con(0,2,0)"west/a +| west_east : opp a href="cic:/matita/tutorial/chapter1/bank.con(0,2,0)"west/a a href="cic:/matita/tutorial/chapter1/bank.con(0,1,0)"east/a. +(* 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 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 *) + +img class="anchor" src="icons/tick.png" id="opp_to_opposite"lemma opp_to_opposite: ∀a,b. a href="cic:/matita/tutorial/chapter1/opp.ind(1,0,0)"opp/a a b → a a title="leibnitz's equality" href="cic:/fakeuri.def(1)"=/a a href="cic:/matita/tutorial/chapter1/opposite.def(1)"opposite/a b. -(* this is working -inductive move : state → state → Type[0] ≝ -| move_goat: ∀g,g1,w,c. change_side g = g1 → - move (mk_state g w c g) (mk_state g1 w c g1) -| move_wolf: ∀g,w,w1,c. change_side w = w1 → - move (mk_state g w c w) (mk_state g w1 c w1) -| move_cabbage: ∀g,w,c,c1. change_side c = c1 → - move (mk_state g w c c) (mk_state g w c1 c1) -| move_boat: ∀g,w,c,b,b1. change_side b = b1 → - move (mk_state g w c b) (mk_state g w c b1) -.*) +(* We start the proof introducing a, b and the hypothesis opp a b, that we +call oppab. *) +#a #b #oppab + +(* Now we proceed by cases on the possible proofs of (opp a b), that is on the +possible shapes of oppab. By definition, there are only two possibilities, +namely east_west or west_east. Both subcases are trivial, and can be closed by +automation *) + +cases oppab // qed. + +(* +h2 class="section"Rewriting/h2 +Let us come to the opposite direction. *) + +img class="anchor" src="icons/tick.png" id="opposite_to_opp"lemma opposite_to_opp: ∀a,b. a a title="leibnitz's equality" href="cic:/fakeuri.def(1)"=/a a href="cic:/matita/tutorial/chapter1/opposite.def(1)"opposite/a b → a href="cic:/matita/tutorial/chapter1/opp.ind(1,0,0)"opp/a a b. + +(* As usual, we start introducing a, b and the hypothesis (a = opposite b), +that we call eqa. *) + +#a #b #eqa + +(* The right way to proceed, now, is by rewriting a into (opposite b). We do +this by typing ">eqa". If we wished to rewrite in the opposite direction, namely +opposite b into a, we would have typed "eqa + +(* We conclude the proof by cases on b. *) + +cases b // qed. (* -inductive move : state →state → Type[0] ≝ -| move_goat: ∀s.∀h:is_movable s goat. move s (mk_state (change_side (goat_pos s)) (wolf_pos s) - (cabbage_pos s) (change_side (boat_pos s))) -| move_wolf: ∀s.∀h:is_movable s wolf. move s (mk_state (goat_pos s) (change_side (wolf_pos s)) - (cabbage_pos s) (change_side (boat_pos s))) -| move_cabbage: ∀s.∀h:is_movable s cabbage. move s (mk_state (goat_pos s) (wolf_pos s) - (change_side (cabbage_pos s)) (change_side (boat_pos s))) -| move_boat: ∀s.move s (mk_state (goat_pos s) (wolf_pos s) - (cabbage_pos s) (change_side (boat_pos s))). +h2 class="section"Records/h2 +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 items: the goat, the +wolf, the cabbage, and the boat. The simplest way to declare such a data type +is to use a record. *) -(* -definition legal_state ≝ λs. - goat_pos s = boat_pos s ∨ - (goat_pos s = change_side (cabbage_pos s) ∧ - goat_pos s = change_side (wolf_pos s)). *) - -inductive legal_state : state → Prop ≝ -| with_boat : ∀g,w,c.legal_state (mk_state g w c g) -| opposite_side : ∀g,b. - legal_state (mk_state g (change_side g) (change_side g) b). - -inductive reachable : state → state → Prop ≝ -| one : ∀s1,s2.move s1 s2 → reachable s1 s2 -| more : ∀s1,s2,s3. reachable s1 s2 → legal_state s2 → move s2 s3 → - reachable s1 s3. - -definition end ≝ mk_state west west west west. -definition second ≝ mk_state west east east west. -definition third ≝ mk_state west east east east. -definition fourth ≝ mk_state west west east west. -definition fifth ≝ mk_state east west east east. -definition sixth ≝ mk_state east west west west. -definition seventh ≝ mk_state east west west east. - -lemma problem: reachable start end. -normalize /8/ qed. - -lemma problem: reachable start end. -normalize -@more [4: @move_goat || 3: //] -@more [4: @move_boat || 3: //] -@more [4: @move_wolf || 3: //] -@more [4: @move_goat || 3: //] -@more [4: @move_cabbage || 3: //] -@more [4: @move_boat || 3: //] -@one // -qed. +img class="anchor" src="icons/tick.png" id="state"record state : Type[0] ≝ + {goat_pos : a href="cic:/matita/tutorial/chapter1/bank.ind(1,0,0)"bank/a; + wolf_pos : a href="cic:/matita/tutorial/chapter1/bank.ind(1,0,0)"bank/a; + cabbage_pos: a href="cic:/matita/tutorial/chapter1/bank.ind(1,0,0)"bank/a; + boat_pos : a href="cic:/matita/tutorial/chapter1/bank.ind(1,0,0)"bank/a}. + +(* 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 *) + +img class="anchor" src="icons/tick.png" id="start"definition start ≝ a href="cic:/matita/tutorial/chapter1/state.con(0,1,0)"mk_state/a a href="cic:/matita/tutorial/chapter1/bank.con(0,1,0)"east/a a href="cic:/matita/tutorial/chapter1/bank.con(0,1,0)"east/a a href="cic:/matita/tutorial/chapter1/bank.con(0,1,0)"east/a a href="cic:/matita/tutorial/chapter1/bank.con(0,1,0)"east/a. +img class="anchor" src="icons/tick.png" id="end"definition end ≝ a href="cic:/matita/tutorial/chapter1/state.con(0,1,0)"mk_state/a a href="cic:/matita/tutorial/chapter1/bank.con(0,2,0)"west/a a href="cic:/matita/tutorial/chapter1/bank.con(0,2,0)"west/a a href="cic:/matita/tutorial/chapter1/bank.con(0,2,0)"west/a a href="cic:/matita/tutorial/chapter1/bank.con(0,2,0)"west/a. + +(* 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. *) + +img class="anchor" src="icons/tick.png" id="move"inductive move : a href="cic:/matita/tutorial/chapter1/state.ind(1,0,0)"state/a → a href="cic:/matita/tutorial/chapter1/state.ind(1,0,0)"state/a → Prop ≝ +| move_goat: ∀g,g1,w,c. a href="cic:/matita/tutorial/chapter1/opp.ind(1,0,0)"opp/a g g1 → move (a href="cic:/matita/tutorial/chapter1/state.con(0,1,0)"mk_state/a g w c g) (a href="cic:/matita/tutorial/chapter1/state.con(0,1,0)"mk_state/a 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. a href="cic:/matita/tutorial/chapter1/opp.ind(1,0,0)"opp/a w w1 → move (a href="cic:/matita/tutorial/chapter1/state.con(0,1,0)"mk_state/a g w c w) (a href="cic:/matita/tutorial/chapter1/state.con(0,1,0)"mk_state/a g w1 c w1) +| move_cabbage: ∀g,w,c,c1.a href="cic:/matita/tutorial/chapter1/opp.ind(1,0,0)"opp/a c c1 → move (a href="cic:/matita/tutorial/chapter1/state.con(0,1,0)"mk_state/a g w c c) (a href="cic:/matita/tutorial/chapter1/state.con(0,1,0)"mk_state/a g w c1 c1) +| move_boat: ∀g,w,c,b,b1. a href="cic:/matita/tutorial/chapter1/opp.ind(1,0,0)"opp/a b b1 → move (a href="cic:/matita/tutorial/chapter1/state.con(0,1,0)"mk_state/a g w c b) (a href="cic:/matita/tutorial/chapter1/state.con(0,1,0)"mk_state/a 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. *) + +img class="anchor" src="icons/tick.png" id="safe_state"inductive safe_state : a href="cic:/matita/tutorial/chapter1/state.ind(1,0,0)"state/a → Prop ≝ +| with_boat : ∀g,w,c.safe_state (a href="cic:/matita/tutorial/chapter1/state.con(0,1,0)"mk_state/a g w c g) +| opposite_side : ∀g,g1,b.a href="cic:/matita/tutorial/chapter1/opp.ind(1,0,0)"opp/a g g1 → safe_state (a href="cic:/matita/tutorial/chapter1/state.con(0,1,0)"mk_state/a 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 *) + +img class="anchor" src="icons/tick.png" id="reachable"inductive reachable : a href="cic:/matita/tutorial/chapter1/state.ind(1,0,0)"state/a → a href="cic:/matita/tutorial/chapter1/state.ind(1,0,0)"state/a → Prop ≝ +| one : ∀x,y.a href="cic:/matita/tutorial/chapter1/move.ind(1,0,0)"move/a x y → reachable x y +| more : ∀x,z,y. span style="text-decoration: underline;"/spanreachable x z → a href="cic:/matita/tutorial/chapter1/safe_state.ind(1,0,0)"safe_state/a z → span style="text-decoration: underline;"/spana href="cic:/matita/tutorial/chapter1/move.ind(1,0,0)"move/a z y → reachable x y. + +(* +h2 class="section"Automation/h2 +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 +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. *) + +img class="anchor" src="icons/tick.png" id="problem"lemma problem: a href="cic:/matita/tutorial/chapter1/reachable.ind(1,0,0)"reachable/a a href="cic:/matita/tutorial/chapter1/start.def(1)"start/a a href="cic:/matita/tutorial/chapter1/end.def(1)"end/a. +normalize /span class="autotactic"9span class="autotrace" trace a href="cic:/matita/tutorial/chapter1/reachable.con(0,1,0)"one/a, a href="cic:/matita/tutorial/chapter1/reachable.con(0,2,0)"more/a, a href="cic:/matita/tutorial/chapter1/safe_state.con(0,1,0)"with_boat/a, a href="cic:/matita/tutorial/chapter1/safe_state.con(0,2,0)"opposite_side/a, a href="cic:/matita/tutorial/chapter1/move.con(0,1,0)"move_goat/a, a href="cic:/matita/tutorial/chapter1/move.con(0,2,0)"move_wolf/a, a href="cic:/matita/tutorial/chapter1/move.con(0,3,0)"move_cabbage/a, a href="cic:/matita/tutorial/chapter1/move.con(0,4,0)"move_boat/a, a href="cic:/matita/tutorial/chapter1/opp.con(0,1,0)"east_west/a, a href="cic:/matita/tutorial/chapter1/opp.con(0,2,0)"west_east/a/span/span/ qed. + +(* +h2 class="section"Application/h2 +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". 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). +*) + +img class="anchor" src="icons/tick.png" id="problem1"lemma problem1: a href="cic:/matita/tutorial/chapter1/reachable.ind(1,0,0)"reachable/a a href="cic:/matita/tutorial/chapter1/start.def(1)"start/a a href="cic:/matita/tutorial/chapter1/end.def(1)"end/a. +normalize @a href="cic:/matita/tutorial/chapter1/reachable.con(0,2,0)"more/a + +(* +h2 class="section"Focusing/h2 +After performing the previous application, we have four open subgoals: + + X : STATE + Y : reachable [east,east,east,east] X + W : safe_state X + Z : move X [west,west,west,west] + +That is, we must guess a state X, such that this is reachable from start, it is +safe, and there is a move leading from X to end. All goals are active, that is +emphasized by the fact that they are all red. Any command typed by the user is +normally applied in parallel to all active goals, but clearly we must proceed +here is a different way for each of them. The way to do it, is by structuring +the script using the following syntax: [...|... |...|...] where we typically have +as many cells inside the brackets as the number of the active subgoals. The +interesting point is that we can associate with the three symbol "[", "|" and +"]" a small-step semantics that allow to execute them individually. In particular + +- the operator "[" opens a new focusing section for the currently active goals, + and focus on the first of them +- the operator "|" shift the focus to the next goal +- the operator "]" close the focusing section, falling back to the previous level + and adding to it all remaining goals not yet closed + +Let us see the effect of the "[" on our proof: +*) + [ + +(* As you see, only the first goal has now the focus on. Moreover, all goals got +a progressive numerical label, to help designating them, if needed. +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. *) + + @(a href="cic:/matita/tutorial/chapter1/state.con(0,1,0)"mk_state/a a href="cic:/matita/tutorial/chapter1/bank.con(0,1,0)"east/a a href="cic:/matita/tutorial/chapter1/bank.con(0,2,0)"west/a a href="cic:/matita/tutorial/chapter1/bank.con(0,2,0)"west/a a href="cic:/matita/tutorial/chapter1/bank.con(0,1,0)"east/a) + +(* 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 +this case, we would like to skip the next goal, and focus on the trivial third +subgoal: a simple way to do it, is by retyping "|". The proof that +[east,west,west,east] is safe is trivial and can be done with //.*) + + || // (* -definition move_item ≝ λs.λi:movable_item s. -match (elem ? i) with -[ goat ⇒ mk_state (change_side (goat_pos s)) (wolf_pos s) - (cabbage_pos s) (change_side (boat_pos s)) -| wolf ⇒ mk_state (goat_pos s) (change_side (wolf_pos s)) - (cabbage_pos s) (change_side (boat_pos s)) -| cabbage ⇒ mk_state (goat_pos s) (wolf_pos s) - (change_side (cabbage_pos s)) (change_side (boat_pos s)) -| boat ⇒ mk_state (goat_pos s) (wolf_pos s) - (cabbage_pos s) (change_side (boat_pos s)) -]. - -definition legal_state ≝ λs. - cabbage_pos s = goat_pos s ∨ - goat_pos s = wolf_pos s → goat_pos s = boat_pos s. - -definition legal_step ≝ λs1,s2. - ∃i.move_item s1 i = s2. - -inductive reachable : state → state → Prop ≝ -| nil : ∀s.reachable s s -| step : ∀s1,s2,s3. legal_step s1 s2 → legal_state s2 → reachable s2 s3 → - reachable s1 s3. - -definition second ≝ mk_state west east east west. -definition end ≝ mk_state west west west west. - -lemma goat_move: ∀s.legal_step s (mk_state (change_side (goat_pos s)) (wolf_pos s) - (cabbage_pos s) (change_side (boat_pos s))). - -lemma problem: reachable start second. -@step [| @ex_intro // [| @move_goat ] // | //] - - [|| @move_goat //| // - |normalize \ No newline at end of file +We then advance to the next goal, namely the fact that there is a move from +[east,west,west,east] to [west,west,west,west]; this is trivial too, but it +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. *) + + | /span class="autotactic"2span class="autotrace" trace a href="cic:/matita/tutorial/chapter1/move.con(0,1,0)"move_goat/a, a href="cic:/matita/tutorial/chapter1/opp.con(0,1,0)"east_west/a/span/span/ ] + +(* +h2 class="section"Implicit arguments/h2 +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. *) + +@(a href="cic:/matita/tutorial/chapter1/reachable.con(0,2,0)"more/a ? (a href="cic:/matita/tutorial/chapter1/state.con(0,1,0)"mk_state/a a href="cic:/matita/tutorial/chapter1/bank.con(0,1,0)"east/a a href="cic:/matita/tutorial/chapter1/bank.con(0,2,0)"west/a a href="cic:/matita/tutorial/chapter1/bank.con(0,2,0)"west/a a href="cic:/matita/tutorial/chapter1/bank.con(0,2,0)"west/a)) + +(* We now get three independent subgoals, all actives, and two of them are +trivial. Wespan style="font-family: Verdana,sans-serif;" /spancan just apply automation to all of them, and it will close the two +trivial goals. *) + +/span class="autotactic"2span class="autotrace" trace a href="cic:/matita/tutorial/chapter1/safe_state.con(0,2,0)"opposite_side/a, a href="cic:/matita/tutorial/chapter1/move.con(0,4,0)"move_boat/a, a href="cic:/matita/tutorial/chapter1/opp.con(0,1,0)"east_west/a, a href="cic:/matita/tutorial/chapter1/opp.con(0,2,0)"west_east/a/span/span/ + +(* 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 +*) + +@(a href="cic:/matita/tutorial/chapter1/reachable.con(0,2,0)"more/a … (a href="cic:/matita/tutorial/chapter1/move.con(0,2,0)"move_wolf/a … )) + +(* The dots stand here for an arbitrary number of implicit arguments, to be +guessed by the system. +Unfortunately, the previous move is not enough to fully instantiate the new +intermediate state: a bank B remains unknown. Automation cannot help here, +since all goals depend from this bank and automation refuses to close some +subgoals instantiating other subgoals remaining open (the instantiation could +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: @a href="cic:/matita/tutorial/chapter1/bank.con(0,1,0)"east/a] /span class="autotactic"2span class="autotrace" trace a href="cic:/matita/tutorial/chapter1/safe_state.con(0,1,0)"with_boat/a, a href="cic:/matita/tutorial/chapter1/opp.con(0,1,0)"east_west/a/span/span/ + +(* Alternatively, we can directly instantiate the bank into the move. Let +us complete the proof in this, very readable way. *) + +@(a href="cic:/matita/tutorial/chapter1/reachable.con(0,2,0)"more/a … (a href="cic:/matita/tutorial/chapter1/move.con(0,1,0)"move_goat/a a href="cic:/matita/tutorial/chapter1/bank.con(0,2,0)"west/a … )) /span class="autotactic"2span class="autotrace" trace a href="cic:/matita/tutorial/chapter1/safe_state.con(0,1,0)"with_boat/a, a href="cic:/matita/tutorial/chapter1/opp.con(0,2,0)"west_east/a/span/span/ +@(a href="cic:/matita/tutorial/chapter1/reachable.con(0,2,0)"more/a … (a href="cic:/matita/tutorial/chapter1/move.con(0,3,0)"move_cabbage/a ?? a href="cic:/matita/tutorial/chapter1/bank.con(0,1,0)"east/a … )) /span class="autotactic"2span class="autotrace" trace a href="cic:/matita/tutorial/chapter1/safe_state.con(0,2,0)"opposite_side/a, a href="cic:/matita/tutorial/chapter1/opp.con(0,1,0)"east_west/a, a href="cic:/matita/tutorial/chapter1/opp.con(0,2,0)"west_east/a/span/span/ +@(a href="cic:/matita/tutorial/chapter1/reachable.con(0,2,0)"more/a … (a href="cic:/matita/tutorial/chapter1/move.con(0,4,0)"move_boat/a ??? a href="cic:/matita/tutorial/chapter1/bank.con(0,2,0)"west/a … )) /span class="autotactic"2span class="autotrace" trace a href="cic:/matita/tutorial/chapter1/safe_state.con(0,1,0)"with_boat/a, a href="cic:/matita/tutorial/chapter1/opp.con(0,2,0)"west_east/a/span/span/ +@a href="cic:/matita/tutorial/chapter1/reachable.con(0,1,0)"one/a /span class="autotactic"2span class="autotrace" trace a href="cic:/matita/tutorial/chapter1/move.con(0,1,0)"move_goat/a, a href="cic:/matita/tutorial/chapter1/opp.con(0,1,0)"east_west/a/span/span/ qed. \ No newline at end of file