src/HOL/Tools/Sledgehammer/sledgehammer_hol_clause.ML
author blanchet
Tue, 15 Jun 2010 16:42:09 +0200
changeset 37411 2d76997730a6
parent 37389 d0cea0796295
child 37454 f6b1ee5b420b
permissions -rw-r--r--
found missing beta-eta-contraction
     1 (*  Title:      HOL/Tools/Sledgehammer/sledgehammer_hol_clause.ML
     2     Author:     Jia Meng, NICTA
     3     Author:     Jasmin Blanchette, TU Muenchen
     4 
     5 FOL clauses translated from HOL formulae.
     6 *)
     7 
     8 signature SLEDGEHAMMER_HOL_CLAUSE =
     9 sig
    10   type name = Sledgehammer_FOL_Clause.name
    11   type name_pool = Sledgehammer_FOL_Clause.name_pool
    12   type kind = Sledgehammer_FOL_Clause.kind
    13   type fol_type = Sledgehammer_FOL_Clause.fol_type
    14   type classrel_clause = Sledgehammer_FOL_Clause.classrel_clause
    15   type arity_clause = Sledgehammer_FOL_Clause.arity_clause
    16   type axiom_name = string
    17   type polarity = bool
    18   type hol_clause_id = int
    19 
    20   datatype combterm =
    21     CombConst of name * fol_type * fol_type list (* Const and Free *) |
    22     CombVar of name * fol_type |
    23     CombApp of combterm * combterm
    24   datatype literal = Literal of polarity * combterm
    25   datatype hol_clause =
    26     HOLClause of {clause_id: hol_clause_id, axiom_name: axiom_name, th: thm,
    27                   kind: kind, literals: literal list, ctypes_sorts: typ list}
    28 
    29   val type_of_combterm : combterm -> fol_type
    30   val strip_combterm_comb : combterm -> combterm * combterm list
    31   val literals_of_term : theory -> term -> literal list * typ list
    32   val conceal_skolem_somes :
    33     int -> (string * term) list -> term -> (string * term) list * term
    34   exception TRIVIAL
    35   val make_conjecture_clauses : bool -> theory -> thm list -> hol_clause list
    36   val make_axiom_clauses : bool -> theory ->
    37        (thm * (axiom_name * hol_clause_id)) list -> (axiom_name * hol_clause) list
    38   val type_wrapper_name : string
    39   val get_helper_clauses :
    40     bool -> theory -> bool -> hol_clause list
    41       -> (thm * (axiom_name * hol_clause_id)) list -> hol_clause list
    42   val write_tptp_file : bool -> bool -> bool -> Path.T ->
    43     hol_clause list * hol_clause list * hol_clause list * hol_clause list *
    44     classrel_clause list * arity_clause list -> name_pool option * int
    45   val write_dfg_file : bool -> bool -> Path.T ->
    46     hol_clause list * hol_clause list * hol_clause list * hol_clause list *
    47     classrel_clause list * arity_clause list -> name_pool option * int
    48 end
    49 
    50 structure Sledgehammer_HOL_Clause : SLEDGEHAMMER_HOL_CLAUSE =
    51 struct
    52 
    53 open Sledgehammer_Util
    54 open Sledgehammer_FOL_Clause
    55 open Sledgehammer_Fact_Preprocessor
    56 
    57 fun min_arity_of const_min_arity c = the_default 0 (Symtab.lookup const_min_arity c);
    58 
    59 (*True if the constant ever appears outside of the top-level position in literals.
    60   If false, the constant always receives all of its arguments and is used as a predicate.*)
    61 fun needs_hBOOL explicit_apply const_needs_hBOOL c =
    62   explicit_apply orelse
    63     the_default false (Symtab.lookup const_needs_hBOOL c);
    64 
    65 
    66 (******************************************************)
    67 (* data types for typed combinator expressions        *)
    68 (******************************************************)
    69 
    70 type axiom_name = string;
    71 type polarity = bool;
    72 type hol_clause_id = int;
    73 
    74 datatype combterm =
    75   CombConst of name * fol_type * fol_type list (* Const and Free *) |
    76   CombVar of name * fol_type |
    77   CombApp of combterm * combterm
    78 
    79 datatype literal = Literal of polarity * combterm;
    80 
    81 datatype hol_clause =
    82   HOLClause of {clause_id: hol_clause_id, axiom_name: axiom_name, th: thm,
    83                 kind: kind, literals: literal list, ctypes_sorts: typ list};
    84 
    85 
    86 (*********************************************************************)
    87 (* convert a clause with type Term.term to a clause with type clause *)
    88 (*********************************************************************)
    89 
    90 fun isFalse (Literal (pol, CombConst ((c, _), _, _))) =
    91       (pol andalso c = "c_False") orelse (not pol andalso c = "c_True")
    92   | isFalse _ = false;
    93 
    94 fun isTrue (Literal (pol, CombConst ((c, _), _, _))) =
    95       (pol andalso c = "c_True") orelse
    96       (not pol andalso c = "c_False")
    97   | isTrue _ = false;
    98 
    99 fun isTaut (HOLClause {literals,...}) = exists isTrue literals;
   100 
   101 fun type_of dfg (Type (a, Ts)) =
   102     let val (folTypes,ts) = types_of dfg Ts in
   103       (TyConstr (`(make_fixed_type_const dfg) a, folTypes), ts)
   104     end
   105   | type_of _ (tp as TFree (a, _)) = (TyFree (`make_fixed_type_var a), [tp])
   106   | type_of _ (tp as TVar (x, _)) =
   107     (TyVar (make_schematic_type_var x, string_of_indexname x), [tp])
   108 and types_of dfg Ts =
   109       let val (folTyps,ts) = ListPair.unzip (map (type_of dfg) Ts)
   110       in  (folTyps, union_all ts)  end;
   111 
   112 (* same as above, but no gathering of sort information *)
   113 fun simp_type_of dfg (Type (a, Ts)) =
   114       TyConstr (`(make_fixed_type_const dfg) a, map (simp_type_of dfg) Ts)
   115   | simp_type_of _ (TFree (a, _)) = TyFree (`make_fixed_type_var a)
   116   | simp_type_of _ (TVar (x, _)) =
   117     TyVar (make_schematic_type_var x, string_of_indexname x);
   118 
   119 
   120 (* convert a Term.term (with combinators) into a combterm, also accummulate sort info *)
   121 fun combterm_of dfg thy (Const (c, T)) =
   122       let
   123         val (tp, ts) = type_of dfg T
   124         val tvar_list =
   125           (if String.isPrefix skolem_theory_name c then
   126              [] |> Term.add_tvarsT T |> map TVar
   127            else
   128              (c, T) |> Sign.const_typargs thy)
   129           |> map (simp_type_of dfg)
   130         val c' = CombConst (`(make_fixed_const dfg) c, tp, tvar_list)
   131       in  (c',ts)  end
   132   | combterm_of dfg _ (Free(v, T)) =
   133       let val (tp,ts) = type_of dfg T
   134           val v' = CombConst (`make_fixed_var v, tp, [])
   135       in  (v',ts)  end
   136   | combterm_of dfg _ (Var(v, T)) =
   137       let val (tp,ts) = type_of dfg T
   138           val v' = CombVar ((make_schematic_var v, string_of_indexname v), tp)
   139       in  (v',ts)  end
   140   | combterm_of dfg thy (P $ Q) =
   141       let val (P',tsP) = combterm_of dfg thy P
   142           val (Q',tsQ) = combterm_of dfg thy Q
   143       in  (CombApp(P',Q'), union (op =) tsP tsQ)  end
   144   | combterm_of _ _ (t as Abs _) = raise CLAUSE ("HOL clause", t);
   145 
   146 fun predicate_of dfg thy ((@{const Not} $ P), polarity) = predicate_of dfg thy (P, not polarity)
   147   | predicate_of dfg thy (t,polarity) = (combterm_of dfg thy (Envir.eta_contract t), polarity);
   148 
   149 fun literals_of_term1 dfg thy args (@{const Trueprop} $ P) = literals_of_term1 dfg thy args P
   150   | literals_of_term1 dfg thy args (@{const "op |"} $ P $ Q) =
   151       literals_of_term1 dfg thy (literals_of_term1 dfg thy args P) Q
   152   | literals_of_term1 dfg thy (lits,ts) P =
   153       let val ((pred,ts'),pol) = predicate_of dfg thy (P,true)
   154       in
   155           (Literal(pol,pred)::lits, union (op =) ts ts')
   156       end;
   157 
   158 fun literals_of_term_dfg dfg thy P = literals_of_term1 dfg thy ([],[]) P;
   159 val literals_of_term = literals_of_term_dfg false;
   160 
   161 fun skolem_name i j num_T_args =
   162   skolem_prefix ^ (space_implode "_" (map Int.toString [i, j, num_T_args])) ^
   163   skolem_infix ^ "g"
   164 
   165 fun conceal_skolem_somes i skolem_somes t =
   166   if exists_Const (curry (op =) @{const_name skolem_id} o fst) t then
   167     let
   168       fun aux skolem_somes
   169               (t as (Const (@{const_name skolem_id}, Type (_, [_, T])) $ _)) =
   170           let
   171             val (skolem_somes, s) =
   172               if i = ~1 then
   173                 (skolem_somes, @{const_name undefined})
   174               else case AList.find (op aconv) skolem_somes t of
   175                 s :: _ => (skolem_somes, s)
   176               | [] =>
   177                 let
   178                   val s = skolem_theory_name ^ "." ^
   179                           skolem_name i (length skolem_somes)
   180                                         (length (Term.add_tvarsT T []))
   181                 in ((s, t) :: skolem_somes, s) end
   182           in (skolem_somes, Const (s, T)) end
   183         | aux skolem_somes (t1 $ t2) =
   184           let
   185             val (skolem_somes, t1) = aux skolem_somes t1
   186             val (skolem_somes, t2) = aux skolem_somes t2
   187           in (skolem_somes, t1 $ t2) end
   188         | aux skolem_somes (Abs (s, T, t')) =
   189           let val (skolem_somes, t') = aux skolem_somes t' in
   190             (skolem_somes, Abs (s, T, t'))
   191           end
   192         | aux skolem_somes t = (skolem_somes, t)
   193     in aux skolem_somes t end
   194   else
   195     (skolem_somes, t)
   196 
   197 (* Trivial problem, which resolution cannot handle (empty clause) *)
   198 exception TRIVIAL;
   199 
   200 (* making axiom and conjecture clauses *)
   201 fun make_clause dfg thy (clause_id, axiom_name, kind, th) skolem_somes =
   202   let
   203     val (skolem_somes, t) =
   204       th |> prop_of |> conceal_skolem_somes clause_id skolem_somes
   205     val (lits, ctypes_sorts) = literals_of_term_dfg dfg thy t
   206   in
   207     if forall isFalse lits then
   208       raise TRIVIAL
   209     else
   210       (skolem_somes,
   211        HOLClause {clause_id = clause_id, axiom_name = axiom_name, th = th,
   212                   kind = kind, literals = lits, ctypes_sorts = ctypes_sorts})
   213   end
   214 
   215 fun add_axiom_clause dfg thy (th, (name, id)) (skolem_somes, clss) =
   216   let
   217     val (skolem_somes, cls) =
   218       make_clause dfg thy (id, name, Axiom, th) skolem_somes
   219   in (skolem_somes, clss |> not (isTaut cls) ? cons (name, cls)) end
   220 
   221 fun make_axiom_clauses dfg thy clauses =
   222   ([], []) |> fold (add_axiom_clause dfg thy) clauses |> snd
   223 
   224 fun make_conjecture_clauses dfg thy =
   225   let
   226     fun aux _ _ [] = []
   227       | aux n skolem_somes (th :: ths) =
   228         let
   229           val (skolem_somes, cls) =
   230             make_clause dfg thy (n, "conjecture", Conjecture, th) skolem_somes
   231         in cls :: aux (n + 1) skolem_somes ths end
   232   in aux 0 [] end
   233 
   234 (**********************************************************************)
   235 (* convert clause into ATP specific formats:                          *)
   236 (* TPTP used by Vampire and E                                         *)
   237 (* DFG used by SPASS                                                  *)
   238 (**********************************************************************)
   239 
   240 (*Result of a function type; no need to check that the argument type matches.*)
   241 fun result_type (TyConstr (_, [_, tp2])) = tp2
   242   | result_type _ = raise Fail "non-function type"
   243 
   244 fun type_of_combterm (CombConst (_, tp, _)) = tp
   245   | type_of_combterm (CombVar (_, tp)) = tp
   246   | type_of_combterm (CombApp (t1, _)) = result_type (type_of_combterm t1);
   247 
   248 (*gets the head of a combinator application, along with the list of arguments*)
   249 fun strip_combterm_comb u =
   250     let fun stripc (CombApp(t,u), ts) = stripc (t, u::ts)
   251         |   stripc  x =  x
   252     in  stripc(u,[])  end;
   253 
   254 val type_wrapper_name = "ti"
   255 
   256 fun head_needs_hBOOL explicit_apply const_needs_hBOOL
   257                      (CombConst ((c, _), _, _)) =
   258     needs_hBOOL explicit_apply const_needs_hBOOL c
   259   | head_needs_hBOOL _ _ _ = true
   260 
   261 fun wrap_type full_types (s, ty) pool =
   262   if full_types then
   263     let val (s', pool) = string_of_fol_type ty pool in
   264       (type_wrapper_name ^ paren_pack [s, s'], pool)
   265     end
   266   else
   267     (s, pool)
   268 
   269 fun wrap_type_if full_types explicit_apply cnh (head, s, tp) =
   270   if head_needs_hBOOL explicit_apply cnh head then
   271     wrap_type full_types (s, tp)
   272   else
   273     pair s
   274 
   275 fun apply ss = "hAPP" ^ paren_pack ss;
   276 
   277 fun rev_apply (v, []) = v
   278   | rev_apply (v, arg::args) = apply [rev_apply (v, args), arg];
   279 
   280 fun string_apply (v, args) = rev_apply (v, rev args);
   281 
   282 (* Apply an operator to the argument strings, using either the "apply" operator
   283    or direct function application. *)
   284 fun string_of_application full_types cma (CombConst ((s, s'), _, tvars), args)
   285                           pool =
   286     let
   287       val s = if s = "equal" then "c_fequal" else s
   288       val nargs = min_arity_of cma s
   289       val args1 = List.take (args, nargs)
   290         handle Subscript =>
   291                raise Fail (quote s ^ " has arity " ^ Int.toString nargs ^
   292                            " but is applied to " ^ commas (map quote args))
   293       val args2 = List.drop (args, nargs)
   294       val (targs, pool) = if full_types then ([], pool)
   295                           else pool_map string_of_fol_type tvars pool
   296       val (s, pool) = nice_name (s, s') pool
   297     in (string_apply (s ^ paren_pack (args1 @ targs), args2), pool) end
   298   | string_of_application _ _ (CombVar (name, _), args) pool =
   299     nice_name name pool |>> (fn s => string_apply (s, args))
   300 
   301 fun string_of_combterm (params as (full_types, explicit_apply, cma, cnh)) t
   302                        pool =
   303   let
   304     val (head, args) = strip_combterm_comb t
   305     val (ss, pool) = pool_map (string_of_combterm params) args pool
   306     val (s, pool) = string_of_application full_types cma (head, ss) pool
   307   in
   308     wrap_type_if full_types explicit_apply cnh (head, s, type_of_combterm t)
   309                  pool
   310   end
   311 
   312 (*Boolean-valued terms are here converted to literals.*)
   313 fun boolify params c =
   314   string_of_combterm params c #>> prefix "hBOOL" o paren_pack o single
   315 
   316 fun string_of_predicate (params as (_, explicit_apply, _, cnh)) t =
   317   case t of
   318     (CombApp (CombApp (CombConst (("equal", _), _, _), t1), t2)) =>
   319     (* DFG only: new TPTP prefers infix equality *)
   320     pool_map (string_of_combterm params) [t1, t2]
   321     #>> prefix "equal" o paren_pack
   322   | _ =>
   323     case #1 (strip_combterm_comb t) of
   324       CombConst ((s, _), _, _) =>
   325       (if needs_hBOOL explicit_apply cnh s then boolify else string_of_combterm)
   326           params t
   327     | _ => boolify params t
   328 
   329 
   330 (*** TPTP format ***)
   331 
   332 fun tptp_of_equality params pos (t1, t2) =
   333   pool_map (string_of_combterm params) [t1, t2]
   334   #>> space_implode (if pos then " = " else " != ")
   335 
   336 fun tptp_literal params
   337         (Literal (pos, CombApp (CombApp (CombConst (("equal", _), _, _), t1),
   338                                          t2))) =
   339     tptp_of_equality params pos (t1, t2)
   340   | tptp_literal params (Literal (pos, pred)) =
   341     string_of_predicate params pred #>> tptp_sign pos
   342  
   343 (* Given a clause, returns its literals paired with a list of literals
   344    concerning TFrees; the latter should only occur in conjecture clauses. *)
   345 fun tptp_type_literals params pos (HOLClause {literals, ctypes_sorts, ...})
   346                        pool =
   347   let
   348     val (lits, pool) = pool_map (tptp_literal params) literals pool
   349     val (tylits, pool) = pool_map (tptp_of_type_literal pos)
   350                                   (type_literals_for_types ctypes_sorts) pool
   351   in ((lits, tylits), pool) end
   352 
   353 fun tptp_clause params (cls as HOLClause {axiom_name, clause_id, kind, ...})
   354                 pool =
   355 let
   356     val ((lits, tylits), pool) =
   357       tptp_type_literals params (kind = Conjecture) cls pool
   358   in
   359     ((gen_tptp_cls (clause_id, axiom_name, kind, lits, tylits), tylits), pool)
   360   end
   361 
   362 
   363 (*** DFG format ***)
   364 
   365 fun dfg_literal params (Literal (pos, pred)) =
   366   string_of_predicate params pred #>> dfg_sign pos
   367 
   368 fun dfg_type_literals params pos (HOLClause {literals, ctypes_sorts, ...}) =
   369   pool_map (dfg_literal params) literals
   370   #>> rpair (map (dfg_of_type_literal pos)
   371                  (type_literals_for_types ctypes_sorts))
   372 
   373 fun get_uvars (CombConst _) vars pool = (vars, pool)
   374   | get_uvars (CombVar (name, _)) vars pool =
   375     nice_name name pool |>> (fn var => var :: vars)
   376   | get_uvars (CombApp (P, Q)) vars pool =
   377     let val (vars, pool) = get_uvars P vars pool in get_uvars Q vars pool end
   378 
   379 fun get_uvars_l (Literal (_, c)) = get_uvars c [];
   380 
   381 fun dfg_vars (HOLClause {literals, ...}) =
   382   pool_map get_uvars_l literals #>> union_all
   383 
   384 fun dfg_clause params (cls as HOLClause {axiom_name, clause_id, kind,
   385                                          ctypes_sorts, ...}) pool =
   386   let
   387     val ((lits, tylits), pool) =
   388       dfg_type_literals params (kind = Conjecture) cls pool
   389     val (vars, pool) = dfg_vars cls pool
   390     val tvars = get_tvar_strs ctypes_sorts
   391   in
   392     ((gen_dfg_cls (clause_id, axiom_name, kind, lits, tylits, tvars @ vars),
   393       tylits), pool)
   394   end
   395 
   396 
   397 (** For DFG format: accumulate function and predicate declarations **)
   398 
   399 fun add_types tvars = fold add_fol_type_funcs tvars
   400 
   401 fun add_decls (full_types, explicit_apply, cma, cnh)
   402               (CombConst ((c, _), ctp, tvars)) (funcs, preds) =
   403       (if c = "equal" then
   404          (add_types tvars funcs, preds)
   405        else
   406          let val arity = min_arity_of cma c
   407              val ntys = if not full_types then length tvars else 0
   408              val addit = Symtab.update(c, arity + ntys)
   409          in
   410              if needs_hBOOL explicit_apply cnh c then
   411                (add_types tvars (addit funcs), preds)
   412              else
   413                (add_types tvars funcs, addit preds)
   414          end) |>> full_types ? add_fol_type_funcs ctp
   415   | add_decls _ (CombVar (_, ctp)) (funcs, preds) =
   416       (add_fol_type_funcs ctp funcs, preds)
   417   | add_decls params (CombApp (P, Q)) decls =
   418       decls |> add_decls params P |> add_decls params Q
   419 
   420 fun add_literal_decls params (Literal (_, c)) = add_decls params c
   421 
   422 fun add_clause_decls params (HOLClause {literals, ...}) decls =
   423     fold (add_literal_decls params) literals decls
   424     handle Symtab.DUP a => error ("function " ^ a ^ " has multiple arities")
   425 
   426 fun decls_of_clauses (params as (full_types, explicit_apply, _, _)) clauses
   427                      arity_clauses =
   428   let
   429     val functab =
   430       init_functab
   431       |> fold Symtab.update [(type_wrapper_name, 2), ("hAPP", 2),
   432                              ("tc_bool", 0)]
   433       val predtab = Symtab.empty |> Symtab.update ("hBOOL", 1)
   434       val (functab, predtab) =
   435         (functab, predtab) |> fold (add_clause_decls params) clauses
   436                            |>> fold add_arity_clause_funcs arity_clauses
   437   in (Symtab.dest functab, Symtab.dest predtab) end
   438 
   439 fun add_clause_preds (HOLClause {ctypes_sorts, ...}) preds =
   440   fold add_type_sort_preds ctypes_sorts preds
   441   handle Symtab.DUP a => error ("predicate " ^ a ^ " has multiple arities")
   442 
   443 (*Higher-order clauses have only the predicates hBOOL and type classes.*)
   444 fun preds_of_clauses clauses clsrel_clauses arity_clauses =
   445   Symtab.empty
   446   |> fold add_clause_preds clauses
   447   |> fold add_arity_clause_preds arity_clauses
   448   |> fold add_classrel_clause_preds clsrel_clauses
   449   |> Symtab.dest
   450 
   451 (**********************************************************************)
   452 (* write clauses to files                                             *)
   453 (**********************************************************************)
   454 
   455 val init_counters =
   456   Symtab.make [("c_COMBI", 0), ("c_COMBK", 0), ("c_COMBB", 0), ("c_COMBC", 0),
   457                ("c_COMBS", 0)];
   458 
   459 fun count_combterm (CombConst ((c, _), _, _)) =
   460     Symtab.map_entry c (Integer.add 1)
   461   | count_combterm (CombVar _) = I
   462   | count_combterm (CombApp (t1, t2)) = count_combterm t1 #> count_combterm t2
   463 
   464 fun count_literal (Literal (_, t)) = count_combterm t
   465 
   466 fun count_clause (HOLClause {literals, ...}) = fold count_literal literals
   467 
   468 fun cnf_helper_thms thy = cnf_rules_pairs thy o map (`Thm.get_name_hint)
   469 
   470 fun get_helper_clauses dfg thy isFO conjectures axcls =
   471   if isFO then
   472     []
   473   else
   474     let
   475         val axclauses = map snd (make_axiom_clauses dfg thy axcls)
   476         val ct = init_counters
   477                  |> fold (fold count_clause) [conjectures, axclauses]
   478         fun needed c = the (Symtab.lookup ct c) > 0
   479         val IK = if needed "c_COMBI" orelse needed "c_COMBK"
   480                  then cnf_helper_thms thy [@{thm COMBI_def}, @{thm COMBK_def}]
   481                  else []
   482         val BC = if needed "c_COMBB" orelse needed "c_COMBC"
   483                  then cnf_helper_thms thy [@{thm COMBB_def}, @{thm COMBC_def}]
   484                  else []
   485         val S = if needed "c_COMBS" then cnf_helper_thms thy [@{thm COMBS_def}]
   486                 else []
   487         val other = cnf_helper_thms thy [@{thm fequal_imp_equal},
   488                                          @{thm equal_imp_fequal}]
   489     in map snd (make_axiom_clauses dfg thy (other @ IK @ BC @ S)) end
   490 
   491 (*Find the minimal arity of each function mentioned in the term. Also, note which uses
   492   are not at top level, to see if hBOOL is needed.*)
   493 fun count_constants_term toplev t (const_min_arity, const_needs_hBOOL) =
   494   let val (head, args) = strip_combterm_comb t
   495       val n = length args
   496       val (const_min_arity, const_needs_hBOOL) =
   497         (const_min_arity, const_needs_hBOOL)
   498         |> fold (count_constants_term false) args
   499   in
   500       case head of
   501           CombConst ((a, _),_,_) => (*predicate or function version of "equal"?*)
   502             let val a = if a="equal" andalso not toplev then "c_fequal" else a
   503             in
   504               (const_min_arity |> Symtab.map_default (a, n) (Integer.min n),
   505                const_needs_hBOOL |> not toplev ? Symtab.update (a, true))
   506             end
   507         | _ => (const_min_arity, const_needs_hBOOL)
   508   end;
   509 
   510 (*A literal is a top-level term*)
   511 fun count_constants_lit (Literal (_,t)) (const_min_arity, const_needs_hBOOL) =
   512   count_constants_term true t (const_min_arity, const_needs_hBOOL);
   513 
   514 fun count_constants_clause (HOLClause {literals, ...})
   515                            (const_min_arity, const_needs_hBOOL) =
   516   fold count_constants_lit literals (const_min_arity, const_needs_hBOOL);
   517 
   518 fun display_arity explicit_apply const_needs_hBOOL (c,n) =
   519   trace_msg (fn () => "Constant: " ^ c ^
   520                 " arity:\t" ^ Int.toString n ^
   521                 (if needs_hBOOL explicit_apply const_needs_hBOOL c then
   522                    " needs hBOOL"
   523                  else
   524                    ""))
   525 
   526 fun count_constants explicit_apply
   527                     (conjectures, _, extra_clauses, helper_clauses, _, _) =
   528   if not explicit_apply then
   529      let val (const_min_arity, const_needs_hBOOL) =
   530           fold count_constants_clause conjectures (Symtab.empty, Symtab.empty)
   531        |> fold count_constants_clause extra_clauses
   532        |> fold count_constants_clause helper_clauses
   533      val _ = app (display_arity explicit_apply const_needs_hBOOL)
   534                  (Symtab.dest (const_min_arity))
   535      in (const_min_arity, const_needs_hBOOL) end
   536   else (Symtab.empty, Symtab.empty);
   537 
   538 fun header () =
   539   "% This file was generated by Isabelle (most likely Sledgehammer)\n" ^
   540   "% " ^ timestamp () ^ "\n"
   541 
   542 (* TPTP format *)
   543 
   544 fun write_tptp_file readable_names full_types explicit_apply file clauses =
   545   let
   546     fun section _ [] = []
   547       | section name ss =
   548         "\n% " ^ name ^ plural_s (length ss) ^ " (" ^ Int.toString (length ss) ^
   549         ")\n" :: ss
   550     val pool = empty_name_pool readable_names
   551     val (conjectures, axclauses, _, helper_clauses,
   552       classrel_clauses, arity_clauses) = clauses
   553     val (cma, cnh) = count_constants explicit_apply clauses
   554     val params = (full_types, explicit_apply, cma, cnh)
   555     val ((conjecture_clss, tfree_litss), pool) =
   556       pool_map (tptp_clause params) conjectures pool |>> ListPair.unzip
   557     val tfree_clss = map tptp_tfree_clause (fold (union (op =)) tfree_litss [])
   558     val (ax_clss, pool) = pool_map (apfst fst oo tptp_clause params) axclauses
   559                                    pool
   560     val classrel_clss = map tptp_classrel_clause classrel_clauses
   561     val arity_clss = map tptp_arity_clause arity_clauses
   562     val (helper_clss, pool) = pool_map (apfst fst oo tptp_clause params)
   563                                        helper_clauses pool
   564     val conjecture_offset =
   565       length ax_clss + length classrel_clss + length arity_clss
   566       + length helper_clss
   567     val _ =
   568       File.write_list file
   569           (header () ::
   570            section "Relevant fact" ax_clss @
   571            section "Class relationship" classrel_clss @
   572            section "Arity declaration" arity_clss @
   573            section "Helper fact" helper_clss @
   574            section "Conjecture" conjecture_clss @
   575            section "Type variable" tfree_clss)
   576   in (pool, conjecture_offset) end
   577 
   578 (* DFG format *)
   579 
   580 fun dfg_tfree_predicate s = (first_field "(" s |> the |> fst, 1)
   581 
   582 fun write_dfg_file full_types explicit_apply file clauses =
   583   let
   584     (* Some of the helper functions below are not name-pool-aware. However,
   585        there's no point in adding name pool support if the DFG format is on its
   586        way out anyway. *)
   587     val pool = NONE
   588     val (conjectures, axclauses, _, helper_clauses,
   589       classrel_clauses, arity_clauses) = clauses
   590     val (cma, cnh) = count_constants explicit_apply clauses
   591     val params = (full_types, explicit_apply, cma, cnh)
   592     val ((conjecture_clss, tfree_litss), pool) =
   593       pool_map (dfg_clause params) conjectures pool |>> ListPair.unzip
   594     val tfree_lits = union_all tfree_litss
   595     val problem_name = Path.implode (Path.base file)
   596     val (axstrs, pool) = pool_map (apfst fst oo dfg_clause params) axclauses pool
   597     val tfree_clss = map dfg_tfree_clause tfree_lits
   598     val tfree_preds = map dfg_tfree_predicate tfree_lits
   599     val (helper_clauses_strs, pool) =
   600       pool_map (apfst fst oo dfg_clause params) helper_clauses pool
   601     val (funcs, cl_preds) =
   602       decls_of_clauses params (helper_clauses @ conjectures @ axclauses) arity_clauses
   603     val ty_preds = preds_of_clauses axclauses classrel_clauses arity_clauses
   604     val preds = tfree_preds @ cl_preds @ ty_preds
   605     val conjecture_offset =
   606       length axclauses + length classrel_clauses + length arity_clauses
   607       + length helper_clauses
   608     val _ =
   609       File.write_list file
   610           (header () ::
   611            string_of_start problem_name ::
   612            string_of_descrip problem_name ::
   613            string_of_symbols (string_of_funcs funcs)
   614                              (string_of_preds preds) ::
   615            "list_of_clauses(axioms, cnf).\n" ::
   616            axstrs @
   617            map dfg_classrel_clause classrel_clauses @
   618            map dfg_arity_clause arity_clauses @
   619            helper_clauses_strs @
   620            ["end_of_list.\n\nlist_of_clauses(conjectures, cnf).\n"] @
   621            conjecture_clss @
   622            tfree_clss @
   623            ["end_of_list.\n\n",
   624             "end_problem.\n"])
   625   in (pool, conjecture_offset) end
   626 
   627 end;