doc-src/TutorialI/Inductive/AB.thy
author nipkow
Fri, 16 Feb 2001 06:46:20 +0100
changeset 11147 d848c6693185
parent 10884 2995639c6a09
child 11257 622331bbdb7f
permissions -rw-r--r--
*** empty log message ***
     1 (*<*)theory AB = Main:(*>*)
     2 
     3 section{*Case Study: A Context Free Grammar*}
     4 
     5 text{*\label{sec:CFG}
     6 Grammars are nothing but shorthands for inductive definitions of nonterminals
     7 which represent sets of strings. For example, the production
     8 $A \to B c$ is short for
     9 \[ w \in B \Longrightarrow wc \in A \]
    10 This section demonstrates this idea with an example
    11 due to Hopcroft and Ullman, a grammar for generating all words with an
    12 equal number of $a$'s and~$b$'s:
    13 \begin{eqnarray}
    14 S &\to& \epsilon \mid b A \mid a B \nonumber\\
    15 A &\to& a S \mid b A A \nonumber\\
    16 B &\to& b S \mid a B B \nonumber
    17 \end{eqnarray}
    18 At the end we say a few words about the relationship between
    19 the original proof \cite[p.\ts81]{HopcroftUllman} and our formal version.
    20 
    21 We start by fixing the alphabet, which consists only of @{term a}'s
    22 and~@{term b}'s:
    23 *}
    24 
    25 datatype alfa = a | b;
    26 
    27 text{*\noindent
    28 For convenience we include the following easy lemmas as simplification rules:
    29 *}
    30 
    31 lemma [simp]: "(x \<noteq> a) = (x = b) \<and> (x \<noteq> b) = (x = a)";
    32 by (case_tac x, auto)
    33 
    34 text{*\noindent
    35 Words over this alphabet are of type @{typ"alfa list"}, and
    36 the three nonterminals are declared as sets of such words:
    37 *}
    38 
    39 consts S :: "alfa list set"
    40        A :: "alfa list set"
    41        B :: "alfa list set";
    42 
    43 text{*\noindent
    44 The productions above are recast as a \emph{mutual} inductive
    45 definition\index{inductive definition!simultaneous}
    46 of @{term S}, @{term A} and~@{term B}:
    47 *}
    48 
    49 inductive S A B
    50 intros
    51   "[] \<in> S"
    52   "w \<in> A \<Longrightarrow> b#w \<in> S"
    53   "w \<in> B \<Longrightarrow> a#w \<in> S"
    54 
    55   "w \<in> S        \<Longrightarrow> a#w   \<in> A"
    56   "\<lbrakk> v\<in>A; w\<in>A \<rbrakk> \<Longrightarrow> b#v@w \<in> A"
    57 
    58   "w \<in> S            \<Longrightarrow> b#w   \<in> B"
    59   "\<lbrakk> v \<in> B; w \<in> B \<rbrakk> \<Longrightarrow> a#v@w \<in> B";
    60 
    61 text{*\noindent
    62 First we show that all words in @{term S} contain the same number of @{term
    63 a}'s and @{term b}'s. Since the definition of @{term S} is by mutual
    64 induction, so is the proof: we show at the same time that all words in
    65 @{term A} contain one more @{term a} than @{term b} and all words in @{term
    66 B} contains one more @{term b} than @{term a}.
    67 *}
    68 
    69 lemma correctness:
    70   "(w \<in> S \<longrightarrow> size[x\<in>w. x=a] = size[x\<in>w. x=b])     \<and>
    71    (w \<in> A \<longrightarrow> size[x\<in>w. x=a] = size[x\<in>w. x=b] + 1) \<and>
    72    (w \<in> B \<longrightarrow> size[x\<in>w. x=b] = size[x\<in>w. x=a] + 1)"
    73 
    74 txt{*\noindent
    75 These propositions are expressed with the help of the predefined @{term
    76 filter} function on lists, which has the convenient syntax @{text"[x\<in>xs. P
    77 x]"}, the list of all elements @{term x} in @{term xs} such that @{prop"P x"}
    78 holds. Remember that on lists @{text size} and @{text length} are synonymous.
    79 
    80 The proof itself is by rule induction and afterwards automatic:
    81 *}
    82 
    83 by (rule S_A_B.induct, auto)
    84 
    85 text{*\noindent
    86 This may seem surprising at first, and is indeed an indication of the power
    87 of inductive definitions. But it is also quite straightforward. For example,
    88 consider the production $A \to b A A$: if $v,w \in A$ and the elements of $A$
    89 contain one more $a$ than~$b$'s, then $bvw$ must again contain one more $a$
    90 than~$b$'s.
    91 
    92 As usual, the correctness of syntactic descriptions is easy, but completeness
    93 is hard: does @{term S} contain \emph{all} words with an equal number of
    94 @{term a}'s and @{term b}'s? It turns out that this proof requires the
    95 following lemma: every string with two more @{term a}'s than @{term
    96 b}'s can be cut somewhere such that each half has one more @{term a} than
    97 @{term b}. This is best seen by imagining counting the difference between the
    98 number of @{term a}'s and @{term b}'s starting at the left end of the
    99 word. We start with 0 and end (at the right end) with 2. Since each move to the
   100 right increases or decreases the difference by 1, we must have passed through
   101 1 on our way from 0 to 2. Formally, we appeal to the following discrete
   102 intermediate value theorem @{thm[source]nat0_intermed_int_val}
   103 @{thm[display]nat0_intermed_int_val[no_vars]}
   104 where @{term f} is of type @{typ"nat \<Rightarrow> int"}, @{typ int} are the integers,
   105 @{text"\<bar>.\<bar>"} is the absolute value function, and @{term"#1::int"} is the
   106 integer 1 (see \S\ref{sec:numbers}).
   107 
   108 First we show that our specific function, the difference between the
   109 numbers of @{term a}'s and @{term b}'s, does indeed only change by 1 in every
   110 move to the right. At this point we also start generalizing from @{term a}'s
   111 and @{term b}'s to an arbitrary property @{term P}. Otherwise we would have
   112 to prove the desired lemma twice, once as stated above and once with the
   113 roles of @{term a}'s and @{term b}'s interchanged.
   114 *}
   115 
   116 lemma step1: "\<forall>i < size w.
   117   \<bar>(int(size[x\<in>take (i+1) w. P x])-int(size[x\<in>take (i+1) w. \<not>P x]))
   118    - (int(size[x\<in>take i w. P x])-int(size[x\<in>take i w. \<not>P x]))\<bar> \<le> #1"
   119 
   120 txt{*\noindent
   121 The lemma is a bit hard to read because of the coercion function
   122 @{text"int :: nat \<Rightarrow> int"}. It is required because @{term size} returns
   123 a natural number, but subtraction on type~@{typ nat} will do the wrong thing.
   124 Function @{term take} is predefined and @{term"take i xs"} is the prefix of
   125 length @{term i} of @{term xs}; below we also need @{term"drop i xs"}, which
   126 is what remains after that prefix has been dropped from @{term xs}.
   127 
   128 The proof is by induction on @{term w}, with a trivial base case, and a not
   129 so trivial induction step. Since it is essentially just arithmetic, we do not
   130 discuss it.
   131 *}
   132 
   133 apply(induct w);
   134  apply(simp);
   135 by(force simp add:zabs_def take_Cons split:nat.split if_splits); 
   136 
   137 text{*
   138 Finally we come to the above mentioned lemma about cutting in half a word with two
   139 more elements of one sort than of the other sort:
   140 *}
   141 
   142 lemma part1:
   143  "size[x\<in>w. P x] = size[x\<in>w. \<not>P x]+2 \<Longrightarrow>
   144   \<exists>i\<le>size w. size[x\<in>take i w. P x] = size[x\<in>take i w. \<not>P x]+1";
   145 
   146 txt{*\noindent
   147 This is proved by @{text force} with the help of the intermediate value theorem,
   148 instantiated appropriately and with its first premise disposed of by lemma
   149 @{thm[source]step1}:
   150 *}
   151 
   152 apply(insert nat0_intermed_int_val[OF step1, of "P" "w" "#1"]);
   153 by force;
   154 
   155 text{*\noindent
   156 
   157 Lemma @{thm[source]part1} tells us only about the prefix @{term"take i w"}.
   158 An easy lemma deals with the suffix @{term"drop i w"}:
   159 *}
   160 
   161 
   162 lemma part2:
   163   "\<lbrakk>size[x\<in>take i w @ drop i w. P x] =
   164     size[x\<in>take i w @ drop i w. \<not>P x]+2;
   165     size[x\<in>take i w. P x] = size[x\<in>take i w. \<not>P x]+1\<rbrakk>
   166    \<Longrightarrow> size[x\<in>drop i w. P x] = size[x\<in>drop i w. \<not>P x]+1";
   167 by(simp del:append_take_drop_id);
   168 
   169 text{*\noindent
   170 In the proof, we have had to disable a normally useful lemma:
   171 \begin{isabelle}
   172 @{thm append_take_drop_id[no_vars]}
   173 \rulename{append_take_drop_id}
   174 \end{isabelle}
   175 
   176 To dispose of trivial cases automatically, the rules of the inductive
   177 definition are declared simplification rules:
   178 *}
   179 
   180 declare S_A_B.intros[simp];
   181 
   182 text{*\noindent
   183 This could have been done earlier but was not necessary so far.
   184 
   185 The completeness theorem tells us that if a word has the same number of
   186 @{term a}'s and @{term b}'s, then it is in @{term S}, and similarly 
   187 for @{term A} and @{term B}:
   188 *}
   189 
   190 theorem completeness:
   191   "(size[x\<in>w. x=a] = size[x\<in>w. x=b]     \<longrightarrow> w \<in> S) \<and>
   192    (size[x\<in>w. x=a] = size[x\<in>w. x=b] + 1 \<longrightarrow> w \<in> A) \<and>
   193    (size[x\<in>w. x=b] = size[x\<in>w. x=a] + 1 \<longrightarrow> w \<in> B)";
   194 
   195 txt{*\noindent
   196 The proof is by induction on @{term w}. Structural induction would fail here
   197 because, as we can see from the grammar, we need to make bigger steps than
   198 merely appending a single letter at the front. Hence we induct on the length
   199 of @{term w}, using the induction rule @{thm[source]length_induct}:
   200 *}
   201 
   202 apply(induct_tac w rule: length_induct);
   203 (*<*)apply(rename_tac w)(*>*)
   204 
   205 txt{*\noindent
   206 The @{text rule} parameter tells @{text induct_tac} explicitly which induction
   207 rule to use. For details see \S\ref{sec:complete-ind} below.
   208 In this case the result is that we may assume the lemma already
   209 holds for all words shorter than @{term w}.
   210 
   211 The proof continues with a case distinction on @{term w},
   212 i.e.\ if @{term w} is empty or not.
   213 *}
   214 
   215 apply(case_tac w);
   216  apply(simp_all);
   217 (*<*)apply(rename_tac x v)(*>*)
   218 
   219 txt{*\noindent
   220 Simplification disposes of the base case and leaves only two step
   221 cases to be proved:
   222 if @{prop"w = a#v"} and @{prop[display]"size[x\<in>v. x=a] = size[x\<in>v. x=b]+2"} then
   223 @{prop"b#v \<in> A"}, and similarly for @{prop"w = b#v"}.
   224 We only consider the first case in detail.
   225 
   226 After breaking the conjuction up into two cases, we can apply
   227 @{thm[source]part1} to the assumption that @{term w} contains two more @{term
   228 a}'s than @{term b}'s.
   229 *}
   230 
   231 apply(rule conjI);
   232  apply(clarify);
   233  apply(frule part1[of "\<lambda>x. x=a", simplified]);
   234  apply(erule exE);
   235  apply(erule conjE);
   236 
   237 txt{*\noindent
   238 This yields an index @{prop"i \<le> length v"} such that
   239 @{prop[display]"length [x\<in>take i v . x = a] = length [x\<in>take i v . x = b] + 1"}
   240 With the help of @{thm[source]part2} it follows that
   241 @{prop[display]"length [x\<in>drop i v . x = a] = length [x\<in>drop i v . x = b] + 1"}
   242 *}
   243 
   244  apply(drule part2[of "\<lambda>x. x=a", simplified]);
   245   apply(assumption);
   246 
   247 txt{*\noindent
   248 Now it is time to decompose @{term v} in the conclusion @{prop"b#v \<in> A"}
   249 into @{term"take i v @ drop i v"},
   250 after which the appropriate rule of the grammar reduces the goal
   251 to the two subgoals @{prop"take i v \<in> A"} and @{prop"drop i v \<in> A"}:
   252 *}
   253 
   254  apply(rule_tac n1=i and t=v in subst[OF append_take_drop_id]);
   255  apply(rule S_A_B.intros);
   256 
   257 txt{*\noindent
   258 Both subgoals follow from the induction hypothesis because both @{term"take i
   259 v"} and @{term"drop i v"} are shorter than @{term w}:
   260 *}
   261 
   262   apply(force simp add: min_less_iff_disj);
   263  apply(force split add: nat_diff_split);
   264 
   265 txt{*\noindent
   266 Note that the variables @{term n1} and @{term t} referred to in the
   267 substitution step above come from the derived theorem @{text"subst[OF
   268 append_take_drop_id]"}.
   269 
   270 The case @{prop"w = b#v"} is proved analogously:
   271 *}
   272 
   273 apply(clarify);
   274 apply(frule part1[of "\<lambda>x. x=b", simplified]);
   275 apply(erule exE);
   276 apply(erule conjE);
   277 apply(drule part2[of "\<lambda>x. x=b", simplified]);
   278  apply(assumption);
   279 apply(rule_tac n1=i and t=v in subst[OF append_take_drop_id]);
   280 apply(rule S_A_B.intros);
   281  apply(force simp add:min_less_iff_disj);
   282 by(force simp add:min_less_iff_disj split add: nat_diff_split);
   283 
   284 text{*
   285 We conclude this section with a comparison of our proof with 
   286 Hopcroft and Ullman's \cite[p.\ts81]{HopcroftUllman}. For a start, the texbook
   287 grammar, for no good reason, excludes the empty word.  That complicates
   288 matters just a little bit because we now have 8 instead of our 7 productions.
   289 
   290 More importantly, the proof itself is different: rather than
   291 separating the two directions, they perform one induction on the
   292 length of a word. This deprives them of the beauty of rule induction,
   293 and in the easy direction (correctness) their reasoning is more
   294 detailed than our @{text auto}. For the hard part (completeness), they
   295 consider just one of the cases that our @{text simp_all} disposes of
   296 automatically. Then they conclude the proof by saying about the
   297 remaining cases: ``We do this in a manner similar to our method of
   298 proof for part (1); this part is left to the reader''. But this is
   299 precisely the part that requires the intermediate value theorem and
   300 thus is not at all similar to the other cases (which are automatic in
   301 Isabelle). The authors are at least cavalier about this point and may
   302 even have overlooked the slight difficulty lurking in the omitted
   303 cases. This is not atypical for pen-and-paper proofs, once analysed in
   304 detail.  *}
   305 
   306 (*<*)end(*>*)