001/* 002 * $Id: QuotSolvablePolynomial.java 5554 2016-07-25 08:10:26Z kredel $ 003 */ 004 005package edu.jas.fd; 006 007 008import java.util.Map; 009import java.util.Set; 010import java.util.SortedMap; 011 012import org.apache.log4j.Logger; 013 014import edu.jas.poly.ExpVector; 015import edu.jas.poly.GenSolvablePolynomial; 016import edu.jas.poly.RecSolvablePolynomial; 017import edu.jas.poly.TableRelation; 018import edu.jas.structure.GcdRingElem; 019 020 021/** 022 * QuotSolvablePolynomial generic recursive solvable polynomials implementing 023 * RingElem. n-variate ordered solvable polynomials over solvable polynomial 024 * coefficients. Objects of this class are intended to be immutable. The 025 * implementation is based on TreeMap respectively SortedMap from exponents to 026 * coefficients by extension of GenPolynomial. 027 * Will be deprecated use QLRSolvablePolynomial. 028 * @param <C> coefficient type 029 * @author Heinz Kredel 030 */ 031 032public class QuotSolvablePolynomial<C extends GcdRingElem<C>> extends 033 GenSolvablePolynomial<SolvableQuotient<C>> { 034 035 036 /** 037 * The factory for the recursive solvable polynomial ring. Hides super.ring. 038 */ 039 public final QuotSolvablePolynomialRing<C> ring; 040 041 042 private static final Logger logger = Logger.getLogger(QuotSolvablePolynomial.class); 043 044 045 private static final boolean debug = logger.isDebugEnabled(); 046 047 048 /** 049 * Constructor for zero QuotSolvablePolynomial. 050 * @param r solvable polynomial ring factory. 051 */ 052 public QuotSolvablePolynomial(QuotSolvablePolynomialRing<C> r) { 053 super(r); 054 ring = r; 055 } 056 057 058 /** 059 * Constructor for QuotSolvablePolynomial. 060 * @param r solvable polynomial ring factory. 061 * @param c coefficient polynomial. 062 * @param e exponent. 063 */ 064 public QuotSolvablePolynomial(QuotSolvablePolynomialRing<C> r, SolvableQuotient<C> c, ExpVector e) { 065 this(r); 066 if (c != null && !c.isZERO()) { 067 val.put(e, c); 068 } 069 } 070 071 072 /** 073 * Constructor for QuotSolvablePolynomial. 074 * @param r solvable polynomial ring factory. 075 * @param c coefficient polynomial. 076 */ 077 public QuotSolvablePolynomial(QuotSolvablePolynomialRing<C> r, SolvableQuotient<C> c) { 078 this(r, c, r.evzero); 079 } 080 081 082 /** 083 * Constructor for QuotSolvablePolynomial. 084 * @param r solvable polynomial ring factory. 085 * @param S solvable polynomial. 086 */ 087 public QuotSolvablePolynomial(QuotSolvablePolynomialRing<C> r, 088 GenSolvablePolynomial<SolvableQuotient<C>> S) { 089 this(r, S.getMap()); 090 } 091 092 093 /** 094 * Constructor for QuotSolvablePolynomial. 095 * @param r solvable polynomial ring factory. 096 * @param v the SortedMap of some other (solvable) polynomial. 097 */ 098 protected QuotSolvablePolynomial(QuotSolvablePolynomialRing<C> r, 099 SortedMap<ExpVector, SolvableQuotient<C>> v) { 100 this(r); 101 val.putAll(v); // assume no zero coefficients 102 } 103 104 105 /** 106 * Get the corresponding element factory. 107 * @return factory for this Element. 108 * @see edu.jas.structure.Element#factory() 109 */ 110 @Override 111 public QuotSolvablePolynomialRing<C> factory() { 112 return ring; 113 } 114 115 116 /** 117 * Clone this QuotSolvablePolynomial. 118 * @see java.lang.Object#clone() 119 */ 120 @Override 121 public QuotSolvablePolynomial<C> copy() { 122 return new QuotSolvablePolynomial<C>(ring, this.val); 123 } 124 125 126 /** 127 * Comparison with any other object. 128 * @see java.lang.Object#equals(java.lang.Object) 129 */ 130 @Override 131 public boolean equals(Object B) { 132 if (!(B instanceof QuotSolvablePolynomial)) { 133 return false; 134 } 135 return super.equals(B); 136 } 137 138 139 /** 140 * QuotSolvablePolynomial multiplication. 141 * @param Bp QuotSolvablePolynomial. 142 * @return this*Bp, where * denotes solvable multiplication. 143 */ 144 // not @Override 145 public QuotSolvablePolynomial<C> multiply(QuotSolvablePolynomial<C> Bp) { 146 if (Bp == null || Bp.isZERO()) { 147 return ring.getZERO(); 148 } 149 if (this.isZERO()) { 150 return this; 151 } 152 if (Bp.isONE()) { 153 return this; 154 } 155 if (this.isONE()) { 156 return Bp; 157 } 158 assert (ring.nvar == Bp.ring.nvar); 159 if (debug) { 160 logger.debug("ring = " + ring); 161 } 162 //System.out.println("this = " + this + ", Bp = " + Bp); 163 ExpVector Z = ring.evzero; 164 QuotSolvablePolynomial<C> Dp = ring.getZERO().copy(); 165 QuotSolvablePolynomial<C> zero = ring.getZERO().copy(); 166 SolvableQuotient<C> one = ring.getONECoefficient(); 167 168 //QuotSolvablePolynomial<C> C1 = null; 169 //QuotSolvablePolynomial<C> C2 = null; 170 Map<ExpVector, SolvableQuotient<C>> A = val; 171 Map<ExpVector, SolvableQuotient<C>> B = Bp.val; 172 Set<Map.Entry<ExpVector, SolvableQuotient<C>>> Bk = B.entrySet(); 173 for (Map.Entry<ExpVector, SolvableQuotient<C>> y : A.entrySet()) { 174 SolvableQuotient<C> a = y.getValue(); 175 ExpVector e = y.getKey(); 176 if (debug) 177 logger.info("e = " + e + ", a = " + a); 178 // int[] ep = e.dependencyOnVariables(); 179 // int el1 = ring.nvar + 1; 180 // if (ep.length > 0) { 181 // el1 = ep[0]; 182 // } 183 // int el1s = ring.nvar + 1 - el1; 184 for (Map.Entry<ExpVector, SolvableQuotient<C>> x : Bk) { 185 SolvableQuotient<C> b = x.getValue(); 186 ExpVector f = x.getKey(); 187 if (debug) 188 logger.info("f = " + f + ", b = " + b); 189 int[] fp = f.dependencyOnVariables(); 190 int fl1 = 0; 191 if (fp.length > 0) { 192 fl1 = fp[fp.length - 1]; 193 } 194 int fl1s = ring.nvar + 1 - fl1; 195 // polynomial with coefficient multiplication 196 QuotSolvablePolynomial<C> Cps = ring.getZERO().copy(); 197 //QuotSolvablePolynomial<C> Cs; 198 QuotSolvablePolynomial<C> qp; 199 if (ring.polCoeff.coeffTable.isEmpty() || b.isConstant() || e.isZERO()) { // symmetric 200 Cps = new QuotSolvablePolynomial<C>(ring, b, e); 201 if (debug) 202 logger.info("symmetric coeff: b = " + b + ", e = " + e); 203 } else { // unsymmetric 204 if (debug) 205 logger.info("unsymmetric coeff: b = " + b + ", e = " + e); 206 // compute e * b as ( e * 1/b.den ) * b.num 207 if (b.den.isONE()) { // recursion base 208 // recursive polynomial coefficient multiplication : e * b.num 209 RecSolvablePolynomial<C> rsp1 = new RecSolvablePolynomial<C>(ring.polCoeff, e); 210 RecSolvablePolynomial<C> rsp2 = new RecSolvablePolynomial<C>(ring.polCoeff, b.num); 211 RecSolvablePolynomial<C> rsp3 = rsp1.multiply(rsp2); 212 QuotSolvablePolynomial<C> rsp = ring.fromPolyCoefficients(rsp3); 213 Cps = rsp; 214 } else { // b.den != 1 215 if (debug) 216 logger.info("coeff-num: Cps = " + Cps + ", num = " + b.num + ", den = " + b.den); 217 Cps = new QuotSolvablePolynomial<C>(ring, b.ring.getONE(), e); 218 219 // coefficient multiplication with 1/den: 220 QuotSolvablePolynomial<C> qv = Cps; 221 SolvableQuotient<C> qden = new SolvableQuotient<C>(b.ring, b.den); // den/1 222 //System.out.println("qv = " + qv + ", den = " + den); 223 // recursion with den==1: 224 QuotSolvablePolynomial<C> v = qv.multiply(qden); 225 QuotSolvablePolynomial<C> vl = qv.multiplyLeft(qden); 226 //System.out.println("v = " + v + ", vl = " + vl + ", qden = " + qden); 227 QuotSolvablePolynomial<C> vr = (QuotSolvablePolynomial<C>) v.subtract(vl); 228 SolvableQuotient<C> qdeni = new SolvableQuotient<C>(b.ring, b.ring.ring.getONE(), 229 b.den); 230 //System.out.println("vr = " + vr + ", qdeni = " + qdeni); 231 // recursion with smaller head term: 232 QuotSolvablePolynomial<C> rq = vr.multiply(qdeni); 233 qp = (QuotSolvablePolynomial<C>) qv.subtract(rq); 234 qp = qp.multiplyLeft(qdeni); 235 //System.out.println("qp_i = " + qp); 236 Cps = qp; 237 238 if (!b.num.isONE()) { 239 SolvableQuotient<C> qnum = new SolvableQuotient<C>(b.ring, b.num); // num/1 240 // recursion with den == 1: 241 Cps = Cps.multiply(qnum); 242 } 243 } 244 } // end coeff 245 if (debug) 246 logger.info("coeff-den: Cps = " + Cps); 247 // polynomial multiplication 248 QuotSolvablePolynomial<C> Dps = ring.getZERO().copy(); 249 QuotSolvablePolynomial<C> Ds = null; 250 QuotSolvablePolynomial<C> D1, D2; 251 if (ring.table.isEmpty() || Cps.isConstant() || f.isZERO()) { // symmetric 252 if (debug) 253 logger.info("symmetric poly: b = " + b + ", e = " + e); 254 ExpVector g = e.sum(f); 255 if (Cps.isConstant()) { 256 Ds = new QuotSolvablePolynomial<C>(ring, Cps.leadingBaseCoefficient(), g); // symmetric! 257 } else { 258 Ds = Cps.shift(f); // symmetric 259 } 260 } else { // eventually unsymmetric 261 if (debug) 262 logger.info("unsymmetric poly: Cps = " + Cps + ", f = " + f); 263 for (Map.Entry<ExpVector, SolvableQuotient<C>> z : Cps.val.entrySet()) { 264 // split g = g1 * g2, f = f1 * f2 265 SolvableQuotient<C> c = z.getValue(); 266 ExpVector g = z.getKey(); 267 if (debug) 268 logger.info("g = " + g + ", c = " + c); 269 int[] gp = g.dependencyOnVariables(); 270 int gl1 = ring.nvar + 1; 271 if (gp.length > 0) { 272 gl1 = gp[0]; 273 } 274 int gl1s = ring.nvar + 1 - gl1; 275 if (gl1s <= fl1s) { // symmetric 276 ExpVector h = g.sum(f); 277 if (debug) 278 logger.info("disjoint poly: g = " + g + ", f = " + f + ", h = " + h); 279 Ds = (QuotSolvablePolynomial<C>) zero.sum(one, h); // symmetric! 280 } else { 281 ExpVector g1 = g.subst(gl1, 0); 282 ExpVector g2 = Z.subst(gl1, g.getVal(gl1)); // bug el1, gl1 283 ExpVector g4; 284 ExpVector f1 = f.subst(fl1, 0); 285 ExpVector f2 = Z.subst(fl1, f.getVal(fl1)); 286 if (debug) { 287 logger.info("poly, g1 = " + g1 + ", f1 = " + f1 + ", Dps = " + Dps); 288 logger.info("poly, g2 = " + g2 + ", f2 = " + f2); 289 } 290 TableRelation<SolvableQuotient<C>> rel = ring.table.lookup(g2, f2); 291 if (debug) 292 logger.info("poly, g = " + g + ", f = " + f + ", rel = " + rel); 293 Ds = new QuotSolvablePolynomial<C>(ring, rel.p); //ring.copy(rel.p); 294 if (rel.f != null) { 295 D2 = new QuotSolvablePolynomial<C>(ring, one, rel.f); 296 Ds = Ds.multiply(D2); 297 if (rel.e == null) { 298 g4 = g2; 299 } else { 300 g4 = g2.subtract(rel.e); 301 } 302 ring.table.update(g4, f2, Ds); 303 } 304 if (rel.e != null) { 305 D1 = new QuotSolvablePolynomial<C>(ring, one, rel.e); 306 Ds = D1.multiply(Ds); 307 ring.table.update(g2, f2, Ds); 308 } 309 if (!f1.isZERO()) { 310 D2 = new QuotSolvablePolynomial<C>(ring, one, f1); 311 Ds = Ds.multiply(D2); 312 //ring.table.update(?,f1,Ds) 313 } 314 if (!g1.isZERO()) { 315 D1 = new QuotSolvablePolynomial<C>(ring, one, g1); 316 Ds = D1.multiply(Ds); 317 //ring.table.update(e1,?,Ds) 318 } 319 } 320 Ds = Ds.multiplyLeft(c); // c * Ds 321 Dps = (QuotSolvablePolynomial<C>) Dps.sum(Ds); 322 } // end Dps loop 323 Ds = Dps; 324 } 325 Ds = Ds.multiplyLeft(a); // multiply(a,b); // non-symmetric 326 if (debug) 327 logger.debug("Ds = " + Ds); 328 Dp = (QuotSolvablePolynomial<C>) Dp.sum(Ds); 329 } // end B loop 330 } // end A loop 331 //System.out.println("this * Bp = " + Dp); 332 return Dp; 333 } 334 335 336 /** 337 * QuotSolvablePolynomial left and right multiplication. Product with two 338 * polynomials. 339 * @param S QuotSolvablePolynomial. 340 * @param T QuotSolvablePolynomial. 341 * @return S*this*T. 342 */ 343 // not @Override 344 public QuotSolvablePolynomial<C> multiply(QuotSolvablePolynomial<C> S, QuotSolvablePolynomial<C> T) { 345 if (S.isZERO() || T.isZERO() || this.isZERO()) { 346 return ring.getZERO(); 347 } 348 if (S.isONE()) { 349 return multiply(T); 350 } 351 if (T.isONE()) { 352 return S.multiply(this); 353 } 354 return S.multiply(this).multiply(T); 355 } 356 357 358 /** 359 * QuotSolvablePolynomial multiplication. Product with coefficient ring 360 * element. 361 * @param b solvable coefficient. 362 * @return this*b, where * is coefficient multiplication. 363 */ 364 @Override 365 public QuotSolvablePolynomial<C> multiply(SolvableQuotient<C> b) { 366 QuotSolvablePolynomial<C> Cp = ring.getZERO().copy(); 367 if (b == null || b.isZERO()) { 368 return Cp; 369 } 370 if (b.isONE()) { 371 return this; 372 } 373 Cp = new QuotSolvablePolynomial<C>(ring, b, ring.evzero); 374 return multiply(Cp); 375 } 376 377 378 /** 379 * QuotSolvablePolynomial left and right multiplication. Product with 380 * coefficient ring element. 381 * @param b coefficient polynomial. 382 * @param c coefficient polynomial. 383 * @return b*this*c, where * is coefficient multiplication. 384 */ 385 @Override 386 public QuotSolvablePolynomial<C> multiply(SolvableQuotient<C> b, SolvableQuotient<C> c) { 387 QuotSolvablePolynomial<C> Cp = ring.getZERO().copy(); 388 if (b == null || b.isZERO()) { 389 return Cp; 390 } 391 if (c == null || c.isZERO()) { 392 return Cp; 393 } 394 if (b.isONE() && c.isONE()) { 395 return this; 396 } 397 Cp = new QuotSolvablePolynomial<C>(ring, b, ring.evzero); 398 QuotSolvablePolynomial<C> Dp = new QuotSolvablePolynomial<C>(ring, c, ring.evzero); 399 return multiply(Cp, Dp); 400 } 401 402 403 /** 404 * QuotSolvablePolynomial multiplication. Product with exponent vector. 405 * @param e exponent. 406 * @return this * x<sup>e</sup>, where * denotes solvable multiplication. 407 */ 408 @Override 409 public QuotSolvablePolynomial<C> multiply(ExpVector e) { 410 if (e == null || e.isZERO()) { 411 return this; 412 } 413 SolvableQuotient<C> b = ring.getONECoefficient(); 414 return multiply(b, e); 415 } 416 417 418 /** 419 * QuotSolvablePolynomial left and right multiplication. Product with 420 * exponent vector. 421 * @param e exponent. 422 * @param f exponent. 423 * @return x<sup>e</sup> * this * x<sup>f</sup>, where * denotes solvable 424 * multiplication. 425 */ 426 @Override 427 public QuotSolvablePolynomial<C> multiply(ExpVector e, ExpVector f) { 428 if (e == null || e.isZERO()) { 429 return this; 430 } 431 if (f == null || f.isZERO()) { 432 return this; 433 } 434 SolvableQuotient<C> b = ring.getONECoefficient(); 435 return multiply(b, e, b, f); 436 } 437 438 439 /** 440 * QuotSolvablePolynomial multiplication. Product with ring element and 441 * exponent vector. 442 * @param b coefficient polynomial. 443 * @param e exponent. 444 * @return this * b x<sup>e</sup>, where * denotes solvable multiplication. 445 */ 446 @Override 447 public QuotSolvablePolynomial<C> multiply(SolvableQuotient<C> b, ExpVector e) { 448 if (b == null || b.isZERO()) { 449 return ring.getZERO(); 450 } 451 if (b.isONE() && e.isZERO()) { 452 return this; 453 } 454 QuotSolvablePolynomial<C> Cp = new QuotSolvablePolynomial<C>(ring, b, e); 455 return multiply(Cp); 456 } 457 458 459 /** 460 * QuotSolvablePolynomial left and right multiplication. Product with ring 461 * element and exponent vector. 462 * @param b coefficient polynomial. 463 * @param e exponent. 464 * @param c coefficient polynomial. 465 * @param f exponent. 466 * @return b x<sup>e</sup> * this * c x<sup>f</sup>, where * denotes 467 * solvable multiplication. 468 */ 469 @Override 470 public QuotSolvablePolynomial<C> multiply(SolvableQuotient<C> b, ExpVector e, SolvableQuotient<C> c, 471 ExpVector f) { 472 if (b == null || b.isZERO()) { 473 return ring.getZERO(); 474 } 475 if (c == null || c.isZERO()) { 476 return ring.getZERO(); 477 } 478 if (b.isONE() && e.isZERO() && c.isONE() && f.isZERO()) { 479 return this; 480 } 481 QuotSolvablePolynomial<C> Cp = new QuotSolvablePolynomial<C>(ring, b, e); 482 QuotSolvablePolynomial<C> Dp = new QuotSolvablePolynomial<C>(ring, c, f); 483 return multiply(Cp, Dp); 484 } 485 486 487 /** 488 * QuotSolvablePolynomial multiplication. Left product with ring element and 489 * exponent vector. 490 * @param b coefficient polynomial. 491 * @param e exponent. 492 * @return b x<sup>e</sup> * this, where * denotes solvable multiplication. 493 */ 494 @Override 495 public QuotSolvablePolynomial<C> multiplyLeft(SolvableQuotient<C> b, ExpVector e) { 496 if (b == null || b.isZERO()) { 497 return ring.getZERO(); 498 } 499 QuotSolvablePolynomial<C> Cp = new QuotSolvablePolynomial<C>(ring, b, e); 500 return Cp.multiply(this); 501 } 502 503 504 /** 505 * QuotSolvablePolynomial multiplication. Left product with exponent vector. 506 * @param e exponent. 507 * @return x<sup>e</sup> * this, where * denotes solvable multiplication. 508 */ 509 @Override 510 public QuotSolvablePolynomial<C> multiplyLeft(ExpVector e) { 511 if (e == null || e.isZERO()) { 512 return this; 513 } 514 SolvableQuotient<C> b = ring.getONECoefficient(); 515 QuotSolvablePolynomial<C> Cp = new QuotSolvablePolynomial<C>(ring, b, e); 516 return Cp.multiply(this); 517 } 518 519 520 /** 521 * QuotSolvablePolynomial multiplication. Left product with coefficient ring 522 * element. 523 * @param b coefficient polynomial. 524 * @return b*this, where * is coefficient multiplication. 525 */ 526 @Override 527 public QuotSolvablePolynomial<C> multiplyLeft(SolvableQuotient<C> b) { 528 QuotSolvablePolynomial<C> Cp = ring.getZERO().copy(); 529 if (b == null || b.isZERO()) { 530 return Cp; 531 } 532 Map<ExpVector, SolvableQuotient<C>> Cm = Cp.val; //getMap(); 533 Map<ExpVector, SolvableQuotient<C>> Am = val; 534 SolvableQuotient<C> c; 535 for (Map.Entry<ExpVector, SolvableQuotient<C>> y : Am.entrySet()) { 536 ExpVector e = y.getKey(); 537 SolvableQuotient<C> a = y.getValue(); 538 c = b.multiply(a); 539 if (!c.isZERO()) { 540 Cm.put(e, c); 541 } 542 } 543 return Cp; 544 } 545 546 547 /** 548 * QuotSolvablePolynomial multiplication. Left product with 'monomial'. 549 * @param m 'monomial'. 550 * @return m * this, where * denotes solvable multiplication. 551 */ 552 @Override 553 public QuotSolvablePolynomial<C> multiplyLeft(Map.Entry<ExpVector, SolvableQuotient<C>> m) { 554 if (m == null) { 555 return ring.getZERO(); 556 } 557 return multiplyLeft(m.getValue(), m.getKey()); 558 } 559 560 561 /** 562 * QuotSolvablePolynomial multiplication. Product with 'monomial'. 563 * @param m 'monomial'. 564 * @return this * m, where * denotes solvable multiplication. 565 */ 566 @Override 567 public QuotSolvablePolynomial<C> multiply(Map.Entry<ExpVector, SolvableQuotient<C>> m) { 568 if (m == null) { 569 return ring.getZERO(); 570 } 571 return multiply(m.getValue(), m.getKey()); 572 } 573 574 575 /** 576 * QuotSolvablePolynomial multiplication. Left product with coefficient ring 577 * element. 578 * @param f exponent vector. 579 * @return B*f, where * is commutative multiplication. 580 */ 581 protected QuotSolvablePolynomial<C> shift(ExpVector f) { 582 QuotSolvablePolynomial<C> C = ring.getZERO().copy(); 583 if (this.isZERO()) { 584 return C; 585 } 586 if (f == null || f.isZERO()) { 587 return this; 588 } 589 Map<ExpVector, SolvableQuotient<C>> Cm = C.val; 590 Map<ExpVector, SolvableQuotient<C>> Bm = this.val; 591 for (Map.Entry<ExpVector, SolvableQuotient<C>> y : Bm.entrySet()) { 592 ExpVector e = y.getKey(); 593 SolvableQuotient<C> a = y.getValue(); 594 ExpVector d = e.sum(f); 595 if (!a.isZERO()) { 596 Cm.put(d, a); 597 } 598 } 599 return C; 600 } 601 602}