001/*
002 * $Id: OrderedPairlist.java 4975 2014-10-23 21:03:46Z 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     * Put all power series in F to the pairlist and reduction matrix.
157     * @param F power series list.
158     * @return the index of the last added power series.
159     */
160    public int put(List<MultiVarPowerSeries<C>> F) {
161        int i = 0;
162        for (MultiVarPowerSeries<C> p : F) {
163            i = put(p);
164        }
165        return i;
166    }
167
168
169    /**
170     * Remove the next required pair from the pairlist and reduction matrix.
171     * Apply the criterions 3 and 4 to see if the S-power-series is required.
172     * @return the next pair if one exists, otherwise null.
173     */
174    public synchronized Pair<C> removeNext() {
175        if (oneInGB) {
176            return null;
177        }
178        Iterator<Map.Entry<ExpVector, LinkedList<Pair<C>>>> ip = pairlist.entrySet().iterator();
179
180        Pair<C> pair = null;
181        boolean c = false;
182        int i, j;
183
184        while (!c && ip.hasNext()) {
185            Map.Entry<ExpVector, LinkedList<Pair<C>>> me = ip.next();
186            ExpVector g = me.getKey();
187            LinkedList<Pair<C>> xl = me.getValue();
188            if (logger.isInfoEnabled())
189                logger.info("g  = " + g);
190            pair = null;
191            while (!c && xl.size() > 0) {
192                pair = xl.removeFirst();
193                // xl is also modified in pairlist 
194                i = pair.i;
195                j = pair.j;
196                // System.out.println("pair(" + j + "," +i+") ");
197                c = true;
198                if (useCriterion4) {
199                    c = reduction.criterion4(pair.pi, pair.pj, g);
200                }
201                //System.out.println("c4  = " + c);  
202                if (c && useCriterion3) {
203                    c = criterion3(i, j, g);
204                    //System.out.println("c3  = " + c); 
205                }
206                red.get(j).clear(i); // set(i,false) jdk1.4
207            }
208            if (xl.size() == 0)
209                ip.remove();
210            // = pairlist.remove( g );
211        }
212        if (!c) {
213            pair = null;
214        } else {
215            remCount++; // count only real pairs
216        }
217        return pair;
218    }
219
220
221    /**
222     * Test if there is possibly a pair in the list.
223     * @return true if a next pair could exist, otherwise false.
224     */
225    public synchronized boolean hasNext() {
226        return pairlist.size() > 0;
227    }
228
229
230    /**
231     * Get the list of power series.
232     * @return the power series list.
233     */
234    public List<MultiVarPowerSeries<C>> getList() {
235        return P;
236    }
237
238
239    /**
240     * Get the number of power series put to the pairlist.
241     * @return the number of calls to put.
242     */
243    public synchronized int putCount() {
244        return putCount;
245    }
246
247
248    /**
249     * Get the number of required pairs removed from the pairlist.
250     * @return the number of non null pairs delivered.
251     */
252    public synchronized int remCount() {
253        return remCount;
254    }
255
256
257    /**
258     * Put to ONE-power-series to the pairlist.
259     * @param one power series. (no more required)
260     * @return the index of the last power series.
261     */
262    public synchronized int putOne(MultiVarPowerSeries<C> one) {
263        putCount++;
264        if (one == null) {
265            return P.size() - 1;
266        }
267        if (!one.isONE()) {
268            return P.size() - 1;
269        }
270        return putOne();
271    }
272
273
274    /**
275     * Put the ONE-power-series to the pairlist.
276     * @return the index of the last power-series.
277     */
278    public synchronized int putOne() {
279        oneInGB = true;
280        pairlist.clear();
281        P.clear();
282        P.add(ring.getONE());
283        red.clear();
284        return P.size() - 1;
285    }
286
287
288    /**
289     * GB criterion 3.
290     * @return true if the S-power-series(i,j) is required.
291     */
292    public boolean criterion3(int i, int j, ExpVector eij) {
293        // assert i < j;
294        boolean s = red.get(j).get(i);
295        if (!s) {
296            logger.warn("c3.s false for " + j + " " + i);
297            return s;
298        }
299        // now s = true;
300        for (int k = 0; k < P.size(); k++) {
301            MultiVarPowerSeries<C> A = P.get(k);
302            ExpVector ek = A.orderExpVector();
303            boolean m = eij.multipleOf(ek);
304            if (m) {
305                if (k < i) {
306                    // System.out.println("k < i "+k+" "+i); 
307                    s = red.get(i).get(k) || red.get(j).get(k);
308                } else if (i < k && k < j) {
309                    // System.out.println("i < k < j "+i+" "+k+" "+j); 
310                    s = red.get(k).get(i) || red.get(j).get(k);
311                } else if (j < k) {
312                    //System.out.println("j < k "+j+" "+k); 
313                    s = red.get(k).get(i) || red.get(k).get(j);
314                }
315                //System.out.println("s."+k+" = " + s); 
316                if (!s) {
317                    return s;
318                }
319            }
320        }
321        return true;
322    }
323
324}