src/Provers/Arith/cancel_factor.ML
author wenzelm
Sat, 11 Mar 2006 21:23:10 +0100
changeset 19250 932a50e2332f
parent 15965 f422f8283491
child 20044 92cc2f4c7335
permissions -rw-r--r--
got rid of type Sign.sg;
wenzelm@4292
     1
(*  Title:      Provers/Arith/cancel_factor.ML
wenzelm@4292
     2
    ID:         $Id$
wenzelm@4292
     3
    Author:     Markus Wenzel and Stefan Berghofer, TU Muenchen
wenzelm@4292
     4
wenzelm@4292
     5
Cancel common constant factor from balanced exression (e.g. =, <=, < of sums).
wenzelm@4292
     6
*)
wenzelm@4292
     7
wenzelm@4292
     8
signature CANCEL_FACTOR_DATA =
wenzelm@4292
     9
sig
wenzelm@4292
    10
  (*abstract syntax*)
wenzelm@4292
    11
  val mk_sum: term list -> term
wenzelm@4292
    12
  val dest_sum: term -> term list
wenzelm@4292
    13
  val mk_bal: term * term -> term
wenzelm@4292
    14
  val dest_bal: term -> term * term
wenzelm@4292
    15
  (*rules*)
wenzelm@19250
    16
  val prove_conv: tactic -> tactic -> theory -> term * term -> thm
wenzelm@4292
    17
  val norm_tac: tactic			(*AC0 etc.*)
paulson@15965
    18
  val multiply_tac: IntInf.int -> tactic	(*apply a ~~ b  ==  k * a ~~ k * b  (for k > 0)*)
wenzelm@4292
    19
end;
wenzelm@4292
    20
wenzelm@4292
    21
signature CANCEL_FACTOR =
wenzelm@4292
    22
sig
wenzelm@19250
    23
  val proc: theory -> thm list -> term -> thm option
wenzelm@4292
    24
end;
wenzelm@4292
    25
wenzelm@4292
    26
wenzelm@4292
    27
functor CancelFactorFun(Data: CANCEL_FACTOR_DATA): CANCEL_FACTOR =
wenzelm@4292
    28
struct
wenzelm@4292
    29
wenzelm@4292
    30
wenzelm@4292
    31
(* greatest common divisor *)
wenzelm@4292
    32
wenzelm@4292
    33
fun gcd (0, n) = n
wenzelm@4292
    34
  | gcd (m, n) = gcd (n mod m, m);
wenzelm@4292
    35
wenzelm@4292
    36
val gcds = foldl gcd;
wenzelm@4292
    37
wenzelm@4292
    38
wenzelm@4292
    39
(* count terms *)
wenzelm@4292
    40
wenzelm@4292
    41
fun ins_term (t, []) = [(t, 1)]
wenzelm@4292
    42
  | ins_term (t, (u, k) :: uks) =
wenzelm@4292
    43
      if t aconv u then (u, k + 1) :: uks
wenzelm@4292
    44
      else (t, 1) :: (u, k) :: uks;
wenzelm@4292
    45
wenzelm@4452
    46
fun count_terms ts = foldr ins_term (sort Term.term_ord ts, []);
wenzelm@4292
    47
wenzelm@4292
    48
wenzelm@4292
    49
(* divide sum *)
wenzelm@4292
    50
wenzelm@4292
    51
fun div_sum d tks =
wenzelm@4292
    52
  Data.mk_sum (flat (map (fn (t, k) => replicate (k div d) t) tks));
wenzelm@4292
    53
wenzelm@4292
    54
wenzelm@4292
    55
(* the simplification procedure *)
wenzelm@4292
    56
wenzelm@4292
    57
fun proc sg _ t =
wenzelm@4292
    58
  (case try Data.dest_bal t of
skalberg@15531
    59
    NONE => NONE
skalberg@15531
    60
  | SOME bal =>
wenzelm@4292
    61
      (case pairself Data.dest_sum bal of
skalberg@15531
    62
        ([_], _) => NONE
skalberg@15531
    63
      | (_, [_]) => NONE
wenzelm@4292
    64
      | ts_us =>
wenzelm@4292
    65
          let
wenzelm@4292
    66
            val (tks, uks) = pairself count_terms ts_us;
wenzelm@4292
    67
            val d = gcds (gcds (0, map snd tks), map snd uks);
wenzelm@4292
    68
          in
skalberg@15531
    69
            if d = 0 orelse d = 1 then NONE
skalberg@15531
    70
            else SOME
wenzelm@4292
    71
              (Data.prove_conv (Data.multiply_tac d) Data.norm_tac sg
wenzelm@4292
    72
                (t, Data.mk_bal (div_sum d tks, div_sum d uks)))
wenzelm@4292
    73
          end));
wenzelm@4292
    74
wenzelm@4292
    75
wenzelm@4292
    76
end;