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