net.maizegenetics.matrixalgebra.Matrix.EJMLDoubleMatrix.kt Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of tassel Show documentation
Show all versions of tassel Show documentation
TASSEL is a software package to evaluate traits associations, evolutionary patterns, and linkage
disequilibrium.
The newest version!
package net.maizegenetics.matrixalgebra.Matrix
import net.maizegenetics.matrixalgebra.decomposition.*
import net.maizegenetics.taxa.distance.DistanceMatrix
import org.ejml.data.DMatrixRMaj
import org.ejml.dense.row.CommonOps_DDRM
import org.ejml.dense.row.factory.LinearSolverFactory_DDRM
class EJMLDoubleMatrix: DoubleMatrix {
val tol = 1e-10
var myMatrix: DMatrixRMaj
constructor(matrix: DMatrixRMaj) {
myMatrix = matrix
}
constructor(row: Int, col: Int) {
myMatrix = DMatrixRMaj(row, col)
}
constructor(row: Int, col: Int, values: DoubleArray) {
myMatrix = DMatrixRMaj(row, col, true, *values)
}
constructor(row: Int, col: Int, value: Double) {
myMatrix = DMatrixRMaj(row, col)
myMatrix.fill(value)
}
constructor(values: Array) {
myMatrix = DMatrixRMaj(values)
}
constructor(dist: DistanceMatrix) {
myMatrix = DMatrixRMaj(dist.distances)
}
constructor(size: Int) {
myMatrix = CommonOps_DDRM.identity(size)
}
constructor(diagonal: DoubleArray) {
myMatrix = CommonOps_DDRM.diag(*diagonal)
}
override fun get(row: Int, col: Int): Double {
return myMatrix.unsafe_get(row, col)
}
override fun getChecked(row: Int, col: Int): Double {
return myMatrix[row,col]
}
override fun set(row: Int, col: Int, value: Double) {
myMatrix.unsafe_set(row, col, value)
}
override fun setChecked(row: Int, col: Int, value: Double) {
myMatrix[row, col] = value
}
override fun transpose(): DoubleMatrix {
return EJMLDoubleMatrix(CommonOps_DDRM.transpose(myMatrix, DMatrixRMaj(myMatrix.numRows, myMatrix.numCols)))
}
override fun mult(dm: DoubleMatrix, transpose: Boolean, transposedm: Boolean): DoubleMatrix {
val otherMatrix = (dm as EJMLDoubleMatrix).myMatrix
val resultMatrix = DMatrixRMaj(1,1)
when {
transpose && transposedm -> CommonOps_DDRM.multTransAB(myMatrix, otherMatrix, resultMatrix)
transpose && !transposedm -> CommonOps_DDRM.multTransA(myMatrix, otherMatrix, resultMatrix)
!transpose && transposedm -> CommonOps_DDRM.multTransB(myMatrix, otherMatrix, resultMatrix)
else -> CommonOps_DDRM.mult(myMatrix, otherMatrix, resultMatrix)
}
return EJMLDoubleMatrix(resultMatrix)
}
override fun mult(dm: DoubleMatrix): DoubleMatrix {
val otherMatrix = (dm as EJMLDoubleMatrix).myMatrix
val resultMatrix = DMatrixRMaj(1,1)
CommonOps_DDRM.mult(myMatrix, otherMatrix, resultMatrix)
return EJMLDoubleMatrix(resultMatrix)
}
override fun multadd(
A: DoubleMatrix,
B: DoubleMatrix?,
alpha: Double,
beta: Double,
transpose: Boolean,
transposeA: Boolean,
): DoubleMatrix {
//result = alpha * myMatrix * A + beta * B
val Amatrix = (A as EJMLDoubleMatrix).myMatrix
val Bmatrix = if (B == null) {
when {
transpose && transposeA -> DMatrixRMaj(myMatrix.numCols, Amatrix.numRows)
transpose && !transposeA -> DMatrixRMaj(myMatrix.numCols, Amatrix.numCols)
!transpose && transposeA -> DMatrixRMaj(myMatrix.numRows, Amatrix.numRows)
else -> DMatrixRMaj(myMatrix.numRows, Amatrix.numCols)
}
}
else if (beta == 1.0) (B as EJMLDoubleMatrix).myMatrix
else {
val scaledB = DMatrixRMaj(1,1)
CommonOps_DDRM.scale(beta, (B as EJMLDoubleMatrix).myMatrix, scaledB)
scaledB
}
when {
transpose && transposeA -> CommonOps_DDRM.multAddTransAB(alpha, myMatrix, Amatrix, Bmatrix)
transpose && !transposeA -> CommonOps_DDRM.multAddTransA(alpha, myMatrix, Amatrix, Bmatrix)
!transpose && transposeA -> CommonOps_DDRM.multAddTransB(alpha, myMatrix, Amatrix, Bmatrix)
else -> CommonOps_DDRM.multAdd(alpha, myMatrix, Amatrix, Bmatrix)
}
return EJMLDoubleMatrix(Bmatrix)
}
override fun crossproduct(): DoubleMatrix {
val resultMatrix = DMatrixRMaj(1,1)
CommonOps_DDRM.multTransA(myMatrix, myMatrix, resultMatrix)
return EJMLDoubleMatrix(resultMatrix)
}
override fun crossproduct(dm: DoubleMatrix): DoubleMatrix {
val resultMatrix = DMatrixRMaj(1,1)
CommonOps_DDRM.multTransA(myMatrix, (dm as EJMLDoubleMatrix).myMatrix, resultMatrix)
return EJMLDoubleMatrix(resultMatrix)
}
override fun tcrossproduct(): DoubleMatrix {
val resultMatrix = DMatrixRMaj(1,1)
CommonOps_DDRM.multTransB(myMatrix, myMatrix, resultMatrix)
return EJMLDoubleMatrix(resultMatrix)
}
override fun tcrossproduct(dm: DoubleMatrix): DoubleMatrix {
val resultMatrix = DMatrixRMaj(1,1)
CommonOps_DDRM.multTransB(myMatrix, (dm as EJMLDoubleMatrix).myMatrix, resultMatrix)
return EJMLDoubleMatrix(resultMatrix)
}
override fun concatenate(dm: DoubleMatrix, rows: Boolean): DoubleMatrix {
val resultMatrix = DMatrixRMaj(1,1)
if (rows) CommonOps_DDRM.concatRows(myMatrix, (dm as EJMLDoubleMatrix).myMatrix, resultMatrix)
else CommonOps_DDRM.concatColumns(myMatrix, (dm as EJMLDoubleMatrix).myMatrix, resultMatrix)
return EJMLDoubleMatrix(resultMatrix)
}
override fun inverse(): DoubleMatrix? {
val resultMatrix = DMatrixRMaj(1,1)
return if (CommonOps_DDRM.invert(myMatrix, resultMatrix)) EJMLDoubleMatrix(resultMatrix) else null
}
override fun invert(): Boolean {
return CommonOps_DDRM.invert(myMatrix)
}
override fun generalizedInverse(): DoubleMatrix {
val resultMatrix = DMatrixRMaj(1,1)
CommonOps_DDRM.pinv(myMatrix, resultMatrix)
return EJMLDoubleMatrix(resultMatrix)
}
override fun generalizedInverseWithRank(rank: IntArray): DoubleMatrix {
val svd = EJMLSingularValueDecomposition(myMatrix)
rank[0] = svd.rank
//get S (W) and invert it
val invS = svd.s
for (ndx in 0 until invS.numberOfRows()) {
invS[ndx,ndx] = if (invS[ndx,ndx] < tol) 0.0 else 1.0 / invS[ndx,ndx]
}
val V = svd.getV(false)
val UT = svd.getU(true)
return V.mult(invS).mult(UT)
}
override fun solve(Y: DoubleMatrix?): DoubleMatrix {
//solve AX = B for X
val solver = LinearSolverFactory_DDRM.leastSquares(myMatrix.numRows, myMatrix.numCols)
val Amatrix = if (solver.modifiesA()) myMatrix.copy() else myMatrix
check(solver.setA(Amatrix)) {"solver unable to set A"}
val Bmatrix = if (solver.modifiesB()) (Y as EJMLDoubleMatrix).myMatrix.copy() else (Y as EJMLDoubleMatrix).myMatrix
val Xmatrix = DMatrixRMaj(Amatrix.numCols, Bmatrix.numCols)
solver.solve(Bmatrix, Xmatrix)
return EJMLDoubleMatrix(Xmatrix)
}
override fun numberOfRows(): Int {
return myMatrix.numRows
}
override fun numberOfColumns(): Int {
return myMatrix.numCols
}
override fun row(i: Int): DoubleMatrix {
val out = CommonOps_DDRM.extractRow(myMatrix, i, null)
out.reshape(myMatrix.numCols, 1)
return EJMLDoubleMatrix(out)
}
override fun column(j: Int): DoubleMatrix {
return EJMLDoubleMatrix(CommonOps_DDRM.extractColumn(myMatrix, j, null))
}
override fun getXtXGM(): Array {
val result0 = DMatrixRMaj(myMatrix.numCols, myMatrix.numCols) //X'X
CommonOps_DDRM.multTransA(myMatrix, myMatrix, result0)
//try inverting using faster code first before calculating pseudo inverse
var result1 = result0.copy() //invX'X=G
if (!CommonOps_DDRM.invert(result1)) {
CommonOps_DDRM.pinv(result0, result1)
}
val tmp1 = DMatrixRMaj(myMatrix.numRows, result1.numCols)
CommonOps_DDRM.mult(myMatrix, result1, tmp1) //tmp1 = XG
val tmp2 = DMatrixRMaj(tmp1.numRows, myMatrix.numRows)
CommonOps_DDRM.multTransB(tmp1,myMatrix,tmp2) //tmp2 = XGX'
val result2 = CommonOps_DDRM.identity(tmp2.numRows) //I - XGX'
CommonOps_DDRM.subtractEquals(result2, tmp2)
return arrayOf(EJMLDoubleMatrix(result0), EJMLDoubleMatrix(result1), EJMLDoubleMatrix(result2))
}
override fun copy(): DoubleMatrix {
return EJMLDoubleMatrix(myMatrix.copy())
}
override fun getEigenvalueDecomposition(): EigenvalueDecomposition {
return EJMLEigenvalueDecomposition(myMatrix)
}
override fun getSingularValueDecomposition(): SingularValueDecomposition {
return EJMLSingularValueDecomposition(myMatrix)
}
override fun getQRDecomposition(): QRDecomposition {
TODO("Not yet implemented")
}
override fun minus(dm: DoubleMatrix): DoubleMatrix {
val otherMatrix = (dm as EJMLDoubleMatrix).myMatrix
check(myMatrix.numRows == otherMatrix.numRows && myMatrix.numCols == otherMatrix.numCols) {"Attempted to subtract unequal size matrices"}
val resultMatrix = DMatrixRMaj(myMatrix.numRows, myMatrix.numCols)
CommonOps_DDRM.subtract(myMatrix, otherMatrix, resultMatrix)
return EJMLDoubleMatrix(resultMatrix)
}
override fun minusEquals(dm: DoubleMatrix) {
val otherMatrix = (dm as EJMLDoubleMatrix).myMatrix
check(myMatrix.numRows == otherMatrix.numRows && myMatrix.numCols == otherMatrix.numCols) {"Attempted to subtract unequal size matrices"}
CommonOps_DDRM.subtractEquals(myMatrix, otherMatrix)
}
override fun plus(dm: DoubleMatrix): DoubleMatrix {
val otherMatrix = (dm as EJMLDoubleMatrix).myMatrix
check(myMatrix.numRows == otherMatrix.numRows && myMatrix.numCols == otherMatrix.numCols) {"Attempted to add unequal size matrices"}
val resultMatrix = DMatrixRMaj(myMatrix.numRows, myMatrix.numCols)
CommonOps_DDRM.add(myMatrix, otherMatrix, resultMatrix)
return EJMLDoubleMatrix(resultMatrix)
}
override fun plusEquals(dm: DoubleMatrix) {
val otherMatrix = (dm as EJMLDoubleMatrix).myMatrix
check(myMatrix.numRows == otherMatrix.numRows && myMatrix.numCols == otherMatrix.numCols) {"Attempted to add unequal size matrices"}
CommonOps_DDRM.addEquals(myMatrix, otherMatrix)
}
override fun scalarAdd(s: Double): DoubleMatrix {
val resultMatrix = DMatrixRMaj(myMatrix.numRows, myMatrix.numCols)
CommonOps_DDRM.add(myMatrix, s, resultMatrix)
return EJMLDoubleMatrix(resultMatrix)
}
override fun scalarAddEquals(s: Double) {
CommonOps_DDRM.add(myMatrix, s)
}
override fun scalarMult(s: Double): DoubleMatrix {
val resultMatrix = DMatrixRMaj(myMatrix.numRows, myMatrix.numCols)
CommonOps_DDRM.scale(s, myMatrix, resultMatrix)
return EJMLDoubleMatrix(resultMatrix)
}
override fun scalarMultEquals(s: Double) {
CommonOps_DDRM.scale(s, myMatrix)
}
override fun getSelection(rows: IntArray?, columns: IntArray?): DoubleMatrix {
val selectedRows = if (rows == null) IntArray(myMatrix.numRows) { it } else rows
val selectedColumns = if (columns == null) IntArray(myMatrix.numCols) { it } else columns
return EJMLDoubleMatrix(CommonOps_DDRM.extract(myMatrix, selectedRows, selectedRows.size, selectedColumns, selectedColumns.size, null))
}
override fun rowSum(row: Int): Double {
return (0 until myMatrix.numCols).map { myMatrix[row, it] }.sum()
}
override fun columnSum(column: Int): Double {
return (0 until myMatrix.numRows).map { myMatrix[it, column] }.sum()
}
override fun columnRank(): Int {
return EJMLSingularValueDecomposition(myMatrix).rank
}
override fun to1DArray(): DoubleArray {
return myMatrix.data
}
override fun toArray(): Array {
return Array(myMatrix.numRows) { rowIndex ->
DoubleArray(myMatrix.numCols) { colIndex -> myMatrix[rowIndex, colIndex]}
}
}
}