src/HOL/Tools/res_hol_clause.ML
author paulson
Thu Jun 14 13:18:59 2007 +0200 (2007-06-14 ago)
changeset 23386 9255c1a75ba9
parent 22851 7b7d6e1c70b6
child 24215 5458fbf18276
permissions -rw-r--r--
Now also handles FO problems
mengj@17998
     1
(* ID: $Id$ 
mengj@17998
     2
   Author: Jia Meng, NICTA
mengj@17998
     3
paulson@22825
     4
FOL clauses translated from HOL formulae.  
paulson@22825
     5
paulson@22825
     6
The combinator code needs to be deleted after the translation paper has been published.
paulson@22825
     7
It cannot be used with proof reconstruction because combinators are not introduced by proof.
paulson@22825
     8
The Turner combinators (B', C', S') yield no improvement and should be deleted.
mengj@17998
     9
*)
mengj@17998
    10
mengj@17998
    11
structure ResHolClause =
mengj@17998
    12
mengj@17998
    13
struct
mengj@17998
    14
paulson@22078
    15
structure RC = ResClause;
paulson@22078
    16
mengj@20791
    17
(* theorems for combinators and function extensionality *)
mengj@20791
    18
val ext = thm "HOL.ext";
wenzelm@21254
    19
val comb_I = thm "ATP_Linkup.COMBI_def";
wenzelm@21254
    20
val comb_K = thm "ATP_Linkup.COMBK_def";
wenzelm@21254
    21
val comb_B = thm "ATP_Linkup.COMBB_def";
wenzelm@21254
    22
val comb_C = thm "ATP_Linkup.COMBC_def";
wenzelm@21254
    23
val comb_S = thm "ATP_Linkup.COMBS_def";
wenzelm@21254
    24
val comb_B' = thm "ATP_Linkup.COMBB'_def";
wenzelm@21254
    25
val comb_C' = thm "ATP_Linkup.COMBC'_def";
wenzelm@21254
    26
val comb_S' = thm "ATP_Linkup.COMBS'_def";
wenzelm@21254
    27
val fequal_imp_equal = thm "ATP_Linkup.fequal_imp_equal";
wenzelm@21254
    28
val equal_imp_fequal = thm "ATP_Linkup.equal_imp_fequal";
mengj@20791
    29
paulson@22825
    30
paulson@22825
    31
(*The different translations of types*)
paulson@22825
    32
datatype type_level = T_FULL | T_PARTIAL | T_CONST;
paulson@22825
    33
paulson@22825
    34
val typ_level = ref T_CONST;
paulson@22825
    35
paulson@22825
    36
fun full_types () = (typ_level:=T_FULL);
paulson@22825
    37
fun partial_types () = (typ_level:=T_PARTIAL);
paulson@22825
    38
fun const_types_only () = (typ_level:=T_CONST);
paulson@22825
    39
paulson@21108
    40
(*A flag to set if we use the Turner optimizations. Currently FALSE, as the 5 standard
paulson@20997
    41
  combinators appear to work best.*)
paulson@21108
    42
val use_Turner = ref false;
mengj@17998
    43
paulson@22064
    44
(*If true, each function will be directly applied to as many arguments as possible, avoiding
paulson@22825
    45
  use of the "apply" operator. Use of hBOOL is also minimized. It only works for the 
paulson@22825
    46
  constant-typed translation, though it could be tried for the partially-typed one.*)
paulson@22078
    47
val minimize_applies = ref true;
paulson@22064
    48
mengj@18356
    49
val const_typargs = ref (Library.K [] : (string*typ -> typ list));
mengj@18356
    50
paulson@22064
    51
val const_min_arity = ref (Symtab.empty : int Symtab.table);
paulson@22064
    52
paulson@22064
    53
val const_needs_hBOOL = ref (Symtab.empty : bool Symtab.table);
paulson@22064
    54
paulson@22064
    55
fun min_arity_of c = getOpt (Symtab.lookup(!const_min_arity) c, 0);
paulson@22064
    56
paulson@22825
    57
(*True if the constant ever appears outside of the top-level position in literals.
paulson@22825
    58
  If false, the constant always receives all of its arguments and is used as a predicate.*)
paulson@22851
    59
fun needs_hBOOL c = not (!minimize_applies) orelse !typ_level=T_PARTIAL orelse
paulson@22064
    60
                    getOpt (Symtab.lookup(!const_needs_hBOOL) c, false);
paulson@22064
    61
paulson@23386
    62
fun init thy = (const_typargs := Sign.const_typargs thy);
mengj@19198
    63
mengj@17998
    64
(**********************************************************************)
mengj@17998
    65
(* convert a Term.term with lambdas into a Term.term with combinators *) 
mengj@17998
    66
(**********************************************************************)
mengj@17998
    67
mengj@17998
    68
fun is_free (Bound(a)) n = (a = n)
mengj@17998
    69
  | is_free (Abs(x,_,b)) n = (is_free b (n+1))
mengj@17998
    70
  | is_free (P $ Q) n = ((is_free P n) orelse (is_free Q n))
mengj@17998
    71
  | is_free _ _ = false;
mengj@17998
    72
paulson@21573
    73
fun mk_compact_comb (tm as (Const("ATP_Linkup.COMBB",_)$p) $ (Const("ATP_Linkup.COMBB",_)$q$r)) bnds =
paulson@21573
    74
      let val tp_p = Term.type_of1(bnds,p)
paulson@21573
    75
	  val tp_q = Term.type_of1(bnds,q)
paulson@21573
    76
	  val tp_r = Term.type_of1(bnds,r)
paulson@22064
    77
	  val typ_B' = [tp_p,tp_q,tp_r] ---> Term.type_of1(bnds,tm)
paulson@21573
    78
      in
paulson@21573
    79
	  Const("ATP_Linkup.COMBB'",typ_B') $ p $ q $ r
paulson@21573
    80
      end
paulson@21573
    81
  | mk_compact_comb (tm as (Const("ATP_Linkup.COMBC",_) $ (Const("ATP_Linkup.COMBB",_)$p$q) $ r)) bnds =
paulson@21573
    82
      let val tp_p = Term.type_of1(bnds,p)
paulson@21573
    83
	  val tp_q = Term.type_of1(bnds,q)
paulson@21573
    84
	  val tp_r = Term.type_of1(bnds,r)
paulson@22064
    85
	  val typ_C' = [tp_p,tp_q,tp_r] ---> Term.type_of1(bnds,tm)
paulson@21573
    86
      in
paulson@21573
    87
	  Const("ATP_Linkup.COMBC'",typ_C') $ p $ q $ r
paulson@21573
    88
      end
paulson@21573
    89
  | mk_compact_comb (tm as (Const("ATP_Linkup.COMBS",_) $ (Const("ATP_Linkup.COMBB",_)$p$q) $ r)) bnds =
paulson@21573
    90
      let val tp_p = Term.type_of1(bnds,p)
paulson@21573
    91
	  val tp_q = Term.type_of1(bnds,q)
paulson@21573
    92
	  val tp_r = Term.type_of1(bnds,r)
paulson@22064
    93
	  val typ_S' = [tp_p,tp_q,tp_r] ---> Term.type_of1(bnds,tm)
paulson@21573
    94
      in
paulson@21573
    95
	  Const("ATP_Linkup.COMBS'",typ_S') $ p $ q $ r
paulson@21573
    96
      end
paulson@21573
    97
  | mk_compact_comb tm _ = tm;
mengj@20644
    98
paulson@21573
    99
fun compact_comb t bnds = 
paulson@21573
   100
  if !use_Turner then mk_compact_comb t bnds else t;
mengj@20644
   101
paulson@21573
   102
fun lam2comb (Abs(x,tp,Bound 0)) _ = Const("ATP_Linkup.COMBI",tp-->tp) 
paulson@21573
   103
  | lam2comb (Abs(x,tp,Bound n)) bnds = 
paulson@21573
   104
      let val tb = List.nth(bnds,n-1)
paulson@22064
   105
      in  Const("ATP_Linkup.COMBK", [tb,tp] ---> tb) $ Bound (n-1)  end
paulson@21573
   106
  | lam2comb (Abs(x,t1,Const(c,t2))) _ = Const("ATP_Linkup.COMBK",[t2,t1] ---> t2) $ Const(c,t2) 
paulson@21573
   107
  | lam2comb (Abs(x,t1,Free(v,t2))) _ = Const("ATP_Linkup.COMBK",[t2,t1] ---> t2) $ Free(v,t2)
paulson@21573
   108
  | lam2comb (Abs(x,t1,Var(ind,t2))) _ = Const("ATP_Linkup.COMBK", [t2,t1] ---> t2) $ Var(ind,t2)
paulson@21573
   109
  | lam2comb (t as (Abs(x,t1,P$(Bound 0)))) bnds =
paulson@21573
   110
      if is_free P 0 then 
paulson@21135
   111
	  let val tI = [t1] ---> t1
paulson@21573
   112
	      val P' = lam2comb (Abs(x,t1,P)) bnds
paulson@21573
   113
	      val tp' = Term.type_of1(bnds,P')
paulson@22064
   114
	      val tS = [tp',tI] ---> Term.type_of1(t1::bnds,P)
paulson@21108
   115
	  in
wenzelm@21254
   116
	      compact_comb (Const("ATP_Linkup.COMBS",tS) $ P' $ 
paulson@21573
   117
	                     Const("ATP_Linkup.COMBI",tI)) bnds
paulson@21108
   118
	  end
paulson@21573
   119
      else incr_boundvars ~1 P
paulson@21573
   120
  | lam2comb (t as (Abs(x,t1,P$Q))) bnds =
paulson@21108
   121
      let val nfreeP = not(is_free P 0)
paulson@21108
   122
	  and nfreeQ = not(is_free Q 0)
paulson@21573
   123
	  val tpq = Term.type_of1(t1::bnds, P$Q) 
paulson@21108
   124
      in
paulson@21108
   125
	  if nfreeP andalso nfreeQ 
paulson@21108
   126
	  then 
paulson@21135
   127
	    let val tK = [tpq,t1] ---> tpq
paulson@22064
   128
	    in  Const("ATP_Linkup.COMBK",tK) $ incr_boundvars ~1 (P $ Q)  end
paulson@21108
   129
	  else if nfreeP then 
paulson@21573
   130
	    let val Q' = lam2comb (Abs(x,t1,Q)) bnds
paulson@21135
   131
		val P' = incr_boundvars ~1 P
paulson@21573
   132
		val tp = Term.type_of1(bnds,P')
paulson@21573
   133
		val tq' = Term.type_of1(bnds, Q')
paulson@21135
   134
		val tB = [tp,tq',t1] ---> tpq
paulson@22064
   135
	    in  compact_comb (Const("ATP_Linkup.COMBB",tB) $ P' $ Q') bnds  end
paulson@21108
   136
	  else if nfreeQ then 
paulson@21573
   137
	    let val P' = lam2comb (Abs(x,t1,P)) bnds
paulson@21135
   138
		val Q' = incr_boundvars ~1 Q
paulson@21573
   139
		val tq = Term.type_of1(bnds,Q')
paulson@21573
   140
		val tp' = Term.type_of1(bnds, P')
paulson@21135
   141
		val tC = [tp',tq,t1] ---> tpq
paulson@22064
   142
	    in  compact_comb (Const("ATP_Linkup.COMBC",tC) $ P' $ Q') bnds  end
paulson@21108
   143
          else
paulson@21573
   144
	    let val P' = lam2comb (Abs(x,t1,P)) bnds
paulson@21573
   145
		val Q' = lam2comb (Abs(x,t1,Q)) bnds 
paulson@21573
   146
		val tp' = Term.type_of1(bnds,P')
paulson@21573
   147
		val tq' = Term.type_of1(bnds,Q')
paulson@21135
   148
		val tS = [tp',tq',t1] ---> tpq
paulson@22064
   149
	    in  compact_comb (Const("ATP_Linkup.COMBS",tS) $ P' $ Q') bnds  end
paulson@21108
   150
      end
paulson@22078
   151
  | lam2comb (t as (Abs(x,t1,_))) _ = raise RC.CLAUSE("HOL CLAUSE",t);
mengj@17998
   152
paulson@22064
   153
fun to_comb (Abs(x,tp,b)) bnds = lam2comb (Abs(x, tp, to_comb b (tp::bnds))) bnds 
paulson@21573
   154
  | to_comb (P $ Q) bnds = (to_comb P bnds) $ (to_comb Q bnds)
paulson@21573
   155
  | to_comb t _ = t;
mengj@17998
   156
mengj@17998
   157
mengj@17998
   158
(******************************************************)
mengj@17998
   159
(* data types for typed combinator expressions        *)
mengj@17998
   160
(******************************************************)
mengj@17998
   161
mengj@17998
   162
type axiom_name = string;
mengj@17998
   163
type polarity = bool;
mengj@17998
   164
type clause_id = int;
mengj@17998
   165
paulson@23386
   166
datatype combterm = CombConst of string * RC.fol_type * RC.fol_type list (*Const and Free*)
paulson@22078
   167
		  | CombVar of string * RC.fol_type
paulson@22078
   168
		  | CombApp of combterm * combterm
paulson@20360
   169
		  
mengj@17998
   170
datatype literal = Literal of polarity * combterm;
mengj@17998
   171
mengj@17998
   172
datatype clause = 
mengj@17998
   173
	 Clause of {clause_id: clause_id,
mengj@17998
   174
		    axiom_name: axiom_name,
paulson@19964
   175
		    th: thm,
paulson@22078
   176
		    kind: RC.kind,
mengj@17998
   177
		    literals: literal list,
paulson@22078
   178
		    ctypes_sorts: (RC.typ_var * Term.sort) list, 
paulson@22078
   179
                    ctvar_type_literals: RC.type_literal list, 
paulson@22078
   180
                    ctfree_type_literals: RC.type_literal list};
mengj@17998
   181
mengj@17998
   182
mengj@17998
   183
(*********************************************************************)
mengj@17998
   184
(* convert a clause with type Term.term to a clause with type clause *)
mengj@17998
   185
(*********************************************************************)
mengj@17998
   186
paulson@21561
   187
fun isFalse (Literal(pol, CombConst(c,_,_))) =
paulson@20360
   188
      (pol andalso c = "c_False") orelse
paulson@20360
   189
      (not pol andalso c = "c_True")
mengj@17998
   190
  | isFalse _ = false;
mengj@17998
   191
paulson@21561
   192
fun isTrue (Literal (pol, CombConst(c,_,_))) =
mengj@17998
   193
      (pol andalso c = "c_True") orelse
mengj@17998
   194
      (not pol andalso c = "c_False")
mengj@17998
   195
  | isTrue _ = false;
mengj@17998
   196
  
mengj@17998
   197
fun isTaut (Clause {literals,...}) = exists isTrue literals;  
mengj@17998
   198
mengj@18440
   199
fun type_of (Type (a, Ts)) =
paulson@21561
   200
      let val (folTypes,ts) = types_of Ts
paulson@22078
   201
      in  (RC.Comp(RC.make_fixed_type_const a, folTypes), ts)  end
mengj@18440
   202
  | type_of (tp as (TFree(a,s))) =
paulson@22078
   203
      (RC.AtomF (RC.make_fixed_type_var a), [RC.mk_typ_var_sort tp])
mengj@18440
   204
  | type_of (tp as (TVar(v,s))) =
paulson@22078
   205
      (RC.AtomV (RC.make_schematic_type_var v), [RC.mk_typ_var_sort tp])
mengj@18440
   206
and types_of Ts =
paulson@22078
   207
      let val (folTyps,ts) = ListPair.unzip (map type_of Ts)
paulson@22078
   208
      in  (folTyps, RC.union_all ts)  end;
mengj@17998
   209
mengj@17998
   210
(* same as above, but no gathering of sort information *)
mengj@18440
   211
fun simp_type_of (Type (a, Ts)) = 
paulson@22078
   212
      RC.Comp(RC.make_fixed_type_const a, map simp_type_of Ts)
paulson@22078
   213
  | simp_type_of (TFree (a,s)) = RC.AtomF(RC.make_fixed_type_var a)
paulson@22078
   214
  | simp_type_of (TVar (v,s)) = RC.AtomV(RC.make_schematic_type_var v);
mengj@18440
   215
mengj@18356
   216
mengj@20865
   217
fun const_type_of (c,t) =
paulson@22078
   218
      let val (tp,ts) = type_of t
paulson@22078
   219
      in  (tp, ts, map simp_type_of (!const_typargs(c,t))) end;
mengj@18356
   220
mengj@17998
   221
(* convert a Term.term (with combinators) into a combterm, also accummulate sort info *)
mengj@17998
   222
fun combterm_of (Const(c,t)) =
paulson@21513
   223
      let val (tp,ts,tvar_list) = const_type_of (c,t)
paulson@22078
   224
	  val c' = CombConst(RC.make_fixed_const c, tp, tvar_list)
paulson@22078
   225
      in  (c',ts)  end
mengj@17998
   226
  | combterm_of (Free(v,t)) =
paulson@21513
   227
      let val (tp,ts) = type_of t
paulson@22078
   228
	  val v' = if RC.isMeta v then CombVar(RC.make_schematic_var(v,0),tp)
paulson@23386
   229
		   else CombConst(RC.make_fixed_var v, tp, [])
paulson@22078
   230
      in  (v',ts)  end
mengj@17998
   231
  | combterm_of (Var(v,t)) =
paulson@21513
   232
      let val (tp,ts) = type_of t
paulson@22078
   233
	  val v' = CombVar(RC.make_schematic_var v,tp)
paulson@22078
   234
      in  (v',ts)  end
mengj@17998
   235
  | combterm_of (t as (P $ Q)) =
paulson@21513
   236
      let val (P',tsP) = combterm_of P
paulson@21513
   237
	  val (Q',tsQ) = combterm_of Q
paulson@22078
   238
      in  (CombApp(P',Q'), tsP union tsQ)  end;
mengj@17998
   239
paulson@21573
   240
fun predicate_of ((Const("Not",_) $ P), polarity) = predicate_of (P, not polarity)
paulson@21573
   241
  | predicate_of (t,polarity) = (combterm_of t, polarity);
mengj@17998
   242
mengj@17998
   243
fun literals_of_term1 args (Const("Trueprop",_) $ P) = literals_of_term1 args P
mengj@17998
   244
  | literals_of_term1 args (Const("op |",_) $ P $ Q) = 
paulson@21509
   245
      literals_of_term1 (literals_of_term1 args P) Q
mengj@17998
   246
  | literals_of_term1 (lits,ts) P =
paulson@21509
   247
      let val ((pred,ts'),pol) = predicate_of (P,true)
paulson@21509
   248
      in
paulson@21509
   249
	  (Literal(pol,pred)::lits, ts union ts')
paulson@21509
   250
      end;
mengj@17998
   251
mengj@17998
   252
fun literals_of_term P = literals_of_term1 ([],[]) P;
mengj@17998
   253
mengj@17998
   254
(* making axiom and conjecture clauses *)
paulson@21573
   255
fun make_clause(clause_id,axiom_name,kind,th) =
paulson@21573
   256
    let val (lits,ctypes_sorts) = literals_of_term (to_comb (prop_of th) [])
paulson@22078
   257
	val (ctvar_lits,ctfree_lits) = RC.add_typs_aux ctypes_sorts
mengj@17998
   258
    in
mengj@20016
   259
	if forall isFalse lits
mengj@20016
   260
	then error "Problem too trivial for resolution (empty clause)"
mengj@20016
   261
	else
paulson@21509
   262
	    Clause {clause_id = clause_id, axiom_name = axiom_name, th = th, kind = kind,
mengj@20016
   263
		    literals = lits, ctypes_sorts = ctypes_sorts, 
mengj@20016
   264
		    ctvar_type_literals = ctvar_lits,
mengj@20016
   265
		    ctfree_type_literals = ctfree_lits}
mengj@17998
   266
    end;
mengj@17998
   267
mengj@20016
   268
paulson@21573
   269
fun add_axiom_clause ((th,(name,id)), pairs) =
paulson@22078
   270
  let val cls = make_clause(id, name, RC.Axiom, th)
paulson@21573
   271
  in
paulson@21573
   272
      if isTaut cls then pairs else (name,cls)::pairs
paulson@21573
   273
  end;
mengj@19354
   274
paulson@21573
   275
val make_axiom_clauses = foldl add_axiom_clause [];
mengj@19354
   276
mengj@17998
   277
fun make_conjecture_clauses_aux _ [] = []
paulson@20421
   278
  | make_conjecture_clauses_aux n (th::ths) =
paulson@22078
   279
      make_clause(n,"conjecture", RC.Conjecture, th) ::
paulson@20421
   280
      make_conjecture_clauses_aux (n+1) ths;
mengj@17998
   281
mengj@17998
   282
val make_conjecture_clauses = make_conjecture_clauses_aux 0;
mengj@17998
   283
mengj@17998
   284
mengj@17998
   285
(**********************************************************************)
mengj@17998
   286
(* convert clause into ATP specific formats:                          *)
mengj@17998
   287
(* TPTP used by Vampire and E                                         *)
mengj@19720
   288
(* DFG used by SPASS                                                  *)
mengj@17998
   289
(**********************************************************************)
mengj@17998
   290
paulson@22078
   291
(*Result of a function type; no need to check that the argument type matches.*)
paulson@22078
   292
fun result_type (RC.Comp ("tc_fun", [_, tp2])) = tp2
paulson@22078
   293
  | result_type _ = raise ERROR "result_type"
paulson@22078
   294
paulson@21513
   295
fun type_of_combterm (CombConst(c,tp,_)) = tp
paulson@21513
   296
  | type_of_combterm (CombVar(v,tp)) = tp
paulson@22078
   297
  | type_of_combterm (CombApp(t1,t2)) = result_type (type_of_combterm t1);
mengj@17998
   298
paulson@22064
   299
(*gets the head of a combinator application, along with the list of arguments*)
paulson@22064
   300
fun strip_comb u =
paulson@22078
   301
    let fun stripc (CombApp(t,u), ts) = stripc (t, u::ts)
paulson@22064
   302
        |   stripc  x =  x
paulson@22064
   303
    in  stripc(u,[])  end;
paulson@22064
   304
paulson@22851
   305
val type_wrapper = "ti";
paulson@22851
   306
paulson@22851
   307
fun head_needs_hBOOL (CombConst(c,_,_)) = needs_hBOOL c
paulson@22851
   308
  | head_needs_hBOOL _ = true;
paulson@22851
   309
paulson@22851
   310
fun wrap_type (s, tp) = 
paulson@22851
   311
  if !typ_level=T_FULL then
paulson@22851
   312
      type_wrapper ^ RC.paren_pack [s, RC.string_of_fol_type tp]
paulson@22851
   313
  else s;
paulson@22851
   314
    
paulson@22851
   315
fun apply ss = "hAPP" ^ RC.paren_pack ss;
paulson@22851
   316
paulson@22851
   317
(*Full (non-optimized) and partial-typed transations*)
paulson@21513
   318
fun string_of_combterm1 (CombConst(c,tp,_)) = 
paulson@21513
   319
      let val c' = if c = "equal" then "c_fequal" else c
paulson@21513
   320
      in  wrap_type (c',tp)  end
paulson@21513
   321
  | string_of_combterm1 (CombVar(v,tp)) = wrap_type (v,tp)
paulson@22078
   322
  | string_of_combterm1 (CombApp(t1,t2)) =
paulson@21513
   323
      let val s1 = string_of_combterm1 t1
paulson@22078
   324
	  and s2 = string_of_combterm1 t2
paulson@21513
   325
      in
paulson@21513
   326
	  case !typ_level of
paulson@22851
   327
	      T_FULL => wrap_type (apply [s1,s2], result_type (type_of_combterm t1))
paulson@22851
   328
	    | T_PARTIAL => apply [s1,s2, RC.string_of_fol_type (type_of_combterm t1)]
paulson@21513
   329
	    | T_CONST => raise ERROR "string_of_combterm1"
paulson@21561
   330
      end;
mengj@18356
   331
paulson@22064
   332
fun rev_apply (v, []) = v
paulson@22851
   333
  | rev_apply (v, arg::args) = apply [rev_apply (v, args), arg];
paulson@22064
   334
paulson@22064
   335
fun string_apply (v, args) = rev_apply (v, rev args);
paulson@22064
   336
paulson@22064
   337
(*Apply an operator to the argument strings, using either the "apply" operator or
paulson@22064
   338
  direct function application.*)
paulson@22851
   339
fun string_of_applic (CombConst(c,tp,tvars), args) =
paulson@22064
   340
      let val c = if c = "equal" then "c_fequal" else c
paulson@22064
   341
          val nargs = min_arity_of c
paulson@22851
   342
          val args1 = List.take(args, nargs)
paulson@22064
   343
            handle Subscript => raise ERROR ("string_of_applic: " ^ c ^ " has arity " ^
paulson@22064
   344
					     Int.toString nargs ^ " but is applied to " ^ 
paulson@22064
   345
					     space_implode ", " args) 
paulson@22064
   346
          val args2 = List.drop(args, nargs)
paulson@22851
   347
          val targs = if !typ_level = T_CONST then map RC.string_of_fol_type tvars
paulson@22851
   348
                      else []
paulson@21513
   349
      in
paulson@22851
   350
	  string_apply (c ^ RC.paren_pack (args1@targs), args2)
paulson@21513
   351
      end
paulson@22851
   352
  | string_of_applic (CombVar(v,tp), args) = string_apply (v, args)
paulson@22064
   353
  | string_of_applic _ = raise ERROR "string_of_applic";
paulson@22064
   354
paulson@22851
   355
fun wrap_type_if (head, s, tp) = if head_needs_hBOOL head then wrap_type (s, tp) else s;
paulson@22851
   356
    
paulson@22851
   357
(*Full (if optimized) and constant-typed transations*)
paulson@22064
   358
fun string_of_combterm2 t = 
paulson@22064
   359
  let val (head, args) = strip_comb t
paulson@22851
   360
  in  wrap_type_if (head, 
paulson@22851
   361
                    string_of_applic (head, map string_of_combterm2 args), 
paulson@22851
   362
                    type_of_combterm t)
paulson@22851
   363
  end;
mengj@18356
   364
paulson@21513
   365
fun string_of_combterm t = 
paulson@22851
   366
    case (!typ_level,!minimize_applies) of
paulson@22851
   367
         (T_PARTIAL, _) => string_of_combterm1 t
paulson@22851
   368
       | (T_FULL, false) => string_of_combterm1 t
paulson@22851
   369
       | _ => string_of_combterm2 t;
paulson@22064
   370
paulson@22064
   371
(*Boolean-valued terms are here converted to literals.*)
paulson@22078
   372
fun boolify t = "hBOOL" ^ RC.paren_pack [string_of_combterm t];
paulson@22064
   373
paulson@22064
   374
fun string_of_predicate t = 
paulson@22064
   375
  case t of
paulson@22078
   376
      (CombApp(CombApp(CombConst("equal",_,_), t1), t2)) =>
paulson@22064
   377
	  (*DFG only: new TPTP prefers infix equality*)
paulson@22078
   378
	  ("equal" ^ RC.paren_pack [string_of_combterm t1, string_of_combterm t2])
paulson@22064
   379
    | _ => 
paulson@22064
   380
          case #1 (strip_comb t) of
paulson@22064
   381
              CombConst(c,_,_) => if needs_hBOOL c then boolify t else string_of_combterm t
paulson@22064
   382
            | _ => boolify t;
mengj@18356
   383
mengj@17998
   384
fun string_of_clausename (cls_id,ax_name) = 
paulson@22078
   385
    RC.clause_prefix ^ RC.ascii_of ax_name ^ "_" ^ Int.toString cls_id;
mengj@17998
   386
mengj@17998
   387
fun string_of_type_clsname (cls_id,ax_name,idx) = 
mengj@17998
   388
    string_of_clausename (cls_id,ax_name) ^ "_tcs" ^ (Int.toString idx);
mengj@17998
   389
mengj@17998
   390
paulson@21561
   391
(*** tptp format ***)
mengj@19720
   392
paulson@21513
   393
fun tptp_of_equality pol (t1,t2) =
paulson@21513
   394
  let val eqop = if pol then " = " else " != "
paulson@21513
   395
  in  string_of_combterm t1 ^ eqop ^ string_of_combterm t2  end;
paulson@21513
   396
paulson@22078
   397
fun tptp_literal (Literal(pol, CombApp(CombApp(CombConst("equal",_,_), t1), t2))) = 
paulson@21513
   398
      tptp_of_equality pol (t1,t2)
paulson@21513
   399
  | tptp_literal (Literal(pol,pred)) = 
paulson@22078
   400
      RC.tptp_sign pol (string_of_predicate pred);
mengj@17998
   401
 
paulson@22064
   402
(*Given a clause, returns its literals paired with a list of literals concerning TFrees;
paulson@22064
   403
  the latter should only occur in conjecture clauses.*)
mengj@17998
   404
fun tptp_type_lits (Clause cls) = 
mengj@17998
   405
    let val lits = map tptp_literal (#literals cls)
paulson@22825
   406
	val ctvar_lits_strs = map RC.tptp_of_typeLit (#ctvar_type_literals cls)
paulson@22825
   407
	val ctfree_lits = map RC.tptp_of_typeLit (#ctfree_type_literals cls)
mengj@17998
   408
    in
mengj@17998
   409
	(ctvar_lits_strs @ lits, ctfree_lits)
mengj@17998
   410
    end; 
mengj@18356
   411
    
paulson@21509
   412
fun clause2tptp (cls as Clause{axiom_name,clause_id,kind,ctypes_sorts,...}) =
mengj@17998
   413
    let val (lits,ctfree_lits) = tptp_type_lits cls
paulson@22078
   414
	val cls_str = RC.gen_tptp_cls(clause_id,axiom_name,kind,lits)
mengj@17998
   415
    in
mengj@17998
   416
	(cls_str,ctfree_lits)
mengj@17998
   417
    end;
mengj@17998
   418
mengj@17998
   419
paulson@21561
   420
(*** dfg format ***)
paulson@21561
   421
paulson@22078
   422
fun dfg_literal (Literal(pol,pred)) = RC.dfg_sign pol (string_of_predicate pred);
mengj@19720
   423
mengj@19720
   424
fun dfg_clause_aux (Clause{literals, ctypes_sorts, ...}) = 
mengj@19720
   425
  let val lits = map dfg_literal literals
paulson@22078
   426
      val (tvar_lits,tfree_lits) = RC.add_typs_aux ctypes_sorts
paulson@22825
   427
      val tvar_lits_strs = map RC.dfg_of_typeLit tvar_lits
paulson@22825
   428
      val tfree_lits = map RC.dfg_of_typeLit tfree_lits 
mengj@19720
   429
  in
mengj@19720
   430
      (tvar_lits_strs @ lits, tfree_lits)
mengj@19720
   431
  end; 
mengj@19720
   432
paulson@22078
   433
fun get_uvars (CombConst _) vars = vars
paulson@22078
   434
  | get_uvars (CombVar(v,_)) vars = (v::vars)
paulson@22078
   435
  | get_uvars (CombApp(P,Q)) vars = get_uvars P (get_uvars Q vars);
mengj@19720
   436
mengj@19720
   437
fun get_uvars_l (Literal(_,c)) = get_uvars c [];
mengj@19720
   438
paulson@22078
   439
fun dfg_vars (Clause {literals,...}) = RC.union_all (map get_uvars_l literals);
mengj@19720
   440
 
mengj@19720
   441
fun clause2dfg (cls as Clause{axiom_name,clause_id,kind,ctypes_sorts,...}) =
mengj@19720
   442
    let val (lits,tfree_lits) = dfg_clause_aux cls 
mengj@19720
   443
        val vars = dfg_vars cls
paulson@22078
   444
        val tvars = RC.get_tvar_strs ctypes_sorts
paulson@22078
   445
	val knd = RC.name_of_kind kind
mengj@19720
   446
	val lits_str = commas lits
paulson@22078
   447
	val cls_str = RC.gen_dfg_cls(clause_id, axiom_name, knd, lits_str, tvars@vars) 
mengj@19720
   448
    in (cls_str, tfree_lits) end;
mengj@19720
   449
paulson@22064
   450
(** For DFG format: accumulate function and predicate declarations **)
mengj@19720
   451
paulson@22078
   452
fun addtypes tvars tab = foldl RC.add_foltype_funcs tab tvars;
mengj@19720
   453
paulson@22825
   454
fun add_decls (CombConst(c,tp,tvars), (funcs,preds)) =
paulson@22064
   455
      if c = "equal" then (addtypes tvars funcs, preds)
paulson@21561
   456
      else
paulson@21561
   457
	(case !typ_level of
paulson@22851
   458
            T_PARTIAL => (RC.add_foltype_funcs (tp, Symtab.update(c,0) funcs), preds)
paulson@22851
   459
	  | _ => 
paulson@22851
   460
               let val arity = min_arity_of c 
paulson@22851
   461
                   val ntys = if !typ_level = T_CONST then length tvars else 0
paulson@22851
   462
                   val addit = Symtab.update(c, arity+ntys) 
paulson@22064
   463
               in
paulson@22064
   464
                   if needs_hBOOL c then (addtypes tvars (addit funcs), preds)
paulson@22064
   465
                   else (addtypes tvars funcs, addit preds)
paulson@22851
   466
               end)
paulson@22064
   467
  | add_decls (CombVar(_,ctp), (funcs,preds)) = 
paulson@22078
   468
      (RC.add_foltype_funcs (ctp,funcs), preds)
paulson@22078
   469
  | add_decls (CombApp(P,Q),decls) = add_decls(P,add_decls (Q,decls));
mengj@19720
   470
paulson@22064
   471
fun add_literal_decls (Literal(_,c), decls) = add_decls (c,decls);
mengj@19720
   472
paulson@22064
   473
fun add_clause_decls (Clause {literals, ...}, decls) =
paulson@22064
   474
    foldl add_literal_decls decls literals
mengj@19720
   475
    handle Symtab.DUP a => raise ERROR ("function " ^ a ^ " has multiple arities")
mengj@19720
   476
paulson@22064
   477
fun decls_of_clauses clauses arity_clauses =
paulson@22064
   478
  let val happ_ar = case !typ_level of T_PARTIAL => 3 | _ => 2
paulson@23386
   479
      val init_functab = Symtab.update (type_wrapper,2) (Symtab.update ("hAPP",happ_ar) RC.init_functab)
paulson@22064
   480
      val init_predtab = Symtab.update ("hBOOL",1) Symtab.empty
paulson@22064
   481
      val (functab,predtab) = (foldl add_clause_decls (init_functab, init_predtab) clauses)
paulson@22064
   482
  in
paulson@22078
   483
      (Symtab.dest (foldl RC.add_arityClause_funcs functab arity_clauses), 
paulson@22064
   484
       Symtab.dest predtab)
paulson@22064
   485
  end;
mengj@19720
   486
paulson@21398
   487
fun add_clause_preds (Clause {ctypes_sorts, ...}, preds) =
paulson@22078
   488
  foldl RC.add_type_sort_preds preds ctypes_sorts
paulson@21398
   489
  handle Symtab.DUP a => raise ERROR ("predicate " ^ a ^ " has multiple arities")
paulson@21398
   490
paulson@21398
   491
(*Higher-order clauses have only the predicates hBOOL and type classes.*)
paulson@21398
   492
fun preds_of_clauses clauses clsrel_clauses arity_clauses = 
mengj@19720
   493
    Symtab.dest
paulson@22078
   494
	(foldl RC.add_classrelClause_preds 
paulson@22078
   495
	       (foldl RC.add_arityClause_preds
paulson@22064
   496
		      (foldl add_clause_preds Symtab.empty clauses) 
mengj@19720
   497
		      arity_clauses)
mengj@19720
   498
	       clsrel_clauses)
mengj@19720
   499
mengj@18440
   500
paulson@21398
   501
mengj@18440
   502
(**********************************************************************)
mengj@19198
   503
(* write clauses to files                                             *)
mengj@19198
   504
(**********************************************************************)
mengj@19198
   505
paulson@21573
   506
paulson@21573
   507
val init_counters =
paulson@21573
   508
    Symtab.make [("c_COMBI", 0), ("c_COMBK", 0),
paulson@21573
   509
		 ("c_COMBB", 0), ("c_COMBC", 0),
paulson@21573
   510
		 ("c_COMBS", 0), ("c_COMBB_e", 0),
paulson@21573
   511
		 ("c_COMBC_e", 0), ("c_COMBS_e", 0)];
paulson@21573
   512
                
paulson@21573
   513
fun count_combterm (CombConst(c,tp,_), ct) = 
paulson@21573
   514
     (case Symtab.lookup ct c of NONE => ct  (*no counter*)
paulson@21573
   515
                               | SOME n => Symtab.update (c,n+1) ct)
paulson@21573
   516
  | count_combterm (CombVar(v,tp), ct) = ct
paulson@22078
   517
  | count_combterm (CombApp(t1,t2), ct) = count_combterm(t1, count_combterm(t2, ct));
paulson@21573
   518
paulson@21573
   519
fun count_literal (Literal(_,t), ct) = count_combterm(t,ct);
paulson@21573
   520
paulson@21573
   521
fun count_clause (Clause{literals,...}, ct) = foldl count_literal ct literals;
paulson@21573
   522
paulson@21573
   523
fun count_user_clause user_lemmas (Clause{axiom_name,literals,...}, ct) = 
paulson@21573
   524
  if axiom_name mem_string user_lemmas then foldl count_literal ct literals
paulson@21573
   525
  else ct;
paulson@21573
   526
mengj@20791
   527
val cnf_helper_thms = ResAxioms.cnf_rules_pairs o (map ResAxioms.pairname)
mengj@20644
   528
paulson@23386
   529
fun get_helper_clauses isFO (conjectures, axclauses, user_lemmas) =
paulson@23386
   530
  if isFO then []  (*first-order*)
paulson@23386
   531
  else
paulson@22064
   532
    let val ct0 = foldl count_clause init_counters conjectures
paulson@22064
   533
        val ct = foldl (count_user_clause user_lemmas) ct0 axclauses
paulson@22064
   534
        fun needed c = valOf (Symtab.lookup ct c) > 0
paulson@21573
   535
        val IK = if needed "c_COMBI" orelse needed "c_COMBK" 
wenzelm@22130
   536
                 then (Output.debug (fn () => "Include combinator I K"); cnf_helper_thms [comb_I,comb_K]) 
paulson@21135
   537
                 else []
paulson@21573
   538
	val BC = if needed "c_COMBB" orelse needed "c_COMBC" 
wenzelm@22130
   539
	         then (Output.debug (fn () => "Include combinator B C"); cnf_helper_thms [comb_B,comb_C]) 
paulson@21135
   540
	         else []
paulson@21573
   541
	val S = if needed "c_COMBS" 
wenzelm@22130
   542
	        then (Output.debug (fn () => "Include combinator S"); cnf_helper_thms [comb_S]) 
paulson@21135
   543
	        else []
paulson@21573
   544
	val B'C' = if needed "c_COMBB_e" orelse needed "c_COMBC_e" 
wenzelm@22130
   545
	           then (Output.debug (fn () => "Include combinator B' C'"); cnf_helper_thms [comb_B', comb_C']) 
paulson@21135
   546
	           else []
paulson@21573
   547
	val S' = if needed "c_COMBS_e" 
wenzelm@22130
   548
	         then (Output.debug (fn () => "Include combinator S'"); cnf_helper_thms [comb_S']) 
paulson@21135
   549
	         else []
mengj@20791
   550
	val other = cnf_helper_thms [ext,fequal_imp_equal,equal_imp_fequal]
mengj@20791
   551
    in
paulson@22064
   552
	map #2 (make_axiom_clauses (other @ IK @ BC @ S @ B'C' @ S'))
paulson@23386
   553
    end;
mengj@20791
   554
paulson@22064
   555
(*Find the minimal arity of each function mentioned in the term. Also, note which uses
paulson@22064
   556
  are not at top level, to see if hBOOL is needed.*)
paulson@22064
   557
fun count_constants_term toplev t =
paulson@22064
   558
  let val (head, args) = strip_comb t
paulson@22064
   559
      val n = length args
paulson@22064
   560
      val _ = List.app (count_constants_term false) args
paulson@22064
   561
  in
paulson@22064
   562
      case head of
paulson@22064
   563
	  CombConst (a,_,_) => (*predicate or function version of "equal"?*)
paulson@22064
   564
	    let val a = if a="equal" andalso not toplev then "c_fequal" else a
paulson@22064
   565
	    in  
paulson@22064
   566
	      const_min_arity := Symtab.map_default (a,n) (curry Int.min n) (!const_min_arity);
paulson@22064
   567
	      if toplev then ()
paulson@22064
   568
	      else const_needs_hBOOL := Symtab.update (a,true) (!const_needs_hBOOL)
paulson@22064
   569
	    end
paulson@22064
   570
	| ts => ()
paulson@22064
   571
  end;
paulson@22064
   572
paulson@22064
   573
(*A literal is a top-level term*)
paulson@22064
   574
fun count_constants_lit (Literal (_,t)) = count_constants_term true t;
paulson@22064
   575
paulson@22064
   576
fun count_constants_clause (Clause{literals,...}) = List.app count_constants_lit literals;
paulson@22064
   577
paulson@22064
   578
fun display_arity (c,n) =
wenzelm@22130
   579
  Output.debug (fn () => "Constant: " ^ c ^ " arity:\t" ^ Int.toString n ^ 
paulson@22064
   580
                (if needs_hBOOL c then " needs hBOOL" else ""));
paulson@22064
   581
paulson@22064
   582
fun count_constants (conjectures, axclauses, helper_clauses) = 
paulson@22851
   583
  if !minimize_applies andalso !typ_level<>T_PARTIAL then
paulson@23386
   584
    (const_min_arity := Symtab.empty; 
paulson@23386
   585
     const_needs_hBOOL := Symtab.empty;
paulson@23386
   586
     List.app count_constants_clause conjectures;
paulson@22064
   587
     List.app count_constants_clause axclauses;
paulson@22064
   588
     List.app count_constants_clause helper_clauses;
paulson@22064
   589
     List.app display_arity (Symtab.dest (!const_min_arity)))
paulson@22064
   590
  else ();
paulson@22064
   591
mengj@20791
   592
(* tptp format *)
mengj@19491
   593
						  
mengj@19198
   594
(* write TPTP format to a single file *)
paulson@23386
   595
fun tptp_write_file isFO thms filename (ax_tuples,classrel_clauses,arity_clauses) user_lemmas =
paulson@23386
   596
    let val _ = Output.debug (fn () => ("Preparing to write the TPTP file " ^ filename))
paulson@23386
   597
        val _ = RC.dfg_format := false
paulson@23386
   598
        val conjectures = make_conjecture_clauses thms
paulson@22064
   599
        val (clnames,axclauses) = ListPair.unzip (make_axiom_clauses ax_tuples)
paulson@23386
   600
	val helper_clauses = get_helper_clauses isFO (conjectures, axclauses, user_lemmas)
paulson@22064
   601
	val _ = count_constants (conjectures, axclauses, helper_clauses);
paulson@21573
   602
	val (tptp_clss,tfree_litss) = ListPair.unzip (map clause2tptp conjectures)
paulson@22078
   603
	val tfree_clss = map RC.tptp_tfree_clause (foldl (op union_string) [] tfree_litss)
paulson@22064
   604
        val out = TextIO.openOut filename
mengj@19198
   605
    in
paulson@22064
   606
	List.app (curry TextIO.output out o #1 o clause2tptp) axclauses;
paulson@22078
   607
	RC.writeln_strs out tfree_clss;
paulson@22078
   608
	RC.writeln_strs out tptp_clss;
paulson@22078
   609
	List.app (curry TextIO.output out o RC.tptp_classrelClause) classrel_clauses;
paulson@22078
   610
	List.app (curry TextIO.output out o RC.tptp_arity_clause) arity_clauses;
mengj@20791
   611
	List.app (curry TextIO.output out o #1 o clause2tptp) helper_clauses;
paulson@20022
   612
	TextIO.closeOut out;
paulson@20022
   613
	clnames
mengj@19198
   614
    end;
mengj@19198
   615
mengj@19720
   616
mengj@20644
   617
mengj@19720
   618
(* dfg format *)
mengj@19720
   619
paulson@23386
   620
fun dfg_write_file isFO thms filename (ax_tuples,classrel_clauses,arity_clauses) user_lemmas =
paulson@23386
   621
    let val _ = Output.debug (fn () => ("Preparing to write the DFG file " ^ filename))
paulson@23386
   622
        val _ = RC.dfg_format := true
paulson@23386
   623
        val conjectures = make_conjecture_clauses thms
paulson@22064
   624
        val (clnames,axclauses) = ListPair.unzip (make_axiom_clauses ax_tuples)
paulson@23386
   625
	val helper_clauses = get_helper_clauses isFO (conjectures, axclauses, user_lemmas)
paulson@22064
   626
	val _ = count_constants (conjectures, axclauses, helper_clauses);
mengj@19720
   627
	val (dfg_clss,tfree_litss) = ListPair.unzip (map clause2dfg conjectures)
wenzelm@21858
   628
	and probname = Path.implode (Path.base (Path.explode filename))
paulson@22064
   629
	val axstrs = map (#1 o clause2dfg) axclauses
paulson@22078
   630
	val tfree_clss = map RC.dfg_tfree_clause (RC.union_all tfree_litss)
mengj@19720
   631
	val out = TextIO.openOut filename
paulson@21573
   632
	val helper_clauses_strs = map (#1 o clause2dfg) helper_clauses
paulson@22064
   633
	val (funcs,cl_preds) = decls_of_clauses (helper_clauses @ conjectures @ axclauses) arity_clauses
paulson@22064
   634
	and ty_preds = preds_of_clauses axclauses classrel_clauses arity_clauses
mengj@19720
   635
    in
paulson@22078
   636
	TextIO.output (out, RC.string_of_start probname); 
paulson@22078
   637
	TextIO.output (out, RC.string_of_descrip probname); 
paulson@22078
   638
	TextIO.output (out, RC.string_of_symbols 
paulson@22078
   639
	                      (RC.string_of_funcs funcs) 
paulson@22078
   640
	                      (RC.string_of_preds (cl_preds @ ty_preds))); 
mengj@19720
   641
	TextIO.output (out, "list_of_clauses(axioms,cnf).\n");
paulson@22078
   642
	RC.writeln_strs out axstrs;
paulson@22078
   643
	List.app (curry TextIO.output out o RC.dfg_classrelClause) classrel_clauses;
paulson@22078
   644
	List.app (curry TextIO.output out o RC.dfg_arity_clause) arity_clauses;
paulson@22078
   645
	RC.writeln_strs out helper_clauses_strs;
mengj@19720
   646
	TextIO.output (out, "end_of_list.\n\nlist_of_clauses(conjectures,cnf).\n");
paulson@22078
   647
	RC.writeln_strs out tfree_clss;
paulson@22078
   648
	RC.writeln_strs out dfg_clss;
paulson@20953
   649
	TextIO.output (out, "end_of_list.\n\n");
paulson@20953
   650
	(*VarWeight=3 helps the HO problems, probably by counteracting the presence of hAPP*)
paulson@20953
   651
	TextIO.output (out, "list_of_settings(SPASS).\n{*\nset_flag(VarWeight,3).\n*}\nend_of_list.\n\n");
paulson@20953
   652
	TextIO.output (out, "end_problem.\n");
paulson@20022
   653
	TextIO.closeOut out;
paulson@20022
   654
	clnames
mengj@19720
   655
    end;
mengj@19720
   656
wenzelm@21254
   657
end