src/Tools/Metis/src/KnuthBendixOrder.sml
author wenzelm
Sun, 18 Sep 2011 13:39:33 +0200
changeset 44962 5554ed48b13f
parent 42102 fcfd07f122d4
child 72004 913162a47d9f
permissions -rw-r--r--
finite sequences as useful as introductory example;
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
39348
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
     1
(* ========================================================================= *)
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
     2
(* KNUTH-BENDIX TERM ORDERING CONSTRAINTS                                    *)
39502
cffceed8e7fa fix license
blanchet
parents: 39501
diff changeset
     3
(* Copyright (c) 2002 Joe Hurd, distributed under the BSD License            *)
39348
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
     4
(* ========================================================================= *)
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
     5
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
     6
structure KnuthBendixOrder :> KnuthBendixOrder =
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
     7
struct
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
     8
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
     9
open Useful;
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
    10
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
    11
(* ------------------------------------------------------------------------- *)
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
    12
(* Helper functions.                                                         *)
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
    13
(* ------------------------------------------------------------------------- *)
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
    14
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
    15
fun notEqualTerm (x,y) = not (Term.equal x y);
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
    16
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
    17
fun firstNotEqualTerm f l =
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
    18
    case List.find notEqualTerm l of
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
    19
      SOME (x,y) => f x y
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
    20
    | NONE => raise Bug "firstNotEqualTerm";
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
    21
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
    22
(* ------------------------------------------------------------------------- *)
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
    23
(* The weight of all constants must be at least 1, and there must be at most *)
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
    24
(* one unary function with weight 0.                                         *)
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
    25
(* ------------------------------------------------------------------------- *)
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
    26
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
    27
type kbo =
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
    28
     {weight : Term.function -> int,
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
    29
      precedence : Term.function * Term.function -> order};
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
    30
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
    31
(* Default weight = uniform *)
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
    32
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
    33
val uniformWeight : Term.function -> int = K 1;
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
    34
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
    35
(* Default precedence = by arity *)
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
    36
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
    37
val arityPrecedence : Term.function * Term.function -> order =
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
    38
    fn ((f1,n1),(f2,n2)) =>
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
    39
       case Int.compare (n1,n2) of
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
    40
         LESS => LESS
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
    41
       | EQUAL => Name.compare (f1,f2)
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
    42
       | GREATER => GREATER;
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
    43
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
    44
(* The default order *)
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
    45
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
    46
val default = {weight = uniformWeight, precedence = arityPrecedence};
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
    47
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
    48
(* ------------------------------------------------------------------------- *)
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
    49
(* Term weight-1 represented as a linear function of the weight-1 of the     *)
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
    50
(* variables in the term (plus a constant).                                  *)
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
    51
(*                                                                           *)
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
    52
(* Note that the conditions on weight functions ensure that all weights are  *)
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
    53
(* at least 1, so all weight-1s are at least 0.                              *)
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
    54
(* ------------------------------------------------------------------------- *)
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
    55
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
    56
datatype weight = Weight of int NameMap.map * int;
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
    57
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
    58
val weightEmpty : int NameMap.map = NameMap.new ();
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
    59
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
    60
val weightZero = Weight (weightEmpty,0);
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
    61
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
    62
fun weightIsZero (Weight (m,c)) = c = 0 andalso NameMap.null m;
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
    63
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
    64
fun weightNeg (Weight (m,c)) = Weight (NameMap.transform ~ m, ~c);
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
    65
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
    66
local
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
    67
  fun add ((_,n1),(_,n2)) =
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
    68
      let
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
    69
        val n = n1 + n2
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
    70
      in
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
    71
        if n = 0 then NONE else SOME n
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
    72
      end;
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
    73
in
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
    74
  fun weightAdd (Weight (m1,c1)) (Weight (m2,c2)) =
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
    75
      Weight (NameMap.union add m1 m2, c1 + c2);
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
    76
end;
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
    77
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
    78
fun weightSubtract w1 w2 = weightAdd w1 (weightNeg w2);
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
    79
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
    80
fun weightTerm weight =
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
    81
    let
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
    82
      fun wt m c [] = Weight (m,c)
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
    83
        | wt m c (Term.Var v :: tms) =
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
    84
          let
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
    85
            val n = Option.getOpt (NameMap.peek m v, 0)
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
    86
          in
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
    87
            wt (NameMap.insert m (v, n + 1)) (c + 1) tms
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
    88
          end
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
    89
        | wt m c (Term.Fn (f,a) :: tms) =
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
    90
          wt m (c + weight (f, length a)) (a @ tms)
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
    91
    in
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
    92
      fn tm => wt weightEmpty ~1 [tm]
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
    93
    end;
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
    94
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
    95
fun weightLowerBound (w as Weight (m,c)) =
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
    96
    if NameMap.exists (fn (_,n) => n < 0) m then NONE else SOME c;
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
    97
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
    98
