src/HOL/Hoare/Hoare.ML
changeset 1465 5d7a7e439cec
parent 1335 5e1c0540f285
child 1558 9c6ebfab4e05
equal deleted inserted replaced
1464:a608f83e3421 1465:5d7a7e439cec
     1 (*  Title: 	HOL/Hoare/Hoare.ML
     1 (*  Title:      HOL/Hoare/Hoare.ML
     2     ID:         $Id$
     2     ID:         $Id$
     3     Author: 	Norbert Galm & Tobias Nipkow
     3     Author:     Norbert Galm & Tobias Nipkow
     4     Copyright   1995 TUM
     4     Copyright   1995 TUM
     5 
     5 
     6 The verification condition generation tactics.
     6 The verification condition generation tactics.
     7 *)
     7 *)
     8 
     8 
    27 \     Spec (%s.q s) c r; Spec (%s.q' s) c' r |] \
    27 \     Spec (%s.q s) c r; Spec (%s.q' s) c' r |] \
    28 \  ==> Spec p (Cond b c c') r"
    28 \  ==> Spec p (Cond b c c') r"
    29   (fn [prem1,prem2,prem3] =>
    29   (fn [prem1,prem2,prem3] =>
    30      [REPEAT (rtac allI 1),
    30      [REPEAT (rtac allI 1),
    31       REPEAT (rtac impI 1),
    31       REPEAT (rtac impI 1),
    32       dresolve_tac [prem1] 1,
    32       dtac prem1 1,
    33       cut_facts_tac [prem2,prem3] 1,
    33       cut_facts_tac [prem2,prem3] 1,
    34       fast_tac (HOL_cs addIs [prem1]) 1]);
    34       fast_tac (HOL_cs addIs [prem1]) 1]);
    35 
    35 
    36 val strenthen_pre = prove_goalw thy [SpecDef]
    36 val strenthen_pre = prove_goalw thy [SpecDef]
    37   "[| !!s. p s ==> p' s; Spec p' c q |] ==> Spec p c q"
    37   "[| !!s. p s ==> p' s; Spec p' c q |] ==> Spec p c q"
    38   (fn [prem1,prem2] =>[cut_facts_tac [prem2] 1,
    38   (fn [prem1,prem2] =>[cut_facts_tac [prem2] 1,
    39 		       fast_tac (HOL_cs addIs [prem1]) 1]);
    39                        fast_tac (HOL_cs addIs [prem1]) 1]);
    40 
    40 
    41 val [iter_0,iter_Suc] = nat_recs IterDef;
    41 val [iter_0,iter_Suc] = nat_recs IterDef;
    42 
    42 
    43 val lemma = prove_goalw thy [SpecDef,WhileDef]
    43 val lemma = prove_goalw thy [SpecDef,WhileDef]
    44   "[| Spec (%s.inv s & b s) c inv; !!s. [| inv s; ~b s |] ==> q s |] \
    44   "[| Spec (%s.inv s & b s) c inv; !!s. [| inv s; ~b s |] ==> q s |] \
    68 (**************************************************************************************************)
    68 (**************************************************************************************************)
    69 
    69 
    70 (* rename_abs:term (von:string,nach:string,trm:term) benennt in trm alle Lambda-Abstraktionen
    70 (* rename_abs:term (von:string,nach:string,trm:term) benennt in trm alle Lambda-Abstraktionen
    71    mit Namen von in nach um *)
    71    mit Namen von in nach um *)
    72 
    72 
    73 fun rename_abs (von,nach,Abs (s,t,trm))	=if von=s
    73 fun rename_abs (von,nach,Abs (s,t,trm)) =if von=s
    74 						then Abs (nach,t,rename_abs (von,nach,trm))
    74                                                 then Abs (nach,t,rename_abs (von,nach,trm))
    75 						else Abs (s,t,rename_abs (von,nach,trm))
    75                                                 else Abs (s,t,rename_abs (von,nach,trm))
    76   | rename_abs (von,nach,trm1 $ trm2)	=rename_abs (von,nach,trm1) $ rename_abs (von,nach,trm2)
    76   | rename_abs (von,nach,trm1 $ trm2)   =rename_abs (von,nach,trm1) $ rename_abs (von,nach,trm2)
    77   | rename_abs (_,_,trm)		=trm;
    77   | rename_abs (_,_,trm)                =trm;
    78 
    78 
    79 (* ren_abs_thm:thm (von:string,nach:string,theorem:thm) benennt in theorem alle Lambda-Abstraktionen
    79 (* ren_abs_thm:thm (von:string,nach:string,theorem:thm) benennt in theorem alle Lambda-Abstraktionen
    80    mit Namen von in nach um. Vorgehen:
    80    mit Namen von in nach um. Vorgehen:
    81 	- Term t zu thoerem bestimmen
    81         - Term t zu thoerem bestimmen
    82 	- Term t' zu t durch Umbenennen der Namen generieren
    82         - Term t' zu t durch Umbenennen der Namen generieren
    83 	- Certified Term ct' zu t' erstellen
    83         - Certified Term ct' zu t' erstellen
    84 	- Thoerem ct'==ct' anlegen
    84         - Thoerem ct'==ct' anlegen
    85 	- Nach der Regel "[|P==Q; P|] ==> Q" wird aus "ct'==ct'" und theorem das Theorem zu ct'
    85         - Nach der Regel "[|P==Q; P|] ==> Q" wird aus "ct'==ct'" und theorem das Theorem zu ct'
    86 	  abgeleitet (ist moeglich, da t' mit t unifiziert werden kann, da nur Umnbenennungen) *)
    86           abgeleitet (ist moeglich, da t' mit t unifiziert werden kann, da nur Umnbenennungen) *)
    87 
    87 
    88 fun ren_abs_thm (von,nach,theorem)	=
    88 fun ren_abs_thm (von,nach,theorem)      =
    89 	equal_elim
    89         equal_elim
    90 		(
    90                 (
    91 			reflexive (
    91                         reflexive (
    92 				cterm_of
    92                                 cterm_of
    93 					(#sign (rep_thm theorem))
    93                                         (#sign (rep_thm theorem))
    94 					(rename_abs (von,nach,#prop (rep_thm theorem)))
    94                                         (rename_abs (von,nach,#prop (rep_thm theorem)))
    95 			)
    95                         )
    96 		)
    96                 )
    97 		theorem;
    97                 theorem;
    98 
    98 
    99 
    99 
   100 (**************************************************************************************************)
   100 (**************************************************************************************************)
   101 (*** Taktik zum Anwenden eines Theorems theorem auf ein Subgoal i durch                         ***)
   101 (*** Taktik zum Anwenden eines Theorems theorem auf ein Subgoal i durch                         ***)
   102 (***  - Umbenennen von Lambda-Abstraktionen im Theorem                                          ***)
   102 (***  - Umbenennen von Lambda-Abstraktionen im Theorem                                          ***)
   105 (**************************************************************************************************)
   105 (**************************************************************************************************)
   106 
   106 
   107 (* - rens:(string*string) list, d.h. es koennen verschiedene Lambda-Abstraktionen umbenannt werden
   107 (* - rens:(string*string) list, d.h. es koennen verschiedene Lambda-Abstraktionen umbenannt werden
   108    - insts:(cterm*cterm) list, d.h. es koennen verschiedene Variablen instanziiert werden *)
   108    - insts:(cterm*cterm) list, d.h. es koennen verschiedene Variablen instanziiert werden *)
   109 
   109 
   110 fun comp_inst_ren_tac rens insts theorem i	=
   110 fun comp_inst_ren_tac rens insts theorem i      =
   111 	let
   111         let
   112 		fun compose_inst_ren_tac [] insts theorem i			=
   112                 fun compose_inst_ren_tac [] insts theorem i                     =
   113 			compose_tac (false,cterm_instantiate insts theorem,nprems_of theorem) i
   113                         compose_tac (false,cterm_instantiate insts theorem,nprems_of theorem) i
   114 		  | compose_inst_ren_tac ((von,nach)::rl) insts theorem i	=
   114                   | compose_inst_ren_tac ((von,nach)::rl) insts theorem i       =
   115 			compose_inst_ren_tac rl insts (ren_abs_thm (von,nach,theorem)) i
   115                         compose_inst_ren_tac rl insts (ren_abs_thm (von,nach,theorem)) i
   116 	in
   116         in
   117 		compose_inst_ren_tac rens insts theorem i
   117                 compose_inst_ren_tac rens insts theorem i
   118 	end;
   118         end;
   119 
   119 
   120 
   120 
   121 (**************************************************************************************************)
   121 (**************************************************************************************************)
   122 (*** Taktik zum Eliminieren des Zustandes waehrend Hoare-Beweisen                               ***)
   122 (*** Taktik zum Eliminieren des Zustandes waehrend Hoare-Beweisen                               ***)
   123 (***    Bsp.: "!!s. s(Suc(0))=0 --> s(Suc(0))+1=1" wird zu "!!s b. b=0 --> b+1=1"               ***)
   123 (***    Bsp.: "!!s. s(Suc(0))=0 --> s(Suc(0))+1=1" wird zu "!!s b. b=0 --> b+1=1"               ***)
   124 (**************************************************************************************************)
   124 (**************************************************************************************************)
   125 
   125 
   126 (* pvars_of_term:term list (name:string,trm:term) gibt die Liste aller Programm-Variablen
   126 (* pvars_of_term:term list (name:string,trm:term) gibt die Liste aller Programm-Variablen
   127    aus trm zurueck. name gibt dabei den Namen der Zustandsvariablen an.
   127    aus trm zurueck. name gibt dabei den Namen der Zustandsvariablen an.
   128 	Bsp.: bei name="s" und dem Term "s(Suc(Suc(0)))=s(0)" (entspricht "c=a")
   128         Bsp.: bei name="s" und dem Term "s(Suc(Suc(0)))=s(0)" (entspricht "c=a")
   129 	      wird [0,Suc(Suc(0))] geliefert (Liste ist i.A. unsortiert) *)
   129               wird [0,Suc(Suc(0))] geliefert (Liste ist i.A. unsortiert) *)
   130 
   130 
   131 fun pvars_of_term (name,trm)	=
   131 fun pvars_of_term (name,trm)    =
   132 	let
   132         let
   133 		fun add_vars (name,Free (s,t) $ trm,vl)	=if name=s
   133                 fun add_vars (name,Free (s,t) $ trm,vl) =if name=s
   134 								then if trm mem vl
   134                                                                 then if trm mem vl
   135 									then vl
   135                                                                         then vl
   136 									else trm::vl
   136                                                                         else trm::vl
   137 								else add_vars (name,trm,vl)
   137                                                                 else add_vars (name,trm,vl)
   138 		  | add_vars (name,Abs (s,t,trm),vl)	=add_vars (name,trm,vl)
   138                   | add_vars (name,Abs (s,t,trm),vl)    =add_vars (name,trm,vl)
   139 		  | add_vars (name,trm1 $ trm2,vl)	=add_vars (name,trm2,add_vars (name,trm1,vl))
   139                   | add_vars (name,trm1 $ trm2,vl)      =add_vars (name,trm2,add_vars (name,trm1,vl))
   140 		  | add_vars (_,_,vl)			=vl
   140                   | add_vars (_,_,vl)                   =vl
   141 	in
   141         in
   142 		add_vars (name,trm,[])
   142                 add_vars (name,trm,[])
   143 	end;
   143         end;
   144 
   144 
   145 (* VarsElimTac: Taktik zum Eliminieren von bestimmten Programmvariablen aus dem Subgoal i
   145 (* VarsElimTac: Taktik zum Eliminieren von bestimmten Programmvariablen aus dem Subgoal i
   146    - v::vl:(term) list	Liste der zu eliminierenden Programmvariablen
   146    - v::vl:(term) list  Liste der zu eliminierenden Programmvariablen
   147    - meta_spec:thm	Theorem, welches zur Entfernung der Variablen benutzt wird
   147    - meta_spec:thm      Theorem, welches zur Entfernung der Variablen benutzt wird
   148 			z.B.: "(!!s x.PROP P(s,x)) ==> (!!s.PROP P(s,x(s)))"
   148                         z.B.: "(!!s x.PROP P(s,x)) ==> (!!s.PROP P(s,x(s)))"
   149    - namexAll:string	Name von    ^                                  (hier "x")
   149    - namexAll:string    Name von    ^                                  (hier "x")
   150    - varx:term		Term zu                                      ^ (hier Var(("x",0),...))
   150    - varx:term          Term zu                                      ^ (hier Var(("x",0),...))
   151    - varP:term		Term zu                                  ^     (hier Var(("P",0),...))
   151    - varP:term          Term zu                                  ^     (hier Var(("P",0),...))
   152    - type_pvar:typ	Typ der Programmvariablen (d.h. 'a bei 'a prog, z.B.: nat, bool, ...)
   152    - type_pvar:typ      Typ der Programmvariablen (d.h. 'a bei 'a prog, z.B.: nat, bool, ...)
   153 
   153 
   154    Vorgehen:
   154    Vorgehen:
   155 	- eliminiere jede pvar durch Anwendung von comp_inst_ren_tac. Dazu:
   155         - eliminiere jede pvar durch Anwendung von comp_inst_ren_tac. Dazu:
   156 	- Unbenennung in meta_spec: namexAll wird in den Namen der Prog.-Var. umbenannt
   156         - Unbenennung in meta_spec: namexAll wird in den Namen der Prog.-Var. umbenannt
   157 	  z.B.: fuer die Prog.-Var. mit Namen "a" ergibt sich
   157           z.B.: fuer die Prog.-Var. mit Namen "a" ergibt sich
   158 		meta_spec zu "(!! s a.PROP P(s,a)) ==> (!! s.PROP P(s,x(s)))"
   158                 meta_spec zu "(!! s a.PROP P(s,a)) ==> (!! s.PROP P(s,x(s)))"
   159 	- Instanziierungen in meta_spec:
   159         - Instanziierungen in meta_spec:
   160 		varx wird mit "%s:(type_pvar) state.s(pvar)" instanziiert
   160                 varx wird mit "%s:(type_pvar) state.s(pvar)" instanziiert
   161 		varP wird entsprechend instanziiert. Beispiel fuer Prog.-Var. "a":
   161                 varP wird entsprechend instanziiert. Beispiel fuer Prog.-Var. "a":
   162 		 -	zu Subgoal "!!s.s(Suc(0)) = s(0) ==> s(0) = 1" bestimme Term ohne "!!s.":
   162                  -      zu Subgoal "!!s.s(Suc(0)) = s(0) ==> s(0) = 1" bestimme Term ohne "!!s.":
   163 			trm0 = "s(Suc(0)) = s(0) ==> s(0) = 1" (s ist hier freie Variable)
   163                         trm0 = "s(Suc(0)) = s(0) ==> s(0) = 1" (s ist hier freie Variable)
   164 		 -	substituiere alle Vorkommen von s(pvar) durch eine freie Var. xs:
   164                  -      substituiere alle Vorkommen von s(pvar) durch eine freie Var. xs:
   165 			trm1 = "s(Suc(0)) = xs ==> xs = 1"
   165                         trm1 = "s(Suc(0)) = xs ==> xs = 1"
   166 		 -	abstrahiere ueber xs:
   166                  -      abstrahiere ueber xs:
   167 			trm2 = "%xs.s(Suc(0)) = xs ==> xs = 1"
   167                         trm2 = "%xs.s(Suc(0)) = xs ==> xs = 1"
   168 		 -	abstrahiere ueber restliche Vorkommen von s:
   168                  -      abstrahiere ueber restliche Vorkommen von s:
   169 			trm3 = "%s xs.s(Suc(0)) = xs ==> xs = 1"
   169                         trm3 = "%s xs.s(Suc(0)) = xs ==> xs = 1"
   170 		 -	instanziiere varP mit trm3
   170                  -      instanziiere varP mit trm3
   171 *)
   171 *)
   172 
   172 
   173 fun VarsElimTac ([],_,_,_,_,_) i					=all_tac
   173 fun VarsElimTac ([],_,_,_,_,_) i                                        =all_tac
   174   | VarsElimTac (v::vl,meta_spec,namexAll,varx,varP,type_pvar) i	=
   174   | VarsElimTac (v::vl,meta_spec,namexAll,varx,varP,type_pvar) i        =
   175 	STATE (
   175         STATE (
   176 		fn state =>
   176                 fn state =>
   177 		comp_inst_ren_tac
   177                 comp_inst_ren_tac
   178 			[(namexAll,pvar2pvarID v)]
   178                         [(namexAll,pvar2pvarID v)]
   179 			[(
   179                         [(
   180 				cterm_of (#sign (rep_thm state)) varx,
   180                                 cterm_of (#sign (rep_thm state)) varx,
   181 				cterm_of (#sign (rep_thm state)) (
   181                                 cterm_of (#sign (rep_thm state)) (
   182 					Abs  ("s",Type ("nat",[]) --> type_pvar,Bound 0 $ v)
   182                                         Abs  ("s",Type ("nat",[]) --> type_pvar,Bound 0 $ v)
   183 				)
   183                                 )
   184 			),(
   184                         ),(
   185 				cterm_of (#sign (rep_thm state)) varP,
   185                                 cterm_of (#sign (rep_thm state)) varP,
   186 				cterm_of (#sign (rep_thm state)) (
   186                                 cterm_of (#sign (rep_thm state)) (
   187 					let
   187                                         let
   188 						val (_,_,_ $ Abs (_,_,trm),_) = dest_state (state,i);
   188                                                 val (_,_,_ $ Abs (_,_,trm),_) = dest_state (state,i);
   189 						val (sname,trm0) = variant_abs ("s",dummyT,trm);
   189                                                 val (sname,trm0) = variant_abs ("s",dummyT,trm);
   190 						val xsname = variant_name ("xs",trm0);
   190                                                 val xsname = variant_name ("xs",trm0);
   191 						val trm1 = subst_term (Free (sname,dummyT) $ v,Syntax.free xsname,trm0)
   191                                                 val trm1 = subst_term (Free (sname,dummyT) $ v,Syntax.free xsname,trm0)
   192 						val trm2 = Abs ("xs",type_pvar,abstract_over (Syntax.free xsname,trm1))
   192                                                 val trm2 = Abs ("xs",type_pvar,abstract_over (Syntax.free xsname,trm1))
   193 					in
   193                                         in
   194 						Abs ("s",Type ("nat",[]) --> type_pvar,abstract_over (Free (sname,dummyT),trm2))
   194                                                 Abs ("s",Type ("nat",[]) --> type_pvar,abstract_over (Free (sname,dummyT),trm2))
   195 					end
   195                                         end
   196 				)
   196                                 )
   197 			)]
   197                         )]
   198 			meta_spec i
   198                         meta_spec i
   199 	)
   199         )
   200 	THEN
   200         THEN
   201 	(VarsElimTac (vl,meta_spec,namexAll,varx,varP,type_pvar) i);
   201         (VarsElimTac (vl,meta_spec,namexAll,varx,varP,type_pvar) i);
   202 
   202 
   203 (* StateElimTac: Taktik zum Eliminieren aller Programmvariablen aus dem Subgoal i
   203 (* StateElimTac: Taktik zum Eliminieren aller Programmvariablen aus dem Subgoal i
   204 
   204 
   205    zur Erinnerung:
   205    zur Erinnerung:
   206     -	das Subgoal hat vor Anwendung dieser Taktik die Form "!!s:('a) state.P(s)",
   206     -   das Subgoal hat vor Anwendung dieser Taktik die Form "!!s:('a) state.P(s)",
   207 	d.h. den Term Const("all",_) $ Abs ("s",pvar --> 'a,_)
   207         d.h. den Term Const("all",_) $ Abs ("s",pvar --> 'a,_)
   208     -   meta_spec hat die Form "(!!s x.PROP P(s,x)) ==> (!!s.PROP P(s,x(s)))"
   208     -   meta_spec hat die Form "(!!s x.PROP P(s,x)) ==> (!!s.PROP P(s,x(s)))"
   209 *)
   209 *)
   210 
   210 
   211 fun StateElimTac i	=
   211 fun StateElimTac i      =
   212 	STATE (
   212         STATE (
   213 		fn state =>
   213                 fn state =>
   214 		let
   214                 let
   215 			val (_,_,_ $ Abs (_,Type ("fun",[_,type_pvar]),trm),_) = dest_state (state,i);
   215                         val (_,_,_ $ Abs (_,Type ("fun",[_,type_pvar]),trm),_) = dest_state (state,i);
   216 			val _ $ (_ $ Abs (_,_,_ $ Abs (namexAll,_,_))) $
   216                         val _ $ (_ $ Abs (_,_,_ $ Abs (namexAll,_,_))) $
   217 			        (_ $ Abs (_,_,varP $ _ $ (varx $ _))) = #prop (rep_thm meta_spec)
   217                                 (_ $ Abs (_,_,varP $ _ $ (varx $ _))) = #prop (rep_thm meta_spec)
   218 		in
   218                 in
   219 			VarsElimTac (pvars_of_term (variant_abs ("s",dummyT,trm)),meta_spec,namexAll,varx,varP,type_pvar) i
   219                         VarsElimTac (pvars_of_term (variant_abs ("s",dummyT,trm)),meta_spec,namexAll,varx,varP,type_pvar) i
   220 		end
   220                 end
   221 	);
   221         );
   222 
   222 
   223 
   223 
   224 
   224 
   225 (*** tactics for verification condition generation ***)
   225 (*** tactics for verification condition generation ***)
   226 
   226 
   230    Zeitpunkt mittels "rtac impI" und "atac" gebunden werden, die Bedingung loest sich dadurch auf. *)
   230    Zeitpunkt mittels "rtac impI" und "atac" gebunden werden, die Bedingung loest sich dadurch auf. *)
   231 
   231 
   232 fun WlpTac i = (rtac SeqRule i) THEN (HoareRuleTac (i+1) false)
   232 fun WlpTac i = (rtac SeqRule i) THEN (HoareRuleTac (i+1) false)
   233 and HoareRuleTac i pre_cond =
   233 and HoareRuleTac i pre_cond =
   234       STATE(fn state =>
   234       STATE(fn state =>
   235 		((WlpTac i) THEN (HoareRuleTac i pre_cond))
   235                 ((WlpTac i) THEN (HoareRuleTac i pre_cond))
   236                 ORELSE
   236                 ORELSE
   237 		(FIRST[rtac SkipRule i,
   237                 (FIRST[rtac SkipRule i,
   238 		       rtac AssignRule i,
   238                        rtac AssignRule i,
   239 		       EVERY[rtac IfRule i,
   239                        EVERY[rtac IfRule i,
   240                              HoareRuleTac (i+2) false,
   240                              HoareRuleTac (i+2) false,
   241                              HoareRuleTac (i+1) false],
   241                              HoareRuleTac (i+1) false],
   242 		       EVERY[rtac WhileRule i,
   242                        EVERY[rtac WhileRule i,
   243                              Asm_full_simp_tac (i+2),
   243                              Asm_full_simp_tac (i+2),
   244                              HoareRuleTac (i+1) true]]
   244                              HoareRuleTac (i+1) true]]
   245 		 THEN
   245                  THEN
   246                  (if pre_cond then (Asm_full_simp_tac i) else (atac i))
   246                  (if pre_cond then (Asm_full_simp_tac i) else (atac i))
   247 		)
   247                 )
   248 	);
   248         );
   249 
   249 
   250 val HoareTac1 =
   250 val HoareTac1 =
   251   EVERY[HoareRuleTac 1 true, ALLGOALS StateElimTac, prune_params_tac];
   251   EVERY[HoareRuleTac 1 true, ALLGOALS StateElimTac, prune_params_tac];
   252 
   252 
   253 val hoare_tac = SELECT_GOAL (HoareTac1);
   253 val hoare_tac = SELECT_GOAL (HoareTac1);