src/Pure/term_ord.ML
author blanchet
Mon May 19 23:43:53 2014 +0200 (2014-05-19)
changeset 57008 10f68b83b474
parent 43794 49cbbe2768a8
child 67561 f0b11413f1c9
permissions -rw-r--r--
use E 1.8's auto scheduler option
     1 (*  Title:      Pure/term_ord.ML
     2     Author:     Tobias Nipkow and Makarius, TU Muenchen
     3 
     4 Term orderings.
     5 *)
     6 
     7 signature BASIC_TERM_ORD =
     8 sig
     9   structure Vartab: TABLE
    10   structure Sorttab: TABLE
    11   structure Typtab: TABLE
    12   structure Termtab: TABLE
    13 end;
    14 
    15 signature TERM_ORD =
    16 sig
    17   include BASIC_TERM_ORD
    18   val fast_indexname_ord: indexname * indexname -> order
    19   val sort_ord: sort * sort -> order
    20   val typ_ord: typ * typ -> order
    21   val fast_term_ord: term * term -> order
    22   val syntax_term_ord: term * term -> order
    23   val indexname_ord: indexname * indexname -> order
    24   val tvar_ord: (indexname * sort) * (indexname * sort) -> order
    25   val var_ord: (indexname * typ) * (indexname * typ) -> order
    26   val term_ord: term * term -> order
    27   val hd_ord: term * term -> order
    28   val termless: term * term -> bool
    29   val term_lpo: (term -> int) -> term * term -> order
    30   val term_cache: (term -> 'a) -> term -> 'a
    31 end;
    32 
    33 structure Term_Ord: TERM_ORD =
    34 struct
    35 
    36 (* fast syntactic ordering -- tuned for inequalities *)
    37 
    38 fun fast_indexname_ord ((x, i), (y, j)) =
    39   (case int_ord (i, j) of EQUAL => fast_string_ord (x, y) | ord => ord);
    40 
    41 fun sort_ord SS =
    42   if pointer_eq SS then EQUAL
    43   else dict_ord fast_string_ord SS;
    44 
    45 local
    46 
    47 fun cons_nr (TVar _) = 0
    48   | cons_nr (TFree _) = 1
    49   | cons_nr (Type _) = 2;
    50 
    51 in
    52 
    53 fun typ_ord TU =
    54   if pointer_eq TU then EQUAL
    55   else
    56     (case TU of
    57       (Type (a, Ts), Type (b, Us)) =>
    58         (case fast_string_ord (a, b) of EQUAL => dict_ord typ_ord (Ts, Us) | ord => ord)
    59     | (TFree (a, S), TFree (b, S')) =>
    60         (case fast_string_ord (a, b) of EQUAL => sort_ord (S, S') | ord => ord)
    61     | (TVar (xi, S), TVar (yj, S')) =>
    62         (case fast_indexname_ord (xi, yj) of EQUAL => sort_ord (S, S') | ord => ord)
    63     | (T, U) => int_ord (cons_nr T, cons_nr U));
    64 
    65 end;
    66 
    67 local
    68 
    69 fun cons_nr (Const _) = 0
    70   | cons_nr (Free _) = 1
    71   | cons_nr (Var _) = 2
    72   | cons_nr (Bound _) = 3
    73   | cons_nr (Abs _) = 4
    74   | cons_nr (_ $ _) = 5;
    75 
    76 fun struct_ord (Abs (_, _, t), Abs (_, _, u)) = struct_ord (t, u)
    77   | struct_ord (t1 $ t2, u1 $ u2) =
    78       (case struct_ord (t1, u1) of EQUAL => struct_ord (t2, u2) | ord => ord)
    79   | struct_ord (t, u) = int_ord (cons_nr t, cons_nr u);
    80 
    81 fun atoms_ord (Abs (_, _, t), Abs (_, _, u)) = atoms_ord (t, u)
    82   | atoms_ord (t1 $ t2, u1 $ u2) =
    83       (case atoms_ord (t1, u1) of EQUAL => atoms_ord (t2, u2) | ord => ord)
    84   | atoms_ord (Const (a, _), Const (b, _)) = fast_string_ord (a, b)
    85   | atoms_ord (Free (x, _), Free (y, _)) = fast_string_ord (x, y)
    86   | atoms_ord (Var (xi, _), Var (yj, _)) = fast_indexname_ord (xi, yj)
    87   | atoms_ord (Bound i, Bound j) = int_ord (i, j)
    88   | atoms_ord _ = EQUAL;
    89 
    90 fun types_ord (Abs (_, T, t), Abs (_, U, u)) =
    91       (case typ_ord (T, U) of EQUAL => types_ord (t, u) | ord => ord)
    92   | types_ord (t1 $ t2, u1 $ u2) =
    93       (case types_ord (t1, u1) of EQUAL => types_ord (t2, u2) | ord => ord)
    94   | types_ord (Const (_, T), Const (_, U)) = typ_ord (T, U)
    95   | types_ord (Free (_, T), Free (_, U)) = typ_ord (T, U)
    96   | types_ord (Var (_, T), Var (_, U)) = typ_ord (T, U)
    97   | types_ord _ = EQUAL;
    98 
    99 fun comments_ord (Abs (x, _, t), Abs (y, _, u)) =
   100       (case fast_string_ord (x, y) of EQUAL => comments_ord (t, u) | ord => ord)
   101   | comments_ord (t1 $ t2, u1 $ u2) =
   102       (case comments_ord (t1, u1) of EQUAL => comments_ord (t2, u2) | ord => ord)
   103   | comments_ord _ = EQUAL;
   104 
   105 in
   106 
   107 fun fast_term_ord tu =
   108   if pointer_eq tu then EQUAL
   109   else
   110     (case struct_ord tu of
   111       EQUAL => (case atoms_ord tu of EQUAL => types_ord tu | ord => ord)
   112     | ord => ord);
   113 
   114 fun syntax_term_ord tu =
   115   (case fast_term_ord tu of EQUAL => comments_ord tu | ord => ord);
   116 
   117 end;
   118 
   119 
   120 (* term_ord *)
   121 
   122 (*a linear well-founded AC-compatible ordering for terms:
   123   s < t <=> 1. size(s) < size(t) or
   124             2. size(s) = size(t) and s=f(...) and t=g(...) and f<g or
   125             3. size(s) = size(t) and s=f(s1..sn) and t=f(t1..tn) and
   126                (s1..sn) < (t1..tn) (lexicographically)*)
   127 
   128 fun indexname_ord ((x, i), (y, j)) =
   129   (case int_ord (i, j) of EQUAL => string_ord (x, y) | ord => ord);
   130 
   131 val tvar_ord = prod_ord indexname_ord sort_ord;
   132 val var_ord = prod_ord indexname_ord typ_ord;
   133 
   134 
   135 local
   136 
   137 fun hd_depth (t $ _, n) = hd_depth (t, n + 1)
   138   | hd_depth p = p;
   139 
   140 fun dest_hd (Const (a, T)) = (((a, 0), T), 0)
   141   | dest_hd (Free (a, T)) = (((a, 0), T), 1)
   142   | dest_hd (Var v) = (v, 2)
   143   | dest_hd (Bound i) = ((("", i), dummyT), 3)
   144   | dest_hd (Abs (_, T, _)) = ((("", 0), T), 4);
   145 
   146 in
   147 
   148 fun term_ord tu =
   149   if pointer_eq tu then EQUAL
   150   else
   151     (case tu of
   152       (Abs (_, T, t), Abs(_, U, u)) =>
   153         (case term_ord (t, u) of EQUAL => typ_ord (T, U) | ord => ord)
   154     | (t, u) =>
   155         (case int_ord (size_of_term t, size_of_term u) of
   156           EQUAL =>
   157             (case prod_ord hd_ord int_ord (hd_depth (t, 0), hd_depth (u, 0)) of
   158               EQUAL => args_ord (t, u) | ord => ord)
   159         | ord => ord))
   160 and hd_ord (f, g) =
   161   prod_ord (prod_ord indexname_ord typ_ord) int_ord (dest_hd f, dest_hd g)
   162 and args_ord (f $ t, g $ u) =
   163       (case args_ord (f, g) of EQUAL => term_ord (t, u) | ord => ord)
   164   | args_ord _ = EQUAL;
   165 
   166 fun termless tu = (term_ord tu = LESS);
   167 
   168 end;
   169 
   170 
   171 (* Lexicographic path order on terms *)
   172 
   173 (*
   174   See Baader & Nipkow, Term rewriting, CUP 1998.
   175   Without variables.  Const, Var, Bound, Free and Abs are treated all as
   176   constants.
   177 
   178   f_ord maps terms to integers and serves two purposes:
   179   - Predicate on constant symbols.  Those that are not recognised by f_ord
   180     must be mapped to ~1.
   181   - Order on the recognised symbols.  These must be mapped to distinct
   182     integers >= 0.
   183   The argument of f_ord is never an application.
   184 *)
   185 
   186 local
   187 
   188 fun unrecognized (Const (a, T)) = ((1, ((a, 0), T)), 0)
   189   | unrecognized (Free (a, T)) = ((1, ((a, 0), T)), 0)
   190   | unrecognized (Var v) = ((1, v), 1)
   191   | unrecognized (Bound i) = ((1, (("", i), dummyT)), 2)
   192   | unrecognized (Abs (_, T, _)) = ((1, (("", 0), T)), 3);
   193 
   194 fun dest_hd f_ord t =
   195   let val ord = f_ord t
   196   in if ord = ~1 then unrecognized t else ((0, (("", ord), fastype_of t)), 0) end;
   197 
   198 fun term_lpo f_ord (s, t) =
   199   let val (f, ss) = strip_comb s and (g, ts) = strip_comb t in
   200     if forall (fn si => term_lpo f_ord (si, t) = LESS) ss
   201     then case hd_ord f_ord (f, g) of
   202         GREATER =>
   203           if forall (fn ti => term_lpo f_ord (s, ti) = GREATER) ts
   204           then GREATER else LESS
   205       | EQUAL =>
   206           if forall (fn ti => term_lpo f_ord (s, ti) = GREATER) ts
   207           then list_ord (term_lpo f_ord) (ss, ts)
   208           else LESS
   209       | LESS => LESS
   210     else GREATER
   211   end
   212 and hd_ord f_ord (f, g) = case (f, g) of
   213     (Abs (_, T, t), Abs (_, U, u)) =>
   214       (case term_lpo f_ord (t, u) of EQUAL => typ_ord (T, U) | ord => ord)
   215   | (_, _) => prod_ord (prod_ord int_ord
   216                   (prod_ord indexname_ord typ_ord)) int_ord
   217                 (dest_hd f_ord f, dest_hd f_ord g);
   218 
   219 in
   220 val term_lpo = term_lpo
   221 end;
   222 
   223 
   224 (* tables and caches *)
   225 
   226 structure Vartab = Table(type key = indexname val ord = fast_indexname_ord);
   227 structure Sorttab = Table(type key = sort val ord = sort_ord);
   228 structure Typtab = Table(type key = typ val ord = typ_ord);
   229 structure Termtab = Table(type key = term val ord = fast_term_ord);
   230 
   231 fun term_cache f = Cache.create Termtab.empty Termtab.lookup Termtab.update f;
   232 
   233 end;
   234 
   235 structure Basic_Term_Ord: BASIC_TERM_ORD = Term_Ord;
   236 open Basic_Term_Ord;
   237 
   238 structure Var_Graph = Graph(type key = indexname val ord = Term_Ord.fast_indexname_ord);
   239 structure Sort_Graph = Graph(type key = sort val ord = Term_Ord.sort_ord);
   240 structure Typ_Graph = Graph(type key = typ val ord = Term_Ord.typ_ord);
   241 structure Term_Graph = Graph(type key = term val ord = Term_Ord.fast_term_ord);
   242