src/HOL/TLA/Action.ML
changeset 3807 82a99b090d9d
child 3945 ae9c61d69888
equal deleted inserted replaced
3806:f371115aed37 3807:82a99b090d9d
       
     1 (* 
       
     2     File:	 Action.ML
       
     3     Author:      Stephan Merz
       
     4     Copyright:   1997 University of Munich
       
     5 
       
     6 Lemmas and tactics for TLA actions.
       
     7 *)
       
     8 
       
     9 val act_rews = [pairSF_def RS eq_reflection,unl_before,unl_after,unchanged_def,
       
    10                 pr_con,pr_before,pr_lift,pr_lift2,pr_lift3,pr_all,pr_ex];
       
    11 
       
    12 val action_rews = act_rews @ intensional_rews;
       
    13 
       
    14 qed_goal "actionI" Action.thy "(!!s t. ([[s,t]] |= A)) ==> A"
       
    15   (fn [prem] => [REPEAT (resolve_tac [prem,intI,state2_ext] 1)]);
       
    16 
       
    17 qed_goal "actionD" Action.thy "A ==> ([[s,t]] |= A)"
       
    18   (fn [prem] => [REPEAT (resolve_tac [prem,intD] 1)]);
       
    19 
       
    20 
       
    21 
       
    22 (* ================ Functions to "unlift" action theorems into HOL rules ================ *)
       
    23 
       
    24 (* Basic unlifting introduces a world parameter and applies basic rewrites, e.g.
       
    25    A .= B    gets   ([[s,t]] |= A) = ([[s,t]] |= B)
       
    26    A .-> B   gets   ([[s,t]] |= A) --> ([[s,t]] |= B)
       
    27 *)
       
    28 fun action_unlift th = rewrite_rule action_rews (th RS actionD);
       
    29 
       
    30 (* A .-> B   becomes   A [[s,t]] ==> B [[s,t]] *)
       
    31 fun action_mp th = zero_var_indexes ((action_unlift th) RS mp);
       
    32 
       
    33 (* A .-> B   becomes   [| A[[s,t]]; B[[s,t]] ==> R |] ==> R 
       
    34    so that it can be used as an elimination rule
       
    35 *)
       
    36 fun action_impE th = zero_var_indexes ((action_unlift th) RS impE);
       
    37 
       
    38 (* A .& B .-> C  becomes  [| A[[s,t]]; B[[s,t]] |] ==> C[[s,t]] *)
       
    39 fun action_conjmp th = zero_var_indexes (conjI RS (action_mp th));
       
    40 
       
    41 (* A .& B .-> C  becomes  [| A[[s,t]]; B[[s,t]]; (C[[s,t]] ==> R) |] ==> R *)
       
    42 fun action_conjimpE th = zero_var_indexes (conjI RS (action_impE th));
       
    43 
       
    44 (* Turn  A .= B  into meta-level rewrite rule  A == B *)
       
    45 fun action_rewrite th = (rewrite_rule action_rews (th RS inteq_reflection));
       
    46 
       
    47 (* ===================== Update simpset and classical prover ============================= *)
       
    48 
       
    49 (* Make the simplifier use action_unlift rather than int_unlift 
       
    50    when action simplifications are added.
       
    51 *)
       
    52 fun maybe_unlift th =
       
    53     (case concl_of th of
       
    54          Const("TrueInt",_) $ p 
       
    55            => (action_unlift th
       
    56                   handle _ => int_unlift th)
       
    57        | _ => th);
       
    58 
       
    59 simpset := !simpset setmksimps ((mksimps mksimps_pairs) o maybe_unlift);
       
    60 
       
    61 (* make act_rews be always active -- intensional_rews has been added before *)
       
    62 Addsimps act_rews;
       
    63 
       
    64 use "cladata.ML";        (* local version! *)
       
    65 
       
    66 (* ================================ action_simp_tac ================================== *)
       
    67 
       
    68 (* A dumb simplification tactic with just a little first-order logic:
       
    69    should plug in only "very safe" rules that can be applied blindly.
       
    70    Note that it applies whatever simplifications are currently active.
       
    71 *)
       
    72 fun action_simp_tac ss intros elims i =
       
    73     (asm_full_simp_tac 
       
    74          (ss setloop ((resolve_tac (intros @ [refl,impI,conjI,actionI,allI]))
       
    75 		      ORELSE' (eresolve_tac (elims @ [conjE,disjE,exE_prop]))))
       
    76          i);
       
    77 (* default version without additional plug-in rules *)
       
    78 fun Action_simp_tac i = (action_simp_tac (!simpset) [] [] i);
       
    79 
       
    80 
       
    81 (* ==================== Simplification of abstractions ==================== *)
       
    82 
       
    83 (* Somewhat obscure simplifications, rarely necessary to get rid
       
    84    of abstractions that may be introduced by higher-order unification.
       
    85 *)
       
    86 
       
    87 qed_goal "pr_con_abs" Action.thy "(%w. c)` .= #c"
       
    88   (fn _ => [rtac actionI 1,
       
    89             rewrite_goals_tac (con_abs::action_rews),
       
    90             rtac refl 1
       
    91            ]);
       
    92 
       
    93 qed_goal "pr_lift_abs" Action.thy "(%w. f(x w))` .= f[x`]"
       
    94   (fn _ => [rtac actionI 1,
       
    95               (* give all rewrites to the engine and it loops! *)
       
    96             rewrite_goals_tac intensional_rews,
       
    97             rewtac lift_abs,
       
    98             rewtac pr_lift,
       
    99             rewtac unl_lift,
       
   100             rtac refl 1
       
   101            ]);
       
   102 
       
   103 qed_goal "pr_lift2_abs" Action.thy "(%w. f(x w) (y w))` .= f[x`,y`]"
       
   104   (fn _ => [rtac actionI 1,
       
   105             rewrite_goals_tac intensional_rews,
       
   106             rewtac lift2_abs,
       
   107             rewtac pr_lift2,
       
   108             rewtac unl_lift2,
       
   109             rtac refl 1
       
   110            ]);
       
   111 
       
   112 qed_goal "pr_lift2_abs_con1" Action.thy "(%w. f x (y w))` .= f[#x, y`]"
       
   113   (fn _ => [rtac actionI 1,
       
   114             rewrite_goals_tac intensional_rews,
       
   115             rewtac lift2_abs_con1,
       
   116             rewtac pr_lift2,
       
   117             rewtac unl_lift2,
       
   118             rewtac pr_con,
       
   119             rewtac unl_con,
       
   120             rtac refl 1
       
   121            ]);
       
   122 
       
   123 qed_goal "pr_lift2_abs_con2" Action.thy "(%w. f (x w) y)` .= f[x`, #y]"
       
   124   (fn _ => [rtac actionI 1,
       
   125             rewrite_goals_tac intensional_rews,
       
   126             rewtac lift2_abs_con2,
       
   127             rewtac pr_lift2,
       
   128             rewtac unl_lift2,
       
   129             rewtac pr_con,
       
   130             rewtac unl_con,
       
   131             rtac refl 1
       
   132            ]);
       
   133 
       
   134 qed_goal "pr_lift3_abs" Action.thy "(%w. f(x w) (y w) (z w))` .= f[x`,y`,z`]"
       
   135   (fn _ => [rtac actionI 1,
       
   136             rewrite_goals_tac intensional_rews,
       
   137             rewtac lift3_abs,
       
   138             rewtac pr_lift3,
       
   139             rewtac unl_lift3,
       
   140             rtac refl 1
       
   141            ]);
       
   142 
       
   143 qed_goal "pr_lift3_abs_con1" Action.thy "(%w. f x (y w) (z w))` .= f[#x, y`, z`]"
       
   144   (fn _ => [rtac actionI 1,
       
   145             rewrite_goals_tac intensional_rews,
       
   146             rewtac lift3_abs_con1,
       
   147             rewtac pr_lift3,
       
   148             rewtac unl_lift3,
       
   149             rewtac pr_con,
       
   150             rewtac unl_con,
       
   151             rtac refl 1
       
   152            ]);
       
   153 
       
   154 qed_goal "pr_lift3_abs_con2" Action.thy "(%w. f (x w) y (z w))` .= f[x`, #y, z`]"
       
   155   (fn _ => [rtac actionI 1,
       
   156             rewrite_goals_tac intensional_rews,
       
   157             rewtac lift3_abs_con2,
       
   158             rewtac pr_lift3,
       
   159             rewtac unl_lift3,
       
   160             rewtac pr_con,
       
   161             rewtac unl_con,
       
   162             rtac refl 1
       
   163            ]);
       
   164 
       
   165 qed_goal "pr_lift3_abs_con3" Action.thy "(%w. f (x w) (y w) z)` .= f[x`, y`, #z]"
       
   166   (fn _ => [rtac actionI 1,
       
   167             rewrite_goals_tac intensional_rews,
       
   168             rewtac lift3_abs_con3,
       
   169             rewtac pr_lift3,
       
   170             rewtac unl_lift3,
       
   171             rewtac pr_con,
       
   172             rewtac unl_con,
       
   173             rtac refl 1
       
   174            ]);
       
   175 
       
   176 qed_goal "pr_lift3_abs_con12" Action.thy "(%w. f x y (z w))` .= f[#x, #y, z`]"
       
   177   (fn _ => [rtac actionI 1,
       
   178             rewrite_goals_tac intensional_rews,
       
   179             rewtac lift3_abs_con12,
       
   180             rewtac pr_lift3,
       
   181             rewtac unl_lift3,
       
   182             rewtac pr_con,
       
   183             rewtac unl_con,
       
   184             rtac refl 1
       
   185            ]);
       
   186 
       
   187 qed_goal "pr_lift3_abs_con13" Action.thy "(%w. f x (y w) z)` .= f[#x, y`, #z]"
       
   188   (fn _ => [rtac actionI 1,
       
   189             rewrite_goals_tac intensional_rews,
       
   190             rewtac lift3_abs_con13,
       
   191             rewtac pr_lift3,
       
   192             rewtac unl_lift3,
       
   193             rewtac pr_con,
       
   194             rewtac unl_con,
       
   195             rtac refl 1
       
   196            ]);
       
   197 
       
   198 qed_goal "pr_lift3_abs_con23" Action.thy "(%w. f (x w) y z)` .= f[x`, #y, #z]"
       
   199   (fn _ => [rtac actionI 1,
       
   200             rewrite_goals_tac intensional_rews,
       
   201             rewtac lift3_abs_con23,
       
   202             rewtac pr_lift3,
       
   203             rewtac unl_lift3,
       
   204             rewtac pr_con,
       
   205             rewtac unl_con,
       
   206             rtac refl 1
       
   207            ]);
       
   208 
       
   209 (* We don't add these as default rewrite rules, because they are
       
   210    rarely needed and may slow down automatic proofs.
       
   211 *)
       
   212 val pr_abs_rews = map (fn th => th RS inteq_reflection) 
       
   213                       [pr_con_abs,
       
   214                        pr_lift_abs,pr_lift2_abs,pr_lift2_abs_con1,pr_lift2_abs_con2,
       
   215                        pr_lift3_abs,pr_lift3_abs_con1,pr_lift3_abs_con2,pr_lift3_abs_con3,
       
   216                        pr_lift3_abs_con12,pr_lift3_abs_con13,pr_lift3_abs_con23];
       
   217 
       
   218 (* =========================== square / angle brackets =========================== *)
       
   219 
       
   220 qed_goalw "idle_squareI" Action.thy [square_def]
       
   221    "!!s t. ([[s,t]] |= unchanged v) ==> ([[s,t]] |= [A]_v)"
       
   222    (fn _ => [ Auto_tac() ]);
       
   223 
       
   224 qed_goalw "busy_squareI" Action.thy [square_def]
       
   225    "!!s t. ([[s,t]] |= A) ==> ([[s,t]] |= [A]_v)"
       
   226    (fn _ => [ Auto_tac() ]);
       
   227 
       
   228 qed_goalw "square_simulation" Action.thy [square_def]
       
   229    "[| unchanged f .& .~B .-> unchanged g;   \
       
   230 \      A .& .~unchanged g .-> B              \
       
   231 \   |] ==> [A]_f .-> [B]_g"
       
   232    (fn [p1,p2] => [Auto_tac(),
       
   233                    etac (action_conjimpE p2) 1,
       
   234                    etac swap 3, etac (action_conjimpE p1) 3,
       
   235                    ALLGOALS atac
       
   236                   ]);
       
   237                    
       
   238 qed_goalw "not_square" Action.thy [square_def,angle_def]
       
   239    "(.~ [A]_v) .= <.~A>_v"
       
   240    (fn _ => [ Auto_tac() ]);
       
   241 
       
   242 qed_goalw "not_angle" Action.thy [square_def,angle_def]
       
   243    "(.~ <A>_v) .= [.~A]_v"
       
   244    (fn _ => [ Auto_tac() ]);
       
   245 
       
   246 (* ============================== Facts about ENABLED ============================== *)
       
   247 
       
   248 qed_goalw "enabledI" Action.thy [enabled_def]
       
   249   "A [[s,t]] ==> (Enabled A) s"
       
   250   (fn prems => [ REPEAT (resolve_tac (exI::prems) 1) ]);
       
   251 
       
   252 qed_goalw "enabledE" Action.thy [enabled_def]
       
   253   "[| (Enabled A) s; !!u. A[[s,u]] ==> PROP R |] ==> PROP R"
       
   254   (fn prems => [cut_facts_tac prems 1,
       
   255                 etac exE_prop 1,
       
   256                 resolve_tac prems 1, atac 1
       
   257                ]);
       
   258 
       
   259 qed_goal "notEnabledD" Action.thy
       
   260   "!!G. ~ (Enabled G s) ==> ~ G [[s,t]]"
       
   261   (fn _ => [ auto_tac (action_css addsimps2 [enabled_def]) ]);
       
   262 
       
   263 (* Monotonicity *)
       
   264 qed_goal "enabled_mono" Action.thy
       
   265   "[| (Enabled F) s; F .-> G |] ==> (Enabled G) s"
       
   266   (fn [min,maj] => [rtac (min RS enabledE) 1,
       
   267                     rtac enabledI 1,
       
   268                     etac (action_mp maj) 1
       
   269                    ]);
       
   270 
       
   271 (* stronger variant *)
       
   272 qed_goal "enabled_mono2" Action.thy
       
   273    "[| (Enabled F) s; !!t. (F [[s,t]] ==> G[[s,t]] ) |] ==> (Enabled G) s"
       
   274    (fn [min,maj] => [rtac (min RS enabledE) 1,
       
   275 		     rtac enabledI 1,
       
   276 		     etac maj 1
       
   277 		    ]);
       
   278 
       
   279 qed_goal "enabled_disj1" Action.thy
       
   280   "!!s. (Enabled F) s ==> (Enabled (F .| G)) s"
       
   281   (fn _ => [etac enabled_mono 1, Auto_tac()
       
   282 	   ]);
       
   283 
       
   284 qed_goal "enabled_disj2" Action.thy
       
   285   "!!s. (Enabled G) s ==> (Enabled (F .| G)) s"
       
   286   (fn _ => [etac enabled_mono 1, Auto_tac()
       
   287 	   ]);
       
   288 
       
   289 qed_goal "enabled_conj1" Action.thy
       
   290   "!!s. (Enabled (F .& G)) s ==> (Enabled F) s"
       
   291   (fn _ => [etac enabled_mono 1, Auto_tac()
       
   292            ]);
       
   293 
       
   294 qed_goal "enabled_conj2" Action.thy
       
   295   "!!s. (Enabled (F .& G)) s ==> (Enabled G) s"
       
   296   (fn _ => [etac enabled_mono 1, Auto_tac()
       
   297            ]);
       
   298 
       
   299 qed_goal "enabled_conjE" Action.thy
       
   300   "[| (Enabled (F .& G)) s; [| (Enabled F) s; (Enabled G) s |] ==> PROP R |] ==> PROP R"
       
   301   (fn prems => [cut_facts_tac prems 1, resolve_tac prems 1,
       
   302                 etac enabled_conj1 1, etac enabled_conj2 1]);
       
   303 
       
   304 qed_goal "enabled_disjD" Action.thy
       
   305   "!!s. (Enabled (F .| G)) s ==> ((Enabled F) s) | ((Enabled G) s)"
       
   306   (fn _ => [etac enabledE 1,
       
   307             auto_tac (action_css addSDs2 [notEnabledD] addSEs2 [enabledI])
       
   308            ]);
       
   309 
       
   310 qed_goal "enabled_disj" Action.thy
       
   311   "(Enabled (F .| G)) s = ( (Enabled F) s | (Enabled G) s )"
       
   312   (fn _ => [rtac iffI 1,
       
   313             etac enabled_disjD 1,
       
   314             REPEAT (eresolve_tac [disjE,enabled_disj1,enabled_disj2] 1)
       
   315            ]);
       
   316 
       
   317 qed_goal "enabled_ex" Action.thy
       
   318   "(Enabled (REX x. F x)) s = (EX x. (Enabled (F x)) s)"
       
   319   (fn _ => [ auto_tac (action_css addsimps2 [enabled_def]) ]);
       
   320 	    
       
   321 
       
   322 (* A rule that combines enabledI and baseE, but generates fewer possible instantiations *)
       
   323 qed_goal "base_enabled" Action.thy
       
   324   "[| base_var(v); !!u. v u = c s ==> A [[s,u]] |] ==> Enabled A s"
       
   325   (fn prems => [cut_facts_tac prems 1,
       
   326 		etac baseE 1, rtac enabledI 1,
       
   327 		REPEAT (ares_tac prems 1)]);
       
   328 
       
   329 
       
   330 (* ---------------- enabled_tac: tactic to prove (Enabled A) -------------------- *)
       
   331 (* "Enabled A" can be proven as follows:
       
   332    - Assume that we know which state variables are "base variables";
       
   333      this should be expressed by a theorem of the form "base_var <x,y,z,...>".
       
   334    - Resolve this theorem with baseE to introduce a constant for the value of the
       
   335      variables in the successor state, and resolve the goal with the result.
       
   336    - E-resolve with PairVarE so that we have one constant per variable.
       
   337    - Resolve with enabledI and do some rewriting.
       
   338    - Solve for the unknowns using standard HOL reasoning.
       
   339    The following tactic combines these steps except the final one.
       
   340 *)
       
   341 
       
   342 fun enabled_tac base_vars i =
       
   343     EVERY [(* apply actionI (plus rewriting) if the goal is of the form $(Enabled A),
       
   344 	      do nothing if it is of the form (Enabled A) s *)
       
   345 	   TRY ((rtac actionI i) THEN (SELECT_GOAL (rewrite_goals_tac action_rews) i)),
       
   346 	   rtac (base_vars RS base_enabled) i,
       
   347 	   REPEAT_DETERM (etac PairVarE i),
       
   348 	   (SELECT_GOAL (rewrite_goals_tac action_rews) i)
       
   349 	  ];
       
   350 
       
   351 (* Example of use:
       
   352 
       
   353 val [prem] = goal Action.thy "base_var <x,y,z> ==> $x .-> $Enabled ($x .& (y$ .= #False))";
       
   354 by (REPEAT ((CHANGED (Action_simp_tac 1)) ORELSE (enabled_tac prem 1)));
       
   355 
       
   356 *)