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 }