1 | //////////////////////////////////////////////////////////// |
---|
2 | // This is really experimental. What is the best order of the variables for |
---|
3 | // an ideal? Clearly, if a variable only occures in one and only one polynomial |
---|
4 | // this variable should be assigned the highest level. |
---|
5 | // But what for the others? |
---|
6 | // |
---|
7 | // The strategy used here is o.k. for *most* of the examples. But there are |
---|
8 | // examples where this strategy doesn't give the best possible answer. |
---|
9 | // So, use this at your own risk! The order given may increase or decrease |
---|
10 | // computing time for your example! |
---|
11 | ///////////////////////////////////////////////////////////// |
---|
12 | // emacs edit mode for this file is -*- C++ -*- |
---|
13 | /* $Id$ */ |
---|
14 | //////////////////////////////////////////////////////////// |
---|
15 | // FACTORY - Includes |
---|
16 | #include <factory.h> |
---|
17 | // Factor - Includes |
---|
18 | #include <tmpl_inst.h> |
---|
19 | #include "homogfactor.h" |
---|
20 | // Charset - Includes |
---|
21 | |
---|
22 | // some CC's need this: |
---|
23 | #include "reorder.h" |
---|
24 | |
---|
25 | #ifdef REORDERDEBUG |
---|
26 | # define DEBUGOUTPUT |
---|
27 | #else |
---|
28 | # undef DEBUGOUTPUT |
---|
29 | #endif |
---|
30 | |
---|
31 | #include <libfac/factor/debug.h> |
---|
32 | #include "timing.h" |
---|
33 | TIMING_DEFINE_PRINT(neworder_time); |
---|
34 | |
---|
35 | #define __ARRAY_INIT__ -1 |
---|
36 | |
---|
37 | // the maximal degree of polys in PS wrt. variable x |
---|
38 | static int |
---|
39 | degpsmax( const CFList & PS, const Variable & x, |
---|
40 | Intarray & A, Intarray & C){ |
---|
41 | int varlevel = level(x); |
---|
42 | if ( A[varlevel] != __ARRAY_INIT__ ) return A[varlevel]; |
---|
43 | int max=0,temp, count=0; |
---|
44 | |
---|
45 | for ( CFListIterator i=PS; i.hasItem();i++){ |
---|
46 | temp = degree(i.getItem(),x); |
---|
47 | if ( temp > max ) {max = temp; count = 0; } |
---|
48 | if ( temp == max) { count += max; } // we count the number of polys |
---|
49 | } |
---|
50 | A[varlevel] = max; C[varlevel] = count; |
---|
51 | return max; |
---|
52 | } |
---|
53 | |
---|
54 | // the minimal non-zero degree of polys in PS wrt. x |
---|
55 | // returns 0 if variable x doesn't occure in any of the polys |
---|
56 | static int |
---|
57 | degpsmin( const CFList & PS, const Variable & x, Intarray & A, Intarray & B, |
---|
58 | Intarray & C, Intarray & D){ |
---|
59 | int varlevel = level(x); |
---|
60 | if ( B[varlevel] != __ARRAY_INIT__ ) return B[varlevel]; |
---|
61 | int min=degpsmax(PS,x,A,C), temp, count=0; |
---|
62 | |
---|
63 | if (min==0) { |
---|
64 | B[varlevel] = min; D[varlevel] = min; |
---|
65 | return min; |
---|
66 | } |
---|
67 | else |
---|
68 | for ( CFListIterator i=PS; i.hasItem();i++){ |
---|
69 | temp = degree(i.getItem(),x); |
---|
70 | if ( temp < min && temp != 0 ){ min = temp; count = 0; } |
---|
71 | if ( temp == min) { count += min;} // we count the number of polys |
---|
72 | } |
---|
73 | B[varlevel] = min; D[varlevel] = count; |
---|
74 | return min; |
---|
75 | } |
---|
76 | |
---|
77 | // the minimal total degree of lcoeffs of polys in PS wrt. x |
---|
78 | // for those polys having degree degpsmin in x. |
---|
79 | // F will be assigned the minimal number of terms of those lcoeffs |
---|
80 | static int |
---|
81 | Tdeg( const CFList & PS, const Variable & x, Intarray & A, Intarray & B, |
---|
82 | Intarray & C, Intarray & D, Intarray & E, Intarray & F){ |
---|
83 | int k= degpsmin(PS,x,A,B,C,D), |
---|
84 | varlevel= level(x), min=0; |
---|
85 | |
---|
86 | if ( E[varlevel] != __ARRAY_INIT__ ) return E[varlevel]; |
---|
87 | if (k == 0){ |
---|
88 | E[varlevel]= 0; F[varlevel]= 0; |
---|
89 | } |
---|
90 | else{ |
---|
91 | int nopslc=0; |
---|
92 | CFList LCdegList; |
---|
93 | CanonicalForm elem; |
---|
94 | CFListIterator i; |
---|
95 | |
---|
96 | for ( i=PS; i.hasItem(); i++ ){ |
---|
97 | elem = i.getItem(); |
---|
98 | if ( degree(elem,x) == k ) LCdegList.append(LC(elem,x)); |
---|
99 | } |
---|
100 | |
---|
101 | if ( LCdegList.length() > 0 ){ |
---|
102 | CFList TermList; |
---|
103 | int newmin, newnopslc; |
---|
104 | |
---|
105 | min= totaldegree(LCdegList.getFirst()); |
---|
106 | TermList= get_Terms(LCdegList.getFirst()); |
---|
107 | nopslc= TermList.length(); |
---|
108 | for ( i=LCdegList; i.hasItem(); i++){ |
---|
109 | elem= i.getItem(); |
---|
110 | newmin= totaldegree(elem); |
---|
111 | TermList= get_Terms(elem); |
---|
112 | newnopslc= TermList.length(); |
---|
113 | if ( newmin < min ) min= newmin; |
---|
114 | if ( newnopslc < nopslc ) nopslc= newnopslc; |
---|
115 | } |
---|
116 | |
---|
117 | } |
---|
118 | E[varlevel]= min; |
---|
119 | F[varlevel]= nopslc; |
---|
120 | } |
---|
121 | return min; |
---|
122 | } |
---|
123 | |
---|
124 | // The number of the poly in which Variable x first occures |
---|
125 | static int |
---|
126 | nr_of_poly( const CFList & PS, const Variable & x, Intarray & G){ |
---|
127 | int min=0, varlevel=level(x); |
---|
128 | if ( G[varlevel] != __ARRAY_INIT__ ) return G[varlevel]; |
---|
129 | for ( CFListIterator i=PS; i.hasItem(); i++ ){ |
---|
130 | min += 1; |
---|
131 | if ( degree(i.getItem(),x) > 0 ) break; |
---|
132 | } |
---|
133 | G[varlevel]= min; |
---|
134 | return min; |
---|
135 | } |
---|
136 | |
---|
137 | static int |
---|
138 | degord( const Variable & x, const Variable & y, const CFList & PS, |
---|
139 | Intarray & A, Intarray & B, Intarray & C, Intarray & D, |
---|
140 | Intarray & E, Intarray & F, Intarray & G){ |
---|
141 | int xlevel= level(x), ylevel= level(y); |
---|
142 | |
---|
143 | if (degpsmax(PS,y,A,C) < degpsmax(PS,x,A,C)) return 1; |
---|
144 | else if (degpsmax(PS,x,A,C) < degpsmax(PS,y,A,C) ) return 0; |
---|
145 | else if (C[ylevel] < C[xlevel]) return 1; |
---|
146 | else if (C[xlevel] < C[ylevel]) return 0; |
---|
147 | else if (degpsmin(PS,x,A,B,C,D) < degpsmin(PS,y,A,B,C,D)) return 1; |
---|
148 | else if (degpsmin(PS,y,A,B,C,D) < degpsmin(PS,x,A,B,C,D)) return 0; |
---|
149 | else if (D[ylevel] < D[xlevel]) return 1; |
---|
150 | else if (D[xlevel] < D[ylevel]) return 0; |
---|
151 | else if (Tdeg(PS,y,A,B,C,D,E,F) < Tdeg(PS,x,A,B,C,D,E,F)) return 1; |
---|
152 | else if (Tdeg(PS,x,A,B,C,D,E,F) < Tdeg(PS,y,A,B,C,D,E,F)) return 0; |
---|
153 | else if (F[ylevel] < F[xlevel]) return 1; |
---|
154 | else if (F[xlevel] < F[ylevel]) return 0; |
---|
155 | else if (nr_of_poly(PS,x,G) <= nr_of_poly(PS,y,G)) return 1; |
---|
156 | else return 0; |
---|
157 | |
---|
158 | } |
---|
159 | |
---|
160 | // determine the highest variable of all involved Variables in PS |
---|
161 | // NOTE: |
---|
162 | // this doesn't give always the correct answer: |
---|
163 | // If a variable is assigned the highest level in the definition of the |
---|
164 | // original ring, but doesn't occure in any of the |
---|
165 | // polynomials, get_max_var returns the variable with a level lower than |
---|
166 | // the highest level. |
---|
167 | // Is there a workaround? |
---|
168 | // But for the redefinition of the ring this doesn't matter due to the |
---|
169 | // implementation of neworder(). |
---|
170 | |
---|
171 | static Variable |
---|
172 | get_max_var(const CFList & PS){ |
---|
173 | Variable x=PS.getFirst().mvar(), y; |
---|
174 | for (CFListIterator i=PS; i.hasItem(); i++){ |
---|
175 | y = i.getItem().mvar(); |
---|
176 | if ( y > x ) x=y; |
---|
177 | } |
---|
178 | return x; |
---|
179 | } |
---|
180 | |
---|
181 | |
---|
182 | // determine if variable x is in one and only one of the polynomials in PS |
---|
183 | // first criterion for neworder |
---|
184 | static CFList |
---|
185 | only_in_one( const CFList & PS , const Variable & x){ |
---|
186 | CFList output; |
---|
187 | |
---|
188 | for ( CFListIterator i=PS; i.hasItem(); i++ ){ |
---|
189 | if ( degree(i.getItem(),x) >= 1 ) output.insert(i.getItem()); |
---|
190 | if ( output.length() >= 2 ) break; |
---|
191 | } |
---|
192 | return output; |
---|
193 | } |
---|
194 | |
---|
195 | // initialize all Arrays (of same range) with __ARRAY_INIT__ |
---|
196 | static void |
---|
197 | initArray(const int highest_level, Intarray & A, Intarray & B, Intarray & C, |
---|
198 | Intarray & D, Intarray & E, Intarray & F, Intarray & G){ |
---|
199 | |
---|
200 | for ( int i=1 ; i <= highest_level; i ++){ |
---|
201 | A[i] = __ARRAY_INIT__; B[i] = __ARRAY_INIT__; |
---|
202 | C[i] = __ARRAY_INIT__; D[i] = __ARRAY_INIT__; |
---|
203 | E[i] = __ARRAY_INIT__; F[i] = __ARRAY_INIT__; |
---|
204 | G[i] = __ARRAY_INIT__; |
---|
205 | } |
---|
206 | } |
---|
207 | |
---|
208 | // now for the second criterion; a little more complex |
---|
209 | // |
---|
210 | // idea: set up seven arrays of lenth highest_level |
---|
211 | // (of which some entries may be empty, because of only_in_one!) |
---|
212 | // A saves maxdegree of Variable x in A(level(x)) |
---|
213 | // B saves mindegree of Variable x in B(level(x)) |
---|
214 | // C saves the number of polys in PS which have degree A(level(x)) in |
---|
215 | // D(level(x)) |
---|
216 | // D saves the number of polys in PS which have degree B(level(x)) in |
---|
217 | // D(level(x)) |
---|
218 | // E saves the minimal total degree of lcoeffs of polys wrt x in E(level(x)) |
---|
219 | // F saves the minimal number of terms of lcoeffs of E(level(x)) in F(~) |
---|
220 | // G saves nr of poly Variable x has first deg <> 0 |
---|
221 | |
---|
222 | #define __INIT_GAP__ 3 |
---|
223 | static Varlist |
---|
224 | reorderb(const Varlist & difference, const CFList & PS, |
---|
225 | const int highest_level){ |
---|
226 | Intarray A(1, highest_level), B(1, highest_level), C(1, highest_level), |
---|
227 | D(1, highest_level), E(1, highest_level), F(1, highest_level), |
---|
228 | G(1, highest_level); |
---|
229 | initArray(highest_level,A,B,C,D,E,F,G); |
---|
230 | int i=0, j, n=difference.length(), gap=1+__INIT_GAP__; |
---|
231 | Variable temp; |
---|
232 | Array<Variable> v(0,n); |
---|
233 | VarlistIterator J; |
---|
234 | |
---|
235 | for (J= difference; J.hasItem(); J++ ){ |
---|
236 | v[i]= J.getItem(); |
---|
237 | i++ ; |
---|
238 | } |
---|
239 | |
---|
240 | while ( gap <= n) gap = __INIT_GAP__ * gap+1; |
---|
241 | gap /= __INIT_GAP__; |
---|
242 | DEBOUTLN(CERR, "gap is ", gap); |
---|
243 | |
---|
244 | while ( gap > 0 ){ |
---|
245 | for ( i=gap; i<= n-1; i++){ |
---|
246 | temp = v[i]; |
---|
247 | for ( j= i-gap; j >=0 ; j-=gap){ |
---|
248 | if (degord(v[j],temp, PS, A,B,C,D,E,F,G)) break; |
---|
249 | v[j+gap] = v[j]; |
---|
250 | //CERR << "v[" << j+gap << "]= " << v[j+gap] << "\n"; |
---|
251 | } |
---|
252 | v[j+gap] = temp; |
---|
253 | //CERR << "v[" << j+gap << "]= " << v[j+gap] << "\n"; |
---|
254 | } |
---|
255 | gap /= __INIT_GAP__; |
---|
256 | } |
---|
257 | Varlist output; |
---|
258 | for (i=0; i<= n-1; i++) |
---|
259 | output.append(v[i]); |
---|
260 | DEBOUTLN(CERR, "A= ", A); DEBOUTLN(CERR, "B= ", B); |
---|
261 | DEBOUTLN(CERR, "C= ", C); DEBOUTLN(CERR, "D= ", D); |
---|
262 | DEBOUTLN(CERR, "E= ", E); DEBOUTLN(CERR, "F= ", F); |
---|
263 | DEBOUTLN(CERR, "G= ", G); |
---|
264 | return output; |
---|
265 | } |
---|
266 | |
---|
267 | // set up a new orderd list of Variables. |
---|
268 | // we try to reorder the variables heuristically optimal. |
---|
269 | Varlist |
---|
270 | neworder( const CFList & PolyList ){ |
---|
271 | CFList PS= PolyList, PS1=PolyList; |
---|
272 | Varlist oldorder, reorder, difference; |
---|
273 | |
---|
274 | DEBINCLEVEL(CERR, "neworder"); |
---|
275 | TIMING_START(neworder_time); |
---|
276 | |
---|
277 | int highest_level= level(get_max_var(PS)); |
---|
278 | DEBOUTLN(CERR, "neworder: highest_level= ", highest_level); |
---|
279 | DEBOUTLN(CERR, "neworder: that is variable ", Variable(highest_level)); |
---|
280 | |
---|
281 | // set up oldorder and first criterion: only_in_one |
---|
282 | for (int i=highest_level; i>=1; i--){ |
---|
283 | oldorder.insert(Variable(i)); |
---|
284 | CFList is_one= only_in_one(PS1, Variable(i)); |
---|
285 | if ( is_one.length() == 1 ){ |
---|
286 | DEBOUTLN(CERR, "Found a variable which is in only one Polynomial: ", |
---|
287 | Variable(i)); |
---|
288 | DEBOUTLN(CERR, ".... in the Polynomial: ", is_one.getFirst()); |
---|
289 | reorder.insert(Variable(i)); |
---|
290 | PS1 = Difference(PS1, is_one); |
---|
291 | DEBOUTLN(CERR, "New cutted list is: ", PS1); |
---|
292 | } |
---|
293 | else if ( is_one.length() == 0 ){ |
---|
294 | DEBOUTLN(CERR, "Found a variable which is in no polynomial: ", |
---|
295 | Variable(i)); |
---|
296 | DEBOUTMSG(CERR, "... assigning it the highest level."); |
---|
297 | reorder.append(Variable(i)); // assigne it the highest level |
---|
298 | PS1 = Difference(PS1, is_one); |
---|
299 | } |
---|
300 | } |
---|
301 | difference = Difference(oldorder,reorder); |
---|
302 | DEBOUTLN(CERR, "Missing variables are: ", difference); |
---|
303 | // rearrange the ordering of the variables! |
---|
304 | difference = reorderb(difference, PS, highest_level); |
---|
305 | DEBOUTLN(CERR, "second criterion gives: ", difference); |
---|
306 | reorder = Union(reorder, difference); |
---|
307 | DEBOUTLN(CERR, "old order was: ", oldorder); |
---|
308 | DEBOUTLN(CERR, "New order will be: ", Union(reorder, Difference(oldorder,reorder))); |
---|
309 | DEBDECLEVEL(CERR, "neworder"); |
---|
310 | TIMING_END(neworder_time); |
---|
311 | |
---|
312 | TIMING_PRINT(neworder_time, "\ntime used for neworder : "); |
---|
313 | |
---|
314 | |
---|
315 | return Union(reorder,Difference(oldorder,reorder)); |
---|
316 | } |
---|
317 | |
---|
318 | // the same as above, only returning a list of CanonicalForms |
---|
319 | CFList |
---|
320 | newordercf(const CFList & PolyList ){ |
---|
321 | Varlist reorder= neworder(PolyList); |
---|
322 | CFList output; |
---|
323 | |
---|
324 | for (VarlistIterator i=reorder; i.hasItem(); i++) |
---|
325 | output.append(CanonicalForm(i.getItem())); |
---|
326 | |
---|
327 | return output; |
---|
328 | } |
---|
329 | |
---|
330 | // the same as above, only returning a list of ints |
---|
331 | IntList |
---|
332 | neworderint(const CFList & PolyList ){ |
---|
333 | Varlist reorder= neworder(PolyList); |
---|
334 | IntList output; |
---|
335 | |
---|
336 | for (VarlistIterator i=reorder; i.hasItem(); i++) |
---|
337 | output.append(level(i.getItem())); |
---|
338 | |
---|
339 | return output; |
---|
340 | } |
---|
341 | |
---|
342 | // swapvar a whole list of CanonicalForms |
---|
343 | static CFList |
---|
344 | swapvar( const CFList & PS, const Variable & x, const Variable & y){ |
---|
345 | CFList ps; |
---|
346 | |
---|
347 | for (CFListIterator i= PS; i.hasItem(); i++) |
---|
348 | ps.append(swapvar(i.getItem(),x,y)); |
---|
349 | return ps; |
---|
350 | } |
---|
351 | |
---|
352 | static CFFList |
---|
353 | swapvar( const CFFList & PS, const Variable & x, const Variable & y){ |
---|
354 | CFFList ps; |
---|
355 | |
---|
356 | for (CFFListIterator i= PS; i.hasItem(); i++) |
---|
357 | ps.append(CFFactor(swapvar(i.getItem().factor(),x,y),i.getItem().exp())); |
---|
358 | return ps; |
---|
359 | } |
---|
360 | |
---|
361 | // a library function: we reorganize the global variable ordering |
---|
362 | CFList |
---|
363 | reorder( const Varlist & betterorder, const CFList & PS){ |
---|
364 | int i=1, n = betterorder.length(); |
---|
365 | Intarray v(1,n); |
---|
366 | CFList ps=PS; |
---|
367 | |
---|
368 | //initalize: |
---|
369 | for (VarlistIterator j = betterorder; j.hasItem(); j++){ |
---|
370 | v[i]= level(j.getItem()); i++; |
---|
371 | } |
---|
372 | DEBOUTLN(CERR, "reorder: Original ps= ", ps); |
---|
373 | // reorder: |
---|
374 | for (i=1; i <= n; i++) |
---|
375 | ps=swapvar(ps,Variable(v[i]),Variable(n+i)); |
---|
376 | DEBOUTLN(CERR, "reorder: Reorganized ps= ", ps); |
---|
377 | return ps; |
---|
378 | } |
---|
379 | |
---|
380 | CFFList |
---|
381 | reorder( const Varlist & betterorder, const CFFList & PS){ |
---|
382 | int i=1, n = betterorder.length(); |
---|
383 | Intarray v(1,n); |
---|
384 | CFFList ps=PS; |
---|
385 | |
---|
386 | //initalize: |
---|
387 | for (VarlistIterator j = betterorder; j.hasItem(); j++){ |
---|
388 | v[i]= level(j.getItem()); i++; |
---|
389 | } |
---|
390 | DEBOUTLN(CERR, "reorder: Original ps= ", ps); |
---|
391 | // reorder: |
---|
392 | for (i=1; i <= n; i++) |
---|
393 | ps=swapvar(ps,Variable(v[i]),Variable(n+i)); |
---|
394 | DEBOUTLN(CERR, "reorder: Reorganized ps= ", ps); |
---|
395 | return ps; |
---|
396 | } |
---|
397 | |
---|
398 | ListCFList |
---|
399 | reorder(const Varlist & betterorder, const ListCFList & Q){ |
---|
400 | ListCFList Q1; |
---|
401 | |
---|
402 | for ( ListCFListIterator i=Q; i.hasItem(); i++) |
---|
403 | Q1.append(reorder(betterorder, i.getItem())); |
---|
404 | return Q1; |
---|
405 | } |
---|
406 | |
---|