src/HOL/Integ/simproc.ML
author oheimb
Thu, 24 Sep 1998 17:17:14 +0200
changeset 5553 ae42b36a50c2
parent 5501 a63e0c326e6c
child 5582 a356fb49e69e
permissions -rw-r--r--
renamed mk_meta_eq to mk_eq
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
5501
a63e0c326e6c new files in Integ
paulson
parents:
diff changeset
     1
(*  Title:      HOL/Integ/simproc
a63e0c326e6c new files in Integ
paulson
parents:
diff changeset
     2
    ID:         $Id$
a63e0c326e6c new files in Integ
paulson
parents:
diff changeset
     3
    Author:     Lawrence C Paulson, Cambridge University Computer Laboratory
a63e0c326e6c new files in Integ
paulson
parents:
diff changeset
     4
    Copyright   1998  University of Cambridge
a63e0c326e6c new files in Integ
paulson
parents:
diff changeset
     5
a63e0c326e6c new files in Integ
paulson
parents:
diff changeset
     6
Simplification procedures for the integers
a63e0c326e6c new files in Integ
paulson
parents:
diff changeset
     7
a63e0c326e6c new files in Integ
paulson
parents:
diff changeset
     8
This one cancels complementary terms in sums.  Examples:
a63e0c326e6c new files in Integ
paulson
parents:
diff changeset
     9
   x + (y + -x)   =   x + (-x + y)  =  y
a63e0c326e6c new files in Integ
paulson
parents:
diff changeset
    10
   -x + (y + (x + z))   =   -x + (x + (y + z))  =  y + z
a63e0c326e6c new files in Integ
paulson
parents:
diff changeset
    11
a63e0c326e6c new files in Integ
paulson
parents:
diff changeset
    12
Should be used with zdiff_def (to eliminate subtraction) and zadd_ac.
a63e0c326e6c new files in Integ
paulson
parents:
diff changeset
    13
*)
a63e0c326e6c new files in Integ
paulson
parents:
diff changeset
    14
a63e0c326e6c new files in Integ
paulson
parents:
diff changeset
    15
a63e0c326e6c new files in Integ
paulson
parents:
diff changeset
    16
structure Int_Cancel =
a63e0c326e6c new files in Integ
paulson
parents:
diff changeset
    17
struct
a63e0c326e6c new files in Integ
paulson
parents:
diff changeset
    18
a63e0c326e6c new files in Integ
paulson
parents:
diff changeset
    19
val intT = Type ("IntDef.int", []);
a63e0c326e6c new files in Integ
paulson
parents:
diff changeset
    20
a63e0c326e6c new files in Integ
paulson
parents:
diff changeset
    21
val zplus = Const ("op +", [intT,intT] ---> intT);
a63e0c326e6c new files in Integ
paulson
parents:
diff changeset
    22
val zminus = Const ("uminus", intT --> intT);
a63e0c326e6c new files in Integ
paulson
parents:
diff changeset
    23
a63e0c326e6c new files in Integ
paulson
parents:
diff changeset
    24
val ssubst_left = read_instantiate [("P", "%x. ?lhs x = ?rhs")] ssubst;
a63e0c326e6c new files in Integ
paulson
parents:
diff changeset
    25
a63e0c326e6c new files in Integ
paulson
parents:
diff changeset
    26
fun inst_left_commute ct = instantiate' [] [None, Some ct] zadd_left_commute;
a63e0c326e6c new files in Integ
paulson
parents:
diff changeset
    27
a63e0c326e6c new files in Integ
paulson
parents:
diff changeset
    28
(*Can LOOP, so include only if the first occurrence at the very end*)
a63e0c326e6c new files in Integ
paulson
parents:
diff changeset
    29
fun inst_commute ct = instantiate' [] [None, Some ct] zadd_commute;
a63e0c326e6c new files in Integ
paulson
parents:
diff changeset
    30
a63e0c326e6c new files in Integ
paulson
parents:
diff changeset
    31
