Dev #72
@ -1,4 +1,4 @@
|
|||||||
val kmathVersion by extra("0.1.2")
|
val kmathVersion by extra("0.1.3-dev-1")
|
||||||
|
|
||||||
allprojects {
|
allprojects {
|
||||||
repositories {
|
repositories {
|
||||||
|
@ -14,7 +14,7 @@ Let us consider following contexts:
|
|||||||
// specialized nd-field for Double. It works as generic Double field as well
|
// specialized nd-field for Double. It works as generic Double field as well
|
||||||
val specializedField = NDField.real(dim, dim)
|
val specializedField = NDField.real(dim, dim)
|
||||||
//A generic boxing field. It should be used for objects, not primitives.
|
//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:
|
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 bufferedField = NDField.auto(RealField, dim, dim)
|
||||||
val specializedField = NDField.real(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
|
package scientifik.kmath.commons.prob
|
||||||
|
|
||||||
import kotlinx.coroutines.flow.take
|
import kotlinx.coroutines.runBlocking
|
||||||
import scientifik.kmath.chains.flow
|
import scientifik.kmath.chains.Chain
|
||||||
|
import scientifik.kmath.chains.StatefulChain
|
||||||
import scientifik.kmath.prob.Distribution
|
import scientifik.kmath.prob.Distribution
|
||||||
import scientifik.kmath.prob.RandomGenerator
|
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() {
|
fun main() {
|
||||||
val normal = Distribution.normal()
|
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
|
// specialized nd-field for Double. It works as generic Double field as well
|
||||||
val specializedField = NDField.real(dim, dim)
|
val specializedField = NDField.real(dim, dim)
|
||||||
//A generic boxing field. It should be used for objects, not primitives.
|
//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 {
|
val autoTime = measureTimeMillis {
|
||||||
|
@ -1,8 +1,10 @@
|
|||||||
package scientifik.kmath.commons.prob
|
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 nextDouble(): Double = generator.nextDouble()
|
||||||
|
|
||||||
override fun nextInt(): Int = generator.nextInt()
|
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) }
|
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() =
|
fun RandomGenerator.asCMGenerator(): CMRandom =
|
||||||
(this as? CMRandomGeneratorWrapper)?.generator ?: TODO("Implement reverse CM wrapper")
|
(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
|
package scientifik.kmath.commons.prob
|
||||||
|
|
||||||
import org.apache.commons.math3.distribution.*
|
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.Distribution
|
||||||
import scientifik.kmath.prob.RandomChain
|
import scientifik.kmath.prob.RandomChain
|
||||||
import scientifik.kmath.prob.RandomGenerator
|
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) }
|
CMRealDistributionWrapper { generator -> NormalDistribution(generator, mean, sigma) }
|
||||||
|
|
||||||
fun Distribution.Companion.poisson(mean: Double): UnivariateDistribution<Int> = CMIntDistributionWrapper { generator ->
|
fun Distribution.Companion.poisson(mean: Double): UnivariateDistribution<Int> = CMIntDistributionWrapper { generator ->
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
package scientifik.kmath.structures
|
package scientifik.kmath.structures
|
||||||
|
|
||||||
|
import scientifik.kmath.operations.Complex
|
||||||
import scientifik.kmath.operations.Field
|
import scientifik.kmath.operations.Field
|
||||||
import scientifik.kmath.operations.Ring
|
import scientifik.kmath.operations.Ring
|
||||||
import scientifik.kmath.operations.Space
|
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
|
//TODO move to extensions after KEEP-176
|
||||||
operator fun N.plus(arg: T) = map(this) { value -> add(arg, value) }
|
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 N.minus(arg: T) = map(this) { value -> add(arg, -value) }
|
||||||
|
|
||||||
operator fun T.plus(arg: N) = map(arg) { value -> add(this@plus, 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
|
//TODO move to extensions after KEEP-176
|
||||||
operator fun N.times(arg: T) = map(this) { value -> multiply(arg, value) }
|
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) }
|
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
|
//TODO move to extensions after KEEP-176
|
||||||
operator fun N.div(arg: T) = map(this) { value -> divide(arg, value) }
|
operator fun N.div(arg: T) = map(this) { value -> divide(arg, value) }
|
||||||
|
|
||||||
operator fun T.div(arg: N) = map(arg) { divide(it, this@div) }
|
operator fun T.div(arg: N) = map(arg) { divide(it, this@div) }
|
||||||
|
|
||||||
companion object {
|
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
|
* Create a nd-field with boxing generic buffer
|
||||||
*/
|
*/
|
||||||
fun <T : Any, F : Field<T>> buffered(
|
fun <T : Any, F : Field<T>> buffered(
|
||||||
shape: IntArray,
|
|
||||||
field: F,
|
field: F,
|
||||||
|
vararg shape: Int,
|
||||||
bufferFactory: BufferFactory<T> = Buffer.Companion::boxing
|
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.
|
* 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> =
|
inline fun <reified T : Any, F : Field<T>> auto(field: F, vararg shape: Int): BufferedNDField<T, F> =
|
||||||
when {
|
when {
|
||||||
T::class == Double::class -> real(*shape) as BufferedNDField<T, F>
|
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)
|
else -> BoxingNDField(shape, field, Buffer.Companion::auto)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -8,4 +8,6 @@ interface RandomGenerator {
|
|||||||
fun nextInt(): Int
|
fun nextInt(): Int
|
||||||
fun nextLong(): Long
|
fun nextLong(): Long
|
||||||
fun nextBlock(size: Int): ByteArray
|
fun nextBlock(size: Int): ByteArray
|
||||||
|
|
||||||
|
companion object
|
||||||
}
|
}
|
Loading…
Reference in New Issue
Block a user