src/HOL/Tools/SMT/smt_replay_methods.ML
changeset 72458 b44e894796d5
parent 69597 ff784d5a5bfb
child 74200 17090e27aae9
equal deleted inserted replaced
72457:2c7f0ef8323a 72458:b44e894796d5
     6 Proof methods for replaying SMT proofs.
     6 Proof methods for replaying SMT proofs.
     7 *)
     7 *)
     8 
     8 
     9 signature SMT_REPLAY_METHODS =
     9 signature SMT_REPLAY_METHODS =
    10 sig
    10 sig
       
    11   (*Printing*)
    11   val pretty_goal: Proof.context -> string -> string -> thm list -> term -> Pretty.T
    12   val pretty_goal: Proof.context -> string -> string -> thm list -> term -> Pretty.T
    12   val trace_goal: Proof.context -> string -> thm list -> term -> unit
    13   val trace_goal: Proof.context -> string -> thm list -> term -> unit
    13   val trace: Proof.context -> (unit -> string) -> unit
    14   val trace: Proof.context -> (unit -> string) -> unit
    14 
    15 
       
    16   (*Replaying*)
    15   val replay_error: Proof.context -> string -> string -> thm list -> term -> 'a
    17   val replay_error: Proof.context -> string -> string -> thm list -> term -> 'a
    16   val replay_rule_error: Proof.context -> string -> thm list -> term -> 'a
    18   val replay_rule_error: string -> Proof.context -> string -> thm list -> term -> 'a
    17 
    19 
    18   (*theory lemma methods*)
    20   (*theory lemma methods*)
    19   type th_lemma_method = Proof.context -> thm list -> term -> thm
    21   type th_lemma_method = Proof.context -> thm list -> term -> thm
    20   val add_th_lemma_method: string * th_lemma_method -> Context.generic ->
    22   val add_th_lemma_method: string * th_lemma_method -> Context.generic ->
    21     Context.generic
    23     Context.generic
    22   val get_th_lemma_method: Proof.context -> th_lemma_method Symtab.table
    24   val get_th_lemma_method: Proof.context -> th_lemma_method Symtab.table
    23   val discharge: int -> thm list -> thm -> thm
    25   val discharge: int -> thm list -> thm -> thm
    24   val match_instantiate: Proof.context -> term -> thm -> thm
    26   val match_instantiate: Proof.context -> term -> thm -> thm
    25   val prove: Proof.context -> term -> (Proof.context -> int -> tactic) -> thm
    27   val prove: Proof.context -> term -> (Proof.context -> int -> tactic) -> thm
    26 
    28 
       
    29   val prove_arith_rewrite: ((term -> int * term Termtab.table ->
       
    30     term * (int * term Termtab.table)) -> term -> int * term Termtab.table ->
       
    31     term * (int * term Termtab.table)) -> Proof.context -> term -> thm
       
    32 
    27   (*abstraction*)
    33   (*abstraction*)
    28   type abs_context = int * term Termtab.table
    34   type abs_context = int * term Termtab.table
    29   type 'a abstracter = term -> abs_context -> 'a * abs_context
    35   type 'a abstracter = term -> abs_context -> 'a * abs_context
    30   val add_arith_abstracter: (term abstracter -> term option abstracter) ->
    36   val add_arith_abstracter: (term abstracter -> term option abstracter) ->
    31     Context.generic -> Context.generic
    37     Context.generic -> Context.generic
    34   val abstract_conj: term -> abs_context -> term * abs_context
    40   val abstract_conj: term -> abs_context -> term * abs_context
    35   val abstract_disj: term -> abs_context -> term * abs_context
    41   val abstract_disj: term -> abs_context -> term * abs_context
    36   val abstract_not:  (term -> abs_context -> term * abs_context) ->
    42   val abstract_not:  (term -> abs_context -> term * abs_context) ->
    37     term -> abs_context -> term * abs_context
    43     term -> abs_context -> term * abs_context
    38   val abstract_unit:  term -> abs_context -> term * abs_context
    44   val abstract_unit:  term -> abs_context -> term * abs_context
       
    45   val abstract_bool:  term -> abs_context -> term * abs_context
       
    46   (* also abstracts over equivalences and conjunction and implication*)
       
    47   val abstract_bool_shallow:  term -> abs_context -> term * abs_context
       
    48   (* abstracts down to equivalence symbols *)
       
    49   val abstract_bool_shallow_equivalence: term -> abs_context -> term * abs_context
    39   val abstract_prop: term -> abs_context -> term * abs_context
    50   val abstract_prop: term -> abs_context -> term * abs_context
    40   val abstract_term:  term -> abs_context -> term * abs_context
    51   val abstract_term:  term -> abs_context -> term * abs_context
       
    52   val abstract_eq: (term -> int * term Termtab.table ->  term * (int * term Termtab.table)) ->
       
    53         term -> int * term Termtab.table -> term * (int * term Termtab.table)
       
    54   val abstract_neq: (term -> int * term Termtab.table ->  term * (int * term Termtab.table)) ->
       
    55         term -> int * term Termtab.table -> term * (int * term Termtab.table)
    41   val abstract_arith: Proof.context -> term -> abs_context -> term * abs_context
    56   val abstract_arith: Proof.context -> term -> abs_context -> term * abs_context
       
    57   (* also abstracts over if-then-else *)
       
    58   val abstract_arith_shallow: Proof.context -> term -> abs_context -> term * abs_context
    42 
    59 
    43   val prove_abstract:  Proof.context -> thm list -> term ->
    60   val prove_abstract:  Proof.context -> thm list -> term ->
    44     (Proof.context -> thm list -> int -> tactic) ->
    61     (Proof.context -> thm list -> int -> tactic) ->
    45     (abs_context -> (term list * term) * abs_context) -> thm
    62     (abs_context -> (term list * term) * abs_context) -> thm
    46   val prove_abstract': Proof.context -> term -> (Proof.context -> thm list -> int -> tactic) ->
    63   val prove_abstract': Proof.context -> term -> (Proof.context -> thm list -> int -> tactic) ->
    47     (abs_context -> term * abs_context) -> thm
    64     (abs_context -> term * abs_context) -> thm
    48   val try_provers:  Proof.context -> string -> (string * (term -> 'a)) list -> thm list -> term ->
    65   val try_provers:  string -> Proof.context -> string -> (string * (term -> 'a)) list -> thm list ->
    49     'a
    66     term -> 'a
    50 
    67 
    51   (*shared tactics*)
    68   (*shared tactics*)
       
    69   val cong_unfolding_trivial: Proof.context -> thm list -> term -> thm
    52   val cong_basic: Proof.context -> thm list -> term -> thm
    70   val cong_basic: Proof.context -> thm list -> term -> thm
    53   val cong_full: Proof.context -> thm list -> term -> thm
    71   val cong_full: Proof.context -> thm list -> term -> thm
    54   val cong_unfolding_first: Proof.context -> thm list -> term -> thm
    72   val cong_unfolding_first: Proof.context -> thm list -> term -> thm
       
    73   val arith_th_lemma: Proof.context -> thm list -> term -> thm
       
    74   val arith_th_lemma_wo: Proof.context -> thm list -> term -> thm
       
    75   val arith_th_lemma_wo_shallow: Proof.context -> thm list -> term -> thm
       
    76   val arith_th_lemma_tac_with_wo: Proof.context -> thm list -> int -> tactic
       
    77 
       
    78   val dest_thm: thm -> term
       
    79   val prop_tac: Proof.context -> thm list -> int -> tactic
    55 
    80 
    56   val certify_prop: Proof.context -> term -> cterm
    81   val certify_prop: Proof.context -> term -> cterm
       
    82   val dest_prop: term -> term
    57 
    83 
    58 end;
    84 end;
    59 
    85 
    60 structure SMT_Replay_Methods: SMT_REPLAY_METHODS =
    86 structure SMT_Replay_Methods: SMT_REPLAY_METHODS =
    61 struct
    87 struct
    75     val concl = Pretty.big_list "proposition:" [Syntax.pretty_term ctxt t]
   101     val concl = Pretty.big_list "proposition:" [Syntax.pretty_term ctxt t]
    76   in Pretty.big_list full_msg (assms @ [concl]) end
   102   in Pretty.big_list full_msg (assms @ [concl]) end
    77 
   103 
    78 fun replay_error ctxt msg rule thms t = error (Pretty.string_of (pretty_goal ctxt msg rule thms t))
   104 fun replay_error ctxt msg rule thms t = error (Pretty.string_of (pretty_goal ctxt msg rule thms t))
    79 
   105 
    80 fun replay_rule_error ctxt = replay_error ctxt "Failed to replay Z3 proof step"
   106 fun replay_rule_error name ctxt = replay_error ctxt ("Failed to replay" ^ name ^ " proof step")
    81 
   107 
    82 fun trace_goal ctxt rule thms t =
   108 fun trace_goal ctxt rule thms t =
    83   trace ctxt (fn () => Pretty.string_of (pretty_goal ctxt "Goal" rule thms t))
   109   trace ctxt (fn () => Pretty.string_of (pretty_goal ctxt "Goal" rule thms t))
    84 
   110 
    85 fun as_prop (t as Const (\<^const_name>\<open>Trueprop\<close>, _) $ _) = t
   111 fun as_prop (t as Const (\<^const_name>\<open>Trueprop\<close>, _) $ _) = t
   219       abstract_bin abstract_prop HOLogic.mk_eq t t1 t2
   245       abstract_bin abstract_prop HOLogic.mk_eq t t1 t2
   220   | abstract_prop t = abstract_not abstract_prop t
   246   | abstract_prop t = abstract_not abstract_prop t
   221 
   247 
   222 fun abstract_arith ctxt u =
   248 fun abstract_arith ctxt u =
   223   let
   249   let
   224     fun abs (t as (c as Const (\<^const_name>\<open>Hilbert_Choice.Eps\<close>, _) $ Abs (s, T, t'))) =
   250     fun abs (t as (Const (\<^const_name>\<open>HOL.The\<close>, _) $ Abs (_, _, _))) =
   225           abstract_sub t (abstract_term t)
   251           abstract_sub t (abstract_term t)
   226       | abs (t as (c as Const _) $ Abs (s, T, t')) =
   252       | abs (t as (c as Const _) $ Abs (s, T, t')) =
   227           abstract_sub t (abs t' #>> (fn u' => c $ Abs (s, T, u')))
   253           abstract_sub t (abs t' #>> (fn u' => c $ Abs (s, T, u')))
   228       | abs (t as (c as Const (\<^const_name>\<open>If\<close>, _)) $ t1 $ t2 $ t3) =
   254       | abs (t as (c as Const (\<^const_name>\<open>If\<close>, _)) $ t1 $ t2 $ t3) =
   229           abstract_ter abs (fn (t1, t2, t3) => c $ t1 $ t2 $ t3) t t1 t2 t3
   255           abstract_ter abs (fn (t1, t2, t3) => c $ t1 $ t2 $ t3) t t1 t2 t3
   265   | abstract_unit (t as (Const(\<^const_name>\<open>HOL.eq\<close>, _) $ t1 $ t2)) =
   291   | abstract_unit (t as (Const(\<^const_name>\<open>HOL.eq\<close>, _) $ t1 $ t2)) =
   266       if fastype_of t1 = \<^typ>\<open>bool\<close> then
   292       if fastype_of t1 = \<^typ>\<open>bool\<close> then
   267         abstract_sub t (abstract_unit t1 ##>> abstract_unit t2 #>>
   293         abstract_sub t (abstract_unit t1 ##>> abstract_unit t2 #>>
   268           HOLogic.mk_eq)
   294           HOLogic.mk_eq)
   269       else abstract_lit t
   295       else abstract_lit t
   270   | abstract_unit (t as (\<^const>\<open>HOL.Not\<close> $ Const(\<^const_name>\<open>HOL.eq\<close>, _) $ t1 $ t2)) =
   296   | abstract_unit (t as (\<^const>\<open>HOL.Not\<close> $ (Const(\<^const_name>\<open>HOL.eq\<close>, _) $ t1 $ t2))) =
   271       if fastype_of t1 = \<^typ>\<open>bool\<close> then
   297       if fastype_of t1 = \<^typ>\<open>bool\<close> then
   272         abstract_sub t (abstract_unit t1 ##>> abstract_unit t2 #>>
   298         abstract_sub t (abstract_unit t1 ##>> abstract_unit t2 #>>
   273           HOLogic.mk_eq #>> HOLogic.mk_not)
   299           HOLogic.mk_eq #>> HOLogic.mk_not)
   274       else abstract_lit t
   300       else abstract_lit t
   275   | abstract_unit (t as (\<^const>\<open>HOL.Not\<close> $ t1)) =
   301   | abstract_unit (t as (\<^const>\<open>HOL.Not\<close> $ t1)) =
   276       abstract_sub t (abstract_unit t1 #>> HOLogic.mk_not)
   302       abstract_sub t (abstract_unit t1 #>> HOLogic.mk_not)
   277   | abstract_unit t = abstract_lit t
   303   | abstract_unit t = abstract_lit t
   278 
   304 
       
   305 fun abstract_bool (t as (@{const HOL.disj} $ t1 $ t2)) =
       
   306       abstract_sub t (abstract_bool t1 ##>> abstract_bool t2 #>>
       
   307         HOLogic.mk_disj)
       
   308   | abstract_bool (t as (@{const HOL.conj} $ t1 $ t2)) =
       
   309       abstract_sub t (abstract_bool t1 ##>> abstract_bool t2 #>>
       
   310         HOLogic.mk_conj)
       
   311   | abstract_bool (t as (Const(@{const_name HOL.eq}, _) $ t1 $ t2)) =
       
   312       if fastype_of t1 = @{typ bool} then
       
   313         abstract_sub t (abstract_bool t1 ##>> abstract_bool t2 #>>
       
   314           HOLogic.mk_eq)
       
   315       else abstract_lit t
       
   316   | abstract_bool (t as (@{const HOL.Not} $ t1)) =
       
   317       abstract_sub t (abstract_bool t1 #>> HOLogic.mk_not)
       
   318   | abstract_bool (t as (@{const HOL.implies} $ t1 $ t2)) =
       
   319       abstract_sub t (abstract_bool t1 ##>> abstract_bool t2 #>>
       
   320         HOLogic.mk_imp)
       
   321   | abstract_bool t = abstract_lit t
       
   322 
       
   323 fun abstract_bool_shallow (t as (@{const HOL.disj} $ t1 $ t2)) =
       
   324       abstract_sub t (abstract_bool_shallow t1 ##>> abstract_bool_shallow t2 #>>
       
   325         HOLogic.mk_disj)
       
   326   | abstract_bool_shallow (t as (@{const HOL.Not} $ t1)) =
       
   327       abstract_sub t (abstract_bool_shallow t1 #>> HOLogic.mk_not)
       
   328   | abstract_bool_shallow t = abstract_term t
       
   329 
       
   330 fun abstract_bool_shallow_equivalence (t as (@{const HOL.disj} $ t1 $ t2)) =
       
   331       abstract_sub t (abstract_bool_shallow_equivalence t1 ##>> abstract_bool_shallow_equivalence t2 #>>
       
   332         HOLogic.mk_disj)
       
   333   | abstract_bool_shallow_equivalence (t as (Const(@{const_name HOL.eq}, _) $ t1 $ t2)) =
       
   334       if fastype_of t1 = @{typ bool} then
       
   335         abstract_sub t (abstract_lit t1 ##>> abstract_lit t2 #>>
       
   336           HOLogic.mk_eq)
       
   337       else abstract_lit t
       
   338   | abstract_bool_shallow_equivalence (t as (@{const HOL.Not} $ t1)) =
       
   339       abstract_sub t (abstract_bool_shallow_equivalence t1 #>> HOLogic.mk_not)
       
   340   | abstract_bool_shallow_equivalence t = abstract_lit t
       
   341 
       
   342 fun abstract_arith_shallow ctxt u =
       
   343   let
       
   344     fun abs (t as (Const (\<^const_name>\<open>HOL.The\<close>, _) $ Abs (_, _, _))) =
       
   345           abstract_sub t (abstract_term t)
       
   346       | abs (t as (c as Const _) $ Abs (s, T, t')) =
       
   347           abstract_sub t (abs t' #>> (fn u' => c $ Abs (s, T, u')))
       
   348       | abs (t as (Const (\<^const_name>\<open>If\<close>, _)) $ _ $ _ $ _) =
       
   349           abstract_sub t (abstract_term t)
       
   350       | abs (t as \<^const>\<open>HOL.Not\<close> $ t1) = abstract_sub t (abs t1 #>> HOLogic.mk_not)
       
   351       | abs (t as \<^const>\<open>HOL.disj\<close> $ t1 $ t2) =
       
   352           abstract_sub t (abs t1 ##>> abs t2 #>> HOLogic.mk_disj)
       
   353       | abs (t as (c as Const (\<^const_name>\<open>uminus_class.uminus\<close>, _)) $ t1) =
       
   354           abstract_sub t (abs t1 #>> (fn u => c $ u))
       
   355       | abs (t as (c as Const (\<^const_name>\<open>plus_class.plus\<close>, _)) $ t1 $ t2) =
       
   356           abstract_sub t (abs t1 ##>> abs t2 #>> (fn (u1, u2) => c $ u1 $ u2))
       
   357       | abs (t as (c as Const (\<^const_name>\<open>minus_class.minus\<close>, _)) $ t1 $ t2) =
       
   358           abstract_sub t (abs t1 ##>> abs t2 #>> (fn (u1, u2) => c $ u1 $ u2))
       
   359       | abs (t as (c as Const (\<^const_name>\<open>times_class.times\<close>, _)) $ t1 $ t2) =
       
   360           abstract_sub t (abs t1 ##>> abs t2 #>> (fn (u1, u2) => c $ u1 $ u2))
       
   361       | abs (t as (Const (\<^const_name>\<open>z3div\<close>, _)) $ _ $ _) =
       
   362          abstract_sub t (abstract_term t)
       
   363       | abs (t as (Const (\<^const_name>\<open>z3mod\<close>, _)) $ _ $ _) =
       
   364           abstract_sub t (abstract_term t)
       
   365       | abs (t as (c as Const (\<^const_name>\<open>HOL.eq\<close>, _)) $ t1 $ t2) =
       
   366           abstract_sub t (abs t1 ##>> abs t2 #>> (fn (u1, u2) => c $ u1 $ u2))
       
   367       | abs (t as (c as Const (\<^const_name>\<open>ord_class.less\<close>, _)) $ t1 $ t2) =
       
   368           abstract_sub t (abs t1 ##>> abs t2 #>> (fn (u1, u2) => c $ u1 $ u2))
       
   369       | abs (t as (c as Const (\<^const_name>\<open>ord_class.less_eq\<close>, _)) $ t1 $ t2) =
       
   370           abstract_sub t (abs t1 ##>> abs t2 #>> (fn (u1, u2) => c $ u1 $ u2))
       
   371       | abs t = abstract_sub t (fn cx =>
       
   372           if can HOLogic.dest_number t then (t, cx)
       
   373           else
       
   374             (case apply_abstracters abs (get_arith_abstracters ctxt) t cx of
       
   375               (SOME u, cx') => (u, cx')
       
   376             | (NONE, _) => abstract_term t cx))
       
   377   in abs u end
   279 
   378 
   280 (* theory lemmas *)
   379 (* theory lemmas *)
   281 
   380 
   282 fun try_provers ctxt rule [] thms t = replay_rule_error ctxt rule thms t
   381 fun try_provers prover_name ctxt rule [] thms t = replay_rule_error prover_name ctxt rule thms t
   283   | try_provers ctxt rule ((name, prover) :: named_provers) thms t =
   382   | try_provers prover_name ctxt rule ((name, prover) :: named_provers) thms t =
   284       (case (trace ctxt (K ("Trying prover " ^ quote name)); try prover t) of
   383       (case (trace ctxt (K ("Trying prover " ^ quote name)); try prover t) of
   285         SOME thm => thm
   384         SOME thm => thm
   286       | NONE => try_provers ctxt rule named_provers thms t)
   385       | NONE => try_provers prover_name ctxt rule named_provers thms t)
       
   386 
       
   387 (*theory-lemma*)
       
   388 
       
   389 fun arith_th_lemma_tac ctxt prems =
       
   390   Method.insert_tac ctxt prems
       
   391   THEN' SELECT_GOAL (Local_Defs.unfold0_tac ctxt @{thms z3div_def z3mod_def})
       
   392   THEN' Arith_Data.arith_tac ctxt
       
   393 
       
   394 fun arith_th_lemma ctxt thms t =
       
   395   prove_abstract ctxt thms t arith_th_lemma_tac (
       
   396     fold_map (abstract_arith ctxt o dest_thm) thms ##>>
       
   397       abstract_arith ctxt (dest_prop t))
       
   398 
       
   399 fun arith_th_lemma_tac_with_wo ctxt prems =
       
   400   Method.insert_tac ctxt prems
       
   401   THEN' SELECT_GOAL (Local_Defs.unfold0_tac ctxt @{thms z3div_def z3mod_def int_distrib})
       
   402   THEN' Simplifier.asm_full_simp_tac
       
   403      (empty_simpset ctxt addsimprocs [(*@{simproc linordered_ring_strict_eq_cancel_factor_poly},
       
   404       @{simproc linordered_ring_strict_le_cancel_factor_poly},
       
   405       @{simproc linordered_ring_strict_less_cancel_factor_poly},
       
   406       @{simproc nat_eq_cancel_factor_poly},
       
   407       @{simproc nat_le_cancel_factor_poly},
       
   408       @{simproc nat_less_cancel_factor_poly}*)])
       
   409   THEN' (fn i => TRY (Arith_Data.arith_tac ctxt i))
       
   410 
       
   411 fun arith_th_lemma_wo ctxt thms t =
       
   412   prove_abstract ctxt thms t arith_th_lemma_tac_with_wo (
       
   413     fold_map (abstract_arith ctxt o dest_thm) thms ##>>
       
   414       abstract_arith ctxt (dest_prop t))
       
   415 
       
   416 fun arith_th_lemma_wo_shallow ctxt thms t =
       
   417   prove_abstract ctxt thms t arith_th_lemma_tac_with_wo (
       
   418     fold_map (abstract_arith_shallow ctxt o dest_thm) thms ##>>
       
   419       abstract_arith_shallow ctxt (dest_prop t))
       
   420 
       
   421 val _ = Theory.setup (Context.theory_map (add_th_lemma_method ("arith", arith_th_lemma)))
   287 
   422 
   288 
   423 
   289 (* congruence *)
   424 (* congruence *)
   290 
   425 
   291 fun certify_prop ctxt t = Thm.cterm_of ctxt (as_prop t)
   426 fun certify_prop ctxt t = Thm.cterm_of ctxt (as_prop t)
   316   Method.insert_tac ctxt thms
   451   Method.insert_tac ctxt thms
   317   THEN' (cong_full_core_tac ctxt'
   452   THEN' (cong_full_core_tac ctxt'
   318     ORELSE' dresolve_tac ctxt cong_dest_rules
   453     ORELSE' dresolve_tac ctxt cong_dest_rules
   319     THEN' cong_full_core_tac ctxt'))
   454     THEN' cong_full_core_tac ctxt'))
   320 
   455 
       
   456 local
       
   457   val reorder_for_simp = try (fn thm =>
       
   458        let val t = Thm.prop_of (@{thm eq_reflection} OF [thm])
       
   459            val thm =
       
   460              (case Logic.dest_equals t of
       
   461                (t1, t2) =>
       
   462                  if t1 aconv t2 then raise TERM("identical terms", [t1, t2])
       
   463                  else if Term.size_of_term t1 > Term.size_of_term t2 then @{thm eq_reflection} OF [thm]
       
   464                  else @{thm eq_reflection} OF [@{thm sym} OF [thm]])
       
   465                   handle TERM("dest_equals", _) => @{thm eq_reflection} OF [thm]
       
   466        in thm end)
       
   467 in  
       
   468 fun cong_unfolding_trivial ctxt thms t =
       
   469    prove ctxt t (fn _ =>
       
   470       EVERY' (map (fn thm => K (unfold_tac ctxt [thm])) ((map_filter reorder_for_simp thms)))
       
   471       THEN' (fn i => TRY (resolve_tac ctxt @{thms refl} i)))
       
   472 
   321 fun cong_unfolding_first ctxt thms t =
   473 fun cong_unfolding_first ctxt thms t =
   322   let val reorder_for_simp = try (fn thm =>
   474   let val ctxt =
   323     let val t = Thm.prop_of ( @{thm eq_reflection} OF [thm])
   475         ctxt
   324           val thm = (case Logic.dest_equals t of
   476         |> empty_simpset
   325                (t1, t2) => if Term.size_of_term t1 > Term.size_of_term t2 then @{thm eq_reflection} OF [thm]
   477         |> put_simpset HOL_basic_ss
   326                    else @{thm eq_reflection} OF [thm OF @{thms sym}])
   478         |> (fn ctxt => ctxt addsimps @{thms not_not eq_commute})
   327                handle TERM("dest_equals", _) =>  @{thm eq_reflection} OF [thm]
       
   328     in thm end)
       
   329   in
   479   in
   330     prove ctxt t (fn ctxt =>
   480     prove ctxt t (fn _ =>
   331       Raw_Simplifier.rewrite_goal_tac ctxt
   481       EVERY' (map (fn thm => K (unfold_tac ctxt [thm])) ((map_filter reorder_for_simp thms)))
   332         (map_filter reorder_for_simp thms)
       
   333       THEN' Method.insert_tac ctxt thms
   482       THEN' Method.insert_tac ctxt thms
   334      THEN' K (Clasimp.auto_tac ctxt))
   483       THEN' (full_simp_tac ctxt)
       
   484       THEN' K (ALLGOALS (K (Clasimp.auto_tac ctxt))))
   335   end
   485   end
   336 
   486 
       
   487 end
       
   488 
       
   489 
       
   490 fun arith_rewrite_tac ctxt _ =
       
   491   let val backup_tac = Arith_Data.arith_tac ctxt ORELSE' Clasimp.force_tac ctxt in
       
   492     (TRY o Simplifier.simp_tac ctxt) THEN_ALL_NEW backup_tac
       
   493     ORELSE' backup_tac
       
   494   end
       
   495 
       
   496 fun abstract_eq f (Const (\<^const_name>\<open>HOL.eq\<close>, _) $ t1 $ t2) =
       
   497       f t1 ##>> f t2 #>> HOLogic.mk_eq
       
   498   | abstract_eq _ t = abstract_term t
       
   499 
       
   500 fun abstract_neq f (Const (\<^const_name>\<open>HOL.eq\<close>, _) $ t1 $ t2) =
       
   501       f t1 ##>> f t2 #>> HOLogic.mk_eq
       
   502   | abstract_neq f (Const (\<^const_name>\<open>HOL.Not\<close>, _) $ (Const (\<^const_name>\<open>HOL.eq\<close>, _) $ t1 $ t2)) =
       
   503        f t1 ##>> f t2 #>> HOLogic.mk_eq #>> curry (op $) HOLogic.Not
       
   504   |  abstract_neq f (Const (\<^const_name>\<open>HOL.disj\<close>, _) $ t1 $ t2) =
       
   505       f t1 ##>> f t2 #>> HOLogic.mk_disj
       
   506   | abstract_neq _ t = abstract_term t
       
   507 
       
   508 fun prove_arith_rewrite abstracter ctxt t =
       
   509   prove_abstract' ctxt t arith_rewrite_tac (
       
   510     abstracter (abstract_arith ctxt) (dest_prop t))
       
   511 
       
   512 fun prop_tac ctxt prems =
       
   513   Method.insert_tac ctxt prems
       
   514   THEN' SUBGOAL (fn (prop, i) =>
       
   515     if Term.size_of_term prop > 100 then SAT.satx_tac ctxt i
       
   516     else (Classical.fast_tac ctxt ORELSE' Clasimp.force_tac ctxt) i)
       
   517 
   337 end;
   518 end;