//////////////////////////////////////////////////////////// // This is really experimental. What is the best order of the variables for // an ideal? Clearly, if a variable only occures in one and only one polynomial // this variable should be assigned the highest level. // But what for the others? // // The strategy used here is o.k. for *most* of the examples. But there are // examples where this strategy doesn't give the best possible answer. // So, use this at your own risk! The order given may increase or decrease // computing time for your example! ///////////////////////////////////////////////////////////// // emacs edit mode for this file is -*- C++ -*- //////////////////////////////////////////////////////////// // FACTORY - Includes #include // Factor - Includes #include #include "homogfactor.h" // Charset - Includes // some CC's need this: #include "reorder.h" #ifdef REORDERDEBUG # define DEBUGOUTPUT #else # undef DEBUGOUTPUT #endif #include #include "timing.h" TIMING_DEFINE_PRINT(neworder_time) #define __ARRAY_INIT__ -1 // the maximal degree of polys in PS wrt. variable x static int degpsmax( const CFList & PS, const Variable & x, Intarray & A, Intarray & C){ int varlevel = level(x); if ( A[varlevel] != __ARRAY_INIT__ ) return A[varlevel]; int max=0,temp, count=0; for ( CFListIterator i=PS; i.hasItem();i++){ temp = degree(i.getItem(),x); if ( temp > max ) {max = temp; count = 0; } if ( temp == max) { count += max; } // we count the number of polys } A[varlevel] = max; C[varlevel] = count; return max; } // the minimal non-zero degree of polys in PS wrt. x // returns 0 if variable x doesn't occure in any of the polys static int degpsmin( const CFList & PS, const Variable & x, Intarray & A, Intarray & B, Intarray & C, Intarray & D){ int varlevel = level(x); if ( B[varlevel] != __ARRAY_INIT__ ) return B[varlevel]; int min=degpsmax(PS,x,A,C), temp, count=0; if (min==0) { B[varlevel] = min; D[varlevel] = min; return min; } else for ( CFListIterator i=PS; i.hasItem();i++){ temp = degree(i.getItem(),x); if ( temp < min && temp != 0 ){ min = temp; count = 0; } if ( temp == min) { count += min;} // we count the number of polys } B[varlevel] = min; D[varlevel] = count; return min; } // the minimal total degree of lcoeffs of polys in PS wrt. x // for those polys having degree degpsmin in x. // F will be assigned the minimal number of terms of those lcoeffs static int Tdeg( const CFList & PS, const Variable & x, Intarray & A, Intarray & B, Intarray & C, Intarray & D, Intarray & E, Intarray & F){ int k= degpsmin(PS,x,A,B,C,D), varlevel= level(x), min=0; if ( E[varlevel] != __ARRAY_INIT__ ) return E[varlevel]; if (k == 0){ E[varlevel]= 0; F[varlevel]= 0; } else{ int nopslc=0; CFList LCdegList; CanonicalForm elem; CFListIterator i; for ( i=PS; i.hasItem(); i++ ){ elem = i.getItem(); if ( degree(elem,x) == k ) LCdegList.append(LC(elem,x)); } if ( LCdegList.length() > 0 ){ CFList TermList; int newmin, newnopslc; min= totaldegree(LCdegList.getFirst()); TermList= get_Terms(LCdegList.getFirst()); nopslc= TermList.length(); for ( i=LCdegList; i.hasItem(); i++){ elem= i.getItem(); newmin= totaldegree(elem); TermList= get_Terms(elem); newnopslc= TermList.length(); if ( newmin < min ) min= newmin; if ( newnopslc < nopslc ) nopslc= newnopslc; } } E[varlevel]= min; F[varlevel]= nopslc; } return min; } // The number of the poly in which Variable x first occures static int nr_of_poly( const CFList & PS, const Variable & x, Intarray & G){ int min=0, varlevel=level(x); if ( G[varlevel] != __ARRAY_INIT__ ) return G[varlevel]; for ( CFListIterator i=PS; i.hasItem(); i++ ){ min += 1; if ( degree(i.getItem(),x) > 0 ) break; } G[varlevel]= min; return min; } static int degord( const Variable & x, const Variable & y, const CFList & PS, Intarray & A, Intarray & B, Intarray & C, Intarray & D, Intarray & E, Intarray & F, Intarray & G){ int xlevel= level(x), ylevel= level(y); if (degpsmax(PS,y,A,C) < degpsmax(PS,x,A,C)) return 1; else if (degpsmax(PS,x,A,C) < degpsmax(PS,y,A,C) ) return 0; else if (C[ylevel] < C[xlevel]) return 1; else if (C[xlevel] < C[ylevel]) return 0; else if (degpsmin(PS,x,A,B,C,D) < degpsmin(PS,y,A,B,C,D)) return 1; else if (degpsmin(PS,y,A,B,C,D) < degpsmin(PS,x,A,B,C,D)) return 0; else if (D[ylevel] < D[xlevel]) return 1; else if (D[xlevel] < D[ylevel]) return 0; else if (Tdeg(PS,y,A,B,C,D,E,F) < Tdeg(PS,x,A,B,C,D,E,F)) return 1; else if (Tdeg(PS,x,A,B,C,D,E,F) < Tdeg(PS,y,A,B,C,D,E,F)) return 0; else if (F[ylevel] < F[xlevel]) return 1; else if (F[xlevel] < F[ylevel]) return 0; else if (nr_of_poly(PS,x,G) <= nr_of_poly(PS,y,G)) return 1; else return 0; } // determine the highest variable of all involved Variables in PS // NOTE: // this doesn't give always the correct answer: // If a variable is assigned the highest level in the definition of the // original ring, but doesn't occure in any of the // polynomials, get_max_var returns the variable with a level lower than // the highest level. // Is there a workaround? // But for the redefinition of the ring this doesn't matter due to the // implementation of neworder(). static Variable get_max_var(const CFList & PS){ Variable x=PS.getFirst().mvar(), y; for (CFListIterator i=PS; i.hasItem(); i++){ y = i.getItem().mvar(); if ( y > x ) x=y; } return x; } // determine if variable x is in one and only one of the polynomials in PS // first criterion for neworder static CFList only_in_one( const CFList & PS , const Variable & x){ CFList output; for ( CFListIterator i=PS; i.hasItem(); i++ ){ if ( degree(i.getItem(),x) >= 1 ) output.insert(i.getItem()); if ( output.length() >= 2 ) break; } return output; } // initialize all Arrays (of same range) with __ARRAY_INIT__ static void initArray(const int highest_level, Intarray & A, Intarray & B, Intarray & C, Intarray & D, Intarray & E, Intarray & F, Intarray & G){ for ( int i=1 ; i <= highest_level; i ++){ A[i] = __ARRAY_INIT__; B[i] = __ARRAY_INIT__; C[i] = __ARRAY_INIT__; D[i] = __ARRAY_INIT__; E[i] = __ARRAY_INIT__; F[i] = __ARRAY_INIT__; G[i] = __ARRAY_INIT__; } } // now for the second criterion; a little more complex // // idea: set up seven arrays of lenth highest_level // (of which some entries may be empty, because of only_in_one!) // A saves maxdegree of Variable x in A(level(x)) // B saves mindegree of Variable x in B(level(x)) // C saves the number of polys in PS which have degree A(level(x)) in // D(level(x)) // D saves the number of polys in PS which have degree B(level(x)) in // D(level(x)) // E saves the minimal total degree of lcoeffs of polys wrt x in E(level(x)) // F saves the minimal number of terms of lcoeffs of E(level(x)) in F(~) // G saves nr of poly Variable x has first deg <> 0 #define __INIT_GAP__ 3 static Varlist reorderb(const Varlist & difference, const CFList & PS, const int highest_level){ Intarray A(1, highest_level), B(1, highest_level), C(1, highest_level), D(1, highest_level), E(1, highest_level), F(1, highest_level), G(1, highest_level); initArray(highest_level,A,B,C,D,E,F,G); int i=0, j, n=difference.length(), gap=1+__INIT_GAP__; Variable temp; Array v(0,n); VarlistIterator J; for (J= difference; J.hasItem(); J++ ){ v[i]= J.getItem(); i++ ; } while ( gap <= n) gap = __INIT_GAP__ * gap+1; gap /= __INIT_GAP__; DEBOUTLN(CERR, "gap is ", gap); while ( gap > 0 ){ for ( i=gap; i<= n-1; i++){ temp = v[i]; for ( j= i-gap; j >=0 ; j-=gap){ if (degord(v[j],temp, PS, A,B,C,D,E,F,G)) break; v[j+gap] = v[j]; //CERR << "v[" << j+gap << "]= " << v[j+gap] << "\n"; } v[j+gap] = temp; //CERR << "v[" << j+gap << "]= " << v[j+gap] << "\n"; } gap /= __INIT_GAP__; } Varlist output; for (i=0; i<= n-1; i++) output.append(v[i]); DEBOUTLN(CERR, "A= ", A); DEBOUTLN(CERR, "B= ", B); DEBOUTLN(CERR, "C= ", C); DEBOUTLN(CERR, "D= ", D); DEBOUTLN(CERR, "E= ", E); DEBOUTLN(CERR, "F= ", F); DEBOUTLN(CERR, "G= ", G); return output; } // set up a new orderd list of Variables. // we try to reorder the variables heuristically optimal. Varlist neworder( const CFList & PolyList ){ CFList PS= PolyList, PS1=PolyList; Varlist oldorder, reorder, difference; DEBINCLEVEL(CERR, "neworder"); TIMING_START(neworder_time); int highest_level= level(get_max_var(PS)); DEBOUTLN(CERR, "neworder: highest_level= ", highest_level); DEBOUTLN(CERR, "neworder: that is variable ", Variable(highest_level)); // set up oldorder and first criterion: only_in_one for (int i=highest_level; i>=1; i--){ oldorder.insert(Variable(i)); CFList is_one= only_in_one(PS1, Variable(i)); if ( is_one.length() == 1 ){ DEBOUTLN(CERR, "Found a variable which is in only one Polynomial: ", Variable(i)); DEBOUTLN(CERR, ".... in the Polynomial: ", is_one.getFirst()); reorder.insert(Variable(i)); PS1 = Difference(PS1, is_one); DEBOUTLN(CERR, "New cutted list is: ", PS1); } else if ( is_one.length() == 0 ){ DEBOUTLN(CERR, "Found a variable which is in no polynomial: ", Variable(i)); DEBOUTMSG(CERR, "... assigning it the highest level."); reorder.append(Variable(i)); // assigne it the highest level PS1 = Difference(PS1, is_one); } } difference = Difference(oldorder,reorder); DEBOUTLN(CERR, "Missing variables are: ", difference); // rearrange the ordering of the variables! difference = reorderb(difference, PS, highest_level); DEBOUTLN(CERR, "second criterion gives: ", difference); reorder = Union(reorder, difference); DEBOUTLN(CERR, "old order was: ", oldorder); DEBOUTLN(CERR, "New order will be: ", Union(reorder, Difference(oldorder,reorder))); DEBDECLEVEL(CERR, "neworder"); TIMING_END(neworder_time); TIMING_PRINT(neworder_time, "\ntime used for neworder : "); return Union(reorder,Difference(oldorder,reorder)); } // the same as above, only returning a list of CanonicalForms CFList newordercf(const CFList & PolyList ){ Varlist reorder= neworder(PolyList); CFList output; for (VarlistIterator i=reorder; i.hasItem(); i++) output.append(CanonicalForm(i.getItem())); return output; } // the same as above, only returning a list of ints IntList neworderint(const CFList & PolyList ){ Varlist reorder= neworder(PolyList); IntList output; for (VarlistIterator i=reorder; i.hasItem(); i++) output.append(level(i.getItem())); return output; } // swapvar a whole list of CanonicalForms static CFList swapvar( const CFList & PS, const Variable & x, const Variable & y){ CFList ps; for (CFListIterator i= PS; i.hasItem(); i++) ps.append(swapvar(i.getItem(),x,y)); return ps; } static CFFList swapvar( const CFFList & PS, const Variable & x, const Variable & y){ CFFList ps; for (CFFListIterator i= PS; i.hasItem(); i++) ps.append(CFFactor(swapvar(i.getItem().factor(),x,y),i.getItem().exp())); return ps; } // a library function: we reorganize the global variable ordering CFList reorder( const Varlist & betterorder, const CFList & PS){ int i=1, n = betterorder.length(); Intarray v(1,n); CFList ps=PS; //initalize: for (VarlistIterator j = betterorder; j.hasItem(); j++){ v[i]= level(j.getItem()); i++; } DEBOUTLN(CERR, "reorder: Original ps= ", ps); // reorder: for (i=1; i <= n; i++) ps=swapvar(ps,Variable(v[i]),Variable(n+i)); DEBOUTLN(CERR, "reorder: Reorganized ps= ", ps); return ps; } CFFList reorder( const Varlist & betterorder, const CFFList & PS){ int i=1, n = betterorder.length(); Intarray v(1,n); CFFList ps=PS; //initalize: for (VarlistIterator j = betterorder; j.hasItem(); j++){ v[i]= level(j.getItem()); i++; } DEBOUTLN(CERR, "reorder: Original ps= ", ps); // reorder: for (i=1; i <= n; i++) ps=swapvar(ps,Variable(v[i]),Variable(n+i)); DEBOUTLN(CERR, "reorder: Reorganized ps= ", ps); return ps; } ListCFList reorder(const Varlist & betterorder, const ListCFList & Q){ ListCFList Q1; for ( ListCFListIterator i=Q; i.hasItem(); i++) Q1.append(reorder(betterorder, i.getItem())); return Q1; }