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