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