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