for cancelling div + mod.
authornipkow
Fri, 23 Aug 2002 07:34:20 +0200
changeset 13516 13a6103b9ac4
parent 13515 a6a7025fd7e8
child 13517 42efec18f5b2
for cancelling div + mod.
src/Provers/Arith/cancel_div_mod.ML
src/Provers/Arith/fast_lin_arith.ML
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/Provers/Arith/cancel_div_mod.ML	Fri Aug 23 07:34:20 2002 +0200
@@ -0,0 +1,82 @@
+(*  Title:      Provers/Arith/cancel_div_mod.ML
+    ID:         $Id$
+    Author:     Tobias Nipkow, TU Muenchen
+
+Cancel div and mod terms:
+
+  A + n*(m div n) + B + (m mod n) + C  ==  A + B + C + m
+
+Is parameterized but assumes for simplicity that + and * are called
+"op +" and "op *"
+*)
+
+signature CANCEL_DIV_MOD_DATA =
+sig
+  (*abstract syntax*)
+  val div_name: string
+  val mod_name: string
+  val mk_binop: string -> term * term -> term
+  val mk_sum: term list -> term
+  val dest_sum: term -> term list
+  (*logic*)
+  val div_mod_eqs: thm list
+  (* (n*(m div n) + m mod n) + k == m + k and
+     ((m div n)*n + m mod n) + k == m + k *)
+  val prove_eq_sums: Sign.sg -> term * term -> thm
+  (* must prove ac0-equivalence of sums *)
+end;
+
+signature CANCEL_DIV_MOD =
+sig
+  val proc: Sign.sg -> thm list -> term -> thm option
+end;
+
+
+functor CancelDivModFun(Data: CANCEL_DIV_MOD_DATA): CANCEL_DIV_MOD =
+struct
+
+fun coll_div_mod (Const("op +",_) $ s $ t) dms =
+      coll_div_mod t (coll_div_mod s dms)
+  | coll_div_mod (Const("op *",_) $ m $ (Const(d,_) $ s $ n))
+                 (dms as (divs,mods)) =
+      if d = Data.div_name andalso m=n then ((s,n)::divs,mods) else dms
+  | coll_div_mod (Const("op *",_) $ (Const(d,_) $ s $ n) $ m)
+                 (dms as (divs,mods)) =
+      if d = Data.div_name andalso m=n then ((s,n)::divs,mods) else dms
+  | coll_div_mod (Const(m,_) $ s $ n) (dms as (divs,mods)) =
+      if m = Data.mod_name then (divs,(s,n)::mods) else dms
+  | coll_div_mod _ dms = dms;
+
+
+(* Proof principle:
+   1. (...div...)+(...mod...) == (div + mod) + rest
+      in function rearrange
+   2. (div + mod) + ?x = d + ?x
+      Data.div_mod_eq
+   ==> thesis by transitivity
+*)
+
+val mk_plus = Data.mk_binop "op +"
+val mk_times = Data.mk_binop "op *"
+
+fun rearrange t pq =
+  let val ts = Data.dest_sum t;
+      val dpq = Data.mk_binop Data.div_name pq
+      val d1 = mk_times (snd pq,dpq) and d2 = mk_times (dpq,snd pq)
+      val d = if d1 mem ts then d1 else d2
+      val m = Data.mk_binop Data.mod_name pq
+  in mk_plus(mk_plus(d,m),Data.mk_sum(ts \ d \ m)) end
+
+fun cancel sg t pq =
+  let val teqt' = Data.prove_eq_sums sg (t, rearrange t pq)
+  in hd(Data.div_mod_eqs RL [teqt' RS transitive_thm]) end;
+
+fun proc sg _ t =
+  let val (divs,mods) = coll_div_mod t ([],[])
+  in if null divs orelse null mods then None
+     else case divs inter mods of
+            pq :: _ => Some(cancel sg t pq)
+          | [] => None
+  end
+
+end
\ No newline at end of file
--- a/src/Provers/Arith/fast_lin_arith.ML	Thu Aug 22 20:49:43 2002 +0200
+++ b/src/Provers/Arith/fast_lin_arith.ML	Fri Aug 23 07:34:20 2002 +0200
@@ -516,7 +516,8 @@
            val (v,lineqs) :: hist' = hist
            val start = if v = ~1 then (findex0 discr n lineqs,hist')
                        else (replicate n rat0,hist)
-       in print_ex ((map s_of_t atoms)~~discr) (findex discr start)
+       in warning "arith failed - see trace for a counter example";
+          print_ex ((map s_of_t atoms)~~discr) (findex discr start)
           handle NoEx =>
   (tracing "The decision procedure failed to prove your proposition\n\
            \but could not construct a counter example either.\n\