001/* 002 * $Id$ 003 */ 004 005package edu.jas.gbufd; 006 007 008import java.util.List; 009import java.util.Map; 010 011import org.apache.logging.log4j.Logger; 012import org.apache.logging.log4j.LogManager; 013 014import edu.jas.gb.SolvableReductionAbstract; 015import edu.jas.poly.ExpVector; 016import edu.jas.poly.GenPolynomial; 017import edu.jas.poly.GenPolynomialRing; 018import edu.jas.poly.GenSolvablePolynomial; 019import edu.jas.poly.GenSolvablePolynomialRing; 020import edu.jas.poly.PolyUtil; 021import edu.jas.structure.GcdRingElem; 022 023 024/** 025 * Polynomial pseudo reduction sequential use algorithm. Coefficients of 026 * polynomials must not be from a field, i.e. the fraction free reduction is 027 * implemented. Implements normalform. 028 * @param <C> coefficient type 029 * @author Heinz Kredel 030 */ 031 032public class SolvablePseudoReductionSeq<C extends GcdRingElem<C>> extends SolvableReductionAbstract<C> 033 implements SolvablePseudoReduction<C> { 034 035 036 private static final Logger logger = LogManager.getLogger(SolvablePseudoReductionSeq.class); 037 038 039 private static final boolean debug = logger.isDebugEnabled(); 040 041 042 /** 043 * Constructor. 044 */ 045 public SolvablePseudoReductionSeq() { 046 } 047 048 049 /** 050 * Left normalform. 051 * @param Ap polynomial. 052 * @param Pp polynomial list. 053 * @return nf(Ap) with respect to Pp. 054 */ 055 @SuppressWarnings("unchecked") 056 public GenSolvablePolynomial<C> leftNormalform(List<GenSolvablePolynomial<C>> Pp, 057 GenSolvablePolynomial<C> Ap) { 058 if (Pp == null || Pp.isEmpty()) { 059 return Ap; 060 } 061 if (Ap == null || Ap.isZERO()) { 062 return Ap; 063 } 064 Map.Entry<ExpVector, C> m; 065 GenSolvablePolynomial<C>[] P = new GenSolvablePolynomial[0]; 066 synchronized (Pp) { 067 P = Pp.toArray(P); 068 } 069 int l = P.length; 070 ExpVector[] htl = new ExpVector[l]; 071 //C[] lbc = (C[]) new GcdRingElem[l]; 072 GenSolvablePolynomial<C>[] p = new GenSolvablePolynomial[l]; 073 int i; 074 int j = 0; 075 for (i = 0; i < l; i++) { 076 if (P[i] == null) { 077 continue; 078 } 079 p[i] = P[i]; 080 m = p[i].leadingMonomial(); 081 if (m != null) { 082 p[j] = p[i]; 083 htl[j] = m.getKey(); 084 //lbc[j] = m.getValue(); 085 j++; 086 } 087 } 088 l = j; 089 ExpVector e; 090 C a; 091 boolean mt = false; 092 GenSolvablePolynomial<C> R = Ap.ring.getZERO().copy(); 093 GenSolvablePolynomial<C> Q = null; 094 GenSolvablePolynomial<C> S = Ap.copy(); 095 while (S.length() > 0) { 096 m = S.leadingMonomial(); 097 e = m.getKey(); 098 a = m.getValue(); 099 for (i = 0; i < l; i++) { 100 mt = e.multipleOf(htl[i]); 101 if (mt) 102 break; 103 } 104 if (!mt) { 105 //logger.debug("irred"); 106 //R = R.sum(a, e); 107 //S = S.subtract(a, e); 108 R.doPutToMap(e, a); 109 S.doRemoveFromMap(e, a); 110 //System.out.println(" S = " + S); 111 } else { 112 e = e.subtract(htl[i]); 113 //logger.info("red div = {}", e); 114 Q = p[i].multiplyLeft(e); 115 C c = Q.leadingBaseCoefficient(); 116 ExpVector g = S.leadingExpVector(); 117 C ap = a; 118 if (a.remainder(c).isZERO()) { // && !c.isConstant()) { 119 a = a.divide(c); 120 S = S.subtractMultiple(a, Q); 121 } else { 122 R = R.multiplyLeft(c); 123 S = S.scaleSubtractMultiple(c, a, Q); 124 } 125 ExpVector h = S.leadingExpVector(); 126 if (g.equals(h)) { // Ore condition not fulfilled 127 logger.info("g==h: g = {}, c = {}", g, c); 128 throw new RuntimeException("g.equals(h): a = " + a + ", ap = " + ap + ", c = " + c); 129 } 130 } 131 } 132 return R; 133 } 134 135 136 /** 137 * Left normalform recursive. 138 * @param Ap recursive polynomial. 139 * @param Pp recursive polynomial list. 140 * @return nf(Ap) with respect to Pp. 141 */ 142 @SuppressWarnings({ "unchecked" }) 143 public GenSolvablePolynomial<GenPolynomial<C>> leftNormalformRecursive( 144 List<GenSolvablePolynomial<GenPolynomial<C>>> Pp, 145 GenSolvablePolynomial<GenPolynomial<C>> Ap) { 146 if (Pp == null || Pp.isEmpty()) { 147 return Ap; 148 } 149 if (Ap == null || Ap.isZERO()) { 150 return Ap; 151 } 152 Map.Entry<ExpVector, GenPolynomial<C>> m; 153 GenSolvablePolynomial<GenPolynomial<C>>[] P = new GenSolvablePolynomial[0]; 154 synchronized (Pp) { 155 P = Pp.toArray(P); 156 } 157 int l = P.length; 158 ExpVector[] htl = new ExpVector[l]; 159 //GenPolynomial<C>[] lbc = (GenPolynomial<C>[]) new GenPolynomial[l]; 160 GenSolvablePolynomial<GenPolynomial<C>>[] p = new GenSolvablePolynomial[l]; 161 int i; 162 int j = 0; 163 for (i = 0; i < l; i++) { 164 if (P[i] == null) { 165 continue; 166 } 167 p[i] = P[i]; 168 m = p[i].leadingMonomial(); 169 if (m != null) { 170 p[j] = p[i]; 171 htl[j] = m.getKey(); 172 //lbc[j] = m.getValue(); 173 j++; 174 } 175 } 176 l = j; 177 ExpVector e, f; 178 GenPolynomial<C> a, b; 179 boolean mt = false; 180 GenSolvablePolynomialRing<GenPolynomial<C>> ring = Ap.ring; 181 final boolean commCoeff = ring.coFac.isCommutative(); 182 final SolvableSyzygyAbstract<C> ssy; 183 if (commCoeff) { 184 ssy = null; 185 } else { 186 ssy = new SolvableSyzygySeq<C>(((GenPolynomialRing<C>) ring.coFac).coFac); 187 } 188 GenSolvablePolynomial<GenPolynomial<C>> R = Ap.ring.getZERO().copy(); 189 GenSolvablePolynomial<GenPolynomial<C>> Q = null; 190 GenSolvablePolynomial<GenPolynomial<C>> S = Ap.copy(); 191 //GenSolvablePolynomial<GenPolynomial<C>> Sp = null; 192 while (S.length() > 0) { 193 m = S.leadingMonomial(); 194 e = m.getKey(); 195 a = m.getValue(); 196 for (i = 0; i < l; i++) { 197 mt = e.multipleOf(htl[i]); 198 if (mt) 199 break; 200 } 201 if (!mt) { 202 //logger.debug("irred"); 203 //R = R.sum(a, e); 204 //S = S.subtract(a, e); 205 R.doPutToMap(e, a); 206 S.doRemoveFromMap(e, a); 207 //System.out.println(" S = " + S); 208 } else { 209 f = e.subtract(htl[i]); 210 if (debug) { 211 logger.info("red div = {}", f); 212 //logger.info("red a = {}", a); 213 } 214 Q = p[i].multiplyLeft(f); 215 //if (a.remainder(c).isZERO()) { //c.isUnit() ) { 216 ExpVector g = S.leadingExpVector(); 217 GenPolynomial<C> ap = a; 218 if (commCoeff) { 219 GenPolynomial<C> c = Q.leadingBaseCoefficient(); 220 if (!c.isConstant() && PolyUtil.<C> baseSparsePseudoRemainder(a, c).isZERO()) { 221 //a = a.divide(c); 222 b = PolyUtil.<C> basePseudoDivide(a, c); 223 if (a.equals(b.multiply(c))) { 224 S = S.subtractMultiple(b, Q); 225 } else { 226 R = R.multiplyLeft(c); 227 S = S.scaleSubtractMultiple(c, a, Q); 228 } 229 } else { 230 R = R.multiplyLeft(c); 231 S = S.scaleSubtractMultiple(c, a, Q); 232 } 233 } else { // use Ore condition 234 GenSolvablePolynomial<C> cs = (GenSolvablePolynomial<C>) Q.leadingBaseCoefficient(); 235 GenSolvablePolynomial<C> as = (GenSolvablePolynomial<C>) a; 236 GenPolynomial<C>[] ore = ssy.leftOreCond(cs, as); 237 //System.out.println("cs = " + cs + ", as = " + as); 238 //System.out.println("ore[0] = " + ore[0] + "\nore[1] = " + ore[1]); 239 R = R.multiplyLeft(ore[1]); 240 S = S.scaleSubtractMultiple(ore[1], ore[0], Q); 241 } 242 ExpVector h = S.leadingExpVector(); 243 if (g.equals(h)) { // ! Ore cond 244 logger.info("g==h: g = {}", g); 245 throw new RuntimeException("g.equals(h): a = " + a + ", ap = " + ap); 246 } 247 } 248 } 249 //System.out.println("Ap = " + Ap + ", R = " + R); 250 return R; 251 } 252 253 254 /** 255 * Left normalform with recording. <b>Note:</b> Only meaningful if all 256 * divisions are exact. Compute first the multiplication factor 257 * <code>m</code> with <code>normalform(Pp,Ap,m)</code>, then call this 258 * method with <code>normalform(row,Pp,m*Ap)</code>. 259 * @param row recording matrix, is modified. 260 * @param Pp a polynomial list for reduction. 261 * @param Ap a polynomial. 262 * @return nf(Pp,Ap), the normal form of Ap wrt. Pp. 263 */ 264 @SuppressWarnings("unchecked") 265 public GenSolvablePolynomial<C> leftNormalform(List<GenSolvablePolynomial<C>> row, 266 List<GenSolvablePolynomial<C>> Pp, GenSolvablePolynomial<C> Ap) { 267 if (Pp == null || Pp.isEmpty()) { 268 return Ap; 269 } 270 if (Ap == null || Ap.isZERO()) { 271 return Ap; 272 } 273 GenSolvablePolynomial<C>[] P = new GenSolvablePolynomial[0]; 274 synchronized (Pp) { 275 P = Pp.toArray(P); 276 } 277 int l = P.length; 278 ExpVector[] htl = new ExpVector[l]; 279 //C[] lbc = (C[]) new GcdRingElem[l]; 280 GenSolvablePolynomial<C>[] p = new GenSolvablePolynomial[l]; 281 Map.Entry<ExpVector, C> m; 282 int j = 0; 283 int i; 284 for (i = 0; i < l; i++) { 285 p[i] = P[i]; 286 m = p[i].leadingMonomial(); 287 if (m != null) { 288 p[j] = p[i]; 289 htl[j] = m.getKey(); 290 //lbc[j] = m.getValue(); 291 j++; 292 } 293 } 294 l = j; 295 ExpVector e; 296 C a; 297 boolean mt = false; 298 GenSolvablePolynomial<C> zero = Ap.ring.getZERO(); 299 GenSolvablePolynomial<C> R = Ap.ring.getZERO().copy(); 300 GenSolvablePolynomial<C> Q = null; 301 GenSolvablePolynomial<C> fac = null; 302 GenSolvablePolynomial<C> S = Ap.copy(); 303 while (S.length() > 0) { 304 m = S.leadingMonomial(); 305 e = m.getKey(); 306 a = m.getValue(); 307 for (i = 0; i < l; i++) { 308 mt = e.multipleOf(htl[i]); 309 if (mt) 310 break; 311 } 312 if (!mt) { 313 //logger.debug("irred"); 314 //R = R.sum(a, e); 315 //S = S.subtract(a, e); 316 R.doPutToMap(e, a); 317 S.doRemoveFromMap(e, a); 318 // System.out.println(" S = " + S); 319 //throw new RuntimeException("Syzygy no GB"); 320 } else { 321 e = e.subtract(htl[i]); 322 //logger.info("red div = {}", e); 323 Q = p[i].multiplyLeft(e); 324 C c = Q.leadingBaseCoefficient(); 325 ExpVector g = S.leadingExpVector(); 326 C ap = a; 327 if (a.remainder(c).isZERO()) { //c.isUnit() ) { 328 a = a.divide(c); 329 S = S.subtractMultiple(a, Q); 330 //System.out.print("|"); 331 } else { 332 //System.out.print("*"); 333 R = R.multiplyLeft(c); 334 S = S.scaleSubtractMultiple(c, a, Q); 335 } 336 ExpVector h = S.leadingExpVector(); 337 if (g.equals(h)) { // Ore condition not fulfilled 338 System.out.println("g = " + g + ", h = " + h); 339 System.out.println("c*ap = " + c.multiply(ap) + ", ap*c = " + ap.multiply(c)); 340 throw new RuntimeException("g.equals(h): a = " + a + ", ap = " + ap + ", c = " + c); 341 } 342 //Q = p[i].multiply(a, e); 343 //S = S.subtract(Q); 344 fac = row.get(i); 345 if (fac == null) { 346 fac = (GenSolvablePolynomial<C>) zero.sum(a, e); 347 } else { // doAddTo ?? 348 fac = (GenSolvablePolynomial<C>) fac.sum(a, e); 349 } 350 row.set(i, fac); 351 } 352 } 353 return R; 354 } 355 356 357 /** 358 * Left normalform with factor. 359 * @param Pp polynomial list. 360 * @param Ap polynomial. 361 * @return ( nf(Ap), mf ) with respect to Pp and mf as multiplication factor 362 * for Ap. 363 */ 364 @SuppressWarnings("unchecked") 365 public PseudoReductionEntry<C> leftNormalformFactor(List<GenSolvablePolynomial<C>> Pp, 366 GenSolvablePolynomial<C> Ap) { 367 if (Ap == null) { 368 return null; 369 } 370 C mfac = Ap.ring.getONECoefficient(); 371 PseudoReductionEntry<C> pf = new PseudoReductionEntry<C>(Ap, mfac); 372 if (Pp == null || Pp.isEmpty()) { 373 return pf; 374 } 375 if (Ap.isZERO()) { 376 return pf; 377 } 378 Map.Entry<ExpVector, C> m; 379 GenSolvablePolynomial<C>[] P = new GenSolvablePolynomial[0]; 380 synchronized (Pp) { 381 P = Pp.toArray(P); 382 } 383 int l = P.length; 384 ExpVector[] htl = new ExpVector[l]; 385 //C[] lbc = (C[]) new GcdRingElem[l]; 386 GenSolvablePolynomial<C>[] p = new GenSolvablePolynomial[l]; 387 int i; 388 int j = 0; 389 for (i = 0; i < l; i++) { 390 if (P[i] == null) { 391 continue; 392 } 393 p[i] = P[i]; 394 m = p[i].leadingMonomial(); 395 if (m != null) { 396 p[j] = p[i]; 397 htl[j] = m.getKey(); 398 //lbc[j] = m.getValue(); 399 j++; 400 } 401 } 402 l = j; 403 ExpVector e; 404 C a; 405 boolean mt = false; 406 GenSolvablePolynomial<C> R = Ap.ring.getZERO().copy(); 407 GenSolvablePolynomial<C> Q = null; 408 GenSolvablePolynomial<C> S = Ap.copy(); 409 while (S.length() > 0) { 410 m = S.leadingMonomial(); 411 e = m.getKey(); 412 a = m.getValue(); 413 for (i = 0; i < l; i++) { 414 mt = e.multipleOf(htl[i]); 415 if (mt) 416 break; 417 } 418 if (!mt) { 419 //logger.debug("irred"); 420 //R = R.sum(a, e); 421 //S = S.subtract(a, e); 422 R.doPutToMap(e, a); 423 S.doRemoveFromMap(e, a); 424 //System.out.println(" S = " + S); 425 } else { 426 e = e.subtract(htl[i]); 427 //logger.info("red div = {}", e); 428 Q = p[i].multiplyLeft(e); 429 C c = Q.leadingBaseCoefficient(); 430 ExpVector g = S.leadingExpVector(); 431 C ap = a; 432 if (a.remainder(c).isZERO()) { 433 a = a.divide(c); 434 S = S.subtractMultiple(a, Q); 435 } else { 436 mfac = c.multiply(mfac); // left 437 R = R.multiplyLeft(c); 438 S = S.scaleSubtractMultiple(c, a, Q); 439 } 440 ExpVector h = S.leadingExpVector(); 441 if (g.equals(h)) { // Ore condition not fulfilled 442 logger.info("g==h: g = {}, c = {}", g, c); 443 throw new RuntimeException("g==h: a = " + a + ", ap = " + ap); 444 } 445 } 446 } 447 logger.info("multiplicative factor = {}", mfac); 448 pf = new PseudoReductionEntry<C>(R, mfac); 449 return pf; 450 } 451 452 453 /** 454 * Right normalform. 455 * @param Ap polynomial. 456 * @param Pp polynomial list. 457 * @return nf(Ap) with respect to Pp. 458 */ 459 @SuppressWarnings({ "unchecked" }) 460 public GenSolvablePolynomial<C> rightNormalform(List<GenSolvablePolynomial<C>> Pp, 461 GenSolvablePolynomial<C> Ap) { 462 if (Pp == null || Pp.isEmpty()) { 463 return Ap; 464 } 465 if (Ap == null || Ap.isZERO()) { 466 return Ap; 467 } 468 Map.Entry<ExpVector, C> m; 469 GenSolvablePolynomial<C>[] P = new GenSolvablePolynomial[0]; 470 synchronized (Pp) { 471 P = Pp.toArray(P); 472 } 473 int l = P.length; 474 ExpVector[] htl = new ExpVector[l]; 475 //C[] lbc = (C[]) new GcdRingElem[l]; 476 GenSolvablePolynomial<C>[] p = new GenSolvablePolynomial[l]; 477 int i; 478 int j = 0; 479 for (i = 0; i < l; i++) { 480 if (P[i] == null) { 481 continue; 482 } 483 p[i] = P[i]; 484 m = p[i].leadingMonomial(); 485 if (m != null) { 486 p[j] = p[i]; 487 htl[j] = m.getKey(); 488 //lbc[j] = m.getValue(); 489 j++; 490 } 491 } 492 l = j; 493 ExpVector e; 494 C a; 495 boolean mt = false; 496 GenSolvablePolynomial<C> R = Ap.ring.getZERO().copy(); 497 GenSolvablePolynomial<C> Q = null; 498 GenSolvablePolynomial<C> S = Ap.copy(); 499 while (S.length() > 0) { 500 m = S.leadingMonomial(); 501 e = m.getKey(); 502 a = m.getValue(); 503 for (i = 0; i < l; i++) { 504 mt = e.multipleOf(htl[i]); 505 if (mt) 506 break; 507 } 508 if (!mt) { 509 //logger.debug("irred"); 510 //R = R.sum(a, e); 511 //S = S.subtract(a, e); 512 R.doPutToMap(e, a); 513 S.doRemoveFromMap(e, a); 514 //System.out.println(" S = " + S); 515 } else { 516 e = e.subtract(htl[i]); 517 //logger.info("red div = {}", e); 518 // need pi * a * e, but only pi * e * a or a * pi * e available 519 Q = p[i].multiply(e); 520 assert Q.multiply(a).equals(Q.multiplyLeft(a)); 521 C c = Q.leadingBaseCoefficient(); 522 ExpVector g = S.leadingExpVector(); 523 C ap = a; 524 if (a.remainder(c).isZERO()) { 525 a = a.divide(c); // left? 526 //S = S.subtractMultiple(Q,a); 527 S = (GenSolvablePolynomial<C>) S.subtract(Q.multiply(a)); 528 } else { 529 R = R.multiply(c); 530 S = S.multiply(c); 531 //S = S.scaleSubtractMultiple(c, Q, a); 532 S = (GenSolvablePolynomial<C>) S.subtract(Q.multiply(a)); 533 } 534 ExpVector h = S.leadingExpVector(); 535 if (g.equals(h)) { // Ore condition not fulfilled 536 logger.info("g==h: g = {}, c = {}", g, c); 537 throw new RuntimeException("g.equals(h): a = " + a + ", ap = " + ap); 538 } 539 } 540 } 541 //System.out.println("R = " + R); 542 return R; 543 } 544 545 546 /** 547 * Right normalform recursive. 548 * @param Ap recursive polynomial. 549 * @param Pp recursive polynomial list. 550 * @return nf(Ap) with respect to Pp. <b>Note: </b> not implemented; 551 */ 552 public GenSolvablePolynomial<GenPolynomial<C>> rightNormalformRecursive( 553 List<GenSolvablePolynomial<GenPolynomial<C>>> Pp, 554 GenSolvablePolynomial<GenPolynomial<C>> Ap) { 555 if (Pp == null || Ap == null) { 556 throw new IllegalArgumentException("Pp or Ap == null not supported"); 557 } 558 throw new UnsupportedOperationException(); // TODO 559 } 560 561 562 /** 563 * Left normalform with recording. <b>Note:</b> Only meaningful if all 564 * divisions are exact. Compute first the multiplication factor 565 * <code>m</code> with <code>normalform(Pp,Ap,m)</code>, then call this 566 * method with <code>normalform(row,Pp,m*Ap)</code>. 567 * @param row recording matrix, is modified. 568 * @param Pp a polynomial list for reduction. 569 * @param Ap a polynomial. 570 * @return nf(Pp,Ap), the normal form of Ap wrt. Pp. <b>Note: </b> not 571 * implemented; 572 */ 573 public GenSolvablePolynomial<C> rightNormalform(List<GenSolvablePolynomial<C>> row, 574 List<GenSolvablePolynomial<C>> Pp, GenSolvablePolynomial<C> Ap) { 575 if (row == null || Pp == null || Ap == null) { 576 throw new IllegalArgumentException("row, Pp or Ap == null not supported"); 577 } 578 throw new UnsupportedOperationException(); // TODO 579 } 580 581 582 /** 583 * Right normalform with multiplication factor. 584 * @param Pp polynomial list. 585 * @param Ap polynomial. 586 * @return ( nf(Ap), mf ) with respect to Pp and mf as multiplication factor 587 * for Ap. <b>Note: </b> not implemented; 588 */ 589 public PseudoReductionEntry<C> rightNormalformFactor(List<GenSolvablePolynomial<C>> Pp, 590 GenSolvablePolynomial<C> Ap) { 591 if (Pp == null || Ap == null) { 592 throw new IllegalArgumentException("Pp or Ap == null not supported"); 593 } 594 throw new UnsupportedOperationException(); // TODO 595 } 596 597}