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") -- $$ "(") |
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, |
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 |