KMP library for tensors #300
@ -5,13 +5,15 @@
|
|||||||
|
|
||||||
package space.kscience.kmath.tensors.api
|
package space.kscience.kmath.tensors.api
|
||||||
|
|
||||||
|
import space.kscience.kmath.operations.Algebra
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Algebra over a ring on [TensorStructure].
|
* Algebra over a ring on [TensorStructure].
|
||||||
* For more information: https://proofwiki.org/wiki/Definition:Algebra_over_Ring
|
* For more information: https://proofwiki.org/wiki/Definition:Algebra_over_Ring
|
||||||
*
|
*
|
||||||
* @param T the type of items in the tensors.
|
* @param T the type of items in the tensors.
|
||||||
*/
|
*/
|
||||||
public interface TensorAlgebra<T> {
|
public interface TensorAlgebra<T>: Algebra<TensorStructure<T>> {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns a single tensor value of unit dimension. The tensor shape must be equal to [1].
|
* Returns a single tensor value of unit dimension. The tensor shape must be equal to [1].
|
||||||
|
@ -14,7 +14,7 @@ import space.kscience.kmath.tensors.core.broadcastTo
|
|||||||
* Basic linear algebra operations implemented with broadcasting.
|
* Basic linear algebra operations implemented with broadcasting.
|
||||||
* For more information: https://pytorch.org/docs/stable/notes/broadcasting.html
|
* For more information: https://pytorch.org/docs/stable/notes/broadcasting.html
|
||||||
*/
|
*/
|
||||||
public class BroadcastDoubleTensorAlgebra : DoubleTensorAlgebra() {
|
public object BroadcastDoubleTensorAlgebra : DoubleTensorAlgebra() {
|
||||||
|
|
||||||
override fun TensorStructure<Double>.plus(other: TensorStructure<Double>): DoubleTensor {
|
override fun TensorStructure<Double>.plus(other: TensorStructure<Double>): DoubleTensor {
|
||||||
val broadcast = broadcastTensors(tensor, other.tensor)
|
val broadcast = broadcastTensors(tensor, other.tensor)
|
||||||
@ -89,5 +89,4 @@ public class BroadcastDoubleTensorAlgebra : DoubleTensorAlgebra() {
|
|||||||
newOther.buffer.array()[tensor.bufferStart + i]
|
newOther.buffer.array()[tensor.bufferStart + i]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
@ -11,10 +11,9 @@ import space.kscience.kmath.tensors.core.DoubleTensor
|
|||||||
import space.kscience.kmath.tensors.core.tensor
|
import space.kscience.kmath.tensors.core.tensor
|
||||||
import kotlin.math.*
|
import kotlin.math.*
|
||||||
|
|
||||||
public class DoubleAnalyticTensorAlgebra:
|
public object DoubleAnalyticTensorAlgebra :
|
||||||
AnalyticTensorAlgebra<Double>,
|
AnalyticTensorAlgebra<Double>,
|
||||||
DoubleTensorAlgebra()
|
DoubleTensorAlgebra() {
|
||||||
{
|
|
||||||
override fun TensorStructure<Double>.exp(): DoubleTensor = tensor.map(::exp)
|
override fun TensorStructure<Double>.exp(): DoubleTensor = tensor.map(::exp)
|
||||||
|
|
||||||
override fun TensorStructure<Double>.log(): DoubleTensor = tensor.map(::ln)
|
override fun TensorStructure<Double>.log(): DoubleTensor = tensor.map(::ln)
|
||||||
@ -50,6 +49,3 @@ public class DoubleAnalyticTensorAlgebra:
|
|||||||
override fun TensorStructure<Double>.floor(): DoubleTensor = tensor.map(::floor)
|
override fun TensorStructure<Double>.floor(): DoubleTensor = tensor.map(::floor)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public inline fun <R> DoubleAnalyticTensorAlgebra(block: DoubleAnalyticTensorAlgebra.() -> R): R =
|
|
||||||
DoubleAnalyticTensorAlgebra().block()
|
|
@ -21,7 +21,7 @@ import space.kscience.kmath.tensors.core.pivInit
|
|||||||
import kotlin.math.min
|
import kotlin.math.min
|
||||||
|
|
||||||
|
|
||||||
public class DoubleLinearOpsTensorAlgebra :
|
public object DoubleLinearOpsTensorAlgebra :
|
||||||
LinearOpsTensorAlgebra<Double>,
|
LinearOpsTensorAlgebra<Double>,
|
||||||
DoubleTensorAlgebra() {
|
DoubleTensorAlgebra() {
|
||||||
|
|
||||||
@ -30,8 +30,8 @@ public class DoubleLinearOpsTensorAlgebra :
|
|||||||
override fun TensorStructure<Double>.det(): DoubleTensor = detLU(1e-9)
|
override fun TensorStructure<Double>.det(): DoubleTensor = detLU(1e-9)
|
||||||
|
|
||||||
public fun TensorStructure<Double>.luFactor(epsilon: Double): Pair<DoubleTensor, IntTensor> =
|
public fun TensorStructure<Double>.luFactor(epsilon: Double): Pair<DoubleTensor, IntTensor> =
|
||||||
computeLU(tensor, epsilon) ?:
|
computeLU(tensor, epsilon)
|
||||||
throw RuntimeException("Tensor contains matrices which are singular at precision $epsilon")
|
?: throw RuntimeException("Tensor contains matrices which are singular at precision $epsilon")
|
||||||
|
|
||||||
public fun TensorStructure<Double>.luFactor(): Pair<DoubleTensor, IntTensor> = luFactor(1e-9)
|
public fun TensorStructure<Double>.luFactor(): Pair<DoubleTensor, IntTensor> = luFactor(1e-9)
|
||||||
|
|
||||||
@ -175,8 +175,4 @@ public class DoubleLinearOpsTensorAlgebra :
|
|||||||
|
|
||||||
override fun TensorStructure<Double>.lu(): Triple<DoubleTensor, DoubleTensor, DoubleTensor> = lu(1e-9)
|
override fun TensorStructure<Double>.lu(): Triple<DoubleTensor, DoubleTensor, DoubleTensor> = lu(1e-9)
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public inline fun <R> DoubleLinearOpsTensorAlgebra(block: DoubleLinearOpsTensorAlgebra.() -> R): R =
|
|
||||||
DoubleLinearOpsTensorAlgebra().block()
|
|
@ -23,6 +23,7 @@ import kotlin.math.abs
|
|||||||
|
|
||||||
public open class DoubleTensorAlgebra : TensorPartialDivisionAlgebra<Double> {
|
public open class DoubleTensorAlgebra : TensorPartialDivisionAlgebra<Double> {
|
||||||
|
|
||||||
|
public companion object : DoubleTensorAlgebra()
|
||||||
|
|
||||||
override fun TensorStructure<Double>.value(): Double {
|
override fun TensorStructure<Double>.value(): Double {
|
||||||
check(tensor.shape contentEquals intArrayOf(1)) {
|
check(tensor.shape contentEquals intArrayOf(1)) {
|
||||||
@ -395,7 +396,3 @@ public open class DoubleTensorAlgebra : TensorPartialDivisionAlgebra<Double> {
|
|||||||
DoubleTensor(tensor.shape, getRandomNormals(tensor.shape.reduce(Int::times), seed))
|
DoubleTensor(tensor.shape, getRandomNormals(tensor.shape.reduce(Int::times), seed))
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public inline fun <R> DoubleTensorAlgebra(block: DoubleTensorAlgebra.() -> R): R =
|
|
||||||
DoubleTensorAlgebra().block()
|
|
||||||
|
@ -1,11 +1,7 @@
|
|||||||
package space.kscience.kmath.tensors.core
|
package space.kscience.kmath.tensors.core
|
||||||
|
|
||||||
import space.kscience.kmath.tensors.core.algebras.BroadcastDoubleTensorAlgebra
|
|
||||||
import kotlin.math.max
|
import kotlin.math.max
|
||||||
|
|
||||||
public inline fun <R> BroadcastDoubleTensorAlgebra(block: BroadcastDoubleTensorAlgebra.() -> R): R =
|
|
||||||
BroadcastDoubleTensorAlgebra().block()
|
|
||||||
|
|
||||||
internal inline fun multiIndexBroadCasting(tensor: DoubleTensor, resTensor: DoubleTensor, linearSize: Int) {
|
internal inline fun multiIndexBroadCasting(tensor: DoubleTensor, resTensor: DoubleTensor, linearSize: Int) {
|
||||||
for (linearIndex in 0 until linearSize) {
|
for (linearIndex in 0 until linearSize) {
|
||||||
val totalMultiIndex = resTensor.linearStructure.index(linearIndex)
|
val totalMultiIndex = resTensor.linearStructure.index(linearIndex)
|
||||||
|
@ -4,6 +4,7 @@ import space.kscience.kmath.nd.MutableStructure1D
|
|||||||
import space.kscience.kmath.nd.MutableStructure2D
|
import space.kscience.kmath.nd.MutableStructure2D
|
||||||
import space.kscience.kmath.nd.as1D
|
import space.kscience.kmath.nd.as1D
|
||||||
import space.kscience.kmath.nd.as2D
|
import space.kscience.kmath.nd.as2D
|
||||||
|
import space.kscience.kmath.operations.invoke
|
||||||
import space.kscience.kmath.tensors.core.algebras.DoubleAnalyticTensorAlgebra
|
import space.kscience.kmath.tensors.core.algebras.DoubleAnalyticTensorAlgebra
|
||||||
import space.kscience.kmath.tensors.core.algebras.DoubleLinearOpsTensorAlgebra
|
import space.kscience.kmath.tensors.core.algebras.DoubleLinearOpsTensorAlgebra
|
||||||
import kotlin.math.abs
|
import kotlin.math.abs
|
||||||
@ -251,7 +252,7 @@ internal inline fun DoubleLinearOpsTensorAlgebra.qrHelper(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
r[j, j] = DoubleAnalyticTensorAlgebra { (v dot v).sqrt().value() }
|
r[j, j] = DoubleAnalyticTensorAlgebra.invoke { (v dot v).sqrt().value() }
|
||||||
for (i in 0 until n) {
|
for (i in 0 until n) {
|
||||||
qM[i, j] = vv[i] / r[j, j]
|
qM[i, j] = vv[i] / r[j, j]
|
||||||
}
|
}
|
||||||
|
@ -1,13 +1,15 @@
|
|||||||
package space.kscience.kmath.tensors.core
|
package space.kscience.kmath.tensors.core
|
||||||
|
|
||||||
|
import space.kscience.kmath.operations.invoke
|
||||||
|
import space.kscience.kmath.tensors.core.algebras.BroadcastDoubleTensorAlgebra
|
||||||
import space.kscience.kmath.tensors.core.algebras.DoubleTensorAlgebra
|
import space.kscience.kmath.tensors.core.algebras.DoubleTensorAlgebra
|
||||||
import kotlin.test.Test
|
import kotlin.test.Test
|
||||||
import kotlin.test.assertTrue
|
import kotlin.test.assertTrue
|
||||||
|
|
||||||
class TestBroadcasting {
|
internal class TestBroadcasting {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun broadcastShapes() = DoubleTensorAlgebra {
|
fun broadcastShapes() = DoubleTensorAlgebra.invoke {
|
||||||
assertTrue(
|
assertTrue(
|
||||||
broadcastShapes(
|
broadcastShapes(
|
||||||
intArrayOf(2, 3), intArrayOf(1, 3), intArrayOf(1, 1, 1)
|
intArrayOf(2, 3), intArrayOf(1, 3), intArrayOf(1, 1, 1)
|
||||||
@ -22,7 +24,7 @@ class TestBroadcasting {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun broadcastTo() = DoubleTensorAlgebra {
|
fun broadcastTo() = DoubleTensorAlgebra.invoke {
|
||||||
val tensor1 = fromArray(intArrayOf(2, 3), doubleArrayOf(1.0, 2.0, 3.0, 4.0, 5.0, 6.0))
|
val tensor1 = fromArray(intArrayOf(2, 3), doubleArrayOf(1.0, 2.0, 3.0, 4.0, 5.0, 6.0))
|
||||||
val tensor2 = fromArray(intArrayOf(1, 3), doubleArrayOf(10.0, 20.0, 30.0))
|
val tensor2 = fromArray(intArrayOf(1, 3), doubleArrayOf(10.0, 20.0, 30.0))
|
||||||
|
|
||||||
@ -32,7 +34,7 @@ class TestBroadcasting {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun broadcastTensors() = DoubleTensorAlgebra {
|
fun broadcastTensors() = DoubleTensorAlgebra.invoke {
|
||||||
val tensor1 = fromArray(intArrayOf(2, 3), doubleArrayOf(1.0, 2.0, 3.0, 4.0, 5.0, 6.0))
|
val tensor1 = fromArray(intArrayOf(2, 3), doubleArrayOf(1.0, 2.0, 3.0, 4.0, 5.0, 6.0))
|
||||||
val tensor2 = fromArray(intArrayOf(1, 3), doubleArrayOf(10.0, 20.0, 30.0))
|
val tensor2 = fromArray(intArrayOf(1, 3), doubleArrayOf(10.0, 20.0, 30.0))
|
||||||
val tensor3 = fromArray(intArrayOf(1, 1, 1), doubleArrayOf(500.0))
|
val tensor3 = fromArray(intArrayOf(1, 1, 1), doubleArrayOf(500.0))
|
||||||
@ -49,7 +51,7 @@ class TestBroadcasting {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun broadcastOuterTensors() = DoubleTensorAlgebra {
|
fun broadcastOuterTensors() = DoubleTensorAlgebra.invoke {
|
||||||
val tensor1 = fromArray(intArrayOf(2, 3), doubleArrayOf(1.0, 2.0, 3.0, 4.0, 5.0, 6.0))
|
val tensor1 = fromArray(intArrayOf(2, 3), doubleArrayOf(1.0, 2.0, 3.0, 4.0, 5.0, 6.0))
|
||||||
val tensor2 = fromArray(intArrayOf(1, 3), doubleArrayOf(10.0, 20.0, 30.0))
|
val tensor2 = fromArray(intArrayOf(1, 3), doubleArrayOf(10.0, 20.0, 30.0))
|
||||||
val tensor3 = fromArray(intArrayOf(1, 1, 1), doubleArrayOf(500.0))
|
val tensor3 = fromArray(intArrayOf(1, 1, 1), doubleArrayOf(500.0))
|
||||||
@ -66,7 +68,7 @@ class TestBroadcasting {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun broadcastOuterTensorsShapes() = DoubleTensorAlgebra {
|
fun broadcastOuterTensorsShapes() = DoubleTensorAlgebra.invoke {
|
||||||
val tensor1 = fromArray(intArrayOf(2, 1, 3, 2, 3), DoubleArray(2 * 1 * 3 * 2 * 3) {0.0})
|
val tensor1 = fromArray(intArrayOf(2, 1, 3, 2, 3), DoubleArray(2 * 1 * 3 * 2 * 3) {0.0})
|
||||||
val tensor2 = fromArray(intArrayOf(4, 2, 5, 1, 3, 3), DoubleArray(4 * 2 * 5 * 1 * 3 * 3) {0.0})
|
val tensor2 = fromArray(intArrayOf(4, 2, 5, 1, 3, 3), DoubleArray(4 * 2 * 5 * 1 * 3 * 3) {0.0})
|
||||||
val tensor3 = fromArray(intArrayOf(1, 1), doubleArrayOf(500.0))
|
val tensor3 = fromArray(intArrayOf(1, 1), doubleArrayOf(500.0))
|
||||||
@ -79,7 +81,7 @@ class TestBroadcasting {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun minusTensor() = BroadcastDoubleTensorAlgebra {
|
fun minusTensor() = BroadcastDoubleTensorAlgebra.invoke {
|
||||||
val tensor1 = fromArray(intArrayOf(2, 3), doubleArrayOf(1.0, 2.0, 3.0, 4.0, 5.0, 6.0))
|
val tensor1 = fromArray(intArrayOf(2, 3), doubleArrayOf(1.0, 2.0, 3.0, 4.0, 5.0, 6.0))
|
||||||
val tensor2 = fromArray(intArrayOf(1, 3), doubleArrayOf(10.0, 20.0, 30.0))
|
val tensor2 = fromArray(intArrayOf(1, 3), doubleArrayOf(10.0, 20.0, 30.0))
|
||||||
val tensor3 = fromArray(intArrayOf(1, 1, 1), doubleArrayOf(500.0))
|
val tensor3 = fromArray(intArrayOf(1, 1, 1), doubleArrayOf(500.0))
|
||||||
|
@ -1,12 +1,13 @@
|
|||||||
package space.kscience.kmath.tensors.core
|
package space.kscience.kmath.tensors.core
|
||||||
|
|
||||||
|
import space.kscience.kmath.operations.invoke
|
||||||
import space.kscience.kmath.tensors.core.algebras.DoubleAnalyticTensorAlgebra
|
import space.kscience.kmath.tensors.core.algebras.DoubleAnalyticTensorAlgebra
|
||||||
import kotlin.math.abs
|
import kotlin.math.abs
|
||||||
import kotlin.math.exp
|
import kotlin.math.exp
|
||||||
import kotlin.test.Test
|
import kotlin.test.Test
|
||||||
import kotlin.test.assertTrue
|
import kotlin.test.assertTrue
|
||||||
|
|
||||||
class TestDoubleAnalyticTensorAlgebra {
|
internal class TestDoubleAnalyticTensorAlgebra {
|
||||||
|
|
||||||
val shape = intArrayOf(2, 1, 3, 2)
|
val shape = intArrayOf(2, 1, 3, 2)
|
||||||
val buffer = doubleArrayOf(27.1, 20.0, 19.84, 23.123, 0.0, 1.0, 3.23, 133.7, 25.3, 100.3, 11.0, 12.012)
|
val buffer = doubleArrayOf(27.1, 20.0, 19.84, 23.123, 0.0, 1.0, 3.23, 133.7, 25.3, 100.3, 11.0, 12.012)
|
||||||
@ -26,7 +27,7 @@ class TestDoubleAnalyticTensorAlgebra {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun testExp() = DoubleAnalyticTensorAlgebra {
|
fun testExp() = DoubleAnalyticTensorAlgebra.invoke {
|
||||||
tensor.exp().let {
|
tensor.exp().let {
|
||||||
assertTrue { shape contentEquals it.shape }
|
assertTrue { shape contentEquals it.shape }
|
||||||
assertTrue { buffer.fmap(::exp).epsEqual(it.buffer.array())}
|
assertTrue { buffer.fmap(::exp).epsEqual(it.buffer.array())}
|
||||||
|
@ -1,15 +1,16 @@
|
|||||||
package space.kscience.kmath.tensors.core
|
package space.kscience.kmath.tensors.core
|
||||||
|
|
||||||
|
import space.kscience.kmath.operations.invoke
|
||||||
import space.kscience.kmath.tensors.core.algebras.DoubleLinearOpsTensorAlgebra
|
import space.kscience.kmath.tensors.core.algebras.DoubleLinearOpsTensorAlgebra
|
||||||
import kotlin.math.abs
|
import kotlin.math.abs
|
||||||
import kotlin.test.Test
|
import kotlin.test.Test
|
||||||
import kotlin.test.assertEquals
|
import kotlin.test.assertEquals
|
||||||
import kotlin.test.assertTrue
|
import kotlin.test.assertTrue
|
||||||
|
|
||||||
class TestDoubleLinearOpsTensorAlgebra {
|
internal class TestDoubleLinearOpsTensorAlgebra {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun testDetLU() = DoubleLinearOpsTensorAlgebra {
|
fun testDetLU() = DoubleLinearOpsTensorAlgebra.invoke {
|
||||||
val tensor = fromArray(
|
val tensor = fromArray(
|
||||||
intArrayOf(2, 2, 2),
|
intArrayOf(2, 2, 2),
|
||||||
doubleArrayOf(
|
doubleArrayOf(
|
||||||
@ -34,7 +35,7 @@ class TestDoubleLinearOpsTensorAlgebra {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun testDet() = DoubleLinearOpsTensorAlgebra {
|
fun testDet() = DoubleLinearOpsTensorAlgebra.invoke {
|
||||||
val expectedValue = 0.019827417
|
val expectedValue = 0.019827417
|
||||||
val m = fromArray(
|
val m = fromArray(
|
||||||
intArrayOf(3, 3), doubleArrayOf(
|
intArrayOf(3, 3), doubleArrayOf(
|
||||||
@ -48,7 +49,7 @@ class TestDoubleLinearOpsTensorAlgebra {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun testDetSingle() = DoubleLinearOpsTensorAlgebra {
|
fun testDetSingle() = DoubleLinearOpsTensorAlgebra.invoke {
|
||||||
val expectedValue = 48.151623
|
val expectedValue = 48.151623
|
||||||
val m = fromArray(
|
val m = fromArray(
|
||||||
intArrayOf(1, 1), doubleArrayOf(
|
intArrayOf(1, 1), doubleArrayOf(
|
||||||
@ -60,7 +61,7 @@ class TestDoubleLinearOpsTensorAlgebra {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun testInvLU() = DoubleLinearOpsTensorAlgebra {
|
fun testInvLU() = DoubleLinearOpsTensorAlgebra.invoke {
|
||||||
val tensor = fromArray(
|
val tensor = fromArray(
|
||||||
intArrayOf(2, 2, 2),
|
intArrayOf(2, 2, 2),
|
||||||
doubleArrayOf(
|
doubleArrayOf(
|
||||||
@ -85,14 +86,14 @@ class TestDoubleLinearOpsTensorAlgebra {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun testScalarProduct() = DoubleLinearOpsTensorAlgebra {
|
fun testScalarProduct() = DoubleLinearOpsTensorAlgebra.invoke {
|
||||||
val a = fromArray(intArrayOf(3), doubleArrayOf(1.8, 2.5, 6.8))
|
val a = fromArray(intArrayOf(3), doubleArrayOf(1.8, 2.5, 6.8))
|
||||||
val b = fromArray(intArrayOf(3), doubleArrayOf(5.5, 2.6, 6.4))
|
val b = fromArray(intArrayOf(3), doubleArrayOf(5.5, 2.6, 6.4))
|
||||||
assertEquals(a.dot(b).value(), 59.92)
|
assertEquals(a.dot(b).value(), 59.92)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun testQR() = DoubleLinearOpsTensorAlgebra {
|
fun testQR() = DoubleLinearOpsTensorAlgebra.invoke {
|
||||||
val shape = intArrayOf(2, 2, 2)
|
val shape = intArrayOf(2, 2, 2)
|
||||||
val buffer = doubleArrayOf(
|
val buffer = doubleArrayOf(
|
||||||
1.0, 3.0,
|
1.0, 3.0,
|
||||||
@ -110,11 +111,10 @@ class TestDoubleLinearOpsTensorAlgebra {
|
|||||||
|
|
||||||
assertTrue((q dot r).eq(tensor))
|
assertTrue((q dot r).eq(tensor))
|
||||||
|
|
||||||
//todo check orthogonality/upper triang.
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun testLU() = DoubleLinearOpsTensorAlgebra {
|
fun testLU() = DoubleLinearOpsTensorAlgebra.invoke {
|
||||||
val shape = intArrayOf(2, 2, 2)
|
val shape = intArrayOf(2, 2, 2)
|
||||||
val buffer = doubleArrayOf(
|
val buffer = doubleArrayOf(
|
||||||
1.0, 3.0,
|
1.0, 3.0,
|
||||||
@ -134,7 +134,7 @@ class TestDoubleLinearOpsTensorAlgebra {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun testCholesky() = DoubleLinearOpsTensorAlgebra {
|
fun testCholesky() = DoubleLinearOpsTensorAlgebra.invoke {
|
||||||
val tensor = randNormal(intArrayOf(2, 5, 5), 0)
|
val tensor = randNormal(intArrayOf(2, 5, 5), 0)
|
||||||
val sigma = (tensor dot tensor.transpose()) + diagonalEmbedding(
|
val sigma = (tensor dot tensor.transpose()) + diagonalEmbedding(
|
||||||
fromArray(intArrayOf(2, 5), DoubleArray(10) { 0.1 })
|
fromArray(intArrayOf(2, 5), DoubleArray(10) { 0.1 })
|
||||||
@ -145,7 +145,7 @@ class TestDoubleLinearOpsTensorAlgebra {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun testSVD1D() = DoubleLinearOpsTensorAlgebra {
|
fun testSVD1D() = DoubleLinearOpsTensorAlgebra.invoke {
|
||||||
val tensor2 = fromArray(intArrayOf(2, 3), doubleArrayOf(1.0, 2.0, 3.0, 4.0, 5.0, 6.0))
|
val tensor2 = fromArray(intArrayOf(2, 3), doubleArrayOf(1.0, 2.0, 3.0, 4.0, 5.0, 6.0))
|
||||||
|
|
||||||
val res = svd1d(tensor2)
|
val res = svd1d(tensor2)
|
||||||
@ -156,13 +156,13 @@ class TestDoubleLinearOpsTensorAlgebra {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun testSVD() = DoubleLinearOpsTensorAlgebra {
|
fun testSVD() = DoubleLinearOpsTensorAlgebra.invoke{
|
||||||
testSVDFor(fromArray(intArrayOf(2, 3), doubleArrayOf(1.0, 2.0, 3.0, 4.0, 5.0, 6.0)))
|
testSVDFor(fromArray(intArrayOf(2, 3), doubleArrayOf(1.0, 2.0, 3.0, 4.0, 5.0, 6.0)))
|
||||||
testSVDFor(fromArray(intArrayOf(2, 2), doubleArrayOf(-1.0, 0.0, 239.0, 238.0)))
|
testSVDFor(fromArray(intArrayOf(2, 2), doubleArrayOf(-1.0, 0.0, 239.0, 238.0)))
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun testBatchedSVD() = DoubleLinearOpsTensorAlgebra {
|
fun testBatchedSVD() = DoubleLinearOpsTensorAlgebra.invoke {
|
||||||
val tensor = randNormal(intArrayOf(2, 5, 3), 0)
|
val tensor = randNormal(intArrayOf(2, 5, 3), 0)
|
||||||
val (tensorU, tensorS, tensorV) = tensor.svd()
|
val (tensorU, tensorS, tensorV) = tensor.svd()
|
||||||
val tensorSVD = tensorU dot (diagonalEmbedding(tensorS) dot tensorV.transpose())
|
val tensorSVD = tensorU dot (diagonalEmbedding(tensorS) dot tensorV.transpose())
|
||||||
@ -170,7 +170,7 @@ class TestDoubleLinearOpsTensorAlgebra {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun testBatchedSymEig() = DoubleLinearOpsTensorAlgebra {
|
fun testBatchedSymEig() = DoubleLinearOpsTensorAlgebra.invoke {
|
||||||
val tensor = randNormal(shape = intArrayOf(2, 3, 3), 0)
|
val tensor = randNormal(shape = intArrayOf(2, 3, 3), 0)
|
||||||
val tensorSigma = tensor + tensor.transpose()
|
val tensorSigma = tensor + tensor.transpose()
|
||||||
val (tensorS, tensorV) = tensorSigma.symEig()
|
val (tensorS, tensorV) = tensorSigma.symEig()
|
||||||
|
@ -4,6 +4,7 @@ import space.kscience.kmath.nd.DefaultStrides
|
|||||||
import space.kscience.kmath.nd.MutableBufferND
|
import space.kscience.kmath.nd.MutableBufferND
|
||||||
import space.kscience.kmath.nd.as1D
|
import space.kscience.kmath.nd.as1D
|
||||||
import space.kscience.kmath.nd.as2D
|
import space.kscience.kmath.nd.as2D
|
||||||
|
import space.kscience.kmath.operations.invoke
|
||||||
import space.kscience.kmath.structures.DoubleBuffer
|
import space.kscience.kmath.structures.DoubleBuffer
|
||||||
import space.kscience.kmath.structures.asMutableBuffer
|
import space.kscience.kmath.structures.asMutableBuffer
|
||||||
import space.kscience.kmath.structures.toDoubleArray
|
import space.kscience.kmath.structures.toDoubleArray
|
||||||
@ -12,17 +13,17 @@ import kotlin.test.Test
|
|||||||
import kotlin.test.assertEquals
|
import kotlin.test.assertEquals
|
||||||
import kotlin.test.assertTrue
|
import kotlin.test.assertTrue
|
||||||
|
|
||||||
class TestDoubleTensor {
|
internal class TestDoubleTensor {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun valueTest() = DoubleTensorAlgebra {
|
fun valueTest() = DoubleTensorAlgebra.invoke {
|
||||||
val value = 12.5
|
val value = 12.5
|
||||||
val tensor = fromArray(intArrayOf(1), doubleArrayOf(value))
|
val tensor = fromArray(intArrayOf(1), doubleArrayOf(value))
|
||||||
assertEquals(tensor.value(), value)
|
assertEquals(tensor.value(), value)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun stridesTest() = DoubleTensorAlgebra {
|
fun stridesTest() = DoubleTensorAlgebra.invoke {
|
||||||
val tensor = fromArray(intArrayOf(2, 2), doubleArrayOf(3.5, 5.8, 58.4, 2.4))
|
val tensor = fromArray(intArrayOf(2, 2), doubleArrayOf(3.5, 5.8, 58.4, 2.4))
|
||||||
assertEquals(tensor[intArrayOf(0, 1)], 5.8)
|
assertEquals(tensor[intArrayOf(0, 1)], 5.8)
|
||||||
assertTrue(
|
assertTrue(
|
||||||
@ -31,7 +32,7 @@ class TestDoubleTensor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun getTest() = DoubleTensorAlgebra {
|
fun getTest() = DoubleTensorAlgebra.invoke {
|
||||||
val tensor = fromArray(intArrayOf(1, 2, 2), doubleArrayOf(3.5, 5.8, 58.4, 2.4))
|
val tensor = fromArray(intArrayOf(1, 2, 2), doubleArrayOf(3.5, 5.8, 58.4, 2.4))
|
||||||
val matrix = tensor[0].as2D()
|
val matrix = tensor[0].as2D()
|
||||||
assertEquals(matrix[0, 1], 5.8)
|
assertEquals(matrix[0, 1], 5.8)
|
||||||
|
@ -1,29 +1,30 @@
|
|||||||
package space.kscience.kmath.tensors.core
|
package space.kscience.kmath.tensors.core
|
||||||
|
|
||||||
|
|
||||||
|
import space.kscience.kmath.operations.invoke
|
||||||
import space.kscience.kmath.tensors.core.algebras.DoubleTensorAlgebra
|
import space.kscience.kmath.tensors.core.algebras.DoubleTensorAlgebra
|
||||||
import kotlin.test.Test
|
import kotlin.test.Test
|
||||||
import kotlin.test.assertFalse
|
import kotlin.test.assertFalse
|
||||||
import kotlin.test.assertTrue
|
import kotlin.test.assertTrue
|
||||||
|
|
||||||
class TestDoubleTensorAlgebra {
|
internal class TestDoubleTensorAlgebra {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun doublePlus() = DoubleTensorAlgebra {
|
fun doublePlus() = DoubleTensorAlgebra.invoke {
|
||||||
val tensor = fromArray(intArrayOf(2), doubleArrayOf(1.0, 2.0))
|
val tensor = fromArray(intArrayOf(2), doubleArrayOf(1.0, 2.0))
|
||||||
val res = 10.0 + tensor
|
val res = 10.0 + tensor
|
||||||
assertTrue(res.buffer.array() contentEquals doubleArrayOf(11.0, 12.0))
|
assertTrue(res.buffer.array() contentEquals doubleArrayOf(11.0, 12.0))
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun doubleDiv() = DoubleTensorAlgebra {
|
fun doubleDiv() = DoubleTensorAlgebra.invoke {
|
||||||
val tensor = fromArray(intArrayOf(2), doubleArrayOf(2.0, 4.0))
|
val tensor = fromArray(intArrayOf(2), doubleArrayOf(2.0, 4.0))
|
||||||
val res = 2.0/tensor
|
val res = 2.0/tensor
|
||||||
assertTrue(res.buffer.array() contentEquals doubleArrayOf(1.0, 0.5))
|
assertTrue(res.buffer.array() contentEquals doubleArrayOf(1.0, 0.5))
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun divDouble() = DoubleTensorAlgebra {
|
fun divDouble() = DoubleTensorAlgebra.invoke {
|
||||||
val tensor = fromArray(intArrayOf(2), doubleArrayOf(10.0, 5.0))
|
val tensor = fromArray(intArrayOf(2), doubleArrayOf(10.0, 5.0))
|
||||||
val res = tensor / 2.5
|
val res = tensor / 2.5
|
||||||
assertTrue(res.buffer.array() contentEquals doubleArrayOf(4.0, 2.0))
|
assertTrue(res.buffer.array() contentEquals doubleArrayOf(4.0, 2.0))
|
||||||
@ -39,7 +40,7 @@ class TestDoubleTensorAlgebra {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun transpose3x2() = DoubleTensorAlgebra {
|
fun transpose3x2() = DoubleTensorAlgebra.invoke {
|
||||||
val tensor = fromArray(intArrayOf(3, 2), doubleArrayOf(1.0, 2.0, 3.0, 4.0, 5.0, 6.0))
|
val tensor = fromArray(intArrayOf(3, 2), doubleArrayOf(1.0, 2.0, 3.0, 4.0, 5.0, 6.0))
|
||||||
val res = tensor.transpose(1, 0)
|
val res = tensor.transpose(1, 0)
|
||||||
|
|
||||||
@ -48,7 +49,7 @@ class TestDoubleTensorAlgebra {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun transpose1x2x3() = DoubleTensorAlgebra {
|
fun transpose1x2x3() = DoubleTensorAlgebra.invoke {
|
||||||
val tensor = fromArray(intArrayOf(1, 2, 3), doubleArrayOf(1.0, 2.0, 3.0, 4.0, 5.0, 6.0))
|
val tensor = fromArray(intArrayOf(1, 2, 3), doubleArrayOf(1.0, 2.0, 3.0, 4.0, 5.0, 6.0))
|
||||||
val res01 = tensor.transpose(0, 1)
|
val res01 = tensor.transpose(0, 1)
|
||||||
val res02 = tensor.transpose(-3, 2)
|
val res02 = tensor.transpose(-3, 2)
|
||||||
@ -64,7 +65,7 @@ class TestDoubleTensorAlgebra {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun linearStructure() = DoubleTensorAlgebra {
|
fun linearStructure() = DoubleTensorAlgebra.invoke {
|
||||||
val shape = intArrayOf(3)
|
val shape = intArrayOf(3)
|
||||||
val tensorA = full(value = -4.5, shape = shape)
|
val tensorA = full(value = -4.5, shape = shape)
|
||||||
val tensorB = full(value = 10.9, shape = shape)
|
val tensorB = full(value = 10.9, shape = shape)
|
||||||
@ -96,7 +97,7 @@ class TestDoubleTensorAlgebra {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun dot() = DoubleTensorAlgebra {
|
fun dot() = DoubleTensorAlgebra.invoke {
|
||||||
val tensor1 = fromArray(intArrayOf(2, 3), doubleArrayOf(1.0, 2.0, 3.0, 4.0, 5.0, 6.0))
|
val tensor1 = fromArray(intArrayOf(2, 3), doubleArrayOf(1.0, 2.0, 3.0, 4.0, 5.0, 6.0))
|
||||||
val tensor11 = fromArray(intArrayOf(3, 2), doubleArrayOf(1.0, 2.0, 3.0, 4.0, 5.0, 6.0))
|
val tensor11 = fromArray(intArrayOf(3, 2), doubleArrayOf(1.0, 2.0, 3.0, 4.0, 5.0, 6.0))
|
||||||
val tensor2 = fromArray(intArrayOf(3), doubleArrayOf(10.0, 20.0, 30.0))
|
val tensor2 = fromArray(intArrayOf(3), doubleArrayOf(10.0, 20.0, 30.0))
|
||||||
@ -132,7 +133,7 @@ class TestDoubleTensorAlgebra {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun diagonalEmbedding() = DoubleTensorAlgebra {
|
fun diagonalEmbedding() = DoubleTensorAlgebra.invoke {
|
||||||
val tensor1 = fromArray(intArrayOf(3), doubleArrayOf(10.0, 20.0, 30.0))
|
val tensor1 = fromArray(intArrayOf(3), doubleArrayOf(10.0, 20.0, 30.0))
|
||||||
val tensor2 = fromArray(intArrayOf(2, 3), doubleArrayOf(1.0, 2.0, 3.0, 4.0, 5.0, 6.0))
|
val tensor2 = fromArray(intArrayOf(2, 3), doubleArrayOf(1.0, 2.0, 3.0, 4.0, 5.0, 6.0))
|
||||||
val tensor3 = zeros(intArrayOf(2, 3, 4, 5))
|
val tensor3 = zeros(intArrayOf(2, 3, 4, 5))
|
||||||
@ -165,7 +166,7 @@ class TestDoubleTensorAlgebra {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun testEq() = DoubleTensorAlgebra {
|
fun testEq() = DoubleTensorAlgebra.invoke {
|
||||||
val tensor1 = fromArray(intArrayOf(2, 3), doubleArrayOf(1.0, 2.0, 3.0, 4.0, 5.0, 6.0))
|
val tensor1 = fromArray(intArrayOf(2, 3), doubleArrayOf(1.0, 2.0, 3.0, 4.0, 5.0, 6.0))
|
||||||
val tensor2 = fromArray(intArrayOf(2, 3), doubleArrayOf(1.0, 2.0, 3.0, 4.0, 5.0, 6.0))
|
val tensor2 = fromArray(intArrayOf(2, 3), doubleArrayOf(1.0, 2.0, 3.0, 4.0, 5.0, 6.0))
|
||||||
val tensor3 = fromArray(intArrayOf(2, 3), doubleArrayOf(1.0, 2.0, 3.0, 4.0, 5.0, 5.0))
|
val tensor3 = fromArray(intArrayOf(2, 3), doubleArrayOf(1.0, 2.0, 3.0, 4.0, 5.0, 5.0))
|
||||||
|
Loading…
Reference in New Issue
Block a user