001 /* 002 * $Id: RGroebnerBaseSeq.java 3626 2011-05-08 09:51:57Z kredel $ 003 */ 004 005 package edu.jas.gbufd; 006 007 008 import java.util.ArrayList; 009 import java.util.List; 010 import java.util.Collections; 011 012 import org.apache.log4j.Logger; 013 014 import edu.jas.gb.GroebnerBaseAbstract; 015 import edu.jas.gb.Pair; 016 import edu.jas.poly.ExpVector; 017 import edu.jas.poly.GenPolynomial; 018 import edu.jas.structure.RegularRingElem; 019 020 021 /** 022 * Regular ring Groebner Base sequential algorithm. Implements R-Groebner bases 023 * and GB test. 024 * @param <C> coefficient type 025 * @author Heinz Kredel 026 */ 027 028 public class RGroebnerBaseSeq<C extends RegularRingElem<C>> extends 029 GroebnerBaseAbstract<C> { 030 031 032 private static final Logger logger = Logger.getLogger(RGroebnerBaseSeq.class); 033 034 035 private final boolean debug = logger.isDebugEnabled(); 036 037 038 /** 039 * Reduction engine. 040 */ 041 protected RReduction<C> red; // shadow super.red 042 043 044 /** 045 * Constructor. 046 */ 047 public RGroebnerBaseSeq() { 048 this(new RReductionSeq<C>()); 049 } 050 051 052 /** 053 * Constructor. 054 * @param red R-Reduction engine 055 */ 056 public RGroebnerBaseSeq(RReduction<C> red) { 057 super(red); 058 this.red = red; 059 assert super.red == this.red; 060 } 061 062 063 /** 064 * R-Groebner base test. 065 * @param modv module variable number. 066 * @param F polynomial list. 067 * @return true, if F is a R-Groebner base, else false. 068 */ 069 @Override 070 public boolean isGB(int modv, List<GenPolynomial<C>> F) { 071 if (F == null) { 072 return true; 073 } 074 if (!red.isBooleanClosed(F)) { 075 if (true || debug) { 076 System.out.println("not boolean closed"); 077 } 078 return false; 079 } 080 GenPolynomial<C> pi, pj, s, h; 081 for (int i = 0; i < F.size(); i++) { 082 pi = F.get(i); 083 for (int j = i + 1; j < F.size(); j++) { 084 pj = F.get(j); 085 if (!red.moduleCriterion(modv, pi, pj)) { 086 continue; 087 } 088 // red.criterion4 not applicable 089 s = red.SPolynomial(pi, pj); 090 if (s.isZERO()) { 091 continue; 092 } 093 s = red.normalform(F, s); 094 if (!s.isZERO()) { 095 if (debug) { 096 System.out.println("p" + i + " = " + pi); 097 System.out.println("p" + j + " = " + pj); 098 System.out.println("s-pol = " + red.SPolynomial(pi, pj)); 099 System.out.println("s-pol(" + i + "," + j + ") != 0: " + s); 100 //System.out.println("red = " + red.getClass().getName()); 101 } 102 return false; 103 } 104 } 105 } 106 return true; 107 } 108 109 110 /** 111 * R-Groebner base using pairlist class. 112 * @param modv module variable number. 113 * @param F polynomial list. 114 * @return GB(F) a R-Groebner base of F. 115 */ 116 public List<GenPolynomial<C>> GB(int modv, List<GenPolynomial<C>> F) { 117 /* boolean closure */ 118 List<GenPolynomial<C>> bcF = red.reducedBooleanClosure(F); 119 logger.info("#bcF-#F = " + (bcF.size() - F.size())); 120 F = bcF; 121 /* normalize input */ 122 List<GenPolynomial<C>> G = new ArrayList<GenPolynomial<C>>(); 123 OrderedRPairlist<C> pairlist = null; 124 for (GenPolynomial<C> p : F) { 125 if (!p.isZERO()) { 126 p = p.monic(); //p.abs(); // not monic, monic if boolean closed 127 if (p.isONE()) { 128 G.clear(); 129 G.add(p); 130 return G; // since boolean closed and no threads are activated 131 } 132 G.add(p); //G.add( 0, p ); //reverse list 133 if (pairlist == null) { 134 pairlist = new OrderedRPairlist<C>(modv, p.ring); 135 } 136 // putOne not required 137 pairlist.put(p); 138 } 139 } 140 if (G.size() <= 1) { 141 return G; // since boolean closed and no threads are activated 142 } 143 /* loop on critical pairs */ 144 Pair<C> pair; 145 GenPolynomial<C> pi; 146 GenPolynomial<C> pj; 147 GenPolynomial<C> S; 148 //GenPolynomial<C> D; 149 GenPolynomial<C> H; 150 List<GenPolynomial<C>> bcH; 151 //int len = G.size(); 152 //System.out.println("len = " + len); 153 while (pairlist.hasNext()) { 154 pair = pairlist.removeNext(); 155 //System.out.println("pair = " + pair); 156 if (pair == null) 157 continue; 158 159 pi = pair.pi; 160 pj = pair.pj; 161 if (logger.isDebugEnabled()) { 162 logger.debug("pi = " + pi); 163 logger.debug("pj = " + pj); 164 } 165 if (!red.moduleCriterion(modv, pi, pj)) { 166 continue; 167 } 168 169 // S-polynomial ----------------------- 170 // Criterion3() Criterion4() not applicable 171 S = red.SPolynomial(pi, pj); 172 if (S.isZERO()) { 173 pair.setZero(); 174 continue; 175 } 176 if (logger.isDebugEnabled()) { 177 logger.debug("ht(S) = " + S.leadingExpVector()); 178 } 179 180 H = red.normalform(G, S); 181 if (H.isZERO()) { 182 pair.setZero(); 183 continue; 184 } 185 //H = H.monic(); // only for boolean closed H 186 if (logger.isDebugEnabled()) { 187 logger.debug("ht(H) = " + H.leadingExpVector()); 188 } 189 190 if (H.isONE()) { // mostly useless 191 G.clear(); 192 G.add(H); 193 return G; // not boolean closed ok, since no threads are activated 194 } 195 if (logger.isDebugEnabled()) { 196 logger.debug("H = " + H); 197 } 198 if (!H.isZERO()) { 199 logger.info("Sred = " + H); 200 //len = G.size(); 201 bcH = red.reducedBooleanClosure(G, H); 202 logger.info("#bcH = " + bcH.size()); 203 for (GenPolynomial<C> h : bcH) { 204 h = h.monic(); // monic() ok, since boolean closed 205 G.add(h); 206 pairlist.put(h); 207 } 208 if (debug) { 209 if (!pair.getUseCriterion3() || !pair.getUseCriterion4()) { 210 logger.info("H != 0 but: " + pair); 211 } 212 } 213 } 214 } 215 logger.debug("#sequential list = " + G.size()); 216 G = minimalGB(G); 217 //G = red.irreducibleSet(G); 218 logger.info("" + pairlist); 219 return G; 220 } 221 222 223 /** 224 * Minimal ordered Groebner basis. 225 * @param Gp a Groebner base. 226 * @return a reduced Groebner base of Gp. 227 */ 228 @Override 229 public List<GenPolynomial<C>> minimalGB(List<GenPolynomial<C>> Gp) { 230 if (Gp == null || Gp.size() <= 1) { 231 return Gp; 232 } 233 // remove zero polynomials 234 List<GenPolynomial<C>> G = new ArrayList<GenPolynomial<C>>(Gp.size()); 235 for (GenPolynomial<C> a : Gp) { 236 if (a != null && !a.isZERO()) { // always true in GB() 237 // already positive a = a.abs(); 238 G.add(a); 239 } 240 } 241 if (G.size() <= 1) { 242 //wg monic do not return G; 243 } 244 // remove top reducible polynomials 245 GenPolynomial<C> a, b; 246 List<GenPolynomial<C>> F; 247 List<GenPolynomial<C>> bcH; 248 F = new ArrayList<GenPolynomial<C>>(G.size()); 249 while (G.size() > 0) { 250 a = G.remove(0); 251 b = a; 252 if (red.isTopReducible(G, a) || red.isTopReducible(F, a)) { 253 // drop polynomial 254 if (true || debug) { 255 List<GenPolynomial<C>> ff; 256 ff = new ArrayList<GenPolynomial<C>>(G); 257 ff.addAll(F); 258 a = red.normalform(ff, a); 259 if (!a.isZERO()) { // happens 260 logger.info("minGB not zero " + a); 261 bcH = red.reducedBooleanClosure(G, a); 262 if (bcH.size() > 1) { // never happend so far 263 System.out.println("minGB not bc: bcH size = " + bcH.size()); 264 F.add(b); // do not replace, stay with b 265 } else { 266 //System.out.println("minGB add bc(a): a = " + a + ", bc(a) = " + bcH.get(0)); 267 F.addAll(bcH); 268 } 269 } else { 270 //System.out.println("minGB dropped " + b); 271 } 272 } 273 } else { 274 F.add(a); 275 } 276 } 277 G = F; 278 if (G.size() <= 1) { 279 // wg monic return G; 280 } 281 Collections.reverse(G); // important for lex GB 282 // reduce remaining polynomials 283 int len = G.size(); 284 int el = 0; 285 while (el < len) { 286 a = G.remove(0); 287 b = a; 288 //System.out.println("doing " + a.length()); 289 a = red.normalform(G, a); 290 bcH = red.reducedBooleanClosure(G, a); 291 if (bcH.size() > 1) { 292 System.out.println("minGB not bc: bcH size = " + bcH.size()); 293 G.add(b); // do not reduce 294 } else { 295 G.addAll(bcH); 296 } 297 el++; 298 } 299 // make monic if possible 300 F = new ArrayList<GenPolynomial<C>>(G.size()); 301 for (GenPolynomial<C> p : G) { 302 a = p.monic().abs(); 303 if (p.length() != a.length()) { 304 System.out.println("minGB not bc: #p != #a: a = " + a + ", p = " + p); 305 a = p; // dont make monic for now 306 } 307 F.add(a); 308 } 309 G = F; 310 311 /* stratify: collect polynomials with equal leading terms */ 312 ExpVector e, f; 313 F = new ArrayList<GenPolynomial<C>>(G.size()); 314 for (int i = 0; i < G.size(); i++) { 315 a = G.get(i); 316 if (a == null || a.isZERO()) { 317 continue; 318 } 319 e = a.leadingExpVector(); 320 for (int j = i + 1; j < G.size(); j++) { 321 b = G.get(j); 322 if (b == null || b.isZERO()) { 323 continue; 324 } 325 f = b.leadingExpVector(); 326 if (e.equals(f)) { 327 //System.out.println("minGB e == f: " + a + ", " + b); 328 a = a.sum(b); 329 G.set(j, null); 330 } 331 } 332 F.add(a); 333 } 334 G = F; 335 336 /* info on boolean algebra element blocks 337 Map<C,List<GenPolynomial<C>>> bd = new TreeMap<C,List<GenPolynomial<C>>>(); 338 for ( GenPolynomial<C> p : G ) { 339 C cf = p.leadingBaseCoefficient(); 340 cf = cf.idempotent(); 341 List<GenPolynomial<C>> block = bd.get( cf ); 342 if ( block == null ) { 343 block = new ArrayList<GenPolynomial<C>>(); 344 } 345 block.add( p ); 346 bd.put( cf, block ); 347 } 348 System.out.println("\nminGB bd:"); 349 for( C k: bd.keySet() ) { 350 System.out.println("\nkey = " + k + ":"); 351 System.out.println("val = " + bd.get(k)); 352 } 353 System.out.println(); 354 */ 355 return G; 356 } 357 358 }