001/* 002 * $Id: SolvableLocalRing.java 5868 2018-07-20 15:44:13Z 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.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 if (true || debug) { 227 logger.info("Xk = " + Xk + ", Xj = " + Xj + ", Xi = " + Xi); 228 logger.info("p = ( Xk * Xj ) * Xi = " + p); 229 logger.info("q = Xk * ( Xj * Xi ) = " + q); 230 } 231 return false; 232 } 233 } 234 } 235 } 236 return true; 237 } 238 239 240 /** 241 * Query if this ring is a field. 242 * @return false. 243 */ 244 public boolean isField() { 245 if (isField > 0) { 246 return true; 247 } 248 if (isField == 0) { 249 return false; 250 } 251 // not reached 252 return false; 253 } 254 255 256 /** 257 * Characteristic of this ring. 258 * @return characteristic of this ring. 259 */ 260 public java.math.BigInteger characteristic() { 261 return ring.characteristic(); 262 } 263 264 265 /** 266 * Get a SolvableLocal element from a BigInteger value. 267 * @param a BigInteger. 268 * @return a SolvableLocal. 269 */ 270 public SolvableLocal<C> fromInteger(java.math.BigInteger a) { 271 return new SolvableLocal<C>(this, ring.fromInteger(a)); 272 } 273 274 275 /** 276 * Get a SolvableLocal element from a long value. 277 * @param a long. 278 * @return a SolvableLocal. 279 */ 280 public SolvableLocal<C> fromInteger(long a) { 281 return new SolvableLocal<C>(this, ring.fromInteger(a)); 282 } 283 284 285 /** 286 * Get the String representation as RingFactory. 287 */ 288 @Override 289 public String toString() { 290 return "SolvableLocalRing[ " + ideal.toString() + " ]"; 291 } 292 293 294 /** 295 * Get a scripting compatible string representation. 296 * @return script compatible representation for this ElemFactory. 297 */ 298 @Override 299 public String toScript() { 300 // Python case 301 return "SLC(" + ideal.list.toScript() + ")"; 302 } 303 304 305 /** 306 * Comparison with any other object. 307 */ 308 @Override 309 @SuppressWarnings("unchecked") 310 public boolean equals(Object b) { 311 if (!(b instanceof SolvableLocalRing)) { 312 return false; 313 } 314 SolvableLocalRing<C> a = null; 315 try { 316 a = (SolvableLocalRing<C>) b; 317 } catch (ClassCastException e) { 318 } 319 if (a == null) { 320 return false; 321 } 322 if (!ring.equals(a.ring)) { 323 return false; 324 } 325 return ideal.equals(a.ideal); 326 } 327 328 329 /** 330 * Hash code for this local ring. 331 */ 332 @Override 333 public int hashCode() { 334 int h; 335 h = ideal.hashCode(); 336 return h; 337 } 338 339 340 /** 341 * SolvableLocal random. 342 * @param n such that 0 ≤ v ≤ (2<sup>n</sup>-1). 343 * @return a random residue element. 344 */ 345 public SolvableLocal<C> random(int n) { 346 GenSolvablePolynomial<C> r = ring.random(n).monic(); 347 r = ideal.normalform(r); 348 GenSolvablePolynomial<C> s; 349 do { 350 s = ring.random(n).monic(); 351 s = ideal.normalform(s); 352 } while (s.isZERO()); 353 return new SolvableLocal<C>(this, r, s, false); 354 } 355 356 357 /** 358 * Generate a random residum polynomial. 359 * @param k bitsize of random coefficients. 360 * @param l number of terms. 361 * @param d maximal degree in each variable. 362 * @param q density of nozero exponents. 363 * @return a random residue polynomial. 364 */ 365 public SolvableLocal<C> random(int k, int l, int d, float q) { 366 GenSolvablePolynomial<C> r = ring.random(k, l, d, q).monic(); 367 r = ideal.normalform(r); 368 GenSolvablePolynomial<C> s; 369 do { 370 s = ring.random(k, l, d, q).monic(); 371 s = ideal.normalform(s); 372 } while (s.isZERO()); 373 return new SolvableLocal<C>(this, r, s, false); 374 } 375 376 377 /** 378 * SolvableLocal random. 379 * @param n such that 0 ≤ v ≤ (2<sup>n</sup>-1). 380 * @param rnd is a source for random bits. 381 * @return a random residue element. 382 */ 383 public SolvableLocal<C> random(int n, Random rnd) { 384 GenSolvablePolynomial<C> r = ring.random(n, rnd).monic(); 385 r = ideal.normalform(r); 386 GenSolvablePolynomial<C> s; 387 do { 388 s = ring.random(n).monic(); 389 s = ideal.normalform(s); 390 } while (s.isZERO()); 391 return new SolvableLocal<C>(this, r, s, false); 392 } 393 394 395 /** 396 * Parse SolvableLocal from String. 397 * @param s String. 398 * @return SolvableLocal from s. 399 */ 400 public SolvableLocal<C> parse(String s) { 401 int i = s.indexOf("{"); 402 if (i >= 0) { 403 s = s.substring(i + 1); 404 } 405 i = s.lastIndexOf("}"); 406 if (i >= 0) { 407 s = s.substring(0, i); 408 } 409 i = s.indexOf("|"); 410 if (i < 0) { 411 GenSolvablePolynomial<C> n = ring.parse(s); 412 return new SolvableLocal<C>(this, n); 413 } 414 String s1 = s.substring(0, i); 415 String s2 = s.substring(i + 1); 416 GenSolvablePolynomial<C> n = ring.parse(s1); 417 GenSolvablePolynomial<C> d = ring.parse(s2); 418 return new SolvableLocal<C>(this, n, d); 419 } 420 421 422 /** 423 * Parse SolvableLocal from Reader. 424 * @param r Reader. 425 * @return next SolvableLocal from r. 426 */ 427 public SolvableLocal<C> parse(Reader r) { 428 String s = StringUtil.nextPairedString(r, '{', '}'); 429 return parse(s); 430 } 431 432}