src/HOL/Tools/abel_cancel.ML
author wenzelm
Thu, 24 Nov 2011 21:01:06 +0100
changeset 45625 750c5a47400b
parent 45464 5a5a6e6c6789
permissions -rw-r--r--
modernized some old-style infix operations, which were left over from the time of ML proof scripts;
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
37884
314a88278715 discontinued pretending that abel_cancel is logic-independent; cleaned up junk
haftmann
parents: 35845
diff changeset
     1
(*  Title:      HOL/Tools/abel_cancel.ML
5589
94c05305fb29 new simproc functor
paulson
parents:
diff changeset
     2
    Author:     Lawrence C Paulson, Cambridge University Computer Laboratory
94c05305fb29 new simproc functor
paulson
parents:
diff changeset
     3
    Copyright   1998  University of Cambridge
94c05305fb29 new simproc functor
paulson
parents:
diff changeset
     4
37884
314a88278715 discontinued pretending that abel_cancel is logic-independent; cleaned up junk
haftmann
parents: 35845
diff changeset
     5
Simplification procedures for abelian groups:
314a88278715 discontinued pretending that abel_cancel is logic-independent; cleaned up junk
haftmann
parents: 35845
diff changeset
     6
- Cancel complementary terms in sums.
314a88278715 discontinued pretending that abel_cancel is logic-independent; cleaned up junk
haftmann
parents: 35845
diff changeset
     7
- Cancel like terms on opposite sides of relations.
5589
94c05305fb29 new simproc functor
paulson
parents:
diff changeset
     8
*)
94c05305fb29 new simproc functor
paulson
parents:
diff changeset
     9
94c05305fb29 new simproc functor
paulson
parents:
diff changeset
    10
signature ABEL_CANCEL =
94c05305fb29 new simproc functor
paulson
parents:
diff changeset
    11
sig
37890
aae46a9ef66c modernized abel_cancel simproc setup
haftmann
parents: 37884
diff changeset
    12
  val sum_proc: simpset -> cterm -> thm option
aae46a9ef66c modernized abel_cancel simproc setup
haftmann
parents: 37884
diff changeset
    13
  val rel_proc: simpset -> cterm -> thm option
5589
94c05305fb29 new simproc functor
paulson
parents:
diff changeset
    14
end;
94c05305fb29 new simproc functor
paulson
parents:
diff changeset
    15
37884
314a88278715 discontinued pretending that abel_cancel is logic-independent; cleaned up junk
haftmann
parents: 35845
diff changeset
    16
structure Abel_Cancel: ABEL_CANCEL =
5589
94c05305fb29 new simproc functor
paulson
parents:
diff changeset
    17
struct
94c05305fb29 new simproc functor
paulson
parents:
diff changeset
    18
37894
b22db9ecf416 tuned code
haftmann
parents: 37890
diff changeset
    19
(** compute cancellation **)
5728
1d1175ef2d56 eliminated 'let ... in structure ...' to make SML/NJ 0.93 happy;
wenzelm
parents: 5610
diff changeset
    20
37894
b22db9ecf416 tuned code
haftmann
parents: 37890
diff changeset
    21
fun add_atoms pos (Const (@{const_name Groups.plus}, _) $ x $ y) =
b22db9ecf416 tuned code
haftmann
parents: 37890
diff changeset
    22
      add_atoms pos x #> add_atoms pos y
b22db9ecf416 tuned code
haftmann
parents: 37890
diff changeset
    23
  | add_atoms pos (Const (@{const_name Groups.minus}, _) $ x $ y) =
b22db9ecf416 tuned code
haftmann
parents: 37890
diff changeset
    24
      add_atoms pos x #> add_atoms (not pos) y
b22db9ecf416 tuned code
haftmann
parents: 37890
diff changeset
    25
  | add_atoms pos (Const (@{const_name Groups.uminus}, _) $ x) =
b22db9ecf416 tuned code
haftmann
parents: 37890
diff changeset
    26
      add_atoms (not pos) x
45464
5a5a6e6c6789 abel_cancel.ML: avoid canceling zeros, which would cause the simproc to return a trivial rewrite;
huffman
parents: 38715
diff changeset
    27
  | add_atoms pos (Const (@{const_name Groups.zero}, _)) = I
37894
b22db9ecf416 tuned code
haftmann
parents: 37890
diff changeset
    28
  | add_atoms pos x = cons (pos, x);
37884
314a88278715 discontinued pretending that abel_cancel is logic-independent; cleaned up junk
haftmann
parents: 35845
diff changeset
    29
37896
haftmann
parents: 37895
diff changeset
    30
