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