src/HOL/Tools/ATP/atp_proof.ML
changeset 54811 df56a01f5684
parent 54803 41a109a00c53
child 54820 d9ab86c044fd
equal deleted inserted replaced
54805:c05ed6333302 54811:df56a01f5684
     6 Abstract representation of ATP proofs and TSTP/SPASS syntax.
     6 Abstract representation of ATP proofs and TSTP/SPASS syntax.
     7 *)
     7 *)
     8 
     8 
     9 signature ATP_PROOF =
     9 signature ATP_PROOF =
    10 sig
    10 sig
       
    11   type 'a atp_type = 'a ATP_Problem.atp_type
    11   type ('a, 'b) atp_term = ('a, 'b) ATP_Problem.atp_term
    12   type ('a, 'b) atp_term = ('a, 'b) ATP_Problem.atp_term
    12   type atp_formula_role = ATP_Problem.atp_formula_role
    13   type atp_formula_role = ATP_Problem.atp_formula_role
    13   type ('a, 'b, 'c, 'd) atp_formula = ('a, 'b, 'c, 'd) ATP_Problem.atp_formula
    14   type ('a, 'b, 'c, 'd) atp_formula = ('a, 'b, 'c, 'd) ATP_Problem.atp_formula
    14   type 'a atp_problem = 'a ATP_Problem.atp_problem
    15   type 'a atp_problem = 'a ATP_Problem.atp_problem
    15 
    16 
    36 
    37 
    37   type atp_step_name = string * string list
    38   type atp_step_name = string * string list
    38   type ('a, 'b) atp_step =
    39   type ('a, 'b) atp_step =
    39     atp_step_name * atp_formula_role * 'a * 'b * atp_step_name list
    40     atp_step_name * atp_formula_role * 'a * 'b * atp_step_name list
    40 
    41 
    41   type 'a atp_proof =
    42   type 'a atp_proof = (('a, 'a, ('a, 'a atp_type) atp_term, 'a) atp_formula, string) atp_step list
    42     (('a, 'a, ('a, 'a) atp_term, 'a) atp_formula, string) atp_step list
       
    43 
    43 
    44   val agsyhol_core_rule : string
    44   val agsyhol_core_rule : string
    45   val satallax_core_rule : string
    45   val satallax_core_rule : string
    46   val spass_input_rule : string
    46   val spass_input_rule : string
    47   val spass_skolemize_rule : string
    47   val spass_skolemize_rule : string
    48   val z3_tptp_core_rule : string
    48   val z3_tptp_core_rule : string
    49 
    49 
    50   val short_output : bool -> string -> string
    50   val short_output : bool -> string -> string
    51   val string_of_atp_failure : atp_failure -> string
    51   val string_of_atp_failure : atp_failure -> string
    52   val extract_important_message : string -> string
    52   val extract_important_message : string -> string
    53   val extract_known_atp_failure :
    53   val extract_known_atp_failure : (atp_failure * string) list -> string -> atp_failure option
    54     (atp_failure * string) list -> string -> atp_failure option
       
    55   val extract_tstplike_proof_and_outcome :
    54   val extract_tstplike_proof_and_outcome :
    56     bool -> (string * string) list -> (atp_failure * string) list -> string
    55     bool -> (string * string) list -> (atp_failure * string) list -> string
    57     -> string * atp_failure option
    56     -> string * atp_failure option
    58   val is_same_atp_step : atp_step_name -> atp_step_name -> bool
    57   val is_same_atp_step : atp_step_name -> atp_step_name -> bool
    59   val scan_general_id : string list -> string * string list
    58   val scan_general_id : string list -> string * string list
    60   val parse_formula :
    59   val parse_formula : string list ->
    61     string list
    60     (string, string atp_type, (string, string atp_type) atp_term, string) atp_formula * string list
    62     -> (string, 'a, (string, 'a) atp_term, string) atp_formula * string list
    61   val atp_proof_of_tstplike_proof : string atp_problem -> string -> string atp_proof
    63   val atp_proof_of_tstplike_proof :
       
    64     string atp_problem -> string -> string atp_proof
       
    65   val clean_up_atp_proof_dependencies : string atp_proof -> string atp_proof
    62   val clean_up_atp_proof_dependencies : string atp_proof -> string atp_proof
    66   val map_term_names_in_atp_proof :
    63   val map_term_names_in_atp_proof : (string -> string) -> string atp_proof -> string atp_proof
    67     (string -> string) -> string atp_proof -> string atp_proof
    64   val nasty_atp_proof : string Symtab.table -> string atp_proof -> string atp_proof
    68   val nasty_atp_proof :
       
    69     string Symtab.table -> string atp_proof -> string atp_proof
       
    70 end;
    65 end;
    71 
    66 
    72 structure ATP_Proof : ATP_PROOF =
    67 structure ATP_Proof : ATP_PROOF =
    73 struct
    68 struct
    74 
    69 
   201     (case pairself (Int.fromString o perhaps (try (unprefix vampire_fact_prefix))) q of
   196     (case pairself (Int.fromString o perhaps (try (unprefix vampire_fact_prefix))) q of
   202       (SOME i, SOME j) => int_ord (i, j)
   197       (SOME i, SOME j) => int_ord (i, j)
   203     | _ => raise Fail "not Vampire")
   198     | _ => raise Fail "not Vampire")
   204   end
   199   end
   205 
   200 
   206 type ('a, 'b) atp_step =
   201 type ('a, 'b) atp_step = atp_step_name * atp_formula_role * 'a * 'b * atp_step_name list
   207   atp_step_name * atp_formula_role * 'a * 'b * atp_step_name list
   202 
   208 
   203 type 'a atp_proof = (('a, 'a, ('a, 'a atp_type) atp_term, 'a) atp_formula, string) atp_step list
   209 type 'a atp_proof =
       
   210   (('a, 'a, ('a, 'a) atp_term, 'a) atp_formula, string) atp_step list
       
   211 
   204 
   212 (**** PARSING OF TSTP FORMAT ****)
   205 (**** PARSING OF TSTP FORMAT ****)
   213 
   206 
   214 (* Strings enclosed in single quotes (e.g., file names) *)
   207 (* Strings enclosed in single quotes (e.g., file names) *)
   215 val scan_general_id =
   208 val scan_general_id =
   243 (* "skip_term" is there to cope with Waldmeister nonsense such as "theory(equality)". *)
   236 (* "skip_term" is there to cope with Waldmeister nonsense such as "theory(equality)". *)
   244 fun parse_dependency x =
   237 fun parse_dependency x =
   245   (parse_inference_source >> snd
   238   (parse_inference_source >> snd
   246    || scan_general_id --| skip_term >> single) x
   239    || scan_general_id --| skip_term >> single) x
   247 and parse_dependencies x =
   240 and parse_dependencies x =
   248   (parse_dependency ::: Scan.repeat ($$ "," |-- parse_dependency)
   241   (parse_dependency ::: Scan.repeat ($$ "," |-- parse_dependency) >> flat) x
   249    >> flat) x
       
   250 and parse_file_source x =
   242 and parse_file_source x =
   251   (Scan.this_string "file" |-- $$ "(" |-- scan_general_id
   243   (Scan.this_string "file" |-- $$ "(" |-- scan_general_id
   252    -- Scan.option ($$ "," |-- scan_general_id) --| $$ ")") x
   244    -- Scan.option ($$ "," |-- scan_general_id) --| $$ ")") x
   253 and parse_inference_source x =
   245 and parse_inference_source x =
   254   (Scan.this_string "inference" |-- $$ "(" |-- scan_general_id
   246   (Scan.this_string "inference" |-- $$ "(" |-- scan_general_id
   264    || scan_general_id >> (fn s => Inference_Source ("", [s])) (* for E *)
   256    || scan_general_id >> (fn s => Inference_Source ("", [s])) (* for E *)
   265    || skip_term >> K dummy_inference) x
   257    || skip_term >> K dummy_inference) x
   266 
   258 
   267 fun list_app (f, args) = fold (fn arg => fn f => ATerm ((tptp_app, []), [f, arg])) args f
   259 fun list_app (f, args) = fold (fn arg => fn f => ATerm ((tptp_app, []), [f, arg])) args f
   268 
   260 
       
   261 fun parse_sort x = scan_general_id x
       
   262 and parse_sorts x = (parse_sort ::: Scan.repeat ($$ "&" |-- parse_sort)) x
       
   263 
       
   264 fun parse_type x =
       
   265   (scan_general_id --| Scan.option ($$ "{" |-- parse_sorts --| $$ "}")
       
   266     -- Scan.optional ($$ "(" |-- parse_types --| $$ ")") []
       
   267    >> AType) x
       
   268 and parse_types x = (parse_type ::: Scan.repeat ($$ "," |-- parse_type)) x
       
   269 
   269 (* We currently ignore TFF and THF types. *)
   270 (* We currently ignore TFF and THF types. *)
   270 fun parse_type_stuff x = Scan.repeat (($$ tptp_has_type || $$ tptp_fun_type) |-- parse_arg) x
   271 fun parse_type_signature x = Scan.repeat (($$ tptp_has_type || $$ tptp_fun_type) |-- parse_arg) x
   271 and parse_arg x =
   272 and parse_arg x =
   272   ($$ "(" |-- parse_term --| $$ ")" --| parse_type_stuff
   273   ($$ "(" |-- parse_term --| $$ ")" --| parse_type_signature
   273    || scan_general_id --| parse_type_stuff
   274    || scan_general_id --| parse_type_signature
   274         -- Scan.optional ($$ "(" |-- parse_terms --| $$ ")") []
   275        -- Scan.optional ($$ "<" |-- parse_types --| $$ ">") []
   275       >> (ATerm o apfst (rpair []))) x
   276        -- Scan.optional ($$ "(" |-- parse_terms --| $$ ")") []
       
   277      >> ATerm) x
   276 and parse_term x = (parse_arg -- Scan.repeat ($$ tptp_app |-- parse_arg) >> list_app) x
   278 and parse_term x = (parse_arg -- Scan.repeat ($$ tptp_app |-- parse_arg) >> list_app) x
   277 and parse_terms x = (parse_term ::: Scan.repeat ($$ "," |-- parse_term)) x
   279 and parse_terms x = (parse_term ::: Scan.repeat ($$ "," |-- parse_term)) x
   278 
   280 
   279 fun parse_atom x =
   281 fun parse_atom x =
   280   (parse_term -- Scan.option (Scan.option ($$ tptp_not_infix) --| $$ tptp_equal
   282   (parse_term -- Scan.option (Scan.option ($$ tptp_not_infix) --| $$ tptp_equal -- parse_term)
   281                               -- parse_term)
       
   282    >> (fn (u1, NONE) => AAtom u1
   283    >> (fn (u1, NONE) => AAtom u1
   283         | (u1, SOME (neg, u2)) =>
   284         | (u1, SOME (neg, u2)) =>
   284           AAtom (ATerm (("equal", []), [u1, u2])) |> is_some neg ? mk_anot)) x
   285           AAtom (ATerm (("equal", []), [u1, u2])) |> is_some neg ? mk_anot)) x
   285 
   286 
   286 (* TPTP formulas are fully parenthesized, so we don't need to worry about operator precedence. *)
   287 (* TPTP formulas are fully parenthesized, so we don't need to worry about operator precedence. *)
   422 (* SPASS returns clause references of the form "x.y". We ignore "y", whose role
   423 (* SPASS returns clause references of the form "x.y". We ignore "y", whose role
   423    is not clear anyway. *)
   424    is not clear anyway. *)
   424 val parse_dot_name = scan_general_id --| $$ "." --| scan_general_id
   425 val parse_dot_name = scan_general_id --| $$ "." --| scan_general_id
   425 
   426 
   426 val parse_spass_annotations =
   427 val parse_spass_annotations =
   427   Scan.optional ($$ ":" |-- Scan.repeat (parse_dot_name
   428   Scan.optional ($$ ":" |-- Scan.repeat (parse_dot_name --| Scan.option ($$ ","))) []
   428                                          --| Scan.option ($$ ","))) []
       
   429 
   429 
   430 (* It is not clear why some literals are followed by sequences of stars and/or
   430 (* It is not clear why some literals are followed by sequences of stars and/or
   431    pluses. We ignore them. *)
   431    pluses. We ignore them. *)
   432 fun parse_decorated_atom x =
   432 fun parse_decorated_atom x =
   433   (parse_atom --| Scan.repeat ($$ "*" || $$ "+" || $$ " ")) x
   433   (parse_atom --| Scan.repeat ($$ "*" || $$ "+" || $$ " ")) x
   458    >> (fn ((((num, rule), deps), u), names) =>
   458    >> (fn ((((num, rule), deps), u), names) =>
   459           ((num, these names), Unknown, u, rule, map (rpair []) deps))) x
   459           ((num, these names), Unknown, u, rule, map (rpair []) deps))) x
   460 
   460 
   461 fun parse_spass_pirate_dependency x = (Scan.option ($$ "-") |-- scan_general_id) x
   461 fun parse_spass_pirate_dependency x = (Scan.option ($$ "-") |-- scan_general_id) x
   462 fun parse_spass_pirate_dependencies x =
   462 fun parse_spass_pirate_dependencies x =
   463   (parse_spass_pirate_dependency ::: Scan.repeat ($$ "," |-- parse_spass_pirate_dependency)) x
   463   Scan.repeat (parse_spass_pirate_dependency --| Scan.option ($$ "," || $$ " ")) x
   464 fun parse_spass_pirate_file_source x =
   464 fun parse_spass_pirate_file_source x =
   465   ((Scan.this_string "Input" || Scan.this_string "Conj") |-- $$ "(" |-- scan_general_id
   465   ((Scan.this_string "Input" || Scan.this_string "Conj") |-- $$ "(" |-- scan_general_id
   466      --| $$ ")") x
   466      --| $$ ")") x
   467 fun parse_spass_pirate_inference_source x =
   467 fun parse_spass_pirate_inference_source x =
   468   (scan_general_id |-- $$ "(" -- parse_spass_pirate_dependencies --| $$ ")") x
   468   (scan_general_id |-- $$ "(" -- parse_spass_pirate_dependencies --| $$ ")") x
   515 fun atp_proof_of_tstplike_proof _ "" = []
   515 fun atp_proof_of_tstplike_proof _ "" = []
   516   | atp_proof_of_tstplike_proof problem tstp =
   516   | atp_proof_of_tstplike_proof problem tstp =
   517     (case core_of_agsyhol_proof tstp of
   517     (case core_of_agsyhol_proof tstp of
   518       SOME facts => facts |> map (core_inference agsyhol_core_rule)
   518       SOME facts => facts |> map (core_inference agsyhol_core_rule)
   519     | NONE =>
   519     | NONE =>
   520       tstp ^ "$"  (* the $ sign acts as a sentinel (FIXME: needed?) *)
   520       tstp ^ "$" (* the $ sign acts as a sentinel (FIXME: needed?) *)
   521       |> parse_proof problem
   521       |> parse_proof problem
   522       |> perhaps (try (sort (vampire_step_name_ord o pairself #1))))
   522       |> perhaps (try (sort (vampire_step_name_ord o pairself #1))))
   523 
   523 
   524 fun clean_up_dependencies _ [] = []
   524 fun clean_up_dependencies _ [] = []
   525   | clean_up_dependencies seen ((name, role, u, rule, deps) :: steps) =
   525   | clean_up_dependencies seen ((name, role, u, rule, deps) :: steps) =
   526     (name, role, u, rule,
   526     (name, role, u, rule, map_filter (fn dep => find_first (is_same_atp_step dep) seen) deps) ::
   527      map_filter (fn dep => find_first (is_same_atp_step dep) seen) deps) ::
       
   528     clean_up_dependencies (name :: seen) steps
   527     clean_up_dependencies (name :: seen) steps
   529 
   528 
   530 fun clean_up_atp_proof_dependencies proof = clean_up_dependencies [] proof
   529 fun clean_up_atp_proof_dependencies proof = clean_up_dependencies [] proof
   531 
   530 
   532 fun map_term_names_in_atp_proof f =
   531 fun map_term_names_in_atp_proof f =
   533   let
   532   let
   534     fun do_term (ATerm ((s, tys), ts)) = ATerm ((f s, tys), map do_term ts)
   533     fun map_type (AType (s, tys)) = AType (f s, map map_type tys)
   535     fun do_formula (AQuant (q, xs, phi)) =
   534       | map_type (AFun (ty, ty')) = AFun (map_type ty, map_type ty')
   536         AQuant (q, map (apfst f) xs, do_formula phi)
   535       | map_type (APi (ss, ty)) = APi (map f ss, map_type ty)
   537       | do_formula (AConn (c, phis)) = AConn (c, map do_formula phis)
   536 
   538       | do_formula (AAtom t) = AAtom (do_term t)
   537     fun map_term (ATerm ((s, tys), ts)) = ATerm ((f s, map map_type tys), map map_term ts)
   539     fun do_step (name, role, phi, rule, deps) =
   538       | map_term (AAbs (((s, ty), tm), args)) =
   540       (name, role, do_formula phi, rule, deps)
   539         AAbs (((f s, map_type ty), map_term tm), map map_term args)
   541   in map do_step end
   540 
       
   541     fun map_formula (AQuant (q, xs, phi)) =
       
   542         AQuant (q, map (apfst f) xs, map_formula phi)
       
   543       | map_formula (AConn (c, phis)) = AConn (c, map map_formula phis)
       
   544       | map_formula (AAtom t) = AAtom (map_term t)
       
   545 
       
   546     fun map_step (name, role, phi, rule, deps) =
       
   547       (name, role, map_formula phi, rule, deps)
       
   548   in
       
   549     map map_step
       
   550   end
   542 
   551 
   543 fun nasty_name pool s = s |> Symtab.lookup pool |> the_default s
   552 fun nasty_name pool s = s |> Symtab.lookup pool |> the_default s
   544 
   553 
   545 fun nasty_atp_proof pool =
   554 fun nasty_atp_proof pool =
   546   not (Symtab.is_empty pool) ? map_term_names_in_atp_proof (nasty_name pool)
   555   not (Symtab.is_empty pool) ? map_term_names_in_atp_proof (nasty_name pool)