src/HOL/Probability/measurable.ML
changeset 59048 7dc8ac6f0895
parent 59047 8d7cec9b861d
child 59353 f0707dc3d9aa
equal deleted inserted replaced
59047:8d7cec9b861d 59048:7dc8ac6f0895
     4 Measurability prover.
     4 Measurability prover.
     5 *)
     5 *)
     6 
     6 
     7 signature MEASURABLE = 
     7 signature MEASURABLE = 
     8 sig
     8 sig
       
     9   type preprocessor = thm -> Proof.context -> (thm list * Proof.context)
       
    10 
     9   datatype level = Concrete | Generic
    11   datatype level = Concrete | Generic
    10 
    12 
    11   val app_thm_attr : attribute context_parser
    13   val app_thm_attr : attribute context_parser
    12   val dest_thm_attr : attribute context_parser
    14   val dest_thm_attr : attribute context_parser
       
    15   val cong_thm_attr : attribute context_parser
    13   val measurable_thm_attr : bool * (bool * level) -> attribute
    16   val measurable_thm_attr : bool * (bool * level) -> attribute
    14 
    17 
       
    18   val add_del_cong_thm : bool -> thm -> Context.generic -> Context.generic ;
       
    19 
       
    20   val get_all : Context.generic -> thm list
       
    21   val get_dest : Context.generic -> thm list
       
    22   val get_cong : Context.generic -> thm list
       
    23 
    15   val measurable_tac : Proof.context -> thm list -> tactic
    24   val measurable_tac : Proof.context -> thm list -> tactic
    16 
    25 
    17   val simproc : Proof.context -> cterm -> thm option
    26   val simproc : Proof.context -> cterm -> thm option
    18 
    27 
    19   val get_thms : Proof.context -> thm list
    28   val add_preprocessor : string -> preprocessor -> Context.generic -> Context.generic
    20   val get_all : Proof.context -> thm list
    29   val del_preprocessor : string -> Context.generic -> Context.generic
       
    30   val add_local_cong : thm -> Proof.context -> Proof.context
    21 end ;
    31 end ;
    22 
    32 
    23 structure Measurable : MEASURABLE =
    33 structure Measurable : MEASURABLE =
    24 struct
    34 struct
    25 
    35 
       
    36 type preprocessor = thm -> Proof.context -> (thm list * Proof.context)
       
    37 
    26 datatype level = Concrete | Generic;
    38 datatype level = Concrete | Generic;
    27 
    39 
    28 fun eq_measurable_thms ((th1, d1), (th2, d2)) = 
    40 fun eq_measurable_thms ((th1, d1), (th2, d2)) = 
    29   d1 = d2 andalso Thm.eq_thm_prop (th1, th2) ;
    41   d1 = d2 andalso Thm.eq_thm_prop (th1, th2) ;
       
    42 
       
    43 fun merge_dups (xs:(string * preprocessor) list) ys =
       
    44   xs @ (filter (fn (name, _) => is_none (find_first (fn (name', _) => name' = name) xs)) ys) 
    30 
    45 
    31 structure Data = Generic_Data
    46 structure Data = Generic_Data
    32 (
    47 (
    33   type T = {
    48   type T = {
    34     measurable_thms : (thm * (bool * level)) Item_Net.T,
    49     measurable_thms : (thm * (bool * level)) Item_Net.T,
    35     dest_thms : thm Item_Net.T,
    50     dest_thms : thm Item_Net.T,
    36     app_thms : thm Item_Net.T }
    51     app_thms : thm Item_Net.T,
       
    52     cong_thms : thm Item_Net.T,
       
    53     preprocessors : (string * preprocessor) list }
    37   val empty = {
    54   val empty = {
    38     measurable_thms = Item_Net.init eq_measurable_thms (single o Thm.prop_of o fst),
    55     measurable_thms = Item_Net.init eq_measurable_thms (single o Thm.prop_of o fst),
    39     dest_thms = Thm.full_rules,
    56     dest_thms = Thm.full_rules,
    40     app_thms = Thm.full_rules };
    57     app_thms = Thm.full_rules,
       
    58     cong_thms = Thm.full_rules,
       
    59     preprocessors = [] };
    41   val extend = I;
    60   val extend = I;
    42   fun merge ({measurable_thms = t1, dest_thms = dt1, app_thms = at1 },
    61   fun merge ({measurable_thms = t1, dest_thms = dt1, app_thms = at1, cong_thms = ct1, preprocessors = i1 },
    43       {measurable_thms = t2, dest_thms = dt2, app_thms = at2 }) = {
    62       {measurable_thms = t2, dest_thms = dt2, app_thms = at2, cong_thms = ct2, preprocessors = i2 }) = {
    44     measurable_thms = Item_Net.merge (t1, t2),
    63     measurable_thms = Item_Net.merge (t1, t2),
    45     dest_thms = Item_Net.merge (dt1, dt2),
    64     dest_thms = Item_Net.merge (dt1, dt2),
    46     app_thms = Item_Net.merge (at1, at2) };
    65     app_thms = Item_Net.merge (at1, at2),
       
    66     cong_thms = Item_Net.merge (ct1, ct2),
       
    67     preprocessors = merge_dups i1 i2 
       
    68     };
    47 );
    69 );
    48 
    70 
    49 val debug =
    71 val debug =
    50   Attrib.setup_config_bool @{binding measurable_debug} (K false)
    72   Attrib.setup_config_bool @{binding measurable_debug} (K false)
    51 
    73 
    52 val split =
    74 val split =
    53   Attrib.setup_config_bool @{binding measurable_split} (K true)
    75   Attrib.setup_config_bool @{binding measurable_split} (K true)
    54 
    76 
    55 fun map_data f1 f2 f3
    77 fun map_data f1 f2 f3 f4 f5
    56   {measurable_thms = t1,    dest_thms = t2,    app_thms = t3} =
    78   {measurable_thms = t1,    dest_thms = t2,    app_thms = t3,    cong_thms = t4,    preprocessors = t5 } =
    57   {measurable_thms = f1 t1, dest_thms = f2 t2, app_thms = f3 t3 }
    79   {measurable_thms = f1 t1, dest_thms = f2 t2, app_thms = f3 t3, cong_thms = f4 t4, preprocessors = f5 t5}
    58 
    80 
    59 fun map_measurable_thms f = map_data f I I
    81 fun map_measurable_thms f = map_data f I I I I
    60 fun map_dest_thms f = map_data I f I
    82 fun map_dest_thms f = map_data I f I I I
    61 fun map_app_thms f = map_data I I f
    83 fun map_app_thms f = map_data I I f I I
       
    84 fun map_cong_thms f = map_data I I I f I
       
    85 fun map_preprocessors f = map_data I I I I f
    62 
    86 
    63 fun generic_add_del map = 
    87 fun generic_add_del map = 
    64   Scan.lift
    88   Scan.lift
    65     (Args.add >> K Item_Net.update || Args.del >> K Item_Net.remove || Scan.succeed Item_Net.update) >>
    89     (Args.add >> K Item_Net.update || Args.del >> K Item_Net.remove || Scan.succeed Item_Net.update) >>
    66     (fn f => Thm.declaration_attribute (Data.map o map o f))
    90     (fn f => Thm.declaration_attribute (Data.map o map o f))
    67 
    91 
    68 val app_thm_attr = generic_add_del map_app_thms
    92 val app_thm_attr = generic_add_del map_app_thms
    69 
    93 
    70 val dest_thm_attr = generic_add_del map_dest_thms
    94 val dest_thm_attr = generic_add_del map_dest_thms
    71 
    95 
       
    96 val cong_thm_attr = generic_add_del map_cong_thms
       
    97 
    72 fun del_thm th net =
    98 fun del_thm th net =
    73   let
    99   let
    74     val thms = net |> Item_Net.content |> filter (fn (th', _) => Thm.eq_thm (th, th'))
   100     val thms = net |> Item_Net.content |> filter (fn (th', _) => Thm.eq_thm (th, th'))
    75   in fold Item_Net.remove thms net end ;
   101   in fold Item_Net.remove thms net end ;
    76 
   102 
    77 fun measurable_thm_attr (do_add, d) = Thm.declaration_attribute
   103 fun measurable_thm_attr (do_add, d) = Thm.declaration_attribute
    78   (Data.map o map_measurable_thms o (if do_add then Item_Net.update o rpair d else del_thm))
   104   (Data.map o map_measurable_thms o (if do_add then Item_Net.update o rpair d else del_thm))
    79 
   105 
    80 val get_dest = Item_Net.content o #dest_thms o Data.get;
   106 val get_dest = Item_Net.content o #dest_thms o Data.get;
    81 val get_app = Item_Net.content o #app_thms o Data.get;
   107 val get_app = Item_Net.content o #app_thms o Data.get;
       
   108 
       
   109 val get_cong = Item_Net.content o #cong_thms o Data.get;
       
   110 val add_cong = Data.map o map_cong_thms o Item_Net.update;
       
   111 val del_cong = Data.map o map_cong_thms o Item_Net.remove;
       
   112 fun add_del_cong_thm true = add_cong
       
   113   | add_del_cong_thm false = del_cong
       
   114 
       
   115 fun add_preprocessor name f = Data.map (map_preprocessors (fn xs => xs @ [(name, f)]))
       
   116 fun del_preprocessor name = Data.map (map_preprocessors (filter (fn (n, _) => n <> name)))
       
   117 val add_local_cong = Context.proof_map o add_cong
       
   118 
       
   119 val get_preprocessors = Context.Proof #> Data.get #> #preprocessors ;
    82 
   120 
    83 fun is_too_generic thm =
   121 fun is_too_generic thm =
    84   let 
   122   let 
    85     val concl = concl_of thm
   123     val concl = concl_of thm
    86     val concl' = HOLogic.dest_Trueprop concl handle TERM _ => concl
   124     val concl' = HOLogic.dest_Trueprop concl handle TERM _ => concl
    87   in is_Var (head_of concl') end
   125   in is_Var (head_of concl') end
    88 
   126 
    89 fun import_theorem ctxt thm = if is_too_generic thm then [] else
   127 val get_thms = Data.get #> #measurable_thms #> Item_Net.content ;
    90   [thm] @ map_filter (try (fn th' => thm RS th')) (get_dest ctxt);
   128 
    91 
   129 val get_all = get_thms #> map fst ;
    92 val get = Context.Proof #> Data.get #> #measurable_thms #> Item_Net.content ;
   130 
    93 
   131 fun debug_tac ctxt msg f =
    94 val get_all = get #> map fst ;
   132   if Config.get ctxt debug then print_tac ctxt (msg ()) THEN f else f
    95 
       
    96 fun get_thms ctxt =
       
    97   let
       
    98     val thms = ctxt |> get |> rev ;
       
    99     fun get lv = map_filter (fn (th, (rw, lv')) => if lv = lv' then SOME (th, rw) else NONE) thms
       
   100   in
       
   101     get Concrete @ get Generic |>
       
   102     maps (fn (th, rw) => if rw then [th] else import_theorem (Context.Proof ctxt) th)
       
   103   end;
       
   104 
       
   105 fun debug_tac ctxt msg f = if Config.get ctxt debug then print_tac ctxt (msg ()) THEN f else f
       
   106 
   133 
   107 fun nth_hol_goal thm i =
   134 fun nth_hol_goal thm i =
   108   HOLogic.dest_Trueprop (Logic.strip_imp_concl (strip_all_body (nth (prems_of thm) (i - 1))))
   135   HOLogic.dest_Trueprop (Logic.strip_imp_concl (strip_all_body (nth (prems_of thm) (i - 1))))
   109 
   136 
   110 fun dest_measurable_fun t =
   137 fun dest_measurable_fun t =
   111   (case t of
   138   (case t of
   112     (Const (@{const_name "Set.member"}, _) $ f $ (Const (@{const_name "measurable"}, _) $ _ $ _)) => f
   139     (Const (@{const_name "Set.member"}, _) $ f $ (Const (@{const_name "measurable"}, _) $ _ $ _)) => f
   113   | _ => raise (TERM ("not a measurability predicate", [t])))
   140   | _ => raise (TERM ("not a measurability predicate", [t])))
   114 
   141 
   115 fun is_cond_formula n thm = if length (prems_of thm) < n then false else
   142 fun not_measurable_prop n thm = if length (prems_of thm) < n then false else
   116   (case nth_hol_goal thm n of
   143   (case nth_hol_goal thm n of
   117     (Const (@{const_name "Set.member"}, _) $ _ $ (Const (@{const_name "sets"}, _) $ _)) => false
   144     (Const (@{const_name "Set.member"}, _) $ _ $ (Const (@{const_name "sets"}, _) $ _)) => false
   118   | (Const (@{const_name "Set.member"}, _) $ _ $ (Const (@{const_name "measurable"}, _) $ _ $ _)) => false
   145   | (Const (@{const_name "Set.member"}, _) $ _ $ (Const (@{const_name "measurable"}, _) $ _ $ _)) => false
   119   | _ => true)
   146   | _ => true)
   120   handle TERM _ => true;
   147   handle TERM _ => true;
   146         [SOME T1, SOME T, SOME T2])
   173         [SOME T1, SOME T, SOME T2])
   147       end) (cnt_walk t [T])
   174       end) (cnt_walk t [T])
   148     end
   175     end
   149   | cnt_prefixes _ _ = []
   176   | cnt_prefixes _ _ = []
   150 
   177 
   151 val split_countable_tac =
       
   152   Subgoal.FOCUS (fn {context = ctxt, ...} => SUBGOAL (fn (t, i) =>
       
   153     let
       
   154       val f = dest_measurable_fun (HOLogic.dest_Trueprop t)
       
   155       fun cert f = map (Option.map (f (Proof_Context.theory_of ctxt)))
       
   156       fun inst t (ts, Ts) = Drule.instantiate' (cert ctyp_of Ts) (cert cterm_of ts) t
       
   157       val cps = cnt_prefixes ctxt f |> map (inst @{thm measurable_compose_countable})
       
   158     in if null cps then no_tac else debug_tac ctxt (K "split countable fun") (resolve_tac cps i) end
       
   159     handle TERM _ => no_tac) 1)
       
   160 
       
   161 val split_app_tac =
       
   162   Subgoal.FOCUS (fn {context = ctxt, ...} => SUBGOAL (fn (t, i) =>
       
   163     let
       
   164       fun app_prefixes (Abs (n, T, (f $ g))) = let
       
   165             val ps = (if not (loose_bvar1 (g, 0)) then [(f, g)] else [])
       
   166           in map (fn (f, c) => (Abs (n, T, f), c, T, type_of c, type_of1 ([T], f $ c))) ps end
       
   167         | app_prefixes _ = []
       
   168 
       
   169       fun dest_app (Abs (_, T, t as ((f $ Bound 0) $ c))) = (f, c, T, type_of c, type_of1 ([T], t))
       
   170         | dest_app t = raise (TERM ("not a measurability predicate of an application", [t]))
       
   171       val thy = Proof_Context.theory_of ctxt
       
   172       val tunify = Sign.typ_unify thy
       
   173       val thms = map
       
   174           (fn thm => (thm, dest_app (dest_measurable_fun (HOLogic.dest_Trueprop (concl_of thm)))))
       
   175           (get_app (Context.Proof ctxt))
       
   176       fun cert f = map (fn (t, t') => (f thy t, f thy t'))
       
   177       fun inst (f, c, T, Tc, Tf) (thm, (thmf, thmc, thmT, thmTc, thmTf)) =
       
   178         let
       
   179           val inst =
       
   180             (Vartab.empty, ~1)
       
   181             |> tunify (T, thmT)
       
   182             |> tunify (Tf, thmTf)
       
   183             |> tunify (Tc, thmTc)
       
   184             |> Vartab.dest o fst
       
   185           val subst = subst_TVars (map (apsnd snd) inst)
       
   186         in
       
   187           Thm.instantiate (cert ctyp_of (map (fn (n, (s, T)) => (TVar (n, s), T)) inst),
       
   188             cert cterm_of [(subst thmf, f), (subst thmc, c)]) thm
       
   189         end
       
   190       val cps = map_product inst (app_prefixes (dest_measurable_fun (HOLogic.dest_Trueprop t))) thms
       
   191     in if null cps then no_tac
       
   192         else debug_tac ctxt (K ("split app fun")) (resolve_tac cps i)
       
   193           ORELSE debug_tac ctxt (fn () => "FAILED") no_tac end
       
   194     handle TERM t => debug_tac ctxt (fn () => "TERM " ^ fst t ^ Pretty.str_of (Pretty.list "[" "]" (map (Syntax.pretty_term ctxt) (snd t)))) no_tac
       
   195     handle Type.TUNIFY => debug_tac ctxt (fn () => "TUNIFY") no_tac) 1)
       
   196 
       
   197 fun measurable_tac ctxt facts =
   178 fun measurable_tac ctxt facts =
   198   let
   179   let
   199     val imported_thms =
   180     fun debug_fact msg thm () =
   200       (maps (import_theorem (Context.Proof ctxt) o Simplifier.norm_hhf ctxt) facts) @ get_thms ctxt
   181       msg ^ " " ^ Pretty.str_of (Syntax.pretty_term ctxt (prop_of thm))
   201 
   182 
   202     fun debug_facts msg () =
   183     fun IF' c t i = COND (c i) (t i) no_tac
   203       msg ^ " + " ^ Pretty.str_of (Pretty.list "[" "]"
   184 
   204         (map (Syntax.pretty_term ctxt o prop_of) (maps (import_theorem (Context.Proof ctxt)) facts)));
   185     fun r_tac msg =
       
   186       if Config.get ctxt debug
       
   187       then FIRST' o
       
   188         map (fn thm => resolve_tac [thm]
       
   189           THEN' K (debug_tac ctxt (debug_fact (msg ^ "resolved using") thm) all_tac))
       
   190       else resolve_tac
       
   191 
       
   192     val elem_congI = @{lemma "A = B \<Longrightarrow> x \<in> B \<Longrightarrow> x \<in> A" by simp}
       
   193 
       
   194     val dests = get_dest (Context.Proof ctxt)
       
   195     fun prep_dest thm =
       
   196       (if is_too_generic thm then [] else [thm] @ map_filter (try (fn th' => thm RS th')) dests) ;
       
   197     val preprocessors = (("std", prep_dest #> pair) :: get_preprocessors ctxt) ;
       
   198     fun preprocess_thm (thm, raw) =
       
   199       if raw then pair [thm] else fold_map (fn (_, proc) => proc thm) preprocessors #>> flat
       
   200     
       
   201     fun sel lv (th, (raw, lv')) = if lv = lv' then SOME (th, raw) else NONE ;
       
   202     fun get lv = ctxt |> Context.Proof |> get_thms |> rev |> map_filter (sel lv) ;
       
   203     val pre_thms = map (Simplifier.norm_hhf ctxt #> rpair false) facts @ get Concrete @ get Generic
       
   204 
       
   205     val (thms, ctxt) = fold_map preprocess_thm pre_thms ctxt |>> flat
       
   206 
       
   207     fun is_sets_eq (Const (@{const_name "HOL.eq"}, _) $
       
   208           (Const (@{const_name "sets"}, _) $ _) $
       
   209           (Const (@{const_name "sets"}, _) $ _)) = true
       
   210       | is_sets_eq (Const (@{const_name "HOL.eq"}, _) $
       
   211           (Const (@{const_name "measurable"}, _) $ _ $ _) $
       
   212           (Const (@{const_name "measurable"}, _) $ _ $ _)) = true
       
   213       | is_sets_eq _ = false
       
   214 
       
   215     val cong_thms = get_cong (Context.Proof ctxt) @
       
   216       filter (fn thm => concl_of thm |> HOLogic.dest_Trueprop |> is_sets_eq handle TERM _ => false) facts
       
   217 
       
   218     fun sets_cong_tac i =
       
   219       Subgoal.FOCUS (fn {context = ctxt', prems = prems, ...} => (
       
   220         let
       
   221           val ctxt'' = Simplifier.add_prems prems ctxt'
       
   222         in
       
   223           r_tac "cong intro" [elem_congI]
       
   224           THEN' SOLVED' (fn i => REPEAT_DETERM (
       
   225               ((r_tac "cong solve" (cong_thms @ [@{thm refl}])
       
   226                 ORELSE' IF' (fn i => fn thm => nprems_of thm > i)
       
   227                   (SOLVED' (asm_full_simp_tac ctxt''))) i)))
       
   228         end) 1) ctxt i
       
   229         THEN flexflex_tac ctxt
       
   230 
       
   231     val simp_solver_tac = 
       
   232       IF' not_measurable_prop (debug_tac ctxt (K "simp ") o SOLVED' (asm_full_simp_tac ctxt))
       
   233 
       
   234     val split_countable_tac =
       
   235       Subgoal.FOCUS (fn {context = ctxt, ...} => SUBGOAL (fn (t, i) =>
       
   236         let
       
   237           val f = dest_measurable_fun (HOLogic.dest_Trueprop t)
       
   238           fun cert f = map (Option.map (f (Proof_Context.theory_of ctxt)))
       
   239           fun inst (ts, Ts) =
       
   240             Drule.instantiate' (cert ctyp_of Ts) (cert cterm_of ts) @{thm measurable_compose_countable}
       
   241         in r_tac "split countable" (cnt_prefixes ctxt f |> map inst) i end
       
   242         handle TERM _ => no_tac) 1)
   205 
   243 
   206     val splitter = if Config.get ctxt split then split_countable_tac ctxt else K no_tac
   244     val splitter = if Config.get ctxt split then split_countable_tac ctxt else K no_tac
   207 
   245 
   208     fun REPEAT_cnt f n st = ((f n THEN REPEAT_cnt f (n + 1)) ORELSE all_tac) st
   246     val split_app_tac =
   209 
   247       Subgoal.FOCUS (fn {context = ctxt, ...} => SUBGOAL (fn (t, i) =>
   210     val depth_measurable_tac = REPEAT_cnt (fn n =>
   248         let
   211        (COND (is_cond_formula 1)
   249           fun app_prefixes (Abs (n, T, (f $ g))) = let
   212         (debug_tac ctxt (K ("simp " ^ string_of_int n)) (SOLVED' (asm_full_simp_tac ctxt) 1))
   250                 val ps = (if not (loose_bvar1 (g, 0)) then [(f, g)] else [])
   213         ((debug_tac ctxt (K ("single " ^ string_of_int n)) (resolve_tac imported_thms 1)) APPEND
   251               in map (fn (f, c) => (Abs (n, T, f), c, T, type_of c, type_of1 ([T], f $ c))) ps end
   214           (split_app_tac ctxt 1) APPEND
   252             | app_prefixes _ = []
   215           (splitter 1)))) 0
   253     
   216 
   254           fun dest_app (Abs (_, T, t as ((f $ Bound 0) $ c))) = (f, c, T, type_of c, type_of1 ([T], t))
   217   in debug_tac ctxt (debug_facts "start") depth_measurable_tac end;
   255             | dest_app t = raise (TERM ("not a measurability predicate of an application", [t]))
       
   256           val thy = Proof_Context.theory_of ctxt
       
   257           val tunify = Sign.typ_unify thy
       
   258           val thms = map
       
   259               (fn thm => (thm, dest_app (dest_measurable_fun (HOLogic.dest_Trueprop (concl_of thm)))))
       
   260               (get_app (Context.Proof ctxt))
       
   261           fun cert f = map (fn (t, t') => (f thy t, f thy t'))
       
   262           fun inst (f, c, T, Tc, Tf) (thm, (thmf, thmc, thmT, thmTc, thmTf)) =
       
   263             let
       
   264               val inst =
       
   265                 (Vartab.empty, ~1)
       
   266                 |> tunify (T, thmT)
       
   267                 |> tunify (Tf, thmTf)
       
   268                 |> tunify (Tc, thmTc)
       
   269                 |> Vartab.dest o fst
       
   270               val subst = subst_TVars (map (apsnd snd) inst)
       
   271             in
       
   272               Thm.instantiate (cert ctyp_of (map (fn (n, (s, T)) => (TVar (n, s), T)) inst),
       
   273                 cert cterm_of [(subst thmf, f), (subst thmc, c)]) thm
       
   274             end
       
   275           val cps = map_product inst (app_prefixes (dest_measurable_fun (HOLogic.dest_Trueprop t))) thms
       
   276         in if null cps then no_tac
       
   277             else r_tac "split app" cps i ORELSE debug_tac ctxt (fn () => "split app fun FAILED") no_tac end
       
   278         handle TERM t => debug_tac ctxt (fn () => "TERM " ^ fst t ^ Pretty.str_of (Pretty.list "[" "]" (map (Syntax.pretty_term ctxt) (snd t)))) no_tac
       
   279         handle Type.TUNIFY => debug_tac ctxt (fn () => "TUNIFY") no_tac) 1)
       
   280 
       
   281     val single_step_tac =
       
   282       simp_solver_tac
       
   283       ORELSE' r_tac "step" thms
       
   284       ORELSE' (split_app_tac ctxt)
       
   285       ORELSE' splitter
       
   286       ORELSE' (CHANGED o sets_cong_tac)
       
   287       ORELSE' (K (debug_tac ctxt (K "backtrack") no_tac))
       
   288 
       
   289   in debug_tac ctxt (K "start") (REPEAT (single_step_tac 1)) end;
   218 
   290 
   219 fun simproc ctxt redex =
   291 fun simproc ctxt redex =
   220   let
   292   let
   221     val t = HOLogic.mk_Trueprop (term_of redex);
   293     val t = HOLogic.mk_Trueprop (term_of redex);
   222     fun tac {context = ctxt, prems = _ } =
   294     fun tac {context = ctxt, prems = _ } =