001/* 002 * $Id: WordGroebnerBasePseudoRecSeq.java 5208 2015-04-05 10:36:25Z kredel $ 003 */ 004 005package edu.jas.gbufd; 006 007 008import java.util.ArrayList; 009import java.util.Collections; 010import java.util.List; 011 012import org.apache.log4j.Logger; 013 014import edu.jas.gb.OrderedWordPairlist; 015import edu.jas.gb.WordGroebnerBaseAbstract; 016import edu.jas.gb.WordPair; 017import edu.jas.gb.WordPairList; 018import edu.jas.poly.GenPolynomial; 019import edu.jas.poly.GenPolynomialRing; 020import edu.jas.poly.GenWordPolynomial; 021import edu.jas.poly.GenWordPolynomialRing; 022import edu.jas.poly.PolyUtil; 023import edu.jas.structure.GcdRingElem; 024import edu.jas.structure.RingFactory; 025import edu.jas.ufd.GCDFactory; 026import edu.jas.ufd.GreatestCommonDivisorAbstract; 027 028 029/** 030 * Non-commutative word Groebner Base sequential algorithm. Implements Groebner 031 * bases and GB test. Coefficients can for example be (commutative) multivariate 032 * polynomials. 033 * @param <C> coefficient type 034 * @author Heinz Kredel 035 */ 036 037public class WordGroebnerBasePseudoRecSeq<C extends GcdRingElem<C>> extends 038 WordGroebnerBaseAbstract<GenPolynomial<C>> { 039 040 041 private static final Logger logger = Logger.getLogger(WordGroebnerBasePseudoRecSeq.class); 042 043 044 private final boolean debug = logger.isDebugEnabled(); 045 046 047 /** 048 * Greatest common divisor engine for coefficient content and primitive 049 * parts. 050 */ 051 protected final GreatestCommonDivisorAbstract<C> engine; 052 053 054 /** 055 * Reduction engine. 056 */ 057 protected final WordPseudoReduction<C> redRec; 058 059 060 /** 061 * Reduction engine. 062 */ 063 protected final WordPseudoReduction<GenPolynomial<C>> red; 064 065 066 /** 067 * Coefficient ring factory. 068 */ 069 //protected final RingFactory<GenPolynomial<C>> cofac; 070 protected final GenPolynomialRing<C> cofac; 071 072 073 /** 074 * Constructor. 075 * @param rf coefficient ring factory. 076 */ 077 public WordGroebnerBasePseudoRecSeq(RingFactory<GenPolynomial<C>> rf) { 078 this(rf, new WordPseudoReductionSeq<GenPolynomial<C>>()); 079 } 080 081 082 /** 083 * Constructor. 084 * @param rf coefficient ring factory. 085 * @param red Reduction engine 086 */ 087 public WordGroebnerBasePseudoRecSeq(RingFactory<GenPolynomial<C>> rf, 088 WordPseudoReductionSeq<GenPolynomial<C>> red) { 089 this(rf, red, new OrderedWordPairlist<GenPolynomial<C>>()); 090 } 091 092 093 /** 094 * Constructor. 095 * @param rf coefficient ring factory. 096 * @param red Reduction engine 097 * @param pl pair selection strategy 098 */ 099 @SuppressWarnings("cast") 100 public WordGroebnerBasePseudoRecSeq(RingFactory<GenPolynomial<C>> rf, 101 WordPseudoReductionSeq<GenPolynomial<C>> red, WordPairList<GenPolynomial<C>> pl) { 102 super(red, pl); 103 this.red = red; 104 redRec = (WordPseudoReduction<C>) (WordPseudoReduction) red; 105 cofac = (GenPolynomialRing<C>) rf; 106 if (!cofac.isCommutative()) { 107 logger.warn("reduction not correct for " + cofac.toScript()); 108 } 109 engine = GCDFactory.<C> getImplementation(cofac.coFac); 110 //not used: engine = GCDFactory.<C>getProxy(cofac.coFac); 111 } 112 113 114 /** 115 * Word Groebner base using word pairlist class. 116 * @param F word polynomial list. 117 * @return GB(F) a finite non-commutative Groebner base of F, if it exists. 118 */ 119 @Override 120 public List<GenWordPolynomial<GenPolynomial<C>>> GB(List<GenWordPolynomial<GenPolynomial<C>>> F) { 121 List<GenWordPolynomial<GenPolynomial<C>>> G = normalizeZerosOnes(F); 122 //G = PolyUtil.<C> wordMonic(G); 123 G = recursivePrimitivePart(G); 124 G = normalizeZerosOnes(G); 125 if (G.size() <= 1) { 126 return G; 127 } 128 GenWordPolynomialRing<GenPolynomial<C>> ring = G.get(0).ring; 129 if (!ring.coFac.isCommutative()) { 130 throw new IllegalArgumentException("coefficient ring not commutative"); 131 } 132 //Collections.sort(G); 133 OrderedWordPairlist<GenPolynomial<C>> pairlist = (OrderedWordPairlist<GenPolynomial<C>>) strategy 134 .create(ring); 135 pairlist.put(G); 136 logger.info("start " + pairlist); 137 138 WordPair<GenPolynomial<C>> pair; 139 GenWordPolynomial<GenPolynomial<C>> pi; 140 GenWordPolynomial<GenPolynomial<C>> pj; 141 List<GenWordPolynomial<GenPolynomial<C>>> S; 142 GenWordPolynomial<GenPolynomial<C>> H; 143 while (pairlist.hasNext()) { 144 pair = pairlist.removeNext(); 145 //logger.debug("pair = " + pair); 146 if (pair == null) { 147 continue; 148 } 149 pi = pair.pi; 150 pj = pair.pj; 151 if (debug) { 152 logger.info("pi = " + pi + ", pj = " + pj); 153 //logger.info("pj = " + pj); 154 } 155 156 S = red.SPolynomials(pi, pj); 157 if (S.isEmpty()) { 158 continue; 159 } 160 for (GenWordPolynomial<GenPolynomial<C>> s : S) { 161 if (s.isZERO()) { 162 //pair.setZero(); 163 continue; 164 } 165 if (debug) { 166 logger.info("ht(S) = " + s.leadingWord()); 167 } 168 boolean t = pairlist.criterion3(pair.i, pair.j, s.leadingWord()); 169 //System.out.println("criterion3(" + pair.i + "," + pair.j + ") = " + t); 170 //if ( !t ) { 171 // continue; 172 //} 173 174 H = redRec.normalformRecursive(G, s); 175 if (debug) { 176 //logger.info("pair = " + pair); 177 //logger.info("ht(S) = " + S.monic()); //.leadingWord() ); 178 logger.info("ht(H) = " + H.monic()); //.leadingWord() ); 179 } 180 if (H.isZERO()) { 181 //pair.setZero(); 182 continue; 183 } 184 if (!t) { 185 logger.info("criterion3(" + pair.i + "," + pair.j + ") wrong: " + s.leadingWord() 186 + " --> '" + H.leadingWord() + "'"); 187 } 188 189 //H = H.monic(); 190 H = recursivePrimitivePart(H); 191 H = H.abs(); 192 if (debug) { 193 logger.info("ht(H) = " + H.leadingWord()); 194 } 195 if (H.isONE()) { 196 G.clear(); 197 G.add(H); 198 return G; // since no threads are activated 199 } 200 if (debug) { 201 logger.info("H = " + H); 202 } 203 if (H.length() > 0) { 204 //l++; 205 G.add(H); 206 pairlist.put(H); 207 } 208 } 209 } 210 //logger.info("#sequential list = " + G.size()); 211 G = minimalGB(G); 212 logger.info("" + pairlist); 213 //Collections.sort(G); 214 //Collections.reverse(G); 215 return G; 216 } 217 218 219 /** 220 * Minimal ordered Groebner basis. 221 * @param Gp a Groebner base. 222 * @return a reduced Groebner base of Gp. 223 */ 224 @Override 225 public List<GenWordPolynomial<GenPolynomial<C>>> minimalGB(List<GenWordPolynomial<GenPolynomial<C>>> Gp) { 226 if (Gp == null || Gp.size() <= 1) { 227 return Gp; 228 } 229 // remove zero polynomials 230 List<GenWordPolynomial<GenPolynomial<C>>> G = new ArrayList<GenWordPolynomial<GenPolynomial<C>>>( 231 Gp.size()); 232 for (GenWordPolynomial<GenPolynomial<C>> a : Gp) { 233 if (a != null && !a.isZERO()) { // always true in GB() 234 // already positive a = a.abs(); 235 G.add(a); 236 } 237 } 238 if (G.size() <= 1) { 239 return G; 240 } 241 // remove top reducible polynomials 242 GenWordPolynomial<GenPolynomial<C>> a; 243 List<GenWordPolynomial<GenPolynomial<C>>> F; 244 F = new ArrayList<GenWordPolynomial<GenPolynomial<C>>>(G.size()); 245 while (G.size() > 0) { 246 a = G.remove(0); 247 if (red.isTopReducible(G, a) || red.isTopReducible(F, a)) { 248 // drop polynomial 249 if (debug) { 250 System.out.println("dropped " + a); 251 List<GenWordPolynomial<GenPolynomial<C>>> ff; 252 ff = new ArrayList<GenWordPolynomial<GenPolynomial<C>>>(G); 253 ff.addAll(F); 254 a = redRec.normalformRecursive(ff, a); 255 if (!a.isZERO()) { 256 System.out.println("error, nf(a) " + a); 257 } 258 } 259 } else { 260 F.add(a); 261 } 262 } 263 G = F; 264 if (G.size() <= 1) { 265 return G; 266 } 267 // reduce remaining polynomials 268 Collections.reverse(G); // important for lex GB 269 int len = G.size(); 270 if (debug) { 271 System.out.println("#G " + len); 272 for (GenWordPolynomial<GenPolynomial<C>> aa : G) { 273 System.out.println("aa = " + aa.length() + ", lt = " + aa.getMap().keySet()); 274 } 275 } 276 int i = 0; 277 while (i < len) { 278 a = G.remove(0); 279 if (debug) { 280 System.out.println("doing " + a.length() + ", lt = " + a.leadingWord()); 281 } 282 a = redRec.normalformRecursive(G, a); 283 G.add(a); // adds as last 284 i++; 285 } 286 return G; 287 } 288 289 290 /** 291 * Wird Groebner base simple test. 292 * @param F recursive polynomial list. 293 * @return true, if F is a Groebner base, else false. 294 */ 295 @Override 296 public boolean isGB(List<GenWordPolynomial<GenPolynomial<C>>> F) { 297 if (F == null || F.isEmpty()) { 298 return true; 299 } 300 GenWordPolynomial<GenPolynomial<C>> pi, pj, h; 301 List<GenWordPolynomial<GenPolynomial<C>>> S; 302 for (int i = 0; i < F.size(); i++) { 303 pi = F.get(i); 304 for (int j = 0; j < F.size(); j++) { 305 if (i == j) { 306 continue; 307 } 308 pj = F.get(j); 309 310 S = red.SPolynomials(pi, pj); 311 if (S.isEmpty()) { 312 continue; 313 } 314 for (GenWordPolynomial<GenPolynomial<C>> s : S) { 315 //System.out.println("i, j = " + i + ", " + j); 316 h = redRec.normalformRecursive(F, s); 317 if (!h.isZERO()) { 318 logger.info("no GB: pi = " + pi + ", pj = " + pj); 319 logger.info("s = " + s + ", h = " + h); 320 return false; 321 } 322 } 323 } 324 } 325 return true; 326 } 327 328 329 /** 330 * GenWordPolynomial recursive coefficient content. 331 * @param P recursive GenWordPolynomial. 332 * @return cont(P). 333 */ 334 public GenPolynomial<C> recursiveContent(GenWordPolynomial<GenPolynomial<C>> P) { 335 if (P == null) { 336 throw new IllegalArgumentException(this.getClass().getName() + " P != null"); 337 } 338 if (P.isZERO()) { 339 return P.ring.getZEROCoefficient(); 340 } 341 GenPolynomial<C> d = null; 342 for (GenPolynomial<C> c : P.getMap().values()) { 343 //System.out.println("value c = " + c.leadingExpVector()); 344 if (d == null) { 345 d = c; 346 } else { 347 d = engine.gcd(d, c); 348 } 349 if (d.isONE()) { 350 return d; 351 } 352 } 353 if (d.signum() < 0) { 354 d = d.negate(); 355 } 356 return d; 357 } 358 359 360 /** 361 * GenWordPolynomial recursive coefficient primitive part. 362 * @param P recursive GenWordPolynomial. 363 * @return pp(P). 364 */ 365 public GenWordPolynomial<GenPolynomial<C>> recursivePrimitivePart(GenWordPolynomial<GenPolynomial<C>> P) { 366 if (P == null) { 367 throw new IllegalArgumentException(this.getClass().getName() + " P != null"); 368 } 369 if (P.isZERO()) { 370 return P; 371 } 372 GenPolynomial<C> d = recursiveContent(P); 373 if (d.isONE()) { 374 return P; 375 } 376 //GenWordPolynomial<GenPolynomial<C>> pp = P.divide(d); 377 GenWordPolynomial<GenPolynomial<C>> pp = PolyUtil.<C> recursiveDivide(P, d); 378 if (debug) { 379 GenWordPolynomial<GenPolynomial<C>> p = pp.multiply(d); 380 if (!p.equals(P)) { 381 throw new ArithmeticException("pp(p)*cont(p) != p: "); 382 } 383 } 384 return pp; 385 } 386 387 388 /** 389 * List of GenWordPolynomial recursive coefficient primitive part. 390 * @param F list of recursive GenWordPolynomials. 391 * @return pp(F). 392 */ 393 public List<GenWordPolynomial<GenPolynomial<C>>> recursivePrimitivePart( 394 List<GenWordPolynomial<GenPolynomial<C>>> F) { 395 if (F == null || F.isEmpty()) { 396 return F; 397 } 398 List<GenWordPolynomial<GenPolynomial<C>>> Pp = new ArrayList<GenWordPolynomial<GenPolynomial<C>>>( 399 F.size()); 400 for (GenWordPolynomial<GenPolynomial<C>> f : F) { 401 GenWordPolynomial<GenPolynomial<C>> p = recursivePrimitivePart(f); 402 Pp.add(p); 403 } 404 return Pp; 405 } 406 407}