fun atoms t = add_atoms true t [];
5589
94c05305fb29 new simproc functor
paulson
parents:
diff changeset
    31
37896
haftmann
parents: 37895
diff changeset
    32
fun zerofy pt ((c as Const (@{const_name Groups.plus}, _)) $ x $ y) =
haftmann
parents: 37895
diff changeset
    33
      (case zerofy pt x of NONE =>
haftmann
parents: 37895
diff changeset
    34
        (case zerofy pt y of NONE => NONE
haftmann
parents: 37895
diff changeset
    35
         | SOME z => SOME (c $ x $ z))
37894
b22db9ecf416 tuned code
haftmann
parents: 37890
diff changeset
    36
       | SOME z => SOME (c $ z $ y))
37896
haftmann
parents: 37895
diff changeset
    37
  | zerofy pt ((c as Const (@{const_name Groups.minus}, _)) $ x $ y) =
haftmann
parents: 37895
diff changeset
    38
      (case zerofy pt x of NONE =>
haftmann
parents: 37895
diff changeset
    39
        (case zerofy (apfst not pt) y of NONE => NONE
haftmann
parents: 37895
diff changeset
    40
         | SOME z => SOME (c $ x $ z))
37894
b22db9ecf416 tuned code
haftmann
parents: 37890
diff changeset
    41
       | SOME z => SOME (c $ z $ y))
37896
haftmann
parents: 37895
diff changeset
    42
  | zerofy pt ((c as Const (@{const_name Groups.uminus}, _)) $ x) =
haftmann
parents: 37895
diff changeset
    43
      (case zerofy (apfst not pt) x of NONE => NONE
37894
b22db9ecf416 tuned code
haftmann
parents: 37890
diff changeset
    44
       | SOME z => SOME (c $ z))
37896
haftmann
parents: 37895
diff changeset
    45
  | zerofy (pos, t) u =
37894
b22db9ecf416 tuned code
haftmann
parents: 37890
diff changeset
    46
      if pos andalso (t aconv u)
b22db9ecf416 tuned code
haftmann
parents: 37890
diff changeset
    47
        then SOME (Const (@{const_name Groups.zero}, fastype_of t))
b22db9ecf416 tuned code
haftmann
parents: 37890
diff changeset
    48
        else NONE
5589
94c05305fb29 new simproc functor
paulson
parents:
diff changeset
    49
20055
24c127b97ab5 simprocs: no theory argument -- use simpset context instead;
wenzelm
parents: 19798
diff changeset
    50
exception Cancel;
5589
94c05305fb29 new simproc functor
paulson
parents:
diff changeset
    51
16569
a12992c34c12 cancels completely within terms as well now.
nipkow
parents: 16423
diff changeset
    52
fun find_common _ [] _ = raise Cancel
37894
b22db9ecf416 tuned code
haftmann
parents: 37890
diff changeset
    53
  | find_common opp ((p, l) :: ls) rs =
16569
a12992c34c12 cancels completely within terms as well now.
nipkow
parents: 16423
diff changeset
    54
      let val pr = if opp then not p else p
37894
b22db9ecf416 tuned code
haftmann
parents: 37890
diff changeset
    55
      in if exists (fn (q, r) => pr = q andalso l aconv r) rs then (p, l)
16569
a12992c34c12 cancels completely within terms as well now.
nipkow
parents: 16423
diff changeset
    56
         else find_common opp ls rs
a12992c34c12 cancels completely within terms as well now.
nipkow
parents: 16423
diff changeset
    57
      end
5589
94c05305fb29 new simproc functor
paulson
parents:
diff changeset
    58
16569
a12992c34c12 cancels completely within terms as well now.
nipkow
parents: 16423
diff changeset
    59
(* turns t1(t) OP t2(t) into t1(0) OP t2(0) where OP can be +, -, =, etc.
a12992c34c12 cancels completely within terms as well now.
nipkow
parents: 16423
diff changeset
    60
   If OP = +, it must be t2(-t) rather than t2(t)
a12992c34c12 cancels completely within terms as well now.
nipkow
parents: 16423
diff changeset
    61
*)
37896
haftmann
parents: 37895
diff changeset
    62
fun cancel (c $ lhs $ rhs) =
20055
24c127b97ab5 simprocs: no theory argument -- use simpset context instead;
wenzelm
parents: 19798
diff changeset
    63
  let
37894
b22db9ecf416 tuned code
haftmann
parents: 37890
diff changeset
    64
    val opp = case c of Const(@{const_name Groups.plus}, _) => true | _ => false;
b22db9ecf416 tuned code
haftmann
parents: 37890
diff changeset
    65
    val (pos, l) = find_common opp (atoms lhs) (atoms rhs);
