forked from kscience/kmath
Refactored Matrix features
This commit is contained in:
parent
569ff6357b
commit
a2ef50ab47
@ -4,11 +4,16 @@ import org.apache.commons.math3.linear.*
|
||||
import org.apache.commons.math3.linear.RealMatrix
|
||||
import org.apache.commons.math3.linear.RealVector
|
||||
|
||||
inline class CMMatrix(val origin: RealMatrix) : Matrix<Double> {
|
||||
class CMMatrix(val origin: RealMatrix, features: Set<MatrixFeature>? = null) : Matrix<Double> {
|
||||
override val rowNum: Int get() = origin.rowDimension
|
||||
override val colNum: Int get() = origin.columnDimension
|
||||
|
||||
override val features: Set<MatrixFeature> get() = emptySet()
|
||||
override val features: Set<MatrixFeature> = features ?: sequence<MatrixFeature> {
|
||||
if(origin is DiagonalMatrix) yield(DiagonalFeature)
|
||||
}.toSet()
|
||||
|
||||
override fun suggestFeature(vararg features: MatrixFeature) =
|
||||
CMMatrix(origin, this.features + features)
|
||||
|
||||
override fun get(i: Int, j: Int): Double = origin.getEntry(i, j)
|
||||
}
|
||||
@ -23,7 +28,7 @@ fun Matrix<Double>.toCM(): CMMatrix = if (this is CMMatrix) {
|
||||
|
||||
fun RealMatrix.toMatrix() = CMMatrix(this)
|
||||
|
||||
inline class CMVector(val origin: RealVector) : Point<Double> {
|
||||
class CMVector(val origin: RealVector) : Point<Double> {
|
||||
override val size: Int get() = origin.dimension
|
||||
|
||||
override fun get(index: Int): Double = origin.getEntry(index)
|
||||
|
@ -35,6 +35,9 @@ class BufferMatrix<T : Any>(
|
||||
|
||||
override val shape: IntArray get() = intArrayOf(rowNum, colNum)
|
||||
|
||||
override fun suggestFeature(vararg features: MatrixFeature) =
|
||||
BufferMatrix(rowNum, colNum, buffer, this.features + features)
|
||||
|
||||
override fun get(index: IntArray): T = get(index[0], index[1])
|
||||
|
||||
override fun get(i: Int, j: Int): T = buffer[i * colNum + j]
|
||||
|
@ -8,20 +8,19 @@ import scientifik.kmath.structures.MutableBufferFactory
|
||||
import scientifik.kmath.structures.NDStructure
|
||||
import scientifik.kmath.structures.get
|
||||
|
||||
|
||||
class LUPDecomposition<T : Comparable<T>>(
|
||||
private val elementContext: Ring<T>,
|
||||
internal val lu: NDStructure<T>,
|
||||
val pivot: IntArray,
|
||||
private val even: Boolean
|
||||
) : DeterminantFeature<T> {
|
||||
) : LUPDecompositionFeature<T>, DeterminantFeature<T> {
|
||||
|
||||
/**
|
||||
* Returns the matrix L of the decomposition.
|
||||
*
|
||||
* L is a lower-triangular matrix with [Ring.one] in diagonal
|
||||
*/
|
||||
val l: Matrix<T> = VirtualMatrix(lu.shape[0], lu.shape[1]) { i, j ->
|
||||
override val l: Matrix<T> = VirtualMatrix(lu.shape[0], lu.shape[1], setOf(LFeature)) { i, j ->
|
||||
when {
|
||||
j < i -> lu[i, j]
|
||||
j == i -> elementContext.one
|
||||
@ -35,7 +34,7 @@ class LUPDecomposition<T : Comparable<T>>(
|
||||
*
|
||||
* U is an upper-triangular matrix including the diagonal
|
||||
*/
|
||||
val u: Matrix<T> = VirtualMatrix(lu.shape[0], lu.shape[1]) { i, j ->
|
||||
override val u: Matrix<T> = VirtualMatrix(lu.shape[0], lu.shape[1], setOf(UFeature)) { i, j ->
|
||||
if (j >= i) lu[i, j] else elementContext.zero
|
||||
}
|
||||
|
||||
@ -46,7 +45,7 @@ class LUPDecomposition<T : Comparable<T>>(
|
||||
* P is a sparse matrix with exactly one element set to [Ring.one] in
|
||||
* each row and each column, all other elements being set to [Ring.zero].
|
||||
*/
|
||||
val p: Matrix<T> = VirtualMatrix(lu.shape[0], lu.shape[1]) { i, j ->
|
||||
override val p: Matrix<T> = VirtualMatrix(lu.shape[0], lu.shape[1]) { i, j ->
|
||||
if (j == pivot[i]) elementContext.one else elementContext.zero
|
||||
}
|
||||
|
||||
|
@ -116,6 +116,14 @@ interface Matrix<T : Any> : NDStructure<T> {
|
||||
|
||||
val features: Set<MatrixFeature>
|
||||
|
||||
/**
|
||||
* Suggest new feature for this matrix. The result is the new matrix that may or may not reuse existing data structure.
|
||||
*
|
||||
* The implementation does not guarantee to check that matrix actually have the feature, so one should be careful to
|
||||
* add only those features that are valid.
|
||||
*/
|
||||
fun suggestFeature(vararg features: MatrixFeature): Matrix<T>
|
||||
|
||||
operator fun get(i: Int, j: Int): T
|
||||
|
||||
override fun get(index: IntArray): T = get(index[0], index[1])
|
||||
|
@ -12,7 +12,7 @@ interface MatrixFeature
|
||||
object DiagonalFeature : MatrixFeature
|
||||
|
||||
/**
|
||||
* Matix with this feature has all zero elements
|
||||
* Matrix with this feature has all zero elements
|
||||
*/
|
||||
object ZeroFeature : MatrixFeature
|
||||
|
||||
@ -21,10 +21,42 @@ object ZeroFeature : MatrixFeature
|
||||
*/
|
||||
object UnitFeature : MatrixFeature
|
||||
|
||||
/**
|
||||
* Inverted matrix feature
|
||||
*/
|
||||
interface InverseMatrixFeature<T : Any> : MatrixFeature {
|
||||
val inverse: Matrix<T>
|
||||
}
|
||||
|
||||
/**
|
||||
* A determinant container
|
||||
*/
|
||||
interface DeterminantFeature<T : Any> : MatrixFeature {
|
||||
val determinant: T
|
||||
}
|
||||
}
|
||||
|
||||
@Suppress("FunctionName")
|
||||
fun <T: Any> DeterminantFeature(determinant: T) = object: DeterminantFeature<T>{
|
||||
override val determinant: T = determinant
|
||||
}
|
||||
|
||||
/**
|
||||
* Lower triangular matrix
|
||||
*/
|
||||
object LFeature: MatrixFeature
|
||||
|
||||
/**
|
||||
* Upper triangular feature
|
||||
*/
|
||||
object UFeature: MatrixFeature
|
||||
|
||||
/**
|
||||
* TODO add documentation
|
||||
*/
|
||||
interface LUPDecompositionFeature<T : Any> : MatrixFeature {
|
||||
val l: Matrix<T>
|
||||
val u: Matrix<T>
|
||||
val p: Matrix<T>
|
||||
}
|
||||
|
||||
//TODO add sparse matrix feature
|
@ -8,6 +8,9 @@ class VirtualMatrix<T : Any>(
|
||||
) : Matrix<T> {
|
||||
override fun get(i: Int, j: Int): T = generator(i, j)
|
||||
|
||||
override fun suggestFeature(vararg features: MatrixFeature) =
|
||||
VirtualMatrix(rowNum, colNum, this.features + features, generator)
|
||||
|
||||
override fun equals(other: Any?): Boolean {
|
||||
if (this === other) return true
|
||||
if (other !is Matrix<*>) return false
|
||||
|
@ -15,6 +15,7 @@ class ShortNDRing(override val shape: IntArray) :
|
||||
override val zero by lazy { produce { ShortRing.zero } }
|
||||
override val one by lazy { produce { ShortRing.one } }
|
||||
|
||||
@Suppress("OVERRIDE_BY_INLINE")
|
||||
override inline fun buildBuffer(size: Int, crossinline initializer: (Int) -> Short): Buffer<Short> =
|
||||
ShortBuffer(ShortArray(size) { initializer(it) })
|
||||
|
||||
|
@ -48,10 +48,25 @@ class KomaMatrixContext<T : Any>(val factory: MatrixFactory<koma.matrix.Matrix<T
|
||||
KomaMatrix(a.toKoma().origin.inv())
|
||||
}
|
||||
|
||||
inline class KomaMatrix<T : Any>(val origin: koma.matrix.Matrix<T>) : Matrix<T> {
|
||||
class KomaMatrix<T : Any>(val origin: koma.matrix.Matrix<T>, features: Set<MatrixFeature>? = null) :
|
||||
Matrix<T> {
|
||||
override val rowNum: Int get() = origin.numRows()
|
||||
override val colNum: Int get() = origin.numCols()
|
||||
override val features: Set<MatrixFeature> get() = emptySet()
|
||||
|
||||
override val features: Set<MatrixFeature> = features ?: setOf(
|
||||
object : DeterminantFeature<T> {
|
||||
override val determinant: T get() = origin.det()
|
||||
},
|
||||
object : LUPDecompositionFeature<T> {
|
||||
private val lup by lazy { origin.LU() }
|
||||
override val l: Matrix<T> get() = KomaMatrix(lup.second)
|
||||
override val u: Matrix<T> get() = KomaMatrix(lup.third)
|
||||
override val p: Matrix<T> get() = KomaMatrix(lup.first)
|
||||
}
|
||||
)
|
||||
|
||||
override fun suggestFeature(vararg features: MatrixFeature): Matrix<T> =
|
||||
KomaMatrix(this.origin, this.features + features)
|
||||
|
||||
override fun get(i: Int, j: Int): T = origin.getGeneric(i, j)
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user