001/*
002 * $Id$
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            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}