001/*
002 * $Id: CriticalPairList.java 4049 2012-07-25 17:10:49Z kredel $
003 */
004
005package edu.jas.gb;
006
007import java.util.ArrayList;
008import java.util.BitSet;
009import java.util.Comparator;
010import java.util.Iterator;
011import java.util.List;
012import java.util.SortedSet;
013import java.util.TreeSet;
014
015import org.apache.log4j.Logger;
016
017import edu.jas.poly.ExpVector;
018import edu.jas.poly.GenPolynomial;
019import edu.jas.poly.GenPolynomialRing;
020import edu.jas.poly.GenSolvablePolynomialRing;
021import edu.jas.structure.RingElem;
022
023/**
024 * Critical pair list management.
025 * Makes some effort to produce the same sequence of critical pairs 
026 * as in the sequential case, when used in parallel.
027 * However already reduced pairs are not re-reduced if new
028 * polynomials appear.
029 * Implemented using GenPolynomial, SortedSet / TreeSet and BitSet.
030 * @author Heinz Kredel
031 */
032
033public class CriticalPairList<C extends RingElem<C>> extends OrderedPairlist<C> {
034
035    protected final SortedSet< CriticalPair<C> > pairlist; // hide super
036
037    protected int recordCount;
038
039    private static final Logger logger = Logger.getLogger(CriticalPairList.class);
040
041
042    /**
043     * Constructor for CriticalPairList.
044     */
045    public CriticalPairList() {
046        super();
047        pairlist = null;
048    }
049
050
051    /**
052     * Constructor for CriticalPairList.
053     * @param r polynomial factory.
054     */
055    public CriticalPairList(GenPolynomialRing<C> r) {
056        this(0,r);
057    }
058
059
060    /**
061     * Constructor for CriticalPairList.
062     * @param m number of module variables.
063     * @param r polynomial factory.
064     */
065    public CriticalPairList(int m, GenPolynomialRing<C> r) {
066        super(m,r);
067        Comparator< AbstractPair<C> > cpc; 
068        cpc = new CriticalPairComparator<C>( ring.tord ); 
069        pairlist = new TreeSet< CriticalPair<C> >( cpc );
070        recordCount = 0;
071    }
072
073
074    /**
075     * Create a new PairList.
076     * @param r polynomial ring.
077     */
078    public PairList<C> create(GenPolynomialRing<C> r) {
079        return new CriticalPairList<C>(r);
080    }
081
082
083    /**
084     * Create a new PairList.
085     * @param m number of module variables.
086     * @param r polynomial ring.
087     */
088    public PairList<C> create(int m, GenPolynomialRing<C> r) {
089        return new CriticalPairList<C>(m,r);
090    }
091
092
093    /**
094     * Put a polynomial to the pairlist and reduction matrix.
095     * @param p polynomial.
096     * @return the index of the added polynomial.
097     */
098    public synchronized int put(GenPolynomial<C> p) { 
099        putCount++;
100        if ( oneInGB ) { 
101           return P.size()-1;
102        }
103        ExpVector e = p.leadingExpVector(); 
104        int len = P.size();
105        for ( int j = 0; j < len; j++ ) {
106            GenPolynomial<C> pj = P.get(j);
107            ExpVector f = pj.leadingExpVector(); 
108            if ( moduleVars > 0 ) { // test moduleCriterion
109            if ( !reduction.moduleCriterion( moduleVars, e, f) ) {
110                  continue; // skip pair
111               }
112            }
113            ExpVector g =  e.lcm( f );
114            CriticalPair<C> pair = new CriticalPair<C>( g, pj, p, j, len );
115            //System.out.println("put pair = " + pair );
116            pairlist.add( pair );
117        }
118        P.add( p );
119        BitSet redi = new BitSet();
120        redi.set( 0, len ); // >= jdk 1.4
121        red.add( redi );
122        if ( recordCount < len ) {
123            recordCount = len;
124        }
125        return len;
126    }
127
128
129    /**
130     * Test if there is possibly a pair in the list.
131     * @return true if a next pair could exist, otherwise false.
132     */
133    public synchronized boolean hasNext() { 
134          return pairlist.size() > 0;
135    }
136
137
138    /**
139     * Get and remove the next required pair from the pairlist.
140     * Appy the criterions 3 and 4 to see if the S-polynomial is required.
141     * The pair is not removed from the pair list.
142     * @return the next pair if one exists, otherwise null.
143     */
144    public Pair<C> removeNext() { 
145        CriticalPair<C> cp = getNext();
146        if ( cp == null ) {
147            return null;
148        }
149        return new Pair<C>(cp.pi,cp.pj,cp.i,cp.j);
150    }
151
152
153    /**
154     * Get the next required pair from the pairlist.
155     * Appy the criterions 3 and 4 to see if the S-polynomial is required.
156     * The pair is not removed from the pair list.
157     * @return the next pair if one exists, otherwise null.
158     */
159    public synchronized CriticalPair<C> getNext() { 
160        if ( oneInGB ) {
161           return null;
162        }
163        CriticalPair<C> pair = null;
164        Iterator< CriticalPair<C> > ip = pairlist.iterator();
165        boolean c = false;
166        while ( !c && ip.hasNext() )  { // findbugs
167           pair = ip.next();
168           if ( pair.getInReduction() ) {
169               continue;
170           }
171           if ( pair.getReductum() != null ) {
172               continue;
173           }
174           if ( logger.isInfoEnabled() ) {
175              logger.info("" + pair);
176           }
177           if ( useCriterion4 ) {
178              c = reduction.criterion4( pair.pi, pair.pj, pair.e ); 
179              // System.out.println("c4  = " + c); 
180           } else {
181              c = true;
182           }
183           if ( c ) {
184              c = criterion3( pair.i, pair.j, pair.e );
185              // System.out.println("c3  = " + c); 
186           }
187           red.get( pair.j ).clear( pair.i ); // set(i,false) jdk1.4
188           if ( ! c ) { // set done
189               pair.setReductum( ring.getZERO() );
190           }
191        }
192        if ( ! c ) {
193           pair = null;
194        } else {
195           remCount++; // count only real pairs
196           pair.setInReduction(); // set to work
197        }
198        return pair; 
199    }
200
201
202    /**
203     * Record reduced polynomial.
204     * @param pair the corresponding critical pair.
205     * @param p polynomial.
206     * @return index of recorded polynomial, or -1 if not added.
207     */
208    public int record(CriticalPair<C> pair, GenPolynomial<C> p) { 
209        if ( p == null ) {
210            p = ring.getZERO();
211        }
212        pair.setReductum(p);
213        // trigger thread
214        if ( ! p.isZERO() && ! p.isONE() ) {
215           recordCount++;
216           return recordCount;
217        }
218        return -1;
219    }
220
221
222    /**
223     * Record reduced polynomial and update critical pair list. 
224     * Note: it is better to use record and uptate separately.
225     * @param pair the corresponding critical pair.
226     * @param p polynomial.
227     * @return index of recorded polynomial
228     */
229    public int update(CriticalPair<C> pair, GenPolynomial<C> p) { 
230        if ( p == null ) {
231            p = ring.getZERO();
232        }
233        pair.setReductum(p);
234        if ( ! p.isZERO() && ! p.isONE() ) {
235           recordCount++;
236        }
237        int c = update();
238        if (c < 0) { // use for findbugs 
239            System.out.println("c < 0");
240        }
241        if ( ! p.isZERO() && ! p.isONE() ) {
242           return recordCount;
243        } 
244        return -1;
245    }
246
247
248    /**
249     * Update pairlist.
250     * Preserve the sequential pair sequence.
251     * Remove pairs with completed reductions.
252     * @return the number of added polynomials.
253     */
254    public synchronized int update() { 
255        int num = 0;
256        if ( oneInGB ) {
257           return num;
258        }
259        while ( pairlist.size() > 0 ) {
260            CriticalPair<C> pair = pairlist.first();
261            GenPolynomial<C> p = pair.getReductum();
262            if ( p != null ) {
263               pairlist.remove( pair );
264               num++;
265               if ( ! p.isZERO() ) {
266                  if ( p.isONE() ) {
267                     putOne(); // sets size = 1
268                  } else {
269                     put( p ); // changes pair list
270                  }
271               }
272            } else {
273               break;
274            }
275        }
276        return num;
277    }
278
279
280    /**
281     * In work pairs. List pairs which are currently reduced.
282     * @return list of critical pairs which are in reduction.
283     */
284    public synchronized List<CriticalPair<C>> inWork() { 
285        List<CriticalPair<C>> iw;
286        iw = new ArrayList<CriticalPair<C>>();
287        if ( oneInGB ) {
288            return iw;
289        }
290        for ( CriticalPair<C> pair : pairlist ) {
291            if ( pair.getInReduction() ) {
292               iw.add( pair );
293            }
294        }
295        return iw;
296    }
297
298
299    /**
300     * Update pairlist, several pairs at once. 
301     * This version does not preserve the sequential pair sequence.
302     * Remove pairs with completed reductions.
303     * @return the number of added polynomials.
304     */
305    public synchronized int updateMany() { 
306        int num = 0;
307        if ( oneInGB ) {
308           return num;
309        }
310        List<CriticalPair<C>> rem = new ArrayList<CriticalPair<C>>();
311        for ( CriticalPair<C> pair : pairlist ) {
312            if ( pair.getReductum() != null ) {
313               rem.add( pair );
314               num++;
315            } else {
316               break;
317            }
318        }
319        // must work on a copy to avoid concurrent modification
320        for ( CriticalPair<C> pair : rem ) {
321            // System.out.println("update = " + pair); 
322            pairlist.remove( pair );
323            GenPolynomial<C> p = pair.getReductum();
324            if ( ! p.isZERO() ) {
325               if ( p.isONE() ) {
326                  putOne();
327               } else {
328                  put( p );
329               }
330            }
331        }
332        return num;
333    }
334
335
336    /**
337     * Put the ONE-Polynomial to the pairlist.
338     * @return the index of the last polynomial.
339     */
340    public synchronized int putOne() { 
341        super.putOne();
342        pairlist.clear();
343        return 0;
344    }
345
346}