Golub-Kahan SVD algorithm for KMP tensors #499
@ -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()
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -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()
|
|
||||||
}
|
}
|
Loading…
Reference in New Issue
Block a user