001/* 002 * $Id$ 003 */ 004 005package edu.jas.gb; 006 007 008import java.util.ArrayList; 009import java.util.BitSet; 010import java.util.Iterator; 011import java.util.LinkedList; 012import java.util.List; 013import java.util.Map; 014import java.util.SortedMap; 015import java.util.TreeMap; 016 017import org.apache.logging.log4j.LogManager; 018import org.apache.logging.log4j.Logger; 019 020import edu.jas.poly.ExpVector; 021import edu.jas.poly.GenPolynomial; 022import edu.jas.poly.GenPolynomialRing; 023import edu.jas.structure.RingElem; 024 025 026/** 027 * Pair list management. The original Buchberger algorithm with criterions 028 * following Winkler in SAC-1, Kredel in ALDES/SAC-2, Kredel in MAS. Implemented 029 * using GenPolynomial, TreeMap and BitSet. 030 * @author Heinz Kredel 031 */ 032 033public class OrderedPairlist<C extends RingElem<C>> implements PairList<C> { 034 035 036 protected final List<GenPolynomial<C>> P; 037 038 039 protected final SortedMap<ExpVector, LinkedList<Pair<C>>> pairlist; 040 041 042 protected final List<BitSet> red; 043 044 045 protected final GenPolynomialRing<C> ring; 046 047 048 protected final Reduction<C> reduction; 049 050 051 protected boolean oneInGB = false; 052 053 054 protected boolean useCriterion4 = true; 055 056 057 protected int putCount; 058 059 060 protected int remCount; 061 062 063 protected final int moduleVars; 064 065 066 private static final Logger logger = LogManager.getLogger(OrderedPairlist.class); 067 068 069 /** 070 * Constructor. 071 */ 072 public OrderedPairlist() { 073 moduleVars = 0; 074 ring = null; 075 P = null; 076 pairlist = null; 077 red = null; 078 reduction = null; 079 putCount = 0; 080 remCount = 0; 081 } 082 083 084 /** 085 * Constructor. 086 * @param r polynomial factory. 087 */ 088 public OrderedPairlist(GenPolynomialRing<C> r) { 089 this(0, r); 090 } 091 092 093 /** 094 * Constructor. 095 * @param m number of module variables. 096 * @param r polynomial factory. 097 */ 098 public OrderedPairlist(int m, GenPolynomialRing<C> r) { 099 moduleVars = m; 100 ring = r; 101 P = new ArrayList<GenPolynomial<C>>(); 102 pairlist = new TreeMap<ExpVector, LinkedList<Pair<C>>>(ring.tord.getAscendComparator()); 103 //pairlist = new TreeMap( to.getSugarComparator() ); 104 red = new ArrayList<BitSet>(); 105 putCount = 0; 106 remCount = 0; 107 if (!ring.isCommutative()) {//ring instanceof GenSolvablePolynomialRing ) { 108 useCriterion4 = false; 109 } 110 reduction = new ReductionSeq<C>(); 111 } 112 113 114 /** 115 * Create a new PairList. 116 * @param r polynomial ring. 117 */ 118 public PairList<C> create(GenPolynomialRing<C> r) { 119 return new OrderedPairlist<C>(r); 120 } 121 122 123 /** 124 * Create a new PairList. 125 * @param m number of module variables. 126 * @param r polynomial ring. 127 */ 128 public PairList<C> create(int m, GenPolynomialRing<C> r) { 129 return new OrderedPairlist<C>(m, r); 130 } 131 132 133 /** 134 * Get polynomial ring. 135 * @return the polynomial ring. 136 */ 137 public GenPolynomialRing<C> getRing() { 138 return ring; 139 } 140 141 142 /** 143 * toString. 144 */ 145 @Override 146 public String toString() { 147 StringBuffer s = new StringBuffer(this.getClass().getSimpleName() + "("); 148 //s.append("polys="+P.size()); 149 s.append("#put=" + putCount); 150 s.append(", #rem=" + remCount); 151 if (pairlist != null && pairlist.size() != 0) { 152 s.append(", size=" + pairlist.size()); 153 } 154 if (moduleVars > 0) { 155 s.append(", modv=" + moduleVars); 156 } 157 s.append(")"); 158 return s.toString(); 159 } 160 161 162 /** 163 * Put one Polynomial to the pairlist and reduction matrix. 164 * @param p polynomial. 165 * @return the index of the added polynomial. 166 */ 167 public synchronized int put(GenPolynomial<C> p) { 168 putCount++; 169 if (oneInGB) { 170 return P.size() - 1; 171 } 172 ExpVector e = p.leadingExpVector(); 173 int l = P.size(); 174 for (int j = 0; j < l; j++) { 175 GenPolynomial<C> pj = P.get(j); 176 ExpVector f = pj.leadingExpVector(); 177 if (moduleVars > 0) { 178 if (!reduction.moduleCriterion(moduleVars, e, f)) { 179 continue; // skip pair 180 } 181 } 182 ExpVector g = e.lcm(f); 183 Pair<C> pair = new Pair<C>(pj, p, j, l); 184 //System.out.println("pair.new = " + pair); 185 //multiple pairs under same keys -> list of pairs 186 LinkedList<Pair<C>> xl = pairlist.get(g); 187 if (xl == null) { 188 xl = new LinkedList<Pair<C>>(); 189 } 190 //xl.addLast( pair ); // first or last ? 191 xl.addFirst(pair); // first or last ? better for d- e-GBs 192 pairlist.put(g, xl); 193 } 194 //System.out.println("pairlist.keys@put = " + pairlist.keySet() ); 195 P.add(p); 196 BitSet redi = new BitSet(); 197 redi.set(0, l); 198 red.add(redi); 199 //System.out.println("pairlist.red = " + red); //.get( pair.j )); //pair); 200 //System.out.println("pairlist.key = " + pairlist.keySet() ); 201 return P.size() - 1; 202 } 203 204 205 /** 206 * Put all polynomials in F to the pairlist and reduction matrix. 207 * @param F polynomial list. 208 * @return the index of the last added polynomial. 209 */ 210 public int put(List<GenPolynomial<C>> F) { 211 int i = 0; 212 for (GenPolynomial<C> p : F) { 213 i = put(p); 214 } 215 return i; 216 } 217 218 219 /** 220 * Remove the next required pair from the pairlist and reduction matrix. 221 * Apply the criterions 3 and 4 to see if the S-polynomial is required. 222 * @return the next pair if one exists, otherwise null. 223 */ 224 public synchronized Pair<C> removeNext() { 225 if (oneInGB) { 226 return null; 227 } 228 Iterator<Map.Entry<ExpVector, LinkedList<Pair<C>>>> ip = pairlist.entrySet().iterator(); 229 230 Pair<C> pair = null; 231 boolean c = false; 232 int i, j; 233 234 while (!c && ip.hasNext()) { 235 Map.Entry<ExpVector, LinkedList<Pair<C>>> me = ip.next(); 236 ExpVector g = me.getKey(); 237 LinkedList<Pair<C>> xl = me.getValue(); 238 if (logger.isInfoEnabled()) { 239 logger.info("g = {}", g); 240 } 241 pair = null; 242 while (!c && xl.size() > 0) { 243 pair = xl.removeFirst(); 244 // xl is also modified in pairlist 245 i = pair.i; 246 j = pair.j; 247 // System.out.println("pair(" + j + "," +i+") "); 248 if (useCriterion4) { 249 c = reduction.criterion4(pair.pi, pair.pj, g); 250 } else { 251 c = true; 252 } 253 //System.out.println("c4_o = " + c); 254 if (c) { 255 c = criterion3(i, j, g); 256 //System.out.println("c3_o = " + c); 257 } 258 red.get(j).clear(i); // set(i,false) jdk1.4 259 } 260 if (xl.size() == 0) { 261 ip.remove(); 262 // = pairlist.remove( g ); 263 } 264 } 265 if (!c) { 266 pair = null; 267 } else { 268 pair.maxIndex(P.size() - 1); 269 remCount++; // count only real pairs 270 if (logger.isDebugEnabled()) { 271 logger.info("pair({},{})", pair.j, pair.i); 272 } 273 } 274 return pair; 275 } 276 277 278 /** 279 * Test if there is possibly a pair in the list. 280 * @return true if a next pair could exist, otherwise false. 281 */ 282 public synchronized boolean hasNext() { 283 return pairlist.size() > 0; 284 } 285 286 287 /** 288 * Get the list of polynomials. 289 * @return the polynomial list. 290 */ 291 public List<GenPolynomial<C>> getList() { 292 return P; 293 } 294 295 296 /** 297 * Set the list of polynomials. 298 * @param F the polynomial list. 299 */ 300 public void setList(List<GenPolynomial<C>> F) { 301 if (!P.isEmpty()) { 302 throw new IllegalArgumentException("P not empty"); 303 } 304 P.addAll(F); 305 for (int i = 0; i < P.size(); i++) { 306 BitSet redi = new BitSet(); 307 red.add(redi); 308 } 309 310 } 311 312 313 /** 314 * Get the size of the list of polynomials. 315 * @return size of the polynomial list. 316 */ 317 public int size() { 318 return P.size(); 319 } 320 321 322 /** 323 * Get the number of polynomials put to the pairlist. 324 * @return the number of calls to put. 325 */ 326 public synchronized int putCount() { 327 return putCount; 328 } 329 330 331 /** 332 * Get the number of required pairs removed from the pairlist. 333 * @return the number of non null pairs delivered. 334 */ 335 public synchronized int remCount() { 336 return remCount; 337 } 338 339 340 /** 341 * Put the ONE-Polynomial to the pairlist. 342 * @param one polynomial. (no more required) 343 * @return the index of the last polynomial. 344 */ 345 public synchronized int putOne(GenPolynomial<C> one) { 346 if (one == null) { 347 return P.size() - 1; 348 } 349 if (!one.isONE()) { 350 return P.size() - 1; 351 } 352 return putOne(); 353 } 354 355 356 /** 357 * Put the ONE-Polynomial to the pairlist. 358 * @return the index of the last polynomial. 359 */ 360 public synchronized int putOne() { 361 putCount++; 362 oneInGB = true; 363 pairlist.clear(); 364 P.clear(); 365 P.add(ring.getONE()); 366 red.clear(); 367 logger.info("outOne {}", this); 368 return P.size() - 1; 369 } 370 371 372 /** 373 * GB criterium 3. 374 * @return true if the S-polynomial(i,j) is required. 375 */ 376 public boolean criterion3(int i, int j, ExpVector eij) { 377 // assert i < j; 378 boolean s = red.get(j).get(i); 379 if (!s) { 380 logger.warn("c3.s false for j, i = {}, {}", j, i); 381 return s; 382 } 383 // now s = true; 384 for (int k = 0; k < P.size(); k++) { 385 // System.out.println("i , k , j "+i+" "+k+" "+j); 386 if (i != k && j != k) { 387 GenPolynomial<C> A = P.get(k); 388 ExpVector ek = A.leadingExpVector(); 389 boolean m = eij.multipleOf(ek); 390 if (m) { 391 if (k < i) { 392 // System.out.println("k < i "+k+" "+i); 393 s = red.get(i).get(k) || red.get(j).get(k); 394 } else if (i < k && k < j) { 395 // System.out.println("i < k < j "+i+" "+k+" "+j); 396 s = red.get(k).get(i) || red.get(j).get(k); 397 } else if (j < k) { 398 //System.out.println("j < k "+j+" "+k); 399 s = red.get(k).get(i) || red.get(k).get(j); 400 } 401 //System.out.println("s."+k+" = " + s); 402 if (!s) { 403 return s; 404 } 405 } 406 } 407 } 408 return true; 409 } 410 411}