001/* 002 * $Id: SolvableQuotientRing.java 5738 2017-02-18 20:37:26Z kredel $ 003 */ 004 005package edu.jas.fd; 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.gbufd.SolvableSyzygyAbstract; 016import edu.jas.gbufd.SolvableSyzygySeq; 017import edu.jas.kern.StringUtil; 018import edu.jas.poly.GenPolynomial; 019import edu.jas.poly.GenSolvablePolynomial; 020import edu.jas.poly.GenSolvablePolynomialRing; 021import edu.jas.poly.PolynomialList; 022import edu.jas.structure.GcdRingElem; 023import edu.jas.structure.QuotPairFactory; 024import edu.jas.structure.RingFactory; 025 026 027/** 028 * SolvableQuotient ring factory based on GenPolynomial with RingElem interface. 029 * Objects of this class are immutable. 030 * @author Heinz Kredel 031 */ 032public class SolvableQuotientRing<C extends GcdRingElem<C>> implements RingFactory<SolvableQuotient<C>>, 033 QuotPairFactory<GenPolynomial<C>, SolvableQuotient<C>> { 034 // should be QuotPairFactory<GenSolvablePolynomial<C> 035 036 037 private static final Logger logger = Logger.getLogger(SolvableQuotientRing.class); 038 039 040 //private static final boolean debug = logger.isDebugEnabled(); 041 042 043 /** 044 * Solvable polynomial ring of the factory. 045 */ 046 public final GenSolvablePolynomialRing<C> ring; 047 048 049 /** 050 * Syzygy engine of the factory. 051 */ 052 public final SolvableSyzygyAbstract<C> engine; 053 054 055 /** 056 * The constructor creates a SolvableQuotientRing object from a 057 * GenSolvablePolynomialRing. 058 * @param r solvable polynomial ring. 059 */ 060 public SolvableQuotientRing(GenSolvablePolynomialRing<C> r) { 061 ring = r; 062 engine = new SolvableSyzygySeq<C>(ring.coFac); 063 logger.debug("quotient ring constructed"); 064 } 065 066 067 /** 068 * Factory for base elements. 069 */ 070 public GenSolvablePolynomialRing<C> pairFactory() { 071 return ring; 072 } 073 074 075 /** 076 * Create from numerator. 077 */ 078 @SuppressWarnings("unchecked") 079 public SolvableQuotient<C> create(GenPolynomial<C> n) { 080 return new SolvableQuotient<C>(this, (GenSolvablePolynomial<C>) n); 081 } 082 083 084 /** 085 * Create from numerator, denominator pair. 086 */ 087 @SuppressWarnings("unchecked") 088 public SolvableQuotient<C> create(GenPolynomial<C> n, GenPolynomial<C> d) { 089 return new SolvableQuotient<C>(this, (GenSolvablePolynomial<C>) n, (GenSolvablePolynomial<C>) d); 090 } 091 092 093 /** 094 * Is this structure finite or infinite. 095 * @return true if this structure is finite, else false. 096 */ 097 public boolean isFinite() { 098 return ring.isFinite(); 099 } 100 101 102 /** 103 * Copy SolvableQuotient element c. 104 * @param c 105 * @return a copy of c. 106 */ 107 public SolvableQuotient<C> copy(SolvableQuotient<C> c) { 108 return new SolvableQuotient<C>(c.ring, c.num, c.den, true); 109 } 110 111 112 /** 113 * Get the zero element. 114 * @return 0 as SolvableQuotient. 115 */ 116 public SolvableQuotient<C> getZERO() { 117 return new SolvableQuotient<C>(this, ring.getZERO()); 118 } 119 120 121 /** 122 * Get the one element. 123 * @return 1 as SolvableQuotient. 124 */ 125 public SolvableQuotient<C> getONE() { 126 return new SolvableQuotient<C>(this, ring.getONE()); 127 } 128 129 130 /** 131 * Get a list of the generating elements. 132 * @return list of generators for the algebraic structure. 133 */ 134 public List<SolvableQuotient<C>> generators() { 135 List<GenSolvablePolynomial<C>> pgens = PolynomialList.<C> castToSolvableList(ring.generators()); 136 List<SolvableQuotient<C>> gens = new ArrayList<SolvableQuotient<C>>(pgens.size() * 2 - 1); 137 GenSolvablePolynomial<C> one = ring.getONE(); 138 for (GenSolvablePolynomial<C> p : pgens) { 139 SolvableQuotient<C> q = new SolvableQuotient<C>(this, p); 140 gens.add(q); 141 if (!p.isONE()) { 142 q = new SolvableQuotient<C>(this, one, p); 143 gens.add(q); 144 } 145 } 146 return gens; 147 } 148 149 150 /** 151 * Query if this ring is commutative. 152 * @return true if this ring is commutative, else false. 153 */ 154 public boolean isCommutative() { 155 return ring.isCommutative(); 156 } 157 158 159 /** 160 * Query if this ring is associative. 161 * @return true if this ring is associative, else false. 162 */ 163 public boolean isAssociative() { 164 if (!ring.isAssociative()) { 165 return false; 166 } 167 SolvableQuotient<C> Xi, Xj, Xk, p, q; 168 List<SolvableQuotient<C>> gens = generators(); 169 int ngen = gens.size(); 170 for (int i = 0; i < ngen; i++) { 171 Xi = gens.get(i); 172 for (int j = i + 1; j < ngen; j++) { 173 Xj = gens.get(j); 174 for (int k = j + 1; k < ngen; k++) { 175 Xk = gens.get(k); 176 p = Xk.multiply(Xj).multiply(Xi); 177 q = Xk.multiply(Xj.multiply(Xi)); 178 if (!p.equals(q)) { 179 if (logger.isInfoEnabled()) { 180 logger.info("Xk = " + Xk + ", Xj = " + Xj + ", Xi = " + Xi); 181 logger.info("p = ( Xk * Xj ) * Xi = " + p); 182 logger.info("q = Xk * ( Xj * Xi ) = " + q); 183 } 184 return false; 185 } 186 } 187 } 188 } 189 return true; 190 } 191 192 193 /** 194 * Query if this ring is a field. 195 * @return true. 196 */ 197 public boolean isField() { 198 return true; 199 } 200 201 202 /** 203 * Characteristic of this ring. 204 * @return characteristic of this ring. 205 */ 206 public java.math.BigInteger characteristic() { 207 return ring.characteristic(); 208 } 209 210 211 /** 212 * Get a SolvableQuotient element from a BigInteger value. 213 * @param a BigInteger. 214 * @return a SolvableQuotient. 215 */ 216 public SolvableQuotient<C> fromInteger(java.math.BigInteger a) { 217 return new SolvableQuotient<C>(this, ring.fromInteger(a)); 218 } 219 220 221 /** 222 * Get a SolvableQuotient element from a long value. 223 * @param a long. 224 * @return a SolvableQuotient. 225 */ 226 public SolvableQuotient<C> fromInteger(long a) { 227 return new SolvableQuotient<C>(this, ring.fromInteger(a)); 228 } 229 230 231 /** 232 * Get the String representation as RingFactory. 233 */ 234 @Override 235 public String toString() { 236 String s = null; 237 if (ring.coFac.characteristic().signum() == 0) { 238 s = "RatFunc"; 239 } else { 240 s = "ModFunc"; 241 } 242 return s + "( " + ring.toString() + " )"; 243 } 244 245 246 /** 247 * Get a scripting compatible string representation. 248 * @return script compatible representation for this ElemFactory. 249 */ 250 @Override 251 public String toScript() { 252 // Python case 253 return "SRF(" + ring.toScript() + ")"; 254 } 255 256 257 /** 258 * Comparison with any other object. 259 */ 260 @Override 261 @SuppressWarnings("unchecked") 262 public boolean equals(Object b) { 263 if (b == null) { 264 return false; 265 } 266 if (!(b instanceof SolvableQuotientRing)) { 267 return false; 268 } 269 SolvableQuotientRing<C> a = (SolvableQuotientRing<C>) b; 270 return ring.equals(a.ring); 271 } 272 273 274 /** 275 * Hash code for this quotient ring. 276 */ 277 @Override 278 public int hashCode() { 279 int h; 280 h = ring.hashCode(); 281 return h; 282 } 283 284 285 /** 286 * SolvableQuotient random. 287 * @param n such that 0 ≤ v ≤ (2<sup>n</sup>-1). 288 * @return a random quotient element. 289 */ 290 public SolvableQuotient<C> random(int n) { 291 GenSolvablePolynomial<C> r = ring.random(n).monic(); 292 GenSolvablePolynomial<C> s; 293 do { 294 s = ring.random(n).monic(); 295 } while (s.isZERO()); 296 return new SolvableQuotient<C>(this, r, s, false); 297 } 298 299 300 /** 301 * Generate a random quotient. 302 * @param k bitsize of random coefficients. 303 * @param l number of terms. 304 * @param d maximal degree in each variable. 305 * @param q density of nozero exponents. 306 * @return a random quotient. 307 */ 308 public SolvableQuotient<C> random(int k, int l, int d, float q) { 309 GenSolvablePolynomial<C> r = ring.random(k, l, d, q).monic(); 310 GenSolvablePolynomial<C> s = ring.random(k, l, d, q).monic(); 311 do { 312 s = ring.random(k, l, d, q).monic(); 313 } while (s.isZERO()); 314 return new SolvableQuotient<C>(this, r, s, false); 315 } 316 317 318 /** 319 * SolvableQuotient random. 320 * @param n such that 0 ≤ v ≤ (2<sup>n</sup>-1). 321 * @param rnd is a source for random bits. 322 * @return a random quotient element. 323 */ 324 public SolvableQuotient<C> random(int n, Random rnd) { 325 GenSolvablePolynomial<C> r = ring.random(n, rnd).monic(); 326 GenSolvablePolynomial<C> s = ring.random(n, rnd).monic(); 327 do { 328 s = ring.random(n, rnd).monic(); 329 } while (s.isZERO()); 330 return new SolvableQuotient<C>(this, r, s, false); 331 } 332 333 334 /** 335 * Parse SolvableQuotient from String. Syntax: "{ polynomial | polynomial }" 336 * or "{ polynomial }" or " polynomial | polynomial " or " polynomial " 337 * @param s String. 338 * @return SolvableQuotient from s. 339 */ 340 public SolvableQuotient<C> parse(String s) { 341 int i = s.indexOf("{"); 342 if (i >= 0) { 343 s = s.substring(i + 1); 344 } 345 i = s.lastIndexOf("}"); 346 if (i >= 0) { 347 s = s.substring(0, i); 348 } 349 i = s.indexOf("|"); 350 if (i < 0) { 351 GenSolvablePolynomial<C> n = ring.parse(s); 352 return new SolvableQuotient<C>(this, n); 353 } 354 String s1 = s.substring(0, i); 355 String s2 = s.substring(i + 1); 356 GenSolvablePolynomial<C> n = ring.parse(s1); 357 GenSolvablePolynomial<C> d = ring.parse(s2); 358 return new SolvableQuotient<C>(this, n, d); 359 } 360 361 362 /** 363 * Parse SolvableQuotient from Reader. 364 * @param r Reader. 365 * @return next SolvableQuotient from r. 366 */ 367 public SolvableQuotient<C> parse(Reader r) { 368 String s = StringUtil.nextPairedString(r, '{', '}'); 369 return parse(s); 370 } 371 372}