001/* 002 * $Id: GBFactory.java 6010 2020-04-01 10:39:15Z kredel $ 003 */ 004 005package edu.jas.gbufd; 006 007 008import org.apache.logging.log4j.LogManager; 009import org.apache.logging.log4j.Logger; 010 011import edu.jas.arith.BigInteger; 012import edu.jas.arith.BigRational; 013import edu.jas.arith.ModInt; 014import edu.jas.arith.ModIntRing; 015import edu.jas.arith.ModInteger; 016import edu.jas.arith.ModIntegerRing; 017import edu.jas.arith.ModLong; 018import edu.jas.arith.ModLongRing; 019import edu.jas.arith.Product; 020import edu.jas.arith.ProductRing; 021import edu.jas.gb.DGroebnerBaseSeq; 022import edu.jas.gb.EGroebnerBaseSeq; 023import edu.jas.gb.GBProxy; 024import edu.jas.gb.GroebnerBaseAbstract; 025import edu.jas.gb.GroebnerBaseParallel; 026import edu.jas.gb.GroebnerBaseSeq; 027import edu.jas.gb.OrderedMinPairlist; 028import edu.jas.gb.OrderedPairlist; 029import edu.jas.gb.OrderedSyzPairlist; 030import edu.jas.gb.PairList; 031import edu.jas.gb.ReductionSeq; 032import edu.jas.kern.ComputerThreads; 033import edu.jas.poly.GenPolynomial; 034import edu.jas.poly.GenPolynomialRing; 035import edu.jas.structure.GcdRingElem; 036import edu.jas.structure.RingElem; 037import edu.jas.structure.RingFactory; 038import edu.jas.ufd.Quotient; 039import edu.jas.ufd.QuotientRing; 040 041 042/** 043 * Groebner bases algorithms factory. Select appropriate Groebner bases engine 044 * based on the coefficient types. 045 * <p> 046 * <b>Usage:</b> To create objects that implement the <code>GroebnerBase</code> 047 * interface use the <code>GBFactory</code>. It will select an appropriate 048 * implementation based on the types of polynomial coefficients C. The method to 049 * obtain an implementation is <code>getImplementation()</code>. 050 * <code>getImplementation()</code> returns an object of a class which 051 * implements the <code>GroebnerBase</code> interface, more precisely an object 052 * of abstract class <code>GroebnerBaseAbstract</code>. 053 * 054 * <pre> 055 * GroebnerBase<CT> engine; 056 * engine = GBFactory.<CT> getImplementation(cofac); 057 * c = engine.GB(A); 058 * </pre> 059 * <p> 060 * For example, if the coefficient type is BigInteger, the usage looks like 061 * 062 * <pre> 063 * BigInteger cofac = new BigInteger(); 064 * GroebnerBase<BigInteger> engine; 065 * engine = GBFactory.getImplementation(cofac); 066 * c = engine.GB(A); 067 * </pre> 068 * 069 * @author Heinz Kredel 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 ModInt. 137 * @param fac ModIntRing. 138 * @return GB algorithm implementation. 139 */ 140 public static GroebnerBaseAbstract<ModInt> getImplementation(ModIntRing fac) { 141 return getImplementation(fac, new OrderedPairlist<ModInt>()); 142 } 143 144 145 /** 146 * Determine suitable implementation of GB algorithms, case ModInt. 147 * @param fac ModIntRing. 148 * @param pl pair selection strategy 149 * @return GB algorithm implementation. 150 */ 151 public static GroebnerBaseAbstract<ModInt> getImplementation(ModIntRing fac, PairList<ModInt> pl) { 152 GroebnerBaseAbstract<ModInt> bba; 153 if (fac.isField()) { 154 bba = new GroebnerBaseSeq<ModInt>(pl); 155 } else { 156 bba = new GroebnerBasePseudoSeq<ModInt>(fac, pl); 157 } 158 return bba; 159 } 160 161 162 /** 163 * Determine suitable implementation of GB algorithms, case ModInteger. 164 * @param fac ModIntegerRing. 165 * @return GB algorithm implementation. 166 */ 167 public static GroebnerBaseAbstract<ModInteger> getImplementation(ModIntegerRing fac) { 168 return getImplementation(fac, new OrderedPairlist<ModInteger>()); 169 } 170 171 172 /** 173 * Determine suitable implementation of GB algorithms, case ModInteger. 174 * @param fac ModIntegerRing. 175 * @param pl pair selection strategy 176 * @return GB algorithm implementation. 177 */ 178 public static GroebnerBaseAbstract<ModInteger> getImplementation(ModIntegerRing fac, 179 PairList<ModInteger> pl) { 180 GroebnerBaseAbstract<ModInteger> bba; 181 if (fac.isField()) { 182 bba = new GroebnerBaseSeq<ModInteger>(pl); 183 } else { 184 bba = new GroebnerBasePseudoSeq<ModInteger>(fac, pl); 185 } 186 return bba; 187 } 188 189 190 /** 191 * Determine suitable implementation of GB algorithms, case BigInteger. 192 * @param fac BigInteger. 193 * @return GB algorithm implementation. 194 */ 195 public static GroebnerBaseAbstract<BigInteger> getImplementation(BigInteger fac) { 196 return getImplementation(fac, Algo.igb); 197 } 198 199 200 /** 201 * Determine suitable implementation of GB algorithms, case BigInteger. 202 * @param fac BigInteger. 203 * @param a algorithm, a = igb, egb, dgb. 204 * @return GB algorithm implementation. 205 */ 206 public static GroebnerBaseAbstract<BigInteger> getImplementation(BigInteger fac, Algo a) { 207 return getImplementation(fac, a, new OrderedPairlist<BigInteger>()); 208 } 209 210 211 /** 212 * Determine suitable implementation of GB algorithms, case BigInteger. 213 * @param fac BigInteger. 214 * @param pl pair selection strategy 215 * @return GB algorithm implementation. 216 */ 217 public static GroebnerBaseAbstract<BigInteger> getImplementation(BigInteger fac, 218 PairList<BigInteger> pl) { 219 return getImplementation(fac, Algo.igb, pl); 220 } 221 222 223 /** 224 * Determine suitable implementation of GB algorithms, case BigInteger. 225 * @param fac BigInteger. 226 * @param a algorithm, a = igb, egb, dgb. 227 * @param pl pair selection strategy 228 * @return GB algorithm implementation. 229 */ 230 public static GroebnerBaseAbstract<BigInteger> getImplementation(BigInteger fac, Algo a, 231 PairList<BigInteger> pl) { 232 GroebnerBaseAbstract<BigInteger> bba; 233 switch (a) { 234 case igb: 235 bba = new GroebnerBasePseudoSeq<BigInteger>(fac, pl); 236 break; 237 case egb: 238 bba = new EGroebnerBaseSeq<BigInteger>(); // pl not suitable 239 break; 240 case dgb: 241 bba = new DGroebnerBaseSeq<BigInteger>(); // pl not suitable 242 break; 243 default: 244 throw new IllegalArgumentException("algorithm not available for BigInteger " + a); 245 } 246 return bba; 247 } 248 249 250 /** 251 * Determine suitable implementation of GB algorithms, case BigRational. 252 * @param fac BigRational. 253 * @return GB algorithm implementation. 254 */ 255 public static GroebnerBaseAbstract<BigRational> getImplementation(BigRational fac) { 256 return getImplementation(fac, Algo.qgb); 257 } 258 259 260 /** 261 * Determine suitable implementation of GB algorithms, case BigRational. 262 * @param fac BigRational. 263 * @param a algorithm, a = qgb, ffgb. 264 * @return GB algorithm implementation. 265 */ 266 public static GroebnerBaseAbstract<BigRational> getImplementation(BigRational fac, Algo a) { 267 return getImplementation(fac, a, new OrderedPairlist<BigRational>()); 268 } 269 270 271 /** 272 * Determine suitable implementation of GB algorithms, case BigRational. 273 * @param fac BigRational. 274 * @param pl pair selection strategy 275 * @return GB algorithm implementation. 276 */ 277 public static GroebnerBaseAbstract<BigRational> getImplementation(BigRational fac, 278 PairList<BigRational> pl) { 279 return getImplementation(fac, Algo.qgb, pl); 280 } 281 282 283 /** 284 * Determine suitable implementation of GB algorithms, case BigRational. 285 * @param fac BigRational. 286 * @param a algorithm, a = qgb, ffgb. 287 * @param pl pair selection strategy 288 * @return GB algorithm implementation. 289 */ 290 public static GroebnerBaseAbstract<BigRational> getImplementation(BigRational fac, Algo a, 291 PairList<BigRational> pl) { 292 GroebnerBaseAbstract<BigRational> bba; 293 switch (a) { 294 case qgb: 295 bba = new GroebnerBaseSeq<BigRational>(pl); 296 break; 297 case ffgb: 298 PairList<BigInteger> pli; 299 if (pl instanceof OrderedMinPairlist) { 300 pli = new OrderedMinPairlist<BigInteger>(); 301 } else if (pl instanceof OrderedSyzPairlist) { 302 pli = new OrderedSyzPairlist<BigInteger>(); 303 } else { 304 pli = new OrderedPairlist<BigInteger>(); 305 } 306 bba = new GroebnerBaseRational<BigRational>(pli); // pl not possible 307 break; 308 default: 309 throw new IllegalArgumentException( 310 "algorithm not available for " + fac.toScriptFactory() + ", Algo = " + a); 311 } 312 return bba; 313 } 314 315 316 /** 317 * Determine suitable implementation of GB algorithms, case Quotient 318 * coefficients. 319 * @param fac QuotientRing. 320 * @return GB algorithm implementation. 321 */ 322 public static <C extends GcdRingElem<C>> GroebnerBaseAbstract<Quotient<C>> getImplementation( 323 QuotientRing<C> fac) { 324 return getImplementation(fac, Algo.qgb); 325 } 326 327 328 /** 329 * Determine suitable implementation of GB algorithms, case Quotient 330 * coefficients. 331 * @param fac QuotientRing. 332 * @param a algorithm, a = qgb, ffgb. 333 * @return GB algorithm implementation. 334 */ 335 public static <C extends GcdRingElem<C>> GroebnerBaseAbstract<Quotient<C>> getImplementation( 336 QuotientRing<C> fac, Algo a) { 337 return getImplementation(fac, a, new OrderedPairlist<Quotient<C>>()); 338 } 339 340 341 /** 342 * Determine suitable implementation of GB algorithms, case Quotient 343 * coefficients. 344 * @param fac QuotientRing. 345 * @param pl pair selection strategy 346 * @return GB algorithm implementation. 347 */ 348 public static <C extends GcdRingElem<C>> GroebnerBaseAbstract<Quotient<C>> getImplementation( 349 QuotientRing<C> fac, PairList<Quotient<C>> pl) { 350 return getImplementation(fac, Algo.qgb, pl); 351 } 352 353 354 /** 355 * Determine suitable implementation of GB algorithms, case Quotient 356 * coefficients. 357 * @param fac QuotientRing. 358 * @param a algorithm, a = qgb, ffgb. 359 * @param pl pair selection strategy 360 * @return GB algorithm implementation. 361 */ 362 public static <C extends GcdRingElem<C>> GroebnerBaseAbstract<Quotient<C>> getImplementation( 363 QuotientRing<C> fac, Algo a, PairList<Quotient<C>> pl) { 364 GroebnerBaseAbstract<Quotient<C>> bba; 365 switch (a) { 366 case qgb: 367 bba = new GroebnerBaseSeq<Quotient<C>>(new ReductionSeq<Quotient<C>>(), pl); 368 break; 369 case ffgb: 370 PairList<GenPolynomial<C>> pli; 371 if (pl instanceof OrderedMinPairlist) { 372 pli = new OrderedMinPairlist<GenPolynomial<C>>(); 373 } else if (pl instanceof OrderedSyzPairlist) { 374 pli = new OrderedSyzPairlist<GenPolynomial<C>>(); 375 } else { 376 pli = new OrderedPairlist<GenPolynomial<C>>(); 377 } 378 bba = new GroebnerBaseQuotient<C>(fac, pli); // pl not possible 379 break; 380 default: 381 throw new IllegalArgumentException("algorithm not available for Quotient " + a); 382 } 383 return bba; 384 } 385 386 387 /** 388 * Determine suitable implementation of GB algorithms, case (recursive) 389 * polynomial. 390 * @param fac GenPolynomialRing<C>. 391 * @return GB algorithm implementation. 392 */ 393 public static <C extends GcdRingElem<C>> GroebnerBaseAbstract<GenPolynomial<C>> getImplementation( 394 GenPolynomialRing<C> fac) { 395 return getImplementation(fac, Algo.igb); 396 } 397 398 399 /** 400 * Determine suitable implementation of GB algorithms, case (recursive) 401 * polynomial. 402 * @param fac GenPolynomialRing<C>. 403 * @param a algorithm, a = igb or egb, dgb if fac is univariate over a 404 * field. 405 * @return GB algorithm implementation. 406 */ 407 public static <C extends GcdRingElem<C>> GroebnerBaseAbstract<GenPolynomial<C>> getImplementation( 408 GenPolynomialRing<C> fac, Algo a) { 409 return getImplementation(fac, a, new OrderedPairlist<GenPolynomial<C>>()); 410 } 411 412 413 /** 414 * Determine suitable implementation of GB algorithms, case (recursive) 415 * polynomial. 416 * @param fac GenPolynomialRing<C>. 417 * @param pl pair selection strategy 418 * @return GB algorithm implementation. 419 */ 420 public static <C extends GcdRingElem<C>> GroebnerBaseAbstract<GenPolynomial<C>> getImplementation( 421 GenPolynomialRing<C> fac, PairList<GenPolynomial<C>> pl) { 422 return getImplementation(fac, Algo.igb, pl); 423 } 424 425 426 /** 427 * Determine suitable implementation of GB algorithms, case (recursive) 428 * polynomial. 429 * @param fac GenPolynomialRing<C>. 430 * @param a algorithm, a = igb or egb, dgb if fac is univariate over a 431 * field. 432 * @param pl pair selection strategy 433 * @return GB algorithm implementation. 434 */ 435 public static <C extends GcdRingElem<C>> GroebnerBaseAbstract<GenPolynomial<C>> getImplementation( 436 GenPolynomialRing<C> fac, Algo a, PairList<GenPolynomial<C>> pl) { 437 GroebnerBaseAbstract<GenPolynomial<C>> bba; 438 switch (a) { 439 case igb: 440 bba = new GroebnerBasePseudoRecSeq<C>(fac, pl); 441 break; 442 case egb: 443 if (fac.nvar > 1 || !fac.coFac.isField()) { 444 throw new IllegalArgumentException("coefficients not univariate or not over a field" + fac); 445 } 446 bba = new EGroebnerBaseSeq<GenPolynomial<C>>(); // pl not suitable 447 break; 448 case dgb: 449 if (fac.nvar > 1 || !fac.coFac.isField()) { 450 throw new IllegalArgumentException("coefficients not univariate or not over a field" + fac); 451 } 452 bba = new DGroebnerBaseSeq<GenPolynomial<C>>(); // pl not suitable 453 break; 454 default: 455 throw new IllegalArgumentException("algorithm not available for GenPolynomial<C> " + a); 456 } 457 return bba; 458 } 459 460 461 /** 462 * Determine suitable implementation of GB algorithms, case regular rings. 463 * @param fac RegularRing. 464 * @return GB algorithm implementation. 465 */ 466 public static <C extends RingElem<C>> GroebnerBaseAbstract<Product<C>> getImplementation( 467 ProductRing<C> fac) { 468 GroebnerBaseAbstract<Product<C>> bba; 469 if (fac.onlyFields()) { 470 bba = new RGroebnerBaseSeq<Product<C>>(); 471 } else { 472 bba = new RGroebnerBasePseudoSeq<Product<C>>(fac); 473 } 474 return bba; 475 } 476 477 478 /** 479 * Determine suitable implementation of GB algorithms, other cases. 480 * @param fac RingFactory<C>. 481 * @return GB algorithm implementation. 482 */ 483 public static <C extends GcdRingElem<C>> // interface RingElem not sufficient 484 GroebnerBaseAbstract<C> getImplementation(RingFactory<C> fac) { 485 return getImplementation(fac, new OrderedPairlist<C>()); 486 } 487 488 489 /** 490 * Determine suitable implementation of GB algorithms, other cases. 491 * @param fac RingFactory<C>. 492 * @param pl pair selection strategy 493 * @return GB algorithm implementation. 494 */ 495 @SuppressWarnings("unchecked") 496 public static <C extends GcdRingElem<C>> // interface RingElem not sufficient 497 GroebnerBaseAbstract<C> getImplementation(RingFactory<C> fac, PairList<C> pl) { 498 logger.debug("fac = " + fac.getClass().getName()); 499 if (fac.isField()) { 500 return new GroebnerBaseSeq<C>(pl); 501 } 502 GroebnerBaseAbstract bba = null; 503 Object ofac = fac; 504 if (ofac instanceof GenPolynomialRing) { 505 PairList<GenPolynomial<C>> pli; 506 if (pl instanceof OrderedMinPairlist) { 507 pli = new OrderedMinPairlist<GenPolynomial<C>>(); 508 } else if (pl instanceof OrderedSyzPairlist) { 509 pli = new OrderedSyzPairlist<GenPolynomial<C>>(); 510 } else { 511 pli = new OrderedPairlist<GenPolynomial<C>>(); 512 } 513 GenPolynomialRing<C> rofac = (GenPolynomialRing<C>) ofac; 514 GroebnerBaseAbstract<GenPolynomial<C>> bbr = new GroebnerBasePseudoRecSeq<C>(rofac, pli); // not pl 515 bba = (GroebnerBaseAbstract) bbr; 516 } else if (ofac instanceof ProductRing) { 517 ProductRing pfac = (ProductRing) ofac; 518 if (pfac.onlyFields()) { 519 bba = new RGroebnerBaseSeq<Product<C>>(); 520 } else { 521 bba = new RGroebnerBasePseudoSeq<Product<C>>(pfac); 522 } 523 } else { 524 bba = new GroebnerBasePseudoSeq<C>(fac, pl); 525 } 526 logger.debug("bba = " + bba.getClass().getName()); 527 return bba; 528 } 529 530 531 /** 532 * Determine suitable parallel/concurrent implementation of GB algorithms if 533 * possible. 534 * @param fac RingFactory<C>. 535 * @return GB proxy algorithm implementation. 536 */ 537 public static <C extends GcdRingElem<C>> // interface RingElem not sufficient 538 GroebnerBaseAbstract<C> getProxy(RingFactory<C> fac) { 539 return getProxy(fac, new OrderedPairlist<C>()); 540 } 541 542 543 /** 544 * Determine suitable parallel/concurrent implementation of GB algorithms if 545 * possible. 546 * @param fac RingFactory<C>. 547 * @param pl pair selection strategy 548 * @return GB proxy algorithm implementation. 549 */ 550 @SuppressWarnings("unchecked") 551 public static <C extends GcdRingElem<C>> // interface RingElem not sufficient 552 GroebnerBaseAbstract<C> getProxy(RingFactory<C> fac, PairList<C> pl) { 553 if (ComputerThreads.NO_THREADS) { 554 return GBFactory.<C> getImplementation(fac, pl); 555 } 556 logger.debug("fac = " + fac.getClass().getName()); 557 int th = (ComputerThreads.N_CPUS > 2 ? ComputerThreads.N_CPUS - 1 : 2); 558 if (fac.isField()) { 559 GroebnerBaseAbstract<C> e1 = new GroebnerBaseSeq<C>(pl); 560 GroebnerBaseAbstract<C> e2 = new GroebnerBaseParallel<C>(th, pl); 561 return new GBProxy<C>(e1, e2); 562 } else if (fac.characteristic().signum() == 0) { 563 if (fac instanceof GenPolynomialRing) { 564 GenPolynomialRing pfac = (GenPolynomialRing) fac; 565 OrderedPairlist ppl = new OrderedPairlist<GenPolynomial<C>>(); 566 GroebnerBaseAbstract e1 = new GroebnerBasePseudoRecSeq<C>(pfac, ppl); 567 GroebnerBaseAbstract e2 = new GroebnerBasePseudoRecParallel<C>(th, pfac, ppl); 568 return new GBProxy<C>(e1, e2); 569 } 570 GroebnerBaseAbstract<C> e1 = new GroebnerBasePseudoSeq<C>(fac, pl); 571 GroebnerBaseAbstract<C> e2 = new GroebnerBasePseudoParallel<C>(th, fac, pl); 572 return new GBProxy<C>(e1, e2); 573 } 574 return getImplementation(fac, pl); 575 } 576 577 578 /** 579 * Determine suitable parallel/concurrent implementation of GB algorithms if 580 * possible. 581 * @param fac RingFactory<C>. 582 * @return GB proxy algorithm implementation. 583 */ 584 @SuppressWarnings("unchecked") 585 public static <C extends GcdRingElem<C>> // interface RingElem not sufficient 586 GroebnerBaseAbstract<GenPolynomial<C>> getProxy(GenPolynomialRing<C> fac) { 587 if (ComputerThreads.NO_THREADS) { 588 //return GBFactory.<GenPolynomial<C>> getImplementation(fac); 589 return GBFactory.getImplementation(fac); 590 } 591 logger.debug("fac = " + fac.getClass().getName()); 592 int th = (ComputerThreads.N_CPUS > 2 ? ComputerThreads.N_CPUS - 1 : 2); 593 OrderedPairlist<GenPolynomial<C>> ppl = new OrderedPairlist<GenPolynomial<C>>(); 594 GroebnerBaseAbstract<GenPolynomial<C>> e1 = new GroebnerBasePseudoRecSeq<C>(fac, ppl); 595 GroebnerBaseAbstract<GenPolynomial<C>> e2 = new GroebnerBasePseudoRecParallel<C>(th, fac, ppl); 596 //return new GBProxy<GenPolynomial<C>>(e1, e2); 597 return new GBProxy(e1, e2); 598 } 599 600}