001/* 002 * $Id: RecSolvablePolynomialRing.java 5835 2018-05-18 19:12:07Z 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.List; 014import java.util.Random; 015 016import org.apache.log4j.Logger; 017 018import edu.jas.kern.PrettyPrint; 019import edu.jas.kern.Scripting; 020import edu.jas.structure.RingElem; 021import edu.jas.structure.RingFactory; 022 023 024/** 025 * RecSolvablePolynomialRing generic recursive solvable polynomial factory 026 * implementing RingFactory and extending GenSolvablePolynomialRing factory. 027 * Factory for n-variate ordered solvable polynomials over solvable polynomial 028 * coefficients. The non-commutative multiplication relations are maintained in 029 * a relation table and the non-commutative multiplication relations between the 030 * coefficients and the main variables are maintained in a coefficient relation 031 * table. Almost immutable object, except variable names and relation table 032 * contents. 033 * @param <C> coefficient type. 034 * @author Heinz Kredel 035 */ 036 037public class RecSolvablePolynomialRing<C extends RingElem<C>> extends 038 GenSolvablePolynomialRing<GenPolynomial<C>> { 039 040 041 /** 042 * The solvable multiplication relations between variables and coefficients. 043 */ 044 public final RelationTable<GenPolynomial<C>> coeffTable; 045 046 047 /** 048 * The constant polynomial 0 for this ring. Hides super ZERO. 049 */ 050 public final RecSolvablePolynomial<C> ZERO; 051 052 053 /** 054 * The constant polynomial 1 for this ring. Hides super ONE. 055 */ 056 public final RecSolvablePolynomial<C> ONE; 057 058 059 private static final Logger logger = Logger.getLogger(RecSolvablePolynomialRing.class); 060 061 062 private static final boolean debug = logger.isDebugEnabled(); 063 064 065 /** 066 * The constructor creates a solvable polynomial factory object with the 067 * default term order and commutative relations. 068 * @param cf factory for coefficients of type C. 069 * @param n number of variables. 070 */ 071 public RecSolvablePolynomialRing(RingFactory<GenPolynomial<C>> cf, int n) { 072 this(cf, n, new TermOrder(), null, null); 073 } 074 075 076 /** 077 * The constructor creates a solvable polynomial factory object with the 078 * default term order. 079 * @param cf factory for coefficients of type C. 080 * @param n number of variables. 081 * @param rt solvable multiplication relations. 082 */ 083 public RecSolvablePolynomialRing(RingFactory<GenPolynomial<C>> cf, int n, 084 RelationTable<GenPolynomial<C>> rt) { 085 this(cf, n, new TermOrder(), null, rt); 086 } 087 088 089 /** 090 * The constructor creates a solvable polynomial factory object with the 091 * given term order and commutative relations. 092 * @param cf factory for coefficients of type C. 093 * @param n number of variables. 094 * @param t a term order. 095 */ 096 public RecSolvablePolynomialRing(RingFactory<GenPolynomial<C>> cf, int n, TermOrder t) { 097 this(cf, n, t, null, null); 098 } 099 100 101 /** 102 * The constructor creates a solvable polynomial factory object with the 103 * given term order. 104 * @param cf factory for coefficients of type C. 105 * @param n number of variables. 106 * @param t a term order. 107 * @param rt solvable multiplication relations. 108 */ 109 public RecSolvablePolynomialRing(RingFactory<GenPolynomial<C>> cf, int n, TermOrder t, 110 RelationTable<GenPolynomial<C>> rt) { 111 this(cf, n, t, null, rt); 112 } 113 114 115 /** 116 * The constructor creates a solvable polynomial factory object with the 117 * given term order and commutative relations. 118 * @param cf factory for coefficients of type C. 119 * @param n number of variables. 120 * @param t a term order. 121 * @param v names for the variables. 122 */ 123 public RecSolvablePolynomialRing(RingFactory<GenPolynomial<C>> cf, int n, TermOrder t, String[] v) { 124 this(cf, n, t, v, null); 125 } 126 127 128 /** 129 * The constructor creates a solvable polynomial factory object with the 130 * given term order and commutative relations. 131 * @param cf factory for coefficients of type C. 132 * @param t a term order. 133 * @param v names for the variables. 134 */ 135 public RecSolvablePolynomialRing(RingFactory<GenPolynomial<C>> cf, TermOrder t, String[] v) { 136 this(cf, v.length, t, v, null); 137 } 138 139 140 /** 141 * The constructor creates a solvable polynomial factory object with the 142 * default term order. 143 * @param cf factory for coefficients of type C. 144 * @param v names for the variables. 145 */ 146 public RecSolvablePolynomialRing(RingFactory<GenPolynomial<C>> cf, String[] v) { 147 this(cf, v.length, new TermOrder(), v, null); 148 } 149 150 151 /** 152 * The constructor creates a solvable polynomial factory object with the 153 * given term order. 154 * @param cf factory for coefficients of type C. 155 * @param n number of variables. 156 * @param t a term order. 157 * @param v names for the variables. 158 * @param rt solvable multiplication relations. 159 */ 160 public RecSolvablePolynomialRing(RingFactory<GenPolynomial<C>> cf, int n, TermOrder t, String[] v, 161 RelationTable<GenPolynomial<C>> rt) { 162 super(cf, n, t, v, rt); 163 //if (rt == null) { // handled in super } 164 coeffTable = new RelationTable<GenPolynomial<C>>(this, true); 165 ZERO = new RecSolvablePolynomial<C>(this); 166 GenPolynomial<C> coeff = coFac.getONE(); 167 //evzero = ExpVector.create(nvar); // from super 168 ONE = new RecSolvablePolynomial<C>(this, coeff, evzero); 169 } 170 171 172 /** 173 * The constructor creates a solvable polynomial factory object with the the 174 * same term order, number of variables and variable names as the given 175 * polynomial factory, only the coefficient factories differ and the 176 * solvable multiplication relations are <b>empty</b>. 177 * @param cf factory for coefficients of type C. 178 * @param o other solvable polynomial ring. 179 */ 180 public RecSolvablePolynomialRing(RingFactory<GenPolynomial<C>> cf, RecSolvablePolynomialRing o) { 181 this(cf, o.nvar, o.tord, o.getVars(), null); 182 } 183 184 185 /** 186 * Get the String representation. 187 * @see java.lang.Object#toString() 188 */ 189 @Override 190 public String toString() { 191 String res = super.toString(); 192 if (PrettyPrint.isTrue()) { 193 //res += "\n" + table.toString(vars); 194 res += "\n" + coeffTable.toString(vars); 195 } else { 196 res += ", #rel = " + table.size() + " + " + coeffTable.size(); 197 } 198 return res; 199 } 200 201 202 /** 203 * Get a scripting compatible string representation. 204 * @return script compatible representation for this Element. 205 * @see edu.jas.structure.Element#toScript() 206 */ 207 @Override 208 public String toScript() { 209 StringBuffer s = new StringBuffer(); 210 switch (Scripting.getLang()) { 211 case Ruby: 212 s.append("SolvPolyRing.new("); 213 break; 214 case Python: 215 default: 216 s.append("SolvPolyRing("); 217 } 218 if (coFac instanceof RingElem) { 219 s.append(((RingElem<GenPolynomial<C>>) coFac).toScriptFactory()); 220 } else { 221 s.append(coFac.toScript().trim()); 222 } 223 s.append(",\"" + varsToString() + "\","); 224 String to = tord.toScript(); 225 s.append(to); 226 if (table.size() > 0) { 227 String rel = table.toScript(); 228 s.append(",rel="); 229 s.append(rel); 230 } 231 if (coeffTable.size() > 0) { 232 String rel = coeffTable.toScript(); 233 s.append(",coeffrel="); 234 s.append(rel); 235 } 236 s.append(")"); 237 return s.toString(); 238 } 239 240 241 /** 242 * Comparison with any other object. 243 * @see java.lang.Object#equals(java.lang.Object) 244 */ 245 @Override 246 @SuppressWarnings("unchecked") 247 public boolean equals(Object other) { 248 if (other == null) { 249 return false; 250 } 251 if (!(other instanceof RecSolvablePolynomialRing)) { 252 return false; 253 } 254 // do a super.equals( ) 255 if (!super.equals(other)) { 256 return false; 257 } 258 RecSolvablePolynomialRing<C> oring = (RecSolvablePolynomialRing<C>) other; 259 // check same base relations 260 //if ( ! table.equals(oring.table) ) { // done in super 261 // return false; 262 //} 263 if (!coeffTable.equals(oring.coeffTable)) { 264 return false; 265 } 266 return true; 267 } 268 269 270 /** 271 * Hash code for this polynomial ring. 272 * @see java.lang.Object#hashCode() 273 */ 274 @Override 275 public int hashCode() { 276 int h; 277 h = super.hashCode(); 278 h = 37 * h + table.hashCode(); // may be different after some computations 279 h = 37 * h + coeffTable.hashCode(); // may be different 280 return h; 281 } 282 283 284 /** 285 * Get the zero element. 286 * @return 0 as RecSolvablePolynomial<C>. 287 */ 288 @Override 289 public RecSolvablePolynomial<C> getZERO() { 290 return ZERO; 291 } 292 293 294 /** 295 * Get the one element. 296 * @return 1 as RecSolvablePolynomial<C>. 297 */ 298 @Override 299 public RecSolvablePolynomial<C> getONE() { 300 return ONE; 301 } 302 303 304 /** 305 * Query if this ring is commutative. 306 * @return true if this ring is commutative, else false. 307 */ 308 @Override 309 public boolean isCommutative() { 310 if (coeffTable.isEmpty()) { 311 return super.isCommutative(); 312 } 313 return false; 314 } 315 316 317 /** 318 * Query if this ring is associative. Test if the relations between the mian 319 * variables and the coefficient generators define an associative solvable 320 * ring. 321 * @return true, if this ring is associative, else false. 322 */ 323 @SuppressWarnings("unused") 324 @Override 325 public boolean isAssociative() { 326 if (!coFac.isAssociative()) { 327 return false; 328 } 329 RecSolvablePolynomial<C> Xi, Xj, Xk, p, q; 330 List<GenPolynomial<GenPolynomial<C>>> gens = generators(); 331 //System.out.println("Rec gens = " + gens); 332 int ngen = gens.size(); 333 for (int i = 0; i < ngen; i++) { 334 Xi = (RecSolvablePolynomial<C>) gens.get(i); 335 for (int j = i + 1; j < ngen; j++) { 336 Xj = (RecSolvablePolynomial<C>) gens.get(j); 337 for (int k = j + 1; k < ngen; k++) { 338 Xk = (RecSolvablePolynomial<C>) gens.get(k); 339 p = Xk.multiply(Xj).multiply(Xi); 340 q = Xk.multiply(Xj.multiply(Xi)); 341 if (!p.equals(q)) { 342 if (true || debug) { 343 logger.info("Xk = " + Xk + ", Xj = " + Xj + ", Xi = " + Xi); 344 logger.info("p = ( Xk * Xj ) * Xi = " + p); 345 logger.info("q = Xk * ( Xj * Xi ) = " + q); 346 } 347 return false; 348 } 349 } 350 } 351 } 352 return true; 353 } 354 355 356 /** 357 * Get a (constant) RecSolvablePolynomial<C> element from a coefficient value. 358 * @param a coefficient. 359 * @return a RecSolvablePolynomial<C>. 360 */ 361 @Override 362 public RecSolvablePolynomial<C> valueOf(GenPolynomial<C> a) { 363 return new RecSolvablePolynomial<C>(this, a); 364 } 365 366 367 /** 368 * Get a RecSolvablePolynomial<C> element from an exponent vector. 369 * @param e exponent vector. 370 * @return a RecSolvablePolynomial<C>. 371 */ 372 @Override 373 public RecSolvablePolynomial<C> valueOf(ExpVector e) { 374 return new RecSolvablePolynomial<C>(this, coFac.getONE(), e); 375 } 376 377 378 /** 379 * Get a RecSolvablePolynomial<C> element from a coeffcient and an exponent 380 * vector. 381 * @param a coefficient. 382 * @param e exponent vector. 383 * @return a RecSolvablePolynomial<C>. 384 */ 385 @Override 386 public RecSolvablePolynomial<C> valueOf(GenPolynomial<C> a, ExpVector e) { 387 return new RecSolvablePolynomial<C>(this, a, e); 388 } 389 390 391 /** 392 * Get a (constant) RecSolvablePolynomial<C> element from a long 393 * value 394 * @param a long. 395 * @return a RecSolvablePolynomial<C>. 396 */ 397 @Override 398 public RecSolvablePolynomial<C> fromInteger(long a) { 399 return new RecSolvablePolynomial<C>(this, coFac.fromInteger(a), evzero); 400 } 401 402 403 /** 404 * Get a (constant) RecSolvablePolynomial<C> element from a BigInteger 405 * value. 406 * @param a BigInteger. 407 * @return a RecSolvablePolynomial<C>. 408 */ 409 @Override 410 public RecSolvablePolynomial<C> fromInteger(BigInteger a) { 411 return new RecSolvablePolynomial<C>(this, coFac.fromInteger(a), evzero); 412 } 413 414 415 /** 416 * Random solvable polynomial. Generates a random solvable polynomial with k 417 * = 5, l = n, d = (nvar == 1) ? n : 3, q = (nvar == 1) ? 0.7 : 0.3. 418 * @param n number of terms. 419 * @return a random solvable polynomial. 420 */ 421 @Override 422 public RecSolvablePolynomial<C> random(int n) { 423 return random(n, random); 424 } 425 426 427 /** 428 * Random solvable polynomial. Generates a random solvable polynomial with k 429 * = 5, l = n, d = (nvar == 1) ? n : 3, q = (nvar == 1) ? 0.7 : 0.3. 430 * @param n number of terms. 431 * @param rnd is a source for random bits. 432 * @return a random solvable polynomial. 433 */ 434 @Override 435 public RecSolvablePolynomial<C> random(int n, Random rnd) { 436 if (nvar == 1) { 437 return random(5, n, n, 0.7f, rnd); 438 } 439 return random(5, n, 3, 0.3f, rnd); 440 } 441 442 443 /** 444 * Generate a random solvable polynomial. 445 * @param k bitsize of random coefficients. 446 * @param l number of terms. 447 * @param d maximal degree in each variable. 448 * @param q density of nozero exponents. 449 * @return a random solvable polynomial. 450 */ 451 @Override 452 public RecSolvablePolynomial<C> random(int k, int l, int d, float q) { 453 return random(k, l, d, q, random); 454 } 455 456 457 /** 458 * Random solvable polynomial. 459 * @param k size of random coefficients. 460 * @param l number of terms. 461 * @param d maximal degree in each variable. 462 * @param q density of nozero exponents. 463 * @param rnd is a source for random bits. 464 * @return a random solvable polynomial. 465 */ 466 @Override 467 public RecSolvablePolynomial<C> random(int k, int l, int d, float q, Random rnd) { 468 RecSolvablePolynomial<C> r = getZERO(); // copy( ZERO ); 469 ExpVector e; 470 GenPolynomial<C> a; 471 // add random coeffs and exponents 472 for (int i = 0; i < l; i++) { 473 e = ExpVector.EVRAND(nvar, d, q, rnd); 474 a = coFac.random(k, rnd); 475 r = (RecSolvablePolynomial<C>) r.sum(a, e); 476 // somewhat inefficient but clean 477 } 478 return r; 479 } 480 481 482 /** 483 * Copy polynomial c. 484 * @param c 485 * @return a copy of c. 486 */ 487 public RecSolvablePolynomial<C> copy(RecSolvablePolynomial<C> c) { 488 return new RecSolvablePolynomial<C>(this, c.val); 489 } 490 491 492 /** 493 * Parse a solvable polynomial with the use of GenPolynomialTokenizer 494 * @param s String. 495 * @return RecSolvablePolynomial from s. 496 */ 497 @Override 498 public RecSolvablePolynomial<C> parse(String s) { 499 return parse(new StringReader(s)); 500 } 501 502 503 /** 504 * Parse a solvable polynomial with the use of GenPolynomialTokenizer 505 * @param r Reader. 506 * @return next RecSolvablePolynomial from r. 507 */ 508 @Override 509 @SuppressWarnings("unchecked") 510 public RecSolvablePolynomial<C> parse(Reader r) { 511 GenPolynomialTokenizer pt = new GenPolynomialTokenizer(this, r); 512 RecSolvablePolynomial<C> p = null; 513 try { 514 GenSolvablePolynomial<GenPolynomial<C>> s = pt.nextSolvablePolynomial(); 515 p = new RecSolvablePolynomial<C>(this, s); 516 } catch (IOException e) { 517 logger.error(e.toString() + " parse " + this); 518 p = ZERO; 519 } 520 return p; 521 } 522 523 524 /** 525 * Generate univariate solvable polynomial in a given variable. 526 * @param i the index of the variable. 527 * @return X_i as solvable univariate polynomial. 528 */ 529 @Override 530 public RecSolvablePolynomial<C> univariate(int i) { 531 return (RecSolvablePolynomial<C>) super.univariate(i); 532 } 533 534 535 /** 536 * Generate univariate solvable polynomial in a given variable with given 537 * exponent. 538 * @param i the index of the variable. 539 * @param e the exponent of the variable. 540 * @return X_i^e as solvable univariate polynomial. 541 */ 542 @Override 543 public RecSolvablePolynomial<C> univariate(int i, long e) { 544 return (RecSolvablePolynomial<C>) super.univariate(i, e); 545 } 546 547 548 /** 549 * Generate univariate solvable polynomial in a given variable with given 550 * exponent. 551 * @param modv number of module variables. 552 * @param i the index of the variable. 553 * @param e the exponent of the variable. 554 * @return X_i^e as solvable univariate polynomial. 555 */ 556 @Override 557 public RecSolvablePolynomial<C> univariate(int modv, int i, long e) { 558 return (RecSolvablePolynomial<C>) super.univariate(modv, i, e); 559 } 560 561 562 /** 563 * Generate list of univariate polynomials in all variables. 564 * @return List(X_1,...,X_n) a list of univariate polynomials. 565 */ 566 @Override 567 public List<RecSolvablePolynomial<C>> univariateList() { 568 //return castToSolvableList( super.univariateList() ); 569 return univariateList(0, 1L); 570 } 571 572 573 /** 574 * Generate list of univariate polynomials in all variables. 575 * @param modv number of module variables. 576 * @return List(X_1,...,X_n) a list of univariate polynomials. 577 */ 578 @Override 579 public List<RecSolvablePolynomial<C>> univariateList(int modv) { 580 return univariateList(modv, 1L); 581 } 582 583 584 /** 585 * Generate list of univariate polynomials in all variables with given 586 * exponent. 587 * @param modv number of module variables. 588 * @param e the exponent of the variables. 589 * @return List(X_1^e,...,X_n^e) a list of univariate polynomials. 590 */ 591 @Override 592 public List<RecSolvablePolynomial<C>> univariateList(int modv, long e) { 593 List<RecSolvablePolynomial<C>> pols = new ArrayList<RecSolvablePolynomial<C>>(nvar); 594 int nm = nvar - modv; 595 for (int i = 0; i < nm; i++) { 596 RecSolvablePolynomial<C> p = univariate(modv, nm - 1 - i, e); 597 pols.add(p); 598 } 599 return pols; 600 } 601 602 603 /** 604 * Extend variables. Used e.g. in module embedding. Extend number of 605 * variables by i. 606 * @param i number of variables to extend. 607 * @return extended solvable polynomial ring factory. 608 */ 609 @Override 610 public RecSolvablePolynomialRing<C> extend(int i) { 611 GenSolvablePolynomialRing<GenPolynomial<C>> pfac = super.extend(i); 612 RecSolvablePolynomialRing<C> spfac = new RecSolvablePolynomialRing<C>(pfac.coFac, pfac.nvar, 613 pfac.tord, pfac.vars, pfac.table); 614 //spfac.table.extend(this.table); // pfac.table 615 spfac.coeffTable.extend(this.coeffTable); 616 return spfac; 617 } 618 619 620 /** 621 * Extend variables. Used e.g. in module embedding. Extend number of 622 * variables by length(vn). New variables commute with the exiting 623 * variables. 624 * @param vs names for extended variables. 625 * @return extended polynomial ring factory. 626 */ 627 @Override 628 public RecSolvablePolynomialRing<C> extend(String[] vs) { 629 GenSolvablePolynomialRing<GenPolynomial<C>> pfac = super.extend(vs); 630 RecSolvablePolynomialRing<C> spfac = new RecSolvablePolynomialRing<C>(pfac.coFac, pfac.nvar, 631 pfac.tord, pfac.vars, pfac.table); 632 //spfac.table.extend(this.table); // pfac.table?? 633 spfac.coeffTable.extend(this.coeffTable); 634 return spfac; 635 } 636 637 638 /** 639 * Contract variables. Used e.g. in module embedding. Contract number of 640 * variables by i. 641 * @param i number of variables to remove. 642 * @return contracted solvable polynomial ring factory. 643 */ 644 @Override 645 public RecSolvablePolynomialRing<C> contract(int i) { 646 GenPolynomialRing<GenPolynomial<C>> pfac = super.contract(i); 647 RecSolvablePolynomialRing<C> spfac = new RecSolvablePolynomialRing<C>(pfac.coFac, pfac.nvar, 648 pfac.tord, pfac.vars); 649 spfac.table.contract(this.table); 650 spfac.coeffTable.contract(this.coeffTable); 651 return spfac; 652 } 653 654 655 /** 656 * Reverse variables. Used e.g. in opposite rings. 657 * @return solvable polynomial ring factory with reversed variables. 658 */ 659 @Override 660 public RecSolvablePolynomialRing<C> reverse() { 661 return reverse(false); 662 } 663 664 665 /** 666 * Reverse variables. Used e.g. in opposite rings. 667 * @param partial true for partialy reversed term orders. 668 * @return solvable polynomial ring factory with reversed variables. 669 */ 670 @Override 671 public RecSolvablePolynomialRing<C> reverse(boolean partial) { 672 GenPolynomialRing<GenPolynomial<C>> pfac = super.reverse(partial); 673 RecSolvablePolynomialRing<C> spfac = new RecSolvablePolynomialRing<C>(pfac.coFac, pfac.nvar, 674 pfac.tord, pfac.vars); 675 spfac.partial = partial; 676 spfac.table.reverse(this.table); 677 spfac.coeffTable.reverse(this.coeffTable); 678 return spfac; 679 } 680 681 682 /** 683 * Distributive representation as polynomial with all main variables. 684 * @return distributive polynomial ring factory. 685 */ 686 @SuppressWarnings({"cast","unchecked"}) 687 public static <C extends RingElem<C>> // must be static because of types 688 GenSolvablePolynomialRing<C> distribute(RecSolvablePolynomialRing<C> rf) { 689 // setup solvable polynomial ring 690 GenSolvablePolynomialRing<C> fring = (GenSolvablePolynomialRing<C>) (GenSolvablePolynomialRing) rf; 691 GenSolvablePolynomialRing<C> pfd = fring.distribute(); 692 // add coefficient relations: 693 List<GenPolynomial<GenPolynomial<C>>> rl = (List<GenPolynomial<GenPolynomial<C>>>) (List) PolynomialList 694 .castToList(rf.coeffTable.relationList()); 695 List<GenPolynomial<C>> rld = PolyUtil.<C> distribute(pfd, rl); 696 pfd.table.addRelations(rld); 697 //System.out.println("pfd = " + pfd.toScript()); 698 return pfd; 699 } 700 701 702 /** 703 * Permutation of polynomial ring variables. 704 * @param P permutation. 705 * @return P(this). 706 */ 707 @Override 708 public GenSolvablePolynomialRing<GenPolynomial<C>> permutation(List<Integer> P) { 709 if (!coeffTable.isEmpty()) { 710 throw new UnsupportedOperationException("permutation with coeff relations: " + this); 711 } 712 GenSolvablePolynomialRing<GenPolynomial<C>> pfac = (GenSolvablePolynomialRing<GenPolynomial<C>>) super.permutation(P); 713 return pfac; 714 } 715 716}