src/HOL/Tools/Metis/metis_translate.ML
author blanchet
Tue Nov 15 22:13:39 2011 +0100 (2011-11-15)
changeset 45508 b216dc1b3630
parent 45043 7e1a73fc0c8b
child 45510 96696c360b3e
permissions -rw-r--r--
started implementing lambda-lifting in Metis
blanchet@39958
     1
(*  Title:      HOL/Tools/Metis/metis_translate.ML
blanchet@38027
     2
    Author:     Jia Meng, Cambridge University Computer Laboratory and NICTA
blanchet@39497
     3
    Author:     Kong W. Susanto, Cambridge University Computer Laboratory
blanchet@39497
     4
    Author:     Lawrence C. Paulson, Cambridge University Computer Laboratory
blanchet@36393
     5
    Author:     Jasmin Blanchette, TU Muenchen
paulson@15347
     6
blanchet@39494
     7
Translation of HOL to FOL for Metis.
paulson@15347
     8
*)
paulson@15347
     9
blanchet@39494
    10
signature METIS_TRANSLATE =
wenzelm@24310
    11
sig
blanchet@44411
    12
  type type_enc = ATP_Translate.type_enc
blanchet@44411
    13
blanchet@43159
    14
  datatype isa_thm =
blanchet@43159
    15
    Isa_Reflexive_or_Trivial |
blanchet@43159
    16
    Isa_Raw of thm
blanchet@43159
    17
blanchet@43094
    18
  val metis_equal : string
blanchet@43094
    19
  val metis_predicator : string
blanchet@43094
    20
  val metis_app_op : string
blanchet@44492
    21
  val metis_systematic_type_tag : string
blanchet@44492
    22
  val metis_ad_hoc_type_tag : string
blanchet@42098
    23
  val metis_generated_var_prefix : string
blanchet@43231
    24
  val trace : bool Config.T
blanchet@43231
    25
  val verbose : bool Config.T
blanchet@45508
    26
  val lambda_translation : string Config.T
blanchet@43231
    27
  val trace_msg : Proof.context -> (unit -> string) -> unit
blanchet@43231
    28
  val verbose_warning : Proof.context -> string -> unit
blanchet@44492
    29
  val metis_name_table : ((string * int) * ((type_enc -> string) * bool)) list
blanchet@39886
    30
  val reveal_old_skolem_terms : (string * term) list -> term -> term
blanchet@45508
    31
  val reveal_lambda_lifted : (string * term) list -> term -> term
blanchet@40157
    32
  val prepare_metis_problem :
blanchet@45508
    33
    Proof.context -> type_enc -> string -> thm list -> thm list
blanchet@45508
    34
    -> int Symtab.table * (Metis_Thm.thm * isa_thm) list
blanchet@45508
    35
       * ((string * term) list * (string * term) list)
wenzelm@24310
    36
end
paulson@15347
    37
blanchet@39494
    38
structure Metis_Translate : METIS_TRANSLATE =
paulson@15347
    39
struct
paulson@15347
    40
blanchet@43092
    41
open ATP_Problem
blanchet@43085
    42
open ATP_Translate
paulson@15347
    43
blanchet@43094
    44
val metis_equal = "="
blanchet@43094
    45
val metis_predicator = "{}"
blanchet@44492
    46
val metis_app_op = Metis_Name.toString Metis_Term.appName
blanchet@44492
    47
val metis_systematic_type_tag =
blanchet@44492
    48
  Metis_Name.toString Metis_Term.hasTypeFunctionName
blanchet@44492
    49
val metis_ad_hoc_type_tag = "**"
blanchet@43085
    50
val metis_generated_var_prefix = "_"
quigley@17150
    51
blanchet@43231
    52
val trace = Attrib.setup_config_bool @{binding metis_trace} (K false)
blanchet@43231
    53
val verbose = Attrib.setup_config_bool @{binding metis_verbose} (K true)
blanchet@45508
    54
val lambda_translation =
blanchet@45508
    55
  Attrib.setup_config_string @{binding metis_lambda_translation}
blanchet@45508
    56
      (K combinatorsN)
blanchet@43231
    57
blanchet@43231
    58
fun trace_msg ctxt msg = if Config.get ctxt trace then tracing (msg ()) else ()
blanchet@43231
    59
fun verbose_warning ctxt msg =
blanchet@43231
    60
  if Config.get ctxt verbose then warning ("Metis: " ^ msg) else ()
