001 /* 002 * $Id: GenMatrixRing.java 3571 2011-03-18 22:02:51Z kredel $ 003 */ 004 005 package edu.jas.vector; 006 007 008 // import java.io.IOException; 009 import java.io.Reader; 010 import java.math.BigInteger; 011 import java.util.ArrayList; 012 import java.util.List; 013 import java.util.Random; 014 015 import org.apache.log4j.Logger; 016 017 import edu.jas.kern.StringUtil; 018 import edu.jas.structure.AlgebraFactory; 019 import edu.jas.structure.RingElem; 020 import edu.jas.structure.RingFactory; 021 022 023 /** 024 * GenMatrixRing implements a generic matrix algebra factory with RingFactory. 025 * Matrices of n rows and m columns over C. 026 * @author Heinz Kredel 027 */ 028 029 public class GenMatrixRing<C extends RingElem<C>> implements AlgebraFactory<GenMatrix<C>, C> { 030 031 032 private static final Logger logger = Logger.getLogger(GenMatrixRing.class); 033 034 035 public final RingFactory<C> coFac; 036 037 038 public final int rows; 039 040 041 public final int cols; 042 043 044 public final int blocksize; 045 046 047 public final static int DEFAULT_BSIZE = 10; 048 049 050 public final GenMatrix<C> ZERO; 051 052 053 public final GenMatrix<C> ONE; 054 055 056 private final static Random random = new Random(); 057 058 059 public final static float DEFAULT_DENSITY = 0.5f; 060 061 062 private final float density = DEFAULT_DENSITY; 063 064 065 /** 066 * Constructors for GenMatrixRing. 067 * @param b coefficient factory. 068 * @param r number of rows. 069 * @param c number of colums. 070 */ 071 public GenMatrixRing(RingFactory<C> b, int r, int c) { 072 this(b, r, c, DEFAULT_BSIZE); 073 } 074 075 076 /** 077 * Constructors for GenMatrixRing. 078 * @param b coefficient factory. 079 * @param r number of rows. 080 * @param c number of colums. 081 * @param s block size for blocked operations. 082 */ 083 @SuppressWarnings("unchecked") 084 public GenMatrixRing(RingFactory<C> b, int r, int c, int s) { 085 if (b == null) { 086 throw new IllegalArgumentException("RingFactory is null"); 087 } 088 if (r < 1) { 089 throw new IllegalArgumentException("rows < 1 " + r); 090 } 091 if (c < 1) { 092 throw new IllegalArgumentException("cols < 1 " + c); 093 } 094 coFac = b; 095 rows = r; 096 cols = c; 097 blocksize = s; 098 ArrayList<C> z = new ArrayList<C>(cols); 099 for (int i = 0; i < cols; i++) { 100 z.add(coFac.getZERO()); 101 } 102 ArrayList<ArrayList<C>> m = new ArrayList<ArrayList<C>>(rows); 103 for (int i = 0; i < rows; i++) { 104 m.add((ArrayList<C>) z.clone()); 105 } 106 ZERO = new GenMatrix<C>(this, m); 107 m = new ArrayList<ArrayList<C>>(rows); 108 C one = coFac.getONE(); 109 ArrayList<C> v; 110 for (int i = 0; i < rows; i++) { 111 if (i < cols) { 112 v = (ArrayList<C>) z.clone(); 113 v.set(i, one); 114 m.add(v); 115 } 116 } 117 ONE = new GenMatrix<C>(this, m); 118 } 119 120 121 /** 122 * Get the String representation as RingElem. 123 * @see java.lang.Object#toString() 124 */ 125 @Override 126 public String toString() { 127 StringBuffer s = new StringBuffer(); 128 s.append(coFac.getClass().getSimpleName()); 129 s.append("[" + rows + "," + cols + "]"); 130 return s.toString(); 131 } 132 133 134 /** 135 * Get a scripting compatible string representation. 136 * @return script compatible representation for this ElemFactory. 137 * @see edu.jas.structure.ElemFactory#toScript() 138 */ 139 //JAVA6only: @Override 140 public String toScript() { 141 // Python case 142 StringBuffer s = new StringBuffer("Mat("); 143 String f = null; 144 try { 145 f = ((RingElem<C>) coFac).toScriptFactory(); // sic 146 } catch (Exception e) { 147 f = coFac.toScript(); 148 } 149 s.append(f + "," + rows + "," + cols + ")"); 150 return s.toString(); 151 } 152 153 154 /** 155 * Get the constant one for the GenMatrix. 156 * @return ZERO. 157 */ 158 public GenMatrix<C> getZERO() { 159 return ZERO; 160 } 161 162 163 /** 164 * Get the constant one for the GenMatrix. 165 * @return 1. 166 */ 167 public GenMatrix<C> getONE() { 168 return ONE; 169 } 170 171 172 /** 173 * Get a list of the generating elements. 174 * @return list of generators for the algebraic structure. 175 * @see edu.jas.structure.ElemFactory#generators() 176 */ 177 public List<GenMatrix<C>> generators() { 178 List<C> rgens = coFac.generators(); 179 List<GenMatrix<C>> gens = new ArrayList<GenMatrix<C>>(rows * cols * rgens.size()); 180 for (int i = 0; i < rows; i++) { 181 for (int j = 0; j < cols; j++) { 182 for (C el : rgens) { 183 GenMatrix<C> g = ZERO.set(i, j, el); // uses clone() 184 gens.add(g); 185 } 186 } 187 } 188 return gens; 189 } 190 191 192 /** 193 * Is this structure finite or infinite. 194 * @return true if this structure is finite, else false. 195 * @see edu.jas.structure.ElemFactory#isFinite() 196 */ 197 public boolean isFinite() { 198 return coFac.isFinite(); 199 } 200 201 202 /** 203 * Comparison with any other object. 204 * @see java.lang.Object#equals(java.lang.Object) 205 */ 206 @Override 207 public boolean equals(Object other) { 208 if (!(other instanceof GenMatrixRing)) { 209 return false; 210 } 211 GenMatrixRing omod = (GenMatrixRing) other; 212 if (rows != omod.rows) { 213 return false; 214 } 215 if (cols != omod.cols) { 216 return false; 217 } 218 if (!coFac.equals(omod.coFac)) { 219 return false; 220 } 221 return true; 222 } 223 224 225 /** 226 * Hash code for this matrix ring. 227 * @see java.lang.Object#hashCode() 228 */ 229 @Override 230 public int hashCode() { 231 int h; 232 h = rows * 17 + cols; 233 h = 37 * h + coFac.hashCode(); 234 return h; 235 } 236 237 238 /** 239 * Query if this ring is a field. May return false if it is to hard to 240 * determine if this ring is a field. 241 * @return true if it is known that this ring is a field, else false. 242 */ 243 public boolean isField() { 244 return false; 245 } 246 247 248 /** 249 * Query if this monoid is commutative. 250 * @return true if this monoid is commutative, else false. 251 */ 252 public boolean isCommutative() { 253 return false; 254 } 255 256 257 /** 258 * Query if this ring is associative. 259 * @return true if this monoid is associative, else false. 260 */ 261 public boolean isAssociative() { 262 return (rows == cols); 263 } 264 265 266 /** 267 * Characteristic of this ring. 268 * @return characteristic of this ring. 269 */ 270 public java.math.BigInteger characteristic() { 271 return coFac.characteristic(); 272 } 273 274 275 /** 276 * Transposed matrix ring. 277 * @return transposed ring factory. 278 */ 279 public GenMatrixRing<C> transpose() { 280 if (rows == cols) { 281 return this; 282 } 283 return new GenMatrixRing<C>(coFac, cols, rows, blocksize); 284 } 285 286 287 /** 288 * Product matrix ring for multiplication. 289 * @param other matrix ring factory. 290 * @return product ring factory. 291 */ 292 public GenMatrixRing<C> product(GenMatrixRing<C> other) { 293 if (cols != other.rows) { 294 throw new IllegalArgumentException("invalid dimensions in product"); 295 } 296 if (!coFac.equals(other.coFac)) { 297 throw new IllegalArgumentException("invalid coefficients in product"); 298 } 299 if (rows == other.rows && cols == other.cols) { 300 return this; 301 } 302 return new GenMatrixRing<C>(coFac, rows, other.cols, blocksize); 303 } 304 305 306 /** 307 * Get the matrix for a. 308 * @param a long 309 * @return matrix corresponding to a. 310 */ 311 public GenMatrix<C> fromInteger(long a) { 312 C c = coFac.fromInteger(a); 313 return ONE.scalarMultiply(c); 314 } 315 316 317 /** 318 * Get the matrix for a. 319 * @param a long 320 * @return matrix corresponding to a. 321 */ 322 public GenMatrix<C> fromInteger(BigInteger a) { 323 C c = coFac.fromInteger(a); 324 return ONE.scalarMultiply(c); 325 } 326 327 328 /** 329 * From List of coefficients. 330 * @param om list of list of coefficients. 331 */ 332 public GenMatrix<C> fromList(List<List<C>> om) { 333 if (om == null) { 334 return ZERO; 335 } 336 if (om.size() > rows) { 337 throw new IllegalArgumentException("size v > rows " + om + " > " + rows); 338 } 339 ArrayList<ArrayList<C>> m = new ArrayList<ArrayList<C>>(rows); 340 for (int i = 0; i < rows; i++) { 341 List<C> ov = om.get(i); 342 ArrayList<C> v; 343 if (ov == null) { 344 v = ZERO.matrix.get(0); 345 } else { 346 if (ov.size() > cols) { 347 throw new IllegalArgumentException("size v > cols " + ov + " > " + cols); 348 } 349 v = new ArrayList<C>(cols); 350 v.addAll(ov); 351 // pad with zeros if required: 352 for (int j = v.size(); j < cols; j++) { 353 v.add(coFac.getZERO()); 354 } 355 } 356 m.add(v); 357 } 358 return new GenMatrix<C>(this, m); 359 } 360 361 362 /** 363 * Random matrix. 364 * @param k size of random coefficients. 365 */ 366 public GenMatrix<C> random(int k) { 367 return random(k, density, random); 368 } 369 370 371 /** 372 * Random matrix. 373 * @param k size of random coefficients. 374 * @param q density of nozero coefficients. 375 */ 376 public GenMatrix<C> random(int k, float q) { 377 return random(k, q, random); 378 } 379 380 381 /** 382 * Random matrix. 383 * @param k size of random coefficients. 384 * @param random is a source for random bits. 385 * @return a random element. 386 */ 387 public GenMatrix<C> random(int k, Random random) { 388 return random(k, density, random); 389 } 390 391 392 /** 393 * Random matrix. 394 * @param k size of random coefficients. 395 * @param q density of nozero coefficients. 396 * @param random is a source for random bits. 397 * @return a random element. 398 */ 399 public GenMatrix<C> random(int k, float q, Random random) { 400 ArrayList<ArrayList<C>> m = new ArrayList<ArrayList<C>>(rows); 401 for (int i = 0; i < rows; i++) { 402 ArrayList<C> v = new ArrayList<C>(cols); 403 for (int j = 0; j < cols; j++) { 404 C e; 405 if (random.nextFloat() < q) { 406 e = coFac.random(k); 407 } else { 408 e = coFac.getZERO(); 409 } 410 v.add(e); 411 } 412 m.add(v); 413 } 414 return new GenMatrix<C>(this, m); 415 } 416 417 418 /** 419 * Random upper triangular matrix. 420 * @param k size of random coefficients. 421 * @param q density of nozero coefficients. 422 */ 423 public GenMatrix<C> randomUpper(int k, float q) { 424 return randomUpper(k, q, random); 425 } 426 427 428 /** 429 * Random upper triangular matrix. 430 * @param k size of random coefficients. 431 * @param q density of nozero coefficients. 432 * @param random is a source for random bits. 433 * @return a random element. 434 */ 435 public GenMatrix<C> randomUpper(int k, float q, Random random) { 436 ArrayList<ArrayList<C>> m = new ArrayList<ArrayList<C>>(rows); 437 for (int i = 0; i < rows; i++) { 438 ArrayList<C> v = new ArrayList<C>(cols); 439 for (int j = 0; j < cols; j++) { 440 C e = coFac.getZERO(); 441 if (j >= i) { 442 if (random.nextFloat() < q) { 443 e = coFac.random(k); 444 } 445 } 446 v.add(e); 447 } 448 m.add(v); 449 } 450 return new GenMatrix<C>(this, m); 451 } 452 453 454 /** 455 * Random lower triangular matrix. 456 * @param k size of random coefficients. 457 * @param q density of nozero coefficients. 458 */ 459 public GenMatrix<C> randomLower(int k, float q) { 460 return randomLower(k, q, random); 461 } 462 463 464 /** 465 * Random lower triangular matrix. 466 * @param k size of random coefficients. 467 * @param q density of nozero coefficients. 468 * @param random is a source for random bits. 469 * @return a random element. 470 */ 471 public GenMatrix<C> randomLower(int k, float q, Random random) { 472 ArrayList<ArrayList<C>> m = new ArrayList<ArrayList<C>>(rows); 473 for (int i = 0; i < rows; i++) { 474 ArrayList<C> v = new ArrayList<C>(cols); 475 for (int j = 0; j < cols; j++) { 476 C e = coFac.getZERO(); 477 if (j <= i) { 478 if (random.nextFloat() < q) { 479 e = coFac.random(k); 480 } 481 } 482 v.add(e); 483 } 484 m.add(v); 485 } 486 return new GenMatrix<C>(this, m); 487 } 488 489 490 /** 491 * copy matrix. 492 */ 493 public GenMatrix<C> copy(GenMatrix<C> c) { 494 if (c == null) { 495 return c; 496 } 497 return c.clone(); 498 } 499 500 501 /** 502 * parse a matrix from a String. Syntax: [ [ c, ..., c ], ..., [ c, ..., c ] 503 * ] 504 */ 505 public GenMatrix<C> parse(String s) { 506 int i = s.indexOf("["); 507 if (i >= 0) { 508 s = s.substring(i + 1); 509 } 510 ArrayList<ArrayList<C>> mat = new ArrayList<ArrayList<C>>(rows); 511 ArrayList<C> v; 512 GenVector<C> vec; 513 GenVectorModul<C> vmod = new GenVectorModul<C>(coFac, cols); 514 String e; 515 int j; 516 do { 517 i = s.indexOf("]"); // delimit vector 518 j = s.lastIndexOf("]"); // delimit matrix 519 if (i != j) { 520 if (i >= 0) { 521 e = s.substring(0, i); 522 s = s.substring(i); 523 vec = vmod.parse(e); 524 v = (ArrayList<C>) vec.val; 525 mat.add(v); 526 i = s.indexOf(","); 527 if (i >= 0) { 528 s = s.substring(i + 1); 529 } 530 } 531 } else { // matrix delimiter 532 if (i >= 0) { 533 e = s.substring(0, i); 534 if (e.trim().length() > 0) { 535 throw new RuntimeException("Error e not empty " + e); 536 } 537 s = s.substring(i + 1); 538 } 539 break; 540 } 541 } while (i >= 0); 542 return new GenMatrix<C>(this, mat); 543 } 544 545 546 /** 547 * parse a matrix from a Reader. 548 */ 549 public GenMatrix<C> parse(Reader r) { 550 String s = StringUtil.nextPairedString(r, '[', ']'); 551 return parse(s); 552 } 553 554 }