001/* 002 * $Id: TermOrderOptimization.java 4162 2012-09-08 10:41:51Z kredel $ 003 */ 004 005package edu.jas.poly; 006 007import java.util.List; 008import java.util.ArrayList; 009import java.util.Collection; 010import java.util.Arrays; 011import java.util.Map; 012import java.util.SortedMap; 013import java.util.TreeMap; 014 015import org.apache.log4j.Logger; 016 017import edu.jas.structure.RingElem; 018 019import edu.jas.arith.BigInteger; 020 021import edu.jas.poly.GenPolynomial; 022import edu.jas.poly.GenPolynomialRing; 023 024import edu.jas.vector.BasicLinAlg; 025 026 027/** 028 * Term order optimization. 029 * See mas10/maspoly/DIPTOO.m{di}. 030 * @author Heinz Kredel 031 */ 032 033public class TermOrderOptimization { 034 035 036 private static final Logger logger = Logger.getLogger(TermOrderOptimization.class); 037 //private static boolean debug = logger.isDebugEnabled(); 038 039 040 /** 041 * Degree matrix. 042 * @param A polynomial to be considered. 043 * @return degree matrix. 044 */ 045 public static <C extends RingElem<C>> 046 List<GenPolynomial<BigInteger>> degreeMatrix( GenPolynomial<C> A ) { 047 048 List<GenPolynomial<BigInteger>> dem = null; 049 if ( A == null ) { 050 return dem; 051 } 052 053 BigInteger cfac = new BigInteger(); 054 GenPolynomialRing<BigInteger> ufac 055 = new GenPolynomialRing<BigInteger>(cfac,1); 056 057 int nvar = A.numberOfVariables(); 058 dem = new ArrayList<GenPolynomial<BigInteger>>( nvar ); 059 060 for ( int i = 0; i < nvar; i++ ) { 061 dem.add( ufac.getZERO() ); 062 } 063 if ( A.isZERO() ) { 064 return dem; 065 } 066 067 for ( ExpVector e: A.getMap().keySet() ) { 068 dem = expVectorAdd(dem, e ); 069 } 070 return dem; 071 } 072 073 074 /** 075 * Degree matrix exponent vector add. 076 * @param dm degree matrix. 077 * @param e exponent vector. 078 * @return degree matrix + e. 079 */ 080 public static 081 List<GenPolynomial<BigInteger>> expVectorAdd(List<GenPolynomial<BigInteger>> dm, ExpVector e) { 082 for ( int i = 0; i < dm.size() && i < e.length(); i++ ) { 083 GenPolynomial<BigInteger> p = dm.get(i); 084 long u = e.getVal(i); 085 ExpVector f = ExpVector.create(1,0,u); 086 p = p.sum( p.ring.getONECoefficient(), f ); 087 dm.set(i,p); 088 } 089 return dm; 090 } 091 092 093 /** 094 * Degree matrix of coefficient polynomials. 095 * @param A polynomial to be considered. 096 * @return degree matrix for the coeficients. 097 */ 098 public static <C extends RingElem<C>> 099 List<GenPolynomial<BigInteger>> degreeMatrixOfCoefficients( GenPolynomial<GenPolynomial<C>> A ) { 100 if ( A == null ) { 101 throw new IllegalArgumentException("polynomial must not be null"); 102 } 103 return degreeMatrix( A.getMap().values() ); 104 } 105 106 107 /** 108 * Degree matrix. 109 * @param L list of polynomial to be considered. 110 * @return degree matrix. 111 */ 112 public static <C extends RingElem<C>> 113 List<GenPolynomial<BigInteger>> degreeMatrix( Collection<GenPolynomial<C>> L ) { 114 if ( L == null ) { 115 throw new IllegalArgumentException("list must be non null"); 116 } 117 BasicLinAlg<GenPolynomial<BigInteger>> blas = new BasicLinAlg<GenPolynomial<BigInteger>>(); 118 List<GenPolynomial<BigInteger>> dem = null; 119 for ( GenPolynomial<C> p : L ) { 120 List<GenPolynomial<BigInteger>> dm = degreeMatrix( p ); 121 if ( dem == null ) { 122 dem = dm; 123 } else { 124 dem = blas.vectorAdd( dem, dm ); 125 } 126 } 127 return dem; 128 } 129 130 131 /** 132 * Degree matrix of coefficient polynomials. 133 * @param L list of polynomial to be considered. 134 * @return degree matrix for the coeficients. 135 */ 136 public static <C extends RingElem<C>> 137 List<GenPolynomial<BigInteger>> 138 degreeMatrixOfCoefficients( Collection<GenPolynomial<GenPolynomial<C>>> L ) { 139 if ( L == null ) { 140 throw new IllegalArgumentException("list must not be null"); 141 } 142 BasicLinAlg<GenPolynomial<BigInteger>> blas = new BasicLinAlg<GenPolynomial<BigInteger>>(); 143 List<GenPolynomial<BigInteger>> dem = null; 144 for ( GenPolynomial<GenPolynomial<C>> p : L ) { 145 List<GenPolynomial<BigInteger>> dm = degreeMatrixOfCoefficients( p ); 146 if ( dem == null ) { 147 dem = dm; 148 } else { 149 dem = blas.vectorAdd( dem, dm ); 150 } 151 } 152 return dem; 153 } 154 155 156 /** 157 * Optimal permutation for the Degree matrix. 158 * @param D degree matrix. 159 * @return optimal permutation for D. 160 */ 161 public static 162 List<Integer> optimalPermutation( List<GenPolynomial<BigInteger>> D ) { 163 if ( D == null ) { 164 throw new IllegalArgumentException("list must be non null"); 165 } 166 List<Integer> P = new ArrayList<Integer>( D.size() ); 167 if ( D.size() == 0 ) { 168 return P; 169 } 170 if ( D.size() == 1 ) { 171 P.add(0); 172 return P; 173 } 174 SortedMap< GenPolynomial<BigInteger>, List<Integer> > map 175 = new TreeMap<GenPolynomial<BigInteger>,List<Integer>>(); 176 int i = 0; 177 for ( GenPolynomial<BigInteger> p : D ) { 178 List<Integer> il = map.get(p); 179 if ( il == null ) { 180 il = new ArrayList<Integer>(3); 181 } 182 il.add( i ); 183 map.put( p, il ); 184 i++; 185 } 186 List<List<Integer>> V = new ArrayList<List<Integer>>( map.values() ); 187 //System.out.println("V = " + V); 188 //for ( int j = V.size()-1; j >= 0; j-- ) { 189 for ( int j = 0; j < V.size(); j++ ) { 190 List<Integer> v = V.get(j); 191 for ( Integer k : v ) { 192 P.add( k ); 193 } 194 } 195 return P; 196 } 197 198 199 /** 200 * Inverse of a permutation. 201 * @param P permutation. 202 * @return S with S*P = id. 203 */ 204 public static List<Integer> inversePermutation( List<Integer> P ) { 205 if ( P == null || P.size() <= 1 ) { 206 return P; 207 } 208 List<Integer> ip = new ArrayList<Integer>(P); // ensure size and content 209 for ( int i = 0; i < P.size(); i++ ) { 210 ip.set(P.get(i),i); // inverse 211 } 212 return ip; 213 } 214 215 216 /** 217 * Test for identity permutation. 218 * @param P permutation. 219 * @return true , if P = id, else false. 220 */ 221 public static boolean isIdentityPermutation( List<Integer> P ) { 222 if ( P == null || P.size() <= 1 ) { 223 return true; 224 } 225 for ( int i = 0; i < P.size(); i++ ) { 226 if ( P.get(i).intValue() != i ) { 227 return false; 228 } 229 } 230 return true; 231 } 232 233 234 /** 235 * Multiplication permutations. 236 * @param P permutation. 237 * @param S permutation. 238 * @return P*S. 239 */ 240 public static List<Integer> multiplyPermutation( List<Integer> P, List<Integer> S ) { 241 if ( P == null || S == null ) { 242 return null; 243 } 244 if ( P.size() != S.size() ) { 245 throw new IllegalArgumentException("#P != #S: P =" + P + ", S = " + S); 246 } 247 List<Integer> ip = new ArrayList<Integer>(P); // ensure size and content 248 for ( int i = 0; i < P.size(); i++ ) { 249 ip.set(i,S.get(P.get(i))); 250 } 251 return ip; 252 } 253 254 255 /** 256 * Permutation of a list. 257 * @param L list. 258 * @param P permutation. 259 * @return P(L). 260 */ 261 public static <T> List<T> listPermutation( List<Integer> P, List<T> L ) { 262 if ( L == null || L.size() <= 1 ) { 263 return L; 264 } 265 List<T> pl = new ArrayList<T>( L.size() ); 266 for ( Integer i : P ) { 267 pl.add( L.get( (int)i ) ); 268 } 269 return pl; 270 } 271 272 273 /** 274 * Permutation of an array. 275 * Compiles, but does not work, requires JDK 1.6 to work. 276 * @param a array. 277 * @param P permutation. 278 * @return P(a). 279 */ 280 @SuppressWarnings("unchecked") 281 public static <T> T[] arrayPermutation( List<Integer> P, T[] a ) { 282 if ( a == null || a.length <= 1 ) { 283 return a; 284 } 285 T[] b = (T[]) new Object[a.length]; // jdk 1.5 286 //T[] b = Arrays.<T>copyOf( a, a.length ); // jdk 1.6, works 287 int j = 0; 288 for ( Integer i : P ) { 289 b[j] = a[ (int)i ]; 290 j++; 291 } 292 return b; 293 } 294 295 296 /** 297 * Permutation of an array. 298 * @param a array. 299 * @param P permutation. 300 * @return P(a). 301 */ 302 public static String[] stringArrayPermutation( List<Integer> P, String[] a ) { 303 if ( a == null || a.length <= 1 ) { 304 return a; 305 } 306 String[] b = new String[a.length]; // jdk 1.5 307 //T[] b = Arrays.<T>copyOf( a, a.length ); // jdk 1.6 308 int j = 0; 309 for ( Integer i : P ) { 310 b[j] = a[ (int)i ]; 311 j++; 312 } 313 return b; 314 } 315 316 317 /** 318 * Permutation of a long array. 319 * @param a array of long. 320 * @param P permutation. 321 * @return P(a). 322 */ 323 public static long[] longArrayPermutation( List<Integer> P, long[] a ) { 324 if ( a == null || a.length <= 1 ) { 325 return a; 326 } 327 long[] b = new long[ a.length ]; 328 int j = 0; 329 for ( Integer i : P ) { 330 b[j] = a[ (int)i ]; 331 j++; 332 } 333 return b; 334 } 335 336 337 /** 338 * Permutation of an exponent vector. 339 * @param e exponent vector. 340 * @param P permutation. 341 * @return P(e). 342 */ 343 public static 344 ExpVector permutation( List<Integer> P, ExpVector e ) { 345 if ( e == null ) { 346 return e; 347 } 348 long[] u = longArrayPermutation( P, e.getVal() ); 349 ExpVector f = ExpVector.create( u ); 350 return f; 351 } 352 353 354 /** 355 * Permutation of polynomial exponent vectors. 356 * @param A polynomial. 357 * @param R polynomial ring. 358 * @param P permutation. 359 * @return P(A). 360 */ 361 public static <C extends RingElem<C>> 362 GenPolynomial<C> permutation( List<Integer> P, GenPolynomialRing<C> R, GenPolynomial<C> A ) { 363 if ( A == null ) { 364 return A; 365 } 366 GenPolynomial<C> B = R.getZERO().copy(); 367 Map<ExpVector,C> Bv = B.val; //getMap(); 368 for ( Map.Entry<ExpVector,C> y: A.getMap().entrySet() ) { 369 ExpVector e = y.getKey(); 370 C a = y.getValue(); 371 //System.out.println("e = " + e); 372 ExpVector f = permutation(P,e); 373 //System.out.println("f = " + f); 374 Bv.put( f, a ); // assert f not in Bv 375 } 376 return B; 377 } 378 379 380 /** 381 * Permutation of polynomial exponent vectors. 382 * @param L list of polynomials. 383 * @param R polynomial ring. 384 * @param P permutation. 385 * @return P(L). 386 */ 387 public static <C extends RingElem<C>> 388 List<GenPolynomial<C>> 389 permutation( List<Integer> P, GenPolynomialRing<C> R, List<GenPolynomial<C>> L ) { 390 if ( L == null || L.size() == 0 ) { 391 return L; 392 } 393 List<GenPolynomial<C>> K = new ArrayList<GenPolynomial<C>>( L.size() ); 394 for ( GenPolynomial<C> a: L ) { 395 GenPolynomial<C> b = permutation( P, R, a ); 396 K.add( b ); 397 } 398 return K; 399 } 400 401 402 /** 403 * Permutation of polynomial exponent vectors of coefficient polynomials. 404 * @param A polynomial. 405 * @param R polynomial ring. 406 * @param P permutation. 407 * @return P(A). 408 */ 409 public static <C extends RingElem<C>> 410 GenPolynomial<GenPolynomial<C>> 411 permutationOnCoefficients( List<Integer> P, 412 GenPolynomialRing<GenPolynomial<C>> R, 413 GenPolynomial<GenPolynomial<C>> A ) { 414 if ( A == null ) { 415 return A; 416 } 417 GenPolynomial<GenPolynomial<C>> B = R.getZERO().copy(); 418 GenPolynomialRing<C> cf = (GenPolynomialRing<C>) R.coFac; 419 Map<ExpVector,GenPolynomial<C>> Bv = B.val; //getMap(); 420 for ( Map.Entry<ExpVector,GenPolynomial<C>> y: A.getMap().entrySet() ) { 421 ExpVector e = y.getKey(); 422 GenPolynomial<C> a = y.getValue(); 423 //System.out.println("e = " + e); 424 GenPolynomial<C> b = permutation(P,cf,a); 425 //System.out.println("b = " + b); 426 Bv.put( e, b ); // assert e not in Bv 427 } 428 return B; 429 } 430 431 432 /** 433 * Permutation of polynomial exponent vectors of coefficients. 434 * @param L list of polynomials. 435 * @param R polynomial ring. 436 * @param P permutation. 437 * @return P(L). 438 */ 439 public static <C extends RingElem<C>> 440 List<GenPolynomial<GenPolynomial<C>>> 441 permutationOnCoefficients( List<Integer> P, 442 GenPolynomialRing<GenPolynomial<C>> R, 443 List<GenPolynomial<GenPolynomial<C>>> L ) { 444 if ( L == null || L.size() == 0 ) { 445 return L; 446 } 447 List<GenPolynomial<GenPolynomial<C>>> K 448 = new ArrayList<GenPolynomial<GenPolynomial<C>>>( L.size() ); 449 for ( GenPolynomial<GenPolynomial<C>> a: L ) { 450 GenPolynomial<GenPolynomial<C>> b = permutationOnCoefficients( P, R, a ); 451 K.add( b ); 452 } 453 return K; 454 } 455 456 457 /** 458 * Permutation of polynomial ring variables. 459 * @param R polynomial ring. 460 * @param P permutation. 461 * @return P(R). 462 */ 463 public static <C extends RingElem<C>> 464 GenPolynomialRing<C> 465 permutation( List<Integer> P, GenPolynomialRing<C> R ) { 466 if ( R == null ) { 467 return R; 468 } 469 if ( R.vars == null || R.nvar <= 1 ) { 470 return R; 471 } 472 GenPolynomialRing<C> S; 473 TermOrder tord = R.tord; 474 if ( tord.getEvord2() != 0 ) { 475 //throw new IllegalArgumentException("split term orders not permutable"); 476 tord = new TermOrder( tord.getEvord2() ); 477 logger.warn("split term order '" + R.tord + "' not permutable, resetting to most base term order " + tord); 478 } 479 long[][] weight = tord.getWeight(); 480 if ( weight != null ) { 481 long[][] w = new long[ weight.length ][]; 482 for ( int i = 0; i < weight.length; i++ ) { 483 w[i] = longArrayPermutation(P,weight[i]); 484 } 485 tord = new TermOrder( w ); 486 } 487 String[] v1 = new String[R.vars.length]; 488 for ( int i = 0; i < v1.length; i++ ) { 489 v1[i] = R.vars[ v1.length-1 - i ]; 490 } 491 String[] vars = stringArrayPermutation( P, v1 ); 492 String[] v2 = new String[R.vars.length]; 493 for ( int i = 0; i < v1.length; i++ ) { 494 v2[i] = vars[ v2.length-1 - i ]; 495 } 496 S = new GenPolynomialRing<C>( R.coFac, R.nvar, tord, v2 ); 497 return S; 498 } 499 500 501 /** 502 * Optimize variable order. 503 * @param R polynomial ring. 504 * @param L list of polynomials. 505 * @return optimized polynomial list. 506 */ 507 public static <C extends RingElem<C>> 508 OptimizedPolynomialList<C> 509 optimizeTermOrder( GenPolynomialRing<C> R, List<GenPolynomial<C>> L ) { 510 List<Integer> perm = optimalPermutation( degreeMatrix(L) ); 511 GenPolynomialRing<C> pring = TermOrderOptimization.<C>permutation( perm, R ); 512 List<GenPolynomial<C>> ppolys = TermOrderOptimization.<C>permutation( perm, pring, L ); 513 OptimizedPolynomialList<C> op = new OptimizedPolynomialList<C>(perm,pring,ppolys); 514 return op; 515 } 516 517 518 /** 519 * Optimize variable order. 520 * @param P polynomial list. 521 * @return optimized polynomial list. 522 */ 523 public static <C extends RingElem<C>> 524 OptimizedPolynomialList<C> optimizeTermOrder( PolynomialList<C> P ) { 525 if ( P == null ) { 526 return null; 527 } 528 return optimizeTermOrder( P.ring, P.list ); 529 } 530 531 532 /** 533 * Optimize variable order on coefficients. 534 * @param P polynomial list. 535 * @return optimized polynomial list. 536 */ 537 public static <C extends RingElem<C>> 538 OptimizedPolynomialList<GenPolynomial<C>> 539 optimizeTermOrderOnCoefficients( PolynomialList<GenPolynomial<C>> P ) { 540 if ( P == null ) { 541 return null; 542 } 543 List<Integer> perm = optimalPermutation( degreeMatrixOfCoefficients( P.list ) ); 544 545 GenPolynomialRing<GenPolynomial<C>> ring = P.ring; 546 GenPolynomialRing<C> coFac = (GenPolynomialRing<C>) ring.coFac; 547 GenPolynomialRing<C> pFac; 548 pFac = TermOrderOptimization.<C>permutation( perm, coFac ); 549 550 GenPolynomialRing<GenPolynomial<C>> pring; 551 pring = new GenPolynomialRing<GenPolynomial<C>>(pFac, ring.nvar, ring.tord, ring.vars); 552 553 List<GenPolynomial<GenPolynomial<C>>> ppolys; 554 ppolys = TermOrderOptimization.<C>permutationOnCoefficients( perm, pring, P.list ); 555 556 OptimizedPolynomialList<GenPolynomial<C>> op 557 = new OptimizedPolynomialList<GenPolynomial<C>>(perm,pring,ppolys); 558 return op; 559 } 560 561}