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