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