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