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