doc-src/TutorialI/Ifexpr/Ifexpr.thy
author nipkow
Thu, 25 Jan 2001 15:31:31 +0100
changeset 10978 5eebea8f359f
parent 10971 6852682eaf16
child 11456 7eb63f63e6c6
permissions -rw-r--r--
*** empty log message ***
nipkow@8745
     1
(*<*)
nipkow@8745
     2
theory Ifexpr = Main:;
nipkow@8745
     3
(*>*)
nipkow@8745
     4
paulson@10885
     5
subsection{*Case Study: Boolean Expressions*}
nipkow@9933
     6
nipkow@9933
     7
text{*\label{sec:boolex}
nipkow@9933
     8
The aim of this case study is twofold: it shows how to model boolean
nipkow@9933
     9
expressions and some algorithms for manipulating them, and it demonstrates
nipkow@9933
    10
the constructs introduced above.
nipkow@9933
    11
*}
nipkow@9933
    12
nipkow@10978
    13
subsubsection{*Modelling Boolean Expressions*}
nipkow@9933
    14
nipkow@8745
    15
text{*
nipkow@8745
    16
We want to represent boolean expressions built up from variables and
nipkow@8745
    17
constants by negation and conjunction. The following datatype serves exactly
nipkow@8745
    18
that purpose:
nipkow@8745
    19
*}
nipkow@8745
    20
nipkow@8745
    21
datatype boolex = Const bool | Var nat | Neg boolex
nipkow@8745
    22
                | And boolex boolex;
nipkow@8745
    23
nipkow@8745
    24
text{*\noindent
nipkow@9541
    25
The two constants are represented by @{term"Const True"} and
nipkow@9541
    26
@{term"Const False"}. Variables are represented by terms of the form
nipkow@9792
    27
@{term"Var n"}, where @{term"n"} is a natural number (type @{typ"nat"}).
nipkow@8745
    28
For example, the formula $P@0 \land \neg P@1$ is represented by the term
nipkow@9541
    29
@{term"And (Var 0) (Neg(Var 1))"}.
nipkow@8745
    30
nipkow@10978
    31
\subsubsection{The Value of a Boolean Expression}
nipkow@8745
    32
nipkow@8745
    33
The value of a boolean expression depends on the value of its variables.
nipkow@9792
    34
Hence the function @{text"value"} takes an additional parameter, an
nipkow@9792
    35
\emph{environment} of type @{typ"nat => bool"}, which maps variables to their
nipkow@9792
    36
values:
nipkow@8745
    37
*}
nipkow@8745
    38
paulson@10795
    39
consts value :: "boolex \<Rightarrow> (nat \<Rightarrow> bool) \<Rightarrow> bool";
nipkow@8745
    40
primrec
nipkow@8745
    41
"value (Const b) env = b"
nipkow@8745
    42
"value (Var x)   env = env x"
paulson@10795
    43
"value (Neg b)   env = (\<not> value b env)"
paulson@10795
    44
"value (And b c) env = (value b env \<and> value c env)";
nipkow@8745
    45
nipkow@8745
    46
text{*\noindent
paulson@10885
    47
\subsubsection{If-Expressions}
nipkow@8745
    48
nipkow@8745
    49
An alternative and often more efficient (because in a certain sense
nipkow@8745
    50
canonical) representation are so-called \emph{If-expressions} built up
nipkow@9792
    51
from constants (@{term"CIF"}), variables (@{term"VIF"}) and conditionals
nipkow@9792
    52
(@{term"IF"}):
nipkow@8745
    53
*}
nipkow@8745
    54
nipkow@8745
    55
datatype ifex = CIF bool | VIF nat | IF ifex ifex ifex;
nipkow@8745
    56
nipkow@8745
    57
text{*\noindent
nipkow@10971
    58
The evaluation of If-expressions proceeds as for @{typ"boolex"}:
nipkow@8745
    59
*}
nipkow@8745
    60
paulson@10795
    61
consts valif :: "ifex \<Rightarrow> (nat \<Rightarrow> bool) \<Rightarrow> bool";
nipkow@8745
    62
