64 \begin{readmore} |
63 \begin{readmore} |
65 To learn more about the function @{ML Goal.prove} see \isccite{sec:results} |
64 To learn more about the function @{ML Goal.prove} see \isccite{sec:results} |
66 and the file @{ML_file "Pure/goal.ML"}. See @{ML_file |
65 and the file @{ML_file "Pure/goal.ML"}. See @{ML_file |
67 "Pure/tactic.ML"} and @{ML_file "Pure/tctical.ML"} for the code of basic |
66 "Pure/tactic.ML"} and @{ML_file "Pure/tctical.ML"} for the code of basic |
68 tactics and tactic combinators; see also Chapters 3 and 4 in the old |
67 tactics and tactic combinators; see also Chapters 3 and 4 in the old |
69 Isabelle Reference Manual. |
68 Isabelle Reference Manual, and Chapter 3 in the Isabelle/Isar Implementation Manual. |
70 \end{readmore} |
69 \end{readmore} |
71 |
70 |
72 Note that in the code above we use antiquotations for referencing the theorems. Many theorems |
71 Note that in the code above we use antiquotations for referencing the theorems. Many theorems |
73 also have ML-bindings with the same name. Therefore, we could also just have |
72 also have ML-bindings with the same name. Therefore, we could also just have |
74 written @{ML "etac disjE 1"}, or in case where there are no ML-binding obtain |
73 written @{ML "etac disjE 1"}, or in case where there are no ML-binding obtain |
1009 |
1008 |
1010 section {* Simplifier Tactics *} |
1009 section {* Simplifier Tactics *} |
1011 |
1010 |
1012 text {* |
1011 text {* |
1013 A lot of convenience in the reasoning with Isabelle derives from its |
1012 A lot of convenience in the reasoning with Isabelle derives from its |
1014 powerful simplifier. The power of simplifier is at the same time a |
1013 powerful simplifier. The power of simplifier is a strength and a weakness at |
1015 strength and a weakness, because you can easily make the simplifier to |
1014 the same time, because you can easily make the simplifier to run into a loop and its |
1016 loop and its behaviour can sometimes be difficult to predict. There is also |
1015 behaviour can be difficult to predict. There is also a multitude |
1017 a multitude of options that configurate the behaviour of the simplifier. We |
1016 of options that you can configurate to control the behaviour of the simplifier. |
1018 describe some of them in this and the next section. |
1017 We describe some of them in this and the next section. |
1019 |
1018 |
1020 There are the following five main tactics behind |
1019 There are the following five main tactics behind |
1021 the simplifier (in parentheses is their user-level counterparts): |
1020 the simplifier (in parentheses is their user-level counterpart): |
1022 |
1021 |
1023 \begin{isabelle} |
1022 \begin{isabelle} |
1024 \begin{center} |
1023 \begin{center} |
1025 \begin{tabular}{l@ {\hspace{2cm}}l} |
1024 \begin{tabular}{l@ {\hspace{2cm}}l} |
1026 @{ML simp_tac} & @{text "(simp (no_asm))"} \\ |
1025 @{ML simp_tac} & @{text "(simp (no_asm))"} \\ |
1047 lemma "Suc (1 + 2) < 3 + 2" |
1046 lemma "Suc (1 + 2) < 3 + 2" |
1048 apply(tactic {* asm_full_simp_tac @{simpset} 1 *}) |
1047 apply(tactic {* asm_full_simp_tac @{simpset} 1 *}) |
1049 done |
1048 done |
1050 |
1049 |
1051 text {* |
1050 text {* |
1052 If the simplifier cannot make any progress, then it leaves the goal unchanged |
1051 If the simplifier cannot make any progress, then it leaves the goal unchanged, |
1053 and does not raise any error message. That means if you use it to unfold a definition |
1052 i.e.~does not raise any error message. That means if you use it to unfold a |
1054 for a constant and this constant is not present in a goal state, you can still |
1053 definition for a constant and this constant is not present in the goal state, |
1055 safely apply the simplifier. |
1054 you can still safely apply the simplifier. |
1056 |
1055 |
1057 When using the simplifier, the crucial information you have to control is |
1056 When using the simplifier, the crucial information you have to provide is |
1058 the simpset. If not handled with care, then the simplifier can easily run |
1057 the simpset. If this information is not handled with care, then the |
1059 into a loop. It might be surprising that a simpset is more complex than just a |
1058 simplifier can easily run into a loop. Therefore a good rule of thumb is to |
1060 simple collection of theorems used as simplification rules. One reason for |
1059 use simpsets that are as minimal as possible. It might be surprising that a |
1061 the complexity is that the simplifier must be able to rewrite inside terms |
1060 simpset is more complex than just a simple collection of theorems used as |
1062 and should also be able to rewrite according to rules that have |
1061 simplification rules. One reason for the complexity is that the simplifier |
1063 precoditions. |
1062 must be able to rewrite inside terms and should also be able to rewrite |
|
1063 according to rules that have precoditions. |
1064 |
1064 |
1065 |
1065 |
1066 The rewriting inside terms requires congruence rules, which |
1066 The rewriting inside terms requires congruence rules, which |
1067 are meta-equalities typical of the form |
1067 are meta-equalities typical of the form |
1068 |
1068 |
1069 \begin{isabelle} |
1069 \begin{isabelle} |
1070 \begin{center} |
1070 \begin{center} |
1071 \mbox{\inferrule{@{text "t\<^isub>i \<equiv> s\<^isub>i"}} |
1071 \mbox{\inferrule{@{text "t\<^isub>1 \<equiv> s\<^isub>1 \<dots> t\<^isub>n \<equiv> s\<^isub>n"}} |
1072 {@{text "constr t\<^isub>1\<dots>t\<^isub>n \<equiv> constr s\<^isub>1\<dots>s\<^isub>n"}}} |
1072 {@{text "constr t\<^isub>1\<dots>t\<^isub>n \<equiv> constr s\<^isub>1\<dots>s\<^isub>n"}}} |
1073 \end{center} |
1073 \end{center} |
1074 \end{isabelle} |
1074 \end{isabelle} |
1075 |
1075 |
1076 with @{text "constr"} being a term-constructor. Every simpset contains only |
1076 with @{text "constr"} being a term-constructor, like @{const "If"} or @{const "Let"}. |
|
1077 Every simpset contains only |
1077 one concruence rule for each term-constructor, which however can be |
1078 one concruence rule for each term-constructor, which however can be |
1078 overwritten. The user can declare lemmas to be congruence rules using the |
1079 overwritten. The user can declare lemmas to be congruence rules using the |
1079 attribute @{text "[cong]"}. In HOL, the user usually states these lemmas as |
1080 attribute @{text "[cong]"}. In HOL, the user usually states these lemmas as |
1080 equations, which are then internally transformed into meta-equations. |
1081 equations, which are then internally transformed into meta-equations. |
1081 |
1082 |
1082 |
1083 |
1083 The rewriting with rules involving preconditions requires what is in |
1084 The rewriting with rules involving preconditions requires what is in |
1084 Isabelle called a subgoaler, a solver and a looper. These can be arbitrary |
1085 Isabelle called a subgoaler, a solver and a looper. These can be arbitrary |
1085 tactics that can be installed in a simpset. However, simpsets also include |
1086 tactics that can be installed in a simpset and which are called during |
|
1087 various stages during simplification. However, simpsets also include |
1086 simprocs, which can produce rewrite rules on demand (see next |
1088 simprocs, which can produce rewrite rules on demand (see next |
1087 section). Another component are split-rules, which can simplify for example |
1089 section). Another component are split-rules, which can simplify for example |
1088 the ``then'' and ``else'' branches of if-statements under the corresponding |
1090 the ``then'' and ``else'' branches of if-statements under the corresponding |
1089 precoditions. |
1091 precoditions. |
|
1092 |
1090 |
1093 |
1091 \begin{readmore} |
1094 \begin{readmore} |
1092 For more information about the simplifier see @{ML_file "Pure/meta_simplifier.ML"} |
1095 For more information about the simplifier see @{ML_file "Pure/meta_simplifier.ML"} |
1093 and @{ML_file "Pure/simplifier.ML"}. The simplifier for HOL is set up in |
1096 and @{ML_file "Pure/simplifier.ML"}. The simplifier for HOL is set up in |
1094 @{ML_file "HOL/Tools/simpdata.ML"}. Generic splitters are implemented in |
1097 @{ML_file "HOL/Tools/simpdata.ML"}. Generic splitters are implemented in |
1160 \end{figure} *} |
1163 \end{figure} *} |
1161 |
1164 |
1162 text {* |
1165 text {* |
1163 To see how they work, consider the two functions in Figure~\ref{fig:prettyss}, which |
1166 To see how they work, consider the two functions in Figure~\ref{fig:prettyss}, which |
1164 print out some parts of a simpset. If you use them to print out the components of the |
1167 print out some parts of a simpset. If you use them to print out the components of the |
1165 empty simpset, the most primitive simpset |
1168 empty simpset, in ML @{ML empty_ss} and the most primitive simpset |
1166 |
1169 |
1167 @{ML_response_fake [display,gray] |
1170 @{ML_response_fake [display,gray] |
1168 "print_parts @{context} empty_ss" |
1171 "print_parts @{context} empty_ss" |
1169 "Simplification rules: |
1172 "Simplification rules: |
1170 Congruences rules:"} |
1173 Congruences rules:"} |
1175 *} |
1178 *} |
1176 |
1179 |
1177 ML{*val ss1 = empty_ss addsimps [@{thm Diff_Int} RS @{thm eq_reflection}] *} |
1180 ML{*val ss1 = empty_ss addsimps [@{thm Diff_Int} RS @{thm eq_reflection}] *} |
1178 |
1181 |
1179 text {* |
1182 text {* |
1180 Printing out the components of this simpset gives: |
1183 Printing then out the components of the simpset gives: |
1181 |
1184 |
1182 @{ML_response_fake [display,gray] |
1185 @{ML_response_fake [display,gray] |
1183 "print_parts @{context} ss1" |
1186 "print_parts @{context} ss1" |
1184 "Simplification rules: |
1187 "Simplification rules: |
1185 ??.unknown: A - B \<inter> C \<equiv> A - B \<union> (A - C) |
1188 ??.unknown: A - B \<inter> C \<equiv> A - B \<union> (A - C) |
1186 Congruences rules:"} |
1189 Congruences rules:"} |
1187 |
1190 |
1188 (FIXME: Why does it print out ??.unknown) |
1191 (FIXME: Why does it print out ??.unknown) |
1189 |
1192 |
1190 Adding the congruence rule @{thm [source] UN_cong} |
1193 Adding also the congruence rule @{thm [source] UN_cong} |
1191 *} |
1194 *} |
1192 |
1195 |
1193 ML{*val ss2 = ss1 addcongs [@{thm UN_cong} RS @{thm eq_reflection}] *} |
1196 ML{*val ss2 = ss1 addcongs [@{thm UN_cong} RS @{thm eq_reflection}] *} |
1194 |
1197 |
1195 text {* |
1198 text {* |
1202 Congruences rules: |
1205 Congruences rules: |
1203 UNION: \<lbrakk>A = B; \<And>x. x \<in> B \<Longrightarrow> C x = D x\<rbrakk> \<Longrightarrow> \<Union>x\<in>A. C x \<equiv> \<Union>x\<in>B. D x"} |
1206 UNION: \<lbrakk>A = B; \<And>x. x \<in> B \<Longrightarrow> C x = D x\<rbrakk> \<Longrightarrow> \<Union>x\<in>A. C x \<equiv> \<Union>x\<in>B. D x"} |
1204 |
1207 |
1205 Notice that we had to add these lemmas as meta-equations. The @{ML empty_ss} |
1208 Notice that we had to add these lemmas as meta-equations. The @{ML empty_ss} |
1206 expects this form of the simplification and congruence rules. However, even |
1209 expects this form of the simplification and congruence rules. However, even |
1207 adding these lemmas to @{ML empty_ss} we do not end up with anything useful yet. |
1210 when adding these lemmas to @{ML empty_ss} we do not end up with anything useful yet. |
1208 |
1211 |
1209 In the context of HOL the first useful simpset is @{ML HOL_basic_ss}. While |
1212 In the context of HOL, the first really useful simpset is @{ML HOL_basic_ss}. While |
1210 printing out the components of this simpset |
1213 printing out the components of this simpset |
1211 |
1214 |
1212 @{ML_response_fake [display,gray] |
1215 @{ML_response_fake [display,gray] |
1213 "print_parts @{context} HOL_basic_ss" |
1216 "print_parts @{context} HOL_basic_ss" |
1214 "Simplification rules: |
1217 "Simplification rules: |
1215 Congruences rules:"} |
1218 Congruences rules:"} |
1216 |
1219 |
1217 also produces ``nothing'', the printout is misleading. In fact |
1220 also produces ``nothing'', the printout is misleading. In fact |
1218 the simpset @{ML HOL_basic_ss} is setup so that it can be used to solve goals of the |
1221 the @{ML HOL_basic_ss} is setup so that it can solve goals of the |
1219 form @{thm TrueI}, @{thm refl[no_vars]}, @{term "t \<equiv> t"} and @{thm FalseE[no_vars]}, |
1222 form @{thm TrueI}, @{thm refl[no_vars]}, @{term "t \<equiv> t"} and @{thm FalseE[no_vars]}; |
1220 and resolve with assumptions. |
1223 and also resolve with assumptions. For example: |
1221 *} |
1224 *} |
1222 |
1225 |
1223 lemma |
1226 lemma |
1224 "True" and "t = t" and "t \<equiv> t" and "False \<Longrightarrow> Foo" and "\<lbrakk>A; B; C\<rbrakk> \<Longrightarrow> A" |
1227 "True" and "t = t" and "t \<equiv> t" and "False \<Longrightarrow> Foo" and "\<lbrakk>A; B; C\<rbrakk> \<Longrightarrow> A" |
1225 apply(tactic {* ALLGOALS (simp_tac HOL_basic_ss) *}) |
1228 apply(tactic {* ALLGOALS (simp_tac HOL_basic_ss) *}) |
1226 done |
1229 done |
1227 |
1230 |
1228 text {* |
1231 text {* |
1229 This is because how the tactics for the subgoaler, solver and looper are set |
1232 This behaviour is not because of simplification rules, but how the subgoaler, solver |
1230 up. |
1233 and looper are set up. @{ML HOL_basic_ss} is usually a good start to build your |
1231 |
1234 own simpsets, because of the low danger of causing loops via interacting simplifiction |
1232 The simpset @{ML HOL_ss}, which is an extention of @{ML HOL_basic_ss}, contains |
1235 rules. |
1233 already many useful simplification rules for the logical connectives in HOL. |
1236 |
|
1237 The simpset @{ML HOL_ss} is an extention of @{ML HOL_basic_ss} containing |
|
1238 already many useful simplification and congruence rules for the logical |
|
1239 connectives in HOL. |
1234 |
1240 |
1235 @{ML_response_fake [display,gray] |
1241 @{ML_response_fake [display,gray] |
1236 "print_parts @{context} HOL_ss" |
1242 "print_parts @{context} HOL_ss" |
1237 "Simplification rules: |
1243 "Simplification rules: |
1238 Pure.triv_forall_equality: (\<And>x. PROP V) \<equiv> PROP V |
1244 Pure.triv_forall_equality: (\<And>x. PROP V) \<equiv> PROP V |
1243 HOL.simp_implies: \<dots> |
1249 HOL.simp_implies: \<dots> |
1244 \<Longrightarrow> (PROP P =simp=> PROP Q) \<equiv> (PROP P' =simp=> PROP Q') |
1250 \<Longrightarrow> (PROP P =simp=> PROP Q) \<equiv> (PROP P' =simp=> PROP Q') |
1245 op -->: \<lbrakk>P \<equiv> P'; P' \<Longrightarrow> Q \<equiv> Q'\<rbrakk> \<Longrightarrow> P \<longrightarrow> Q \<equiv> P' \<longrightarrow> Q'"} |
1251 op -->: \<lbrakk>P \<equiv> P'; P' \<Longrightarrow> Q \<equiv> Q'\<rbrakk> \<Longrightarrow> P \<longrightarrow> Q \<equiv> P' \<longrightarrow> Q'"} |
1246 |
1252 |
1247 |
1253 |
1248 The main point of these simpsets is that they are small enough to |
1254 The simplifier is often used to unfold definitions in a proof. For this the |
1249 not cause any loops with most of the simplification rules that |
1255 simplifier contains the @{ML rewrite_goals_tac}. Suppose for example the |
1250 you might like to add. |
1256 definition |
|
1257 *} |
|
1258 |
|
1259 definition "MyTrue \<equiv> True" |
|
1260 |
|
1261 lemma shows "MyTrue \<Longrightarrow> True \<and> True" |
|
1262 apply(rule conjI) |
|
1263 apply(tactic {* rewrite_goals_tac [@{thm MyTrue_def}] *}) |
|
1264 txt{* then the tactic produces the goal state |
|
1265 |
|
1266 \begin{minipage}{\textwidth} |
|
1267 @{subgoals [display]} |
|
1268 \end{minipage} *} |
|
1269 (*<*)oops(*>*) |
|
1270 |
|
1271 text {* |
|
1272 As you can see, the tactic unfolds the definitions in all subgoals. |
1251 *} |
1273 *} |
1252 |
1274 |
1253 |
1275 |
1254 text_raw {* |
1276 text_raw {* |
1255 \begin{figure}[tp] |
1277 \begin{figure}[tp] |
1298 (FIXME: Uses old primrec.)} |
1319 (FIXME: Uses old primrec.)} |
1299 \end{figure} *} |
1320 \end{figure} *} |
1300 |
1321 |
1301 |
1322 |
1302 text {* |
1323 text {* |
1303 Often the situation arises that simplification rules will cause the |
1324 The simplifier is often used in order to bring terms into a normal form. |
1304 simplifier to run into an infinite loop. Consider for example the simple |
1325 Unfortunately, often the situation arises that the corresponding |
1305 theory about permutations shown in Figure~\ref{fig:perms}. The purpose of |
1326 simplification rules will cause the simplifier to run into an infinite |
1306 the lemmas is to pus permutations as far inside a term where they might |
1327 loop. Consider for example the simple theory about permutations over natural |
1307 disappear using the lemma @{thm [source] perm_rev}. However, to fully |
1328 numbers shown in Figure~\ref{fig:perms}. The purpose of the lemmas is to |
1308 simplifiy all instances, it would be desirable to add also the lemma @{thm |
1329 push permutations as far inside as possible, where they might disappear by |
1309 [source] perm_compose} to the simplifier in order to push permutations over |
1330 Lemma @{thm [source] perm_rev}. However, to fully normalise all instances, |
1310 other permutations. Unfortunately, the right-hand side of this lemma is |
1331 it would be desirable to add also the lemma @{thm [source] perm_compose} to |
1311 again an instance of the left-hand side and so causes an infinite |
1332 the simplifier for pushing permutations over other permutations. Unfortunately, |
1312 loop. On the user-level it is difficult to work around such situations |
1333 the right-hand side of this lemma is again an instance of the left-hand side |
1313 and we end up with clunky proofs such as: |
1334 and so causes an infinite loop. The seems to be no easy way to reformulate |
|
1335 this rule and so one ends up with clunky proofs like: |
1314 *} |
1336 *} |
1315 |
1337 |
1316 lemma |
1338 lemma |
1317 fixes c d::"nat" and pi\<^isub>1 pi\<^isub>2::"prm" |
1339 fixes c d::"nat" and pi\<^isub>1 pi\<^isub>2::"prm" |
1318 shows "pi\<^isub>1\<bullet>(c, pi\<^isub>2\<bullet>((rev pi\<^isub>1)\<bullet>d)) = (pi\<^isub>1\<bullet>c, (pi\<^isub>1\<bullet>pi\<^isub>2)\<bullet>d)" |
1340 shows "pi\<^isub>1\<bullet>(c, pi\<^isub>2\<bullet>((rev pi\<^isub>1)\<bullet>d)) = (pi\<^isub>1\<bullet>c, (pi\<^isub>1\<bullet>pi\<^isub>2)\<bullet>d)" |
1321 apply(rule perm_compose) |
1343 apply(rule perm_compose) |
1322 apply(simp) |
1344 apply(simp) |
1323 done |
1345 done |
1324 |
1346 |
1325 text {* |
1347 text {* |
1326 On the ML-level, we can however generate a single simplifier tactic that solves |
1348 It is however possible to create a single simplifier tactic that solves |
1327 such proofs. The trick is to introduce an auxiliary constant for permutations |
1349 such proofs. The trick is to introduce an auxiliary constant for permutations |
1328 and split the simplification into two phases. Let us say the auxiliary constant is |
1350 and split the simplification into two phases (below actually three). Let |
|
1351 assume the auxiliary constant is |
1329 *} |
1352 *} |
1330 |
1353 |
1331 definition |
1354 definition |
1332 perm_aux :: "prm \<Rightarrow> 'a \<Rightarrow> 'a" ("_ \<bullet>aux _" [80,80] 80) |
1355 perm_aux :: "prm \<Rightarrow> 'a \<Rightarrow> 'a" ("_ \<bullet>aux _" [80,80] 80) |
1333 where |
1356 where |
1334 "pi \<bullet>aux c \<equiv> pi \<bullet> c" |
1357 "pi \<bullet>aux c \<equiv> pi \<bullet> c" |
1335 |
1358 |
1336 text {* Now the lemmas *} |
1359 text {* Now the two lemmas *} |
1337 |
1360 |
1338 lemma perm_aux_expand: |
1361 lemma perm_aux_expand: |
1339 fixes c::"nat" and pi\<^isub>1 pi\<^isub>2::"prm" |
1362 fixes c::"nat" and pi\<^isub>1 pi\<^isub>2::"prm" |
1340 shows "pi\<^isub>1\<bullet>(pi\<^isub>2\<bullet>c) = pi\<^isub>1 \<bullet>aux (pi\<^isub>2\<bullet>c)" |
1363 shows "pi\<^isub>1\<bullet>(pi\<^isub>2\<bullet>c) = pi\<^isub>1 \<bullet>aux (pi\<^isub>2\<bullet>c)" |
1341 unfolding perm_aux_def by (rule refl) |
1364 unfolding perm_aux_def by (rule refl) |
1347 |
1370 |
1348 text {* |
1371 text {* |
1349 are simple consequence of the definition and @{thm [source] perm_compose}. |
1372 are simple consequence of the definition and @{thm [source] perm_compose}. |
1350 More importantly, the lemma @{thm [source] perm_compose_aux} can be safely |
1373 More importantly, the lemma @{thm [source] perm_compose_aux} can be safely |
1351 added to the simplifier, because now the right-hand side is not anymore an instance |
1374 added to the simplifier, because now the right-hand side is not anymore an instance |
1352 of the left-hand side. So you can write |
1375 of the left-hand side. In a sense it freezes all redexes of permutation compositions |
|
1376 after one step. In this way, we can split simplification of permutations |
|
1377 into three phases without the user not noticing anything about the auxiliary |
|
1378 contant. We first freeze any instance of permutation compositions in the term using |
|
1379 lemma @{thm [source] "perm_aux_expand"} (Line 9); |
|
1380 then simplifiy all other permutations including pusing permutations over |
|
1381 other permutations by rule @{thm [source] perm_compose_aux} (Line 10); and |
|
1382 finally ``unfreeze'' all instances of permutation compositions by unfolding |
|
1383 the definition of the auxiliary constant. |
1353 *} |
1384 *} |
1354 |
1385 |
1355 ML %linenosgray{*val perm_simp_tac = |
1386 ML %linenosgray{*val perm_simp_tac = |
1356 let |
1387 let |
1357 val thms1 = [@{thm perm_aux_expand}] |
1388 val thms1 = [@{thm perm_aux_expand}] |
1364 THEN' simp_tac (HOL_basic_ss addsimps thms2) |
1395 THEN' simp_tac (HOL_basic_ss addsimps thms2) |
1365 THEN' simp_tac (HOL_basic_ss addsimps thms3) |
1396 THEN' simp_tac (HOL_basic_ss addsimps thms3) |
1366 end*} |
1397 end*} |
1367 |
1398 |
1368 text {* |
1399 text {* |
1369 This trick is not noticable for the user. |
1400 For all three phases we have to build simpsets addig specific lemmas. As is sufficient |
|
1401 for our purposes here, we can add these lemma to @{ML HOL_basic_ss} in order to obtain |
|
1402 the desired results. Now we can solve the following lemma |
1370 *} |
1403 *} |
1371 |
1404 |
1372 lemma |
1405 lemma |
1373 fixes c d::"nat" and pi\<^isub>1 pi\<^isub>2::"prm" |
1406 fixes c d::"nat" and pi\<^isub>1 pi\<^isub>2::"prm" |
1374 shows "pi\<^isub>1\<bullet>(c, pi\<^isub>2\<bullet>((rev pi\<^isub>1)\<bullet>d)) = (pi\<^isub>1\<bullet>c, (pi\<^isub>1\<bullet>pi\<^isub>2)\<bullet>d)" |
1407 shows "pi\<^isub>1\<bullet>(c, pi\<^isub>2\<bullet>((rev pi\<^isub>1)\<bullet>d)) = (pi\<^isub>1\<bullet>c, (pi\<^isub>1\<bullet>pi\<^isub>2)\<bullet>d)" |
1375 apply(tactic {* perm_simp_tac 1 *}) |
1408 apply(tactic {* perm_simp_tac 1 *}) |
1376 done |
1409 done |
1377 |
1410 |
1378 |
1411 |
1379 text {* |
1412 text {* |
|
1413 in one step. This tactic can deal with most instances of normalising permutations; |
|
1414 in order to solve all cases we have to deal with corner-cases such as the |
|
1415 lemma being an exact instance of the permutation composition lemma. This can |
|
1416 often be done easier by implementing a simproc or a conversion. Both will be |
|
1417 explained in the next two chapters. |
|
1418 |
1380 (FIXME: Is it interesting to say something about @{term "op =simp=>"}?) |
1419 (FIXME: Is it interesting to say something about @{term "op =simp=>"}?) |
1381 |
1420 |
1382 (FIXME: Unfortunately one cannot access any simproc, as there is |
1421 (FIXME: Unfortunately one cannot access any simproc, as there is |
1383 no @{text rep_proc} in function @{ML get_parts}.) |
1422 no @{text rep_proc} in function @{ML get_parts}.) |
1384 |
1423 |
1385 (FIXME: What are the second components of the congruence rules---something to |
1424 (FIXME: What are the second components of the congruence rules---something to |
1386 do with weak congruence constants?) |
1425 do with weak congruence constants?) |
1387 |
1426 |
1388 (FIXME: Anything interesting to say about @{ML Simplifier.clear_ss}?) |
1427 (FIXME: Anything interesting to say about @{ML Simplifier.clear_ss}?) |
1389 |
1428 |
1390 (FIXME: @{ML rewrite_goals_tac}, @{ML ObjectLogic.full_atomize_tac}, |
1429 (FIXME: @{ML ObjectLogic.full_atomize_tac}, |
1391 @{ML ObjectLogic.rulify_tac}) |
1430 @{ML ObjectLogic.rulify_tac}) |
1392 |
1431 |
1393 *} |
1432 *} |
1394 |
1433 |
1395 section {* Simprocs *} |
1434 section {* Simprocs *} |