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