001 /* 002 * $Id: ProductRing.java 3368 2010-10-24 13:53:32Z kredel $ 003 */ 004 005 package edu.jas.arith; 006 007 import java.io.Reader; 008 import java.io.StringReader; 009 010 import java.util.List; 011 import java.util.SortedMap; 012 import java.util.TreeMap; 013 import java.util.Random; 014 import java.util.ArrayList; 015 016 import org.apache.log4j.Logger; 017 018 import edu.jas.structure.ElemFactory; 019 import edu.jas.structure.RingElem; 020 import edu.jas.structure.RingFactory; 021 022 023 /** 024 * Direct product ring factory based on RingElem and RingFactory module. 025 * Objects of this class are <b>mutable</b>. 026 * @author Heinz Kredel 027 */ 028 public class ProductRing<C extends RingElem<C> > 029 implements RingFactory< Product<C> > { 030 031 private static final Logger logger = Logger.getLogger(ProductRing.class); 032 //private boolean debug = logger.isDebugEnabled(); 033 034 035 /** Ring factory is n copies. 036 */ 037 protected int nCopies; 038 039 040 /** One Ring factory. 041 */ 042 protected final RingFactory<C> ring; 043 044 045 /** Ring factory list. 046 */ 047 protected final List<RingFactory<C>> ringList; 048 049 050 /** 051 * A default random sequence generator. 052 */ 053 protected final static Random random = new Random(); 054 055 056 /** The constructor creates a ProductRing object 057 * from an ring factory and a modul. 058 * @param r ring factory. 059 * @param n number of copies. 060 */ 061 public ProductRing(RingFactory<C> r, int n) { 062 ring = r; 063 nCopies = n; 064 ringList = null; 065 } 066 067 068 /** The constructor creates a ProductRing object 069 * from an ring factory and a modul. 070 * @param l list of ring factories. 071 */ 072 public ProductRing(List<RingFactory<C>> l) { 073 ringList = l; 074 ring = null; 075 nCopies = 0; 076 } 077 078 079 /** Get ring factory at index i. 080 * @param i index. 081 * @return RingFactory_i. 082 */ 083 public RingFactory<C> getFactory(int i) { 084 if ( nCopies != 0 ) { 085 if ( 0 <= i && i < nCopies ) { 086 return ring; 087 } 088 throw new IllegalArgumentException("index out of bound " 089 + this.getClass().getName()); 090 } else { 091 return ringList.get(i); 092 } 093 } 094 095 096 /** Add a ring factory. 097 * @param rf new ring factory. 098 */ 099 public synchronized void addFactory(RingFactory<C> rf) { 100 if ( nCopies != 0 ) { 101 if ( ring.equals(rf) ) { 102 nCopies++; 103 } 104 throw new IllegalArgumentException("wrong RingFactory: " + rf); 105 } else { 106 ringList.add(rf); 107 } 108 } 109 110 111 /** Contains a ring factory. 112 * @param rf ring factory. 113 * @return true, if rf is contained in this, else false. 114 */ 115 public boolean containsFactory(RingFactory<C> rf) { 116 if ( nCopies != 0 ) { 117 if ( ring.equals(rf) ) { 118 return true; 119 } 120 return false; // misleading 121 } else { 122 return ringList.contains(rf); 123 } 124 } 125 126 127 /** 128 * Is this structure finite or infinite. 129 * @return true if this structure is finite, else false. 130 * @see edu.jas.structure.ElemFactory#isFinite() 131 */ 132 public boolean isFinite() { 133 if ( nCopies != 0 ) { 134 return ring.isFinite(); 135 } else { 136 for ( RingFactory<C> f : ringList ) { 137 boolean b = f.isFinite(); 138 if ( !b ) { 139 return false; 140 } 141 } 142 return true; 143 } 144 } 145 146 147 /** Copy Product element c. 148 * @param c 149 * @return a copy of c. 150 */ 151 public Product<C> copy(Product<C> c) { 152 return new Product<C>( c.ring, c.val, c.isunit ); 153 } 154 155 156 /** Get the zero element. 157 * @return 0 as Product. 158 */ 159 public Product<C> getZERO() { 160 return new Product<C>( this ); 161 } 162 163 164 /** Get the one element. 165 * @return 1 as Product. 166 */ 167 public Product<C> getONE() { 168 SortedMap<Integer,C> elem = new TreeMap<Integer,C>(); 169 if ( nCopies != 0 ) { 170 for ( int i = 0; i < nCopies; i++ ) { 171 elem.put( i, ring.getONE() ); 172 } 173 } else { 174 int i = 0; 175 for ( RingFactory<C> f : ringList ) { 176 elem.put( i, f.getONE() ); 177 i++; 178 } 179 } 180 return new Product<C>( this, elem, 1 ); 181 } 182 183 184 /** Get a list of the generating elements. 185 * @return list of generators for the algebraic structure. 186 * @see edu.jas.structure.ElemFactory#generators() 187 */ 188 public List<Product<C>> generators() { 189 List<Product<C>> gens = new ArrayList<Product<C>>(/*nCopies*ring.generators.size()*/); 190 int n = nCopies; 191 if ( n == 0 ) { 192 n = ringList.size(); 193 } 194 for ( int i = 0; i < n; i++ ) { 195 //System.out.println("i = " + i + ", n = " + n); 196 RingFactory<C> f = getFactory(i); 197 List<? extends C> rgens = f.generators(); 198 for ( C c: rgens ) { 199 SortedMap<Integer,C> elem = new TreeMap<Integer,C>(); 200 elem.put( i, c ); 201 Product<C> g = new Product<C>( this, elem ); 202 //g = g.fillOne(); 203 gens.add( g ); 204 } 205 } 206 return gens; 207 } 208 209 210 /** Get an atomic element. 211 * @param i index. 212 * @return e_i as Product. 213 */ 214 public Product<C> getAtomic(int i) { 215 if ( i < 0 || i >= length() ) { 216 throw new IllegalArgumentException("index out of bounds " + i); 217 } 218 SortedMap<Integer,C> elem = new TreeMap<Integer,C>(); 219 if ( nCopies != 0 ) { 220 elem.put( i, ring.getONE() ); 221 } else { 222 RingFactory<C> f = ringList.get(i); 223 elem.put( i, f.getONE() ); 224 } 225 return new Product<C>( this, elem, 1 ); 226 } 227 228 229 /** Get the number of factors of this ring. 230 * @return nCopies or ringList.size(). 231 */ 232 public int length() { 233 if ( nCopies != 0 ) { 234 return nCopies; 235 } else { 236 return ringList.size(); 237 } 238 } 239 240 241 /** 242 * Query if this ring is commutative. 243 * @return true if this ring is commutative, else false. 244 */ 245 public boolean isCommutative() { 246 if ( nCopies != 0 ) { 247 return ring.isCommutative(); 248 } else { 249 for ( RingFactory<C> f : ringList ) { 250 if ( ! f.isCommutative() ) { 251 return false; 252 } 253 } 254 return true; 255 } 256 } 257 258 259 /** 260 * Query if this ring is associative. 261 * @return true if this ring is associative, else false. 262 */ 263 public boolean isAssociative() { 264 if ( nCopies != 0 ) { 265 return ring.isAssociative(); 266 } else { 267 for ( RingFactory<C> f : ringList ) { 268 if ( ! f.isAssociative() ) { 269 return false; 270 } 271 } 272 return true; 273 } 274 } 275 276 277 /** 278 * Query if this ring is a field. 279 * @return true or false. 280 */ 281 public boolean isField() { 282 if ( nCopies != 0 ) { 283 if ( nCopies == 1 ) { 284 return ring.isField(); 285 } 286 } else { 287 if ( ringList.size() == 1 ) { 288 return ringList.get(0).isField(); 289 } 290 } 291 return false; 292 } 293 294 295 /** 296 * Query if this ring consists only of fields. 297 * @return true or false. 298 */ 299 public boolean onlyFields() { 300 if ( nCopies != 0 ) { 301 return ring.isField(); 302 } else { 303 for ( RingFactory<C> f : ringList ) { 304 if ( ! f.isField() ) { 305 return false; 306 } 307 } 308 } 309 return true; 310 } 311 312 313 /** 314 * Characteristic of this ring. 315 * @return minimal characteristic of ring component. 316 */ 317 public java.math.BigInteger characteristic() { 318 if ( nCopies != 0 ) { 319 return ring.characteristic(); 320 } else { 321 java.math.BigInteger c = null; 322 java.math.BigInteger d; 323 for ( RingFactory<C> f : ringList ) { 324 if ( c == null ) { 325 c = f.characteristic(); 326 } else { 327 d = f.characteristic(); 328 if ( c.compareTo(d) > 0 ) { // c > d 329 c = d; 330 } 331 } 332 } 333 return c; 334 } 335 } 336 337 338 /** Get a Product element from a BigInteger value. 339 * @param a BigInteger. 340 * @return a Product. 341 */ 342 public Product<C> fromInteger(java.math.BigInteger a) { 343 SortedMap<Integer,C> elem = new TreeMap<Integer,C>(); 344 if ( nCopies != 0 ) { 345 C c = ring.fromInteger(a); 346 for ( int i = 0; i < nCopies; i++ ) { 347 elem.put( i, c ); 348 } 349 } else { 350 int i = 0; 351 for ( RingFactory<C> f : ringList ) { 352 elem.put( i, f.fromInteger(a) ); 353 i++; 354 } 355 } 356 return new Product<C>( this, elem ); 357 } 358 359 360 /** Get a Product element from a long value. 361 * @param a long. 362 * @return a Product. 363 */ 364 public Product<C> fromInteger(long a) { 365 return fromInteger( new java.math.BigInteger(""+a) ); 366 } 367 368 369 /** Get the String representation as RingFactory. 370 * @see java.lang.Object#toString() 371 */ 372 @Override 373 public String toString() { 374 if ( nCopies != 0 ) { 375 String cf = ring.toString(); 376 if ( cf.matches("[0-9].*") ) { 377 cf = ring.getClass().getSimpleName(); 378 } 379 return "ProductRing[ " 380 + cf + "^" + nCopies + " ]"; 381 } else { 382 StringBuffer sb = new StringBuffer("ProductRing[ "); 383 int i = 0; 384 for ( RingFactory<C> f : ringList ) { 385 if ( i != 0 ) { 386 sb.append( ", " ); 387 } 388 String cf = f.toString(); 389 if ( cf.matches("[0-9].*") ) { 390 cf = f.getClass().getSimpleName(); 391 } 392 sb.append( cf ); 393 i++; 394 } 395 sb.append(" ]"); 396 return sb.toString(); 397 } 398 } 399 400 401 /** Get a scripting compatible string representation. 402 * @return script compatible representation for this ElemFactory. 403 * @see edu.jas.structure.ElemFactory#toScript() 404 */ 405 //JAVA6only: @Override 406 public String toScript() { 407 // Python case 408 StringBuffer s = new StringBuffer("RR( [ "); 409 for ( int i = 0; i < length(); i++ ) { 410 if ( i > 0 ) { 411 s.append(", "); 412 } 413 RingFactory<C> v = getFactory(i); 414 String f = null; 415 try { 416 f = ((RingElem<C>)v).toScriptFactory(); // sic 417 } catch (Exception e) { 418 f = v.toScript(); 419 } 420 s.append( f ); 421 } 422 s.append(" ] )"); 423 return s.toString(); 424 } 425 426 427 /** Comparison with any other object. 428 * @see java.lang.Object#equals(java.lang.Object) 429 */ 430 @Override 431 @SuppressWarnings("unchecked") 432 public boolean equals(Object b) { 433 if ( ! ( b instanceof ProductRing ) ) { 434 return false; 435 } 436 ProductRing<C> a = null; 437 try { 438 a = (ProductRing<C>) b; 439 } catch (ClassCastException e) { 440 } 441 if ( a == null ) { 442 return false; 443 } 444 if ( nCopies != 0 ) { 445 if ( nCopies != a.nCopies || !ring.equals( a.ring ) ) { 446 return false; 447 } 448 } else { 449 if ( ringList.size() != a.ringList.size() ) { 450 return false; 451 } 452 int i = 0; 453 for ( RingFactory<C> f : ringList ) { 454 if ( !f.equals( a.ringList.get(i) ) ) { 455 return false; 456 } 457 i++; 458 } 459 } 460 return true; 461 } 462 463 464 /** Hash code for this product ring. 465 * @see java.lang.Object#hashCode() 466 */ 467 @Override 468 public int hashCode() { 469 int h = 0; 470 if ( nCopies != 0 ) { 471 h = ring.hashCode(); 472 h = 37 * h + nCopies; 473 } else { 474 for ( RingFactory<C> f : ringList ) { 475 h = 37 * h + f.hashCode(); 476 } 477 } 478 return h; 479 } 480 481 482 /** Product random. 483 * @param n such that 0 ≤ v ≤ (2<sup>n</sup>-1). 484 * @return a random product element v. 485 */ 486 public Product<C> random(int n) { 487 return random( n, 0.5f ); 488 } 489 490 491 /** Product random. 492 * @param n such that 0 ≤ v ≤ (2<sup>n</sup>-1). 493 * @param q density of nozero entries. 494 * @return a random product element v. 495 */ 496 public Product<C> random(int n, float q) { 497 return random( n, q, random ); 498 } 499 500 501 /** Product random. 502 * @param n such that 0 ≤ v ≤ (2<sup>n</sup>-1). 503 * @param rnd is a source for random bits. 504 * @return a random product element v. 505 */ 506 public Product<C> random(int n, Random rnd) { 507 return random( n, 0.5f, random ); 508 } 509 510 511 /** Product random. 512 * @param n such that 0 ≤ v ≤ (2<sup>n</sup>-1). 513 * @param q density of nozero entries. 514 * @param rnd is a source for random bits. 515 * @return a random product element v. 516 */ 517 public Product<C> random(int n, float q, Random rnd) { 518 SortedMap<Integer,C> elem = new TreeMap<Integer,C>(); 519 float d; 520 if ( nCopies != 0 ) { 521 for ( int i = 0; i < nCopies; i++ ) { 522 d = rnd.nextFloat(); 523 if ( d < q ) { 524 C r = ring.random( n, rnd ); 525 if ( !r.isZERO() ) { 526 elem.put( i, r ); 527 } 528 } 529 } 530 } else { 531 int i = 0; 532 for ( RingFactory<C> f : ringList ) { 533 d = rnd.nextFloat(); 534 if ( d < q ) { 535 C r = f.random( n, rnd ); 536 if ( !r.isZERO() ) { 537 elem.put( i, r ); 538 } 539 } 540 i++; 541 } 542 } 543 return new Product<C>( this, elem ); 544 } 545 546 547 /** Parse Product from String. 548 * @param s String. 549 * @return Product from s. 550 */ 551 public Product<C> parse(String s) { 552 StringReader sr = new StringReader(s); 553 return parse( sr ); 554 } 555 556 557 /** Parse Product from Reader. 558 * Syntax: p1 ... pn (no commas) 559 * @param r Reader. 560 * @return next Product from r. 561 */ 562 public Product<C> parse(Reader r) { 563 SortedMap<Integer,C> elem = new TreeMap<Integer,C>(); 564 if ( nCopies != 0 ) { 565 for ( int i = 0; i < nCopies; i++ ) { 566 elem.put( i, ring.parse( r ) ); 567 } 568 } else { 569 int i = 0; 570 for ( RingFactory<C> f : ringList ) { 571 elem.put( i, f.parse( r ) ); 572 i++; 573 } 574 } 575 return new Product<C>( this, elem ); 576 } 577 578 }