src/HOL/Tools/Sledgehammer/sledgehammer_reconstruct.ML
changeset 39372 2fd8a9a7080d
parent 39370 f8292d3020db
child 39373 fe95c860434c
equal deleted inserted replaced
39371:6549ca3671f3 39372:2fd8a9a7080d
    60 
    60 
    61 fun mk_anot (AConn (ANot, [phi])) = phi
    61 fun mk_anot (AConn (ANot, [phi])) = phi
    62   | mk_anot phi = AConn (ANot, [phi])
    62   | mk_anot phi = AConn (ANot, [phi])
    63 fun mk_aconn c (phi1, phi2) = AConn (c, [phi1, phi2])
    63 fun mk_aconn c (phi1, phi2) = AConn (c, [phi1, phi2])
    64 
    64 
    65 datatype tstp_name = Str of string * string | Num of string
    65 datatype raw_step_name = Str of string * string | Num of string
       
    66 
       
    67 fun raw_step_name_num (Str (num, _)) = num
       
    68   | raw_step_name_num (Num num) = num
       
    69 
       
    70 fun raw_step_name_ord p =
       
    71   let val q = pairself raw_step_name_num p in
       
    72     case pairself Int.fromString q of
       
    73       (NONE, NONE) => string_ord q
       
    74     | (NONE, SOME _) => LESS
       
    75     | (SOME _, NONE) => GREATER
       
    76     | (SOME i, SOME j) => int_ord (i, j)
       
    77   end
    66 
    78 
    67 fun index_in_shape x = find_index (exists (curry (op =) x))
    79 fun index_in_shape x = find_index (exists (curry (op =) x))
    68 fun resolve_axiom axiom_names (Str (_, str)) =
    80 fun resolve_axiom axiom_names (Str (_, str)) =
    69     (case find_first_in_list_vector axiom_names str of
    81     (case find_first_in_list_vector axiom_names str of
    70        SOME x => [(str, x)]
    82        SOME x => [(str, x)]
   101     @{const HOL.conj} $ negate_term t1 $ negate_term t2
   113     @{const HOL.conj} $ negate_term t1 $ negate_term t2
   102   | negate_term (@{const Not} $ t) = t
   114   | negate_term (@{const Not} $ t) = t
   103   | negate_term t = @{const Not} $ t
   115   | negate_term t = @{const Not} $ t
   104 
   116 
   105 datatype ('a, 'b, 'c) raw_step =
   117 datatype ('a, 'b, 'c) raw_step =
   106   Definition of tstp_name * 'a * 'b |
   118   Definition of raw_step_name * 'a * 'b |
   107   Inference of tstp_name * 'c * tstp_name list
   119   Inference of raw_step_name * 'c * raw_step_name list
   108 
   120 
   109 (**** PARSING OF TSTP FORMAT ****)
   121 (**** PARSING OF TSTP FORMAT ****)
   110 
   122 
   111 (*Strings enclosed in single quotes, e.g. filenames*)
   123 (*Strings enclosed in single quotes, e.g. filenames*)
   112 val scan_general_id =
   124 val scan_general_id =
   125       if String.isPrefix "sQ" s andalso String.isSuffix "_eqProxy" s then
   137       if String.isPrefix "sQ" s andalso String.isSuffix "_eqProxy" s then
   126         "c_equal" (* seen in Vampire proofs *)
   138         "c_equal" (* seen in Vampire proofs *)
   127       else
   139       else
   128         s
   140         s
   129 (* Generalized first-order terms, which include file names, numbers, etc. *)
   141 (* Generalized first-order terms, which include file names, numbers, etc. *)
   130 fun parse_annotation x =
   142 fun parse_annotation strict x =
   131   ((scan_general_id ::: Scan.repeat ($$ " " |-- scan_general_id))
   143   ((scan_general_id ::: Scan.repeat ($$ " " |-- scan_general_id)
   132    -- Scan.optional parse_annotation [] >> uncurry (union (op =))
   144       >> (strict ? filter (is_some o Int.fromString)))
   133    || $$ "(" |-- parse_annotations --| $$ ")"
   145    -- Scan.optional (parse_annotation strict) [] >> uncurry (union (op =))
   134    || $$ "[" |-- parse_annotations --| $$ "]") x
   146    || $$ "(" |-- parse_annotations strict --| $$ ")"
   135 and parse_annotations x =
   147    || $$ "[" |-- parse_annotations strict --| $$ "]") x
   136   (Scan.optional (parse_annotation
   148 and parse_annotations strict x =
   137                   ::: Scan.repeat ($$ "," |-- parse_annotation)) []
   149   (Scan.optional (parse_annotation strict
       
   150                   ::: Scan.repeat ($$ "," |-- parse_annotation strict)) []
   138    >> (fn numss => fold (union (op =)) numss [])) x
   151    >> (fn numss => fold (union (op =)) numss [])) x
   139 
   152 
   140 (* Vampire proof lines sometimes contain needless information such as "(0:3)",
   153 (* Vampire proof lines sometimes contain needless information such as "(0:3)",
   141    which can be hard to disambiguate from function application in an LL(1)
   154    which can be hard to disambiguate from function application in an LL(1)
   142    parser. As a workaround, we extend the TPTP term syntax with such detritus
   155    parser. As a workaround, we extend the TPTP term syntax with such detritus
   181                    -- parse_formula pool)
   194                    -- parse_formula pool)
   182    >> (fn (phi1, NONE) => phi1
   195    >> (fn (phi1, NONE) => phi1
   183         | (phi1, SOME (c, phi2)) => mk_aconn c (phi1, phi2))) x
   196         | (phi1, SOME (c, phi2)) => mk_aconn c (phi1, phi2))) x
   184 
   197 
   185 val parse_tstp_extra_arguments =
   198 val parse_tstp_extra_arguments =
   186   Scan.optional ($$ "," |-- parse_annotation
   199   Scan.optional ($$ "," |-- parse_annotation false
   187                  --| Scan.option ($$ "," |-- parse_annotations)) []
   200                  --| Scan.option ($$ "," |-- parse_annotations false)) []
   188 
   201 
   189 (* Syntax: (fof|cnf)\(<num>, <formula_role>, <formula> <extra_arguments>\).
   202 (* Syntax: (fof|cnf)\(<num>, <formula_role>, <formula> <extra_arguments>\).
   190    The <num> could be an identifier, but we assume integers. *)
   203    The <num> could be an identifier, but we assume integers. *)
   191  fun parse_tstp_line pool =
   204  fun parse_tstp_line pool =
   192    ((Scan.this_string "fof" || Scan.this_string "cnf") -- $$ "(")
   205    ((Scan.this_string "fof" || Scan.this_string "cnf") -- $$ "(")
   206 
   219 
   207 (**** PARSING OF VAMPIRE OUTPUT ****)
   220 (**** PARSING OF VAMPIRE OUTPUT ****)
   208 
   221 
   209 (* Syntax: <num>. <formula> <annotation> *)
   222 (* Syntax: <num>. <formula> <annotation> *)
   210 fun parse_vampire_line pool =
   223 fun parse_vampire_line pool =
   211   scan_general_id --| $$ "." -- parse_formula pool -- parse_annotation
   224   scan_general_id --| $$ "." -- parse_formula pool -- parse_annotation true
   212   >> (fn ((num, phi), deps) => Inference (Num num, phi, map Num deps))
   225   >> (fn ((num, phi), deps) => Inference (Num num, phi, map Num deps))
   213 
   226 
   214 (**** PARSING OF SPASS OUTPUT ****)
   227 (**** PARSING OF SPASS OUTPUT ****)
   215 
   228 
   216 (* SPASS returns clause references of the form "x.y". We ignore "y", whose role
   229 (* SPASS returns clause references of the form "x.y". We ignore "y", whose role
   613 val assum_prefix = "A"
   626 val assum_prefix = "A"
   614 val fact_prefix = "F"
   627 val fact_prefix = "F"
   615 
   628 
   616 fun string_for_label (s, num) = s ^ string_of_int num
   629 fun string_for_label (s, num) = s ^ string_of_int num
   617 
   630 
   618 fun name_num (Str (num, _)) = num
       
   619   | name_num (Num num) = num
       
   620 
       
   621 fun raw_label_for_name conjecture_shape name =
   631 fun raw_label_for_name conjecture_shape name =
   622   case resolve_conjecture conjecture_shape name of
   632   case resolve_conjecture conjecture_shape name of
   623     [j] => (conjecture_prefix, j)
   633     [j] => (conjecture_prefix, j)
   624   | _ => case Int.fromString (name_num name) of
   634   | _ => case Int.fromString (raw_step_name_num name) of
   625            SOME j => (raw_prefix, j)
   635            SOME j => (raw_prefix, j)
   626          | NONE => (raw_prefix ^ name_num name, 0)
   636          | NONE => (raw_prefix ^ raw_step_name_num name, 0)
   627 
   637 
   628 fun metis_using [] = ""
   638 fun metis_using [] = ""
   629   | metis_using ls =
   639   | metis_using ls =
   630     "using " ^ space_implode " " (map string_for_label ls) ^ " "
   640     "using " ^ space_implode " " (map string_for_label ls) ^ " "
   631 fun metis_apply _ 1 = "by "
   641 fun metis_apply _ 1 = "by "
   702     Have (if j = 1 then [Show] else [],
   712     Have (if j = 1 then [Show] else [],
   703           raw_label_for_name conjecture_shape name, forall_vars t,
   713           raw_label_for_name conjecture_shape name, forall_vars t,
   704           ByMetis (fold (add_fact_from_dep conjecture_shape axiom_names) deps
   714           ByMetis (fold (add_fact_from_dep conjecture_shape axiom_names) deps
   705                         ([], [])))
   715                         ([], [])))
   706 
   716 
       
   717 fun raw_step_name (Definition (name, _, _)) = name
       
   718   | raw_step_name (Inference (name, _, _)) = name
       
   719 
   707 fun proof_from_atp_proof pool ctxt full_types tfrees isar_shrink_factor
   720 fun proof_from_atp_proof pool ctxt full_types tfrees isar_shrink_factor
   708                          atp_proof conjecture_shape axiom_names params frees =
   721                          atp_proof conjecture_shape axiom_names params frees =
   709   let
   722   let
   710     val lines =
   723     val lines =
   711       atp_proof ^ "$" (* the $ sign acts as a sentinel (FIXME: needed?) *)
   724       atp_proof ^ "$" (* the $ sign acts as a sentinel (FIXME: needed?) *)
   712       |> parse_proof pool
   725       |> parse_proof pool
   713 (*### FIXME
   726       |> sort (raw_step_name_ord o pairself raw_step_name)
   714       |> sort (tstp_name_ord o pairself raw_step_name)
       
   715 
       
   716 fun raw_step_name (Definition (name, _, _)) = name
       
   717   | raw_step_name (Inference (name, _, _)) = name
       
   718 *)
       
   719       |> decode_lines ctxt full_types tfrees
   727       |> decode_lines ctxt full_types tfrees
   720       |> rpair [] |-> fold_rev (add_line conjecture_shape axiom_names)
   728       |> rpair [] |-> fold_rev (add_line conjecture_shape axiom_names)
   721       |> rpair [] |-> fold_rev add_nontrivial_line
   729       |> rpair [] |-> fold_rev add_nontrivial_line
   722       |> rpair (0, []) |-> fold_rev (add_desired_line isar_shrink_factor
   730       |> rpair (0, []) |-> fold_rev (add_desired_line isar_shrink_factor
   723                                              conjecture_shape axiom_names frees)
   731                                              conjecture_shape axiom_names frees)
   774   case length proofs of
   782   case length proofs of
   775     0 => []
   783     0 => []
   776   | 1 => [Then]
   784   | 1 => [Then]
   777   | _ => [Ultimately]
   785   | _ => [Ultimately]
   778 
   786 
   779 fun redirect_proof conjecture_shape hyp_ts concl_t proof =
   787 fun redirect_proof hyp_ts concl_t proof =
   780   let
   788   let
   781     (* The first pass outputs those steps that are independent of the negated
   789     (* The first pass outputs those steps that are independent of the negated
   782        conjecture. The second pass flips the proof by contradiction to obtain a
   790        conjecture. The second pass flips the proof by contradiction to obtain a
   783        direct proof, introducing case splits when an inference depends on
   791        direct proof, introducing case splits when an inference depends on
   784        several facts that depend on the negated conjecture. *)
   792        several facts that depend on the negated conjecture. *)
   785     fun find_hyp j =
   793      val concl_l = (conjecture_prefix, length hyp_ts)
   786       nth hyp_ts (index_in_shape j conjecture_shape)
       
   787       handle Subscript =>
       
   788              raise Fail ("Cannot find hypothesis " ^ Int.toString j)
       
   789      val concl_ls = map (pair conjecture_prefix) (List.last conjecture_shape)
       
   790 val _ = priority ("*** " ^ PolyML.makestring concl_ls)(*###*)
       
   791      val canonicalize_labels =
       
   792        map (fn l => if member (op =) concl_ls l then hd concl_ls else l)
       
   793        #> distinct (op =)
       
   794      fun first_pass ([], contra) = ([], contra)
   794      fun first_pass ([], contra) = ([], contra)
   795        | first_pass ((step as Fix _) :: proof, contra) =
   795        | first_pass ((step as Fix _) :: proof, contra) =
   796          first_pass (proof, contra) |>> cons step
   796          first_pass (proof, contra) |>> cons step
   797        | first_pass ((step as Let _) :: proof, contra) =
   797        | first_pass ((step as Let _) :: proof, contra) =
   798          first_pass (proof, contra) |>> cons step
   798          first_pass (proof, contra) |>> cons step
   799        | first_pass ((step as Assume (l as (_, j), _)) :: proof, contra) =
   799        | first_pass ((step as Assume (l as (_, j), _)) :: proof, contra) =
   800          if member (op =) concl_ls l then
   800          if l = concl_l then first_pass (proof, contra ||> cons step)
   801            first_pass (proof, contra ||> l = hd concl_ls ? cons step)
   801          else first_pass (proof, contra) |>> cons (Assume (l, nth hyp_ts j))
   802          else
       
   803            first_pass (proof, contra) |>> cons (Assume (l, find_hyp j))
       
   804        | first_pass (Have (qs, l, t, ByMetis (ls, ss)) :: proof, contra) =
   802        | first_pass (Have (qs, l, t, ByMetis (ls, ss)) :: proof, contra) =
   805          let
   803          let val step = Have (qs, l, t, ByMetis (ls, ss)) in
   806            val ls = canonicalize_labels ls
       
   807            val step = Have (qs, l, t, ByMetis (ls, ss))
       
   808          in
       
   809            if exists (member (op =) (fst contra)) ls then
   804            if exists (member (op =) (fst contra)) ls then
   810              first_pass (proof, contra |>> cons l ||> cons step)
   805              first_pass (proof, contra |>> cons l ||> cons step)
   811            else
   806            else
   812              first_pass (proof, contra) |>> cons step
   807              first_pass (proof, contra) |>> cons step
   813          end
   808          end
   814        | first_pass _ = raise Fail "malformed proof"
   809        | first_pass _ = raise Fail "malformed proof"
   815     val (proof_top, (contra_ls, contra_proof)) =
   810     val (proof_top, (contra_ls, contra_proof)) =
   816       first_pass (proof, (concl_ls, []))
   811       first_pass (proof, ([concl_l], []))
   817     val backpatch_label = the_default ([], []) oo AList.lookup (op =) o fst
   812     val backpatch_label = the_default ([], []) oo AList.lookup (op =) o fst
   818     fun backpatch_labels patches ls =
   813     fun backpatch_labels patches ls =
   819       fold merge_fact_sets (map (backpatch_label patches) ls) ([], [])
   814       fold merge_fact_sets (map (backpatch_label patches) ls) ([], [])
   820     fun second_pass end_qs ([], assums, patches) =
   815     fun second_pass end_qs ([], assums, patches) =
   821         ([Have (end_qs, no_label, concl_t,
   816         ([Have (end_qs, no_label, concl_t,
   846            | (contra_ls as _ :: _, co_ls) =>
   841            | (contra_ls as _ :: _, co_ls) =>
   847              let
   842              let
   848                val proofs =
   843                val proofs =
   849                  map_filter
   844                  map_filter
   850                      (fn l =>
   845                      (fn l =>
   851                          if member (op =) concl_ls l then
   846                          if l = concl_l then
   852                            NONE
   847                            NONE
   853                          else
   848                          else
   854                            let
   849                            let
   855                              val drop_ls = filter (curry (op <>) l) contra_ls
   850                              val drop_ls = filter (curry (op <>) l) contra_ls
   856                            in
   851                            in
  1041     val (one_line_proof, lemma_names) = metis_proof_text other_params
  1036     val (one_line_proof, lemma_names) = metis_proof_text other_params
  1042     fun isar_proof_for () =
  1037     fun isar_proof_for () =
  1043       case proof_from_atp_proof pool ctxt full_types tfrees isar_shrink_factor
  1038       case proof_from_atp_proof pool ctxt full_types tfrees isar_shrink_factor
  1044                                 atp_proof conjecture_shape axiom_names params
  1039                                 atp_proof conjecture_shape axiom_names params
  1045                                 frees
  1040                                 frees
  1046 (*###
  1041            |> redirect_proof hyp_ts concl_t
  1047            |> redirect_proof conjecture_shape hyp_ts concl_t
       
  1048            |> kill_duplicate_assumptions_in_proof
  1042            |> kill_duplicate_assumptions_in_proof
  1049            |> then_chain_proof
  1043            |> then_chain_proof
  1050            |> kill_useless_labels_in_proof
  1044            |> kill_useless_labels_in_proof
  1051            |> relabel_proof
  1045            |> relabel_proof
  1052 *)
       
  1053            |> string_for_proof ctxt full_types i n of
  1046            |> string_for_proof ctxt full_types i n of
  1054         "" => "\nNo structured proof available."
  1047         "" => "\nNo structured proof available."
  1055       | proof => "\n\nStructured proof:\n" ^ Markup.markup Markup.sendback proof
  1048       | proof => "\n\nStructured proof:\n" ^ Markup.markup Markup.sendback proof
  1056     val isar_proof =
  1049     val isar_proof =
  1057       if debug then
  1050       if debug then