Refactoring

This commit is contained in:
Alexander Nozik 2021-11-09 13:42:22 +03:00
parent f6b576071d
commit d62bc66d4a
32 changed files with 86 additions and 55 deletions

View File

@ -6,31 +6,38 @@
package space.kscience.kmath.benchmarks
import kotlinx.benchmark.Benchmark
import kotlinx.benchmark.Blackhole
import kotlinx.benchmark.Scope
import kotlinx.benchmark.State
import space.kscience.kmath.complex.Complex
import space.kscience.kmath.complex.ComplexField
import space.kscience.kmath.complex.complex
import space.kscience.kmath.operations.invoke
import space.kscience.kmath.structures.Buffer
import space.kscience.kmath.structures.DoubleBuffer
import space.kscience.kmath.structures.MutableBuffer
@State(Scope.Benchmark)
internal class BufferBenchmark {
@Benchmark
fun genericDoubleBufferReadWrite() {
fun genericDoubleBufferReadWrite(blackhole: Blackhole) {
val buffer = DoubleBuffer(size) { it.toDouble() }
var res = 0.0
(0 until size).forEach {
buffer[it]
res += buffer[it]
}
blackhole.consume(res)
}
@Benchmark
fun complexBufferReadWrite() {
val buffer = MutableBuffer.complex(size / 2) { Complex(it.toDouble(), -it.toDouble()) }
fun complexBufferReadWrite(blackhole: Blackhole) = ComplexField {
val buffer = Buffer.complex(size / 2) { Complex(it.toDouble(), -it.toDouble()) }
var res = zero
(0 until size / 2).forEach {
buffer[it]
res += buffer[it]
}
blackhole.consume(res)
}
private companion object {

View File

@ -16,10 +16,10 @@ import space.kscience.kmath.optimization.FunctionOptimizationTarget
import space.kscience.kmath.optimization.optimizeWith
import space.kscience.kmath.optimization.resultPoint
import space.kscience.kmath.optimization.resultValue
import space.kscience.kmath.random.RandomGenerator
import space.kscience.kmath.real.DoubleVector
import space.kscience.kmath.real.map
import space.kscience.kmath.real.step
import space.kscience.kmath.stat.RandomGenerator
import space.kscience.kmath.structures.asIterable
import space.kscience.kmath.structures.toList
import space.kscience.plotly.*

View File

@ -17,9 +17,9 @@ import space.kscience.kmath.optimization.QowOptimizer
import space.kscience.kmath.optimization.chiSquaredOrNull
import space.kscience.kmath.optimization.fitWith
import space.kscience.kmath.optimization.resultPoint
import space.kscience.kmath.random.RandomGenerator
import space.kscience.kmath.real.map
import space.kscience.kmath.real.step
import space.kscience.kmath.stat.RandomGenerator
import space.kscience.kmath.structures.asIterable
import space.kscience.kmath.structures.toList
import space.kscience.plotly.*

View File

@ -10,6 +10,7 @@ import kotlinx.coroutines.async
import kotlinx.coroutines.runBlocking
import org.apache.commons.rng.sampling.distribution.BoxMullerNormalizedGaussianSampler
import org.apache.commons.rng.simple.RandomSource
import space.kscience.kmath.random.RandomGenerator
import space.kscience.kmath.samplers.GaussianSampler
import java.time.Duration
import java.time.Instant

View File

@ -9,6 +9,7 @@ import kotlinx.coroutines.runBlocking
import space.kscience.kmath.chains.Chain
import space.kscience.kmath.chains.collectWithState
import space.kscience.kmath.distributions.NormalDistribution
import space.kscience.kmath.random.RandomGenerator
private data class AveragingChainState(var num: Int = 0, var value: Double = 0.0)

View File

@ -8,9 +8,9 @@ package space.kscience.kmath.commons.random
import kotlinx.coroutines.runBlocking
import space.kscience.kmath.misc.PerformancePitfall
import space.kscience.kmath.misc.toIntExact
import space.kscience.kmath.random.RandomGenerator
import space.kscience.kmath.samplers.GaussianSampler
import space.kscience.kmath.samplers.next
import space.kscience.kmath.stat.RandomGenerator
public class CMRandomGeneratorWrapper(

View File

@ -14,7 +14,7 @@ import space.kscience.kmath.expressions.Symbol.Companion.y
import space.kscience.kmath.expressions.chiSquaredExpression
import space.kscience.kmath.expressions.symbol
import space.kscience.kmath.optimization.*
import space.kscience.kmath.stat.RandomGenerator
import space.kscience.kmath.random.RandomGenerator
import space.kscience.kmath.structures.DoubleBuffer
import space.kscience.kmath.structures.asBuffer
import space.kscience.kmath.structures.map

View File

@ -21,11 +21,6 @@ public interface BufferAlgebra<T, out A : Algebra<T>> : Algebra<Buffer<T>> {
public val elementAlgebra: A
public val bufferFactory: BufferFactory<T>
public fun buffer(size: Int, vararg elements: T): Buffer<T> {
require(elements.size == size) { "Expected $size elements but found ${elements.size}" }
return bufferFactory(size) { elements[it] }
}
//TODO move to multi-receiver inline extension
public fun Buffer<T>.map(block: A.(T) -> T): Buffer<T> = mapInline(this, block)
@ -49,12 +44,15 @@ public interface BufferAlgebra<T, out A : Algebra<T>> : Algebra<Buffer<T>> {
}
}
public fun <T, A : Algebra<T>> BufferAlgebra<T, A>.buffer(vararg elements: T): Buffer<T> =
bufferFactory(elements.size) { elements[it] }
/**
* Inline map
*/
private inline fun <T, A : Algebra<T>> BufferAlgebra<T, A>.mapInline(
buffer: Buffer<T>,
crossinline block: A.(T) -> T
crossinline block: A.(T) -> T,
): Buffer<T> = bufferFactory(buffer.size) { elementAlgebra.block(buffer[it]) }
/**
@ -62,7 +60,7 @@ private inline fun <T, A : Algebra<T>> BufferAlgebra<T, A>.mapInline(
*/
private inline fun <T, A : Algebra<T>> BufferAlgebra<T, A>.mapIndexedInline(
buffer: Buffer<T>,
crossinline block: A.(index: Int, arg: T) -> T
crossinline block: A.(index: Int, arg: T) -> T,
): Buffer<T> = bufferFactory(buffer.size) { elementAlgebra.block(it, buffer[it]) }
/**
@ -71,7 +69,7 @@ private inline fun <T, A : Algebra<T>> BufferAlgebra<T, A>.mapIndexedInline(
private inline fun <T, A : Algebra<T>> BufferAlgebra<T, A>.zipInline(
l: Buffer<T>,
r: Buffer<T>,
crossinline block: A.(l: T, r: T) -> T
crossinline block: A.(l: T, r: T) -> T,
): Buffer<T> {
require(l.size == r.size) { "Incompatible buffer sizes. left: ${l.size}, right: ${r.size}" }
return bufferFactory(l.size) { elementAlgebra.block(l[it], r[it]) }
@ -128,13 +126,13 @@ public fun <T, A : ExponentialOperations<T>> BufferAlgebra<T, A>.atanh(arg: Buff
mapInline(arg) { atanh(it) }
public fun <T, A : PowerOperations<T>> BufferAlgebra<T, A>.pow(arg: Buffer<T>, pow: Number): Buffer<T> =
mapInline(arg) {it.pow(pow) }
mapInline(arg) { it.pow(pow) }
public open class BufferRingOps<T, A: Ring<T>>(
public open class BufferRingOps<T, A : Ring<T>>(
override val elementAlgebra: A,
override val bufferFactory: BufferFactory<T>,
) : BufferAlgebra<T, A>, RingOps<Buffer<T>>{
) : BufferAlgebra<T, A>, RingOps<Buffer<T>> {
override fun add(left: Buffer<T>, right: Buffer<T>): Buffer<T> = zipInline(left, right) { l, r -> l + r }
override fun multiply(left: Buffer<T>, right: Buffer<T>): Buffer<T> = zipInline(left, right) { l, r -> l * r }
@ -155,7 +153,8 @@ public val ShortRing.bufferAlgebra: BufferRingOps<Short, ShortRing>
public open class BufferFieldOps<T, A : Field<T>>(
elementAlgebra: A,
bufferFactory: BufferFactory<T>,
) : BufferRingOps<T, A>(elementAlgebra, bufferFactory), BufferAlgebra<T, A>, FieldOps<Buffer<T>>, ScaleOperations<Buffer<T>> {
) : BufferRingOps<T, A>(elementAlgebra, bufferFactory), BufferAlgebra<T, A>, FieldOps<Buffer<T>>,
ScaleOperations<Buffer<T>> {
override fun add(left: Buffer<T>, right: Buffer<T>): Buffer<T> = zipInline(left, right) { l, r -> l + r }
override fun multiply(left: Buffer<T>, right: Buffer<T>): Buffer<T> = zipInline(left, right) { l, r -> l * r }
@ -172,7 +171,7 @@ public open class BufferFieldOps<T, A : Field<T>>(
public class BufferField<T, A : Field<T>>(
elementAlgebra: A,
bufferFactory: BufferFactory<T>,
override val size: Int
override val size: Int,
) : BufferFieldOps<T, A>(elementAlgebra, bufferFactory), Field<Buffer<T>>, WithSize {
override val zero: Buffer<T> = bufferFactory(size) { elementAlgebra.zero }
@ -195,4 +194,4 @@ public fun BufferField<Double, *>.buffer(vararg elements: Number): Buffer<Double
public fun <T, A : Field<T>> A.bufferAlgebra(bufferFactory: BufferFactory<T>): BufferFieldOps<T, A> =
BufferFieldOps(this, bufferFactory)
public val DoubleField.bufferAlgebra: DoubleBufferOps get() = DoubleBufferOps
public val DoubleField.bufferAlgebra: DoubleBufferOps get() = DoubleBufferOps

View File

@ -135,6 +135,7 @@ public abstract class DoubleBufferOps : BufferAlgebra<Double, DoubleField>, Exte
override fun scale(a: Buffer<Double>, value: Double): DoubleBuffer = a.mapInline { it * value }
public companion object : DoubleBufferOps() {
public inline fun Buffer<Double>.mapInline(block: (Double) -> Double): DoubleBuffer =
if (this is DoubleBuffer) {
DoubleArray(size) { block(array[it]) }.asBuffer()
@ -144,6 +145,14 @@ public abstract class DoubleBufferOps : BufferAlgebra<Double, DoubleField>, Exte
}
}
public inline fun BufferAlgebra<Double, DoubleField>.buffer(size: Int, init: (Int) -> Double): DoubleBuffer {
val res = DoubleArray(size)
for (i in 0 until size) {
res[i] = init(i)
}
return res.asBuffer()
}
public object DoubleL2Norm : Norm<Point<Double>, Double> {
override fun norm(arg: Point<Double>): Double = sqrt(arg.fold(0.0) { acc: Double, d: Double -> acc + d.pow(2) })
}

View File

@ -6,8 +6,8 @@
package space.kscience.kmath.distributions
import space.kscience.kmath.chains.Chain
import space.kscience.kmath.random.RandomGenerator
import space.kscience.kmath.samplers.Sampler
import space.kscience.kmath.stat.RandomGenerator
/**
* A distribution of typed objects.

View File

@ -7,7 +7,7 @@ package space.kscience.kmath.distributions
import space.kscience.kmath.chains.Chain
import space.kscience.kmath.chains.SimpleChain
import space.kscience.kmath.stat.RandomGenerator
import space.kscience.kmath.random.RandomGenerator
/**
* A multivariate distribution that takes a map of parameters.

View File

@ -6,11 +6,11 @@
package space.kscience.kmath.distributions
import space.kscience.kmath.chains.Chain
import space.kscience.kmath.random.RandomGenerator
import space.kscience.kmath.samplers.GaussianSampler
import space.kscience.kmath.samplers.InternalErf
import space.kscience.kmath.samplers.NormalizedGaussianSampler
import space.kscience.kmath.samplers.ZigguratNormalizedGaussianSampler
import space.kscience.kmath.stat.RandomGenerator
import kotlin.math.*
/**

View File

@ -7,7 +7,7 @@ package space.kscience.kmath.distributions
import space.kscience.kmath.chains.Chain
import space.kscience.kmath.chains.SimpleChain
import space.kscience.kmath.stat.RandomGenerator
import space.kscience.kmath.random.RandomGenerator
public class UniformDistribution(public val range: ClosedFloatingPointRange<Double>) : UnivariateDistribution<Double> {
private val length: Double = range.endInclusive - range.start

View File

@ -22,6 +22,10 @@ public class MCScope(
public val random: RandomGenerator,
)
public fun MCScope.asCoroutineScope(): CoroutineScope = object : CoroutineScope {
override val coroutineContext: CoroutineContext get() = this@asCoroutineScope.coroutineContext
}
/**
* Launches a supervised Monte-Carlo scope
*/

View File

@ -6,7 +6,7 @@
package space.kscience.kmath.samplers
import space.kscience.kmath.chains.BlockingDoubleChain
import space.kscience.kmath.stat.RandomGenerator
import space.kscience.kmath.random.RandomGenerator
import space.kscience.kmath.structures.DoubleBuffer
import kotlin.math.ln
import kotlin.math.pow

View File

@ -6,8 +6,8 @@
package space.kscience.kmath.samplers
import space.kscience.kmath.chains.Chain
import space.kscience.kmath.stat.RandomGenerator
import space.kscience.kmath.stat.chain
import space.kscience.kmath.random.RandomGenerator
import space.kscience.kmath.random.chain
import kotlin.math.*
/**
@ -23,14 +23,14 @@ import kotlin.math.*
*/
public class AhrensDieterMarsagliaTsangGammaSampler private constructor(
alpha: Double,
theta: Double
theta: Double,
) : Sampler<Double> {
private val delegate: BaseGammaSampler =
if (alpha < 1) AhrensDieterGammaSampler(alpha, theta) else MarsagliaTsangGammaSampler(alpha, theta)
private abstract class BaseGammaSampler internal constructor(
protected val alpha: Double,
protected val theta: Double
protected val theta: Double,
) : Sampler<Double> {
init {
require(alpha > 0) { "alpha is not strictly positive: $alpha" }
@ -117,7 +117,7 @@ public class AhrensDieterMarsagliaTsangGammaSampler private constructor(
public companion object {
public fun of(
alpha: Double,
theta: Double
theta: Double,
): Sampler<Double> = AhrensDieterMarsagliaTsangGammaSampler(alpha, theta)
}
}

View File

@ -6,8 +6,8 @@
package space.kscience.kmath.samplers
import space.kscience.kmath.chains.Chain
import space.kscience.kmath.stat.RandomGenerator
import space.kscience.kmath.stat.chain
import space.kscience.kmath.random.RandomGenerator
import space.kscience.kmath.random.chain
import kotlin.math.ceil
import kotlin.math.max
import kotlin.math.min

View File

@ -6,7 +6,7 @@
package space.kscience.kmath.samplers
import space.kscience.kmath.chains.BlockingDoubleChain
import space.kscience.kmath.stat.RandomGenerator
import space.kscience.kmath.random.RandomGenerator
import space.kscience.kmath.structures.DoubleBuffer
import kotlin.math.*

View File

@ -7,7 +7,7 @@ package space.kscience.kmath.samplers
import space.kscience.kmath.chains.BlockingDoubleChain
import space.kscience.kmath.chains.map
import space.kscience.kmath.stat.RandomGenerator
import space.kscience.kmath.random.RandomGenerator
/**
* Sampling from a Gaussian distribution with given mean and standard deviation.
@ -21,7 +21,7 @@ import space.kscience.kmath.stat.RandomGenerator
public class GaussianSampler(
public val mean: Double,
public val standardDeviation: Double,
private val normalized: NormalizedGaussianSampler = BoxMullerSampler
private val normalized: NormalizedGaussianSampler = BoxMullerSampler,
) : BlockingDoubleSampler {
init {

View File

@ -6,7 +6,7 @@
package space.kscience.kmath.samplers
import space.kscience.kmath.chains.BlockingIntChain
import space.kscience.kmath.stat.RandomGenerator
import space.kscience.kmath.random.RandomGenerator
import space.kscience.kmath.structures.IntBuffer
import kotlin.math.exp

View File

@ -6,7 +6,7 @@
package space.kscience.kmath.samplers
import space.kscience.kmath.chains.BlockingDoubleChain
import space.kscience.kmath.stat.RandomGenerator
import space.kscience.kmath.random.RandomGenerator
import space.kscience.kmath.structures.DoubleBuffer
import kotlin.math.ln
import kotlin.math.sqrt

View File

@ -6,9 +6,9 @@
package space.kscience.kmath.samplers
import space.kscience.kmath.chains.BlockingDoubleChain
import space.kscience.kmath.stat.RandomGenerator
import space.kscience.kmath.random.RandomGenerator
public interface BlockingDoubleSampler: Sampler<Double>{
public interface BlockingDoubleSampler : Sampler<Double> {
override fun sample(generator: RandomGenerator): BlockingDoubleChain
}
@ -17,6 +17,6 @@ public interface BlockingDoubleSampler: Sampler<Double>{
* Marker interface for a sampler that generates values from an N(0,1)
* [Gaussian distribution](https://en.wikipedia.org/wiki/Normal_distribution).
*/
public fun interface NormalizedGaussianSampler : BlockingDoubleSampler{
public fun interface NormalizedGaussianSampler : BlockingDoubleSampler {
public companion object
}

View File

@ -7,7 +7,7 @@ package space.kscience.kmath.samplers
import space.kscience.kmath.chains.BlockingIntChain
import space.kscience.kmath.misc.toIntExact
import space.kscience.kmath.stat.RandomGenerator
import space.kscience.kmath.random.RandomGenerator
import space.kscience.kmath.structures.IntBuffer
import kotlin.math.*

View File

@ -8,7 +8,7 @@ package space.kscience.kmath.samplers
import kotlinx.coroutines.flow.first
import space.kscience.kmath.chains.Chain
import space.kscience.kmath.chains.collect
import space.kscience.kmath.stat.RandomGenerator
import space.kscience.kmath.random.RandomGenerator
import space.kscience.kmath.structures.Buffer
import space.kscience.kmath.structures.BufferFactory
import space.kscience.kmath.structures.DoubleBuffer

View File

@ -12,7 +12,7 @@ import space.kscience.kmath.chains.zip
import space.kscience.kmath.operations.Group
import space.kscience.kmath.operations.ScaleOperations
import space.kscience.kmath.operations.invoke
import space.kscience.kmath.stat.RandomGenerator
import space.kscience.kmath.random.RandomGenerator
/**
* Implements [Sampler] by sampling only certain [value].

View File

@ -6,8 +6,7 @@
package space.kscience.kmath.samplers
import space.kscience.kmath.chains.BlockingDoubleChain
import space.kscience.kmath.misc.toIntExact
import space.kscience.kmath.stat.RandomGenerator
import space.kscience.kmath.random.RandomGenerator
import space.kscience.kmath.structures.DoubleBuffer
import kotlin.math.*

View File

@ -7,13 +7,17 @@ package space.kscience.kmath.stat
import org.apache.commons.rng.UniformRandomProvider
import org.apache.commons.rng.simple.RandomSource
import space.kscience.kmath.random.RandomGenerator
/**
* Implements [RandomGenerator] by delegating all operations to [RandomSource].
*
* @property source the underlying [RandomSource] object.
*/
public class RandomSourceGenerator internal constructor(public val source: RandomSource, seed: Long?) : RandomGenerator {
public class RandomSourceGenerator internal constructor(
public val source: RandomSource,
seed: Long?,
) : RandomGenerator {
internal val random: UniformRandomProvider = seed?.let { RandomSource.create(source, seed) }
?: RandomSource.create(source)

View File

@ -8,6 +8,7 @@ package space.kscience.kmath.stat
import kotlinx.coroutines.runBlocking
import org.junit.jupiter.api.Assertions
import org.junit.jupiter.api.Test
import space.kscience.kmath.random.RandomGenerator
import space.kscience.kmath.samplers.GaussianSampler
internal class CommonsDistributionsTest {

View File

@ -6,20 +6,22 @@
package space.kscience.kmath.stat
import kotlinx.coroutines.*
import space.kscience.kmath.random.launch
import space.kscience.kmath.random.mcScope
import java.util.*
import kotlin.test.Test
import kotlin.test.assertEquals
data class RandomResult(val branch: String, val order: Int, val value: Int)
typealias ATest = suspend CoroutineScope.() -> Set<RandomResult>
internal typealias ATest = suspend () -> Set<RandomResult>
class MCScopeTest {
internal class MCScopeTest {
val simpleTest: ATest = {
mcScope(1111) {
val res = Collections.synchronizedSet(HashSet<RandomResult>())
launch {
launch{
//println(random)
repeat(10) {
delay(10)

View File

@ -6,6 +6,8 @@
package space.kscience.kmath.stat
import kotlinx.coroutines.runBlocking
import space.kscience.kmath.random.RandomGenerator
import space.kscience.kmath.random.chain
import space.kscience.kmath.samplers.Sampler
import space.kscience.kmath.samplers.sampleBuffer
import kotlin.test.Test

View File

@ -9,6 +9,8 @@ import kotlinx.coroutines.flow.first
import kotlinx.coroutines.flow.last
import kotlinx.coroutines.flow.take
import kotlinx.coroutines.runBlocking
import space.kscience.kmath.random.RandomGenerator
import space.kscience.kmath.random.chain
import space.kscience.kmath.streaming.chunked
import kotlin.test.Test
import kotlin.test.assertEquals

View File

@ -6,8 +6,8 @@
package space.kscience.kmath.tensors.core.internal
import space.kscience.kmath.nd.as1D
import space.kscience.kmath.random.RandomGenerator
import space.kscience.kmath.samplers.GaussianSampler
import space.kscience.kmath.stat.RandomGenerator
import space.kscience.kmath.structures.*
import space.kscience.kmath.tensors.core.BufferedTensor
import space.kscience.kmath.tensors.core.DoubleTensor