b22db9ecf416 tuned code
haftmann
parents: 37890
diff changeset
    66
    val posr = if opp then not pos else pos;
37896
haftmann
parents: 37895
diff changeset
    67
  in c $ the (zerofy (pos, l) lhs) $ the (zerofy (posr, l) rhs) end;
16569
a12992c34c12 cancels completely within terms as well now.
nipkow
parents: 16423
diff changeset
    68
a12992c34c12 cancels completely within terms as well now.
nipkow
parents: 16423
diff changeset
    69
37894
b22db9ecf416 tuned code
haftmann
parents: 37890
diff changeset
    70
(** prove cancellation **)
b22db9ecf416 tuned code
haftmann
parents: 37890
diff changeset
    71
b22db9ecf416 tuned code
haftmann
parents: 37890
diff changeset
    72
fun agrp_ord (Const (a, _)) = find_index (fn a' => a = a')
b22db9ecf416 tuned code
haftmann
parents: 37890
diff changeset
    73
      [@{const_name Groups.zero}, @{const_name Groups.plus},
b22db9ecf416 tuned code
haftmann
parents: 37890
diff changeset
    74
        @{const_name Groups.uminus}, @{const_name Groups.minus}]
b22db9ecf416 tuned code
haftmann
parents: 37890
diff changeset
    75
  | agrp_ord _ = ~1;
b22db9ecf416 tuned code
haftmann
parents: 37890
diff changeset
    76
b22db9ecf416 tuned code
haftmann
parents: 37890
diff changeset
    77
fun less_agrp (a, b) = (Term_Ord.term_lpo agrp_ord (a, b) = LESS);
b22db9ecf416 tuned code
haftmann
parents: 37890
diff changeset
    78
b22db9ecf416 tuned code
haftmann
parents: 37890
diff changeset
    79
fun solve (_ $ (Const (@{const_name Groups.plus}, _) $ _ $ _) $ _) =
b22db9ecf416 tuned code
haftmann
parents: 37890
diff changeset
    80
      SOME @{thm add_assoc [THEN eq_reflection]}
b22db9ecf416 tuned code
haftmann
parents: 37890
diff changeset
    81
  | solve (_ $ x $ (Const (@{const_name Groups.plus}, _) $ y $ _)) =
b22db9ecf416 tuned code
haftmann
parents: 37890
diff changeset
    82
      if less_agrp (y, x) then
b22db9ecf416 tuned code
haftmann
parents: 37890
diff changeset
    83
        SOME @{thm add_left_commute [THEN eq_reflection]}
b22db9ecf416 tuned code
haftmann
parents: 37890
diff changeset
    84
        else NONE
b22db9ecf416 tuned code
haftmann
parents: 37890
diff changeset
    85
  | solve (_ $ x $ y) =
b22db9ecf416 tuned code
haftmann
parents: 37890
diff changeset
    86
      if less_agrp (y, x) then
b22db9ecf416 tuned code
haftmann
parents: 37890
diff changeset
    87
        SOME @{thm add_commute [THEN eq_reflection]} else
b22db9ecf416 tuned code
haftmann
parents: 37890
diff changeset
    88
        NONE
b22db9ecf416 tuned code
haftmann
parents: 37890
diff changeset
    89
  | solve _ = NONE;
b22db9ecf416 tuned code
haftmann
parents: 37890
diff changeset
    90
  
38715
6513ea67d95d renamed Simplifier.simproc(_i) to Simplifier.simproc_global(_i) to emphasize that this is not the real thing;
wenzelm
parents: 37896
diff changeset
    91
val simproc = Simplifier.simproc_global @{theory}
37894
b22db9ecf416 tuned code
haftmann
parents: 37890
diff changeset
    92
  "add_ac_proc" ["x + y::'a::ab_semigroup_add"] ((K o K) solve);
b22db9ecf416 tuned code
haftmann
parents: 37890
diff changeset
    93
45625
750c5a47400b modernized some old-style infix operations, which were left over from the time of ML proof scripts;
wenzelm
parents: 45464
diff changeset
    94
val cancel_ss = (HOL_basic_ss |> Simplifier.set_termless less_agrp)
37894
b22db9ecf416 tuned code
haftmann
parents: 37890
diff changeset
    95
  addsimprocs [simproc] addsimps
