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