src/HOL/Isar_examples/HoareEx.thy
changeset 10148 739327964a5c
child 10838 9423817dee84
equal deleted inserted replaced
10147:178deaacb244 10148:739327964a5c
       
     1 
       
     2 header {* Using Hoare Logic *}
       
     3 
       
     4 theory HoareEx = Hoare:
       
     5 
       
     6 subsection {* State spaces *}
       
     7 
       
     8 text {*
       
     9  First of all we provide a store of program variables that
       
    10  occur in any of the programs considered later.  Slightly unexpected
       
    11  things may happen when attempting to work with undeclared variables.
       
    12 *}
       
    13 
       
    14 record vars =
       
    15   I :: nat
       
    16   M :: nat
       
    17   N :: nat
       
    18   S :: nat
       
    19 
       
    20 text {*
       
    21  While all of our variables happen to have the same type, nothing
       
    22  would prevent us from working with many-sorted programs as well, or
       
    23  even polymorphic ones.  Also note that Isabelle/HOL's extensible
       
    24  record types even provides simple means to extend the state space
       
    25  later.
       
    26 *}
       
    27 
       
    28 
       
    29 subsection {* Basic examples *}
       
    30 
       
    31 text {*
       
    32  We look at few trivialities involving assignment and sequential
       
    33  composition, in order to get an idea of how to work with our
       
    34  formulation of Hoare Logic.
       
    35 *}
       
    36 
       
    37 text {*
       
    38  Using the basic \name{assign} rule directly is a bit cumbersome.
       
    39 *}
       
    40 
       
    41 lemma
       
    42   "|- .{`(N_update (2 * `N)) : .{`N = #10}.}. `N := 2 * `N .{`N = #10}."
       
    43   by (rule assign)
       
    44 
       
    45 text {*
       
    46  Certainly we want the state modification already done, e.g.\ by
       
    47  simplification.  The \name{hoare} method performs the basic state
       
    48  update for us; we may apply the Simplifier afterwards to achieve
       
    49  ``obvious'' consequences as well.
       
    50 *}
       
    51 
       
    52 lemma "|- .{True}. `N := #10 .{`N = #10}."
       
    53   by hoare
       
    54 
       
    55 lemma "|- .{2 * `N = #10}. `N := 2 * `N .{`N = #10}."
       
    56   by hoare
       
    57 
       
    58 lemma "|- .{`N = #5}. `N := 2 * `N .{`N = #10}."
       
    59   by hoare simp
       
    60 
       
    61 lemma "|- .{`N + 1 = a + 1}. `N := `N + 1 .{`N = a + 1}."
       
    62   by hoare
       
    63 
       
    64 lemma "|- .{`N = a}. `N := `N + 1 .{`N = a + 1}."
       
    65   by hoare simp
       
    66 
       
    67 lemma "|- .{a = a & b = b}. `M := a; `N := b .{`M = a & `N = b}."
       
    68   by hoare
       
    69 
       
    70 lemma "|- .{True}. `M := a; `N := b .{`M = a & `N = b}."
       
    71   by hoare simp
       
    72 
       
    73 lemma
       
    74 "|- .{`M = a & `N = b}.
       
    75     `I := `M; `M := `N; `N := `I
       
    76     .{`M = b & `N = a}."
       
    77   by hoare simp
       
    78 
       
    79 text {*
       
    80  It is important to note that statements like the following one can
       
    81  only be proven for each individual program variable.  Due to the
       
    82  extra-logical nature of record fields, we cannot formulate a theorem
       
    83  relating record selectors and updates schematically.
       
    84 *}
       
    85 
       
    86 lemma "|- .{`N = a}. `N := `N .{`N = a}."
       
    87   by hoare
       
    88 
       
    89 lemma "|- .{`x = a}. `x := `x .{`x = a}."
       
    90   oops
       
    91 
       
    92 lemma
       
    93   "Valid {s. x s = a} (Basic (\<lambda>s. x_update (x s) s)) {s. x s = n}"
       
    94   -- {* same statement without concrete syntax *}
       
    95   oops
       
    96 
       
    97 
       
    98 text {*
       
    99  In the following assignments we make use of the consequence rule in
       
   100  order to achieve the intended precondition.  Certainly, the
       
   101  \name{hoare} method is able to handle this case, too.
       
   102 *}
       
   103 
       
   104 lemma "|- .{`M = `N}. `M := `M + 1 .{`M ~= `N}."
       
   105 proof -
       
   106   have ".{`M = `N}. <= .{`M + 1 ~= `N}."
       
   107     by auto
       
   108   also have "|- ... `M := `M + 1 .{`M ~= `N}."
       
   109     by hoare
       
   110   finally show ?thesis .
       
   111 qed
       
   112 
       
   113 lemma "|- .{`M = `N}. `M := `M + 1 .{`M ~= `N}."
       
   114 proof -
       
   115   have "!!m n. m = n --> m + 1 ~= n"
       
   116       -- {* inclusion of assertions expressed in ``pure'' logic, *}
       
   117       -- {* without mentioning the state space *}
       
   118     by simp
       
   119   also have "|- .{`M + 1 ~= `N}. `M := `M + 1 .{`M ~= `N}."
       
   120     by hoare
       
   121   finally show ?thesis .
       
   122 qed
       
   123 
       
   124 lemma "|- .{`M = `N}. `M := `M + 1 .{`M ~= `N}."
       
   125   by hoare simp
       
   126 
       
   127 
       
   128 subsection {* Multiplication by addition *}
       
   129 
       
   130 text {*
       
   131  We now do some basic examples of actual \texttt{WHILE} programs.
       
   132  This one is a loop for calculating the product of two natural
       
   133  numbers, by iterated addition.  We first give detailed structured
       
   134  proof based on single-step Hoare rules.
       
   135 *}
       
   136 
       
   137 lemma
       
   138   "|- .{`M = 0 & `S = 0}.
       
   139       WHILE `M ~= a
       
   140       DO `S := `S + b; `M := `M + 1 OD
       
   141       .{`S = a * b}."
       
   142 proof -
       
   143   let "|- _ ?while _" = ?thesis
       
   144   let ".{`?inv}." = ".{`S = `M * b}."
       
   145 
       
   146   have ".{`M = 0 & `S = 0}. <= .{`?inv}." by auto
       
   147   also have "|- ... ?while .{`?inv & ~ (`M ~= a)}."
       
   148   proof
       
   149     let ?c = "`S := `S + b; `M := `M + 1"
       
   150     have ".{`?inv & `M ~= a}. <= .{`S + b = (`M + 1) * b}."
       
   151       by auto
       
   152     also have "|- ... ?c .{`?inv}." by hoare
       
   153     finally show "|- .{`?inv & `M ~= a}. ?c .{`?inv}." .
       
   154   qed
       
   155   also have "... <= .{`S = a * b}." by auto
       
   156   finally show ?thesis .
       
   157 qed
       
   158 
       
   159 text {*
       
   160  The subsequent version of the proof applies the \name{hoare} method
       
   161  to reduce the Hoare statement to a purely logical problem that can be
       
   162  solved fully automatically.  Note that we have to specify the
       
   163  \texttt{WHILE} loop invariant in the original statement.
       
   164 *}
       
   165 
       
   166 lemma
       
   167   "|- .{`M = 0 & `S = 0}.
       
   168       WHILE `M ~= a
       
   169       INV .{`S = `M * b}.
       
   170       DO `S := `S + b; `M := `M + 1 OD
       
   171       .{`S = a * b}."
       
   172   by hoare auto
       
   173 
       
   174 
       
   175 subsection {* Summing natural numbers *}
       
   176 
       
   177 text {*
       
   178  We verify an imperative program to sum natural numbers up to a given
       
   179  limit.  First some functional definition for proper specification of
       
   180  the problem.
       
   181 *}
       
   182 
       
   183 consts
       
   184   sum :: "(nat => nat) => nat => nat"
       
   185 primrec
       
   186   "sum f 0 = 0"
       
   187   "sum f (Suc n) = f n + sum f n"
       
   188 
       
   189 syntax
       
   190   "_sum" :: "idt => nat => nat => nat"
       
   191     ("SUM _<_. _" [0, 0, 10] 10)
       
   192 translations
       
   193   "SUM j<k. b" == "sum (\<lambda>j. b) k"
       
   194 
       
   195 text {*
       
   196  The following proof is quite explicit in the individual steps taken,
       
   197  with the \name{hoare} method only applied locally to take care of
       
   198  assignment and sequential composition.  Note that we express
       
   199  intermediate proof obligation in pure logic, without referring to the
       
   200  state space.
       
   201 *}
       
   202 
       
   203 theorem
       
   204   "|- .{True}.
       
   205       `S := 0; `I := 1;
       
   206       WHILE `I ~= n
       
   207       DO
       
   208         `S := `S + `I;
       
   209         `I := `I + 1
       
   210       OD
       
   211       .{`S = (SUM j<n. j)}."
       
   212   (is "|- _ (_; ?while) _")
       
   213 proof -
       
   214   let ?sum = "\<lambda>k. SUM j<k. j"
       
   215   let ?inv = "\<lambda>s i. s = ?sum i"
       
   216 
       
   217   have "|- .{True}. `S := 0; `I := 1 .{?inv `S `I}."
       
   218   proof -
       
   219     have "True --> 0 = ?sum 1"
       
   220       by simp
       
   221     also have "|- .{...}. `S := 0; `I := 1 .{?inv `S `I}."
       
   222       by hoare
       
   223     finally show ?thesis .
       
   224   qed
       
   225   also have "|- ... ?while .{?inv `S `I & ~ `I ~= n}."
       
   226   proof
       
   227     let ?body = "`S := `S + `I; `I := `I + 1"
       
   228     have "!!s i. ?inv s i & i ~= n -->  ?inv (s + i) (i + 1)"
       
   229       by simp
       
   230     also have "|- .{`S + `I = ?sum (`I + 1)}. ?body .{?inv `S `I}."
       
   231       by hoare
       
   232     finally show "|- .{?inv `S `I & `I ~= n}. ?body .{?inv `S `I}." .
       
   233   qed
       
   234   also have "!!s i. s = ?sum i & ~ i ~= n --> s = ?sum n"
       
   235     by simp
       
   236   finally show ?thesis .
       
   237 qed
       
   238 
       
   239 text {*
       
   240  The next version uses the \name{hoare} method, while still explaining
       
   241  the resulting proof obligations in an abstract, structured manner.
       
   242 *}
       
   243 
       
   244 theorem
       
   245   "|- .{True}.
       
   246       `S := 0; `I := 1;
       
   247       WHILE `I ~= n
       
   248       INV .{`S = (SUM j<`I. j)}.
       
   249       DO
       
   250         `S := `S + `I;
       
   251         `I := `I + 1
       
   252       OD
       
   253       .{`S = (SUM j<n. j)}."
       
   254 proof -
       
   255   let ?sum = "\<lambda>k. SUM j<k. j"
       
   256   let ?inv = "\<lambda>s i. s = ?sum i"
       
   257 
       
   258   show ?thesis
       
   259   proof hoare
       
   260     show "?inv 0 1" by simp
       
   261   next
       
   262     fix s i assume "?inv s i & i ~= n"
       
   263     thus "?inv (s + i) (i + 1)" by simp
       
   264   next
       
   265     fix s i assume "?inv s i & ~ i ~= n"
       
   266     thus "s = ?sum n" by simp
       
   267   qed
       
   268 qed
       
   269 
       
   270 text {*
       
   271  Certainly, this proof may be done fully automatic as well, provided
       
   272  that the invariant is given beforehand.
       
   273 *}
       
   274 
       
   275 theorem
       
   276   "|- .{True}.
       
   277       `S := 0; `I := 1;
       
   278       WHILE `I ~= n
       
   279       INV .{`S = (SUM j<`I. j)}.
       
   280       DO
       
   281         `S := `S + `I;
       
   282         `I := `I + 1
       
   283       OD
       
   284       .{`S = (SUM j<n. j)}."
       
   285   by hoare auto
       
   286 
       
   287 end