src/HOL/Tools/Sledgehammer/sledgehammer_reconstruct.ML
changeset 39368 f661064b2b80
parent 39353 7f11d833d65b
child 39370 f8292d3020db
equal deleted inserted replaced
39367:ce60294425a0 39368:f661064b2b80
    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 | Num of int
       
    66 
       
    67 fun tstp_name_ord (Str s, Str t) = string_ord (s, t)
       
    68   | tstp_name_ord (Str _, Num _) = LESS
       
    69   | tstp_name_ord (Num i, Num j) = int_ord (i, j)
       
    70   | tstp_name_ord (Num _, Str _) = GREATER
       
    71 
    65 fun index_in_shape x = find_index (exists (curry (op =) x))
    72 fun index_in_shape x = find_index (exists (curry (op =) x))
    66 fun is_axiom_number axiom_names num =
    73 fun resolve_axiom axiom_names (Str str) =
    67   num > 0 andalso num <= Vector.length axiom_names andalso
    74     (case find_first_in_list_vector axiom_names str of
    68   not (null (Vector.sub (axiom_names, num - 1)))
    75        SOME x => [(str, x)]
    69 fun is_conjecture_number conjecture_shape num =
    76      | NONE => [])
    70   index_in_shape num conjecture_shape >= 0
    77   | resolve_axiom axiom_names (Num num) =
       
    78     if num > 0 andalso num <= Vector.length axiom_names then
       
    79       Vector.sub (axiom_names, num - 1)
       
    80     else
       
    81       []
       
    82 val is_axiom_name = not o null oo resolve_axiom
       
    83 fun is_conjecture_name _ (Str str) = String.isPrefix conjecture_prefix str
       
    84   | is_conjecture_name conjecture_shape (Num num) =
       
    85     index_in_shape num conjecture_shape >= 0
    71 
    86 
    72 fun negate_term (Const (@{const_name All}, T) $ Abs (s, T', t')) =
    87 fun negate_term (Const (@{const_name All}, T) $ Abs (s, T', t')) =
    73     Const (@{const_name Ex}, T) $ Abs (s, T', negate_term t')
    88     Const (@{const_name Ex}, T) $ Abs (s, T', negate_term t')
    74   | negate_term (Const (@{const_name Ex}, T) $ Abs (s, T', t')) =
    89   | negate_term (Const (@{const_name Ex}, T) $ Abs (s, T', t')) =
    75     Const (@{const_name All}, T) $ Abs (s, T', negate_term t')
    90     Const (@{const_name All}, T) $ Abs (s, T', negate_term t')
    80   | negate_term (@{const HOL.disj} $ t1 $ t2) =
    95   | negate_term (@{const HOL.disj} $ t1 $ t2) =
    81     @{const HOL.conj} $ negate_term t1 $ negate_term t2
    96     @{const HOL.conj} $ negate_term t1 $ negate_term t2
    82   | negate_term (@{const Not} $ t) = t
    97   | negate_term (@{const Not} $ t) = t
    83   | negate_term t = @{const Not} $ t
    98   | negate_term t = @{const Not} $ t
    84 
    99 
    85 datatype ('a, 'b, 'c, 'd, 'e) raw_step =
   100 datatype ('a, 'b, 'c) raw_step =
    86   Definition of 'a * 'b * 'c |
   101   Definition of tstp_name * 'a * 'b |
    87   Inference of 'a * 'd * 'e list
   102   Inference of tstp_name * 'c * tstp_name list
    88 
   103 
    89 fun raw_step_number (Definition (num, _, _)) = num
   104 fun raw_step_name (Definition (name, _, _)) = name
    90   | raw_step_number (Inference (num, _, _)) = num
   105   | raw_step_name (Inference (name, _, _)) = name
    91 
   106 
    92 (**** PARSING OF TSTP FORMAT ****)
   107 (**** PARSING OF TSTP FORMAT ****)
    93 
   108 
    94 (*Strings enclosed in single quotes, e.g. filenames*)
   109 (*Strings enclosed in single quotes, e.g. filenames*)
    95 val scan_quoted = $$ "'" |-- Scan.repeat (~$$ "'") --| $$ "'" >> implode;
   110 val scan_quoted = $$ "'" |-- Scan.repeat (~$$ "'") --| $$ "'" >> implode;
   182     >> (fn (((num, role), phi), deps) =>
   197     >> (fn (((num, role), phi), deps) =>
   183            case role of
   198            case role of
   184              "definition" =>
   199              "definition" =>
   185              (case phi of
   200              (case phi of
   186                 AConn (AIff, [phi1 as AAtom _, phi2]) =>
   201                 AConn (AIff, [phi1 as AAtom _, phi2]) =>
   187                 Definition (num, phi1, phi2)
   202                 Definition (Num num, phi1, phi2)
   188               | AAtom (ATerm ("c_equal", _)) =>
   203               | AAtom (ATerm ("c_equal", _)) =>
   189                 Inference (num, phi, deps) (* Vampire's equality proxy axiom *)
   204                 (* Vampire's equality proxy axiom *)
       
   205                 Inference (Num num, phi, map Num deps)
   190               | _ => raise Fail "malformed definition")
   206               | _ => raise Fail "malformed definition")
   191            | _ => Inference (num, phi, deps))
   207            | _ => Inference (Num num, phi, map Num deps))
   192 
   208 
   193 (**** PARSING OF VAMPIRE OUTPUT ****)
   209 (**** PARSING OF VAMPIRE OUTPUT ****)
   194 
   210 
   195 (* Syntax: <num>. <formula> <annotation> *)
   211 (* Syntax: <num>. <formula> <annotation> *)
   196 fun parse_vampire_line pool =
   212 fun parse_vampire_line pool =
   197   scan_integer --| $$ "." -- parse_formula pool -- parse_annotation
   213   scan_integer --| $$ "." -- parse_formula pool -- parse_annotation
   198   >> (fn ((num, phi), deps) => Inference (num, phi, deps))
   214   >> (fn ((num, phi), deps) => Inference (Num num, phi, map Num deps))
   199 
   215 
   200 (**** PARSING OF SPASS OUTPUT ****)
   216 (**** PARSING OF SPASS OUTPUT ****)
   201 
   217 
   202 (* SPASS returns clause references of the form "x.y". We ignore "y", whose role
   218 (* SPASS returns clause references of the form "x.y". We ignore "y", whose role
   203    is not clear anyway. *)
   219    is not clear anyway. *)
   228 (* Syntax: <num>[0:<inference><annotations>]
   244 (* Syntax: <num>[0:<inference><annotations>]
   229    <atoms> || <atoms> -> <atoms>. *)
   245    <atoms> || <atoms> -> <atoms>. *)
   230 fun parse_spass_line pool =
   246 fun parse_spass_line pool =
   231   scan_integer --| $$ "[" --| $$ "0" --| $$ ":" --| Symbol.scan_id
   247   scan_integer --| $$ "[" --| $$ "0" --| $$ ":" --| Symbol.scan_id
   232     -- parse_spass_annotations --| $$ "]" -- parse_horn_clause pool --| $$ "."
   248     -- parse_spass_annotations --| $$ "]" -- parse_horn_clause pool --| $$ "."
   233   >> (fn ((num, deps), u) => Inference (num, u, deps))
   249   >> (fn ((num, deps), u) => Inference (Num num, u, map Num deps))
   234 
   250 
   235 fun parse_line pool =
   251 fun parse_line pool =
   236   parse_tstp_line pool || parse_vampire_line pool || parse_spass_line pool
   252   parse_tstp_line pool || parse_vampire_line pool || parse_spass_line pool
   237 fun parse_lines pool = Scan.repeat1 (parse_line pool)
   253 fun parse_lines pool = Scan.repeat1 (parse_line pool)
   238 fun parse_proof pool =
   254 fun parse_proof pool =
   445 (**** Translation of TSTP files to Isar Proofs ****)
   461 (**** Translation of TSTP files to Isar Proofs ****)
   446 
   462 
   447 fun unvarify_term (Var ((s, 0), T)) = Free (s, T)
   463 fun unvarify_term (Var ((s, 0), T)) = Free (s, T)
   448   | unvarify_term t = raise TERM ("unvarify_term: non-Var", [t])
   464   | unvarify_term t = raise TERM ("unvarify_term: non-Var", [t])
   449 
   465 
   450 fun decode_line full_types tfrees (Definition (num, phi1, phi2)) ctxt =
   466 fun decode_line full_types tfrees (Definition (name, phi1, phi2)) ctxt =
   451     let
   467     let
   452       val thy = ProofContext.theory_of ctxt
   468       val thy = ProofContext.theory_of ctxt
   453       val t1 = prop_from_formula thy full_types tfrees phi1
   469       val t1 = prop_from_formula thy full_types tfrees phi1
   454       val vars = snd (strip_comb t1)
   470       val vars = snd (strip_comb t1)
   455       val frees = map unvarify_term vars
   471       val frees = map unvarify_term vars
   458       val (t1, t2) =
   474       val (t1, t2) =
   459         HOLogic.eq_const HOLogic.typeT $ t1 $ t2
   475         HOLogic.eq_const HOLogic.typeT $ t1 $ t2
   460         |> unvarify_args |> uncombine_term |> check_formula ctxt
   476         |> unvarify_args |> uncombine_term |> check_formula ctxt
   461         |> HOLogic.dest_eq
   477         |> HOLogic.dest_eq
   462     in
   478     in
   463       (Definition (num, t1, t2),
   479       (Definition (name, t1, t2),
   464        fold Variable.declare_term (maps OldTerm.term_frees [t1, t2]) ctxt)
   480        fold Variable.declare_term (maps OldTerm.term_frees [t1, t2]) ctxt)
   465     end
   481     end
   466   | decode_line full_types tfrees (Inference (num, u, deps)) ctxt =
   482   | decode_line full_types tfrees (Inference (name, u, deps)) ctxt =
   467     let
   483     let
   468       val thy = ProofContext.theory_of ctxt
   484       val thy = ProofContext.theory_of ctxt
   469       val t = u |> prop_from_formula thy full_types tfrees
   485       val t = u |> prop_from_formula thy full_types tfrees
   470                 |> uncombine_term |> check_formula ctxt
   486                 |> uncombine_term |> check_formula ctxt
   471     in
   487     in
   472       (Inference (num, t, deps),
   488       (Inference (name, t, deps),
   473        fold Variable.declare_term (OldTerm.term_frees t) ctxt)
   489        fold Variable.declare_term (OldTerm.term_frees t) ctxt)
   474     end
   490     end
   475 fun decode_lines ctxt full_types tfrees lines =
   491 fun decode_lines ctxt full_types tfrees lines =
   476   fst (fold_map (decode_line full_types tfrees) lines ctxt)
   492   fst (fold_map (decode_line full_types tfrees) lines ctxt)
   477 
   493 
   482    clsarity). *)
   498    clsarity). *)
   483 val is_only_type_information = curry (op aconv) HOLogic.true_const
   499 val is_only_type_information = curry (op aconv) HOLogic.true_const
   484 
   500 
   485 fun replace_one_dep (old, new) dep = if dep = old then new else [dep]
   501 fun replace_one_dep (old, new) dep = if dep = old then new else [dep]
   486 fun replace_deps_in_line _ (line as Definition _) = line
   502 fun replace_deps_in_line _ (line as Definition _) = line
   487   | replace_deps_in_line p (Inference (num, t, deps)) =
   503   | replace_deps_in_line p (Inference (name, t, deps)) =
   488     Inference (num, t, fold (union (op =) o replace_one_dep p) deps [])
   504     Inference (name, t, fold (union (op =) o replace_one_dep p) deps [])
   489 
   505 
   490 (* Discard axioms; consolidate adjacent lines that prove the same formula, since
   506 (* Discard axioms; consolidate adjacent lines that prove the same formula, since
   491    they differ only in type information.*)
   507    they differ only in type information.*)
   492 fun add_line _ _ (line as Definition _) lines = line :: lines
   508 fun add_line _ _ (line as Definition _) lines = line :: lines
   493   | add_line conjecture_shape axiom_names (Inference (num, t, [])) lines =
   509   | add_line conjecture_shape axiom_names (Inference (name, t, [])) lines =
   494     (* No dependencies: axiom, conjecture, or (for Vampire) internal axioms or
   510     (* No dependencies: axiom, conjecture, or (for Vampire) internal axioms or
   495        definitions. *)
   511        definitions. *)
   496     if is_axiom_number axiom_names num then
   512     if is_axiom_name axiom_names name then
   497       (* Axioms are not proof lines. *)
   513       (* Axioms are not proof lines. *)
   498       if is_only_type_information t then
   514       if is_only_type_information t then
   499         map (replace_deps_in_line (num, [])) lines
   515         map (replace_deps_in_line (name, [])) lines
   500       (* Is there a repetition? If so, replace later line by earlier one. *)
   516       (* Is there a repetition? If so, replace later line by earlier one. *)
   501       else case take_prefix (not o is_same_inference t) lines of
   517       else case take_prefix (not o is_same_inference t) lines of
   502         (_, []) => lines (*no repetition of proof line*)
   518         (_, []) => lines (*no repetition of proof line*)
   503       | (pre, Inference (num', _, _) :: post) =>
   519       | (pre, Inference (name', _, _) :: post) =>
   504         pre @ map (replace_deps_in_line (num', [num])) post
   520         pre @ map (replace_deps_in_line (name', [name])) post
   505     else if is_conjecture_number conjecture_shape num then
   521     else if is_conjecture_name conjecture_shape name then
   506       Inference (num, negate_term t, []) :: lines
   522       Inference (name, negate_term t, []) :: lines
   507     else
   523     else
   508       map (replace_deps_in_line (num, [])) lines
   524       map (replace_deps_in_line (name, [])) lines
   509   | add_line _ _ (Inference (num, t, deps)) lines =
   525   | add_line _ _ (Inference (name, t, deps)) lines =
   510     (* Type information will be deleted later; skip repetition test. *)
   526     (* Type information will be deleted later; skip repetition test. *)
   511     if is_only_type_information t then
   527     if is_only_type_information t then
   512       Inference (num, t, deps) :: lines
   528       Inference (name, t, deps) :: lines
   513     (* Is there a repetition? If so, replace later line by earlier one. *)
   529     (* Is there a repetition? If so, replace later line by earlier one. *)
   514     else case take_prefix (not o is_same_inference t) lines of
   530     else case take_prefix (not o is_same_inference t) lines of
   515       (* FIXME: Doesn't this code risk conflating proofs involving different
   531       (* FIXME: Doesn't this code risk conflating proofs involving different
   516          types? *)
   532          types? *)
   517        (_, []) => Inference (num, t, deps) :: lines
   533        (_, []) => Inference (name, t, deps) :: lines
   518      | (pre, Inference (num', t', _) :: post) =>
   534      | (pre, Inference (name', t', _) :: post) =>
   519        Inference (num, t', deps) ::
   535        Inference (name, t', deps) ::
   520        pre @ map (replace_deps_in_line (num', [num])) post
   536        pre @ map (replace_deps_in_line (name', [name])) post
   521 
   537 
   522 (* Recursively delete empty lines (type information) from the proof. *)
   538 (* Recursively delete empty lines (type information) from the proof. *)
   523 fun add_nontrivial_line (Inference (num, t, [])) lines =
   539 fun add_nontrivial_line (Inference (name, t, [])) lines =
   524     if is_only_type_information t then delete_dep num lines
   540     if is_only_type_information t then delete_dep name lines
   525     else Inference (num, t, []) :: lines
   541     else Inference (name, t, []) :: lines
   526   | add_nontrivial_line line lines = line :: lines
   542   | add_nontrivial_line line lines = line :: lines
   527 and delete_dep num lines =
   543 and delete_dep name lines =
   528   fold_rev add_nontrivial_line (map (replace_deps_in_line (num, [])) lines) []
   544   fold_rev add_nontrivial_line (map (replace_deps_in_line (name, [])) lines) []
   529 
   545 
   530 (* ATPs sometimes reuse free variable names in the strangest ways. Removing
   546 (* ATPs sometimes reuse free variable names in the strangest ways. Removing
   531    offending lines often does the trick. *)
   547    offending lines often does the trick. *)
   532 fun is_bad_free frees (Free x) = not (member (op =) frees x)
   548 fun is_bad_free frees (Free x) = not (member (op =) frees x)
   533   | is_bad_free _ _ = false
   549   | is_bad_free _ _ = false
   534 
   550 
   535 fun add_desired_line _ _ _ _ (line as Definition (num, _, _)) (j, lines) =
   551 fun add_desired_line _ _ _ _ (line as Definition (name, _, _)) (j, lines) =
   536     (j, line :: map (replace_deps_in_line (num, [])) lines)
   552     (j, line :: map (replace_deps_in_line (name, [])) lines)
   537   | add_desired_line isar_shrink_factor conjecture_shape axiom_names frees
   553   | add_desired_line isar_shrink_factor conjecture_shape axiom_names frees
   538                      (Inference (num, t, deps)) (j, lines) =
   554                      (Inference (name, t, deps)) (j, lines) =
   539     (j + 1,
   555     (j + 1,
   540      if is_axiom_number axiom_names num orelse
   556      if is_axiom_name axiom_names name orelse
   541         is_conjecture_number conjecture_shape num orelse
   557         is_conjecture_name conjecture_shape name orelse
   542         (not (is_only_type_information t) andalso
   558         (not (is_only_type_information t) andalso
   543          null (Term.add_tvars t []) andalso
   559          null (Term.add_tvars t []) andalso
   544          not (exists_subterm (is_bad_free frees) t) andalso
   560          not (exists_subterm (is_bad_free frees) t) andalso
   545          (null lines orelse (* last line must be kept *)
   561          (null lines orelse (* last line must be kept *)
   546           (length deps >= 2 andalso j mod isar_shrink_factor = 0))) then
   562           (length deps >= 2 andalso j mod isar_shrink_factor = 0))) then
   547        Inference (num, t, deps) :: lines  (* keep line *)
   563        Inference (name, t, deps) :: lines  (* keep line *)
   548      else
   564      else
   549        map (replace_deps_in_line (num, deps)) lines)  (* drop line *)
   565        map (replace_deps_in_line (name, deps)) lines)  (* drop line *)
   550 
   566 
   551 (** EXTRACTING LEMMAS **)
   567 (** EXTRACTING LEMMAS **)
   552 
   568 
   553 (* Like "split_line", but ignores "\n" that follow a comma (as in SNARK's
   569 (* Like "split_line", but ignores "\n" that follow a comma (as in SNARK's
   554    output). *)
   570    output). *)
   568    "108. ... [input]". *)
   584    "108. ... [input]". *)
   569 fun used_facts_in_atp_proof axiom_names atp_proof =
   585 fun used_facts_in_atp_proof axiom_names atp_proof =
   570   let
   586   let
   571     fun axiom_names_at_index num =
   587     fun axiom_names_at_index num =
   572       let val j = Int.fromString num |> the_default ~1 in
   588       let val j = Int.fromString num |> the_default ~1 in
   573         if is_axiom_number axiom_names j then Vector.sub (axiom_names, j - 1)
   589         resolve_axiom axiom_names (Num j)
   574         else []
       
   575       end
   590       end
   576     val tokens_of =
   591     val tokens_of =
   577       String.tokens (fn c => not (Char.isAlphaNum c) andalso c <> #"_")
   592       String.tokens (fn c => not (Char.isAlphaNum c) andalso c <> #"_")
   578     fun do_line (tag :: num :: "axiom" :: (rest as _ :: _)) =
   593     fun do_line (tag :: num :: "axiom" :: (rest as _ :: _)) =
   579         if tag = "cnf" orelse tag = "fof" then
   594         if tag = "cnf" orelse tag = "fof" then
   600 val raw_prefix = "X"
   615 val raw_prefix = "X"
   601 val assum_prefix = "A"
   616 val assum_prefix = "A"
   602 val fact_prefix = "F"
   617 val fact_prefix = "F"
   603 
   618 
   604 fun string_for_label (s, num) = s ^ string_of_int num
   619 fun string_for_label (s, num) = s ^ string_of_int num
       
   620 
       
   621 fun raw_label_for_name (Str str) = (raw_prefix ^ str, 0)
       
   622   | raw_label_for_name (Num num) = (raw_prefix, num)
   605 
   623 
   606 fun metis_using [] = ""
   624 fun metis_using [] = ""
   607   | metis_using ls =
   625   | metis_using ls =
   608     "using " ^ space_implode " " (map string_for_label ls) ^ " "
   626     "using " ^ space_implode " " (map string_for_label ls) ^ " "
   609 fun metis_apply _ 1 = "by "
   627 fun metis_apply _ 1 = "by "
   662   CaseSplit of step list list * facts
   680   CaseSplit of step list list * facts
   663 
   681 
   664 fun smart_case_split [] facts = ByMetis facts
   682 fun smart_case_split [] facts = ByMetis facts
   665   | smart_case_split proofs facts = CaseSplit (proofs, facts)
   683   | smart_case_split proofs facts = CaseSplit (proofs, facts)
   666 
   684 
   667 fun add_fact_from_dep axiom_names num =
   685 fun add_fact_from_dep axiom_names name =
   668   if is_axiom_number axiom_names num then
   686   if is_axiom_name axiom_names name then
   669     apsnd (union (op =) (map fst (Vector.sub (axiom_names, num - 1))))
   687     apsnd (union (op =) (map fst (resolve_axiom axiom_names name)))
   670   else
   688   else
   671     apfst (insert (op =) (raw_prefix, num))
   689     apfst (insert (op =) (raw_label_for_name name))
   672 
   690 
   673 fun forall_of v t = HOLogic.all_const (fastype_of v) $ lambda v t
   691 fun forall_of v t = HOLogic.all_const (fastype_of v) $ lambda v t
   674 fun forall_vars t = fold_rev forall_of (map Var (Term.add_vars t [])) t
   692 fun forall_vars t = fold_rev forall_of (map Var (Term.add_vars t [])) t
   675 
   693 
   676 fun step_for_line _ _ (Definition (_, t1, t2)) = Let (t1, t2)
   694 fun step_for_line _ _ (Definition (_, t1, t2)) = Let (t1, t2)
   677   | step_for_line _ _ (Inference (num, t, [])) = Assume ((raw_prefix, num), t)
   695   | step_for_line _ _ (Inference (name, t, [])) =
   678   | step_for_line axiom_names j (Inference (num, t, deps)) =
   696     Assume (raw_label_for_name name, t)
   679     Have (if j = 1 then [Show] else [], (raw_prefix, num),
   697   | step_for_line axiom_names j (Inference (name, t, deps)) =
       
   698     Have (if j = 1 then [Show] else [], raw_label_for_name name,
   680           forall_vars t,
   699           forall_vars t,
   681           ByMetis (fold (add_fact_from_dep axiom_names) deps ([], [])))
   700           ByMetis (fold (add_fact_from_dep axiom_names) deps ([], [])))
   682 
   701 
   683 fun proof_from_atp_proof pool ctxt full_types tfrees isar_shrink_factor
   702 fun proof_from_atp_proof pool ctxt full_types tfrees isar_shrink_factor
   684                          atp_proof conjecture_shape axiom_names params frees =
   703                          atp_proof conjecture_shape axiom_names params frees =
   685   let
   704   let
   686     val lines =
   705     val lines =
   687       atp_proof ^ "$" (* the $ sign acts as a sentinel (FIXME: needed?) *)
   706       atp_proof ^ "$" (* the $ sign acts as a sentinel (FIXME: needed?) *)
   688       |> parse_proof pool
   707       |> parse_proof pool
   689       |> sort (int_ord o pairself raw_step_number)
   708       |> sort (tstp_name_ord o pairself raw_step_name)
   690       |> decode_lines ctxt full_types tfrees
   709       |> decode_lines ctxt full_types tfrees
   691       |> rpair [] |-> fold_rev (add_line conjecture_shape axiom_names)
   710       |> rpair [] |-> fold_rev (add_line conjecture_shape axiom_names)
   692       |> rpair [] |-> fold_rev add_nontrivial_line
   711       |> rpair [] |-> fold_rev add_nontrivial_line
   693       |> rpair (0, []) |-> fold_rev (add_desired_line isar_shrink_factor
   712       |> rpair (0, []) |-> fold_rev (add_desired_line isar_shrink_factor
   694                                              conjecture_shape axiom_names frees)
   713                                              conjecture_shape axiom_names frees)