001/* 002 * $Id: WordIdeal.java 5303 2015-08-16 17:11:07Z kredel $ 003 */ 004 005package edu.jas.application; 006 007 008import java.io.Serializable; 009import java.util.ArrayList; 010import java.util.Collections; 011import java.util.Comparator; 012import java.util.List; 013import java.util.SortedSet; 014import java.util.TreeSet; 015 016import org.apache.log4j.Logger; 017 018import edu.jas.gb.WordGroebnerBaseAbstract; 019import edu.jas.gb.WordGroebnerBaseSeq; 020import edu.jas.gb.WordReduction; 021import edu.jas.gb.WordReductionSeq; 022import edu.jas.kern.Scripting; 023import edu.jas.poly.GenWordPolynomial; 024import edu.jas.poly.GenWordPolynomialRing; 025import edu.jas.poly.Word; 026import edu.jas.structure.GcdRingElem; 027import edu.jas.structure.NotInvertibleException; 028 029 030/** 031 * Word Ideal implements some methods for ideal arithmetic, for example 032 * containment, sum or product. <b>Note:</b> only two-sided ideals. 033 * @author Heinz Kredel 034 */ 035public class WordIdeal<C extends GcdRingElem<C>> implements Comparable<WordIdeal<C>>, Serializable { 036 037 038 private static final Logger logger = Logger.getLogger(WordIdeal.class); 039 040 041 private final boolean debug = logger.isDebugEnabled(); 042 043 044 /** 045 * The data structure is a list of word polynomials. 046 */ 047 protected List<GenWordPolynomial<C>> list; 048 049 050 /** 051 * Reference to the word polynomial ring. 052 */ 053 protected GenWordPolynomialRing<C> ring; 054 055 056 /** 057 * Indicator if list is a Groebner Base. 058 */ 059 protected boolean isGB; 060 061 062 /** 063 * Indicator if test has been performed if this is a Groebner Base. 064 */ 065 protected boolean testGB; 066 067 068 /** 069 * Groebner base engine. 070 */ 071 protected final WordGroebnerBaseAbstract<C> bb; 072 073 074 /** 075 * Reduction engine. 076 */ 077 protected final WordReduction<C> red; 078 079 080 /** 081 * Constructor. 082 * @param ring solvable polynomial ring 083 */ 084 public WordIdeal(GenWordPolynomialRing<C> ring) { 085 this(ring, new ArrayList<GenWordPolynomial<C>>()); 086 } 087 088 089 /** 090 * Constructor. 091 * @param ring word polynomial ring 092 * @param list word polynomial list 093 */ 094 public WordIdeal(GenWordPolynomialRing<C> ring, List<GenWordPolynomial<C>> list) { 095 this(ring, list, false); 096 } 097 098 099 /** 100 * Constructor. 101 * @param ring word polynomial ring 102 * @param list word polynomial list 103 * @param bb Groebner Base engine 104 * @param red Reduction engine 105 */ 106 public WordIdeal(GenWordPolynomialRing<C> ring, List<GenWordPolynomial<C>> list, 107 WordGroebnerBaseAbstract<C> bb, WordReduction<C> red) { 108 this(ring, list, false, bb, red); 109 } 110 111 112 /** 113 * Constructor. 114 * @param ring word polynomial ring 115 * @param list word polynomial list 116 * @param gb true if list is known to be a Groebner Base, else false 117 */ 118 public WordIdeal(GenWordPolynomialRing<C> ring, List<GenWordPolynomial<C>> list, boolean gb) { 119 this(ring, list, gb, new WordGroebnerBaseSeq<C>(), new WordReductionSeq<C>()); 120 //this(list, gb, topt, GBFactory.getImplementation(list.ring.coFac)); 121 } 122 123 124 /** 125 * Constructor. 126 * @param ring word polynomial ring 127 * @param list word polynomial list 128 * @param gb true if list is known to be a Groebner Base, else false 129 * @param bb Groebner Base engine 130 */ 131 public WordIdeal(GenWordPolynomialRing<C> ring, List<GenWordPolynomial<C>> list, boolean gb, 132 WordGroebnerBaseAbstract<C> bb) { 133 this(ring, list, gb, bb, bb.red); 134 } 135 136 137 /** 138 * Constructor. 139 * @param ring word polynomial ring 140 * @param list word polynomial list 141 * @param gb true if list is known to be a Groebner Base, else false 142 * @param bb Groebner Base engine 143 * @param red Reduction engine 144 */ 145 public WordIdeal(GenWordPolynomialRing<C> ring, List<GenWordPolynomial<C>> list, boolean gb, 146 WordGroebnerBaseAbstract<C> bb, WordReduction<C> red) { 147 if (ring == null) { 148 throw new IllegalArgumentException("ring may not be null"); 149 } 150 if (list == null) { 151 throw new IllegalArgumentException("list may not be null"); 152 } 153 this.ring = ring; 154 this.list = list; 155 this.isGB = gb; 156 this.testGB = (gb ? true : false); // ?? 157 this.bb = bb; 158 this.red = red; 159 if (debug) { 160 logger.info("constructed: " + this); 161 } 162 } 163 164 165 /** 166 * Clone this. 167 * @return a copy of this. 168 */ 169 public WordIdeal<C> copy() { 170 return new WordIdeal<C>(ring, new ArrayList<GenWordPolynomial<C>>(list), isGB, bb, red); 171 } 172 173 174 /** 175 * Get the List of GenWordPolynomials. 176 * @return (cast) list.list 177 */ 178 public List<GenWordPolynomial<C>> getList() { 179 return list; 180 } 181 182 183 /** 184 * Get the GenWordPolynomialRing. 185 * @return (cast) list.ring 186 */ 187 public GenWordPolynomialRing<C> getRing() { 188 return ring; 189 } 190 191 192 /** 193 * Get the zero ideal. 194 * @return ideal(0) 195 */ 196 public WordIdeal<C> getZERO() { 197 List<GenWordPolynomial<C>> z = new ArrayList<GenWordPolynomial<C>>(0); 198 return new WordIdeal<C>(ring, z, true, bb, red); 199 } 200 201 202 /** 203 * Get the one ideal. 204 * @return ideal(1) 205 */ 206 public WordIdeal<C> getONE() { 207 List<GenWordPolynomial<C>> one = new ArrayList<GenWordPolynomial<C>>(1); 208 one.add(getRing().getONE()); 209 return new WordIdeal<C>(ring, one, true, bb, red); 210 } 211 212 213 /** 214 * String representation of the solvable ideal. 215 * @see java.lang.Object#toString() 216 */ 217 @Override 218 public String toString() { 219 StringBuffer sb = new StringBuffer("("); 220 boolean first = true; 221 for (GenWordPolynomial<C> p : list) { 222 if (!first) { 223 sb.append(","); 224 } else { 225 first = false; 226 } 227 sb.append(p.toString()); 228 } 229 sb.append(")"); 230 return sb.toString(); 231 } 232 233 234 /** 235 * Get a scripting compatible string representation. 236 * @return script compatible representation for this Element. 237 * @see edu.jas.structure.Element#toScript() 238 */ 239 public String toScript() { 240 StringBuffer s = new StringBuffer(); 241 switch (Scripting.getLang()) { 242 case Ruby: 243 s.append("WordPolyIdeal.new("); 244 break; 245 case Python: 246 default: 247 s.append("WordIdeal("); 248 } 249 if (ring != null) { 250 s.append(ring.toScript()); 251 } 252 if (list == null) { 253 s.append(")"); 254 return s.toString(); 255 } 256 switch (Scripting.getLang()) { 257 case Ruby: 258 s.append(",\"\",["); 259 break; 260 case Python: 261 default: 262 s.append(",list=["); 263 } 264 boolean first = true; 265 String sa = null; 266 for (GenWordPolynomial<C> oa : list) { 267 sa = oa.toScript(); 268 if (first) { 269 first = false; 270 } else { 271 s.append(", "); 272 } 273 //s.append("( " + sa + " )"); 274 s.append(sa); 275 } 276 s.append("])"); 277 return s.toString(); 278 } 279 280 281 /** 282 * Comparison with any other object. <b>Note:</b> If not both ideals are 283 * Groebner Bases, then false may be returned even the ideals are equal. 284 * @see java.lang.Object#equals(java.lang.Object) 285 */ 286 @Override 287 @SuppressWarnings("unchecked") 288 public boolean equals(Object b) { 289 if (!(b instanceof WordIdeal)) { 290 logger.warn("equals no Ideal"); 291 return false; 292 } 293 WordIdeal<C> B = null; 294 try { 295 B = (WordIdeal<C>) b; 296 } catch (ClassCastException ignored) { 297 return false; 298 } 299 SortedSet<GenWordPolynomial<C>> s = new TreeSet<GenWordPolynomial<C>>(list); 300 SortedSet<GenWordPolynomial<C>> t = new TreeSet<GenWordPolynomial<C>>(B.list); 301 if (isGB && B.isGB) { //requires also monic polys 302 return s.equals(t); 303 } 304 if (s.equals(t)) { 305 return true; 306 } 307 //System.out.println("no GBs contains"); 308 return this.contains(B) && B.contains(this); 309 } 310 311 312 /** 313 * WordIdeal comparison. 314 * @param L other solvable ideal. 315 * @return compareTo() of polynomial lists. 316 */ 317 public int compareTo(WordIdeal<C> L) { 318 int si = Math.min(L.list.size(), list.size()); 319 int s = 0; 320 final Comparator<Word> wc = ring.alphabet.getAscendComparator(); 321 Comparator<GenWordPolynomial<C>> cmp = new Comparator<GenWordPolynomial<C>>() { 322 323 324 public int compare(GenWordPolynomial<C> p1, GenWordPolynomial<C> p2) { 325 Word w1 = p1.leadingWord(); 326 Word w2 = p2.leadingWord(); 327 if (w1 == null) { 328 return -1; // dont care 329 } 330 if (w2 == null) { 331 return 1; // dont care 332 } 333 if (w1.length() != w2.length()) { 334 if (w1.length() > w2.length()) { 335 return 1; // dont care 336 } 337 return -1; // dont care 338 } 339 return wc.compare(w1, w2); 340 } 341 }; 342 343 List<GenWordPolynomial<C>> l1 = new ArrayList<GenWordPolynomial<C>>(list); 344 List<GenWordPolynomial<C>> l2 = new ArrayList<GenWordPolynomial<C>>(L.list); 345 //Collections.sort(l1); 346 //Collections.sort(l2); 347 Collections.sort(l1, cmp); 348 Collections.sort(l2, cmp); 349 for (int i = 0; i < si; i++) { 350 GenWordPolynomial<C> a = l1.get(i); 351 GenWordPolynomial<C> b = l2.get(i); 352 s = a.compareTo(b); 353 if (s != 0) { 354 return s; 355 } 356 } 357 if (list.size() > si) { 358 return 1; 359 } 360 if (L.list.size() > si) { 361 return -1; 362 } 363 return s; 364 } 365 366 367 /** 368 * Hash code for this solvable ideal. 369 * @see java.lang.Object#hashCode() 370 */ 371 @Override 372 public int hashCode() { 373 int h; 374 h = list.hashCode(); 375 if (isGB) { 376 h = h << 1; 377 } 378 if (testGB) { 379 h += 1; 380 } 381 return h; 382 } 383 384 385 /** 386 * Test if ZERO ideal. 387 * @return true, if this is the 0 ideal, else false 388 */ 389 public boolean isZERO() { 390 //return list.isZERO(); 391 if (list == null) { // never true 392 return true; 393 } 394 for (GenWordPolynomial<C> p : list) { 395 if (p == null) { 396 continue; 397 } 398 if (!p.isZERO()) { 399 return false; 400 } 401 } 402 return true; 403 } 404 405 406 /** 407 * Test if ONE is contained in the ideal. To test for a proper ideal use 408 * <code>! id.isONE()</code>. 409 * @return true, if this is the 1 ideal, else false 410 */ 411 public boolean isONE() { 412 //return list.isONE(); 413 if (list == null) { 414 return false; 415 } 416 for (GenWordPolynomial<C> p : list) { 417 if (p == null) { 418 continue; 419 } 420 if (p.isONE()) { 421 return true; 422 } 423 } 424 return false; 425 } 426 427 428 /** 429 * Test if this is a twosided Groebner base. 430 * @return true, if this is a twosided Groebner base, else false 431 */ 432 public boolean isGB() { 433 if (testGB) { 434 return isGB; 435 } 436 logger.warn("isGB computing"); 437 isGB = bb.isGB(getList()); 438 testGB = true; 439 return isGB; 440 } 441 442 443 /** 444 * Do Groebner Base. Compute the Groebner Base for this ideal. 445 */ 446 @SuppressWarnings("unchecked") 447 public void doGB() { 448 if (isGB && testGB) { 449 return; 450 } 451 List<GenWordPolynomial<C>> G = getList(); 452 logger.info("GB computing = " + G); 453 list = bb.GB(G); 454 isGB = true; 455 testGB = true; 456 return; 457 } 458 459 460 /** 461 * Groebner Base. Get a Groebner Base for this ideal. 462 * @return twosidedGB(this) 463 */ 464 public WordIdeal<C> GB() { 465 if (isGB) { 466 return this; 467 } 468 doGB(); 469 return this; 470 } 471 472 473 /** 474 * Word ideal containment. Test if B is contained in this ideal. Note: this 475 * is eventually modified to become a Groebner Base. 476 * @param B solvable ideal 477 * @return true, if B is contained in this, else false 478 */ 479 public boolean contains(WordIdeal<C> B) { 480 if (B == null || B.isZERO()) { 481 return true; 482 } 483 return contains(B.getList()); 484 } 485 486 487 /** 488 * Word ideal containment. Test if b is contained in this ideal. Note: this 489 * is eventually modified to become a Groebner Base. 490 * @param b solvable polynomial 491 * @return true, if b is contained in this, else false 492 */ 493 public boolean contains(GenWordPolynomial<C> b) { 494 if (b == null || b.isZERO()) { 495 return true; 496 } 497 if (this.isONE()) { 498 return true; 499 } 500 if (this.isZERO()) { 501 return false; 502 } 503 if (!isGB) { 504 doGB(); 505 } 506 GenWordPolynomial<C> z = red.normalform(getList(), b); 507 if (z == null || z.isZERO()) { 508 return true; 509 } 510 return false; 511 } 512 513 514 /** 515 * Word ideal containment. Test if each b in B is contained in this ideal. 516 * Note: this is eventually modified to become a Groebner Base. 517 * @param B list of solvable polynomials 518 * @return true, if each b in B is contained in this, else false 519 */ 520 public boolean contains(List<GenWordPolynomial<C>> B) { 521 if (B == null || B.size() == 0) { 522 return true; 523 } 524 if (this.isONE()) { 525 return true; 526 } 527 if (!isGB) { 528 doGB(); 529 } 530 List<GenWordPolynomial<C>> si = getList(); 531 for (GenWordPolynomial<C> b : B) { 532 if (b == null) { 533 continue; 534 } 535 GenWordPolynomial<C> z = red.normalform(si, b); 536 if (!z.isZERO()) { 537 System.out.println("contains nf(b) != 0: " + b + ", z = " + z); 538 //System.out.println("contains nf(b) != 0: si = " + si); 539 return false; 540 } 541 } 542 return true; 543 } 544 545 546 /** 547 * Word ideal summation. Generators for the sum of ideals. Note: if both 548 * ideals are Groebner bases, a Groebner base is returned. 549 * @param B solvable ideal 550 * @return ideal(this+B) 551 */ 552 public WordIdeal<C> sum(WordIdeal<C> B) { 553 if (B == null || B.isZERO()) { 554 return this; 555 } 556 if (this.isZERO()) { 557 return B; 558 } 559 int s = getList().size() + B.getList().size(); 560 List<GenWordPolynomial<C>> c; 561 c = new ArrayList<GenWordPolynomial<C>>(s); 562 c.addAll(getList()); 563 c.addAll(B.getList()); 564 WordIdeal<C> I = new WordIdeal<C>(getRing(), c, false); 565 if (isGB && B.isGB) { 566 I.doGB(); 567 } 568 return I; 569 } 570 571 572 /** 573 * Word summation. Generators for the sum of ideal and a polynomial. Note: 574 * if this ideal is a Groebner base, a Groebner base is returned. 575 * @param b solvable polynomial 576 * @return ideal(this+{b}) 577 */ 578 public WordIdeal<C> sum(GenWordPolynomial<C> b) { 579 if (b == null || b.isZERO()) { 580 return this; 581 } 582 int s = getList().size() + 1; 583 List<GenWordPolynomial<C>> c; 584 c = new ArrayList<GenWordPolynomial<C>>(s); 585 c.addAll(getList()); 586 c.add(b); 587 WordIdeal<C> I = new WordIdeal<C>(getRing(), c, false); 588 if (isGB) { 589 I.doGB(); 590 } 591 return I; 592 } 593 594 595 /** 596 * Word summation. Generators for the sum of this ideal and a list of 597 * polynomials. Note: if this ideal is a Groebner base, a Groebner base is 598 * returned. 599 * @param L list of solvable polynomials 600 * @return ideal(this+L) 601 */ 602 public WordIdeal<C> sum(List<GenWordPolynomial<C>> L) { 603 if (L == null || L.isEmpty()) { 604 return this; 605 } 606 int s = getList().size() + L.size(); 607 List<GenWordPolynomial<C>> c = new ArrayList<GenWordPolynomial<C>>(s); 608 c.addAll(getList()); 609 c.addAll(L); 610 WordIdeal<C> I = new WordIdeal<C>(getRing(), c, false); 611 if (isGB) { 612 I.doGB(); 613 } 614 return I; 615 } 616 617 618 /** 619 * Product. Generators for the product of ideals. Note: if both ideals are 620 * Groebner bases, a Groebner base is returned. 621 * @param B solvable ideal 622 * @return ideal(this*B) 623 */ 624 public WordIdeal<C> product(WordIdeal<C> B) { 625 if (B == null || B.isZERO()) { 626 return B; 627 } 628 if (this.isZERO()) { 629 return this; 630 } 631 int s = getList().size() * B.getList().size(); 632 List<GenWordPolynomial<C>> c; 633 c = new ArrayList<GenWordPolynomial<C>>(s); 634 for (GenWordPolynomial<C> p : getList()) { 635 for (GenWordPolynomial<C> q : B.getList()) { 636 q = p.multiply(q); 637 c.add(q); 638 } 639 } 640 WordIdeal<C> I = new WordIdeal<C>(getRing(), c, false); 641 if (isGB && B.isGB) { 642 I.doGB(); 643 } 644 return I; 645 } 646 647 648 /** 649 * Left product. Generators for the product this by a polynomial. 650 * @param b solvable polynomial 651 * @return ideal(this*b) 652 */ 653 public WordIdeal<C> product(GenWordPolynomial<C> b) { 654 if (b == null || b.isZERO()) { 655 return getZERO(); 656 } 657 if (this.isZERO()) { 658 return this; 659 } 660 List<GenWordPolynomial<C>> c; 661 c = new ArrayList<GenWordPolynomial<C>>(getList().size()); 662 for (GenWordPolynomial<C> p : getList()) { 663 GenWordPolynomial<C> q = p.multiply(b); 664 c.add(q); 665 } 666 WordIdeal<C> I = new WordIdeal<C>(getRing(), c, false); 667 if (isGB) { 668 I.doGB(); 669 } 670 return I; 671 } 672 673 674 /* 675 * Intersection. Generators for the intersection of ideals. Using an 676 * iterative algorithm. 677 * @param Bl list of solvable ideals 678 * @return ideal(cap_i B_i), a Groebner base 679 public WordIdeal<C> intersect(List<WordIdeal<C>> Bl) { 680 if (Bl == null || Bl.size() == 0) { 681 return getZERO(); 682 } 683 WordIdeal<C> I = null; 684 for (WordIdeal<C> B : Bl) { 685 if (I == null) { 686 I = B; 687 continue; 688 } 689 if (I.isONE()) { 690 return I; 691 } 692 I = I.intersect(B); 693 } 694 return I; 695 } 696 */ 697 698 699 /* 700 * Intersection. Generators for the intersection of ideals. 701 * @param B solvable ideal 702 * @return ideal(this \cap B), a Groebner base 703 public WordIdeal<C> intersect(WordIdeal<C> B) { 704 if (B == null || B.isZERO()) { // (0) 705 return B; 706 } 707 if (this.isZERO()) { 708 return this; 709 } 710 List<GenWordPolynomial<C>> c = PolyGBUtil.<C> intersect(getRing(),getList(),B.getList()); 711 WordIdeal<C> I = new WordIdeal<C>(getRing(), c, true); 712 return I; 713 } 714 */ 715 716 717 /* 718 * Intersection. Generators for the intersection of a ideal with a 719 * polynomial ring. The polynomial ring of this ideal must be a contraction 720 * of R and the TermOrder must be an elimination order. 721 * @param R solvable polynomial ring 722 * @return ideal(this \cap R) 723 public WordIdeal<C> intersect(GenWordPolynomialRing<C> R) { 724 if (R == null) { 725 throw new IllegalArgumentException("R may not be null"); 726 } 727 List<GenWordPolynomial<C>> H = PolyUtil.<C> intersect(R,getList()); 728 return new WordIdeal<C>(R, H, isGB, isTopt); 729 } 730 */ 731 732 733 /* 734 * Eliminate. Generators for the intersection of this ideal with a solvable 735 * polynomial ring. The solvable polynomial ring of this ideal must be a 736 * contraction of R and the TermOrder must be an elimination order. 737 * @param R solvable polynomial ring 738 * @return ideal(this \cap R) 739 public WordIdeal<C> eliminate(GenWordPolynomialRing<C> R) { 740 if (R == null) { 741 throw new IllegalArgumentException("R may not be null"); 742 } 743 if (getRing().equals(R)) { 744 return this; 745 } 746 return intersect(R); 747 } 748 */ 749 750 751 /* 752 * Quotient. Generators for the solvable ideal quotient. 753 * @param h solvable polynomial 754 * @return ideal(this : h), a Groebner base 755 public WordIdeal<C> quotient(GenWordPolynomial<C> h) { 756 if (h == null) { // == (0) 757 return this; 758 } 759 if (h.isZERO()) { 760 return this; 761 } 762 if (this.isZERO()) { 763 return this; 764 } 765 List<GenWordPolynomial<C>> H; 766 H = new ArrayList<GenWordPolynomial<C>>(1); 767 H.add(h); 768 WordIdeal<C> Hi = new WordIdeal<C>(getRing(), H, true); 769 770 WordIdeal<C> I = this.intersect(Hi); 771 772 List<GenWordPolynomial<C>> Q; 773 Q = new ArrayList<GenWordPolynomial<C>>(I.getList().size()); 774 for (GenWordPolynomial<C> q : I.getList()) { 775 q = (GenWordPolynomial<C>) q.divide(h); // remainder == 0 776 Q.add(q); 777 } 778 return new WordIdeal<C>(getRing(), Q, true); 779 } 780 */ 781 782 783 /* 784 * Quotient. Generators for the solvable ideal quotient. 785 * @param H solvable ideal 786 * @return ideal(this : H), a Groebner base 787 public WordIdeal<C> quotient(WordIdeal<C> H) { 788 if (H == null || H.isZERO()) { // == (0) 789 return this; 790 } 791 if (this.isZERO()) { 792 return this; 793 } 794 WordIdeal<C> Q = null; 795 for (GenWordPolynomial<C> h : H.getList()) { 796 WordIdeal<C> Hi = this.quotient(h); 797 if (Q == null) { 798 Q = Hi; 799 } else { 800 Q = Q.intersect(Hi); 801 } 802 } 803 return Q; 804 } 805 */ 806 807 808 /** 809 * Power. Generators for the power of this solvable ideal. Note: if this 810 * ideal is a Groebner base, a Groebner base is returned. 811 * @param d integer 812 * @return ideal(this^d) 813 */ 814 public WordIdeal<C> power(int d) { 815 if (d <= 0) { 816 return getONE(); 817 } 818 if (this.isZERO() || this.isONE()) { 819 return this; 820 } 821 WordIdeal<C> c = this; 822 for (int i = 1; i < d; i++) { 823 c = c.product(this); 824 } 825 return c; 826 } 827 828 829 /** 830 * Normalform for element. 831 * @param h solvable polynomial 832 * @return left normalform of h with respect to this 833 */ 834 public GenWordPolynomial<C> normalform(GenWordPolynomial<C> h) { 835 if (h == null) { 836 return h; 837 } 838 if (h.isZERO()) { 839 return h; 840 } 841 if (this.isZERO()) { 842 return h; 843 } 844 GenWordPolynomial<C> r; 845 r = red.normalform(getList(), h); 846 return r; 847 } 848 849 850 /** 851 * Normalform for list of solvable elements. 852 * @param L solvable polynomial list 853 * @return list of left normalforms of the elements of L with respect to 854 * this 855 */ 856 public List<GenWordPolynomial<C>> normalform(List<GenWordPolynomial<C>> L) { 857 if (L == null) { 858 return L; 859 } 860 if (L.size() == 0) { 861 return L; 862 } 863 if (this.isZERO()) { 864 return L; 865 } 866 List<GenWordPolynomial<C>> M = new ArrayList<GenWordPolynomial<C>>(L.size()); 867 for (GenWordPolynomial<C> h : L) { 868 GenWordPolynomial<C> r = normalform(h); 869 if (r != null && !r.isZERO()) { 870 M.add(r); 871 } 872 } 873 return M; 874 } 875 876 877 /** 878 * Inverse for element modulo this ideal. 879 * @param h word polynomial 880 * @return inverse of h with respect to this, if defined 881 */ 882 public GenWordPolynomial<C> inverse(GenWordPolynomial<C> h) { 883 if (h == null || h.isZERO()) { 884 throw new NotInvertibleException("zero not invertible"); 885 } 886 if (this.isZERO()) { 887 throw new NotInvertibleException("zero ideal"); 888 } 889 if (h.isUnit()) { 890 return h.inverse(); 891 } 892 throw new UnsupportedOperationException("inverse of " + h); 893 /* 894 doGB(); 895 List<GenWordPolynomial<C>> F = new ArrayList<GenWordPolynomial<C>>(1 + list.list.size()); 896 F.add(h); 897 F.addAll(getList()); 898 //System.out.println("F = " + F); 899 WordExtendedGB<C> x = bb.extLeftGB(F); 900 List<GenWordPolynomial<C>> G = x.G; 901 //System.out.println("G = " + G); 902 GenWordPolynomial<C> one = null; 903 int i = -1; 904 for (GenWordPolynomial<C> p : G) { 905 i++; 906 if (p == null) { 907 continue; 908 } 909 if (p.isUnit()) { 910 one = p; 911 break; 912 } 913 } 914 if (one == null) { 915 throw new NotInvertibleException("one == null: h = " + h); 916 } 917 List<GenWordPolynomial<C>> row = x.G2F.get(i); // != -1 918 //System.out.println("row = " + row); 919 GenWordPolynomial<C> g = row.get(0); 920 if (g == null || g.isZERO()) { 921 throw new NotInvertibleException("g == 0: h = " + h); 922 } 923 GenWordPolynomial<C> gp = red.leftNormalform(getList(), g); 924 if (gp.isZERO()) { // can happen with solvable rings 925 throw new NotInvertibleException("solv|gp == 0: h = " + h + ", g = " + g); 926 } 927 // adjust leading coefficient of g to get g*h == 1 928 GenWordPolynomial<C> f = g.multiply(h); 929 //System.out.println("f = " + f); 930 GenWordPolynomial<C> k = red.leftNormalform(getList(), f); 931 //System.out.println("k = " + k); 932 if (!k.isONE()) { 933 C lbc = k.leadingBaseCoefficient(); 934 lbc = lbc.inverse(); 935 g = g.multiply(lbc); 936 } 937 if (debug) { 938 //logger.info("inv G = " + G); 939 //logger.info("inv G2F = " + x.G2F); 940 //logger.info("inv row "+i+" = " + row); 941 //logger.info("inv h = " + h); 942 //logger.info("inv g = " + g); 943 //logger.info("inv f = " + f); 944 f = g.multiply(h); 945 k = red.leftNormalform(getList(), f); 946 logger.debug("inv k = " + k); 947 if (!k.isUnit()) { 948 throw new NotInvertibleException(" k = " + k); 949 } 950 } 951 return g; 952 */ 953 } 954 955 956 /** 957 * Test if element is a unit modulo this ideal. 958 * @param h solvable polynomial 959 * @return true if h is a unit with respect to this, else false 960 */ 961 public boolean isUnit(GenWordPolynomial<C> h) { 962 if (h == null || h.isZERO()) { 963 return false; 964 } 965 if (this.isZERO()) { 966 return false; 967 } 968 if (h.isUnit()) { 969 return true; 970 } 971 /* TODO together wit inverse 972 List<GenWordPolynomial<C>> F = new ArrayList<GenWordPolynomial<C>>(1 + list.size()); 973 F.add(h); 974 F.addAll(getList()); 975 List<GenWordPolynomial<C>> G = bb.GB(F); 976 if (debug) { 977 logger.info("isUnit GB = " + G); 978 } 979 for (GenWordPolynomial<C> p : G) { 980 if (p == null) { 981 continue; 982 } 983 if (p.isUnit()) { 984 return true; 985 } 986 } 987 */ 988 return false; 989 } 990 991 992 /** 993 * Ideal common zero test. 994 * @return -1, 0 or 1 if dimension(this) &eq; -1, 0 or ≥ 1. 995 */ 996 public int commonZeroTest() { 997 if (this.isZERO()) { 998 return 1; 999 } 1000 if (!isGB) { 1001 doGB(); 1002 } 1003 if (this.isONE()) { 1004 return -1; 1005 } 1006 return bb.commonZeroTest(getList()); 1007 } 1008 1009 1010 /** 1011 * Test if this ideal is maximal. 1012 * @return true, if this is maximal and not one, else false. 1013 */ 1014 public boolean isMaximal() { 1015 if (commonZeroTest() != 0) { 1016 return false; 1017 } 1018 for (Long d : univariateDegrees()) { 1019 if (d > 1L) { 1020 // todo: test if irreducible 1021 return false; 1022 } 1023 } 1024 return true; 1025 } 1026 1027 1028 /** 1029 * Univariate head term degrees. 1030 * @return a list of the degrees of univariate head terms. 1031 */ 1032 public List<Long> univariateDegrees() { 1033 List<Long> ud = new ArrayList<Long>(); 1034 if (this.isZERO()) { 1035 return ud; 1036 } 1037 if (!isGB) { 1038 doGB(); 1039 } 1040 if (this.isONE()) { 1041 return ud; 1042 } 1043 return bb.univariateDegrees(getList()); 1044 } 1045 1046 1047 /* 1048 * Construct univariate polynomials of minimal degree in all variables in 1049 * zero dimensional ideal(G). 1050 * @return list of univariate solvable polynomial of minimal degree in each 1051 * variable in ideal(G) 1052 public List<GenWordPolynomial<C>> constructUnivariate() { 1053 List<GenWordPolynomial<C>> univs = new ArrayList<GenWordPolynomial<C>>(); 1054 for (int i = ring.alphabet.length() - 1; i >= 0; i--) { 1055 GenWordPolynomial<C> u = constructUnivariate(i); 1056 univs.add(u); 1057 } 1058 return univs; 1059 } 1060 */ 1061 1062 1063 /* 1064 * Construct univariate polynomial of minimal degree in variable i in zero 1065 * dimensional ideal(G). 1066 * @param i variable index. 1067 * @return univariate solvable polynomial of minimal degree in variable i in 1068 * ideal(G) 1069 public GenWordPolynomial<C> constructUnivariate(int i) { 1070 doGB(); 1071 return bb.constructUnivariate(i, getList()); 1072 } 1073 */ 1074 1075}