Quellcodebibliothek Statistik Leitseite products/Sources/formale Sprachen/C/LibreOffice/extensions/source/config/   (Office von Apache Version 25.8.3.2©) image not shown  

Quellcode-Bibliothek VcgEx.thy

  Sprache: Isabelle
 

(*
    Author:      Norbert Schirmer
    Maintainer:  Norbert Schirmer, norbert.schirmer at web de

Copyright (C) 2006-2008 Norbert Schirmer
*)


section Examples using the Verification Environment

theory VcgEx imports "../HeapList" "../Vcg" begin

text Some examples, especially the single-step Isar proofs are taken from
 texttt{HOL/Isar\_examples/HoareEx.thy}.
 


subsection State Spaces

text 
 First of all we provide a store of program variables that
 occur in the programs considered later. Slightly unexpected
 things may happen when attempting to work with undeclared variables.
 


record 'g vars = "'g state" +
  A_' :: nat
  I_' :: nat
  M_' :: nat
  N_' :: nat
  R_' :: nat
  S_' :: nat
  B_' :: bool
  Arr_' :: "nat list"
  Abr_':: string



text We decorate the state components in the record with the suffix _',
  avoid cluttering the namespace with the simple names that could no longer
  used for logical variables otherwise.
 


text We will first consider programs without procedures, later on
  will regard procedures without global variables and finally we
  get the full pictures: mutually recursive procedures with global
  (including heap).
 


subsection Basic Examples

text 
 We look at few trivialities involving assignment and sequential
 composition, in order to get an idea of how to work with our
 formulation of Hoare Logic.
 


text 
 Using the basic rule directly is a bit cumbersome.
 


lemma  {|🍋N = 5|} 🍋N :== 2 * 🍋N {|🍋N = 10|}"
  apply (rule HoarePartial.Basic)  apply simp
  done