blanchet@43231
    61
blanchet@43094
    62
val metis_name_table =
blanchet@44492
    63
  [((tptp_equal, 2), (K metis_equal, false)),
blanchet@44492
    64
   ((tptp_old_equal, 2), (K metis_equal, false)),
blanchet@44492
    65
   ((prefixed_predicator_name, 1), (K metis_predicator, false)),
blanchet@44492
    66
   ((prefixed_app_op_name, 2), (K metis_app_op, false)),
blanchet@44492
    67
   ((prefixed_type_tag_name, 2),
blanchet@44782
    68
    (fn type_enc =>
blanchet@44782
    69
        if level_of_type_enc type_enc = All_Types then metis_systematic_type_tag
blanchet@44782
    70
        else metis_ad_hoc_type_tag, true))]
blanchet@43094
    71
blanchet@39896
    72
fun old_skolem_const_name i j num_T_args =
blanchet@39896
    73
  old_skolem_const_prefix ^ Long_Name.separator ^
wenzelm@41491
    74
  (space_implode Long_Name.separator (map string_of_int [i, j, num_T_args]))
blanchet@37577
    75
blanchet@39886
    76
fun conceal_old_skolem_terms i old_skolems t =
blanchet@39953
    77
  if exists_Const (curry (op =) @{const_name Meson.skolem} o fst) t then
blanchet@37577
    78
    let
blanchet@39886
    79
      fun aux old_skolems
blanchet@39953
    80
             (t as (Const (@{const_name Meson.skolem}, Type (_, [_, T])) $ _)) =
blanchet@37577
    81
          let
blanchet@39886
    82
            val (old_skolems, s) =
blanchet@37577
    83
              if i = ~1 then
blanchet@39886
    84
                (old_skolems, @{const_name undefined})
blanchet@39886
    85
              else case AList.find (op aconv) old_skolems t of
blanchet@39886
    86
                s :: _ => (old_skolems, s)
blanchet@37577
    87
              | [] =>
blanchet@37577
    88
                let
blanchet@39896
    89
                  val s = old_skolem_const_name i (length old_skolems)
blanchet@39896
    90
                                                (length (Term.add_tvarsT T []))
blanchet@39886
    91
                in ((s, t) :: old_skolems, s) end
blanchet@39886
    92
          in (old_skolems, Const (s, T)) end
blanchet@39886
    93
        | aux old_skolems (t1 $ t2) =
blanchet@37577
    94
          let
blanchet@39886
    95
            val (old_skolems, t1) = aux old_skolems t1
blanchet@39886
    96
            val (old_skolems, t2) = aux old_skolems t2
blanchet@39886
    97
          in (old_skolems, t1 $ t2) end