(*MetisDebug
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
    99
val ppWeightList =
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   100
    let
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   101
      fun ppCoeff n =
39443
e330437cd22a copied the unmodified official Metis 2.3 (15 Sept. 2010) sources into Isabelle
blanchet
parents: 39353
diff changeset
   102
          if n < 0 then Print.sequence (Print.ppString "~") (ppCoeff (~n))
39348
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   103
          else if n = 1 then Print.skip
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   104
          else Print.ppInt n
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   105
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   106
      fun pp_tm (NONE,n) = Print.ppInt n
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   107
        | pp_tm (SOME v, n) = Print.sequence (ppCoeff n) (Name.pp v)
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   108
    in
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   109
      fn [] => Print.ppInt 0
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   110
       | tms => Print.ppOpList " +" pp_tm tms
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   111
    end;
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   112
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   113
fun ppWeight (Weight (m,c)) =
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   114
    let
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   115
      val l = NameMap.toList m
42102
fcfd07f122d4 new version of Metis 2.3 (29 Dec. 2010)
blanchet
parents: 39502
diff changeset
   116
      val l = List.map (fn (v,n) => (SOME v, n)) l
39348
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   117
      val l = if c = 0 then l else l @ [(NONE,c)]
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   118
    in
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   119
      ppWeightList l
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   120
    end;
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   121
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   122
val weightToString = Print.toString ppWeight;
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   123
*)
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   124
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   125
(* ------------------------------------------------------------------------- *)
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   126
(* The Knuth-Bendix term order.                                              *)
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   127
(* ------------------------------------------------------------------------- *)
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   128
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   129
fun compare {weight,precedence} =
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   130
    let
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   131
      fun weightDifference tm1 tm2 =
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   132
          let
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   133
            val w1 = weightTerm weight tm1
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   134
            and w2 = weightTerm weight tm2
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   135
          in
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   136
            weightSubtract w2 w1
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   137
          end
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   138
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   139
      fun weightLess tm1 tm2 =
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   140
          let
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   141
            val w = weightDifference tm1 tm2
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   142
          in
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   143
            if weightIsZero w then precedenceLess tm1 tm2
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   144
            else weightDiffLess w tm1 tm2
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   145
          end
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   146
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   147
      and weightDiffLess w tm1 tm2 =
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   148
          case weightLowerBound w of
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   149
            NONE => false
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   150
          | SOME 0 => precedenceLess tm1 tm2
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   151
          | SOME n => n > 0
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   152
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   153
      and precedenceLess (Term.Fn (f1,a1)) (Term.Fn (f2,a2)) =
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   154
          (case precedence ((f1, length a1), (f2, length a2)) of
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   155
             LESS => true
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   156
           | EQUAL => firstNotEqualTerm weightLess (zip a1 a2)
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   157
           | GREATER => false)
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   158
        | precedenceLess _ _ = false
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   159
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   160
      fun weightDiffGreater w tm1 tm2 = weightDiffLess (weightNeg w) tm2 tm1
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   161
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   162
      fun weightCmp tm1 tm2 =
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   163
          let
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   164
            val w = weightDifference tm1 tm2
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   165
          in
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   166
            if weightIsZero w then precedenceCmp tm1 tm2
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   167
            else if weightDiffLess w tm1 tm2 then SOME LESS
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   168
            else if weightDiffGreater w tm1 tm2 then SOME GREATER
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   169
            else NONE
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   170
          end
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   171
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   172
      and precedenceCmp (Term.Fn (f1,a1)) (Term.Fn (f2,a2)) =
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   173
          (case precedence ((f1, length a1), (f2, length a2)) of
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   174
             LESS => SOME LESS
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   175
           | EQUAL => firstNotEqualTerm weightCmp (zip a1 a2)
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   176
           | GREATER => SOME GREATER)
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   177
        | precedenceCmp _ _ = raise Bug "kboOrder.precendenceCmp"
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   178
    in
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   179
      fn (tm1,tm2) =>
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   180
         if Term.equal tm1 tm2 then SOME EQUAL else weightCmp tm1 tm2
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   181
    end;
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   182
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   183
(*MetisTrace7
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   184
val compare = fn kbo => fn (tm1,tm2) =>
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   185
    let
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   186
      val () = Print.trace Term.pp "KnuthBendixOrder.compare: tm1" tm1
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   187
      val () = Print.trace Term.pp "KnuthBendixOrder.compare: tm2" tm2
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   188
      val result = compare kbo (tm1,tm2)
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   189
      val () =
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   190
          case result of
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   191
            NONE => trace "KnuthBendixOrder.compare: result = Incomparable\n"
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   192
          | SOME x =>
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   193
            Print.trace Print.ppOrder "KnuthBendixOrder.compare: result" x
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   194
    in
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   195
      result
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   196
    end;
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   197
*)
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   198
6f9c9899f99f new version of the Metis files
blanchet
parents:
diff changeset
   199
end