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