src/HOL/Imperative_HOL/ex/Congproc_Ex.thy
author wenzelm
Fri, 14 Mar 2025 23:03:58 +0100
changeset 82276 d22e9c5b5dc6
parent 80715 613417b3edad
permissions -rw-r--r--
support for .tar.xz archives;
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
80715
613417b3edad adapt and activate congprocs examples, following the current Simplifier implementation;
wenzelm
parents: 80714
diff changeset
     1
(*  Title:      HOL/Imperative_HOL/ex/Congproc_Ex.thy
80714
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
     2
    Author:     Norbert Schirmer, Apple, 2024
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
     3
*)
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
     4
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
     5
section \<open>Examples for congruence procedures (congprocs)\<close>
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
     6
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
     7
theory Congproc_Ex
80715
613417b3edad adapt and activate congprocs examples, following the current Simplifier implementation;
wenzelm
parents: 80714
diff changeset
     8
  imports "../Imperative_HOL"
80714
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
     9
begin
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
    10
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
    11
text \<open>The simplifier works bottom up, which means that when invoked on a (compound) term it first
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
    12
descends into the subterms to normalise those and then works its way up to the head of the term
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
    13
trying to apply rewrite rules for the current redex (reducible expression) it encounters on the
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
    14
way up. Descending into the term can be influenced by congruence rules. Before descending into the
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
    15
subterms the simplifier checks for a congruence rule for the head of the term. If it finds one
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
    16
it behaves according to that rule, otherwise the simplifier descends into each subterm subsequently.
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
    17
80715
613417b3edad adapt and activate congprocs examples, following the current Simplifier implementation;
wenzelm
parents: 80714
diff changeset
    18
While rewrite rules can be complemented with simplification procedures (simprocs) to get even
613417b3edad adapt and activate congprocs examples, following the current Simplifier implementation;
wenzelm
parents: 80714
diff changeset
    19
more programmatic control, congruence rules can be complemented with congruence
80714
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
    20
procedures (congprocs):
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
    21
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
    22
\<^item> Congprocs share the same ML signature as simprocs and provide a similar interface in
80715
613417b3edad adapt and activate congprocs examples, following the current Simplifier implementation;
wenzelm
parents: 80714
diff changeset
    23
  Isabelle/ML as well as Isabelle/Isar:
80714
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
    24
  @{ML_type "morphism -> Proof.context -> thm option"}
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
    25
\<^item> Congprocs are triggered by associated term patterns (just like simprocs) not just the head constant
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
    26
  (which is the case for congruence rules). Like simprocs, congprocs are managed in a term net.
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
    27
\<^item> Congprocs have precedence over congruence rules (unlike simprocs)
80715
613417b3edad adapt and activate congprocs examples, following the current Simplifier implementation;
wenzelm
parents: 80714
diff changeset
    28
\<^item> In case the term net selects multiple candidates,
80714
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
    29
  the one with the more specific term pattern is tried first. A pattern
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
    30
  \<open>p1\<close> is considered more specific than \<open>p2\<close> if \<open>p2\<close> matches \<open>p1\<close> but not vice versa.
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
    31
\<^item> To avoid surprises the theorems returned by a congproc should follow the structure of
80715
613417b3edad adapt and activate congprocs examples, following the current Simplifier implementation;
wenzelm
parents: 80714
diff changeset
    32
  ordinary congruence rule. Either the conclusion should return an equation where the head of the
80714
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
    33
  left hand side and right hand side coincide, or the right hand side is already in normal form.
80715
613417b3edad adapt and activate congprocs examples, following the current Simplifier implementation;
wenzelm
parents: 80714
diff changeset
    34
  Otherwise, simplification might skip some relevant subterms or do repeated simplification of
80714
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
    35
  some subterms. Some fine points are illustrated by the following examples.
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
    36
\<close>
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
    37
80715
613417b3edad adapt and activate congprocs examples, following the current Simplifier implementation;
wenzelm
parents: 80714
diff changeset
    38
80714
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
    39
subsection \<open>Congproc examples with if-then-else\<close>
80715
613417b3edad adapt and activate congprocs examples, following the current Simplifier implementation;
wenzelm
parents: 80714
diff changeset
    40
80714
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
    41
ML \<open>
80715
613417b3edad adapt and activate congprocs examples, following the current Simplifier implementation;
wenzelm
parents: 80714
diff changeset
    42
fun assert expected eq = if (expected aconvc (Thm.rhs_of eq)) then eq else
80714
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
    43
  raise error ("unexpected: " ^ @{make_string} eq)
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
    44
80715
613417b3edad adapt and activate congprocs examples, following the current Simplifier implementation;
wenzelm
parents: 80714
diff changeset
    45
fun assert_equiv expected eq =
613417b3edad adapt and activate congprocs examples, following the current Simplifier implementation;
wenzelm
parents: 80714
diff changeset
    46
  if Pattern.equiv @{theory} (Thm.term_of expected, Thm.term_of (Thm.rhs_of eq)) then eq else
80714
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
    47
  raise error ("unexpected: " ^ @{make_string} eq)
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
    48
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
    49
\<close>
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
    50
text \<open>The standard setup uses @{thm if_weak_cong}. Only if the condition simplifies to
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
    51
 \<^term>\<open>True\<close> or \<^term>\<open>False\<close> the branches are simplified.\<close>
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
    52
experiment fixes a::nat
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
    53
begin
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
    54
ML_val \<open>
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
    55
@{cterm "if a < 2 then a < 2 else \<not> a < 2"}
80715
613417b3edad adapt and activate congprocs examples, following the current Simplifier implementation;
wenzelm
parents: 80714
diff changeset
    56
  |> Simplifier.asm_full_rewrite @{context}
80714
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
    57
  |> assert @{cterm "if a < 2 then a < 2 else \<not> a < 2"}
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
    58
\<close>
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
    59
end
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
    60
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
    61
