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