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