1 (* |
1 (* |
2 Title: Term order, needed for normal forms in rings |
2 Title: Term order, needed for normal forms in rings |
3 Id: $Id$ |
3 Id: $Id$ |
4 Author: Clemens Ballarin and Roland Zumkeller |
4 Author: Clemens Ballarin |
5 Copyright: TU Muenchen |
5 Copyright: TU Muenchen |
6 *) |
6 *) |
7 |
7 |
8 local |
8 local |
9 |
9 |
10 (* |
10 (*** Lexicographic path order on terms. |
11 An order is a value of type |
|
12 ('a -> bool, 'a * 'a -> bool). |
|
13 |
11 |
14 The two parts are: |
12 See Baader & Nipkow, Term rewriting, CUP 1998. |
15 1) a unary predicate denoting the order's domain |
13 Without variables. Const, Var, Bound, Free and Abs are treated all as |
16 2) a binary predicate with the semanitcs "greater than" |
14 constants. |
17 |
15 |
18 If (d, ord) is an order then ord (a,b) is defined if both d a and d b. |
16 f_ord maps strings to integers and serves two purposes: |
19 *) |
17 - Predicate on constant symbols. Those that are not recognised by f_ord |
|
18 must be mapped to ~1. |
|
19 - Order on the recognised symbols. These must be mapped to distinct |
|
20 integers >= 0. |
20 |
21 |
21 (* |
22 ***) |
22 Combines two orders with disjoint domains and returns |
|
23 another one. |
|
24 When the compared values are from the same domain, the corresponding |
|
25 order is used. If not the ones from the first domain are considerer |
|
26 greater. (If a value is in neither of the two domains, exception |
|
27 "Domain" is raised.) |
|
28 *) |
|
29 |
23 |
30 fun combineOrd ((d1, ord1), (d2, ord2)) = |
24 fun dest_hd f_ord (Const (a, T)) = |
31 (fn x => d1 x orelse d2 x, |
25 let val ord = f_ord a in |
32 fn (a, b) => |
26 if ord = ~1 then ((1, ((a, 0), T)), 0) else ((0, (("", ord), T)), 0) |
33 if d1 a andalso d1 b then ord1 (a, b) else |
27 end |
34 if d1 a andalso d2 b then true else |
28 | dest_hd _ (Free (a, T)) = ((1, ((a, 0), T)), 0) |
35 if d2 a andalso d2 b then ord2 (a, b) else |
29 | dest_hd _ (Var v) = ((1, v), 1) |
36 if d2 a andalso d1 b then false else raise Domain) |
30 | dest_hd _ (Bound i) = ((1, (("", i), Term.dummyT)), 2) |
|
31 | dest_hd _ (Abs (_, T, _)) = ((1, (("", 0), T)), 3); |
37 |
32 |
38 |
33 fun term_lpo f_ord (s, t) = |
39 (* Counts the number of function applications + 1. *) |
34 let val (f, ss) = strip_comb s and (g, ts) = strip_comb t in |
40 (* ### is there a standard Isabelle function for this? *) |
35 if forall (fn si => term_lpo f_ord (si, t) = LESS) ss |
41 |
36 then case hd_ord f_ord (f, g) of |
42 fun tsize (a $ b) = tsize a + tsize b |
37 GREATER => |
43 | tsize _ = 1; |
38 if forall (fn ti => term_lpo f_ord (s, ti) = GREATER) ts |
44 |
39 then GREATER else LESS |
45 (* foldl on non-empty lists *) |
40 | EQUAL => |
46 |
41 if forall (fn ti => term_lpo f_ord (s, ti) = GREATER) ts |
47 fun foldl2 f (x::xs) = foldl f (x,xs) |
42 then list_ord (term_lpo f_ord) (ss, ts) |
48 |
43 else LESS |
49 |
44 | LESS => LESS |
50 (* Compares two terms, ignoring type information. *) |
45 else GREATER |
51 infix e; |
46 end |
52 fun (Const (s1, _)) e (Const (s2, _)) = s1 = s2 |
47 and hd_ord f_ord (f, g) = case (f, g) of |
53 | (Free (s1, _)) e (Free (s2, _)) = s1 = s2 |
48 (Abs (_, T, t), Abs (_, U, u)) => |
54 | (Var (ix1, _)) e (Var (ix2, _)) = ix1 = ix2 |
49 (case term_lpo f_ord (t, u) of EQUAL => Term.typ_ord (T, U) | ord => ord) |
55 | (Bound i1) e (Bound i2) = i1 = i2 |
50 | (_, _) => prod_ord (prod_ord int_ord |
56 | (Abs (s1, _, t1)) e (Abs (s2, _, t2)) = s1 = s2 andalso t1 = t2 |
51 (prod_ord Term.indexname_ord Term.typ_ord)) int_ord |
57 | (s1 $ s2) e (t1 $ t2) = s1 = t1 andalso s2 = t2 |
52 (dest_hd f_ord f, dest_hd f_ord g) |
58 | _ e _ = false |
|
59 |
|
60 |
|
61 |
|
62 (* Curried lexicographich path order induced by an order on function symbols. |
|
63 Its feature include: |
|
64 - compatibility with Epsilon-operations |
|
65 - closure under substitutions |
|
66 - well-foundedness |
|
67 - subterm-property |
|
68 - termination |
|
69 - defined on all terms (not only on ground terms) |
|
70 - linearity |
|
71 |
|
72 The order ignores types. |
|
73 *) |
|
74 |
|
75 infix g; |
|
76 fun clpo (d, ord) (s,t) = |
|
77 let val (op g) = clpo (d, ord) in |
|
78 (s <> t) andalso |
|
79 if tsize s < tsize t then not (t g s) else |
|
80 (* improves performance. allowed because clpo is total. *) |
|
81 #2 (foldl2 combineOrd [ |
|
82 (fn _ $ _ => true | Abs _ => true | _ => false, |
|
83 fn (Abs (_, _, s'), t) => s' e t orelse s' g t orelse |
|
84 (case t of |
|
85 Abs (_, _, t') => s' g t' |
|
86 | t1 $ t2 => s g t1 andalso s g t2 |
|
87 ) |
|
88 | (s1 $ s2, t) => s1 e t orelse s2 e t orelse |
|
89 s1 g t orelse s2 g t orelse |
|
90 (case t of |
|
91 t1 $ t2 => (s1 e t1 andalso s2 g t2) orelse |
|
92 (s1 g t1 andalso s g t2) |
|
93 | _ => false |
|
94 ) |
|
95 ), |
|
96 (fn Free _ => true | _ => false, fn (Free (a,_), Free (b,_)) => a > b), |
|
97 (fn Bound _ => true | _ => false, fn (Bound a, Bound b) => a > b), |
|
98 (fn Const (c, _) => not (d c) | _ => false, fn (Const (a, _), Const (b, _)) => a > b), |
|
99 (fn Const (c, _) => d c | _ => false, fn (Const (a, _), Const (b, _)) => ord (a,b)) |
|
100 ]) (s,t) |
|
101 end; |
|
102 |
|
103 (* |
|
104 Open Issues: |
|
105 - scheme variables have to be ordered (should be simple) |
|
106 *) |
|
107 |
|
108 (* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *) |
|
109 |
|
110 (* Returns the position of an element in a list. If the |
|
111 element doesn't occur in the list, a MatchException is raised. *) |
|
112 fun pos (x::xs) i = if x = i then 0 else 1 + pos xs i; |
|
113 |
|
114 (* Generates a finite linear order from a list. |
|
115 [a, b, c] results in the order "a > b > c". *) |
|
116 fun linOrd l = fn (a,b) => pos l a < pos l b; |
|
117 |
|
118 (* Determines whether an element is contained in a list. *) |
|
119 fun contains (x::xs) i = (x = i) orelse (contains xs i) | |
|
120 contains [] i = false; |
|
121 |
53 |
122 in |
54 in |
123 |
55 |
124 (* Term order for commutative rings *) |
56 (*** Term order for commutative rings ***) |
125 |
57 |
126 fun termless_ring (a, b) = |
58 fun ring_ord a = |
127 let |
59 find_index_eq a ["0", "op +", "uminus", "op -", "1", "op *"]; |
128 val S = ["op *", "op -", "uminus", "op +", "0"]; |
60 |
129 (* Order (decending from left to right) on the constant symbols *) |
61 fun termless_ring (a, b) = (term_lpo ring_ord (a, b) = LESS); |
130 val baseOrd = (contains S, linOrd S); |
62 |
131 in clpo baseOrd (b, a) |
63 (* Some code useful for debugging |
132 end; |
64 |
|
65 val intT = HOLogic.intT; |
|
66 val a = Free ("a", intT); |
|
67 val b = Free ("b", intT); |
|
68 val c = Free ("c", intT); |
|
69 val plus = Const ("op +", [intT, intT]--->intT); |
|
70 val mult = Const ("op *", [intT, intT]--->intT); |
|
71 val uminus = Const ("uminus", intT-->intT); |
|
72 val one = Const ("1", intT); |
|
73 val f = Const("f", intT-->intT); |
|
74 |
|
75 *) |
133 |
76 |
134 (*** Rewrite rules ***) |
77 (*** Rewrite rules ***) |
135 |
78 |
136 val a_assoc = thm "ring.a_assoc"; |
79 val a_assoc = thm "ring.a_assoc"; |
137 val l_zero = thm "ring.l_zero"; |
80 val l_zero = thm "ring.l_zero"; |
231 simp_tac (simpset() addsimps [r_null, r_neg]) 1]); |
174 simp_tac (simpset() addsimps [r_null, r_neg]) 1]); |
232 |
175 |
233 val ring_ss = HOL_basic_ss settermless termless_ring addsimps |
176 val ring_ss = HOL_basic_ss settermless termless_ring addsimps |
234 [a_assoc, l_zero, l_neg, a_comm, m_assoc, l_one, l_distr, m_comm, minus_def, |
177 [a_assoc, l_zero, l_neg, a_comm, m_assoc, l_one, l_distr, m_comm, minus_def, |
235 r_zero, r_neg, r_neg2, r_neg1, minus_add, minus_minus, minus0, |
178 r_zero, r_neg, r_neg2, r_neg1, minus_add, minus_minus, minus0, |
236 a_lcomm, m_lcomm, r_distr, l_null, r_null, l_minus, r_minus]; |
179 a_lcomm, m_lcomm, (*r_one,*) r_distr, l_null, r_null, l_minus, r_minus]; |
237 |
180 |
238 val x = bind_thms ("ring_simps", [l_zero, r_zero, l_neg, r_neg, |
181 (* Note: r_one is not necessary in ring_ss *) |
239 minus_minus, minus0, |
182 |
|
183 val x = bind_thms ("ring_simps", |
|
184 [l_zero, r_zero, l_neg, r_neg, minus_minus, minus0, |
240 l_one, r_one, l_null, r_null, l_minus, r_minus]); |
185 l_one, r_one, l_null, r_null, l_minus, r_minus]); |
241 |
|
242 (* note: r_one added to ring_simp but not ring_ss *) |
|
243 |
186 |
244 (* note: not added (and not proved): |
187 (* note: not added (and not proved): |
245 a_lcancel_eq, a_rcancel_eq, power_one, power_Suc, power_zero, power_one, |
188 a_lcancel_eq, a_rcancel_eq, power_one, power_Suc, power_zero, power_one, |
246 m_lcancel_eq, m_rcancel_eq, |
189 m_lcancel_eq, m_rcancel_eq, |
247 thms involving dvd, integral domains, fields |
190 thms involving dvd, integral domains, fields |