Random demo

This commit is contained in:
Alexander Nozik 2019-06-08 16:44:49 +03:00
parent cd1c155e7d
commit 1b647b6014
9 changed files with 52 additions and 19 deletions

View File

@ -1,4 +1,4 @@
val kmathVersion by extra("0.1.2")
val kmathVersion by extra("0.1.3-dev-1")
allprojects {
repositories {

View File

@ -14,7 +14,7 @@ Let us consider following contexts:
// specialized nd-field for Double. It works as generic Double field as well
val specializedField = NDField.real(dim, dim)
//A generic boxing field. It should be used for objects, not primitives.
val genericField = NDField.buffered(intArrayOf(dim, dim), RealField)
val genericField = NDField.buffered(RealField, dim, dim)
```
Now let us perform several tests and see which implementation is best suited for each case:

View File

@ -53,6 +53,6 @@ class NDFieldBenchmark {
val bufferedField = NDField.auto(RealField, dim, dim)
val specializedField = NDField.real(dim, dim)
val genericField = NDField.buffered(intArrayOf(dim, dim), RealField)
val genericField = NDField.buffered(RealField, dim, dim)
}
}

View File

@ -1,11 +1,31 @@
package scientifik.kmath.commons.prob
import kotlinx.coroutines.flow.take
import scientifik.kmath.chains.flow
import kotlinx.coroutines.runBlocking
import scientifik.kmath.chains.Chain
import scientifik.kmath.chains.StatefulChain
import scientifik.kmath.prob.Distribution
import scientifik.kmath.prob.RandomGenerator
data class AveragingChainState(var num: Int = 0, var value: Double = 0.0)
fun Chain<Double>.mean(): Chain<Double> = StatefulChain(AveragingChainState(), 0.0) {
val next = this@mean.next()
num++
value += next
return@StatefulChain value / num
}
fun main() {
val normal = Distribution.normal()
normal.sample(RandomGenerator.default)
val chain = normal.sample(RandomGenerator.default).mean()
runBlocking {
repeat(10001) { counter ->
val mean = chain.next()
if(counter % 1000 ==0){
println("[$counter] Average value is $mean")
}
}
}
}

View File

@ -13,7 +13,7 @@ fun main(args: Array<String>) {
// specialized nd-field for Double. It works as generic Double field as well
val specializedField = NDField.real(dim, dim)
//A generic boxing field. It should be used for objects, not primitives.
val genericField = NDField.buffered(intArrayOf(dim, dim), RealField)
val genericField = NDField.buffered(RealField, dim, dim)
val autoTime = measureTimeMillis {

View File

@ -1,8 +1,10 @@
package scientifik.kmath.commons.prob
import org.apache.commons.math3.random.RandomGenerator
import org.apache.commons.math3.random.JDKRandomGenerator
import scientifik.kmath.prob.RandomGenerator
import org.apache.commons.math3.random.RandomGenerator as CMRandom
inline class CMRandomGeneratorWrapper(val generator: RandomGenerator) : scientifik.kmath.prob.RandomGenerator {
inline class CMRandomGeneratorWrapper(val generator: CMRandom) : RandomGenerator {
override fun nextDouble(): Double = generator.nextDouble()
override fun nextInt(): Int = generator.nextInt()
@ -12,7 +14,15 @@ inline class CMRandomGeneratorWrapper(val generator: RandomGenerator) : scientif
override fun nextBlock(size: Int): ByteArray = ByteArray(size).apply { generator.nextBytes(this) }
}
fun RandomGenerator.asKmathGenerator() = CMRandomGeneratorWrapper(this)
fun CMRandom.asKmathGenerator(): RandomGenerator = CMRandomGeneratorWrapper(this)
fun scientifik.kmath.prob.RandomGenerator.asCMGenerator() =
(this as? CMRandomGeneratorWrapper)?.generator ?: TODO("Implement reverse CM wrapper")
fun RandomGenerator.asCMGenerator(): CMRandom =
(this as? CMRandomGeneratorWrapper)?.generator ?: TODO("Implement reverse CM wrapper")
val RandomGenerator.Companion.default: RandomGenerator by lazy { JDKRandomGenerator().asKmathGenerator() }
fun RandomGenerator.Companion.jdk(seed: Int? = null): RandomGenerator = if (seed == null) {
JDKRandomGenerator()
} else {
JDKRandomGenerator(seed)
}.asKmathGenerator()

View File

@ -1,8 +1,6 @@
package scientifik.kmath.commons.prob
import org.apache.commons.math3.distribution.*
import scientifik.kmath.chains.Chain
import scientifik.kmath.chains.SimpleChain
import scientifik.kmath.prob.Distribution
import scientifik.kmath.prob.RandomChain
import scientifik.kmath.prob.RandomGenerator
@ -38,7 +36,7 @@ class CMIntDistributionWrapper(val builder: (CMRandom?) -> IntegerDistribution)
}
fun Distribution.Companion.normal(mean: Double, sigma: Double): UnivariateDistribution<Double> =
fun Distribution.Companion.normal(mean: Double = 0.0, sigma: Double = 1.0): UnivariateDistribution<Double> =
CMRealDistributionWrapper { generator -> NormalDistribution(generator, mean, sigma) }
fun Distribution.Companion.poisson(mean: Double): UnivariateDistribution<Int> = CMIntDistributionWrapper { generator ->

View File

@ -1,9 +1,9 @@
package scientifik.kmath.structures
import scientifik.kmath.operations.Complex
import scientifik.kmath.operations.Field
import scientifik.kmath.operations.Ring
import scientifik.kmath.operations.Space
import kotlin.jvm.JvmName
/**
@ -77,6 +77,7 @@ interface NDSpace<T, S : Space<T>, N : NDStructure<T>> : Space<N>, NDAlgebra<T,
//TODO move to extensions after KEEP-176
operator fun N.plus(arg: T) = map(this) { value -> add(arg, value) }
operator fun N.minus(arg: T) = map(this) { value -> add(arg, -value) }
operator fun T.plus(arg: N) = map(arg) { value -> add(this@plus, value) }
@ -95,6 +96,7 @@ interface NDRing<T, R : Ring<T>, N : NDStructure<T>> : Ring<N>, NDSpace<T, R, N>
//TODO move to extensions after KEEP-176
operator fun N.times(arg: T) = map(this) { value -> multiply(arg, value) }
operator fun T.times(arg: N) = map(arg) { value -> multiply(this@times, value) }
}
@ -115,6 +117,7 @@ interface NDField<T, F : Field<T>, N : NDStructure<T>> : Field<N>, NDRing<T, F,
//TODO move to extensions after KEEP-176
operator fun N.div(arg: T) = map(this) { value -> divide(arg, value) }
operator fun T.div(arg: N) = map(arg) { divide(it, this@div) }
companion object {
@ -130,11 +133,10 @@ interface NDField<T, F : Field<T>, N : NDStructure<T>> : Field<N>, NDRing<T, F,
* Create a nd-field with boxing generic buffer
*/
fun <T : Any, F : Field<T>> buffered(
shape: IntArray,
field: F,
vararg shape: Int,
bufferFactory: BufferFactory<T> = Buffer.Companion::boxing
) =
BoxingNDField(shape, field, bufferFactory)
) = BoxingNDField(shape, field, bufferFactory)
/**
* Create a most suitable implementation for nd-field using reified class.
@ -143,6 +145,7 @@ interface NDField<T, F : Field<T>, N : NDStructure<T>> : Field<N>, NDRing<T, F,
inline fun <reified T : Any, F : Field<T>> auto(field: F, vararg shape: Int): BufferedNDField<T, F> =
when {
T::class == Double::class -> real(*shape) as BufferedNDField<T, F>
T::class == Complex::class -> complex(*shape) as BufferedNDField<T, F>
else -> BoxingNDField(shape, field, Buffer.Companion::auto)
}
}

View File

@ -8,4 +8,6 @@ interface RandomGenerator {
fun nextInt(): Int
fun nextLong(): Long
fun nextBlock(size: Int): ByteArray
companion object
}