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