001/*
002 * $Id: OrderedCPairlist.java 4127 2012-08-19 19:27:47Z kredel $
003 */
004
005package edu.jas.application;
006
007
008import java.io.Serializable;
009import java.util.ArrayList;
010import java.util.BitSet;
011import java.util.Iterator;
012import java.util.LinkedList;
013import java.util.List;
014import java.util.Map;
015import java.util.SortedMap;
016import java.util.TreeMap;
017
018import org.apache.log4j.Logger;
019
020import edu.jas.poly.ExpVector;
021import edu.jas.poly.GenPolynomial;
022import edu.jas.poly.GenPolynomialRing;
023import edu.jas.poly.GenSolvablePolynomialRing;
024import edu.jas.structure.GcdRingElem;
025import edu.jas.structure.RingFactory;
026
027
028/**
029 * Pair list management. Implemented for ColorPolynomials using TreeMap and
030 * BitSet.
031 * @author Heinz Kredel
032 */
033
034public class OrderedCPairlist<C extends GcdRingElem<C>> implements Serializable {
035
036
037    private static final Logger logger = Logger.getLogger(OrderedCPairlist.class);
038
039
040    protected final GenPolynomialRing<GenPolynomial<C>> ring;
041
042
043    protected final List<ColorPolynomial<C>> P;
044
045
046    protected final SortedMap<ExpVector, LinkedList<CPair<C>>> pairlist;
047
048
049    protected final List<BitSet> red;
050
051
052    protected final CReductionSeq<C> reduction;
053
054
055    protected boolean oneInGB = false;
056
057
058    protected boolean useCriterion4 = false; // unused
059
060
061    protected int putCount;
062
063
064    protected int remCount;
065
066
067    protected final int moduleVars; // unused
068
069
070    /**
071     * Constructor for OrderedPairlist.
072     * @param r polynomial factory.
073     */
074    public OrderedCPairlist(GenPolynomialRing<GenPolynomial<C>> r) {
075        this(0, r);
076    }
077
078
079    /**
080     * Constructor for OrderedPairlist.
081     * @param m number of module variables.
082     * @param r polynomial factory.
083     */
084    public OrderedCPairlist(int m, GenPolynomialRing<GenPolynomial<C>> r) {
085        moduleVars = m;
086        ring = r;
087        P = new ArrayList<ColorPolynomial<C>>();
088        pairlist = new TreeMap<ExpVector, LinkedList<CPair<C>>>(ring.tord.getAscendComparator());
089        // pairlist = new TreeMap( to.getSugarComparator() );
090        red = new ArrayList<BitSet>();
091        putCount = 0;
092        remCount = 0;
093        if (ring instanceof GenSolvablePolynomialRing) {
094            useCriterion4 = false;
095        }
096        RingFactory<GenPolynomial<C>> rf = ring.coFac;
097        GenPolynomialRing<C> cf = (GenPolynomialRing<C>) rf;
098        reduction = new CReductionSeq<C>(cf.coFac);
099    }
100
101
102    /**
103     * Internal constructor for OrderedPairlist. Used to clone this pair list.
104     * @param m number of module variables.
105     * @param r polynomial factory.
106     */
107    private OrderedCPairlist(int m, GenPolynomialRing<GenPolynomial<C>> ring, List<ColorPolynomial<C>> P,
108                    SortedMap<ExpVector, LinkedList<CPair<C>>> pl, List<BitSet> red, CReductionSeq<C> cred,
109                    int pc, int rc) {
110        moduleVars = m;
111        this.ring = ring;
112        this.P = P;
113        pairlist = pl;
114        this.red = red;
115        reduction = cred;
116        putCount = pc;
117        remCount = rc;
118    }
119
120
121    /**
122     * Clone this OrderedPairlist.
123     * @return a 2 level clone of this.
124     */
125    public synchronized OrderedCPairlist<C> copy() {
126        return new OrderedCPairlist<C>(moduleVars, ring, new ArrayList<ColorPolynomial<C>>(P),
127                        clonePairlist(), cloneBitSet(), reduction, putCount, remCount);
128    }
129
130
131    /**
132     * Clone this pairlist.
133     * @return a 2 level clone of this pairlist.
134     */
135    private SortedMap<ExpVector, LinkedList<CPair<C>>> clonePairlist() {
136        SortedMap<ExpVector, LinkedList<CPair<C>>> pl = new TreeMap<ExpVector, LinkedList<CPair<C>>>(
137                        ring.tord.getAscendComparator());
138        for (Map.Entry<ExpVector, LinkedList<CPair<C>>> m : pairlist.entrySet()) {
139            ExpVector e = m.getKey();
140            LinkedList<CPair<C>> l = m.getValue();
141            l = new LinkedList<CPair<C>>(l);
142            pl.put(e, l);
143        }
144        return pl;
145    }
146
147
148    /**
149     * Count remaining Pairs.
150     * @return number of pairs remaining in this pairlist.
151     */
152    public int pairCount() {
153        int c = 0;
154        for (Map.Entry<ExpVector, LinkedList<CPair<C>>> m : pairlist.entrySet()) {
155            LinkedList<CPair<C>> l = m.getValue();
156            c += l.size();
157        }
158        return c;
159    }
160
161
162    /**
163     * Clone this reduction BitSet.
164     * @return a 2 level clone of this reduction BitSet.
165     */
166    private List<BitSet> cloneBitSet() {
167        List<BitSet> r = new ArrayList<BitSet>(this.red.size());
168        for (BitSet b : red) {
169            BitSet n = (BitSet) b.clone();
170            r.add(n);
171        }
172        return r;
173    }
174
175
176    /**
177     * bitCount.
178     * @return number of bits set in this bitset.
179     */
180    public int bitCount() {
181        int c = 0;
182        for (BitSet b : red) {
183            c += b.cardinality();
184        }
185        return c;
186    }
187
188
189    /**
190     * toString.
191     * @return counters of this.
192     */
193    @Override
194    public String toString() {
195        int p = pairCount();
196        int b = bitCount();
197        if (p != b) {
198            return "OrderedCPairlist( pairCount=" + p + ", bitCount=" + b + ", putCount=" + putCount
199                            + ", remCount=" + remCount + " )";
200        }
201        return "OrderedCPairlist( pairCount=" + p + ", putCount=" + putCount + ", remCount=" + remCount
202                        + " )";
203    }
204
205
206    /**
207     * Equals.
208     * @param ob an Object.
209     * @return true if this is equal to o, else false.
210     */
211    @Override
212    @SuppressWarnings("unchecked")
213    public boolean equals(Object ob) {
214        OrderedCPairlist<C> c = null;
215        try {
216            c = (OrderedCPairlist<C>) ob;
217        } catch (ClassCastException e) {
218            return false;
219        }
220        if (c == null) {
221            return false;
222        }
223        boolean t = getList().equals(c.getList());
224        if (!t) {
225            return t;
226        }
227        t = pairCount() == c.pairCount();
228        if (!t) {
229            return t;
230        }
231        return true;
232    }
233
234
235    /**
236     * Hash code for this pair list.
237     * @see java.lang.Object#hashCode()
238     */
239    @Override
240    public int hashCode() {
241        int h;
242        h = getList().hashCode();
243        h = h << 7;
244        h += pairCount(); // findbugs
245        return h;
246    }
247
248
249    /**
250     * Put one Polynomial to the pairlist and reduction matrix.
251     * @param p polynomial.
252     * @return the index of the added polynomial.
253     */
254    public synchronized int put(ColorPolynomial<C> p) {
255        putCount++;
256        if (oneInGB) {
257            return P.size() - 1;
258        }
259        ExpVector e = p.leadingExpVector();
260        // System.out.println("p = " + p);
261        int l = P.size();
262        for (int j = 0; j < l; j++) {
263            ColorPolynomial<C> pj = P.get(j);
264            // System.out.println("pj = " + pj);
265            ExpVector f = pj.leadingExpVector();
266            if (moduleVars > 0) {
267                if (e.invLexCompareTo(f, 0, moduleVars) != 0) {
268                    continue; // skip pair
269                }
270            }
271            // System.out.println("e = " + e + ", f = " + f);
272            ExpVector g = e.lcm(f); // EVLCM( e, f );
273            CPair<C> pair = new CPair<C>(pj, p, j, l);
274            // redi = (BitSet)red.get(j);
275            // /if ( j < l ) redi.set( l );
276            // System.out.println("bitset."+j+" = " + redi );
277
278            // multiple pairs under same keys -> list of pairs
279            LinkedList<CPair<C>> xl = pairlist.get(g);
280            if (xl == null) {
281                xl = new LinkedList<CPair<C>>();
282            }
283            // xl.addLast( pair ); // first or last ?
284            xl.addFirst(pair); // first or last ? better for d- e-GBs
285            pairlist.put(g, xl);
286        }
287        // System.out.println("pairlist.keys@put = " + pairlist.keySet() );
288        P.add(p);
289        BitSet redi = new BitSet();
290        redi.set(0, l); // jdk 1.4
291        red.add(redi);
292        return P.size() - 1;
293    }
294
295
296    /**
297     * Remove the next required pair from the pairlist and reduction matrix.
298     * Appy the criterions 3 and 4 to see if the S-polynomial is required.
299     * @return the next pair if one exists, otherwise null.
300     */
301    public synchronized CPair<C> removeNext() {
302        if (oneInGB) {
303            return null;
304        }
305        Iterator<Map.Entry<ExpVector, LinkedList<CPair<C>>>> ip = pairlist.entrySet().iterator();
306
307        CPair<C> pair = null;
308        boolean c = false;
309        int i, j;
310
311        while (!c && ip.hasNext()) {
312            Map.Entry<ExpVector, LinkedList<CPair<C>>> me = ip.next();
313            ExpVector g = me.getKey();
314            LinkedList<CPair<C>> xl = me.getValue();
315            if (logger.isInfoEnabled())
316                logger.info("g  = " + g);
317            pair = null;
318            while (!c && xl.size() > 0) {
319                pair = xl.removeFirst();
320                // xl is also modified in pairlist
321                i = pair.i;
322                j = pair.j;
323                // System.out.println("pair(" + j + "," +i+") ");
324                //if (useCriterion4) {
325                    // c = reduction.criterion4( pair.pi, pair.pj, g );
326                //    c = true;
327                //}
328                c = true; 
329                // System.out.println("c4 = " + c);
330                //if (c) {
331                    // c = criterion3( i, j, g );
332                    // System.out.println("c3 = " + c);
333                //}
334                red.get(j).clear(i); // set(i,false) jdk1.4
335            }
336            if (xl.size() == 0)
337                ip.remove();
338            // = pairlist.remove( g );
339        }
340        if (!c) {
341            pair = null;
342        } else {
343            remCount++; // count only real pairs
344        }
345        return pair;
346    }
347
348
349    /**
350     * Test if there is possibly a pair in the list.
351     * @return true if a next pair could exist, otherwise false.
352     */
353    public synchronized boolean hasNext() {
354        return pairlist.size() > 0;
355    }
356
357
358    /**
359     * Get the list of polynomials.
360     * @return the polynomial list.
361     */
362    public List<ColorPolynomial<C>> getList() {
363        return P;
364    }
365
366
367    /**
368     * Get the number of polynomials put to the pairlist.
369     * @return the number of calls to put.
370     */
371    public synchronized int putCount() {
372        return putCount;
373    }
374
375
376    /**
377     * Get the number of required pairs removed from the pairlist.
378     * @return the number of non null pairs delivered.
379     */
380    public synchronized int remCount() {
381        return remCount;
382    }
383
384
385    /**
386     * Put to ONE-Polynomial to the pairlist.
387     * @param one polynomial. (no more required)
388     * @return the index of the last polynomial.
389     */
390    public synchronized int putOne(ColorPolynomial<C> one) {
391        putCount++;
392        if (one == null) {
393            return P.size() - 1;
394        }
395        if (!one.isONE()) {
396            return P.size() - 1;
397        }
398        oneInGB = true;
399        pairlist.clear();
400        P.clear();
401        P.add(one);
402        red.clear();
403        return P.size() - 1;
404    }
405
406
407    /**
408     * GB criterium 3.
409     * @return true if the S-polynomial(i,j) is required.
410     */
411    public boolean criterion3(int i, int j, ExpVector eij) {
412        // assert i < j;
413        boolean s = red.get(j).get(i);
414        if (!s) {
415            logger.warn("c3.s false for " + j + " " + i);
416            return s;
417        }
418        // now s = true;
419        for (int k = 0; k < P.size(); k++) {
420            if (i != k && j != k) {
421                ColorPolynomial<C> A = P.get(k);
422                ExpVector ek = A.leadingExpVector();
423                boolean m = eij.multipleOf(ek); // EVMT(eij,ek);
424                if (m) {
425                    if (k < i) {
426                        // System.out.println("k < i "+k+" "+i);
427                        s = red.get(i).get(k) || red.get(j).get(k);
428                    } else if (i < k && k < j) {
429                        // System.out.println("i < k < j "+i+" "+k+" "+j);
430                        s = red.get(k).get(i) || red.get(j).get(k);
431                    } else if (j < k) {
432                        // System.out.println("j < k "+j+" "+k);
433                        s = red.get(k).get(i) || red.get(k).get(j);
434                    }
435                    // System.out.println("s."+k+" = " + s);
436                    if (!s) {
437                        return s;
438                    }
439                }
440            }
441        }
442        return true;
443    }
444}