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