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.SortedMap; 018import java.util.concurrent.atomic.AtomicLong; 019 020import org.apache.logging.log4j.LogManager; 021import org.apache.logging.log4j.Logger; 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; 032import edu.jas.vector.GenVector; 033 034 035/** 036 * GenPolynomialRing generic polynomial factory. It implements RingFactory for 037 * n-variate ordered polynomials over coefficients C. The variables commute with 038 * each other and with the coefficients. For non-commutative coefficients some 039 * care is taken 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>> 047 implements RingFactory<GenPolynomial<C>>, 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 * Counter to distinguish new variables. 082 */ 083 private static AtomicLong varCounter = new AtomicLong(0L); 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 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() << 9); 421 h += Arrays.hashCode(vars); 422 //System.out.println("GenPolynomialRing.hashCode: " + h); 423 return h; 424 } 425 426 427 /** 428 * Get the number of polynomial creations. 429 * @return creations. 430 */ 431 public int getCreations() { 432 return creations; 433 } 434 435 436 /** 437 * Get the variable names. 438 * @return vars. 439 */ 440 public String[] getVars() { 441 return Arrays.copyOf(vars, vars.length); // > Java-5 442 } 443 444 445 /** 446 * Set the variable names. 447 * @return old vars. 448 */ 449 public String[] setVars(String[] v) { 450 if (v.length != nvar) { 451 throw new IllegalArgumentException( 452 "v not matching number of variables: " + Arrays.toString(v) + ", nvar " + nvar); 453 } 454 String[] t = vars; 455 vars = Arrays.copyOf(v, v.length); // > Java-5 456 return t; 457 } 458 459 460 /** 461 * Get a String representation of the variable names. 462 * @return names seperated by commas. 463 */ 464 public String varsToString() { 465 if (vars == null) { 466 return "#" + nvar; 467 } 468 //return Arrays.toString(vars); 469 return ExpVector.varsToString(vars); 470 } 471 472 473 /** 474 * Get the zero element from the coefficients. 475 * @return 0 as C. 476 */ 477 public C getZEROCoefficient() { 478 return coFac.getZERO(); 479 } 480 481 482 /** 483 * Get the one element from the coefficients. 484 * @return 1 as C. 485 */ 486 public C getONECoefficient() { 487 return coFac.getONE(); 488 } 489 490 491 /** 492 * Get the zero element. 493 * @return 0 as GenPolynomial<C>. 494 */ 495 public GenPolynomial<C> getZERO() { 496 return ZERO; 497 } 498 499 500 /** 501 * Get the one element. 502 * @return 1 as GenPolynomial<C>. 503 */ 504 public GenPolynomial<C> getONE() { 505 return ONE; 506 } 507 508 509 /** 510 * Query if this ring is commutative. 511 * @return true if this ring is commutative, else false. 512 */ 513 public boolean isCommutative() { 514 return coFac.isCommutative(); 515 } 516 517 518 /** 519 * Query if this ring is associative. 520 * @return true if this ring is associative, else false. 521 */ 522 public boolean isAssociative() { 523 return coFac.isAssociative(); 524 } 525 526 527 /** 528 * Query if this ring is a field. 529 * @return false. 530 */ 531 public boolean isField() { 532 if (isField > 0) { 533 return true; 534 } 535 if (isField == 0) { 536 return false; 537 } 538 if (coFac.isField() && nvar == 0) { 539 isField = 1; 540 return true; 541 } 542 isField = 0; 543 return false; 544 } 545 546 547 /** 548 * Characteristic of this ring. 549 * @return characteristic of this ring. 550 */ 551 public java.math.BigInteger characteristic() { 552 return coFac.characteristic(); 553 } 554 555 556 /** 557 * Get a (constant) GenPolynomial<C> element from a coefficient value. 558 * @param a coefficient. 559 * @return a GenPolynomial<C>. 560 */ 561 public GenPolynomial<C> valueOf(C a) { 562 return new GenPolynomial<C>(this, a); 563 } 564 565 566 /** 567 * Get a GenPolynomial<C> element from an exponent vector. 568 * @param e exponent vector. 569 * @return a GenPolynomial<C>. 570 */ 571 public GenPolynomial<C> valueOf(ExpVector e) { 572 if (e == null) { 573 return getZERO(); 574 } 575 return new GenPolynomial<C>(this, coFac.getONE(), e); 576 } 577 578 579 /** 580 * Get a GenPolynomial<C> element from a list of exponent vectors. 581 * @param E list of exponent vector. 582 * @return a GenPolynomial<C>. 583 */ 584 public List<GenPolynomial<C>> valueOf(Iterable<ExpVector> E) { 585 if (E == null) { 586 return null; 587 } 588 List<GenPolynomial<C>> P = new ArrayList<GenPolynomial<C>>(); //E.size()); 589 for (ExpVector e : E) { 590 GenPolynomial<C> p = valueOf(e); 591 P.add(p); 592 } 593 return P; 594 } 595 596 597 /** 598 * Get a GenPolynomial<C> element from a coeffcient and an exponent 599 * vector. 600 * @param a coefficient. 601 * @param e exponent vector. 602 * @return a GenPolynomial<C>. 603 */ 604 public GenPolynomial<C> valueOf(C a, ExpVector e) { 605 return new GenPolynomial<C>(this, a, e); 606 } 607 608 609 /** 610 * Get a GenPolynomial<C> element from a monomial. 611 * @param m monomial. 612 * @return a GenPolynomial<C>. 613 */ 614 public GenPolynomial<C> valueOf(Monomial<C> m) { 615 return new GenPolynomial<C>(this, m.c, m.e); 616 } 617 618 619 /** 620 * Get a (constant) GenPolynomial<C> element from a long value. 621 * @param a long. 622 * @return a GenPolynomial<C>. 623 */ 624 public GenPolynomial<C> fromInteger(long a) { 625 return new GenPolynomial<C>(this, coFac.fromInteger(a), evzero); 626 } 627 628 629 /** 630 * Get a (constant) GenPolynomial<C> element from a BigInteger value. 631 * @param a BigInteger. 632 * @return a GenPolynomial<C>. 633 */ 634 public GenPolynomial<C> fromInteger(BigInteger a) { 635 return new GenPolynomial<C>(this, coFac.fromInteger(a), evzero); 636 } 637 638 639 /** 640 * Get a GenPolynomial<C> from a GenVector<C>. 641 * @param a GenVector<C>. 642 * @return a GenPolynomial<C>. 643 */ 644 public GenPolynomial<C> fromVector(GenVector<C> a) { 645 if (a == null || a.isZERO()) { 646 return ZERO; 647 } 648 if (nvar != 1) { 649 throw new IllegalArgumentException("no univariate polynomial ring"); 650 } 651 GenPolynomial<C> ret = copy(ZERO); 652 SortedMap<ExpVector, C> tm = ret.val; 653 long i = -1; 654 for (C m : a.val) { 655 i++; 656 if (m.isZERO()) { 657 continue; 658 } 659 ExpVector e = ExpVector.create(1, 0, i); 660 tm.put(e, m); 661 } 662 return ret; 663 } 664 665 666 /** 667 * Random polynomial. Generates a random polynomial with k = 5, l = n, d = 668 * (nvar == 1) ? n : 3, q = (nvar == 1) ? 0.7 : 0.3. 669 * @param n number of terms. 670 * @return a random polynomial. 671 */ 672 public GenPolynomial<C> random(int n) { 673 return random(n, random); 674 } 675 676 677 /** 678 * Random polynomial. Generates a random polynomial with k = 5, l = n, d = 679 * n, q = (nvar == 1) ? 0.5 : 0.3. 680 * @param n number of terms. 681 * @param rnd is a source for random bits. 682 * @return a random polynomial. 683 */ 684 public GenPolynomial<C> random(int n, Random rnd) { 685 if (nvar == 1) { 686 return random(3, n, n, 0.5f, rnd); 687 } 688 return random(3, n, n, 0.3f, rnd); 689 } 690 691 692 /** 693 * Generate a random polynomial. 694 * @param k bitsize of random coefficients. 695 * @param l number of terms. 696 * @param d maximal degree in each variable. 697 * @param q density of nozero exponents. 698 * @return a random polynomial. 699 */ 700 public GenPolynomial<C> random(int k, int l, int d, float q) { 701 return random(k, l, d, q, random); 702 } 703 704 705 /** 706 * Generate a random polynomial. 707 * @param k bitsize of random coefficients. 708 * @param l number of terms. 709 * @param d maximal degree in each variable. 710 * @param q density of nozero exponents. 711 * @param rnd is a source for random bits. 712 * @return a random polynomial. 713 */ 714 public GenPolynomial<C> random(int k, int l, int d, float q, Random rnd) { 715 GenPolynomial<C> r = getZERO(); //.clone() or copy( ZERO ); 716 ExpVector e; 717 C a; 718 // add l random coeffs and exponents 719 for (int i = 0; i < l; i++) { 720 e = ExpVector.random(nvar, d, q, rnd); 721 a = coFac.random(k, rnd); 722 r = r.sum(a, e); // somewhat inefficient but clean 723 //System.out.println("e = " + e + " a = " + a); 724 } 725 // System.out.println("r = " + r); 726 return r; 727 } 728 729 730 /** 731 * Copy polynomial c. 732 * @param c 733 * @return a copy of c. 734 */ 735 public GenPolynomial<C> copy(GenPolynomial<C> c) { 736 //System.out.println("GP copy = " + this); 737 return new GenPolynomial<C>(this, c.val); 738 } 739 740 741 /** 742 * Copy polynomial list. 743 * @param L polynomial list 744 * @return a copy of L in this ring. 745 */ 746 public List<GenPolynomial<C>> copy(List<GenPolynomial<C>> L) { 747 if (L == null) { 748 return L; 749 } 750 List<GenPolynomial<C>> R = new ArrayList<GenPolynomial<C>>(L.size()); 751 for (GenPolynomial<C> a : L) { 752 R.add(copy(a)); 753 } 754 return R; 755 } 756 757 758 /** 759 * Parse a polynomial with the use of GenPolynomialTokenizer. 760 * @param s String. 761 * @return GenPolynomial from s. 762 */ 763 public GenPolynomial<C> parse(String s) { 764 String val = s; 765 if (!s.contains("|")) { 766 val = val.replace("{", "").replace("}", ""); 767 } 768 return parse(new StringReader(val)); 769 } 770 771 772 /** 773 * Parse a polynomial with the use of GenPolynomialTokenizer. 774 * @param r Reader. 775 * @return next GenPolynomial from r. 776 */ 777 @SuppressWarnings({ "unchecked", "cast" }) 778 public GenPolynomial<C> parse(Reader r) { 779 GenPolynomialTokenizer pt = new GenPolynomialTokenizer(this, r); 780 GenPolynomial<C> p = null; 781 try { 782 p = (GenPolynomial<C>) pt.nextPolynomial(); 783 } catch (IOException e) { 784 logger.error("{} parse {}", e, this); 785 p = ZERO; 786 } 787 return p; 788 } 789 790 791 /** 792 * Generate univariate polynomial in a given variable with given exponent. 793 * @param x the name of a variable. 794 * @return x as univariate polynomial. 795 */ 796 public GenPolynomial<C> univariate(String x) { 797 return univariate(x, 1L); 798 } 799 800 801 /** 802 * Generate univariate polynomial in a given variable with given exponent. 803 * @param x the name of the variable. 804 * @param e the exponent of the variable. 805 * @return x^e as univariate polynomial. 806 */ 807 public GenPolynomial<C> univariate(String x, long e) { 808 if (vars == null) { // should not happen 809 throw new IllegalArgumentException("no variables defined for polynomial ring"); 810 } 811 if (x == null || x.isEmpty()) { 812 throw new IllegalArgumentException("no variable name given"); 813 } 814 int i; 815 for (i = 0; i < vars.length; i++) { 816 if (x.equals(vars[i])) { // use HashMap or TreeMap 817 break; 818 } 819 } 820 if (i >= vars.length) { 821 throw new IllegalArgumentException("variable '" + x + "' not defined in polynomial ring"); 822 } 823 return univariate(0, nvar - i - 1, e); 824 } 825 826 827 /** 828 * Generate univariate polynomial in a given variable. 829 * @param i the index of the variable. 830 * @return X_i as univariate polynomial. 831 */ 832 public GenPolynomial<C> univariate(int i) { 833 return univariate(0, i, 1L); 834 } 835 836 837 /** 838 * Generate univariate polynomial in a given variable with given exponent. 839 * @param i the index of the variable. 840 * @param e the exponent of the variable. 841 * @return X_i^e as univariate polynomial. 842 */ 843 public GenPolynomial<C> univariate(int i, long e) { 844 return univariate(0, i, e); 845 } 846 847 848 /** 849 * Generate univariate polynomial in a given variable with given exponent. 850 * @param modv number of module variables. 851 * @param i the index of the variable. 852 * @param e the exponent of the variable. 853 * @return X_i^e as univariate polynomial. 854 */ 855 public GenPolynomial<C> univariate(int modv, int i, long e) { 856 GenPolynomial<C> p = getZERO(); 857 int r = nvar - modv; 858 if (0 <= i && i < r) { 859 C one = coFac.getONE(); 860 ExpVector f = ExpVector.create(r, i, e); 861 if (modv > 0) { 862 f = f.extend(modv, 0, 0l); 863 } 864 p = p.sum(one, f); 865 } 866 return p; 867 } 868 869 870 /** 871 * Get the generating elements excluding the generators for the coefficient 872 * ring. 873 * @return a list of generating elements for this ring. 874 */ 875 public List<GenPolynomial<C>> getGenerators() { 876 List<? extends GenPolynomial<C>> univs = univariateList(); 877 List<GenPolynomial<C>> gens = new ArrayList<GenPolynomial<C>>(univs.size() + 1); 878 gens.add(getONE()); 879 gens.addAll(univs); 880 return gens; 881 } 882 883 884 /** 885 * Get a list of the generating elements. 886 * @return list of generators for the algebraic structure. 887 * @see edu.jas.structure.ElemFactory#generators() 888 */ 889 public List<GenPolynomial<C>> generators() { 890 List<? extends C> cogens = coFac.generators(); 891 List<? extends GenPolynomial<C>> univs = univariateList(); 892 List<GenPolynomial<C>> gens = new ArrayList<GenPolynomial<C>>(univs.size() + cogens.size()); 893 for (C c : cogens) { 894 gens.add(getONE().multiply(c)); 895 } 896 gens.addAll(univs); 897 return gens; 898 } 899 900 901 /** 902 * Get a list of the generating elements excluding the module variables. 903 * @param modv number of module variables 904 * @return list of generators for the polynomial ring. 905 */ 906 public List<GenPolynomial<C>> generators(int modv) { 907 List<? extends C> cogens = coFac.generators(); 908 List<? extends GenPolynomial<C>> univs = univariateList(modv); 909 List<GenPolynomial<C>> gens = new ArrayList<GenPolynomial<C>>(univs.size() + cogens.size()); 910 for (C c : cogens) { 911 gens.add(getONE().multiply(c)); 912 } 913 gens.addAll(univs); 914 return gens; 915 } 916 917 918 /** 919 * Is this structure finite or infinite. 920 * @return true if this structure is finite, else false. 921 * @see edu.jas.structure.ElemFactory#isFinite() 922 */ 923 public boolean isFinite() { 924 return (nvar == 0) && coFac.isFinite(); 925 } 926 927 928 /** 929 * Generate list of univariate polynomials in all variables. 930 * @return List(X_1,...,X_n) a list of univariate polynomials. 931 */ 932 public List<? extends GenPolynomial<C>> univariateList() { 933 return univariateList(0, 1L); 934 } 935 936 937 /** 938 * Generate list of univariate polynomials in all variables. 939 * @param modv number of module variables. 940 * @return List(X_1,...,X_n) a list of univariate polynomials. 941 */ 942 public List<? extends GenPolynomial<C>> univariateList(int modv) { 943 return univariateList(modv, 1L); 944 } 945 946 947 /** 948 * Generate list of univariate polynomials in all variables with given 949 * exponent. 950 * @param modv number of module variables. 951 * @param e the exponent of the variables. 952 * @return List(X_1^e,...,X_n^e) a list of univariate polynomials. 953 */ 954 public List<? extends GenPolynomial<C>> univariateList(int modv, long e) { 955 List<GenPolynomial<C>> pols = new ArrayList<GenPolynomial<C>>(nvar); 956 int nm = nvar - modv; 957 for (int i = 0; i < nm; i++) { 958 GenPolynomial<C> p = univariate(modv, nm - 1 - i, e); 959 pols.add(p); 960 } 961 return pols; 962 } 963 964 965 /** 966 * Extend variables. Used e.g. in module embedding. Extend number of 967 * variables by i. 968 * @param i number of variables to extend. 969 * @return extended polynomial ring factory. 970 */ 971 public GenPolynomialRing<C> extend(int i) { 972 return extend(i, false); 973 } 974 975 976 /** 977 * Extend variables. Used e.g. in module embedding. Extend number of 978 * variables by i. 979 * @param i number of variables to extend. 980 * @param top true for TOP term order, false for POT term order. 981 * @return extended polynomial ring factory. 982 */ 983 public GenPolynomialRing<C> extend(int i, boolean top) { 984 // add module variable names 985 String[] v = newVars("e", i); 986 return extend(v, top); 987 } 988 989 990 /** 991 * Extend variables. Used e.g. in module embedding. Extend number of 992 * variables by length(vn). 993 * @param vn names for extended variables. 994 * @return extended polynomial ring factory. 995 */ 996 public GenPolynomialRing<C> extend(String[] vn) { 997 return extend(vn, false); 998 } 999 1000 1001 /** 1002 * Extend variables. Used e.g. in module embedding. Extend number of 1003 * variables by length(vn). 1004 * @param vn names for extended variables. 1005 * @param top true for TOP term order, false for POT term order. 1006 * @return extended polynomial ring factory. 1007 */ 1008 public GenPolynomialRing<C> extend(String[] vn, boolean top) { 1009 if (vn == null || vars == null) { 1010 throw new IllegalArgumentException("vn and vars may not be null"); 1011 } 1012 int i = vn.length; 1013 String[] v = new String[vars.length + i]; 1014 for (int k = 0; k < vars.length; k++) { 1015 v[k] = vars[k]; 1016 } 1017 for (int k = 0; k < vn.length; k++) { 1018 v[vars.length + k] = vn[k]; 1019 } 1020 TermOrder to = tord.extend(nvar, i, top); 1021 GenPolynomialRing<C> pfac = new GenPolynomialRing<C>(coFac, nvar + i, to, v); 1022 return pfac; 1023 } 1024 1025 1026 /** 1027 * Extend lower variables. Extend number of variables by i. 1028 * @param i number of variables to extend. 1029 * @return extended polynomial ring factory. 1030 */ 1031 public GenPolynomialRing<C> extendLower(int i) { 1032 String[] v = newVars("e", i); 1033 return extendLower(v); 1034 } 1035 1036 1037 /** 1038 * Extend lower variables. Extend number of variables by length(vn). 1039 * @param vn names for extended lower variables. 1040 * @return extended polynomial ring factory. 1041 */ 1042 public GenPolynomialRing<C> extendLower(String[] vn) { 1043 return extendLower(vn, false); 1044 } 1045 1046 1047 /** 1048 * Extend lower variables. Extend number of variables by length(vn). 1049 * @param vn names for extended lower variables. 1050 * @param top true for TOP term order, false for POT term order. 1051 * @return extended polynomial ring factory. 1052 */ 1053 public GenPolynomialRing<C> extendLower(String[] vn, boolean top) { 1054 if (vn == null || vars == null) { 1055 throw new IllegalArgumentException("vn and vars may not be null"); 1056 } 1057 int i = vn.length; 1058 String[] v = new String[vars.length + i]; 1059 for (int k = 0; k < vn.length; k++) { 1060 v[k] = vn[k]; 1061 } 1062 for (int k = 0; k < vars.length; k++) { 1063 v[vn.length + k] = vars[k]; 1064 } 1065 TermOrder to = tord.extendLower(nvar, i, top); 1066 GenPolynomialRing<C> pfac = new GenPolynomialRing<C>(coFac, nvar + i, to, v); 1067 return pfac; 1068 } 1069 1070 1071 /** 1072 * Contract variables. Used e.g. in module embedding. Contract number of 1073 * variables by i. 1074 * @param i number of variables to remove. 1075 * @return contracted polynomial ring factory. 1076 */ 1077 public GenPolynomialRing<C> contract(int i) { 1078 String[] v = null; 1079 if (vars != null) { 1080 v = new String[vars.length - i]; 1081 for (int j = 0; j < vars.length - i; j++) { 1082 v[j] = vars[j]; 1083 } 1084 } 1085 TermOrder to = tord.contract(i, nvar - i); 1086 GenPolynomialRing<C> pfac = new GenPolynomialRing<C>(coFac, nvar - i, to, v); 1087 return pfac; 1088 } 1089 1090 1091 /** 1092 * Recursive representation as polynomial with i main variables. 1093 * @param i number of main variables. 1094 * @return recursive polynomial ring factory. 1095 */ 1096 public GenPolynomialRing<GenPolynomial<C>> recursive(int i) { 1097 if (i <= 0 || i >= nvar) { 1098 throw new IllegalArgumentException("wrong: 0 < " + i + " < " + nvar); 1099 } 1100 GenPolynomialRing<C> cfac = contract(i); 1101 String[] v = null; 1102 if (vars != null) { 1103 v = new String[i]; 1104 int k = 0; 1105 for (int j = nvar - i; j < nvar; j++) { 1106 v[k++] = vars[j]; 1107 } 1108 } 1109 TermOrder to = tord.contract(0, i); // ?? 1110 GenPolynomialRing<GenPolynomial<C>> pfac = new GenPolynomialRing<GenPolynomial<C>>(cfac, i, to, v); 1111 return pfac; 1112 } 1113 1114 1115 /** 1116 * Distributive representation as polynomial with all main variables. 1117 * @return distributive polynomial ring factory. 1118 */ 1119 @SuppressWarnings("unchecked") 1120 public GenPolynomialRing<C> distribute() { 1121 if (!(coFac instanceof GenPolynomialRing)) { 1122 return this; 1123 } 1124 RingFactory cf = coFac; 1125 RingFactory<GenPolynomial<C>> cfp = (RingFactory<GenPolynomial<C>>) cf; 1126 GenPolynomialRing cr = (GenPolynomialRing) cfp; 1127 GenPolynomialRing<C> pfac; 1128 if (cr.vars != null) { 1129 pfac = extend(cr.vars); 1130 } else { 1131 pfac = extend(cr.nvar); 1132 } 1133 return pfac; 1134 } 1135 1136 1137 /** 1138 * Reverse variables. Used e.g. in opposite rings. 1139 * @return polynomial ring factory with reversed variables. 1140 */ 1141 public GenPolynomialRing<C> reverse() { 1142 return reverse(false); 1143 } 1144 1145 1146 /** 1147 * Reverse variables. Used e.g. in opposite rings. 1148 * @param partial true for partialy reversed term orders. 1149 * @return polynomial ring factory with reversed variables. 1150 */ 1151 public GenPolynomialRing<C> reverse(boolean partial) { 1152 String[] v = null; 1153 if (vars != null) { // vars are not inversed 1154 v = new String[vars.length]; 1155 int k = tord.getSplit(); 1156 if (partial && k < vars.length) { 1157 // copy upper 1158 for (int j = 0; j < k; j++) { 1159 //v[vars.length - k + j] = vars[vars.length - 1 - j]; // reverse upper 1160 v[vars.length - k + j] = vars[vars.length - k + j]; 1161 } 1162 // reverse lower 1163 for (int j = 0; j < vars.length - k; j++) { 1164 //v[j] = vars[j]; // copy upper 1165 v[j] = vars[vars.length - k - j - 1]; 1166 } 1167 } else { 1168 for (int j = 0; j < vars.length; j++) { 1169 v[j] = vars[vars.length - 1 - j]; 1170 } 1171 } 1172 //System.out.println("vars = " + Arrays.toString(vars)); 1173 //System.out.println("v = " + Arrays.toString(v)); 1174 } 1175 TermOrder to = tord.reverse(partial); 1176 GenPolynomialRing<C> pfac = new GenPolynomialRing<C>(coFac, nvar, to, v); 1177 pfac.partial = partial; 1178 return pfac; 1179 } 1180 1181 1182 /** 1183 * Get PolynomialComparator. 1184 * @return polynomial comparator. 1185 */ 1186 public PolynomialComparator<C> getComparator() { 1187 return new PolynomialComparator<C>(tord, false); 1188 } 1189 1190 1191 /** 1192 * Get PolynomialComparator. 1193 * @param rev for reverse comparator. 1194 * @return polynomial comparator. 1195 */ 1196 public PolynomialComparator<C> getComparator(boolean rev) { 1197 return new PolynomialComparator<C>(tord, rev); 1198 } 1199 1200 1201 /** 1202 * New variable names. Generate new names for variables, 1203 * @param prefix name prefix. 1204 * @param n number of variables. 1205 * @return new variable names. 1206 */ 1207 public static String[] newVars(String prefix, int n) { 1208 String[] vars = new String[n]; 1209 for (int i = 0; i < n; i++) { 1210 long m = varCounter.getAndIncrement(); 1211 vars[i] = prefix + m; 1212 } 1213 return vars; 1214 } 1215 1216 1217 /** 1218 * New variable names. Generate new names for variables, 1219 * @param prefix name prefix. 1220 * @return new variable names. 1221 */ 1222 public String[] newVars(String prefix) { 1223 return newVars(prefix, nvar); 1224 } 1225 1226 1227 /** 1228 * New variable names. Generate new names for variables, 1229 * @param n number of variables. 1230 * @return new variable names. 1231 */ 1232 public static String[] newVars(int n) { 1233 return newVars("x", n); 1234 } 1235 1236 1237 /** 1238 * New variable names. Generate new names for variables, 1239 * @return new variable names. 1240 */ 1241 public String[] newVars() { 1242 return newVars(nvar); 1243 } 1244 1245 1246 /* 1247 * Add variable names. 1248 * @param vars variable names to be recorded. 1249 public static void addVars(String[] vars) { 1250 if (vars == null) { 1251 return; 1252 } 1253 // synchronized (knownVars) { 1254 // for (int i = 0; i < vars.length; i++) { 1255 // knownVars.add(vars[i]); // eventualy names 'overwritten' 1256 // } 1257 // } 1258 } 1259 */ 1260 1261 1262 /** 1263 * Permute variable names. 1264 * @param vars variable names. 1265 * @param P permutation. 1266 * @return P(vars). 1267 */ 1268 public static String[] permuteVars(List<Integer> P, String[] vars) { 1269 if (vars == null || vars.length <= 1) { 1270 return vars; 1271 } 1272 String[] b = new String[vars.length]; 1273 int j = 0; 1274 for (Integer i : P) { 1275 b[j++] = vars[i]; 1276 } 1277 return b; 1278 } 1279 1280 1281 /** 1282 * Permutation of polynomial ring variables. 1283 * @param P permutation. 1284 * @return P(this). 1285 */ 1286 public GenPolynomialRing<C> permutation(List<Integer> P) { 1287 if (nvar <= 1) { 1288 return this; 1289 } 1290 TermOrder tp = tord.permutation(P); 1291 if (vars == null) { 1292 return new GenPolynomialRing<C>(coFac, nvar, tp); 1293 } 1294 String[] v1 = new String[vars.length]; 1295 for (int i = 0; i < v1.length; i++) { 1296 v1[i] = vars[v1.length - 1 - i]; 1297 } 1298 String[] vp = permuteVars(P, v1); 1299 String[] v2 = new String[vp.length]; 1300 for (int i = 0; i < vp.length; i++) { 1301 v2[i] = vp[vp.length - 1 - i]; 1302 } 1303 return new GenPolynomialRing<C>(coFac, nvar, tp, v2); 1304 } 1305 1306 1307 /** 1308 * Get a GenPolynomial iterator. 1309 * @return an iterator over all polynomials. 1310 */ 1311 public Iterator<GenPolynomial<C>> iterator() { 1312 if (coFac.isFinite()) { 1313 return new GenPolynomialIterator<C>(this); 1314 } 1315 logger.warn("ring of coefficients {} is infinite, constructing iterator only over monomials", coFac); 1316 return new GenPolynomialMonomialIterator<C>(this); 1317 //throw new IllegalArgumentException("only for finite iterable coefficients implemented"); 1318 } 1319 1320} 1321 1322 1323/** 1324 * Polynomial iterator. 1325 * @author Heinz Kredel 1326 */ 1327class GenPolynomialIterator<C extends RingElem<C>> implements Iterator<GenPolynomial<C>> { 1328 1329 1330 /** 1331 * data structure. 1332 */ 1333 final GenPolynomialRing<C> ring; 1334 1335 1336 final Iterator<List<Long>> eviter; 1337 1338 1339 final List<ExpVector> powers; 1340 1341 1342 final List<Iterable<C>> coeffiter; 1343 1344 1345 Iterator<List<C>> itercoeff; 1346 1347 1348 GenPolynomial<C> current; 1349 1350 1351 /** 1352 * Polynomial iterator constructor. 1353 */ 1354 @SuppressWarnings("unchecked") 1355 public GenPolynomialIterator(GenPolynomialRing<C> fac) { 1356 ring = fac; 1357 LongIterable li = new LongIterable(); 1358 li.setNonNegativeIterator(); 1359 List<Iterable<Long>> tlist = new ArrayList<Iterable<Long>>(ring.nvar); 1360 for (int i = 0; i < ring.nvar; i++) { 1361 tlist.add(li); 1362 } 1363 CartesianProductInfinite<Long> ei = new CartesianProductInfinite<Long>(tlist); 1364 eviter = ei.iterator(); 1365 RingFactory<C> cf = ring.coFac; 1366 coeffiter = new ArrayList<Iterable<C>>(); 1367 if (cf instanceof Iterable && cf.isFinite()) { 1368 Iterable<C> cfi = (Iterable<C>) cf; 1369 coeffiter.add(cfi); 1370 } else { 1371 throw new IllegalArgumentException("only for finite iterable coefficients implemented"); 1372 } 1373 CartesianProduct<C> tuples = new CartesianProduct<C>(coeffiter); 1374 itercoeff = tuples.iterator(); 1375 powers = new ArrayList<ExpVector>(); 1376 ExpVector e = ExpVector.create(eviter.next()); 1377 powers.add(e); 1378 //System.out.println("new e = " + e); 1379 //System.out.println("powers = " + powers); 1380 List<C> c = itercoeff.next(); 1381 //System.out.println("coeffs = " + c); 1382 current = new GenPolynomial<C>(ring, c.get(0), e); 1383 } 1384 1385 1386 /** 1387 * Test for availability of a next element. 1388 * @return true if the iteration has more elements, else false. 1389 */ 1390 public boolean hasNext() { 1391 return true; 1392 } 1393 1394 1395 /** 1396 * Get next polynomial. 1397 * @return next polynomial. 1398 */ 1399 public synchronized GenPolynomial<C> next() { 1400 GenPolynomial<C> res = current; 1401 if (!itercoeff.hasNext()) { 1402 ExpVector e = ExpVector.create(eviter.next()); 1403 powers.add(0, e); // add new ev at beginning 1404 //System.out.println("new e = " + e); 1405 //System.out.println("powers = " + powers); 1406 if (coeffiter.size() == 1) { // shorten frist iterator by one element 1407 coeffiter.add(coeffiter.get(0)); 1408 Iterable<C> it = coeffiter.get(0); 1409 List<C> elms = new ArrayList<C>(); 1410 for (C elm : it) { 1411 elms.add(elm); 1412 } 1413 elms.remove(0); 1414 coeffiter.set(0, elms); 1415 } else { 1416 coeffiter.add(coeffiter.get(1)); 1417 } 1418 CartesianProduct<C> tuples = new CartesianProduct<C>(coeffiter); 1419 itercoeff = tuples.iterator(); 1420 } 1421 List<C> coeffs = itercoeff.next(); 1422 // while ( coeffs.get(0).isZERO() ) { 1423 // System.out.println(" skip zero "); 1424 // coeffs = itercoeff.next(); // skip tuples with zero in first component 1425 // } 1426 //System.out.println("coeffs = " + coeffs); 1427 GenPolynomial<C> pol = ring.getZERO().copy(); 1428 int i = 0; 1429 for (ExpVector f : powers) { 1430 C c = coeffs.get(i++); 1431 if (c.isZERO()) { 1432 continue; 1433 } 1434 if (pol.val.get(f) != null) { 1435 System.out.println("error f in pol = " + f + ", " + pol.getMap().get(f)); 1436 throw new RuntimeException("error in iterator"); 1437 } 1438 pol.doPutToMap(f, c); 1439 } 1440 current = pol; 1441 return res; 1442 } 1443 1444 1445 /** 1446 * Remove an element if allowed. 1447 */ 1448 public void remove() { 1449 throw new UnsupportedOperationException("cannnot remove elements"); 1450 } 1451} 1452 1453 1454/** 1455 * Polynomial monomial iterator. 1456 * @author Heinz Kredel 1457 */ 1458class GenPolynomialMonomialIterator<C extends RingElem<C>> implements Iterator<GenPolynomial<C>> { 1459 1460 1461 /** 1462 * data structure. 1463 */ 1464 final GenPolynomialRing<C> ring; 1465 1466 1467 final Iterator<List> iter; 1468 1469 1470 GenPolynomial<C> current; 1471 1472 1473 /** 1474 * Polynomial iterator constructor. 1475 */ 1476 @SuppressWarnings("unchecked") 1477 public GenPolynomialMonomialIterator(GenPolynomialRing<C> fac) { 1478 ring = fac; 1479 LongIterable li = new LongIterable(); 1480 li.setNonNegativeIterator(); 1481 List<Iterable<Long>> tlist = new ArrayList<Iterable<Long>>(ring.nvar); 1482 for (int i = 0; i < ring.nvar; i++) { 1483 tlist.add(li); 1484 } 1485 CartesianProductInfinite<Long> ei = new CartesianProductInfinite<Long>(tlist); 1486 //Iterator<List<Long>> eviter = ei.iterator(); 1487 1488 RingFactory<C> cf = ring.coFac; 1489 Iterable<C> coeffiter; 1490 if (cf instanceof Iterable && !cf.isFinite()) { 1491 Iterable<C> cfi = (Iterable<C>) cf; 1492 coeffiter = cfi; 1493 } else { 1494 throw new IllegalArgumentException("only for infinite iterable coefficients implemented"); 1495 } 1496 1497 // Cantor iterator for exponents and coeffcients 1498 List<Iterable> eci = new ArrayList<Iterable>(2); // no type parameter 1499 eci.add(ei); 1500 eci.add(coeffiter); 1501 CartesianProductInfinite ecp = new CartesianProductInfinite(eci); 1502 iter = ecp.iterator(); 1503 1504 List ec = iter.next(); 1505 List<Long> ecl = (List<Long>) ec.get(0); 1506 C c = (C) ec.get(1); // zero 1507 ExpVector e = ExpVector.create(ecl); 1508 //System.out.println("exp = " + e); 1509 //System.out.println("coeffs = " + c); 1510 current = new GenPolynomial<C>(ring, c, e); 1511 } 1512 1513 1514 /** 1515 * Test for availability of a next element. 1516 * @return true if the iteration has more elements, else false. 1517 */ 1518 public boolean hasNext() { 1519 return true; 1520 } 1521 1522 1523 /** 1524 * Get next polynomial. 1525 * @return next polynomial. 1526 */ 1527 @SuppressWarnings("unchecked") 1528 public synchronized GenPolynomial<C> next() { 1529 GenPolynomial<C> res = current; 1530 1531 List ec = iter.next(); 1532 C c = (C) ec.get(1); 1533 while (c.isZERO()) { // zero already done in first next 1534 ec = iter.next(); 1535 c = (C) ec.get(1); 1536 } 1537 List<Long> ecl = (List<Long>) ec.get(0); 1538 ExpVector e = ExpVector.create(ecl); 1539 //System.out.println("exp = " + e); 1540 //System.out.println("coeffs = " + c); 1541 current = new GenPolynomial<C>(ring, c, e); 1542 1543 return res; 1544 } 1545 1546 1547 /** 1548 * Remove an element if allowed. 1549 */ 1550 public void remove() { 1551 throw new UnsupportedOperationException("cannnot remove elements"); 1552 } 1553}