001/*
002 * $Id: GroebnerBasePseudoRecSeq.java 5841 2018-05-20 21:26:13Z 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 static 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("unchecked")
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()) { // 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        Pair<GenPolynomial<C>> pair;
143        GenPolynomial<GenPolynomial<C>> pi, pj, S, H;
144        while (pairlist.hasNext()) {
145            pair = pairlist.removeNext();
146            if (pair == null)
147                continue;
148
149            pi = pair.pi;
150            pj = pair.pj;
151            if (debug) {
152                logger.debug("pi    = " + pi);
153                logger.debug("pj    = " + pj);
154            }
155
156            S = red.SPolynomial(pi, pj);
157            if (S.isZERO()) {
158                pair.setZero();
159                continue;
160            }
161            if (debug) {
162                logger.info("ht(S) = " + S.leadingExpVector());
163            }
164
165            H = redRec.normalformRecursive(G, S);
166            if (H.isZERO()) {
167                pair.setZero();
168                continue;
169            }
170            if (debug) {
171                logger.info("ht(H) = " + H.leadingExpVector());
172            }
173            H = engine.recursivePrimitivePart(H);
174            H = H.abs();
175            if (H.isConstant()) {
176                G.clear();
177                G.add(H);
178                return G; // since no threads are activated
179            }
180            if (debug) {
181                logger.debug("H = " + H);
182            }
183            if (H.length() > 0) {
184                //l++;
185                G.add(H);
186                pairlist.put(H);
187            }
188        }
189        logger.debug("#sequential list = " + G.size());
190        G = minimalGB(G);
191        logger.info("" + pairlist);
192        return G;
193    }
194
195
196    /**
197     * Minimal ordered Groebner basis.
198     * @param Gp a Groebner base.
199     * @return a reduced Groebner base of Gp.
200     */
201    @Override
202    public List<GenPolynomial<GenPolynomial<C>>> minimalGB(List<GenPolynomial<GenPolynomial<C>>> Gp) {
203        List<GenPolynomial<GenPolynomial<C>>> G = normalizeZerosOnes(Gp);
204        if (G.size() <= 1) {
205            return G;
206        }
207        // remove top reducible polynomials
208        GenPolynomial<GenPolynomial<C>> a;
209        List<GenPolynomial<GenPolynomial<C>>> F;
210        F = new ArrayList<GenPolynomial<GenPolynomial<C>>>(G.size());
211        while (G.size() > 0) {
212            a = G.remove(0);
213            if (red.isTopReducible(G, a) || red.isTopReducible(F, a)) {
214                // drop polynomial 
215                if (debug) {
216                    System.out.println("dropped " + a);
217                    List<GenPolynomial<GenPolynomial<C>>> ff;
218                    ff = new ArrayList<GenPolynomial<GenPolynomial<C>>>(G);
219                    ff.addAll(F);
220                    a = redRec.normalformRecursive(ff, a);
221                    if (!a.isZERO()) {
222                        System.out.println("error, nf(a) " + a);
223                    }
224                }
225            } else {
226                F.add(a);
227            }
228        }
229        G = F;
230        if (G.size() <= 1) {
231            return G;
232        }
233        Collections.reverse(G); // important for lex GB
234        // reduce remaining polynomials
235        int len = G.size();
236        int i = 0;
237        while (i < len) {
238            a = G.remove(0);
239            //System.out.println("doing " + a.length());
240            a = redRec.normalformRecursive(G, a);
241            a = engine.recursivePrimitivePart(a); //a.monic(); was not required
242            a = a.abs();
243            //a = redRec.normalformRecursive( F, a );
244            G.add(a); // adds as last
245            i++;
246        }
247        Collections.reverse(G); // undo reverse
248        return G;
249    }
250
251
252    /**
253     * Groebner base simple test.
254     * @param modv module variable number.
255     * @param F recursive polynomial list.
256     * @return true, if F is a Groebner base, else false.
257     */
258    @Override
259    public boolean isGBsimple(int modv, List<GenPolynomial<GenPolynomial<C>>> F) {
260        if (F == null || F.isEmpty()) {
261            return true;
262        }
263        GenPolynomial<GenPolynomial<C>> pi, pj, s, h;
264        ExpVector ei, ej, eij;
265        for (int i = 0; i < F.size(); i++) {
266            pi = F.get(i);
267            ei = pi.leadingExpVector();
268            for (int j = i + 1; j < F.size(); j++) {
269                pj = F.get(j);
270                ej = pj.leadingExpVector();
271                if (!red.moduleCriterion(modv, ei, ej)) {
272                    continue;
273                }
274                eij = ei.lcm(ej);
275                if (!red.criterion4(ei, ej, eij)) {
276                    continue;
277                }
278                //if (!criterion3(i, j, eij, F)) {
279                //    continue;
280                //}
281                s = red.SPolynomial(pi, pj);
282                if (s.isZERO()) {
283                    continue;
284                }
285                //System.out.println("i, j = " + i + ", " + j); 
286                h = redRec.normalformRecursive(F, s);
287                if (!h.isZERO()) {
288                    logger.info("no GB: pi = " + pi + ", pj = " + pj);
289                    logger.info("s  = " + s + ", h = " + h);
290                    return false;
291                }
292            }
293        }
294        return true;
295    }
296
297}