From 4575ab2b797ff5dfea99ea72e0470b977eb9ee48 Mon Sep 17 00:00:00 2001 From: Alexander Nozik Date: Mon, 7 Mar 2022 10:39:59 +0300 Subject: [PATCH] Update interpolation API to agree with other conventions. --- .../kscience/kmath/benchmarks/DotBenchmark.kt | 7 +++++ .../kmath/functions/interpolateSquare.kt | 4 +-- .../kmath/integration/SplineIntegrator.kt | 3 ++ .../kmath/interpolation/Interpolator.kt | 31 +++++++++++++++++++ .../kmath/interpolation/LinearInterpolator.kt | 4 +++ .../kmath/interpolation/SplineInterpolator.kt | 16 ++++++---- .../interpolation/LinearInterpolatorTest.kt | 6 ++-- .../interpolation/SplineInterpolatorTest.kt | 7 ++--- .../kscience/kmath/multik/MultikNDTest.kt | 25 +++++++++++++++ .../kmath/tensorflow/DoubleTensorFlowOps.kt | 2 -- 10 files changed, 87 insertions(+), 18 deletions(-) diff --git a/benchmarks/src/jvmMain/kotlin/space/kscience/kmath/benchmarks/DotBenchmark.kt b/benchmarks/src/jvmMain/kotlin/space/kscience/kmath/benchmarks/DotBenchmark.kt index 16fd544a8..7d5ae310b 100644 --- a/benchmarks/src/jvmMain/kotlin/space/kscience/kmath/benchmarks/DotBenchmark.kt +++ b/benchmarks/src/jvmMain/kotlin/space/kscience/kmath/benchmarks/DotBenchmark.kt @@ -15,8 +15,10 @@ import space.kscience.kmath.linear.invoke import space.kscience.kmath.linear.linearSpace import space.kscience.kmath.multik.multikAlgebra import space.kscience.kmath.operations.DoubleField +import space.kscience.kmath.operations.invoke import space.kscience.kmath.structures.Buffer import space.kscience.kmath.tensorflow.produceWithTF +import space.kscience.kmath.tensors.core.DoubleTensorAlgebra import space.kscience.kmath.tensors.core.tensorAlgebra import kotlin.random.Random @@ -90,4 +92,9 @@ internal class DotBenchmark { fun doubleDot(blackhole: Blackhole) = with(DoubleField.linearSpace) { blackhole.consume(matrix1 dot matrix2) } + + @Benchmark + fun doubleTensorDot(blackhole: Blackhole) = DoubleTensorAlgebra.invoke { + blackhole.consume(matrix1 dot matrix2) + } } diff --git a/examples/src/main/kotlin/space/kscience/kmath/functions/interpolateSquare.kt b/examples/src/main/kotlin/space/kscience/kmath/functions/interpolateSquare.kt index 091242829..feefedece 100644 --- a/examples/src/main/kotlin/space/kscience/kmath/functions/interpolateSquare.kt +++ b/examples/src/main/kotlin/space/kscience/kmath/functions/interpolateSquare.kt @@ -5,8 +5,8 @@ package space.kscience.kmath.functions -import space.kscience.kmath.interpolation.SplineInterpolator import space.kscience.kmath.interpolation.interpolatePolynomials +import space.kscience.kmath.interpolation.splineInterpolator import space.kscience.kmath.operations.DoubleField import space.kscience.kmath.real.map import space.kscience.kmath.real.step @@ -28,7 +28,7 @@ fun main() { val xs = 0.0..100.0 step 0.5 val ys = xs.map(function) - val polynomial: PiecewisePolynomial = SplineInterpolator.double.interpolatePolynomials(xs, ys) + val polynomial: PiecewisePolynomial = DoubleField.splineInterpolator.interpolatePolynomials(xs, ys) val polyFunction = polynomial.asFunction(DoubleField, 0.0) diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/integration/SplineIntegrator.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/integration/SplineIntegrator.kt index 15d548641..eb88d9ae0 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/integration/SplineIntegrator.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/integration/SplineIntegrator.kt @@ -28,6 +28,8 @@ public fun > PiecewisePolynomial.integrate(algebra: Field> PiecewisePolynomial.integrate( @@ -98,6 +100,7 @@ public object DoubleSplineIntegrator : UnivariateIntegrator { } } +@Suppress("unused") @UnstableKMathAPI public inline val DoubleField.splineIntegrator: UnivariateIntegrator get() = DoubleSplineIntegrator \ No newline at end of file diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/interpolation/Interpolator.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/interpolation/Interpolator.kt index b13adefa5..2266092a3 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/interpolation/Interpolator.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/interpolation/Interpolator.kt @@ -9,6 +9,7 @@ package space.kscience.kmath.interpolation import space.kscience.kmath.data.XYColumnarData import space.kscience.kmath.functions.PiecewisePolynomial +import space.kscience.kmath.functions.asFunction import space.kscience.kmath.functions.value import space.kscience.kmath.misc.UnstableKMathAPI import space.kscience.kmath.operations.Ring @@ -59,3 +60,33 @@ public fun > PolynomialInterpolator.interpolatePolynomials( val pointSet = XYColumnarData.of(data.map { it.first }.asBuffer(), data.map { it.second }.asBuffer()) return interpolatePolynomials(pointSet) } + +public fun > PolynomialInterpolator.interpolate( + x: Buffer, + y: Buffer, +): (T) -> T? = interpolatePolynomials(x, y).asFunction(algebra) + +public fun > PolynomialInterpolator.interpolate( + data: Map, +): (T) -> T? = interpolatePolynomials(data).asFunction(algebra) + +public fun > PolynomialInterpolator.interpolate( + data: List>, +): (T) -> T? = interpolatePolynomials(data).asFunction(algebra) + + +public fun > PolynomialInterpolator.interpolate( + x: Buffer, + y: Buffer, + defaultValue: T, +): (T) -> T = interpolatePolynomials(x, y).asFunction(algebra, defaultValue) + +public fun > PolynomialInterpolator.interpolate( + data: Map, + defaultValue: T, +): (T) -> T = interpolatePolynomials(data).asFunction(algebra, defaultValue) + +public fun > PolynomialInterpolator.interpolate( + data: List>, + defaultValue: T, +): (T) -> T = interpolatePolynomials(data).asFunction(algebra, defaultValue) \ No newline at end of file diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/interpolation/LinearInterpolator.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/interpolation/LinearInterpolator.kt index edd0e6b0a..34d7bcf41 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/interpolation/LinearInterpolator.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/interpolation/LinearInterpolator.kt @@ -22,6 +22,7 @@ internal fun > insureSorted(points: XYColumnarData<*, T, *>) { * Reference JVM implementation: https://github.com/apache/commons-math/blob/master/src/main/java/org/apache/commons/math4/analysis/interpolation/LinearInterpolator.java */ public class LinearInterpolator>(override val algebra: Field) : PolynomialInterpolator { + @OptIn(UnstableKMathAPI::class) override fun interpolatePolynomials(points: XYColumnarData): PiecewisePolynomial = algebra { require(points.size > 0) { "Point array should not be empty" } @@ -37,3 +38,6 @@ public class LinearInterpolator>(override val algebra: Field> Field.linearInterpolator: LinearInterpolator + get() = LinearInterpolator(this) diff --git a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/interpolation/SplineInterpolator.kt b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/interpolation/SplineInterpolator.kt index 39c33ee69..afcb33bd4 100644 --- a/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/interpolation/SplineInterpolator.kt +++ b/kmath-functions/src/commonMain/kotlin/space/kscience/kmath/interpolation/SplineInterpolator.kt @@ -63,8 +63,8 @@ public class SplineInterpolator>( //Shift coefficients to represent absolute polynomial instead of one with an offset val polynomial = Polynomial( a - b * x0 + c * x02 - d * x03, - b - 2*c*x0 + 3*d*x02, - c - 3*d*x0, + b - 2 * c * x0 + 3 * d * x02, + c - 3 * d * x0, d ) cOld = c @@ -72,8 +72,12 @@ public class SplineInterpolator>( } } } - - public companion object { - public val double: SplineInterpolator = SplineInterpolator(DoubleField, ::DoubleBuffer) - } } + + +public fun > Field.splineInterpolator( + bufferFactory: MutableBufferFactory, +): SplineInterpolator = SplineInterpolator(this, bufferFactory) + +public val DoubleField.splineInterpolator: SplineInterpolator + get() = SplineInterpolator(this, ::DoubleBuffer) \ No newline at end of file diff --git a/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/interpolation/LinearInterpolatorTest.kt b/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/interpolation/LinearInterpolatorTest.kt index bec678bae..1143036d4 100644 --- a/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/interpolation/LinearInterpolatorTest.kt +++ b/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/interpolation/LinearInterpolatorTest.kt @@ -5,8 +5,6 @@ package space.kscience.kmath.interpolation -import space.kscience.kmath.functions.PiecewisePolynomial -import space.kscience.kmath.functions.asFunction import space.kscience.kmath.operations.DoubleField import kotlin.test.Test import kotlin.test.assertEquals @@ -21,8 +19,8 @@ internal class LinearInterpolatorTest { 3.0 to 4.0 ) - val polynomial: PiecewisePolynomial = LinearInterpolator(DoubleField).interpolatePolynomials(data) - val function = polynomial.asFunction(DoubleField) + //val polynomial: PiecewisePolynomial = DoubleField.linearInterpolator.interpolatePolynomials(data) + val function = DoubleField.linearInterpolator.interpolate(data) assertEquals(null, function(-1.0)) assertEquals(0.5, function(0.5)) assertEquals(2.0, function(1.5)) diff --git a/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/interpolation/SplineInterpolatorTest.kt b/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/interpolation/SplineInterpolatorTest.kt index 3adaab2d1..4c7d816d4 100644 --- a/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/interpolation/SplineInterpolatorTest.kt +++ b/kmath-functions/src/commonTest/kotlin/space/kscience/kmath/interpolation/SplineInterpolatorTest.kt @@ -5,8 +5,6 @@ package space.kscience.kmath.interpolation -import space.kscience.kmath.functions.PiecewisePolynomial -import space.kscience.kmath.functions.asFunction import space.kscience.kmath.operations.DoubleField import kotlin.math.PI import kotlin.math.sin @@ -21,9 +19,10 @@ internal class SplineInterpolatorTest { x to sin(x) } - val polynomial: PiecewisePolynomial = SplineInterpolator.double.interpolatePolynomials(data) + //val polynomial: PiecewisePolynomial = DoubleField.splineInterpolator.interpolatePolynomials(data) + + val function = DoubleField.splineInterpolator.interpolate(data, Double.NaN) - val function = polynomial.asFunction(DoubleField, Double.NaN) assertEquals(Double.NaN, function(-1.0)) assertEquals(sin(0.5), function(0.5), 0.1) assertEquals(sin(1.5), function(1.5), 0.1) diff --git a/kmath-multik/src/test/kotlin/space/kscience/kmath/multik/MultikNDTest.kt b/kmath-multik/src/test/kotlin/space/kscience/kmath/multik/MultikNDTest.kt index 404541776..72c43d8e6 100644 --- a/kmath-multik/src/test/kotlin/space/kscience/kmath/multik/MultikNDTest.kt +++ b/kmath-multik/src/test/kotlin/space/kscience/kmath/multik/MultikNDTest.kt @@ -6,13 +6,38 @@ package space.kscience.kmath.multik import org.junit.jupiter.api.Test +import space.kscience.kmath.nd.StructureND import space.kscience.kmath.nd.one import space.kscience.kmath.operations.DoubleField import space.kscience.kmath.operations.invoke +import space.kscience.kmath.tensors.core.DoubleTensorAlgebra +import space.kscience.kmath.tensors.core.tensorAlgebra +import kotlin.test.assertTrue internal class MultikNDTest { @Test fun basicAlgebra(): Unit = DoubleField.multikAlgebra{ one(2,2) + 1.0 } + + @Test + fun dotResult(){ + val dim = 100 + + val tensor1 = DoubleTensorAlgebra.randomNormal(shape = intArrayOf(dim, dim), 12224) + val tensor2 = DoubleTensorAlgebra.randomNormal(shape = intArrayOf(dim, dim), 12225) + + val multikResult = with(DoubleField.multikAlgebra){ + tensor1 dot tensor2 + } + + val defaultResult = with(DoubleField.tensorAlgebra){ + tensor1 dot tensor2 + } + + assertTrue { + StructureND.contentEquals(multikResult, defaultResult) + } + + } } \ No newline at end of file diff --git a/kmath-tensorflow/src/test/kotlin/space/kscience/kmath/tensorflow/DoubleTensorFlowOps.kt b/kmath-tensorflow/src/test/kotlin/space/kscience/kmath/tensorflow/DoubleTensorFlowOps.kt index 3d118d980..308469eed 100644 --- a/kmath-tensorflow/src/test/kotlin/space/kscience/kmath/tensorflow/DoubleTensorFlowOps.kt +++ b/kmath-tensorflow/src/test/kotlin/space/kscience/kmath/tensorflow/DoubleTensorFlowOps.kt @@ -6,7 +6,6 @@ import space.kscience.kmath.nd.structureND import space.kscience.kmath.operations.DoubleField import space.kscience.kmath.tensors.core.DoubleTensorAlgebra import space.kscience.kmath.tensors.core.DoubleTensorAlgebra.Companion.sum -import kotlin.random.Random import kotlin.test.assertEquals class DoubleTensorFlowOps { @@ -23,7 +22,6 @@ class DoubleTensorFlowOps { @Test fun dot(){ - val random = Random(12224) val dim = 1000 val tensor1 = DoubleTensorAlgebra.randomNormal(shape = intArrayOf(dim, dim), 12224)