001/*
002 * $Id: OrderedMinPairlist.java 5869 2018-07-20 15:53:10Z kredel $
003 */
004
005package edu.jas.gb;
006
007import java.util.ArrayList;
008import java.util.BitSet;
009import java.util.Iterator;
010import java.util.LinkedList;
011import java.util.Map;
012import java.util.TreeMap;
013
014import org.apache.logging.log4j.Logger;
015import org.apache.logging.log4j.LogManager; 
016
017import edu.jas.poly.ExpVector;
018import edu.jas.poly.GenPolynomial;
019import edu.jas.poly.GenPolynomialRing;
020import edu.jas.poly.GenSolvablePolynomialRing;
021import edu.jas.structure.RingElem;
022
023/**
024 * Pair list management.
025 * The original Buchberger algorithm with criterions 
026 * using early pair exclusion.
027 * Implemented using GenPolynomial, TreeMap and BitSet.
028 * @author Heinz Kredel
029 */
030
031public class OrderedMinPairlist<C extends RingElem<C> > extends OrderedPairlist<C> {
032
033    private static final Logger logger = LogManager.getLogger(OrderedMinPairlist.class);
034
035
036    /**
037     * Constructor.
038     */
039    public OrderedMinPairlist() {
040        super();
041    }
042
043
044    /**
045     * Constructor.
046     * @param r polynomial factory.
047     */
048    public OrderedMinPairlist(GenPolynomialRing<C> r) {
049        this(0,r);
050    }
051
052
053    /**
054     * Constructor.
055     * @param m number of module variables.
056     * @param r polynomial factory.
057     */
058    public OrderedMinPairlist(int m, GenPolynomialRing<C> r) {
059        super(m,r);
060    }
061
062
063    /**
064     * Create a new PairList.
065     * @param r polynomial ring.
066     */
067    public PairList<C> create(GenPolynomialRing<C> r) {
068        return new OrderedMinPairlist<C>(r);
069    }
070
071
072    /**
073     * Create a new PairList.
074     * @param m number of module variables.
075     * @param r polynomial ring.
076     */
077    public PairList<C> create(int m, GenPolynomialRing<C> r) {
078        return new OrderedMinPairlist<C>(m,r);
079    }
080
081
082    /**
083     * Put one Polynomial to the pairlist and reduction matrix.
084     * @param p polynomial.
085     * @return the index of the added polynomial.
086     */
087    public synchronized int put(GenPolynomial<C> p) { 
088        putCount++;
089        if ( oneInGB ) { 
090            return P.size()-1;
091        }
092        ExpVector e = p.leadingExpVector();
093        int l = P.size();
094        BitSet redi = new BitSet();
095        redi.set( 0, l ); // [0..l-1] = true
096        red.add( redi );
097        P.add(  p );
098        for ( int j = 0; j < l; j++ ) {
099            GenPolynomial<C> pj = P.get(j);
100            ExpVector f = pj.leadingExpVector(); 
101            if ( moduleVars > 0 ) {
102                if ( !reduction.moduleCriterion( moduleVars, e, f) ) {
103                    red.get(j).clear(l); 
104                    continue; // skip pair
105                }
106            }
107            ExpVector g =  e.lcm( f );
108            //System.out.println("g  = " + g);  
109            Pair<C> pair = new Pair<C>( pj, p, j, l);
110            boolean c = true;
111            if ( useCriterion4 ) {
112                c = reduction.criterion4( pair.pi, pair.pj, g ); 
113            }
114            //System.out.println("c4  = " + c);  
115            if ( c ) {
116                c = criterion3( j, l, g );
117                //System.out.println("c3  = " + c); 
118            }
119            if ( !c ) { // skip pair
120                red.get(j).clear(l); 
121                //System.out.println("c_skip = " + g); 
122                continue; 
123            }
124            //multiple pairs under same keys -> list of pairs
125            LinkedList<Pair<C>> xl = pairlist.get( g );
126            if ( xl == null ) {
127                xl = new LinkedList<Pair<C>>();
128            }
129            //xl.addLast( pair ); // first or last ?
130            xl.addFirst( pair ); // first or last ? better for d- e-GBs
131            pairlist.put( g, xl );
132        }
133        // System.out.println("pairlist.keys@put = " + pairlist.keySet() );  
134        return P.size()-1;
135    }
136
137
138    /**
139     * Remove the next required pair from the pairlist and reduction matrix.
140     * Appy the criterions 3 and 4 to see if the S-polynomial is required.
141     * @return the next pair if one exists, otherwise null.
142     */
143    public synchronized Pair<C> removeNext() { 
144        if ( oneInGB ) {
145            return null;
146        }
147        Iterator< Map.Entry<ExpVector,LinkedList<Pair<C>>> > ip 
148            = pairlist.entrySet().iterator();
149
150        Pair<C> pair = null;
151        boolean c = false;
152        int i, j;
153
154        while ( !c && ip.hasNext() )  {
155            Map.Entry<ExpVector,LinkedList<Pair<C>>> me = ip.next();
156            ExpVector g =  me.getKey();
157            LinkedList<Pair<C>> xl = me.getValue();
158            if ( logger.isInfoEnabled() ) {
159                logger.info("g  = " + g);
160            }
161            pair = null;
162            while ( !c && xl.size() > 0 ) {
163                pair = xl.removeFirst();
164                // xl is also modified in pairlist 
165                i = pair.i; 
166                j = pair.j; 
167                // System.out.println("pair(" + j + "," +i+") ");
168                if ( !red.get(j).get(i) ) {
169                    System.out.println("c_y = " + g); // + ", " + red.get(j).get(i)); 
170                    continue;
171                }
172                c = true;
173                if ( useCriterion4 ) {
174                    c = reduction.criterion4( pair.pi, pair.pj, g ); 
175                }
176                //System.out.println("c4_x = " + c);  
177                if ( c ) {
178                    c = criterion3( i, j, g );
179                    //System.out.println("c3_x = " + c); 
180                }
181                if ( !c ) {
182                    //System.out.println("c_x = " + g); 
183                }
184                red.get( j ).clear(i); // set(i,false) jdk1.4
185            }
186            if ( xl.size() == 0 ) {
187                ip.remove(); 
188                // = pairlist.remove( g );
189            }
190        }
191        if ( ! c ) {
192            pair = null;
193        } else {
194            pair.maxIndex(P.size()-1);
195            remCount++; // count only real pairs
196            if ( logger.isDebugEnabled() ) {
197                logger.info("pair(" + pair.j + "," + pair.i + ")");
198            }
199        }
200        return pair; 
201    }
202
203
204    /**
205     * GB criterium 3.
206     * @return true if the S-polynomial(i,j) is required.
207     */
208    public boolean criterion3(int i, int j, ExpVector eij) {  
209        // assert i < j;
210        boolean s;
211        s = red.get( j ).get(i); 
212        if ( ! s ) { 
213            logger.warn("c3.s false for " + j + " " + i); 
214            return s;
215        }
216        s = true;
217        boolean m;
218        GenPolynomial<C> A;
219        ExpVector ek;
220        for ( int k = 0; k < P.size(); k++ ) {
221            A = P.get( k );
222            ek = A.leadingExpVector();
223            m = eij.multipleOf(ek) && eij.compareTo(ek) != 0;
224            if ( m ) {
225                if ( k < i ) {
226                    // System.out.println("k < i "+k+" "+i); 
227                    s =    red.get( i ).get(k) 
228                        || red.get( j ).get(k); 
229                }
230                if ( i < k && k < j ) {
231                    // System.out.println("i < k < j "+i+" "+k+" "+j); 
232                    s =    red.get( k ).get(i) 
233                        || red.get( j ).get(k); 
234                }
235                if ( j < k ) {
236                    //System.out.println("j < k "+j+" "+k); 
237                    s =    red.get( k ).get(i) 
238                        || red.get( k ).get(j); 
239                }
240                //System.out.println("s."+k+" = " + s); 
241                if ( ! s ) return s;
242            }
243        }
244        return true;
245    }
246
247}