blanchet@39886
    98
        | aux old_skolems (Abs (s, T, t')) =
blanchet@39886
    99
          let val (old_skolems, t') = aux old_skolems t' in
blanchet@39886
   100
            (old_skolems, Abs (s, T, t'))
blanchet@37577
   101
          end
blanchet@39886
   102
        | aux old_skolems t = (old_skolems, t)
blanchet@39886
   103
    in aux old_skolems t end
blanchet@37577
   104
  else
blanchet@39886
   105
    (old_skolems, t)
blanchet@37577
   106
blanchet@39886
   107
fun reveal_old_skolem_terms old_skolems =
blanchet@37632
   108
  map_aterms (fn t as Const (s, _) =>
blanchet@39896
   109
                 if String.isPrefix old_skolem_const_prefix s then
blanchet@39886
   110
                   AList.lookup (op =) old_skolems s |> the
blanchet@43826
   111
                   |> map_types (map_type_tvar (K dummyT))
blanchet@37632
   112
                 else
blanchet@37632
   113
                   t
blanchet@37632
   114
               | t => t)
blanchet@37632
   115
blanchet@45508
   116
fun reveal_lambda_lifted lambdas =
blanchet@45508
   117
  map_aterms (fn t as Free (s, _) =>
blanchet@45508
   118
                 if String.isPrefix lambda_lifted_prefix s then
blanchet@45508
   119
                   case AList.lookup (op =) lambdas s of
blanchet@45508
   120
                     SOME t => t |> map_types (map_type_tvar (K dummyT))
blanchet@45508
   121
                   | NONE => t
blanchet@45508
   122
                 else
blanchet@45508
   123
                   t
blanchet@45508
   124
               | t => t)
blanchet@45508
   125
blanchet@37577
   126
blanchet@39497
   127
(* ------------------------------------------------------------------------- *)
blanchet@39497
   128
(* Logic maps manage the interface between HOL and first-order logic.        *)
blanchet@39497
   129
(* ------------------------------------------------------------------------- *)
blanchet@39497
   130
blanchet@43159
   131
datatype isa_thm =
blanchet@43159
   132
  Isa_Reflexive_or_Trivial |
blanchet@43159
   133
  Isa_Raw of thm
blanchet@43159
   134
blanchet@43159
   135
val proxy_defs = map (fst o snd o snd) proxy_table
blanchet@43159
   136
val prepare_helper =
blanchet@43159
   137
  Meson.make_meta_clause #> rewrite_rule (map safe_mk_meta_eq proxy_defs)
blanchet@43159
   138
blanchet@44492
   139
fun metis_term_from_atp type_enc (ATerm (s, tms)) =
blanchet@43094
   140
  if is_tptp_variable s then
blanchet@43268
   141
    Metis_Term.Var (Metis_Name.fromString s)
blanchet@43094
   142
  else
blanchet@44492
   143
    (case AList.lookup (op =) metis_name_table (s, length tms) of
blanchet@44492
   144
       SOME (f, swap) => (f type_enc, swap)
blanchet@44492
   145
     | NONE => (s, false))
blanchet@44492
   146
    |> (fn (s, swap) =>
blanchet@44492
   147
           Metis_Term.Fn (Metis_Name.fromString s,
blanchet@44492
   148
                          tms |> map (metis_term_from_atp type_enc)
blanchet@44492
   149
                              |> swap ? rev))
blanchet@44492
   150
fun metis_atom_from_atp type_enc (AAtom tm) =
blanchet@44492
   151
    (case metis_term_from_atp type_enc tm of
blanchet@43104
   152
       Metis_Term.Fn x => x
blanchet@43104
   153
     | _ => raise Fail "non CNF -- expected function")
blanchet@44492
   154
  | metis_atom_from_atp _ _ = raise Fail "not CNF -- expected atom"
blanchet@44492
   155
fun metis_literal_from_atp type_enc (AConn (ANot, [phi])) =
blanchet@44492
   156
    (false, metis_atom_from_atp type_enc phi)
blanchet@44492
   157
  | metis_literal_from_atp type_enc phi =
blanchet@44492
   158
    (true, metis_atom_from_atp type_enc phi)
blanchet@44492
   159
fun metis_literals_from_atp type_enc (AConn (AOr, phis)) =
blanchet@44492
   160
    maps (metis_literals_from_atp type_enc) phis
blanchet@44492
   161
  | metis_literals_from_atp type_enc phi = [metis_literal_from_atp type_enc phi]
blanchet@44492
   162
fun metis_axiom_from_atp type_enc clauses (Formula (ident, _, phi, _, _)) =
blanchet@43173
   163
    let
blanchet@43173
   164
      fun some isa =
blanchet@44492
   165
        SOME (phi |> metis_literals_from_atp type_enc
blanchet@44492
   166
                  |> Metis_LiteralSet.fromList
blanchet@43173
   167
                  |> Metis_Thm.axiom, isa)
blanchet@43173
   168
    in
blanchet@43173
   169
      if ident = type_tag_idempotence_helper_name orelse
blanchet@44396
   170
         String.isPrefix tags_sym_formula_prefix ident then
blanchet@43173
   171
        Isa_Reflexive_or_Trivial |> some
blanchet@43295
   172
      else if String.isPrefix conjecture_prefix ident then
blanchet@43295
   173
        NONE
blanchet@43173
   174
      else if String.isPrefix helper_prefix ident then
blanchet@43194
   175
        case (String.isSuffix typed_helper_suffix ident,
blanchet@43194
   176
              space_explode "_" ident) of
blanchet@43194
   177
          (needs_fairly_sound, _ :: const :: j :: _) =>
blanchet@43194
   178
          nth ((const, needs_fairly_sound)
blanchet@43194
   179
               |> AList.lookup (op =) helper_table |> the)
blanchet@43173
   180
              (the (Int.fromString j) - 1)
blanchet@43194
   181
          |> prepare_helper
blanchet@43194
   182
          |> Isa_Raw |> some
blanchet@43173
   183
        | _ => raise Fail ("malformed helper identifier " ^ quote ident)
blanchet@43295
   184
      else case try (unprefix fact_prefix) ident of
blanchet@43173
   185
        SOME s =>
blanchet@43295
   186
        let
blanchet@43295
   187
          val j = s |> space_explode "_" |> List.last |> Int.fromString |> the
blanchet@43295
   188
        in Meson.make_meta_clause (snd (nth clauses j)) |> Isa_Raw |> some end
blanchet@43173
   189
      | NONE => TrueI |> Isa_Raw |> some
blanchet@43173
   190
    end
blanchet@44492
   191
  | metis_axiom_from_atp _ _ _ = raise Fail "not CNF -- expected formula"
blanchet@43092
   192
blanchet@39497
   193
(* Function to generate metis clauses, including comb and type clauses *)
blanchet@45508
   194
fun prepare_metis_problem ctxt type_enc lambda_trans conj_clauses fact_clauses =
blanchet@43212
   195
  let
blanchet@43295
   196
    val (conj_clauses, fact_clauses) =
blanchet@43626
   197
      if polymorphism_of_type_enc type_enc = Polymorphic then
blanchet@43295
   198
        (conj_clauses, fact_clauses)
blanchet@43295
   199
      else
blanchet@43295
   200
        conj_clauses @ fact_clauses
blanchet@43295
   201
        |> map (pair 0)
blanchet@45043
   202
        |> rpair (ctxt |> Config.put Monomorph.keep_partial_instances false)
blanchet@43295
   203
        |-> Monomorph.monomorph atp_schematic_consts_of
blanchet@43295
   204
        |> fst |> chop (length conj_clauses)
blanchet@43295
   205
        |> pairself (maps (map (zero_var_indexes o snd)))
blanchet@43295
   206
    val num_conjs = length conj_clauses
blanchet@43212
   207
    val clauses =
blanchet@43295
   208
      map2 (fn j => pair (Int.toString j, Local))
blanchet@43295
   209
           (0 upto num_conjs - 1) conj_clauses @
blanchet@43295
   210
      (* "General" below isn't quite correct; the fact could be local. *)
blanchet@43295
   211
      map2 (fn j => pair (Int.toString (num_conjs + j), General))
blanchet@43295
   212
           (0 upto length fact_clauses - 1) fact_clauses
blanchet@43212
   213
    val (old_skolems, props) =
blanchet@43295
   214
      fold_rev (fn (name, th) => fn (old_skolems, props) =>
blanchet@43295
   215
                   th |> prop_of |> Logic.strip_imp_concl
blanchet@43295
   216
                      |> conceal_old_skolem_terms (length clauses) old_skolems
blanchet@43295
   217
                      ||> (fn prop => (name, prop) :: props))
blanchet@43295
   218
               clauses ([], [])
blanchet@43295
   219
    (*
blanchet@43295
   220
    val _ =
blanchet@45042
   221
      tracing ("PROPS:\n" ^
blanchet@45042
   222
               cat_lines (map (Syntax.string_of_term ctxt o snd) props))
blanchet@43295
   223
    *)
blanchet@45508
   224
    val (lambda_trans, preproc) =
blanchet@45508
   225
      if lambda_trans = combinatorsN then (no_lambdasN, false)
blanchet@45508
   226
      else (lambda_trans, true)
blanchet@45508
   227
    val (atp_problem, _, _, _, _, _, lifted, sym_tab) =
blanchet@45508
   228
      prepare_atp_problem ctxt CNF Hypothesis Axiom type_enc false lambda_trans
blanchet@45508
   229
                          false preproc [] @{prop False} props
blanchet@43295
   230
    val _ = tracing ("ATP PROBLEM: " ^
blanchet@45508
   231
                     cat_lines (lines_for_atp_problem CNF atp_problem))
blanchet@45508
   232
    (* "rev" is for compatibility with existing proof scripts. *)
blanchet@43212
   233
    val axioms =
blanchet@44492
   234
      atp_problem
blanchet@44492
   235
      |> maps (map_filter (metis_axiom_from_atp type_enc clauses) o snd) |> rev
blanchet@45508
   236
  in (sym_tab, axioms, (lifted, old_skolems)) end
blanchet@39497
   237
paulson@15347
   238
end;