primrec
nipkow@8745
    63
"valif (CIF b)    env = b"
nipkow@8745
    64
"valif (VIF x)    env = env x"
nipkow@8745
    65
"valif (IF b t e) env = (if valif b env then valif t env
nipkow@8745
    66
                                        else valif e env)";
nipkow@8745
    67
nipkow@8745
    68
text{*
nipkow@10978
    69
\subsubsection{Converting Boolean and If-Expressions}
nipkow@8745
    70
nipkow@9792
    71
The type @{typ"boolex"} is close to the customary representation of logical
nipkow@9792
    72
formulae, whereas @{typ"ifex"} is designed for efficiency. It is easy to
nipkow@9792
    73
translate from @{typ"boolex"} into @{typ"ifex"}:
nipkow@8745
    74
*}
nipkow@8745
    75
paulson@10795
    76
consts bool2if :: "boolex \<Rightarrow> ifex";
nipkow@8745
    77
primrec
nipkow@8745
    78
"bool2if (Const b) = CIF b"
nipkow@8745
    79
"bool2if (Var x)   = VIF x"
nipkow@8745
    80
"bool2if (Neg b)   = IF (bool2if b) (CIF False) (CIF True)"
nipkow@8745
    81
"bool2if (And b c) = IF (bool2if b) (bool2if c) (CIF False)";
nipkow@8745
    82
nipkow@8745
    83
text{*\noindent
nipkow@9792
    84
At last, we have something we can verify: that @{term"bool2if"} preserves the
nipkow@8745
    85
value of its argument:
nipkow@8745
    86
*}
nipkow@8745
    87
nipkow@8745
    88
lemma "valif (bool2if b) env = value b env";
nipkow@8745
    89
nipkow@8745
    90
txt{*\noindent
nipkow@8745
    91
The proof is canonical:
nipkow@8745
    92
*}
nipkow@8745
    93
nipkow@8745
    94
apply(induct_tac b);
nipkow@10171
    95
apply(auto);
nipkow@10171
    96
done
nipkow@8745
    97
nipkow@8745
    98
text{*\noindent
nipkow@8745
    99
In fact, all proofs in this case study look exactly like this. Hence we do
nipkow@8745
   100
not show them below.
nipkow@8745
   101
nipkow@8745
   102
More interesting is the transformation of If-expressions into a normal form
nipkow@9792
   103
where the first argument of @{term"IF"} cannot be another @{term"IF"} but
nipkow@8745
   104
must be a constant or variable. Such a normal form can be computed by
nipkow@9541
   105
repeatedly replacing a subterm of the form @{term"IF (IF b x y) z u"} by
nipkow@9541
   106
@{term"IF b (IF x z u) (IF y z u)"}, which has the same value. The following
nipkow@8745
   107
primitive recursive functions perform this task:
nipkow@8745
   108
*}
nipkow@8745
   109
paulson@10795
   110
consts normif :: "ifex \<Rightarrow> ifex \<Rightarrow> ifex \<Rightarrow> ifex";
nipkow@8745
   111
primrec
nipkow@8745
   112
"normif (CIF b)    t e = IF (CIF b) t e"
nipkow@8745
   113
"normif (VIF x)    t e = IF (VIF x) t e"
nipkow@8745
   114
"normif (IF b t e) u f = normif b (normif t u f) (normif e u f)";
nipkow@8745
   115
paulson@10795
   116
consts norm :: "ifex \<Rightarrow> ifex";
nipkow@8745
   117
primrec
nipkow@8745
   118
"norm (CIF b)    = CIF b"
nipkow@8745
   119
"norm (VIF x)    = VIF x"
nipkow@8745
   120
"norm (IF b t e) = normif b (norm t) (norm e)";
nipkow@8745
   121
nipkow@8745
   122
text{*\noindent
nipkow@8745
   123
Their interplay is a bit tricky, and we leave it to the reader to develop an
nipkow@8745
   124
intuitive understanding. Fortunately, Isabelle can help us to verify that the
nipkow@8745
   125
transformation preserves the value of the expression:
nipkow@8745
   126
*}
nipkow@8745
   127