b22db9ecf416 tuned code
haftmann
parents: 37890
diff changeset
    96
  [@{thm add_0_left}, @{thm add_0_right}, @{thm diff_minus},
b22db9ecf416 tuned code
haftmann
parents: 37890
diff changeset
    97
   @{thm minus_add_distrib}, @{thm minus_minus}, @{thm minus_zero},
b22db9ecf416 tuned code
haftmann
parents: 37890
diff changeset
    98
   @{thm right_minus}, @{thm left_minus}, @{thm add_minus_cancel},
b22db9ecf416 tuned code
haftmann
parents: 37890
diff changeset
    99
   @{thm minus_add_cancel}];
b22db9ecf416 tuned code
haftmann
parents: 37890
diff changeset
   100
b22db9ecf416 tuned code
haftmann
parents: 37890
diff changeset
   101
fun cancel_simp_tac ss = simp_tac (Simplifier.inherit_context ss cancel_ss);
b22db9ecf416 tuned code
haftmann
parents: 37890
diff changeset
   102
b22db9ecf416 tuned code
haftmann
parents: 37890
diff changeset
   103
b22db9ecf416 tuned code
haftmann
parents: 37890
diff changeset
   104
(** simprocs **)
b22db9ecf416 tuned code
haftmann
parents: 37890
diff changeset
   105
b22db9ecf416 tuned code
haftmann
parents: 37890
diff changeset
   106
(* cancel complementary terms in arbitrary sums *)
b22db9ecf416 tuned code
haftmann
parents: 37890
diff changeset
   107
37890
aae46a9ef66c modernized abel_cancel simproc setup
haftmann
parents: 37884
diff changeset
   108
fun sum_proc ss ct =
aae46a9ef66c modernized abel_cancel simproc setup
haftmann
parents: 37884
diff changeset
   109
  let
aae46a9ef66c modernized abel_cancel simproc setup
haftmann
parents: 37884
diff changeset
   110
    val t = Thm.term_of ct;
37896
haftmann
parents: 37895
diff changeset
   111
    val prop = Logic.mk_equals (t, cancel t);
haftmann
parents: 37895
diff changeset
   112
    val thm = Goal.prove (Simplifier.the_context ss) [] [] prop
haftmann
parents: 37895
diff changeset
   113
      (fn _ => cancel_simp_tac ss 1)
37890
aae46a9ef66c modernized abel_cancel simproc setup
haftmann
parents: 37884
diff changeset
   114
  in SOME thm end handle Cancel => NONE;
5589
94c05305fb29 new simproc functor
paulson
parents:
diff changeset
   115
94c05305fb29 new simproc functor
paulson
parents:
diff changeset
   116
37894
b22db9ecf416 tuned code
haftmann
parents: 37890
diff changeset
   117
(* cancel like terms on the opposite sides of relations:
b22db9ecf416 tuned code
haftmann
parents: 37890
diff changeset
   118
    (x + y - z < -z + x) = (y < 0)
b22db9ecf416 tuned code
haftmann
parents: 37890
diff changeset
   119
   Works for (=) and (<=) as well as (<), if the necessary rules are supplied.
b22db9ecf416 tuned code
haftmann
parents: 37890
diff changeset
   120
   Reduces the problem to subtraction. *)
b22db9ecf416 tuned code
haftmann
parents: 37890
diff changeset
   121
37890
aae46a9ef66c modernized abel_cancel simproc setup
haftmann
parents: 37884
diff changeset
   122
fun rel_proc ss ct =
20055
24c127b97ab5 simprocs: no theory argument -- use simpset context instead;
wenzelm
parents: 19798
diff changeset
   123
  let
37890
aae46a9ef66c modernized abel_cancel simproc setup
haftmann
parents: 37884
diff changeset
   124
    val t = Thm.term_of ct;
37896
haftmann
parents: 37895
diff changeset
   125
    val prop = Logic.mk_equals (t, cancel t);
haftmann
parents: 37895
diff changeset
   126
    val thm = Goal.prove (Simplifier.the_context ss) [] [] prop
37884
314a88278715 discontinued pretending that abel_cancel is logic-independent; cleaned up junk
haftmann
parents: 35845
diff changeset
   127
      (fn _ => rtac @{thm eq_reflection} 1 THEN
37896
haftmann
parents: 37895
diff changeset
   128
        resolve_tac [@{thm diff_eq_diff_less}, @{thm diff_eq_diff_less_eq}, @{thm diff_eq_diff_eq}] 1 THEN
haftmann
parents: 37895
diff changeset
   129
        cancel_simp_tac ss 1)
37890
aae46a9ef66c modernized abel_cancel simproc setup
haftmann
parents: 37884
diff changeset
   130
  in SOME thm end handle Cancel => NONE;
5589
94c05305fb29 new simproc functor
paulson
parents:
diff changeset
   131
94c05305fb29 new simproc functor
paulson
parents:
diff changeset
   132
end;