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