| author | wenzelm | 
| Sun, 05 Sep 2021 23:21:32 +0200 | |
| changeset 74240 | 36774e8af3db | 
| parent 74183 | af81e4a307be | 
| child 74262 | 839a6e284545 | 
| permissions | -rw-r--r-- | 
| 6778 | 1 | (* Title: Pure/Isar/calculation.ML | 
| 2 | Author: Markus Wenzel, TU Muenchen | |
| 3 | ||
| 17350 
26cd3756377a
more self-contained proof elements (material from isar_thy.ML);
 wenzelm parents: 
16571diff
changeset | 4 | Generic calculational proofs. | 
| 6778 | 5 | *) | 
| 6 | ||
| 7 | signature CALCULATION = | |
| 8 | sig | |
| 21506 | 9 | val print_rules: Proof.context -> unit | 
| 63543 | 10 | val check: Proof.state -> thm list option | 
| 18728 | 11 | val trans_add: attribute | 
| 12 | val trans_del: attribute | |
| 13 | val sym_add: attribute | |
| 14 | val sym_del: attribute | |
| 15 | val symmetric: attribute | |
| 49868 
3039922ffd8d
more informative errors for 'also' and 'finally';
 wenzelm parents: 
45375diff
changeset | 16 | val also: thm list option -> bool -> Proof.state -> Proof.state Seq.result Seq.seq | 
| 58011 
bc6bced136e5
tuned signature -- moved type src to Token, without aliases;
 wenzelm parents: 
56894diff
changeset | 17 | val also_cmd: (Facts.ref * Token.src list) list option -> | 
| 49868 
3039922ffd8d
more informative errors for 'also' and 'finally';
 wenzelm parents: 
45375diff
changeset | 18 | bool -> Proof.state -> Proof.state Seq.result Seq.seq | 
| 
3039922ffd8d
more informative errors for 'also' and 'finally';
 wenzelm parents: 
45375diff
changeset | 19 | val finally: thm list option -> bool -> Proof.state -> Proof.state Seq.result Seq.seq | 
| 58011 
bc6bced136e5
tuned signature -- moved type src to Token, without aliases;
 wenzelm parents: 
56894diff
changeset | 20 | val finally_cmd: (Facts.ref * Token.src list) list option -> bool -> | 
| 49868 
3039922ffd8d
more informative errors for 'also' and 'finally';
 wenzelm parents: 
45375diff
changeset | 21 | Proof.state -> Proof.state Seq.result Seq.seq | 
| 17350 
26cd3756377a
more self-contained proof elements (material from isar_thy.ML);
 wenzelm parents: 
16571diff
changeset | 22 | val moreover: bool -> Proof.state -> Proof.state | 
| 
26cd3756377a
more self-contained proof elements (material from isar_thy.ML);
 wenzelm parents: 
16571diff
changeset | 23 | val ultimately: bool -> Proof.state -> Proof.state | 
| 6778 | 24 | end; | 
| 25 | ||
| 26 | structure Calculation: CALCULATION = | |
| 27 | struct | |
| 28 | ||
| 18637 | 29 | (** calculation data **) | 
| 6778 | 30 | |
| 63543 | 31 | type calculation = {result: thm list, level: int, serial: serial, pos: Position.T};
 | 
| 32 | ||
| 37047 
4a95a50d0ec4
print calculation result in the context where the fact is actually defined -- proper externing;
 wenzelm parents: 
36323diff
changeset | 33 | structure Data = Generic_Data | 
| 18637 | 34 | ( | 
| 74149 | 35 | type T = (thm Item_Net.T * thm Item_Net.T) * calculation option; | 
| 74152 | 36 | val empty = ((Thm.item_net_elim, Thm.item_net), NONE); | 
| 18637 | 37 | val extend = I; | 
| 33519 | 38 | fun merge (((trans1, sym1), _), ((trans2, sym2), _)) = | 
| 74149 | 39 | ((Item_Net.merge (trans1, trans2), Item_Net.merge (sym1, sym2)), NONE); | 
| 18637 | 40 | ); | 
| 41 | ||
| 38332 
6551e310e7cb
prefer plain Attrib.eval_thmss -- also means the assert_forward of Proof.get_thmss_cmd is skipped, leading to uniform (albeit odd) behaviour concerning forward chaining;
 wenzelm parents: 
