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