src/HOL/Tools/Sledgehammer/sledgehammer_fact_preprocessor.ML
changeset 37410 2bf7e6136047
parent 37403 7e3d7af86215
child 37416 d5ac8280497e
equal deleted inserted replaced
37409:6c9f23863808 37410:2bf7e6136047
     8 signature SLEDGEHAMMER_FACT_PREPROCESSOR =
     8 signature SLEDGEHAMMER_FACT_PREPROCESSOR =
     9 sig
     9 sig
    10   val chained_prefix: string
    10   val chained_prefix: string
    11   val trace: bool Unsynchronized.ref
    11   val trace: bool Unsynchronized.ref
    12   val trace_msg: (unit -> string) -> unit
    12   val trace_msg: (unit -> string) -> unit
    13   val skolem_Eps_pseudo_theory: string
    13   val skolem_theory_name: string
    14   val skolem_prefix: string
    14   val skolem_prefix: string
    15   val skolem_infix: string
    15   val skolem_infix: string
    16   val is_skolem_const_name: string -> bool
    16   val is_skolem_const_name: string -> bool
    17   val skolem_type_and_args: typ -> term -> typ * term list
       
    18   val cnf_axiom: theory -> thm -> thm list
    17   val cnf_axiom: theory -> thm -> thm list
    19   val multi_base_blacklist: string list
    18   val multi_base_blacklist: string list
    20   val is_theorem_bad_for_atps: thm -> bool
    19   val is_theorem_bad_for_atps: thm -> bool
    21   val type_has_topsort: typ -> bool
    20   val type_has_topsort: typ -> bool
    22   val cnf_rules_pairs:
    21   val cnf_rules_pairs:
    40 val chained_prefix = "Sledgehammer.chained_"
    39 val chained_prefix = "Sledgehammer.chained_"
    41 
    40 
    42 val trace = Unsynchronized.ref false;
    41 val trace = Unsynchronized.ref false;
    43 fun trace_msg msg = if !trace then tracing (msg ()) else ();
    42 fun trace_msg msg = if !trace then tracing (msg ()) else ();
    44 
    43 
    45 val skolem_Eps_pseudo_theory = "Sledgehammer.Eps"
    44 val skolem_theory_name = "Sledgehammer.Sko"
    46 val skolem_prefix = "sko_"
    45 val skolem_prefix = "sko_"
    47 val skolem_infix = "$"
    46 val skolem_infix = "$"
    48 
    47 
    49 fun freeze_thm th = #1 (Drule.legacy_freeze_thaw th);
    48 fun freeze_thm th = #1 (Drule.legacy_freeze_thaw th);
    50 
    49 
    74 exception Clausify_failure of theory;
    73 exception Clausify_failure of theory;
    75 
    74 
    76 
    75 
    77 (**** SKOLEMIZATION BY INFERENCE (lcp) ****)
    76 (**** SKOLEMIZATION BY INFERENCE (lcp) ****)
    78 
    77 
    79 fun skolem_Eps_const T =
       
    80   Const (@{const_name skolem_Eps}, (T --> HOLogic.boolT) --> T)
       
    81 
       
    82 (*Keep the full complexity of the original name*)
    78 (*Keep the full complexity of the original name*)
    83 fun flatten_name s = space_implode "_X" (Long_Name.explode s);
    79 fun flatten_name s = space_implode "_X" (Long_Name.explode s);
    84 
    80 
    85 fun skolem_name thm_name j var_name =
    81 fun skolem_name thm_name j var_name =
    86   skolem_prefix ^ thm_name ^ "_" ^ Int.toString j ^
    82   skolem_prefix ^ thm_name ^ "_" ^ Int.toString j ^
   118         (*Existential: declare a Skolem function, then insert into body and continue*)
   114         (*Existential: declare a Skolem function, then insert into body and continue*)
   119         let
   115         let
   120           val id = skolem_name s (Unsynchronized.inc skolem_count) s'
   116           val id = skolem_name s (Unsynchronized.inc skolem_count) s'
   121           val (cT, args) = skolem_type_and_args T body
   117           val (cT, args) = skolem_type_and_args T body
   122           val rhs = list_abs_free (map dest_Free args,
   118           val rhs = list_abs_free (map dest_Free args,
   123                                    skolem_Eps_const T $ body)
   119                                    HOLogic.choice_const T $ body)
   124                   (*Forms a lambda-abstraction over the formal parameters*)
   120                   (*Forms a lambda-abstraction over the formal parameters*)
   125           val (c, thy) =
   121           val (c, thy) =
   126             Sign.declare_const ((Binding.conceal (Binding.name id), cT), NoSyn) thy
   122             Sign.declare_const ((Binding.conceal (Binding.name id), cT), NoSyn) thy
   127           val cdef = id ^ "_def"
   123           val cdef = id ^ "_def"
   128           val ((_, ax), thy) =
   124           val ((_, ax), thy) =
   137       | dec_sko (@{const "op |"} $ p $ q) thx = dec_sko q (dec_sko p thx)
   133       | dec_sko (@{const "op |"} $ p $ q) thx = dec_sko q (dec_sko p thx)
   138       | dec_sko (@{const Trueprop} $ p) thx = dec_sko p thx
   134       | dec_sko (@{const Trueprop} $ p) thx = dec_sko p thx
   139       | dec_sko t thx = thx
   135       | dec_sko t thx = thx
   140   in dec_sko (prop_of th) ([], thy) end
   136   in dec_sko (prop_of th) ([], thy) end
   141 
   137 
       
   138 fun mk_skolem_id t =
       
   139   let val T = fastype_of t in Const (@{const_name skolem_id}, T --> T) $ t end
       
   140 
   142 (*Traverse a theorem, accumulating Skolem function definitions.*)
   141 (*Traverse a theorem, accumulating Skolem function definitions.*)
   143 fun assume_skolem_funs inline s th =
   142 fun assume_skolem_funs inline s th =
   144   let
   143   let
   145     val skolem_count = Unsynchronized.ref 0   (* FIXME ??? *)
   144     val skolem_count = Unsynchronized.ref 0   (* FIXME ??? *)
   146     fun dec_sko (Const (@{const_name Ex}, _) $ (body as Abs (s', T, p))) defs =
   145     fun dec_sko (Const (@{const_name Ex}, _) $ (body as Abs (s', T, p))) defs =
   150           val args = subtract (op =) skos (OldTerm.term_frees body) (*the formal parameters*)
   149           val args = subtract (op =) skos (OldTerm.term_frees body) (*the formal parameters*)
   151           val Ts = map type_of args
   150           val Ts = map type_of args
   152           val cT = Ts ---> T (* FIXME: use "skolem_type_and_args" *)
   151           val cT = Ts ---> T (* FIXME: use "skolem_type_and_args" *)
   153           val id = skolem_name s (Unsynchronized.inc skolem_count) s'
   152           val id = skolem_name s (Unsynchronized.inc skolem_count) s'
   154           val c = Free (id, cT)
   153           val c = Free (id, cT)
   155           val rhs = list_abs_free (map dest_Free args, skolem_Eps_const T $ body)
   154           val rhs = list_abs_free (map dest_Free args,
       
   155                                    HOLogic.choice_const T $ body)
       
   156                     |> inline ? mk_skolem_id
   156                 (*Forms a lambda-abstraction over the formal parameters*)
   157                 (*Forms a lambda-abstraction over the formal parameters*)
   157           val def = Logic.mk_equals (c, rhs)
   158           val def = Logic.mk_equals (c, rhs)
   158           val comb = list_comb (if inline then rhs else c, args)
   159           val comb = list_comb (if inline then rhs else c, args)
   159         in dec_sko (subst_bound (comb, p)) (def :: defs) end
   160         in dec_sko (subst_bound (comb, p)) (def :: defs) end
   160       | dec_sko (Const (@{const_name All},_) $ Abs (a, T, p)) defs =
   161       | dec_sko (Const (@{const_name All},_) $ Abs (a, T, p)) defs =
   293 (*Given the definition of a Skolem function, return a theorem to replace
   294 (*Given the definition of a Skolem function, return a theorem to replace
   294   an existential formula by a use of that function.
   295   an existential formula by a use of that function.
   295    Example: "EX x. x : A & x ~: B ==> sko A B : A & sko A B ~: B"  [.] *)
   296    Example: "EX x. x : A & x ~: B ==> sko A B : A & sko A B ~: B"  [.] *)
   296 fun skolem_theorem_of_def inline def =
   297 fun skolem_theorem_of_def inline def =
   297   let
   298   let
   298       val (c,rhs) = Thm.dest_equals (cprop_of (freeze_thm def))
   299       val (c, rhs) = Thm.dest_equals (cprop_of (freeze_thm def))
   299       val (ch, frees) = c_variant_abs_multi (rhs, [])
   300       val rhs' = rhs |> inline ? (snd o Thm.dest_comb)
   300       val (chilbert,cabs) = Thm.dest_comb ch
   301       val (ch, frees) = c_variant_abs_multi (rhs', [])
       
   302       val (chilbert, cabs) = ch |> Thm.dest_comb
   301       val thy = Thm.theory_of_cterm chilbert
   303       val thy = Thm.theory_of_cterm chilbert
   302       val t = Thm.term_of chilbert
   304       val t = Thm.term_of chilbert
   303       val T =
   305       val T =
   304         case t of
   306         case t of
   305           Const (@{const_name skolem_Eps}, Type (@{type_name fun}, [_, T])) => T
   307           Const (@{const_name Eps}, Type (@{type_name fun}, [_, T])) => T
   306         | _ => raise THM ("skolem_theorem_of_def: expected \"Eps\"", 0, [def])
   308         | _ => raise TERM ("skolem_theorem_of_def: expected \"Eps\"", [t])
   307       val cex = Thm.cterm_of thy (HOLogic.exists_const T)
   309       val cex = Thm.cterm_of thy (HOLogic.exists_const T)
   308       val ex_tm = c_mkTrueprop (Thm.capply cex cabs)
   310       val ex_tm = c_mkTrueprop (Thm.capply cex cabs)
   309       and conc =
   311       and conc =
   310         Drule.list_comb (if inline then rhs else c, frees)
   312         Drule.list_comb (if inline then rhs else c, frees)
   311         |> Drule.beta_conv cabs |> c_mkTrueprop
   313         |> Drule.beta_conv cabs |> c_mkTrueprop
   312       fun tacf [prem] =
   314       fun tacf [prem] =
   313         (if inline then all_tac else rewrite_goals_tac [def])
   315         (if inline then rewrite_goals_tac @{thms skolem_id_def_raw}
   314         THEN rtac (prem RS @{thm skolem_someI_ex}) 1
   316          else rewrite_goals_tac [def])
       
   317         THEN rtac ((prem |> inline ? rewrite_rule @{thms skolem_id_def_raw})
       
   318                    RS @{thm someI_ex}) 1
   315   in  Goal.prove_internal [ex_tm] conc tacf
   319   in  Goal.prove_internal [ex_tm] conc tacf
   316        |> forall_intr_list frees
   320        |> forall_intr_list frees
   317        |> Thm.forall_elim_vars 0  (*Introduce Vars, but don't discharge defs.*)
   321        |> Thm.forall_elim_vars 0  (*Introduce Vars, but don't discharge defs.*)
   318        |> Thm.varifyT_global
   322        |> Thm.varifyT_global
   319   end;
   323   end;
   396     []
   400     []
   397   else
   401   else
   398     let
   402     let
   399       val ctxt0 = Variable.global_thm_context th
   403       val ctxt0 = Variable.global_thm_context th
   400       val (nnfth, ctxt) = to_nnf th ctxt0
   404       val (nnfth, ctxt) = to_nnf th ctxt0
   401 
       
   402       val inline = false
       
   403 (*
       
   404 FIXME: Reintroduce code:
       
   405       val inline = exists_type (exists_subtype (can dest_TFree)) (prop_of nnfth)
   405       val inline = exists_type (exists_subtype (can dest_TFree)) (prop_of nnfth)
   406 *)
       
   407       val defs = skolem_theorems_of_assume inline s nnfth
   406       val defs = skolem_theorems_of_assume inline s nnfth
   408       val (cnfs, ctxt) = Meson.make_cnf defs nnfth ctxt
   407       val (cnfs, ctxt) = Meson.make_cnf defs nnfth ctxt
   409     in
   408     in
   410       cnfs |> map introduce_combinators
   409       cnfs |> map introduce_combinators
   411            |> Variable.export ctxt ctxt0
   410            |> Variable.export ctxt ctxt0
   490     val new_thms = (new_facts, []) |-> fold (fn (name, ths) =>
   489     val new_thms = (new_facts, []) |-> fold (fn (name, ths) =>
   491       if member (op =) multi_base_blacklist (Long_Name.base_name name) then
   490       if member (op =) multi_base_blacklist (Long_Name.base_name name) then
   492         I
   491         I
   493       else
   492       else
   494         fold_index (fn (i, th) =>
   493         fold_index (fn (i, th) =>
   495           if is_theorem_bad_for_atps th orelse is_some (lookup_cache thy th) then
   494           if is_theorem_bad_for_atps th orelse
       
   495              is_some (lookup_cache thy th) then
   496             I
   496             I
   497           else
   497           else
   498             cons (name ^ "_" ^ string_of_int (i + 1), Thm.transfer thy th)) ths)
   498             cons (name ^ "_" ^ string_of_int (i + 1), Thm.transfer thy th)) ths)
   499   in
   499   in
   500     if null new_facts then
   500     if null new_facts then