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