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