Golub-Kahan SVD algorithm for KMP tensors #499

Closed
grinisrit wants to merge 64 commits from dev into dev
2 changed files with 25 additions and 41 deletions
Showing only changes of commit 8b48eaa1ed - Show all commits

View File

@ -11,28 +11,9 @@ import space.kscience.kmath.nd.MutableStructure2D
import space.kscience.kmath.nd.Structure2D import space.kscience.kmath.nd.Structure2D
import space.kscience.kmath.nd.as2D import space.kscience.kmath.nd.as2D
import space.kscience.kmath.tensors.core.* import space.kscience.kmath.tensors.core.*
import space.kscience.kmath.tensors.core.BroadcastDoubleTensorAlgebra.dot
import space.kscience.kmath.tensors.core.BroadcastDoubleTensorAlgebra.mapIndexed
import space.kscience.kmath.tensors.core.BroadcastDoubleTensorAlgebra.zeros
import space.kscience.kmath.tensors.core.DoubleTensorAlgebra.Companion.minus
import space.kscience.kmath.tensors.core.DoubleTensorAlgebra.Companion.sum
import space.kscience.kmath.tensors.core.tensorAlgebra import space.kscience.kmath.tensors.core.tensorAlgebra
import kotlin.math.* import kotlin.math.*
fun DoubleArray.fmap(transform: (Double) -> Double): DoubleArray {
return this.map(transform).toDoubleArray()
}
fun scalarProduct(v1: Structure2D<Double>, v2: Structure2D<Double>): Double {
return v1.mapIndexed { index, d -> d * v2[index] }.sum()
}
internal fun diagonal(shape: IntArray, v: Double) : DoubleTensor {
val matrix = zeros(shape)
return matrix.mapIndexed { index, _ -> if (index.component1() == index.component2()) v else 0.0 }
}
fun MutableStructure2D<Double>.print() { fun MutableStructure2D<Double>.print() {
val n = this.shape.component1() val n = this.shape.component1()
val m = this.shape.component2() val m = this.shape.component2()
@ -63,11 +44,22 @@ fun main(): Unit = Double.tensorAlgebra.withBroadcast {
) )
val tensor = fromArray(shape, buffer).as2D() val tensor = fromArray(shape, buffer).as2D()
val v = fromArray(intArrayOf(3, 3), buffer2).as2D() val v = fromArray(intArrayOf(3, 3), buffer2).as2D()
val w_shape = intArrayOf(3, 1)
var w_buffer = doubleArrayOf(0.000000)
for (i in 0 until 3 - 1) {
w_buffer += doubleArrayOf(0.000000)
}
val w = BroadcastDoubleTensorAlgebra.fromArray(w_shape, w_buffer).as2D()
tensor.print() tensor.print()
tensor.svdcmp(v) var ans = Pair(w, v)
tensor.svdGolabKahan(v, w)
println("u")
tensor.print()
println("w")
w.print()
println("v")
v.print()
} }

View File

@ -1,7 +1,6 @@
package space.kscience.kmath.tensors package space.kscience.kmath.tensors
import space.kscience.kmath.nd.* import space.kscience.kmath.nd.*
import space.kscience.kmath.tensors.core.BroadcastDoubleTensorAlgebra
import kotlin.math.abs import kotlin.math.abs
import kotlin.math.max import kotlin.math.max
import kotlin.math.min import kotlin.math.min
@ -34,10 +33,12 @@ fun SIGN(a: Double, b: Double): Double {
return -abs(a) return -abs(a)
} }
internal fun MutableStructure2D<Double>.svdcmp(v: MutableStructure2D<Double>) { // matrix v is not transposed at the output
internal fun MutableStructure2D<Double>.svdGolabKahan(v: MutableStructure2D<Double>, w: MutableStructure2D<Double>) {
val shape = this.shape val shape = this.shape
val n = shape.component2()
val m = shape.component1() val m = shape.component1()
val n = shape.component2()
var f = 0.0 var f = 0.0
val rv1 = DoubleArray(n) val rv1 = DoubleArray(n)
var s = 0.0 var s = 0.0
@ -45,12 +46,6 @@ internal fun MutableStructure2D<Double>.svdcmp(v: MutableStructure2D<Double>) {
var anorm = 0.0 var anorm = 0.0
var g = 0.0 var g = 0.0
var l = 0 var l = 0
val w_shape = intArrayOf(n, 1)
var w_buffer = doubleArrayOf(0.000000)
for (i in 0 until n - 1) {
w_buffer += doubleArrayOf(0.000000)
}
val w = BroadcastDoubleTensorAlgebra.fromArray(w_shape, w_buffer).as2D()
for (i in 0 until n) { for (i in 0 until n) {
/* left-hand reduction */ /* left-hand reduction */
l = i + 1 l = i + 1
@ -212,6 +207,9 @@ internal fun MutableStructure2D<Double>.svdcmp(v: MutableStructure2D<Double>) {
this[3, 2] = -0.297540 this[3, 2] = -0.297540
this[4, 2] = 0.548193 this[4, 2] = 0.548193
// задала правильные значения, чтобы проверить правильность кода дальше
// дальше - все корректно
var flag = 0 var flag = 0
var nm = 0 var nm = 0
var c = 0.0 var c = 0.0
@ -268,9 +266,10 @@ internal fun MutableStructure2D<Double>.svdcmp(v: MutableStructure2D<Double>) {
break break
} }
if (its == 30) { // надо придумать, что сделать - выкинуть ошибку?
return // if (its == 30) {
} // return
// }
x = w[l, 0] x = w[l, 0]
nm = k - 1 nm = k - 1
@ -326,11 +325,4 @@ internal fun MutableStructure2D<Double>.svdcmp(v: MutableStructure2D<Double>) {
w[k, 0] = x w[k, 0] = x
} }
} }
println("u")
this.print()
println("w")
w.print()
println("v")
v.print()
} }