fun terms (t as f$x$y) =
a63e0c326e6c new files in Integ
paulson
parents:
diff changeset
    32
        if f=zplus then x :: terms y else [t]
a63e0c326e6c new files in Integ
paulson
parents:
diff changeset
    33
  | terms t = [t];
a63e0c326e6c new files in Integ
paulson
parents:
diff changeset
    34
a63e0c326e6c new files in Integ
paulson
parents:
diff changeset
    35
val mk_sum = foldr1 (fn (x,y) => zplus $ x $ y);
a63e0c326e6c new files in Integ
paulson
parents:
diff changeset
    36
a63e0c326e6c new files in Integ
paulson
parents:
diff changeset
    37
(*We map -t to t and (in other cases) t to -t.  No need to check the type of
a63e0c326e6c new files in Integ
paulson
parents:
diff changeset
    38
  uminus, since the simproc is only called on integer sums.*)
a63e0c326e6c new files in Integ
paulson
parents:
diff changeset
    39
fun negate (Const("uminus",_) $ t) = t
a63e0c326e6c new files in Integ
paulson
parents:
diff changeset
    40
  | negate t                       = zminus $ t;
a63e0c326e6c new files in Integ
paulson
parents:
diff changeset
    41
a63e0c326e6c new files in Integ
paulson
parents:
diff changeset
    42
(*These rules eliminate the first two terms, if they cancel*)
a63e0c326e6c new files in Integ
paulson
parents:
diff changeset
    43
val cancel_laws = [zadd_zminus_cancel, zminus_zadd_cancel];
a63e0c326e6c new files in Integ
paulson
parents:
diff changeset
    44
a63e0c326e6c new files in Integ
paulson
parents:
diff changeset
    45
exception Cancel;
a63e0c326e6c new files in Integ
paulson
parents:
diff changeset
    46
a63e0c326e6c new files in Integ
paulson
parents:
diff changeset
    47
