001/*
002 * $Id: WordGroebnerBaseAbstract.java 4150 2012-09-01 09:18:23Z kredel $
003 */
004
005package edu.jas.gb;
006
007import java.util.ArrayList;
008import java.util.List;
009import java.util.Map;
010import java.util.TreeMap;
011import java.util.ListIterator;
012import java.util.Set;
013import java.util.HashSet;
014import java.util.Collections;
015
016import org.apache.log4j.Logger;
017
018import edu.jas.poly.GenWordPolynomial;
019import edu.jas.poly.GenWordPolynomialRing;
020import edu.jas.poly.TermOrder;
021import edu.jas.poly.PolyUtil;
022import edu.jas.structure.RingElem;
023import edu.jas.structure.RingFactory;
024import edu.jas.poly.Word;
025
026
027/**
028 * Non-commutative Groebner Bases abstract class.
029 * Implements common Groebner bases and GB test methods.
030 * @param <C> coefficient type
031 * @author Heinz Kredel
032 */
033
034public abstract class WordGroebnerBaseAbstract<C extends RingElem<C>> 
035                      implements WordGroebnerBase<C> {
036
037    private static final Logger logger = Logger.getLogger(WordGroebnerBaseAbstract.class);
038    private final boolean debug = logger.isDebugEnabled();
039
040
041    /**
042     * Reduction engine.
043     */
044    public final WordReduction<C> red;
045
046
047    /**
048     * Strategy for pair selection.
049     */
050    public final WordPairList<C> strategy;
051
052
053    /**
054     * Constructor.
055     */
056    public WordGroebnerBaseAbstract() {
057        this( new WordReductionSeq<C>() );
058    }
059
060
061    /**
062     * Constructor.
063     * @param red Word Reduction engine
064     */
065    public WordGroebnerBaseAbstract(WordReduction<C> red) {
066        this(red, new OrderedWordPairlist<C>() );
067    }
068
069
070    /**
071     * Constructor.
072     * @param red Word Reduction engine
073     * @param pl Word pair selection strategy
074     */
075    public WordGroebnerBaseAbstract(WordReduction<C> red, WordPairList<C> pl) {
076        this.red = red;
077        this.strategy = pl;
078    }
079
080
081    /**
082     * Word Groebner base test.
083     * @param F Word polynomial list.
084     * @return true, if F is a Groebner base, else false.
085     */
086    public boolean isGB(List<GenWordPolynomial<C>> F) {  
087        if ( F == null || F.isEmpty() ) {
088           return true;
089        }
090        for ( int i = 0; i < F.size(); i++ ) {
091            GenWordPolynomial<C> pi = F.get(i);
092            for ( int j = i+1; j < F.size(); j++ ) {
093                GenWordPolynomial<C> pj = F.get(j);
094                List<GenWordPolynomial<C>> S = red.SPolynomials( pi, pj );
095                if ( S.isEmpty() ) {
096                   continue;
097                }
098                for ( GenWordPolynomial<C> s : S ) {
099                    GenWordPolynomial<C> h = red.normalform( F, s );
100                    if ( ! h.isZERO() ) {
101                        logger.info("no GB: pi = " + pi + ", pj = " + pj);
102                        logger.info("s  = " + s  + ", h = " + h);
103                        return false;
104                    }
105                }
106            }
107        }
108        return true;
109    }
110
111
112    /**
113     * Groebner base using pairlist class.
114     * @param F polynomial list.
115     * @return GB(F) a Groebner base of F.
116     */
117    public abstract List<GenWordPolynomial<C>> GB( List<GenWordPolynomial<C>> F );
118
119
120    /**
121     * Minimal ordered Groebner basis.
122     * @param Gp a Groebner base.
123     * @return a reduced Groebner base of Gp.
124     */
125    public List<GenWordPolynomial<C>> minimalGB(List<GenWordPolynomial<C>> Gp) {  
126        if ( Gp == null || Gp.size() <= 1 ) {
127            return Gp;
128        }
129        // remove zero polynomials
130        List<GenWordPolynomial<C>> G
131            = new ArrayList<GenWordPolynomial<C>>( Gp.size() );
132        for ( GenWordPolynomial<C> a : Gp ) { 
133            if ( a != null && !a.isZERO() ) { // always true in GB()
134               // already positive a = a.abs();
135               G.add( a );
136            }
137        }
138        if ( G.size() <= 1 ) {
139           return G;
140        }
141        // remove top reducible polynomials
142        GenWordPolynomial<C> a;
143        List<GenWordPolynomial<C>> F;
144        F = new ArrayList<GenWordPolynomial<C>>( G.size() );
145        while ( G.size() > 0 ) {
146            a = G.remove(0);
147            if ( red.isTopReducible(G,a) || red.isTopReducible(F,a) ) {
148               // drop polynomial 
149               if ( debug ) {
150                  System.out.println("dropped " + a);
151                  List<GenWordPolynomial<C>> ff;
152                  ff = new ArrayList<GenWordPolynomial<C>>( G );
153                  ff.addAll(F);
154                  a = red.normalform( ff, a );
155                  if ( !a.isZERO() ) {
156                     System.out.println("error, nf(a) " + a);
157                  }
158               }
159            } else {
160                F.add(a);
161            }
162        }
163        G = F;
164        if ( G.size() <= 1 ) {
165           return G;
166        }
167        // reduce remaining polynomials
168        Collections.reverse(G); // important for lex GB
169        int len = G.size();
170        if ( debug ) {
171            System.out.println("#G " + len);
172            for (GenWordPolynomial<C> aa : G) {
173                System.out.println("aa = " + aa.length() + ", lt = " + aa.getMap().keySet());
174            }
175        }
176        int i = 0;
177        while ( i < len ) {
178            a = G.remove(0);
179            if ( debug ) {
180                System.out.println("doing " + a.length() + ", lt = " + a.leadingWord());
181            }
182            a = red.normalform( G, a );
183            G.add( a ); // adds as last
184            i++;
185        }
186        return G;
187    }
188
189
190    /**
191     * Test for minimal ordered Groebner basis.
192     * @param Gp an ideal base.
193     * @return true, if Gp is a reduced minimal Groebner base.
194     */
195    public boolean isMinimalGB(List<GenWordPolynomial<C>> Gp) {  
196        if ( Gp == null || Gp.size() == 0 ) {
197            return true;
198        }
199        // test for zero polynomials
200        for ( GenWordPolynomial<C> a : Gp ) { 
201            if ( a == null || a.isZERO() ) { 
202                if (debug) {
203                    logger.debug("zero polynomial " + a);
204                }
205                return false;
206            }
207        }
208        // test for top reducible polynomials
209        List<GenWordPolynomial<C>> G = new ArrayList<GenWordPolynomial<C>>( Gp );
210        List<GenWordPolynomial<C>> F = new ArrayList<GenWordPolynomial<C>>( G.size() );
211        while ( G.size() > 0 ) {
212            GenWordPolynomial<C> a = G.remove(0);
213            if ( red.isTopReducible(G,a) || red.isTopReducible(F,a) ) {
214                if (debug) {
215                    logger.debug("top reducible polynomial " + a);
216                }
217                return false;
218            } else {
219                F.add(a);
220            }
221        }
222        G = F;
223        if ( G.size() <= 1 ) {
224           return true;
225        }
226        // test reducibility of polynomials
227        int len = G.size();
228        int i = 0;
229        while ( i < len ) {
230            GenWordPolynomial<C> a = G.remove(0);
231            if ( ! red.isNormalform( G, a ) ) {
232                if (debug) {
233                    logger.debug("reducible polynomial " + a);
234                }
235                return false;
236            }
237            G.add( a ); // re-adds as last
238            i++;
239        }
240        return true;
241    }
242
243
244    /**
245     * Cleanup and terminate ThreadPool.
246     */
247    public void terminate() {
248        logger.info("terminate not implemented");
249    }
250
251
252    /**
253     * Cancel ThreadPool.
254     */
255    public int cancel() {
256        logger.info("cancel not implemented");
257        return 0;
258    }
259
260}