nipkow@8745
   128
theorem "valif (norm b) env = valif b env";(*<*)oops;(*>*)
nipkow@8745
   129
nipkow@8745
   130
text{*\noindent
nipkow@8745
   131
The proof is canonical, provided we first show the following simplification
nipkow@9792
   132
lemma (which also helps to understand what @{term"normif"} does):
nipkow@8745
   133
*}
nipkow@8745
   134
nipkow@8745
   135
lemma [simp]:
paulson@10795
   136
  "\<forall>t e. valif (normif b t e) env = valif (IF b t e) env";
nipkow@8745
   137
(*<*)
nipkow@8745
   138
apply(induct_tac b);
nipkow@9458
   139
by(auto);
nipkow@8745
   140
nipkow@8745
   141
theorem "valif (norm b) env = valif b env";
nipkow@8745
   142
apply(induct_tac b);
nipkow@9458
   143
by(auto);
nipkow@8745
   144
(*>*)
nipkow@8745
   145
text{*\noindent
nipkow@8745
   146
Note that the lemma does not have a name, but is implicitly used in the proof
nipkow@9792
   147
of the theorem shown above because of the @{text"[simp]"} attribute.
nipkow@8745
   148
nipkow@9792
   149
But how can we be sure that @{term"norm"} really produces a normal form in
nipkow@8745
   150
the above sense? We define a function that tests If-expressions for normality
nipkow@8745
   151
*}
nipkow@8745
   152
paulson@10795
   153
consts normal :: "ifex \<Rightarrow> bool";
nipkow@8745
   154
primrec
nipkow@8745
   155
"normal(CIF b) = True"
nipkow@8745
   156
"normal(VIF x) = True"
paulson@10795
   157
"normal(IF b t e) = (normal t \<and> normal e \<and>
paulson@10795
   158
     (case b of CIF b \<Rightarrow> True | VIF x \<Rightarrow> True | IF x y z \<Rightarrow> False))";
nipkow@8745
   159
nipkow@8745
   160
text{*\noindent
nipkow@9792
   161
and prove @{term"normal(norm b)"}. Of course, this requires a lemma about
nipkow@9792
   162
normality of @{term"normif"}:
nipkow@8745
   163
*}
nipkow@8745
   164
paulson@10795
   165
lemma[simp]: "\<forall>t e. normal(normif b t e) = (normal t \<and> normal e)";
nipkow@8771
   166
(*<*)
nipkow@8745
   167
apply(induct_tac b);
nipkow@9458
   168
by(auto);
nipkow@8745
   169
nipkow@8745
   170
theorem "normal(norm b)";
nipkow@8745
   171
apply(induct_tac b);
nipkow@9458
   172
by(auto);
nipkow@9933
   173
(*>*)
nipkow@8745
   174
nipkow@9933
   175
text{*\medskip
paulson@10795
   176
How do we come up with the required lemmas? Try to prove the main theorems
paulson@10795
   177
without them and study carefully what @{text auto} leaves unproved. This 
paulson@10795
   178
can provide the clue.  The necessity of universal quantification
nipkow@9933
   179
(@{text"\<forall>t e"}) in the two lemmas is explained in
nipkow@9933
   180
\S\ref{sec:InductionHeuristics}
nipkow@9933
   181
nipkow@9933
   182
\begin{exercise}
nipkow@9933
   183
  We strengthen the definition of a @{term normal} If-expression as follows:
nipkow@9933
   184
  the first argument of all @{term IF}s must be a variable. Adapt the above
nipkow@9933
   185
  development to this changed requirement. (Hint: you may need to formulate
nipkow@9933
   186
  some of the goals as implications (@{text"\<longrightarrow>"}) rather than
nipkow@9933
   187
  equalities (@{text"="}).)
nipkow@9933
   188
\end{exercise}
nipkow@9933
   189
*}
nipkow@9933
   190
(*<*)
nipkow@8771
   191
end
nipkow@8771
   192
(*>*)