package jaea.optimization.tools;
import java.io.BufferedReader;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.IOException;
import java.io.PrintStream;
/**
* Matrix class with standard matrix manipulation functions
*
* @author Le Minh Nghia, NTU-Singapore
*
*/
public class Matrix {
/**
* 2-D array to store matrix values
*/
public double[][] mat;
/**
* Dimensions
*/
public int row, col;
/**
* Indicate matrix with 0's
*/
final static public int M_ZEROS = 0;
/**
* Indicate matrix with 1's
*/
final static public int M_ONES = 1;
/**
* Indicate diagonal matrix
*/
final static public int M_DIAG = 2;
/**
* Get function
*/
public double[][] getMat() {
return mat;
}
/**
* Constructor
*
* @param r
* Number of rows
* @param c
* Number of columns
*/
public Matrix(int r, int c) {
row = r;
col = c;
mat = new double[row][col];
}
/**
* Constructor
*
* @param r
* Number of rows
* @param c
* Number of columns
* @param code
* Initialize matrix with 0's, 1's or diagonal
*/
public Matrix(int r, int c, int code) {
row = r;
col = c;
mat = new double[row][col];
switch (code) {
case Matrix.M_ZEROS:
for (int i = 0; i < row; i++)
for (int j = 0; j < col; j++)
mat[i][j] = 0;
break;
case Matrix.M_ONES:
for (int i = 0; i < row; i++)
for (int j = 0; j < col; j++)
mat[i][j] = 1;
break;
case Matrix.M_DIAG:
for (int i = 0; i < row; i++)
for (int j = 0; j < col; j++)
mat[i][j] = 0;
int a = (row < col) ? row : col;
for (int i = 0; i < a; i++)
mat[i][i] = 1;
break;
default:
break;
}
}
/**
* Constructor as matrix 'wrapper' for double [][] 2D array (copy by
* reference)
*/
public Matrix(double[][] srcMat) {
mat = srcMat;
row = mat.length;
col = mat[0].length;
}
/**
* Constructor as matrix 'wrapper' for double [] 1D array (copy by value)
*/
public Matrix(double[] srcMat) {
row = 1;
col = srcMat.length;
mat = new double[row][col];
for (int i = 0; i < col; i++)
mat[0][i] = srcMat[i];
}
/**
* Transpose function
*
* @param inMat
* Input matrix
* @return Transposed matrix
*/
public static Matrix transpose(Matrix inMat) {
double[][] temp = new double[inMat.col][inMat.row];
for (int i = 0; i < inMat.row; i++)
for (int j = 0; j < inMat.col; j++)
temp[j][i] = inMat.mat[i][j];
return new Matrix(temp);
}
/**
* Get i-th row as 1D array
*
* @param index
* Row index
*/
public double[] getFlatRow(int index) {
double[] rowMat = new double[this.col];
for (int i = 0; i < this.col; i++)
rowMat[i] = this.mat[index][i];
return rowMat;
}
/**
* Get i-th row as Matrix
*
* @param index
* Row index
*/
public Matrix getRow(int index) {
double[] rowMat = new double[this.col];
for (int i = 0; i < this.col; i++)
rowMat[i] = this.mat[index][i];
return new Matrix(rowMat);
}
/**
* Get i-th column as 1D array
*
* @param index
* Column index
*/
public double[] getFlatCol(int index) {
double[] colMat = new double[this.row];
for (int i = 0; i < this.row; i++)
colMat[i] = this.mat[i][index];
return colMat;
}
/**
* Get i-th column as Matrix
*
* @param index
* Column index
*/
public Matrix getCol(int index) {
double[][] colMat = new double[this.row][1];
for (int i = 0; i < this.row; i++)
colMat[i][0] = this.mat[i][index];
return new Matrix(colMat);
}
/**
* Copy value from source to dest array
*
* @param dest
* Destination 1D array
* @param src
* Source 1D array
*/
static public void copyArray(double[] dest, double[] src) {
if (dest.length != src.length) {
System.err.println("Array mismatched...");
return;
}
for (int i = 0; i < dest.length; i++) {
dest[i] = src[i];
}
}
/**
* Multiply matrices
*
* @param A
* Input matrix
* @param B
* Input matrix
* @return Matrix C = A*B
*/
public static Matrix multiply(Matrix A, Matrix B) {
double[][] res = new double[A.row][B.col];
for (int i = 0; i < A.row; i++)
for (int j = 0; j < B.col; j++) {
double temp = 0;
for (int k = 0; k < A.col; k++)
if (Math.abs(A.mat[i][k]) > 1E-9
&& Math.abs(B.mat[k][j]) > 1E-9)
temp += A.mat[i][k] * B.mat[k][j];
res[i][j] = temp;
}
return (new Matrix(res));
}
/**
* Multiply matrix with scalar
*
* @param A
* Input matrix
* @param d
* Scalar value
* @return Matrix C = d*A
*/
public static Matrix multiply(Matrix A, double d) {
double[][] res = new double[A.row][A.col];
for (int i = 0; i < A.row; i++)
for (int j = 0; j < A.col; j++) {
res[i][j] = d * A.mat[i][j];
}
return (new Matrix(res));
}
/**
* Add matrices
*
* @param A
* Input matrix
* @param B
* Input matrix
* @return Matrix C = A + B
*/
public static Matrix add(Matrix A, Matrix B) {
double[][] res = new double[A.row][A.col];
for (int i = 0; i < A.row; i++)
for (int j = 0; j < A.col; j++) {
res[i][j] = A.mat[i][j] + B.mat[i][j];
}
return (new Matrix(res));
}
/**
* Add matrix and scalar
*
* @param A
* Input matrix
* @param d
* Scalar value
*/
public static Matrix add(Matrix A, double d) {
double[][] res = new double[A.row][A.col];
for (int i = 0; i < A.row; i++)
for (int j = 0; j < A.col; j++) {
res[i][j] = A.mat[i][j] + d;
}
return (new Matrix(res));
}
/**
* Generate a m-by-n tiling of copies of input matrix
*
* @param matIn
* Input matrix
* @param m
* @param n
*/
public static Matrix repmat(Matrix matIn, int m, int n) {
int r = matIn.row;
int c = matIn.col;
double[][] res = new double[m * r][n * c];
for (int outR = 0; outR < m; outR++)
for (int outC = 0; outC < n; outC++) {
int indexR = outR * r;
int indexC = outC * c;
for (int i = 0; i < r; i++)
for (int j = 0; j < c; j++)
res[indexR + i][indexC + j] = matIn.mat[i][j];
}
Matrix resM = new Matrix(res);
return resM;
}
/**
* Return lower triangular part of matrix
*
* @param matIn
* Input matrix
* @return Lower triangular matrix
*/
public static Matrix tril(Matrix matIn) {
int r = matIn.row;
int c = matIn.col;
int n = (r <= c) ? r : c;
double[][] res = new double[n][n];
for (int i = 0; i < n; i++)
for (int j = 0; j < n; j++)
if (j <= i)
res[i][j] = matIn.mat[i][j];
else
res[i][j] = 0;
Matrix resM = new Matrix(res);
return resM;
}
/**
* Copy rows from srcMat to rows in destMat
*
* @param destMat
* Destination matrix
* @param destInd
* Row indices of destination matrix
* @param srcMat
* Source matrix
* @param srcInd
* Row indices of source matrix to be copied from
*/
public static void copyRows(Matrix destMat, int[] destInd, Matrix srcMat,
int[] srcInd) {
if (srcInd.length != destInd.length) {
System.err.println("Index mismatched...");
return;
}
if (destMat.col != srcMat.col) {
System.err.println("Matrix mismatched...");
return;
}
int nRows = destInd.length;
for (int n = 0; n < nRows; n++) {
for (int c = 0; c < srcMat.col; c++)
destMat.mat[destInd[n]][c] = srcMat.mat[srcInd[n]][c];
}
}
/**
* Copy columns from srcMat to columns in destMat
*
* @param destMat
* Destination matrix
* @param destInd
* Column indices of destination matrix
* @param srcMat
* Source matrix
* @param srcInd
* Column indices of source matrix
*/
public static void copyCols(Matrix destMat, int[] destInd, Matrix srcMat,
int[] srcInd) {
if (srcInd.length != destInd.length) {
System.err.println("Index mismatched...");
return;
}
if (destMat.row != srcMat.row) {
System.err.println("Matrix mismatched...");
return;
}
int nCols = destInd.length;
for (int n = 0; n < nCols; n++) {
for (int r = 0; r < srcMat.row; r++)
destMat.mat[r][destInd[n]] = srcMat.mat[r][srcInd[n]];
}
}
/**
* Subtraction operator
*
* @param A
* Input matrix
* @param B
* Input matrix
* @return Matrix C = A - B
*/
public static Matrix substract(Matrix A, Matrix B) {
double[][] res = new double[A.row][A.col];
for (int i = 0; i < A.row; i++)
for (int j = 0; j < A.col; j++) {
res[i][j] = A.mat[i][j] - B.mat[i][j];
}
return (new Matrix(res));
}
/**
* Write matrix to file in CSV format
*
* @param filename
* Output file name
* @param matC
* Matrix
*/
static public void DMat2File(String filename, Matrix matC) {
double[][] matrix = matC.mat;
/* prepare log file */
PrintStream MyOutput = null;
try {
MyOutput = new PrintStream(new FileOutputStream(filename));
} catch (IOException e) {
System.out.println("IO Error in Mat2File");
}
// output all population
int maxRow = matC.row;
int maxCol = matC.col;
MyOutput.println(maxRow);
MyOutput.println(maxCol);
for (int i = 0; i < maxRow; i++) {
for (int j = 0; j < maxCol; j++)
if (j < maxCol - 1)
MyOutput.print(matrix[i][j] + ",");
else
MyOutput.println(matrix[i][j]);
}
}
/**
* Read matrix from file in CSV format [row \n col \n matrix]
*/
static public Matrix File2DMat(String filename) {
try {
FileReader fr = new FileReader(filename);
BufferedReader input = new BufferedReader(fr);
String s = "";
/* Pass 2 first lines */
s = input.readLine();
int N = Integer.parseInt(s);
s = input.readLine();
int dim = Integer.parseInt(s);
double[][] matrix = new double[N][dim];
int count = 0;
do {
s = input.readLine();
if (s != null) {
String[] params = s.split(",");
for (int k = 0; k < params.length; k++)
matrix[count][k] = Double.parseDouble(params[k]);
count++;
}
} while (s != null);
fr.close();
Matrix res = new Matrix(matrix);
return res;
} catch (IOException e) {
System.out.println(e.toString());
return null;
}
}
public String toString() {
String res = "";
for (int i = 0; i < row; i++) {
for (int j = 0; j < col; j++)
if (j == col - 1)
res += mat[i][j] + "\n";
else
res += mat[i][j] + ", ";
}
return res;
}
/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
// Matrix A = new Matrix(4,4,Matrix.M_ONES);
// Matrix B = new Matrix(4,4,Matrix.M_DIAG);
// Matrix C = Matrix.multiply(Matrix.add(A, B),B);
// System.out.println("A: \n" + A.toString());
// System.out.println("B: \n" + B.toString());
// System.out.println("C: \n" + C.toString());
// Matrix.DMat2File("C.csv", C);
Matrix T = Matrix.File2DMat("C.csv");
System.out.println(T.toString());
}
}