001/* 002 * $Id: GenPolynomialRing.java 6004 2020-03-22 12:49:53Z 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; 019import java.util.concurrent.atomic.AtomicLong; 020 021import org.apache.logging.log4j.Logger; 022import org.apache.logging.log4j.LogManager; 023 024import edu.jas.arith.ModIntegerRing; 025import edu.jas.kern.PreemptStatus; 026import edu.jas.kern.PrettyPrint; 027import edu.jas.kern.Scripting; 028import edu.jas.structure.RingElem; 029import edu.jas.structure.RingFactory; 030import edu.jas.util.CartesianProduct; 031import edu.jas.util.CartesianProductInfinite; 032import edu.jas.util.LongIterable; 033 034 035/** 036 * GenPolynomialRing generic polynomial factory. It implements 037 * RingFactory for n-variate ordered polynomials over coefficients 038 * C. The variables commute with each other and with the 039 * coefficients. For non-commutative coefficients some care is taken 040 * to respect the multiplication order. 041 * 042 * Almost immutable object, except variable names. 043 * @param <C> coefficient type 044 * @author Heinz Kredel 045 */ 046 047public class GenPolynomialRing<C extends RingElem<C>> implements RingFactory<GenPolynomial<C>>, 048 Iterable<GenPolynomial<C>> { 049 050 051 /** 052 * The factory for the coefficients. 053 */ 054 public final RingFactory<C> coFac; 055 056 057 /** 058 * The number of variables. 059 */ 060 public final int nvar; 061 062 063 /** 064 * The term order. 065 */ 066 public final TermOrder tord; 067 068 069 /** 070 * True for partially reversed variables. 071 */ 072 protected boolean partial; 073 074 075 /** 076 * The names of the variables. This value can be modified. 077 */ 078 protected String[] vars; 079 080 081 /** 082 * Counter to distinguish new variables. 083 */ 084 private static AtomicLong varCounter = new AtomicLong(0L); 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 res = "AN[ (" + an.ring.varsToString() + ") (" + an.toString() + ") ]"; 279 } 280 if (coFac instanceof GenPolynomialRing) { 281 GenPolynomialRing rf = (GenPolynomialRing) coFac; 282 //String[] v = rf.vars; 283 //RingFactory cf = rf.coFac; 284 //String cs; 285 //if (cf instanceof ModIntegerRing) { 286 // cs = cf.toString(); 287 //} else { 288 // cs = " " + cf.getClass().getSimpleName(); 289 //} 290 //res = "IntFunc" + "{" + cs + "( " + rf.varsToString() + " )" + " } "; 291 res = "IntFunc" + "( " + rf.toString() + " )"; 292 } 293 if (((Object) coFac) instanceof ModIntegerRing) { 294 ModIntegerRing mn = (ModIntegerRing) ((Object) coFac); 295 res = "Mod " + mn.getModul() + " "; 296 } 297 if (res == null) { 298 res = coFac.toString(); 299 if (res.matches("[0-9].*")) { 300 res = scf; 301 } 302 } 303 res += "( " + varsToString() + " ) " + tord.toString() + " "; 304 } else { 305 res = this.getClass().getSimpleName() + "[ " + coFac.toString() + " "; 306 if (coFac instanceof AlgebraicNumberRing) { 307 AlgebraicNumberRing an = (AlgebraicNumberRing) coFac; 308 res = "AN[ (" + an.ring.varsToString() + ") (" + an.modul + ") ]"; 309 } 310 if (coFac instanceof GenPolynomialRing) { 311 GenPolynomialRing rf = (GenPolynomialRing) coFac; 312 //String[] v = rf.vars; 313 //RingFactory cf = rf.coFac; 314 //String cs; 315 //if (cf instanceof ModIntegerRing) { 316 // cs = cf.toString(); 317 //} else { 318 // cs = " " + cf.getClass().getSimpleName(); 319 //} 320 //res = "IntFunc{ " + cs + "( " + rf.varsToString() + " )" + " } "; 321 res = "IntFunc" + "( " + rf.toString() + " )"; 322 } 323 if (((Object) coFac) instanceof ModIntegerRing) { 324 ModIntegerRing mn = (ModIntegerRing) ((Object) coFac); 325 res = "Mod " + mn.getModul() + " "; 326 } 327 //res += ", " + nvar + ", " + tord.toString() + ", " + varsToString() + ", " + partial + " ]"; 328 res += "( " + varsToString() + " ) " + tord.toString() + " ]"; 329 } 330 return res; 331 } 332 333 334 /** 335 * Get a scripting compatible string representation. 336 * @return script compatible representation for this Element. 337 * @see edu.jas.structure.Element#toScript() 338 */ 339 @Override 340 public String toScript() { 341 StringBuffer s = new StringBuffer(); 342 switch (Scripting.getLang()) { 343 case Ruby: 344 s.append("PolyRing.new("); 345 break; 346 case Python: 347 default: 348 s.append("PolyRing("); 349 } 350 if (coFac instanceof RingElem) { 351 s.append(((RingElem<C>) coFac).toScriptFactory()); 352 } else { 353 s.append(coFac.toScript().trim()); 354 } 355 s.append(",\"" + varsToString() + "\""); 356 String to = tord.toScript(); 357 s.append("," + to); 358 s.append(")"); 359 return s.toString(); 360 } 361 362 363 /** 364 * Get a scripting compatible string representation of an ExpVector of this 365 * ring. 366 * @param e exponent vector 367 * @return script compatible representation for the ExpVector. 368 */ 369 public String toScript(ExpVector e) { 370 if (e == null) { 371 return "null"; 372 } 373 if (vars != null) { 374 return e.toScript(vars); 375 } 376 return e.toScript(); 377 } 378 379 380 /** 381 * Comparison with any other object. 382 * @see java.lang.Object#equals(java.lang.Object) 383 */ 384 @Override 385 @SuppressWarnings("unchecked") 386 public boolean equals(Object other) { 387 if (other == null) { 388 return false; 389 } 390 if (!(other instanceof GenPolynomialRing)) { 391 return false; 392 } 393 GenPolynomialRing<C> oring = (GenPolynomialRing<C>) other; 394 if (nvar != oring.nvar) { 395 return false; 396 } 397 if (!coFac.equals(oring.coFac)) { 398 return false; 399 } 400 if (!tord.equals(oring.tord)) { 401 return false; 402 } 403 // same variables required ? 404 if (!Arrays.deepEquals(vars, oring.vars)) { 405 return false; 406 } 407 return true; 408 } 409 410 411 /** 412 * Hash code for this polynomial ring. 413 * @see java.lang.Object#hashCode() 414 */ 415 @Override 416 public int hashCode() { 417 int h; 418 h = (nvar << 27); 419 h += (coFac.hashCode() << 11); 420 h += tord.hashCode(); 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("v not matching number of variables: " + Arrays.toString(v) 450 + ", 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 if (vn == null || vars == null) { 1015 throw new IllegalArgumentException("vn and vars may not be null"); 1016 } 1017 int i = vn.length; 1018 String[] v = new String[vars.length + i]; 1019 for (int k = 0; k < vn.length; k++) { 1020 v[k] = vn[k]; 1021 } 1022 for (int k = 0; k < vars.length; k++) { 1023 v[vn.length + k] = vars[k]; 1024 } 1025 TermOrder to = tord.extendLower(nvar, i); 1026 GenPolynomialRing<C> pfac = new GenPolynomialRing<C>(coFac, nvar + i, to, v); 1027 return pfac; 1028 } 1029 1030 1031 /** 1032 * Contract variables. Used e.g. in module embedding. Contract number of 1033 * variables by i. 1034 * @param i number of variables to remove. 1035 * @return contracted polynomial ring factory. 1036 */ 1037 public GenPolynomialRing<C> contract(int i) { 1038 String[] v = null; 1039 if (vars != null) { 1040 v = new String[vars.length - i]; 1041 for (int j = 0; j < vars.length - i; j++) { 1042 v[j] = vars[j]; 1043 } 1044 } 1045 TermOrder to = tord.contract(i, nvar - i); 1046 GenPolynomialRing<C> pfac = new GenPolynomialRing<C>(coFac, nvar - i, to, v); 1047 return pfac; 1048 } 1049 1050 1051 /** 1052 * Recursive representation as polynomial with i main variables. 1053 * @param i number of main variables. 1054 * @return recursive polynomial ring factory. 1055 */ 1056 public GenPolynomialRing<GenPolynomial<C>> recursive(int i) { 1057 if (i <= 0 || i >= nvar) { 1058 throw new IllegalArgumentException("wrong: 0 < " + i + " < " + nvar); 1059 } 1060 GenPolynomialRing<C> cfac = contract(i); 1061 String[] v = null; 1062 if (vars != null) { 1063 v = new String[i]; 1064 int k = 0; 1065 for (int j = nvar - i; j < nvar; j++) { 1066 v[k++] = vars[j]; 1067 } 1068 } 1069 TermOrder to = tord.contract(0, i); // ?? 1070 GenPolynomialRing<GenPolynomial<C>> pfac = new GenPolynomialRing<GenPolynomial<C>>(cfac, i, to, v); 1071 return pfac; 1072 } 1073 1074 1075 /** 1076 * Distributive representation as polynomial with all main variables. 1077 * @return distributive polynomial ring factory. 1078 */ 1079 @SuppressWarnings("unchecked") 1080 public GenPolynomialRing<C> distribute() { 1081 if (!(coFac instanceof GenPolynomialRing)) { 1082 return this; 1083 } 1084 RingFactory cf = coFac; 1085 RingFactory<GenPolynomial<C>> cfp = (RingFactory<GenPolynomial<C>>) cf; 1086 GenPolynomialRing cr = (GenPolynomialRing) cfp; 1087 GenPolynomialRing<C> pfac; 1088 if (cr.vars != null) { 1089 pfac = extend(cr.vars); 1090 } else { 1091 pfac = extend(cr.nvar); 1092 } 1093 return pfac; 1094 } 1095 1096 1097 /** 1098 * Reverse variables. Used e.g. in opposite rings. 1099 * @return polynomial ring factory with reversed variables. 1100 */ 1101 public GenPolynomialRing<C> reverse() { 1102 return reverse(false); 1103 } 1104 1105 1106 /** 1107 * Reverse variables. Used e.g. in opposite rings. 1108 * @param partial true for partialy reversed term orders. 1109 * @return polynomial ring factory with reversed variables. 1110 */ 1111 public GenPolynomialRing<C> reverse(boolean partial) { 1112 String[] v = null; 1113 if (vars != null) { // vars are not inversed 1114 v = new String[vars.length]; 1115 int k = tord.getSplit(); 1116 if (partial && k < vars.length) { 1117 // copy upper 1118 for (int j = 0; j < k; j++) { 1119 //v[vars.length - k + j] = vars[vars.length - 1 - j]; // reverse upper 1120 v[vars.length - k + j] = vars[vars.length - k + j]; 1121 } 1122 // reverse lower 1123 for (int j = 0; j < vars.length - k; j++) { 1124 //v[j] = vars[j]; // copy upper 1125 v[j] = vars[vars.length - k - j - 1]; 1126 } 1127 } else { 1128 for (int j = 0; j < vars.length; j++) { 1129 v[j] = vars[vars.length - 1 - j]; 1130 } 1131 } 1132 //System.out.println("vars = " + Arrays.toString(vars)); 1133 //System.out.println("v = " + Arrays.toString(v)); 1134 } 1135 TermOrder to = tord.reverse(partial); 1136 GenPolynomialRing<C> pfac = new GenPolynomialRing<C>(coFac, nvar, to, v); 1137 pfac.partial = partial; 1138 return pfac; 1139 } 1140 1141 1142 /** 1143 * Get PolynomialComparator. 1144 * @return polynomial comparator. 1145 */ 1146 public PolynomialComparator<C> getComparator() { 1147 return new PolynomialComparator<C>(tord, false); 1148 } 1149 1150 1151 /** 1152 * Get PolynomialComparator. 1153 * @param rev for reverse comparator. 1154 * @return polynomial comparator. 1155 */ 1156 public PolynomialComparator<C> getComparator(boolean rev) { 1157 return new PolynomialComparator<C>(tord, rev); 1158 } 1159 1160 1161 /** 1162 * New variable names. Generate new names for variables, 1163 * @param prefix name prefix. 1164 * @param n number of variables. 1165 * @return new variable names. 1166 */ 1167 public static String[] newVars(String prefix, int n) { 1168 String[] vars = new String[n]; 1169 for (int i = 0; i < n; i++) { 1170 long m = varCounter.getAndIncrement(); 1171 vars[i] = prefix + m; 1172 } 1173 return vars; 1174 } 1175 1176 1177 /** 1178 * New variable names. Generate new names for variables, 1179 * @param prefix name prefix. 1180 * @return new variable names. 1181 */ 1182 public String[] newVars(String prefix) { 1183 return newVars(prefix, nvar); 1184 } 1185 1186 1187 /** 1188 * New variable names. Generate new names for variables, 1189 * @param n number of variables. 1190 * @return new variable names. 1191 */ 1192 public static String[] newVars(int n) { 1193 return newVars("x", n); 1194 } 1195 1196 1197 /** 1198 * New variable names. Generate new names for variables, 1199 * @return new variable names. 1200 */ 1201 public String[] newVars() { 1202 return newVars(nvar); 1203 } 1204 1205 1206 /* 1207 * Add variable names. 1208 * @param vars variable names to be recorded. 1209 public static void addVars(String[] vars) { 1210 if (vars == null) { 1211 return; 1212 } 1213 // synchronized (knownVars) { 1214 // for (int i = 0; i < vars.length; i++) { 1215 // knownVars.add(vars[i]); // eventualy names 'overwritten' 1216 // } 1217 // } 1218 } 1219 */ 1220 1221 1222 /** 1223 * Permute variable names. 1224 * @param vars variable names. 1225 * @param P permutation. 1226 * @return P(vars). 1227 */ 1228 public static String[] permuteVars(List<Integer> P, String[] vars) { 1229 if (vars == null || vars.length <= 1) { 1230 return vars; 1231 } 1232 String[] b = new String[vars.length]; 1233 int j = 0; 1234 for (Integer i : P) { 1235 b[j++] = vars[i]; 1236 } 1237 return b; 1238 } 1239 1240 1241 /** 1242 * Permutation of polynomial ring variables. 1243 * @param P permutation. 1244 * @return P(this). 1245 */ 1246 public GenPolynomialRing<C> permutation(List<Integer> P) { 1247 if (nvar <= 1) { 1248 return this; 1249 } 1250 TermOrder tp = tord.permutation(P); 1251 if (vars == null) { 1252 return new GenPolynomialRing<C>(coFac, nvar, tp); 1253 } 1254 String[] v1 = new String[vars.length]; 1255 for (int i = 0; i < v1.length; i++) { 1256 v1[i] = vars[v1.length - 1 - i]; 1257 } 1258 String[] vp = permuteVars(P, v1); 1259 String[] v2 = new String[vp.length]; 1260 for (int i = 0; i < vp.length; i++) { 1261 v2[i] = vp[vp.length - 1 - i]; 1262 } 1263 return new GenPolynomialRing<C>(coFac, nvar, tp, v2); 1264 } 1265 1266 1267 /** 1268 * Get a GenPolynomial iterator. 1269 * @return an iterator over all polynomials. 1270 */ 1271 public Iterator<GenPolynomial<C>> iterator() { 1272 if (coFac.isFinite()) { 1273 return new GenPolynomialIterator<C>(this); 1274 } 1275 logger.warn("ring of coefficients " + coFac 1276 + " is infinite, constructing iterator only over monomials"); 1277 return new GenPolynomialMonomialIterator<C>(this); 1278 //throw new IllegalArgumentException("only for finite iterable coefficients implemented"); 1279 } 1280 1281} 1282 1283 1284/** 1285 * Polynomial iterator. 1286 * @author Heinz Kredel 1287 */ 1288class GenPolynomialIterator<C extends RingElem<C>> implements Iterator<GenPolynomial<C>> { 1289 1290 1291 /** 1292 * data structure. 1293 */ 1294 final GenPolynomialRing<C> ring; 1295 1296 1297 final Iterator<List<Long>> eviter; 1298 1299 1300 final List<ExpVector> powers; 1301 1302 1303 final List<Iterable<C>> coeffiter; 1304 1305 1306 Iterator<List<C>> itercoeff; 1307 1308 1309 GenPolynomial<C> current; 1310 1311 1312 /** 1313 * Polynomial iterator constructor. 1314 */ 1315 @SuppressWarnings("unchecked") 1316 public GenPolynomialIterator(GenPolynomialRing<C> fac) { 1317 ring = fac; 1318 LongIterable li = new LongIterable(); 1319 li.setNonNegativeIterator(); 1320 List<Iterable<Long>> tlist = new ArrayList<Iterable<Long>>(ring.nvar); 1321 for (int i = 0; i < ring.nvar; i++) { 1322 tlist.add(li); 1323 } 1324 CartesianProductInfinite<Long> ei = new CartesianProductInfinite<Long>(tlist); 1325 eviter = ei.iterator(); 1326 RingFactory<C> cf = ring.coFac; 1327 coeffiter = new ArrayList<Iterable<C>>(); 1328 if (cf instanceof Iterable && cf.isFinite()) { 1329 Iterable<C> cfi = (Iterable<C>) cf; 1330 coeffiter.add(cfi); 1331 } else { 1332 throw new IllegalArgumentException("only for finite iterable coefficients implemented"); 1333 } 1334 CartesianProduct<C> tuples = new CartesianProduct<C>(coeffiter); 1335 itercoeff = tuples.iterator(); 1336 powers = new ArrayList<ExpVector>(); 1337 ExpVector e = ExpVector.create(eviter.next()); 1338 powers.add(e); 1339 //System.out.println("new e = " + e); 1340 //System.out.println("powers = " + powers); 1341 List<C> c = itercoeff.next(); 1342 //System.out.println("coeffs = " + c); 1343 current = new GenPolynomial<C>(ring, c.get(0), e); 1344 } 1345 1346 1347 /** 1348 * Test for availability of a next element. 1349 * @return true if the iteration has more elements, else false. 1350 */ 1351 public boolean hasNext() { 1352 return true; 1353 } 1354 1355 1356 /** 1357 * Get next polynomial. 1358 * @return next polynomial. 1359 */ 1360 public synchronized GenPolynomial<C> next() { 1361 GenPolynomial<C> res = current; 1362 if (!itercoeff.hasNext()) { 1363 ExpVector e = ExpVector.create(eviter.next()); 1364 powers.add(0, e); // add new ev at beginning 1365 //System.out.println("new e = " + e); 1366 //System.out.println("powers = " + powers); 1367 if (coeffiter.size() == 1) { // shorten frist iterator by one element 1368 coeffiter.add(coeffiter.get(0)); 1369 Iterable<C> it = coeffiter.get(0); 1370 List<C> elms = new ArrayList<C>(); 1371 for (C elm : it) { 1372 elms.add(elm); 1373 } 1374 elms.remove(0); 1375 coeffiter.set(0, elms); 1376 } else { 1377 coeffiter.add(coeffiter.get(1)); 1378 } 1379 CartesianProduct<C> tuples = new CartesianProduct<C>(coeffiter); 1380 itercoeff = tuples.iterator(); 1381 } 1382 List<C> coeffs = itercoeff.next(); 1383 // while ( coeffs.get(0).isZERO() ) { 1384 // System.out.println(" skip zero "); 1385 // coeffs = itercoeff.next(); // skip tuples with zero in first component 1386 // } 1387 //System.out.println("coeffs = " + coeffs); 1388 GenPolynomial<C> pol = ring.getZERO().copy(); 1389 int i = 0; 1390 for (ExpVector f : powers) { 1391 C c = coeffs.get(i++); 1392 if (c.isZERO()) { 1393 continue; 1394 } 1395 if (pol.val.get(f) != null) { 1396 System.out.println("error f in pol = " + f + ", " + pol.getMap().get(f)); 1397 throw new RuntimeException("error in iterator"); 1398 } 1399 pol.doPutToMap(f, c); 1400 } 1401 current = pol; 1402 return res; 1403 } 1404 1405 1406 /** 1407 * Remove an element if allowed. 1408 */ 1409 public void remove() { 1410 throw new UnsupportedOperationException("cannnot remove elements"); 1411 } 1412} 1413 1414 1415/** 1416 * Polynomial monomial iterator. 1417 * @author Heinz Kredel 1418 */ 1419class GenPolynomialMonomialIterator<C extends RingElem<C>> implements Iterator<GenPolynomial<C>> { 1420 1421 1422 /** 1423 * data structure. 1424 */ 1425 final GenPolynomialRing<C> ring; 1426 1427 1428 final Iterator<List> iter; 1429 1430 1431 GenPolynomial<C> current; 1432 1433 1434 /** 1435 * Polynomial iterator constructor. 1436 */ 1437 @SuppressWarnings("unchecked") 1438 public GenPolynomialMonomialIterator(GenPolynomialRing<C> fac) { 1439 ring = fac; 1440 LongIterable li = new LongIterable(); 1441 li.setNonNegativeIterator(); 1442 List<Iterable<Long>> tlist = new ArrayList<Iterable<Long>>(ring.nvar); 1443 for (int i = 0; i < ring.nvar; i++) { 1444 tlist.add(li); 1445 } 1446 CartesianProductInfinite<Long> ei = new CartesianProductInfinite<Long>(tlist); 1447 //Iterator<List<Long>> eviter = ei.iterator(); 1448 1449 RingFactory<C> cf = ring.coFac; 1450 Iterable<C> coeffiter; 1451 if (cf instanceof Iterable && !cf.isFinite()) { 1452 Iterable<C> cfi = (Iterable<C>) cf; 1453 coeffiter = cfi; 1454 } else { 1455 throw new IllegalArgumentException("only for infinite iterable coefficients implemented"); 1456 } 1457 1458 // Cantor iterator for exponents and coeffcients 1459 List<Iterable> eci = new ArrayList<Iterable>(2); // no type parameter 1460 eci.add(ei); 1461 eci.add(coeffiter); 1462 CartesianProductInfinite ecp = new CartesianProductInfinite(eci); 1463 iter = ecp.iterator(); 1464 1465 List ec = iter.next(); 1466 List<Long> ecl = (List<Long>) ec.get(0); 1467 C c = (C) ec.get(1); // zero 1468 ExpVector e = ExpVector.create(ecl); 1469 //System.out.println("exp = " + e); 1470 //System.out.println("coeffs = " + c); 1471 current = new GenPolynomial<C>(ring, c, e); 1472 } 1473 1474 1475 /** 1476 * Test for availability of a next element. 1477 * @return true if the iteration has more elements, else false. 1478 */ 1479 public boolean hasNext() { 1480 return true; 1481 } 1482 1483 1484 /** 1485 * Get next polynomial. 1486 * @return next polynomial. 1487 */ 1488 @SuppressWarnings("unchecked") 1489 public synchronized GenPolynomial<C> next() { 1490 GenPolynomial<C> res = current; 1491 1492 List ec = iter.next(); 1493 C c = (C) ec.get(1); 1494 while (c.isZERO()) { // zero already done in first next 1495 ec = iter.next(); 1496 c = (C) ec.get(1); 1497 } 1498 List<Long> ecl = (List<Long>) ec.get(0); 1499 ExpVector e = ExpVector.create(ecl); 1500 //System.out.println("exp = " + e); 1501 //System.out.println("coeffs = " + c); 1502 current = new GenPolynomial<C>(ring, c, e); 1503 1504 return res; 1505 } 1506 1507 1508 /** 1509 * Remove an element if allowed. 1510 */ 1511 public void remove() { 1512 throw new UnsupportedOperationException("cannnot remove elements"); 1513 } 1514}