001/* 002 * $Id: GenPolynomialRing.java 5908 2018-08-25 11:49:29Z kredel $ 003 */ 004 005package edu.jas.poly; 006 007 008import java.io.IOException; 009import java.io.Reader; 010import java.io.StringReader; 011import java.math.BigInteger; 012import java.util.ArrayList; 013import java.util.Arrays; 014import java.util.HashSet; 015import java.util.Iterator; 016import java.util.List; 017import java.util.Random; 018import java.util.Set; 019 020import org.apache.logging.log4j.Logger; 021import org.apache.logging.log4j.LogManager; 022 023import edu.jas.arith.ModIntegerRing; 024import edu.jas.kern.PreemptStatus; 025import edu.jas.kern.PrettyPrint; 026import edu.jas.kern.Scripting; 027import edu.jas.structure.RingElem; 028import edu.jas.structure.RingFactory; 029import edu.jas.util.CartesianProduct; 030import edu.jas.util.CartesianProductInfinite; 031import edu.jas.util.LongIterable; 032 033 034/** 035 * GenPolynomialRing generic polynomial factory. It implements 036 * RingFactory for n-variate ordered polynomials over coefficients 037 * C. The variables commute with each other and with the 038 * coefficients. For non-commutative coefficients some care is taken 039 * to respect the multiplication order. 040 * 041 * Almost immutable object, except variable names. 042 * @param <C> coefficient type 043 * @author Heinz Kredel 044 */ 045 046public class GenPolynomialRing<C extends RingElem<C>> implements RingFactory<GenPolynomial<C>>, 047 Iterable<GenPolynomial<C>> { 048 049 050 /** 051 * The factory for the coefficients. 052 */ 053 public final RingFactory<C> coFac; 054 055 056 /** 057 * The number of variables. 058 */ 059 public final int nvar; 060 061 062 /** 063 * The term order. 064 */ 065 public final TermOrder tord; 066 067 068 /** 069 * True for partially reversed variables. 070 */ 071 protected boolean partial; 072 073 074 /** 075 * The names of the variables. This value can be modified. 076 */ 077 protected String[] vars; 078 079 080 /** 081 * The names of all known variables. 082 */ 083 private static Set<String> knownVars = new HashSet<String>(); 084 085 086 /** 087 * The constant polynomial 0 for this ring. 088 */ 089 public final GenPolynomial<C> ZERO; 090 091 092 /** 093 * The constant polynomial 1 for this ring. 094 */ 095 public final GenPolynomial<C> ONE; 096 097 098 /** 099 * The constant exponent vector 0 for this ring. 100 */ 101 public final ExpVector evzero; 102 103 104 /** 105 * A default random sequence generator. 106 */ 107 protected final static Random random = new Random(); 108 109 110 /** 111 * Indicator if this ring is a field. 112 */ 113 protected int isField = -1; // initially unknown 114 115 116 /** 117 * Log4j logger object. 118 */ 119 private static final Logger logger = LogManager.getLogger(GenPolynomialRing.class); 120 121 122 /** 123 * Count for number of polynomial creations. 124 */ 125 static int creations = 0; 126 127 128 /** 129 * Flag to enable if preemptive interrrupt is checked. 130 */ 131 final boolean checkPreempt = PreemptStatus.isAllowed(); 132 133 134 /** 135 * The constructor creates a polynomial factory object with the default term 136 * order. 137 * @param cf factory for coefficients of type C. 138 * @param n number of variables. 139 */ 140 public GenPolynomialRing(RingFactory<C> cf, int n) { 141 this(cf, n, new TermOrder(), null); 142 } 143 144 145 /** 146 * The constructor creates a polynomial factory object. 147 * @param cf factory for coefficients of type C. 148 * @param n number of variables. 149 * @param t a term order. 150 */ 151 public GenPolynomialRing(RingFactory<C> cf, int n, TermOrder t) { 152 this(cf, n, t, null); 153 } 154 155 156 /** 157 * The constructor creates a polynomial factory object. 158 * @param cf factory for coefficients of type C. 159 * @param v names for the variables. 160 */ 161 public GenPolynomialRing(RingFactory<C> cf, String[] v) { 162 this(cf, v.length, v); 163 } 164 165 166 /** 167 * The constructor creates a polynomial factory object. 168 * @param cf factory for coefficients of type C. 169 * @param n number of variables. 170 * @param v names for the variables. 171 */ 172 public GenPolynomialRing(RingFactory<C> cf, int n, String[] v) { 173 this(cf, n, new TermOrder(), v); 174 } 175 176 177 /** 178 * The constructor creates a polynomial factory object. 179 * @param cf factory for coefficients of type C. 180 * @param t a term order. 181 * @param v names for the variables. 182 */ 183 public GenPolynomialRing(RingFactory<C> cf, TermOrder t, String[] v) { 184 this(cf, v.length, t, v); 185 } 186 187 188 /** 189 * The constructor creates a polynomial factory object. 190 * @param cf factory for coefficients of type C. 191 * @param v names for the variables. 192 * @param t a term order. 193 */ 194 public GenPolynomialRing(RingFactory<C> cf, String[] v, TermOrder t) { 195 this(cf, v.length, t, v); 196 } 197 198 199 /** 200 * The constructor creates a polynomial factory object. 201 * @param cf factory for coefficients of type C. 202 * @param n number of variables. 203 * @param t a term order. 204 * @param v names for the variables. 205 */ 206 public GenPolynomialRing(RingFactory<C> cf, int n, TermOrder t, String[] v) { 207 coFac = cf; 208 nvar = n; 209 tord = t; 210 partial = false; 211 if (v == null) { 212 vars = null; 213 } else { 214 vars = Arrays.copyOf(v, v.length); // > Java-5 215 } 216 ZERO = new GenPolynomial<C>(this); 217 C coeff = coFac.getONE(); 218 evzero = ExpVector.create(nvar); 219 ONE = new GenPolynomial<C>(this, coeff, evzero); 220 if (vars == null) { 221 if (PrettyPrint.isTrue()) { 222 vars = newVars("x", nvar); 223 } 224 } else { 225 if (vars.length != nvar) { 226 throw new IllegalArgumentException("incompatible variable size " + vars.length + ", " + nvar); 227 } 228 addVars(vars); 229 } 230 } 231 232 233 /** 234 * The constructor creates a polynomial factory object with the the same 235 * term order, number of variables and variable names as the given 236 * polynomial factory, only the coefficient factories differ. 237 * @param cf factory for coefficients of type C. 238 * @param o other polynomial ring. 239 */ 240 public GenPolynomialRing(RingFactory<C> cf, GenPolynomialRing o) { 241 this(cf, o.nvar, o.tord, o.vars); 242 } 243 244 245 /** 246 * The constructor creates a polynomial factory object with the the same 247 * coefficient factory, number of variables and variable names as the given 248 * polynomial factory, only the term order differs. 249 * @param to term order. 250 * @param o other polynomial ring. 251 */ 252 public GenPolynomialRing(GenPolynomialRing<C> o, TermOrder to) { 253 this(o.coFac, o.nvar, to, o.vars); 254 } 255 256 257 /** 258 * Copy this factory. 259 * @return a clone of this. 260 */ 261 public GenPolynomialRing<C> copy() { 262 return new GenPolynomialRing<C>(coFac, this); 263 } 264 265 266 /** 267 * Get the String representation. 268 * @see java.lang.Object#toString() 269 */ 270 @SuppressWarnings("cast") 271 @Override 272 public String toString() { 273 String res = null; 274 if (PrettyPrint.isTrue()) { // wrong: && coFac != null 275 String scf = coFac.getClass().getSimpleName(); 276 if (coFac instanceof AlgebraicNumberRing) { 277 AlgebraicNumberRing an = (AlgebraicNumberRing) coFac; 278 //String[] v = an.ring.vars; 279 res = "AN[ (" + an.ring.varsToString() + ") (" + an.toString() + ") ]"; 280 } 281 if (coFac instanceof GenPolynomialRing) { 282 GenPolynomialRing rf = (GenPolynomialRing) coFac; 283 //String[] v = rf.vars; 284 //RingFactory cf = rf.coFac; 285 //String cs; 286 //if (cf instanceof ModIntegerRing) { 287 // cs = cf.toString(); 288 //} else { 289 // cs = " " + cf.getClass().getSimpleName(); 290 //} 291 //res = "IntFunc" + "{" + cs + "( " + rf.varsToString() + " )" + " } "; 292 res = "IntFunc" + "( " + rf.toString() + " )"; 293 } 294 if (((Object) coFac) instanceof ModIntegerRing) { 295 ModIntegerRing mn = (ModIntegerRing) ((Object) coFac); 296 res = "Mod " + mn.getModul() + " "; 297 } 298 if (res == null) { 299 res = coFac.toString(); 300 if (res.matches("[0-9].*")) { 301 res = scf; 302 } 303 } 304 res += "( " + varsToString() + " ) " + tord.toString() + " "; 305 } else { 306 res = this.getClass().getSimpleName() + "[ " + coFac.toString() + " "; 307 // + coFac.getClass().getSimpleName(); 308 if (coFac instanceof AlgebraicNumberRing) { 309 AlgebraicNumberRing an = (AlgebraicNumberRing) coFac; 310 res = "AN[ (" + an.ring.varsToString() + ") (" + an.modul + ") ]"; 311 } 312 if (coFac instanceof GenPolynomialRing) { 313 GenPolynomialRing rf = (GenPolynomialRing) coFac; 314 //String[] v = rf.vars; 315 //RingFactory cf = rf.coFac; 316 //String cs; 317 //if (cf instanceof ModIntegerRing) { 318 // cs = cf.toString(); 319 //} else { 320 // cs = " " + cf.getClass().getSimpleName(); 321 //} 322 //res = "IntFunc{ " + cs + "( " + rf.varsToString() + " )" + " } "; 323 res = "IntFunc" + "( " + rf.toString() + " )"; 324 } 325 if (((Object) coFac) instanceof ModIntegerRing) { 326 ModIntegerRing mn = (ModIntegerRing) ((Object) coFac); 327 res = "Mod " + mn.getModul() + " "; 328 } 329 //res += ", " + nvar + ", " + tord.toString() + ", " + varsToString() + ", " + partial + " ]"; 330 res += "( " + varsToString() + " ) " + tord.toString() + " ]"; 331 } 332 return res; 333 } 334 335 336 /** 337 * Get a scripting compatible string representation. 338 * @return script compatible representation for this Element. 339 * @see edu.jas.structure.Element#toScript() 340 */ 341 @Override 342 public String toScript() { 343 StringBuffer s = new StringBuffer(); 344 switch (Scripting.getLang()) { 345 case Ruby: 346 s.append("PolyRing.new("); 347 break; 348 case Python: 349 default: 350 s.append("PolyRing("); 351 } 352 if (coFac instanceof RingElem) { 353 s.append(((RingElem<C>) coFac).toScriptFactory()); 354 } else { 355 s.append(coFac.toScript().trim()); 356 } 357 s.append(",\"" + varsToString() + "\""); 358 String to = tord.toScript(); 359 //if (tord.getEvord() == TermOrder.INVLEX) { 360 // to = "PolyRing.lex"; 361 //} 362 //if (tord.getEvord() == TermOrder.IGRLEX) { 363 // to = "PolyRing.grad"; 364 //} 365 s.append("," + to); 366 s.append(")"); 367 return s.toString(); 368 } 369 370 371 /** 372 * Get a scripting compatible string representation of an ExpVector of this 373 * ring. 374 * @param e exponent vector 375 * @return script compatible representation for the ExpVector. 376 */ 377 public String toScript(ExpVector e) { 378 if (e == null) { 379 return "null"; 380 } 381 if (vars != null) { 382 return e.toScript(vars); 383 } 384 return e.toScript(); 385 } 386 387 388 /** 389 * Comparison with any other object. 390 * @see java.lang.Object#equals(java.lang.Object) 391 */ 392 @Override 393 @SuppressWarnings("unchecked") 394 public boolean equals(Object other) { 395 if (other == null) { 396 return false; 397 } 398 if (!(other instanceof GenPolynomialRing)) { 399 return false; 400 } 401 GenPolynomialRing<C> oring = (GenPolynomialRing<C>) other; 402 if (nvar != oring.nvar) { 403 return false; 404 } 405 if (!coFac.equals(oring.coFac)) { 406 return false; 407 } 408 if (!tord.equals(oring.tord)) { 409 return false; 410 } 411 // same variables required ? 412 if (!Arrays.deepEquals(vars, oring.vars)) { 413 return false; 414 } 415 return true; 416 } 417 418 419 /** 420 * Hash code for this polynomial ring. 421 * @see java.lang.Object#hashCode() 422 */ 423 @Override 424 public int hashCode() { 425 int h; 426 h = (nvar << 27); 427 h += (coFac.hashCode() << 11); 428 h += tord.hashCode(); 429 return h; 430 } 431 432 433 /** 434 * Get the number of polynomial creations. 435 * @return creations. 436 */ 437 public int getCreations() { 438 return creations; 439 } 440 441 442 /** 443 * Get the variable names. 444 * @return vars. 445 */ 446 public String[] getVars() { 447 return Arrays.copyOf(vars, vars.length); // > Java-5 448 } 449 450 451 /** 452 * Set the variable names. 453 * @return old vars. 454 */ 455 public String[] setVars(String[] v) { 456 if (v.length != nvar) { 457 throw new IllegalArgumentException("v not matching number of variables: " + Arrays.toString(v) 458 + ", nvar " + nvar); 459 } 460 String[] t = vars; 461 vars = Arrays.copyOf(v, v.length); // > Java-5 462 return t; 463 } 464 465 466 /** 467 * Get a String representation of the variable names. 468 * @return names seperated by commas. 469 */ 470 public String varsToString() { 471 if (vars == null) { 472 return "#" + nvar; 473 } 474 //return Arrays.toString(vars); 475 return ExpVector.varsToString(vars); 476 } 477 478 479 /** 480 * Get the zero element from the coefficients. 481 * @return 0 as C. 482 */ 483 public C getZEROCoefficient() { 484 return coFac.getZERO(); 485 } 486 487 488 /** 489 * Get the one element from the coefficients. 490 * @return 1 as C. 491 */ 492 public C getONECoefficient() { 493 return coFac.getONE(); 494 } 495 496 497 /** 498 * Get the zero element. 499 * @return 0 as GenPolynomial<C>. 500 */ 501 public GenPolynomial<C> getZERO() { 502 return ZERO; 503 } 504 505 506 /** 507 * Get the one element. 508 * @return 1 as GenPolynomial<C>. 509 */ 510 public GenPolynomial<C> getONE() { 511 return ONE; 512 } 513 514 515 /** 516 * Query if this ring is commutative. 517 * @return true if this ring is commutative, else false. 518 */ 519 public boolean isCommutative() { 520 return coFac.isCommutative(); 521 } 522 523 524 /** 525 * Query if this ring is associative. 526 * @return true if this ring is associative, else false. 527 */ 528 public boolean isAssociative() { 529 return coFac.isAssociative(); 530 } 531 532 533 /** 534 * Query if this ring is a field. 535 * @return false. 536 */ 537 public boolean isField() { 538 if (isField > 0) { 539 return true; 540 } 541 if (isField == 0) { 542 return false; 543 } 544 if (coFac.isField() && nvar == 0) { 545 isField = 1; 546 return true; 547 } 548 isField = 0; 549 return false; 550 } 551 552 553 /** 554 * Characteristic of this ring. 555 * @return characteristic of this ring. 556 */ 557 public java.math.BigInteger characteristic() { 558 return coFac.characteristic(); 559 } 560 561 562 /** 563 * Get a (constant) GenPolynomial<C> element from a coefficient value. 564 * @param a coefficient. 565 * @return a GenPolynomial<C>. 566 */ 567 public GenPolynomial<C> valueOf(C a) { 568 return new GenPolynomial<C>(this, a); 569 } 570 571 572 /** 573 * Get a GenPolynomial<C> element from an exponent vector. 574 * @param e exponent vector. 575 * @return a GenPolynomial<C>. 576 */ 577 public GenPolynomial<C> valueOf(ExpVector e) { 578 if (e == null) { 579 return getZERO(); 580 } 581 return new GenPolynomial<C>(this, coFac.getONE(), e); 582 } 583 584 585 /** 586 * Get a GenPolynomial<C> element from a list of exponent vectors. 587 * @param E list of exponent vector. 588 * @return a GenPolynomial<C>. 589 */ 590 public List<GenPolynomial<C>> valueOf(Iterable<ExpVector> E) { 591 if (E == null) { 592 return null; 593 } 594 List<GenPolynomial<C>> P = new ArrayList<GenPolynomial<C>>(); //E.size()); 595 for ( ExpVector e : E ) { 596 GenPolynomial<C> p = valueOf(e); 597 P.add(p); 598 } 599 return P; 600 } 601 602 603 /** 604 * Get a GenPolynomial<C> element from a coeffcient and an exponent 605 * vector. 606 * @param a coefficient. 607 * @param e exponent vector. 608 * @return a GenPolynomial<C>. 609 */ 610 public GenPolynomial<C> valueOf(C a, ExpVector e) { 611 return new GenPolynomial<C>(this, a, e); 612 } 613 614 615 /** 616 * Get a GenPolynomial<C> element from a monomial. 617 * @param m monomial. 618 * @return a GenPolynomial<C>. 619 */ 620 public GenPolynomial<C> valueOf(Monomial<C> m) { 621 return new GenPolynomial<C>(this, m.c, m.e); 622 } 623 624 625 /** 626 * Get a (constant) GenPolynomial<C> element from a long value. 627 * @param a long. 628 * @return a GenPolynomial<C>. 629 */ 630 public GenPolynomial<C> fromInteger(long a) { 631 return new GenPolynomial<C>(this, coFac.fromInteger(a), evzero); 632 } 633 634 635 /** 636 * Get a (constant) GenPolynomial<C> element from a BigInteger value. 637 * @param a BigInteger. 638 * @return a GenPolynomial<C>. 639 */ 640 public GenPolynomial<C> fromInteger(BigInteger a) { 641 return new GenPolynomial<C>(this, coFac.fromInteger(a), evzero); 642 } 643 644 645 /** 646 * Random polynomial. Generates a random polynomial with k = 5, l = n, d = 647 * (nvar == 1) ? n : 3, q = (nvar == 1) ? 0.7 : 0.3. 648 * @param n number of terms. 649 * @return a random polynomial. 650 */ 651 public GenPolynomial<C> random(int n) { 652 return random(n, random); 653 } 654 655 656 /** 657 * Random polynomial. Generates a random polynomial with k = 5, l = n, d = 658 * n, q = (nvar == 1) ? 0.5 : 0.3. 659 * @param n number of terms. 660 * @param rnd is a source for random bits. 661 * @return a random polynomial. 662 */ 663 public GenPolynomial<C> random(int n, Random rnd) { 664 if (nvar == 1) { 665 return random(3, n, n, 0.5f, rnd); 666 } 667 return random(3, n, n, 0.3f, rnd); 668 } 669 670 671 /** 672 * Generate a random polynomial. 673 * @param k bitsize of random coefficients. 674 * @param l number of terms. 675 * @param d maximal degree in each variable. 676 * @param q density of nozero exponents. 677 * @return a random polynomial. 678 */ 679 public GenPolynomial<C> random(int k, int l, int d, float q) { 680 return random(k, l, d, q, random); 681 } 682 683 684 /** 685 * Generate a random polynomial. 686 * @param k bitsize of random coefficients. 687 * @param l number of terms. 688 * @param d maximal degree in each variable. 689 * @param q density of nozero exponents. 690 * @param rnd is a source for random bits. 691 * @return a random polynomial. 692 */ 693 public GenPolynomial<C> random(int k, int l, int d, float q, Random rnd) { 694 GenPolynomial<C> r = getZERO(); //.clone() or copy( ZERO ); 695 ExpVector e; 696 C a; 697 // add l random coeffs and exponents 698 for (int i = 0; i < l; i++) { 699 e = ExpVector.random(nvar, d, q, rnd); 700 a = coFac.random(k, rnd); 701 r = r.sum(a, e); // somewhat inefficient but clean 702 //System.out.println("e = " + e + " a = " + a); 703 } 704 // System.out.println("r = " + r); 705 return r; 706 } 707 708 709 /** 710 * Copy polynomial c. 711 * @param c 712 * @return a copy of c. 713 */ 714 public GenPolynomial<C> copy(GenPolynomial<C> c) { 715 //System.out.println("GP copy = " + this); 716 return new GenPolynomial<C>(this, c.val); 717 } 718 719 720 /** 721 * Copy polynomial list. 722 * @param L polynomial list 723 * @return a copy of L in this ring. 724 */ 725 public List<GenPolynomial<C>> copy(List<GenPolynomial<C>> L) { 726 if (L == null) { 727 return L; 728 } 729 List<GenPolynomial<C>> R = new ArrayList<GenPolynomial<C>>(L.size()); 730 for ( GenPolynomial<C> a : L ) { 731 R.add( copy(a) ); 732 } 733 return R; 734 } 735 736 737 /** 738 * Parse a polynomial with the use of GenPolynomialTokenizer. 739 * @param s String. 740 * @return GenPolynomial from s. 741 */ 742 public GenPolynomial<C> parse(String s) { 743 String val = s; 744 if (!s.contains("|")) { 745 val = val.replace("{", "").replace("}", ""); 746 } 747 return parse(new StringReader(val)); 748 } 749 750 751 /** 752 * Parse a polynomial with the use of GenPolynomialTokenizer. 753 * @param r Reader. 754 * @return next GenPolynomial from r. 755 */ 756 @SuppressWarnings({ "unchecked", "cast" }) 757 public GenPolynomial<C> parse(Reader r) { 758 GenPolynomialTokenizer pt = new GenPolynomialTokenizer(this, r); 759 GenPolynomial<C> p = null; 760 try { 761 p = (GenPolynomial<C>) pt.nextPolynomial(); 762 } catch (IOException e) { 763 logger.error(e.toString() + " parse " + this); 764 p = ZERO; 765 } 766 return p; 767 } 768 769 770 /** 771 * Generate univariate polynomial in a given variable with given exponent. 772 * @param x the name of a variable. 773 * @return x as univariate polynomial. 774 */ 775 public GenPolynomial<C> univariate(String x) { 776 return univariate(x, 1L); 777 } 778 779 780 /** 781 * Generate univariate polynomial in a given variable with given exponent. 782 * @param x the name of the variable. 783 * @param e the exponent of the variable. 784 * @return x^e as univariate polynomial. 785 */ 786 public GenPolynomial<C> univariate(String x, long e) { 787 if (vars == null) { // should not happen 788 throw new IllegalArgumentException("no variables defined for polynomial ring"); 789 } 790 if (x == null || x.isEmpty()) { 791 throw new IllegalArgumentException("no variable name given"); 792 } 793 int i; 794 for ( i = 0 ; i < vars.length; i++ ) { 795 if (x.equals(vars[i])) { // use HashMap or TreeMap 796 break; 797 } 798 } 799 if (i >= vars.length) { 800 throw new IllegalArgumentException("variable '" + x + "' not defined in polynomial ring"); 801 } 802 return univariate(0, nvar - i - 1, e); 803 } 804 805 806 /** 807 * Generate univariate polynomial in a given variable. 808 * @param i the index of the variable. 809 * @return X_i as univariate polynomial. 810 */ 811 public GenPolynomial<C> univariate(int i) { 812 return univariate(0, i, 1L); 813 } 814 815 816 /** 817 * Generate univariate polynomial in a given variable with given exponent. 818 * @param i the index of the variable. 819 * @param e the exponent of the variable. 820 * @return X_i^e as univariate polynomial. 821 */ 822 public GenPolynomial<C> univariate(int i, long e) { 823 return univariate(0, i, e); 824 } 825 826 827 /** 828 * Generate univariate polynomial in a given variable with given exponent. 829 * @param modv number of module variables. 830 * @param i the index of the variable. 831 * @param e the exponent of the variable. 832 * @return X_i^e as univariate polynomial. 833 */ 834 public GenPolynomial<C> univariate(int modv, int i, long e) { 835 GenPolynomial<C> p = getZERO(); 836 int r = nvar - modv; 837 if (0 <= i && i < r) { 838 C one = coFac.getONE(); 839 ExpVector f = ExpVector.create(r, i, e); 840 if (modv > 0) { 841 f = f.extend(modv, 0, 0l); 842 } 843 p = p.sum(one, f); 844 } 845 return p; 846 } 847 848 849 /** 850 * Get the generating elements excluding the generators for the coefficient 851 * ring. 852 * @return a list of generating elements for this ring. 853 */ 854 public List<GenPolynomial<C>> getGenerators() { 855 List<? extends GenPolynomial<C>> univs = univariateList(); 856 List<GenPolynomial<C>> gens = new ArrayList<GenPolynomial<C>>(univs.size() + 1); 857 gens.add(getONE()); 858 gens.addAll(univs); 859 return gens; 860 } 861 862 863 /** 864 * Get a list of the generating elements. 865 * @return list of generators for the algebraic structure. 866 * @see edu.jas.structure.ElemFactory#generators() 867 */ 868 public List<GenPolynomial<C>> generators() { 869 List<? extends C> cogens = coFac.generators(); 870 List<? extends GenPolynomial<C>> univs = univariateList(); 871 List<GenPolynomial<C>> gens = new ArrayList<GenPolynomial<C>>(univs.size() + cogens.size()); 872 for (C c : cogens) { 873 gens.add(getONE().multiply(c)); 874 } 875 gens.addAll(univs); 876 return gens; 877 } 878 879 880 /** 881 * Get a list of the generating elements excluding the module variables. 882 * @param modv number of module variables 883 * @return list of generators for the polynomial ring. 884 */ 885 public List<GenPolynomial<C>> generators(int modv) { 886 List<? extends C> cogens = coFac.generators(); 887 List<? extends GenPolynomial<C>> univs = univariateList(modv); 888 List<GenPolynomial<C>> gens = new ArrayList<GenPolynomial<C>>(univs.size() + cogens.size()); 889 for (C c : cogens) { 890 gens.add(getONE().multiply(c)); 891 } 892 gens.addAll(univs); 893 return gens; 894 } 895 896 897 /** 898 * Is this structure finite or infinite. 899 * @return true if this structure is finite, else false. 900 * @see edu.jas.structure.ElemFactory#isFinite() 901 */ 902 public boolean isFinite() { 903 return (nvar == 0) && coFac.isFinite(); 904 } 905 906 907 /** 908 * Generate list of univariate polynomials in all variables. 909 * @return List(X_1,...,X_n) a list of univariate polynomials. 910 */ 911 public List<? extends GenPolynomial<C>> univariateList() { 912 return univariateList(0, 1L); 913 } 914 915 916 /** 917 * Generate list of univariate polynomials in all variables. 918 * @param modv number of module variables. 919 * @return List(X_1,...,X_n) a list of univariate polynomials. 920 */ 921 public List<? extends GenPolynomial<C>> univariateList(int modv) { 922 return univariateList(modv, 1L); 923 } 924 925 926 /** 927 * Generate list of univariate polynomials in all variables with given 928 * exponent. 929 * @param modv number of module variables. 930 * @param e the exponent of the variables. 931 * @return List(X_1^e,...,X_n^e) a list of univariate polynomials. 932 */ 933 public List<? extends GenPolynomial<C>> univariateList(int modv, long e) { 934 List<GenPolynomial<C>> pols = new ArrayList<GenPolynomial<C>>(nvar); 935 int nm = nvar - modv; 936 for (int i = 0; i < nm; i++) { 937 GenPolynomial<C> p = univariate(modv, nm - 1 - i, e); 938 pols.add(p); 939 } 940 return pols; 941 } 942 943 944 /** 945 * Extend variables. Used e.g. in module embedding. Extend number of 946 * variables by i. 947 * @param i number of variables to extend. 948 * @return extended polynomial ring factory. 949 */ 950 public GenPolynomialRing<C> extend(int i) { 951 return extend(i, false); 952 } 953 954 955 /** 956 * Extend variables. Used e.g. in module embedding. Extend number of 957 * variables by i. 958 * @param i number of variables to extend. 959 * @param top true for TOP term order, false for POT term order. 960 * @return extended polynomial ring factory. 961 */ 962 public GenPolynomialRing<C> extend(int i, boolean top) { 963 // add module variable names 964 String[] v = newVars("e", i); 965 return extend(v, top); 966 } 967 968 969 /** 970 * Extend variables. Used e.g. in module embedding. Extend number of 971 * variables by length(vn). 972 * @param vn names for extended variables. 973 * @return extended polynomial ring factory. 974 */ 975 public GenPolynomialRing<C> extend(String[] vn) { 976 return extend(vn, false); 977 } 978 979 980 /** 981 * Extend variables. Used e.g. in module embedding. Extend number of 982 * variables by length(vn). 983 * @param vn names for extended variables. 984 * @param top true for TOP term order, false for POT term order. 985 * @return extended polynomial ring factory. 986 */ 987 public GenPolynomialRing<C> extend(String[] vn, boolean top) { 988 if (vn == null || vars == null) { 989 throw new IllegalArgumentException("vn and vars may not be null"); 990 } 991 int i = vn.length; 992 String[] v = new String[vars.length + i]; 993 for (int k = 0; k < vars.length; k++) { 994 v[k] = vars[k]; 995 } 996 for (int k = 0; k < vn.length; k++) { 997 v[vars.length + k] = vn[k]; 998 } 999 TermOrder to = tord.extend(nvar, i, top); 1000 GenPolynomialRing<C> pfac = new GenPolynomialRing<C>(coFac, nvar + i, to, v); 1001 return pfac; 1002 } 1003 1004 1005 /** 1006 * Extend lower variables. Extend number of variables by i. 1007 * @param i number of variables to extend. 1008 * @return extended polynomial ring factory. 1009 */ 1010 public GenPolynomialRing<C> extendLower(int i) { 1011 String[] v = newVars("e", i); 1012 return extendLower(v); 1013 } 1014 1015 1016 /** 1017 * Extend lower variables. Extend number of variables by length(vn). 1018 * @param vn names for extended lower variables. 1019 * @return extended polynomial ring factory. 1020 */ 1021 public GenPolynomialRing<C> extendLower(String[] vn) { 1022 if (vn == null || vars == null) { 1023 throw new IllegalArgumentException("vn and vars may not be null"); 1024 } 1025 int i = vn.length; 1026 String[] v = new String[vars.length + i]; 1027 for (int k = 0; k < vn.length; k++) { 1028 v[k] = vn[k]; 1029 } 1030 for (int k = 0; k < vars.length; k++) { 1031 v[vn.length + k] = vars[k]; 1032 } 1033 TermOrder to = tord.extendLower(nvar, i); 1034 GenPolynomialRing<C> pfac = new GenPolynomialRing<C>(coFac, nvar + i, to, v); 1035 return pfac; 1036 } 1037 1038 1039 /** 1040 * Contract variables. Used e.g. in module embedding. Contract number of 1041 * variables by i. 1042 * @param i number of variables to remove. 1043 * @return contracted polynomial ring factory. 1044 */ 1045 public GenPolynomialRing<C> contract(int i) { 1046 String[] v = null; 1047 if (vars != null) { 1048 v = new String[vars.length - i]; 1049 for (int j = 0; j < vars.length - i; j++) { 1050 v[j] = vars[j]; 1051 } 1052 } 1053 TermOrder to = tord.contract(i, nvar - i); 1054 GenPolynomialRing<C> pfac = new GenPolynomialRing<C>(coFac, nvar - i, to, v); 1055 return pfac; 1056 } 1057 1058 1059 /** 1060 * Recursive representation as polynomial with i main variables. 1061 * @param i number of main variables. 1062 * @return recursive polynomial ring factory. 1063 */ 1064 public GenPolynomialRing<GenPolynomial<C>> recursive(int i) { 1065 if (i <= 0 || i >= nvar) { 1066 throw new IllegalArgumentException("wrong: 0 < " + i + " < " + nvar); 1067 } 1068 GenPolynomialRing<C> cfac = contract(i); 1069 String[] v = null; 1070 if (vars != null) { 1071 v = new String[i]; 1072 int k = 0; 1073 for (int j = nvar - i; j < nvar; j++) { 1074 v[k++] = vars[j]; 1075 } 1076 } 1077 TermOrder to = tord.contract(0, i); // ?? 1078 GenPolynomialRing<GenPolynomial<C>> pfac = new GenPolynomialRing<GenPolynomial<C>>(cfac, i, to, v); 1079 return pfac; 1080 } 1081 1082 1083 /** 1084 * Distributive representation as polynomial with all main variables. 1085 * @return distributive polynomial ring factory. 1086 */ 1087 @SuppressWarnings("unchecked") 1088 public GenPolynomialRing<C> distribute() { 1089 if (!(coFac instanceof GenPolynomialRing)) { 1090 return this; 1091 } 1092 RingFactory cf = coFac; 1093 RingFactory<GenPolynomial<C>> cfp = (RingFactory<GenPolynomial<C>>) cf; 1094 GenPolynomialRing cr = (GenPolynomialRing) cfp; 1095 GenPolynomialRing<C> pfac; 1096 if (cr.vars != null) { 1097 pfac = extend(cr.vars); 1098 } else { 1099 pfac = extend(cr.nvar); 1100 } 1101 return pfac; 1102 } 1103 1104 1105 /** 1106 * Reverse variables. Used e.g. in opposite rings. 1107 * @return polynomial ring factory with reversed variables. 1108 */ 1109 public GenPolynomialRing<C> reverse() { 1110 return reverse(false); 1111 } 1112 1113 1114 /** 1115 * Reverse variables. Used e.g. in opposite rings. 1116 * @param partial true for partialy reversed term orders. 1117 * @return polynomial ring factory with reversed variables. 1118 */ 1119 public GenPolynomialRing<C> reverse(boolean partial) { 1120 String[] v = null; 1121 if (vars != null) { // vars are not inversed 1122 v = new String[vars.length]; 1123 int k = tord.getSplit(); 1124 if (partial && k < vars.length) { 1125 // copy upper 1126 for (int j = 0; j < k; j++) { 1127 //v[vars.length - k + j] = vars[vars.length - 1 - j]; // reverse upper 1128 v[vars.length - k + j] = vars[vars.length - k + j]; 1129 } 1130 // reverse lower 1131 for (int j = 0; j < vars.length - k; j++) { 1132 //v[j] = vars[j]; // copy upper 1133 v[j] = vars[vars.length - k - j - 1]; 1134 } 1135 } else { 1136 for (int j = 0; j < vars.length; j++) { 1137 v[j] = vars[vars.length - 1 - j]; 1138 } 1139 } 1140 //System.out.println("vars = " + Arrays.toString(vars)); 1141 //System.out.println("v = " + Arrays.toString(v)); 1142 } 1143 TermOrder to = tord.reverse(partial); 1144 GenPolynomialRing<C> pfac = new GenPolynomialRing<C>(coFac, nvar, to, v); 1145 pfac.partial = partial; 1146 return pfac; 1147 } 1148 1149 1150 /** 1151 * Get PolynomialComparator. 1152 * @return polynomial comparator. 1153 */ 1154 public PolynomialComparator<C> getComparator() { 1155 return new PolynomialComparator<C>(tord, false); 1156 } 1157 1158 1159 /** 1160 * Get PolynomialComparator. 1161 * @param rev for reverse comparator. 1162 * @return polynomial comparator. 1163 */ 1164 public PolynomialComparator<C> getComparator(boolean rev) { 1165 return new PolynomialComparator<C>(tord, rev); 1166 } 1167 1168 1169 /** 1170 * New variable names. Generate new names for variables, 1171 * @param prefix name prefix. 1172 * @param n number of variables. 1173 * @return new variable names. 1174 */ 1175 public static String[] newVars(String prefix, int n) { 1176 String[] vars = new String[n]; 1177 synchronized (knownVars) { 1178 int m = knownVars.size(); 1179 String name = prefix + m; 1180 for (int i = 0; i < n; i++) { 1181 while (knownVars.contains(name)) { 1182 m++; 1183 name = prefix + m; 1184 } 1185 vars[i] = name; 1186 //System.out.println("new variable: " + name); 1187 knownVars.add(name); 1188 m++; 1189 name = prefix + m; 1190 } 1191 } 1192 return vars; 1193 } 1194 1195 1196 /** 1197 * New variable names. Generate new names for variables, 1198 * @param prefix name prefix. 1199 * @return new variable names. 1200 */ 1201 public String[] newVars(String prefix) { 1202 return newVars(prefix, nvar); 1203 } 1204 1205 1206 /** 1207 * New variable names. Generate new names for variables, 1208 * @param n number of variables. 1209 * @return new variable names. 1210 */ 1211 public static String[] newVars(int n) { 1212 return newVars("x", n); 1213 } 1214 1215 1216 /** 1217 * New variable names. Generate new names for variables, 1218 * @return new variable names. 1219 */ 1220 public String[] newVars() { 1221 return newVars(nvar); 1222 } 1223 1224 1225 /** 1226 * Add variable names. 1227 * @param vars variable names to be recorded. 1228 */ 1229 public static void addVars(String[] vars) { 1230 if (vars == null) { 1231 return; 1232 } 1233 synchronized (knownVars) { 1234 for (int i = 0; i < vars.length; i++) { 1235 knownVars.add(vars[i]); // eventualy names 'overwritten' 1236 } 1237 } 1238 } 1239 1240 1241 /** 1242 * Permute variable names. 1243 * @param vars variable names. 1244 * @param P permutation. 1245 * @return P(vars). 1246 */ 1247 public static String[] permuteVars(List<Integer> P, String[] vars) { 1248 if (vars == null || vars.length <= 1) { 1249 return vars; 1250 } 1251 String[] b = new String[vars.length]; 1252 int j = 0; 1253 for (Integer i : P) { 1254 b[j++] = vars[i]; 1255 } 1256 return b; 1257 } 1258 1259 1260 /** 1261 * Permutation of polynomial ring variables. 1262 * @param P permutation. 1263 * @return P(this). 1264 */ 1265 public GenPolynomialRing<C> permutation(List<Integer> P) { 1266 if (nvar <= 1) { 1267 return this; 1268 } 1269 TermOrder tp = tord.permutation(P); 1270 if (vars == null) { 1271 return new GenPolynomialRing<C>(coFac, nvar, tp); 1272 } 1273 String[] v1 = new String[vars.length]; 1274 for (int i = 0; i < v1.length; i++) { 1275 v1[i] = vars[v1.length - 1 - i]; 1276 } 1277 String[] vp = permuteVars(P, v1); 1278 String[] v2 = new String[vp.length]; 1279 for (int i = 0; i < vp.length; i++) { 1280 v2[i] = vp[vp.length - 1 - i]; 1281 } 1282 return new GenPolynomialRing<C>(coFac, nvar, tp, v2); 1283 } 1284 1285 1286 /** 1287 * Get a GenPolynomial iterator. 1288 * @return an iterator over all polynomials. 1289 */ 1290 public Iterator<GenPolynomial<C>> iterator() { 1291 if (coFac.isFinite()) { 1292 return new GenPolynomialIterator<C>(this); 1293 } 1294 logger.warn("ring of coefficients " + coFac 1295 + " is infinite, constructing iterator only over monomials"); 1296 return new GenPolynomialMonomialIterator<C>(this); 1297 //throw new IllegalArgumentException("only for finite iterable coefficients implemented"); 1298 } 1299 1300} 1301 1302 1303/** 1304 * Polynomial iterator. 1305 * @author Heinz Kredel 1306 */ 1307class GenPolynomialIterator<C extends RingElem<C>> implements Iterator<GenPolynomial<C>> { 1308 1309 1310 /** 1311 * data structure. 1312 */ 1313 final GenPolynomialRing<C> ring; 1314 1315 1316 final Iterator<List<Long>> eviter; 1317 1318 1319 final List<ExpVector> powers; 1320 1321 1322 final List<Iterable<C>> coeffiter; 1323 1324 1325 Iterator<List<C>> itercoeff; 1326 1327 1328 GenPolynomial<C> current; 1329 1330 1331 /** 1332 * Polynomial iterator constructor. 1333 */ 1334 @SuppressWarnings("unchecked") 1335 public GenPolynomialIterator(GenPolynomialRing<C> fac) { 1336 ring = fac; 1337 LongIterable li = new LongIterable(); 1338 li.setNonNegativeIterator(); 1339 List<Iterable<Long>> tlist = new ArrayList<Iterable<Long>>(ring.nvar); 1340 for (int i = 0; i < ring.nvar; i++) { 1341 tlist.add(li); 1342 } 1343 CartesianProductInfinite<Long> ei = new CartesianProductInfinite<Long>(tlist); 1344 eviter = ei.iterator(); 1345 RingFactory<C> cf = ring.coFac; 1346 coeffiter = new ArrayList<Iterable<C>>(); 1347 if (cf instanceof Iterable && cf.isFinite()) { 1348 Iterable<C> cfi = (Iterable<C>) cf; 1349 coeffiter.add(cfi); 1350 } else { 1351 throw new IllegalArgumentException("only for finite iterable coefficients implemented"); 1352 } 1353 CartesianProduct<C> tuples = new CartesianProduct<C>(coeffiter); 1354 itercoeff = tuples.iterator(); 1355 powers = new ArrayList<ExpVector>(); 1356 ExpVector e = ExpVector.create(eviter.next()); 1357 powers.add(e); 1358 //System.out.println("new e = " + e); 1359 //System.out.println("powers = " + powers); 1360 List<C> c = itercoeff.next(); 1361 //System.out.println("coeffs = " + c); 1362 current = new GenPolynomial<C>(ring, c.get(0), e); 1363 } 1364 1365 1366 /** 1367 * Test for availability of a next element. 1368 * @return true if the iteration has more elements, else false. 1369 */ 1370 public boolean hasNext() { 1371 return true; 1372 } 1373 1374 1375 /** 1376 * Get next polynomial. 1377 * @return next polynomial. 1378 */ 1379 public synchronized GenPolynomial<C> next() { 1380 GenPolynomial<C> res = current; 1381 if (!itercoeff.hasNext()) { 1382 ExpVector e = ExpVector.create(eviter.next()); 1383 powers.add(0, e); // add new ev at beginning 1384 //System.out.println("new e = " + e); 1385 //System.out.println("powers = " + powers); 1386 if (coeffiter.size() == 1) { // shorten frist iterator by one element 1387 coeffiter.add(coeffiter.get(0)); 1388 Iterable<C> it = coeffiter.get(0); 1389 List<C> elms = new ArrayList<C>(); 1390 for (C elm : it) { 1391 elms.add(elm); 1392 } 1393 elms.remove(0); 1394 coeffiter.set(0, elms); 1395 } else { 1396 coeffiter.add(coeffiter.get(1)); 1397 } 1398 CartesianProduct<C> tuples = new CartesianProduct<C>(coeffiter); 1399 itercoeff = tuples.iterator(); 1400 } 1401 List<C> coeffs = itercoeff.next(); 1402 // while ( coeffs.get(0).isZERO() ) { 1403 // System.out.println(" skip zero "); 1404 // coeffs = itercoeff.next(); // skip tuples with zero in first component 1405 // } 1406 //System.out.println("coeffs = " + coeffs); 1407 GenPolynomial<C> pol = ring.getZERO().copy(); 1408 int i = 0; 1409 for (ExpVector f : powers) { 1410 C c = coeffs.get(i++); 1411 if (c.isZERO()) { 1412 continue; 1413 } 1414 if (pol.val.get(f) != null) { 1415 System.out.println("error f in pol = " + f + ", " + pol.getMap().get(f)); 1416 throw new RuntimeException("error in iterator"); 1417 } 1418 pol.doPutToMap(f, c); 1419 } 1420 current = pol; 1421 return res; 1422 } 1423 1424 1425 /** 1426 * Remove an element if allowed. 1427 */ 1428 public void remove() { 1429 throw new UnsupportedOperationException("cannnot remove elements"); 1430 } 1431} 1432 1433 1434/** 1435 * Polynomial monomial iterator. 1436 * @author Heinz Kredel 1437 */ 1438class GenPolynomialMonomialIterator<C extends RingElem<C>> implements Iterator<GenPolynomial<C>> { 1439 1440 1441 /** 1442 * data structure. 1443 */ 1444 final GenPolynomialRing<C> ring; 1445 1446 1447 final Iterator<List> iter; 1448 1449 1450 GenPolynomial<C> current; 1451 1452 1453 /** 1454 * Polynomial iterator constructor. 1455 */ 1456 @SuppressWarnings("unchecked") 1457 public GenPolynomialMonomialIterator(GenPolynomialRing<C> fac) { 1458 ring = fac; 1459 LongIterable li = new LongIterable(); 1460 li.setNonNegativeIterator(); 1461 List<Iterable<Long>> tlist = new ArrayList<Iterable<Long>>(ring.nvar); 1462 for (int i = 0; i < ring.nvar; i++) { 1463 tlist.add(li); 1464 } 1465 CartesianProductInfinite<Long> ei = new CartesianProductInfinite<Long>(tlist); 1466 //Iterator<List<Long>> eviter = ei.iterator(); 1467 1468 RingFactory<C> cf = ring.coFac; 1469 Iterable<C> coeffiter; 1470 if (cf instanceof Iterable && !cf.isFinite()) { 1471 Iterable<C> cfi = (Iterable<C>) cf; 1472 coeffiter = cfi; 1473 } else { 1474 throw new IllegalArgumentException("only for infinite iterable coefficients implemented"); 1475 } 1476 1477 // Cantor iterator for exponents and coeffcients 1478 List<Iterable> eci = new ArrayList<Iterable>(2); // no type parameter 1479 eci.add(ei); 1480 eci.add(coeffiter); 1481 CartesianProductInfinite ecp = new CartesianProductInfinite(eci); 1482 iter = ecp.iterator(); 1483 1484 List ec = iter.next(); 1485 List<Long> ecl = (List<Long>) ec.get(0); 1486 C c = (C) ec.get(1); // zero 1487 ExpVector e = ExpVector.create(ecl); 1488 //System.out.println("exp = " + e); 1489 //System.out.println("coeffs = " + c); 1490 current = new GenPolynomial<C>(ring, c, e); 1491 } 1492 1493 1494 /** 1495 * Test for availability of a next element. 1496 * @return true if the iteration has more elements, else false. 1497 */ 1498 public boolean hasNext() { 1499 return true; 1500 } 1501 1502 1503 /** 1504 * Get next polynomial. 1505 * @return next polynomial. 1506 */ 1507 @SuppressWarnings("unchecked") 1508 public synchronized GenPolynomial<C> next() { 1509 GenPolynomial<C> res = current; 1510 1511 List ec = iter.next(); 1512 C c = (C) ec.get(1); 1513 while (c.isZERO()) { // zero already done in first next 1514 ec = iter.next(); 1515 c = (C) ec.get(1); 1516 } 1517 List<Long> ecl = (List<Long>) ec.get(0); 1518 ExpVector e = ExpVector.create(ecl); 1519 //System.out.println("exp = " + e); 1520 //System.out.println("coeffs = " + c); 1521 current = new GenPolynomial<C>(ring, c, e); 1522 1523 return res; 1524 } 1525 1526 1527 /** 1528 * Remove an element if allowed. 1529 */ 1530 public void remove() { 1531 throw new UnsupportedOperationException("cannnot remove elements"); 1532 } 1533}