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