src/Provers/induct_method.ML
changeset 18250 dfe5d09514eb
parent 18240 3b72f559e942
child 18259 7b14579c58f2
equal deleted inserted replaced
18249:4398f0f12579 18250:dfe5d09514eb
    17   val localize: thm list
    17   val localize: thm list
    18 end;
    18 end;
    19 
    19 
    20 signature INDUCT_METHOD =
    20 signature INDUCT_METHOD =
    21 sig
    21 sig
       
    22   val fix_tac: Proof.context -> int -> (string * typ) list -> int -> tactic
       
    23   val atomize_term: theory -> term -> term
       
    24   val atomize_tac: int -> tactic
       
    25   val rulified_term: thm -> theory * term
       
    26   val rulify_tac: int -> tactic
    22   val cases_tac: Proof.context -> bool -> term option list list -> thm option ->
    27   val cases_tac: Proof.context -> bool -> term option list list -> thm option ->
    23     thm list -> int -> cases_tactic
    28     thm list -> int -> cases_tactic
    24   val fix_tac: Proof.context -> (string * typ) list -> int -> tactic
       
    25   val induct_tac: Proof.context -> bool -> (string option * term) option list list ->
    29   val induct_tac: Proof.context -> bool -> (string option * term) option list list ->
    26     (string * typ) list list -> term option list -> thm option -> thm list -> int -> cases_tactic
    30     (string * typ) list list -> term option list -> thm option -> thm list -> int -> cases_tactic
    27   val coinduct_tac: Proof.context -> bool -> term option list -> term option list ->
    31   val coinduct_tac: Proof.context -> bool -> term option list -> term option list ->
    28     thm option -> thm list -> int -> cases_tactic
    32     thm option -> thm list -> int -> cases_tactic
    29   val setup: (theory -> theory) list
    33   val setup: (theory -> theory) list
   143 
   147 
   144 (** induct method **)
   148 (** induct method **)
   145 
   149 
   146 (* fix_tac *)
   150 (* fix_tac *)
   147 
   151 
   148 fun revert_skolem ctxt x =
   152 local
   149   (case ProofContext.revert_skolem ctxt x of
   153 
   150     SOME x' => x'
   154 fun goal_prefix k ((c as Const ("all", _)) $ Abs (a, T, B)) = c $ Abs (a, T, goal_prefix k B)
   151   | NONE => Syntax.deskolem x);
   155   | goal_prefix 0 _ = Term.dummy_pattern propT
   152 
   156   | goal_prefix k ((c as Const ("==>", _)) $ A $ B) = c $ A $ goal_prefix (k - 1) B
   153 local
   157   | goal_prefix _ _ = Term.dummy_pattern propT;
       
   158 
       
   159 fun goal_params k (Const ("all", _) $ Abs (_, _, B)) = goal_params k B + 1
       
   160   | goal_params 0 _ = 0
       
   161   | goal_params k (Const ("==>", _) $ _ $ B) = goal_params (k - 1) B
       
   162   | goal_params _ _ = 0;
   154 
   163 
   155 val meta_spec = PureThy.get_thm Pure.thy (Name "meta_spec");
   164 val meta_spec = PureThy.get_thm Pure.thy (Name "meta_spec");
   156 
   165 
   157 fun meta_spec_tac ctxt (x, T) = SUBGOAL (fn (goal, i) => fn st =>
   166 fun meta_spec_tac ctxt n (x, T) = SUBGOAL (fn (goal, i) =>
   158   let
   167   let
   159     val thy = Thm.theory_of_thm st;
   168     val thy = ProofContext.theory_of ctxt;
   160     val cert = Thm.cterm_of thy;
   169     val cert = Thm.cterm_of thy;
   161     val certT = Thm.ctyp_of thy;
   170     val certT = Thm.ctyp_of thy;
   162 
   171 
   163     val v = Free (x, T);
   172     val v = Free (x, T);
       
   173     fun spec_rule prfx (xs, body) =
       
   174       meta_spec
       
   175       |> Thm.rename_params_rule ([ProofContext.revert_skolem ctxt x], 1)
       
   176       |> Thm.lift_rule (cert prfx)
       
   177       |> `(Thm.prop_of #> Logic.strip_assums_concl)
       
   178       |-> (fn pred $ arg =>
       
   179         Drule.cterm_instantiate
       
   180           [(cert (Term.head_of pred), cert (Unify.rlist_abs (xs, body))),
       
   181            (cert (Term.head_of arg), cert (Unify.rlist_abs (xs, v)))]);
       
   182 
       
   183     fun goal_concl k xs (Const ("all", _) $ Abs (a, T, B)) = goal_concl k ((a, T) :: xs) B
       
   184       | goal_concl 0 xs B =
       
   185           if not (Term.exists_subterm (fn t => t aconv v) B) then NONE
       
   186           else SOME (xs, Term.absfree (x, T, Term.incr_boundvars 1 B))
       
   187       | goal_concl k xs (Const ("==>", _) $ _ $ B) = goal_concl (k - 1) xs B
       
   188       | goal_concl _ _ _ = NONE;
   164   in
   189   in
   165     if Term.exists_subterm (fn t => t aconv v) goal then
   190     (case goal_concl n [] goal of
   166       let
   191       SOME concl =>
   167         val P = Term.absfree (x, T, goal);
   192         (compose_tac (false, spec_rule (goal_prefix n goal) concl, 1) THEN' rtac asm_rl) i
   168         val rule = meta_spec
   193     | NONE => (warning ("induct: no variable " ^ ProofContext.string_of_term ctxt v ^
   169           |> Drule.instantiate' [SOME (certT T)] [SOME (cert P), SOME (cert v)]
   194         " to be fixed -- ignored"); all_tac))
   170           |> Thm.rename_params_rule ([revert_skolem ctxt x], 1);
   195   end);
   171       in compose_tac (false, rule, 1) i end
   196 
   172     else all_tac
   197 fun miniscope_tac n i = PRIMITIVE (Drule.fconv_rule
   173   end st);
   198   (Drule.goals_conv (Library.equal i)
   174 
   199     (Drule.forall_conv n (Tactic.rewrite true [Thm.symmetric Drule.norm_hhf_eq]))));
   175 in
   200 
   176 
   201 in
   177 fun fix_tac ctxt xs = EVERY' (map (meta_spec_tac ctxt) (rev (gen_distinct (op =) xs)));
   202 
       
   203 fun fix_tac _ _ [] = K all_tac
       
   204   | fix_tac ctxt n xs = SUBGOAL (fn (goal, i) =>
       
   205      (EVERY' (map (meta_spec_tac ctxt n) xs) THEN'
       
   206       (miniscope_tac (goal_params n goal))) i);
   178 
   207 
   179 end;
   208 end;
   180 
   209 
   181 
   210 
   182 (* add_defs *)
   211 (* add_defs *)
   192 
   221 
   193 
   222 
   194 (* atomize and rulify *)
   223 (* atomize and rulify *)
   195 
   224 
   196 fun atomize_term thy =
   225 fun atomize_term thy =
   197   ObjectLogic.drop_judgment thy o MetaSimplifier.rewrite_term thy Data.atomize [];
   226   MetaSimplifier.rewrite_term thy Data.atomize []
       
   227   #> ObjectLogic.drop_judgment thy;
       
   228 
       
   229 val atomize_tac =
       
   230   Tactic.rewrite_goal_tac Data.atomize;
   198 
   231 
   199 fun rulified_term thm =
   232 fun rulified_term thm =
   200   let val thy = Thm.theory_of_thm thm in
   233   let val thy = Thm.theory_of_thm thm in
   201     Thm.prop_of thm
   234     Thm.prop_of thm
   202     |> MetaSimplifier.rewrite_term thy Data.rulify1 []
   235     |> MetaSimplifier.rewrite_term thy Data.rulify1 []
   203     |> MetaSimplifier.rewrite_term thy Data.rulify2 []
   236     |> MetaSimplifier.rewrite_term thy Data.rulify2 []
   204     |> pair thy
   237     |> pair thy
   205   end;
   238   end;
   206 
   239 
   207 val atomize_tac = Tactic.rewrite_goal_tac Data.atomize;
       
   208 
       
   209 val rulify_tac =
   240 val rulify_tac =
   210   Tactic.rewrite_goal_tac Data.rulify1 THEN'
   241   Tactic.rewrite_goal_tac Data.rulify1 THEN'
   211   Tactic.rewrite_goal_tac Data.rulify2 THEN'
   242   Tactic.rewrite_goal_tac Data.rulify2 THEN'
   212   Tactic.norm_hhf_tac;
   243   Tactic.norm_hhf_tac;
   213 
   244 
   216 
   247 
   217 local
   248 local
   218 
   249 
   219 fun imp_intr i raw_th =
   250 fun imp_intr i raw_th =
   220   let
   251   let
       
   252     val cert = Thm.cterm_of (Thm.theory_of_thm raw_th);
   221     val th = Thm.permute_prems (i - 1) 1 raw_th;
   253     val th = Thm.permute_prems (i - 1) 1 raw_th;
   222     val {thy, maxidx, ...} = Thm.rep_thm th;
   254     val prems = Thm.prems_of th;
   223     val cprems = Drule.cprems_of th;
   255     val As = Library.take (length prems - 1, prems);
   224     val As = Library.take (length cprems - 1, cprems);
   256     val C = Term.dummy_pattern propT;
   225     val C = Thm.cterm_of thy (Var (("C", maxidx + 1), propT));
   257   in th COMP Thm.lift_rule (cert (Logic.list_implies (As, C))) Data.local_impI end;
   226   in th COMP Thm.lift_rule (Drule.list_implies (As, C)) Data.local_impI end;
       
   227 
   258 
   228 in
   259 in
   229 
   260 
   230 fun internalize k th = if k > 0 then internalize (k - 1) (imp_intr k th) else th;
   261 fun internalize k th = if k > 0 then internalize (k - 1) (imp_intr k th) else th;
   231 
   262 
   297 
   328 
   298 (* special renaming of rule parameters *)
   329 (* special renaming of rule parameters *)
   299 
   330 
   300 fun special_rename_params ctxt [[SOME (Free (z, Type (T, _)))]] thm =
   331 fun special_rename_params ctxt [[SOME (Free (z, Type (T, _)))]] thm =
   301       let
   332       let
   302         val x = revert_skolem ctxt z;
   333         val x = ProofContext.revert_skolem ctxt z;
   303         fun index i [] = []
   334         fun index i [] = []
   304           | index i (y :: ys) =
   335           | index i (y :: ys) =
   305               if x = y then x ^ string_of_int i :: index (i + 1) ys
   336               if x = y then x ^ string_of_int i :: index (i + 1) ys
   306               else y :: index i ys;
   337               else y :: index i ys;
   307         fun rename_params [] = []
   338         fun rename_params [] = []
   387       ruleq
   418       ruleq
   388       |> Seq.maps (RuleCases.consume (List.concat defs) facts)
   419       |> Seq.maps (RuleCases.consume (List.concat defs) facts)
   389       |> Seq.maps (fn ((cases, (k, more_facts)), rule) =>
   420       |> Seq.maps (fn ((cases, (k, more_facts)), rule) =>
   390         (CONJUNCTS (ALLGOALS (fn j =>
   421         (CONJUNCTS (ALLGOALS (fn j =>
   391             Method.insert_tac (more_facts @ nth_list defs (j - 1)) j
   422             Method.insert_tac (more_facts @ nth_list defs (j - 1)) j
   392             THEN fix_tac defs_ctxt (nth_list fixing (j - 1)) j))
   423             THEN fix_tac defs_ctxt k (nth_list fixing (j - 1)) j))
   393           THEN' atomize_tac) i st |> Seq.maps (fn st' =>
   424           THEN' atomize_tac) i st |> Seq.maps (fn st' =>
   394             divinate_inst (internalize k rule) i st'
   425             divinate_inst (internalize k rule) i st'
   395             |> Seq.map (rule_instance thy taking)
   426             |> Seq.map (rule_instance thy taking)
   396             |> Seq.maps (fn rule' =>
   427             |> Seq.maps (fn rule' =>
   397               CASES (rule_cases rule' cases)
   428               CASES (rule_cases rule' cases)