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