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