001/* 002 * $Id: SigReductionSeq.java 5869 2018-07-20 15:53:10Z kredel $ 003 */ 004 005package edu.jas.gb; 006 007 008import java.util.ArrayList; 009import java.util.LinkedList; 010import java.util.List; 011import java.util.Comparator; 012import java.util.stream.Collectors; 013import java.util.Map; 014 015import org.apache.logging.log4j.Logger; 016import org.apache.logging.log4j.LogManager; 017 018import edu.jas.poly.ExpVector; 019import edu.jas.poly.GenPolynomial; 020import edu.jas.poly.GenPolynomialRing; 021import edu.jas.structure.RingElem; 022 023 024/** 025 * Polynomial SigReduction class. Implements common S-Polynomial, normalform 026 * with respect to signatures. 027 * @param <C> coefficient type 028 * @author Heinz Kredel 029 */ 030 031public class SigReductionSeq<C extends RingElem<C>> implements SigReduction<C> { 032 033 034 private static final Logger logger = LogManager.getLogger(SigReductionSeq.class); 035 036 037 //private static final boolean debug = logger.isDebugEnabled(); 038 039 040 final ReductionAbstract<C> red; 041 042 043 /** 044 * Constructor. 045 */ 046 public SigReductionSeq() { 047 red = new ReductionSeq<C>(); 048 } 049 050 051 /** 052 * S-Polynomial. 053 * @param A polynomial. 054 * @param B polynomial. 055 * @return spol(A,B) the S-polynomial of A and B. 056 */ 057 public GenPolynomial<C> SPolynomial(SigPoly<C> A, SigPoly<C> B) { 058 GenPolynomial<C> s = red.SPolynomial(A.poly, B.poly); 059 return s; 060 } 061 062 063 /** 064 * S-Polynomial factors. 065 * @param A monic polynomial. 066 * @param B monic polynomial. 067 * @return exponent vectors [e,f] such that spol(A,B) = e*a - f*B. 068 */ 069 public ExpVector[] SPolynomialExpVectorFactors(SigPoly<C> A, SigPoly<C> B) { 070 Map.Entry<ExpVector, C> ma = A.poly.leadingMonomial(); 071 Map.Entry<ExpVector, C> mb = B.poly.leadingMonomial(); 072 ExpVector e = ma.getKey(); 073 ExpVector f = mb.getKey(); 074 ExpVector g = e.lcm(f); 075 ExpVector e1 = g.subtract(e); 076 ExpVector f1 = g.subtract(f); 077 ExpVector[] F = new ExpVector[] { e1, f1 }; 078 return F; 079 } 080 081 082 /** 083 * S-Polynomial half. 084 * @param A monic polynomial. 085 * @param B monic polynomial. 086 * @return e*A "half" of an S-polynomial such that spol(A,B) = e*A - f*B. 087 */ 088 public GenPolynomial<C> SPolynomialHalf(SigPoly<C> A, SigPoly<C> B) { 089 Map.Entry<ExpVector, C> ma = A.poly.leadingMonomial(); 090 Map.Entry<ExpVector, C> mb = B.poly.leadingMonomial(); 091 ExpVector e = ma.getKey(); 092 ExpVector f = mb.getKey(); 093 ExpVector g = e.lcm(f); 094 ExpVector e1 = g.subtract(e); 095 GenPolynomial<C> F = A.poly.multiply(e1); 096 return F; 097 } 098 099 100 /** 101 * S-Polynomial polynomial factors. 102 * @param A monic polynomial. 103 * @param B monic polynomial. 104 * @return polynomials [e,f] such that spol(A,B) = e*a - f*B. 105 */ 106 public GenPolynomial<C>[] SPolynomialFactors(SigPoly<C> A, SigPoly<C> B) { 107 ExpVector[] ev = SPolynomialExpVectorFactors(A, B); 108 GenPolynomial<C> e1 = A.poly.ring.valueOf(ev[0]); 109 GenPolynomial<C> f1 = A.poly.ring.valueOf(ev[1]); 110 @SuppressWarnings("unchecked") 111 GenPolynomial<C>[] F = new GenPolynomial[] { e1, f1 }; 112 return F; 113 } 114 115 116 /** 117 * Is top reducible. Condition is lt(B) | lt(A) for some B in F or G. 118 * @param A polynomial. 119 * @param F polynomial list. 120 * @param G polynomial list. 121 * @return true if A is top reducible with respect to F and G. 122 */ 123 public boolean isSigReducible(List<SigPoly<C>> F, List<SigPoly<C>> G, SigPoly<C> A) { 124 return !isSigNormalform(F, G, A); 125 } 126 127 128 /** 129 * Is in top normalform. 130 * @param A polynomial. 131 * @param F polynomial list. 132 * @param G polynomial list. 133 * @return true if A is in top normalform with respect to F and G. 134 */ 135 public boolean isSigNormalform(List<SigPoly<C>> F, List<SigPoly<C>> G, SigPoly<C> A) { 136 if (F.isEmpty() && G.isEmpty()) { 137 return true; 138 } 139 if (A.poly.isZERO()) { 140 return true; 141 } 142 boolean mt = false; 143 for (ExpVector e : A.poly.getMap().keySet()) { 144 for (SigPoly<C> p : F) { 145 ExpVector f = p.poly.leadingExpVector(); 146 mt = e.multipleOf(f); 147 if (mt) { 148 return false; 149 } 150 } 151 for (SigPoly<C> p : G) { 152 if (p.poly.isZERO()) { 153 continue; 154 } 155 ExpVector f = p.poly.leadingExpVector(); 156 mt = e.multipleOf(f); 157 if (mt) { 158 ExpVector g = e.subtract(f); 159 GenPolynomial<C> sigma = p.sigma.multiply(g); 160 if (sigma.leadingExpVector().compareTo(A.sigma.leadingExpVector()) < 0) { 161 return false; 162 } 163 if (sigma.leadingExpVector().compareTo(A.sigma.leadingExpVector()) == 0 164 && sigma.leadingBaseCoefficient().compareTo( 165 A.sigma.leadingBaseCoefficient()) != 0) { 166 return false; 167 } 168 } 169 } 170 } 171 return true; 172 } 173 174 175 /** 176 * Is sigma redundant. 177 * @param A polynomial. 178 * @param G polynomial list. 179 * @return true if A is sigma redundant with respect to G. 180 */ 181 public boolean isSigRedundant(List<SigPoly<C>> G, SigPoly<C> A) { 182 if (G.isEmpty()) { 183 return false; 184 } 185 ExpVector e = A.sigma.leadingExpVector(); 186 if (e == null) { 187 e = A.poly.ring.evzero; 188 } 189 for (SigPoly<C> p : G) { 190 if (p.sigma.isZERO()) { 191 continue; 192 } 193 ExpVector f = p.sigma.leadingExpVector(); 194 if (f == null) { // does not happen 195 f = p.poly.ring.evzero; 196 } 197 boolean mt = e.multipleOf(f); 198 if (mt) { 199 ExpVector g = e.subtract(f); 200 ExpVector h = p.poly.leadingExpVector(); 201 h = h.sum(g); 202 if (h.compareTo(A.poly.leadingExpVector()) == 0) { 203 return true; 204 } 205 } 206 } 207 return false; 208 } 209 210 211 /** 212 * Is sigma redundant, alternative algorithm. 213 * @param A polynomial. 214 * @param G polynomial list. 215 * @return true if A is sigma redundant per alternative algorithm with 216 * respect to G. 217 */ 218 public boolean isSigRedundantAlt(List<SigPoly<C>> G, SigPoly<C> A) { 219 if (G.isEmpty()) { 220 return false; 221 } 222 ExpVector e = A.sigma.leadingExpVector(); 223 if (e == null) { 224 e = A.poly.ring.evzero; 225 } 226 for (SigPoly<C> p : G) { 227 if (p.sigma.isZERO()) { 228 continue; 229 } 230 ExpVector f = p.sigma.leadingExpVector(); 231 if (f == null) { // does not happen 232 f = p.poly.ring.evzero; 233 } 234 boolean mt = e.multipleOf(f); 235 if (mt) { 236 if (p.poly.isZERO()) { 237 continue; 238 } 239 ExpVector h = p.poly.leadingExpVector(); 240 ExpVector g = A.poly.leadingExpVector(); 241 if (g.multipleOf(h)) { 242 return true; 243 } 244 } 245 } 246 return false; 247 } 248 249 250 /** 251 * Top normalform. 252 * @param A polynomial. 253 * @param F polynomial list. 254 * @param G polynomial list. 255 * @return nf(A) with respect to F and G. 256 */ 257 public SigPoly<C> sigNormalform(List<GenPolynomial<C>> F, List<SigPoly<C>> G, SigPoly<C> A) { 258 if (F.isEmpty() && G.isEmpty()) { 259 return A; 260 } 261 if (A.poly.isZERO()) { 262 return A; 263 } 264 List<GenPolynomial<C>> ff = F; //polys(F); 265 GenPolynomial<C> a = A.poly; 266 GenPolynomial<C> sigma = A.sigma; 267 GenPolynomialRing<C> ring = a.ring; 268 boolean reduced = true; 269 while (!a.isZERO() && reduced) { 270 reduced = false; 271 a = red.normalform(ff, a); 272 if (a.isZERO()) { 273 continue; 274 } 275 ExpVector e = a.leadingExpVector(); 276 for (SigPoly<C> p : G) { 277 if (p.poly.isZERO()) { 278 continue; 279 } 280 ExpVector f = p.poly.leadingExpVector(); 281 boolean mt = e.multipleOf(f); 282 if (mt) { 283 ExpVector g = e.subtract(f); 284 C sc = a.leadingBaseCoefficient().divide(p.poly.leadingBaseCoefficient()); 285 GenPolynomial<C> sigup = p.sigma.multiply(sc, g); 286 ExpVector se = sigma.leadingExpVector(); 287 if (se == null) { 288 se = ring.evzero; 289 } 290 ExpVector sp = sigup.leadingExpVector(); 291 if (sp == null) { 292 sp = ring.evzero; 293 } 294 //logger.info("sigup, sigma = " + sigup + ", " + sigma); 295 boolean sigeq = (sigup.compareTo(sigma) < 0) 296 || ((sp.compareTo(se) == 0 && (sigup.leadingBaseCoefficient().compareTo( 297 sigma.leadingBaseCoefficient()) != 0))); 298 //logger.info("sigup < sigma = " + sigup.compareTo(sigma)); 299 if (sigeq) { 300 reduced = true; 301 a = a.subtractMultiple(sc, g, p.poly); 302 if (sp.invGradCompareTo(se) == 0) { 303 sigma = sigma.subtract(sigup); 304 } 305 if (a.isZERO()) { 306 break; 307 } 308 e = a.leadingExpVector(); 309 } else { 310 //logger.info("not reduced: a = " + a + ", p = " + p.poly); 311 } 312 } 313 } 314 } 315 if (!a.isZERO()) { 316 C ac = a.leadingBaseCoefficient(); 317 if (!ac.isONE()) { 318 ac = ac.inverse(); 319 a = a.multiply(ac); 320 sigma = sigma.multiply(ac); 321 } 322 } 323 return new SigPoly<C>(sigma, a); 324 } 325 326 327 /** 328 * Top semi-complete normalform. 329 * @param A polynomial. 330 * @param F polynomial list. 331 * @param G polynomial list. 332 * @return nf(A) with respect to F and G. 333 */ 334 public SigPoly<C> sigSemiNormalform(List<GenPolynomial<C>> F, List<SigPoly<C>> G, SigPoly<C> A) { 335 if (F.isEmpty() && G.isEmpty()) { 336 return A; 337 } 338 if (A.poly.isZERO()) { 339 return A; 340 } 341 List<GenPolynomial<C>> ff = F; //polys(F); 342 GenPolynomial<C> a = A.poly; 343 GenPolynomial<C> sigma = A.sigma; 344 ExpVector esig = sigma.leadingExpVector(); 345 if (esig == null) { 346 logger.info("esig = null"); 347 //esig = a.ring.evzero; 348 } 349 //GenPolynomialRing<C> ring = a.ring; 350 boolean reduced = true; 351 while (!a.isZERO() && reduced) { 352 reduced = false; 353 a = red.normalform(ff, a); 354 if (a.isZERO()) { 355 continue; 356 } 357 ExpVector e = a.leadingExpVector(); 358 for (SigPoly<C> p : G) { 359 if (p.poly.isZERO()) { 360 continue; 361 } 362 ExpVector f = p.poly.leadingExpVector(); 363 boolean mt = e.multipleOf(f); 364 if (mt) { 365 ExpVector g = e.subtract(f); 366 C sc = a.leadingBaseCoefficient().divide(p.poly.leadingBaseCoefficient()); 367 GenPolynomial<C> sigup = p.sigma.multiply(sc, g); 368 ExpVector eup = sigup.leadingExpVector(); 369 if (eup == null) { 370 logger.info("eup = null"); 371 //eup = a.ring.evzero; 372 throw new IllegalArgumentException("eup == null: " + sigup); 373 } 374 375 //wrong: boolean sigeq = (sigup.compareTo(sigma) < 0); 376 boolean sigeq = (eup.compareTo(esig) < 0); 377 if (sigeq) { 378 //logger.info("reduced: sigup = " + sigup + ", sigma = " + sigma); 379 reduced = true; 380 a = a.subtractMultiple(sc, g, p.poly); 381 if (a.isZERO()) { 382 break; 383 } 384 e = a.leadingExpVector(); 385 } else { 386 //logger.info("not reduced: a = " + a + ", p = " + p.poly); 387 } 388 } 389 } 390 } 391 if (!a.isZERO()) { 392 C ac = a.leadingBaseCoefficient(); 393 if (!ac.isONE()) { 394 ac = ac.inverse(); 395 a = a.multiply(ac); 396 } 397 } 398 return new SigPoly<C>(sigma, a); 399 } 400 401 402 /** 403 * Select polynomials. 404 * @param F list of signature polynomials. 405 * @return the polynomials in F. 406 */ 407 public List<GenPolynomial<C>> polys(List<SigPoly<C>> F) { 408 List<GenPolynomial<C>> ff = new ArrayList<GenPolynomial<C>>(); 409 for (SigPoly<C> p : F) { 410 if (!p.poly.isZERO()) { 411 ff.add(p.poly); 412 } 413 } 414 return ff; 415 } 416 417 418 /** 419 * Select signatures. 420 * @param F list of signature polynomials. 421 * @return the signatures in F. 422 */ 423 public List<GenPolynomial<C>> sigmas(List<SigPair<C>> F) { 424 List<GenPolynomial<C>> ff = new ArrayList<GenPolynomial<C>>(); 425 for (SigPair<C> p : F) { 426 ff.add(p.sigma); 427 } 428 return ff; 429 } 430 431 432 /** 433 * Minimal degree of signatures. 434 * @param F list of signature polynomials. 435 * @return the minimal degree of the signatures in F. 436 */ 437 public long minimalSigDegree(List<SigPair<C>> F) { 438 long deg = Long.MAX_VALUE; 439 for (SigPair<C> p : F) { 440 //long d = p.sigma.totalDegree(); 441 long d = p.sigma.degree(); 442 if (d < deg) { 443 deg = d; 444 } 445 } 446 return deg; 447 } 448 449 450 /** 451 * Select signature polynomials of minimal degree and non minimal degree. 452 * @param F list of signature polynomials. 453 * @return [m,p] where m is the list of signature polynomials of F of 454 * minimal degree and p contains the rest of the signature 455 * polynomials with non minimal degree. 456 */ 457 public List<SigPair<C>>[] minDegSubset(List<SigPair<C>> F) { 458 long mdeg = minimalSigDegree(F); 459 List<SigPair<C>> ff = new ArrayList<SigPair<C>>(); 460 List<SigPair<C>> pp = new ArrayList<SigPair<C>>(); 461 for (SigPair<C> p : F) { 462 //if (p.sigma.totalDegree() == mdeg) { 463 if (p.sigma.degree() == mdeg) { 464 ff.add(p); 465 } else { 466 pp.add(p); 467 } 468 } 469 @SuppressWarnings("unchecked") 470 List<SigPair<C>>[] P = new List[2]; 471 P[0] = ff; 472 P[1] = pp; 473 return P; 474 } 475 476 477 /** 478 * Sort signature polynomials according to the degree its signatures. 479 * @param F list of signature polynomials. 480 * @return list of signature polynomials sorted by degree of sigma. 481 */ 482 public List<SigPair<C>> sortSigma(List<SigPair<C>> F) { 483 //Comparator<SigPair<C>> sigcmp = Comparator.comparing(SigPair::getSigma::degree); 484 Comparator<SigPair<C>> sigcmp = Comparator.comparingLong(SigPair::getSigmaDegree); 485 List<SigPair<C>> ff = F.stream().sorted(sigcmp).collect(Collectors.toList()); 486 return ff; 487 } 488}