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<CT> engine; 053 * engine = GBFactory.<CT> 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<BigInteger> 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<C>. 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<C>. 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<C>. 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}