001/*
002 * $Id$
003 */
004
005package edu.jas.gbufd;
006
007
008import java.util.ArrayList;
009import java.util.List;
010
011import org.apache.logging.log4j.Logger;
012import org.apache.logging.log4j.LogManager; 
013
014import edu.jas.gb.GroebnerBaseAbstract;
015import edu.jas.gb.PairList;
016import edu.jas.poly.GenPolynomial;
017import edu.jas.poly.GenPolynomialRing;
018import edu.jas.poly.PolyUtil;
019import edu.jas.structure.GcdRingElem;
020import edu.jas.ufd.PolyUfdUtil;
021import edu.jas.ufd.Quotient;
022import edu.jas.ufd.QuotientRing;
023
024
025/**
026 * Groebner Base sequential algorithm for rational function coefficients,
027 * fraction free computation. Implements Groebner bases.
028 * @param <C> Quotient coefficient type
029 * @author Heinz Kredel
030 */
031
032public class GroebnerBaseQuotient<C extends GcdRingElem<C>> extends GroebnerBaseAbstract<Quotient<C>> {
033
034
035    private static final Logger logger = LogManager.getLogger(GroebnerBaseQuotient.class);
036
037
038    private static final boolean debug = logger.isDebugEnabled();
039
040
041    public final GroebnerBaseAbstract<GenPolynomial<C>> bba;
042
043
044    /**
045     * Constructor.
046     * @param rf quotient coefficient ring factory.
047     */
048    public GroebnerBaseQuotient(QuotientRing<C> rf) {
049        this(new GroebnerBasePseudoRecSeq<C>(rf.ring));
050    }
051
052
053    /**
054     * Constructor.
055     * @param threads the number of parallel threads.
056     * @param rf quotient coefficient ring factory.
057     */
058    public GroebnerBaseQuotient(int threads, QuotientRing<C> rf) {
059        this(new GroebnerBasePseudoRecParallel<C>(threads, rf.ring));
060    }
061
062
063    /**
064     * Constructor.
065     * @param rf quotient coefficient ring factory.
066     * @param pl pair selection strategy (for fraction parts).
067     */
068    public GroebnerBaseQuotient(QuotientRing<C> rf, PairList<GenPolynomial<C>> pl) {
069        this(new GroebnerBasePseudoRecSeq<C>(rf.ring, pl));
070    }
071
072
073    /**
074     * Constructor.
075     * @param threads the number of parallel threads.
076     * @param rf quotient coefficient ring factory.
077     * @param pl pair selection strategy (for fraction parts).
078     */
079    public GroebnerBaseQuotient(int threads, QuotientRing<C> rf, PairList<GenPolynomial<C>> pl) {
080        this(new GroebnerBasePseudoRecParallel<C>(threads, rf.ring, pl));
081    }
082
083
084    /**
085     * Constructor.
086     * @param bba Groebner base algorithm for GenPolynomial coefficients.
087     */
088    public GroebnerBaseQuotient(GroebnerBaseAbstract<GenPolynomial<C>> bba) {
089        super();
090        this.bba = bba;
091    }
092
093
094    /**
095     * Get the String representation with GB engines.
096     * @see java.lang.Object#toString()
097     */
098    @Override
099    public String toString() {
100        return this.getClass().getSimpleName() + "(" + bba.toString() + ")";
101    }
102
103
104    /**
105     * Groebner base using fraction free computation.
106     * @param modv module variable number.
107     * @param F polynomial list.
108     * @return GB(F) a Groebner base of F.
109     */
110    @Override
111    public List<GenPolynomial<Quotient<C>>> GB(int modv, List<GenPolynomial<Quotient<C>>> F) {
112        List<GenPolynomial<Quotient<C>>> G = F;
113        if (F == null || F.isEmpty()) {
114            return G;
115        }
116        GenPolynomialRing<Quotient<C>> rring = F.get(0).ring;
117        QuotientRing<C> cf = (QuotientRing<C>) rring.coFac;
118        GenPolynomialRing<GenPolynomial<C>> iring = new GenPolynomialRing<GenPolynomial<C>>(cf.ring, rring);
119        List<GenPolynomial<GenPolynomial<C>>> Fi = PolyUfdUtil.<C> integralFromQuotientCoefficients(iring, F);
120        //System.out.println("Fi = " + Fi);
121        logger.info("#Fi = {}", Fi.size());
122
123        List<GenPolynomial<GenPolynomial<C>>> Gi = bba.GB(modv, Fi);
124        //System.out.println("Gi = " + Gi);
125        logger.info("#Gi = {}", Gi.size());
126
127        G = PolyUfdUtil.<C> quotientFromIntegralCoefficients(rring, Gi);
128        G = PolyUtil.<Quotient<C>> monic(G);
129        return G;
130    }
131
132
133    /**
134     * Minimal ordered Groebner basis.
135     * @param Gp a Groebner base.
136     * @return a reduced Groebner base of Gp.
137     */
138    @Override
139    public List<GenPolynomial<Quotient<C>>> minimalGB(List<GenPolynomial<Quotient<C>>> Gp) {
140        if (Gp == null || Gp.size() <= 1) {
141            return Gp;
142        }
143        // remove zero polynomials
144        List<GenPolynomial<Quotient<C>>> G = new ArrayList<GenPolynomial<Quotient<C>>>(Gp.size());
145        for (GenPolynomial<Quotient<C>> a : Gp) {
146            if (a != null && !a.isZERO()) { // always true in GB()
147                // already positive a = a.abs();
148                G.add(a);
149            }
150        }
151        if (G.size() <= 1) {
152            return G;
153        }
154        // remove top reducible polynomials
155        GenPolynomial<Quotient<C>> a;
156        List<GenPolynomial<Quotient<C>>> F;
157        F = new ArrayList<GenPolynomial<Quotient<C>>>(G.size());
158        while (G.size() > 0) {
159            a = G.remove(0);
160            if (red.isTopReducible(G, a) || red.isTopReducible(F, a)) {
161                // drop polynomial 
162                if (debug) {
163                    System.out.println("dropped " + a);
164                    List<GenPolynomial<Quotient<C>>> ff;
165                    ff = new ArrayList<GenPolynomial<Quotient<C>>>(G);
166                    ff.addAll(F);
167                    a = red.normalform(ff, a);
168                    if (!a.isZERO()) {
169                        System.out.println("error, nf(a) " + a);
170                    }
171                }
172            } else {
173                F.add(a);
174            }
175        }
176        G = F;
177        if (G.size() <= 1) {
178            return G;
179        }
180
181        // reduce remaining polynomials
182        GenPolynomialRing<Quotient<C>> rring = G.get(0).ring;
183        QuotientRing<C> cf = (QuotientRing<C>) rring.coFac;
184        GenPolynomialRing<GenPolynomial<C>> iring = new GenPolynomialRing<GenPolynomial<C>>(cf.ring, rring);
185        List<GenPolynomial<GenPolynomial<C>>> Fi = PolyUfdUtil.integralFromQuotientCoefficients(iring, F);
186        logger.info("#Fi = {}", Fi.size());
187
188        List<GenPolynomial<GenPolynomial<C>>> Gi = bba.minimalGB(Fi);
189        logger.info("#Gi = {}", Gi.size());
190
191        G = PolyUfdUtil.<C> quotientFromIntegralCoefficients(rring, Gi);
192        G = PolyUtil.<Quotient<C>> monic(G);
193        return G;
194    }
195
196
197    /**
198     * Cleanup and terminate ThreadPool.
199     */
200    @Override
201    public void terminate() {
202        bba.terminate();
203    }
204
205
206    /**
207     * Cancel ThreadPool.
208     */
209    @Override
210    public int cancel() {
211        return bba.cancel();
212    }
213
214}