001/*
002 * $Id: GBFactory.java 4296 2012-11-11 18:09:53Z kredel $
003 */
004
005package edu.jas.gbufd;
006
007
008import org.apache.log4j.Logger;
009
010import edu.jas.arith.BigInteger;
011import edu.jas.arith.BigRational;
012import edu.jas.arith.ModInteger;
013import edu.jas.arith.ModIntegerRing;
014import edu.jas.arith.ModLong;
015import edu.jas.arith.ModLongRing;
016import edu.jas.arith.Product;
017import edu.jas.arith.ProductRing;
018import edu.jas.gb.DGroebnerBaseSeq;
019import edu.jas.gb.EGroebnerBaseSeq;
020import edu.jas.gb.GBProxy;
021import edu.jas.gb.GroebnerBase;
022import edu.jas.gb.GroebnerBaseAbstract;
023import edu.jas.gb.GroebnerBaseParallel;
024import edu.jas.gb.GroebnerBaseSeq;
025import edu.jas.gb.ReductionSeq;
026import edu.jas.gb.OrderedSyzPairlist;
027import edu.jas.kern.ComputerThreads;
028import edu.jas.poly.GenPolynomial;
029import edu.jas.poly.GenPolynomialRing;
030import edu.jas.ufd.Quotient;
031import edu.jas.ufd.QuotientRing;
032import edu.jas.structure.GcdRingElem;
033import edu.jas.structure.RingElem;
034import edu.jas.structure.RingFactory;
035
036
037/**
038 * Groebner bases algorithms factory. Select appropriate Groebner bases engine
039 * based on the coefficient types.
040 * @author Heinz Kredel
041 * @usage To create objects that implement the <code>GroebnerBase</code>
042 *        interface use the <code>GBFactory</code>. It will select an
043 *        appropriate implementation based on the types of polynomial
044 *        coefficients C. The method to obtain an implementation is
045 *        <code>getImplementation()</code>. <code>getImplementation()</code>
046 *        returns an object of a class which implements the
047 *        <code>GroebnerBase</code> interface, more precisely an object of
048 *        abstract class <code>GroebnerBaseAbstract</code>.
049 * 
050 *        <pre>
051 *
052 * GroebnerBase&lt;CT&gt; engine;
053 * engine = GBFactory.&lt;CT&gt; getImplementation(cofac);
054 * c = engine.GB(A);
055 * </pre>
056 * 
057 *        For example, if the coefficient type is BigInteger, the usage looks
058 *        like
059 * 
060 *        <pre>
061 *
062 * BigInteger cofac = new BigInteger();
063 * GroebnerBase&lt;BigInteger&gt; engine;
064 * engine = GBFactory.getImplementation(cofac);
065 * c = engine.GB(A);
066 * </pre>
067 * 
068 * @see edu.jas.gb.GroebnerBase
069 * @see edu.jas.application.GBAlgorithmBuilder
070 */
071
072public class GBFactory {
073
074
075    private static final Logger logger = Logger.getLogger(GBFactory.class);
076
077
078    /**
079     * Algorithm indicators: igb = integerGB, egb = e-GB, dgb = d-GB, 
080     * qgb = fraction coefficients GB, ffgb = fraction free GB.
081     */
082    public static enum Algo {
083        igb, egb, dgb, qgb, ffgb
084    };
085
086
087    /**
088     * Protected factory constructor.
089     */
090    protected GBFactory() {
091    }
092
093
094    /**
095     * Determine suitable implementation of GB algorithms, no factory case.
096     * @return GB algorithm implementation for field coefficients.
097     */
098    public static <C extends GcdRingElem<C>> GroebnerBaseAbstract<C> getImplementation() {
099        logger.warn("no coefficent factory given, assuming field coeffcients");
100        GroebnerBaseAbstract<C> bba = new GroebnerBaseSeq<C>();
101        return bba;
102    }
103
104
105    /**
106     * Determine suitable implementation of GB algorithms, case ModLong.
107     * @param fac ModLongRing.
108     * @return GB algorithm implementation.
109     */
110    public static GroebnerBaseAbstract<ModLong> getImplementation(ModLongRing fac) {
111        GroebnerBaseAbstract<ModLong> bba;
112        if (fac.isField()) {
113            bba = new GroebnerBaseSeq<ModLong>();
114        } else {
115            bba = new GroebnerBasePseudoSeq<ModLong>(fac);
116        }
117        return bba;
118    }
119
120
121    /**
122     * Determine suitable implementation of GB algorithms, case ModInteger.
123     * @param fac ModIntegerRing.
124     * @return GB algorithm implementation.
125     */
126    public static GroebnerBaseAbstract<ModInteger> getImplementation(ModIntegerRing fac) {
127        GroebnerBaseAbstract<ModInteger> bba;
128        if (fac.isField()) {
129            bba = new GroebnerBaseSeq<ModInteger>();
130        } else {
131            bba = new GroebnerBasePseudoSeq<ModInteger>(fac);
132        }
133        return bba;
134    }
135
136
137    /**
138     * Determine suitable implementation of GB algorithms, case BigInteger.
139     * @param fac BigInteger.
140     * @return GB algorithm implementation.
141     */
142    public static GroebnerBaseAbstract<BigInteger> getImplementation(BigInteger fac) {
143        return getImplementation(fac, Algo.igb);
144    }
145
146
147    /**
148     * Determine suitable implementation of GB algorithms, case BigInteger.
149     * @param fac BigInteger.
150     * @param a algorithm, a = igb, egb, dgb.
151     * @return GB algorithm implementation.
152     */
153    public static GroebnerBaseAbstract<BigInteger> getImplementation(BigInteger fac, Algo a) {
154        GroebnerBaseAbstract<BigInteger> bba;
155        switch (a) {
156        case igb:
157            bba = new GroebnerBasePseudoSeq<BigInteger>(fac);
158            break;
159        case egb:
160            bba = new EGroebnerBaseSeq<BigInteger>();
161            break;
162        case dgb:
163            bba = new DGroebnerBaseSeq<BigInteger>();
164            break;
165        default:
166            throw new IllegalArgumentException("algorithm not available for BigInteger " + a);
167        }
168        return bba;
169    }
170
171
172    /**
173     * Determine suitable implementation of GB algorithms, case BigRational.
174     * @param fac BigRational.
175     * @return GB algorithm implementation.
176     */
177    public static GroebnerBaseAbstract<BigRational> getImplementation(BigRational fac) {
178        return getImplementation(fac, Algo.qgb);
179    }
180
181
182    /**
183     * Determine suitable implementation of GB algorithms, case BigRational.
184     * @param fac BigRational.
185     * @param a algorithm, a = qgb, ffgb.
186     * @return GB algorithm implementation.
187     */
188    public static GroebnerBaseAbstract<BigRational> getImplementation(BigRational fac, Algo a) {
189        GroebnerBaseAbstract<BigRational> bba;
190        switch (a) {
191        case qgb:
192            bba = new GroebnerBaseSeq<BigRational>();
193            //bba = new GroebnerBaseSeq<BigRational>(new ReductionSeq<BigRational>(),new OrderedSyzPairlist<BigRational>());
194            break;
195        case ffgb:
196            bba = new GroebnerBaseRational<BigRational>();
197            break;
198        default:
199            throw new IllegalArgumentException("algorithm not available for BigRational " + a);
200        }
201        return bba;
202    }
203
204
205    /**
206     * Determine suitable implementation of GB algorithms, case Quotient coefficients.
207     * @param fac QuotientRing.
208     * @return GB algorithm implementation.
209     */
210    public static <C extends GcdRingElem<C>>
211      GroebnerBaseAbstract<Quotient<C>> getImplementation(QuotientRing<C> fac) {
212        return getImplementation(fac, Algo.qgb);
213    }
214
215
216    /**
217     * Determine suitable implementation of GB algorithms, case Quotient coefficients.
218     * @param fac QuotientRing.
219     * @param a algorithm, a = qgb, ffgb.
220     * @return GB algorithm implementation.
221     */
222    public static <C extends GcdRingElem<C>>
223      GroebnerBaseAbstract<Quotient<C>> getImplementation(QuotientRing<C> fac, Algo a) {
224        GroebnerBaseAbstract<Quotient<C>> bba;
225        switch (a) {
226        case qgb:
227            bba = new GroebnerBaseSeq<Quotient<C>>(new ReductionSeq<Quotient<C>>());
228            break;
229        case ffgb:
230            bba = new GroebnerBaseSeqQuotient<C>(fac);
231            break;
232        default:
233            throw new IllegalArgumentException("algorithm not available for Quotient " + a);
234        }
235        return bba;
236    }
237
238
239    /**
240     * Determine suitable implementation of GB algorithms, case (recursive)
241     * polynomial.
242     * @param fac GenPolynomialRing&lt;C&gt;.
243     * @return GB algorithm implementation.
244     */
245    public static <C extends GcdRingElem<C>> 
246      GroebnerBaseAbstract<GenPolynomial<C>> getImplementation(GenPolynomialRing<C> fac) {
247        GroebnerBaseAbstract<GenPolynomial<C>> bba;
248        bba = new GroebnerBasePseudoRecSeq<C>(fac);
249        return bba;
250    }
251
252
253    /**
254     * Determine suitable implementation of GB algorithms, case regular rings.
255     * @param fac RegularRing.
256     * @return GB algorithm implementation.
257     */
258    public static <C extends RingElem<C>> 
259       GroebnerBaseAbstract<Product<C>> getImplementation(ProductRing<C> fac) {
260        GroebnerBaseAbstract<Product<C>> bba;
261        if (fac.onlyFields()) {
262            bba = new RGroebnerBaseSeq<Product<C>>();
263        } else {
264            bba = new RGroebnerBasePseudoSeq<Product<C>>(fac);
265        }
266        return bba;
267    }
268
269
270    /**
271     * Determine suitable implementation of GB algorithms, other cases.
272     * @param fac RingFactory&lt;C&gt;.
273     * @return GB algorithm implementation.
274     */
275    @SuppressWarnings("unchecked")
276    public static <C extends GcdRingElem<C>> // interface RingElem not sufficient 
277      GroebnerBaseAbstract<C> getImplementation(RingFactory<C> fac) {
278        logger.debug("fac = " + fac.getClass().getName());
279        if (fac.isField()) {
280            return new GroebnerBaseSeq<C>();
281            //return new GroebnerBaseSeq<C>(new ReductionSeq<C>(),new OrderedSyzPairlist<C>());
282        }
283        GroebnerBaseAbstract bba = null;
284        Object ofac = fac;
285        if (ofac instanceof GenPolynomialRing) {
286            GenPolynomialRing<C> rofac = (GenPolynomialRing<C>) ofac;
287            GroebnerBaseAbstract<GenPolynomial<C>> bbr = new GroebnerBasePseudoRecSeq<C>(rofac);
288            bba = (GroebnerBaseAbstract) bbr;
289        } else if (ofac instanceof ProductRing) {
290            ProductRing pfac = (ProductRing) ofac;
291            if (pfac.onlyFields()) {
292                bba = new RGroebnerBaseSeq<Product<C>>();
293            } else {
294                bba = new RGroebnerBasePseudoSeq<Product<C>>(pfac);
295            }
296        } else {
297            bba = new GroebnerBasePseudoSeq<C>(fac);
298        }
299        logger.debug("bba = " + bba.getClass().getName());
300        return bba;
301    }
302
303
304    /**
305     * Determine suitable concurrent implementation of GB algorithms if
306     * possible.
307     * @param fac RingFactory&lt;C&gt;.
308     * @return GB proxy algorithm implementation.
309     */
310    public static <C extends GcdRingElem<C>> // interface RingElem not sufficient 
311      GroebnerBaseAbstract<C> getProxy(RingFactory<C> fac) {
312        if (ComputerThreads.NO_THREADS) {
313            return GBFactory.<C> getImplementation(fac);
314        }
315        logger.debug("fac = " + fac.getClass().getName());
316        int th = ComputerThreads.N_CPUS-1;
317        if (fac.isField()) {
318            GroebnerBaseAbstract<C> e1 = new GroebnerBaseSeq<C>();
319            //GroebnerBaseAbstract<C> e1 = new GroebnerBaseSeq<C>(new ReductionSeq<C>(),new OrderedSyzPairlist<C>());
320            GroebnerBaseAbstract<C> e2 = new GroebnerBaseParallel<C>(th);
321            //GroebnerBaseAbstract<C> e2 = new GroebnerBaseParallel<C>(th,
322            //                                       new ReductionPar<C>(),new OrderedSyzPairlist<C>());
323            return new GBProxy<C>(e1, e2);
324        } else if (fac.getONE() instanceof GcdRingElem && fac.characteristic().signum() == 0) {
325            GroebnerBaseAbstract<C> e1 = new GroebnerBasePseudoSeq<C>(fac);
326            GroebnerBaseAbstract<C> e2 = new GroebnerBasePseudoParallel<C>(th,fac);
327            return new GBProxy<C>(e1, e2);
328        }
329        return getImplementation(fac);
330    }
331
332}