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