src/Provers/Arith/cancel_sums.ML
 author wenzelm Mon, 16 Nov 1998 13:54:35 +0100 changeset 5897 b3548f939dd2 parent 4452 b2ee34200dab child 15027 d23887300b96 permissions -rw-r--r--
removed genelim.ML;
```
(*  Title:      Provers/Arith/cancel_sums.ML
ID:         \$Id\$
Author:     Markus Wenzel and Stefan Berghofer, TU Muenchen

Cancel common summands of balanced expressions:

A + x + B ~~ A' + x + B'  ==  A + B ~~ A' + B'

where + is AC0 and ~~ an appropriate balancing operation (e.g. =, <=, <, -).
*)

signature CANCEL_SUMS_DATA =
sig
(*abstract syntax*)
val mk_sum: term list -> term
val dest_sum: term -> term list
val mk_bal: term * term -> term
val dest_bal: term -> term * term
(*rules*)
val prove_conv: tactic -> tactic -> Sign.sg -> term * term -> thm
val norm_tac: tactic                   	(*AC0 etc.*)
val uncancel_tac: cterm -> tactic      	(*apply A ~~ B  ==  x + A ~~ x + B*)
end;

signature CANCEL_SUMS =
sig
val proc: Sign.sg -> thm list -> term -> thm option
end;

functor CancelSumsFun(Data: CANCEL_SUMS_DATA): CANCEL_SUMS =
struct

(* cancel *)

fun cons1 x (xs, y, z) = (x :: xs, y, z);
fun cons2 y (x, ys, z) = (x, y :: ys, z);
fun cons12 x y (xs, ys, z) = (x :: xs, y :: ys, z);

(*symmetric difference of multisets -- assumed to be sorted wrt. Logic.term_ord*)
fun cancel ts [] vs = (ts, [], vs)
| cancel [] us vs = ([], us, vs)
| cancel (t :: ts) (u :: us) vs =
(case Term.term_ord (t, u) of
EQUAL => cancel ts us (t :: vs)
| LESS => cons1 t (cancel ts (u :: us) vs)
| GREATER => cons2 u (cancel (t :: ts) us vs));

(* uncancel *)

fun uncancel_sums_tac _ [] = all_tac
| uncancel_sums_tac sg (t :: ts) =
Data.uncancel_tac (Thm.cterm_of sg t) THEN
uncancel_sums_tac sg ts;

(* the simplification procedure *)

fun proc sg _ t =
(case try Data.dest_bal t of
None => None
| Some bal =>
let
val (ts, us) = pairself (sort Term.term_ord o Data.dest_sum) bal;
val (ts', us', vs) = cancel ts us [];
in
if null vs then None
else Some
(Data.prove_conv (uncancel_sums_tac sg vs) Data.norm_tac sg
(t, Data.mk_bal (Data.mk_sum ts', Data.mk_sum us')))
end);

end;
```