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