CookBook/Tactical.thy
changeset 143 f7cf072e72d6
parent 142 c06885c36575
child 145 f1ba430a5e7d
equal deleted inserted replaced
138:e4d8dfb7e34a 143:f7cf072e72d6
     1 theory Tactical
     1 theory Tactical
     2 imports Base FirstSteps
     2 imports Base FirstSteps
       
     3 uses "infix_conv.ML"
     3 begin
     4 begin
     4 
     5 
     5 chapter {* Tactical Reasoning\label{chp:tactical} *}
     6 chapter {* Tactical Reasoning\label{chp:tactical} *}
     6 
     7 
     7 text {*
     8 text {*
  1315 *}
  1316 *}
  1316 
  1317 
  1317 section {* Conversions\label{sec:conversion} *}
  1318 section {* Conversions\label{sec:conversion} *}
  1318 
  1319 
  1319 text {*
  1320 text {*
  1320 conversions: core of the simplifier
  1321 Conversions are meta-equalities depending on some input term. Their type is
  1321 
  1322 as follows:
  1322 see: Pure/conv.ML
  1323 *}
  1323 *}
  1324 
  1324 
  1325 ML {*type conv = Thm.cterm -> Thm.thm*}
  1325 ML {* type conv = Thm.cterm -> Thm.thm *}
  1326 
  1326 
  1327 text {*
  1327 text {*
  1328 The simplest two conversions are @{ML "Conv.all_conv"}, which maps a term to an instance of the reflexivity theorem, and @{ML "Conv.no_conv"}, which always fails:
  1328 simple example:
  1329 
  1329 *}
  1330 @{ML_response_fake "Conv.all_conv @{cterm True}" "True \<equiv> True"}
  1330 
  1331 
  1331 lemma true_conj_1: "True \<and> P \<equiv> P" by simp
  1332 @{ML_response_fake "Conv.no_conv @{cterm True}" "*** Exception- CTERM (\"no conversion\", []) raised"}
  1332 
  1333 
  1333 ML {*
  1334 A further basic conversion is, for example, @{ML "Thm.beta_conversion"}:
  1334 val true1_conv = Conv.rewr_conv @{thm true_conj_1}
  1335 
  1335 *}
  1336 @{ML_response_fake "Thm.beta_conversion true @{cterm \"(\<lambda>x. x \<or> False) True\"}"
  1336 
  1337 "(\<lambda>x. x \<or> False) True \<equiv> True \<or> False"}
  1337 ML {*
  1338 
  1338 true1_conv @{cterm "True \<and> False"}
  1339 User-defined rewrite rules can be applied by the conversion
  1339 *}
  1340 @{ML "Conv.rewr_conv"}. Consider, for example, the following rule:
  1340 
  1341 *}
  1341 text {*
  1342 
  1342 @{ML_response_fake "true1_conv @{cterm \"True \<and> False\"}"
  1343 lemma true_conj1: "True \<and> P \<equiv> P" by simp
  1343   "True \<and> False \<equiv> False"}
  1344 
  1344 *}
  1345 text {*
  1345 
  1346 Here is how this rule can be used for rewriting:
  1346 text {*
  1347 
  1347 how to extend rewriting to more complex cases? e.g.:
  1348 @{ML_response_fake "Conv.rewr_conv @{thm true_conj1} @{cterm \"True \<or> False\"}"
  1348 *}
  1349  "True \<and> False \<equiv> False"}
  1349 
  1350 *}
  1350 ML {*
  1351 
  1351 val complex = @{cterm "distinct [1, x] \<longrightarrow> True \<and> 1 \<noteq> (x::int)"}
  1352 text {*
  1352 *}
  1353 Basic conversions can be combined with a number of conversionals, i.e.
  1353 
  1354 conversion combinators:
  1354 text {* conversionals: basically a count-down version of MetaSimplifier.rewrite *}
  1355 
  1355 
  1356 @{ML_response_fake
  1356 ML {*
  1357 "(Thm.beta_conversion true then_conv Conv.rewr_conv @{thm true_conj1})
  1357 fun all_true1_conv ctxt ct =
  1358   @{cterm \"(\<lambda>x. x \<and> False) True\"}"
       
  1359 "(\<lambda>x. x \<and> False) True \<equiv> False"}
       
  1360 
       
  1361 @{ML_response_fake
       
  1362 "(Conv.rewr_conv @{thm true_conj1} else_conv Conv.all_conv)
       
  1363   @{cterm \"P \<or> (True \<and> Q)\"}"
       
  1364 "P \<or> (True \<and> Q) \<equiv> P \<or> (True \<and> Q)"}
       
  1365 
       
  1366 @{ML_response_fake
       
  1367 "Conv.arg_conv (Conv.rewr_conv @{thm true_conj1})
       
  1368   @{cterm \"P \<or> (True \<and> Q)\"}"
       
  1369 "P \<or> (True \<and> Q) \<equiv> P \<or> Q"}
       
  1370 
       
  1371 \begin{readmore}
       
  1372 See @{ML_file "Pure/conv.ML"} for more conversionals. Further basic conversions
       
  1373 can be found in, for example, @{ML_file "Pure/thm.ML"},
       
  1374 @{ML_file "Pure/drule.ML"}, and @{ML_file "Pure/meta_simplifier.ML"}.
       
  1375 \end{readmore}
       
  1376 
       
  1377 Conversions are a thin layer on top of Isabelle's inference kernel, and may
       
  1378 be seen as a controllable, bare-bone version of Isabelle's simplifier. We
       
  1379 will demonstrate this feature in the following example.
       
  1380 
       
  1381 To begin with, let's assumes we want to simplify with the rewrite rule
       
  1382 @{text true_conj1}. As a conversion, this may look as follows:
       
  1383 *}
       
  1384 
       
  1385 ML {*fun all_true1_conv ctxt ct =
  1358   (case Thm.term_of ct of
  1386   (case Thm.term_of ct of
  1359     @{term "op \<and>"} $ @{term True} $ _ => true1_conv ct
  1387     @{term "op \<and>"} $ @{term True} $ _ => 
  1360   | _ $ _ => Conv.combination_conv (all_true1_conv ctxt) (all_true1_conv ctxt) ct
  1388       (Conv.arg_conv (all_true1_conv ctxt) then_conv
  1361   | Abs _ => Conv.abs_conv (fn (_, cx) => all_true1_conv cx) ctxt ct)
  1389         Conv.rewr_conv @{thm true_conj1}) ct
  1362 *}
  1390   | _ $ _ => Conv.combination_conv (all_true1_conv ctxt)
  1363 
  1391       (all_true1_conv ctxt) ct
  1364 text {*
  1392   | Abs _ => Conv.abs_conv (fn (_, cx) => all_true1_conv cx) ctxt ct
  1365 @{ML_response_fake "all_true1_conv @{context} complex"
  1393   | _ => Conv.all_conv ct)*}
  1366   "distinct [1, x] \<longrightarrow> True \<and> 1 \<noteq> x \<equiv> distinct [1, x] \<longrightarrow> 1 \<noteq> x"}
  1394 
  1367 *}
  1395 text {*
  1368 
  1396 Here is this conversion in action:
  1369 
  1397 
  1370 text {*
  1398 @{ML_response_fake
  1371 transforming theorems: @{ML "Conv.fconv_rule"} (give type)
  1399 "all_true1_conv @{context}
  1372 
  1400   @{cterm \"distinct [1, x] \<longrightarrow> True \<and> 1 \<noteq> x\"}"
  1373 example:
  1401 "distinct [1, x] \<longrightarrow> True \<and> 1 \<noteq> x \<equiv> distinct [1, x] \<longrightarrow> 1 \<noteq> x"}
  1374 *}
  1402 
  1375 
  1403 Now, let's complicate the task a bit: Rewrite according to the rule
  1376 lemma foo: "True \<and> (P \<or> \<not>P)" by simp
  1404 @{text true_conj1}, but only in the first arguments of @{term If}:
  1377 
  1405 *}
  1378 text {*
  1406 
  1379 @{ML_response_fake "Conv.fconv_rule (Conv.arg_conv (all_true1_conv @{context})) @{thm foo}" "P \<or> \<not>P"}
  1407 ML {*fun if_true1_conv ctxt ct =
  1380 *}
       
  1381 
       
  1382 text {* now, replace "True and P" with "P" if it occurs inside an If *}
       
  1383 
       
  1384 ML {*
       
  1385 fun if_true1_conv ctxt ct =
       
  1386   (case Thm.term_of ct of
  1408   (case Thm.term_of ct of
  1387     Const (@{const_name If}, _) $ _ => Conv.arg_conv (all_true1_conv ctxt) ct
  1409     Const (@{const_name If}, _) $ _ =>
  1388   | _ $ _ => Conv.combination_conv (if_true1_conv ctxt) (if_true1_conv ctxt) ct
  1410       Conv.arg_conv (all_true1_conv ctxt) ct
  1389   | Abs _ => Conv.abs_conv (fn (_, cx) => if_true1_conv cx) ctxt ct)
  1411   | _ $ _ => Conv.combination_conv (if_true1_conv ctxt)
  1390 *}
  1412       (if_true1_conv ctxt) ct
  1391 
  1413   | Abs _ => Conv.abs_conv (fn (_, cx) => if_true1_conv cx) ctxt ct
  1392 text {* show example *}
  1414   | _ => Conv.all_conv ct)*}
  1393 
  1415 
  1394 text {*
  1416 text {*
  1395 conversions inside a tactic: replace "true" in conclusion, "if true" in assumptions
  1417 Here is an application of this conversion:
  1396 *}
  1418 
  1397 
  1419 @{ML_response_fake
  1398 ML {*
  1420 "if_true1_conv @{context}
  1399 local open Conv 
  1421   @{cterm \"if P (True \<and> 1 \<noteq> 2) then True \<and> True else True \<and> False\"}"
  1400 in
  1422 "if P (True \<and> 1 \<noteq> 2) then True \<and> True else True \<and> False \<equiv> if P (1 \<noteq> 2) then True \<and> True else True \<and> False"}
  1401 fun true1_tac ctxt =
  1423 *}
  1402   CONVERSION (
  1424 
  1403     Conv.params_conv ~1 (fn cx =>
  1425 text {*
  1404       (Conv.prems_conv ~1 (if_true1_conv cx)) then_conv
  1426 Conversions can also be turned into a tactic with the @{ML CONVERSION}
  1405         (Conv.concl_conv ~1 (all_true1_conv cx))) ctxt)
  1427 tactical, and there are predefined conversionals to traverse a goal state.
  1406 end
  1428 Given a state @{term "\<And>x. P \<Longrightarrow> Q"},  the conversional
  1407 *}
  1429 @{ML Conv.params_conv} applies a conversion to @{term "P \<Longrightarrow> Q"};
  1408 
  1430 given a state @{term "\<lbrakk> P1; P2 \<rbrakk> \<Longrightarrow> Q"},
  1409 text {* give example, show that the conditional rewriting works *}
  1431 the conversional @{ML Conv.prems_conv} applies a conversion to the premises
       
  1432 @{term P1} and @{term P2}, and @{ML Conv.concl_conv} applies a conversion to
       
  1433 the conclusion @{term Q}.
       
  1434 
       
  1435 Assume we want to apply @{ML all_true1_conv} only in the conclusion
       
  1436 of the goal, and @{ML if_true1_conv} should only be applied in the premises.
       
  1437 Here is a tactic doing exactly that:
       
  1438 *}
       
  1439 
       
  1440 ML {*val true1_tac = CSUBGOAL (fn (goal, i) =>
       
  1441   let val ctxt = ProofContext.init (Thm.theory_of_cterm goal)
       
  1442   in
       
  1443     CONVERSION (
       
  1444       Conv.params_conv ~1 (fn cx =>
       
  1445         (Conv.prems_conv ~1 (if_true1_conv cx)) then_conv
       
  1446           Conv.concl_conv ~1 (all_true1_conv cx)) ctxt) i
       
  1447   end)*}
       
  1448 
       
  1449 text {* 
       
  1450 To demonstrate this tactic, consider the following example:
       
  1451 *}
       
  1452 
       
  1453 lemma
       
  1454   "if True \<and> P then P else True \<and> False \<Longrightarrow>
       
  1455   (if True \<and> Q then Q else P) \<longrightarrow> True \<and> (True \<and> Q)"
       
  1456 apply(tactic {* true1_tac 1 *})
       
  1457 txt {* \begin{minipage}{\textwidth}
       
  1458        @{subgoals [display]} 
       
  1459        \end{minipage} *}
       
  1460 (*<*)oops(*>*)
       
  1461 
       
  1462 text {*
       
  1463 Conversions are not restricted to work on certified terms only, they can also
       
  1464 be lifted to theorem transformers, i.e. functions mapping a theorem to a
       
  1465 theorem, by the help of @{ML Conv.fconv_rule}. As an example, consider the
       
  1466 conversion @{ML all_true1_conv} again:
       
  1467 
       
  1468 @{ML_response_fake
       
  1469 "Conv.fconv_rule (all_true1_conv @{context})
       
  1470   @{lemma \"P \<or> (True \<and> \<not>P)\" by simp}" "P \<or> \<not>P"}
       
  1471 *}
  1410 
  1472 
  1411 
  1473 
  1412 
  1474 
  1413 
  1475 
  1414 
  1476