001/* 002 * $Id: WordReductionSeq.java 5869 2018-07-20 15:53:10Z kredel $ 003 */ 004 005package edu.jas.gb; 006 007 008import java.util.ArrayList; 009import java.util.List; 010import java.util.Map; 011 012import org.apache.logging.log4j.Logger; 013import org.apache.logging.log4j.LogManager; 014 015import edu.jas.poly.GenWordPolynomial; 016import edu.jas.poly.Word; 017import edu.jas.structure.RingElem; 018 019 020/** 021 * Polynomial word reduction sequential use algorithm. Implements normalform. 022 * @param <C> coefficient type 023 * @author Heinz Kredel 024 */ 025 026public class WordReductionSeq<C extends RingElem<C>> // should be FieldElem<C>> 027 extends WordReductionAbstract<C> { 028 029 030 private static final Logger logger = LogManager.getLogger(WordReductionSeq.class); 031 032 033 private static final boolean debug = logger.isDebugEnabled(); 034 035 036 /** 037 * Constructor. 038 */ 039 public WordReductionSeq() { 040 } 041 042 043 /** 044 * Normalform. 045 * @param Ap polynomial. 046 * @param Pp polynomial list. 047 * @return nf(Ap) with respect to Pp. 048 */ 049 @SuppressWarnings("unchecked") 050 public GenWordPolynomial<C> normalform(List<GenWordPolynomial<C>> Pp, GenWordPolynomial<C> Ap) { 051 if (Pp == null || Pp.isEmpty()) { 052 return Ap; 053 } 054 if (Ap == null || Ap.isZERO()) { 055 return Ap; 056 } 057 if (!Ap.ring.coFac.isField()) { 058 throw new IllegalArgumentException("coefficients not from a field"); 059 } 060 Map.Entry<Word, C> m; 061 int l; 062 GenWordPolynomial<C>[] P; 063 synchronized (Pp) { 064 l = Pp.size(); 065 P = new GenWordPolynomial[l]; 066 //P = Pp.toArray(); 067 for (int i = 0; i < Pp.size(); i++) { 068 P[i] = Pp.get(i); 069 } 070 } 071 Word[] htl = new Word[l]; 072 C[] lbc = (C[]) new RingElem[l]; // want C[] 073 GenWordPolynomial<C>[] p = new GenWordPolynomial[l]; 074 int i; 075 int j = 0; 076 for (i = 0; i < l; i++) { 077 p[i] = P[i]; 078 m = p[i].leadingMonomial(); 079 if (m != null) { 080 p[j] = p[i]; 081 htl[j] = m.getKey(); 082 lbc[j] = m.getValue(); 083 j++; 084 } 085 } 086 l = j; 087 Word e, f, g; 088 C a; 089 boolean mt = false; 090 GenWordPolynomial<C> R = Ap.ring.getZERO(); 091 C cone = Ap.ring.coFac.getONE(); 092 093 //GenWordPolynomial<C> T = null; 094 GenWordPolynomial<C> Q = null; 095 GenWordPolynomial<C> S = Ap; 096 while (S.length() > 0) { 097 m = S.leadingMonomial(); 098 e = m.getKey(); 099 a = m.getValue(); 100 for (i = 0; i < l; i++) { 101 mt = e.multipleOf(htl[i]); 102 if (mt) 103 break; 104 } 105 if (!mt) { 106 //logger.debug("irred"); 107 //T = new OrderedMapPolynomial( a, e ); 108 R = R.sum(a, e); 109 S = S.subtract(a, e); 110 // System.out.println(" S = " + S); 111 } else { 112 Word[] elr = e.divideWord(htl[i]); 113 g = e; 114 e = elr[0]; 115 f = elr[1]; 116 if (debug) { 117 logger.info("red divideWord: e = " + e + ", f = " + f); 118 } 119 a = a.divide(lbc[i]); 120 Q = p[i].multiply(a, e, cone, f); 121 S = S.subtract(Q); 122 if (!S.isZERO() && g.equals(S.leadingWord())) { 123 throw new RuntimeException("HT(S) not descending"); 124 } 125 } 126 } 127 return R; 128 } 129 130 131 /** 132 * Normalform with left and right recording. 133 * @param lrow left recording matrix, is modified. 134 * @param rrow right recording matrix, is modified. 135 * @param Pp a polynomial list for reduction. 136 * @param Ap a polynomial. 137 * @return nf(Pp,Ap), the normal form of Ap wrt. Pp. 138 */ 139 @SuppressWarnings("unchecked") 140 public GenWordPolynomial<C> normalform(List<GenWordPolynomial<C>> lrow, List<GenWordPolynomial<C>> rrow, 141 List<GenWordPolynomial<C>> Pp, GenWordPolynomial<C> Ap) { 142 if (Pp == null || Pp.isEmpty()) { 143 return Ap; 144 } 145 if (Ap == null || Ap.isZERO()) { 146 return Ap; 147 } 148 if (!Ap.ring.coFac.isField()) { 149 throw new IllegalArgumentException("coefficients not from a field"); 150 } 151 int l = Pp.size(); 152 GenWordPolynomial<C>[] P = new GenWordPolynomial[l]; 153 synchronized (Pp) { 154 //P = Pp.toArray(); 155 for (int i = 0; i < Pp.size(); i++) { 156 P[i] = Pp.get(i); 157 } 158 } 159 Word[] htl = new Word[l]; 160 C[] lbc = (C[]) new RingElem[l]; 161 GenWordPolynomial<C>[] p = new GenWordPolynomial[l]; 162 Map.Entry<Word, C> m; 163 int j = 0; 164 int i; 165 for (i = 0; i < l; i++) { 166 p[i] = P[i]; 167 m = p[i].leadingMonomial(); 168 if (m != null) { 169 p[j] = p[i]; 170 htl[j] = m.getKey(); 171 lbc[j] = m.getValue(); 172 j++; 173 } 174 } 175 l = j; 176 Word e, g; 177 C a, b, lc, rc; 178 boolean mt = false; 179 GenWordPolynomial<C> zero = Ap.ring.getZERO(); 180 GenWordPolynomial<C> one = Ap.ring.getONE(); 181 GenWordPolynomial<C> R = Ap.ring.getZERO(); 182 C cone = Ap.ring.coFac.getONE(); 183 // ensure polynomials at each index 184 for (i = 0; i < lrow.size(); i++) { 185 GenWordPolynomial<C> w = lrow.get(i); 186 if (w == null) { 187 lrow.set(i, zero); 188 } 189 w = rrow.get(i); 190 if (w == null) { 191 rrow.set(i, zero); 192 } 193 } 194 195 GenWordPolynomial<C> fac = null; 196 // GenWordPolynomial<C> T = null; 197 GenWordPolynomial<C> Q = null; 198 GenWordPolynomial<C> S = Ap; 199 while (S.length() > 0) { 200 m = S.leadingMonomial(); 201 e = m.getKey(); 202 a = m.getValue(); 203 for (i = 0; i < l; i++) { 204 mt = e.multipleOf(htl[i]); 205 if (mt) 206 break; 207 } 208 if (!mt) { 209 //logger.debug("irred"); 210 R = R.sum(a, e); 211 S = S.subtract(a, e); 212 // System.out.println("S = " + S); 213 } else { 214 g = e; 215 Word[] elr = e.divideWord(htl[i]); 216 e = elr[0]; 217 Word f = elr[1]; 218 if (debug) { 219 logger.info("redRec divideWord: e = " + e + ", f = " + f + ", htl = " + htl[i]); 220 } 221 C c = lbc[i]; 222 b = a.divide(c); 223 if (e.isONE()) { // todo simplify multiply 224 lc = cone; 225 rc = b; 226 } else { 227 lc = b; 228 rc = cone; 229 } 230 Q = p[i].multiply(lc, e, rc, f); 231 S = S.subtract(Q); 232 //logger.info("redRec: S = " + S + ", R = " + R + ", Q = " + Q); 233 if (!S.isZERO() && g.equals(S.leadingWord())) { 234 System.out.println("divideWord: e = " + e + ", f = " + f); 235 System.out.println("R = " + R); 236 System.out.println("Q = " + Q + ", a = " + a + ", b = " + b + ", c = " + c); 237 throw new RuntimeException("HT(S) not descending, S = " + S); 238 } 239 // left row 240 fac = lrow.get(i); 241 boolean doset = true; 242 if (!lc.isONE() || !e.isONE()) { 243 if (!fac.coefficient(e).isZERO()) { 244 logger.warn("e exists in polynomial: " + fac + ", e = " + e + ", lc = " + lc); 245 logger.warn("f = " + f + ", rc = " + rc); 246 logger.warn("S = " + S + ", R = " + R); 247 } 248 fac = fac.sum(lc, e); 249 doset = false; 250 } 251 //logger.info("redRec: left = " + fac + ", lc = " + lc + ", e = " + e); 252 lrow.set(i, fac); 253 // right row 254 fac = rrow.get(i); 255 if (!rc.isONE() || !f.isONE() || doset) { 256 if (!fac.coefficient(f).isZERO()) { 257 logger.warn("f exists in polynomial: " + fac + ", f = " + f + ", rc = " + rc); 258 logger.warn("e = " + e + ", lc = " + lc); 259 logger.warn("S = " + S + ", R = " + R); 260 } 261 fac = fac.sum(rc, f); 262 } 263 //logger.info("redRec: right = " + fac + ", rc = " + rc + ", f = " + f); 264 rrow.set(i, fac); 265 } 266 } 267 // set factor to one if other non-zero 268 for (i = 0; i < lrow.size(); i++) { 269 GenWordPolynomial<C> lw = lrow.get(i); 270 GenWordPolynomial<C> rw = rrow.get(i); 271 if (!lw.isZERO() && rw.isZERO()) { 272 rrow.set(i, one); 273 } 274 if (lw.isZERO() && !rw.isZERO()) { 275 lrow.set(i, one); 276 } 277 } 278 return R; 279 } 280 281 282 /** 283 * Left normalform with recording. 284 * @param Pp a polynomial list for reduction. 285 * @param Ap a polynomial. 286 * @return nf(Pp,Ap), the left normal form of Ap wrt. Pp. 287 */ 288 public GenWordPolynomial<C> leftNormalform(List<GenWordPolynomial<C>> Pp, GenWordPolynomial<C> Ap) { 289 if (Pp == null || Pp.isEmpty()) { 290 return Ap; 291 } 292 if (Ap == null || Ap.isZERO()) { 293 return Ap; 294 } 295 List<GenWordPolynomial<C>> lrow = new ArrayList<GenWordPolynomial<C>>(Pp.size()); 296 for (int i = 0; i < Pp.size(); i++) { 297 lrow.add(Ap.ring.getZERO()); 298 } 299 GenWordPolynomial<C> r = leftNormalform(lrow, Pp, Ap); 300 return r; 301 } 302 303 304 /** 305 * Left normalform with recording. 306 * @param lrow left recording matrix, is modified. 307 * @param Pp a polynomial list for reduction. 308 * @param Ap a polynomial. 309 * @return nf(Pp,Ap), the left normal form of Ap wrt. Pp. 310 */ 311 @SuppressWarnings("unchecked") 312 public GenWordPolynomial<C> leftNormalform(List<GenWordPolynomial<C>> lrow, 313 List<GenWordPolynomial<C>> Pp, GenWordPolynomial<C> Ap) { 314 if (Pp == null || Pp.isEmpty()) { 315 return Ap; 316 } 317 if (Ap == null || Ap.isZERO()) { 318 return Ap; 319 } 320 if (!Ap.ring.coFac.isField()) { 321 throw new IllegalArgumentException("coefficients not from a field"); 322 } 323 int l = Pp.size(); 324 GenWordPolynomial<C>[] P = new GenWordPolynomial[l]; 325 synchronized (Pp) { 326 //P = Pp.toArray(); 327 for (int i = 0; i < Pp.size(); i++) { 328 P[i] = Pp.get(i); 329 } 330 } 331 Word[] htl = new Word[l]; 332 C[] lbc = (C[]) new RingElem[l]; // want C[] 333 GenWordPolynomial<C>[] p = new GenWordPolynomial[l]; 334 Map.Entry<Word, C> m; 335 int j = 0; 336 int i; 337 for (i = 0; i < l; i++) { 338 p[i] = P[i]; 339 m = p[i].leadingMonomial(); 340 if (m != null) { 341 p[j] = p[i]; 342 htl[j] = m.getKey(); 343 lbc[j] = m.getValue(); 344 j++; 345 } 346 } 347 l = j; 348 Word e; 349 C a; 350 boolean mt = false; 351 GenWordPolynomial<C> zero = Ap.ring.getZERO(); 352 GenWordPolynomial<C> R = Ap.ring.getZERO(); 353 C cone = Ap.ring.coFac.getONE(); 354 355 GenWordPolynomial<C> fac = null; 356 // GenWordPolynomial<C> T = null; 357 GenWordPolynomial<C> Q = null; 358 GenWordPolynomial<C> S = Ap; 359 while (S.length() > 0) { 360 m = S.leadingMonomial(); 361 e = m.getKey(); 362 a = m.getValue(); 363 for (i = 0; i < l; i++) { 364 mt = e.multipleOf(htl[i]); 365 if (mt) 366 break; 367 } 368 if (!mt) { 369 //logger.info("irred_1"); 370 R = R.sum(a, e); 371 S = S.subtract(a, e); 372 // System.out.println(" S = " + S); 373 } else { 374 Word g = e; 375 Word[] elr = e.divideWord(htl[i]); 376 e = elr[0]; 377 Word f = elr[1]; 378 if (debug) { 379 logger.info("redRec divideWord: e = " + e + ", f = " + f); 380 } 381 if (f.isONE()) { 382 C c = lbc[i]; 383 //System.out.println("a = " + a + ", c = " + c); 384 a = a.divide(c); 385 //System.out.println("a/c = " + a); 386 Q = p[i].multiply(a, e, cone, f); 387 S = S.subtract(Q); 388 // left row 389 fac = lrow.get(i); 390 if (fac == null) { 391 fac = zero.sum(a, e); 392 } else { 393 fac = fac.sum(a, e); 394 } 395 lrow.set(i, fac); 396 } else { 397 //logger.info("irred_2"); 398 R = R.sum(a, g); 399 S = S.subtract(a, g); 400 } 401 } 402 } 403 return R; 404 } 405 406 407 /** 408 * Right normalform with recording. 409 * @param Pp a polynomial list for reduction. 410 * @param Ap a polynomial. 411 * @return nf(Pp,Ap), the right normal form of Ap wrt. Pp. 412 */ 413 public GenWordPolynomial<C> rightNormalform(List<GenWordPolynomial<C>> Pp, GenWordPolynomial<C> Ap) { 414 if (Pp == null || Pp.isEmpty()) { 415 return Ap; 416 } 417 if (Ap == null || Ap.isZERO()) { 418 return Ap; 419 } 420 List<GenWordPolynomial<C>> lrow = new ArrayList<GenWordPolynomial<C>>(Pp.size()); 421 for (int i = 0; i < Pp.size(); i++) { 422 lrow.add(Ap.ring.getZERO()); 423 } 424 GenWordPolynomial<C> r = rightNormalform(lrow, Pp, Ap); 425 return r; 426 } 427 428 429 /** 430 * Right normalform with recording. 431 * @param rrow right recording matrix, is modified. 432 * @param Pp a polynomial list for reduction. 433 * @param Ap a polynomial. 434 * @return nf(Pp,Ap), the right normal form of Ap wrt. Pp. 435 */ 436 @SuppressWarnings("unchecked") 437 public GenWordPolynomial<C> rightNormalform(List<GenWordPolynomial<C>> rrow, 438 List<GenWordPolynomial<C>> Pp, GenWordPolynomial<C> Ap) { 439 if (Pp == null || Pp.isEmpty()) { 440 return Ap; 441 } 442 if (Ap == null || Ap.isZERO()) { 443 return Ap; 444 } 445 if (!Ap.ring.coFac.isField()) { 446 throw new IllegalArgumentException("coefficients not from a field"); 447 } 448 int l = Pp.size(); 449 GenWordPolynomial<C>[] P = new GenWordPolynomial[l]; 450 synchronized (Pp) { 451 //P = Pp.toArray(); 452 for (int i = 0; i < Pp.size(); i++) { 453 P[i] = Pp.get(i); 454 } 455 } 456 Word[] htl = new Word[l]; 457 C[] lbc = (C[]) new RingElem[l]; // want C[] 458 GenWordPolynomial<C>[] p = new GenWordPolynomial[l]; 459 Map.Entry<Word, C> m; 460 int j = 0; 461 int i; 462 for (i = 0; i < l; i++) { 463 p[i] = P[i]; 464 m = p[i].leadingMonomial(); 465 if (m != null) { 466 p[j] = p[i]; 467 htl[j] = m.getKey(); 468 lbc[j] = m.getValue(); 469 j++; 470 } 471 } 472 l = j; 473 Word e; 474 C a; 475 boolean mt = false; 476 GenWordPolynomial<C> zero = Ap.ring.getZERO(); 477 GenWordPolynomial<C> R = Ap.ring.getZERO(); 478 C cone = Ap.ring.coFac.getONE(); 479 480 GenWordPolynomial<C> fac = null; 481 // GenWordPolynomial<C> T = null; 482 GenWordPolynomial<C> Q = null; 483 GenWordPolynomial<C> S = Ap; 484 while (S.length() > 0) { 485 m = S.leadingMonomial(); 486 e = m.getKey(); 487 a = m.getValue(); 488 for (i = 0; i < l; i++) { 489 mt = e.multipleOf(htl[i]); 490 if (mt) 491 break; 492 } 493 if (!mt) { 494 //logger.info("irred_1"); 495 R = R.sum(a, e); 496 S = S.subtract(a, e); 497 // System.out.println(" S = " + S); 498 } else { 499 Word g = e; 500 Word[] elr = e.divideWord(htl[i]); 501 e = elr[0]; 502 Word f = elr[1]; 503 if (debug) { 504 logger.info("redRec divideWord: e = " + e + ", f = " + f); 505 } 506 if (e.isONE()) { 507 C c = lbc[i]; 508 //System.out.println("a = " + a + ", c = " + c); 509 a = a.divide(c); 510 //System.out.println("a/c = " + a); 511 Q = p[i].multiply(cone, e, a, f); 512 S = S.subtract(Q); 513 // left row 514 fac = rrow.get(i); 515 if (fac == null) { 516 fac = zero.sum(a, f); 517 } else { 518 fac = fac.sum(a, f); 519 } 520 rrow.set(i, fac); 521 } else { 522 //logger.info("irred_2"); 523 R = R.sum(a, g); 524 S = S.subtract(a, g); 525 } 526 } 527 } 528 return R; 529 } 530 531}