src/HOL/Tools/res_axioms.ML
author wenzelm
Sun Sep 30 16:20:33 2007 +0200 (2007-09-30)
changeset 24771 6c7e94742afa
parent 24742 73b8b42a36b6
child 24785 197e4df96fd4
permissions -rw-r--r--
skofuns/absfuns: explicit markup as internal consts;
     1 (*  Author: Jia Meng, Cambridge University Computer Laboratory
     2     ID: $Id$
     3     Copyright 2004 University of Cambridge
     4 
     5 Transformation of axiom rules (elim/intro/etc) into CNF forms.
     6 *)
     7 
     8 signature RES_AXIOMS =
     9 sig
    10   val cnf_axiom: thm -> thm list
    11   val meta_cnf_axiom: thm -> thm list
    12   val pairname: thm -> string * thm
    13   val skolem_thm: thm -> thm list
    14   val cnf_rules_pairs: (string * thm) list -> (thm * (string * int)) list
    15   val cnf_rules_of_ths: thm list -> thm list
    16   val neg_clausify: thm list -> thm list
    17   val expand_defs_tac: thm -> tactic
    18   val assume_abstract_list: string -> thm list -> thm list
    19   val neg_conjecture_clauses: thm -> int -> thm list * (string * typ) list
    20   val claset_rules_of: Proof.context -> (string * thm) list   (*FIXME DELETE*)
    21   val simpset_rules_of: Proof.context -> (string * thm) list  (*FIXME DELETE*)
    22   val atpset_rules_of: Proof.context -> (string * thm) list
    23   val meson_method_setup: theory -> theory
    24   val clause_cache_endtheory: theory -> theory option
    25   val setup: theory -> theory
    26 end;
    27 
    28 structure ResAxioms: RES_AXIOMS =
    29 struct
    30 
    31 (* FIXME legacy *)
    32 fun freeze_thm th = #1 (Drule.freeze_thaw th);
    33 
    34 val lhs_of = #1 o Logic.dest_equals o Thm.prop_of;
    35 val rhs_of = #2 o Logic.dest_equals o Thm.prop_of;
    36 
    37 
    38 (*Store definitions of abstraction functions, ensuring that identical right-hand
    39   sides are denoted by the same functions and thereby reducing the need for
    40   extensionality in proofs.
    41   FIXME!  Store in theory data!!*)
    42 
    43 (*Populate the abstraction cache with common combinators.*)
    44 fun seed th net =
    45   let val (_,ct) = Thm.dest_abs NONE (Thm.rhs_of th)
    46       val t = Logic.legacy_varify (term_of ct)
    47   in  Net.insert_term Thm.eq_thm (t, th) net end;
    48 
    49 val abstraction_cache = ref
    50       (seed (thm"ATP_Linkup.I_simp")
    51        (seed (thm"ATP_Linkup.B_simp")
    52         (seed (thm"ATP_Linkup.K_simp") Net.empty)));
    53 
    54 
    55 (**** Transformation of Elimination Rules into First-Order Formulas****)
    56 
    57 val cfalse = cterm_of HOL.thy HOLogic.false_const;
    58 val ctp_false = cterm_of HOL.thy (HOLogic.mk_Trueprop HOLogic.false_const);
    59 
    60 (*Converts an elim-rule into an equivalent theorem that does not have the
    61   predicate variable.  Leaves other theorems unchanged.  We simply instantiate the
    62   conclusion variable to False.*)
    63 fun transform_elim th =
    64   case concl_of th of    (*conclusion variable*)
    65        Const("Trueprop",_) $ (v as Var(_,Type("bool",[]))) =>
    66            Thm.instantiate ([], [(cterm_of HOL.thy v, cfalse)]) th
    67     | v as Var(_, Type("prop",[])) =>
    68            Thm.instantiate ([], [(cterm_of HOL.thy v, ctp_false)]) th
    69     | _ => th;
    70 
    71 (*To enforce single-threading*)
    72 exception Clausify_failure of theory;
    73 
    74 (**** SKOLEMIZATION BY INFERENCE (lcp) ****)
    75 
    76 fun rhs_extra_types lhsT rhs =
    77   let val lhs_vars = Term.add_tfreesT lhsT []
    78       fun add_new_TFrees (TFree v) =
    79 	    if member (op =) lhs_vars v then I else insert (op =) (TFree v)
    80 	| add_new_TFrees _ = I
    81       val rhs_consts = fold_aterms (fn Const c => insert (op =) c | _ => I) rhs []
    82   in fold (#2 #> Term.fold_atyps add_new_TFrees) rhs_consts [] end;
    83 
    84 (*Traverse a theorem, declaring Skolem function definitions. String s is the suggested
    85   prefix for the Skolem constant. Result is a new theory*)
    86 fun declare_skofuns s th thy =
    87   let val nref = ref 0
    88       fun dec_sko (Const ("Ex",_) $ (xtp as Abs(_,T,p))) (thy, axs) =
    89             (*Existential: declare a Skolem function, then insert into body and continue*)
    90             let val cname = Name.internal ("sko_" ^ s ^ "_" ^ Int.toString (inc nref))
    91                 val args0 = term_frees xtp  (*get the formal parameter list*)
    92                 val Ts = map type_of args0
    93                 val extraTs = rhs_extra_types (Ts ---> T) xtp
    94                 val _ = if null extraTs then () else
    95                    warning ("Skolemization: extra type vars: " ^ 
    96                             commas_quote (map (Sign.string_of_typ thy) extraTs)); 
    97                 val argsx = map (fn T => Free(gensym"vsk", T)) extraTs
    98                 val args = argsx @ args0
    99                 val cT = extraTs ---> Ts ---> T
   100                 val c = Const (Sign.full_name thy cname, cT)
   101                 val rhs = list_abs_free (map dest_Free args, HOLogic.choice_const T $ xtp)
   102                         (*Forms a lambda-abstraction over the formal parameters*)
   103                 val _ = Output.debug (fn () => "declaring the constant " ^ cname)
   104                 val thy' =
   105                   Sign.add_consts_authentic [Markup.property_internal] [(cname, cT, NoSyn)] thy
   106                            (*Theory is augmented with the constant, then its def*)
   107                 val cdef = cname ^ "_def"
   108                 val thy'' = Theory.add_defs_i false false [(cdef, equals cT $ c $ rhs)] thy'
   109                             handle ERROR _ => raise Clausify_failure thy'
   110             in dec_sko (subst_bound (list_comb(c,args), p))
   111 			       (thy'', get_axiom thy'' cdef :: axs)
   112             end
   113         | dec_sko (Const ("All",_) $ (xtp as Abs(a,T,p))) thx =
   114             (*Universal quant: insert a free variable into body and continue*)
   115             let val fname = Name.variant (add_term_names (p,[])) a
   116             in dec_sko (subst_bound (Free(fname,T), p)) thx end
   117         | dec_sko (Const ("op &", _) $ p $ q) thx = dec_sko q (dec_sko p thx)
   118         | dec_sko (Const ("op |", _) $ p $ q) thx = dec_sko q (dec_sko p thx)
   119         | dec_sko (Const ("Trueprop", _) $ p) thx = dec_sko p thx
   120         | dec_sko t thx = thx (*Do nothing otherwise*)
   121   in  dec_sko (prop_of th) (thy,[])  end;
   122 
   123 (*Traverse a theorem, accumulating Skolem function definitions.*)
   124 fun assume_skofuns s th =
   125   let val sko_count = ref 0
   126       fun dec_sko (Const ("Ex",_) $ (xtp as Abs(_,T,p))) defs =
   127             (*Existential: declare a Skolem function, then insert into body and continue*)
   128             let val skos = map (#1 o Logic.dest_equals) defs  (*existing sko fns*)
   129                 val args = term_frees xtp \\ skos  (*the formal parameters*)
   130                 val Ts = map type_of args
   131                 val cT = Ts ---> T
   132                 val id = "sko_" ^ s ^ "_" ^ Int.toString (inc sko_count)
   133                 val c = Free (id, cT)
   134                 val rhs = list_abs_free (map dest_Free args,
   135                                          HOLogic.choice_const T $ xtp)
   136                       (*Forms a lambda-abstraction over the formal parameters*)
   137                 val def = equals cT $ c $ rhs
   138             in dec_sko (subst_bound (list_comb(c,args), p))
   139                        (def :: defs)
   140             end
   141         | dec_sko (Const ("All",_) $ (xtp as Abs(a,T,p))) defs =
   142             (*Universal quant: insert a free variable into body and continue*)
   143             let val fname = Name.variant (add_term_names (p,[])) a
   144             in dec_sko (subst_bound (Free(fname,T), p)) defs end
   145         | dec_sko (Const ("op &", _) $ p $ q) defs = dec_sko q (dec_sko p defs)
   146         | dec_sko (Const ("op |", _) $ p $ q) defs = dec_sko q (dec_sko p defs)
   147         | dec_sko (Const ("Trueprop", _) $ p) defs = dec_sko p defs
   148         | dec_sko t defs = defs (*Do nothing otherwise*)
   149   in  dec_sko (prop_of th) []  end;
   150 
   151 
   152 (**** REPLACING ABSTRACTIONS BY FUNCTION DEFINITIONS ****)
   153 
   154 (*Returns the vars of a theorem*)
   155 fun vars_of_thm th =
   156   map (Thm.cterm_of (theory_of_thm th) o Var) (Thm.fold_terms Term.add_vars th []);
   157 
   158 (*Make a version of fun_cong with a given variable name*)
   159 local
   160     val fun_cong' = fun_cong RS asm_rl; (*renumber f, g to prevent clashes with (a,0)*)
   161     val cx = hd (vars_of_thm fun_cong');
   162     val ty = typ_of (ctyp_of_term cx);
   163     val thy = theory_of_thm fun_cong;
   164     fun mkvar a = cterm_of thy (Var((a,0),ty));
   165 in
   166 fun xfun_cong x = Thm.instantiate ([], [(cx, mkvar x)]) fun_cong'
   167 end;
   168 
   169 (*Removes the lambdas from an equation of the form t = (%x. u).  A non-negative n,
   170   serves as an upper bound on how many to remove.*)
   171 fun strip_lambdas 0 th = th
   172   | strip_lambdas n th =
   173       case prop_of th of
   174           _ $ (Const ("op =", _) $ _ $ Abs (x,_,_)) =>
   175               strip_lambdas (n-1) (freeze_thm (th RS xfun_cong x))
   176         | _ => th;
   177 
   178 (*Convert meta- to object-equality. Fails for theorems like split_comp_eq,
   179   where some types have the empty sort.*)
   180 val meta_eq_to_obj_eq = thm "meta_eq_to_obj_eq";
   181 fun mk_object_eq th = th RS meta_eq_to_obj_eq
   182     handle THM _ => error ("Theorem contains empty sort: " ^ string_of_thm th);
   183 
   184 (*Apply a function definition to an argument, beta-reducing the result.*)
   185 fun beta_comb cf x =
   186   let val th1 = combination cf (reflexive x)
   187       val th2 = beta_conversion false (Thm.rhs_of th1)
   188   in  transitive th1 th2  end;
   189 
   190 (*Apply a function definition to arguments, beta-reducing along the way.*)
   191 fun list_combination cf [] = cf
   192   | list_combination cf (x::xs) = list_combination (beta_comb cf x) xs;
   193 
   194 fun list_cabs ([] ,     t) = t
   195   | list_cabs (v::vars, t) = Thm.cabs v (list_cabs(vars,t));
   196 
   197 fun assert_eta_free ct =
   198   let val t = term_of ct
   199   in if (t aconv Envir.eta_contract t) then ()
   200      else error ("Eta redex in term: " ^ string_of_cterm ct)
   201   end;
   202 
   203 fun eq_absdef (th1, th2) =
   204     Context.joinable (theory_of_thm th1, theory_of_thm th2)  andalso
   205     rhs_of th1 aconv rhs_of th2;
   206 
   207 val lambda_free = not o Term.has_abs;
   208 
   209 val monomorphic = not o Term.exists_type (Term.exists_subtype Term.is_TVar);
   210 
   211 fun dest_abs_list ct =
   212   let val (cv,ct') = Thm.dest_abs NONE ct
   213       val (cvs,cu) = dest_abs_list ct'
   214   in (cv::cvs, cu) end
   215   handle CTERM _ => ([],ct);
   216 
   217 fun abstract_rule_list [] [] th = th
   218   | abstract_rule_list (v::vs) (ct::cts) th = abstract_rule v ct (abstract_rule_list vs cts th)
   219   | abstract_rule_list _ _ th = raise THM ("abstract_rule_list", 0, [th]);
   220 
   221 
   222 val Envir.Envir {asol = tenv0, iTs = tyenv0, ...} = Envir.empty 0
   223 
   224 (*Does an existing abstraction definition have an RHS that matches the one we need now?
   225   thy is the current theory, which must extend that of theorem th.*)
   226 fun match_rhs thy t th =
   227   let val _ = Output.debug (fn()=> "match_rhs: " ^ string_of_cterm (cterm_of thy t) ^
   228                                    " against\n" ^ string_of_thm th);
   229       val (tyenv,tenv) = Pattern.first_order_match thy (rhs_of th, t) (tyenv0,tenv0)
   230       val term_insts = map Meson.term_pair_of (Vartab.dest tenv)
   231       val ct_pairs = if subthy (theory_of_thm th, thy) andalso
   232                         forall lambda_free (map #2 term_insts)
   233                      then map (pairself (cterm_of thy)) term_insts
   234                      else raise Pattern.MATCH (*Cannot allow lambdas in the instantiation*)
   235       fun ctyp2 (ixn, (S, T)) = (ctyp_of thy (TVar (ixn, S)), ctyp_of thy T)
   236       val th' = cterm_instantiate ct_pairs th
   237   in  SOME (th, instantiate (map ctyp2 (Vartab.dest tyenv), []) th')  end
   238   handle _ => NONE;
   239 
   240 (*Traverse a theorem, declaring abstraction function definitions. String s is the suggested
   241   prefix for the constants. Resulting theory is returned in the first theorem. *)
   242 fun declare_absfuns s th =
   243   let val nref = ref 0
   244       fun abstract thy ct =
   245         if lambda_free (term_of ct) then (transfer thy (reflexive ct), [])
   246         else
   247         case term_of ct of
   248           Abs _ =>
   249             let val cname = Name.internal ("llabs_" ^ s ^ "_" ^ Int.toString (inc nref))
   250                 val _ = assert_eta_free ct;
   251                 val (cvs,cta) = dest_abs_list ct
   252                 val (vs,Tvs) = ListPair.unzip (map (dest_Free o term_of) cvs)
   253                 val _ = Output.debug (fn()=>"Nested lambda: " ^ string_of_cterm cta);
   254                 val (u'_th,defs) = abstract thy cta
   255                 val _ = Output.debug (fn()=>"Returned " ^ string_of_thm u'_th);
   256                 val cu' = Thm.rhs_of u'_th
   257                 val u' = term_of cu'
   258                 val abs_v_u = fold_rev (lambda o term_of) cvs u'
   259                 (*get the formal parameters: ALL variables free in the term*)
   260                 val args = term_frees abs_v_u
   261                 val _ = Output.debug (fn()=>Int.toString (length args) ^ " arguments");
   262                 val rhs = list_abs_free (map dest_Free args, abs_v_u)
   263                       (*Forms a lambda-abstraction over the formal parameters*)
   264                 val _ = Output.debug (fn()=>"Looking up " ^ string_of_cterm cu');
   265                 val thy = theory_of_thm u'_th
   266                 val (ax,ax',thy) =
   267                  case List.mapPartial (match_rhs thy abs_v_u)
   268                          (Net.match_term (!abstraction_cache) u') of
   269                      (ax,ax')::_ =>
   270                        (Output.debug (fn()=>"Re-using axiom " ^ string_of_thm ax);
   271                         (ax,ax',thy))
   272                    | [] =>
   273                       let val _ = Output.debug (fn()=>"Lookup was empty");
   274                           val Ts = map type_of args
   275                           val cT = Ts ---> (Tvs ---> typ_of (ctyp_of_term cu'))
   276                           val c = Const (Sign.full_name thy cname, cT)
   277                           val thy =
   278                             Sign.add_consts_authentic [Markup.property_internal] [(cname, cT, NoSyn)] thy
   279                                      (*Theory is augmented with the constant,
   280                                        then its definition*)
   281                           val cdef = cname ^ "_def"
   282                           val thy = Theory.add_defs_i false false
   283                                        [(cdef, equals cT $ c $ rhs)] thy
   284                                     handle ERROR _ => raise Clausify_failure thy
   285                           val _ = Output.debug (fn()=> "Definition is " ^ string_of_thm (get_axiom thy cdef));
   286                           val ax = get_axiom thy cdef |> freeze_thm
   287                                      |> mk_object_eq |> strip_lambdas (length args)
   288                                      |> mk_meta_eq |> Meson.generalize
   289                           val (_,ax') = Option.valOf (match_rhs thy abs_v_u ax)
   290                           val _ = Output.debug (fn()=> "Declaring: " ^ string_of_thm ax ^ "\n" ^
   291                                                        "Instance: " ^ string_of_thm ax');
   292                           val _ = abstraction_cache := Net.insert_term eq_absdef
   293                                             ((Logic.varify u'), ax) (!abstraction_cache)
   294                             handle Net.INSERT =>
   295                               raise THM ("declare_absfuns: INSERT", 0, [th,u'_th,ax])
   296                        in  (ax,ax',thy)  end
   297             in Output.debug (fn()=>"Lookup result: " ^ string_of_thm ax');
   298                (transitive (abstract_rule_list vs cvs u'_th) (symmetric ax'), ax::defs) end
   299         | (t1$t2) =>
   300             let val (ct1,ct2) = Thm.dest_comb ct
   301                 val (th1,defs1) = abstract thy ct1
   302                 val (th2,defs2) = abstract (theory_of_thm th1) ct2
   303             in  (combination th1 th2, defs1@defs2)  end
   304       val _ = Output.debug (fn()=>"declare_absfuns, Abstracting: " ^ string_of_thm th);
   305       val (eqth,defs) = abstract (theory_of_thm th) (cprop_of th)
   306       val ths = equal_elim eqth th :: map (strip_lambdas ~1 o mk_object_eq o freeze_thm) defs
   307       val _ = Output.debug (fn()=>"declare_absfuns, Result: " ^ string_of_thm (hd ths));
   308   in  (theory_of_thm eqth, map Drule.eta_contraction_rule ths)  end;
   309 
   310 fun name_of def = try (#1 o dest_Free o lhs_of) def;
   311 
   312 (*A name is valid provided it isn't the name of a defined abstraction.*)
   313 fun valid_name defs (Free(x,T)) = not (x mem_string (List.mapPartial name_of defs))
   314   | valid_name defs _ = false;
   315 
   316 (*s is the theorem name (hint) or the word "subgoal"*)
   317 fun assume_absfuns s th =
   318   let val thy = theory_of_thm th
   319       val cterm = cterm_of thy
   320       val abs_count = ref 0
   321       fun abstract ct =
   322         if lambda_free (term_of ct) then (reflexive ct, [])
   323         else
   324         case term_of ct of
   325           Abs (_,T,u) =>
   326             let val _ = assert_eta_free ct;
   327                 val (cvs,cta) = dest_abs_list ct
   328                 val (vs,Tvs) = ListPair.unzip (map (dest_Free o term_of) cvs)
   329                 val (u'_th,defs) = abstract cta
   330                 val cu' = Thm.rhs_of u'_th
   331                 val u' = term_of cu'
   332                 (*Could use Thm.cabs instead of lambda to work at level of cterms*)
   333                 val abs_v_u = fold_rev (lambda o term_of) cvs (term_of cu')
   334                 (*get the formal parameters: free variables not present in the defs
   335                   (to avoid taking abstraction function names as parameters) *)
   336                 val args = filter (valid_name defs) (term_frees abs_v_u)
   337                 val crhs = list_cabs (map cterm args, cterm abs_v_u)
   338                       (*Forms a lambda-abstraction over the formal parameters*)
   339                 val rhs = term_of crhs
   340                 val (ax,ax') =
   341                  case List.mapPartial (match_rhs thy abs_v_u)
   342                         (Net.match_term (!abstraction_cache) u') of
   343                      (ax,ax')::_ =>
   344                        (Output.debug (fn()=>"Re-using axiom " ^ string_of_thm ax);
   345                         (ax,ax'))
   346                    | [] =>
   347                       let val Ts = map type_of args
   348                           val const_ty = Ts ---> (Tvs ---> typ_of (ctyp_of_term cu'))
   349                           val id = "llabs_" ^ s ^ "_" ^ Int.toString (inc abs_count)
   350                           val c = Free (id, const_ty)
   351                           val ax = assume (Thm.capply (cterm (equals const_ty $ c)) crhs)
   352                                      |> mk_object_eq |> strip_lambdas (length args)
   353                                      |> mk_meta_eq |> Meson.generalize
   354                           val (_,ax') = Option.valOf (match_rhs thy abs_v_u ax)
   355                           val _ = abstraction_cache := Net.insert_term eq_absdef (rhs,ax)
   356                                     (!abstraction_cache)
   357                             handle Net.INSERT =>
   358                               raise THM ("assume_absfuns: INSERT", 0, [th,u'_th,ax])
   359                       in (ax,ax') end
   360             in Output.debug (fn()=>"Lookup result: " ^ string_of_thm ax');
   361                (transitive (abstract_rule_list vs cvs u'_th) (symmetric ax'), ax::defs) end
   362         | (t1$t2) =>
   363             let val (ct1,ct2) = Thm.dest_comb ct
   364                 val (t1',defs1) = abstract ct1
   365                 val (t2',defs2) = abstract ct2
   366             in  (combination t1' t2', defs1@defs2)  end
   367       val _ = Output.debug (fn()=>"assume_absfuns, Abstracting: " ^ string_of_thm th);
   368       val (eqth,defs) = abstract (cprop_of th)
   369       val ths = equal_elim eqth th :: map (strip_lambdas ~1 o mk_object_eq o freeze_thm) defs
   370       val _ = Output.debug (fn()=>"assume_absfuns, Result: " ^ string_of_thm (hd ths));
   371   in  map Drule.eta_contraction_rule ths  end;
   372 
   373 
   374 (*cterms are used throughout for efficiency*)
   375 val cTrueprop = Thm.cterm_of HOL.thy HOLogic.Trueprop;
   376 
   377 (*cterm version of mk_cTrueprop*)
   378 fun c_mkTrueprop A = Thm.capply cTrueprop A;
   379 
   380 (*Given an abstraction over n variables, replace the bound variables by free
   381   ones. Return the body, along with the list of free variables.*)
   382 fun c_variant_abs_multi (ct0, vars) =
   383       let val (cv,ct) = Thm.dest_abs NONE ct0
   384       in  c_variant_abs_multi (ct, cv::vars)  end
   385       handle CTERM _ => (ct0, rev vars);
   386 
   387 (*Given the definition of a Skolem function, return a theorem to replace
   388   an existential formula by a use of that function.
   389    Example: "EX x. x : A & x ~: B ==> sko A B : A & sko A B ~: B"  [.] *)
   390 fun skolem_of_def def =
   391   let val (c,rhs) = Thm.dest_equals (cprop_of (freeze_thm def))
   392       val (ch, frees) = c_variant_abs_multi (rhs, [])
   393       val (chilbert,cabs) = Thm.dest_comb ch
   394       val {thy,t, ...} = rep_cterm chilbert
   395       val T = case t of Const ("Hilbert_Choice.Eps", Type("fun",[_,T])) => T
   396                       | _ => raise THM ("skolem_of_def: expected Eps", 0, [def])
   397       val cex = Thm.cterm_of thy (HOLogic.exists_const T)
   398       val ex_tm = c_mkTrueprop (Thm.capply cex cabs)
   399       and conc =  c_mkTrueprop (Drule.beta_conv cabs (Drule.list_comb(c,frees)));
   400       fun tacf [prem] = rewrite_goals_tac [def] THEN rtac (prem RS someI_ex) 1
   401   in  Goal.prove_internal [ex_tm] conc tacf
   402        |> forall_intr_list frees
   403        |> forall_elim_vars 0  (*Introduce Vars, but don't discharge defs.*)
   404        |> Thm.varifyT
   405   end;
   406 
   407 
   408 (*This will refer to the final version of theory ATP_Linkup.*)
   409 val atp_linkup_thy_ref = Theory.check_thy @{theory}
   410 
   411 (*Transfer a theorem into theory ATP_Linkup.thy if it is not already
   412   inside that theory -- because it's needed for Skolemization.
   413   If called while ATP_Linkup is being created, it will transfer to the
   414   current version. If called afterward, it will transfer to the final version.*)
   415 fun transfer_to_ATP_Linkup th =
   416     transfer (Theory.deref atp_linkup_thy_ref) th handle THM _ => th;
   417 
   418 (*Converts an Isabelle theorem (intro, elim or simp format, even higher-order) into NNF.*)
   419 fun to_nnf th =
   420     th |> transfer_to_ATP_Linkup
   421        |> transform_elim |> zero_var_indexes |> freeze_thm
   422        |> Conv.fconv_rule ObjectLogic.atomize |> Meson.make_nnf |> strip_lambdas ~1;
   423 
   424 (*Generate Skolem functions for a theorem supplied in nnf*)
   425 fun skolem_of_nnf s th =
   426   map (skolem_of_def o assume o (cterm_of (theory_of_thm th))) (assume_skofuns s th);
   427 
   428 fun assert_lambda_free ths msg =
   429   case filter (not o lambda_free o prop_of) ths of
   430       [] => ()
   431     | ths' => error (msg ^ "\n" ^ cat_lines (map string_of_thm ths'));
   432 
   433 fun assume_abstract s th =
   434   if lambda_free (prop_of th) then [th]
   435   else th |> Drule.eta_contraction_rule |> assume_absfuns s
   436           |> tap (fn ths => assert_lambda_free ths "assume_abstract: lambdas")
   437 
   438 (*Replace lambdas by assumed function definitions in the theorems*)
   439 fun assume_abstract_list s ths = List.concat (map (assume_abstract s) ths);
   440 
   441 (*Replace lambdas by declared function definitions in the theorems*)
   442 fun declare_abstract s (thy, []) = (thy, [])
   443   | declare_abstract s (thy, th::ths) =
   444       let val (thy', th_defs) =
   445             if lambda_free (prop_of th) then (thy, [th])
   446             else
   447                 th |> zero_var_indexes |> freeze_thm
   448                    |> Drule.eta_contraction_rule |> transfer thy |> declare_absfuns s
   449                 handle Clausify_failure thy_e => (thy_e,[])
   450           val _ = assert_lambda_free th_defs "declare_abstract: lambdas"
   451           val (thy'', ths') = declare_abstract (s^"'") (thy', ths)
   452       in  (thy'', th_defs @ ths')  end;
   453 
   454 (*Keep the full complexity of the original name*)
   455 fun flatten_name s = space_implode "_X" (NameSpace.explode s);
   456 
   457 fun fake_name th =
   458   if PureThy.has_name_hint th then flatten_name (PureThy.get_name_hint th)
   459   else gensym "unknown_thm_";
   460 
   461 fun name_or_string th =
   462   if PureThy.has_name_hint th then PureThy.get_name_hint th
   463   else string_of_thm th;
   464 
   465 (*Skolemize a named theorem, with Skolem functions as additional premises.*)
   466 fun skolem_thm th =
   467   let val nnfth = to_nnf th and s = fake_name th
   468   in  Meson.make_cnf (skolem_of_nnf s nnfth) nnfth |> assume_abstract_list s |> Meson.finish_cnf
   469   end
   470   handle THM _ => [];
   471 
   472 (*Declare Skolem functions for a theorem, supplied in nnf and with its name.
   473   It returns a modified theory, unless skolemization fails.*)
   474 fun skolem thy th =
   475      Option.map
   476         (fn nnfth =>
   477           let val _ = Output.debug (fn () => "skolemizing " ^ name_or_string th ^ ": ")
   478               val _ = Output.debug (fn () => string_of_thm nnfth)
   479               val s = fake_name th
   480               val (thy',defs) = declare_skofuns s nnfth thy
   481               val cnfs = Meson.make_cnf (map skolem_of_def defs) nnfth
   482               val _ = Output.debug (fn () => Int.toString (length cnfs) ^ " clauses yielded")
   483               val (thy'',cnfs') = declare_abstract s (thy',cnfs)
   484           in (map Goal.close_result (Meson.finish_cnf cnfs'), thy'') end
   485           handle Clausify_failure thy_e => ([],thy_e)
   486         )
   487       (try to_nnf th);
   488 
   489 (*The cache prevents repeated clausification of a theorem, and also repeated declaration of
   490   Skolem functions.*)
   491 structure ThmCache = TheoryDataFun
   492 (
   493   type T = (thm list) Thmtab.table;
   494   val empty = Thmtab.empty;
   495   fun copy tab : T = tab;
   496   val extend = copy;
   497   fun merge _ (tab1, tab2) : T = Thmtab.merge (K true) (tab1, tab2);
   498 );
   499 
   500 (*Populate the clause cache using the supplied theorem. Return the clausal form
   501   and modified theory.*)
   502 fun skolem_cache_thm th thy =
   503   case Thmtab.lookup (ThmCache.get thy) th of
   504       NONE =>
   505         (case skolem thy (Thm.transfer thy th) of
   506              NONE => ([th],thy)
   507            | SOME (cls,thy') =>
   508                  (Output.debug (fn () => "skolem_cache_thm: " ^ Int.toString (length cls) ^ 
   509                                          " clauses inserted into cache: " ^ name_or_string th);
   510                   (cls, ThmCache.put (Thmtab.update (th,cls) (ThmCache.get thy')) thy')))
   511     | SOME cls => (cls,thy);
   512 
   513 (*Exported function to convert Isabelle theorems into axiom clauses*)
   514 fun cnf_axiom th =
   515   let val thy = Theory.merge (Theory.deref atp_linkup_thy_ref, Thm.theory_of_thm th)
   516   in
   517       case Thmtab.lookup (ThmCache.get thy) th of
   518 	  NONE => (Output.debug (fn () => "cnf_axiom: " ^ name_or_string th);
   519 		   map Goal.close_result (skolem_thm th))
   520 	| SOME cls => cls
   521   end;
   522 
   523 fun pairname th = (PureThy.get_name_hint th, th);
   524 
   525 (**** Extract and Clausify theorems from a theory's claset and simpset ****)
   526 
   527 fun rules_of_claset cs =
   528   let val {safeIs,safeEs,hazIs,hazEs,...} = rep_cs cs
   529       val intros = safeIs @ hazIs
   530       val elims  = map Classical.classical_rule (safeEs @ hazEs)
   531   in
   532      Output.debug (fn () => "rules_of_claset intros: " ^ Int.toString(length intros) ^
   533             " elims: " ^ Int.toString(length elims));
   534      map pairname (intros @ elims)
   535   end;
   536 
   537 fun rules_of_simpset ss =
   538   let val ({rules,...}, _) = rep_ss ss
   539       val simps = Net.entries rules
   540   in
   541     Output.debug (fn () => "rules_of_simpset: " ^ Int.toString(length simps));
   542     map (fn r => (#name r, #thm r)) simps
   543   end;
   544 
   545 fun claset_rules_of ctxt = rules_of_claset (local_claset_of ctxt);
   546 fun simpset_rules_of ctxt = rules_of_simpset (local_simpset_of ctxt);
   547 
   548 fun atpset_rules_of ctxt = map pairname (ResAtpset.get ctxt);
   549 
   550 
   551 (**** Translate a set of theorems into CNF ****)
   552 
   553 (* classical rules: works for both FOL and HOL *)
   554 fun cnf_rules [] err_list = ([],err_list)
   555   | cnf_rules ((name,th) :: ths) err_list =
   556       let val (ts,es) = cnf_rules ths err_list
   557       in  (cnf_axiom th :: ts,es) handle  _ => (ts, (th::es))  end;
   558 
   559 fun pair_name_cls k (n, []) = []
   560   | pair_name_cls k (n, cls::clss) = (cls, (n,k)) :: pair_name_cls (k+1) (n, clss)
   561 
   562 fun cnf_rules_pairs_aux pairs [] = pairs
   563   | cnf_rules_pairs_aux pairs ((name,th)::ths) =
   564       let val pairs' = (pair_name_cls 0 (name, cnf_axiom th)) @ pairs
   565                        handle THM _ => pairs | ResClause.CLAUSE _ => pairs
   566       in  cnf_rules_pairs_aux pairs' ths  end;
   567 
   568 (*The combination of rev and tail recursion preserves the original order*)
   569 fun cnf_rules_pairs l = cnf_rules_pairs_aux [] (rev l);
   570 
   571 
   572 (**** Convert all theorems of a claset/simpset into clauses (ResClause.clause, or ResHolClause.clause) ****)
   573 
   574 (*Setup function: takes a theory and installs ALL known theorems into the clause cache*)
   575 
   576 val mark_skolemized = Sign.add_consts_i [("ResAxioms_endtheory", HOLogic.boolT, NoSyn)];
   577 
   578 fun skolem_cache th thy = #2 (skolem_cache_thm th thy);
   579 
   580 fun skolem_cache_all thy = fold skolem_cache (map #2 (PureThy.all_thms_of thy)) thy;
   581 
   582 fun skolem_cache_new thy = fold skolem_cache (map #2 (PureThy.thms_of thy)) thy;
   583 
   584 (*The cache can be kept smaller by inspecting the prop of each thm. Can ignore all that are
   585   lambda_free, but then the individual theory caches become much bigger.*)
   586 
   587 (*The new constant is a hack to prevent multiple execution*)
   588 fun clause_cache_endtheory thy =
   589   let val _ = Output.debug (fn () => "RexAxioms end theory action: " ^ Context.str_of_thy thy)
   590   in
   591     Option.map skolem_cache_new (try mark_skolemized thy)
   592   end;
   593 
   594 (*** meson proof methods ***)
   595 
   596 fun cnf_rules_of_ths ths = List.concat (map cnf_axiom ths);
   597 
   598 (*Expand all new*definitions of abstraction or Skolem functions in a proof state.*)
   599 fun is_absko (Const ("==", _) $ Free (a,_) $ u) = String.isPrefix "llabs_" a orelse String.isPrefix "sko_" a
   600   | is_absko _ = false;
   601 
   602 fun is_okdef xs (Const ("==", _) $ t $ u) =   (*Definition of Free, not in certain terms*)
   603       is_Free t andalso not (member (op aconv) xs t)
   604   | is_okdef _ _ = false
   605 
   606 (*This function tries to cope with open locales, which introduce hypotheses of the form
   607   Free == t, conjecture clauses, which introduce various hypotheses, and also definitions
   608   of llabs_ and sko_ functions. *)
   609 fun expand_defs_tac st0 st =
   610   let val hyps0 = #hyps (rep_thm st0)
   611       val hyps = #hyps (crep_thm st)
   612       val newhyps = filter_out (member (op aconv) hyps0 o Thm.term_of) hyps
   613       val defs = filter (is_absko o Thm.term_of) newhyps
   614       val remaining_hyps = filter_out (member (op aconv) (map Thm.term_of defs))
   615                                       (map Thm.term_of hyps)
   616       val fixed = term_frees (concl_of st) @
   617                   foldl (gen_union (op aconv)) [] (map term_frees remaining_hyps)
   618   in  Output.debug (fn _ => "expand_defs_tac: " ^ string_of_thm st);
   619       Output.debug (fn _ => "  st0: " ^ string_of_thm st0);
   620       Output.debug (fn _ => "  defs: " ^ commas (map string_of_cterm defs));
   621       Seq.of_list [LocalDefs.expand (filter (is_okdef fixed o Thm.term_of) defs) st]
   622   end;
   623 
   624 
   625 fun meson_general_tac ths i st0 =
   626  let val _ = Output.debug (fn () => "Meson called: " ^ cat_lines (map string_of_thm ths))
   627  in  (Meson.meson_claset_tac (cnf_rules_of_ths ths) HOL_cs i THEN expand_defs_tac st0) st0 end;
   628 
   629 val meson_method_setup = Method.add_methods
   630   [("meson", Method.thms_args (fn ths =>
   631       Method.SIMPLE_METHOD' (CHANGED_PROP o meson_general_tac ths)),
   632     "MESON resolution proof procedure")];
   633 
   634 (** Attribute for converting a theorem into clauses **)
   635 
   636 fun meta_cnf_axiom th = map Meson.make_meta_clause (cnf_axiom th);
   637 
   638 fun clausify_rule (th,i) = List.nth (meta_cnf_axiom th, i)
   639 
   640 val clausify = Attrib.syntax (Scan.lift Args.nat
   641   >> (fn i => Thm.rule_attribute (fn _ => fn th => clausify_rule (th, i))));
   642 
   643 
   644 (*** Converting a subgoal into negated conjecture clauses. ***)
   645 
   646 val neg_skolemize_tac = EVERY' [rtac ccontr, ObjectLogic.atomize_prems_tac, Meson.skolemize_tac];
   647 
   648 (*finish_cnf removes tautologies and functional reflexivity axioms, but by calling Thm.varifyT
   649   it can introduce TVars, which are useless in conjecture clauses.*)
   650 val no_tvars = null o term_tvars o prop_of;
   651 
   652 val neg_clausify =
   653   filter no_tvars o Meson.finish_cnf o assume_abstract_list "subgoal" o Meson.make_clauses;
   654 
   655 fun neg_conjecture_clauses st0 n =
   656   let val st = Seq.hd (neg_skolemize_tac n st0)
   657       val (params,_,_) = strip_context (Logic.nth_prem (n, Thm.prop_of st))
   658   in (neg_clausify (Option.valOf (metahyps_thms n st)), params) end
   659   handle Option => raise ERROR "unable to Skolemize subgoal";
   660 
   661 (*Conversion of a subgoal to conjecture clauses. Each clause has
   662   leading !!-bound universal variables, to express generality. *)
   663 val neg_clausify_tac =
   664   neg_skolemize_tac THEN'
   665   SUBGOAL
   666     (fn (prop,_) =>
   667      let val ts = Logic.strip_assums_hyp prop
   668      in EVERY1
   669          [METAHYPS
   670             (fn hyps =>
   671               (Method.insert_tac
   672                 (map forall_intr_vars (neg_clausify hyps)) 1)),
   673           REPEAT_DETERM_N (length ts) o (etac thin_rl)]
   674      end);
   675 
   676 (** The Skolemization attribute **)
   677 
   678 fun conj2_rule (th1,th2) = conjI OF [th1,th2];
   679 
   680 (*Conjoin a list of theorems to form a single theorem*)
   681 fun conj_rule []  = TrueI
   682   | conj_rule ths = foldr1 conj2_rule ths;
   683 
   684 fun skolem_attr (Context.Theory thy, th) =
   685       let val (cls, thy') = skolem_cache_thm th thy
   686       in (Context.Theory thy', conj_rule cls) end
   687   | skolem_attr (context, th) = (context, th)
   688 
   689 val setup_attrs = Attrib.add_attributes
   690   [("skolem", Attrib.no_args skolem_attr, "skolemization of a theorem"),
   691    ("clausify", clausify, "conversion of theorem to clauses")];
   692 
   693 val setup_methods = Method.add_methods
   694   [("neg_clausify", Method.no_args (Method.SIMPLE_METHOD' neg_clausify_tac),
   695     "conversion of goal to conjecture clauses")];
   696 
   697 val setup = mark_skolemized #> skolem_cache_all #> ThmCache.init #> setup_attrs #> setup_methods;
   698 
   699 end;