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