text 
 If we refer to components (variables) of the state-space of the program
 we always mark these with 🍋. It is the acute-symbol and is present on
 most keyboards. So all program variables are marked with the acute and all
 logical variables are not.
 The assertions of the Hoare tuple are
 ordinary Isabelle sets. As we usually want to refer to the state space
 in the assertions, we provide special brackets for them. They can be written
 as {\verb+{| |}+} in ASCII or { } with symbols. Internally
 marking variables has two effects. First of all we refer to the implicit
 state and secondary we get rid of the suffix _'.
 So the assertion @{term "{|🍋N = 5|}"} internally gets expanded to
 {s. N_' s = 5} written in ordinary set comprehension notation of
 Isabelle. It describes the set of states where the N_' component
 is equal to 5.
 



text 
 Certainly we want the state modification already done, e.g.by
 simplification. The vcg method performs the basic state
 update for us; we may apply the Simplifier afterwards to achieve
 ``obvious'' consequences as well.
 



lemma  {True} 🍋N :== 10 {🍋N = 10}"
  by vcg

lemma  {2 * 🍋N = 10} 🍋N :== 2 * 🍋N {🍋N = 10}"
  by vcg

lemma  {🍋N = 5} 🍋N :== 2 * 🍋N {🍋N = 10}"
  apply vcg
  apply simp
  done

lemma  {🍋N + 1 = a + 1} 🍋N :== 🍋N + 1 {🍋N = a + 1}"
  by vcg

lemma  {🍋N = a} 🍋N :== 🍋N + 1 {🍋N = a + 1}"
  by vcg


lemma  {a = a b = b} 🍋M :== a;; 🍋N :== b {🍋M = a 🍋N = b}"
  by vcg


lemma  {True} 🍋M :== a;; 🍋N :== b {🍋M = a 🍋N = b}"
  by vcg

lemma  {🍋M = a 🍋N = b}
                🍋I :== 🍋M;; 🍋M :== 🍋N;; 🍋N :== 🍋I
              {🍋M = b 🍋N = a}"
  by vcg

text 
  can also perform verification conditions generation step by step by using
  vcg_step method.
 


lemma  {🍋M = a 🍋N = b}
               🍋I :== 🍋M;; 🍋M :== 🍋N;; 🍋N :== 🍋I
              {🍋M = b 🍋N = a}"
  apply vcg_step
  apply vcg_step
  apply vcg_step
  apply vcg_step
  done

text 
 It is important to note that statements like the following one can
 only be proven for each individual program variable. Due to the
 extra-logical nature of record fields, we cannot formulate a theorem
 relating record selectors and updates schematically.
 


lemma  {🍋N = a} 🍋N :== 🍋N {🍋N = a}"
  by vcg


(*
lemma "\<Gamma>\<turnstile> \<lbrace>\<acute>x = a\<rbrace> \<acute>x :== \<acute>x \<lbrace>\<acute>x = a\<rbrace>"
  apply (rule HoarePartial.Basic)
  -- {* We can't proof this since we don't know what @{text "x_'_update"} is. *}
  oops
 *)

lemma {s. x_' s = a} (Basic (λs. x_'_update (x_' s) s)) {s. x_' s = a}"
  oops


text 
 In the following assignments we make use of the consequence rule in
 order to achieve the intended precondition. Certainly, the
 vcg method is able to handle this case, too.
 


lemma  {🍋M = 🍋N} 🍋M :== 🍋M + 1 {🍋M 🍋N}"
proof -
  have "{🍋M = 🍋N} {🍋M + 1 🍋N}"
    by auto
  also have  🍋M :== 🍋M + 1 {🍋M 🍋N}"
    by vcg
  finally show ?thesis .
qed

lemma  {🍋M = 🍋N} 🍋M :== 🍋M + 1 {🍋M 🍋N}"
proof -
  have "m n::nat. m = n m + 1 n"
      ― inclusion of assertions expressed in ``pure'' logic,
      ― without mentioning the state space
    by simp
  also have  {🍋M + 1 🍋N} 🍋M :== 🍋M + 1 {🍋M 🍋N}"
    by vcg
  finally show ?thesis .
qed

lemma  {🍋M = 🍋N} 🍋M :== 🍋M + 1 {\(*
  apply vcg
  apply simp
  done

subsection Multiplication by Addition

text at web de
 We n do some babasic examp of actual \texttt{WHILE} programs.
 This one is a loop for calculating the product of two natural
 numbers, by iterated addition. We first give detailed structured
 proof based on single-step Hoare rules.
\<close>

lemma
      WHILE \text\openSome exexamples, especially the single-step Isar proofs are taken from
      DO 🍋S :== 🍋S + b;; 🍋M + 1 OD
      {S = a * b}"
  -
 
 let "{🍋?inv}\<acute M * b<>"

 have "{M = 0 & 🍋 {?inv}" by auto
 also have "Γ 'gvas "g tt"+
 roof
 We decorate the state components in the record with the suffix ,
 have "{?inv 🍋 a} {S + b = (🍋 1 * b\rbrace"
 by auto
 also have "Γ ?c {🍋oWe will first consider programs without procedures, later on
 finally show
 qed
 also have "{🍋and> ¬ (🍋M 🍋" by ato
 ally shw?thehesis by bast
 


 
 The subsequent version of t 🚫
 to reduce the Hoare statement to a purely logical problem that can be
 solved fully automatically. Note that we have to specify the
 \texttt{WHILE} loop invariant in the original statement.
 


 
 WHILE 🍋M a
 INV {🍋S = 🍋
 🚫 :== 🍋S + b;; 🍋M :== 🍋
 {🍋🚫
 apply vc
 apply auto
 done

 

 <>S
 TRY
 WHILE True
 INV {🍋S = 🍋
 DO IF 🍋S :== 🍋M :== 🍋+ 1 FI OD
  CATCH
 SKIP
 END
 {🍋S = a * b}"
  vcg
  auto
 

  "Γ {M = 0 🍋
 TRY
 WHILE True
 INV {🍋M * b}
 DO IF 🍋\<urnstile {True} 🍋N :== 10 {N = 10}"
 ELSE acute>>S :== 🍋S + b;; 🍋M :== 🍋
 FI
 OD
 CATCH
 IF 🍋Abr = ''Break'' THEN SKIP ELSE Throw FI
 END
 {🍋S = a * b}"
  vcg
  auto
 


 
  the above, and the for an state-update followed
  a {N = a} 🍋N + 1 {🍋"
 

  "ΓTrue}acute>>M :== a;; 🍋N :== b {🍋M = a 🍋"
 {Abr = ''Break''} WHILE True INV {🍋S = 🍋M * b\\}
 DO IF 🍋M = a THEN RAISE 🍋Abr :== ''Break''
 ELSE 🍋S :== 🍋S + b;; 🍋M :== 🍋M + 1
 FI
 OD
 {🍋S = a * b}"
  vcg
  auto
 

  "Γ {🍋M = 0 🍋S = 0}
 TRY
 WHILE True
 INV {🍋S = 🍋M * b}
 DO IF 🍋M = a THEN RAISE 🍋Abr :== ''Break''
 ELSE 🍋S :== 🍋M :== 🍋
 FI
 OD
 CATCH
 IF 🍋''Break'' THEN SKIP ELSE Throw FI
 END
 {S = a * b}
  vcg
  auto
 

  "Γ🍋N = a}
 {🍋 WHILE True
 INV \<>\
 DO IF 🍋
 ELSE 🍋 {N = a}N :== 🍋🍋
 
 OD
 {Γs. x_'_update (x_' s) s)) {s. x_' s = a}"
  voops
 auto
 

  \openvcg
method is able to handle this case, too.

  "Γ{I = i}O\acutea> :== 2 COL {🍋I i}"
 apply vcg
 by simp
 <>< LOC 🍋N :== 🚫
 by vcg

  "Γ {🍋N = n} LOC 🍋
 by vcg


  🍋M + 1 {M 🍋"

 
 We verify an imperative program to sum natural numbers up to a given
 limit. First some functional definition for proper specification of
  pr.
 


 
 sum :: "(nat => nat) => nat => nat"
 
 "sum f 0 = 0"
 apply simp

 
 "_sum" :: "idt => nat => nat => nat"
 (SUMM _<_.Multiplication by Addition
 
 "_sum" == sum
 
 "SUMM j<k.

  a
 The following proof is quite explicit in DO \acuteS :== 🍋M :== 🍋
 with the
 nmentet and seentialcompiti oe that e expres
 intermediate proof obligation in pure logic, wi
 state space.
 


  "ΓTre}
 🍋I :== 1;;
 WHILE 🍋 ?c {?inv}
 DO
 🍋🍋M ?c {?inv}.
 🍋I + 1
 OD
java.lang.NullPointerException: Cannot invoke "String.equals(Object)" because "macro" is null
  (is "\<Gamma>\<turnstile>           
proof java.lang.StringIndexOutOfBoundsException: Index 7 out of bounds for length 7
  let?sum=\<k. .SUMM j<. "
  let ?inv = "\<lambda>s i. s = ?sum i"

  have "\<Gamma>\<turnstile> \<lbrace>          CATCH

    have "True \<longrightarrow> 0 = ?sum 1"
      bysimp
    also have "\<Gamma>\<turnstile> \<lbrace>\<dots>\<rbrace> \<acute>S :== 0;; \<acute>I :== applyvcg
      by vcg
    finally show ?thesis .
  qed
  also have "\<Gamma>\<turnstile> \<lbrace>?inv \<acute>S \<acute>I\<rbrace           \lbrace<S= <>  b<>
  proof
    let ?body = "\<acute>S :== \<acute>S + \<acute>I;; \<acute>I :== \<acute>I + 1"
    have "\<And>s i. ?inv s i java.lang.StringIndexOutOfBoundsException: Index 46 out of bounds for length 46
      by simp
    also have "\<Gamma>\<turnstile> \<lbrace>\<acute>S + \<acute>I = ?sum (\<acute>I + 1)\<rbrace> ?body \<lbrace>?inv \<acute>S \<acute>I\<rbrace>"
      by vcg
    finally show "\<Gamma>\<turnstile> \<lbrace>?inv \<acute>S \<acute>I \<and> \<acute>I \<noteq> n\<rbrace> ?body \<lbrace>?inv \<acute>S \<acute>I\<rbrace>" .
  qed
  also have "\<And>s i. s = ?sum i \<and> \<not> i \<noteq> n \<longrightarrow> s = ?sum n"
    by simp
  finally show ?thesis .
qed

text \<penjava.lang.StringIndexOutOfBoundsException: Index 12 out of bounds for length 12
 The next version uses the \<open>vcg\<close> method, while still explaining
 the resulting proof obligations in an abstract, structured manner.
<lose>

theorem the problem.
           
            <> <> java.lang.StringIndexOutOfBoundsException: Index 37 out of bounds for length 37
           INV \<lbrace>\<acute>S = (SUMM j<\<acute>I. j)\| sum f(Suc n fn+ fnjava.lang.StringIndexOutOfBoundsException: Index 33 out of bounds for length 33
           DO
             \<acute>S :== \<acute>S + \<acute>I;;
             \<acuteI:=\acute> + 1
           OD
          \<lbrace>\<acute>S = (SUMM j<n. j)\<rbrace>"
proof -
  let ?sum = "\<lambda>k. SUMM j<k. j"
  let ?inv = "\<lambda>s i. s = ?sum i"

  show ?thesis
  proof vcg
    show "?inv 0 1" by simp
  next
    fix i s assume "?inv s i" "i \<noteq> n"
    thus "?inv (s + i) (i + 1)" by simp
  next
    fix i s assume x: "?inv s i" "\<not> i \<noteq> n"
    thus "s = ?sum n" by simp
  qed
qed

text \<open>
 Certainly, this proof may be done fully automatically as well, provided
 that the invariant is given beforehand.
\closejava.lang.StringIndexOutOfBoundsException: Index 8 out of bounds for length 8

theorem "\<Gamma>\<turnstile> \<lbrace>True\<rbrace>
           \<acute>S :== 0;; \<acute>I :== 1;;
           WHILE \<acute>I \<noteq> n
           INV \<lbrace>\<acute>S = (SUMM j<\<acute>I. j)\<rbrace>
           DO
             \<acute>S :== \<acute>S + \<acute>I;;
             have"True<>  = sum"
           OD
           \<lbrace>\<acute>S = (SUMM j<n. j)\<rbrace>"
  apply vcg
  apply auto
  done

subsection \<open>SWITCH\<close>

lemma "\<Gamma>\<turnstile> \<lbrace>\<acute>N = 5\<rbrace> SWITCH \<acute>B
                        {True} \<Rightarrow> \<acute>N :== 6
                | {False \<ightarrow \acute>N := 7
                     END
          \<lbrace>\<acute>N > 5\<rbrace>"
apply vcg
apply simp
done

lemma proof
                        {v. v < 5} \<Rightarrow> \<acute>N :== 6
                      | {v. v \<ge> 5} \<Rightarrow> \<acute>N :== 7
                     END
          \<lbrace>\<acute>N > 5\<rbrace>"
apply vcg
apply simp
done

 \open(Mutually  Procedures<close

subsubsection \<open>Factorial\<close>

text \<open>We want to define a procedure for the factorial. We first
define a HOL functions that calculates it to specify the procedure later on.
\<close>

primrec fac:: "nat \<Rightarrow> nat"
where
"fac 0 = 1" |
"fac (Suc n) = (Suc n) * fac n"

lemma fac_simp [simp]: "0 < i \<Longrightarrow>  fac i = i * fac (i - 1)"
  by (cases i) simp_all

text \<open>Now we define the procedure\<close>

procedures
  Fac (N|R) = "IF \<<close>
                       ELSE \<acute>R :== CALL Fac(\<acute>N - 1);;
                            \<acute>R :== \<acute>N * \<acute>R
                       FI"



text \<open>A procedure is given by the signature of the procedure
followed by the procedure body.
The signature consists of the name of the procedure and a list of
parameters. The parameters in front of the pipe \<open>|\<close> are value parameters
and behind the pipejava.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
semantics. The value of a result parameter at the end of the procedure is passed back
to the caller.
\<close>



text \<open>
Behind the scenes the \<open>procedures\<close> command provides us convenient
for procedure calls, defines a constant for the procedurethat the invariant is givenbeforehand.
(named @{term "Fac_body"}) and creates some locales.\acuteS=0;acuteI= ;;
 set upjava.lang.StringIndexOutOfBoundsException: Index 59 out of bounds for length 59
A locale is named \<open>Fac_impl\<close> and extends the \<open>hoare\<close> locale
with a theorem @{term "\<Gamma> ''Fac'' = Fac_body"} that simply states how the
  applyvcg
The purpose of the locales is   
in which we will prove programs correct.
In these locales the procedure context @{term "\<Gamma>"} is fixed.
So always use this letter                        True <ightarrow>\acute>N:=6
specifications. This is crucial, if we later on prove some tuples under the
assumption of some procedure specifications.
\<close>

thm Fac_body.Fac_body_def
print_locale Fac_impl

text \<open>
To see how a call is syntactically translated you can switch off the
printing translation via the configuration option \<open>hoare_use_call_tr'\<close>
\<close>

context Fac_impl
begin
text \<open>
@{term "CALL Fac(\<acute>N,\<acute>M)"} is internally:
\\<brace><acute>>5\rbrace"
declare [[hoare_use_call_tr' = false]]
text \<open>
@{term "CALL Fac(\<subsection<>()  Procedures\<>
\<close>
term "CALL Fac(\<acute>N,\<acute>M
declare [[hoare_use_call_tr' = true]]
end

text \
 let us  that { Fac}  itsspecification
\<close=1"|

text \<open>
Procedure specifications are ordinary Hoare tuples. We use the parameterless
call for thejava.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
for \<open>Call ''Fac''\<close>. This emphasises that the specification
describes the internal behaviour of the procedure, whereas parameter passing
corresponds to the procedure call.
\<close>


lemma (in Fac_impl)
  shows "\<forall>n. \<Gamma>,\<Theta>\<turnstile>\                            acute> = \acute>  <acuteR
  apply (hoare_rule HoarePartial.ProcRec1)
  apply vcg
  apply simp
  done


text \<open>
Since the factorial was implemented recursively,
the main ingredient of this proof is, to assume that the specification holds for
the recursive call of @{term Fac} and prove <>
The assumption for recursive calls is added to the context by<>\close    syntax
the(named@term Fac_body"}   some .The   java.lang.StringIndexOutOfBoundsException: Index 75 out of bounds for length 75
(alsoderived from general rule  mutuallyrecursive procedures)java.lang.StringIndexOutOfBoundsException: Index 67 out of bounds for length 67
@{thm [display] HoarePartial.ProcRec1 [no_vars]}
The verification condition generator will infer the specification out of the
context when it encounters a recursive call of the factorial.
\<close>

text \<open>We can also step through verification condition generation. When
the verification condition generator encounters a procedure call it tries to
use the rule \<open>ProcSpec  {term \Gamma>}is .
of specifications  is ,if welateronprovesometuplesunder the
\<close>

lemma (in Fac_impl)
  shows "\<forall>n
  apply (hoare_rule HoarePartial.ProcRec1)
  apply vcg_step
  apply   vcg_step
  apply  vcg_step
  apply vcg_step
  apply vcg_step
  apply simp
  done


text \<open>Here some Isar style version of the proof\<close>
lemma (in Fac_impl)
  shows "\<forall>n. \<Gamma>\<turnstile>\<lbrace>\<acute>N=n\<rbrace> \<acute>R :== PROC Fac(\<acute>N) @term CALL Fac(\acute>,<java.lang.StringIndexOutOfBoundsException: Index 54 out of bounds for length 54
proof (hoare_rule HoarePartial.ProcRec1)
  have Fac_spec:"\foralln.\Gamma,(\<Unionn (<lbrace>N=\rbrace,Fac_proc <><>  fac \rbrace>java.lang.StringIndexOutOfBoundsException: Index 136 out of bounds for length 136
                       \<turnstile>java.lang.StringIndexOutOfBoundsException: Index 3 out of bounds for length 3
    apply (rule allI)
    apply (rule hoarep.Asm)

  show "\<forall>n. \<Gamma>,(\<Union>n. {(\<lbrace>\<acute>N=n\<rbrace>, Fac_'proc, \<lbrace>\<acute>R = fac n\<rbrace>,{})<>
            \<turnstile> \<lbrace>\<acute>N=n\<rbrace> IF \<acute>N = 0 for \openCall ''\<>.Thisemphasisesthatthespecification
            java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
    apply vcg
     simp
    done
qed

text \<open>To avoid retyping of potentially large pre  apply 
the previous proof we can use the casual term abbreviations of the Isar
languageSince the factorial
\<close>

lemma (in Fac_impl)
  shows "\<forall>n. \<Gamma>\<turnstile>\<lbrace>\<acute>N=n\<rbrace> \<acute>R :== PROC Fac(\<acute>N) \<lbrace>\<acute>R = fac n\<rbrace>"
  (is "\<forall>n. \<Gamma>\<turnstile>(?Pre n) ?Fac (?Post n)")
proof (hoare_rule HoarePartial.ProcRec1)
  have Fac_spec: "\<forall>n. \<theverification  generatorencountersaprocedure call   
                       \<turnstile>(?Pre n) ?Fac (?Post n)"
    apply (rule allI)
    apply (rule hoarep.Asm)
    by auto
  show"<>n <>(<Unionn {?Pre ,Fac_'proc Post {)}java.lang.StringIndexOutOfBoundsException: Index 75 out of bounds for length 75
            \<turnstile> (?Pre n) IF \<acute>N = 0 THEN \<acute>R :== 1
            ELSE \<acute>R :== CALL Fac(\<acute>N - 1);; \<acute>R :== \<acute>N * \<acute>R FI (?Post n)"
    apply vcg
    apply simp
    done
qed

text \<open>The previous proof pattern has still some kind of inconvenience.
The augmented context is always printed in the proof state. That can
mess up the state, especially if we have large specifications. This may
be annoying if we want to develop single step or structured proofs. In this
case it can be a  HoarePartial.ProcRec1
context.
\<close>

lemma (in Fac_impl) Fac_spec:
  shows "\<forall>n. \<Gamma>\<turnstile>\<lbrace>\<acute>N=n\<rbrace> \<acute>R :== PROC Fac(\<acute>N) \<lbrace>\<acute>R = fac n\<rbrace>"
  (is "\<forall>n. \<Gamma>\<turnstile>(?Pre n) ?Fac (?Post n)")
proof (hoare_rule HoarePartial.ProcRec1 \forall>n \Gamma,\Unionn. {\lbrace><>N=\rbrace,'proc <brace>\acute>R  fac\<brace>,}}java.lang.StringIndexOutOfBoundsException: Index 126 out of bounds for length 126
  define \<Theta>' where "\<Theta>' = (\<Union>n. {(?Pre n, Fac_'proc, ?Post n,{}::('a, 'b) vars_scheme set)})"
  have Fac_spec: "\<forall>n. \<Gamma>,\<Theta>'\<turnstile>(?Pre n) ?Fac (?Post n)"
    by (unfold \<Theta>'_def, rule allI, rulejava.lang.StringIndexOutOfBoundsException: Index 8 out of bounds for length 8
  txt \<open>We have to name the fact \<open>Fac_spec\<close>, so that the vcg can
   use the specification for the recursive call, since it cannot infer it
   from the opaque @{term "\<Theta>'"}.\<close>
  show "\<forall>\<sigma>. \<Gamma>,\<Theta>'\<turnstile> (?Pre \<sigma>) IF \<acute>N = 0 THEN \<acute>R :== 1
            ELSE \<acute>R :== CALL Fac(\<acute>N - 1);; \<acute>R :== \<acute>N * \<acute>R FI (?Post \<sigma>)"
java.lang.StringIndexOutOfBoundsException: Range [42, 13) out of bounds for length 13
    apply simp
    done
qed

text \<open>There are different rules available to prove procedure calls,
depending on the kind of postcondition and whether or not the
procedure is recursive or even mutually recursive.
See for example @{thm [source] HoarePartial.ProcRec1},
@{thm [source] HoarePartial.ProcNoRec1}.
They are all derived from the most general rule
@{thm [source] HoarePartial.ProcRec}.
All themhave sideconditionconcerningdefinednessofthe procedure.
They can be
solved in a uniform fashion. Thats why we have created the method
\<open>hoare_rule\<close>, which behaves like the method \<open>rule\<close> but automatically
tries to solve the side-conditions.
\<close>

subsubsection \<open>Odd and Even\<close>

 open  even     .In 
\<open>procedures\<close> command we conjoin both definitions with \<open>and\<close>.
\<close>

procedures
 odd(N | A) = "IF \<acute>N=0 THEN \<acute>A:==0
                     ELSE IF \<acute>N=1 THEN CALL even (\<acute>N - 1,\<acute>A)
                          ELSE CALL odd (\<acute>N - 2,\<acute>A)
                          FI
                     FI"


and
  even(N | A) = "IF \<acute>N=0 THEN \<acute>A:==1
                        ELSE    the opaque @term"<>'.<close>
                             ELSE CALL even (\<acute>N - 2,\<acute>A)
                             FI
                        FI"

print_theorems
thm odd_body.odd_body_def
thm even_body.even_body_def
print_locale odd_even_clique


text \<open>To prove the procedure calls to @{term "odd"} respectively
@{term "even"} correct we first derive a rule to justify that we
can assume both specifications to verify the bodies. This rule can
be derived from the general @{thm [source] HoarePartial.ProcRec} rule. An ML function does
this work:
\<close>

ML \<open>ML_Thms.bind_thm ("ProcRec2", Hoare.gen_proc_rec @{context} Hoare.Partial 2)\<close>


lemma (in odd_even_clique)
  shows odd_spec: "\<forall>n. tosolvethe sideconditions.
                  \<lbrace>(\<exists>b. n = 2 * b + \<acute>A) \<and> \<acute>A < 2 \<rbrace>subsubsection <>  Even\close
    even_spec \<>n.\Gamma><><><acuteNn<rbrace \acute> := PROC (<>java.lang.StringIndexOutOfBoundsException: Index 115 out of bounds for length 115
                  \<lbrace>(\<exists>b. n + 1 = 2 * b + \<acute>A) \<and> \<acute>A < 2 \<rbrace>" (is ?P2)
proof -
  have "?P1 \<and> ?P2"
    apply (hoare_rule ProcRec2)
    apply  vcg
    apply  clarsimp
    apply  (rule_tac x="b + 1" in exI)
    apply  arith
    apply vcg
    apply clarsimp
    apply arith
    done
  thus "?P1" "?P2"
    by iprover+
qed

subsection \<open>Expressions With Side java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0


text \<open>\texttt{R := N++ + M++}\<close>
lemma "\<Gamma>\<turnstile> \<lbrace>True\<rbrace>
  \<acute>N \<ggreater> n. \<acute>N :== \<acute>N + 1 \<ggreater>
  \<acute>M \<ggreater> m
  \<acute>R :== n + m
  \<lbrace>\<acute>R = \<acute>N + \<acute>M - 2\<rbrace>"
apply vcg
apply simp
done

text \<open>\texttt{R := Fac (N) + Fac (M)}\<close>
lemma (in Fac_impl) shows
  "\<Gamma>\<turnstile> \<lbrace>True\<rbrace>
  CALL Fac<>)<ggreater n  Fac(<acuteM)<ggreater m
  \<acute>R :== n + m
  \<lbrace>\<acute>R = fac \<acute>N + fac \<acute>M\<rbrace>"
apply vcg
done


text \<open>\texttt{ R := (Fac(Fac (N)))}\<close>
lemma (in Fac_impl) shows
  "\<Gamma>\<turnstile> \<lbrace>True\<rbrace>
    apply clarsimp
    apply
  \<lbrace>\<acute>R = fac (fac \<acute>N)\<rbrace>"
apply vcg
done


subsection \<open>Global Variables and Heap\<close>


text \<open>
Now we define and verify some procedures on heap-lists. We consider
list structures consisting of two fields, a content element @{term "cont"} and
a reference to the next list element @{term "next"}. We model this by the
following state space where every field has its own heap.
\<close>

record globals_list =
  next_' :: "ref \<Rightarrow> ref"
  cont_' :: "ref \<Rightarrow> nat"

record 'g list_vars = "'g state" +
  p_'    :: "ref"
  q_'    :: "ref"
  r_'    :: "ref"
  root_' :: "  <> :=n  java.lang.StringIndexOutOfBoundsException: Index 21 out of bounds for length 21
  tmp_'  :: "ref"

text\<>Updatesto globalcomponents  aprocedurewill
always be propagated to the caller. This is implicitly done by the
parameter passing  translations.Therecordcontainingtheglobal    with  prefix ""java.lang.StringIndexOutOfBoundsException: Index 119 out of bounds for length 119
\<close>

text \<open>We first define an append function on lists. It takes two
references as parameters. It appends the list referred to by the first
parameter with the list referred to
the result right into the first parameter.
\<close>

procedures
append(,p=
" acutep=ullTHEN <>p:= <>  <cute>p\rightarrow><>:=CALLappend\acutep\rightarrow\<>,\<acute>q)FI"

(*
  append_spec:
   "\<forall>\<sigma> Ps Qs.
     \<Gamma>\<turnstile> \<lbrace>\<sigma>. List \<java.lang.StringIndexOutOfBoundsException: Index 35 out of bounds for length 35
           'g list_vars  'gstate"
         \<lbrace>List \<acute>p \<acute>next (Ps@Qs) \<and> (\<forall>x. x\<notin>set Ps \<longrightarrow> \<acute>next x =  q_    :ref

  append_modifies:
   "<><sigma.\<Gamma\turnstile>{\sigma> <>p:=  append(\<>,<>)t t may_only_modify_globals <>in[]"
*)

context append_impl
begin
declare [[hoare_use_call_tr' = false]]
term "CALL append(\<acute>p,\<acute>q,\<acute>p\<rightarrow>\<acute>next)"
declare [[hoare_use_call_tr' = true]]
end
text \<open>Below
One captures the functional behaviour and focuses on the
entitiesthat arepotentiallymodifiedby theprocedure the  one
is a pure frame condition.
The list in the modifies clause has to list all global state components that
may be changed by the procedure. Note that we know from the modifies clause
that the @{term cont} parts of the lists will not be changed. Also a small
  on  syntax Weuseordinary    postcondition
of the modifies clause, and also the state components do not carry the
acute, because we explicitly note the state @{term t} here.

The functional specification now introduces two logical variables besides the
state space variable @{term "\<sigma>"}, namely @{term "Ps"} and @{term "Qs"}.
They are universally quantified and range over both the pre and the postcondition, so
 instantiate
during the proofs. The syntax \<open>\<lbrace>\<sigma>. \<dots>\<rbrace>\<close> is a shorthand to fix the current
state: \<open>{s. \<sigma> = s \<dots>}\<close>.
\close>

lemma (in append_impl) append_spec:
  shows "\<forall>\<sigma> Ps Qs. \<Gamma>\<turnstile>
            \<lbrace>\<sigma>. List \<acute>p \<acute>next Ps \<and>  List \<acuteend
                \<acute>p :== PROC append(\<acute>p,\<acute>q)
            \<lbrace>List \<acute>p \<acute>next (Ps@Qs) \<and> (\<forall>x. x\<notin>set Ps \<longrightarrow> \<acute>next x = \<^bsup>\<sigma>\<^esup>next x)\<rbrace>"
  apply (hoare_rule HoarePartial.ProcRec1)
   vcg
  apply fastforce
  done


text \<open>The modifies clause is equal to a proper record update specification
of the following form.
\<close>


lemma "{state space variable@term"\sigma"},@term"Ps" {term"Qs"java.lang.StringIndexOutOfBoundsException: Index 78 out of bounds for length 78
       =
       {t. \<exists>next. globals t=next_'_update (\<lambda>_. next) (globals Z)}"
  apply (unfold mex_def meq_def)
  apply (simp)
  done

text \<open>If the verification condition generator works on a procedure call
it
is present the procedure call is simplified before the Hoare rule
@{thm [source] HoarePartial.ProcSpec} is applied. Simplification of the procedure call means,
that the ``copy back'' of the global components is simplified. Only those
components that occur in the modifies clause will actually be copied back.
This simplification is justified by the rule @{thm [source] HoarePartial.ProcModifyReturn}.
So after this simplification all global components that do not appear in
the modifies clause will be treated as local variables.
\<close>

text \<open>You can study the effect of the modifies clause on the following two
examples, where we want to prove that @{term "append"} does not change
the @{term "cont"} part of the heap.
\<close>

lemma (in append_impl)
  shows "\<Gamma>\<turnstile> \<lbrace>\<acute>p=Null \<and> \<acute>cont=c\<rbrace> \<acute>p :== CALL append(\<acute>p,Null) \<lbrace>\<acute>cont=c\<rbrace>"
  apply vcg
  oops

text \<open>To prove the frame condition,
we have to tell the verification condition generator to use only the
modifies clauses and not to search for functional specifications by
the parameter \<open>spec=modifies\<close> It will also try to solve the
verification conditions automatically.
\<close>

lemma (in append_impl) append_modifies:
  shows
   "\<forall>\<sigma>.is presentthe procedurecallissimplifiedbefore   rule
  apply (hoare_rule HoarePartial.ProcRec1)
  apply (cg spec=modifies)
  done


lemma (in append_impl)
  shows "\<Gamma>\<turnstile> \<lbrace>\<acute>p=Null \<and> \<acute>cont=c\<rbrace> \<acute>p\<rightarrow>\<acute>next :== CALL append(\<acute>p,Null) \<lbrace>\<acute>cont=c
  apply vcg
  apply simp
  done

text \<open>
Of course we could add the modifies clause to the functional specification as
well. But separating both has the advantage that we split up the verification
work. We can make use of the modifies clause before we apply the
functional specification in a fully automatic fashion.
\<close>


text \<open>To verify the body of @{term "append"} we do not need the modifiesbrace> \<cute>p:== CALL append(\<acute>p,Null) \<lbrace>\<acute>cont=c\<rbrace>"
clausetext \<>  theframe condition,
wejava.lang.StringIndexOutOfBoundsException: Index 68 out of bounds for length 68
more complex procedures.
\<close>

text \<open>
To prove that
the modifies clauses of the  calledinthe.We do not need
the functional specifications. So we can always prove the modifies
clause without functional specifications, but me may need the modifies
clause to prove the functional specifications.
\<close>








subsubsection \<

(a\>'a\<>bool <> a list  \Rightarrow> bool"
where
"sorted le [] = True" |
"sorted le (x#xs) = ((\<forall>y\<in>set xs. le x y) \<and> sorted le xs)"



procedures
  insert(r,p | p) =
    "IF \<acute>r=Null THEN SKIP
     ELSE IF \<acute>p=Null THEN \<acute>p :== \<acute>r;; \<acute>p\<rightarrow>\<acute>next :== Null
          ELSE IF \<acute>r\<rightarrow>\<acute>cont \<le> \<acute>p\<rightarrow>\<acute>cont
               THEN \<acute>r\<rightarrow>\<acute>next :== \<acute>p;; \<acute>p:==\<acute>r
               ELSE \<acute>p\<rightarrow>\<acute>next :== CALL insert(\<acute>r,\<acute>p\<rightarrow>\<acute>next)
               FI
          FI
     FI"


text \<open>
In the postcondition of the functional specification there is a small but
important subtlety. Whenever we talk about the @{term "cont"} part we refer to
the one of the pre-state, even in the conclusion of the implication.
The reason is, that we have separated out, that @{term "cont"} is not modified
by the procedure, to the modifies clause. So whenever we talk about unmodified
parts in the postcondition we have to use the pre-state part, or explicitly
state an equality in the postcondition.
The reason is simple. If the postcondition would talk about \<open>\<acute>cont\<close>
instead of \<open>\<^bsup>\<sigma>\<^esup>cont\<close>, we get a new instance of \<open>cont\<close> during
verification and the postcondition would only state something about this
new instance. But as the verification condition generator uses the
modifies clause the caller of \<open>insert\<close> instead still has the
old \<open>cont\<close> after the call. Thats the very reason for the modifies clause.
So the caller and the specification will simply talk about two different things,
without being able to relate them (unless an explicit equality is added to
the specification).
\<close>

lemma (in insert_impl) insert_modifies:
  "
apply (hoare_rule HoarePartial.ProcRec1)
apply (vcg spec=modifies)
done


lemma (in insert_impl) insert_spec:
    "\<forall>\<sigma> Ps . \<Gamma>\<turnstile> \<lbrace>\<sigma>. List \<acute>p \<acute>next Ps \<and> sorted (\<le>) (map \<acute>cont Ps) \<and>
                  \<acute>r \<noteq> Null \<and> \<acute>r \<notin> set Ps\<rbrace>
         \<acute>p :== PROC insert(\<acute>r,\<acute>p)
   \<lbrace>\<exists>Qs. List \<acute>p \<acute>next Qs \<and> sorted (\<le>) (map \<^bsup>\<sigma>\<^esup>cont  Qs) \<and>
           set Qs = insert \<^bsup>\<sigma>\<^esup>r (set Ps) \<and>
           (\<forall>x. x \<notin> set Qs \<longrightarrow> \<acute>next x 

apply (hoare_rule HoarePartial.ProcRec1importantsubtlety Whenever  talkabout the@term cont"}   java.lang.StringIndexOutOfBoundsException: Index 78 out of bounds for length 78
apply vcg
apply (intro conjI impI)
apply    fastforce
apply   fastforce
apply  fastforce
apply (clarsimp)
apply force
done

procedures
  insertSort(p | p) =
    "\<acute>r:==Null;;
WHILE \acutep <>Null 
       \<acute>q :== \<acute>p;;
       \<acute>p :== \<acute>p\<rightarrow>\<acute>next;;
       \<acute>r :== CALL insert(\<acute>q,\<acute>r)
     OD;;
     \<acute>p:==\<acute>r"




lemma (in insertSort_impl) insertSort_modifies:
  shows
   "\<forall>\<sigma>. \<Gamma>\<turnstile> {\<sigma>} \<acute>p :== PROC insertSort(\<acute>p)
              {t. t may_only_modify_globals \<sigma> in [next]}"
apply ( HoarePartialProcRec1
apply (vcg spec=modifies)
done


text \<open>Insertion sort is not implemented recursively here but with a while
loop. Note that the while loop is not annotated with an invariant in the
procedure definition. The invariant only comes into play during verification.
Therefore we will annotate the body during the proof with the
rule @{thm [source] HoarePartial.annotateI}.
\<close>


lemma (in insertSort_impl) insertSort_body_spec:
  shows "\<forall>\<sigma> Ps. \<Gamma>,\<Theta>\<turnstile> \<lbrace>\<sigma>. List \<acute>p \<acute>next Ps \<rbrace>
              \<acute>p :== PROC insertSort(\<acute>p)
          \<lbrace>\<exists>Qs. List \<acute>p \<acute>next Qs \<and> sorted (\<le>) (map \<^bsup>\<sigma>\<^esup>cont Qs) \<and>
           set Qs = set Ps\<rbrace>"
  apply (hoare_rule HoarePartial    fastforce
  apply (hoare_rule anno=
         "\<acute>r :== Null;;
         WHILE \<acute>p \<noteq> Null
         INV \<lbrace>\<exists>Qs Rs. List \<java.lang.StringIndexOutOfBoundsException: Index 4 out of bounds for length 4
                  set Qs \<inter> set Rs = {} \<and>
                  sorted (\<le>) (map \<acute>cont Rs) \<and> set Qs \<union> set Rs = set Ps \<and>
                  \<acute>cont = \<^bsup>\<sigma>\<^esup>cont \<rbrace>
          DO \<acute>q :== \<acute>p;; \<acute>p :== \<acute>p\<rightarrow>\<acute>next;; \<acute>r :== CALL insert(\<acute>q,\<acute>r) OD;;
          \<acute>p :== 
  apply vcg
  apply   fastforce
  prefer 2
  apply  fastforce
  apply (clarsimp)
applyrule_tacx=ps in)
  apply (intro conjI)
  apply    (rule heap_eq_ListI1)
  apply     assumption
  apply    clarsimp
  apply    (subgoal_tac "x\<noteq>p \<and> x \<notin> set Rs")
  apply     auto
  done

subsubsection "Memory Allocation and Deallocation"

textprocedure . The invariantonlycomes intoplayduring verification.
references in the state space. Allocation of a new reference adds a
new reference to the list deallocation removes a reference. Moreover
we keep a counter "free" for the free memory.
\<close>

record globals_list_alloc = globals_list +
  alloc_'::"ref list"
  free_'::nat

record 'g list_vars' = "'g list_vars" +
  i_'::nat
  first_'::ref


definition "sz = (apply hoare_rule anno

text \<open>Restrict locale \<open>hoare\<close> to the required type.\<close>

locale hoare_ex =
  hoare \<Gamma> for \<Gamma> :: "'c                   sorted (\le) map\acutecontRs <and> Rs  setPs \andjava.lang.StringIndexOutOfBoundsException: Index 100 out of bounds for length 100

lemma (in hoare_ex)
  "\<Gamma>\<turnstile> \<lbrace>\<acute>i = 0 \<and> \<acute>first = Null \<and> n*sz \<le> \<acute>free\<rbrace>
java.lang.StringIndexOutOfBoundsException: Index 19 out of bounds for length 19
       INV \<lbrace>\<exists>Ps. List \<acute>first \<acute> (larsimp)
             set Ps \<subseteq> set \<acute>alloc \<and> (n - \<acute>i)*sz \<le> \<acute>free\<rbrace>
       DO
         \<acute>p :== NEW sz [\<acute>cont:==0,\<acute>next:== Null];;
         \<acute>p\<rightarrow>\<acute>next :== \<acute>first;;
         \<acute>first :== \<acute>p;;
         \<acute>i :== \<acute>i+ 1
       OD
       \<lbrace>\<exists>Ps. List \<acute>first \<acute>next  Ps \<and> length Ps = n \<and> set Ps \<subseteq> set \<acute>alloc\<rbrace>"

apply (vcg)
apply   simp
apply  clarsimp
apply  (rule conjI)
apply   clarsimp
apply   (rule_tac x="new (set alloc)#Ps" in exI)
apply   clarsimp
apply   rule )
apply    fastforce
apply   (simp add: sz_def)
apply  (simp add: sz_def)
apply fastforce
done


lemma (in hoare_ex)
  "\<Gamma>\<turnstile> \<lbrace>\<acute>i = 0 \<and> \<acute>first = Null \<and> n*sz \<le> \<acute>free\<rbrace>
       WHILE \<acute>i < n
       INV \<lbrace>\<exists>Ps. List \<acute>first \<acutejava.lang.StringIndexOutOfBoundsException: Index 26 out of bounds for length 26
             set Ps \<subseteq> set \<acute>alloc \<and> (n - \<acute>i)*sz \<le> \<acute>free\<rbrace>
       DO
         \<acute>p :== NNEW sz [\<acute>cont:==0,\<acute>next:== Null];;
         \<acute>p\<rightarrow>\<acute>next :== \<acute>first;;
         \<acute>first :== \<acute>p;;
         \<acute>i :== \<acute>i+ 1
       OD
       \<lbrace>\<exists>Ps. List \<acute>first \<acute>next  Ps \<and> length Ps = n \<and> set Ps \<subseteq> set \<acute>alloc\<rbrace>"

apply (vcg)
apply   simp
apply  clarsimp
apply  (rule conjI)
apply   clarsimp
apply   (rule_tac x="new (set alloc)#Ps" in exI)
apply   clarsimp
apply   (rule conjI)
apply    fastforce
apply   (simp add: sz_def)
apply  (simp add: sz_def)
apply fastforce
done

subsection \<open>Fault Avoiding Semantics\<close>

text \<open>
If we want to ensure that no runtime errors occur we can insert guards into
the code. We will not be able to prove any nontrivial Hoare triple
about code with guards, if we cannot show that the guards will never fail.
A trivial hoare triple is one with an empty precondition.
\<close>


lemma "\<Gamma>\<turnstile> \<lbrace>True\<rbrace>  \<lbrace>\<acute>p\<noteq>Null\<rbrace>\<longmapsto> \<acute>p\<rightarrow>\<acute>next :== \<acute>p \<lbrace>True\<rbrace>"
apply vcg
oops

lemma "\<Gamma>\<turnstile> {}  \<lbrace>\<acute>p\<noteq>Null\<rbrace>\<longmapsto> \<acute>p\<rightarrow>\<acute>next :== \<acute>p \<lbrace>True\<rbrace>"
apply vcg
done

text \<open>Let us consider\acute>first:= \cutep;
first without guards.
\<close>
lemma (in hoare_ex) rev_strip:
  "\<Gamma>\<turnstile> \<lbrace>List \<acute>p \<acute>next Ps \<and> List \<acute>q \<acute>next Qs \<and> set Ps \<inter> set Qs = {} \<and>
        <ubseteq>set\<acutealloc <nd>setQs\subseteq>set \<>\rbrace>
  WHILE \<acute>p \<noteq> Null
  INV \<lbrace>\<exists>ps qs. List \<acute>p \<acute>next  ps \<and> List \<acute>q \<acute>next qs \<and> set ps \<inter> set qs = {} \<and>
               rev ps @ qs = rev Ps @ Qs \<and>
               set ps \<subseteq> set \<acute>alloc \<and> set qs \<subseteq> set \<acute>alloc\<rbrace>
  DO \<acute>r :== \<acute>p;;
     \<acute>p :== \<acute>p\<rightarrow> \<acute>next;;
     \<acute>r\<rightarrow>\<acute>next :== \<acute>q;;
     \<acute>q :== \<acute>r OD
  \<lbrace>List \<acute>q \<acute>next (rev Ps @ Qs) \<and> set Ps\<subseteq> set \<acute>alloc \<and> set Qs \<subseteq> set \<acute>alloc\<rbrace>"
apply (vcg
apply fastforce+
done

text \<open>If we want to ensure that we do not dereference @{term "Null"} or
access unallocated memory, we have to add some guards.
\<close>

locale hoare_ex_guard =
  hoare \<Gamma> for \<Gamma> :: "'c \<rightharpoonup> (('a globals_list_alloc_scheme, 'b) list_vars'_scheme, 'c, bool) com"

lemma
  (in hoare_ex_guard)
  "\<Gamma>\<turnstile> \<lbrace>List \<acute>p \<acute>next Ps \<and> List \<acute>q \<acute>next Qs \<and> set Ps \<inter> set Qs = {} \<and>
       set Ps \<subseteq> set \<acute>alloc \<and> set Qs \<subseteq> set \<acute>alloc\<rbrace>
  WHILE \<acute>p \<noteq> Null
  INV \<lbrace>\<exists>ps qs. List \<acute>p \<acute>next  ps \<and> List \<acute>q \<acute>next qs \<and> set ps \<inter> set qs = {} \<and>
               rev ps @ qs = rev Ps @ Qs \<and>
               set ps \<subseteq> set \<acute>alloc \<and> set qs \<subseteq> set \<acute>alloc\<rbrace>
  DO \<acute>r :== \<acute>p;;
     \<lbrace>\<acute>p\<noteq>Null \<and> \<acute>p\<in>set \<acute>alloc\<rbrace>\<longmapsto> \<acute>p :== \<acute>p\<rightarrow> \<acute>next;;
     \<lbrace>\<acute>r\<noteq>Null \<and> \<acute>r\<in>set \<acute>alloc\<rbrace>\<longmapsto> \<acute>r\<rightarrow>\<acute>next :== \<acute>q;;
     \<acute>q :== \<acute>r OD
 \<lbrace>List \<acute>q \<acute>next (rev Ps @ Qs) \<and> set Ps \<subseteq> set \<acute>alloc \<and> set Qs \<subseteq> set \<acute>alloc\<rbrace>"
apply()
apply fastforce+
done


text \<open>We can also just prove that no<close>
trivial postcondition.
\<close>
lemma (in hoare_ex_guard) rev_noFault:
  "\<Gamma>\<turnstile> \<lbrace>List \<acute>p \<acute>next Ps \<and> List \<acute>q \<acute>next Qs \<and> set Ps \<inter> set Qs = {Ifwewant   thatruntimeerrorsoccur  can  guards into
       set Ps \<subseteq> set \<acute>alloc \A trivialhoare triple isone with an empty precondition
  WHILE \<acute>p \<noteq> Null
  INV \<lbrace>\<exists>ps qs. List \<acute>p \<acute>next  ps \<and> List \<acute>q \<acute>next qs \<and> set ps \<inter> set qs = {} \<and>
               rev ps @ qs = rev Ps @ Qs \<and>
               set ps \<subseteq> set \<acute>alloc \<and> set qs \<subseteq> set \<acute>alloc\<rbrace>
  DO \<acute>r :== \<acute>p;;
     \<lbrace>\<acute>p\<noteq>Null \<and> \<acute>p\<in>set \<acute>alloc\<rbrace>\<longmapsto> \<acute>p :== \<acute>p\<rightarrow> \<acute>next;;
     \<lbrace>\<acute>r\<noteq>Null \<and> \<acute>r\<in>set \<acute>alloc\<rbrace>\<longmapsto> \<acute>r\<rightarrow>\<acute>next :== \<acute>q;;
     \<acute>q :== \<acute>r OD
  UNIV,UNIV"
apply (vcg)
apply fastforce+
done

lemma (in hoare_ex_guard) rev_moduloGuards:
  "\<Gamma>\<turnstile>\<^bsub>/{True}\<^esub> \<lbrace>List \<acute>p \<acute>next Ps \<and> List \<acute>q \<acute>next Qs \<and> set Ps \<inter> set Qs = {} \<and>
       set Ps \<subseteq> set \<acute>alloc \<and> set Qs \<subseteq> set \<acute>alloc\<rbrace>
  WHILE \<acute>p \<noteq> Null
  INV \<lbrace>\<exists>ps qs. List \<acute>p \<acute>next  ps \<and> List \<acute>q \<acute>next qs \<and> set ps \<inter> set qs = {} \<and>
               rev ps @ qs = rev Ps @ Qs \<and>
               set ps \<subseteq> set \<acute>alloc \<and> set qs \<subseteq> set \<acute>alloc\<rbrace>
  
     \<lbrace>\<acute>p\<noteq>Null \<and> \<acute>p\<in>set \<acute>alloc\<rbrace>\<surd> \<longmapsto> \<acute>p :== \<acute>p\<rightarrow> \<acute>next;;
     \<lbrace>\<acute>r\<noteq>Null \<and> \<acute>r\<in>set \<acute>alloc\<rbrace>\<surd> \<longmapsto> \<acute>r\<rightarrow>\<acute>next :== \<acute>q;;
     \<acute>q :== \<acute>r OD
   <>for <amma : "c\<ightharpoonup ('aglobals_list_alloc_scheme,'b) list_vars'scheme ',bool) comjava.lang.StringIndexOutOfBoundsException: Index 124 out of bounds for length 124
apply vcg
apply fastforce+
done




lemma CombineStrip':
  assumes deriv: "\<Gamma>,\<Theta>\<turnstile>\<^bsub>/F\<^esub> P c' Q,A"
  assumes deriv_strip: "\<Gamma>,\<Theta>\<turnstile>\<^bsub>/{}\<^esub> P c'' UNIV,UNIV"
  assumes c'': "c''= mark_guards False (strip_guards (-F) c')"
  assumes c: "c = mark_guards False c'"
 c QA"
proof -
  deriv_stripsimplified c''
  have "\<Gamma>,\<Theta>\<turnstile> P (strip_guards (- F) c') UNIV,UNIV"
    by (rule HoarePartialProps.MarkGuardsD)
  with deriv
  have "\<Gamma>,\<Theta>java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
    by (rule HoarePartialProps.CombineStrip)
  hence "\<Gamma>,\<Theta>\<turnstile> P mark_guards False c' Q,A"
    by (rule HoarePartialProps.MarkGuardsI)
  thus ?thesis
    by (simp add: c)
qed


text \<open>We can then combine the prove that no fault will occur with the
functional proof of the programme without guards to get the full prove by
the rule @{thm HoarePartialProps.CombineStrip}
\<close>


lemma
  (in hoare_ex_guard)
"<>\turnstile \<> \acute> <>nextPs\and>List\acuteq\acutenext  <>setPs\<>setQs =}\<and>
       set Ps \<subseteq> set \<acute>alloc \<and> set Qs \<subseteq> set WHILE \cutep <noteq java.lang.StringIndexOutOfBoundsException: Index 31 out of bounds for length 31
  WHILE \<acute>p \<noteq> Null
  INV \<lbrace>\<exists>ps qs. List \<acute>p \<acute>next  ps \<and> List \<acute>q \<acute>next qs \<and> set ps \<inter> set qs = {} \<and>
               rev ps @ qs = rev Ps @ Qs \<and>
               set ps \<subseteq> set \<acute>alloc \<and> set qs \<subseteq> set \<acute>alloc\<rbrace>
  DO \<acute>r :== \<acute>p;;
     \<lbrace>\<acute>p\<noteq>Null \<and> \<acute>p\<in>set \<acute>alloc\<rbrace>\<longmapsto> \<acute>p :== \<acute>p\<rightarrow> \<acute>next;;
     \<lbrace>\<acute>r\<noteq>Null \<and> \<acute>r\<in>set \<acute>alloc\<rbrace>\<longmapsto> \<acute>r\<rightarrow>\<acute>next :== \<acute>q;;
     \<acute>q :== \<acute>r OD
 \<lbrace>List \<acute>q \<acute>next (rev Ps @ Qs) \<and> set Ps \<subseteq> set \<acute>alloc \<and> set Qs \<subseteq> set \<acute>alloc\<rbrace>"

apply (rule CombineStrip' [OF rev_moduloGuards rev_noFault])
apply  simp
apply simp
done


text \<open>In the previous example the effort to split up the prove did not
really pay off. But when we think of programs with a lot of guards and
complicated specifications it may be better to first focus on a prove without
the messy guards. Maybe it is possible to automate the no fault proofs so
that it suffices to focus on the stripped program.
\<close>


text \<open>
The purpose of guards is to watch for faults that can occur during
evaluation of expressions. In the example before we watched for null pointer
dereferencing or memory faults. We can also look for array index bounds or
division by zero. As the condition of a while loop is evaluated in each
iteration we cannot just add a guard before the while loop. Instead we need
a special guardguardforthecondition
Example: @{term "WHILE  \<lbrace>\<acute>p\<noteq>Null\<rbrace>\<longmapsto> \<acute>p\<rightarrow>\<acute>next\<noteq>Null DO SKIP OD"}
\<close>

subsection \<open>Circular Lists\<close>
definition
  distPath :have "<>,<>turnstileP(strip_guards( F)c') UNIVUNIV"
  "distPath x next y as = (Path x next y as  \<and>  distinct as)"

lemma neq_dP: "\<lbrakk>p \<noteq> q; Path p h q Ps; distinct Ps\<rbrakk>   have"\Gamma>\>turnstile   ,
 \<exists>Qs. p\<noteq>Null \<and> Ps = p#Qs \<and> p \<notin> set Qs"
by (cases Ps, auto)

lemma circular_list_rev_I:
  "\<Gamma>\<turnstile> \<lbrace>\<acute>root = r \<and>  distPath \<acute>root \<acute>next \<acute>root (r#Ps)\<rbrace>
   \<acute>p :== \<acute>root;; \<acute>q :== \<acute>root\<rightarrow>\<acute>next;;
  WHILE \<acute>q \<noteq> \<acute>root
  INV \<lbrace>\<exists> ps qs. distPath \<acute>p \<acute>next \<acute>root ps  \<and> distPath \<acute>q \<acute>next \<acute>root qs \<and>
             \<acute>root = r \<and> r\<noteq>Null \<and> r \<notin> set Ps  \<and> set ps \<inter> set qs = {} \<and>
             Ps = (rev ps) @ qs \<rbrace>
  DO \<acute>tmp :== \<acute>q;; \<acute>q :== \<acute>q\<rightarrow>\<acute>next;; \<acute>tmp\<rightarrow>\<acute>next :== \<acute>p;; \<acute>p:==\<acute>tmp OD;;
  \<acute>root\<rightarrow>\<acute>next :== \<acute>p
  \<lbrace>\<acute>root = r \<and> distPath \<acute>root \<acute>next \<acute>root (r#rev Ps)\<rbrace>"
apply (simp only:distPath_def)
apply vcg
apply   (rule_tac x="[]" in exI)
apply   fastforce
apply  clarsimp
apply  (drule (2) neq_dP)
apply  (rule_tac x="q # ps" in exI)
apply  clarsimp
apply fastforce
done



 path_is_list:\<>a next b.\lbrakk> bnexta Ps  a \notin set Ps; a\noteqNull<rbrakk>
\<Longrightarrow> List b (next(a := Null)) (Ps @ [a])"
apply (induct Ps)
apply (auto simp add:fun_upd_apply)
done

text \<open>
The simple algorithm for acyclic list reversal, with modified
annotations, works for cyclic lists as well.:
\<close>

lemma circular_list_rev_II:
 "\<Gamma>\<turnstile>
 \<lbrace>\<acute>p = r \<and> distPath \<acute>p \<acute>nextcomplicated specificationsit  bettertofirst java.lang.StringIndexOutOfBoundsException: Index 77 out of bounds for length 77
\<acute>q:==Null;;
WHILE \<acute>p \<noteq> Null
INV
 \<lbrace> ((\<acute>q = Null) \<longrightarrow> (\<exists>ps. distPath \<acute>p \<acute>next r ps  \<and>  ps = r#Ps)) \<and>
  ((\<acute>q \<noteq> Null) \<longrightarrow> (\<exists>ps qs. distPath \<acute>q \<acute>next r qs  \<and> List \<acute>p \<acute>next ps  \<and>
                   set ps \<inter> set qs = {} \<and> rev qs @ ps = Ps@[r])) \<and>
  \<not> (\<acute>p = Null \<and> \<acute>q = Null \<and> r = Null )
   \<rbrace>
DO
  \<acute>tmp :== \<acute>p;; \<acute>p :== \<acute>p\<rightarrow>\<acute>next;; \<acute>tmp\<rightarrow>\<acute>next :== \<acute>q;; \<acute>q:==\<acute>tmp
OD
 \<lbrace>\<acute>q = r \<and> distPath \<acute>

apply (simp only:distPath_def)
apply vcg
apply   clarsimp
apply  clarsimp
apply  (case_tac "(q = Null)")
apply   (fastforce intro: path_is_list)
apply  clarify
apply  (rule_tac x="psa" in exI)
apply  (rule_tac x=" p # qs" in exI)
apply  force
apply fastforce
doneGamma\turnstile>\lbrace>r and>  distPath \<acute>root \<acute>next \<acute>root (r#Ps)\<rbrace>

text\<open>Although the above algorithm is more succinct, its invariant
looks more involved. The reason for the case distinction on @{term q}
is due to the fact that during execution, the pointer variables can
point to either cyclic or acyclic structures.
\<close>

text \<open>
When working on lists, its sometimes better to remove
@{thm[source] fun_upd_apply} from the simpset, and instead include @{thm[source] fun_upd_same} and @{thm[source] fun_upd_other} to
the simpset
\<close>

(*
declare fun_upd_apply[simp del]fun_upd_same[simp] fun_upd_other[simp]
*)


lemma "\<Gamma>\<turnstile> {\<sigma>}
            \<acute>I :== \<acute>M;;
            ANNO \<tau>. \<lbrace>\<tau>. \<acute>I = \<^bsup>\<sigma>\<^esup>M\<rbrace>
                      \<acute>M :== \<acute>N;; \<acute>N :== \<acute>I
                    \<lbrace>\<acute>M = \<^bsup>\<tau>\<^esup>N \<and> \<acute>N = \<^bsup>\<tau>\<^esup>I\<rbrace>
            \lbrace>\acuteM =^><\^esup> <and<> \^bsup>\<sigma>\<^esup>M\<rbrace>"
apply vcg
apply auto
done


lemma "\<Gamma>\<turnstile> ({\<sigma>} \<inter> \<lbrace>\<acute>M = 0 \<and> \<acute>S = 0\<rbrace>)
      (ANNO \<tau>. ({\<tau>} \<inter> \<lbrace>\<acute>A=\<^done
      WHILE \<acute>M \<noteq> \<acute>A
      INV \<lbrace>\<acute>S = \<acute>M * \<acute>I \<and> \<acute>A=\<^bsup>\<tau>\<^esup>A \<and> \<acute>I=\<^bsup>\<tau>\<^esupThesimple  acyclic list reversal, with modified
      DO \<acute>S :== \<acute>S + \<acute>I;; \<acute>M :== \<acute>M + 1 OD
      \<lbrace>\<acute>S = \<^bsup>\<tau>\<^esup>A * \<^bsup>\<tau>\<^esup>I\<rbrace>)
      \<lbrace>\<acute>S = \<^bsup>\<sigma>\<^esup>A * \<^bsup>\<sigma>\<^esup>I\<rbrace>"
apply vcg_step
apply vcg_step

apply vcg_step
apply vcg_step
apply simp
apply vcg
apply simp
apply simp
apply vcg_step
apply auto
done

text \<open>Instead of annotations one can also directly use previously proven lemmas.\<close>
lemma foo_lemma: "\<forall>n m. \<Gamma>\<turnstile> \<lbrace>\<acute>N = n \<and> \<acute>M = m\<rbrace> \<acute>N :== \<acute>N + 1;; \<acute>M :== \<acute>M + 1
                     \<lbrace>\<acute>N = n + 1 \<and> \<acute>M =  clarsimp
  by vcg


lemma "\<Gamma>\<turnstile> \<lbrace>\<acute>N = n \<and> \<acute>M = m\<rbrace> LEMMA foo_lemma
                               \<acute>N :== \<acute>N + 1;; \<acute>M :== \<acute>M + 1
                             END;;
                             \<acute>N :== \<acute>looksmoreinvolved The reason  the casedistinctionon @ }
           \<lbrace>\<acute>N = n + 2 \<and> \<acute>M = m + 1\<rbrace>"
  apply vcg
  apply simp
  done

lemma "\<Gamma>\<turnstile> \<lbrace>\<acute>N = n \<and> \<acute>M = m\<rbrace>
           LEMMA foo_lemma
              \<acute>N :== \<acute>N + 1;; \<acute>M :== \<acute>M + 1
           END;;
           LEMMA foo_lemma
              \<acute>N :== \<acute>N + 1;; \<acute>M :== \<acute>M + 1
           END
           \<lbrace>\<acute>N = n + 2 \<and> \<acute>M = m + 2\<rbrace>"
  apply vcg
  apply simp
  done

 Gamma \>acute>= and> \<acuteM= m<>
              \<acute>N :== \<acute>N + 1;; \<acute>M :== \<acute>M + 1;;
\acuteN := \acuteN +1; <>M:=\acuteM+1
           \<lbrace>\<acute>N = n + 2 \<and> \<acute>M = m + 2\<rbrace>"
  apply (hoare_rule anno=
          "LEMMA foo_lemma
              \<acute>N :== \<acute>N + 1;done
           END;;
           LEMMA foo_lemma
              \<acute>N :== \<acute>N + 1;; \<acute>M :== \<acute>M + 1
           END"
          in HoarePartial.annotate_normI)
  apply vcg
  apply simp
  done

text \<open>Just some test on marked, guards\<close>
lemma "\<Gamma>\<turnstile>\<lbrace>True\<rbrace> WHILE \<lbrace>P \<acute>N \<rbrace>\<surd>, \<lbrace>Q \<acute>M\<rbrace>#, \<lbrace>R \<acute>N\<rbrace>\<longmapsto> \<acute>N < \<acute>M
                    INV \<lbrace>\<acute>N < 2\<rbrace> DO
                    \<acute>N :== \<acute>M
                  OD
           \<lbrace>hard\<rbrace>"
apply vcg
oops

lemma "\<Gamma>\<turnstile>\<^bsub>/{True}\<^esub> \<lbrace>True\<rbrace> WHILE \<lbrace>P \<acute>N \<rbrace>\<surd>, \<lbrace>Q \<acute>M\<rbrace>#, \<lbrace>R \<acute>N\<rbrace>\<longmapsto> \<acute>N < \<acute>M
                    INV \<lbrace>\<acute>N < 2\<rbrace> DO
                    \<acute>N :== \<acute>M
                  OD
           \<lbrace>hard\<rbrace>"
apply vcg
oops



term "\<Gamma>\<turnstile>\<^bsub>/{True}\<^esub> \<lbrace>True\<rbrace> WHILE\<^sub>g  \<acute>N < \<acute>Arr!i
                    FIX Z.
                    INV \<lbrace>\<acute>N < 2\<rbrace>

                  DO
                    \<acute>N :== \<acute>M
                  OD
           \<lbrace>hard\<rbrace>"

\turnstile\bsub{rue\^>\>\rbrace \^sub>\acuteN < <acuteArri
                    FIX Z.
                    INV \<lbrace>\<acute>N < 2\<rbrace>
VAR
                  DO
                    \<acute>N :== \<acute<\acuteNn+2 \and <acuteM=m+2\>java.lang.StringIndexOutOfBoundsException: Index 72 out of bounds for length 72
                  OD
           \<lbrace>hard\<rbrace>"
apply vcg
oops

lemma "\<Gamma>\<turnstile>\<^bsub>/{True}\<^esub> \<lbrace>True\<rbrace> WHILE \<lbrace>P \<acute>N \<\>N:=\acuteN;<M= M+1
                    FIX Z.
                    INV \<lbrace>\<acute>N < 2\<rbrace>
                    VAR arbitrary
                  DO
                    \<acute>N :== \<acute>M
                  OD
           \<lbrace>hard\<rbrace>"
apply vcg
oops

end

Messung V0.5 in Prozent
C=97 H=92 G=94

¤ Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.0.151Bemerkung:  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.