37047diff
changeset | 42 | val get_rules = #1 o Data.get o Context.Proof; | 
| 74149 | 43 | val get_trans_rules = Item_Net.content o #1 o get_rules; | 
| 44 | val get_sym_rules = Item_Net.content o #2 o get_rules; | |
| 63543 | 45 | val get_calculation = #2 o Data.get o Context.Proof; | 
| 38332 
6551e310e7cb
prefer plain Attrib.eval_thmss -- also means the assert_forward of Proof.get_thmss_cmd is skipped, leading to uniform (albeit odd) behaviour concerning forward chaining;
 wenzelm parents: 
37047diff
changeset | 46 | |
| 22846 | 47 | fun print_rules ctxt = | 
| 74149 | 48 | let val pretty_thm = Thm.pretty_thm_item ctxt in | 
| 49 | [Pretty.big_list "transitivity rules:" (map pretty_thm (get_trans_rules ctxt)), | |
| 50 | Pretty.big_list "symmetry rules:" (map pretty_thm (get_sym_rules ctxt))] | |
| 56334 
6b3739fee456
some shortcuts for chunks, which sometimes avoid bulky string output;
 wenzelm parents: 
55141diff
changeset | 51 | end |> Pretty.writeln_chunks; | 
| 6778 | 52 | |
| 53 | ||
| 54 | (* access calculation *) | |
| 55 | ||
| 63543 | 56 | fun check_calculation state = | 
| 57 | (case get_calculation (Proof.context_of state) of | |
| 15531 | 58 | NONE => NONE | 
| 63543 | 59 | | SOME calculation => | 
| 60 | if #level calculation = Proof.level state then SOME calculation else NONE); | |
| 61 | ||
| 62 | val check = Option.map #result o check_calculation; | |
| 6778 | 63 | |
| 17350 
26cd3756377a
more self-contained proof elements (material from isar_thy.ML);
 wenzelm parents: 
16571diff
changeset | 64 | val calculationN = "calculation"; | 
| 6778 | 65 | |
| 63543 | 66 | fun update_calculation calc state = | 
| 67 | let | |
| 68 | fun report def serial pos = | |
| 69 | Context_Position.report (Proof.context_of state) | |
| 70 | (Position.thread_data ()) | |
| 74183 | 71 |         (Position.make_entity_markup def serial calculationN ("", pos));
 | 
| 63543 | 72 | val calculation = | 
| 73 | (case calc of | |
| 74 | NONE => NONE | |
| 75 | | SOME result => | |
| 76 | (case check_calculation state of | |
| 77 | NONE => | |
| 78 | let | |
| 79 | val level = Proof.level state; | |
| 80 | val serial = serial (); | |
| 81 | val pos = Position.thread_data (); | |
| 82 | val _ = report true serial pos; | |
| 83 |               in SOME {result = result, level = level, serial = serial, pos = pos} end
 | |
| 84 |           | SOME {level, serial, pos, ...} =>
 | |
| 85 | (report false serial pos; | |
| 86 |                 SOME {result = result, level = level, serial = serial, pos = pos})));
 | |
| 87 | in | |
| 88 | state | |
| 89 | |> (Proof.map_context o Context.proof_map o Data.map o apsnd) (K calculation) | |
| 90 | |> Proof.map_context (Proof_Context.put_thms false (calculationN, calc)) | |
| 91 | end; | |
| 6778 | 92 | |
| 93 | ||
| 18637 | 94 | |
| 6778 | 95 | (** attributes **) | 
| 96 | ||
| 12379 | 97 | (* add/del rules *) | 
| 98 | ||
| 67627 | 99 | val trans_add = | 
| 100 | Thm.declaration_attribute (Data.map o apfst o apfst o Item_Net.update o Thm.trim_context); | |
| 101 | ||
| 102 | val trans_del = | |
| 103 | Thm.declaration_attribute (Data.map o apfst o apfst o Item_Net.remove); | |
| 6778 | 104 | |
| 18637 | 105 | val sym_add = | 
| 45375 
7fe19930dfc9
more explicit representation of rule_attribute vs. declaration_attribute vs. mixed_attribute;
 wenzelm parents: 
42360diff
changeset | 106 | Thm.declaration_attribute (fn th => | 
| 74149 | 107 | (Data.map o apfst o apsnd) (Item_Net.update (Thm.trim_context th)) #> | 
| 45375 
7fe19930dfc9
more explicit representation of rule_attribute vs. declaration_attribute vs. mixed_attribute;
 wenzelm parents: 
42360diff
changeset | 108 | Thm.attribute_declaration (Context_Rules.elim_query NONE) th); | 
| 33369 | 109 | |
| 18637 | 110 | val sym_del = | 
| 45375 
7fe19930dfc9
more explicit representation of rule_attribute vs. declaration_attribute vs. mixed_attribute;
 wenzelm parents: 
42360diff
changeset | 111 | Thm.declaration_attribute (fn th => | 
| 74149 | 112 | (Data.map o apfst o apsnd) (Item_Net.remove th) #> | 
| 45375 
7fe19930dfc9
more explicit representation of rule_attribute vs. declaration_attribute vs. mixed_attribute;
 wenzelm parents: 
42360diff
changeset | 113 | Thm.attribute_declaration Context_Rules.rule_del th); | 
| 12379 | 114 | |
| 115 | ||
| 18637 | 116 | (* symmetric *) | 
| 12379 | 117 | |
| 61853 
fb7756087101
rule_attribute and declaration_attribute implicitly support abstract closure, but mixed_attribute implementations need to be aware of Thm.is_free_dummy;
 wenzelm parents: 
61268diff
changeset | 118 | val symmetric = | 
| 
fb7756087101
rule_attribute and declaration_attribute implicitly support abstract closure, but mixed_attribute implementations need to be aware of Thm.is_free_dummy;
 wenzelm parents: 
61268diff
changeset | 119 | Thm.rule_attribute [] (fn context => fn th => | 
| 74149 | 120 | let val ctxt = Context.proof_of context in | 
| 121 | (case Seq.chop 2 (Drule.multi_resolves (SOME ctxt) [th] (get_sym_rules ctxt)) of | |
| 122 | ([th'], _) => Drule.zero_var_indexes th' | |
| 123 |       | ([], _) => raise THM ("symmetric: no unifiers", 1, [th])
 | |
| 124 |       | _ => raise THM ("symmetric: multiple unifiers", 1, [th]))
 | |
| 125 | end); | |
| 12379 | 126 | |
| 6778 | 127 | |
| 128 | (* concrete syntax *) | |
| 129 | ||
| 53171 | 130 | val _ = Theory.setup | 
| 67147 | 131 | (Attrib.setup \<^binding>\<open>trans\<close> (Attrib.add_del trans_add trans_del) | 
| 30528 | 132 | "declaration of transitivity rule" #> | 
| 67147 | 133 | Attrib.setup \<^binding>\<open>sym\<close> (Attrib.add_del sym_add sym_del) | 
| 30528 | 134 | "declaration of symmetry rule" #> | 
| 67147 | 135 | Attrib.setup \<^binding>\<open>symmetric\<close> (Scan.succeed symmetric) | 
| 30528 | 136 | "resolution with symmetry rule" #> | 
| 39557 
fe5722fce758
renamed structure PureThy to Pure_Thy and moved most content to Global_Theory, to emphasize that this is global-only;
 wenzelm parents: 
38332diff
changeset | 137 | Global_Theory.add_thms | 
| 29579 | 138 | [((Binding.empty, transitive_thm), [trans_add]), | 
| 53171 | 139 | ((Binding.empty, symmetric_thm), [sym_add])] #> snd); | 
| 15801 | 140 | |
| 6778 | 141 | |
| 6787 | 142 | |
| 6778 | 143 | (** proof commands **) | 
| 144 | ||
| 14555 
341908d6c792
'also'/'moreover': do not interfere with current facts, allow in chain mode;
 wenzelm parents: 
14549diff
changeset | 145 | fun assert_sane final = | 
| 59126 | 146 | if final then Proof.assert_forward | 
| 147 | else | |
| 148 | Proof.assert_forward_or_chain #> | |
| 149 | tap (fn state => | |
| 150 | if can Proof.assert_chain state then | |
| 151 | Context_Position.report (Proof.context_of state) (Position.thread_data ()) Markup.improper | |
| 152 | else ()); | |
| 14555 
341908d6c792
'also'/'moreover': do not interfere with current facts, allow in chain mode;
 wenzelm parents: 
14549diff
changeset | 153 | |
| 37047 
4a95a50d0ec4
print calculation result in the context where the fact is actually defined -- proper externing;
 wenzelm parents: 
36323diff
changeset | 154 | fun maintain_calculation int final calc state = | 
| 
4a95a50d0ec4
print calculation result in the context where the fact is actually defined -- proper externing;
 wenzelm parents: 
36323diff
changeset | 155 | let | 
| 63541 | 156 | val state' = state | 
| 63543 | 157 | |> update_calculation (SOME calc) | 
| 63541 | 158 | |> Proof.improper_reset_facts; | 
| 37047 
4a95a50d0ec4
print calculation result in the context where the fact is actually defined -- proper externing;
 wenzelm parents: 
36323diff
changeset | 159 | val ctxt' = Proof.context_of state'; | 
| 
4a95a50d0ec4
print calculation result in the context where the fact is actually defined -- proper externing;
 wenzelm parents: 
36323diff
changeset | 160 | val _ = | 
| 
4a95a50d0ec4
print calculation result in the context where the fact is actually defined -- proper externing;
 wenzelm parents: 
36323diff
changeset | 161 | if int then | 
| 56894 | 162 | Proof_Context.pretty_fact ctxt' | 
| 163 | (Proof_Context.full_name ctxt' (Binding.name calculationN), calc) | |
| 58843 | 164 | |> Pretty.string_of |> writeln | 
| 37047 
4a95a50d0ec4
print calculation result in the context where the fact is actually defined -- proper externing;
 wenzelm parents: 
36323diff
changeset | 165 | else (); | 
| 63543 | 166 | in state' |> final ? (update_calculation NONE #> Proof.chain_facts calc) end; | 
| 8562 | 167 | |
| 168 | ||
| 17350 
26cd3756377a
more self-contained proof elements (material from isar_thy.ML);
 wenzelm parents: 
16571diff
changeset | 169 | (* also and finally *) | 
| 8562 | 170 | |
| 17350 
26cd3756377a
more self-contained proof elements (material from isar_thy.ML);
 wenzelm parents: 
16571diff
changeset | 171 | fun calculate prep_rules final raw_rules int state = | 
| 6778 | 172 | let | 
| 38332 
6551e310e7cb
prefer plain Attrib.eval_thmss -- also means the assert_forward of Proof.get_thmss_cmd is skipped, leading to uniform (albeit odd) behaviour concerning forward chaining;
 wenzelm parents: 
37047diff
changeset | 173 | val ctxt = Proof.context_of state; | 
| 61268 | 174 | val pretty_thm = Thm.pretty_thm ctxt; | 
| 175 | val pretty_thm_item = Thm.pretty_thm_item ctxt; | |
| 38332 
6551e310e7cb
prefer plain Attrib.eval_thmss -- also means the assert_forward of Proof.get_thmss_cmd is skipped, leading to uniform (albeit odd) behaviour concerning forward chaining;
 wenzelm parents: 
37047diff
changeset | 176 | |
| 12805 | 177 | val strip_assums_concl = Logic.strip_assums_concl o Thm.prop_of; | 
| 59058 
a78612c67ec0
renamed "pairself" to "apply2", in accordance to @{apply 2};
 wenzelm parents: 
58950diff
changeset | 178 | val eq_prop = op aconv o apply2 (Envir.beta_eta_contract o strip_assums_concl); | 
| 49868 
3039922ffd8d
more informative errors for 'also' and 'finally';
 wenzelm parents: 
45375diff
changeset | 179 | fun check_projection ths th = | 
| 
3039922ffd8d
more informative errors for 'also' and 'finally';
 wenzelm parents: 
45375diff
changeset | 180 | (case find_index (curry eq_prop th) ths of | 
| 
3039922ffd8d
more informative errors for 'also' and 'finally';
 wenzelm parents: 
45375diff
changeset | 181 | ~1 => Seq.Result [th] | 
| 
3039922ffd8d
more informative errors for 'also' and 'finally';
 wenzelm parents: 
45375diff
changeset | 182 | | i => | 
| 
3039922ffd8d
more informative errors for 'also' and 'finally';
 wenzelm parents: 
45375diff
changeset | 183 | Seq.Error (fn () => | 
| 
3039922ffd8d
more informative errors for 'also' and 'finally';
 wenzelm parents: 
45375diff
changeset | 184 | (Pretty.string_of o Pretty.chunks) | 
| 
3039922ffd8d
more informative errors for 'also' and 'finally';
 wenzelm parents: 
45375diff
changeset | 185 | [Pretty.block [Pretty.str "Vacuous calculation result:", Pretty.brk 1, pretty_thm th], | 
| 
3039922ffd8d
more informative errors for 'also' and 'finally';
 wenzelm parents: 
45375diff
changeset | 186 | (Pretty.block o Pretty.fbreaks) | 
| 
3039922ffd8d
more informative errors for 'also' and 'finally';
 wenzelm parents: 
45375diff
changeset | 187 |                 (Pretty.str ("derived as projection (" ^ string_of_int (i + 1) ^ ") from:") ::
 | 
| 51584 | 188 | map pretty_thm_item ths)])); | 
| 8300 | 189 | |
| 38332 
6551e310e7cb
prefer plain Attrib.eval_thmss -- also means the assert_forward of Proof.get_thmss_cmd is skipped, leading to uniform (albeit odd) behaviour concerning forward chaining;
 wenzelm parents: 
37047diff
changeset | 190 | val opt_rules = Option.map (prep_rules ctxt) raw_rules; | 
| 11097 | 191 | fun combine ths = | 
| 49868 
3039922ffd8d
more informative errors for 'also' and 'finally';
 wenzelm parents: 
45375diff
changeset | 192 | Seq.append | 
| 
3039922ffd8d
more informative errors for 'also' and 'finally';
 wenzelm parents: 
45375diff
changeset | 193 | ((case opt_rules of | 
| 
3039922ffd8d
more informative errors for 'also' and 'finally';
 wenzelm parents: 
45375diff
changeset | 194 | SOME rules => rules | 
| 
3039922ffd8d
more informative errors for 'also' and 'finally';
 wenzelm parents: 
45375diff
changeset | 195 | | NONE => | 
| 
3039922ffd8d
more informative errors for 'also' and 'finally';
 wenzelm parents: 
45375diff
changeset | 196 | (case ths of | 
| 
3039922ffd8d
more informative errors for 'also' and 'finally';
 wenzelm parents: 
45375diff
changeset | 197 | [] => Item_Net.content (#1 (get_rules ctxt)) | 
| 
3039922ffd8d
more informative errors for 'also' and 'finally';
 wenzelm parents: 
45375diff
changeset | 198 | | th :: _ => Item_Net.retrieve (#1 (get_rules ctxt)) (strip_assums_concl th))) | 
| 58950 
d07464875dd4
optional proof context for unify operations, for the sake of proper local options;
 wenzelm parents: 
58893diff
changeset | 199 | |> Seq.of_list |> Seq.maps (Drule.multi_resolve (SOME ctxt) ths) | 
| 49868 
3039922ffd8d
more informative errors for 'also' and 'finally';
 wenzelm parents: 
45375diff
changeset | 200 | |> Seq.map (check_projection ths)) | 
| 
3039922ffd8d
more informative errors for 'also' and 'finally';
 wenzelm parents: 
45375diff
changeset | 201 | (Seq.single (Seq.Error (fn () => | 
| 
3039922ffd8d
more informative errors for 'also' and 'finally';
 wenzelm parents: 
45375diff
changeset | 202 | (Pretty.string_of o Pretty.block o Pretty.fbreaks) | 
| 
3039922ffd8d
more informative errors for 'also' and 'finally';
 wenzelm parents: 
45375diff
changeset | 203 | (Pretty.str "No matching trans rules for calculation:" :: | 
| 51584 | 204 | map pretty_thm_item ths)))); | 
| 7414 | 205 | |
| 14555 
341908d6c792
'also'/'moreover': do not interfere with current facts, allow in chain mode;
 wenzelm parents: 
14549diff
changeset | 206 | val facts = Proof.the_facts (assert_sane final state); | 
| 6903 | 207 | val (initial, calculations) = | 
| 63543 | 208 | (case check state of | 
| 49868 
3039922ffd8d
more informative errors for 'also' and 'finally';
 wenzelm parents: 
45375diff
changeset | 209 | NONE => (true, Seq.single (Seq.Result facts)) | 
| 
3039922ffd8d
more informative errors for 'also' and 'finally';
 wenzelm parents: 
45375diff
changeset | 210 | | SOME calc => (false, combine (calc @ facts))); | 
| 37047 
4a95a50d0ec4
print calculation result in the context where the fact is actually defined -- proper externing;
 wenzelm parents: 
36323diff
changeset | 211 | |
| 
4a95a50d0ec4
print calculation result in the context where the fact is actually defined -- proper externing;
 wenzelm parents: 
36323diff
changeset | 212 | val _ = initial andalso final andalso error "No calculation yet"; | 
| 
4a95a50d0ec4
print calculation result in the context where the fact is actually defined -- proper externing;
 wenzelm parents: 
36323diff
changeset | 213 | val _ = initial andalso is_some opt_rules andalso | 
| 
4a95a50d0ec4
print calculation result in the context where the fact is actually defined -- proper externing;
 wenzelm parents: 
36323diff
changeset | 214 | error "Initial calculation -- no rules to be given"; | 
| 6778 | 215 | in | 
| 49868 
3039922ffd8d
more informative errors for 'also' and 'finally';
 wenzelm parents: 
45375diff
changeset | 216 | calculations |> Seq.map_result (fn calc => maintain_calculation int final calc state) | 
| 6778 | 217 | end; | 
| 218 | ||
| 36323 
655e2d74de3a
modernized naming conventions of main Isar proof elements;
 wenzelm parents: 
33519diff
changeset | 219 | val also = calculate (K I) false; | 
| 38332 
6551e310e7cb
prefer plain Attrib.eval_thmss -- also means the assert_forward of Proof.get_thmss_cmd is skipped, leading to uniform (albeit odd) behaviour concerning forward chaining;
 wenzelm parents: 
37047diff
changeset | 220 | val also_cmd = calculate Attrib.eval_thms false; | 
| 36323 
655e2d74de3a
modernized naming conventions of main Isar proof elements;
 wenzelm parents: 
33519diff
changeset | 221 | val finally = calculate (K I) true; | 
| 38332 
6551e310e7cb
prefer plain Attrib.eval_thmss -- also means the assert_forward of Proof.get_thmss_cmd is skipped, leading to uniform (albeit odd) behaviour concerning forward chaining;
 wenzelm parents: 
37047diff
changeset | 222 | val finally_cmd = calculate Attrib.eval_thms true; | 
| 6778 | 223 | |
| 224 | ||
| 17350 
26cd3756377a
more self-contained proof elements (material from isar_thy.ML);
 wenzelm parents: 
16571diff
changeset | 225 | (* moreover and ultimately *) | 
| 8562 | 226 | |
| 17350 
26cd3756377a
more self-contained proof elements (material from isar_thy.ML);
 wenzelm parents: 
16571diff
changeset | 227 | fun collect final int state = | 
| 8588 | 228 | let | 
| 14555 
341908d6c792
'also'/'moreover': do not interfere with current facts, allow in chain mode;
 wenzelm parents: 
14549diff
changeset | 229 | val facts = Proof.the_facts (assert_sane final state); | 
| 8588 | 230 | val (initial, thms) = | 
| 63543 | 231 | (case check state of | 
| 15531 | 232 | NONE => (true, []) | 
| 233 | | SOME thms => (false, thms)); | |
| 8588 | 234 | val calc = thms @ facts; | 
| 37047 
4a95a50d0ec4
print calculation result in the context where the fact is actually defined -- proper externing;
 wenzelm parents: 
36323diff
changeset | 235 | val _ = initial andalso final andalso error "No calculation yet"; | 
| 
4a95a50d0ec4
print calculation result in the context where the fact is actually defined -- proper externing;
 wenzelm parents: 
36323diff
changeset | 236 | in maintain_calculation int final calc state end; | 
| 8588 | 237 | |
| 17350 
26cd3756377a
more self-contained proof elements (material from isar_thy.ML);
 wenzelm parents: 
16571diff
changeset | 238 | val moreover = collect false; | 
| 
26cd3756377a
more self-contained proof elements (material from isar_thy.ML);
 wenzelm parents: 
16571diff
changeset | 239 | val ultimately = collect true; | 
| 8562 | 240 | |
| 6778 | 241 | end; |