001/*
002 * $Id: GroebnerBasePseudoRecSeq.java 5061 2015-01-01 19:45:33Z kredel $
003 */
004
005package edu.jas.gbufd;
006
007
008import java.util.ArrayList;
009import java.util.Collections;
010import java.util.List;
011
012import org.apache.log4j.Logger;
013
014import edu.jas.gb.GroebnerBaseAbstract;
015import edu.jas.gb.OrderedPairlist;
016import edu.jas.gb.Pair;
017import edu.jas.gb.PairList;
018import edu.jas.poly.ExpVector;
019import edu.jas.poly.GenPolynomial;
020import edu.jas.poly.GenPolynomialRing;
021import edu.jas.structure.GcdRingElem;
022import edu.jas.structure.RingFactory;
023import edu.jas.ufd.GCDFactory;
024import edu.jas.ufd.GreatestCommonDivisorAbstract;
025
026
027/**
028 * Groebner Base with pseudo reduction sequential algorithm for integral
029 * function coefficients. Implements polynomial fraction free coefficients
030 * Groebner bases. Coefficients can for example be 
031 * (commutative) multivariate polynomials.
032 * @param <C> base coefficient type
033 * @author Heinz Kredel
034 * 
035 * @see edu.jas.application.GBAlgorithmBuilder
036 * @see edu.jas.gbufd.GBFactory
037 */
038
039public class GroebnerBasePseudoRecSeq<C extends GcdRingElem<C>> extends
040                GroebnerBaseAbstract<GenPolynomial<C>> {
041
042
043    private static final Logger logger = Logger.getLogger(GroebnerBasePseudoRecSeq.class);
044
045
046    private final boolean debug = logger.isDebugEnabled();
047
048
049    /**
050     * Greatest common divisor engine for coefficient content and primitive
051     * parts.
052     */
053    protected final GreatestCommonDivisorAbstract<C> engine;
054
055
056    /**
057     * Pseudo reduction engine.
058     */
059    protected final PseudoReduction<C> redRec;
060
061
062    /**
063     * Pseudo reduction engine.
064     */
065    protected final PseudoReduction<GenPolynomial<C>> red;
066
067
068    /**
069     * Coefficient ring factory.
070     */
071    protected final RingFactory<GenPolynomial<C>> cofac;
072
073
074    /**
075     * Base coefficient ring factory.
076     */
077    protected final RingFactory<C> baseCofac;
078
079
080    /**
081     * Constructor.
082     * @param rf coefficient ring factory.
083     */
084    public GroebnerBasePseudoRecSeq(RingFactory<GenPolynomial<C>> rf) {
085        this(new PseudoReductionSeq<GenPolynomial<C>>(), rf, new OrderedPairlist<GenPolynomial<C>>(
086                        new GenPolynomialRing<GenPolynomial<C>>(rf, 1))); // 1=hack
087    }
088
089
090    /**
091     * Constructor.
092     * @param rf coefficient ring factory.
093     * @param pl pair selection strategy
094     */
095    public GroebnerBasePseudoRecSeq(RingFactory<GenPolynomial<C>> rf, PairList<GenPolynomial<C>> pl) {
096        this(new PseudoReductionSeq<GenPolynomial<C>>(), rf, pl);
097    }
098
099
100    /**
101     * Constructor.
102     * @param red pseudo reduction engine. <b>Note:</b> red must be an instance
103     *            of PseudoReductionSeq.
104     * @param rf coefficient ring factory.
105     * @param pl pair selection strategy
106     */
107    @SuppressWarnings("cast")
108    public GroebnerBasePseudoRecSeq(PseudoReduction<GenPolynomial<C>> red, RingFactory<GenPolynomial<C>> rf,
109                    PairList<GenPolynomial<C>> pl) {
110        super(red, pl);
111        this.red = red;
112        this.redRec = (PseudoReduction<C>) (PseudoReduction) red;
113        cofac = rf;
114        GenPolynomialRing<C> rp = (GenPolynomialRing<C>) cofac;
115        baseCofac = rp.coFac;
116        //engine = (GreatestCommonDivisorAbstract<C>)GCDFactory.<C>getImplementation( baseCofac );
117        //not used: 
118        engine = GCDFactory.<C> getProxy(baseCofac);
119    }
120
121
122    /**
123     * Groebner base using pairlist class.
124     * @param modv module variable number.
125     * @param F polynomial list.
126     * @return GB(F) a Groebner base of F.
127     */
128    //@Override
129    public List<GenPolynomial<GenPolynomial<C>>> GB(int modv, List<GenPolynomial<GenPolynomial<C>>> F) {
130        List<GenPolynomial<GenPolynomial<C>>> G = normalizeZerosOnes(F);
131        G = engine.recursivePrimitivePart(G);
132        if (G.size() <= 1) {
133            return G;
134        }
135        GenPolynomialRing<GenPolynomial<C>> ring = G.get(0).ring;
136        if (ring.coFac.isField()) { // TODO remove
137            throw new IllegalArgumentException("coefficients from a field");
138        }
139        PairList<GenPolynomial<C>> pairlist = strategy.create(modv, ring);
140        pairlist.put(G);
141
142        /*
143        GenPolynomial<GenPolynomial<C>> p;
144        List<GenPolynomial<GenPolynomial<C>>> G = new ArrayList<GenPolynomial<GenPolynomial<C>>>();
145        PairList<GenPolynomial<C>> pairlist = null;
146        int l = F.size();
147        ListIterator<GenPolynomial<GenPolynomial<C>>> it = F.listIterator();
148        while (it.hasNext()) {
149            p = it.next();
150            if (p.length() > 0) {
151                p = engine.recursivePrimitivePart(p); //p.monic();
152                p = p.abs();
153                if (p.isConstant()) {
154                    G.clear();
155                    G.add(p);
156                    return G; // since no threads are activated
157                }
158                G.add(p);
159                if (pairlist == null) {
160                    //pairlist = new OrderedPairlist<GenPolynomial<C>>(modv, p.ring);
161                    pairlist = strategy.create(modv, p.ring);
162                }
163                // putOne not required
164                pairlist.put(p);
165            } else {
166                l--;
167            }
168        }
169        if (l <= 1) {
170            return G; // since no threads are activated
171        }
172        */
173
174        Pair<GenPolynomial<C>> pair;
175        GenPolynomial<GenPolynomial<C>> pi, pj, S, H;
176        while (pairlist.hasNext()) {
177            pair = pairlist.removeNext();
178            if (pair == null)
179                continue;
180
181            pi = pair.pi;
182            pj = pair.pj;
183            if (debug) {
184                logger.debug("pi    = " + pi);
185                logger.debug("pj    = " + pj);
186            }
187
188            S = red.SPolynomial(pi, pj);
189            if (S.isZERO()) {
190                pair.setZero();
191                continue;
192            }
193            if (debug) {
194                logger.info("ht(S) = " + S.leadingExpVector());
195            }
196
197            H = redRec.normalformRecursive(G, S);
198            if (H.isZERO()) {
199                pair.setZero();
200                continue;
201            }
202            if (debug) {
203                logger.info("ht(H) = " + H.leadingExpVector());
204            }
205            H = engine.recursivePrimitivePart(H);
206            H = H.abs();
207            if (H.isConstant()) {
208                G.clear();
209                G.add(H);
210                return G; // since no threads are activated
211            }
212            if (debug) {
213                logger.debug("H = " + H);
214            }
215            if (H.length() > 0) {
216                //l++;
217                G.add(H);
218                pairlist.put(H);
219            }
220        }
221        logger.debug("#sequential list = " + G.size());
222        G = minimalGB(G);
223        logger.info("" + pairlist);
224        return G;
225    }
226
227
228    /**
229     * Minimal ordered Groebner basis.
230     * @param Gp a Groebner base.
231     * @return a reduced Groebner base of Gp.
232     */
233    @Override
234    public List<GenPolynomial<GenPolynomial<C>>> minimalGB(List<GenPolynomial<GenPolynomial<C>>> Gp) {
235        List<GenPolynomial<GenPolynomial<C>>> G = normalizeZerosOnes(Gp);
236        /*
237        if (Gp == null || Gp.size() <= 1) {
238            return Gp;
239        }
240        // remove zero polynomials
241        List<GenPolynomial<GenPolynomial<C>>> G = new ArrayList<GenPolynomial<GenPolynomial<C>>>(Gp.size());
242        for (GenPolynomial<GenPolynomial<C>> a : Gp) {
243            if (a != null && !a.isZERO()) { // always true in GB()
244                // already positive a = a.abs();
245                G.add(a);
246            }
247        }
248        */
249        if (G.size() <= 1) {
250            return G;
251        }
252        // remove top reducible polynomials
253        GenPolynomial<GenPolynomial<C>> a;
254        List<GenPolynomial<GenPolynomial<C>>> F;
255        F = new ArrayList<GenPolynomial<GenPolynomial<C>>>(G.size());
256        while (G.size() > 0) {
257            a = G.remove(0);
258            if (red.isTopReducible(G, a) || red.isTopReducible(F, a)) {
259                // drop polynomial 
260                if (debug) {
261                    System.out.println("dropped " + a);
262                    List<GenPolynomial<GenPolynomial<C>>> ff;
263                    ff = new ArrayList<GenPolynomial<GenPolynomial<C>>>(G);
264                    ff.addAll(F);
265                    a = redRec.normalformRecursive(ff, a);
266                    if (!a.isZERO()) {
267                        System.out.println("error, nf(a) " + a);
268                    }
269                }
270            } else {
271                F.add(a);
272            }
273        }
274        G = F;
275        if (G.size() <= 1) {
276            return G;
277        }
278        Collections.reverse(G); // important for lex GB
279        // reduce remaining polynomials
280        int len = G.size();
281        int i = 0;
282        while (i < len) {
283            a = G.remove(0);
284            //System.out.println("doing " + a.length());
285            a = redRec.normalformRecursive(G, a);
286            a = engine.recursivePrimitivePart(a); //a.monic(); was not required
287            a = a.abs();
288            //a = redRec.normalformRecursive( F, a );
289            G.add(a); // adds as last
290            i++;
291        }
292        return G;
293    }
294
295
296    /**
297     * Groebner base simple test.
298     * @param modv module variable number.
299     * @param F recursive polynomial list.
300     * @return true, if F is a Groebner base, else false.
301     */
302    @Override
303    public boolean isGBsimple(int modv, List<GenPolynomial<GenPolynomial<C>>> F) {
304        if (F == null || F.isEmpty()) {
305            return true;
306        }
307        GenPolynomial<GenPolynomial<C>> pi, pj, s, h;
308        ExpVector ei, ej, eij;
309        for (int i = 0; i < F.size(); i++) {
310            pi = F.get(i);
311            ei = pi.leadingExpVector();
312            for (int j = i + 1; j < F.size(); j++) {
313                pj = F.get(j);
314                ej = pj.leadingExpVector();
315                if (!red.moduleCriterion(modv, ei, ej)) {
316                    continue;
317                }
318                eij = ei.lcm(ej);
319                if (!red.criterion4(ei, ej, eij)) {
320                    continue;
321                }
322                //if (!criterion3(i, j, eij, F)) {
323                //    continue;
324                //}
325                s = red.SPolynomial(pi, pj);
326                if (s.isZERO()) {
327                    continue;
328                }
329                //System.out.println("i, j = " + i + ", " + j); 
330                h = redRec.normalformRecursive(F, s);
331                if (!h.isZERO()) {
332                    logger.info("no GB: pi = " + pi + ", pj = " + pj);
333                    logger.info("s  = " + s + ", h = " + h);
334                    return false;
335                }
336            }
337        }
338        return true;
339    }
340
341}