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