(*Cancels just the first occurrence of head', leaving the rest unchanged*)
a63e0c326e6c new files in Integ
paulson
parents:
diff changeset
    48
fun cancelled head' tail =
a63e0c326e6c new files in Integ
paulson
parents:
diff changeset
    49
    let fun find ([], _) = raise Cancel
a63e0c326e6c new files in Integ
paulson
parents:
diff changeset
    50
	  | find (t::ts, heads) = if head' aconv t then rev heads @ ts
a63e0c326e6c new files in Integ
paulson
parents:
diff changeset
    51
				  else find (ts, t::heads)
a63e0c326e6c new files in Integ
paulson
parents:
diff changeset
    52
    in  mk_sum (find (tail, []))  end;
a63e0c326e6c new files in Integ
paulson
parents:
diff changeset
    53
a63e0c326e6c new files in Integ
paulson
parents:
diff changeset
    54
a63e0c326e6c new files in Integ
paulson
parents:
diff changeset
    55
val trace = ref false;
a63e0c326e6c new files in Integ
paulson
parents:
diff changeset
    56
a63e0c326e6c new files in Integ
paulson
parents:
diff changeset
    57
fun proc sg _ lhs =
a63e0c326e6c new files in Integ
paulson
parents:
diff changeset
    58
  let val _ = if !trace then prs ("lhs = " ^ string_of_cterm (cterm_of sg lhs))
a63e0c326e6c new files in Integ
paulson
parents:
diff changeset
    59
              else ()
a63e0c326e6c new files in Integ
paulson
parents:
diff changeset
    60
      val (head::tail) = terms lhs
a63e0c326e6c new files in Integ
paulson
parents:
diff changeset
    61
      val head' = negate head
a63e0c326e6c new files in Integ
paulson
parents:
diff changeset
    62
      val rhs = cancelled head' tail
a63e0c326e6c new files in Integ
paulson
parents:
diff changeset
    63
      and chead' = Thm.cterm_of sg head'
a63e0c326e6c new files in Integ
paulson
parents:
diff changeset
    64
      val comms = [inst_left_commute chead' RS ssubst_left,
a63e0c326e6c new files in Integ
paulson
parents:
diff changeset
    65
		   inst_commute chead' RS ssubst_left]
a63e0c326e6c new files in Integ
paulson
parents:
diff changeset
    66
      val _ = if !trace then 
a63e0c326e6c new files in Integ
paulson
parents:
diff changeset
    67
	        writeln ("rhs = " ^ string_of_cterm (Thm.cterm_of sg rhs))
a63e0c326e6c new files in Integ
paulson
parents:
diff changeset
    68
              else ()
a63e0c326e6c new files in Integ
paulson
parents:
diff changeset
    69
      val ct = Thm.cterm_of sg (HOLogic.mk_Trueprop (HOLogic.mk_eq (lhs, rhs)))
a63e0c326e6c new files in Integ
paulson
parents:
diff changeset
    70
      (*Simplification is much faster than substitution, but loops for terms
a63e0c326e6c new files in Integ
paulson
parents:
diff changeset
    71
        like (x + (-x + (-x + y))).  Substitution finds the outermost -x, so
a63e0c326e6c new files in Integ
paulson
parents:
diff changeset
    72
        is seems not to loop, and the counter prevents looping for sure.*)
a63e0c326e6c new files in Integ
paulson
parents:
diff changeset
    73
      fun cancel_tac 0 = no_tac   
a63e0c326e6c new files in Integ
paulson
parents:
diff changeset
    74
	| cancel_tac n = 
a63e0c326e6c new files in Integ
paulson
parents:
diff changeset
    75
	      (resolve_tac cancel_laws 1 ORELSE
a63e0c326e6c new files in Integ
paulson
parents:
diff changeset
    76
	       resolve_tac comms 1 THEN cancel_tac (n-1));
a63e0c326e6c new files in Integ
paulson
parents:
diff changeset
    77
      val thm = prove_goalw_cterm [] ct 
a63e0c326e6c new files in Integ
paulson
parents:
diff changeset
    78
	          (fn _ => [cancel_tac (length tail + 1)])
a63e0c326e6c new files in Integ
paulson
parents:
diff changeset
    79
	handle ERROR =>
a63e0c326e6c new files in Integ
paulson
parents:
diff changeset
    80
	error("The error(s) above occurred while trying to prove " ^
a63e0c326e6c new files in Integ
paulson
parents:
diff changeset
    81
	      string_of_cterm ct)
5553
ae42b36a50c2 renamed mk_meta_eq to mk_eq
oheimb
parents: 5501
diff changeset
    82
  in Some (mk_meta_eq thm) end
5501
a63e0c326e6c new files in Integ
paulson
parents:
diff changeset
    83
  handle Cancel => None;
a63e0c326e6c new files in Integ
paulson
parents:
diff changeset
    84
a63e0c326e6c new files in Integ
paulson
parents:
diff changeset
    85
a63e0c326e6c new files in Integ
paulson
parents:
diff changeset
    86
val conv = 
a63e0c326e6c new files in Integ
paulson
parents:
diff changeset
    87
    Simplifier.mk_simproc "cancel_sums"
a63e0c326e6c new files in Integ
paulson
parents:
diff changeset
    88
      [Thm.read_cterm (sign_of IntDef.thy) ("x + (y + (z::int))", intT)]
a63e0c326e6c new files in Integ
paulson
parents:
diff changeset
    89
      proc;
a63e0c326e6c new files in Integ
paulson
parents:
diff changeset
    90
a63e0c326e6c new files in Integ
paulson
parents:
diff changeset
    91
end;
a63e0c326e6c new files in Integ
paulson
parents:
diff changeset
    92
a63e0c326e6c new files in Integ
paulson
parents:
diff changeset
    93
a63e0c326e6c new files in Integ
paulson
parents:
diff changeset
    94
Addsimprocs [Int_Cancel.conv];
a63e0c326e6c new files in Integ
paulson
parents:
diff changeset
    95