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