From 88ee3e5ab789cab5f5bd44ce91a6a494481d9bae Mon Sep 17 00:00:00 2001 From: Alexander Nozik Date: Sun, 9 Jun 2019 10:54:45 +0300 Subject: [PATCH] Random generator forks --- README.md | 1 + .../commons/expressions/DiffExpression.kt | 7 ++-- .../commons/prob/CMRandomGeneratorWrapper.kt | 4 ++ .../kmath/commons/expressions/AutoDiffTest.kt | 4 +- .../scientifik/kmath/linear/BufferMatrix.kt | 1 + .../scientifik/kmath/prob/Distribution.kt | 41 +++++++++++++++++-- .../scientifik/kmath/prob/RandomChain.kt | 3 +- .../scientifik/kmath/prob/RandomGenerator.kt | 5 +++ 8 files changed, 54 insertions(+), 12 deletions(-) diff --git a/README.md b/README.md index c828103e9..4f9ca77b4 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,7 @@ Bintray: [ ![Download](https://api.bintray.com/packages/mipt-npm/scientifik/kmath-core/images/download.svg) ](https://bintray.com/mipt-npm/scientifik/kmath-core/_latestVersion) # KMath +Could be pronounced as `key-math`. The Kotlin MATHematics library is intended as a Kotlin-based analog to Python's `numpy` library. In contrast to `numpy` and `scipy` it is modular and has a lightweight core. ## Features diff --git a/kmath-commons/src/main/kotlin/scientifik/kmath/commons/expressions/DiffExpression.kt b/kmath-commons/src/main/kotlin/scientifik/kmath/commons/expressions/DiffExpression.kt index e687cb2af..d5c038dc4 100644 --- a/kmath-commons/src/main/kotlin/scientifik/kmath/commons/expressions/DiffExpression.kt +++ b/kmath-commons/src/main/kotlin/scientifik/kmath/commons/expressions/DiffExpression.kt @@ -83,13 +83,12 @@ class DerivativeStructureField( /** * A constructs that creates a derivative structure with required order on-demand */ -class DiffExpression(val function: DerivativeStructureField.() -> DerivativeStructure) : - Expression { +class DiffExpression(val function: DerivativeStructureField.() -> DerivativeStructure) : Expression { + override fun invoke(arguments: Map): Double = DerivativeStructureField( 0, arguments - ) - .run(function).value + ).run(function).value /** * Get the derivative expression with given orders diff --git a/kmath-commons/src/main/kotlin/scientifik/kmath/commons/prob/CMRandomGeneratorWrapper.kt b/kmath-commons/src/main/kotlin/scientifik/kmath/commons/prob/CMRandomGeneratorWrapper.kt index a32626e0d..74e035ecb 100644 --- a/kmath-commons/src/main/kotlin/scientifik/kmath/commons/prob/CMRandomGeneratorWrapper.kt +++ b/kmath-commons/src/main/kotlin/scientifik/kmath/commons/prob/CMRandomGeneratorWrapper.kt @@ -12,6 +12,10 @@ inline class CMRandomGeneratorWrapper(val generator: CMRandom) : RandomGenerator override fun nextLong(): Long = generator.nextLong() override fun nextBlock(size: Int): ByteArray = ByteArray(size).apply { generator.nextBytes(this) } + + override fun fork(): RandomGenerator { + TODO("not implemented") //To change body of created functions use File | Settings | File Templates. + } } fun CMRandom.asKmathGenerator(): RandomGenerator = CMRandomGeneratorWrapper(this) diff --git a/kmath-commons/src/test/kotlin/scientifik/kmath/commons/expressions/AutoDiffTest.kt b/kmath-commons/src/test/kotlin/scientifik/kmath/commons/expressions/AutoDiffTest.kt index 37e4e9ff9..100f49948 100644 --- a/kmath-commons/src/test/kotlin/scientifik/kmath/commons/expressions/AutoDiffTest.kt +++ b/kmath-commons/src/test/kotlin/scientifik/kmath/commons/expressions/AutoDiffTest.kt @@ -1,9 +1,7 @@ package scientifik.kmath.commons.expressions import org.junit.Test -import scientifik.kmath.commons.expressions.DerivativeStructureField -import scientifik.kmath.commons.expressions.DiffExpression -import scientifik.kmath.commons.expressions.derivative +import scientifik.kmath.expressions.invoke import kotlin.test.assertEquals inline fun diff(order: Int, vararg parameters: Pair, block: DerivativeStructureField.() -> R) = diff --git a/kmath-core/src/commonMain/kotlin/scientifik/kmath/linear/BufferMatrix.kt b/kmath-core/src/commonMain/kotlin/scientifik/kmath/linear/BufferMatrix.kt index 34d9a6883..624cd44d4 100644 --- a/kmath-core/src/commonMain/kotlin/scientifik/kmath/linear/BufferMatrix.kt +++ b/kmath-core/src/commonMain/kotlin/scientifik/kmath/linear/BufferMatrix.kt @@ -24,6 +24,7 @@ class BufferMatrixContext>( } } +@Suppress("OVERRIDE_BY_INLINE") object RealMatrixContext : GenericMatrixContext { override val elementContext = RealField diff --git a/kmath-prob/src/commonMain/kotlin/scientifik/kmath/prob/Distribution.kt b/kmath-prob/src/commonMain/kotlin/scientifik/kmath/prob/Distribution.kt index a8614963b..d3cac9163 100644 --- a/kmath-prob/src/commonMain/kotlin/scientifik/kmath/prob/Distribution.kt +++ b/kmath-prob/src/commonMain/kotlin/scientifik/kmath/prob/Distribution.kt @@ -1,11 +1,17 @@ package scientifik.kmath.prob import scientifik.kmath.chains.Chain +import scientifik.kmath.chains.map +import kotlin.jvm.JvmName + +interface Sampler { + fun sample(generator: RandomGenerator): RandomChain +} /** * A distribution of typed objects */ -interface Distribution { +interface Distribution : Sampler { /** * A probability value for given argument [arg]. * For continuous distributions returns PDF @@ -16,8 +22,7 @@ interface Distribution { * Create a chain of samples from this distribution. * The chain is not guaranteed to be stateless. */ - fun sample(generator: RandomGenerator): RandomChain - //TODO add sample bunch generator + override fun sample(generator: RandomGenerator): RandomChain /** * An empty companion. Distribution factories should be written as its extensions @@ -31,3 +36,33 @@ interface UnivariateDistribution> : Distribution { */ fun cumulative(arg: T): Double } + +/** + * Compute probability integral in an interval + */ +fun > UnivariateDistribution.integral(from: T, to: T): Double { + require(to > from) + return cumulative(to) - cumulative(from) +} + + +/** + * Sample a bunch of values + */ +fun Sampler.sampleBunch(generator: RandomGenerator, size: Int): Chain> { + require(size > 1) + return sample(generator).map{chain -> + List(size){chain.next()} + } +} + +/** + * Generate a bunch of samples from real distributions + */ +@JvmName("realSampleBunch") +fun Sampler.sampleBunch(generator: RandomGenerator, size: Int): Chain { + require(size > 1) + return sample(generator).map{chain -> + DoubleArray(size){chain.next()} + } +} \ No newline at end of file diff --git a/kmath-prob/src/commonMain/kotlin/scientifik/kmath/prob/RandomChain.kt b/kmath-prob/src/commonMain/kotlin/scientifik/kmath/prob/RandomChain.kt index 792b60603..61e0dae4e 100644 --- a/kmath-prob/src/commonMain/kotlin/scientifik/kmath/prob/RandomChain.kt +++ b/kmath-prob/src/commonMain/kotlin/scientifik/kmath/prob/RandomChain.kt @@ -9,9 +9,8 @@ import scientifik.kmath.chains.Chain */ class RandomChain(val generator: RandomGenerator, private val gen: suspend RandomGenerator.() -> R) : Chain { private val atomicValue = atomic(null) - override fun peek(): R? = atomicValue.value override suspend fun next(): R = generator.gen().also { atomicValue.lazySet(it) } - override fun fork(): Chain = RandomChain(generator, gen) + override fun fork(): Chain = RandomChain(generator.fork(), gen) } \ No newline at end of file diff --git a/kmath-prob/src/commonMain/kotlin/scientifik/kmath/prob/RandomGenerator.kt b/kmath-prob/src/commonMain/kotlin/scientifik/kmath/prob/RandomGenerator.kt index 039ee3d2b..381bd9736 100644 --- a/kmath-prob/src/commonMain/kotlin/scientifik/kmath/prob/RandomGenerator.kt +++ b/kmath-prob/src/commonMain/kotlin/scientifik/kmath/prob/RandomGenerator.kt @@ -9,5 +9,10 @@ interface RandomGenerator { fun nextLong(): Long fun nextBlock(size: Int): ByteArray + /** + * Fork the current state of generator + */ + fun fork(): RandomGenerator + companion object } \ No newline at end of file