001    /*
002     * $Id: SolvableGroebnerBaseAbstract.java 3452 2010-12-27 12:48:08Z kredel $
003     */
004    
005    package edu.jas.gb;
006    
007    import java.util.ArrayList;
008    import java.util.List;
009    import java.util.ListIterator;
010    
011    import org.apache.log4j.Logger;
012    
013    import edu.jas.poly.ExpVector;
014    import edu.jas.poly.GenPolynomial;
015    import edu.jas.poly.GenSolvablePolynomial;
016    import edu.jas.poly.GenSolvablePolynomialRing;
017    import edu.jas.poly.PolynomialList;
018    
019    import edu.jas.structure.RingElem;
020    
021    import edu.jas.vector.BasicLinAlg;
022    
023    
024    /**
025     * Solvable Groebner Bases abstract class.
026     * Implements common left, right and twosided Groebner bases 
027     * and left, right and twosided GB tests.
028     * @param <C> coefficient type
029     * @author Heinz Kredel.
030     */
031    
032    public abstract class SolvableGroebnerBaseAbstract<C extends RingElem<C>> 
033           implements SolvableGroebnerBase<C> {
034    
035        private static final Logger logger = Logger.getLogger(SolvableGroebnerBaseAbstract.class);
036        private final boolean debug = logger.isDebugEnabled();
037    
038    
039        /**
040         * Solvable reduction engine.
041         */
042        protected SolvableReduction<C> sred;
043    
044    
045        /**
046         * Reduction engine.
047         */
048        protected final Reduction<C> red;
049    
050    
051        /**
052         * Strategy for pair selection.
053         */
054        public final PairList<C> strategy;
055    
056    
057        /**
058         * Linear algebra engine.
059         */
060        protected final BasicLinAlg<GenPolynomial<C>> blas;
061    
062    
063        /**
064         * Constructor.
065         */
066        public SolvableGroebnerBaseAbstract() {
067            this( new SolvableReductionSeq<C>() );
068        }
069    
070    
071        /**
072         * Constructor.
073         * @param sred Solvable reduction engine
074         */
075        public SolvableGroebnerBaseAbstract(SolvableReduction<C> sred) {
076            this(sred,new OrderedPairlist<C>());
077        }
078    
079    
080        /**
081         * Constructor.
082         * @param sred Solvable reduction engine
083         * @param pl pair selection strategy
084         */
085        public SolvableGroebnerBaseAbstract(SolvableReduction<C> sred, PairList<C> pl) {
086            this.red = new ReductionSeq<C>();
087            this.sred = sred;
088            this.strategy = pl;
089            blas = new BasicLinAlg<GenPolynomial<C>>();
090        }
091    
092    
093        /**
094         * Left Groebner base test.
095         * @param F solvable polynomial list.
096         * @return true, if F is a left Groebner base, else false.
097         */
098        public boolean isLeftGB(List<GenSolvablePolynomial<C>> F) {  
099            return isLeftGB(0,F);
100        }
101    
102    
103        /**
104         * Left Groebner base test.
105         * @param modv number of module variables.
106         * @param F solvable polynomial list.
107         * @return true, if F is a left Groebner base, else false.
108         */
109        public boolean isLeftGB(int modv, 
110                                List<GenSolvablePolynomial<C>> F) {  
111            GenSolvablePolynomial<C> pi, pj, s, h;
112            for ( int i = 0; i < F.size(); i++ ) {
113                pi = F.get(i);
114                for ( int j = i+1; j < F.size(); j++ ) {
115                    pj = F.get(j);
116                    if ( ! red.moduleCriterion( modv, pi, pj ) ) {
117                       continue;
118                    }
119                    // if ( ! red.criterion4( pi, pj ) ) { continue; }
120                    s = sred.leftSPolynomial( pi, pj );
121                    if ( s.isZERO() ) {
122                       continue;
123                    }
124                    h = sred.leftNormalform( F, s );
125                    if ( ! h.isZERO() ) {
126                       return false;
127                    }
128                }
129            }
130            return true;
131        }
132    
133    
134        /**
135         * Twosided Groebner base test.
136         * @param Fp solvable polynomial list.
137         * @return true, if Fp is a two-sided Groebner base, else false.
138         */
139        public boolean isTwosidedGB(List<GenSolvablePolynomial<C>> Fp) {  
140            return isTwosidedGB(0,Fp);
141        }
142    
143    
144        /**
145         * Twosided Groebner base test.
146         * @param modv number of module variables.
147         * @param Fp solvable polynomial list.
148         * @return true, if Fp is a two-sided Groebner base, else false.
149         */
150        public boolean isTwosidedGB(int modv, 
151                                    List<GenSolvablePolynomial<C>> Fp) {
152            if ( Fp == null || Fp.size() == 0 ) { // 0 not 1
153                return true;
154            }
155            GenSolvablePolynomialRing<C> fac = Fp.get(0).ring; // assert != null
156            //List<GenSolvablePolynomial<C>> X = generateUnivar( modv, Fp );
157            List<GenSolvablePolynomial<C>> X = fac.univariateList( modv );
158            List<GenSolvablePolynomial<C>> F 
159                = new ArrayList<GenSolvablePolynomial<C>>( Fp.size() * (1+X.size()) );
160            F.addAll( Fp );
161            GenSolvablePolynomial<C> p, x, pi, pj, s, h;
162            for ( int i = 0; i < Fp.size(); i++ ) {
163                p = Fp.get(i);
164                for ( int j = 0; j < X.size(); j++ ) {
165                    x = X.get(j);
166                    p = p.multiply( x );
167                    F.add( p );
168                }
169            }
170            //System.out.println("F to check = " + F);
171            for ( int i = 0; i < F.size(); i++ ) {
172                pi = F.get(i);
173                for ( int j = i+1; j < F.size(); j++ ) {
174                    pj = F.get(j);
175                    if ( ! red.moduleCriterion( modv, pi, pj ) ) {
176                       continue;
177                    }
178                    // if ( ! red.criterion4( pi, pj ) ) { continue; }
179                    s = sred.leftSPolynomial( pi, pj );
180                    if ( s.isZERO() ) {
181                       continue;
182                    }
183                    h = sred.leftNormalform( F, s );
184                    if ( ! h.isZERO() ) {
185                       logger.info("is not TwosidedGB: " + h);
186                       return false;
187                    }
188                }
189            }
190            return true;
191        }
192    
193    
194        /**
195         * Right Groebner base test.
196         * @param F solvable polynomial list.
197         * @return true, if F is a right Groebner base, else false.
198         */
199        public boolean isRightGB(List<GenSolvablePolynomial<C>> F) {
200            return isRightGB(0,F);
201        }
202    
203    
204        /**
205         * Right Groebner base test.
206         * @param modv number of module variables.
207         * @param F solvable polynomial list.
208         * @return true, if F is a right Groebner base, else false.
209         */
210        public boolean isRightGB(int modv, List<GenSolvablePolynomial<C>> F) {
211            GenSolvablePolynomial<C> pi, pj, s, h;
212            for ( int i = 0; i < F.size(); i++ ) {
213                pi = F.get(i);
214                //System.out.println("pi right = " + pi);
215                for ( int j = i+1; j < F.size(); j++ ) {
216                    pj = F.get(j);
217                    //System.out.println("pj right = " + pj);
218                    if ( ! red.moduleCriterion( modv, pi, pj ) ) {
219                       continue;
220                    }
221                    // if ( ! red.criterion4( pi, pj ) ) { continue; }
222                    s = sred.rightSPolynomial( pi, pj );
223                    if ( s.isZERO() ) {
224                       continue;
225                    }
226                    //System.out.println("s right = " + s);
227                    h = sred.rightNormalform( F, s );
228                    if ( ! h.isZERO() ) {
229                       logger.info("isRightGB non zero h = " + h);
230                       return false;
231                    } else {
232                        //logger.info("isRightGB zero h = " + h);
233                    }
234                }
235            }
236            return true;
237        }
238    
239    
240        /**
241         * Left Groebner base using pairlist class.
242         * @param F solvable polynomial list.
243         * @return leftGB(F) a left Groebner base of F.
244         */
245        public List<GenSolvablePolynomial<C>> 
246               leftGB(List<GenSolvablePolynomial<C>> F) {  
247            return leftGB(0,F);
248        }
249    
250    
251        /** 
252         * Solvable Extended Groebner base using critical pair class.
253         * @param F solvable polynomial list.
254         * @return a container for an extended left Groebner base of F.
255         */
256        public SolvableExtendedGB<C>  
257               extLeftGB( List<GenSolvablePolynomial<C>> F ) {
258            return extLeftGB(0,F); 
259        }
260    
261    
262        /**
263         * Left minimal ordered groebner basis.
264         * @param Gp a left Groebner base.
265         * @return leftGBmi(F) a minimal left Groebner base of Gp.
266         */
267        public List<GenSolvablePolynomial<C>> 
268                   leftMinimalGB(List<GenSolvablePolynomial<C>> Gp) {  
269            ArrayList<GenSolvablePolynomial<C>> G 
270               = new ArrayList<GenSolvablePolynomial<C>>();
271            ListIterator<GenSolvablePolynomial<C>> it = Gp.listIterator();
272            for ( GenSolvablePolynomial<C> a: Gp ) { 
273                // a = (SolvablePolynomial) it.next();
274                if ( a.length() != 0 ) { // always true
275                   // already monic a = a.monic();
276                   G.add( a );
277                }
278            }
279            if ( G.size() <= 1 ) {
280               return G;
281            }
282    
283            ExpVector e;        
284            ExpVector f;        
285            GenSolvablePolynomial<C> a, p;
286            ArrayList<GenSolvablePolynomial<C>> F 
287               = new ArrayList<GenSolvablePolynomial<C>>();
288            boolean mt;
289    
290            while ( G.size() > 0 ) {
291                a = G.remove(0);
292                e = a.leadingExpVector();
293    
294                it = G.listIterator();
295                mt = false;
296                while ( it.hasNext() && ! mt ) {
297                   p = it.next();
298                   f = p.leadingExpVector();
299                   mt =  e.multipleOf( f );
300                }
301                it = F.listIterator();
302                while ( it.hasNext() && ! mt ) {
303                   p = it.next();
304                   f = p.leadingExpVector();
305                   mt =  e.multipleOf( f );
306                }
307                if ( ! mt ) {
308                    F.add( a );
309                } else {
310                    // System.out.println("dropped " + a.length());
311                }
312            }
313            G = F;
314            if ( G.size() <= 1 ) {
315               return G;
316            }
317    
318            F = new ArrayList<GenSolvablePolynomial<C>>();
319            while ( G.size() > 0 ) {
320                a = G.remove(0);
321                // System.out.println("doing " + a.length());
322                a = sred.leftNormalform( G, a );
323                a = sred.leftNormalform( F, a );
324                F.add( a );
325            }
326            return F;
327        }
328    
329    
330        /**
331         * Twosided Groebner base using pairlist class.
332         * @param Fp solvable polynomial list.
333         * @return tsGB(Fp) a twosided Groebner base of Fp.
334         */
335        public List<GenSolvablePolynomial<C>> 
336                   twosidedGB(List<GenSolvablePolynomial<C>> Fp) {  
337            return twosidedGB(0,Fp);
338        }
339    
340    
341        /**
342         * Right Groebner base using opposite ring left GB.
343         * @param F solvable polynomial list.
344         * @return rightGB(F) a right Groebner base of F.
345         */
346        public List<GenSolvablePolynomial<C>> 
347               rightGB(List<GenSolvablePolynomial<C>> F) {  
348            return rightGB(0,F);
349        }
350    
351    
352        /**
353         * Right Groebner base using opposite ring left GB.
354         * @param modv number of module variables.
355         * @param F solvable polynomial list.
356         * @return rightGB(F) a right Groebner base of F.
357         */
358        public List<GenSolvablePolynomial<C>> 
359               rightGB(int modv, 
360                       List<GenSolvablePolynomial<C>> F) {
361            GenSolvablePolynomialRing<C> ring = null;
362            for ( GenSolvablePolynomial<C> p : F ) {
363                if ( p != null ) {
364                    ring = p.ring;
365                    break;
366                }
367            }
368            if ( ring == null ) {
369                return F;
370            }
371            GenSolvablePolynomialRing<C> rring = ring.reverse(true); //true
372            //ring = rring.reverse(true); // true
373            GenSolvablePolynomial<C> q;
374            List<GenSolvablePolynomial<C>> rF;
375               rF = new ArrayList<GenSolvablePolynomial<C>>( F.size() );
376            for ( GenSolvablePolynomial<C> p : F ) {
377                if ( p != null ) {
378                   q = (GenSolvablePolynomial<C>)p.reverse(rring);
379                   rF.add( q );
380                }
381            }
382            if ( true || debug ) {
383               PolynomialList<C> pl = new PolynomialList<C>(rring,rF);
384               logger.info("reversed problem = " + pl);
385            }
386            List<GenSolvablePolynomial<C>> rG = leftGB( modv, rF );
387            if ( true || debug ) {
388                //PolynomialList<C> pl = new PolynomialList<C>(rring,rG);
389                //logger.info("reversed GB = " + pl);
390                long t = System.currentTimeMillis();
391                boolean isit = isLeftGB( rG );
392                t = System.currentTimeMillis() - t;
393                logger.info("is left GB = " + isit + ", in " + t + " milliseconds");
394            }
395            ring = rring.reverse(true); // true
396            List<GenSolvablePolynomial<C>> G = new ArrayList<GenSolvablePolynomial<C>>(rG.size());
397            for ( GenSolvablePolynomial<C> p : rG ) {
398                if ( p != null ) {
399                   q = (GenSolvablePolynomial<C>)p.reverse(ring);
400                   G.add( q );
401                }
402            }
403            if ( true || debug ) {
404                //PolynomialList<C> pl = new PolynomialList<C>(ring,G);
405                //logger.info("GB = " + pl);
406                long t = System.currentTimeMillis();
407                boolean isit = isRightGB( G );
408                t = System.currentTimeMillis() - t;
409                logger.info("is right GB = " + isit + ", in " + t + " milliseconds");
410            }
411            return G;
412        }
413    
414    
415        /**
416         * Test if left reduction matrix.
417         * @param exgb an SolvableExtendedGB container.
418         * @return true, if exgb contains a left reduction matrix, else false.
419         */
420        public boolean
421               isLeftReductionMatrix(SolvableExtendedGB<C> exgb) {  
422            if ( exgb == null ) {
423                return true;
424            }
425            return isLeftReductionMatrix(exgb.F,exgb.G,exgb.F2G,exgb.G2F);
426        }
427    
428    
429        /**
430         * Test if left reduction matrix.
431         * @param F a solvable polynomial list.
432         * @param G a left Groebner base.
433         * @param Mf a possible left reduction matrix.
434         * @param Mg a possible left reduction matrix.
435         * @return true, if Mg and Mf are left reduction matrices, else false.
436         */
437        public boolean
438               isLeftReductionMatrix(List<GenSolvablePolynomial<C>> F, 
439                                     List<GenSolvablePolynomial<C>> G,
440                                     List<List<GenSolvablePolynomial<C>>> Mf,  
441                                     List<List<GenSolvablePolynomial<C>>> Mg) {  
442            // no more check G and Mg: G * Mg[i] == 0
443            // check F and Mg: F * Mg[i] == G[i]
444            int k = 0;
445            for ( List<GenSolvablePolynomial<C>> row : Mg ) {
446                boolean t = sred.isLeftReductionNF( row, F, G.get( k ), null );  
447                if ( ! t ) {
448                    System.out.println("row = " + row);
449                    System.out.println("F   = " + F);
450                    System.out.println("Gk  = " + G.get(k));
451                    logger.info("F isLeftReductionMatrix s, k = " + F.size() + ", " + k);
452                    return false;
453                }
454                k++;
455            }
456            // check G and Mf: G * Mf[i] == F[i]
457            k = 0;
458            for ( List<GenSolvablePolynomial<C>> row : Mf ) {
459                boolean t = sred.isLeftReductionNF( row, G, F.get( k ), null );  
460                if ( ! t ) {
461                   logger.error("G isLeftReductionMatrix s, k = " + G.size() + ", " + k);
462                   return false;
463                }
464                k++;
465            }
466            return true;
467        }
468    
469    }