text \<open>A congproc that supplies the 'strong' rule @{thm if_cong}\<close>
80715
613417b3edad adapt and activate congprocs examples, following the current Simplifier implementation;
wenzelm
parents: 80714
diff changeset
    62
simproc_setup passive congproc if_cong (\<open>if x then a else b\<close>) = \<open>
613417b3edad adapt and activate congprocs examples, following the current Simplifier implementation;
wenzelm
parents: 80714
diff changeset
    63
  (K (K (K (SOME @{thm if_cong [cong_format]}))))
80714
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
    64
\<close>
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
    65
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
    66
experiment
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
    67
begin
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
    68
text \<open>The congproc takes precedence over the cong rules\<close>
80715
613417b3edad adapt and activate congprocs examples, following the current Simplifier implementation;
wenzelm
parents: 80714
diff changeset
    69
declare [[simproc add: if_cong, simp_trace = false]]
80714
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
    70
ML_val \<open>
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
    71
@{cterm "if ((a::nat) < 2) then a < 2 else \<not> ((a::nat) < 2)"}
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
    72
  |> Simplifier.asm_full_rewrite @{context}
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
    73
  |> assert @{cterm True}
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
    74
\<close>
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
    75
end
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
    76
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
    77
text \<open>When we replace the congruence rule with a congproc that provides the same
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
    78
rule we would expect that the result is the same.\<close>
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
    79
80715
613417b3edad adapt and activate congprocs examples, following the current Simplifier implementation;
wenzelm
parents: 80714
diff changeset
    80
simproc_setup passive congproc if_weak_cong_bad (\<open>if x then a else b\<close>) = \<open>
613417b3edad adapt and activate congprocs examples, following the current Simplifier implementation;
wenzelm
parents: 80714
diff changeset
    81
  (K (K (K (SOME @{thm if_weak_cong [cong_format]}))))
80714
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
    82
\<close>
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
    83
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
    84
experiment
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
    85
begin
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
    86
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
    87
ML_val \<open>
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
    88
@{cterm "if True then (1::nat) + 2 else 2 + 3"}
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
    89
  |> Simplifier.asm_full_rewrite @{context}
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
    90
  |> assert @{cterm "Suc (Suc (Suc 0))"}
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
    91
\<close>
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
    92
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
    93
80715
613417b3edad adapt and activate congprocs examples, following the current Simplifier implementation;
wenzelm
parents: 80714
diff changeset
    94
declare if_weak_cong [cong del]
613417b3edad adapt and activate congprocs examples, following the current Simplifier implementation;
wenzelm
parents: 80714
diff changeset
    95
declare [[simproc add: if_weak_cong_bad, simp_trace]]
80714
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
    96
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
    97
ML_val \<open>
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
    98
@{cterm "if True then (1::nat) + 2 else 2 + 3"}
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
    99
  |> Simplifier.asm_full_rewrite @{context}
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
   100
  |> assert @{cterm "(1::nat) + 2"}
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
   101
\<close>
80715
613417b3edad adapt and activate congprocs examples, following the current Simplifier implementation;
wenzelm
parents: 80714
diff changeset
   102
text \<open>We do not get the same result. The then-branch is selected but not simplified.
613417b3edad adapt and activate congprocs examples, following the current Simplifier implementation;
wenzelm
parents: 80714
diff changeset
   103
As the simplifier works bottom up it can usually assume that the subterms are already in
613417b3edad adapt and activate congprocs examples, following the current Simplifier implementation;
wenzelm
parents: 80714
diff changeset
   104
'simp normal form'. So the simplifier avoids to revisit the then-branch when it applies
80714
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
   105
@{thm if_True}. However, the weak congruence rule
80715
613417b3edad adapt and activate congprocs examples, following the current Simplifier implementation;
wenzelm
parents: 80714
diff changeset
   106
@{thm if_weak_cong} only simplifies the condition and neither branch.
80714
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
   107
As the simplifier analyses congruence rules this rule is classified as weak. Whenever a
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
   108
redex is simplified (for which a weak congruence rule is active) the simplifier deviates from its
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
   109
 default behaviour and rewrites the result. However, the simplifier does not analyse the
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
   110
congproc. To achieve the same result we can explicitly specify it as \<^emph>\<open>weak\<close>.\<close>
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
   111
end
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
   112
80715
613417b3edad adapt and activate congprocs examples, following the current Simplifier implementation;
wenzelm
parents: 80714
diff changeset
   113
simproc_setup passive weak_congproc if_weak_cong (\<open>if x then a else b\<close>) = \<open>
613417b3edad adapt and activate congprocs examples, following the current Simplifier implementation;
wenzelm
parents: 80714
diff changeset
   114
  (K (K (K (SOME @{thm if_weak_cong [cong_format]}))))
80714
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
   115
\<close>
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
   116
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
   117
experiment
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
   118
begin
80715
613417b3edad adapt and activate congprocs examples, following the current Simplifier implementation;
wenzelm
parents: 80714
diff changeset
   119
declare if_weak_cong [cong del]
613417b3edad adapt and activate congprocs examples, following the current Simplifier implementation;
wenzelm
parents: 80714
diff changeset
   120
declare [[simproc add: if_weak_cong, simp_trace]]
80714
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
   121
ML_val \<open>
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
   122
@{cterm "if True then (1::nat) + 2 else 2 + 3"}
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
   123
  |> Simplifier.asm_full_rewrite @{context}
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
   124
  |> assert @{cterm "Suc (Suc (Suc 0))"}
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
   125
\<close>
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
   126
end
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
   127
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
   128
text \<open>Now some more ambitious congproc that combines the effect of @{thm if_weak_cong} and @{thm if_cong}.
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
   129
It first simplifies the condition and depending on the result decides to either simplify only
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
   130
