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