001    /*
002     * $Id: OrderedSyzPairlist.java 3418 2010-12-19 17:54:17Z kredel $
003     */
004    
005    package edu.jas.gb;
006    
007    import java.util.ArrayList;
008    import java.util.BitSet;
009    import java.util.Iterator;
010    import java.util.List;
011    import java.util.LinkedList;
012    import java.util.Map;
013    import java.util.TreeMap;
014    import java.util.SortedMap;
015    
016    import org.apache.log4j.Logger;
017    
018    import edu.jas.poly.ExpVector;
019    import edu.jas.poly.GenPolynomial;
020    import edu.jas.poly.GenPolynomialRing;
021    import edu.jas.poly.GenSolvablePolynomialRing;
022    import edu.jas.structure.RingElem;
023    
024    /**
025     * Pair list management.
026     * For the Buchberger algorithm following 
027     * the syzygy criterions by Gebauer & Möller.
028     * Implemented using GenPolynomial, TreeMap and BitSet.
029     * @author Heinz Kredel
030     */
031    
032    public class OrderedSyzPairlist<C extends RingElem<C> > extends OrderedPairlist<C> {
033    
034        private static final Logger logger = Logger.getLogger(OrderedSyzPairlist.class);
035    
036    
037        /**
038         * Constructor.
039         */
040        public OrderedSyzPairlist() {
041            super();
042        }
043    
044    
045        /**
046         * Constructor.
047         * @param r polynomial factory.
048         */
049        public OrderedSyzPairlist(GenPolynomialRing<C> r) {
050            this(0,r);
051        }
052    
053    
054        /**
055         * Constructor.
056         * @param m number of module variables.
057         * @param r polynomial factory.
058         */
059        public OrderedSyzPairlist(int m, GenPolynomialRing<C> r) {
060            super(m,r);
061        }
062    
063    
064        /**
065         * Create a new PairList.
066         * @param r polynomial ring.
067         */
068        public PairList<C> create(GenPolynomialRing<C> r) {
069            return new OrderedSyzPairlist<C>(r);
070        }
071    
072    
073        /**
074         * Create a new PairList.
075         * @param m number of module variables.
076         * @param r polynomial ring.
077         */
078        public PairList<C> create(int m, GenPolynomialRing<C> r) {
079            return new OrderedSyzPairlist<C>(m,r);
080        }
081    
082    
083        /**
084         * Put one Polynomial to the pairlist and reduction matrix.
085         * Removes all unnecessary pairs identified by the syzygy criterion and criterion 4.
086         * @param p polynomial.
087         * @return the index of the added polynomial.
088         */
089        public synchronized int put(GenPolynomial<C> p) { 
090            putCount++;
091            if ( oneInGB ) { 
092                return P.size()-1;
093            }
094            ExpVector e = p.leadingExpVector();
095            int ps = P.size();
096            BitSet redi = new BitSet(); // all zeros
097            //redi.set( 0, ps ); // [0..ps-1] = true, i.e. all ones
098            red.add( redi ); 
099            P.add( p );
100            // remove from existing pairs:
101            List<ExpVector> es = new ArrayList<ExpVector>();
102            for (Map.Entry<ExpVector,LinkedList<Pair<C>>> me : pairlist.entrySet()) {
103                ExpVector g = me.getKey();
104                if ( moduleVars > 0 ) {
105                    if ( !reduction.moduleCriterion( moduleVars, e, g) ) {
106                        continue; // skip pair
107                    }
108                }
109                ExpVector ge = g.lcm(e);
110                LinkedList<Pair<C>> ll = me.getValue();
111                if (g.compareTo(ge) == 0) {
112                    LinkedList<Pair<C>> lle = new LinkedList<Pair<C>>();
113                    for (Pair<C> pair : ll) {
114                        ExpVector eil = pair.pi.leadingExpVector().lcm(e);
115                        if ( g.compareTo(eil) == 0 ) {
116                            continue;
117                        }
118                        ExpVector ejl = pair.pj.leadingExpVector().lcm(e);
119                        if ( g.compareTo(ejl) == 0 ) {
120                            continue;
121                        }
122                        // g == ge && g != eil && g != ejl  
123                        red.get( pair.j ).clear( pair.i ); 
124                        lle.add(pair);
125                    }
126                    if ( lle.size() > 0 ) {
127                        for ( Pair<C> pair : lle ) {
128                            ll.remove(pair); 
129                        }
130                        if ( ! es.contains(g) ) {
131                            es.add(g);
132                        }
133                    }
134                }
135            }
136            for ( ExpVector ei : es ) {
137                LinkedList<Pair<C>> ll = pairlist.get(ei);
138                if ( ll != null && ll.size() == 0 ) {
139                    ll = pairlist.remove(ei);
140                }
141            }
142            // generate new pairs:
143            SortedMap<ExpVector,LinkedList<Pair<C>>> npl 
144                = new TreeMap<ExpVector,LinkedList<Pair<C>>>( ring.tord.getAscendComparator() );
145            for ( int j = 0; j < ps; j++ ) {
146                GenPolynomial<C> pj = P.get(j);
147                ExpVector f = pj.leadingExpVector(); 
148                if ( moduleVars > 0 ) {
149                    if ( !reduction.moduleCriterion( moduleVars, e, f) ) {
150                        //red.get(j).clear(l); 
151                        continue; // skip pair
152                    }
153                }
154                ExpVector g =  e.lcm(f);
155                Pair<C> pair = new Pair<C>( pj, p, j, ps);
156                //System.out.println("pair.new      = " + pair);
157                //multiple pairs under same keys -> list of pairs
158                LinkedList<Pair<C>> xl = npl.get(g);
159                if ( xl == null ) {
160                    xl = new LinkedList<Pair<C>>();
161                }
162                //xl.addLast( pair ); // first or last ?
163                xl.addFirst( pair ); // first or last ? better for d- e-GBs
164                npl.put( g, xl );
165            }
166            //System.out.println("npl.new      = " + npl.keySet());
167            // skip by divisibility:
168            es = new ArrayList<ExpVector>(npl.size());
169            for ( ExpVector eil : npl.keySet() ) {
170                for ( ExpVector ejl : npl.keySet() ) {
171                    if ( eil.compareTo(ejl) == 0 ) {
172                        continue;
173                    }
174                    if ( eil.multipleOf(ejl) ) {
175                        if ( !es.contains(eil) ) {
176                            es.add(eil);
177                        }
178                    }
179                }
180            }
181            //System.out.println("npl.skip div = " + es);
182            for ( ExpVector ei : es ) {
183                LinkedList<Pair<C>> ignored = npl.remove(ei);
184            }
185            // skip by criterion 4:
186            if ( useCriterion4 ) {
187                es = new ArrayList<ExpVector>(npl.size());
188                for ( ExpVector ei : npl.keySet() ) {
189                    LinkedList<Pair<C>> exl = npl.get( ei );
190                    //System.out.println("exl = " + exl ); 
191                    boolean c = true;
192                    for ( Pair<C> pair : exl ) {
193                        c = c && reduction.criterion4( pair.pi, pair.pj, pair.e ); 
194                    }
195                    if ( c ) {
196                        if ( exl.size() > 1 ) {
197                            Pair<C> pair = exl.getFirst(); // or exl.getLast();
198                            exl.clear();
199                            exl.add(pair);
200                            //npl.put(ei,exl);
201                        }
202                    } else {
203                        if ( !es.contains(ei) ) {
204                            es.add(ei);
205                        }
206                    }
207                }
208                //System.out.println("npl.skip c4  = " + es);
209                for ( ExpVector ei : es ) {
210                    LinkedList<Pair<C>> ignored = npl.remove(ei);
211                }
212            }
213            // add to existing pairlist:
214            //System.out.println("npl.put new  = " + npl.keySet() );  
215            for ( ExpVector ei : npl.keySet() ) {
216                LinkedList<Pair<C>> exl = npl.get( ei );
217                for ( Pair<C> pair : exl ) {
218                    red.get( pair.j ).set( pair.i ); 
219                }
220                LinkedList<Pair<C>> ex = pairlist.get( ei );
221                if ( ex != null ) {
222                    exl.addAll(ex); // add new pairs first 
223                    ex = exl;
224                    //ex.addAll(exl); // add old pairs first
225                } else {
226                    ex = exl;
227                }
228                pairlist.put(ei,ex); // replace ex
229            }
230            return P.size()-1;
231        }
232    
233    
234        /**
235         * Remove the next required pair from the pairlist and reduction matrix.
236         * Appy the criterions 3 and 4 to see if the S-polynomial is required.
237         * @return the next pair if one exists, otherwise null.
238         */
239        public synchronized Pair<C> removeNext() { 
240            if ( oneInGB ) {
241                return null;
242            }
243            Iterator< Map.Entry<ExpVector,LinkedList<Pair<C>>> > ip 
244                = pairlist.entrySet().iterator();
245            Pair<C> pair = null;
246            boolean c = false;
247            int i, j;
248            while ( ip.hasNext() )  {
249                Map.Entry<ExpVector,LinkedList<Pair<C>>> me = ip.next();
250                ExpVector g =  me.getKey();
251                LinkedList<Pair<C>> xl = me.getValue();
252                if ( logger.isInfoEnabled() )
253                    logger.info("g  = " + g);
254                pair = null;
255                while ( xl.size() > 0 ) {
256                    pair = xl.removeFirst(); // xl is also modified in pairlist 
257                    i = pair.i; 
258                    j = pair.j; 
259                    //System.out.println("pair.remove = " + pair );
260                    if ( !red.get(j).get(i) ) { // should not happen
261                        System.out.println("c_red.get("+j+").get("+i+") = " + g); 
262                        pair = null;
263                        continue;
264                    }
265                    red.get(j).clear(i);
266                    break; 
267                }
268                if ( xl.size() == 0 ) {
269                    ip.remove(); // = pairlist.remove( g );
270                }
271                if ( pair != null ) {
272                    break;
273                }
274            }
275            remCount++; // count only real pairs
276            return pair; 
277        }
278    
279    
280        /**
281         * GB criterium 3.
282         * @return true if the S-polynomial(i,j) is required.
283         */
284        public boolean criterion3(int i, int j, ExpVector eij) {  
285            throw new UnsupportedOperationException("not used in " + this.getClass().getName());
286        }
287    
288    }