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