001/* 002 * $Id$ 003 */ 004 005package edu.jas.application; 006 007 008import java.io.Reader; 009import java.util.ArrayList; 010import java.util.List; 011import java.util.Random; 012 013import org.apache.logging.log4j.Logger; 014import org.apache.logging.log4j.LogManager; 015 016import edu.jas.gb.SolvableGroebnerBaseAbstract; 017import edu.jas.gbufd.SGBFactory; 018import edu.jas.gbufd.SolvableSyzygyAbstract; 019import edu.jas.gbufd.SolvableSyzygySeq; 020import edu.jas.kern.StringUtil; 021import edu.jas.poly.GenPolynomial; 022import edu.jas.poly.GenSolvablePolynomial; 023import edu.jas.poly.GenSolvablePolynomialRing; 024import edu.jas.poly.PolynomialList; 025import edu.jas.structure.GcdRingElem; 026import edu.jas.structure.QuotPairFactory; 027import edu.jas.structure.RingFactory; 028import edu.jas.fd.GreatestCommonDivisorAbstract; 029import edu.jas.fd.SGCDFactory; 030 031/** 032 * SolvableLocal ring factory for SolvableLocal with GcdRingElem interface. 033 * Objects of this class are immutable. 034 * @author Heinz Kredel 035 */ 036public class SolvableLocalRing<C extends GcdRingElem<C>> implements RingFactory<SolvableLocal<C>>, 037 QuotPairFactory<GenPolynomial<C>, SolvableLocal<C>> { 038 039 040 // Can not extend SolvableQuotientRing 041 // because of different constructor semantics. 042 043 044 private static final Logger logger = LogManager.getLogger(SolvableLocalRing.class); 045 046 047 private static final boolean debug = logger.isDebugEnabled(); 048 049 050 /** 051 * Solvable polynomial ideal for localization. 052 */ 053 public final SolvableIdeal<C> ideal; 054 055 056 /** 057 * Solvable polynomial ring of the factory. 058 */ 059 public final GenSolvablePolynomialRing<C> ring; 060 061 062 /** 063 * Syzygy engine of the factory. 064 */ 065 public final SolvableSyzygyAbstract<C> engine; 066 067 068 /** 069 * FD engine of the factory. 070 */ 071 public final GreatestCommonDivisorAbstract<C> fdengine; 072 073 074 /** 075 * Groebner base engine. 076 */ 077 protected final SolvableGroebnerBaseAbstract<C> bb; 078 079 080 /** 081 * Indicator if this ring is a field. 082 */ 083 protected int isField = -1; // initially unknown 084 085 086 /** 087 * The constructor creates a SolvableLocalRing object from a SolvableIdeal. 088 * @param i solvable localization polynomial ideal. 089 */ 090 public SolvableLocalRing(SolvableIdeal<C> i) { 091 if (i == null) { 092 throw new IllegalArgumentException("ideal may not be null"); 093 } 094 ring = i.getRing(); 095 ideal = i.GB(); // cheap if isGB 096 if (ideal.isONE()) { 097 throw new IllegalArgumentException("ideal may not be 1"); 098 } 099 if (ideal.isMaximal()) { 100 isField = 1; 101 } else { 102 isField = 0; 103 logger.warn("ideal not maximal"); 104 //throw new IllegalArgumentException("ideal must be maximal"); 105 } 106 engine = new SolvableSyzygySeq<C>(ring.coFac); 107 //fdengine = SGCDFactory.<C> getImplementation(ring.coFac); 108 fdengine = SGCDFactory.<C> getFakeImplementation(ring.coFac); 109 bb = SGBFactory.getImplementation(ring.coFac); // new SolvableGroebnerBaseSeq<C>(); 110 logger.debug("solvable local ring constructed"); 111 } 112 113 114 /** 115 * Factory for base elements. 116 */ 117 public GenSolvablePolynomialRing<C> pairFactory() { 118 return ring; 119 } 120 121 122 /** 123 * Create from numerator. 124 */ 125 @SuppressWarnings("unchecked") 126 public SolvableLocal<C> create(GenPolynomial<C> n) { 127 return new SolvableLocal<C>(this, (GenSolvablePolynomial<C>) n); 128 } 129 130 131 /** 132 * Create from numerator, denominator pair. 133 */ 134 @SuppressWarnings("unchecked") 135 public SolvableLocal<C> create(GenPolynomial<C> n, GenPolynomial<C> d) { 136 return new SolvableLocal<C>(this, (GenSolvablePolynomial<C>) n, (GenSolvablePolynomial<C>) d); 137 } 138 139 140 /** 141 * Is this structure finite or infinite. 142 * @return true if this structure is finite, else false. 143 */ 144 public boolean isFinite() { 145 return ring.isFinite() && bb.commonZeroTest(ideal.getList()) <= 0; 146 } 147 148 149 /** 150 * Copy SolvableLocal element c. 151 * @param c element to copy 152 * @return a copy of c. 153 */ 154 public SolvableLocal<C> copy(SolvableLocal<C> c) { 155 return new SolvableLocal<C>(c.ring, c.num, c.den, true); 156 } 157 158 159 /** 160 * Get the zero element. 161 * @return 0 as SolvableLocal. 162 */ 163 public SolvableLocal<C> getZERO() { 164 return new SolvableLocal<C>(this, ring.getZERO()); 165 } 166 167 168 /** 169 * Get the one element. 170 * @return 1 as SolvableLocal. 171 */ 172 public SolvableLocal<C> getONE() { 173 return new SolvableLocal<C>(this, ring.getONE()); 174 } 175 176 177 /** 178 * Get a list of the generating elements. 179 * @return list of generators for the algebraic structure. 180 */ 181 public List<SolvableLocal<C>> generators() { 182 List<GenSolvablePolynomial<C>> pgens = PolynomialList.<C> castToSolvableList(ring.generators()); 183 List<SolvableLocal<C>> gens = new ArrayList<SolvableLocal<C>>(pgens.size() * 2 - 1); 184 GenSolvablePolynomial<C> one = ring.getONE(); 185 for (GenSolvablePolynomial<C> p : pgens) { 186 SolvableLocal<C> q = new SolvableLocal<C>(this, p); 187 gens.add(q); 188 if (!p.isONE() && !ideal.contains(p)) { // q.isUnit() 189 q = new SolvableLocal<C>(this, one, p); 190 gens.add(q); 191 } 192 } 193 return gens; 194 } 195 196 197 /** 198 * Query if this ring is commutative. 199 * @return true if this ring is commutative, else false. 200 */ 201 public boolean isCommutative() { 202 return ring.isCommutative(); 203 } 204 205 206 /** 207 * Query if this ring is associative. 208 * @return true if this ring is associative, else false. 209 */ 210 @SuppressWarnings("unused") 211 public boolean isAssociative() { 212 if (!ring.isAssociative()) { 213 return false; 214 } 215 SolvableLocal<C> Xi, Xj, Xk, p, q; 216 List<SolvableLocal<C>> gens = generators(); 217 int ngen = gens.size(); 218 for (int i = 0; i < ngen; i++) { 219 Xi = gens.get(i); 220 for (int j = i + 1; j < ngen; j++) { 221 Xj = gens.get(j); 222 for (int k = j + 1; k < ngen; k++) { 223 Xk = gens.get(k); 224 try { 225 p = Xk.multiply(Xj).multiply(Xi); 226 q = Xk.multiply(Xj.multiply(Xi)); 227 } catch (IllegalArgumentException e) { 228 //e.printStackTrace(); 229 continue; // ignore undefined multiplication 230 } 231 if (!p.equals(q)) { 232 logger.info("Xk = {}, Xj = {}, Xi = {}", Xk, Xj, Xi); 233 logger.info("p = ( Xk * Xj ) * Xi = {}", p); 234 logger.info("q = Xk * ( Xj * Xi ) = {}", q); 235 return false; 236 } 237 } 238 } 239 } 240 return true; 241 } 242 243 244 /** 245 * Query if this ring is a field. 246 * @return false. 247 */ 248 public boolean isField() { 249 if (isField > 0) { 250 return true; 251 } 252 if (isField == 0) { 253 return false; 254 } 255 // not reached 256 return false; 257 } 258 259 260 /** 261 * Characteristic of this ring. 262 * @return characteristic of this ring. 263 */ 264 public java.math.BigInteger characteristic() { 265 return ring.characteristic(); 266 } 267 268 269 /** 270 * Get a SolvableLocal element from a BigInteger value. 271 * @param a BigInteger. 272 * @return a SolvableLocal. 273 */ 274 public SolvableLocal<C> fromInteger(java.math.BigInteger a) { 275 return new SolvableLocal<C>(this, ring.fromInteger(a)); 276 } 277 278 279 /** 280 * Get a SolvableLocal element from a long value. 281 * @param a long. 282 * @return a SolvableLocal. 283 */ 284 public SolvableLocal<C> fromInteger(long a) { 285 return new SolvableLocal<C>(this, ring.fromInteger(a)); 286 } 287 288 289 /** 290 * Get the String representation as RingFactory. 291 */ 292 @Override 293 public String toString() { 294 return "SolvableLocalRing[ " + ideal.toString() + " ]"; 295 } 296 297 298 /** 299 * Get a scripting compatible string representation. 300 * @return script compatible representation for this ElemFactory. 301 */ 302 @Override 303 public String toScript() { 304 // Python case 305 return "SLC(" + ideal.list.toScript() + ")"; 306 } 307 308 309 /** 310 * Comparison with any other object. 311 */ 312 @Override 313 @SuppressWarnings("unchecked") 314 public boolean equals(Object b) { 315 if (!(b instanceof SolvableLocalRing)) { 316 return false; 317 } 318 SolvableLocalRing<C> a = null; 319 try { 320 a = (SolvableLocalRing<C>) b; 321 } catch (ClassCastException e) { 322 } 323 if (a == null) { 324 return false; 325 } 326 if (!ring.equals(a.ring)) { 327 return false; 328 } 329 return ideal.equals(a.ideal); 330 } 331 332 333 /** 334 * Hash code for this local ring. 335 */ 336 @Override 337 public int hashCode() { 338 int h; 339 h = ideal.hashCode(); 340 return h; 341 } 342 343 344 /** 345 * SolvableLocal random. 346 * @param n such that 0 ≤ v ≤ (2<sup>n</sup>-1). 347 * @return a random residue element. 348 */ 349 public SolvableLocal<C> random(int n) { 350 GenSolvablePolynomial<C> r = ring.random(n).monic(); 351 r = ideal.normalform(r); 352 GenSolvablePolynomial<C> s; 353 do { 354 s = ring.random(n).monic(); 355 s = ideal.normalform(s); 356 } while (s.isZERO()); 357 return new SolvableLocal<C>(this, r, s, false); 358 } 359 360 361 /** 362 * Generate a random residum polynomial. 363 * @param k bitsize of random coefficients. 364 * @param l number of terms. 365 * @param d maximal degree in each variable. 366 * @param q density of nozero exponents. 367 * @return a random residue polynomial. 368 */ 369 public SolvableLocal<C> random(int k, int l, int d, float q) { 370 GenSolvablePolynomial<C> r = ring.random(k, l, d, q).monic(); 371 r = ideal.normalform(r); 372 GenSolvablePolynomial<C> s; 373 do { 374 s = ring.random(k, l, d, q).monic(); 375 s = ideal.normalform(s); 376 } while (s.isZERO()); 377 return new SolvableLocal<C>(this, r, s, false); 378 } 379 380 381 /** 382 * SolvableLocal random. 383 * @param n such that 0 ≤ v ≤ (2<sup>n</sup>-1). 384 * @param rnd is a source for random bits. 385 * @return a random residue element. 386 */ 387 public SolvableLocal<C> random(int n, Random rnd) { 388 GenSolvablePolynomial<C> r = ring.random(n, rnd).monic(); 389 r = ideal.normalform(r); 390 GenSolvablePolynomial<C> s; 391 do { 392 s = ring.random(n).monic(); 393 s = ideal.normalform(s); 394 } while (s.isZERO()); 395 return new SolvableLocal<C>(this, r, s, false); 396 } 397 398 399 /** 400 * Parse SolvableLocal from String. 401 * @param s String. 402 * @return SolvableLocal from s. 403 */ 404 public SolvableLocal<C> parse(String s) { 405 int i = s.indexOf("{"); 406 if (i >= 0) { 407 s = s.substring(i + 1); 408 } 409 i = s.lastIndexOf("}"); 410 if (i >= 0) { 411 s = s.substring(0, i); 412 } 413 i = s.indexOf("|"); 414 if (i < 0) { 415 GenSolvablePolynomial<C> n = ring.parse(s); 416 return new SolvableLocal<C>(this, n); 417 } 418 String s1 = s.substring(0, i); 419 String s2 = s.substring(i + 1); 420 GenSolvablePolynomial<C> n = ring.parse(s1); 421 GenSolvablePolynomial<C> d = ring.parse(s2); 422 return new SolvableLocal<C>(this, n, d); 423 } 424 425 426 /** 427 * Parse SolvableLocal from Reader. 428 * @param r Reader. 429 * @return next SolvableLocal from r. 430 */ 431 public SolvableLocal<C> parse(Reader r) { 432 String s = StringUtil.nextPairedString(r, '{', '}'); 433 return parse(s); 434 } 435 436}