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