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