001/* 002 * $Id: ReductionAbstract.java 5601 2016-09-25 19:17:08Z kredel $ 003 */ 004 005package edu.jas.gb; 006 007 008import java.util.ArrayList; 009import java.util.LinkedList; 010import java.util.List; 011import java.util.Map; 012 013import org.apache.log4j.Logger; 014 015import edu.jas.poly.ExpVector; 016import edu.jas.poly.GenPolynomial; 017import edu.jas.poly.Monomial; 018import edu.jas.structure.RingElem; 019 020 021/** 022 * Polynomial Reduction abstract class. Implements common S-Polynomial, 023 * normalform, criterion 4 module criterion and irreducible set. 024 * @param <C> coefficient type 025 * @author Heinz Kredel 026 */ 027 028public abstract class ReductionAbstract<C extends RingElem<C>> implements Reduction<C> { 029 030 031 private static final Logger logger = Logger.getLogger(ReductionAbstract.class); 032 033 034 private static final boolean debug = logger.isDebugEnabled(); 035 036 037 /** 038 * Constructor. 039 */ 040 public ReductionAbstract() { 041 } 042 043 044 /** 045 * S-Polynomial. 046 * @param A polynomial. 047 * @param B polynomial. 048 * @return spol(A,B) the S-polynomial of A and B. 049 */ 050 public GenPolynomial<C> SPolynomial(GenPolynomial<C> A, GenPolynomial<C> B) { 051 if (B == null || B.isZERO()) { 052 if (A == null) { 053 return B; 054 } 055 return A.ring.getZERO(); 056 } 057 if (A == null || A.isZERO()) { 058 return B.ring.getZERO(); 059 } 060 if (debug) { 061 if (!A.ring.equals(B.ring)) { 062 logger.error("rings not equal " + A.ring + ", " + B.ring); 063 } 064 } 065 Map.Entry<ExpVector, C> ma = A.leadingMonomial(); 066 Map.Entry<ExpVector, C> mb = B.leadingMonomial(); 067 068 ExpVector e = ma.getKey(); 069 ExpVector f = mb.getKey(); 070 071 ExpVector g = e.lcm(f); 072 ExpVector e1 = g.subtract(e); 073 ExpVector f1 = g.subtract(f); 074 075 C a = ma.getValue(); 076 C b = mb.getValue(); 077 078 //GenPolynomial<C> App = A.multiply(b, e1); 079 //GenPolynomial<C> Bpp = B.multiply(a, f1); 080 //GenPolynomial<C> Cp = App.subtract(Bpp); 081 GenPolynomial<C> Cp = A.scaleSubtractMultiple(b, e1, a, f1, B); 082 return Cp; 083 } 084 085 086 /** 087 * S-Polynomial with recording. 088 * @param S recording matrix, is modified. <b>Note</b> the negative 089 * S-polynomial is recorded as required by all applications. 090 * @param i index of Ap in basis list. 091 * @param A a polynomial. 092 * @param j index of Bp in basis list. 093 * @param B a polynomial. 094 * @return Spol(A, B), the S-Polynomial for A and B. 095 */ 096 public GenPolynomial<C> SPolynomial(List<GenPolynomial<C>> S, int i, GenPolynomial<C> A, int j, 097 GenPolynomial<C> B) { 098 if (debug) { 099 if (B == null || B.isZERO()) { 100 throw new ArithmeticException("Spol B is zero"); 101 } 102 if (A == null || A.isZERO()) { 103 throw new ArithmeticException("Spol A is zero"); 104 } 105 if (!A.ring.equals(B.ring)) { 106 logger.error("rings not equal " + A.ring + ", " + B.ring); 107 } 108 } 109 Map.Entry<ExpVector, C> ma = A.leadingMonomial(); 110 Map.Entry<ExpVector, C> mb = B.leadingMonomial(); 111 112 ExpVector e = ma.getKey(); 113 ExpVector f = mb.getKey(); 114 115 ExpVector g = e.lcm(f); 116 ExpVector e1 = g.subtract(e); 117 ExpVector f1 = g.subtract(f); 118 119 C a = ma.getValue(); 120 C b = mb.getValue(); 121 122 //GenPolynomial<C> App = A.multiply(b, e1); 123 //GenPolynomial<C> Bpp = B.multiply(a, f1); 124 //GenPolynomial<C> Cp = App.subtract(Bpp); 125 GenPolynomial<C> Cp = A.scaleSubtractMultiple(b, e1, a, f1, B); 126 127 GenPolynomial<C> zero = A.ring.getZERO(); 128 GenPolynomial<C> As = zero.sum(b.negate(), e1); 129 GenPolynomial<C> Bs = zero.sum(a /*correct .negate()*/, f1); 130 S.set(i, As); 131 S.set(j, Bs); 132 return Cp; 133 } 134 135 136 /** 137 * Module criterium. 138 * @param modv number of module variables. 139 * @param A polynomial. 140 * @param B polynomial. 141 * @return true if the module S-polynomial(i,j) is required. 142 */ 143 public boolean moduleCriterion(int modv, GenPolynomial<C> A, GenPolynomial<C> B) { 144 if (modv == 0) { 145 return true; 146 } 147 ExpVector ei = A.leadingExpVector(); 148 ExpVector ej = B.leadingExpVector(); 149 return moduleCriterion(modv, ei, ej); 150 } 151 152 153 /** 154 * Module criterium. 155 * @param modv number of module variables. 156 * @param ei ExpVector. 157 * @param ej ExpVector. 158 * @return true if the module S-polynomial(i,j) is required. 159 */ 160 public boolean moduleCriterion(int modv, ExpVector ei, ExpVector ej) { 161 if (modv == 0) { 162 return true; 163 } 164 if (ei.invLexCompareTo(ej, 0, modv) != 0) { 165 return false; // skip pair 166 } 167 return true; 168 } 169 170 171 /** 172 * GB criterium 4. Use only for commutative polynomial rings. 173 * @param A polynomial. 174 * @param B polynomial. 175 * @param e = lcm(ht(A),ht(B)) 176 * @return true if the S-polynomial(i,j) is required, else false. 177 */ 178 public boolean criterion4(GenPolynomial<C> A, GenPolynomial<C> B, ExpVector e) { 179 if (logger.isInfoEnabled()) { 180 if (!A.ring.equals(B.ring)) { 181 logger.error("rings not equal " + A.ring + ", " + B.ring); 182 } 183 if (!A.ring.isCommutative()) { //B instanceof GenSolvablePolynomial ) { 184 logger.error("GBCriterion4 not applicabable to non-commutative polynomials"); 185 return true; 186 } 187 } 188 ExpVector ei = A.leadingExpVector(); 189 ExpVector ej = B.leadingExpVector(); 190 return criterion4(ei, ej, e); 191 } 192 193 194 /** 195 * GB criterium 4. Use only for commutative polynomial rings. 196 * @param ei exponent vector. 197 * @param ej exponent vector. 198 * @param e = lcm(ei,ej) 199 * @return true if the S-polynomial(i,j) is required, else false. 200 */ 201 public boolean criterion4(ExpVector ei, ExpVector ej, ExpVector e) { 202 ExpVector g = ei.sum(ej); 203 ExpVector h = g.subtract(e); 204 int s = h.signum(); 205 return s != 0; 206 } 207 208 209 /** 210 * GB criterium 4. 211 * @param A polynomial. 212 * @param B polynomial. 213 * @return true if the S-polynomial(i,j) is required, else false. 214 */ 215 public boolean criterion4(GenPolynomial<C> A, GenPolynomial<C> B) { 216 if (logger.isInfoEnabled()) { 217 if (!A.ring.isCommutative() || !B.ring.isCommutative()) { // A instanceof GenSolvablePolynomial 218 logger.error("GBCriterion4 not applicabable to non-commutative polynomials"); 219 return true; 220 } 221 } 222 ExpVector ei = A.leadingExpVector(); 223 ExpVector ej = B.leadingExpVector(); 224 ExpVector e = ei.lcm(ej); 225 return criterion4(ei, ej, e); 226 } 227 228 229 /** 230 * Normalform with respect to marked head terms. 231 * @param Mp leading monomial list. 232 * @param Pp polynomial list. 233 * @param Ap polynomial. 234 * @return nf(Ap) with respect to Mp+Pp. 235 */ 236 public GenPolynomial<C> normalformMarked(List<Monomial<C>> Mp, List<GenPolynomial<C>> Pp, 237 GenPolynomial<C> Ap) { 238 throw new UnsupportedOperationException("not implemented: " + Mp + " " + Pp + " " + Ap); 239 } 240 241 242 /** 243 * Normalform Set. 244 * @param Ap polynomial list. 245 * @param Pp polynomial list. 246 * @return list of nf(a) with respect to Pp for all a in Ap. 247 */ 248 public List<GenPolynomial<C>> normalform(List<GenPolynomial<C>> Pp, List<GenPolynomial<C>> Ap) { 249 if (Pp == null || Pp.isEmpty()) { 250 return Ap; 251 } 252 if (Ap == null || Ap.isEmpty()) { 253 return Ap; 254 } 255 ArrayList<GenPolynomial<C>> red = new ArrayList<GenPolynomial<C>>(); 256 for (GenPolynomial<C> A : Ap) { 257 A = normalform(Pp, A); 258 red.add(A); 259 } 260 return red; 261 } 262 263 264 /** 265 * Is top reducible. 266 * @param A polynomial. 267 * @param P polynomial list. 268 * @return true if A is top reducible with respect to P. 269 */ 270 public boolean isTopReducible(List<GenPolynomial<C>> P, GenPolynomial<C> A) { 271 if (P == null || P.isEmpty()) { 272 return false; 273 } 274 if (A == null || A.isZERO()) { 275 return false; 276 } 277 boolean mt = false; 278 ExpVector e = A.leadingExpVector(); 279 for (GenPolynomial<C> p : P) { 280 mt = e.multipleOf(p.leadingExpVector()); 281 if (mt) { 282 return true; 283 } 284 } 285 return false; 286 } 287 288 289 /** 290 * Is reducible. 291 * @param Ap polynomial. 292 * @param Pp polynomial list. 293 * @return true if Ap is reducible with respect to Pp. 294 */ 295 public boolean isReducible(List<GenPolynomial<C>> Pp, GenPolynomial<C> Ap) { 296 return !isNormalform(Pp, Ap); 297 } 298 299 300 /** 301 * Is in Normalform. 302 * @param Ap polynomial. 303 * @param Pp polynomial list. 304 * @return true if Ap is in normalform with respect to Pp. 305 */ 306 @SuppressWarnings("unchecked") 307 public boolean isNormalform(List<GenPolynomial<C>> Pp, GenPolynomial<C> Ap) { 308 if (Pp == null || Pp.isEmpty()) { 309 return true; 310 } 311 if (Ap == null || Ap.isZERO()) { 312 return true; 313 } 314 int l; 315 GenPolynomial<C>[] P; 316 synchronized (Pp) { 317 l = Pp.size(); 318 P = new GenPolynomial[l]; 319 //P = Pp.toArray(); 320 for (int i = 0; i < Pp.size(); i++) { 321 P[i] = Pp.get(i); 322 } 323 } 324 ExpVector[] htl = new ExpVector[l]; 325 GenPolynomial<C>[] p = new GenPolynomial[l]; 326 Map.Entry<ExpVector, C> m; 327 int i; 328 int j = 0; 329 for (i = 0; i < l; i++) { 330 p[i] = P[i]; 331 m = p[i].leadingMonomial(); 332 if (m != null) { 333 p[j] = p[i]; 334 htl[j] = m.getKey(); 335 j++; 336 } 337 } 338 l = j; 339 boolean mt = false; 340 for (ExpVector e : Ap.getMap().keySet()) { 341 for (i = 0; i < l; i++) { 342 mt = e.multipleOf(htl[i]); 343 if (mt) { 344 return false; 345 } 346 } 347 } 348 return true; 349 } 350 351 352 /** 353 * Is in Normalform. 354 * @param Pp polynomial list. 355 * @return true if each Ap in Pp is in normalform with respect to Pp\{Ap}. 356 */ 357 public boolean isNormalform(List<GenPolynomial<C>> Pp) { 358 if (Pp == null || Pp.isEmpty()) { 359 return true; 360 } 361 GenPolynomial<C> Ap; 362 List<GenPolynomial<C>> P = new LinkedList<GenPolynomial<C>>(Pp); 363 int s = P.size(); 364 for (int i = 0; i < s; i++) { 365 Ap = P.remove(i); 366 if (!isNormalform(P, Ap)) { 367 return false; 368 } 369 P.add(Ap); 370 } 371 return true; 372 } 373 374 375 /** 376 * Irreducible set. 377 * @param Pp polynomial list. 378 * @return a list P of monic polynomials which are in normalform wrt. P and 379 * with ideal(Pp) = ideal(P). 380 */ 381 public List<GenPolynomial<C>> irreducibleSet(List<GenPolynomial<C>> Pp) { 382 ArrayList<GenPolynomial<C>> P = new ArrayList<GenPolynomial<C>>(); 383 for (GenPolynomial<C> a : Pp) { 384 if (a.length() != 0) { 385 a = a.monic(); 386 if (a.isONE()) { 387 P.clear(); 388 P.add(a); 389 return P; 390 } 391 P.add(a); 392 } 393 } 394 int l = P.size(); 395 if (l <= 1) 396 return P; 397 398 int irr = 0; 399 ExpVector e; 400 ExpVector f; 401 GenPolynomial<C> a; 402 logger.debug("irr = "); 403 while (irr != l) { 404 //it = P.listIterator(); 405 //a = P.get(0); //it.next(); 406 a = P.remove(0); 407 e = a.leadingExpVector(); 408 a = normalform(P, a); 409 logger.debug(String.valueOf(irr)); 410 if (a.length() == 0) { 411 l--; 412 if (l <= 1) { 413 return P; 414 } 415 } else { 416 f = a.leadingExpVector(); 417 if (f.signum() == 0) { 418 P = new ArrayList<GenPolynomial<C>>(); 419 P.add(a.monic()); 420 return P; 421 } 422 if (e.equals(f)) { 423 irr++; 424 } else { 425 irr = 0; 426 a = a.monic(); 427 } 428 P.add(a); 429 } 430 } 431 //System.out.println(); 432 return P; 433 } 434 435 436 /** 437 * Is reduction of normal form. 438 * @param row recording matrix. 439 * @param Pp a polynomial list for reduction. 440 * @param Ap a polynomial. 441 * @param Np nf(Pp,Ap), a normal form of Ap wrt. Pp. 442 * @return true, if Np + sum( row[i]*Pp[i] ) == Ap, else false. 443 */ 444 445 public boolean isReductionNF(List<GenPolynomial<C>> row, List<GenPolynomial<C>> Pp, GenPolynomial<C> Ap, 446 GenPolynomial<C> Np) { 447 if (row == null && Pp == null) { 448 if (Ap == null) { 449 return Np == null; 450 } 451 return Ap.equals(Np); 452 } 453 if (row == null || Pp == null) { 454 return false; 455 } 456 if (row.size() != Pp.size()) { 457 return false; 458 } 459 GenPolynomial<C> t = Np; 460 //System.out.println("t0 = " + t ); 461 GenPolynomial<C> r; 462 GenPolynomial<C> p; 463 for (int m = 0; m < Pp.size(); m++) { 464 r = row.get(m); 465 p = Pp.get(m); 466 if (r != null && p != null) { 467 if (t == null) { 468 t = r.multiply(p); 469 } else { 470 t = t.sum(r.multiply(p)); 471 } 472 } 473 //System.out.println("r = " + r ); 474 //System.out.println("p = " + p ); 475 } 476 //System.out.println("t+ = " + t ); 477 if (t == null) { 478 if (Ap == null) { 479 return true; 480 } 481 return Ap.isZERO(); 482 } 483 r = t.subtract(Ap); 484 boolean z = r.isZERO(); 485 if (!z) { 486 logger.info("t = " + t); 487 logger.info("a = " + Ap); 488 logger.info("t-a = " + r); 489 } 490 return z; 491 } 492}