001/* 002 * $Id: GroebnerBaseAbstract.java 5476 2016-03-25 17:57:05Z kredel $ 003 */ 004 005package edu.jas.gb; 006 007 008import java.util.ArrayList; 009import java.util.Collections; 010import java.util.HashSet; 011import java.util.List; 012import java.util.ListIterator; 013import java.util.Map; 014import java.util.Set; 015import java.util.TreeMap; 016 017import org.apache.log4j.Logger; 018 019import edu.jas.poly.ExpVector; 020import edu.jas.poly.GenPolynomial; 021import edu.jas.poly.GenPolynomialRing; 022import edu.jas.poly.ModuleList; 023import edu.jas.poly.OrderedPolynomialList; 024import edu.jas.poly.PolyUtil; 025import edu.jas.poly.PolynomialList; 026import edu.jas.poly.TermOrder; 027import edu.jas.structure.RingElem; 028import edu.jas.structure.RingFactory; 029import edu.jas.vector.BasicLinAlg; 030 031 032/** 033 * Groebner Bases abstract class. Implements common Groebner bases and GB test 034 * methods. 035 * @param <C> coefficient type 036 * @author Heinz Kredel 037 * 038 * @see edu.jas.application.GBAlgorithmBuilder 039 * @see edu.jas.gbufd.GBFactory 040 */ 041 042public abstract class GroebnerBaseAbstract<C extends RingElem<C>> implements GroebnerBase<C> { 043 044 045 private static final Logger logger = Logger.getLogger(GroebnerBaseAbstract.class); 046 047 048 private static final boolean debug = logger.isDebugEnabled(); 049 050 051 /** 052 * Reduction engine. 053 */ 054 public final Reduction<C> red; 055 056 057 /** 058 * Strategy for pair selection. 059 */ 060 public final PairList<C> strategy; 061 062 063 /** 064 * linear algebra engine. 065 */ 066 public final BasicLinAlg<GenPolynomial<C>> blas; 067 068 069 /** 070 * Constructor. 071 */ 072 public GroebnerBaseAbstract() { 073 this(new ReductionSeq<C>()); 074 } 075 076 077 /** 078 * Constructor. 079 * @param red Reduction engine 080 */ 081 public GroebnerBaseAbstract(Reduction<C> red) { 082 this(red, new OrderedPairlist<C>()); 083 } 084 085 086 /** 087 * Constructor. 088 * @param pl pair selection strategy 089 */ 090 public GroebnerBaseAbstract(PairList<C> pl) { 091 this(new ReductionSeq<C>(), pl); 092 } 093 094 095 /** 096 * Constructor. 097 * @param red Reduction engine 098 * @param pl pair selection strategy 099 */ 100 public GroebnerBaseAbstract(Reduction<C> red, PairList<C> pl) { 101 if (red == null) { 102 red = new ReductionSeq<C>(); 103 } 104 this.red = red; 105 if (pl == null) { 106 pl = new OrderedPairlist<C>(); 107 } 108 this.strategy = pl; 109 blas = new BasicLinAlg<GenPolynomial<C>>(); 110 } 111 112 113 /** 114 * Get the String representation with GB engines. 115 * @see java.lang.Object#toString() 116 */ 117 @Override 118 public String toString() { 119 return this.getClass().getSimpleName(); 120 } 121 122 123 /** 124 * Normalize polynomial list. 125 * @param A list of polynomials. 126 * @return list of polynomials with zeros removed and ones/units reduced. 127 */ 128 public List<GenPolynomial<C>> normalizeZerosOnes(List<GenPolynomial<C>> A) { 129 if (A == null) { 130 return A; 131 } 132 List<GenPolynomial<C>> N = new ArrayList<GenPolynomial<C>>(A.size()); 133 if (A.isEmpty()) { 134 return N; 135 } 136 for (GenPolynomial<C> p : A) { 137 if (p == null || p.isZERO()) { 138 continue; 139 } 140 if (p.isUnit()) { 141 N.clear(); 142 N.add(p.ring.getONE()); 143 return N; 144 } 145 N.add(p.abs()); 146 } 147 //N.trimToSize(); 148 return N; 149 } 150 151 152 /** 153 * Groebner base test. 154 * @param F polynomial list. 155 * @return true, if F is a Groebner base, else false. 156 */ 157 public boolean isGB(List<GenPolynomial<C>> F) { 158 return isGB(0, F); 159 } 160 161 162 /** 163 * Groebner base test. 164 * @param modv module variable number. 165 * @param F polynomial list. 166 * @return true, if F is a Groebner base, else false. 167 */ 168 public boolean isGB(int modv, List<GenPolynomial<C>> F) { 169 return isGB(modv, F, true); 170 } 171 172 173 /** 174 * Groebner base test. 175 * @param F polynomial list. 176 * @param b true for simple test, false for GB test. 177 * @return true, if F is a Groebner base, else false. 178 */ 179 public boolean isGB(List<GenPolynomial<C>> F, boolean b) { 180 return isGB(0, F, b); 181 } 182 183 184 /** 185 * Groebner base test. 186 * @param modv module variable number. 187 * @param F polynomial list. 188 * @param b true for simple test, false for GB test. 189 * @return true, if F is a Groebner base, else false. 190 */ 191 public boolean isGB(int modv, List<GenPolynomial<C>> F, boolean b) { 192 if (b) { 193 return isGBsimple(modv, F); 194 } 195 return isGBidem(modv, F); 196 } 197 198 199 /** 200 * Groebner base simple test. 201 * @param modv module variable number. 202 * @param F polynomial list. 203 * @return true, if F is a Groebner base, else false. 204 */ 205 public boolean isGBsimple(int modv, List<GenPolynomial<C>> F) { 206 if (F == null || F.isEmpty()) { 207 return true; 208 } 209 GenPolynomial<C> pi, pj, s, h; 210 ExpVector ei, ej, eij; 211 for (int i = 0; i < F.size(); i++) { 212 pi = F.get(i); 213 ei = pi.leadingExpVector(); 214 for (int j = i + 1; j < F.size(); j++) { 215 pj = F.get(j); 216 ej = pj.leadingExpVector(); 217 if (!red.moduleCriterion(modv, ei, ej)) { 218 continue; 219 } 220 eij = ei.lcm(ej); 221 if (!red.criterion4(ei, ej, eij)) { 222 continue; 223 } 224 if (!criterion3(i, j, eij, F)) { 225 continue; 226 } 227 s = red.SPolynomial(pi, pj); 228 if (s.isZERO()) { 229 continue; 230 } 231 //System.out.println("i, j = " + i + ", " + j); 232 h = red.normalform(F, s); 233 if (!h.isZERO()) { 234 logger.info("no GB: pi = " + pi + ", pj = " + pj); 235 logger.info("s = " + s + ", h = " + h); 236 return false; 237 } 238 } 239 } 240 return true; 241 } 242 243 244 /** 245 * GB criterium 3. 246 * @return true if the S-polynomial(i,j) is required. 247 */ 248 boolean criterion3(int i, int j, ExpVector eij, List<GenPolynomial<C>> P) { 249 assert i < j; 250 //for ( int k = 0; k < P.size(); k++ ) { 251 // not of much use 252 for (int k = 0; k < i; k++) { 253 GenPolynomial<C> A = P.get(k); 254 ExpVector ek = A.leadingExpVector(); 255 if (eij.multipleOf(ek)) { 256 return false; 257 } 258 } 259 return true; 260 } 261 262 263 /** 264 * Groebner base idempotence test. 265 * @param modv module variable number. 266 * @param F polynomial list. 267 * @return true, if F is equal to GB(F), else false. 268 */ 269 public boolean isGBidem(int modv, List<GenPolynomial<C>> F) { 270 if (F == null || F.isEmpty()) { 271 return true; 272 } 273 GenPolynomialRing<C> pring = F.get(0).ring; 274 List<GenPolynomial<C>> G = GB(modv, F); 275 PolynomialList<C> Fp = new PolynomialList<C>(pring, F); 276 PolynomialList<C> Gp = new PolynomialList<C>(pring, G); 277 return Fp.compareTo(Gp) == 0; 278 } 279 280 281 /** 282 * Common zero test. 283 * @param F polynomial list. 284 * @return -1, 0 or 1 if dimension(ideal(F)) &eq; -1, 0 or ≥ 1. 285 */ 286 public int commonZeroTest(List<GenPolynomial<C>> F) { 287 if (F == null || F.isEmpty()) { 288 return 1; 289 } 290 GenPolynomialRing<C> pfac = F.get(0).ring; 291 if (pfac.nvar <= 0) { 292 return -1; 293 } 294 //int uht = 0; 295 Set<Integer> v = new HashSet<Integer>(); // for non reduced GBs 296 for (GenPolynomial<C> p : F) { 297 if (p.isZERO()) { 298 continue; 299 } 300 if (p.isConstant()) { // for non-monic lists 301 return -1; 302 } 303 ExpVector e = p.leadingExpVector(); 304 if (e == null) { 305 continue; 306 } 307 int[] u = e.dependencyOnVariables(); 308 if (u == null) { 309 continue; 310 } 311 if (u.length == 1) { 312 //uht++; 313 v.add(u[0]); 314 } 315 } 316 if (pfac.nvar == v.size()) { 317 return 0; 318 } 319 return 1; 320 } 321 322 323 /** 324 * Groebner base using pairlist class. 325 * @param F polynomial list. 326 * @return GB(F) a Groebner base of F. 327 */ 328 public List<GenPolynomial<C>> GB(List<GenPolynomial<C>> F) { 329 return GB(0, F); 330 } 331 332 333 /** 334 * isGB. 335 * @param M a module basis. 336 * @return true, if M is a Groebner base, else false. 337 */ 338 public boolean isGB(ModuleList<C> M) { 339 if (M == null || M.list == null) { 340 return true; 341 } 342 if (M.rows == 0 || M.cols == 0) { 343 return true; 344 } 345 PolynomialList<C> F = M.getPolynomialList(); 346 int modv = M.cols; // > 0 347 return isGB(modv, F.list); 348 } 349 350 351 /** 352 * GB. 353 * @param M a module basis. 354 * @return GB(M), a Groebner base of M. 355 */ 356 public ModuleList<C> GB(ModuleList<C> M) { 357 ModuleList<C> N = M; 358 if (M == null || M.list == null) { 359 return N; 360 } 361 if (M.rows == 0 || M.cols == 0) { 362 return N; 363 } 364 365 PolynomialList<C> F = M.getPolynomialList(); 366 int modv = M.cols; 367 List<GenPolynomial<C>> G = GB(modv, F.list); 368 F = new PolynomialList<C>(F.ring, G); 369 N = F.getModuleList(modv); 370 return N; 371 } 372 373 374 /** 375 * Extended Groebner base using critical pair class. 376 * @param F polynomial list. 377 * @return a container for a Groebner base G of F together with 378 * back-and-forth transformations. 379 */ 380 public ExtendedGB<C> extGB(List<GenPolynomial<C>> F) { 381 return extGB(0, F); 382 } 383 384 385 /** 386 * Extended Groebner base using critical pair class. 387 * @param modv module variable number. 388 * @param F polynomial list. 389 * @return a container for a Groebner base G of F together with 390 * back-and-forth transformations. 391 */ 392 public ExtendedGB<C> extGB(int modv, List<GenPolynomial<C>> F) { 393 throw new UnsupportedOperationException("extGB not implemented in " + this.getClass().getSimpleName()); 394 } 395 396 397 /** 398 * Minimal ordered Groebner basis. 399 * @param Gp a Groebner base. 400 * @return a reduced Groebner base of Gp. 401 */ 402 public List<GenPolynomial<C>> minimalGB(List<GenPolynomial<C>> Gp) { 403 if (Gp == null || Gp.size() <= 1) { 404 return Gp; 405 } 406 // remove zero polynomials 407 List<GenPolynomial<C>> G = new ArrayList<GenPolynomial<C>>(Gp.size()); 408 for (GenPolynomial<C> a : Gp) { 409 if (a != null && !a.isZERO()) { // always true in GB() 410 // already positive a = a.abs(); 411 G.add(a); 412 } 413 } 414 if (G.size() <= 1) { 415 return G; 416 } 417 // remove top reducible polynomials 418 GenPolynomial<C> a; 419 List<GenPolynomial<C>> F; 420 F = new ArrayList<GenPolynomial<C>>(G.size()); 421 while (G.size() > 0) { 422 a = G.remove(0); 423 if (red.isTopReducible(G, a) || red.isTopReducible(F, a)) { 424 // drop polynomial 425 if (debug) { 426 System.out.println("dropped " + a); 427 List<GenPolynomial<C>> ff; 428 ff = new ArrayList<GenPolynomial<C>>(G); 429 ff.addAll(F); 430 a = red.normalform(ff, a); 431 if (!a.isZERO()) { 432 System.out.println("error, nf(a) " + a); 433 } 434 } 435 } else { 436 F.add(a); 437 } 438 } 439 G = F; 440 if (G.size() <= 1) { 441 return G; 442 } 443 // reduce remaining polynomials 444 Collections.reverse(G); // important for lex GB 445 int len = G.size(); 446 if (debug) { 447 System.out.println("#G " + len); 448 for (GenPolynomial<C> aa : G) { 449 System.out.println("aa = " + aa.length() + ", lt = " + aa.getMap().keySet()); 450 } 451 } 452 int i = 0; 453 while (i < len) { 454 a = G.remove(0); 455 if (debug) { 456 System.out.println("doing " + a.length() + ", lt = " + a.leadingExpVector()); 457 } 458 a = red.normalform(G, a); 459 G.add(a); // adds as last 460 i++; 461 } 462 Collections.reverse(G); // undo reverse 463 return G; 464 } 465 466 467 /** 468 * Test for minimal ordered Groebner basis. 469 * @param Gp an ideal base. 470 * @return true, if Gp is a reduced minimal Groebner base. 471 */ 472 public boolean isMinimalGB(List<GenPolynomial<C>> Gp) { 473 if (Gp == null || Gp.size() == 0) { 474 return true; 475 } 476 // test for zero polynomials 477 for (GenPolynomial<C> a : Gp) { 478 if (a == null || a.isZERO()) { 479 if (debug) { 480 logger.debug("zero polynomial " + a); 481 } 482 return false; 483 } 484 } 485 // test for top reducible polynomials 486 List<GenPolynomial<C>> G = new ArrayList<GenPolynomial<C>>(Gp); 487 List<GenPolynomial<C>> F = new ArrayList<GenPolynomial<C>>(G.size()); 488 while (G.size() > 0) { 489 GenPolynomial<C> a = G.remove(0); 490 if (red.isTopReducible(G, a) || red.isTopReducible(F, a)) { 491 if (debug) { 492 logger.debug("top reducible polynomial " + a); 493 } 494 return false; 495 } 496 F.add(a); 497 } 498 G = F; 499 if (G.size() <= 1) { 500 return true; 501 } 502 // test reducibility of polynomials 503 int len = G.size(); 504 int i = 0; 505 while (i < len) { 506 GenPolynomial<C> a = G.remove(0); 507 if (!red.isNormalform(G, a)) { 508 if (debug) { 509 logger.debug("reducible polynomial " + a); 510 } 511 return false; 512 } 513 G.add(a); // re-adds as last 514 i++; 515 } 516 return true; 517 } 518 519 520 /** 521 * Test if reduction matrix. 522 * @param exgb an ExtendedGB container. 523 * @return true, if exgb contains a reduction matrix, else false. 524 */ 525 public boolean isReductionMatrix(ExtendedGB<C> exgb) { 526 if (exgb == null) { 527 return true; 528 } 529 return isReductionMatrix(exgb.F, exgb.G, exgb.F2G, exgb.G2F); 530 } 531 532 533 /** 534 * Test if reduction matrix. 535 * @param F a polynomial list. 536 * @param G a Groebner base. 537 * @param Mf a possible reduction matrix. 538 * @param Mg a possible reduction matrix. 539 * @return true, if Mg and Mf are reduction matrices, else false. 540 */ 541 public boolean isReductionMatrix(List<GenPolynomial<C>> F, List<GenPolynomial<C>> G, 542 List<List<GenPolynomial<C>>> Mf, List<List<GenPolynomial<C>>> Mg) { 543 // no more check G and Mg: G * Mg[i] == 0 544 // check F and Mg: F * Mg[i] == G[i] 545 int k = 0; 546 for (List<GenPolynomial<C>> row : Mg) { 547 boolean t = red.isReductionNF(row, F, G.get(k), null); 548 if (!t) { 549 logger.error("F isReductionMatrix s, k = " + F.size() + ", " + k); 550 return false; 551 } 552 k++; 553 } 554 // check G and Mf: G * Mf[i] == F[i] 555 k = 0; 556 for (List<GenPolynomial<C>> row : Mf) { 557 boolean t = red.isReductionNF(row, G, F.get(k), null); 558 if (!t) { 559 logger.error("G isReductionMatrix s, k = " + G.size() + ", " + k); 560 return false; 561 } 562 k++; 563 } 564 return true; 565 } 566 567 568 /** 569 * Normalize M. Make all rows the same size and make certain column elements 570 * zero. 571 * @param M a reduction matrix. 572 * @return normalized M. 573 */ 574 public List<List<GenPolynomial<C>>> normalizeMatrix(int flen, List<List<GenPolynomial<C>>> M) { 575 if (M == null) { 576 return M; 577 } 578 if (M.size() == 0) { 579 return M; 580 } 581 List<List<GenPolynomial<C>>> N = new ArrayList<List<GenPolynomial<C>>>(); 582 List<List<GenPolynomial<C>>> K = new ArrayList<List<GenPolynomial<C>>>(); 583 int len = M.get(M.size() - 1).size(); // longest row 584 // pad / extend rows 585 for (List<GenPolynomial<C>> row : M) { 586 List<GenPolynomial<C>> nrow = new ArrayList<GenPolynomial<C>>(row); 587 for (int i = row.size(); i < len; i++) { 588 nrow.add(null); 589 } 590 N.add(nrow); 591 } 592 // System.out.println("norm N fill = " + N); 593 // make zero columns 594 int k = flen; 595 for (int i = 0; i < N.size(); i++) { // 0 596 List<GenPolynomial<C>> row = N.get(i); 597 if (debug) { 598 logger.info("row = " + row); 599 } 600 K.add(row); 601 if (i < flen) { // skip identity part 602 continue; 603 } 604 List<GenPolynomial<C>> xrow; 605 GenPolynomial<C> a; 606 //System.out.println("norm i = " + i); 607 for (int j = i + 1; j < N.size(); j++) { 608 List<GenPolynomial<C>> nrow = N.get(j); 609 //System.out.println("nrow j = " +j + ", " + nrow); 610 if (k < nrow.size()) { // always true 611 a = nrow.get(k); 612 //System.out.println("k, a = " + k + ", " + a); 613 if (a != null && !a.isZERO()) { 614 xrow = blas.scalarProduct(a, row); 615 xrow = blas.vectorAdd(xrow, nrow); 616 //System.out.println("xrow = " + xrow); 617 N.set(j, xrow); 618 } 619 } 620 } 621 k++; 622 } 623 //System.out.println("norm K reduc = " + K); 624 // truncate 625 N.clear(); 626 for (List<GenPolynomial<C>> row : K) { 627 List<GenPolynomial<C>> tr = new ArrayList<GenPolynomial<C>>(); 628 for (int i = 0; i < flen; i++) { 629 tr.add(row.get(i)); 630 } 631 N.add(tr); 632 } 633 K = N; 634 //System.out.println("norm K trunc = " + K); 635 return K; 636 } 637 638 639 /** 640 * Minimal extended groebner basis. 641 * @param Gp a Groebner base. 642 * @param M a reduction matrix, is modified. 643 * @return a (partially) reduced Groebner base of Gp in a container. 644 */ 645 public ExtendedGB<C> minimalExtendedGB(int flen, List<GenPolynomial<C>> Gp, List<List<GenPolynomial<C>>> M) { 646 if (Gp == null) { 647 return null; //new ExtendedGB<C>(null,Gp,null,M); 648 } 649 if (Gp.size() <= 1) { 650 return new ExtendedGB<C>(null, Gp, null, M); 651 } 652 List<GenPolynomial<C>> G; 653 List<GenPolynomial<C>> F; 654 G = new ArrayList<GenPolynomial<C>>(Gp); 655 F = new ArrayList<GenPolynomial<C>>(Gp.size()); 656 657 List<List<GenPolynomial<C>>> Mg; 658 List<List<GenPolynomial<C>>> Mf; 659 Mg = new ArrayList<List<GenPolynomial<C>>>(M.size()); 660 Mf = new ArrayList<List<GenPolynomial<C>>>(M.size()); 661 List<GenPolynomial<C>> row; 662 for (List<GenPolynomial<C>> r : M) { 663 // must be copied also 664 row = new ArrayList<GenPolynomial<C>>(r); 665 Mg.add(row); 666 } 667 row = null; 668 669 GenPolynomial<C> a; 670 ExpVector e; 671 ExpVector f; 672 GenPolynomial<C> p; 673 boolean mt; 674 ListIterator<GenPolynomial<C>> it; 675 ArrayList<Integer> ix = new ArrayList<Integer>(); 676 ArrayList<Integer> jx = new ArrayList<Integer>(); 677 int k = 0; 678 //System.out.println("flen, Gp, M = " + flen + ", " + Gp.size() + ", " + M.size() ); 679 while (G.size() > 0) { 680 a = G.remove(0); 681 e = a.leadingExpVector(); 682 683 it = G.listIterator(); 684 mt = false; 685 while (it.hasNext() && !mt) { 686 p = it.next(); 687 f = p.leadingExpVector(); 688 mt = e.multipleOf(f); 689 } 690 it = F.listIterator(); 691 while (it.hasNext() && !mt) { 692 p = it.next(); 693 f = p.leadingExpVector(); 694 mt = e.multipleOf(f); 695 } 696 //System.out.println("k, mt = " + k + ", " + mt); 697 if (!mt) { 698 F.add(a); 699 ix.add(k); 700 } else { // drop polynomial and corresponding row and column 701 // F.add( a.ring.getZERO() ); 702 jx.add(k); 703 } 704 k++; 705 } 706 if (debug) { 707 logger.debug("ix, #M, jx = " + ix + ", " + Mg.size() + ", " + jx); 708 } 709 int fix = -1; // copied polys 710 // copy Mg to Mf as indicated by ix 711 for (int i = 0; i < ix.size(); i++) { 712 int u = ix.get(i); 713 if (u >= flen && fix == -1) { 714 fix = Mf.size(); 715 } 716 //System.out.println("copy u, fix = " + u + ", " + fix); 717 if (u >= 0) { 718 row = Mg.get(u); 719 Mf.add(row); 720 } 721 } 722 if (F.size() <= 1 || fix == -1) { 723 return new ExtendedGB<C>(null, F, null, Mf); 724 } 725 // must return, since extended normalform has not correct order of polys 726 /* 727 G = F; 728 F = new ArrayList<GenPolynomial<C>>( G.size() ); 729 List<GenPolynomial<C>> temp; 730 k = 0; 731 final int len = G.size(); 732 while ( G.size() > 0 ) { 733 a = G.remove(0); 734 if ( k >= fix ) { // dont touch copied polys 735 row = Mf.get( k ); 736 //System.out.println("doing k = " + k + ", " + a); 737 // must keep order, but removed polys missing 738 temp = new ArrayList<GenPolynomial<C>>( len ); 739 temp.addAll( F ); 740 temp.add( a.ring.getZERO() ); // ?? 741 temp.addAll( G ); 742 //System.out.println("row before = " + row); 743 a = red.normalform( row, temp, a ); 744 //System.out.println("row after = " + row); 745 } 746 F.add( a ); 747 k++; 748 } 749 // does Mf need renormalization? 750 */ 751 return new ExtendedGB<C>(null, F, null, Mf); 752 } 753 754 755 /** 756 * Univariate head term degrees. 757 * @param A list of polynomials. 758 * @return a list of the degrees of univariate head terms. 759 */ 760 public List<Long> univariateDegrees(List<GenPolynomial<C>> A) { 761 List<Long> ud = new ArrayList<Long>(); 762 if (A == null || A.size() == 0) { 763 return ud; 764 } 765 GenPolynomialRing<C> pfac = A.get(0).ring; 766 if (pfac.nvar <= 0) { 767 return ud; 768 } 769 //int uht = 0; 770 Map<Integer, Long> v = new TreeMap<Integer, Long>(); // for non reduced GBs 771 for (GenPolynomial<C> p : A) { 772 ExpVector e = p.leadingExpVector(); 773 if (e == null) { 774 continue; 775 } 776 int[] u = e.dependencyOnVariables(); 777 if (u == null) { 778 continue; 779 } 780 if (u.length == 1) { 781 //uht++; 782 Long d = v.get(u[0]); 783 if (d == null) { 784 v.put(u[0], e.getVal(u[0])); 785 } 786 } 787 } 788 for (int i = 0; i < pfac.nvar; i++) { 789 Long d = v.get(i); 790 ud.add(d); 791 } 792 //Collections.reverse(ud); 793 return ud; 794 } 795 796 797 /** 798 * Construct univariate polynomial of minimal degree in variable i of a zero 799 * dimensional ideal(G). 800 * @param i variable index. 801 * @param G list of polynomials, a monic reduced Gröbner base of a zero 802 * dimensional ideal. 803 * @return univariate polynomial of minimal degree in variable i in ideal(G) 804 */ 805 public GenPolynomial<C> constructUnivariate(int i, List<GenPolynomial<C>> G) { 806 if (G == null || G.size() == 0) { 807 throw new IllegalArgumentException("G may not be null or empty"); 808 } 809 //logger.info("G in = " + G); 810 //Collections.reverse(G); // test 811 G = OrderedPolynomialList.<C> sort(G); // better performance 812 List<Long> ud = univariateDegrees(G); 813 if (ud.size() <= i) { 814 //logger.info("univ pol, ud = " + ud); 815 throw new IllegalArgumentException("ideal(G) not zero dimensional " + ud); 816 } 817 int ll = 0; 818 Long di = ud.get(i); 819 if (di != null) { 820 ll = (int) (long) di; 821 } else { 822 throw new IllegalArgumentException("ideal(G) not zero dimensional"); 823 } 824 long vsdim = 1; 825 for (Long d : ud) { 826 if (d != null) { 827 vsdim *= d; 828 } 829 } 830 logger.info("univariate construction, deg = " + ll + ", vsdim = " + vsdim); 831 GenPolynomialRing<C> pfac = G.get(0).ring; 832 RingFactory<C> cfac = pfac.coFac; 833 String var = pfac.getVars()[pfac.nvar - 1 - i]; 834 GenPolynomialRing<C> ufac = new GenPolynomialRing<C>(cfac, 1, new TermOrder(TermOrder.INVLEX), 835 new String[] { var }); 836 837 GenPolynomialRing<C> cpfac = new GenPolynomialRing<C>(cfac, ll, new TermOrder(TermOrder.INVLEX)); 838 GenPolynomialRing<GenPolynomial<C>> rfac = new GenPolynomialRing<GenPolynomial<C>>(cpfac, pfac); 839 GenPolynomial<GenPolynomial<C>> P = rfac.getZERO(); 840 for (int k = 0; k < ll; k++) { 841 GenPolynomial<GenPolynomial<C>> Pp = rfac.univariate(i, k); 842 GenPolynomial<C> cp = cpfac.univariate(cpfac.nvar - 1 - k); 843 Pp = Pp.multiply(cp); 844 P = P.sum(Pp); 845 } 846 if (debug) { 847 logger.info("univariate construction, P = " + P); 848 logger.info("univariate construction, deg_*(G) = " + ud); 849 //throw new RuntimeException("check"); 850 } 851 GenPolynomial<C> X; 852 GenPolynomial<C> XP; 853 // solve system of linear equations for the coefficients of the univariate polynomial 854 List<GenPolynomial<C>> ls; 855 int z = -1; 856 do { 857 //System.out.println("ll = " + ll); 858 GenPolynomial<GenPolynomial<C>> Pp = rfac.univariate(i, ll); 859 GenPolynomial<C> cp = cpfac.univariate(cpfac.nvar - 1 - ll); 860 Pp = Pp.multiply(cp); 861 P = P.sum(Pp); 862 X = pfac.univariate(i, ll); 863 XP = red.normalform(G, X); 864 if (debug) { 865 logger.info("XP = " + XP); 866 } 867 GenPolynomial<GenPolynomial<C>> XPp = PolyUtil.<C> toRecursive(rfac, XP); 868 GenPolynomial<GenPolynomial<C>> XPs = XPp.sum(P); 869 ls = new ArrayList<GenPolynomial<C>>(XPs.getMap().values()); 870 //System.out.println("ls,1 = " + ls); 871 ls = red.irreducibleSet(ls); 872 z = commonZeroTest(ls); 873 if (z != 0) { 874 ll++; 875 if (ll > vsdim) { 876 logger.info("univariate construction, P = " + P); 877 logger.info("univariate construction, nf(P) = " + XP); 878 logger.info("G = " + G); 879 throw new ArithmeticException( 880 "univariate polynomial degree greater than vector space dimansion"); 881 } 882 cpfac = cpfac.extend(1); 883 rfac = new GenPolynomialRing<GenPolynomial<C>>(cpfac, pfac); 884 P = PolyUtil.<C> extendCoefficients(rfac, P, 0, 0L); 885 XPp = PolyUtil.<C> extendCoefficients(rfac, XPp, 0, 1L); 886 P = P.sum(XPp); 887 } 888 } while (z != 0); // && ll <= 5 && !XP.isZERO() 889 // construct result polynomial 890 GenPolynomial<C> pol = ufac.univariate(0, ll); 891 for (GenPolynomial<C> pc : ls) { 892 ExpVector e = pc.leadingExpVector(); 893 if (e == null) { 894 continue; 895 } 896 int[] v = e.dependencyOnVariables(); 897 if (v == null || v.length == 0) { 898 continue; 899 } 900 int vi = v[0]; 901 C lc = pc.leadingBaseCoefficient(); 902 C tc = pc.trailingBaseCoefficient(); 903 tc = tc.negate(); 904 if (!lc.isONE()) { 905 tc = tc.divide(lc); 906 } 907 GenPolynomial<C> pi = ufac.univariate(0, ll - 1 - vi); 908 pi = pi.multiply(tc); 909 pol = pol.sum(pi); 910 } 911 if (logger.isInfoEnabled()) { 912 logger.info("univariate construction, pol = " + pol); 913 } 914 return pol; 915 } 916 917 918 /** 919 * Cleanup and terminate ThreadPool. 920 */ 921 public void terminate() { 922 logger.info("terminate not implemented"); 923 //throw new RuntimeException("get a stack trace"); 924 } 925 926 927 /** 928 * Cancel ThreadPool. 929 */ 930 public int cancel() { 931 logger.info("cancel not implemented"); 932 return 0; 933 } 934 935}