001/* 002 * $Id: SolvableIdeal.java 5839 2018-05-20 20:30:09Z kredel $ 003 */ 004 005package edu.jas.application; 006 007 008import java.io.Serializable; 009import java.util.ArrayList; 010import java.util.List; 011 012import org.apache.log4j.Logger; 013 014import edu.jas.gb.SolvableExtendedGB; 015import edu.jas.gb.SolvableGroebnerBaseAbstract; 016import edu.jas.gb.SolvableReduction; 017import edu.jas.gb.SolvableReductionSeq; 018import edu.jas.gbufd.PolyGBUtil; 019import edu.jas.gbufd.SGBFactory; 020import edu.jas.gbufd.SolvableSyzygyAbstract; 021import edu.jas.gbufd.SolvableSyzygySeq; 022import edu.jas.poly.GenSolvablePolynomial; 023import edu.jas.poly.GenSolvablePolynomialRing; 024import edu.jas.poly.PolyUtil; 025import edu.jas.poly.PolynomialList; 026import edu.jas.structure.GcdRingElem; 027import edu.jas.structure.NotInvertibleException; 028 029 030/** 031 * Solvable Ideal implements some methods for ideal arithmetic, for example sum, 032 * intersection, quotient. <b>Note:</b> only left ideals at the moment. 033 * @author Heinz Kredel 034 */ 035public class SolvableIdeal<C extends GcdRingElem<C>> implements Comparable<SolvableIdeal<C>>, Serializable { 036 037 038 private static final Logger logger = Logger.getLogger(SolvableIdeal.class); 039 040 041 private static final boolean debug = logger.isDebugEnabled(); 042 043 044 /** 045 * Side variant of ideal. 046 */ 047 public static enum Side { 048 left, right, twosided 049 } 050 051 052 /** 053 * The data structure is a PolynomialList. 054 */ 055 protected PolynomialList<C> list; 056 057 058 /** 059 * Indicator if list is a Groebner Base. 060 */ 061 protected boolean isGB; 062 063 064 /** 065 * Indicator of side of Groebner Base. 066 */ 067 protected Side sided; 068 069 070 /** 071 * Indicator if test has been performed if this is a Groebner Base. 072 */ 073 protected boolean testGB; 074 075 076 /** 077 * Indicator if list has optimized term order. 078 */ 079 protected boolean isTopt; 080 081 082 /** 083 * Groebner base engine. 084 */ 085 protected final SolvableGroebnerBaseAbstract<C> bb; 086 087 088 /** 089 * Reduction engine. 090 */ 091 protected final SolvableReduction<C> red; 092 093 094 /** 095 * Constructor. 096 * @param ring solvable polynomial ring 097 */ 098 public SolvableIdeal(GenSolvablePolynomialRing<C> ring) { 099 this(ring, new ArrayList<GenSolvablePolynomial<C>>()); 100 } 101 102 103 /** 104 * Constructor. 105 * @param ring solvable polynomial ring 106 * @param F list of solvable polynomials 107 */ 108 public SolvableIdeal(GenSolvablePolynomialRing<C> ring, List<GenSolvablePolynomial<C>> F) { 109 this(new PolynomialList<C>(ring, F)); 110 } 111 112 113 /** 114 * Constructor. 115 * @param ring solvable polynomial ring 116 * @param F list of solvable polynomials 117 * @param gb true if F is known to be a Groebner Base, else false 118 */ 119 public SolvableIdeal(GenSolvablePolynomialRing<C> ring, List<GenSolvablePolynomial<C>> F, boolean gb) { 120 this(new PolynomialList<C>(ring, F), gb); 121 } 122 123 124 /** 125 * Constructor. 126 * @param ring solvable polynomial ring 127 * @param F list of solvable polynomials 128 * @param gb true if F is known to be a Groebner Base, else false 129 * @param topt true if term order is optimized, else false 130 */ 131 public SolvableIdeal(GenSolvablePolynomialRing<C> ring, List<GenSolvablePolynomial<C>> F, boolean gb, 132 boolean topt) { 133 this(new PolynomialList<C>(ring, F), gb, topt); 134 } 135 136 137 /** 138 * Constructor. 139 * @param ring solvable polynomial ring 140 * @param F list of solvable polynomials 141 * @param s side variant of ideal or Groebner Base 142 */ 143 public SolvableIdeal(GenSolvablePolynomialRing<C> ring, List<GenSolvablePolynomial<C>> F, Side s) { 144 this(new PolynomialList<C>(ring, F), false, false, s); 145 } 146 147 148 /** 149 * Constructor. 150 * @param ring solvable polynomial ring 151 * @param F list of solvable polynomials 152 * @param gb true if F is known to be a Groebner Base, else false 153 * @param s side variant of ideal or Groebner Base 154 */ 155 public SolvableIdeal(GenSolvablePolynomialRing<C> ring, List<GenSolvablePolynomial<C>> F, boolean gb, 156 Side s) { 157 this(new PolynomialList<C>(ring, F), gb, false, s); 158 } 159 160 161 /** 162 * Constructor. 163 * @param list solvable polynomial list 164 */ 165 public SolvableIdeal(PolynomialList<C> list) { 166 this(list, false); 167 } 168 169 170 /** 171 * Constructor. 172 * @param list solvable polynomial list 173 * @param bb Groebner Base engine 174 * @param red Reduction engine 175 */ 176 public SolvableIdeal(PolynomialList<C> list, SolvableGroebnerBaseAbstract<C> bb, 177 SolvableReduction<C> red) { 178 this(list, false, bb, red); 179 } 180 181 182 /** 183 * Constructor. 184 * @param list solvable polynomial list 185 * @param gb true if list is known to be a Groebner Base, else false 186 */ 187 public SolvableIdeal(PolynomialList<C> list, boolean gb) { 188 //this(list, gb, new SolvableGroebnerBaseSeq<C>(), new SolvableReductionSeq<C>()); 189 this(list, gb, SGBFactory.getImplementation(list.ring.coFac), new SolvableReductionSeq<C>()); 190 } 191 192 193 /** 194 * Constructor. 195 * @param list solvable polynomial list 196 * @param gb true if list is known to be a Groebner Base, else false 197 * @param topt true if term order is optimized, else false 198 */ 199 public SolvableIdeal(PolynomialList<C> list, boolean gb, boolean topt) { 200 //this(list, gb, topt, new SolvableGroebnerBaseSeq<C>(), new SolvableReductionSeq<C>()); 201 this(list, gb, topt, SGBFactory.getImplementation(list.ring.coFac), new SolvableReductionSeq<C>()); 202 } 203 204 205 /** 206 * Constructor. 207 * @param list solvable polynomial list 208 * @param gb true if list is known to be a Groebner Base, else false 209 * @param s side variant of ideal or Groebner Base 210 */ 211 public SolvableIdeal(PolynomialList<C> list, boolean gb, Side s) { 212 //this(list, gb, false, new SolvableGroebnerBaseSeq<C>(), new SolvableReductionSeq<C>()); 213 this(list, gb, false, SGBFactory.getImplementation(list.ring.coFac), new SolvableReductionSeq<C>(), 214 s); 215 } 216 217 218 /** 219 * Constructor. 220 * @param list solvable polynomial list 221 * @param gb true if list is known to be a Groebner Base, else false 222 * @param topt true if term order is optimized, else false 223 * @param s side variant of ideal or Groebner Base 224 */ 225 public SolvableIdeal(PolynomialList<C> list, boolean gb, boolean topt, Side s) { 226 //this(list, gb, topt, new SolvableGroebnerBaseSeq<C>(), new SolvableReductionSeq<C>()); 227 this(list, gb, topt, SGBFactory.getImplementation(list.ring.coFac), new SolvableReductionSeq<C>(), s); 228 } 229 230 231 /** 232 * Constructor. 233 * @param list solvable polynomial list 234 * @param gb true if list is known to be a Groebner Base, else false 235 * @param bb Groebner Base engine 236 * @param red Reduction engine 237 */ 238 public SolvableIdeal(PolynomialList<C> list, boolean gb, SolvableGroebnerBaseAbstract<C> bb, 239 SolvableReduction<C> red) { 240 this(list, gb, false, bb, red); 241 } 242 243 244 /** 245 * Constructor. 246 * @param list solvable polynomial list 247 * @param gb true if list is known to be a Groebner Base, else false 248 * @param bb Groebner Base engine 249 */ 250 public SolvableIdeal(PolynomialList<C> list, boolean gb, SolvableGroebnerBaseAbstract<C> bb) { 251 this(list, gb, false, bb, bb.sred); 252 } 253 254 255 /** 256 * Constructor. 257 * @param list solvable polynomial list 258 * @param gb true if list is known to be a Groebner Base, else false 259 * @param topt true if term order is optimized, else false 260 * @param bb Groebner Base engine 261 */ 262 public SolvableIdeal(PolynomialList<C> list, boolean gb, boolean topt, 263 SolvableGroebnerBaseAbstract<C> bb) { 264 this(list, gb, topt, bb, bb.sred); 265 } 266 267 268 /** 269 * Constructor. 270 * @param list solvable polynomial list 271 * @param gb true if list is known to be a Groebner Base, else false 272 * @param topt true if term order is optimized, else false 273 * @param bb Groebner Base engine 274 * @param red Reduction engine 275 */ 276 public SolvableIdeal(PolynomialList<C> list, boolean gb, boolean topt, SolvableGroebnerBaseAbstract<C> bb, 277 SolvableReduction<C> red) { 278 this(list, gb, topt, bb, red, Side.left); 279 } 280 281 282 /** 283 * Constructor. 284 * @param list solvable polynomial list 285 * @param gb true if list is known to be a Groebner Base, else false 286 * @param topt true if term order is optimized, else false 287 * @param bb Groebner Base engine 288 * @param red Reduction engine 289 * @param s side variant of ideal or Groebner Base 290 */ 291 public SolvableIdeal(PolynomialList<C> list, boolean gb, boolean topt, SolvableGroebnerBaseAbstract<C> bb, 292 SolvableReduction<C> red, Side s) { 293 if (list == null || list.list == null) { 294 throw new IllegalArgumentException("list and list.list may not be null"); 295 } 296 this.list = list; 297 this.isGB = gb; 298 this.isTopt = topt; 299 this.testGB = (gb ? true : false); // ?? 300 this.bb = bb; 301 this.red = red; 302 if (s == null) { 303 s = Side.left; // default 304 } 305 this.sided = s; 306 } 307 308 309 /** 310 * Clone this. 311 * @return a copy of this. 312 */ 313 public SolvableIdeal<C> copy() { 314 return new SolvableIdeal<C>(list.copy(), isGB, isTopt, bb, red, sided); 315 } 316 317 318 /** 319 * Get the List of GenSolvablePolynomials. 320 * @return (cast) list.list 321 */ 322 public List<GenSolvablePolynomial<C>> getList() { 323 return list.getSolvableList(); 324 } 325 326 327 /** 328 * Get the GenSolvablePolynomialRing. 329 * @return (cast) list.ring 330 */ 331 public GenSolvablePolynomialRing<C> getRing() { 332 return list.getSolvableRing(); 333 } 334 335 336 /** 337 * Get the zero ideal. 338 * @return ideal(0) 339 */ 340 public SolvableIdeal<C> getZERO() { 341 List<GenSolvablePolynomial<C>> z = new ArrayList<GenSolvablePolynomial<C>>(0); 342 PolynomialList<C> pl = new PolynomialList<C>(getRing(), z); 343 return new SolvableIdeal<C>(pl, true, isTopt, bb, red, sided); 344 } 345 346 347 /** 348 * Get the one ideal. 349 * @return ideal(1) 350 */ 351 public SolvableIdeal<C> getONE() { 352 List<GenSolvablePolynomial<C>> one = new ArrayList<GenSolvablePolynomial<C>>(1); 353 one.add(getRing().getONE()); 354 PolynomialList<C> pl = new PolynomialList<C>(getRing(), one); 355 return new SolvableIdeal<C>(pl, true, isTopt, bb, red, sided); 356 } 357 358 359 /** 360 * String representation of the solvable ideal. 361 * @see java.lang.Object#toString() 362 */ 363 @Override 364 public String toString() { 365 return list.toString() + " # " + sided; 366 } 367 368 369 /** 370 * Get a scripting compatible string representation. 371 * @return script compatible representation for this Element. 372 * @see edu.jas.structure.Element#toScript() 373 */ 374 public String toScript() { 375 // any script case 376 return list.toScript() + " # " + sided; 377 } 378 379 380 /** 381 * Comparison with any other object. <b>Note:</b> If not both ideals are 382 * Groebner Bases, then false may be returned even the ideals are equal. 383 * @see java.lang.Object#equals(java.lang.Object) 384 */ 385 @Override 386 @SuppressWarnings("unchecked") 387 public boolean equals(Object b) { 388 if (!(b instanceof SolvableIdeal)) { 389 logger.warn("equals no Ideal"); 390 return false; 391 } 392 SolvableIdeal<C> B = null; 393 try { 394 B = (SolvableIdeal<C>) b; 395 } catch (ClassCastException ignored) { 396 return false; 397 } 398 //if ( isGB && B.isGB ) { 399 // return list.equals( B.list ); requires also monic polys 400 //} else { // compute GBs ? 401 return this.contains(B) && B.contains(this); 402 //} 403 } 404 405 406 /** 407 * SolvableIdeal comparison. 408 * @param L other solvable ideal. 409 * @return compareTo() of polynomial lists. 410 */ 411 public int compareTo(SolvableIdeal<C> L) { 412 return list.compareTo(L.list); 413 } 414 415 416 /** 417 * Hash code for this solvable ideal. 418 * @see java.lang.Object#hashCode() 419 */ 420 @Override 421 public int hashCode() { 422 int h; 423 h = list.hashCode(); 424 if (isGB) { 425 h = h << 1; 426 } 427 if (testGB) { 428 h += 1; 429 } 430 return h; 431 } 432 433 434 /** 435 * Test if ZERO ideal. 436 * @return true, if this is the 0 ideal, else false 437 */ 438 public boolean isZERO() { 439 return list.isZERO(); 440 } 441 442 443 /** 444 * Test if ONE is contained in the ideal. To test for a proper ideal use 445 * <code>! id.isONE()</code>. 446 * @return true, if this is the 1 ideal, else false 447 */ 448 public boolean isONE() { 449 return list.isONE(); 450 } 451 452 453 /** 454 * Test if this is a left Groebner base. 455 * @return true, if this is a left Groebner base, else false 456 */ 457 public boolean isGB() { 458 if (testGB && sided == Side.left) { 459 return isGB; 460 } 461 logger.warn("isLeftGB computing"); 462 boolean igb = bb.isLeftGB(getList()); 463 if (sided != Side.left) { 464 logger.warn("wrong usage for is left sided GB: " + sided); 465 //sided = Side.left; 466 } else { 467 isGB = igb; 468 testGB = true; 469 } 470 return igb; 471 } 472 473 474 /** 475 * Do Groebner Base. compute the left Groebner Base for this ideal. 476 */ 477 @SuppressWarnings("unchecked") 478 public void doGB() { 479 if (isGB && sided == Side.left) { 480 return; 481 } 482 if (isGB && sided == Side.twosided) { 483 return; 484 } 485 if (sided == Side.right) { 486 logger.warn("wrong usage for left sided GB: " + sided); 487 throw new IllegalArgumentException("wrong usage for left sided GB: " + sided); 488 } 489 List<GenSolvablePolynomial<C>> G = getList(); 490 if (sided == Side.left) { 491 logger.info("leftGB computing = " + G); 492 G = bb.leftGB(G); 493 } 494 if (sided == Side.twosided) { 495 logger.info("twosidedGB computing = " + G); 496 G = bb.twosidedGB(G); 497 } 498 //if (isTopt) { 499 // List<Integer> perm = ((OptimizedPolynomialList<C>) list).perm; 500 // list = new OptimizedPolynomialList<C>(perm, getRing(), G); 501 //} else { 502 //} 503 list = new PolynomialList<C>(getRing(), G); 504 isGB = true; 505 testGB = true; 506 //sided = Side.left; 507 return; 508 } 509 510 511 /** 512 * Groebner Base. Get a left Groebner Base for this ideal. 513 * @return leftGB(this) 514 */ 515 public SolvableIdeal<C> GB() { 516 if (isGB && sided == Side.left) { 517 return this; 518 } 519 doGB(); 520 return this; 521 } 522 523 524 /** 525 * Test if this is a twosided Groebner base. 526 * @return true, if this is a twosided Groebner base, else false 527 */ 528 public boolean isTwosidedGB() { 529 if (testGB && sided == Side.twosided) { 530 return isGB; 531 } 532 logger.warn("isTwosidedGB computing"); 533 isGB = bb.isTwosidedGB(getList()); 534 testGB = true; 535 sided = Side.twosided; 536 return isGB; 537 } 538 539 540 /** 541 * Groebner Base. Get a twosided Groebner Base for this ideal. 542 * @return twosidedGB(this) 543 */ 544 public SolvableIdeal<C> twosidedGB() { 545 if (isGB && sided == Side.twosided) { 546 return this; 547 } 548 //logger.warn("GB computing"); 549 List<GenSolvablePolynomial<C>> G = getList(); 550 logger.info("twosidedGB computing = " + G); 551 G = bb.twosidedGB(G); 552 PolynomialList<C> li = new PolynomialList<C>(getRing(), G); 553 SolvableIdeal<C> tsgb = new SolvableIdeal<C>(li, true, true, bb, red, Side.twosided); 554 return tsgb; 555 } 556 557 558 /** 559 * Test if this is a right Groebner base. 560 * @return true, if this is a right Groebner base, else false 561 */ 562 public boolean isRightGB() { 563 if (testGB && sided == Side.right) { 564 return isGB; 565 } 566 if (isGB && sided == Side.twosided) { 567 return true; 568 } 569 logger.warn("isRightGB computing"); 570 isGB = bb.isRightGB(getList()); 571 testGB = true; 572 sided = Side.right; 573 return isGB; 574 } 575 576 577 /** 578 * Groebner Base. Get a right Groebner Base for this ideal. 579 * @return rightGB(this) 580 */ 581 public SolvableIdeal<C> rightGB() { 582 if (isGB && sided == Side.twosided) { 583 return this; 584 } 585 if (isGB && sided == Side.right) { 586 return this; 587 } 588 //logger.warn("GB computing"); 589 List<GenSolvablePolynomial<C>> G = getList(); 590 logger.info("rightGB computing = " + G); 591 G = bb.rightGB(G); 592 PolynomialList<C> li = new PolynomialList<C>(getRing(), G); 593 SolvableIdeal<C> rgb = new SolvableIdeal<C>(li, true, true, bb, red, Side.right); 594 return rgb; 595 } 596 597 598 /** 599 * Solvable ideal containment. Test if B is contained in this ideal. Note: 600 * this is eventually modified to become a Groebner Base. 601 * @param B solvable ideal 602 * @return true, if B is contained in this, else false 603 */ 604 public boolean contains(SolvableIdeal<C> B) { 605 if (B == null || B.isZERO()) { 606 return true; 607 } 608 return contains(B.getList()); 609 } 610 611 612 /** 613 * Solvable ideal containment. Test if b is contained in this ideal. Note: 614 * this is eventually modified to become a Groebner Base. 615 * @param b solvable polynomial 616 * @return true, if b is contained in this, else false 617 */ 618 public boolean contains(GenSolvablePolynomial<C> b) { 619 if (b == null || b.isZERO()) { 620 return true; 621 } 622 if (this.isONE()) { 623 return true; 624 } 625 if (this.isZERO()) { 626 return false; 627 } 628 if (!isGB) { 629 doGB(); 630 } 631 GenSolvablePolynomial<C> z = red.leftNormalform(getList(), b); 632 if (z == null || z.isZERO()) { 633 return true; 634 } 635 return false; 636 } 637 638 639 /** 640 * Solvable ideal containment. Test if each b in B is contained in this 641 * ideal. Note: this is eventually modified to become a Groebner Base. 642 * @param B list of solvable polynomials 643 * @return true, if each b in B is contained in this, else false 644 */ 645 public boolean contains(List<GenSolvablePolynomial<C>> B) { 646 if (B == null || B.size() == 0) { 647 return true; 648 } 649 if (this.isONE()) { 650 return true; 651 } 652 if (!isGB) { 653 doGB(); 654 } 655 List<GenSolvablePolynomial<C>> si = getList(); 656 for (GenSolvablePolynomial<C> b : B) { 657 if (b == null) { 658 continue; 659 } 660 GenSolvablePolynomial<C> z = red.leftNormalform(si, b); 661 if (!z.isZERO()) { 662 logger.info("contains nf(b) != 0: " + z + " of " + b); 663 // + ", si = " + si + ", ring = " + z.ring.toScript()); 664 return false; 665 } 666 } 667 return true; 668 } 669 670 671 /** 672 * Solvable ideal summation. Generators for the sum of ideals. Note: if both 673 * ideals are Groebner bases, a Groebner base is returned. 674 * @param B solvable ideal 675 * @return ideal(this+B) 676 */ 677 public SolvableIdeal<C> sum(SolvableIdeal<C> B) { 678 if (B == null || B.isZERO()) { 679 return this; 680 } 681 if (this.isZERO()) { 682 return B; 683 } 684 int s = getList().size() + B.getList().size(); 685 List<GenSolvablePolynomial<C>> c; 686 c = new ArrayList<GenSolvablePolynomial<C>>(s); 687 c.addAll(getList()); 688 c.addAll(B.getList()); 689 SolvableIdeal<C> I = new SolvableIdeal<C>(getRing(), c, false, sided); 690 if (isGB && B.isGB) { 691 I.doGB(); // left, twosided, right handled in doGB 692 } 693 return I; 694 } 695 696 697 /** 698 * Solvable summation. Generators for the sum of ideal and a polynomial. 699 * Note: if this ideal is a Groebner base, a Groebner base is returned. 700 * @param b solvable polynomial 701 * @return ideal(this+{b}) 702 */ 703 public SolvableIdeal<C> sum(GenSolvablePolynomial<C> b) { 704 if (b == null || b.isZERO()) { 705 return this; 706 } 707 int s = getList().size() + 1; 708 List<GenSolvablePolynomial<C>> c; 709 c = new ArrayList<GenSolvablePolynomial<C>>(s); 710 c.addAll(getList()); 711 c.add(b); 712 SolvableIdeal<C> I = new SolvableIdeal<C>(getRing(), c, false, sided); 713 if (isGB) { 714 I.doGB(); 715 } 716 return I; 717 } 718 719 720 /** 721 * Solvable summation. Generators for the sum of this ideal and a list of 722 * polynomials. Note: if this ideal is a Groebner base, a Groebner base is 723 * returned. 724 * @param L list of solvable polynomials 725 * @return ideal(this+L) 726 */ 727 public SolvableIdeal<C> sum(List<GenSolvablePolynomial<C>> L) { 728 if (L == null || L.isEmpty()) { 729 return this; 730 } 731 int s = getList().size() + L.size(); 732 List<GenSolvablePolynomial<C>> c = new ArrayList<GenSolvablePolynomial<C>>(s); 733 c.addAll(getList()); 734 c.addAll(L); 735 SolvableIdeal<C> I = new SolvableIdeal<C>(getRing(), c, false, sided); 736 if (isGB) { 737 I.doGB(); 738 } 739 return I; 740 } 741 742 743 /** 744 * Product. Generators for the product of ideals. Note: if both ideals are 745 * Groebner bases, a Groebner base is returned. 746 * @param B solvable ideal 747 * @return ideal(this*B) 748 */ 749 public SolvableIdeal<C> product(SolvableIdeal<C> B) { 750 if (B == null || B.isZERO()) { 751 return B; 752 } 753 if (this.isZERO()) { 754 return this; 755 } 756 int s = getList().size() * B.getList().size(); 757 List<GenSolvablePolynomial<C>> c; 758 c = new ArrayList<GenSolvablePolynomial<C>>(s); 759 for (GenSolvablePolynomial<C> p : getList()) { 760 for (GenSolvablePolynomial<C> q : B.getList()) { 761 q = p.multiply(q); 762 c.add(q); 763 } 764 } 765 SolvableIdeal<C> I = new SolvableIdeal<C>(getRing(), c, false, sided); 766 if (isGB && B.isGB) { 767 I.doGB(); 768 } 769 return I; 770 } 771 772 773 /** 774 * Left product. Generators for the product this by a polynomial. 775 * @param b solvable polynomial 776 * @return ideal(this*b) 777 */ 778 public SolvableIdeal<C> product(GenSolvablePolynomial<C> b) { 779 if (b == null || b.isZERO()) { 780 return getZERO(); 781 } 782 if (this.isZERO()) { 783 return this; 784 } 785 List<GenSolvablePolynomial<C>> c; 786 c = new ArrayList<GenSolvablePolynomial<C>>(getList().size()); 787 for (GenSolvablePolynomial<C> p : getList()) { 788 GenSolvablePolynomial<C> q = p.multiply(b); 789 c.add(q); 790 } 791 SolvableIdeal<C> I = new SolvableIdeal<C>(getRing(), c, false, sided); 792 if (isGB) { 793 I.doGB(); 794 } 795 return I; 796 } 797 798 799 /** 800 * Intersection. Generators for the intersection of ideals. Using an 801 * iterative algorithm. 802 * @param Bl list of solvable ideals 803 * @return ideal(cap_i B_i), a Groebner base 804 */ 805 public SolvableIdeal<C> intersect(List<SolvableIdeal<C>> Bl) { 806 if (Bl == null || Bl.size() == 0) { 807 return getZERO(); 808 } 809 SolvableIdeal<C> I = null; 810 for (SolvableIdeal<C> B : Bl) { 811 if (I == null) { 812 I = B; 813 continue; 814 } 815 if (I.isONE()) { 816 return I; 817 } 818 I = I.intersect(B); 819 } 820 return I; 821 } 822 823 824 /** 825 * Intersection. Generators for the intersection of ideals. 826 * @param B solvable ideal 827 * @return ideal(this \cap B), a Groebner base 828 */ 829 public SolvableIdeal<C> intersect(SolvableIdeal<C> B) { 830 if (B == null || B.isZERO()) { // (0) 831 return B; 832 } 833 if (this.isZERO()) { 834 return this; 835 } 836 List<GenSolvablePolynomial<C>> c = PolyGBUtil.<C> intersect(getRing(), getList(), B.getList()); 837 SolvableIdeal<C> I = new SolvableIdeal<C>(getRing(), c, true, sided); 838 return I; 839 } 840 841 842 /** 843 * Intersection. Generators for the intersection of a ideal with a 844 * polynomial ring. The polynomial ring R must be a contraction 845 * of this ideal and the TermOrder must be an elimination order. 846 * @param R solvable polynomial ring 847 * @return ideal(this \cap R) 848 */ 849 public SolvableIdeal<C> intersect(GenSolvablePolynomialRing<C> R) { 850 if (R == null) { 851 throw new IllegalArgumentException("R may not be null"); 852 } 853 String[] rvars = R.getVars(); 854 String[] tvars = getRing().getVars(); 855 for (int i = 0; i < rvars.length; i++) { 856 if (rvars[i] != tvars[i]) { 857 throw new IllegalArgumentException("no contraction: " + R.toScript() 858 + " of " + getRing().toScript()); 859 } 860 } 861 List<GenSolvablePolynomial<C>> H = PolyUtil.<C> intersect(R, getList()); 862 return new SolvableIdeal<C>(R, H, isGB, sided); 863 } 864 865 866 /** 867 * Eliminate. Generators for the intersection of this ideal with a solvable 868 * polynomial ring. The solvable polynomial ring of this ideal must be a 869 * contraction of R and the TermOrder must be an elimination order. 870 * @param R solvable polynomial ring 871 * @return ideal(this \cap R) 872 */ 873 public SolvableIdeal<C> eliminate(GenSolvablePolynomialRing<C> R) { 874 if (R == null) { 875 throw new IllegalArgumentException("R may not be null"); 876 } 877 if (getRing().equals(R)) { 878 return this; 879 } 880 return intersect(R); 881 } 882 883 884 /** 885 * Quotient. Generators for the solvable ideal quotient. 886 * @param h solvable polynomial 887 * @return ideal(this : h), a Groebner base 888 */ 889 //@SuppressWarnings("unchecked") 890 public SolvableIdeal<C> quotient(GenSolvablePolynomial<C> h) { 891 if (h == null) { // == (0) 892 return this; 893 } 894 if (h.isZERO()) { 895 return this; 896 } 897 if (this.isZERO()) { 898 return this; 899 } 900 List<GenSolvablePolynomial<C>> H; 901 H = new ArrayList<GenSolvablePolynomial<C>>(1); 902 H.add(h); 903 SolvableIdeal<C> Hi = new SolvableIdeal<C>(getRing(), H, true, sided); 904 905 SolvableIdeal<C> I = this.intersect(Hi); 906 907 List<GenSolvablePolynomial<C>> Q; 908 Q = new ArrayList<GenSolvablePolynomial<C>>(I.getList().size()); 909 GenSolvablePolynomial<C> p; 910 for (GenSolvablePolynomial<C> q : I.getList()) { 911 p = q.divide(h); // remainder == 0, (GenSolvablePolynomial<C>) 912 if (!p.isZERO()) { 913 p = p.monic(); 914 Q.add(p); 915 } 916 if (debug) { 917 GenSolvablePolynomial<C> r = q.remainder(h); // (GenSolvablePolynomial<C>) 918 if (!r.isZERO()) { 919 System.out.println("error remainder !=0: " + r + ", q = " + q + ", h = " + h); 920 throw new RuntimeException("remainder !=0"); 921 } 922 } 923 } 924 return new SolvableIdeal<C>(getRing(), Q, true /*false?*/, sided); 925 } 926 927 928 /** 929 * Quotient. Generators for the solvable ideal quotient. 930 * @param H solvable ideal 931 * @return ideal(this : H), a Groebner base 932 */ 933 public SolvableIdeal<C> quotient(SolvableIdeal<C> H) { 934 if (H == null || H.isZERO()) { // == (0) 935 return this; 936 } 937 if (this.isZERO()) { 938 return this; 939 } 940 SolvableIdeal<C> Q = null; 941 for (GenSolvablePolynomial<C> h : H.getList()) { 942 SolvableIdeal<C> Hi = this.quotient(h); 943 if (Q == null) { 944 Q = Hi; 945 } else { 946 Q = Q.intersect(Hi); 947 } 948 } 949 return Q; 950 } 951 952 953 /** 954 * Infinite quotient. Generators for the infinite solvable ideal quotient. 955 * @param h solvable polynomial 956 * @return ideal(this : h<sup>s</sup>), a Groebner base 957 */ 958 public SolvableIdeal<C> infiniteQuotientRab(GenSolvablePolynomial<C> h) { 959 if (h == null || h.isZERO()) { // == (0) 960 return getONE(); 961 } 962 if (h.isONE()) { 963 return this; 964 } 965 if (this.isZERO()) { 966 return this; 967 } 968 if (!getRing().isCommutative()) { 969 throw new UnsupportedOperationException("Rabinowich trick only for commutative polynomial rings"); 970 } 971 SolvableIdeal<C> I = this.GB(); // should be already 972 List<GenSolvablePolynomial<C>> a = I.getList(); 973 List<GenSolvablePolynomial<C>> c; 974 c = new ArrayList<GenSolvablePolynomial<C>>(a.size() + 1); 975 976 GenSolvablePolynomialRing<C> tfac = getRing().extend(1); 977 // term order is also adjusted 978 for (GenSolvablePolynomial<C> p : a) { 979 p = (GenSolvablePolynomial<C>) p.extend(tfac, 0, 0L); // p 980 c.add(p); 981 } 982 GenSolvablePolynomial<C> q = (GenSolvablePolynomial<C>) h.extend(tfac, 0, 1L); 983 GenSolvablePolynomial<C> r = tfac.getONE(); // h.extend( tfac, 0, 0L ); 984 GenSolvablePolynomial<C> hs = (GenSolvablePolynomial<C>) q.subtract(r); // 1 - t*h // (1-t)*h 985 c.add(hs); 986 logger.warn("infiniteQuotientRab computing GB "); 987 List<GenSolvablePolynomial<C>> g = bb.leftGB(c); 988 if (debug) { 989 logger.info("infiniteQuotientRab = " + tfac + ", c = " + c); 990 logger.info("infiniteQuotientRab GB = " + g); 991 } 992 SolvableIdeal<C> E = new SolvableIdeal<C>(tfac, g, true, sided); 993 SolvableIdeal<C> Is = E.intersect(getRing()); 994 return Is; 995 } 996 997 998 /** 999 * Infinite quotient exponent. 1000 * @param h solvable polynomial 1001 * @param Q quotient this : h^\infinity 1002 * @return s with Q = this : h<sup>s</sup> 1003 */ 1004 public int infiniteQuotientExponent(GenSolvablePolynomial<C> h, SolvableIdeal<C> Q) { 1005 int s = 0; 1006 if (h == null) { // == 0 1007 return s; 1008 } 1009 if (h.isZERO() || h.isONE()) { 1010 return s; 1011 } 1012 if (this.isZERO() || this.isONE()) { 1013 return s; 1014 } 1015 //see below: if (this.contains(Q)) { 1016 // return s; 1017 //} 1018 GenSolvablePolynomial<C> p = getRing().getONE(); 1019 for (GenSolvablePolynomial<C> q : Q.getList()) { 1020 if (this.contains(q)) { 1021 continue; 1022 } 1023 //System.out.println("q = " + q + ", p = " + p + ", s = " + s); 1024 GenSolvablePolynomial<C> qp = q.multiply(p); 1025 while (!this.contains(qp)) { 1026 p = p.multiply(h); 1027 s++; 1028 qp = q.multiply(p); 1029 } 1030 } 1031 return s; 1032 } 1033 1034 1035 /** 1036 * Infinite quotient. Generators for the infinite solvable ideal quotient. 1037 * @param h solvable polynomial 1038 * @return ideal(this : h<sup>s</sup>), a Groebner base 1039 */ 1040 public SolvableIdeal<C> infiniteQuotient(GenSolvablePolynomial<C> h) { 1041 if (h == null) { // == (0) 1042 return this; 1043 } 1044 if (h.isZERO()) { 1045 return this; 1046 } 1047 if (this.isZERO()) { 1048 return this; 1049 } 1050 int s = 0; 1051 SolvableIdeal<C> I = this.GB(); // should be already 1052 GenSolvablePolynomial<C> hs = h; 1053 SolvableIdeal<C> Is = null; 1054 logger.info("infiniteQuotient hs = " + hs); 1055 long dm = -1; 1056 boolean eq = false; 1057 while (!eq) { 1058 Is = I.quotient(hs); 1059 Is = Is.GB(); // should be already 1060 //logger.info("ideal Is = " + Is); 1061 logger.info("infiniteQuotient s = " + s); 1062 if (Is.isZERO()) { 1063 logger.warn("infiniteQuotient does not exist"); 1064 return I; 1065 } 1066 eq = Is.contains(I); // I.contains(Is) always 1067 if (!eq) { 1068 long ds = PolyUtil.<C> totalDegree(Is.list.getList()); 1069 if (dm < 0) { 1070 dm = ds; 1071 } 1072 //System.out.println("deg(Is) = " + ds); 1073 if (ds > dm) { 1074 logger.warn("no convergence in infiniteQuotient (dm,ds): " + dm + " < " + ds); 1075 return I; 1076 //throw new RuntimeException("no convergence in infiniteQuotient"); 1077 } 1078 I = Is; 1079 s++; 1080 // hs = hs.multiply( h ); 1081 } 1082 } 1083 return Is; 1084 } 1085 1086 1087 /** 1088 * Radical membership test. 1089 * @param h solvable polynomial 1090 * @return true if h is contained in the radical of ideal(this), else false. 1091 */ 1092 public boolean isRadicalMember(GenSolvablePolynomial<C> h) { 1093 if (h == null) { // == (0) 1094 return true; 1095 } 1096 if (h.isZERO()) { 1097 return true; 1098 } 1099 if (this.isZERO()) { 1100 return true; 1101 } 1102 SolvableIdeal<C> x = infiniteQuotientRab(h); // may fail 1103 if (debug) { 1104 logger.debug("infiniteQuotientRab = " + x); 1105 } 1106 return x.isONE(); 1107 } 1108 1109 1110 /** 1111 * Infinite Quotient. Generators for the solvable ideal infinite quotient. 1112 * @param H solvable ideal 1113 * @return ideal(this : H<sup>s</sup>), a Groebner base 1114 */ 1115 public SolvableIdeal<C> infiniteQuotient(SolvableIdeal<C> H) { 1116 if (H == null) { // == (0) 1117 return this; 1118 } 1119 if (H.isZERO()) { 1120 return this; 1121 } 1122 if (this.isZERO()) { 1123 return this; 1124 } 1125 SolvableIdeal<C> Q = null; 1126 for (GenSolvablePolynomial<C> h : H.getList()) { 1127 SolvableIdeal<C> Hi = this.infiniteQuotient(h); 1128 if (Q == null) { 1129 Q = Hi; 1130 } else { 1131 Q = Q.intersect(Hi); 1132 } 1133 } 1134 return Q; 1135 } 1136 1137 1138 /** 1139 * Infinite Quotient. Generators for the solvable ideal infinite quotient. 1140 * @param H solvable ideal 1141 * @return ideal(this : H<sup>s</sup>), a Groebner base 1142 */ 1143 public SolvableIdeal<C> infiniteQuotientRab(SolvableIdeal<C> H) { 1144 if (H == null) { // == (0) 1145 return this; 1146 } 1147 if (H.isZERO()) { 1148 return this; 1149 } 1150 if (this.isZERO()) { 1151 return this; 1152 } 1153 SolvableIdeal<C> Q = null; 1154 for (GenSolvablePolynomial<C> h : H.getList()) { 1155 SolvableIdeal<C> Hi = this.infiniteQuotientRab(h); // may fail 1156 if (Q == null) { 1157 Q = Hi; 1158 } else { 1159 Q = Q.intersect(Hi); 1160 } 1161 } 1162 return Q; 1163 } 1164 1165 1166 /** 1167 * Power. Generators for the power of this solvable ideal. Note: if this 1168 * ideal is a Groebner base, a Groebner base is returned. 1169 * @param d integer 1170 * @return ideal(this^d) 1171 */ 1172 public SolvableIdeal<C> power(int d) { 1173 if (d <= 0) { 1174 return getONE(); 1175 } 1176 if (this.isZERO() || this.isONE()) { 1177 return this; 1178 } 1179 SolvableIdeal<C> c = this; 1180 for (int i = 1; i < d; i++) { 1181 c = c.product(this); 1182 } 1183 return c; 1184 } 1185 1186 1187 /** 1188 * Normalform for element. 1189 * @param h solvable polynomial 1190 * @return left normalform of h with respect to this 1191 */ 1192 public GenSolvablePolynomial<C> normalform(GenSolvablePolynomial<C> h) { 1193 if (h == null) { 1194 return h; 1195 } 1196 if (h.isZERO()) { 1197 return h; 1198 } 1199 if (this.isZERO()) { 1200 return h; 1201 } 1202 GenSolvablePolynomial<C> r; 1203 r = red.leftNormalform(getList(), h); 1204 return r; 1205 } 1206 1207 1208 /** 1209 * Normalform for list of solvable elements. 1210 * @param L solvable polynomial list 1211 * @return list of left normalforms of the elements of L with respect to 1212 * this 1213 */ 1214 public List<GenSolvablePolynomial<C>> normalform(List<GenSolvablePolynomial<C>> L) { 1215 if (L == null) { 1216 return L; 1217 } 1218 if (L.size() == 0) { 1219 return L; 1220 } 1221 if (this.isZERO()) { 1222 return L; 1223 } 1224 List<GenSolvablePolynomial<C>> M = new ArrayList<GenSolvablePolynomial<C>>(L.size()); 1225 for (GenSolvablePolynomial<C> h : L) { 1226 GenSolvablePolynomial<C> r = normalform(h); 1227 if (r != null && !r.isZERO()) { 1228 M.add(r); 1229 } 1230 } 1231 return M; 1232 } 1233 1234 1235 /** 1236 * Annihilator for element modulo this ideal. 1237 * @param h solvable polynomial 1238 * @return annihilator of h with respect to this 1239 */ 1240 public SolvableIdeal<C> annihilator(GenSolvablePolynomial<C> h) { 1241 if (h == null || h.isZERO()) { 1242 return getZERO(); 1243 } 1244 if (this.isZERO()) { 1245 return this; 1246 } 1247 doGB(); 1248 List<GenSolvablePolynomial<C>> F = new ArrayList<GenSolvablePolynomial<C>>(1 + getList().size()); 1249 F.add(h); 1250 F.addAll(getList()); 1251 //System.out.println("F = " + F); 1252 SolvableSyzygyAbstract<C> syz = new SolvableSyzygySeq<C>(getRing().coFac); 1253 List<List<GenSolvablePolynomial<C>>> S = syz.leftZeroRelationsArbitrary(F); 1254 //System.out.println("S = " + S); 1255 List<GenSolvablePolynomial<C>> gen = new ArrayList<GenSolvablePolynomial<C>>(S.size()); 1256 for (List<GenSolvablePolynomial<C>> rel : S) { 1257 if (rel == null || rel.isEmpty()) { 1258 continue; 1259 } 1260 GenSolvablePolynomial<C> p = rel.get(0); 1261 if (p == null || p.isZERO()) { 1262 continue; 1263 } 1264 gen.add(p); 1265 } 1266 SolvableIdeal<C> ann = new SolvableIdeal<C>(getRing(), gen, false, sided); 1267 //System.out.println("ann = " + ann); 1268 return ann; 1269 } 1270 1271 1272 /** 1273 * Test for annihilator of element modulo this ideal. 1274 * @param h solvable polynomial 1275 * @param A solvable ideal 1276 * @return true, if A is the annihilator of h with respect to this 1277 */ 1278 public boolean isAnnihilator(GenSolvablePolynomial<C> h, SolvableIdeal<C> A) { 1279 SolvableIdeal<C> B = A.product(h); 1280 return contains(B); 1281 } 1282 1283 1284 /** 1285 * Annihilator for ideal modulo this ideal. 1286 * @param H solvable ideal 1287 * @return annihilator of H with respect to this 1288 */ 1289 public SolvableIdeal<C> annihilator(SolvableIdeal<C> H) { 1290 if (H == null || H.isZERO()) { 1291 return getZERO(); 1292 } 1293 if (this.isZERO()) { 1294 return this; 1295 } 1296 SolvableIdeal<C> ann = null; 1297 for (GenSolvablePolynomial<C> h : H.getList()) { 1298 SolvableIdeal<C> Hi = this.annihilator(h); 1299 if (ann == null) { 1300 ann = Hi; 1301 } else { 1302 ann = ann.intersect(Hi); 1303 } 1304 } 1305 return ann; 1306 } 1307 1308 1309 /** 1310 * Test for annihilator of ideal modulo this ideal. 1311 * @param H solvable ideal 1312 * @param A solvable ideal 1313 * @return true, if A is the annihilator of H with respect to this 1314 */ 1315 public boolean isAnnihilator(SolvableIdeal<C> H, SolvableIdeal<C> A) { 1316 SolvableIdeal<C> B = A.product(H); 1317 return contains(B); 1318 } 1319 1320 1321 /** 1322 * Inverse for element modulo this ideal. 1323 * @param h solvable polynomial 1324 * @return inverse of h with respect to this, if defined 1325 */ 1326 public GenSolvablePolynomial<C> inverse(GenSolvablePolynomial<C> h) { 1327 if (h == null || h.isZERO()) { 1328 throw new NotInvertibleException("zero not invertible"); 1329 } 1330 if (this.isZERO()) { 1331 throw new NotInvertibleException("zero ideal"); 1332 } 1333 if (h.isUnit()) { 1334 return (GenSolvablePolynomial<C>) h.inverse(); 1335 } 1336 doGB(); 1337 List<GenSolvablePolynomial<C>> F = new ArrayList<GenSolvablePolynomial<C>>(1 + list.list.size()); 1338 F.add(h); 1339 F.addAll(getList()); 1340 //System.out.println("F = " + F); 1341 SolvableExtendedGB<C> x = bb.extLeftGB(F); 1342 List<GenSolvablePolynomial<C>> G = x.G; 1343 //System.out.println("G = " + G); 1344 GenSolvablePolynomial<C> one = null; 1345 int i = -1; 1346 for (GenSolvablePolynomial<C> p : G) { 1347 i++; 1348 if (p == null) { 1349 continue; 1350 } 1351 if (p.isUnit()) { 1352 one = p; 1353 break; 1354 } 1355 } 1356 if (one == null) { 1357 throw new NotInvertibleException("one == null: h = " + h); 1358 } 1359 List<GenSolvablePolynomial<C>> row = x.G2F.get(i); // != -1 1360 //System.out.println("row = " + row); 1361 GenSolvablePolynomial<C> g = row.get(0); 1362 if (g == null || g.isZERO()) { 1363 throw new NotInvertibleException("g == 0: h = " + h); 1364 } 1365 GenSolvablePolynomial<C> gp = red.leftNormalform(getList(), g); 1366 if (gp.isZERO()) { // can happen with solvable rings 1367 throw new NotInvertibleException("solv|gp == 0: h = " + h + ", g = " + g); 1368 } 1369 // adjust leading coefficient of g to get g*h == 1 1370 GenSolvablePolynomial<C> f = g.multiply(h); 1371 //System.out.println("f = " + f); 1372 GenSolvablePolynomial<C> k = red.leftNormalform(getList(), f); 1373 //System.out.println("k = " + k); 1374 if (!k.isONE()) { 1375 C lbc = k.leadingBaseCoefficient(); 1376 lbc = lbc.inverse(); 1377 g = g.multiply(lbc); 1378 } 1379 if (debug) { 1380 //logger.info("inv G = " + G); 1381 //logger.info("inv G2F = " + x.G2F); 1382 //logger.info("inv row "+i+" = " + row); 1383 //logger.info("inv h = " + h); 1384 //logger.info("inv g = " + g); 1385 //logger.info("inv f = " + f); 1386 f = g.multiply(h); 1387 k = red.leftNormalform(getList(), f); 1388 logger.debug("inv k = " + k); 1389 if (!k.isUnit()) { 1390 throw new NotInvertibleException(" k = " + k); 1391 } 1392 } 1393 return g; 1394 } 1395 1396 1397 /** 1398 * Test if element is a unit modulo this ideal. 1399 * @param h solvable polynomial 1400 * @return true if h is a unit with respect to this, else false 1401 */ 1402 public boolean isUnit(GenSolvablePolynomial<C> h) { 1403 if (h == null || h.isZERO()) { 1404 return false; 1405 } 1406 if (this.isZERO()) { 1407 return false; 1408 } 1409 List<GenSolvablePolynomial<C>> F = new ArrayList<GenSolvablePolynomial<C>>(1 + list.list.size()); 1410 F.add(h); 1411 F.addAll(getList()); 1412 List<GenSolvablePolynomial<C>> G = bb.leftGB(F); 1413 for (GenSolvablePolynomial<C> p : G) { 1414 if (p == null) { 1415 continue; 1416 } 1417 if (p.isUnit()) { 1418 return true; 1419 } 1420 } 1421 return false; 1422 } 1423 1424 1425 /** 1426 * Ideal common zero test. 1427 * @return -1, 0 or 1 if dimension(this) &eq; -1, 0 or ≥ 1. 1428 */ 1429 public int commonZeroTest() { 1430 if (this.isZERO()) { 1431 return 1; 1432 } 1433 if (!isGB) { 1434 doGB(); 1435 } 1436 if (this.isONE()) { 1437 return -1; 1438 } 1439 return bb.commonZeroTest(getList()); 1440 } 1441 1442 1443 /** 1444 * Test if this ideal is maximal. 1445 * @return true, if this is maximal and not one, else false. 1446 */ 1447 public boolean isMaximal() { 1448 if (commonZeroTest() != 0) { 1449 return false; 1450 } 1451 for (Long d : univariateDegrees()) { 1452 if (d > 1L) { 1453 // todo: test if univariate irreducible and no multiple polynomials 1454 return false; 1455 } 1456 } 1457 return true; 1458 } 1459 1460 1461 /** 1462 * Univariate head term degrees. 1463 * @return a list of the degrees of univariate head terms. 1464 */ 1465 public List<Long> univariateDegrees() { 1466 List<Long> ud = new ArrayList<Long>(); 1467 if (this.isZERO()) { 1468 return ud; 1469 } 1470 if (!isGB) { 1471 doGB(); 1472 } 1473 if (this.isONE()) { 1474 return ud; 1475 } 1476 return bb.univariateDegrees(getList()); 1477 } 1478 1479 1480 /** 1481 * Ideal dimension. 1482 * @return a dimension container (dim,maxIndep,list(maxIndep),vars). 1483 */ 1484 public Dimension dimension() { 1485 Ideal<C> ci = new Ideal<C>(list); 1486 return ci.dimension(); 1487 } 1488 1489 1490 /** 1491 * Construct univariate polynomials of minimal degree in all variables in 1492 * zero dimensional ideal(G). 1493 * @return list of univariate solvable polynomial of minimal degree in each 1494 * variable in ideal(G) 1495 */ 1496 public List<GenSolvablePolynomial<C>> constructUnivariate() { 1497 List<GenSolvablePolynomial<C>> univs = new ArrayList<GenSolvablePolynomial<C>>(); 1498 for (int i = getRing().nvar - 1; i >= 0; i--) { 1499 GenSolvablePolynomial<C> u = constructUnivariate(i); 1500 univs.add(u); 1501 } 1502 return univs; 1503 } 1504 1505 1506 /** 1507 * Construct univariate polynomial of minimal degree in variable i in zero 1508 * dimensional ideal(G). 1509 * @param i variable index. 1510 * @return univariate solvable polynomial of minimal degree in variable i in 1511 * ideal(G) 1512 */ 1513 public GenSolvablePolynomial<C> constructUnivariate(int i) { 1514 doGB(); 1515 return bb.constructUnivariate(i, getList()); 1516 } 1517 1518}