forked from kscience/kmath
Random demo
This commit is contained in:
parent
cd1c155e7d
commit
1b647b6014
@ -1,4 +1,4 @@
|
||||
val kmathVersion by extra("0.1.2")
|
||||
val kmathVersion by extra("0.1.3-dev-1")
|
||||
|
||||
allprojects {
|
||||
repositories {
|
||||
|
@ -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:
|
||||
|
||||
|
@ -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)
|
||||
}
|
||||
}
|
@ -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")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -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 {
|
||||
|
@ -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()
|
@ -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 ->
|
||||
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
@ -8,4 +8,6 @@ interface RandomGenerator {
|
||||
fun nextInt(): Int
|
||||
fun nextLong(): Long
|
||||
fun nextBlock(size: Int): ByteArray
|
||||
|
||||
companion object
|
||||
}
|
Loading…
Reference in New Issue
Block a user