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