001/* 002 * $Id: GBAlgorithmBuilder.java 4296 2012-11-11 18:09:53Z kredel $ 003 */ 004 005package edu.jas.application; 006 007 008import java.io.Serializable; 009 010import org.apache.log4j.Logger; 011 012import edu.jas.arith.BigInteger; 013import edu.jas.arith.BigRational; 014import edu.jas.gb.GBOptimized; 015import edu.jas.gb.GBProxy; 016import edu.jas.gb.GroebnerBaseAbstract; 017import edu.jas.gb.GroebnerBaseParallel; 018import edu.jas.gbufd.GBFactory; 019import edu.jas.gbufd.GroebnerBaseFGLM; 020import edu.jas.gbufd.GroebnerBasePseudoParallel; 021import edu.jas.gbufd.GroebnerBaseRational; 022import edu.jas.kern.ComputerThreads; 023import edu.jas.poly.GenPolynomialRing; 024import edu.jas.structure.GcdRingElem; 025import edu.jas.ufd.Quotient; 026import edu.jas.ufd.QuotientRing; 027 028 029/** 030 * Builder for commutative Gröbner bases algorithm implementations. 031 * @author Heinz Kredel 032 * @usage To create objects that implement the <code>GroebnerBase</code> 033 * interface one can use the <code>GBFactory</code> or this <code>GBAlgorithmBuilder</code>. 034 * This class will select and compose an 035 * appropriate implementation based on the types of polynomial 036 * coefficients C and the desired properties. To build an implementation start with 037 * the static method <code>polynomialRing()</code> to define the polynomial ring. 038 * Then continue to construct the algorithm with the methods 039 * <ul> 040 * <li><code>optimize()</code> or <code>optimize(boolean)</code> for term order (variable order) 041 * optimization, 042 * </li> 043 * <li><code>fractionFree()</code> for clearing denominators and computing with pseudo reduction, 044 * </li> 045 * <li><code>graded()</code> for using the FGLM algorithm to first compute with a graded term order and 046 * then constructing a lexicographical Gröbner base, 047 * </li> 048 * <li><code>parallel()</code> additionaly compute a Gröbner base over a field in parallel, 049 * </li> 050 * <li><code>euclideanDomain()</code> for computing a e-Gröbner base, 051 * </li> 052 * <li><code>domainAlgorithm(Algo)</code> for computing a d- or e-Gröbner base, 053 * </li> 054 * </ul> 055 * Finaly call the method <code>build()</code> to obtain an implementaton of 056 * class <code>GroebnerBaseAbstract</code>. For example 057 * 058 * <pre> 059 * 060 * GenPolynomialRing<C> pf = new GenPolynomialRing<C>(cofac, vars); 061 * GroebnerBaseAbstract<C> engine; 062 * engine = GBAlgorithmBuilder.<C> polynomialRing(pf).fractionFree().parallel().optimize().build(); 063 * c = engine.GB(A); 064 * </pre> 065 * 066 * For example, if the coefficient type is BigRational, the usage looks 067 * like 068 * 069 * <pre> 070 * 071 * GenPolynomialRing<BigRational> pf = new GenPolynomialRing<BigRational>(cofac, vars); 072 * GroebnerBaseAbstract<BigRational> engine; 073 * engine = GBAlgorithmBuilder.<BigRational> polynomialRing(pf).fractionFree().parallel().optimize().build(); 074 * c = engine.GB(A); 075 * </pre> 076 * 077 * <b>Note:</b> Not all combinations are meanigful 078 * 079 * @see edu.jas.gb.GroebnerBase 080 * @see edu.jas.gbufd.GBFactory 081 */ 082 083public class GBAlgorithmBuilder<C extends GcdRingElem<C>> implements Serializable { 084 085 086 private static final Logger logger = Logger.getLogger(GBAlgorithmBuilder.class); 087 088 089 /** 090 * The current GB algorithm implementation. 091 */ 092 private GroebnerBaseAbstract<C> algo; 093 094 095 /** 096 * The current polynomial ring. 097 */ 098 public final GenPolynomialRing<C> ring; 099 100 101 /** 102 * Constructor not for use. 103 */ 104 protected GBAlgorithmBuilder() { 105 throw new IllegalArgumentException("do not use this constructor"); 106 } 107 108 109 /** 110 * Constructor. 111 * @param ring the polynomial ring. 112 */ 113 public GBAlgorithmBuilder(GenPolynomialRing<C> ring) { 114 this(ring, null); 115 } 116 117 118 /** 119 * Constructor. 120 * @param ring the polynomial ring. 121 * @param algo already determined algorithm. 122 */ 123 public GBAlgorithmBuilder(GenPolynomialRing<C> ring, GroebnerBaseAbstract<C> algo) { 124 this.ring = ring; 125 this.algo = algo; 126 } 127 128 129 /** 130 * Build the GB algorithm implementaton. 131 * @return GB algorithm implementaton as GroebnerBaseAbstract object. 132 */ 133 public GroebnerBaseAbstract<C> build() { 134 if (algo == null) { 135 algo = GBFactory.<C> getImplementation(ring.coFac); 136 } 137 return algo; 138 } 139 140 141 /** 142 * Define polynomial ring. 143 * @param fac the commutative polynomial ring. 144 * @return GBAlgorithmBuilder object. 145 */ 146 public static <C extends GcdRingElem<C>> GBAlgorithmBuilder<C> polynomialRing(GenPolynomialRing<C> fac) { 147 return new GBAlgorithmBuilder<C>(fac); 148 } 149 150 151 /** 152 * Request term order optimization. 153 * Call optimize(true) for return of permuted polynomials. 154 * @return GBAlgorithmBuilder object. 155 */ 156 public GBAlgorithmBuilder<C> optimize() { 157 return optimize(true); 158 } 159 160 161 /** 162 * Request term order optimization. 163 * @param rP true for return of permuted polynomials, false for inverse 164 * permuted polynomials and new GB computation. 165 * @return GBAlgorithmBuilder object. 166 */ 167 public GBAlgorithmBuilder<C> optimize(boolean rP) { 168 if (algo == null) { 169 algo = GBFactory.<C> getImplementation(ring.coFac); 170 } 171 GroebnerBaseAbstract<C> bb = new GBOptimized<C>(algo, rP); 172 return new GBAlgorithmBuilder<C>(ring, bb); 173 } 174 175 176 /** 177 * Request fraction free algorithm. For BigRational and Quotient 178 * coefficients denominators are cleared and pseudo reduction is 179 * used. 180 * @return GBAlgorithmBuilder object. 181 */ 182 @SuppressWarnings("unchecked") 183 public GBAlgorithmBuilder<C> fractionFree() { 184 if (algo != null) { 185 logger.warn("selected algorithm ignored: " + algo + ", use fractionFree before"); 186 } 187 if (((Object)ring.coFac) instanceof BigRational) { 188 BigRational cf = (BigRational) (Object) ring.coFac; 189 GroebnerBaseAbstract<BigRational> bb = GBFactory.getImplementation(cf, GBFactory.Algo.ffgb); 190 GroebnerBaseAbstract<C> cbb = (GroebnerBaseAbstract<C>) (GroebnerBaseAbstract) bb; 191 return new GBAlgorithmBuilder<C>(ring, cbb); 192 } 193 if (((Object)ring.coFac) instanceof QuotientRing) { 194 QuotientRing<C> cf = (QuotientRing<C>) (Object) ring.coFac; 195 GroebnerBaseAbstract<Quotient<C>> bb = GBFactory.<C> getImplementation(cf, GBFactory.Algo.ffgb); 196 GroebnerBaseAbstract<C> cbb = (GroebnerBaseAbstract<C>) (GroebnerBaseAbstract) bb; 197 return new GBAlgorithmBuilder<C>(ring, cbb); 198 } 199 logger.warn("no fraction free algorithm implemented for " + ring); 200 return this; 201 } 202 203 204 /** 205 * Request e-GB algorithm. 206 * @return GBAlgorithmBuilder object. 207 */ 208 public GBAlgorithmBuilder<C> euclideanDomain() { 209 return domainAlgorithm(GBFactory.Algo.egb); 210 } 211 212 213 /** 214 * Request d- or e-GB algorithm. 215 * @param a algorithm from GBFactory.Algo. 216 * @return GBAlgorithmBuilder object. 217 */ 218 @SuppressWarnings("unchecked") 219 public GBAlgorithmBuilder<C> domainAlgorithm(GBFactory.Algo a) { 220 if (((Object)ring.coFac) instanceof BigInteger) { 221 BigInteger cf = (BigInteger) (Object) ring.coFac; 222 GroebnerBaseAbstract<BigInteger> bb = GBFactory.getImplementation(cf, a); 223 GroebnerBaseAbstract<C> cbb = (GroebnerBaseAbstract<C>) (GroebnerBaseAbstract) bb; 224 return new GBAlgorithmBuilder<C>(ring, cbb); 225 } 226 logger.warn("no domain algorithm implemented for " + ring); 227 return this; 228 } 229 230 231 /** 232 * Request parallel algorithm. 233 * Additionaly run a parallel algorithm via GBProxy. 234 * @return GBAlgorithmBuilder object. 235 */ 236 @SuppressWarnings("unchecked") 237 public GBAlgorithmBuilder<C> parallel() { 238 return parallel(ComputerThreads.N_CPUS); 239 } 240 241 242 /** 243 * Request parallel algorithm. 244 * Additionaly run a parallel algorithm via GBProxy. 245 * @param threads number of threads requested. 246 * @return GBAlgorithmBuilder object. 247 */ 248 @SuppressWarnings("unchecked") 249 public GBAlgorithmBuilder<C> parallel(int threads) { 250 if (ComputerThreads.NO_THREADS) { 251 logger.warn("parallel algorithms disabled"); 252 return this; 253 } 254 if (algo == null) { 255 algo = GBFactory.<C> getImplementation(ring.coFac); 256 } 257 if (ring.coFac instanceof BigRational) { 258 GroebnerBaseAbstract<C> bb; 259 if (algo instanceof GroebnerBaseRational) { // fraction free requested 260 bb = (GroebnerBaseAbstract) new GroebnerBaseRational<BigRational>(threads); 261 } else { 262 bb = (GroebnerBaseAbstract) new GroebnerBaseParallel<C>(threads); 263 } 264 GroebnerBaseAbstract<C> pbb = new GBProxy<C>(algo, bb); 265 return new GBAlgorithmBuilder<C>(ring, pbb); 266 } else if (ring.coFac.isField()) { 267 GroebnerBaseAbstract<C> bb = new GroebnerBaseParallel<C>(threads); 268 GroebnerBaseAbstract<C> pbb = new GBProxy<C>(algo, bb); 269 return new GBAlgorithmBuilder<C>(ring, pbb); 270 } else if (ring.coFac.getONE() instanceof GcdRingElem) { 271 GroebnerBaseAbstract<C> bb = new GroebnerBasePseudoParallel<C>(threads,ring.coFac); 272 GroebnerBaseAbstract<C> pbb = new GBProxy<C>(algo, bb); 273 return new GBAlgorithmBuilder<C>(ring, pbb); 274 } 275 logger.warn("no parallel algorithm implemented for " + ring); 276 return this; 277 } 278 279 280 /** 281 * Request FGLM algorithm. 282 * @return GBAlgorithmBuilder object. 283 */ 284 @SuppressWarnings("unchecked") 285 public GBAlgorithmBuilder<C> graded() { 286 if (ring.coFac.isField()) { 287 GroebnerBaseAbstract<C> bb; 288 if (algo == null) { 289 bb = new GroebnerBaseFGLM<C>(); 290 } else { 291 bb = new GroebnerBaseFGLM<C>(algo); 292 } 293 return new GBAlgorithmBuilder<C>(ring, bb); 294 } 295 logger.warn("no FGLM algorithm implemented for " + ring); 296 return this; 297 } 298 299 300 /** 301 * String representation of the GB algorithm implementation. 302 * @see java.lang.Object#toString() 303 */ 304 @Override 305 public String toString() { 306 StringBuffer s = new StringBuffer(" "); 307 if ( algo != null ) { 308 s.append(algo.toString()); 309 s.append(" for "); 310 } 311 s.append(ring.toString()); 312 return s.toString(); 313 } 314 315 316 /** 317 * Get a scripting compatible string representation. 318 * @return script compatible representation for this Element. 319 * @see edu.jas.structure.Element#toScript() 320 */ 321 public String toScript() { 322 // Python case 323 StringBuffer s = new StringBuffer(" "); 324 if ( algo != null ) { 325 s.append(algo.toString()); // nonsense 326 s.append(" "); 327 } 328 s.append(ring.toScript()); 329 return s.toString(); 330 } 331 332}