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