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