001/* 002 * $Id$ 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.LogManager; 018import org.apache.logging.log4j.Logger; 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 = {}, pj = {}", pi, pj); 236 logger.info("s = {}, h = {}", s, 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( 416 "extGB not implemented in " + this.getClass().getSimpleName()); 417 } 418 419 420 /** 421 * Minimal ordered Groebner basis. 422 * @param Gp a Groebner base. 423 * @return a reduced Groebner base of Gp. 424 */ 425 public List<GenPolynomial<C>> minimalGB(List<GenPolynomial<C>> Gp) { 426 if (Gp == null || Gp.size() <= 1) { 427 return Gp; 428 } 429 // remove zero polynomials 430 List<GenPolynomial<C>> G = new ArrayList<GenPolynomial<C>>(Gp.size()); 431 for (GenPolynomial<C> a : Gp) { 432 if (a != null && !a.isZERO()) { // always true in GB() 433 // already positive a = a.abs(); 434 G.add(a); 435 } 436 } 437 if (G.size() <= 1) { 438 return G; 439 } 440 // remove top reducible polynomials 441 GenPolynomial<C> a; 442 List<GenPolynomial<C>> F; 443 F = new ArrayList<GenPolynomial<C>>(G.size()); 444 while (G.size() > 0) { 445 a = G.remove(0); 446 if (red.isTopReducible(G, a) || red.isTopReducible(F, a)) { 447 // drop polynomial 448 if (debug) { 449 System.out.println("dropped " + a); 450 List<GenPolynomial<C>> ff; 451 ff = new ArrayList<GenPolynomial<C>>(G); 452 ff.addAll(F); 453 a = red.normalform(ff, a); 454 if (!a.isZERO()) { 455 System.out.println("error, nf(a) " + a); 456 } 457 } 458 } else { 459 F.add(a); 460 } 461 } 462 G = F; 463 if (G.size() <= 1) { 464 return G; 465 } 466 // reduce remaining polynomials 467 Collections.reverse(G); // important for lex GB 468 int len = G.size(); 469 if (debug) { 470 System.out.println("#G " + len); 471 for (GenPolynomial<C> aa : G) { 472 System.out.println("aa = " + aa.length() + ", lt = " + aa.getMap().keySet()); 473 } 474 } 475 int i = 0; 476 while (i < len) { 477 a = G.remove(0); 478 if (debug) { 479 System.out.println("doing " + a.length() + ", lt = " + a.leadingExpVector()); 480 } 481 a = red.normalform(G, a); 482 G.add(a); // adds as last 483 i++; 484 } 485 Collections.reverse(G); // undo reverse 486 return G; 487 } 488 489 490 /** 491 * Test for minimal ordered Groebner basis. 492 * @param Gp an ideal base. 493 * @return true, if Gp is a reduced minimal Groebner base. 494 */ 495 public boolean isMinimalGB(List<GenPolynomial<C>> Gp) { 496 if (Gp == null || Gp.size() == 0) { 497 return true; 498 } 499 // test for zero polynomials 500 for (GenPolynomial<C> a : Gp) { 501 if (a == null || a.isZERO()) { 502 if (debug) { 503 logger.debug("zero polynomial {}", a); 504 } 505 return false; 506 } 507 } 508 // test for top reducible polynomials 509 List<GenPolynomial<C>> G = new ArrayList<GenPolynomial<C>>(Gp); 510 List<GenPolynomial<C>> F = new ArrayList<GenPolynomial<C>>(G.size()); 511 while (G.size() > 0) { 512 GenPolynomial<C> a = G.remove(0); 513 if (red.isTopReducible(G, a) || red.isTopReducible(F, a)) { 514 if (debug) { 515 logger.debug("top reducible polynomial {}", a); 516 } 517 return false; 518 } 519 F.add(a); 520 } 521 G = F; 522 if (G.size() <= 1) { 523 return true; 524 } 525 // test reducibility of polynomials 526 int len = G.size(); 527 int i = 0; 528 while (i < len) { 529 GenPolynomial<C> a = G.remove(0); 530 if (!red.isNormalform(G, a)) { 531 if (debug) { 532 logger.debug("reducible polynomial {}", a); 533 } 534 return false; 535 } 536 G.add(a); // re-adds as last 537 i++; 538 } 539 return true; 540 } 541 542 543 /** 544 * Test if reduction matrix. 545 * @param exgb an ExtendedGB container. 546 * @return true, if exgb contains a reduction matrix, else false. 547 */ 548 public boolean isReductionMatrix(ExtendedGB<C> exgb) { 549 if (exgb == null) { 550 return true; 551 } 552 return isReductionMatrix(exgb.F, exgb.G, exgb.F2G, exgb.G2F); 553 } 554 555 556 /** 557 * Test if minimal reduction matrix. 558 * @param exgb an ExtendedGB container. 559 * @return true, if exgb contains a minimal reduction matrix, else false. 560 */ 561 public boolean isMinReductionMatrix(ExtendedGB<C> exgb) { 562 if (exgb == null) { 563 return true; 564 } 565 return isMinReductionMatrix(exgb.F, exgb.G, exgb.F2G, exgb.G2F); 566 } 567 568 569 /** 570 * Test if reduction matrix. 571 * @param F a polynomial list. 572 * @param G a Groebner base, G starting with +/- elements of F. 573 * @param Mf a possible reduction matrix. 574 * @param Mg a possible reduction matrix. 575 * @return true, if Mg and Mf are reduction matrices, else false. 576 */ 577 public boolean isReductionMatrix(List<GenPolynomial<C>> F, List<GenPolynomial<C>> G, 578 List<List<GenPolynomial<C>>> Mf, List<List<GenPolynomial<C>>> Mg) { 579 final int flen; 580 if (F == null) { 581 flen = -1; 582 } else { 583 flen = F.size(); 584 } 585 // no more check G and Mg: G * Mg[i] == 0 586 // i < #F: check F and Mg: Mg[i] * F == G[i] 587 // i >= #F: check G and Mg: Mg[i] * G == G[i] 588 int k = 0; 589 for (List<GenPolynomial<C>> row : Mg) { 590 boolean t; 591 if (k < flen) { 592 t = red.isReductionNF(row, F, G.get(k), null); 593 //logger.info("{} isReductionMatrix row, F, G(k), k = {}, {}, {}, {}", t, row, F, G.get(k), k); 594 } else { 595 t = red.isReductionNF(row, G, G.get(k), null); 596 //logger.info("{} isReductionMatrix row, G, G(k), k = {}, {}, {}, {}", t, row, G, G.get(k), k); 597 } 598 if (!t) { 599 logger.warn("isReductionMatrix row, F, G, k = {}, {}, {}, {}", row, F, G, k); 600 return false; 601 } 602 k++; 603 } 604 // check G and Mf: Mf[i] * G == F[i] 605 k = 0; 606 for (List<GenPolynomial<C>> row : Mf) { 607 boolean t = red.isReductionNF(row, G, F.get(k), null); 608 //logger.info("{} isMinReductionMatrix row, G, F(k), k = {}, {}, {}, {}", t, row, G, F.get(k), k); 609 if (!t) { 610 logger.warn("G isReductionMatrix row, G, F(k), k = {}, {}, {}, {}", row, G, F.get(k), k); 611 return false; 612 } 613 k++; 614 } 615 return true; 616 } 617 618 619 /** 620 * Test if minimal reduction matrix. 621 * @param F a polynomial list. 622 * @param G a minimal Groebner base of F. 623 * @param Mf a possible reduction matrix. 624 * @param Mg a possible reduction matrix. 625 * @return true, if Mg and Mf are reduction matrices, else false. 626 */ 627 public boolean isMinReductionMatrix(List<GenPolynomial<C>> F, List<GenPolynomial<C>> G, 628 List<List<GenPolynomial<C>>> Mf, List<List<GenPolynomial<C>>> Mg) { 629 if (F == null || G == null) { 630 throw new IllegalArgumentException("F or G may not be null or empty"); 631 } 632 //final int flen = F.size(); 633 // no more check G and Mg: G * Mg[i] == 0 634 // check F and Mg: Mg[i] * F == G[i] 635 int k = 0; 636 for (List<GenPolynomial<C>> row : Mg) { 637 boolean t = red.isReductionNF(row, F, G.get(k), null); 638 //logger.info("{} isMinReductionMatrix row, F, G(k), k = {}, {}, {}, {}", t, row, F, G.get(k), k); 639 if (!t) { 640 logger.warn("isMinReductionMatrix row, F, G, k = {}, {}, {}, {}", row, F, G, k); 641 return false; 642 } 643 k++; 644 } 645 // check G and Mf: Mf[i] * G == F[i] 646 k = 0; 647 for (List<GenPolynomial<C>> row : Mf) { 648 boolean t = red.isReductionNF(row, G, F.get(k), null); 649 //logger.info("{} isMinReductionMatrix row, G, F(k), k = {}, {}, {}, {}", t, row, G, F.get(k), k); 650 if (!t) { 651 logger.warn("G isMinReductionMatrix row, G, F(k), k = {}, {}, {}, {}", row, G, F.get(k), k); 652 return false; 653 } 654 k++; 655 } 656 return true; 657 } 658 659 660 /** 661 * Normalize M. Scale and shift right triangular matrix (new G elements) to 662 * left and make all right column elements zero. Then truncate all rows to 663 * the size of F. 664 * @param flen length of rows. 665 * @param M a reduction matrix. 666 * @return normalized M. 667 */ 668 public List<List<GenPolynomial<C>>> normalizeMatrix(int flen, List<List<GenPolynomial<C>>> M) { 669 if (M == null) { 670 return M; 671 } 672 if (M.size() == 0) { 673 return M; 674 } 675 List<List<GenPolynomial<C>>> N = new ArrayList<List<GenPolynomial<C>>>(); 676 List<List<GenPolynomial<C>>> K = new ArrayList<List<GenPolynomial<C>>>(); 677 int mlen = M.get(M.size() - 1).size(); // longest row 678 //System.out.println("norm M pre reduc = " + M); 679 // pad / extend rows 680 for (List<GenPolynomial<C>> row : M) { 681 List<GenPolynomial<C>> nrow = blas.genVector(mlen, null, row); 682 N.add(nrow); 683 } 684 // System.out.println("norm N fill = " + N); 685 // make zero right columns 686 int k = flen; // right part 687 for (int i = 0; i < N.size(); i++) { // 0 688 List<GenPolynomial<C>> row = N.get(i); 689 if (debug) { 690 logger.info("row = {}", row); 691 } 692 K.add(row); 693 if (i < flen) { // skip identity part?? 694 continue; // what with -1 ? 695 } 696 //System.out.println("norm i = " + i + ", row = " + row); 697 for (int j = i + 1; j < N.size(); j++) { 698 List<GenPolynomial<C>> nrow = N.get(j); 699 //System.out.println("nrow j = " + j + ", nrow = " + nrow); 700 if (k < nrow.size()) { // always true 701 GenPolynomial<C> a = nrow.get(k); // right matrix k ~ flen+i 702 //System.out.println("k, a = " + k + ", " + a); 703 if (a != null && !a.isZERO()) { 704 List<GenPolynomial<C>> xrow = blas.scalarProduct(a, row); 705 xrow = blas.vectorAdd(xrow, nrow); 706 //System.out.println("xrow = " + xrow); 707 N.set(j, xrow); 708 } 709 } 710 } 711 k++; 712 } 713 //System.out.println("norm K reduc = " + K); 714 // truncate 715 N.clear(); 716 for (List<GenPolynomial<C>> row : K) { 717 List<GenPolynomial<C>> tr = blas.genVector(flen, null, row); 718 N.add(tr); 719 } 720 K = N; 721 //System.out.println("norm K trunc = " + K); 722 return K; 723 } 724 725 726 /** 727 * Minimal extended groebner basis. 728 * @param flen length of rows. 729 * @param Gp a Groebner base. 730 * @param M a reduction matrix, is modified. 731 * @return a (partially) reduced Groebner base of Gp in a (fake) container. 732 */ 733 public ExtendedGB<C> minimalExtendedGB(int flen, List<GenPolynomial<C>> Gp, 734 List<List<GenPolynomial<C>>> M) { 735 if (Gp == null) { 736 return null; //new ExtendedGB<C>(null,Gp,null,M); 737 } 738 //if (Gp.size() <= 1) { 739 // return new ExtendedGB<C>(null, Gp, null, M); 740 //} 741 List<GenPolynomial<C>> G, F; 742 G = new ArrayList<GenPolynomial<C>>(Gp); 743 F = new ArrayList<GenPolynomial<C>>(Gp.size()); 744 745 List<List<GenPolynomial<C>>> Mg, Mf; 746 Mg = new ArrayList<List<GenPolynomial<C>>>(M.size()); 747 Mf = new ArrayList<List<GenPolynomial<C>>>(M.size()); 748 for (List<GenPolynomial<C>> r : M) { 749 // must be copied also 750 List<GenPolynomial<C>> row = new ArrayList<GenPolynomial<C>>(r); 751 Mg.add(row); 752 } 753 754 GenPolynomial<C> a, p; 755 ExpVector e, f; 756 boolean mt; 757 ListIterator<GenPolynomial<C>> it; 758 ArrayList<Integer> ix = new ArrayList<Integer>(); 759 //??ArrayList<Integer> jx = new ArrayList<Integer>(); 760 int k = 0; 761 //System.out.println("flen, Gp, M = " + flen + ", " + Gp.size() + ", " + M.size() ); 762 while (G.size() > 0) { 763 a = G.remove(0); 764 e = a.leadingExpVector(); 765 766 it = G.listIterator(); 767 mt = false; 768 while (it.hasNext() && !mt) { 769 p = it.next(); 770 f = p.leadingExpVector(); 771 mt = e.multipleOf(f); 772 } 773 it = F.listIterator(); 774 while (it.hasNext() && !mt) { 775 p = it.next(); 776 f = p.leadingExpVector(); 777 mt = e.multipleOf(f); 778 } 779 //System.out.println("k, mt = " + k + ", " + mt); 780 if (!mt) { 781 F.add(a); 782 ix.add(k); 783 //} else { // drop polynomial and corresponding row and column 784 // F.add( a.ring.getZERO() ); 785 //??jx.add(k); 786 } 787 k++; 788 } 789 if (debug) { 790 logger.debug("ix, #M = {}, {}", ix, Mg.size()); //??, jx); 791 } 792 int fix = -1; // copied polys 793 // copy Mg to Mf as indicated by ix 794 for (int i = 0; i < ix.size(); i++) { 795 int u = ix.get(i); 796 if (u >= flen && fix == -1) { 797 fix = Mf.size(); 798 } 799 //System.out.println("copy u, fix = " + u + ", " + fix); 800 if (u >= 0) { 801 List<GenPolynomial<C>> row = Mg.get(u); 802 Mf.add(row); 803 } 804 } 805 if (F.size() <= 1 || fix == -1) { 806 return new ExtendedGB<C>(null, F, null, Mf); 807 } 808 // must return, since extended normalform has not correct order of polys 809 /* 810 G = F; 811 F = new ArrayList<GenPolynomial<C>>( G.size() ); 812 List<GenPolynomial<C>> temp; 813 k = 0; 814 final int len = G.size(); 815 while ( G.size() > 0 ) { 816 a = G.remove(0); 817 if ( k >= fix ) { // dont touch copied polys 818 row = Mf.get( k ); 819 //System.out.println("doing k = " + k + ", " + a); 820 // must keep order, but removed polys missing 821 temp = new ArrayList<GenPolynomial<C>>( len ); 822 temp.addAll( F ); 823 temp.add( a.ring.getZERO() ); // ?? 824 temp.addAll( G ); 825 //System.out.println("row before = " + row); 826 a = red.normalform( row, temp, a ); 827 //System.out.println("row after = " + row); 828 } 829 F.add( a ); 830 k++; 831 } 832 // does Mf need renormalization? 833 */ 834 return new ExtendedGB<C>(null, F, null, Mf); 835 } 836 837 838 /** 839 * Univariate head term degrees. 840 * @param A list of polynomials. 841 * @return a list of the degrees of univariate head terms. 842 */ 843 public List<Long> univariateDegrees(List<GenPolynomial<C>> A) { 844 List<Long> ud = new ArrayList<Long>(); 845 if (A == null || A.size() == 0) { 846 return ud; 847 } 848 GenPolynomialRing<C> pfac = A.get(0).ring; 849 if (pfac.nvar <= 0) { 850 return ud; 851 } 852 //int uht = 0; 853 Map<Integer, Long> v = new TreeMap<Integer, Long>(); // for non reduced GBs 854 for (GenPolynomial<C> p : A) { 855 ExpVector e = p.leadingExpVector(); 856 if (e == null) { 857 continue; 858 } 859 int[] u = e.dependencyOnVariables(); 860 if (u == null) { 861 continue; 862 } 863 if (u.length == 1) { 864 //uht++; 865 Long d = v.get(u[0]); 866 if (d == null) { 867 v.put(u[0], e.getVal(u[0])); 868 } 869 } 870 } 871 for (int i = 0; i < pfac.nvar; i++) { 872 Long d = v.get(i); 873 ud.add(d); 874 } 875 //Collections.reverse(ud); 876 return ud; 877 } 878 879 880 /** 881 * Construct univariate polynomial of minimal degree in variable i of a zero 882 * dimensional ideal(G). 883 * @param i variable index. 884 * @param G list of polynomials, a monic reduced Gröbner base of a zero 885 * dimensional ideal. 886 * @return univariate polynomial of minimal degree in variable i in ideal(G) 887 */ 888 public GenPolynomial<C> constructUnivariate(int i, List<GenPolynomial<C>> G) { 889 if (G == null || G.size() == 0) { 890 throw new IllegalArgumentException("G may not be null or empty"); 891 } 892 //logger.info("G in = {}", G); 893 //Collections.reverse(G); // test 894 G = OrderedPolynomialList.<C> sort(G); // better performance 895 List<Long> ud = univariateDegrees(G); 896 if (ud.size() <= i) { 897 //logger.info("univ pol, ud = {}", ud); 898 throw new IllegalArgumentException("ideal(G) not zero dimensional " + ud); 899 } 900 int ll = 0; 901 Long di = ud.get(i); 902 if (di != null) { 903 ll = (int) (long) di; 904 } else { 905 throw new IllegalArgumentException("ideal(G) not zero dimensional"); 906 } 907 long vsdim = 1; 908 for (Long d : ud) { 909 if (d != null) { 910 vsdim *= d; 911 } 912 } 913 logger.info("univariate construction, deg = {}, vsdim = {}", ll, vsdim); 914 GenPolynomialRing<C> pfac = G.get(0).ring; 915 RingFactory<C> cfac = pfac.coFac; 916 String var = pfac.getVars()[pfac.nvar - 1 - i]; 917 GenPolynomialRing<C> ufac = new GenPolynomialRing<C>(cfac, 1, new TermOrder(TermOrder.INVLEX), 918 new String[] { var }); 919 920 GenPolynomialRing<C> cpfac = new GenPolynomialRing<C>(cfac, ll, new TermOrder(TermOrder.INVLEX)); 921 GenPolynomialRing<GenPolynomial<C>> rfac = new GenPolynomialRing<GenPolynomial<C>>(cpfac, pfac); 922 GenPolynomial<GenPolynomial<C>> P = rfac.getZERO(); 923 for (int k = 0; k < ll; k++) { 924 GenPolynomial<GenPolynomial<C>> Pp = rfac.univariate(i, k); 925 GenPolynomial<C> cp = cpfac.univariate(cpfac.nvar - 1 - k); 926 Pp = Pp.multiply(cp); 927 P = P.sum(Pp); 928 } 929 if (debug) { 930 logger.info("univariate construction, P = {}", P); 931 logger.info("univariate construction, deg_*(G) = {}", ud); 932 //throw new RuntimeException("check"); 933 } 934 GenPolynomial<C> X; 935 GenPolynomial<C> XP; 936 // solve system of linear equations for the coefficients of the univariate polynomial 937 List<GenPolynomial<C>> ls; 938 int z = -1; 939 do { 940 //System.out.println("ll = " + ll); 941 GenPolynomial<GenPolynomial<C>> Pp = rfac.univariate(i, ll); 942 GenPolynomial<C> cp = cpfac.univariate(cpfac.nvar - 1 - ll); 943 Pp = Pp.multiply(cp); 944 P = P.sum(Pp); 945 X = pfac.univariate(i, ll); 946 XP = red.normalform(G, X); 947 if (debug) { 948 logger.info("XP = {}", XP); 949 } 950 GenPolynomial<GenPolynomial<C>> XPp = PolyUtil.<C> toRecursive(rfac, XP); 951 GenPolynomial<GenPolynomial<C>> XPs = XPp.sum(P); 952 ls = new ArrayList<GenPolynomial<C>>(XPs.getMap().values()); 953 //System.out.println("ls,1 = " + ls); 954 ls = red.irreducibleSet(ls); 955 z = commonZeroTest(ls); 956 if (z != 0) { 957 ll++; 958 if (ll > vsdim) { 959 logger.info("univariate construction, P = {}", P); 960 logger.info("univariate construction, nf(P) = {}", XP); 961 logger.info("G = {}", G); 962 throw new ArithmeticException( 963 "univariate polynomial degree greater than vector space dimansion"); 964 } 965 cpfac = cpfac.extend(1); 966 rfac = new GenPolynomialRing<GenPolynomial<C>>(cpfac, pfac); 967 P = PolyUtil.<C> extendCoefficients(rfac, P, 0, 0L); 968 XPp = PolyUtil.<C> extendCoefficients(rfac, XPp, 0, 1L); 969 P = P.sum(XPp); 970 } 971 } while (z != 0); // && ll <= 5 && !XP.isZERO() 972 // construct result polynomial 973 GenPolynomial<C> pol = ufac.univariate(0, ll); 974 for (GenPolynomial<C> pc : ls) { 975 ExpVector e = pc.leadingExpVector(); 976 if (e == null) { 977 continue; 978 } 979 int[] v = e.dependencyOnVariables(); 980 if (v == null || v.length == 0) { 981 continue; 982 } 983 int vi = v[0]; 984 C lc = pc.leadingBaseCoefficient(); 985 C tc = pc.trailingBaseCoefficient(); 986 tc = tc.negate(); 987 if (!lc.isONE()) { 988 tc = tc.divide(lc); 989 } 990 GenPolynomial<C> pi = ufac.univariate(0, ll - 1 - vi); 991 pi = pi.multiply(tc); 992 pol = pol.sum(pi); 993 } 994 if (logger.isInfoEnabled()) { 995 logger.info("univariate construction, pol = {}", pol); 996 } 997 return pol; 998 } 999 1000 1001 /** 1002 * Cleanup and terminate ThreadPool. 1003 */ 1004 public void terminate() { 1005 logger.info("terminate not implemented"); 1006 //throw new RuntimeException("get a stack trace"); 1007 } 1008 1009 1010 /** 1011 * Cancel ThreadPool. 1012 */ 1013 public int cancel() { 1014 logger.info("cancel not implemented"); 1015 return 0; 1016 } 1017 1018}