001/*
002 * $Id: GroebnerBasePseudoSeq.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.GenPolynomial;
019import edu.jas.poly.GenPolynomialRing;
020import edu.jas.structure.GcdRingElem;
021import edu.jas.structure.RingFactory;
022import edu.jas.ufd.GCDFactory;
023import edu.jas.ufd.GreatestCommonDivisorAbstract;
024
025
026/**
027 * Groebner Base with pseudo reduction sequential algorithm. Implements
028 * coefficient fraction free Groebner bases.
029 * Coefficients can for example be integers or (commutative) univariate polynomials.
030 * @param <C> coefficient type
031 * @author Heinz Kredel
032 * 
033 * @see edu.jas.application.GBAlgorithmBuilder
034 * @see edu.jas.gbufd.GBFactory
035 */
036
037public class GroebnerBasePseudoSeq<C extends GcdRingElem<C>> extends GroebnerBaseAbstract<C> {
038
039
040    private static final Logger logger = Logger.getLogger(GroebnerBasePseudoSeq.class);
041
042
043    private static final boolean debug = logger.isDebugEnabled();
044
045
046    /**
047     * Greatest common divisor engine for coefficient content and primitive
048     * parts.
049     */
050    protected final GreatestCommonDivisorAbstract<C> engine;
051
052
053    /**
054     * Pseudo reduction engine.
055     */
056    protected final PseudoReduction<C> red;
057
058
059    /**
060     * Coefficient ring factory.
061     */
062    protected final RingFactory<C> cofac;
063
064
065    /**
066     * Constructor.
067     * @param rf coefficient ring factory.
068     */
069    public GroebnerBasePseudoSeq(RingFactory<C> rf) {
070        this(new PseudoReductionSeq<C>(), rf, new OrderedPairlist<C>());
071    }
072
073
074    /**
075     * Constructor.
076     * @param rf coefficient ring factory.
077     * @param pl pair selection strategy
078     */
079    public GroebnerBasePseudoSeq(RingFactory<C> rf, PairList<C> pl) {
080        this(new PseudoReductionSeq<C>(), rf, pl);
081    }
082
083
084    /**
085     * Constructor.
086     * @param red pseudo reduction engine. <b>Note:</b> red must be an instance
087     *            of PseudoReductionSeq.
088     * @param rf coefficient ring factory.
089     * @param pl pair selection strategy
090     */
091    public GroebnerBasePseudoSeq(PseudoReduction<C> red, RingFactory<C> rf, PairList<C> pl) {
092        super(red, pl);
093        this.red = red;
094        cofac = rf;
095        engine = GCDFactory.<C> getImplementation(rf);
096        //not used: engine = (GreatestCommonDivisorAbstract<C>)GCDFactory.<C>getProxy( rf );
097    }
098
099
100    /**
101     * Groebner base using pairlist class.
102     * @param modv module variable number.
103     * @param F polynomial list.
104     * @return GB(F) a Groebner base of F.
105     */
106    public List<GenPolynomial<C>> GB(int modv, List<GenPolynomial<C>> F) {
107        List<GenPolynomial<C>> G = normalizeZerosOnes(F);
108        G = engine.basePrimitivePart(G);
109        if (G.size() <= 1) {
110            return G;
111        }
112        GenPolynomialRing<C> ring = G.get(0).ring;
113        if (ring.coFac.isField()) { // remove ?
114            throw new IllegalArgumentException("coefficients from a field");
115        }
116        PairList<C> pairlist = strategy.create(modv, ring);
117        pairlist.put(G);
118
119        Pair<C> pair;
120        GenPolynomial<C> pi, pj, S, H;
121        while (pairlist.hasNext()) {
122            pair = pairlist.removeNext();
123            if (pair == null)
124                continue;
125
126            pi = pair.pi;
127            pj = pair.pj;
128            if (debug) {
129                logger.debug("pi    = " + pi);
130                logger.debug("pj    = " + pj);
131            }
132
133            S = red.SPolynomial(pi, pj);
134            if (S.isZERO()) {
135                pair.setZero();
136                continue;
137            }
138            if (debug) {
139                logger.debug("ht(S) = " + S.leadingExpVector());
140            }
141
142            H = red.normalform(G, S);
143            if (H.isZERO()) {
144                pair.setZero();
145                continue;
146            }
147            if (debug) {
148                logger.debug("ht(H) = " + H.leadingExpVector());
149            }
150            H = engine.basePrimitivePart(H);
151            H = H.abs();
152            if (H.isConstant()) {
153                G.clear();
154                G.add(H);
155                return G; // since no threads are activated
156            }
157            if (logger.isDebugEnabled()) {
158                logger.debug("H = " + H);
159            }
160            if (H.length() > 0) {
161                //l++;
162                G.add(H);
163                pairlist.put(H);
164            }
165        }
166        logger.debug("#sequential list = " + G.size());
167        G = minimalGB(G);
168        logger.info("" + pairlist);
169        return G;
170    }
171
172
173    /**
174     * Minimal ordered Groebner basis.
175     * @param Gp a Groebner base.
176     * @return a reduced Groebner base of Gp.
177     */
178    @Override
179    public List<GenPolynomial<C>> minimalGB(List<GenPolynomial<C>> Gp) {
180        List<GenPolynomial<C>> G = normalizeZerosOnes(Gp);
181        if (G.size() <= 1) {
182            return G;
183        }
184        // remove top reducible polynomials
185        GenPolynomial<C> a;
186        List<GenPolynomial<C>> F;
187        F = new ArrayList<GenPolynomial<C>>(G.size());
188        while (G.size() > 0) {
189            a = G.remove(0);
190            if (red.isTopReducible(G, a) || red.isTopReducible(F, a)) {
191                // drop polynomial 
192                if (debug) {
193                    System.out.println("dropped " + a);
194                    List<GenPolynomial<C>> ff;
195                    ff = new ArrayList<GenPolynomial<C>>(G);
196                    ff.addAll(F);
197                    a = red.normalform(ff, a);
198                    if (!a.isZERO()) {
199                        System.out.println("error, nf(a) " + a);
200                    }
201                }
202            } else {
203                F.add(a);
204            }
205        }
206        G = F;
207        if (G.size() <= 1) {
208            return G;
209        }
210        Collections.reverse(G); // important for lex GB
211        // reduce remaining polynomials
212        int len = G.size();
213        int i = 0;
214        while (i < len) {
215            a = G.remove(0);
216            //System.out.println("doing " + a.length());
217            a = red.normalform(G, a);
218            a = engine.basePrimitivePart(a); //a.monic(); not possible
219            a = a.abs();
220            //a = red.normalform( F, a );
221            G.add(a); // adds as last
222            i++;
223        }
224        Collections.reverse(G); // undo reverse
225        return G;
226    }
227
228}