10 |
10 |
11 (* ------------------------------------------------------------------------- *) |
11 (* ------------------------------------------------------------------------- *) |
12 (* Helper functions. *) |
12 (* Helper functions. *) |
13 (* ------------------------------------------------------------------------- *) |
13 (* ------------------------------------------------------------------------- *) |
14 |
14 |
15 fun firstNotEqual f l = |
15 fun notEqualTerm (x,y) = not (Term.equal x y); |
16 case List.find op<> l of |
16 |
|
17 fun firstNotEqualTerm f l = |
|
18 case List.find notEqualTerm l of |
17 SOME (x,y) => f x y |
19 SOME (x,y) => f x y |
18 | NONE => raise Bug "firstNotEqual"; |
20 | NONE => raise Bug "firstNotEqualTerm"; |
19 |
21 |
20 (* ------------------------------------------------------------------------- *) |
22 (* ------------------------------------------------------------------------- *) |
21 (* The weight of all constants must be at least 1, and there must be at most *) |
23 (* The weight of all constants must be at least 1, and there must be at most *) |
22 (* one unary function with weight 0. *) |
24 (* one unary function with weight 0. *) |
23 (* ------------------------------------------------------------------------- *) |
25 (* ------------------------------------------------------------------------- *) |
34 |
36 |
35 val arityPrecedence : Term.function * Term.function -> order = |
37 val arityPrecedence : Term.function * Term.function -> order = |
36 fn ((f1,n1),(f2,n2)) => |
38 fn ((f1,n1),(f2,n2)) => |
37 case Int.compare (n1,n2) of |
39 case Int.compare (n1,n2) of |
38 LESS => LESS |
40 LESS => LESS |
39 | EQUAL => String.compare (f1,f2) |
41 | EQUAL => Name.compare (f1,f2) |
40 | GREATER => GREATER; |
42 | GREATER => GREATER; |
41 |
43 |
42 (* The default order *) |
44 (* The default order *) |
43 |
45 |
44 val default = {weight = uniformWeight, precedence = arityPrecedence}; |
46 val default = {weight = uniformWeight, precedence = arityPrecedence}; |
72 fun weightAdd (Weight (m1,c1)) (Weight (m2,c2)) = |
74 fun weightAdd (Weight (m1,c1)) (Weight (m2,c2)) = |
73 Weight (NameMap.union add m1 m2, c1 + c2); |
75 Weight (NameMap.union add m1 m2, c1 + c2); |
74 end; |
76 end; |
75 |
77 |
76 fun weightSubtract w1 w2 = weightAdd w1 (weightNeg w2); |
78 fun weightSubtract w1 w2 = weightAdd w1 (weightNeg w2); |
77 |
|
78 fun weightMult 0 _ = weightZero |
|
79 | weightMult 1 w = w |
|
80 | weightMult k (Weight (m,c)) = |
|
81 let |
|
82 fun mult n = k * n |
|
83 in |
|
84 Weight (NameMap.transform mult m, k * c) |
|
85 end; |
|
86 |
79 |
87 fun weightTerm weight = |
80 fun weightTerm weight = |
88 let |
81 let |
89 fun wt m c [] = Weight (m,c) |
82 fun wt m c [] = Weight (m,c) |
90 | wt m c (Term.Var v :: tms) = |
83 | wt m c (Term.Var v :: tms) = |
97 wt m (c + weight (f, length a)) (a @ tms) |
90 wt m (c + weight (f, length a)) (a @ tms) |
98 in |
91 in |
99 fn tm => wt weightEmpty ~1 [tm] |
92 fn tm => wt weightEmpty ~1 [tm] |
100 end; |
93 end; |
101 |
94 |
102 fun weightIsVar v (Weight (m,c)) = |
|
103 c = 0 andalso NameMap.size m = 1 andalso NameMap.peek m v = SOME 1; |
|
104 |
|
105 fun weightConst (Weight (_,c)) = c; |
|
106 |
|
107 fun weightVars (Weight (m,_)) = |
|
108 NameMap.foldl (fn (v,_,s) => NameSet.add s v) NameSet.empty m; |
|
109 |
|
110 val weightsVars = |
|
111 List.foldl (fn (w,s) => NameSet.union (weightVars w) s) NameSet.empty; |
|
112 |
|
113 fun weightVarList w = NameSet.toList (weightVars w); |
|
114 |
|
115 fun weightNumVars (Weight (m,_)) = NameMap.size m; |
|
116 |
|
117 fun weightNumVarsWithPositiveCoeff (Weight (m,_)) = |
|
118 NameMap.foldl (fn (_,n,z) => if n > 0 then z + 1 else z) 0 m; |
|
119 |
|
120 fun weightCoeff var (Weight (m,_)) = Option.getOpt (NameMap.peek m var, 0); |
|
121 |
|
122 fun weightCoeffs varList w = map (fn var => weightCoeff var w) varList; |
|
123 |
|
124 fun weightCoeffSum (Weight (m,_)) = NameMap.foldl (fn (_,n,z) => n + z) 0 m; |
|
125 |
|
126 fun weightLowerBound (w as Weight (m,c)) = |
95 fun weightLowerBound (w as Weight (m,c)) = |
127 if NameMap.exists (fn (_,n) => n < 0) m then NONE else SOME c; |
96 if NameMap.exists (fn (_,n) => n < 0) m then NONE else SOME c; |
128 |
97 |
129 fun weightNoLowerBound w = not (Option.isSome (weightLowerBound w)); |
98 (*MetisDebug |
|
99 val ppWeightList = |
|
100 let |
|
101 fun ppCoeff n = |
|
102 if n < 0 then Print.sequence (Print.addString "~") (ppCoeff (~n)) |
|
103 else if n = 1 then Print.skip |
|
104 else Print.ppInt n |
130 |
105 |
131 fun weightAlwaysPositive w = |
106 fun pp_tm (NONE,n) = Print.ppInt n |
132 case weightLowerBound w of NONE => false | SOME n => n > 0; |
107 | pp_tm (SOME v, n) = Print.sequence (ppCoeff n) (Name.pp v) |
133 |
|
134 fun weightUpperBound (w as Weight (m,c)) = |
|
135 if NameMap.exists (fn (_,n) => n > 0) m then NONE else SOME c; |
|
136 |
|
137 fun weightNoUpperBound w = not (Option.isSome (weightUpperBound w)); |
|
138 |
|
139 fun weightAlwaysNegative w = |
|
140 case weightUpperBound w of NONE => false | SOME n => n < 0; |
|
141 |
|
142 fun weightGcd (w as Weight (m,c)) = |
|
143 NameMap.foldl (fn (_,i,k) => gcd i k) (Int.abs c) m; |
|
144 |
|
145 fun ppWeightList pp = |
|
146 let |
|
147 fun coeffToString n = |
|
148 if n < 0 then "~" ^ coeffToString (~n) |
|
149 else if n = 1 then "" |
|
150 else Int.toString n |
|
151 |
|
152 fun pp_tm pp ("",n) = Parser.ppInt pp n |
|
153 | pp_tm pp (v,n) = Parser.ppString pp (coeffToString n ^ v) |
|
154 in |
108 in |
155 fn [] => Parser.ppInt pp 0 |
109 fn [] => Print.ppInt 0 |
156 | tms => Parser.ppSequence " +" pp_tm pp tms |
110 | tms => Print.ppOpList " +" pp_tm tms |
157 end; |
111 end; |
158 |
112 |
159 fun ppWeight pp (Weight (m,c)) = |
113 fun ppWeight (Weight (m,c)) = |
160 let |
114 let |
161 val l = NameMap.toList m |
115 val l = NameMap.toList m |
162 val l = if c = 0 then l else l @ [("",c)] |
116 val l = map (fn (v,n) => (SOME v, n)) l |
|
117 val l = if c = 0 then l else l @ [(NONE,c)] |
163 in |
118 in |
164 ppWeightList pp l |
119 ppWeightList l |
165 end; |
120 end; |
166 |
121 |
167 val weightToString = Parser.toString ppWeight; |
122 val weightToString = Print.toString ppWeight; |
|
123 *) |
168 |
124 |
169 (* ------------------------------------------------------------------------- *) |
125 (* ------------------------------------------------------------------------- *) |
170 (* The Knuth-Bendix term order. *) |
126 (* The Knuth-Bendix term order. *) |
171 (* ------------------------------------------------------------------------- *) |
127 (* ------------------------------------------------------------------------- *) |
172 |
128 |
173 datatype kboOrder = Less | Equal | Greater | SignOf of weight; |
129 fun compare {weight,precedence} = |
174 |
|
175 fun kboOrder {weight,precedence} = |
|
176 let |
130 let |
177 fun weightDifference tm1 tm2 = |
131 fun weightDifference tm1 tm2 = |
178 let |
132 let |
179 val w1 = weightTerm weight tm1 |
133 val w1 = weightTerm weight tm1 |
180 and w2 = weightTerm weight tm2 |
134 and w2 = weightTerm weight tm2 |
197 | SOME n => n > 0 |
151 | SOME n => n > 0 |
198 |
152 |
199 and precedenceLess (Term.Fn (f1,a1)) (Term.Fn (f2,a2)) = |
153 and precedenceLess (Term.Fn (f1,a1)) (Term.Fn (f2,a2)) = |
200 (case precedence ((f1, length a1), (f2, length a2)) of |
154 (case precedence ((f1, length a1), (f2, length a2)) of |
201 LESS => true |
155 LESS => true |
202 | EQUAL => firstNotEqual weightLess (zip a1 a2) |
156 | EQUAL => firstNotEqualTerm weightLess (zip a1 a2) |
203 | GREATER => false) |
157 | GREATER => false) |
204 | precedenceLess _ _ = false |
158 | precedenceLess _ _ = false |
205 |
159 |
206 fun weightDiffGreater w tm1 tm2 = weightDiffLess (weightNeg w) tm2 tm1 |
160 fun weightDiffGreater w tm1 tm2 = weightDiffLess (weightNeg w) tm2 tm1 |
207 |
161 |
208 fun weightCmp tm1 tm2 = |
162 fun weightCmp tm1 tm2 = |
209 let |
163 let |
210 val w = weightDifference tm1 tm2 |
164 val w = weightDifference tm1 tm2 |
211 in |
165 in |
212 if weightIsZero w then precedenceCmp tm1 tm2 |
166 if weightIsZero w then precedenceCmp tm1 tm2 |
213 else if weightDiffLess w tm1 tm2 then Less |
167 else if weightDiffLess w tm1 tm2 then SOME LESS |
214 else if weightDiffGreater w tm1 tm2 then Greater |
168 else if weightDiffGreater w tm1 tm2 then SOME GREATER |
215 else SignOf w |
169 else NONE |
216 end |
170 end |
217 |
171 |
218 and precedenceCmp (Term.Fn (f1,a1)) (Term.Fn (f2,a2)) = |
172 and precedenceCmp (Term.Fn (f1,a1)) (Term.Fn (f2,a2)) = |
219 (case precedence ((f1, length a1), (f2, length a2)) of |
173 (case precedence ((f1, length a1), (f2, length a2)) of |
220 LESS => Less |
174 LESS => SOME LESS |
221 | EQUAL => firstNotEqual weightCmp (zip a1 a2) |
175 | EQUAL => firstNotEqualTerm weightCmp (zip a1 a2) |
222 | GREATER => Greater) |
176 | GREATER => SOME GREATER) |
223 | precedenceCmp _ _ = raise Bug "kboOrder.precendenceCmp" |
177 | precedenceCmp _ _ = raise Bug "kboOrder.precendenceCmp" |
224 in |
178 in |
225 fn (tm1,tm2) => if tm1 = tm2 then Equal else weightCmp tm1 tm2 |
179 fn (tm1,tm2) => |
|
180 if Term.equal tm1 tm2 then SOME EQUAL else weightCmp tm1 tm2 |
226 end; |
181 end; |
227 |
182 |
228 fun compare kbo tm1_tm2 = |
183 (*MetisTrace7 |
229 case kboOrder kbo tm1_tm2 of |
|
230 Less => SOME LESS |
|
231 | Equal => SOME EQUAL |
|
232 | Greater => SOME GREATER |
|
233 | SignOf _ => NONE; |
|
234 |
|
235 (*TRACE7 |
|
236 val compare = fn kbo => fn (tm1,tm2) => |
184 val compare = fn kbo => fn (tm1,tm2) => |
237 let |
185 let |
238 val () = Parser.ppTrace Term.pp "KnuthBendixOrder.compare: tm1" tm1 |
186 val () = Print.trace Term.pp "KnuthBendixOrder.compare: tm1" tm1 |
239 val () = Parser.ppTrace Term.pp "KnuthBendixOrder.compare: tm2" tm2 |
187 val () = Print.trace Term.pp "KnuthBendixOrder.compare: tm2" tm2 |
240 val result = compare kbo (tm1,tm2) |
188 val result = compare kbo (tm1,tm2) |
241 val () = |
189 val () = |
242 case result of |
190 case result of |
243 NONE => trace "KnuthBendixOrder.compare: result = Incomparable\n" |
191 NONE => trace "KnuthBendixOrder.compare: result = Incomparable\n" |
244 | SOME x => |
192 | SOME x => |
245 Parser.ppTrace Parser.ppOrder "KnuthBendixOrder.compare: result" x |
193 Print.trace Print.ppOrder "KnuthBendixOrder.compare: result" x |
246 in |
194 in |
247 result |
195 result |
248 end; |
196 end; |
249 *) |
197 *) |
250 |
198 |