001/* 002 * $Id: ResidueSolvablePolynomial.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.RecSolvablePolynomial; 018import edu.jas.poly.TableRelation; 019import edu.jas.structure.GcdRingElem; 020 021 022/** 023 * ResidueSolvablePolynomial generic solvable polynomials with solvable residue 024 * coefficients implementing RingElem. n-variate ordered solvable polynomials 025 * over solvable residue coefficients. Objects of this class are intended to be 026 * immutable. The implementation is based on TreeMap respectively SortedMap from 027 * exponents to coefficients by extension of GenPolynomial. 028 * @param <C> coefficient type 029 * @author Heinz Kredel 030 */ 031 032public class ResidueSolvablePolynomial<C extends GcdRingElem<C>> extends 033 GenSolvablePolynomial<SolvableResidue<C>> { 034 035 036 /** 037 * The factory for the recursive solvable polynomial ring. Hides super.ring. 038 */ 039 public final ResidueSolvablePolynomialRing<C> ring; 040 041 042 private static final Logger logger = LogManager.getLogger(ResidueSolvablePolynomial.class); 043 044 045 private static final boolean debug = logger.isDebugEnabled(); 046 047 048 /** 049 * Constructor for zero ResidueSolvablePolynomial. 050 * @param r solvable polynomial ring factory. 051 */ 052 public ResidueSolvablePolynomial(ResidueSolvablePolynomialRing<C> r) { 053 super(r); 054 ring = r; 055 } 056 057 058 /** 059 * Constructor for ResidueSolvablePolynomial. 060 * @param r solvable polynomial ring factory. 061 * @param e exponent. 062 */ 063 public ResidueSolvablePolynomial(ResidueSolvablePolynomialRing<C> r, ExpVector e) { 064 this(r); 065 val.put(e, ring.getONECoefficient()); 066 } 067 068 069 /** 070 * Constructor for ResidueSolvablePolynomial. 071 * @param r solvable polynomial ring factory. 072 * @param c coefficient polynomial. 073 * @param e exponent. 074 */ 075 public ResidueSolvablePolynomial(ResidueSolvablePolynomialRing<C> r, SolvableResidue<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 ResidueSolvablePolynomial. 085 * @param r solvable polynomial ring factory. 086 * @param c coefficient polynomial. 087 */ 088 public ResidueSolvablePolynomial(ResidueSolvablePolynomialRing<C> r, SolvableResidue<C> c) { 089 this(r, c, r.evzero); 090 } 091 092 093 /** 094 * Constructor for ResidueSolvablePolynomial. 095 * @param r solvable polynomial ring factory. 096 * @param S solvable polynomial. 097 */ 098 public ResidueSolvablePolynomial(ResidueSolvablePolynomialRing<C> r, 099 GenSolvablePolynomial<SolvableResidue<C>> S) { 100 this(r, S.getMap()); 101 } 102 103 104 /** 105 * Constructor for ResidueSolvablePolynomial. 106 * @param r solvable polynomial ring factory. 107 * @param v the SortedMap of some other (solvable) polynomial. 108 */ 109 protected ResidueSolvablePolynomial(ResidueSolvablePolynomialRing<C> r, 110 SortedMap<ExpVector, SolvableResidue<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 ResidueSolvablePolynomialRing<C> factory() { 123 return ring; 124 } 125 126 127 /** 128 * Clone this ResidueSolvablePolynomial. 129 * @see java.lang.Object#clone() 130 */ 131 @Override 132 public ResidueSolvablePolynomial<C> copy() { 133 return new ResidueSolvablePolynomial<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 ResidueSolvablePolynomial)) { 144 return false; 145 } 146 return super.equals(B); 147 } 148 149 150 /** 151 * ResidueSolvablePolynomial multiplication. 152 * @param Bp ResidueSolvablePolynomial. 153 * @return this*Bp, where * denotes solvable multiplication. 154 */ 155 public ResidueSolvablePolynomial<C> multiply(ResidueSolvablePolynomial<C> Bp) { 156 if (Bp == null || Bp.isZERO()) { 157 return ring.getZERO(); 158 } 159 if (this.isZERO()) { 160 return this; 161 } 162 assert (ring.nvar == Bp.ring.nvar); 163 if (debug) { 164 logger.debug("ring = " + ring); 165 } 166 ExpVector Z = ring.evzero; 167 ResidueSolvablePolynomial<C> Dp = ring.getZERO().copy(); 168 ResidueSolvablePolynomial<C> zero = ring.getZERO().copy(); 169 SolvableResidue<C> one = ring.getONECoefficient(); 170 171 //ResidueSolvablePolynomial<C> C1 = null; 172 //ResidueSolvablePolynomial<C> C2 = null; 173 Map<ExpVector, SolvableResidue<C>> A = val; 174 Map<ExpVector, SolvableResidue<C>> B = Bp.val; 175 Set<Map.Entry<ExpVector, SolvableResidue<C>>> Bk = B.entrySet(); 176 for (Map.Entry<ExpVector, SolvableResidue<C>> y : A.entrySet()) { 177 SolvableResidue<C> a = y.getValue(); 178 ExpVector e = y.getKey(); 179 if (debug) 180 logger.info("e = " + e + ", a = " + a); 181 //int[] ep = e.dependencyOnVariables(); 182 //int el1 = ring.nvar + 1; 183 //if (ep.length > 0) { 184 // el1 = ep[0]; 185 //} 186 //int el1s = ring.nvar + 1 - el1; 187 for (Map.Entry<ExpVector, SolvableResidue<C>> x : Bk) { 188 SolvableResidue<C> b = x.getValue(); 189 ExpVector f = x.getKey(); 190 if (debug) 191 logger.info("f = " + f + ", b = " + b); 192 int[] fp = f.dependencyOnVariables(); 193 int fl1 = 0; 194 if (fp.length > 0) { 195 fl1 = fp[fp.length - 1]; 196 } 197 int fl1s = ring.nvar + 1 - fl1; 198 // polynomial coefficient multiplication 199 ResidueSolvablePolynomial<C> Cps = ring.getZERO().copy(); 200 //ResidueSolvablePolynomial<C> Cs = null; 201 if (ring.polCoeff.coeffTable.isEmpty() || b.isConstant() || e.isZERO()) { // symmetric 202 Cps = new ResidueSolvablePolynomial<C>(ring, b, e); 203 if (debug) 204 logger.info("symmetric coeff: b = " + b + ", e = " + e); 205 } else { // unsymmetric 206 if (debug) 207 logger.info("unsymmetric coeff: b = " + b + ", e = " + e); 208 // recursive polynomial coefficient multiplication : e * b.val 209 RecSolvablePolynomial<C> rsp1 = new RecSolvablePolynomial<C>(ring.polCoeff, e); 210 RecSolvablePolynomial<C> rsp2 = new RecSolvablePolynomial<C>(ring.polCoeff, b.val); 211 RecSolvablePolynomial<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 ResidueSolvablePolynomial<C> Dps = ring.getZERO().copy(); 219 ResidueSolvablePolynomial<C> Ds = null; 220 ResidueSolvablePolynomial<C> D1, D2; 221 if (ring.table.isEmpty() || Cps.isConstant() || f.isZERO()) { // symmetric 222 if (debug) 223 logger.info("symmetric poly: b = " + b + ", e = " + e); 224 ExpVector g = e.sum(f); 225 if (Cps.isConstant()) { 226 Ds = new ResidueSolvablePolynomial<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 = " + Cps + ", f = " + f); 233 for (Map.Entry<ExpVector, SolvableResidue<C>> z : Cps.val.entrySet()) { 234 // split g = g1 * g2, f = f1 * f2 235 SolvableResidue<C> c = z.getValue(); 236 ExpVector g = z.getKey(); 237 if (debug) 238 logger.info("g = " + g + ", c = " + 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 = " + g + ", f = " + f + ", h = " + h); 249 Ds = (ResidueSolvablePolynomial<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 = " + g1 + ", f1 = " + f1 + ", Dps = " + Dps); 258 if (debug) 259 logger.info("poly, g2 = " + g2 + ", f2 = " + f2); 260 TableRelation<SolvableResidue<C>> rel = ring.table.lookup(g2, f2); 261 if (debug) 262 logger.info("poly, g = " + g + ", f = " + f + ", rel = " + rel); 263 Ds = new ResidueSolvablePolynomial<C>(ring, rel.p); //ring.copy(rel.p); 264 if (rel.f != null) { 265 D2 = new ResidueSolvablePolynomial<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 ResidueSolvablePolynomial<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 ResidueSolvablePolynomial<C>(ring, one, f1); 281 Ds = Ds.multiply(D2); 282 //ring.table.update(?,f1,Ds) 283 } 284 if (!g1.isZERO()) { 285 D1 = new ResidueSolvablePolynomial<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 = (ResidueSolvablePolynomial<C>) Dps.sum(Ds); 292 } // end Dps loop 293 Ds = Dps; 294 } 295 Ds = Ds.multiplyLeft(a); // multiply(a,b); // non-symmetric 296 if (debug) 297 logger.debug("Ds = " + Ds); 298 Dp = (ResidueSolvablePolynomial<C>) Dp.sum(Ds); 299 } // end B loop 300 } // end A loop 301 return Dp; 302 } 303 304 305 /** 306 * ResidueSolvablePolynomial left and right multiplication. Product with two 307 * polynomials. 308 * @param S ResidueSolvablePolynomial. 309 * @param T ResidueSolvablePolynomial. 310 * @return S*this*T. 311 */ 312 public ResidueSolvablePolynomial<C> multiply(ResidueSolvablePolynomial<C> S, 313 ResidueSolvablePolynomial<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 * ResidueSolvablePolynomial multiplication. Product with coefficient ring 329 * element. 330 * @param b coefficient polynomial. 331 * @return this*b, where * is coefficient multiplication. 332 */ 333 @Override 334 public ResidueSolvablePolynomial<C> multiply(SolvableResidue<C> b) { 335 ResidueSolvablePolynomial<C> Cp = ring.getZERO().copy(); 336 if (b == null || b.isZERO()) { 337 return Cp; 338 } 339 Cp = new ResidueSolvablePolynomial<C>(ring, b, ring.evzero); 340 return multiply(Cp); 341 } 342 343 344 /** 345 * ResidueSolvablePolynomial left and right multiplication. Product with 346 * coefficient ring element. 347 * @param b coefficient polynomial. 348 * @param c coefficient polynomial. 349 * @return b*this*c, where * is coefficient multiplication. 350 */ 351 @Override 352 public ResidueSolvablePolynomial<C> multiply(SolvableResidue<C> b, SolvableResidue<C> c) { 353 ResidueSolvablePolynomial<C> Cp = ring.getZERO().copy(); 354 if (b == null || b.isZERO()) { 355 return Cp; 356 } 357 if (c == null || c.isZERO()) { 358 return Cp; 359 } 360 ResidueSolvablePolynomial<C> Cb = new ResidueSolvablePolynomial<C>(ring, b, ring.evzero); 361 ResidueSolvablePolynomial<C> Cc = new ResidueSolvablePolynomial<C>(ring, c, ring.evzero); 362 return Cb.multiply(this).multiply(Cc); 363 } 364 365 366 /** 367 * ResidueSolvablePolynomial multiplication. Product with exponent vector. 368 * @param e exponent. 369 * @return this * x<sup>e</sup>, where * denotes solvable multiplication. 370 */ 371 @Override 372 public ResidueSolvablePolynomial<C> multiply(ExpVector e) { 373 if (e == null || e.isZERO()) { 374 return this; 375 } 376 SolvableResidue<C> b = ring.getONECoefficient(); 377 return multiply(b, e); 378 } 379 380 381 /** 382 * ResidueSolvablePolynomial left and right multiplication. Product with 383 * exponent vector. 384 * @param e exponent. 385 * @param f exponent. 386 * @return x<sup>e</sup> * this * x<sup>f</sup>, where * denotes solvable 387 * multiplication. 388 */ 389 @Override 390 public ResidueSolvablePolynomial<C> multiply(ExpVector e, ExpVector f) { 391 if (e == null || e.isZERO()) { 392 return this; 393 } 394 if (f == null || f.isZERO()) { 395 return this; 396 } 397 SolvableResidue<C> b = ring.getONECoefficient(); 398 return multiply(b, e, b, f); 399 } 400 401 402 /** 403 * ResidueSolvablePolynomial multiplication. Product with ring element and 404 * exponent vector. 405 * @param b coefficient polynomial. 406 * @param e exponent. 407 * @return this * b x<sup>e</sup>, where * denotes solvable multiplication. 408 */ 409 @Override 410 public ResidueSolvablePolynomial<C> multiply(SolvableResidue<C> b, ExpVector e) { 411 if (b == null || b.isZERO()) { 412 return ring.getZERO(); 413 } 414 ResidueSolvablePolynomial<C> Cp = new ResidueSolvablePolynomial<C>(ring, b, e); 415 return multiply(Cp); 416 } 417 418 419 /** 420 * ResidueSolvablePolynomial left and right multiplication. Product with 421 * ring element and exponent vector. 422 * @param b coefficient polynomial. 423 * @param e exponent. 424 * @param c coefficient polynomial. 425 * @param f exponent. 426 * @return b x<sup>e</sup> * this * c x<sup>f</sup>, where * denotes 427 * solvable multiplication. 428 */ 429 @Override 430 public ResidueSolvablePolynomial<C> multiply(SolvableResidue<C> b, ExpVector e, SolvableResidue<C> c, 431 ExpVector f) { 432 if (b == null || b.isZERO()) { 433 return ring.getZERO(); 434 } 435 if (c == null || c.isZERO()) { 436 return ring.getZERO(); 437 } 438 ResidueSolvablePolynomial<C> Cp = new ResidueSolvablePolynomial<C>(ring, b, e); 439 ResidueSolvablePolynomial<C> Dp = new ResidueSolvablePolynomial<C>(ring, c, f); 440 return multiply(Cp, Dp); 441 } 442 443 444 /** 445 * ResidueSolvablePolynomial multiplication. Left product with ring element 446 * and exponent vector. 447 * @param b coefficient polynomial. 448 * @param e exponent. 449 * @return b x<sup>e</sup> * this, where * denotes solvable multiplication. 450 */ 451 @Override 452 public ResidueSolvablePolynomial<C> multiplyLeft(SolvableResidue<C> b, ExpVector e) { 453 if (b == null || b.isZERO()) { 454 return ring.getZERO(); 455 } 456 ResidueSolvablePolynomial<C> Cp = new ResidueSolvablePolynomial<C>(ring, b, e); 457 return Cp.multiply(this); 458 } 459 460 461 /** 462 * ResidueSolvablePolynomial multiplication. Left product with exponent 463 * vector. 464 * @param e exponent. 465 * @return x<sup>e</sup> * this, where * denotes solvable multiplication. 466 */ 467 @Override 468 public ResidueSolvablePolynomial<C> multiplyLeft(ExpVector e) { 469 if (e == null || e.isZERO()) { 470 return this; 471 } 472 SolvableResidue<C> b = ring.getONECoefficient(); 473 ResidueSolvablePolynomial<C> Cp = new ResidueSolvablePolynomial<C>(ring, b, e); 474 return Cp.multiply(this); 475 } 476 477 478 /** 479 * ResidueSolvablePolynomial multiplication. Left product with coefficient 480 * ring element. 481 * @param b coefficient polynomial. 482 * @return b*this, where * is coefficient multiplication. 483 */ 484 @Override 485 public ResidueSolvablePolynomial<C> multiplyLeft(SolvableResidue<C> b) { 486 ResidueSolvablePolynomial<C> Cp = ring.getZERO().copy(); 487 if (b == null || b.isZERO()) { 488 return Cp; 489 } 490 Map<ExpVector, SolvableResidue<C>> Cm = Cp.val; //getMap(); 491 Map<ExpVector, SolvableResidue<C>> Am = val; 492 SolvableResidue<C> c; 493 for (Map.Entry<ExpVector, SolvableResidue<C>> y : Am.entrySet()) { 494 ExpVector e = y.getKey(); 495 SolvableResidue<C> a = y.getValue(); 496 c = b.multiply(a); 497 if (!c.isZERO()) { 498 Cm.put(e, c); 499 } 500 } 501 return Cp; 502 } 503 504 505 /** 506 * ResidueSolvablePolynomial multiplication. Left product with 'monomial'. 507 * @param m 'monomial'. 508 * @return m * this, where * denotes solvable multiplication. 509 */ 510 @Override 511 public ResidueSolvablePolynomial<C> multiplyLeft(Map.Entry<ExpVector, SolvableResidue<C>> m) { 512 if (m == null) { 513 return ring.getZERO(); 514 } 515 return multiplyLeft(m.getValue(), m.getKey()); 516 } 517 518 519 /** 520 * ResidueSolvablePolynomial multiplication. Product with 'monomial'. 521 * @param m 'monomial'. 522 * @return this * m, where * denotes solvable multiplication. 523 */ 524 @Override 525 public ResidueSolvablePolynomial<C> multiply(Map.Entry<ExpVector, SolvableResidue<C>> m) { 526 if (m == null) { 527 return ring.getZERO(); 528 } 529 return multiply(m.getValue(), m.getKey()); 530 } 531 532 533 /** 534 * ResidueSolvablePolynomial multiplication with exponent vector. 535 * @param f exponent vector. 536 * @return B*f, where * is commutative multiplication. 537 */ 538 protected ResidueSolvablePolynomial<C> shift(ExpVector f) { 539 ResidueSolvablePolynomial<C> C = ring.getZERO().copy(); 540 if (this.isZERO()) { 541 return C; 542 } 543 if (f == null || f.isZERO()) { 544 return this; 545 } 546 Map<ExpVector, SolvableResidue<C>> Cm = C.val; 547 Map<ExpVector, SolvableResidue<C>> Bm = this.val; 548 for (Map.Entry<ExpVector, SolvableResidue<C>> y : Bm.entrySet()) { 549 ExpVector e = y.getKey(); 550 SolvableResidue<C> a = y.getValue(); 551 ExpVector d = e.sum(f); 552 if (!a.isZERO()) { 553 Cm.put(d, a); 554 } 555 } 556 return C; 557 } 558 559}