com.actelion.research.calc.Matrix Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of openchemlib Show documentation
Show all versions of openchemlib Show documentation
Open Source Chemistry Library
/*
* Copyright (c) 1997 - 2016
* Actelion Pharmaceuticals Ltd.
* Gewerbestrasse 16
* CH-4123 Allschwil, Switzerland
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. Neither the name of the the copyright holder nor the
* names of its contributors may be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
package com.actelion.research.calc;
import com.actelion.research.util.DoubleVec;
import com.actelion.research.util.convert.String2DoubleArray;
import com.actelion.research.util.datamodel.IntegerDouble;
import com.actelion.research.util.datamodel.ScorePoint;
import java.awt.*;
import java.io.*;
import java.text.DecimalFormat;
import java.text.DecimalFormatSymbols;
import java.text.NumberFormat;
import java.util.List;
import java.util.*;
public class Matrix {
public static final double TINY04 = 0.0001;
public static final double TINY08 = 0.00000001;
public static final double TINY16 = Math.pow(10, -16);
public static String OUT_SEPARATOR_COL = "\t";
public static String OUT_SEPARATOR_ROW = "\n";
private final static String FORMAT = "0.############";
public static final double TINY = 10e-12;
private double [][] data;
private int identifier;
public Matrix() {
data = new double[1][1];
}
public Matrix(int rows, int cols) {
data = new double[rows][cols];
}
public Matrix(Matrix ma) {
this(ma.getArray());
}
/**
*
* @param row if true the matrix has one row. If false the matrix has one column.
* @param arr
*/
public Matrix(boolean row, double [] arr) {
if (row) {
data = new double[1][];
data[0]=arr;
}
else {
data = new double[arr.length][1];
for (int i = 0; i < getRowDim(); i++) {
data[i][0] = arr[i];
}
}
}
public Matrix(boolean row, byte [] arr) {
if (row) {
data = new double[1][arr.length];
for (int i = 0; i < arr.length; i++) {
data[0][i]=arr[i];
}
}
else {
data = new double[arr.length][1];
for (int i = 0; i < getRowDim(); i++) {
data[i][0] = arr[i];
}
}
}
public Matrix(boolean row, int [] dArray) {
if (row) {
data = new double[1][dArray.length];
for (int jj = 0; jj < getColDim(); jj++) {
data[0][jj] = dArray[jj];
}
}
else {
data = new double[dArray.length][1];
for (int ii = 0; ii < getRowDim(); ii++) {
data[ii][0] = dArray[ii];
}
}
}
/**
* Deep copy
* @param arrArr
*/
public Matrix(double [][]arrArr) {
data = new double[arrArr.length][];
int rows = arrArr.length;
int cols = arrArr[0].length;
for (int i = 0; i < rows; i++) {
double [] arr = new double [cols];
System.arraycopy(arrArr[i], 0, arr, 0, cols);
data[i] = arr;
}
}
public Matrix(double [][]arrArr, boolean flat) {
if(!flat){
throw new RuntimeException("Only flat constructor!");
}
data = arrArr;
}
public Matrix(float [][]arrArr) {
data = new double[arrArr.length][arrArr[0].length];
int rows = arrArr.length;
int cols = arrArr[0].length;
for (int i = 0; i < rows; i++) {
double [] arr = new double [cols];
for (int j = 0; j < arr.length; j++) {
data[i][j] = arrArr[i][j];
}
}
}
public Matrix(int [][]arrArr) {
data = new double[arrArr.length][];
int rows = arrArr.length;
int cols = arrArr[0].length;
// 29.06.2012 System.arrayCopy gave ArrayStoreException.
for (int i = 0; i < rows; i++) {
double [] arr = new double [cols];
for (int j = 0; j < cols; j++) {
arr[j]=arrArr[i][j];
}
data[i] = arr;
}
}
public Matrix(byte [][]arrArr) {
data = new double[arrArr.length][];
int rows = arrArr.length;
int cols = arrArr[0].length;
for (int i = 0; i < rows; i++) {
double [] arr = new double [cols];
System.arraycopy(arrArr[i], 0, arr, 0, cols);
data[i] = arr;
}
}
/**
*
* @param vecDoubleVec Vector with DoubleVec
*/
public Matrix(List vecDoubleVec) {
DoubleVec dv = (DoubleVec) vecDoubleVec.get(0);
data = new double[vecDoubleVec.size()][dv.size()];
for (int ii = 0; ii < getRowDim(); ii++) {
dv = (DoubleVec) vecDoubleVec.get(ii);
for (int jj = 0; jj < getColDim(); jj++) {
data[ii][jj] = dv.get(jj);
}
}
}
public Matrix(boolean bRow, List liDoubles) {
if (bRow) {
data = new double[1][liDoubles.size()];
for (int i = 0; i < getColDim(); i++) {
data[0][i] = liDoubles.get(i);
}
}
else {
data = new double[liDoubles.size()][1];
for (int i = 0; i < getRowDim(); i++) {
data[i][0] = liDoubles.get(i);
}
}
}
public Matrix add(double v) {
int r = rows();
int c = cols();
Matrix A = new Matrix(r,c);
for (int i = 0; i < r; i++) {
for (int j = 0; j < c; j++) {
double s = get(i,j) + v;
A.set(i,j,s);
}
}
return A;
}
/**
*
* @param arr adds a row at the end of the matrix.
*/
public void addRow(double [] arr) {
if(getColDim() != arr.length) {
throw new RuntimeException("Matrices have wrong dimensions.");
}
resize(getRowDim() + 1, getColDim());
for (int ii = 0; ii < arr.length; ii++)
data[getRowDim() - 1][ii] = arr[ii];
}
public void addRow(int [] arr) {
if(getColDim() != arr.length) {
throw new RuntimeException("Matrices have wrong dimensions.");
}
resize(getRowDim() + 1, getColDim());
for (int ii = 0; ii < arr.length; ii++)
data[getRowDim() - 1][ii] = arr[ii];
}
/**
* @param row where the data are added on
* @param ma2 matrix from where the data are taken
* @param row2 data row
*/
public void add2Row(int row, Matrix ma2, int row2) {
for (int ii = 0; ii < getColDim(); ii++)
data[row][ii] += ma2.data[row2][ii];
}
public void addToElement(int i, int j, double value) {
data[i][j]+=value;
}
/**
* The value in the col from the input matrix is
* added to all values in the corresponding col in the matrix.
* @param maRow matrix with one row.
*/
public Matrix add2CompleteCol(Matrix maRow) {
Matrix m = new Matrix(this);
for (int ii = 0; ii < getRowDim(); ii++)
for (int jj = 0; jj < getColDim(); jj++)
m.data[ii][jj] += maRow.data[0][jj];
return m;
}
public void assignCol(int iCol, Matrix ma) {
if(getRowDim() != ma.getRowDim()) {
throw new RuntimeException("Matrices have wrong dimensions.");
}
for (int ii = 0; ii < data.length; ii++) {
data[ii][iCol] = ma.data[ii][0];
}
}
public void assignCol(int iCol, Matrix ma, int iColMa) {
if(getRowDim() != ma.getRowDim()) {
throw new RuntimeException("Matrices have wrong dimensions.");
}
for (int ii = 0; ii < data.length; ii++) {
data[ii][iCol] = ma.data[ii][iColMa];
}
}
public void assignRow(int iRow, Vector vecRow) {
if(getColDim() != vecRow.size()) {
throw new RuntimeException("Matrix and Vector have wrong dimensions.");
}
for (int jj = 0; jj < data[0].length; jj++) {
data[iRow][jj] = vecRow.get(jj);
}
}
public void assignRow(int iRow, double [] arr) {
if(getColDim() != arr.length) {
throw new RuntimeException("Matrix and Vector have wrong dimensions.");
}
for (int jj = 0; jj < arr.length; jj++) {
data[iRow][jj] = arr[jj];
}
}
public void assignRow(int iRow, int [] arr) {
if(getColDim() != arr.length) {
throw new RuntimeException("Matrix and Vector have wrong dimensions.");
}
for (int jj = 0; jj < arr.length; jj++) {
data[iRow][jj] = arr[jj];
}
}
public void assignRow(int iRow, DoubleVec dv) {
if(getColDim() != dv.size()) {
throw new RuntimeException("Matrix and Vector have wrong dimensions.");
}
for (int jj = 0; jj < dv.size(); jj++) {
data[iRow][jj] = dv.get(jj);
}
}
public boolean containsRow(DoubleVec dv) {
boolean bOK = false;
int iRows = getRowDim();
int iCols = getColDim();
for(int ii=0; ii < iRows; ii++) {
bOK = true;
for (int jj = 0; jj < iCols; jj++)
if (data[ii][jj] != dv.get(jj)) {
bOK = false;
break;
}
if(bOK)
break;
}
return bOK;
}
/**
* Copies a matrix ma into this, the pointer to ma1 is not changed.
* @param maSource
*/
public void copy(Matrix maSource) {
int rows = maSource.rows();
int cols = maSource.cols();
if (rows() == rows && cols() == cols) {
for (int i = 0; i < rows; i++) {
System.arraycopy(maSource.data[i], 0, data[i], 0, cols);
}
} else {
data = new double[rows][];
for (int i = 0; i < rows; i++) {
double[] a = new double[cols];
System.arraycopy(maSource.data[i], 0, a, 0, cols);
data[i] = a;
}
}
}
/**
* This (target matrix) must have appropriate dimensions.
* @param offsetRows
* @param maSource
*/
public void copy(int offsetRows, Matrix maSource) {
if(cols() != maSource.cols()){
throw new RuntimeException("Matrix col dimension error. Number of cols differ!");
}
int cols = cols();
int r = maSource.rows();
for (int i = 0; i < r; i++) {
System.arraycopy(maSource.data[i], 0, data[offsetRows+i], 0, cols);
}
}
public void copyColumn(Matrix maSource, int colSource, int colDestination) {
int rows = maSource.rows();
for (int i = 0; i < rows; i++) {
data[i][colDestination] = maSource.get(i, colSource);
}
}
final public double get(final int row, final int col) {
return data[row][col];
}
public Matrix getAbs() {
Matrix ma = new Matrix(getRowDim(), getColDim());
for (int ii = 0; ii < getRowDim(); ii++) {
for (int jj = 0; jj < getColDim(); jj++) {
ma.data[ii][jj] = Math.abs(data[ii][jj]);
}
}
return ma;
}
final public double [][] getArray() {
return data;
}
public int [][] getArrayAsInt() throws NumberFormatException {
int [][] arr = new int[data.length][data[0].length];
for (int ii = 0; ii < getRowDim(); ii++) {
for (int jj = 0; jj < getColDim(); jj++) {
if(data[ii][jj] > Integer.MAX_VALUE ||
data[ii][jj] < Integer.MIN_VALUE) {
String err = "Double value instead of int " + data[ii][jj] + ".";
throw new NumberFormatException(err);
}
arr[ii][jj] = (int)data[ii][jj];
}
}
return arr;
}
public double [][] getArrayCopy() {
double [][] arr = new double[data.length][data[0].length];
for (int ii = 0; ii < getRowDim(); ii++) {
for (int jj = 0; jj < getColDim(); jj++) {
arr[ii][jj] = data[ii][jj];
}
}
return arr;
}
/**
*
* @return column wise centered matrix.
*/
public Matrix getCenteredMatrix() {
final int cols = cols();
final int rows = rows();
double [][] arr = new double[rows][];
Matrix maMean = getMeanCols();
double [] arrMean = maMean.getRow(0);
for (int i = 0; i < rows; i++) {
double [] arrRowSrc = getRow(i);
double [] arrRow = new double [cols];
System.arraycopy(arrRowSrc, 0, arrRow, 0, arrRowSrc.length);
for (int j = 0; j < cols; j++) {
arrRow[j] = arrRow[j] - arrMean[j];
}
arr[i]=arrRow;
}
Matrix ma = new Matrix();
ma.setFlat(arr);
return ma;
}
public Matrix getCenteredMatrix(Matrix maMean) {
Matrix ma = new Matrix(getRowDim(), getColDim());
for (int i = 0; i < rows(); i++) {
for (int j = 0; j < cols(); j++) {
ma.data[i][j] = data[i][j] - maMean.data[0][j];
}
}
return ma;
}
public Matrix getCol(int col) {
Matrix ma = new Matrix(rows(), 1);
int iRows = getRowDim();
for(int i=0; i < iRows; i++){
ma.data[i][0] = data[i][col];
}
return ma;
}
public Matrix removeCol(int col2Remove) {
int r = rows();
int c = cols();
Matrix ma = new Matrix(r,c-1);
for(int i=0; i < r; i++){
int ccColNew=0;
for (int j = 0; j < c; j++) {
if(j!=col2Remove) {
ma.data[i][ccColNew++] = data[i][j];
}
}
}
return ma;
}
public double [] getColAsDouble(int col) {
double [] arr = new double [rows()];
for(int i=0; i < rows(); i++){
arr[i] = data[i][col];
}
return arr;
}
public List getColAsList(int col) {
List li = new ArrayList(rows());
for(int i=0; i < rows(); i++){
li.add(data[i][col]);
}
return li;
}
public float [] getColAsFloat(int iCol) {
float [] arr = new float [rows()];
for(int i=0; i < rows(); i++){
arr[i] = (float)data[i][iCol];
}
return arr;
}
public int [] getColAsInt(int iCol) {
int [] arr = new int [rows()];
for(int i=0; i < rows(); i++){
arr[i] = (int)(data[i][iCol]+0.5);
}
return arr;
}
/**
*
* @param vecIndices
* @return
* @deprecated use getColumns(List vecIndices) instead
*/
public Matrix getColumns(Vector vecIndices) {
Matrix maReduced = new Matrix(getRowDim(), vecIndices.size());
for (int i = 0; i < vecIndices.size(); i++) {
int col= vecIndices.get(i);
maReduced.assignCol(i, this, col);
}
return maReduced;
}
public Matrix getColumns(List liIndex) {
Matrix maReduced = new Matrix(getRowDim(), liIndex.size());
for (int i = 0; i < liIndex.size(); i++) {
int col = liIndex.get(i);
maReduced.assignCol(i, this, col);
}
return maReduced;
}
public Matrix getColumns(int [] arrIndex) {
Matrix maReduced = new Matrix(getRowDim(), arrIndex.length);
for (int i = 0; i < arrIndex.length; i++) {
int col = arrIndex[i];
maReduced.assignCol(i, this, col);
}
return maReduced;
}
public int getColDim() {
return data[0].length;
}
public int cols() {
return data[0].length;
}
/**
* Deletes columns with zero variance.
* @param vecIndices the integer vector is filled with the indices from the input
* matrix which are taken for the new matrix.
* @return input matrix reduced by all cols with zero variance.
*/
public Matrix getDeleteColsZeroVar(List vecIndices) {
vecIndices.clear();
Matrix maReduced = new Matrix(0,0);
Matrix maVar = getVarianceCols();
vecIndices.clear();
for(int ii = 0; ii < maVar.getColDim(); ii++) {
if(maVar.get(0,ii) > 0) {
vecIndices.add(new Integer(ii));
}
}
maReduced = getColumns(vecIndices);
return maReduced;
}
/** Generate a covariance matrix, each column contains values of a pulling.
@return An n-by-n matrix.
*/
/*T
Matrix A = Matrix.random(4,4);Matrix B = A.covariance();
A
B
*/
public Matrix covariance() {
int n = getColDim();
int m = getRowDim();
Matrix X = new Matrix(n, n);
int degrees = (m - 1);
double c;
double s1;
double s2;
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
c = 0;
s1 = 0;
s2 = 0;
for (int k = 0; k < m; k++) {
s1 += this.get(k, i);
s2 += this.get(k, j);
}
s1 = s1 / m;
s2 = s2 / m;
for (int k = 0; k < m; k++) {
c += (this.get(k, i) - s1) * (this.get(k, j) - s2);
}
X.set(i, j, c / degrees);
}
}
return X;
}
/** Generate a correlation matrix, each column contains values of a pulling.
@return An n-by-n matrix.
*/
/*T
Matrix A = Matrix.random(4,4);Matrix B = A.correlation();
A
B
*/
public Matrix correlation() {
int n = getColDim();
int m = getRowDim();
Matrix X = new Matrix(n, n);
int degrees = (m - 1);
Matrix V = new Matrix(n, n);
double c;
double s1;
double s2;
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
c = 0;
s1 = 0;
s2 = 0;
for (int k = 0; k < m; k++) {
s1 += this.get(k, i);
s2 += this.get(k, j);
}
s1 = s1 / m;
s2 = s2 / m;
for (int k = 0; k < m; k++) {
c += (this.get(k, i) - s1) * (this.get(k, j) - s2);
}
V.set(i, j, c / degrees);
}
}
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
X.set(i, j, V.get(i, j) / Math.sqrt(V.get(i, i) * V.get(j, j)));
}
}
return X;
}
/**
* Matrix diagonal extraction.
* @return An d*1 Matrix of diagonal elements, d = min(m,n).
*/
public Matrix getDiagonal() {
int n = Math.min(getRowDim(), getColDim());
Matrix ma = new Matrix(n,1);
for (int i = 0; i < n; i++) {
ma.set(i,0, data[i][i]);
}
return ma;
}
public Matrix getLinedCol() {
Matrix ma = new Matrix(getNumElements(), 1);
int ind = 0;
for (int i = 0; i < getRowDim(); i++) {
for (int j = 0; j < getColDim(); j++) {
ma.data[ind][0] = data[i][j];
ind++;
}
}
return ma;
}
public List getList() {
List li = new ArrayList(getRowDim()*getColDim());
for (int i = 0; i < getRowDim(); i++) {
for (int j = 0; j < getColDim(); j++) {
li.add(data[i][j]);
}
}
return li;
}
public Matrix getMatrix (int i0, int i1, int j0, int j1) {
Matrix X = new Matrix(i1-i0+1,j1-j0+1);
double[][] B = X.getArray();
try {
for (int i = i0; i <= i1; i++) {
for (int j = j0; j <= j1; j++) {
B[i-i0][j-j0] = data[i][j];
}
}
} catch(ArrayIndexOutOfBoundsException e) {
throw new ArrayIndexOutOfBoundsException("Submatrix indices");
}
return X;
}
/** Get a submatrix.
@param r Array of row indices.
@param c Array of column indices.
@return A(r(:),c(:))
@exception ArrayIndexOutOfBoundsException Submatrix indices
*/
public Matrix getMatrix (int[] r, int[] c) {
Matrix X = new Matrix(r.length,c.length);
double[][] B = X.getArray();
try {
for (int i = 0; i < r.length; i++) {
for (int j = 0; j < c.length; j++) {
B[i][j] = data[r[i]][c[j]];
}
}
} catch(ArrayIndexOutOfBoundsException e) {
throw new ArrayIndexOutOfBoundsException("Submatrix indices");
}
return X;
}
/** Get a submatrix.
@param i0 Initial row index
@param i1 Final row index
@param c Array of column indices.
@return A(i0:i1,c(:))
@exception ArrayIndexOutOfBoundsException Submatrix indices
*/
public Matrix getMatrix (int i0, int i1, int[] c) {
Matrix X = new Matrix(i1-i0+1,c.length);
double[][] B = X.getArray();
try {
for (int i = i0; i <= i1; i++) {
for (int j = 0; j < c.length; j++) {
B[i-i0][j] = data[i][c[j]];
}
}
} catch(ArrayIndexOutOfBoundsException e) {
throw new ArrayIndexOutOfBoundsException("Submatrix indices");
}
return X;
}
/** Get a submatrix.
@param r Array of row indices.
@param j0 Initial column index
@param j1 Final column index
@return A(r(:),j0:j1)
@exception ArrayIndexOutOfBoundsException Submatrix indices
*/
public Matrix getMatrix (int[] r, int j0, int j1) {
Matrix X = new Matrix(r.length,j1-j0+1);
double[][] B = X.getArray();
try {
for (int i = 0; i < r.length; i++) {
for (int j = j0; j <= j1; j++) {
B[i][j-j0] = data[r[i]][j];
}
}
} catch(ArrayIndexOutOfBoundsException e) {
throw new ArrayIndexOutOfBoundsException("Submatrix indices");
}
return X;
}
public int getNumElements() {
return cols() * rows();
}
public int getNumElementsLarger(double val2Compare) {
int ind = 0;
for (int i = 0; i < rows(); i++) {
for (int j = 0; j < cols(); j++) {
if(data[i][j]>val2Compare)
ind++;
}
}
return ind;
}
public int getNumElementsEqual(double val2Compare) {
int ind = 0;
for (int i = 0; i < rows(); i++) {
for (int j = 0; j < cols(); j++) {
if(data[i][j]==val2Compare)
ind++;
}
}
return ind;
}
/**
* Log function from the class Math .
* @return matrix with the natural logarithm (base e) of a double value.
*/
public Matrix log() {
Matrix maResult = new Matrix(getRowDim(), getColDim());
for (int i = 0; i < rows(); i++) {
for (int j = 0; j < cols(); j++) {
if(data[i][j] > 0) {
maResult.data[i][j] = Math.log(data[i][j]);
} else {
maResult.data[i][j] = 0.0;
}
}
}
return maResult;
}
public Matrix diagonalize() {
Matrix maResult = new Matrix();
if((getRowDim() > 1) && (cols() == 1)) {
maResult.resize(rows(), rows());
for (int i = 0; i < maResult.rows(); i++) {
maResult.data[i][i] = data[i][0];
}
} else if((cols() > 1) && (rows() == 1)) {
maResult.resize(cols() , cols());
for (int i = 0; i < maResult.cols(); i++) {
maResult.data[i][i] = data[0][i];
}
}
return maResult;
}
public Matrix devide(double dDivisor) {
Matrix maResult = new Matrix(getRowDim(), getColDim());
for (int i = 0; i < getRowDim(); i++) {
for (int j = 0; j < getColDim(); j++) {
maResult.data[i][j] = data[i][j] / dDivisor;
}
}
return maResult;
}
public Matrix devide(Matrix maDivisor) {
Matrix maResult = new Matrix(getRowDim(), getColDim());
for (int i = 0; i < getRowDim(); i++) {
for (int j = 0; j < getColDim(); j++) {
maResult.data[i][j] = data[i][j] / maDivisor.data[i][j];
}
}
return maResult;
}
public Matrix devideDivisorBigger(Matrix maDivisor) {
Matrix maResult = new Matrix(getRowDim(), getColDim());
for (int i = 0; i < getRowDim(); i++) {
for (int j = 0; j < getColDim(); j++) {
if(data[i][j] < maDivisor.data[i][j]) {
maResult.data[i][j] = data[i][j] / maDivisor.data[i][j];
} else {
maResult.data[i][j] = maDivisor.data[i][j] / data[i][j] ;
}
}
}
return maResult;
}
public Matrix devideCols(Matrix maDivisor) {
Matrix maResult = new Matrix(getRowDim(), getColDim());
for (int i = 0; i < getRowDim(); i++) {
for (int j = 0; j < getColDim(); j++) {
maResult.data[i][j] = data[i][j] / maDivisor.get(0,j);
}
}
return maResult;
}
public void devideRow(int row, double denominator) {
for (int j = 0; j < getColDim(); j++) {
data[row][j] /= denominator;
}
}
/*
public static void getEigenvectorBig(Matrix a, int n, Matrix d, Matrix e)
{
mt.DenseMatrix A = new mt.DenseMatrix(a.mData);
// mt.Matrix B = new mt.DenseMatrix(ma.mData);
// mt.Matrix C = new mt.DenseMatrix(getRowDim(), ma.getColDim());
// maResult = new Matrix(mt.util.Matrices.getArray(C));
mt.fact.EigenvalueComputer evc = new mt.fact.EigenvalueComputer(a.getRowDim());
try {
EigenvalueDecomposition evd = evc.factor(A);
double [] arrEV = evd.getRealEigenvalues();
d.resize(arrEV.length,1);
for (int ii = 0; ii < arrEV.length; ii++) {
d.set(ii, 0, arrEV[ii]);
}
a.set(mt.util.Matrices.getArray(evd.getLeftEigenvectors()));
e.set(mt.util.Matrices.getArray(evd.getRightEigenvectors()));
}
catch (NotConvergedException ex) {
ex.printStackTrace();
}
}
*/
/**
* Householder reduction according num rec 11.2.
* Followed from an Eigen value decomposition with the calculation of the
* Eigen vectors according num rec 11.3.
* @param A intercept input matrix
* @param n number of considered eigen values
* @param D
* @param E
*/
final public static void getEigenvector(Matrix A, int n, Matrix D, Matrix E) {
int l,k,j, i;
double scale,hh,h,g,f;
double [] a = A.toArray();
double [] d = new double [n];
double [] e = new double [n];
int cols = n;
// Householder reduction of a real, symmetric matrix
for (i = n-1; i >= 1; i--) {
l = i;
h = scale = 0.0;
if (l > 0) {
for (k = 0; k < l; k++)
scale += Math.abs(a[i * cols + k]);
if (scale == 0.0)
e[i] = a[i * cols + l-1];
else {
for (k = 0; k < l; k++) {
a[i * cols + k] /= scale;
h += a[i * cols + k] * a[i * cols + k];
}
f = a[i * cols + l-1];
g = (f >= 0.0 ? - Math.sqrt(h) : Math.sqrt(h));
e[i] = scale * g;
h -= f * g;
a[i * cols + l-1] = f - g;
f = 0.0;
for (j = 0; j < l; j++) {
a[j * cols + i] = a[i * cols + j] / h;
g = 0.0;
for (k = 0; k < j+1; k++)
g += a[j * cols + k] * a[i * cols + k];
for (k = j+1; k < l; k++)
g += a[k * cols + j] * a[i * cols + k];
e[j] = g / h;
f += e[j] * a[i * cols + j];
}
hh = f / (h + h);
for (j = 0; j < l; j++) {
f=a[i * cols + j];
e[j]= g = e[j] - hh * f;
for (k = 0; k < j+1; k++)
a[j * cols + k] -= (f * e[k] + g * a[i * cols + k]);
}
}
} else
e[i] = a[i * cols + l-1];
d[i] = h;
}
d[0] = 0.0;
e[0] = 0.0;
// Contents of this loop can be omitted if Eigen vectors not
// wanted except for statement d[i]=a[i * cols + i]
for (i = 0; i < n; i++) {
l = i;
if (d[i] != 0) {
for (j = 0; j < l; j++) {
g = 0.0;
for (k = 0; k < l; k++)
g += a[i * cols + k] * a[k * cols + j];
for (k = 0; k < l; k++)
a[k * cols + j] -= g * a[k * cols + i];
}
}
d[i] = a[i * cols + i];
a[i * cols + i] = 1.0;
for (j = 0; j < l; j++)
a[j * cols + i] = a[i * cols + j] = 0.0;
}
// Eigen values and Eigen vectors of a trigiagonal matrix
// void tqli(float d[], float e[], int n, float **z)
int m,iter;
double s,r,p,dd,c,b;
for (i = 1; i < n; i++)
e[i - 1] = e[i];
e[n-1] = 0.0;
for (l = 0; l < n; l++) {
iter = 0;
do {
for (m = l; m <= n-2; m++) {
dd = Math.abs(d[m]) + Math.abs(d[m + 1]);
if ((double)(Math.abs(e[m]) + dd) == dd)
break;
}
if (m != l) {
if (iter++ == 30)
System.err.println("Too many iterations in tqli");
g=(d[l+1] - d[l]) / (2.0 * e[l]);
r = getPythag(g,1.0);
g=d[m] - d[l] + e[l] / (g + Sign(r,g)); // ??? Sign correct
s=c=1.0;
p=0.0;
for (i = m-1; i >= l; i--) {
f = s * e[i];
b = c * e[i];
e[i+1]= (r = getPythag(f,g));
if (r == 0.0) {
d[i+1] -= p;
e[m] = 0.0;
break;
}
s = f / r;
c = g / r;
g = d[i+1] - p;
r = (d[i] - g) * s + 2.0 * c * b;
d[i+1] = g + (p = s * r);
g = c * r - b;
for (k = 0; k < n; k++) {
f = a[k * cols + i + 1];
a[k * cols + i + 1] = s * a[k * cols + i] + c * f;
a[k * cols + i] = c * a[k * cols + i] - s * f;
}
}
if (r == 0.0 && i >= l)
continue;
d[l] -= p;
e[l] = g;
e[m] = 0.0;
}
} while (m != l);
}
for (int o = 0; o < A.rows(); o++) {
for (int q = 0; q < A.cols(); q++) {
A.set(o,q, a[o*n+q]);
}
}
D.resize(n, 1);
D.setCol(0, d);
E.resize(n, 1);
E.setCol(0, e);
return;
}
// public static void getEigenvector(MatrixK a, int n, MatrixK d, MatrixK e) {
// int l,k,j, i;
// double scale,hh,h,g,f;
//
// a.resize((n + 1), (n + 1));
// d.resize((n + 1), 1);
// e.resize((n + 1), 1);
//
// // Shift since routine works from indices 1..n and not from 0..n-1
// for (i = n; i > 0; i--)
// for (j = n; j > 0; j--)
// a.data[i][j] = a.data[i - 1][j - 1];
//
// // Householder reduction of a real, symmetric matrix
// for (i = n; i >= 2; i--) {
// l = i - 1;
// h = scale = 0.0;
// if (l > 1) {
// for (k = 1; k <= l; k++)
// scale += Math.abs(a.data[i][k]);
// if (scale == 0.0)
// e.data[i][0] = a.data[i][l];
// else {
// for (k = 1; k <= l; k++) {
// a.data[i][k] /= scale;
// h += a.data[i][k] * a.data[i][k];
// }
// f = a.data[i][l];
// g = (f >= 0.0 ? - Math.sqrt(h) : Math.sqrt(h));
// e.data[i][0] = scale * g;
// h -= f * g;
// a.data[i][l] = f - g;
// f = 0.0;
// for (j = 1; j <= l; j++) {
// a.data[j][i] = a.data[i][j] / h;
// g = 0.0;
// for (k = 1; k <= j; k++)
// g += a.data[j][k] * a.data[i][k];
// for (k = j + 1; k <= l; k++)
// g += a.data[k][j] * a.data[i][k];
// e.data[j][0] = g / h;
// f += e.data[j][0] * a.data[i][j];
// }
// hh = f / (h + h);
// for (j = 1; j <= l; j++) {
// f=a.data[i][j];
// e.data[j][0]= g = e.data[j][0] - hh * f;
// for (k = 1; k <= j; k++)
// a.data[j][k] -= (f * e.data[k][0] + g * a.data[i][k]);
// }
// }
// } else
// e.data[i][0] = a.data[i][l];
// d.data[i][0] = h;
// }
// d.data[1][0] = 0.0;
// e.data[1][0] = 0.0;
// // Contents of this loop can be omitted if eigenvectors not
// // wanted except for statement d[i]=a[i][i]
// for (i = 1; i <= n; i++) {
// l = i - 1;
// if (d.data[i][0] != 0) {
// for (j = 1; j <= l; j++) {
// g = 0.0;
// for (k = 1; k <= l; k++)
// g += a.data[i][k] * a.data[k][j];
// for (k = 1; k<= l; k++)
// a.data[k][j] -= g * a.data[k][i];
// }
// }
// d.data[i][0] = a.data[i][i];
// a.data[i][i] = 1.0;
// for (j = 1; j <= l; j++)
// a.data[j][i] = a.data[i][j] = 0.0;
// }
//
// // Eigenvalues and Eigenvectors of a trigiagonal matrix
// // void tqli(float d[], float e[], int n, float **z)
//
// int m,iter;
// double s,r,p,dd,c,b;
//
// for (i = 2; i <= n; i++)
// e.data[i - 1][0] = e.data[i][0];
// e.data[n][0] = 0.0;
//
// for (l = 1; l <= n; l++) {
// iter = 0;
// do {
// for (m = l; m <= n-1; m++) {
// dd = Math.abs(d.data[m][0]) + Math.abs(d.data[m + 1][0]);
//
// if ((double)(Math.abs(e.data[m][0]) + dd) == dd)
// break;
// }
// if (m != l) {
// if (iter++ == 30)
// System.err.println("Too many iterations in tqli");
// g=(d.data[l+1][0] - d.data[l][0]) / (2.0 * e.data[l][0]);
// r = getPythag(g,1.0);
// g=d.data[m][0] - d.data[l][0] + e.data[l][0] / (g + Sign(r,g)); // ??? Sign correct
//
// s=c=1.0;
// p=0.0;
// for (i=m-1;i>=l;i--) {
// f = s * e.data[i][0];
// b = c * e.data[i][0];
// e.data[i+1][0] = (r = getPythag(f,g));
// if (r == 0.0) {
// d.data[i+1][0] -= p;
// e.data[m][0] = 0.0;
// break;
// }
// s = f / r;
// c = g / r;
// g = d.data[i+1][0] - p;
// r = (d.data[i][0] - g) * s + 2.0 * c * b;
// d.data[i+1][0] = g + (p = s * r);
// g = c * r - b;
// for (k = 1; k <= n; k++) {
// f = a.data[k][i + 1];
// a.data[k][i + 1] = s * a.data[k][i] + c * f;
// a.data[k][i] = c * a.data[k][i] - s * f;
// }
// }
// if (r == 0.0 && i >= l)
// continue;
// d.data[l][0] -= p;
// e.data[l][0] = g;
// e.data[m][0] = 0.0;
// }
// } while (m != l);
// }
//
// // Shift back;
// for(i = 0; i < n; i++)
// for (j = 0; j < n; j++)
// a.data[i][j] = a.data[i + 1][j + 1];
//
// for(j = 0; j < n; j++)
// d.data[j][0] = d.data[j + 1][0];
//
// for(j = 0; j < n; j++)
// e.data[j][0] = e.data[j + 1][0];
//
// // Resize arrays properly
// a.resize(n, n);
// d.resize(n, 1);
// e.resize(n, 1);
//
// return;
// }
/**
*
* @param row row
* @return smallest value in specified row.
*/
public double getMinRow(int row) {
double val = Double.MAX_VALUE;
for (int i = 0; i < getColDim(); i++) {
if(data[row][i] < val) {
val = data[row][i];
}
}
return val;
}
/**
*
* @param row row
* @return the column index of the smallest value in the row.
*/
public int getMinRowIndex(int row) {
int index = 0;
double min = Double.MAX_VALUE;
for (int i = 0; i < getColDim(); i++) {
if(data[row][i] < min) {
min = data[row][i];
index = i;
}
}
return index;
}
/**
* 03.10.04 MvK
* Shuffles the indices before searching the minimum. This randomizes the
* search order.
* @param row row
* @return the column index of the smallest value in the row.
*/
public int getMinRowIndexRND(int row) {
int indexMin = 0;
List list = new ArrayList();
for (int i = 0; i < getColDim(); i++) {
list.add(new Integer(i));
}
Collections.shuffle(list);
int [] arrIndex = new int [getColDim()];
for (int i = 0; i < arrIndex.length; i++) {
arrIndex[i] = ((Integer) list.get(i)).intValue();
}
double min = Double.MAX_VALUE;
for (int i = 0; i < getColDim(); i++) {
int ind = arrIndex[i];
if (data[row][ind] < min) {
min = data[row][ind];
indexMin = ind;
}
}
return indexMin;
}
public int getID() {
return identifier;
}
/**
* Skipping the sqrt.
* @param iRow
* @param A
* @param iRowA
* @return
*/
public double getEuclideanDistanceFastRows(int iRow, Matrix A, int iRowA) {
double distance = 0;
int cols = cols();
for (int i = 0; i < cols; i++) {
distance += (data[iRow][i] - A.data[iRowA][i]) * (data[iRow][i] - A.data[iRowA][i]);
}
return distance;
}
/**
* Skipping the sqrt.
* @param row1
* @param row2
* @return
*/
public double getEuclideanDistanceFastRows(int row1, int row2) {
double distance = 0;
int cols = cols();
for (int i = 0; i < cols; i++) {
distance += (data[row1][i] - data[row2][i]) * (data[row1][i] - data[row2][i]);
}
return distance;
}
public double getMaximumValue() {
double max = Double.MIN_VALUE;
for (int i = 0; i < data.length; i++) {
for (int j = 0; j < data[0].length; j++) {
if(max < data[i][j])
max = data[i][j];
}
}
return max;
}
public double getMean() {
int cols = getColDim();
int rows = getRowDim();
double mean = getSum() / (cols * rows);
return mean;
}
public Matrix getMeanCols() {
final int cols = cols();
final int rows = rows();
final double [] a = new double [cols];
for (int i = 0; i < rows; i++) {
final double [] arrRow = data[i];
for (int j = 0; j < arrRow.length; j++) {
a[j] += arrRow[j];
}
}
for (int i = 0; i < cols; i++) {
a[i] /= rows;
}
return new Matrix(true, a);
}
public Matrix getMeanCols(int [] rowIndex) {
Matrix ma = new Matrix(1, getColDim());
int cols = getColDim();
for (int j = 0; j < cols; j++) {
ma.data[0][j] = getMeanCol(j, rowIndex);
}
return ma;
}
public double getMeanCol(int col) {
int rows = rows();
double sum = 0;
for (int i = 0; i < rows; i++) {
sum += data[i][col];
}
return sum / rows;
}
public double getMeanRow(int row) {
int iCols = getColDim();
double dMean = 0;
for (int i = 0; i < iCols; i++) {
dMean += data[row][i];
}
return dMean / iCols;
}
public Matrix getMeanRows() {
Matrix ma = new Matrix(1, getRowDim());
int iRows = getRowDim();
for (int i = 0; i < iRows; i++) {
ma.set(0,i,getMeanRow(i));
}
return ma;
}
public double getMeanCol(int iColIndex, int [] rowIndex) {
int iRows = getRowDim();
double dMean = 0;
for (int ii = 0; ii < rowIndex.length; ii++) {
dMean += data[rowIndex[ii]][iColIndex];
}
return dMean / iRows;
}
public double getMedian(int row) {
double [] arr = getRowCopy(row);
Arrays.sort(arr);
double median = 0;
int len = arr.length;
if(len % 2 != 0) {
median = arr[len / 2];
} else {
int ind = (int)(((double)len / 2.0)+0.5);
median = (arr[ind] + arr[ind-1]) / 2.0;
}
return median;
}
public double getMedian() {
int nRows = rows();
int nCols = cols();
double [] arr = new double [nRows*nCols];
int k = 0;
for (int i = 0; i < nRows; i++) {
for (int j = 0; j < nCols; j++) {
arr[k++]=get(i, j);
}
}
Arrays.sort(arr);
double median = 0;
int len = arr.length;
if(len % 2 != 0) {
median = arr[len / 2];
} else {
int ind = (int)(((double)len / 2.0)+0.5);
median = (arr[ind] + arr[ind-1]) / 2.0;
}
return median;
}
public Matrix getMedianCols() {
Matrix maMedian = new Matrix(1, cols());
int rows = rows();
int cols = cols();
double [] arr = new double [rows];
for (int i = 0; i < cols; i++) {
for (int j = 0; j < rows; j++) {
arr[j]=get(j,i);
}
Arrays.sort(arr);
double median = 0;
int len = arr.length;
if(len % 2 != 0) {
median = arr[len / 2];
} else {
int ind = (int)(((double)len / 2.0)+0.5);
median = (arr[ind] + arr[ind-1]) / 2.0;
}
maMedian.set(0, i, median);
}
return maMedian;
}
public Matrix getMergeRows(Matrix ma) {
Matrix maMerge = new Matrix(getRowDim() + ma.getRowDim(), getColDim());
for (int i = 0; i < getRowDim(); i++) {
for (int j = 0; j < getColDim(); j++) {
maMerge.data[i][j] = data[i][j];
}
}
int iRow = getRowDim();
for (int ii = 0; ii < ma.getRowDim(); ii++) {
for (int jj = 0; jj < getColDim(); jj++) {
maMerge.data[iRow + ii][jj] = ma.data[ii][jj];
}
}
return maMerge;
}
/**
* max and min vals for all cols
* @return matrix with two rows.
*/
public Matrix getMaxMin() {
Matrix maMaxMin = new Matrix(2, getColDim());
int cols = getColDim();
for (int i = 0; i < cols; i++) {
maMaxMin.set(1,i, getMin(i));
maMaxMin.set(0,i, getMax(i));
}
return maMaxMin;
}
/**
*
* @return
*/
public double getMax() {
int rows = getRowDim();
int cols = getColDim();
double dMax = -Double.MAX_VALUE;
for (int i = 0; i < rows; i++)
for (int j = 0; j < cols; j++)
if(data[i][j] > dMax)
dMax = data[i][j];
return dMax;
}
/**
* get max value for that col.
* @param col
* @return
*/
public double getMax(int col) {
int iRows = getRowDim();
double max = -Double.MAX_VALUE;
for (int i = 0; i < iRows; i++) {
if(data[i][col] > max)
max = data[i][col];
}
return max;
}
/**
*
* @return Point(row,col) for the largest value.
*/
public Point getMaxIndex() {
Point p = new Point(0,0);
int rows = rows();
int cols = cols();
double max = data[0][0];
for (int i = 0; i < rows; i++) {
for (int j = 0; j < cols; j++) {
if(data[i][j] > max) {
max = data[i][j];
p.y = i;
p.x = j;
}
}
}
return p;
}
public double getMaxRow(int row) {
double max = -Double.MAX_VALUE;
for (int i = 0; i < getColDim(); i++) {
if(data[row][i] > max)
max = data[row][i];
}
return max;
}
/**
* Shuffles the indices before searching the minimum.
* @param row row
* @return the column index of the largest value in the row.
*/
public int getMaxRowIndexRND(int row) {
int indexMax = 0;
List list = new ArrayList();
for (int i = 0; i < cols(); i++) {
list.add(i);
}
Collections.shuffle(list);
int [] arrIndex = new int [getColDim()];
for (int i = 0; i < arrIndex.length; i++) {
arrIndex[i] = ((Integer) list.get(i)).intValue();
}
double max = -Double.MAX_VALUE;
for (int i = 0; i < getColDim(); i++) {
int ind = arrIndex[i];
if (data[row][ind] > max) {
max = data[row][ind];
indexMax = ind;
}
}
return indexMax;
}
/**
* @param col
* @return the row index of the largest value in the col.
*/
public int getMaxRowIndex(int col) {
int row = -1;
double max = -Double.MAX_VALUE;
for (int i = 0; i < rows(); i++) {
if (data[i][col] > max) {
max = data[i][col];
row = i;
}
}
return row;
}
public double getMin() {
int rows = getRowDim();
int cols = getColDim();
double min = Double.MAX_VALUE;
for (int i = 0; i < rows; i++)
for (int j = 0; j < cols; j++)
if(data[i][j] < min)
min = data[i][j];
return min;
}
/**
*
* @return ValPos
*/
public ScorePoint getMinPos() {
int rows = getRowDim();
int cols = getColDim();
ScorePoint td = new ScorePoint();
td.setScore(Double.MAX_VALUE);
for (int i = 0; i < rows; i++)
for (int j = 0; j < cols; j++)
if(data[i][j] < td.getScore()) {
td.y = i;
td.x = j;
td.setScore(data[i][j]);
}
return td;
}
/**
*
* @return matrix with minimum value from each row.
*/
public Matrix getMinRows() {
int rows = getRowDim();
int cols = getColDim();
Matrix ma = new Matrix(rows, 1);
for (int i = 0; i < rows; i++) {
double dMin = Double.MAX_VALUE;
for (int j = 0; j < cols; j++)
if(data[i][j] < dMin)
dMin = data[i][j];
ma.set(i, 0, dMin);
}
return ma;
}
/**
*
* @return matrix dimension n,2. First row contains column position of min val,
* second col the min value.
*/
public Matrix getMinRowsPosCol() {
int rows = getRowDim();
int cols = getColDim();
Matrix ma = new Matrix(rows, 2);
for (int i = 0; i < rows; i++) {
double dMin = Double.MAX_VALUE;
for (int j = 0; j < cols; j++)
if(data[i][j] < dMin) {
ma.set(i, 0, j);
ma.set(i, 1, data[i][j]);
}
}
return ma;
}
public double getMin(int col) {
int rows = getRowDim();
double min = Double.MAX_VALUE;
for (int i = 0; i < rows; i++) {
if(data[i][col] < min)
min = data[i][col];
}
return min;
}
/**
*
* @param row
* @return column index for the field with the lowest value for the given row.
*/
public int getMinColIndex(int row) {
int cols = getColDim();
double min = Double.MAX_VALUE;
int ind = -1;
for (int i = 0; i < cols; i++) {
if(data[row][i] < min) {
min = data[row][i];
ind=i;
}
}
return ind;
}
/**
*
* @param row
* @return column index for the field with the largest value for the given row.
*/
public int getColIndexContainingMaxVal(int row) {
int cols = getColDim();
double max = -Double.MAX_VALUE;
int col = -1;
for (int i = 0; i < cols; i++) {
if(data[row][i] > max) {
max = data[row][i];
col=i;
}
}
return col;
}
/**
*
* @param rowEnd the values in the matrix will be considered until this row (exclusively).
* @param colEnd the values in the matrix will be considered until this col (exclusively).
* @return
*/
public ScorePoint getColIndexContainingMaxVal(int rowEnd, int colEnd) {
int cols = colEnd;
int rows = rowEnd;
double max = -Double.MAX_VALUE;
int rowMax = -1;
int colMax = -1;
for (int i = 0; i < cols; i++) {
double maxInCol = -Double.MAX_VALUE;
int rowMaxInCol=-1;
for (int j = 0; j < rows; j++) {
if(data[j][i] > maxInCol) {
maxInCol = data[j][i];
rowMaxInCol=j;
}
}
if(maxInCol>max){
max = maxInCol;
rowMax = rowMaxInCol;
colMax = i;
}
}
ScorePoint sc = new ScorePoint(rowMax, colMax);
sc.setScore(max);
return sc;
}
public Matrix getNormalizedMatrix() {
int iRows = getRowDim();
int iCols = getColDim();
Matrix maNorm = new Matrix(iRows, iCols);
Matrix maStandardDeviation = getStandardDeviationCols();
for (int ii = 0; ii < iRows; ii++)
for (int jj = 0; jj < iCols; jj++) {
double dStandardDeviation = maStandardDeviation.get(0, jj);
if (dStandardDeviation == 0) {
dStandardDeviation = Float.MIN_VALUE;
}
double dVal = get(ii, jj) / dStandardDeviation;
maNorm.set(ii, jj, dVal);
}
return maNorm;
}
public Matrix getNormalizedMatrix(Matrix maStandardDeviation) {
int iRows = getRowDim();
int iCols = getColDim();
Matrix maNorm = new Matrix(iRows, iCols);
for (int ii = 0; ii < iRows; ii++)
for (int jj = 0; jj < iCols; jj++) {
double dStandardDeviation = maStandardDeviation.get(0, jj);
if (dStandardDeviation == 0) {
dStandardDeviation = Float.MIN_VALUE;
}
double dVal = get(ii, jj) / dStandardDeviation;
maNorm.set(ii, jj, dVal);
}
return maNorm;
}
/**
* For a quadratic matrix only.
* @return
*/
public double [] getUpperTriangle(){
int r = rows();
int c = cols();
if(r != c){
throw new RuntimeException("Not a quadratic matrix.");
}
int n = ((r * r) - r)/2;
double [] a = new double[n];
int cc = 0;
for (int i = 0; i < r; i++) {
for (int j = i+1; j < r; j++) {
a[cc++] = get(i,j);
}
}
return a;
}
/**
*pythag computes sqrt(a^2 + b^2) without destructive underflow or overflow.
* @param a length a
* @param b length b
* @return double
*/
public static double getPythag(double a, double b)
{
double absa = Math.abs(a);
double absb = Math.abs(b);
if (absa > absb) {
double dScale = (absb / absa) * (absb / absa);
return absa * Math.sqrt(1.0 + dScale);
}
else if(absb == 0.0)
return 0.0;
else {
double dScale = (absa / absb) * (absa / absb);
return (absb * Math.sqrt(1.0 + dScale));
}
}
public static double getPythag2(double a, double b)
{
return Math.sqrt((a * a) + (b * b));
}
public boolean areRowsEqual(int row1, int row2) {
boolean equal = true;
int cols = cols();
for (int i = 0; i < cols; i++) {
double diff = Math.abs(data[row1][i]-data[row2][i]);
if(diff>TINY){
equal=false;
break;
}
}
return equal;
}
public boolean equal(Matrix ma) {
boolean bEQ = true;
if(equalDimension(ma) == true) {
for (int i = 0; i < getRowDim(); i++) {
for (int j = 0; j < getColDim(); j++) {
if(data[i][j] != ma.data[i][j]) {
bEQ = false;
break;
}
}
}
} else {
bEQ = false;
}
return bEQ;
}
public boolean equal(Matrix ma, double dLimit) {
boolean bEQ = true;
if(equalDimension(ma) == true) {
for (int i = 0; i < getRowDim(); i++) {
for (int j = 0; j < getColDim(); j++) {
double dDiff = Math.abs(data[i][j] - ma.data[i][j]);
if(dDiff > dLimit) {
bEQ = false;
break;
}
}
}
} else {
bEQ = false;
}
return bEQ;
}
/**
* Checks two matrices for equal dimensions.
* @param ma matrix to compare with.
* @return true if the number of getColDim and the number of getRowDim are
* corresponding.
*/
public boolean equalDimension(Matrix ma) {
boolean bEqual = false;
if((getColDim() == ma.getColDim()) && (getRowDim() == ma.getRowDim()))
bEqual = true;
return bEqual;
}
public boolean hasOnlyFinite() {
boolean finite = true;
int r = rows();
int c = cols();
ma:
for (int i = 0; i < r; i++) {
for (int j = 0; j < c; j++) {
if(!Double.isFinite(data[i][j])){
finite = false;
break ma;
}
}
}
return finite;
}
/**
* Value by value multiplication
* Matrices must have the same dimensions.
* @param ma
* @return
*/
public Matrix multiplyValByVal(Matrix ma) {
Matrix maProd = new Matrix(rows(), cols());
for (int i = 0; i < rows(); i++) {
for (int j = 0; j < cols(); j++) {
maProd.set(i, j, get(i,j) * ma.get(i, j));
}
}
return maProd;
}
public Matrix multCols(Matrix maMuiltiplicant) {
Matrix maResult = new Matrix(getRowDim(), getColDim());
for (int i = 0; i < getRowDim(); i++) {
for (int j = 0; j < getColDim(); j++) {
maResult.data[i][j] = data[i][j] * maMuiltiplicant.get(0,j);
}
}
return maResult;
}
public Matrix multiply(double dScalar) {
Matrix maResult = new Matrix(getRowDim(), getColDim());
for (int i = 0; i < getRowDim(); i++) {
for (int j = 0; j < getColDim(); j++) {
maResult.data[i][j] = data[i][j] * dScalar;
}
}
return maResult;
}
public Matrix multiply(Matrix ma) {
return multiply(false,false,ma);
}
public double multiply(int row1, Matrix ma2, int row2) {
double sum = 0;
for (int ii = 0; ii < getColDim(); ii++) {
sum += data[row1][ii] * ma2.data[row2][ii];
}
return sum;
}
/**
* Multiplication of two matrices. The algorithm checks for the correct
* dimensions of the matrices. If the dimensions are not corresponding a
* runtime exception is thrown. The left matrix is the instantiated object.
* @param transA if true the left matrix is transposed before the
* multiplication
* @param transB if true the right matrix is transposed before the
* multiplication
* @param ma right matrix
* @return matrix with dimension getRowDim(), ma.getColDim().
*/
// public MatrixK multiply(boolean transA, boolean transB, MatrixK ma) {
// MatrixK maResult = null;
//
//
// // Tasks:
// // Computes
// // C = A * B
// // C = A' * B
// // C = A * B'
// // C = A' * B'
// //
//
// // C = A * B
// if ( (transA == false) && (transB == false)) {
// MatrixK B = ma.getTranspose();
//
// maResult = multATransB(B);
//
// }
//
// //
// // C = A' * B
// //
// // Matrix A is transposed
// if ( (transA == true) && (transB == false)) {
//
// MatrixK A = getTranspose();
// MatrixK B = ma.getTranspose();
//
// maResult = A.multATransB(B);
//
// }
//
// //
// // C = A * B'
// //
// // Matrix B is transposed
// if ( (transA == false) && (transB == true)) {
// maResult = multATransB(ma);
// }
//
// //
// // C = A' * B'
// //
// // Matrix A + B are transposed
// if ( (transA == true) && (transB == true)) {
// MatrixK A = getTranspose();
// maResult = A.multATransB(ma);
// }
//
// return maResult;
// }
// private MatrixK multATransB(MatrixK ma){
// //
// // C = A * B'
// //
// int n = cols();
//
// int m = rows();
//
// int maRows = ma.rows();
//
// if (n != ma.cols()) {
// throw new RuntimeException("Error in Routine SMatrix::Mult(). Attempt to calculate the product of two incompatible matrices. Do nothing and return.");
// }
//
// MatrixK maResult = new MatrixK(rows(), maRows);
//
// double[][] C = maResult.getArray();
//
// double[] Bcolj = new double[n];
//
// for (int j = 0; j < maRows; j++) {
// for (int k = 0; k < n; k++) {
// Bcolj[k] = ma.data[j][k];
// }
// for (int i = 0; i < m; i++) {
// double[] Arowi = data[i];
// double s = 0;
// for (int k = 0; k < n; k++) {
// s += Arowi[k]*Bcolj[k];
// }
// C[i][j] = s;
// }
// }
// return maResult;
// }
/**
* Multiplication of two matrices. The algorithm checks for the correct
* dimensions of the matrices. If the dimensions are not corresponding a
* runtime exception is thrown. The left matrix is the instantiated object.
* Algorithm taken from Sedgewick.
* @param transA if true the left matrix is transposed before the
* multiplication
* @param transB if true the right matrix is transposed before the
* multiplication
* @param ma right matrix
* @return matrix with dimension getRowDim(), ma.getColDim().
*/
final public Matrix multiply(boolean transA, boolean transB, Matrix ma) {
Matrix maResult = null;
// Tasks:
// Computes
// C = A * B
// C = A' * B
// C = A * B'
// C = A' * B'
//
// C = A * B
if ( (transA == false) && (transB == false)) {
int n = cols();
int m = rows();
int maCols = ma.cols();
if (n != ma.rows()) {
throw new RuntimeException("Error in Routine Matrix.multiply(...). Attempt to calculate the product of two incompatible matrices. Do nothing and return.");
}
maResult = new Matrix(rows(), ma.cols());
double[][] C = maResult.getArray();
Matrix Btrans = ma.getTranspose();
double[][] bTrans = Btrans.getArray();
double [] Bcolj = null;
double [] Arowi = null;
int c4 = n/4 * 4;
for (int j = 0; j < maCols; j++) {
Bcolj = bTrans[j];
for (int i = 0; i < m; i++) {
Arowi = data[i];
double s = 0;
for (int k = 0; k < c4; k+=4) {
final double s1 = Arowi[k]*Bcolj[k];
final double s2 = Arowi[k+1]*Bcolj[k+1];
final double s3 = Arowi[k+2]*Bcolj[k+2];
final double s4 = Arowi[k+3]*Bcolj[k+3];
s += s1+s2+s3+s4;
}
for (int k = c4; k < n; k++) {
s += Arowi[k]*Bcolj[k];
}
C[i][j] = s;
}
}
}
//
// C = A' * B
//
// Matrix A is transposed
if ( (transA == true) && (transB == false)) {
// Reverse n
int n = rows();
int m = cols();
int maCols = ma.cols();
if (n != ma.rows()) {
throw new RuntimeException("Error in Routine SMatrix::Mult(). Attempt to calculate the product of two incompatible matrices. Do nothing and return.");
}
// Perform C = A' * B
maResult = new Matrix(cols(), ma.cols());
double[][] C = maResult.getArray();
double [] Bcolj = null;
int c4 = n/4 * 4;
Matrix Atrans = getTranspose();
double [][] aTrans = Atrans.getArray();
Matrix Btrans = ma.getTranspose();
double[][] bTrans = Btrans.getArray();
double [] Arowi = null;
for (int j = 0; j < maCols; j++) {
Bcolj = bTrans[j];
for (int i = 0; i < m; i++) {
Arowi = aTrans[i];
double s = 0;
for (int k = 0; k < c4; k+=4) {
final double s1 = Arowi[k]*Bcolj[k];
final double s2 = Arowi[k+1]*Bcolj[k+1];
final double s3 = Arowi[k+2]*Bcolj[k+2];
final double s4 = Arowi[k+3]*Bcolj[k+3];
s += s1+s2+s3+s4;
}
for (int k = c4; k < n; k++) {
s += Arowi[k]*Bcolj[k];
}
C[i][j] = s;
}
}
}
//
// C = A * B'
//
// Matrix B is transposed
if ( (transA == false) && (transB == true)) {
int n = cols();
int m = rows();
int maRows = ma.rows();
if (n != ma.cols()) {
throw new RuntimeException("Error in Routine SMatrix::Mult(). Attempt to calculate the product of two incompatible matrices. Do nothing and return.");
}
maResult = new Matrix(rows(), maRows);
double[][] C = maResult.getArray();
double [] Bcolj = null;
int c4 = n/4 * 4;
double [] Arowi = null;
for (int j = 0; j < maRows; j++) {
Bcolj = ma.data[j];
for (int i = 0; i < m; i++) {
Arowi = data[i];
double s = 0;
for (int k = 0; k < c4; k+=4) {
final double s1 = Arowi[k]*Bcolj[k];
final double s2 = Arowi[k+1]*Bcolj[k+1];
final double s3 = Arowi[k+2]*Bcolj[k+2];
final double s4 = Arowi[k+3]*Bcolj[k+3];
s += s1+s2+s3+s4;
}
for (int k = c4; k < n; k++) {
s += Arowi[k]*Bcolj[k];
}
C[i][j] = s;
}
}
}
//
// C = A' * B'
//
// Matrix A + B are transposed
if ( (transA == true) && (transB == true)) {
// Reverse n
int n = rows();
int m = cols();
int maRows = ma.rows();
if (n != ma.cols()) {
throw new RuntimeException("Error in Routine SMatrix::Mult(). Attempt to calculate the product of two incompatible matrices. Do nothing and return.");
}
// Perform C = A' * B'
maResult = new Matrix(cols(), maRows);
double[][] C = maResult.getArray();
double [] Bcolj = null;
int c4 = n/4 * 4;
Matrix Atrans = getTranspose();
double [][] aTrans = Atrans.getArray();
double [] Arowi = null;
for (int j = 0; j < maRows; j++) {
Bcolj = ma.data[j];
for (int i = 0; i < m; i++) {
Arowi = aTrans[i];
double s = 0;
for (int k = 0; k < c4; k+=4) {
final double s1 = Arowi[k]*Bcolj[k];
final double s2 = Arowi[k+1]*Bcolj[k+1];
final double s3 = Arowi[k+2]*Bcolj[k+2];
final double s4 = Arowi[k+3]*Bcolj[k+3];
s += s1+s2+s3+s4;
}
for (int k = c4; k < n; k++) {
s += Arowi[k]*Bcolj[k];
}
C[i][j] = s;
}
}
}
return maResult;
}
/*
public Matrix multiplyBig(boolean bTransA, boolean bTransB, Matrix ma) {
Matrix maResult = new Matrix(getRowDim(), ma.getColDim());
// Tasks:
// Computes
// C = A * B
// C = A' * B
// C = A * B'
// C = A' * B'
//
// ==>> where *this.Val == C
//
// Input:
// A() n x m matrix
// B() s x r matrix, where m == s
//
// Output:
// C() n x r matrix (*this.Val is changed)
//
// Requirements:
// m = s
//
// Resulting dimensions of matrix product:
// Matrix C => n x r (C == *this.Val)
//
// Remark:
// For Var/Covar-Matrix the routine requires a centered Matrix
// => more options could be added here
int i, j, k, n, m, s, r;
//
// C = A * B
//
// No matrix should be transposed
if ( (bTransA == false) && (bTransB == false)) {
mt.Matrix A = new mt.DenseMatrix(mData);
mt.Matrix B = new mt.DenseMatrix(ma.mData);
mt.Matrix C = new mt.DenseMatrix(getRowDim(), ma.getColDim());
C = A.mult(B,C);
maResult = new Matrix(mt.util.Matrices.getArray(C));
} // End if
//
// C = A' * B
//
// Matrix A should be transposed
if ( (bTransA == true) && (bTransB == false)) {
mt.Matrix A = new mt.DenseMatrix(mData);
mt.Matrix B = new mt.DenseMatrix(ma.mData);
mt.Matrix C = new mt.DenseMatrix(getColDim(), ma.getColDim());
C = A.transAmult(B,C);
maResult = new Matrix(mt.util.Matrices.getArray(C));
} // End if
//
// C = A * B'
//
// Matrix B should be transposed
if ( (bTransA == false) && (bTransB == true)) {
mt.Matrix A = new mt.DenseMatrix(mData);
mt.Matrix B = new mt.DenseMatrix(ma.mData);
mt.Matrix C = new mt.DenseMatrix(getRowDim(), ma.getRowDim());
C = A.transBmult(B,C);
maResult = new Matrix(mt.util.Matrices.getArray(C));
} // End if
//
// C = A' * B'
//
// Matrix A + B should be transposed
if ( (bTransA == true) && (bTransB == true)) {
mt.Matrix A = new mt.DenseMatrix(mData);
mt.Matrix B = new mt.DenseMatrix(ma.mData);
mt.Matrix C = new mt.DenseMatrix(getColDim(), ma.getRowDim());
C = A.transABmult(B,C);
maResult = new Matrix(mt.util.Matrices.getArray(C));
}
return maResult;
}
*/
/**
* Parses an vector with Strings and converts it to a Matrix.
* @param vecStringMatrix vector with strings.
* @return Matrix
*/
public static Matrix getParsed(Vector vecStringMatrix) throws Exception {
Matrix ma = new Matrix();
String sRow = vecStringMatrix.get(0);
int iLen = 0;
double[] dArr = String2DoubleArray.convert(sRow);
iLen = dArr.length;
ma.resize(vecStringMatrix.size(), dArr.length);
for (int ii = 0; ii < dArr.length; ii++) {
ma.set(0, ii, dArr[ii]);
}
for (int ii = 1; ii < vecStringMatrix.size(); ii++) {
sRow = (String) vecStringMatrix.get(ii);
dArr = String2DoubleArray.convert(sRow);
if (iLen != dArr.length) {
System.err.println(
"Vectors for matrix generation differ in length");
(new RuntimeException()).printStackTrace();
break;
}
for (int jj = 0; jj < dArr.length; jj++) {
ma.set(ii, jj, dArr[jj]);
}
}
return ma;
}
public Matrix plus(Matrix ma) {
Matrix maResult = new Matrix(getRowDim(), getColDim());
if(!equalDimension(ma)) {
throw new RuntimeException("Matrices have wrong dimensions.");
}
for (int ii = 0; ii < getRowDim(); ii++) {
for (int jj = 0; jj < getColDim(); jj++) {
maResult.data[ii][jj] = data[ii][jj] + ma.data[ii][jj];
}
}
return maResult;
}
public Matrix pow(double exp) {
Matrix ma = new Matrix(getRowDim(), getColDim());
for (int i = 0; i < getRowDim(); i++) {
for (int j = 0; j < getColDim(); j++) {
ma.data[i][j] = Math.pow(data[i][j], exp);
}
}
return ma;
}
/** Matrix determinant
@return determinant
*/
public double det () {
return new LUDecomposition(this).det();
}
/** Matrix rank
@return effective numerical rank, obtained from SVD.
*/
/** Matrix condition (2 norm)
@return ratio of largest to smallest singular value.
*/
/** Matrix trace.
@return sum of the diagonal elements.
*/
/**
* Resizes the matrix, the old data are written to the new matrix, if
* possible.
* @param rowsNew new number of getRowDim.
* @param colsNew new number of getColDim.
*/
public void resize(int rowsNew, int colsNew) {
double [][] arrTmp = new double [rowsNew][];
int rowsMin = Math.min(rows(), rowsNew);
int colsMin = Math.min(cols(), colsNew);
for (int i = 0; i < rowsMin; i++) {
double [] a = new double [colsNew];
System.arraycopy(data[i], 0, a, 0, colsMin);
arrTmp[i]=a;
}
for (int i = rowsMin; i < rowsNew; i++) {
double [] a = new double [colsNew];
arrTmp[i]=a;
}
data = arrTmp;
}
// public void resize(int iNumberRowsNew, int iNumberColsNew) {
// double [][] dTmp = new double [iNumberRowsNew][iNumberColsNew];
//
// int iRows = iNumberRowsNew;
// int iCols = iNumberColsNew;
//
// if(iNumberRowsNew > getRowDim())
// iRows = getRowDim();
// if(iNumberColsNew > getColDim())
// iCols = getColDim();
// for (int ii = 0; ii < iRows; ii++) {
// for (int jj = 0; jj < iCols; jj++) {
// dTmp[ii][jj] = data[ii][jj];
// }
// }
// data = dTmp;
// }
/**
* Flat copy.
* @param row
* @return
*/
public double [] getRow(int row) {
return data[row];
}
public double [] getRowCopy(int row) {
double [] arr = new double[data[0].length];
for (int i = 0; i < arr.length; i++) {
arr[i] = data[row][i];
}
return arr;
}
public List getRowAsList(int row) {
List list = new ArrayList();
for (int ii = 0; ii < data[0].length; ii++) {
list.add(new Double(data[row][ii]));
}
return list;
}
public float [] getRowAsFloat(int row) {
float [] arr = new float [data[0].length];
for (int i = 0; i < data[0].length; i++) {
arr[i]=(float)data[row][i];
}
return arr;
}
public int getRowDim() {
return data.length;
}
public int rows() {
return data.length;
}
/**
* Sorts the row of the matrix according the compareTo(...) function in
* DoubleVec
* @return sorted matrix
*/
public Matrix getSorted() {
Matrix ma = new Matrix(getRowDim(), getColDim());
List list = new ArrayList();
for (int i = 0; i < data.length; i++) {
list.add(new DoubleVec(data[i]));
}
Collections.sort(list);
for (int i = 0; i < data.length; i++) {
ma.assignRow(i, (DoubleVec) list.get(i));
}
return ma;
}
public Matrix getSQRT() {
Matrix ma = new Matrix(getRowDim(), getColDim());
for (int i = 0; i < data.length; i++) {
for (int j = 0; j < data[0].length; j++) {
ma.data[i][j] = Math.sqrt(data[i][j]);
}
}
return ma;
}
public double getSquaredSum() {
double s = 0;
for (int i = 0; i < data.length; i++) {
for (int j = 0; j < data[0].length; j++) {
s += data[i][j] * data[i][j];
}
}
return s;
}
public Matrix getStandardDeviationCols() {
Matrix maMean = getMeanCols();
final double [] arrMeanCols = maMean.getRow(0);
final int cols = cols();
final int rows = rows();
final double [] arrStdvCols = new double [cols];
for (int i = 0; i < rows; i++) {
final double [] arrRow = data[i];
for (int j = 0; j < cols; j++) {
arrStdvCols[j] += (arrRow[j] - arrMeanCols[j]) * (arrRow[j] - arrMeanCols[j]);
}
}
for (int i = 0; i < cols; i++) {
double sdv = Math.sqrt(arrStdvCols[i] / (rows - 1));
arrStdvCols[i] = sdv;
}
return new Matrix(true, arrStdvCols);
}
public double getStandardDeviation() {
double sdv=0;
double n = rows()*cols();
double mean = getMean();
double sum=0;
for (int i = 0; i < data.length; i++) {
for (int j = 0; j < data[0].length; j++) {
sum += (data[i][j]-mean)*(data[i][j]-mean);
}
}
sdv = Math.sqrt(sum / (n - 1));
return sdv;
}
public double getVariance() {
double var = 0;
double mean = getMean();
double sum = 0;
for (int j = 0; j < data[0].length; j++) {
for (int i = 0; i < data.length; i++) {
sum += (data[i][j] - mean) * (data[i][j] - mean);
}
}
var = sum / (getNumElements() - 1);
return var;
}
/**
* Coefficient of variation (CV) is a normalized measure of dispersion of a probability distribution.
* It is defined as the ratio of the standard deviation sigma to the mean mu.
* @return
*/
public double getCoefficientVariation() {
double mean = getMean();
double sum = 0;
for (int j = 0; j < data[0].length; j++) {
for (int i = 0; i < data.length; i++) {
sum += (data[i][j] - mean) * (data[i][j] - mean);
}
}
double var = sum / (getNumElements() - 1);
double sdv = Math.sqrt(var);
double varCoeff=sdv/mean;
return varCoeff;
}
public double getVarianceCol(int col) {
double var = 0;
double mean = getMeanCol(col);
double dSum = 0;
for (int i = 0; i < data.length; i++) {
dSum += (data[i][col] - mean) * (data[i][col] - mean);
}
var = dSum / (data.length - 1.0);
return var;
}
public double getVarianceRow(int row) {
double var = 0;
int cols = cols();
double mean = getMeanRow(row);
double dSum = 0;
for (int i = 0; i < cols; i++) {
dSum += (data[row][i] - mean) * (data[row][i] - mean);
}
var = dSum / (cols - 1.0);
return var;
}
public double getVarianceCentered() {
double var = 0;
double sum = 0;
for (int j = 0; j < data[0].length; j++) {
for (int i = 0; i < data.length; i++) {
sum += (data[i][j]) * (data[i][j]);
}
}
var = sum / (getNumElements() - 1);
return var;
}
/**
*
* @return row with variance
*/
public Matrix getVarianceCols() {
Matrix ma = new Matrix(1, getColDim());
Matrix maMean = getMeanCols();
for (int j = 0; j < data[0].length; j++) {
double sum = 0;
for (int i = 0; i < data.length; i++) {
sum += (data[i][j] - maMean.data[0][j]) * (data[i][j] - maMean.data[0][j]);
}
double dVariance = sum / (getRowDim() - 1);
ma.data[0][j] = dVariance;
}
return ma;
}
public void increase(int row, int col, double v){
data[row][col]+=v;
}
final public void set(final int row, final int col, final double v) {
data[row][col] = v;
}
public void set(Matrix ma) {
resize(ma.getRowDim(), ma.getColDim());
for (int ii = 0; ii < data.length; ii++) {
for (int jj = 0; jj < data[0].length; jj++) {
data[ii][jj] = ma.data[ii][jj];
}
}
}
public void set(double [][] arr) {
resize(arr.length, arr[0].length);
for (int ii = 0; ii < data.length; ii++) {
for (int jj = 0; jj < data[0].length; jj++) {
data[ii][jj] = arr[ii][jj];
}
}
}
public void setFlat(double [][] arr) {
data = arr;
}
public void set(double v) {
for (int i = 0; i < data.length; i++) {
for (int j = 0; j < data[0].length; j++) {
data[i][j] = v;
}
}
}
public void setID(int id) {
identifier = id;
}
public void setCol(int col, double v) {
for (int i = 0; i < data.length; i++)
data[i][col] = v;
}
public void setCol(int col, double [] arr) {
for (int i = 0; i < data.length; i++)
data[i][col] = arr[i];
}
public void setRow(int iRow, double v) {
for (int i = 0; i < data[0].length; i++)
data[iRow][i] = v;
}
/**
* Deep copy
* @param iRow
* @param arr
*/
public void setRow(int iRow, double [] arr) {
for (int i = 0; i < data[0].length; i++)
data[iRow][i] = arr[i];
}
public void setRow(int iRow, int [] arr) {
for (int i = 0; i < data[0].length; i++)
data[iRow][i] = arr[i];
}
public static void setSeparatorCol(String s) {
OUT_SEPARATOR_COL = s;
}
public static void setSeparatorRow(String s) {
OUT_SEPARATOR_ROW = s;
}
public void shuffleRows() {
int r = rows();
List li = new ArrayList<>(r);
for (int i = 0; i < r; i++) {
li.add(i);
}
Collections.shuffle(li);
for (int i = 0; i < li.size(); i++) {
swapRows(i, li.get(i));
}
}
public void swapRows(int a, int b) {
double [] t = data[a];
data[a]=data[b];
data[b]=t;
}
public void sortRows(int col){
int r= rows();
List li = new ArrayList<>(r);
for (int i = 0; i < r; i++) {
li.add(new IntegerDouble(i, get(i, col)));
}
Collections.sort(li, IntegerDouble.getComparatorDouble());
double [][] dataSorted = new double[r][];
for (int i = 0; i < r; i++) {
dataSorted[i]=data[li.get(i).getInt()];
}
data = dataSorted;
}
/**
* Get the standard scores, also known as z-scores.
* @return matrux with standardized values.
*/
public Matrix getStandardized() {
Matrix ma = new Matrix(getRowDim(), getColDim());
Matrix maStandardDeviation = getStandardDeviationCols();
Matrix Xc = getCenteredMatrix();
for (int i = 0; i < data.length; i++) {
for (int j = 0; j < data[0].length; j++) {
//double d = Xc.mData[ii][jj] / maStandardDeviation.mData[0][jj];
ma.data[i][j] = Xc.data[i][j] / maStandardDeviation.data[0][j];
}
}
return ma;
}
/**
*
* @param indexRowStart start row included
* @param indexRowEnd end row included
* @param indexColStart start col included
* @param indexColEnd end col included
* @return matrix
*/
public Matrix getSubMatrix(int indexRowStart, int indexRowEnd, int indexColStart, int indexColEnd) {
int rows = indexRowEnd - indexRowStart + 1;
int cols = indexColEnd - indexColStart + 1;
Matrix ma = new Matrix();
double [][] arr = new double [rows][cols];
for (int i = 0; i < rows; i++) {
System.arraycopy(data[indexRowStart+i], indexColStart, arr[i], 0, cols);
}
ma.data = arr;
return ma;
}
public Matrix getSubMatrix(List liIndexRow) {
int cols = cols();
Matrix ma = new Matrix();
double [][] arr = new double [liIndexRow.size()][cols];
int row=0;
for (int i = 0; i < liIndexRow.size(); i++) {
System.arraycopy(data[liIndexRow.get(i)], 0, arr[row], 0, cols);
row++;
}
ma.data = arr;
return ma;
}
public double getSum() {
double sum = 0;
for (int i = 0; i < getRowDim(); i++) {
for (int j = 0; j < getColDim(); j++) {
sum += data[i][j];
}
}
return sum;
}
/**
* Matrix has to be quadratic.
* @return
*/
public double getSumUpperTriangle() {
if(rows()!=cols()){
throw new RuntimeException("Not a quadratic matrix.");
}
int rows = cols();
double sum=0;
for (int i = 0; i < rows; i++) {
for (int j = i+1; j < rows; j++) {
if(!Double.isNaN(get(i, j))) {
sum += get(i, j);
}
}
}
return sum;
}
public Matrix getSumCols() {
Matrix ma = new Matrix(1,getColDim());
for (int i = 0; i < getRowDim(); i++) {
for (int j = 0; j < getColDim(); j++) {
ma.data[0][j] += data[i][j];
}
}
return ma;
}
public Matrix getSumRows() {
Matrix ma = new Matrix(1,getRowDim());
for (int i = 0; i < getRowDim(); i++) {
ma.set(0, i, getSumRow(i));
}
return ma;
}
public double getSumCol(int col) {
double sum = 0;
for (int i = 0; i < getRowDim(); i++) {
sum += data[i][col];
}
return sum;
}
public double getSumRow(int row) {
double sum = 0;
for (int i = 0; i < getColDim(); i++) {
sum += data[row][i];
}
return sum;
}
public double getSumSquared() {
double sum = 0;
for (int i = 0; i < getRowDim(); i++) {
for (int j = 0; j < getColDim(); j++) {
sum += (data[i][j] * data[i][j]);
}
}
return sum;
}
public double [] getNext4NeighboursTorus(int row, int col) {
double [] arr = new double [4];
// value above
arr[0] = getTorus(row - 1, col);
// left
arr[1] = getTorus(row, col - 1);
// right
arr[2] = getTorus(row, col + 1);
// down
arr[3] = getTorus(row + 1, col);
return arr;
}
public double [] getNext8NeighboursTorus(int row, int col) {
double [] arr = new double [8];
int cc = 0;
for (int i = -1; i < 2; i++) {
for (int j = -1; j < 2; j++) {
if(i != 0 || j != 0) {
arr[cc] = getTorus(row + i, col + j);
cc++;
}
}
}
return arr;
}
public Matrix row2Matrix(int row, int len) {
Matrix m = new Matrix(getColDim()/len, len);
int r = 0;
int c = 0;
for (int i = 0; i < getColDim(); i++) {
if((i % len == 0) && (i > 0)) {
r++;
c = 0;
}
m.set(r,c, get(0,i));
c++;
}
return m;
}
public double getTorus(int row, int col) {
int torRow = row;
int torCol = col;
while(torRow < 0) {
torRow += getRowDim();
}
while(torRow >= getRowDim()) {
torRow -= getRowDim();
}
while(torCol < 0) {
torCol += getColDim();
}
while(torCol >= getColDim()) {
torCol -= getColDim();
}
return get(torRow, torCol);
}
/** Matrix trace.
@return sum of the diagonal elements.
*/
public double getTrace() {
double t = 0;
int m = getRowDim();
int n = getColDim();
for (int ii = 0; ii < Math.min(m, n); ii++) {
t = t + get(ii, ii);
}
return t;
}
public Matrix getTranspose() {
int rows = getRowDim();
int cols = getColDim();
Matrix ma = new Matrix(cols, rows);
for (int ii = 0; ii < rows; ii++) {
for (int jj = 0; jj < cols; jj++) {
ma.data[jj][ii] = data[ii][jj];
}
}
return ma;
}
/**
* Opposite direction to transpose.
*/
public Matrix getFlipped() {
int rows = getRowDim();
int cols = getColDim();
Matrix ma = new Matrix(cols, rows);
for (int ii = 0; ii < rows; ii++) {
for (int jj = 0; jj < cols; jj++) {
ma.data[cols-jj-1][ii] = data[ii][jj];
}
}
return ma;
}
public Matrix toRow() {
Matrix m = new Matrix(1, getRowDim() * getColDim());
for (int i = 0; i < getRowDim(); i++) {
for (int j = 0; j < getColDim(); j++) {
m.set(0,i * getColDim() + j, get(i,j));
}
}
return m;
}
/**
*
* @return deep copy.
*/
public double [] toArray() {
final int rows = rows();
final int cols = cols();
double [] a = new double [rows*cols];
for (int i = 0; i < rows; i++) {
for (int j = 0; j < cols; j++) {
a[i * cols + j] = get(i,j);
}
}
return a;
}
public String toString() {
int iRequireDigits = 20;
int len = getRowDim() * getColDim() * iRequireDigits;
StringBuilder sb = new StringBuilder(len);
for (int i = 0; i < data.length; i++) {
for (int j = 0; j < data[0].length - 1; j++) {
sb.append(data[i][j] + OUT_SEPARATOR_COL);
}
sb.append(data[i][data[0].length - 1]);
// No line break after the last line
if(i < data.length - 1)
sb.append(OUT_SEPARATOR_ROW);
}
return sb.toString();
}
public String toStringBinary() {
int len = getRowDim() * getColDim();
StringBuilder sb = new StringBuilder(len);
for (int i = 0; i < data.length; i++) {
for (int j = 0; j < data[0].length; j++) {
if(data[i][j]==0)
sb.append(0);
else
sb.append(1);
}
// No line break after the last line
if(i < data.length - 1)
sb.append(OUT_SEPARATOR_ROW);
}
return sb.toString();
}
public String toString(int digits) {
return toString(rows(), cols(), digits, 0);
}
public String toString(int digits, int width) {
return toString(rows(), cols(), digits, width);
}
/**
*
* @param rowEnd exclusive
* @param colEnd exclusive
* @param digits
* @return
*/
public String toString(int rowEnd, int colEnd, int digits, int width) {
int iRequireDigits = 20;
String sFormat = "";
sFormat += "0";
int iCounter = 0;
if(digits > 0)
sFormat += ".";
while(iCounter < digits) {
sFormat += "0";
iCounter++;
}
DecimalFormat nf = new DecimalFormat(sFormat, new DecimalFormatSymbols(Locale.US));
int len = getRowDim() * getColDim() * iRequireDigits;
StringBuilder sb = new StringBuilder(len);
for (int i = 0; i < rowEnd; i++) {
for (int j = 0; j < colEnd; j++) {
String sVal = nf.format(data[i][j]);
if(data[i][j]==Double.MAX_VALUE)
sVal = "Max";
StringBuilder sbVal = new StringBuilder(sVal);
while (sbVal.length() 0)
sFormat += ".";
while(iCounter < iDigits) {
sFormat += "0";
iCounter++;
}
DecimalFormat nf = new DecimalFormat(sFormat);
int len = getRowDim() * getColDim() * iRequireDigits;
StringBuilder sb = new StringBuilder(len);
for (int j = 0; j < data[0].length; j++) {
String sVal = nf.format(data[row][j]);
if(data[row][j]==Double.MAX_VALUE)
sVal = "Max";
sb.append(sVal);
if(j= 0.0 ? Math.abs(a) : -Math.abs(a))
if(b >= 0.0)
return Math.abs(a);
else
return -Math.abs(a);
}
public static Matrix getRND(int rows, int cols){
Matrix ma = new Matrix(rows, cols);
for (int i = 0; i < rows; i++)
for (int j = 0; j < cols; j++)
ma.set(i,j,Math.random());
return ma;
}
public void write(String sFile, boolean apppend) {
DecimalFormat df = new DecimalFormat(FORMAT);
write(new File(sFile), df, apppend);
}
public void write(String sFile) {
DecimalFormat df = new DecimalFormat(FORMAT);
write(new File(sFile), df, false);
}
public void write(File fiMa) {
DecimalFormat df = new DecimalFormat(FORMAT);
write(fiMa, df, false);
}
public void write(File fiMa, boolean apppend, int digits) throws IOException{
String sFormat = "##,";
int iCounter = 0;
while(iCounter < digits) {
sFormat += "#";
iCounter++;
}
sFormat += "0.";
iCounter = 0;
while(iCounter < digits) {
sFormat += "0";
iCounter++;
}
DecimalFormat nf = new DecimalFormat(sFormat);
write(fiMa, nf, apppend);
}
public void write(String sFiMa, boolean apppend, int digits) throws IOException{
write(new File (sFiMa), apppend, digits);
}
public void write(File fiMa, DecimalFormat nf, boolean apppend) {
try {
FileOutputStream os = new FileOutputStream(fiMa, apppend);
write(os, nf);
os.close();
} catch (IOException e) {
throw new RuntimeException(e);
}
}
public void write(OutputStream os) {
NumberFormat nf = new DecimalFormat("#.###############");
write(os, nf);
}
public String writeAsLineBase64Encoded() {
NumberFormat nf = new DecimalFormat("#.###############");
ByteArrayOutputStream baos = new ByteArrayOutputStream();
write(baos, nf);
Base64.Encoder encoder = Base64.getEncoder();
byte [] arr64 = encoder.encode(baos.toByteArray());
return new String(arr64);
}
public void write(OutputStream os, NumberFormat nf) {
try {
for (int i = 0; i < data.length; i++) {
StringBuilder sb = new StringBuilder();
for (int j = 0; j < data[0].length; j++) {
sb.append(nf.format(data[i][j]));
if(j liColTags, DecimalFormat nf, String separator) {
if(cols()!=liColTags.size()){
throw new RuntimeException("Number of cols and col tags differ.");
}
int [] arrWidth = new int [cols()];
for (int i = 0; i < arrWidth.length; i++) {
arrWidth[i] = liColTags.get(i).length();
}
for (int i = 0; i < arrWidth.length; i++) {
for (int j = 0; j < rows(); j++) {
arrWidth[i] = Math.max(arrWidth[i], nf.format(get(j,i)).length());
}
}
StringBuilder sbAll = new StringBuilder();
for (int i = 0; i < arrWidth.length; i++) {
int w = arrWidth[i];
StringBuilder sb = new StringBuilder(liColTags.get(i));
int l = w-sb.length();
for (int j = 0; j < l; j++) {
sb.append(" ");
}
sbAll.append(sb.toString());
sbAll.append(" ");
}
sbAll.append("\n");
for (int i = 0; i < rows(); i++) {
for (int j = 0; j < arrWidth.length; j++) {
int w = arrWidth[j];
StringBuilder sb = new StringBuilder(nf.format(get(i,j)));
int l = w-sb.length();
for (int k = 0; k < l; k++) {
sb.append(" ");
}
sbAll.append(sb.toString());
sbAll.append(" ");
}
sbAll.append("\n");
}
return sbAll.toString();
}
public String toStringWithRowTags(List liRowTags, DecimalFormat nf, String separator) {
if(rows()!=liRowTags.size()){
throw new RuntimeException("Number of rows and row tags differ.");
}
int [] arrWidth = new int [cols()+1];
for (int i = 0; i < liRowTags.size(); i++) {
arrWidth[0] = Math.max(arrWidth[0], liRowTags.get(i).length());
}
for (int i = 0; i < cols(); i++) {
for (int j = 0; j < rows(); j++) {
arrWidth[i+1] = Math.max(arrWidth[i+1], nf.format(get(j,i)).length());
}
}
StringBuilder sbAll = new StringBuilder();
for (int i = 0; i < arrWidth.length; i++) {
int w = arrWidth[i];
StringBuilder sb = new StringBuilder(liRowTags.get(i));
int l = w-sb.length();
for (int j = 0; j < l; j++) {
sb.append(" ");
}
sbAll.append(sb.toString());
sbAll.append(" ");
}
sbAll.append("\n");
for (int i = 0; i < rows(); i++) {
for (int j = 0; j < arrWidth.length; j++) {
int w = arrWidth[j];
StringBuilder sb = new StringBuilder(nf.format(get(i,j)));
int l = w-sb.length();
for (int k = 0; k < l; k++) {
sb.append(" ");
}
sbAll.append(sb.toString());
sbAll.append(" ");
}
sbAll.append("\n");
}
return sbAll.toString();
}
public void writeSerialized(File fiOut) throws IOException {
FileOutputStream fos = new FileOutputStream(fiOut);
ObjectOutputStream oos = new ObjectOutputStream(fos);
oos.writeObject(data);
oos.close();
}
public static Matrix readSerialized(File fiIn) throws FileNotFoundException, IOException, ClassNotFoundException {
Matrix ma = null;
FileInputStream fos = new FileInputStream(fiIn);
ObjectInputStream ois = new ObjectInputStream(fos);
double [][] data = (double [][]) ois.readObject();
/**
* We are using a deep copy because of memory handling problems with using the de-serialized object directly.
*/
ma = new Matrix(data);
ois.close();
return ma;
}
public static DecimalFormat format(int digits) {
String sFormat = "##,###";
if(digits > 0) {
sFormat += ".";
int iCounter = 0;
while (iCounter < digits) {
sFormat += "0";
iCounter++;
}
}
return new DecimalFormat(sFormat, new DecimalFormatSymbols(Locale.US));
}
public void write(String sFile, boolean bApppend, int digits, int totalWidth) {
try {
DecimalFormat nf = format(digits);
BufferedWriter writer = new BufferedWriter(new FileWriter(new File(
sFile), bApppend));
StringBuffer sVal = new StringBuffer();
for (int ii = 0; ii < data.length; ii++) {
sVal = new StringBuffer();
for (int jj = 0; jj < data[0].length; jj++) {
sVal.append(format(data[ii][jj], nf, totalWidth) +
OUT_SEPARATOR_COL);
}
writer.write(sVal.toString());
// No line break after the last line
if (ii < data.length - 1) {
writer.write(OUT_SEPARATOR_ROW);
}
}
writer.flush();
writer.close();
} catch (IOException ex) {
ex.printStackTrace();
}
}
public static String format(double val, DecimalFormat nf, int totalWidth) {
String str = "";
str = nf.format(val);
while(str.length() < totalWidth) {
str = " " + str;
}
return str;
}
}