001/*
002 * $Id: GroebnerBaseSeq.java 4240 2012-10-07 08:40:47Z kredel $
003 */
004
005package edu.jas.gb;
006
007import java.util.ArrayList;
008import java.util.List;
009import java.util.ListIterator;
010
011import org.apache.log4j.Logger;
012
013import edu.jas.structure.RingElem;
014
015//import edu.jas.poly.ExpVector;
016import edu.jas.gb.OrderedPairlist;
017import edu.jas.poly.GenPolynomial;
018import edu.jas.poly.GenPolynomialRing;
019
020
021/**
022 * Groebner Base sequential algorithm.
023 * Implements Groebner bases and GB test.
024 * @param <C> coefficient type
025 * @author Heinz Kredel
026 *
027 * @see edu.jas.application.GBAlgorithmBuilder
028 * @see edu.jas.gbufd.GBFactory
029 */
030
031public class GroebnerBaseSeq<C extends RingElem<C>> 
032       extends GroebnerBaseAbstract<C>  {
033
034    private static final Logger logger = Logger.getLogger(GroebnerBaseSeq.class);
035    private final boolean debug = logger.isDebugEnabled();
036
037
038    /**
039     * Constructor.
040     */
041    public GroebnerBaseSeq() {
042        super();
043    }
044
045
046    /**
047     * Constructor.
048     * @param red Reduction engine
049     */
050    public GroebnerBaseSeq(Reduction<C> red) {
051        super(red);
052    }
053
054
055    /**
056     * Constructor.
057     * @param red Reduction engine
058     * @param pl pair selection strategy
059     */
060    public GroebnerBaseSeq(Reduction<C> red, PairList<C> pl) {
061        super(red,pl);
062    }
063
064
065    /**
066     * Groebner base using pairlist class.
067     * @param modv module variable number.
068     * @param F polynomial list.
069     * @return GB(F) a Groebner base of F.
070     */
071    public List<GenPolynomial<C>> 
072             GB( int modv, 
073                 List<GenPolynomial<C>> F ) {  
074        GenPolynomial<C> p;
075        List<GenPolynomial<C>> G = new ArrayList<GenPolynomial<C>>();
076        PairList<C> pairlist = null; 
077        int l = F.size();
078        ListIterator<GenPolynomial<C>> it = F.listIterator();
079        while ( it.hasNext() ) { 
080            p = it.next();
081            if ( p.length() > 0 ) {
082               p = p.monic();
083               if ( p.isONE() ) {
084                  G.clear(); G.add( p );
085                  return G; // since no threads are activated
086               }
087               G.add( p );
088               if ( pairlist == null ) {
089                   //pairlist = new OrderedPairlist<C>( modv, p.ring );
090                  pairlist = strategy.create( modv, p.ring );
091                  if ( ! p.ring.coFac.isField() ) {
092                     throw new IllegalArgumentException("coefficients not from a field");
093                  }
094               }
095               // putOne not required
096               pairlist.put( p );
097            } else { 
098               l--;
099            }
100        }
101        if ( l <= 1 ) {
102           return G; // since no threads are activated
103        }
104        logger.info("start " + pairlist); 
105
106        Pair<C> pair;
107        GenPolynomial<C> pi;
108        GenPolynomial<C> pj;
109        GenPolynomial<C> S;
110        GenPolynomial<C> H;
111        while ( pairlist.hasNext() ) {
112              pair = pairlist.removeNext();
113              //logger.debug("pair = " + pair);
114              if ( pair == null ) {
115                  continue; 
116              }
117              pi = pair.pi; 
118              pj = pair.pj; 
119              if ( /*false &&*/ debug ) {
120                 logger.debug("pi    = " + pi );
121                 logger.debug("pj    = " + pj );
122              }
123
124              S = red.SPolynomial( pi, pj );
125              if ( S.isZERO() ) {
126                 pair.setZero();
127                 continue;
128              }
129              if ( debug ) {
130                  logger.debug("ht(S) = " + S.leadingExpVector() );
131              }
132
133              H = red.normalform( G, S );
134              if ( debug ) {
135                  //logger.info("pair = " + pair); 
136                  //logger.info("ht(S) = " + S.monic()); //.leadingExpVector() );
137                  logger.info("ht(H) = " + H.monic()); //.leadingExpVector() );
138              }
139              if ( H.isZERO() ) {
140                 pair.setZero();
141                 continue;
142              }
143              H = H.monic();
144              if ( debug ) {
145                  logger.info("ht(H) = " + H.leadingExpVector() );
146              }
147
148              H = H.monic();
149              if ( H.isONE() ) {
150                  G.clear(); G.add( H );
151                  pairlist.putOne();
152                  logger.info("end " + pairlist); 
153                  return G; // since no threads are activated
154              }
155              if ( debug ) {
156                 logger.info("H = " + H );
157              }
158              if ( H.length() > 0 ) {
159                 l++;
160                 G.add( H );
161                 pairlist.put( H );
162              }
163        }
164        logger.debug("#sequential list = " + G.size());
165        G = minimalGB(G);
166        logger.info("end " + pairlist); 
167        return G;
168    }
169
170
171    /**
172     * Extended Groebner base using critical pair class.
173     * @param modv module variable number.
174     * @param F polynomial list.
175     * @return a container for an extended Groebner base of F.
176     */
177    @Override
178    public ExtendedGB<C> 
179             extGB( int modv, 
180                    List<GenPolynomial<C>> F ) {  
181        List<GenPolynomial<C>> G = new ArrayList<GenPolynomial<C>>();
182        List<List<GenPolynomial<C>>> F2G = new ArrayList<List<GenPolynomial<C>>>();
183        List<List<GenPolynomial<C>>> G2F = new ArrayList<List<GenPolynomial<C>>>();
184        PairList<C> pairlist = null; 
185        boolean oneInGB = false;
186        int len = F.size();
187
188        List<GenPolynomial<C>> row = null;
189        List<GenPolynomial<C>> rows = null;
190        List<GenPolynomial<C>> rowh = null;
191        GenPolynomialRing<C> ring = null;
192        GenPolynomial<C> H;
193        GenPolynomial<C> p;
194
195        int nzlen = 0;
196        for ( GenPolynomial<C> f : F ) { 
197            if ( f.length() > 0 ) {
198                nzlen++;
199            }
200            if ( ring == null ) {
201               ring = f.ring;
202            }
203        }
204        GenPolynomial<C> mone = ring.getONE(); //.negate();
205        int k = 0;
206        ListIterator<GenPolynomial<C>> it = F.listIterator();
207        while ( it.hasNext() ) { 
208            p = it.next();
209            if ( p.length() > 0 ) {
210               row = new ArrayList<GenPolynomial<C>>( nzlen );
211               for ( int j = 0; j < nzlen; j++ ) {
212                   row.add(null);
213               }
214               //C c = p.leadingBaseCoefficient();
215               //c = c.inverse();
216               //p = p.multiply( c );
217               row.set( k, mone ); //.multiply(c) );
218               k++;
219               if ( p.isUnit() ) {
220                  G.clear(); G.add( p );
221                  G2F.clear(); G2F.add( row );
222                  oneInGB = true;
223                  break;
224               }
225               G.add( p );
226               G2F.add( row );
227               if ( pairlist == null ) {
228                  //pairlist = new OrderedPairlist<C>( modv, p.ring );
229                  pairlist = strategy.create( modv, p.ring );
230                  if ( ! p.ring.coFac.isField() ) {
231                     throw new RuntimeException("coefficients not from a field");
232                  }
233               }
234               // putOne not required
235               pairlist.put( p );
236            } else { 
237               len--;
238            }
239        }
240        ExtendedGB<C> exgb;
241        if ( len <= 1 || oneInGB ) {
242           // adjust F2G
243           for ( GenPolynomial<C> f : F ) {
244               row = new ArrayList<GenPolynomial<C>>( G.size() );
245               for ( int j = 0; j < G.size(); j++ ) {
246                   row.add(null);
247               }
248               H = red.normalform( row, G, f );
249               if ( ! H.isZERO() ) {
250                  logger.error("nonzero H = " + H );
251               }
252               F2G.add( row );
253           }
254           exgb = new ExtendedGB<C>(F,G,F2G,G2F);
255           //System.out.println("exgb 1 = " + exgb);
256           return exgb;
257        }
258
259        Pair<C> pair;
260        int i, j;
261        GenPolynomial<C> pi;
262        GenPolynomial<C> pj;
263        GenPolynomial<C> S;
264        GenPolynomial<C> x;
265        GenPolynomial<C> y;
266        //GenPolynomial<C> z;
267        while ( pairlist.hasNext() && ! oneInGB ) {
268              pair = pairlist.removeNext();
269              if ( pair == null ) { 
270                 continue; 
271              }
272              i = pair.i; 
273              j = pair.j; 
274              pi = pair.pi; 
275              pj = pair.pj; 
276              if ( debug ) {
277                 logger.info("i, pi    = " + i + ", " + pi );
278                 logger.info("j, pj    = " + j + ", " + pj );
279              }
280
281              rows = new ArrayList<GenPolynomial<C>>( G.size() );
282              for ( int m = 0; m < G.size(); m++ ) {
283                  rows.add(null);
284              }
285              S = red.SPolynomial( rows, i, pi, j, pj );
286              if ( debug ) {
287                 logger.debug("is reduction S = " 
288                             + red.isReductionNF( rows, G, ring.getZERO(), S ) );
289              }
290              if ( S.isZERO() ) {
291                 // do not add to G2F
292                 continue;
293              }
294              if ( debug ) {
295                 logger.debug("ht(S) = " + S.leadingExpVector() );
296              }
297
298              rowh = new ArrayList<GenPolynomial<C>>( G.size() );
299              for ( int m = 0; m < G.size(); m++ ) {
300                  rowh.add(null);
301              }
302              H = red.normalform( rowh, G, S );
303              if ( debug ) {
304                 logger.debug("is reduction H = " 
305                              + red.isReductionNF( rowh, G, S, H ) );
306              }
307              if ( H.isZERO() ) {
308                 // do not add to G2F
309                 continue;
310              }
311              if ( debug ) {
312                 logger.debug("ht(H) = " + H.leadingExpVector() );
313              }
314
315              row = new ArrayList<GenPolynomial<C>>( G.size()+1 );
316              for ( int m = 0; m < G.size(); m++ ) {
317                  x = rows.get(m);
318                  if ( x != null ) {
319                     //System.out.println("ms = " + m + " " + x);
320                     x = x.negate();
321                  }
322                  y = rowh.get(m);
323                  if ( y != null ) {
324                     y = y.negate();
325                     //System.out.println("mh = " + m + " " + y);
326                  }
327                  if ( x == null ) {
328                     x = y;
329                  } else {
330                     x = x.sum( y );
331                  }
332                  //System.out.println("mx = " + m + " " + x);
333                  row.add( x );
334              }
335              if ( debug ) {
336                 logger.debug("is reduction 0+sum(row,G) == H : " 
337                             + red.isReductionNF( row, G, H, ring.getZERO() ) );
338              }
339              row.add( null );
340
341
342              //  H = H.monic();
343              C c = H.leadingBaseCoefficient();
344              c = c.inverse();
345              H = H.multiply( c );
346              row = blas.scalarProduct( mone.multiply(c), row );
347              row.set( G.size(), mone );
348              if ( H.isONE() ) {
349                 // G.clear(); 
350                 G.add( H );
351                 G2F.add( row );
352                 oneInGB = true;
353                 break; 
354              }
355              if ( debug ) {
356                 logger.debug("H = " + H );
357              }
358              G.add( H );
359              pairlist.put( H );
360              G2F.add( row );
361        }
362        if ( debug ) {
363           exgb = new ExtendedGB<C>(F,G,F2G,G2F);
364           logger.info("exgb unnorm = " + exgb);
365        }
366        G2F = normalizeMatrix( F.size(), G2F );
367        if ( debug ) {
368           exgb = new ExtendedGB<C>(F,G,F2G,G2F);
369           logger.info("exgb nonmin = " + exgb);
370           boolean t2 = isReductionMatrix( exgb );
371           logger.info("exgb t2 = " + t2);
372        }
373        exgb = minimalExtendedGB(F.size(),G,G2F);
374        G = exgb.G;
375        G2F = exgb.G2F;
376        logger.debug("#sequential list = " + G.size());
377        logger.info("" + pairlist); 
378        // setup matrices F and F2G
379        for ( GenPolynomial<C> f : F ) {
380            row = new ArrayList<GenPolynomial<C>>( G.size() );
381            for ( int m = 0; m < G.size(); m++ ) {
382                row.add(null);
383            }
384            H = red.normalform( row, G, f );
385            if ( ! H.isZERO() ) {
386               logger.error("nonzero H = " + H );
387            }
388            F2G.add( row );
389        }
390        exgb = new ExtendedGB<C>(F,G,F2G,G2F);
391        if ( debug ) {
392           logger.info("exgb nonmin = " + exgb);
393           boolean t2 = isReductionMatrix( exgb );
394           logger.info("exgb t2 = " + t2);
395        }
396        return exgb;
397    }
398
399}