001/* 002 * $Id: QLRSolvablePolynomial.java 5934 2018-09-30 11:23:44Z kredel $ 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 * QLRSolvablePolynomial multiplication. 138 * @param Bp QLRSolvablePolynomial. 139 * @return this*Bp, where * denotes solvable multiplication. 140 */ 141 // not @Override 142 @SuppressWarnings("unchecked") 143 public QLRSolvablePolynomial<C, D> multiply(QLRSolvablePolynomial<C, D> Bp) { 144 if (Bp == null || Bp.isZERO()) { 145 return ring.getZERO(); 146 } 147 if (this.isZERO()) { 148 return this; 149 } 150 if (Bp.isONE()) { 151 return this; 152 } 153 if (this.isONE()) { 154 return Bp; 155 } 156 assert (ring.nvar == Bp.ring.nvar); 157 if (debug) { 158 logger.debug("ring = " + ring); 159 } 160 //System.out.println("this = " + this + ", Bp = " + Bp); 161 ExpVector Z = ring.evzero; 162 QLRSolvablePolynomial<C, D> Dp = ring.getZERO().copy(); 163 QLRSolvablePolynomial<C, D> zero = ring.getZERO().copy(); 164 C one = ring.getONECoefficient(); 165 166 Map<ExpVector, C> A = val; 167 Map<ExpVector, C> B = Bp.val; 168 Set<Map.Entry<ExpVector, C>> Bk = B.entrySet(); 169 for (Map.Entry<ExpVector, C> y : A.entrySet()) { 170 C a = y.getValue(); 171 ExpVector e = y.getKey(); 172 if (debug) 173 logger.info("e = " + e + ", a = " + a); 174 //int[] ep = e.dependencyOnVariables(); 175 //int el1 = ring.nvar + 1; 176 //if (ep.length > 0) { 177 // el1 = ep[0]; 178 //} 179 //int el1s = ring.nvar + 1 - el1; 180 for (Map.Entry<ExpVector, C> x : Bk) { 181 C b = x.getValue(); 182 ExpVector f = x.getKey(); 183 if (debug) 184 logger.info("f = " + f + ", b = " + b); 185 int[] fp = f.dependencyOnVariables(); 186 int fl1 = 0; 187 if (fp.length > 0) { 188 fl1 = fp[fp.length - 1]; 189 } 190 int fl1s = ring.nvar + 1 - fl1; 191 // polynomial with coefficient multiplication 192 QLRSolvablePolynomial<C, D> Cps = ring.getZERO().copy(); 193 //QLRSolvablePolynomial<C, D> Cs; 194 QLRSolvablePolynomial<C, D> qp; 195 if (ring.polCoeff.isCommutative() || b.isConstant() || e.isZERO()) { // symmetric 196 Cps = new QLRSolvablePolynomial<C, D>(ring, b, e); 197 if (debug) 198 logger.info("symmetric coeff: b = " + b + ", e = " + e); 199 } else { // unsymmetric 200 if (debug) 201 logger.info("unsymmetric coeff: b = " + b + ", e = " + e); 202 // compute e * b as ( e * 1/b.den ) * b.num 203 if (b.denominator().isONE()) { // recursion base 204 // recursive polynomial coefficient multiplication : e * b.num 205 RecSolvablePolynomial<D> rsp1 = new RecSolvablePolynomial<D>(ring.polCoeff, e); 206 RecSolvablePolynomial<D> rsp2 = new RecSolvablePolynomial<D>(ring.polCoeff, 207 b.numerator()); 208 RecSolvablePolynomial<D> rsp3 = rsp1.multiply(rsp2); 209 QLRSolvablePolynomial<C, D> rsp = ring.fromPolyCoefficients(rsp3); 210 Cps = rsp; 211 } else { // b.denominator() != 1 212 if (debug) 213 logger.info("coeff-num: Cps = " + Cps + ", num = " + b.numerator() + ", den = " 214 + b.denominator()); 215 RingFactory<C> bfq = (RingFactory<C>) b.factory(); 216 Cps = new QLRSolvablePolynomial<C, D>(ring, bfq.getONE(), e); 217 218 // coefficient multiplication with 1/den: 219 QLRSolvablePolynomial<C, D> qv = Cps; 220 //C qden = new C(b.denominator().factory(), b.denominator()); // den/1 221 C qden = ring.qpfac.create(b.denominator()); // den/1 222 //System.out.println("qv = " + qv + ", den = " + den); 223 // recursion with den==1: 224 QLRSolvablePolynomial<C, D> v = qv.multiply(qden); 225 QLRSolvablePolynomial<C, D> vl = qv.multiplyLeft(qden); 226 //System.out.println("v = " + v + ", vl = " + vl + ", qden = " + qden); 227 QLRSolvablePolynomial<C, D> vr = (QLRSolvablePolynomial<C, D>) v.subtract(vl); 228 //C qdeni = new C(b.factory(), b.factory().getONE().numerator(), b.denominator()); 229 C qdeni = ring.qpfac.create(ring.qpfac.pairFactory().getONE(), b.denominator()); // 1/den 230 //System.out.println("vr = " + vr + ", qdeni = " + qdeni); 231 // recursion with smaller head term: 232 if (qv.leadingExpVector().equals(vr.leadingExpVector())) { 233 throw new IllegalArgumentException("qr !> vr: qv = " + qv + ", vr = " + vr); 234 } 235 QLRSolvablePolynomial<C, D> rq = vr.multiply(qdeni); 236 qp = (QLRSolvablePolynomial<C, D>) qv.subtract(rq); 237 qp = qp.multiplyLeft(qdeni); 238 //System.out.println("qp_i = " + qp); 239 Cps = qp; 240 241 if (!b.numerator().isONE()) { 242 //C qnum = new C(b.denominator().factory(), b.numerator()); // num/1 243 C qnum = ring.qpfac.create(b.numerator()); // num/1 244 // recursion with den == 1: 245 Cps = Cps.multiply(qnum); 246 } 247 } 248 } // end coeff 249 if (debug) 250 logger.info("coeff-den: Cps = " + Cps); 251 // polynomial multiplication 252 QLRSolvablePolynomial<C, D> Dps = ring.getZERO().copy(); 253 QLRSolvablePolynomial<C, D> Ds = null; 254 QLRSolvablePolynomial<C, D> D1, D2; 255 if (ring.isCommutative() || Cps.isConstant() || f.isZERO()) { // symmetric 256 if (debug) 257 logger.info("symmetric poly: b = " + b + ", e = " + e); 258 if (Cps.isConstant()) { 259 ExpVector g = e.sum(f); 260 Ds = new QLRSolvablePolynomial<C, D>(ring, Cps.leadingBaseCoefficient(), g); // symmetric! 261 } else { 262 Ds = Cps.shift(f); // symmetric 263 } 264 } else { // eventually unsymmetric 265 if (debug) 266 logger.info("unsymmetric poly: Cps = " + Cps + ", f = " + f); 267 for (Map.Entry<ExpVector, C> z : Cps.val.entrySet()) { 268 // split g = g1 * g2, f = f1 * f2 269 C c = z.getValue(); 270 ExpVector g = z.getKey(); 271 if (debug) 272 logger.info("g = " + g + ", c = " + c); 273 int[] gp = g.dependencyOnVariables(); 274 int gl1 = ring.nvar + 1; 275 if (gp.length > 0) { 276 gl1 = gp[0]; 277 } 278 int gl1s = ring.nvar + 1 - gl1; 279 if (gl1s <= fl1s) { // symmetric 280 ExpVector h = g.sum(f); 281 if (debug) 282 logger.info("disjoint poly: g = " + g + ", f = " + f + ", h = " + h); 283 Ds = (QLRSolvablePolynomial<C, D>) zero.sum(one, h); // symmetric! 284 } else { 285 ExpVector g1 = g.subst(gl1, 0); 286 ExpVector g2 = Z.subst(gl1, g.getVal(gl1)); // bug el1, gl1 287 ExpVector g4; 288 ExpVector f1 = f.subst(fl1, 0); 289 ExpVector f2 = Z.subst(fl1, f.getVal(fl1)); 290 if (debug) { 291 logger.info("poly, g1 = " + g1 + ", f1 = " + f1 + ", Dps = " + Dps); 292 logger.info("poly, g2 = " + g2 + ", f2 = " + f2); 293 } 294 TableRelation<C> rel = ring.table.lookup(g2, f2); 295 if (debug) 296 logger.info("poly, g = " + g + ", f = " + f + ", rel = " + rel); 297 Ds = new QLRSolvablePolynomial<C, D>(ring, rel.p); //ring.copy(rel.p); 298 if (rel.f != null) { 299 D2 = new QLRSolvablePolynomial<C, D>(ring, one, rel.f); 300 Ds = Ds.multiply(D2); 301 if (rel.e == null) { 302 g4 = g2; 303 } else { 304 g4 = g2.subtract(rel.e); 305 } 306 ring.table.update(g4, f2, Ds); 307 } 308 if (rel.e != null) { 309 D1 = new QLRSolvablePolynomial<C, D>(ring, one, rel.e); 310 Ds = D1.multiply(Ds); 311 ring.table.update(g2, f2, Ds); 312 } 313 if (!f1.isZERO()) { 314 D2 = new QLRSolvablePolynomial<C, D>(ring, one, f1); 315 Ds = Ds.multiply(D2); 316 //ring.table.update(?,f1,Ds) 317 } 318 if (!g1.isZERO()) { 319 D1 = new QLRSolvablePolynomial<C, D>(ring, one, g1); 320 Ds = D1.multiply(Ds); 321 //ring.table.update(e1,?,Ds) 322 } 323 } 324 Ds = Ds.multiplyLeft(c); // c * Ds 325 //Dps = (QLRSolvablePolynomial<C, D>) Dps.sum(Ds); 326 Dps.doAddTo(Ds); 327 } // end Dps loop 328 Ds = Dps; 329 } 330 Ds = Ds.multiplyLeft(a); // multiply(a,b); // non-symmetric 331 if (debug) 332 logger.debug("Ds = " + Ds); 333 //Dp = (QLRSolvablePolynomial<C, D>) Dp.sum(Ds); 334 Dp.doAddTo(Ds); 335 } // end B loop 336 } // end A loop 337 //System.out.println("this * Bp = " + Dp); 338 return Dp; 339 } 340 341 342 /** 343 * QLRSolvablePolynomial left and right multiplication. Product with two 344 * polynomials. 345 * @param S QLRSolvablePolynomial. 346 * @param T QLRSolvablePolynomial. 347 * @return S*this*T. 348 */ 349 // not @Override 350 public QLRSolvablePolynomial<C, D> multiply(QLRSolvablePolynomial<C, D> S, QLRSolvablePolynomial<C, D> T) { 351 if (S.isZERO() || T.isZERO() || this.isZERO()) { 352 return ring.getZERO(); 353 } 354 if (S.isONE()) { 355 return multiply(T); 356 } 357 if (T.isONE()) { 358 return S.multiply(this); 359 } 360 return S.multiply(this).multiply(T); 361 } 362 363 364 /** 365 * QLRSolvablePolynomial multiplication. Product with coefficient ring 366 * element. 367 * @param b solvable coefficient. 368 * @return this*b, where * is coefficient multiplication. 369 */ 370 @Override 371 public QLRSolvablePolynomial<C, D> multiply(C b) { 372 QLRSolvablePolynomial<C, D> Cp = ring.getZERO().copy(); 373 if (b == null || b.isZERO()) { 374 return Cp; 375 } 376 if (b.isONE()) { 377 return this; 378 } 379 Cp = new QLRSolvablePolynomial<C, D>(ring, b, ring.evzero); 380 return multiply(Cp); 381 } 382 383 384 /** 385 * QLRSolvablePolynomial left and right multiplication. Product with 386 * coefficient ring element. 387 * @param b coefficient polynomial. 388 * @param c coefficient polynomial. 389 * @return b*this*c, where * is coefficient multiplication. 390 */ 391 @Override 392 public QLRSolvablePolynomial<C, D> multiply(C b, C c) { 393 QLRSolvablePolynomial<C, D> Cp = ring.getZERO().copy(); 394 if (b == null || b.isZERO()) { 395 return Cp; 396 } 397 if (c == null || c.isZERO()) { 398 return Cp; 399 } 400 if (b.isONE() && c.isONE()) { 401 return this; 402 } 403 Cp = new QLRSolvablePolynomial<C, D>(ring, b, ring.evzero); 404 QLRSolvablePolynomial<C, D> Dp = new QLRSolvablePolynomial<C, D>(ring, c, ring.evzero); 405 return multiply(Cp, Dp); 406 } 407 408 409 /** 410 * QLRSolvablePolynomial multiplication. Product with exponent vector. 411 * @param e exponent. 412 * @return this * x<sup>e</sup>, where * denotes solvable multiplication. 413 */ 414 @Override 415 public QLRSolvablePolynomial<C, D> multiply(ExpVector e) { 416 if (e == null || e.isZERO()) { 417 return this; 418 } 419 C b = ring.getONECoefficient(); 420 return multiply(b, e); 421 } 422 423 424 /** 425 * QLRSolvablePolynomial left and right multiplication. Product with 426 * exponent vector. 427 * @param e exponent. 428 * @param f exponent. 429 * @return x<sup>e</sup> * this * x<sup>f</sup>, where * denotes solvable 430 * multiplication. 431 */ 432 @Override 433 public QLRSolvablePolynomial<C, D> multiply(ExpVector e, ExpVector f) { 434 if (e == null || e.isZERO()) { 435 return this; 436 } 437 if (f == null || f.isZERO()) { 438 return this; 439 } 440 C b = ring.getONECoefficient(); 441 return multiply(b, e, b, f); 442 } 443 444 445 /** 446 * QLRSolvablePolynomial multiplication. Product with ring element and 447 * exponent vector. 448 * @param b coefficient polynomial. 449 * @param e exponent. 450 * @return this * b x<sup>e</sup>, where * denotes solvable multiplication. 451 */ 452 @Override 453 public QLRSolvablePolynomial<C, D> multiply(C b, ExpVector e) { 454 if (b == null || b.isZERO()) { 455 return ring.getZERO(); 456 } 457 if (b.isONE() && e.isZERO()) { 458 return this; 459 } 460 QLRSolvablePolynomial<C, D> Cp = new QLRSolvablePolynomial<C, D>(ring, b, e); 461 return multiply(Cp); 462 } 463 464 465 /** 466 * QLRSolvablePolynomial left and right multiplication. Product with ring 467 * element and exponent vector. 468 * @param b coefficient polynomial. 469 * @param e exponent. 470 * @param c coefficient polynomial. 471 * @param f exponent. 472 * @return b x<sup>e</sup> * this * c x<sup>f</sup>, where * denotes 473 * solvable multiplication. 474 */ 475 @Override 476 public QLRSolvablePolynomial<C, D> multiply(C b, ExpVector e, C c, ExpVector f) { 477 if (b == null || b.isZERO()) { 478 return ring.getZERO(); 479 } 480 if (c == null || c.isZERO()) { 481 return ring.getZERO(); 482 } 483 if (b.isONE() && e.isZERO() && c.isONE() && f.isZERO()) { 484 return this; 485 } 486 QLRSolvablePolynomial<C, D> Cp = new QLRSolvablePolynomial<C, D>(ring, b, e); 487 QLRSolvablePolynomial<C, D> Dp = new QLRSolvablePolynomial<C, D>(ring, c, f); 488 return multiply(Cp, Dp); 489 } 490 491 492 /** 493 * QLRSolvablePolynomial multiplication. Left product with ring element and 494 * exponent vector. 495 * @param b coefficient polynomial. 496 * @param e exponent. 497 * @return b x<sup>e</sup> * this, where * denotes solvable multiplication. 498 */ 499 @Override 500 public QLRSolvablePolynomial<C, D> multiplyLeft(C b, ExpVector e) { 501 if (b == null || b.isZERO()) { 502 return ring.getZERO(); 503 } 504 QLRSolvablePolynomial<C, D> Cp = new QLRSolvablePolynomial<C, D>(ring, b, e); 505 return Cp.multiply(this); 506 } 507 508 509 /** 510 * QLRSolvablePolynomial multiplication. Left product with exponent vector. 511 * @param e exponent. 512 * @return x<sup>e</sup> * this, where * denotes solvable multiplication. 513 */ 514 @Override 515 public QLRSolvablePolynomial<C, D> multiplyLeft(ExpVector e) { 516 if (e == null || e.isZERO()) { 517 return this; 518 } 519 C b = ring.getONECoefficient(); 520 QLRSolvablePolynomial<C, D> Cp = new QLRSolvablePolynomial<C, D>(ring, b, e); 521 return Cp.multiply(this); 522 } 523 524 525 /** 526 * QLRSolvablePolynomial multiplication. Left product with coefficient ring 527 * element. 528 * @param b coefficient polynomial. 529 * @return b*this, where * is coefficient multiplication. 530 */ 531 @Override 532 public QLRSolvablePolynomial<C, D> multiplyLeft(C b) { 533 QLRSolvablePolynomial<C, D> Cp = ring.getZERO().copy(); 534 if (b == null || b.isZERO()) { 535 return Cp; 536 } 537 Map<ExpVector, C> Cm = Cp.val; //getMap(); 538 Map<ExpVector, C> Am = val; 539 C c; 540 for (Map.Entry<ExpVector, C> y : Am.entrySet()) { 541 ExpVector e = y.getKey(); 542 C a = y.getValue(); 543 c = b.multiply(a); 544 if (!c.isZERO()) { 545 Cm.put(e, c); 546 } 547 } 548 return Cp; 549 } 550 551 552 /** 553 * QLRSolvablePolynomial multiplication. Left product with 'monomial'. 554 * @param m 'monomial'. 555 * @return m * this, where * denotes solvable multiplication. 556 */ 557 @Override 558 public QLRSolvablePolynomial<C, D> multiplyLeft(Map.Entry<ExpVector, C> m) { 559 if (m == null) { 560 return ring.getZERO(); 561 } 562 return multiplyLeft(m.getValue(), m.getKey()); 563 } 564 565 566 /** 567 * QLRSolvablePolynomial multiplication. Product with 'monomial'. 568 * @param m 'monomial'. 569 * @return this * m, where * denotes solvable multiplication. 570 */ 571 @Override 572 public QLRSolvablePolynomial<C, D> multiply(Map.Entry<ExpVector, C> m) { 573 if (m == null) { 574 return ring.getZERO(); 575 } 576 return multiply(m.getValue(), m.getKey()); 577 } 578 579 580 /** 581 * QLRSolvablePolynomial multiplication with exponent vector. 582 * @param f exponent vector. 583 * @return B*f, where * is commutative multiplication. 584 */ 585 protected QLRSolvablePolynomial<C, D> shift(ExpVector f) { 586 QLRSolvablePolynomial<C, D> C = ring.getZERO().copy(); 587 if (this.isZERO()) { 588 return C; 589 } 590 if (f == null || f.isZERO()) { 591 return this; 592 } 593 Map<ExpVector, C> Cm = C.val; 594 Map<ExpVector, C> Bm = this.val; 595 for (Map.Entry<ExpVector, C> y : Bm.entrySet()) { 596 ExpVector e = y.getKey(); 597 C a = y.getValue(); 598 ExpVector d = e.sum(f); 599 if (!a.isZERO()) { 600 Cm.put(d, a); 601 } 602 } 603 return C; 604 } 605 606}