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