one of the branches (in case the condition evaluates to \<^term>\<open>True\<close> or \<^term>\<open>False\<close>, or otherwise
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
   131
it simplifies both branches.
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
   132
\<close>
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
   133
80715
613417b3edad adapt and activate congprocs examples, following the current Simplifier implementation;
wenzelm
parents: 80714
diff changeset
   134
lemma if_True_weak_cong:
80714
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
   135
  "P = True \<Longrightarrow> x = x' \<Longrightarrow> (if P then x else y) = (if True then x' else y)"
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
   136
  by simp
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
   137
80715
613417b3edad adapt and activate congprocs examples, following the current Simplifier implementation;
wenzelm
parents: 80714
diff changeset
   138
lemma if_False_weak_cong:
80714
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
   139
  "P = False \<Longrightarrow> y = y' \<Longrightarrow> (if P then x else y) = (if False then x else y')"
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
   140
  by simp
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
   141
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
   142
text \<open>Note that we do not specify the congproc as \<^emph>\<open>weak\<close> as every relevant subterm is
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
   143
simplified.\<close>
80715
613417b3edad adapt and activate congprocs examples, following the current Simplifier implementation;
wenzelm
parents: 80714
diff changeset
   144
simproc_setup passive congproc if_cong_canonical (\<open>if x then a else b\<close>) = \<open>
80714
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
   145
  let
80715
613417b3edad adapt and activate congprocs examples, following the current Simplifier implementation;
wenzelm
parents: 80714
diff changeset
   146
    val if_True_weak_cong = @{thm if_True_weak_cong [cong_format]}
613417b3edad adapt and activate congprocs examples, following the current Simplifier implementation;
wenzelm
parents: 80714
diff changeset
   147
    val if_False_weak_cong = @{thm if_False_weak_cong [cong_format]}
613417b3edad adapt and activate congprocs examples, following the current Simplifier implementation;
wenzelm
parents: 80714
diff changeset
   148
    val if_cong = @{thm if_cong [cong_format]}
80714
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
   149
  in
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
   150
    (K (fn ctxt => fn ct =>
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
   151
      let
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
   152
         val (_, [P, x, y]) = Drule.strip_comb ct
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
   153
         val P_eq = Simplifier.asm_full_rewrite ctxt P
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
   154
         val rhs = Thm.dest_equals_rhs (Thm.cprop_of P_eq)
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
   155
         val rule = (case Thm.term_of rhs of
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
   156
                       @{term True}  => if_True_weak_cong
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
   157
                     | @{term False} => if_False_weak_cong
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
   158
                     | _ => if_cong)
80715
613417b3edad adapt and activate congprocs examples, following the current Simplifier implementation;
wenzelm
parents: 80714
diff changeset
   159
      in
80714
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
   160
        SOME (rule OF [P_eq])
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
   161
      end))
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
   162
   end
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
   163
\<close>
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
   164
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
   165
experiment
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
   166
begin
80715
613417b3edad adapt and activate congprocs examples, following the current Simplifier implementation;
wenzelm
parents: 80714
diff changeset
   167
declare if_weak_cong [cong del]
613417b3edad adapt and activate congprocs examples, following the current Simplifier implementation;
wenzelm
parents: 80714
diff changeset
   168
declare [[simproc add: if_cong_canonical, simp_trace]]
80714
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
   169
ML_val \<open>
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
   170
@{cterm "if True then (1::nat) + 2 else 2 + 3"}
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
   171
  |> Simplifier.asm_full_rewrite @{context}
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
   172
  |> assert @{cterm "Suc (Suc (Suc 0))"}
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
   173
\<close>
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
   174
end
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
   175
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
   176
experiment
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
   177
begin
80715
613417b3edad adapt and activate congprocs examples, following the current Simplifier implementation;
wenzelm
parents: 80714
diff changeset
   178
declare if_weak_cong [cong del]
613417b3edad adapt and activate congprocs examples, following the current Simplifier implementation;
wenzelm
parents: 80714
diff changeset
   179
declare [[simproc add: if_cong_canonical, simp_trace]]
80714
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
   180
text \<open>Canonical congruence behaviour:
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
   181
\<^enum> First condition is simplified to True
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
   182
\<^enum> Congruence rule is selected and then "then-branch" is simplified but "else-branch" is left untouched
80715
613417b3edad adapt and activate congprocs examples, following the current Simplifier implementation;
wenzelm
parents: 80714
diff changeset
   183
\<^enum> Congruence step is finished and now rewriting with @{thm if_True} is done.
80714
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
   184
Note that there is no attempt to revisit the result, as congproc is not weak.\<close>
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
   185
ML_val \<open>
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
   186
@{cterm "if ((2::nat) < 3) then 22 + 2 else 21 + 1"}
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
   187
  |> Simplifier.asm_full_rewrite @{context}
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
   188
  |> assert @{cterm "24"}
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
   189
\<close>
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
   190
end
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
   191
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
   192
experiment fixes a ::nat
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
   193
begin
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
   194
text \<open>The weak congruence rule shows no effect.\<close>
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
   195
ML_val \<open>
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
   196
@{cterm "if a < b then a < b \<longrightarrow> True else \<not> a < b \<longrightarrow> True"}
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
   197
  |> Simplifier.asm_full_rewrite @{context}
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
   198
  |> assert @{cterm "if a < b then a < b \<longrightarrow> True else \<not> a < b \<longrightarrow> True"}
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
   199
\<close>
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
   200
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
   201
text \<open>The congproc simplifies the term.\<close>
80715
613417b3edad adapt and activate congprocs examples, following the current Simplifier implementation;
wenzelm
parents: 80714
diff changeset
   202
declare if_weak_cong [cong del]
613417b3edad adapt and activate congprocs examples, following the current Simplifier implementation;
wenzelm
parents: 80714
diff changeset
   203
declare [[simproc add: if_cong_canonical, simp_trace]]
80714
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
   204
ML_val \<open>
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
   205
@{cterm "if a < b then a < b \<longrightarrow> True else \<not> a < b \<longrightarrow> True"}
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
   206
  |> Simplifier.asm_full_rewrite @{context}
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
   207
  |> assert @{cterm "True"}
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
   208
\<close>
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
   209
end
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
   210
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
   211
text \<open>Beware of congprocs that implement non-standard congruence rules, like:\<close>
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
   212
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
   213
lemma if_True_cong: "P = True \<Longrightarrow> (if P then x else y) = x"
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
   214
  by simp
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
   215
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
   216
lemma if_False_cong: "P = False \<Longrightarrow> (if P then x else y) = y"
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
   217
  by simp
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
   218
80715
613417b3edad adapt and activate congprocs examples, following the current Simplifier implementation;
wenzelm
parents: 80714
diff changeset
   219
simproc_setup passive congproc if_cong_bad (\<open>if x then a else b\<close>) = \<open>
80714
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
   220
  let
80715
613417b3edad adapt and activate congprocs examples, following the current Simplifier implementation;
wenzelm
parents: 80714
diff changeset
   221
    val if_True_cong = @{thm if_True_cong [cong_format]}
613417b3edad adapt and activate congprocs examples, following the current Simplifier implementation;
wenzelm
parents: 80714
diff changeset
   222
    val if_False_cong = @{thm if_False_cong [cong_format]}
613417b3edad adapt and activate congprocs examples, following the current Simplifier implementation;
wenzelm
parents: 80714
diff changeset
   223
    val if_cong = @{thm if_cong [cong_format]}
80714
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
   224
  in
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
   225
    (K (fn ctxt => fn ct =>
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
   226
      let
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
   227
         val (_, [P, x, y]) = Drule.strip_comb ct
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
   228
         val P_eq = Simplifier.asm_full_rewrite ctxt P
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
   229
         val rhs = Thm.dest_equals_rhs (Thm.cprop_of P_eq)
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
   230
         val rule = (case Thm.term_of rhs of
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
   231
                       @{term True}  => if_True_cong
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
   232
                     | @{term False} => if_False_cong
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
   233
                     | _ => if_cong )
80715
613417b3edad adapt and activate congprocs examples, following the current Simplifier implementation;
wenzelm
parents: 80714
diff changeset
   234
      in
80714
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
   235
        SOME (rule OF [P_eq])
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
   236
      end))
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
   237
   end
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
   238
\<close>
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
   239
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
   240
experiment
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
   241
begin
80715
613417b3edad adapt and activate congprocs examples, following the current Simplifier implementation;
wenzelm
parents: 80714
diff changeset
   242
declare if_weak_cong [cong del]
613417b3edad adapt and activate congprocs examples, following the current Simplifier implementation;
wenzelm
parents: 80714
diff changeset
   243
declare [[simproc add: if_cong_bad, simp_trace]]
80714
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
   244
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
   245
ML_val \<open>
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
   246
@{cterm "if ((2::nat) < 3) then 22 + 2 else 21 + 1"}
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
   247
  |> Simplifier.asm_full_rewrite @{context}
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
   248
  |> assert @{cterm "24"}
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
   249
\<close>
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
   250
text \<open>The result is the same as with the canonical congproc. But when inspecting the \<open>simp_trace\<close>
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
   251
we can  observe some odd congruence behaviour:
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
   252
\<^enum> First condition is simplified to True
80715
613417b3edad adapt and activate congprocs examples, following the current Simplifier implementation;
wenzelm
parents: 80714
diff changeset
   253
\<^enum> Non-standard congruence rule @{thm if_True_cong} is selected which does
80714
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
   254
  not have the same head on the right hand side and simply gives back the "then-branch"
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
   255
\<^enum> Incidently simplification continues on the then-branch as there are simplification rules for
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
   256
  the redex @{term "22 + 2"}. So we were lucky.
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
   257
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
   258
The following example with a nested if-then-else illustrates what can go wrong.
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
   259
\<close>
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
   260
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
   261
ML_val \<open>
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
   262
@{cterm "if ((2::nat) < 3) then (if ((3::nat) < 2) then 20 + 1 else 20 + 2) else 20 + 3"}
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
   263
  |> Simplifier.asm_full_rewrite @{context}
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
   264
  |> assert @{cterm "if (3::nat) < 2 then 20 + 1 else 20 + 2"}
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
   265
\<close>
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
   266
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
   267
text \<open>For the a nested if-then-else we get stuck as there is no simplification rule
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
   268
triggering for the inner if-then-else once it is at the toplevel. Note that it does not
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
   269
help to specify the congproc as \<^emph>\<open>weak\<close>. The last step of the simplifier was the application
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
   270
of the congruence rule. No rewrite rule is triggered for the resulting redex so the simplifier
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
   271
does not revisit the term. Note that congruence rules (and congprocs) are applied only when the
80715
613417b3edad adapt and activate congprocs examples, following the current Simplifier implementation;
wenzelm
parents: 80714
diff changeset
   272
simplifier walks down the term (top-down), simplification rules (and simprocs) on the other hand
613417b3edad adapt and activate congprocs examples, following the current Simplifier implementation;
wenzelm
parents: 80714
diff changeset
   273
are only applied when the simplifier walks up the term (bottom-up). As the simplifier is on its
613417b3edad adapt and activate congprocs examples, following the current Simplifier implementation;
wenzelm
parents: 80714
diff changeset
   274
way up there is no reason to try a congruence rule on the resulting redex.
80714
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
   275
It only tries to apply simplification rules.
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
   276
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
   277
So congprocs should better behave canonically like ordinary congruence rules and
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
   278
 preserve the head of the redex:
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
   279
\<close>
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
   280
end
80715
613417b3edad adapt and activate congprocs examples, following the current Simplifier implementation;
wenzelm
parents: 80714
diff changeset
   281
80714
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
   282
experiment
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
   283
begin
80715
613417b3edad adapt and activate congprocs examples, following the current Simplifier implementation;
wenzelm
parents: 80714
diff changeset
   284
declare if_weak_cong [cong del]
613417b3edad adapt and activate congprocs examples, following the current Simplifier implementation;
wenzelm
parents: 80714
diff changeset
   285
declare [[simproc add: if_cong, simp_trace]]
80714
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
   286
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
   287
ML_val \<open>
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
   288
@{cterm "if ((2::nat) < 3) then (if ((3::nat) < 2) then 20 + 1 else 20 + 2) else 20 + 3"}
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
   289
  |> Simplifier.asm_full_rewrite @{context}
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
   290
  |> assert @{cterm "22"}
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
   291
\<close>
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
   292
end
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
   293
80715
613417b3edad adapt and activate congprocs examples, following the current Simplifier implementation;
wenzelm
parents: 80714
diff changeset
   294
text \<open>Alternatively one can supply a non standard rule if the congproc takes care of the normalisation
80714
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
   295
of the relevant subterms itself.\<close>
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
   296
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
   297
lemma if_True_diy_cong: "P = True \<Longrightarrow> x = x' \<Longrightarrow> (if P then x else y) = x'"
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
   298
  by simp
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
   299
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
   300
lemma if_False_diy_cong: "P = False \<Longrightarrow> y = y' \<Longrightarrow> (if P then x else y) = y'"
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
   301
  by simp
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
   302
80715
613417b3edad adapt and activate congprocs examples, following the current Simplifier implementation;
wenzelm
parents: 80714
diff changeset
   303
simproc_setup passive congproc if_cong_diy (\<open>if x then a else b\<close>) = \<open>
80714
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
   304
  let
80715
613417b3edad adapt and activate congprocs examples, following the current Simplifier implementation;
wenzelm
parents: 80714
diff changeset
   305
    val if_True_diy_cong = @{thm if_True_diy_cong [cong_format]}
613417b3edad adapt and activate congprocs examples, following the current Simplifier implementation;
wenzelm
parents: 80714
diff changeset
   306
    val if_False_diy_cong = @{thm if_False_diy_cong [cong_format]}
613417b3edad adapt and activate congprocs examples, following the current Simplifier implementation;
wenzelm
parents: 80714
diff changeset
   307
    val if_cong = @{thm if_cong [cong_format]}
80714
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
   308
  in
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
   309
    (K (fn ctxt => fn ct =>
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
   310
      let
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
   311
         val (_, [P, x, y]) = Drule.strip_comb ct
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
   312
         val P_eq = Simplifier.asm_full_rewrite ctxt P
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
   313
         val rhs = Thm.dest_equals_rhs (Thm.cprop_of P_eq)
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
   314
         val (rule, ts)  = (case Thm.term_of rhs of
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
   315
                       @{term True}  => (if_True_diy_cong, [x])
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
   316
                     | @{term False} => (if_False_diy_cong, [y])
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
   317
                     | _ => (if_cong, []) )
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
   318
         val eqs = map (Simplifier.asm_full_rewrite ctxt) ts \<comment> \<open>explicitly simplify the subterms\<close>
80715
613417b3edad adapt and activate congprocs examples, following the current Simplifier implementation;
wenzelm
parents: 80714
diff changeset
   319
      in
80714
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
   320
        SOME (rule OF (P_eq::eqs))
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
   321
      end))
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
   322
   end
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
   323
\<close>
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
   324
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
   325
experiment
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
   326
begin
80715
613417b3edad adapt and activate congprocs examples, following the current Simplifier implementation;
wenzelm
parents: 80714
diff changeset
   327
declare if_weak_cong [cong del]
613417b3edad adapt and activate congprocs examples, following the current Simplifier implementation;
wenzelm
parents: 80714
diff changeset
   328
declare [[simproc add: if_cong_diy, simp_trace]]
80714
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
   329
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
   330
ML_val \<open>
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
   331
@{cterm "if ((2::nat) < 3) then (if ((3::nat) < 2) then 20 + 1 else 20 + 2) else 20 + 3"}
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
   332
  |> Simplifier.asm_full_rewrite @{context}
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
   333
  |> assert @{cterm "22"}
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
   334
\<close>
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
   335
end
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
   336
80715
613417b3edad adapt and activate congprocs examples, following the current Simplifier implementation;
wenzelm
parents: 80714
diff changeset
   337
80714
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
   338
subsection \<open>Sketches for more meaningful congprocs\<close>
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
   339
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
   340
text \<open>One motivation for congprocs is the simplification of monadic terms which occur in the
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
   341
context of the verification of imperative programs. We use Imperative_HOL as an example here.
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
   342
In typical monadic programs we encounter lots of monadic binds and
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
   343
guards aka assertions. Typical assertions protect against arithmetic overflows, dangling pointers
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
   344
or might encode type information for some pointers. In particular when those assertions are
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
   345
mechanically generated, e.g. by refinement proofs, there tends to be a lot of redundancy in
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
   346
the assertions that are sprinkled all over the place in the program. Removing those redundant
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
   347
guards by simplification can be utilised by congprocs.
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
   348
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
   349
\<close>
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
   350
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
   351
text \<open>
80715
613417b3edad adapt and activate congprocs examples, following the current Simplifier implementation;
wenzelm
parents: 80714
diff changeset
   352
A first attempt for a congruence rule to propagate an assertion through a bind is the following:
80714
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
   353
We can assume the predicate when simplifying the 'body' \<^term>\<open>f\<close>:
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
   354
\<close>
80715
613417b3edad adapt and activate congprocs examples, following the current Simplifier implementation;
wenzelm
parents: 80714
diff changeset
   355
lemma assert_bind_cong':
80714
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
   356
  "(P x = P' x) \<Longrightarrow> (P x \<Longrightarrow> f = f') \<Longrightarrow> ((assert P x) \<bind> f) = ((assert P' x) \<bind> f')"
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
   357
  by (auto simp add: assert_def bind_def simp add: execute_raise split: option.splits)
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
   358
80715
613417b3edad adapt and activate congprocs examples, following the current Simplifier implementation;
wenzelm
parents: 80714
diff changeset
   359
text \<open>Unfortunately this is not a plain congruence rule that the simplifier can work with.
80714
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
   360
The problem is that congruence rules only work on the head constant of the left hand side of
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
   361
 the equation in the conclusion. This is \<^const>\<open>bind\<close>. But the rule is too specific as it only works
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
   362
for binds where the first monadic action is an \<^const>\<open>assert\<close>. Fortunately congprocs offer
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
   363
that flexibility. Like simprocs they can be triggered by patterns not only the head constant.
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
   364
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
   365
A slightly more abstract version, generalises the parameter \<^term>\<open>x\<close> for simplification of the body
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
   366
\<^term>\<open>f\<close>. This also illustrates the introduction of bound variables that are passed along through
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
   367
the \<^const>\<open>bind\<close>.
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
   368
\<close>
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
   369
80715
613417b3edad adapt and activate congprocs examples, following the current Simplifier implementation;
wenzelm
parents: 80714
diff changeset
   370
lemma assert_bind_cong:
80714
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
   371
  "(P x = P' x) \<Longrightarrow> (\<And>x. P x \<Longrightarrow> f x = f' x) \<Longrightarrow> ((assert P x) \<bind> f) = ((assert P' x) \<bind> f')"
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
   372
  by (auto simp add: assert_def bind_def simp add: execute_raise execute_return split: option.splits)
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
   373
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
   374
text \<open>Another typical use case is that a monadic action returns a tuple which is then propagated
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
   375
through the binds. The tuple is naturally stated in 'eta expanded' form like \<^term>\<open>\<lambda>(x,y). f x y\<close> such that the
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
   376
body can directly refer to the bound variables \<^term>\<open>x\<close> and \<^term>\<open>z\<close> and not via \<^const>\<open>fst\<close> and
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
   377
 \<^const>\<open>snd\<close>.\<close>
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
   378
80715
613417b3edad adapt and activate congprocs examples, following the current Simplifier implementation;
wenzelm
parents: 80714
diff changeset
   379
lemma assert_bind_cong2':
613417b3edad adapt and activate congprocs examples, following the current Simplifier implementation;
wenzelm
parents: 80714
diff changeset
   380
  "(P a b = P' a b) \<Longrightarrow> (P a b \<Longrightarrow> f a b = f' a b) \<Longrightarrow>
80714
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
   381
  ((assert (\<lambda>(x,y). P x y) (a,b)) \<bind> (\<lambda>(x,y). f x y)) = ((assert (\<lambda>(x,y). P' x y) (a,b)) \<bind> (\<lambda>(x,y). f' x y))"
80715
613417b3edad adapt and activate congprocs examples, following the current Simplifier implementation;
wenzelm
parents: 80714
diff changeset
   382
  apply (auto simp add: assert_def bind_def simp add: execute_raise execute_return
80714
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
   383
      split: option.splits)
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
   384
  done
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
   385
80715
613417b3edad adapt and activate congprocs examples, following the current Simplifier implementation;
wenzelm
parents: 80714
diff changeset
   386
lemma assert_bind_cong2:
613417b3edad adapt and activate congprocs examples, following the current Simplifier implementation;
wenzelm
parents: 80714
diff changeset
   387
  "(P a b = P' a b) \<Longrightarrow> (\<And>a b. P a b \<Longrightarrow> f a b = f' a b) \<Longrightarrow>
80714
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
   388
  ((assert (\<lambda>(x,y). P x y) (a,b)) \<bind> (\<lambda>(x,y). f x y)) = ((assert (\<lambda>(x,y). P' x y) (a,b)) \<bind> (\<lambda>(x,y). f' x y))"
80715
613417b3edad adapt and activate congprocs examples, following the current Simplifier implementation;
wenzelm
parents: 80714
diff changeset
   389
  apply (auto simp add: assert_def bind_def simp add: execute_raise execute_return
80714
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
   390
      split: option.splits)
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
   391
  done
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
   392
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
   393
lemma assert_True_cond[simp]: "P x \<Longrightarrow> ((assert P x) \<bind> f) = f x"
80715
613417b3edad adapt and activate congprocs examples, following the current Simplifier implementation;
wenzelm
parents: 80714
diff changeset
   394
  by (auto simp add: assert_def bind_def
80714
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
   395
      simp add: execute_return execute_raise split: option.splits)
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
   396
80715
613417b3edad adapt and activate congprocs examples, following the current Simplifier implementation;
wenzelm
parents: 80714
diff changeset
   397
simproc_setup passive congproc assert_bind_cong (\<open>(assert P x) \<bind> f\<close>) = \<open>
613417b3edad adapt and activate congprocs examples, following the current Simplifier implementation;
wenzelm
parents: 80714
diff changeset
   398
  K (K (K (SOME @{thm assert_bind_cong [cong_format]})))
80714
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
   399
\<close>
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
   400
80715
613417b3edad adapt and activate congprocs examples, following the current Simplifier implementation;
wenzelm
parents: 80714
diff changeset
   401
simproc_setup passive congproc assert_bind_cong2 (\<open>(assert P x) \<bind> f\<close>) = \<open>
613417b3edad adapt and activate congprocs examples, following the current Simplifier implementation;
wenzelm
parents: 80714
diff changeset
   402
  K (K (K (SOME @{thm assert_bind_cong2 [cong_format]})))
80714
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
   403
\<close>
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
   404
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
   405
experiment
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
   406
begin
80715
613417b3edad adapt and activate congprocs examples, following the current Simplifier implementation;
wenzelm
parents: 80714
diff changeset
   407
declare [[simproc add: assert_bind_cong]]
80714
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
   408
text \<open>The second assert is removed as expected.\<close>
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
   409
ML_val \<open>
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
   410
@{cterm "do {x <- assert P x; y <- assert P x; f y}"}
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
   411
  |> (Simplifier.asm_full_rewrite @{context})
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
   412
  |> assert_equiv @{cterm "assert P x \<bind> f"}
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
   413
\<close>
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
   414
end
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
   415
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
   416
experiment fixes a::nat
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
   417
begin
80715
613417b3edad adapt and activate congprocs examples, following the current Simplifier implementation;
wenzelm
parents: 80714
diff changeset
   418
declare [[simproc add: assert_bind_cong]]
80714
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
   419
text \<open>Does not work as expected due to issues with binding of the tuples\<close>
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
   420
ML_val \<open>
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
   421
@{cterm "do {(a, b) <- assert (\<lambda>(x,y). x < y) (a,b); (k,i) <- assert (\<lambda>(x,y). x < y)  (a, b); return (k < i)}"}
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
   422
  |> (Simplifier.asm_full_rewrite @{context})
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
   423
  |> assert_equiv @{cterm "assert (\<lambda>c. a < b) (a, b) \<bind>
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
   424
      (\<lambda>x. case x of (a, b) \<Rightarrow> assert (\<lambda>c. a < b) (a, b) \<bind> (\<lambda>x. case x of (k, i) \<Rightarrow> return (k < i)))"}
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
   425
\<close>
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
   426
end
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
   427
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
   428
experiment fixes a::nat
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
   429
begin
80715
613417b3edad adapt and activate congprocs examples, following the current Simplifier implementation;
wenzelm
parents: 80714
diff changeset
   430
declare [[simproc add: assert_bind_cong2]]
80714
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
   431
text \<open>Works as expected. The second assert is removed and the condition is propagated to the final
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
   432
 \<^const>\<open>return\<close>\<close>
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
   433
ML_val \<open>
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
   434
@{cterm "do {(a, b) <- assert (\<lambda>(x,y). x < y) (a,b); (k,i) <- assert (\<lambda>(x,y). x < y)  (a, b); return (k < i)}"}
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
   435
  |> (Simplifier.asm_full_rewrite @{context})
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
   436
  |> assert_equiv @{cterm "assert (\<lambda>(x, y). x < y) (a, b) \<bind> (\<lambda>(x, y). return True)"}
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
   437
\<close>
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
   438
end
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
   439
80715
613417b3edad adapt and activate congprocs examples, following the current Simplifier implementation;
wenzelm
parents: 80714
diff changeset
   440
text \<open>To properly handle tuples in general we cold of course refine our congproc to
80714
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
   441
analyse the arity of the \<^const>\<open>bind\<close> and then derive a variant of @{thm assert_bind_cong2} with the
80715
613417b3edad adapt and activate congprocs examples, following the current Simplifier implementation;
wenzelm
parents: 80714
diff changeset
   442
corresponding arity, 3, 4, 5... We leave this as a exercise for the reader.
80714
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
   443
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
   444
N.B. For the problem of tuple-splitting there sure are other solutions, e.g. normalising the
80715
613417b3edad adapt and activate congprocs examples, following the current Simplifier implementation;
wenzelm
parents: 80714
diff changeset
   445
program with @{thm case_prod_conv} or @{thm case_prod_unfold}. The drawback is that this usually
80714
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
   446
diminishes the readability of the monadic expression. Moreover, from a performance perspective it
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
   447
is usually better to split a rule like @{thm assert_bind_cong2}, which is abstract and of a fixed
80715
613417b3edad adapt and activate congprocs examples, following the current Simplifier implementation;
wenzelm
parents: 80714
diff changeset
   448
known small size, compared to normalisation of an unknown user defined  monadic expression which might
80714
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
   449
be quite sizeable.
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
   450
\<close>
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
   451
80715
613417b3edad adapt and activate congprocs examples, following the current Simplifier implementation;
wenzelm
parents: 80714
diff changeset
   452
80714
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
   453
subsection \<open>Customizing the context in congruence rules and congprocs\<close>
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
   454
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
   455
text \<open>
80715
613417b3edad adapt and activate congprocs examples, following the current Simplifier implementation;
wenzelm
parents: 80714
diff changeset
   456
When the simplifier works on a term it manages its context in the simpset. In
80714
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
   457
particular when 'going under' an abstraction \<open>\<lambda>x. ...\<close> it introduces a fresh free variable \<^term>\<open>x\<close>,
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
   458
substitutes it in the body and continues. Also when going under an implication \<^term>\<open>P \<Longrightarrow> C\<close> it
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
   459
assumes \<^term>\<open>P\<close>, extracts simplification rules from \<^term>\<open>P\<close> which it adds to the simpset and
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
   460
simplifies the conclusion \<^term>\<open>C\<close>. This pattern is what we typically encounter in congruence rules
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
   461
like @{thm assert_bind_cong2} where we have a precondition like
80715
613417b3edad adapt and activate congprocs examples, following the current Simplifier implementation;
wenzelm
parents: 80714
diff changeset
   462
 \<^term>\<open>\<And>a b. P a b \<Longrightarrow> f a b = f' a b\<close>. This advises the simplifier to fix \<^term>\<open>a\<close> and \<^term>\<open>b\<close>,
80714
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
   463
assume \<^term>\<open>P a b\<close>, extract simplification rules from that, and continue to simplify \<^term>\<open>f a b\<close>.
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
   464
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
   465
With congprocs we can go beyond this default behaviour of the simplifier as we are not restricted
80715
613417b3edad adapt and activate congprocs examples, following the current Simplifier implementation;
wenzelm
parents: 80714
diff changeset
   466
to the format of congruence rules. In the end we have to deliver an equation but are free how we
80714
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
   467
derive it. A common building block of such more refined congprocs is that we
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
   468
not only want to add \<^term>\<open>P a b\<close> to the simpset but want to enhance some other application specific
80715
613417b3edad adapt and activate congprocs examples, following the current Simplifier implementation;
wenzelm
parents: 80714
diff changeset
   469
data with that premise, e.g. add it to a collection of named theorems or come up with some derived facts
80714
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
   470
that we want to offer some other tool (like another simproc, or solver).
80715
613417b3edad adapt and activate congprocs examples, following the current Simplifier implementation;
wenzelm
parents: 80714
diff changeset
   471
The simpset already offers the possiblity to customise @{ML \<open>Simplifier.mksimps\<close>} which is a
80714
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
   472
function of type @{ML_type "Proof.context -> thm -> thm list"}. This function is used to derive equations
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
   473
from a premise like \<^term>\<open>P a b\<close> when it is added by the simplifier. We have extended that
80715
613417b3edad adapt and activate congprocs examples, following the current Simplifier implementation;
wenzelm
parents: 80714
diff changeset
   474
function to type @{ML_type "thm -> Proof.context -> thm list * Proof.context"} to give the user the
613417b3edad adapt and activate congprocs examples, following the current Simplifier implementation;
wenzelm
parents: 80714
diff changeset
   475
control to do additional modifications to the context:
613417b3edad adapt and activate congprocs examples, following the current Simplifier implementation;
wenzelm
parents: 80714
diff changeset
   476
@{ML Simplifier.get_mksimps_context}, @{ML Simplifier.set_mksimps_context}
80714
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
   477
The following contrived example illustrates the potential usage:
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
   478
\<close>
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
   479
80715
613417b3edad adapt and activate congprocs examples, following the current Simplifier implementation;
wenzelm
parents: 80714
diff changeset
   480
definition EXTRACT :: "bool \<Rightarrow> bool" where "EXTRACT P = P"
613417b3edad adapt and activate congprocs examples, following the current Simplifier implementation;
wenzelm
parents: 80714
diff changeset
   481
definition UNPROTECT :: "bool \<Rightarrow> bool" where "UNPROTECT P = P"
80714
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
   482
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
   483
lemma EXTRACT_TRUE_UNPROTECT_D: "EXTRACT P \<equiv> True \<Longrightarrow> (UNPROTECT P \<equiv> True)"
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
   484
  by (simp add: EXTRACT_def UNPROTECT_def)
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
   485
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
   486
named_theorems my_theorems
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
   487
80715
613417b3edad adapt and activate congprocs examples, following the current Simplifier implementation;
wenzelm
parents: 80714
diff changeset
   488
text \<open>We modify @{ML Simplifier.mksimps} to derive a theorem about \<^term>\<open>UNPROTECT P\<close> from
80714
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
   489
 \<^term>\<open>EXTRACT P\<close> and add it to the named theorems @{thm my_theorems}.\<close>
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
   490
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
   491
setup \<open>
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
   492
let
80715
613417b3edad adapt and activate congprocs examples, following the current Simplifier implementation;
wenzelm
parents: 80714
diff changeset
   493
  fun my_mksimps old_mksimps thm ctxt =
80714
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
   494
    let
80715
613417b3edad adapt and activate congprocs examples, following the current Simplifier implementation;
wenzelm
parents: 80714
diff changeset
   495
      val (thms, ctxt') = old_mksimps thm ctxt
80714
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
   496
      val thms' = map_filter (try (fn thm => @{thm EXTRACT_TRUE_UNPROTECT_D} OF [thm])) thms
80715
613417b3edad adapt and activate congprocs examples, following the current Simplifier implementation;
wenzelm
parents: 80714
diff changeset
   497
      val _ = tracing ("adding: " ^ @{make_string} thms' ^ " to my_theorems")
613417b3edad adapt and activate congprocs examples, following the current Simplifier implementation;
wenzelm
parents: 80714
diff changeset
   498
      val ctxt'' = ctxt' |> Context.proof_map (fold (Named_Theorems.add_thm @{named_theorems my_theorems}) thms')
80714
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
   499
    in
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
   500
      (thms, ctxt'' )
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
   501
    end
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
   502
in
80715
613417b3edad adapt and activate congprocs examples, following the current Simplifier implementation;
wenzelm
parents: 80714
diff changeset
   503
  Context.theory_map (fn context =>
613417b3edad adapt and activate congprocs examples, following the current Simplifier implementation;
wenzelm
parents: 80714
diff changeset
   504
    let val old_mksimps = Simplifier.get_mksimps_context (Context.proof_of context)
613417b3edad adapt and activate congprocs examples, following the current Simplifier implementation;
wenzelm
parents: 80714
diff changeset
   505
    in context |> Simplifier.map_ss (Simplifier.set_mksimps_context (my_mksimps old_mksimps)) end)
80714
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
   506
end
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
   507
\<close>
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
   508
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
   509
text \<open>We provide a simproc that matches on \<^term>\<open>UNPROTECT P\<close> and tries to solve it
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
   510
with rules in named theorems @{thm my_theorems}.\<close>
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
   511
simproc_setup UNPROTECT (\<open>UNPROTECT P\<close>) = \<open>fn _ => fn ctxt => fn ct =>
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
   512
  let
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
   513
    val thms = Named_Theorems.get ctxt @{named_theorems my_theorems}
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
   514
    val _ = tracing ("my_theorems: " ^ @{make_string} thms)
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
   515
    val eq = Simplifier.rewrite (ctxt addsimps thms) ct
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
   516
  in if Thm.is_reflexive eq then NONE else SOME eq end\<close>
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
   517
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
   518
lemma "EXTRACT P \<Longrightarrow> UNPROTECT P"
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
   519
  supply [[simp_trace]]
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
   520
  apply (simp)
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
   521
  done
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
   522
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
   523
text \<open>Illustrate the antiquotation.\<close>
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
   524
ML \<open>
80715
613417b3edad adapt and activate congprocs examples, following the current Simplifier implementation;
wenzelm
parents: 80714
diff changeset
   525
val conproc1 = \<^simproc_setup>\<open>passive weak_congproc if_cong1  ("if x then a else b") =
613417b3edad adapt and activate congprocs examples, following the current Simplifier implementation;
wenzelm
parents: 80714
diff changeset
   526
  \<open>(K (K (K (SOME @{thm if_cong [cong_format]}))))\<close>\<close>
80714
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
   527
\<close>
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
   528
055ac404d48d original Congproc_Ex.thy by Norbert Schirmer: still inactive;
wenzelm
parents:
diff changeset
   529
end