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