001/*
002 * $Id: GBFactory.java 5104 2015-02-07 13:12:43Z 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.GroebnerBaseAbstract;
022import edu.jas.gb.GroebnerBaseParallel;
023import edu.jas.gb.GroebnerBaseSeq;
024import edu.jas.gb.OrderedMinPairlist;
025import edu.jas.gb.OrderedPairlist;
026import edu.jas.gb.OrderedSyzPairlist;
027import edu.jas.gb.PairList;
028import edu.jas.gb.ReductionSeq;
029import edu.jas.kern.ComputerThreads;
030import edu.jas.poly.GenPolynomial;
031import edu.jas.poly.GenPolynomialRing;
032import edu.jas.structure.GcdRingElem;
033import edu.jas.structure.RingElem;
034import edu.jas.structure.RingFactory;
035import edu.jas.ufd.Quotient;
036import edu.jas.ufd.QuotientRing;
037
038
039/**
040 * Groebner bases algorithms factory. Select appropriate Groebner bases engine
041 * based on the coefficient types.
042 * @author Heinz Kredel
043 * @usage To create objects that implement the <code>GroebnerBase</code>
044 *        interface use the <code>GBFactory</code>. It will select an
045 *        appropriate implementation based on the types of polynomial
046 *        coefficients C. The method to obtain an implementation is
047 *        <code>getImplementation()</code>. <code>getImplementation()</code>
048 *        returns an object of a class which implements the
049 *        <code>GroebnerBase</code> interface, more precisely an object of
050 *        abstract class <code>GroebnerBaseAbstract</code>.
051 * 
052 *        <pre>
053 * 
054 * GroebnerBase&lt;CT&gt; engine;
055 * engine = GBFactory.&lt;CT&gt; getImplementation(cofac);
056 * c = engine.GB(A);
057 * </pre>
058 * 
059 *        For example, if the coefficient type is BigInteger, the usage looks
060 *        like
061 * 
062 *        <pre>
063 * 
064 * BigInteger cofac = new BigInteger();
065 * GroebnerBase&lt;BigInteger&gt; engine;
066 * engine = GBFactory.getImplementation(cofac);
067 * c = engine.GB(A);
068 * </pre>
069 * 
070 * @see edu.jas.gb.GroebnerBase
071 * @see edu.jas.application.GBAlgorithmBuilder
072 */
073
074public class GBFactory {
075
076
077    private static final Logger logger = Logger.getLogger(GBFactory.class);
078
079
080    /**
081     * Algorithm indicators: igb = integerGB, egb = e-GB, dgb = d-GB, qgb =
082     * fraction coefficients GB, ffgb = fraction free GB.
083     */
084    public static enum Algo {
085        igb, egb, dgb, qgb, ffgb
086    };
087
088
089    /**
090     * Protected factory constructor.
091     */
092    protected GBFactory() {
093    }
094
095
096    /**
097     * Determine suitable implementation of GB algorithms, no factory case.
098     * @return GB algorithm implementation for field coefficients.
099     */
100    public static <C extends GcdRingElem<C>> GroebnerBaseAbstract<C> getImplementation() {
101        logger.warn("no coefficent factory given, assuming field coeffcients");
102        GroebnerBaseAbstract<C> bba = new GroebnerBaseSeq<C>();
103        return bba;
104    }
105
106
107    /**
108     * Determine suitable implementation of GB algorithms, case ModLong.
109     * @param fac ModLongRing.
110     * @return GB algorithm implementation.
111     */
112    public static GroebnerBaseAbstract<ModLong> getImplementation(ModLongRing fac) {
113        return getImplementation(fac, new OrderedPairlist<ModLong>());
114    }
115
116
117    /**
118     * Determine suitable implementation of GB algorithms, case ModLong.
119     * @param fac ModLongRing.
120     * @param pl pair selection strategy
121     * @return GB algorithm implementation.
122     */
123    public static GroebnerBaseAbstract<ModLong> getImplementation(ModLongRing fac, PairList<ModLong> pl) {
124        GroebnerBaseAbstract<ModLong> bba;
125        if (fac.isField()) {
126            bba = new GroebnerBaseSeq<ModLong>(pl);
127        } else {
128            bba = new GroebnerBasePseudoSeq<ModLong>(fac, pl);
129        }
130        return bba;
131    }
132
133
134    /**
135     * Determine suitable implementation of GB algorithms, case ModInteger.
136     * @param fac ModIntegerRing.
137     * @return GB algorithm implementation.
138     */
139    public static GroebnerBaseAbstract<ModInteger> getImplementation(ModIntegerRing fac) {
140        return getImplementation(fac, new OrderedPairlist<ModInteger>());
141    }
142
143
144    /**
145     * Determine suitable implementation of GB algorithms, case ModInteger.
146     * @param fac ModIntegerRing.
147     * @param pl pair selection strategy
148     * @return GB algorithm implementation.
149     */
150    public static GroebnerBaseAbstract<ModInteger> getImplementation(ModIntegerRing fac,
151                    PairList<ModInteger> pl) {
152        GroebnerBaseAbstract<ModInteger> bba;
153        if (fac.isField()) {
154            bba = new GroebnerBaseSeq<ModInteger>(pl);
155        } else {
156            bba = new GroebnerBasePseudoSeq<ModInteger>(fac, pl);
157        }
158        return bba;
159    }
160
161
162    /**
163     * Determine suitable implementation of GB algorithms, case BigInteger.
164     * @param fac BigInteger.
165     * @return GB algorithm implementation.
166     */
167    public static GroebnerBaseAbstract<BigInteger> getImplementation(BigInteger fac) {
168        return getImplementation(fac, Algo.igb);
169    }
170
171
172    /**
173     * Determine suitable implementation of GB algorithms, case BigInteger.
174     * @param fac BigInteger.
175     * @param a algorithm, a = igb, egb, dgb.
176     * @return GB algorithm implementation.
177     */
178    public static GroebnerBaseAbstract<BigInteger> getImplementation(BigInteger fac, Algo a) {
179        return getImplementation(fac, a, new OrderedPairlist<BigInteger>());
180    }
181
182
183    /**
184     * Determine suitable implementation of GB algorithms, case BigInteger.
185     * @param fac BigInteger.
186     * @param pl pair selection strategy
187     * @return GB algorithm implementation.
188     */
189    public static GroebnerBaseAbstract<BigInteger> getImplementation(BigInteger fac, PairList<BigInteger> pl) {
190        return getImplementation(fac, Algo.igb, pl);
191    }
192
193
194    /**
195     * Determine suitable implementation of GB algorithms, case BigInteger.
196     * @param fac BigInteger.
197     * @param a algorithm, a = igb, egb, dgb.
198     * @param pl pair selection strategy
199     * @return GB algorithm implementation.
200     */
201    public static GroebnerBaseAbstract<BigInteger> getImplementation(BigInteger fac, Algo a,
202                    PairList<BigInteger> pl) {
203        GroebnerBaseAbstract<BigInteger> bba;
204        switch (a) {
205        case igb:
206            bba = new GroebnerBasePseudoSeq<BigInteger>(fac, pl);
207            break;
208        case egb:
209            bba = new EGroebnerBaseSeq<BigInteger>(); // pl not suitable
210            break;
211        case dgb:
212            bba = new DGroebnerBaseSeq<BigInteger>(); // pl not suitable
213            break;
214        default:
215            throw new IllegalArgumentException("algorithm not available for BigInteger " + a);
216        }
217        return bba;
218    }
219
220
221    /**
222     * Determine suitable implementation of GB algorithms, case BigRational.
223     * @param fac BigRational.
224     * @return GB algorithm implementation.
225     */
226    public static GroebnerBaseAbstract<BigRational> getImplementation(BigRational fac) {
227        return getImplementation(fac, Algo.qgb);
228    }
229
230
231    /**
232     * Determine suitable implementation of GB algorithms, case BigRational.
233     * @param fac BigRational.
234     * @param a algorithm, a = qgb, ffgb.
235     * @return GB algorithm implementation.
236     */
237    public static GroebnerBaseAbstract<BigRational> getImplementation(BigRational fac, Algo a) {
238        return getImplementation(fac, a, new OrderedPairlist<BigRational>());
239    }
240
241
242    /**
243     * Determine suitable implementation of GB algorithms, case BigRational.
244     * @param fac BigRational.
245     * @param pl pair selection strategy
246     * @return GB algorithm implementation.
247     */
248    public static GroebnerBaseAbstract<BigRational> getImplementation(BigRational fac,
249                    PairList<BigRational> pl) {
250        return getImplementation(fac, Algo.qgb, pl);
251    }
252
253
254    /**
255     * Determine suitable implementation of GB algorithms, case BigRational.
256     * @param fac BigRational.
257     * @param a algorithm, a = qgb, ffgb.
258     * @param pl pair selection strategy
259     * @return GB algorithm implementation.
260     */
261    public static GroebnerBaseAbstract<BigRational> getImplementation(BigRational fac, Algo a,
262                    PairList<BigRational> pl) {
263        GroebnerBaseAbstract<BigRational> bba;
264        switch (a) {
265        case qgb:
266            bba = new GroebnerBaseSeq<BigRational>(pl);
267            break;
268        case ffgb:
269            PairList<BigInteger> pli;
270            if (pl instanceof OrderedMinPairlist) {
271                pli = new OrderedMinPairlist<BigInteger>();
272            } else if (pl instanceof OrderedSyzPairlist) {
273                pli = new OrderedSyzPairlist<BigInteger>();
274            } else {
275                pli = new OrderedPairlist<BigInteger>();
276            }
277            bba = new GroebnerBaseRational<BigRational>(pli); // pl not possible
278            break;
279        default:
280            throw new IllegalArgumentException("algorithm not available for " + fac.toScriptFactory()
281                            + ", Algo = " + a);
282        }
283        return bba;
284    }
285
286
287    /**
288     * Determine suitable implementation of GB algorithms, case Quotient
289     * coefficients.
290     * @param fac QuotientRing.
291     * @return GB algorithm implementation.
292     */
293    public static <C extends GcdRingElem<C>> GroebnerBaseAbstract<Quotient<C>> getImplementation(
294                    QuotientRing<C> fac) {
295        return getImplementation(fac, Algo.qgb);
296    }
297
298
299    /**
300     * Determine suitable implementation of GB algorithms, case Quotient
301     * coefficients.
302     * @param fac QuotientRing.
303     * @param a algorithm, a = qgb, ffgb.
304     * @return GB algorithm implementation.
305     */
306    public static <C extends GcdRingElem<C>> GroebnerBaseAbstract<Quotient<C>> getImplementation(
307                    QuotientRing<C> fac, Algo a) {
308        return getImplementation(fac, a, new OrderedPairlist<Quotient<C>>());
309    }
310
311
312    /**
313     * Determine suitable implementation of GB algorithms, case Quotient
314     * coefficients.
315     * @param fac QuotientRing.
316     * @param pl pair selection strategy
317     * @return GB algorithm implementation.
318     */
319    public static <C extends GcdRingElem<C>> GroebnerBaseAbstract<Quotient<C>> getImplementation(
320                    QuotientRing<C> fac, PairList<Quotient<C>> pl) {
321        return getImplementation(fac, Algo.qgb, pl);
322    }
323
324
325    /**
326     * Determine suitable implementation of GB algorithms, case Quotient
327     * coefficients.
328     * @param fac QuotientRing.
329     * @param a algorithm, a = qgb, ffgb.
330     * @param pl pair selection strategy
331     * @return GB algorithm implementation.
332     */
333    public static <C extends GcdRingElem<C>> GroebnerBaseAbstract<Quotient<C>> getImplementation(
334                    QuotientRing<C> fac, Algo a, PairList<Quotient<C>> pl) {
335        GroebnerBaseAbstract<Quotient<C>> bba;
336        switch (a) {
337        case qgb:
338            bba = new GroebnerBaseSeq<Quotient<C>>(new ReductionSeq<Quotient<C>>(), pl);
339            break;
340        case ffgb:
341            PairList<GenPolynomial<C>> pli;
342            if (pl instanceof OrderedMinPairlist) {
343                pli = new OrderedMinPairlist<GenPolynomial<C>>();
344            } else if (pl instanceof OrderedSyzPairlist) {
345                pli = new OrderedSyzPairlist<GenPolynomial<C>>();
346            } else {
347                pli = new OrderedPairlist<GenPolynomial<C>>();
348            }
349            bba = new GroebnerBaseQuotient<C>(fac, pli); // pl not possible
350            break;
351        default:
352            throw new IllegalArgumentException("algorithm not available for Quotient " + a);
353        }
354        return bba;
355    }
356
357
358    /**
359     * Determine suitable implementation of GB algorithms, case (recursive)
360     * polynomial.
361     * @param fac GenPolynomialRing&lt;C&gt;.
362     * @return GB algorithm implementation.
363     */
364    public static <C extends GcdRingElem<C>> GroebnerBaseAbstract<GenPolynomial<C>> getImplementation(
365                    GenPolynomialRing<C> fac) {
366        return getImplementation(fac, Algo.igb);
367    }
368
369
370    /**
371     * Determine suitable implementation of GB algorithms, case (recursive)
372     * polynomial.
373     * @param fac GenPolynomialRing&lt;C&gt;.
374     * @param a algorithm, a = igb or egb, dgb if fac is univariate over a
375     *            field.
376     * @return GB algorithm implementation.
377     */
378    public static <C extends GcdRingElem<C>> GroebnerBaseAbstract<GenPolynomial<C>> getImplementation(
379                    GenPolynomialRing<C> fac, Algo a) {
380        return getImplementation(fac, a, new OrderedPairlist<GenPolynomial<C>>());
381    }
382
383
384    /**
385     * Determine suitable implementation of GB algorithms, case (recursive)
386     * polynomial.
387     * @param fac GenPolynomialRing&lt;C&gt;.
388     * @param pl pair selection strategy
389     * @return GB algorithm implementation.
390     */
391    public static <C extends GcdRingElem<C>> GroebnerBaseAbstract<GenPolynomial<C>> getImplementation(
392                    GenPolynomialRing<C> fac, PairList<GenPolynomial<C>> pl) {
393        return getImplementation(fac, Algo.igb, pl);
394    }
395
396
397    /**
398     * Determine suitable implementation of GB algorithms, case (recursive)
399     * polynomial.
400     * @param fac GenPolynomialRing&lt;C&gt;.
401     * @param a algorithm, a = igb or egb, dgb if fac is univariate over a
402     *            field.
403     * @param pl pair selection strategy
404     * @return GB algorithm implementation.
405     */
406    public static <C extends GcdRingElem<C>> GroebnerBaseAbstract<GenPolynomial<C>> getImplementation(
407                    GenPolynomialRing<C> fac, Algo a, PairList<GenPolynomial<C>> pl) {
408        GroebnerBaseAbstract<GenPolynomial<C>> bba;
409        switch (a) {
410        case igb:
411            bba = new GroebnerBasePseudoRecSeq<C>(fac, pl);
412            break;
413        case egb:
414            if (fac.nvar > 1 || !fac.coFac.isField()) {
415                throw new IllegalArgumentException("coefficients not univariate or not over a field" + fac);
416            }
417            bba = new EGroebnerBaseSeq<GenPolynomial<C>>(); // pl not suitable
418            break;
419        case dgb:
420            if (fac.nvar > 1 || !fac.coFac.isField()) {
421                throw new IllegalArgumentException("coefficients not univariate or not over a field" + fac);
422            }
423            bba = new DGroebnerBaseSeq<GenPolynomial<C>>(); // pl not suitable
424            break;
425        default:
426            throw new IllegalArgumentException("algorithm not available for GenPolynomial<C> " + a);
427        }
428        return bba;
429    }
430
431
432    /**
433     * Determine suitable implementation of GB algorithms, case regular rings.
434     * @param fac RegularRing.
435     * @return GB algorithm implementation.
436     */
437    public static <C extends RingElem<C>> GroebnerBaseAbstract<Product<C>> getImplementation(
438                    ProductRing<C> fac) {
439        GroebnerBaseAbstract<Product<C>> bba;
440        if (fac.onlyFields()) {
441            bba = new RGroebnerBaseSeq<Product<C>>();
442        } else {
443            bba = new RGroebnerBasePseudoSeq<Product<C>>(fac);
444        }
445        return bba;
446    }
447
448
449    /**
450     * Determine suitable implementation of GB algorithms, other cases.
451     * @param fac RingFactory&lt;C&gt;.
452     * @return GB algorithm implementation.
453     */
454    public static <C extends GcdRingElem<C>> // interface RingElem not sufficient 
455    GroebnerBaseAbstract<C> getImplementation(RingFactory<C> fac) {
456        return getImplementation(fac, new OrderedPairlist<C>());
457    }
458
459
460    /**
461     * Determine suitable implementation of GB algorithms, other cases.
462     * @param fac RingFactory&lt;C&gt;.
463     * @param pl pair selection strategy
464     * @return GB algorithm implementation.
465     */
466    @SuppressWarnings("cast")
467    public static <C extends GcdRingElem<C>> // interface RingElem not sufficient 
468    GroebnerBaseAbstract<C> getImplementation(RingFactory<C> fac, PairList<C> pl) {
469        logger.debug("fac = " + fac.getClass().getName());
470        if (fac.isField()) {
471            return new GroebnerBaseSeq<C>(pl);
472        }
473        GroebnerBaseAbstract bba = null;
474        Object ofac = fac;
475        if (ofac instanceof GenPolynomialRing) {
476            PairList<GenPolynomial<C>> pli;
477            if (pl instanceof OrderedMinPairlist) {
478                pli = new OrderedMinPairlist<GenPolynomial<C>>();
479            } else if (pl instanceof OrderedSyzPairlist) {
480                pli = new OrderedSyzPairlist<GenPolynomial<C>>();
481            } else {
482                pli = new OrderedPairlist<GenPolynomial<C>>();
483            }
484            GenPolynomialRing<C> rofac = (GenPolynomialRing<C>) ofac;
485            GroebnerBaseAbstract<GenPolynomial<C>> bbr = new GroebnerBasePseudoRecSeq<C>(rofac, pli); // not pl
486            bba = (GroebnerBaseAbstract) bbr;
487        } else if (ofac instanceof ProductRing) {
488            ProductRing pfac = (ProductRing) ofac;
489            if (pfac.onlyFields()) {
490                bba = new RGroebnerBaseSeq<Product<C>>();
491            } else {
492                bba = new RGroebnerBasePseudoSeq<Product<C>>(pfac);
493            }
494        } else {
495            bba = new GroebnerBasePseudoSeq<C>(fac, pl);
496        }
497        logger.debug("bba = " + bba.getClass().getName());
498        return bba;
499    }
500
501
502    /**
503     * Determine suitable parallel/concurrent implementation of GB algorithms if
504     * possible.
505     * @param fac RingFactory&lt;C&gt;.
506     * @return GB proxy algorithm implementation.
507     */
508    public static <C extends GcdRingElem<C>> // interface RingElem not sufficient 
509    GroebnerBaseAbstract<C> getProxy(RingFactory<C> fac) {
510        return getProxy(fac, new OrderedPairlist<C>());
511    }
512
513
514    /**
515     * Determine suitable parallel/concurrent implementation of GB algorithms if
516     * possible.
517     * @param fac RingFactory&lt;C&gt;.
518     * @param pl pair selection strategy
519     * @return GB proxy algorithm implementation.
520     */
521    public static <C extends GcdRingElem<C>> // interface RingElem not sufficient 
522    GroebnerBaseAbstract<C> getProxy(RingFactory<C> fac, PairList<C> pl) {
523        if (ComputerThreads.NO_THREADS) {
524            return GBFactory.<C> getImplementation(fac, pl);
525        }
526        logger.debug("fac = " + fac.getClass().getName());
527        int th = (ComputerThreads.N_CPUS > 2 ? ComputerThreads.N_CPUS - 1 : 2);
528        if (fac.isField()) {
529            GroebnerBaseAbstract<C> e1 = new GroebnerBaseSeq<C>(pl);
530            GroebnerBaseAbstract<C> e2 = new GroebnerBaseParallel<C>(th, pl);
531            return new GBProxy<C>(e1, e2);
532        } else if (fac.characteristic().signum() == 0) {
533            if (fac instanceof GenPolynomialRing) {
534                GenPolynomialRing pfac = (GenPolynomialRing) fac;
535                OrderedPairlist ppl = new OrderedPairlist<GenPolynomial<C>>();
536                GroebnerBaseAbstract e1 = new GroebnerBasePseudoRecSeq<C>(pfac, ppl);
537                GroebnerBaseAbstract e2 = new GroebnerBasePseudoRecParallel<C>(th, pfac, ppl);
538                return new GBProxy<C>(e1, e2);
539            }
540            GroebnerBaseAbstract<C> e1 = new GroebnerBasePseudoSeq<C>(fac, pl);
541            GroebnerBaseAbstract<C> e2 = new GroebnerBasePseudoParallel<C>(th, fac, pl);
542            return new GBProxy<C>(e1, e2);
543        }
544        return getImplementation(fac, pl);
545    }
546
547
548    /**
549     * Determine suitable parallel/concurrent implementation of GB algorithms if
550     * possible.
551     * @param fac RingFactory&lt;C&gt;.
552     * @return GB proxy algorithm implementation.
553     */
554    public static <C extends GcdRingElem<C>> // interface RingElem not sufficient 
555    GroebnerBaseAbstract<GenPolynomial<C>> getProxy(GenPolynomialRing<C> fac) {
556        if (ComputerThreads.NO_THREADS) {
557            //return GBFactory.<GenPolynomial<C>> getImplementation(fac);
558            return GBFactory.getImplementation(fac);
559        }
560        logger.debug("fac = " + fac.getClass().getName());
561        int th = (ComputerThreads.N_CPUS > 2 ? ComputerThreads.N_CPUS - 1 : 2);
562        OrderedPairlist<GenPolynomial<C>> ppl = new OrderedPairlist<GenPolynomial<C>>();
563        GroebnerBaseAbstract<GenPolynomial<C>> e1 = new GroebnerBasePseudoRecSeq<C>(fac, ppl);
564        GroebnerBaseAbstract<GenPolynomial<C>> e2 = new GroebnerBasePseudoRecParallel<C>(th, fac, ppl);
565        //return new GBProxy<GenPolynomial<C>>(e1, e2);
566        return new GBProxy(e1, e2);
567    }
568
569}