405 sometimes useful during the development of tactics. |
405 sometimes useful during the development of tactics. |
406 *} |
406 *} |
407 |
407 |
408 lemma |
408 lemma |
409 shows "False" and "Goldbach_conjecture" |
409 shows "False" and "Goldbach_conjecture" |
410 apply(tactic {* Skip_Proof.cheat_tac @{theory} *}) |
410 apply(tactic {* Skip_Proof.cheat_tac 1 *}) |
411 txt{*\begin{minipage}{\textwidth} |
411 txt{*\begin{minipage}{\textwidth} |
412 @{subgoals [display]} |
412 @{subgoals [display]} |
413 \end{minipage}*} |
413 \end{minipage}*} |
414 (*<*)oops(*>*) |
414 (*<*)oops(*>*) |
415 |
415 |
1342 corresponds on the ML-level to the tactic |
1342 corresponds on the ML-level to the tactic |
1343 *} |
1343 *} |
1344 |
1344 |
1345 lemma |
1345 lemma |
1346 shows "Suc (1 + 2) < 3 + 2" |
1346 shows "Suc (1 + 2) < 3 + 2" |
1347 apply(tactic {* asm_full_simp_tac @{simpset} 1 *}) |
1347 apply(tactic {* asm_full_simp_tac @{context} 1 *}) |
1348 done |
1348 done |
1349 |
1349 |
1350 text {* |
1350 text {* |
1351 If the simplifier cannot make any progress, then it leaves the goal unchanged, |
1351 If the simplifier cannot make any progress, then it leaves the goal unchanged, |
1352 i.e., does not raise any error message. That means if you use it to unfold a |
1352 i.e., does not raise any error message. That means if you use it to unfold a |
1428 \begin{isabelle}*} |
1428 \begin{isabelle}*} |
1429 ML %grayML{*fun print_ss ctxt ss = |
1429 ML %grayML{*fun print_ss ctxt ss = |
1430 let |
1430 let |
1431 val {simps, congs, procs, ...} = Raw_Simplifier.dest_ss ss |
1431 val {simps, congs, procs, ...} = Raw_Simplifier.dest_ss ss |
1432 |
1432 |
1433 fun name_thm (nm, thm) = |
1433 fun name_sthm (nm, thm) = |
|
1434 Pretty.enclose (nm ^ ": ") "" [pretty_thm_no_vars ctxt thm] |
|
1435 fun name_cthm ((_, nm), thm) = |
1434 Pretty.enclose (nm ^ ": ") "" [pretty_thm_no_vars ctxt thm] |
1436 Pretty.enclose (nm ^ ": ") "" [pretty_thm_no_vars ctxt thm] |
1435 fun name_ctrm (nm, ctrm) = |
1437 fun name_ctrm (nm, ctrm) = |
1436 Pretty.enclose (nm ^ ": ") "" [pretty_cterms ctxt ctrm] |
1438 Pretty.enclose (nm ^ ": ") "" [pretty_cterms ctxt ctrm] |
1437 |
1439 |
1438 val pps = [Pretty.big_list "Simplification rules:" (map name_thm simps), |
1440 val pps = [Pretty.big_list "Simplification rules:" (map name_sthm simps), |
1439 Pretty.big_list "Congruences rules:" (map name_thm congs), |
1441 Pretty.big_list "Congruences rules:" (map name_cthm congs), |
1440 Pretty.big_list "Simproc patterns:" (map name_ctrm procs)] |
1442 Pretty.big_list "Simproc patterns:" (map name_ctrm procs)] |
1441 in |
1443 in |
1442 pps |> Pretty.chunks |
1444 pps |> Pretty.chunks |
1443 |> pwriteln |
1445 |> pwriteln |
1444 end*} |
1446 end*} |
1465 you can see it contains nothing. This simpset is usually not useful, except as a |
1467 you can see it contains nothing. This simpset is usually not useful, except as a |
1466 building block to build bigger simpsets. For example you can add to @{ML empty_ss} |
1468 building block to build bigger simpsets. For example you can add to @{ML empty_ss} |
1467 the simplification rule @{thm [source] Diff_Int} as follows: |
1469 the simplification rule @{thm [source] Diff_Int} as follows: |
1468 *} |
1470 *} |
1469 |
1471 |
1470 ML %grayML{*val ss1 = empty_ss addsimps [@{thm Diff_Int} RS @{thm eq_reflection}] *} |
1472 ML %grayML{*val ss1 = put_simpset empty_ss @{context} addsimps [@{thm Diff_Int} RS @{thm eq_reflection}] *} |
1471 |
1473 |
1472 text {* |
1474 text {* |
1473 Printing then out the components of the simpset gives: |
1475 Printing then out the components of the simpset gives: |
1474 |
1476 |
1475 @{ML_response_fake [display,gray] |
1477 @{ML_response_fake [display,gray] |
1476 "print_ss @{context} ss1" |
1478 "print_ss @{context} (Raw_Simplifier.simpset_of ss1)" |
1477 "Simplification rules: |
1479 "Simplification rules: |
1478 ??.unknown: A - B \<inter> C \<equiv> A - B \<union> (A - C) |
1480 ??.unknown: A - B \<inter> C \<equiv> A - B \<union> (A - C) |
1479 Congruences rules: |
1481 Congruences rules: |
1480 Simproc patterns:"} |
1482 Simproc patterns:"} |
1481 |
1483 |
1482 \footnote{\bf FIXME: Why does it print out ??.unknown} |
1484 \footnote{\bf FIXME: Why does it print out ??.unknown} |
1483 |
1485 |
1484 Adding also the congruence rule @{thm [source] UN_cong} |
1486 Adding also the congruence rule @{thm [source] UN_cong} |
1485 *} |
1487 *} |
1486 |
1488 |
1487 ML %grayML{*val ss2 = Simplifier.add_cong (@{thm UN_cong} RS @{thm eq_reflection}) ss1 *} |
1489 ML %grayML{*val ss2 = ss1 |> Simplifier.add_cong (@{thm UN_cong} RS @{thm eq_reflection}) *} |
1488 |
1490 |
1489 text {* |
1491 text {* |
1490 gives |
1492 gives |
1491 |
1493 |
1492 @{ML_response_fake [display,gray] |
1494 @{ML_response_fake [display,gray] |
1493 "print_ss @{context} ss2" |
1495 "print_ss @{context} (Raw_Simplifier.simpset_of ss2)" |
1494 "Simplification rules: |
1496 "Simplification rules: |
1495 ??.unknown: A - B \<inter> C \<equiv> A - B \<union> (A - C) |
1497 ??.unknown: A - B \<inter> C \<equiv> A - B \<union> (A - C) |
1496 Congruences rules: |
1498 Congruences rules: |
1497 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 |
1499 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 |
1498 Simproc patterns:"} |
1500 Simproc patterns:"} |
1526 shows "True" |
1528 shows "True" |
1527 and "t = t" |
1529 and "t = t" |
1528 and "t \<equiv> t" |
1530 and "t \<equiv> t" |
1529 and "False \<Longrightarrow> Foo" |
1531 and "False \<Longrightarrow> Foo" |
1530 and "\<lbrakk>A; B; C\<rbrakk> \<Longrightarrow> A" |
1532 and "\<lbrakk>A; B; C\<rbrakk> \<Longrightarrow> A" |
1531 apply(tactic {* ALLGOALS (simp_tac HOL_basic_ss) *}) |
1533 apply(tactic {* ALLGOALS (simp_tac (put_simpset HOL_basic_ss @{context})) *}) |
1532 done |
1534 done |
1533 |
1535 |
1534 text {* |
1536 text {* |
1535 This behaviour is not because of simplification rules, but how the subgoaler, solver |
1537 This behaviour is not because of simplification rules, but how the subgoaler, solver |
1536 and looper are set up in @{ML HOL_basic_ss}. |
1538 and looper are set up in @{ML HOL_basic_ss}. |
1709 other permutations by rule @{thm [source] perm_compose_aux} (Line 10); and |
1711 other permutations by rule @{thm [source] perm_compose_aux} (Line 10); and |
1710 finally ``unfreeze'' all instances of permutation compositions by unfolding |
1712 finally ``unfreeze'' all instances of permutation compositions by unfolding |
1711 the definition of the auxiliary constant. |
1713 the definition of the auxiliary constant. |
1712 *} |
1714 *} |
1713 |
1715 |
1714 ML %linenosgray{*val perm_simp_tac = |
1716 ML %linenosgray{*fun perm_simp_tac ctxt = |
1715 let |
1717 let |
1716 val thms1 = [@{thm perm_aux_expand}] |
1718 val thms1 = [@{thm perm_aux_expand}] |
1717 val thms2 = [@{thm perm_append}, @{thm perm_bij}, @{thm perm_rev}, |
1719 val thms2 = [@{thm perm_append}, @{thm perm_bij}, @{thm perm_rev}, |
1718 @{thm perm_compose_aux}] @ @{thms perm_prod.simps} @ |
1720 @{thm perm_compose_aux}] @ @{thms perm_prod.simps} @ |
1719 @{thms perm_list.simps} @ @{thms perm_nat.simps} |
1721 @{thms perm_list.simps} @ @{thms perm_nat.simps} |
1720 val thms3 = [@{thm perm_aux_def}] |
1722 val thms3 = [@{thm perm_aux_def}] |
|
1723 val ss = put_simpset HOL_basic_ss ctxt |
1721 in |
1724 in |
1722 simp_tac (HOL_basic_ss addsimps thms1) |
1725 simp_tac (ss addsimps thms1) |
1723 THEN' simp_tac (HOL_basic_ss addsimps thms2) |
1726 THEN' simp_tac (ss addsimps thms2) |
1724 THEN' simp_tac (HOL_basic_ss addsimps thms3) |
1727 THEN' simp_tac (ss addsimps thms3) |
1725 end*} |
1728 end*} |
1726 |
1729 |
1727 text {* |
1730 text {* |
1728 For all three phases we have to build simpsets adding specific lemmas. As is sufficient |
1731 For all three phases we have to build simpsets adding specific lemmas. As is sufficient |
1729 for our purposes here, we can add these lemmas to @{ML HOL_basic_ss} in order to obtain |
1732 for our purposes here, we can add these lemmas to @{ML HOL_basic_ss} in order to obtain |
1731 *} |
1734 *} |
1732 |
1735 |
1733 lemma |
1736 lemma |
1734 fixes c d::"nat" and pi\<^isub>1 pi\<^isub>2::"prm" |
1737 fixes c d::"nat" and pi\<^isub>1 pi\<^isub>2::"prm" |
1735 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)" |
1738 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)" |
1736 apply(tactic {* perm_simp_tac 1 *}) |
1739 apply(tactic {* perm_simp_tac @{context} 1 *}) |
1737 done |
1740 done |
1738 |
1741 |
1739 |
1742 |
1740 text {* |
1743 text {* |
1741 in one step. This tactic can deal with most instances of normalising permutations. |
1744 in one step. This tactic can deal with most instances of normalising permutations. |
1747 (FIXME: Is it interesting to say something about @{term "op =simp=>"}?) |
1750 (FIXME: Is it interesting to say something about @{term "op =simp=>"}?) |
1748 |
1751 |
1749 (FIXME: What are the second components of the congruence rules---something to |
1752 (FIXME: What are the second components of the congruence rules---something to |
1750 do with weak congruence constants?) |
1753 do with weak congruence constants?) |
1751 |
1754 |
1752 (FIXME: Anything interesting to say about @{ML Simplifier.clear_ss}?) |
|
1753 |
|
1754 (FIXME: what are @{ML mksimps_pairs}; used in Nominal.thy) |
1755 (FIXME: what are @{ML mksimps_pairs}; used in Nominal.thy) |
1755 |
1756 |
1756 (FIXME: explain @{ML simplify} and @{ML "Simplifier.rewrite_rule"} etc.) |
1757 (FIXME: explain @{ML simplify} and @{ML "Simplifier.rewrite_rule"} etc.) |
1757 |
1758 |
1758 *} |
1759 *} |
1769 To see how simprocs work, let us first write a simproc that just prints out |
1770 To see how simprocs work, let us first write a simproc that just prints out |
1770 the pattern which triggers it and otherwise does nothing. For this |
1771 the pattern which triggers it and otherwise does nothing. For this |
1771 you can use the function: |
1772 you can use the function: |
1772 *} |
1773 *} |
1773 |
1774 |
1774 ML %linenosgray{*fun fail_simproc simpset redex = |
1775 ML %linenosgray{*fun fail_simproc ctxt redex = |
1775 let |
1776 let |
1776 val ctxt = Simplifier.the_context simpset |
|
1777 val _ = pwriteln (Pretty.block |
1777 val _ = pwriteln (Pretty.block |
1778 [Pretty.str "The redex: ", pretty_cterm ctxt redex]) |
1778 [Pretty.str "The redex: ", pretty_cterm ctxt redex]) |
1779 in |
1779 in |
1780 NONE |
1780 NONE |
1781 end*} |
1781 end*} |
1842 want this, then you have to use a slightly different method for setting |
1843 want this, then you have to use a slightly different method for setting |
1843 up the simproc. First the function @{ML fail_simproc} needs to be modified |
1844 up the simproc. First the function @{ML fail_simproc} needs to be modified |
1844 to |
1845 to |
1845 *} |
1846 *} |
1846 |
1847 |
1847 ML %grayML{*fun fail_simproc' simpset redex = |
1848 ML %grayML{*fun fail_simproc' ctxt redex = |
1848 let |
1849 let |
1849 val ctxt = Simplifier.the_context simpset |
|
1850 val _ = pwriteln (Pretty.block |
1850 val _ = pwriteln (Pretty.block |
1851 [Pretty.str "The redex:", pretty_term ctxt redex]) |
1851 [Pretty.str "The redex:", pretty_term ctxt redex]) |
1852 in |
1852 in |
1853 NONE |
1853 NONE |
1854 end*} |
1854 end*} |
1859 We can turn this function into a proper simproc using the function |
1859 We can turn this function into a proper simproc using the function |
1860 @{ML Simplifier.simproc_global_i}: |
1860 @{ML Simplifier.simproc_global_i}: |
1861 *} |
1861 *} |
1862 |
1862 |
1863 |
1863 |
1864 ML %grayML{*val fail' = |
1864 ML %grayML{*fun fail' ctxt = |
1865 let |
1865 let |
1866 val thy = @{theory} |
1866 val thy = @{theory} |
1867 val pat = [@{term "Suc n"}] |
1867 val pat = [@{term "Suc n"}] |
1868 in |
1868 in |
1869 Simplifier.simproc_global_i thy "fail_simproc'" pat (K fail_simproc') |
1869 Simplifier.simproc_global_i thy "fail_simproc'" pat (K fail_simproc' ctxt) |
1870 end*} |
1870 end*} |
1871 |
1871 |
1872 text {* |
1872 text {* |
1873 Here the pattern is given as @{ML_type term} (instead of @{ML_type cterm}). |
1873 Here the pattern is given as @{ML_type term} (instead of @{ML_type cterm}). |
1874 The function also takes a list of patterns that can trigger the simproc. |
1874 The function also takes a list of patterns that can trigger the simproc. |
1907 the rewriting with simprocs, let us further assume we want that the simproc |
1907 the rewriting with simprocs, let us further assume we want that the simproc |
1908 only rewrites terms ``greater'' than @{term "Suc 0"}. For this we can write |
1908 only rewrites terms ``greater'' than @{term "Suc 0"}. For this we can write |
1909 *} |
1909 *} |
1910 |
1910 |
1911 |
1911 |
1912 ML %grayML{*fun plus_one_simproc ss redex = |
1912 ML %grayML{*fun plus_one_simproc ctxt redex = |
1913 case redex of |
1913 case redex of |
1914 @{term "Suc 0"} => NONE |
1914 @{term "Suc 0"} => NONE |
1915 | _ => SOME @{thm plus_one}*} |
1915 | _ => SOME @{thm plus_one}*} |
1916 |
1916 |
1917 text {* |
1917 text {* |
1918 and set up the simproc as follows. |
1918 and set up the simproc as follows. |
1919 *} |
1919 *} |
1920 |
1920 |
1921 ML %grayML{*val plus_one = |
1921 ML %grayML{*fun plus_one ctxt = |
1922 let |
1922 let |
1923 val thy = @{theory} |
1923 val thy = @{theory} |
1924 val pat = [@{term "Suc n"}] |
1924 val pat = [@{term "Suc n"}] |
1925 in |
1925 in |
1926 Simplifier.simproc_global_i thy "sproc +1" pat (K plus_one_simproc) |
1926 Simplifier.simproc_global_i thy "sproc +1" pat (K plus_one_simproc ctxt) |
1927 end*} |
1927 end*} |
1928 |
1928 |
1929 text {* |
1929 text {* |
1930 Now the simproc is set up so that it is triggered by terms |
1930 Now the simproc is set up so that it is triggered by terms |
1931 of the form @{term "Suc n"}, but inside the simproc we only produce |
1931 of the form @{term "Suc n"}, but inside the simproc we only produce |
1933 in the following proof |
1933 in the following proof |
1934 *} |
1934 *} |
1935 |
1935 |
1936 lemma |
1936 lemma |
1937 shows "P (Suc (Suc (Suc 0))) (Suc 0)" |
1937 shows "P (Suc (Suc (Suc 0))) (Suc 0)" |
1938 apply(tactic {* simp_tac (HOL_basic_ss addsimprocs [plus_one]) 1*}) |
1938 apply(tactic {* simp_tac (put_simpset HOL_basic_ss @{context} addsimprocs [plus_one @{context}]) 1*}) |
1939 txt{* |
1939 txt{* |
1940 where the simproc produces the goal state |
1940 where the simproc produces the goal state |
1941 \begin{isabelle} |
1941 \begin{isabelle} |
1942 @{subgoals[display]} |
1942 @{subgoals[display]} |
1943 \end{isabelle} |
1943 \end{isabelle} |
1988 |
1988 |
1989 ML %grayML{*fun get_thm_alt ctxt (t, n) = |
1989 ML %grayML{*fun get_thm_alt ctxt (t, n) = |
1990 let |
1990 let |
1991 val num = HOLogic.mk_number @{typ "nat"} n |
1991 val num = HOLogic.mk_number @{typ "nat"} n |
1992 val goal = Logic.mk_equals (t, num) |
1992 val goal = Logic.mk_equals (t, num) |
1993 val num_ss = HOL_ss addsimps @{thms semiring_norm} |
1993 val num_ss = put_simpset HOL_ss ctxt addsimps @{thms semiring_norm} |
1994 in |
1994 in |
1995 Goal.prove ctxt [] [] goal (K (simp_tac num_ss 1)) |
1995 Goal.prove ctxt [] [] goal (K (simp_tac num_ss 1)) |
1996 end*} |
1996 end*} |
1997 |
1997 |
1998 text {* |
1998 text {* |
2008 |
2008 |
2009 Anyway, either version can be used in the function that produces the actual |
2009 Anyway, either version can be used in the function that produces the actual |
2010 theorem for the simproc. |
2010 theorem for the simproc. |
2011 *} |
2011 *} |
2012 |
2012 |
2013 ML %grayML{*fun nat_number_simproc ss t = |
2013 ML %grayML{*fun nat_number_simproc ctxt t = |
2014 let |
|
2015 val ctxt = Simplifier.the_context ss |
|
2016 in |
|
2017 SOME (get_thm_alt ctxt (t, dest_suc_trm t)) |
2014 SOME (get_thm_alt ctxt (t, dest_suc_trm t)) |
2018 handle TERM _ => NONE |
2015 handle TERM _ => NONE *} |
2019 end*} |
|
2020 |
2016 |
2021 text {* |
2017 text {* |
2022 This function uses the fact that @{ML dest_suc_trm} might raise an exception |
2018 This function uses the fact that @{ML dest_suc_trm} might raise an exception |
2023 @{ML TERM}. In this case there is nothing that can be rewritten and therefore no |
2019 @{ML TERM}. In this case there is nothing that can be rewritten and therefore no |
2024 theorem is produced (i.e.~the function returns @{ML NONE}). To try out the simproc |
2020 theorem is produced (i.e.~the function returns @{ML NONE}). To try out the simproc |
2025 on an example, you can set it up as follows: |
2021 on an example, you can set it up as follows: |
2026 *} |
2022 *} |
2027 |
2023 |
2028 ML %grayML{*val nat_number = |
2024 ML %grayML{*fun nat_number ctxt = |
2029 let |
2025 let |
2030 val thy = @{theory} |
2026 val thy = @{theory} |
2031 val pat = [@{term "Suc n"}] |
2027 val pat = [@{term "Suc n"}] |
2032 in |
2028 in |
2033 Simplifier.simproc_global_i thy "nat_number" pat (K nat_number_simproc) |
2029 Simplifier.simproc_global_i thy "nat_number" pat (K nat_number_simproc ctxt) |
2034 end*} |
2030 end*} |
2035 |
2031 |
2036 text {* |
2032 text {* |
2037 Now in the lemma |
2033 Now in the lemma |
2038 *} |
2034 *} |
2039 |
2035 |
2040 lemma |
2036 lemma |
2041 shows "P (Suc (Suc 2)) (Suc 99) (0::nat) (Suc 4 + Suc 0) (Suc (0 + 0))" |
2037 shows "P (Suc (Suc 2)) (Suc 99) (0::nat) (Suc 4 + Suc 0) (Suc (0 + 0))" |
2042 apply(tactic {* simp_tac (HOL_ss addsimprocs [nat_number]) 1*}) |
2038 apply(tactic {* simp_tac (put_simpset HOL_ss @{context} addsimprocs [nat_number @{context}]) 1*}) |
2043 txt {* |
2039 txt {* |
2044 you obtain the more legible goal state |
2040 you obtain the more legible goal state |
2045 \begin{isabelle} |
2041 \begin{isabelle} |
2046 @{subgoals [display]} |
2042 @{subgoals [display]} |
2047 \end{isabelle}*} |
2043 \end{isabelle}*} |