forked from kscience/kmath
Drop koma support, add more explicit visibility modifiers
This commit is contained in:
parent
8ae9a071ef
commit
fc5ec8fed7
@ -54,9 +54,6 @@ can be used for a wide variety of purposes from high performance calculations to
|
|||||||
library in Kotlin code and maybe rewrite some parts to better suit the Kotlin programming paradigm, however there is no fixed roadmap for that. Feel free
|
library in Kotlin code and maybe rewrite some parts to better suit the Kotlin programming paradigm, however there is no fixed roadmap for that. Feel free
|
||||||
to submit a feature request if you want something to be done first.
|
to submit a feature request if you want something to be done first.
|
||||||
|
|
||||||
* **Koma wrapper** [Koma](https://github.com/kyonifer/koma) is a well established numerics library in Kotlin, specifically linear algebra.
|
|
||||||
The plan is to have wrappers for koma implementations for compatibility with kmath API.
|
|
||||||
|
|
||||||
## Planned features
|
## Planned features
|
||||||
|
|
||||||
* **Messaging** A mathematical notation to support multi-language and multi-node communication for mathematical tasks.
|
* **Messaging** A mathematical notation to support multi-language and multi-node communication for mathematical tasks.
|
||||||
|
@ -12,6 +12,3 @@ api and multiple library back-ends.
|
|||||||
* [Expressions](./expressions.md)
|
* [Expressions](./expressions.md)
|
||||||
|
|
||||||
* Commons math integration
|
* Commons math integration
|
||||||
|
|
||||||
* Koma integration
|
|
||||||
|
|
||||||
|
@ -10,7 +10,6 @@ plugins {
|
|||||||
allOpen.annotation("org.openjdk.jmh.annotations.State")
|
allOpen.annotation("org.openjdk.jmh.annotations.State")
|
||||||
|
|
||||||
repositories {
|
repositories {
|
||||||
maven("http://dl.bintray.com/kyonifer/maven")
|
|
||||||
maven("https://dl.bintray.com/mipt-npm/scientifik")
|
maven("https://dl.bintray.com/mipt-npm/scientifik")
|
||||||
maven("https://dl.bintray.com/mipt-npm/dev")
|
maven("https://dl.bintray.com/mipt-npm/dev")
|
||||||
maven("https://dl.bintray.com/kotlin/kotlin-dev/")
|
maven("https://dl.bintray.com/kotlin/kotlin-dev/")
|
||||||
@ -25,10 +24,8 @@ dependencies {
|
|||||||
implementation(project(":kmath-coroutines"))
|
implementation(project(":kmath-coroutines"))
|
||||||
implementation(project(":kmath-commons"))
|
implementation(project(":kmath-commons"))
|
||||||
implementation(project(":kmath-prob"))
|
implementation(project(":kmath-prob"))
|
||||||
implementation(project(":kmath-koma"))
|
|
||||||
implementation(project(":kmath-viktor"))
|
implementation(project(":kmath-viktor"))
|
||||||
implementation(project(":kmath-dimensions"))
|
implementation(project(":kmath-dimensions"))
|
||||||
implementation("com.kyonifer:koma-core-ejml:0.12")
|
|
||||||
implementation("org.jetbrains.kotlinx:kotlinx-io-jvm:0.2.0-npm-dev-6")
|
implementation("org.jetbrains.kotlinx:kotlinx-io-jvm:0.2.0-npm-dev-6")
|
||||||
implementation("org.jetbrains.kotlinx:kotlinx.benchmark.runtime:0.2.0-dev-20")
|
implementation("org.jetbrains.kotlinx:kotlinx.benchmark.runtime:0.2.0-dev-20")
|
||||||
"benchmarksCompile"(sourceSets.main.get().output + sourceSets.main.get().compileClasspath) //sourceSets.main.output + sourceSets.main.runtimeClasspath
|
"benchmarksCompile"(sourceSets.main.get().output + sourceSets.main.get().compileClasspath) //sourceSets.main.output + sourceSets.main.runtimeClasspath
|
||||||
|
@ -5,44 +5,33 @@ import org.openjdk.jmh.annotations.Scope
|
|||||||
import org.openjdk.jmh.annotations.State
|
import org.openjdk.jmh.annotations.State
|
||||||
import java.nio.IntBuffer
|
import java.nio.IntBuffer
|
||||||
|
|
||||||
|
|
||||||
@State(Scope.Benchmark)
|
@State(Scope.Benchmark)
|
||||||
class ArrayBenchmark {
|
class ArrayBenchmark {
|
||||||
|
|
||||||
@Benchmark
|
@Benchmark
|
||||||
fun benchmarkArrayRead() {
|
fun benchmarkArrayRead() {
|
||||||
var res = 0
|
var res = 0
|
||||||
for (i in 1..size) {
|
for (i in 1..size) res += array[size - i]
|
||||||
res += array[size - i]
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Benchmark
|
@Benchmark
|
||||||
fun benchmarkBufferRead() {
|
fun benchmarkBufferRead() {
|
||||||
var res = 0
|
var res = 0
|
||||||
for (i in 1..size) {
|
for (i in 1..size) res += arrayBuffer.get(size - i)
|
||||||
res += arrayBuffer.get(size - i)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Benchmark
|
@Benchmark
|
||||||
fun nativeBufferRead() {
|
fun nativeBufferRead() {
|
||||||
var res = 0
|
var res = 0
|
||||||
for (i in 1..size) {
|
for (i in 1..size) res += nativeBuffer.get(size - i)
|
||||||
res += nativeBuffer.get(size - i)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
val size = 1000
|
const val size: Int = 1000
|
||||||
|
val array: IntArray = IntArray(size) { it }
|
||||||
val array = IntArray(size) { it }
|
val arrayBuffer: IntBuffer = IntBuffer.wrap(array)
|
||||||
val arrayBuffer = IntBuffer.wrap(array)
|
|
||||||
val nativeBuffer = IntBuffer.allocate(size).also {
|
|
||||||
for (i in 0 until size) {
|
|
||||||
it.put(i, i)
|
|
||||||
}
|
|
||||||
|
|
||||||
|
val nativeBuffer: IntBuffer = IntBuffer.allocate(size).also {
|
||||||
|
for (i in 0 until size) it.put(i, i)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,70 +1,70 @@
|
|||||||
package scientifik.kmath.ast
|
//package scientifik.kmath.ast
|
||||||
|
//
|
||||||
import scientifik.kmath.asm.compile
|
//import scientifik.kmath.asm.compile
|
||||||
import scientifik.kmath.expressions.Expression
|
//import scientifik.kmath.expressions.Expression
|
||||||
import scientifik.kmath.expressions.expressionInField
|
//import scientifik.kmath.expressions.expressionInField
|
||||||
import scientifik.kmath.expressions.invoke
|
//import scientifik.kmath.expressions.invoke
|
||||||
import scientifik.kmath.operations.Field
|
//import scientifik.kmath.operations.Field
|
||||||
import scientifik.kmath.operations.RealField
|
//import scientifik.kmath.operations.RealField
|
||||||
import kotlin.random.Random
|
//import kotlin.random.Random
|
||||||
import kotlin.system.measureTimeMillis
|
//import kotlin.system.measureTimeMillis
|
||||||
|
//
|
||||||
class ExpressionsInterpretersBenchmark {
|
//class ExpressionsInterpretersBenchmark {
|
||||||
private val algebra: Field<Double> = RealField
|
// private val algebra: Field<Double> = RealField
|
||||||
fun functionalExpression() {
|
// fun functionalExpression() {
|
||||||
val expr = algebra.expressionInField {
|
// val expr = algebra.expressionInField {
|
||||||
variable("x") * const(2.0) + const(2.0) / variable("x") - const(16.0)
|
// variable("x") * const(2.0) + const(2.0) / variable("x") - const(16.0)
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
invokeAndSum(expr)
|
// invokeAndSum(expr)
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
fun mstExpression() {
|
// fun mstExpression() {
|
||||||
val expr = algebra.mstInField {
|
// val expr = algebra.mstInField {
|
||||||
symbol("x") * number(2.0) + number(2.0) / symbol("x") - number(16.0)
|
// symbol("x") * number(2.0) + number(2.0) / symbol("x") - number(16.0)
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
invokeAndSum(expr)
|
// invokeAndSum(expr)
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
fun asmExpression() {
|
// fun asmExpression() {
|
||||||
val expr = algebra.mstInField {
|
// val expr = algebra.mstInField {
|
||||||
symbol("x") * number(2.0) + number(2.0) / symbol("x") - number(16.0)
|
// symbol("x") * number(2.0) + number(2.0) / symbol("x") - number(16.0)
|
||||||
}.compile()
|
// }.compile()
|
||||||
|
//
|
||||||
invokeAndSum(expr)
|
// invokeAndSum(expr)
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
private fun invokeAndSum(expr: Expression<Double>) {
|
// private fun invokeAndSum(expr: Expression<Double>) {
|
||||||
val random = Random(0)
|
// val random = Random(0)
|
||||||
var sum = 0.0
|
// var sum = 0.0
|
||||||
|
//
|
||||||
repeat(1000000) {
|
// repeat(1000000) {
|
||||||
sum += expr("x" to random.nextDouble())
|
// sum += expr("x" to random.nextDouble())
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
println(sum)
|
// println(sum)
|
||||||
}
|
// }
|
||||||
}
|
//}
|
||||||
|
//
|
||||||
fun main() {
|
//fun main() {
|
||||||
val benchmark = ExpressionsInterpretersBenchmark()
|
// val benchmark = ExpressionsInterpretersBenchmark()
|
||||||
|
//
|
||||||
val fe = measureTimeMillis {
|
// val fe = measureTimeMillis {
|
||||||
benchmark.functionalExpression()
|
// benchmark.functionalExpression()
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
println("fe=$fe")
|
// println("fe=$fe")
|
||||||
|
//
|
||||||
val mst = measureTimeMillis {
|
// val mst = measureTimeMillis {
|
||||||
benchmark.mstExpression()
|
// benchmark.mstExpression()
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
println("mst=$mst")
|
// println("mst=$mst")
|
||||||
|
//
|
||||||
val asm = measureTimeMillis {
|
// val asm = measureTimeMillis {
|
||||||
benchmark.asmExpression()
|
// benchmark.asmExpression()
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
println("asm=$asm")
|
// println("asm=$asm")
|
||||||
}
|
//}
|
||||||
|
@ -1,55 +0,0 @@
|
|||||||
package scientifik.kmath.linear
|
|
||||||
|
|
||||||
import koma.matrix.ejml.EJMLMatrixFactory
|
|
||||||
import scientifik.kmath.commons.linear.CMMatrixContext
|
|
||||||
import scientifik.kmath.commons.linear.inverse
|
|
||||||
import scientifik.kmath.commons.linear.toCM
|
|
||||||
import scientifik.kmath.operations.RealField
|
|
||||||
import scientifik.kmath.operations.invoke
|
|
||||||
import scientifik.kmath.structures.Matrix
|
|
||||||
import kotlin.contracts.ExperimentalContracts
|
|
||||||
import kotlin.random.Random
|
|
||||||
import kotlin.system.measureTimeMillis
|
|
||||||
|
|
||||||
@ExperimentalContracts
|
|
||||||
fun main() {
|
|
||||||
val random = Random(1224)
|
|
||||||
val dim = 100
|
|
||||||
//creating invertible matrix
|
|
||||||
val u = Matrix.real(dim, dim) { i, j -> if (i <= j) random.nextDouble() else 0.0 }
|
|
||||||
val l = Matrix.real(dim, dim) { i, j -> if (i >= j) random.nextDouble() else 0.0 }
|
|
||||||
val matrix = l dot u
|
|
||||||
|
|
||||||
val n = 5000 // iterations
|
|
||||||
|
|
||||||
MatrixContext.real {
|
|
||||||
repeat(50) { val res = inverse(matrix) }
|
|
||||||
val inverseTime = measureTimeMillis { repeat(n) { val res = inverse(matrix) } }
|
|
||||||
println("[kmath] Inversion of $n matrices $dim x $dim finished in $inverseTime millis")
|
|
||||||
}
|
|
||||||
|
|
||||||
//commons-math
|
|
||||||
|
|
||||||
val commonsTime = measureTimeMillis {
|
|
||||||
CMMatrixContext {
|
|
||||||
val cm = matrix.toCM() //avoid overhead on conversion
|
|
||||||
repeat(n) { val res = inverse(cm) }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
println("[commons-math] Inversion of $n matrices $dim x $dim finished in $commonsTime millis")
|
|
||||||
|
|
||||||
//koma-ejml
|
|
||||||
|
|
||||||
val komaTime = measureTimeMillis {
|
|
||||||
(KomaMatrixContext(EJMLMatrixFactory(), RealField)) {
|
|
||||||
val km = matrix.toKoma() //avoid overhead on conversion
|
|
||||||
repeat(n) {
|
|
||||||
val res = inverse(km)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
println("[koma-ejml] Inversion of $n matrices $dim x $dim finished in $komaTime millis")
|
|
||||||
}
|
|
@ -1,49 +0,0 @@
|
|||||||
package scientifik.kmath.linear
|
|
||||||
|
|
||||||
import koma.matrix.ejml.EJMLMatrixFactory
|
|
||||||
import scientifik.kmath.commons.linear.CMMatrixContext
|
|
||||||
import scientifik.kmath.commons.linear.toCM
|
|
||||||
import scientifik.kmath.operations.RealField
|
|
||||||
import scientifik.kmath.operations.invoke
|
|
||||||
import scientifik.kmath.structures.Matrix
|
|
||||||
import kotlin.random.Random
|
|
||||||
import kotlin.system.measureTimeMillis
|
|
||||||
|
|
||||||
fun main() {
|
|
||||||
val random = Random(12224)
|
|
||||||
val dim = 1000
|
|
||||||
//creating invertible matrix
|
|
||||||
val matrix1 = Matrix.real(dim, dim) { i, j -> if (i <= j) random.nextDouble() else 0.0 }
|
|
||||||
val matrix2 = Matrix.real(dim, dim) { i, j -> if (i <= j) random.nextDouble() else 0.0 }
|
|
||||||
|
|
||||||
// //warmup
|
|
||||||
// matrix1 dot matrix2
|
|
||||||
|
|
||||||
CMMatrixContext {
|
|
||||||
val cmMatrix1 = matrix1.toCM()
|
|
||||||
val cmMatrix2 = matrix2.toCM()
|
|
||||||
|
|
||||||
val cmTime = measureTimeMillis {
|
|
||||||
cmMatrix1 dot cmMatrix2
|
|
||||||
}
|
|
||||||
|
|
||||||
println("CM implementation time: $cmTime")
|
|
||||||
}
|
|
||||||
|
|
||||||
(KomaMatrixContext(EJMLMatrixFactory(), RealField)) {
|
|
||||||
val komaMatrix1 = matrix1.toKoma()
|
|
||||||
val komaMatrix2 = matrix2.toKoma()
|
|
||||||
|
|
||||||
val komaTime = measureTimeMillis {
|
|
||||||
komaMatrix1 dot komaMatrix2
|
|
||||||
}
|
|
||||||
|
|
||||||
println("Koma-ejml implementation time: $komaTime")
|
|
||||||
}
|
|
||||||
|
|
||||||
val genericTime = measureTimeMillis {
|
|
||||||
val res = matrix1 dot matrix2
|
|
||||||
}
|
|
||||||
|
|
||||||
println("Generic implementation time: $genericTime")
|
|
||||||
}
|
|
@ -5,6 +5,6 @@ dependencies {
|
|||||||
api(project(":kmath-core"))
|
api(project(":kmath-core"))
|
||||||
api(project(":kmath-coroutines"))
|
api(project(":kmath-coroutines"))
|
||||||
api(project(":kmath-prob"))
|
api(project(":kmath-prob"))
|
||||||
api(project(":kmath-functions"))
|
// api(project(":kmath-functions"))
|
||||||
api("org.apache.commons:commons-math3:3.6.1")
|
api("org.apache.commons:commons-math3:3.6.1")
|
||||||
}
|
}
|
||||||
|
@ -43,7 +43,6 @@ public interface Chain<out R> : Flow<R> {
|
|||||||
public companion object
|
public companion object
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public fun <T> Iterator<T>.asChain(): Chain<T> = SimpleChain { next() }
|
public fun <T> Iterator<T>.asChain(): Chain<T> = SimpleChain { next() }
|
||||||
public fun <T> Sequence<T>.asChain(): Chain<T> = iterator().asChain()
|
public fun <T> Sequence<T>.asChain(): Chain<T> = iterator().asChain()
|
||||||
|
|
||||||
@ -51,22 +50,20 @@ public fun <T> Sequence<T>.asChain(): Chain<T> = iterator().asChain()
|
|||||||
* A simple chain of independent tokens
|
* A simple chain of independent tokens
|
||||||
*/
|
*/
|
||||||
public class SimpleChain<out R>(private val gen: suspend () -> R) : Chain<R> {
|
public class SimpleChain<out R>(private val gen: suspend () -> R) : Chain<R> {
|
||||||
override suspend fun next(): R = gen()
|
public override suspend fun next(): R = gen()
|
||||||
override fun fork(): Chain<R> = this
|
public override fun fork(): Chain<R> = this
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A stateless Markov chain
|
* A stateless Markov chain
|
||||||
*/
|
*/
|
||||||
public class MarkovChain<out R : Any>(private val seed: suspend () -> R, private val gen: suspend (R) -> R) : Chain<R> {
|
public class MarkovChain<out R : Any>(private val seed: suspend () -> R, private val gen: suspend (R) -> R) : Chain<R> {
|
||||||
|
private val mutex: Mutex = Mutex()
|
||||||
private val mutex = Mutex()
|
|
||||||
|
|
||||||
private var value: R? = null
|
private var value: R? = null
|
||||||
|
|
||||||
public fun value(): R? = value
|
public fun value(): R? = value
|
||||||
|
|
||||||
override suspend fun next(): R {
|
public override suspend fun next(): R {
|
||||||
mutex.withLock {
|
mutex.withLock {
|
||||||
val newValue = gen(value ?: seed())
|
val newValue = gen(value ?: seed())
|
||||||
value = newValue
|
value = newValue
|
||||||
@ -74,9 +71,7 @@ public class MarkovChain<out R : Any>(private val seed: suspend () -> R, private
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun fork(): Chain<R> {
|
public override fun fork(): Chain<R> = MarkovChain(seed = { value ?: seed() }, gen = gen)
|
||||||
return MarkovChain(seed = { value ?: seed() }, gen = gen)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -91,12 +86,11 @@ public class StatefulChain<S, out R>(
|
|||||||
private val gen: suspend S.(R) -> R
|
private val gen: suspend S.(R) -> R
|
||||||
) : Chain<R> {
|
) : Chain<R> {
|
||||||
private val mutex: Mutex = Mutex()
|
private val mutex: Mutex = Mutex()
|
||||||
|
|
||||||
private var value: R? = null
|
private var value: R? = null
|
||||||
|
|
||||||
public fun value(): R? = value
|
public fun value(): R? = value
|
||||||
|
|
||||||
override suspend fun next(): R {
|
public override suspend fun next(): R {
|
||||||
mutex.withLock {
|
mutex.withLock {
|
||||||
val newValue = state.gen(value ?: state.seed())
|
val newValue = state.gen(value ?: state.seed())
|
||||||
value = newValue
|
value = newValue
|
||||||
@ -104,16 +98,15 @@ public class StatefulChain<S, out R>(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun fork(): Chain<R> = StatefulChain(forkState(state), seed, forkState, gen)
|
public override fun fork(): Chain<R> = StatefulChain(forkState(state), seed, forkState, gen)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A chain that repeats the same value
|
* A chain that repeats the same value
|
||||||
*/
|
*/
|
||||||
public class ConstantChain<out T>(public val value: T) : Chain<T> {
|
public class ConstantChain<out T>(public val value: T) : Chain<T> {
|
||||||
override suspend fun next(): T = value
|
public override suspend fun next(): T = value
|
||||||
|
public override fun fork(): Chain<T> = this
|
||||||
override fun fork(): Chain<T> = this
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -24,7 +24,7 @@ public interface SuspendableMathFunction<T, C : Algebra<T>, R> {
|
|||||||
public suspend operator fun C.invoke(arg: T): R
|
public suspend operator fun C.invoke(arg: T): R
|
||||||
}
|
}
|
||||||
|
|
||||||
public suspend fun <R> SuspendableMathFunction<Double, RealField, R>.invoke(arg: Double) = RealField.invoke(arg)
|
public suspend fun <R> SuspendableMathFunction<Double, RealField, R>.invoke(arg: Double): R = RealField.invoke(arg)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A parametric function with parameter
|
* A parametric function with parameter
|
||||||
|
@ -29,7 +29,6 @@ public interface Histogram<T : Any, out B : Bin<T>> : Iterable<B> {
|
|||||||
* Dimension of the histogram
|
* Dimension of the histogram
|
||||||
*/
|
*/
|
||||||
public val dimension: Int
|
public val dimension: Int
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public interface MutableHistogram<T : Any, out B : Bin<T>> : Histogram<T, B> {
|
public interface MutableHistogram<T : Any, out B : Bin<T>> : Histogram<T, B> {
|
||||||
|
@ -44,7 +44,7 @@ public class UnivariateHistogram private constructor(private val factory: (Doubl
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun createBin(value: Double): UnivariateBin = factory(value).also {
|
private fun createBin(value: Double): UnivariateBin = factory(value).also {
|
||||||
synchronized(this) { bins.put(it.position, it) }
|
synchronized(this) { bins[it.position] = it }
|
||||||
}
|
}
|
||||||
|
|
||||||
public override operator fun get(point: Buffer<out Double>): UnivariateBin? = get(point[0])
|
public override operator fun get(point: Buffer<out Double>): UnivariateBin? = get(point[0])
|
||||||
@ -87,7 +87,7 @@ public class UnivariateHistogram private constructor(private val factory: (Doubl
|
|||||||
)
|
)
|
||||||
|
|
||||||
else -> {
|
else -> {
|
||||||
val index = (0 until sorted.size).first { value > sorted[it] }
|
val index = sorted.indices.first { value > sorted[it] }
|
||||||
val left = sorted[index]
|
val left = sorted[index]
|
||||||
val right = sorted[index + 1]
|
val right = sorted[index + 1]
|
||||||
UnivariateBin((left + right) / 2, (right - left))
|
UnivariateBin((left + right) / 2, (right - left))
|
||||||
|
@ -1,30 +0,0 @@
|
|||||||
plugins { id("ru.mipt.npm.mpp") }
|
|
||||||
|
|
||||||
repositories.maven("http://dl.bintray.com/kyonifer/maven")
|
|
||||||
|
|
||||||
kotlin.sourceSets {
|
|
||||||
commonMain {
|
|
||||||
dependencies {
|
|
||||||
api(project(":kmath-core"))
|
|
||||||
api("com.kyonifer:koma-core-api-common:0.12")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
jvmMain {
|
|
||||||
dependencies {
|
|
||||||
api("com.kyonifer:koma-core-api-jvm:0.12")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
jvmTest {
|
|
||||||
dependencies {
|
|
||||||
implementation("com.kyonifer:koma-core-ejml:0.12")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
jsMain {
|
|
||||||
dependencies {
|
|
||||||
api("com.kyonifer:koma-core-api-js:0.12")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,105 +0,0 @@
|
|||||||
package scientifik.kmath.linear
|
|
||||||
|
|
||||||
import koma.extensions.fill
|
|
||||||
import koma.matrix.MatrixFactory
|
|
||||||
import scientifik.kmath.operations.Space
|
|
||||||
import scientifik.kmath.operations.invoke
|
|
||||||
import scientifik.kmath.structures.Matrix
|
|
||||||
import scientifik.kmath.structures.NDStructure
|
|
||||||
|
|
||||||
public class KomaMatrixContext<T : Any>(
|
|
||||||
private val factory: MatrixFactory<koma.matrix.Matrix<T>>,
|
|
||||||
private val space: Space<T>
|
|
||||||
) : MatrixContext<T> {
|
|
||||||
public override fun produce(rows: Int, columns: Int, initializer: (i: Int, j: Int) -> T): KomaMatrix<T> =
|
|
||||||
KomaMatrix(factory.zeros(rows, columns).fill(initializer))
|
|
||||||
|
|
||||||
public fun Matrix<T>.toKoma(): KomaMatrix<T> = if (this is KomaMatrix)
|
|
||||||
this
|
|
||||||
else
|
|
||||||
produce(rowNum, colNum) { i, j -> get(i, j) }
|
|
||||||
|
|
||||||
public fun Point<T>.toKoma(): KomaVector<T> = if (this is KomaVector)
|
|
||||||
this
|
|
||||||
else
|
|
||||||
KomaVector(factory.zeros(size, 1).fill { i, _ -> get(i) })
|
|
||||||
|
|
||||||
public override fun Matrix<T>.dot(other: Matrix<T>): KomaMatrix<T> =
|
|
||||||
KomaMatrix(toKoma().origin * other.toKoma().origin)
|
|
||||||
|
|
||||||
public override fun Matrix<T>.dot(vector: Point<T>): KomaVector<T> =
|
|
||||||
KomaVector(toKoma().origin * vector.toKoma().origin)
|
|
||||||
|
|
||||||
public override operator fun Matrix<T>.unaryMinus(): KomaMatrix<T> =
|
|
||||||
KomaMatrix(toKoma().origin.unaryMinus())
|
|
||||||
|
|
||||||
public override fun add(a: Matrix<T>, b: Matrix<T>): KomaMatrix<T> =
|
|
||||||
KomaMatrix(a.toKoma().origin + b.toKoma().origin)
|
|
||||||
|
|
||||||
public override operator fun Matrix<T>.minus(b: Matrix<T>): KomaMatrix<T> =
|
|
||||||
KomaMatrix(toKoma().origin - b.toKoma().origin)
|
|
||||||
|
|
||||||
public override fun multiply(a: Matrix<T>, k: Number): Matrix<T> =
|
|
||||||
produce(a.rowNum, a.colNum) { i, j -> space { a[i, j] * k } }
|
|
||||||
|
|
||||||
public override operator fun Matrix<T>.times(value: T): KomaMatrix<T> =
|
|
||||||
KomaMatrix(toKoma().origin * value)
|
|
||||||
|
|
||||||
public companion object
|
|
||||||
}
|
|
||||||
|
|
||||||
public fun <T : Any> KomaMatrixContext<T>.solve(a: Matrix<T>, b: Matrix<T>): KomaMatrix<T> =
|
|
||||||
KomaMatrix(a.toKoma().origin.solve(b.toKoma().origin))
|
|
||||||
|
|
||||||
public fun <T : Any> KomaMatrixContext<T>.solve(a: Matrix<T>, b: Point<T>): KomaVector<T> =
|
|
||||||
KomaVector(a.toKoma().origin.solve(b.toKoma().origin))
|
|
||||||
|
|
||||||
public fun <T : Any> KomaMatrixContext<T>.inverse(a: Matrix<T>): KomaMatrix<T> =
|
|
||||||
KomaMatrix(a.toKoma().origin.inv())
|
|
||||||
|
|
||||||
public class KomaMatrix<T : Any>(public val origin: koma.matrix.Matrix<T>, features: Set<MatrixFeature>? = null) :
|
|
||||||
FeaturedMatrix<T> {
|
|
||||||
public override val rowNum: Int get() = origin.numRows()
|
|
||||||
public override val colNum: Int get() = origin.numCols()
|
|
||||||
|
|
||||||
public override val shape: IntArray get() = intArrayOf(origin.numRows(), origin.numCols())
|
|
||||||
|
|
||||||
public override val features: Set<MatrixFeature> = features ?: hashSetOf(
|
|
||||||
object : DeterminantFeature<T> {
|
|
||||||
override val determinant: T get() = origin.det()
|
|
||||||
},
|
|
||||||
|
|
||||||
object : LUPDecompositionFeature<T> {
|
|
||||||
private val lup by lazy { origin.LU() }
|
|
||||||
override val l: FeaturedMatrix<T> get() = KomaMatrix(lup.second)
|
|
||||||
override val u: FeaturedMatrix<T> get() = KomaMatrix(lup.third)
|
|
||||||
override val p: FeaturedMatrix<T> get() = KomaMatrix(lup.first)
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
override fun suggestFeature(vararg features: MatrixFeature): FeaturedMatrix<T> =
|
|
||||||
KomaMatrix(this.origin, this.features + features)
|
|
||||||
|
|
||||||
override operator fun get(i: Int, j: Int): T = origin.getGeneric(i, j)
|
|
||||||
|
|
||||||
override fun equals(other: Any?): Boolean {
|
|
||||||
return NDStructure.equals(this, other as? NDStructure<*> ?: return false)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun hashCode(): Int {
|
|
||||||
var result = origin.hashCode()
|
|
||||||
result = 31 * result + features.hashCode()
|
|
||||||
return result
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public class KomaVector<T : Any> internal constructor(public val origin: koma.matrix.Matrix<T>) : Point<T> {
|
|
||||||
override val size: Int get() = origin.numRows()
|
|
||||||
|
|
||||||
init {
|
|
||||||
require(origin.numCols() == 1) { error("Only single column matrices are allowed") }
|
|
||||||
}
|
|
||||||
|
|
||||||
override operator fun get(index: Int): T = origin.getGeneric(index)
|
|
||||||
override operator fun iterator(): Iterator<T> = origin.toIterable().iterator()
|
|
||||||
}
|
|
@ -73,5 +73,5 @@ public fun <T : Any> Sampler<T>.sampleBuffer(
|
|||||||
/**
|
/**
|
||||||
* Generate a bunch of samples from real distributions
|
* Generate a bunch of samples from real distributions
|
||||||
*/
|
*/
|
||||||
public fun Sampler<Double>.sampleBuffer(generator: RandomGenerator, size: Int) =
|
public fun Sampler<Double>.sampleBuffer(generator: RandomGenerator, size: Int): Chain<Buffer<Double>> =
|
||||||
sampleBuffer(generator, size, Buffer.Companion::real)
|
sampleBuffer(generator, size, Buffer.Companion::real)
|
||||||
|
@ -6,42 +6,38 @@ import scientifik.kmath.chains.SimpleChain
|
|||||||
/**
|
/**
|
||||||
* A multivariate distribution which takes a map of parameters
|
* A multivariate distribution which takes a map of parameters
|
||||||
*/
|
*/
|
||||||
interface NamedDistribution<T> : Distribution<Map<String, T>>
|
public interface NamedDistribution<T> : Distribution<Map<String, T>>
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A multivariate distribution that has independent distributions for separate axis
|
* A multivariate distribution that has independent distributions for separate axis
|
||||||
*/
|
*/
|
||||||
class FactorizedDistribution<T>(val distributions: Collection<NamedDistribution<T>>) : NamedDistribution<T> {
|
public class FactorizedDistribution<T>(public val distributions: Collection<NamedDistribution<T>>) :
|
||||||
|
NamedDistribution<T> {
|
||||||
override fun probability(arg: Map<String, T>): Double {
|
override fun probability(arg: Map<String, T>): Double =
|
||||||
return distributions.fold(1.0) { acc, distr -> acc * distr.probability(arg) }
|
distributions.fold(1.0) { acc, distr -> acc * distr.probability(arg) }
|
||||||
}
|
|
||||||
|
|
||||||
override fun sample(generator: RandomGenerator): Chain<Map<String, T>> {
|
override fun sample(generator: RandomGenerator): Chain<Map<String, T>> {
|
||||||
val chains = distributions.map { it.sample(generator) }
|
val chains = distributions.map { it.sample(generator) }
|
||||||
return SimpleChain<Map<String, T>> {
|
return SimpleChain { chains.fold(emptyMap()) { acc, chain -> acc + chain.next() } }
|
||||||
chains.fold(emptyMap()) { acc, chain -> acc + chain.next() }
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class NamedDistributionWrapper<T : Any>(val name: String, val distribution: Distribution<T>) : NamedDistribution<T> {
|
public class NamedDistributionWrapper<T : Any>(public val name: String, public val distribution: Distribution<T>) :
|
||||||
|
NamedDistribution<T> {
|
||||||
override fun probability(arg: Map<String, T>): Double = distribution.probability(
|
override fun probability(arg: Map<String, T>): Double = distribution.probability(
|
||||||
arg[name] ?: error("Argument with name $name not found in input parameters")
|
arg[name] ?: error("Argument with name $name not found in input parameters")
|
||||||
)
|
)
|
||||||
|
|
||||||
override fun sample(generator: RandomGenerator): Chain<Map<String, T>> {
|
override fun sample(generator: RandomGenerator): Chain<Map<String, T>> {
|
||||||
val chain = distribution.sample(generator)
|
val chain = distribution.sample(generator)
|
||||||
return SimpleChain {
|
return SimpleChain { mapOf(name to chain.next()) }
|
||||||
mapOf(name to chain.next())
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class DistributionBuilder<T: Any>{
|
public class DistributionBuilder<T : Any> {
|
||||||
private val distributions = ArrayList<NamedDistribution<T>>()
|
private val distributions = ArrayList<NamedDistribution<T>>()
|
||||||
|
|
||||||
infix fun String.to(distribution: Distribution<T>){
|
public infix fun String.to(distribution: Distribution<T>) {
|
||||||
distributions.add(NamedDistributionWrapper(this, distribution))
|
distributions.add(NamedDistributionWrapper(this, distribution))
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -5,10 +5,13 @@ import scientifik.kmath.chains.Chain
|
|||||||
/**
|
/**
|
||||||
* A possibly stateful chain producing random values.
|
* A possibly stateful chain producing random values.
|
||||||
*/
|
*/
|
||||||
class RandomChain<out R>(val generator: RandomGenerator, private val gen: suspend RandomGenerator.() -> R) : Chain<R> {
|
public class RandomChain<out R>(
|
||||||
|
public val generator: RandomGenerator,
|
||||||
|
private val gen: suspend RandomGenerator.() -> R
|
||||||
|
) : Chain<R> {
|
||||||
override suspend fun next(): R = generator.gen()
|
override suspend fun next(): R = generator.gen()
|
||||||
|
|
||||||
override fun fork(): Chain<R> = RandomChain(generator.fork(), gen)
|
override fun fork(): Chain<R> = RandomChain(generator.fork(), gen)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun <R> RandomGenerator.chain(gen: suspend RandomGenerator.() -> R): RandomChain<R> = RandomChain(this, gen)
|
public fun <R> RandomGenerator.chain(gen: suspend RandomGenerator.() -> R): RandomChain<R> = RandomChain(this, gen)
|
||||||
|
@ -5,17 +5,15 @@ import kotlin.random.Random
|
|||||||
/**
|
/**
|
||||||
* A basic generator
|
* A basic generator
|
||||||
*/
|
*/
|
||||||
interface RandomGenerator {
|
public interface RandomGenerator {
|
||||||
fun nextBoolean(): Boolean
|
public fun nextBoolean(): Boolean
|
||||||
|
public fun nextDouble(): Double
|
||||||
fun nextDouble(): Double
|
public fun nextInt(): Int
|
||||||
fun nextInt(): Int
|
public fun nextInt(until: Int): Int
|
||||||
fun nextInt(until: Int): Int
|
public fun nextLong(): Long
|
||||||
fun nextLong(): Long
|
public fun nextLong(until: Long): Long
|
||||||
fun nextLong(until: Long): Long
|
public fun fillBytes(array: ByteArray, fromIndex: Int = 0, toIndex: Int = array.size)
|
||||||
|
public fun nextBytes(size: Int): ByteArray = ByteArray(size).also { fillBytes(it) }
|
||||||
fun fillBytes(array: ByteArray, fromIndex: Int = 0, toIndex: Int = array.size)
|
|
||||||
fun nextBytes(size: Int): ByteArray = ByteArray(size).also { fillBytes(it) }
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a new generator which is independent from current generator (operations on new generator do not affect this one
|
* Create a new generator which is independent from current generator (operations on new generator do not affect this one
|
||||||
@ -24,32 +22,27 @@ interface RandomGenerator {
|
|||||||
*
|
*
|
||||||
* The thread safety of this operation is not guaranteed since it could affect the state of the generator.
|
* The thread safety of this operation is not guaranteed since it could affect the state of the generator.
|
||||||
*/
|
*/
|
||||||
fun fork(): RandomGenerator
|
public fun fork(): RandomGenerator
|
||||||
|
|
||||||
companion object {
|
public companion object {
|
||||||
val default by lazy { DefaultGenerator() }
|
public val default: DefaultGenerator by lazy { DefaultGenerator() }
|
||||||
|
|
||||||
fun default(seed: Long) = DefaultGenerator(Random(seed))
|
public fun default(seed: Long): DefaultGenerator = DefaultGenerator(Random(seed))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
inline class DefaultGenerator(val random: Random = Random) : RandomGenerator {
|
public inline class DefaultGenerator(public val random: Random = Random) : RandomGenerator {
|
||||||
override fun nextBoolean(): Boolean = random.nextBoolean()
|
public override fun nextBoolean(): Boolean = random.nextBoolean()
|
||||||
|
public override fun nextDouble(): Double = random.nextDouble()
|
||||||
|
public override fun nextInt(): Int = random.nextInt()
|
||||||
|
public override fun nextInt(until: Int): Int = random.nextInt(until)
|
||||||
|
public override fun nextLong(): Long = random.nextLong()
|
||||||
|
public override fun nextLong(until: Long): Long = random.nextLong(until)
|
||||||
|
|
||||||
override fun nextDouble(): Double = random.nextDouble()
|
public override fun fillBytes(array: ByteArray, fromIndex: Int, toIndex: Int) {
|
||||||
|
|
||||||
override fun nextInt(): Int = random.nextInt()
|
|
||||||
override fun nextInt(until: Int): Int = random.nextInt(until)
|
|
||||||
|
|
||||||
override fun nextLong(): Long = random.nextLong()
|
|
||||||
|
|
||||||
override fun nextLong(until: Long): Long = random.nextLong(until)
|
|
||||||
|
|
||||||
override fun fillBytes(array: ByteArray, fromIndex: Int, toIndex: Int) {
|
|
||||||
random.nextBytes(array, fromIndex, toIndex)
|
random.nextBytes(array, fromIndex, toIndex)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun nextBytes(size: Int): ByteArray = random.nextBytes(size)
|
public override fun nextBytes(size: Int): ByteArray = random.nextBytes(size)
|
||||||
|
public override fun fork(): RandomGenerator = RandomGenerator.default(random.nextLong())
|
||||||
override fun fork(): RandomGenerator = RandomGenerator.default(random.nextLong())
|
|
||||||
}
|
}
|
@ -7,26 +7,25 @@ import scientifik.kmath.chains.zip
|
|||||||
import scientifik.kmath.operations.Space
|
import scientifik.kmath.operations.Space
|
||||||
import scientifik.kmath.operations.invoke
|
import scientifik.kmath.operations.invoke
|
||||||
|
|
||||||
class BasicSampler<T : Any>(val chainBuilder: (RandomGenerator) -> Chain<T>) : Sampler<T> {
|
public class BasicSampler<T : Any>(public val chainBuilder: (RandomGenerator) -> Chain<T>) : Sampler<T> {
|
||||||
override fun sample(generator: RandomGenerator): Chain<T> = chainBuilder(generator)
|
public override fun sample(generator: RandomGenerator): Chain<T> = chainBuilder(generator)
|
||||||
}
|
}
|
||||||
|
|
||||||
class ConstantSampler<T : Any>(val value: T) : Sampler<T> {
|
public class ConstantSampler<T : Any>(public val value: T) : Sampler<T> {
|
||||||
override fun sample(generator: RandomGenerator): Chain<T> = ConstantChain(value)
|
public override fun sample(generator: RandomGenerator): Chain<T> = ConstantChain(value)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A space for samplers. Allows to perform simple operations on distributions
|
* A space for samplers. Allows to perform simple operations on distributions
|
||||||
*/
|
*/
|
||||||
class SamplerSpace<T : Any>(val space: Space<T>) : Space<Sampler<T>> {
|
public class SamplerSpace<T : Any>(public val space: Space<T>) : Space<Sampler<T>> {
|
||||||
|
public override val zero: Sampler<T> = ConstantSampler(space.zero)
|
||||||
|
|
||||||
override val zero: Sampler<T> = ConstantSampler(space.zero)
|
public override fun add(a: Sampler<T>, b: Sampler<T>): Sampler<T> = BasicSampler { generator ->
|
||||||
|
|
||||||
override fun add(a: Sampler<T>, b: Sampler<T>): Sampler<T> = BasicSampler { generator ->
|
|
||||||
a.sample(generator).zip(b.sample(generator)) { aValue, bValue -> space { aValue + bValue } }
|
a.sample(generator).zip(b.sample(generator)) { aValue, bValue -> space { aValue + bValue } }
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun multiply(a: Sampler<T>, k: Number): Sampler<T> = BasicSampler { generator ->
|
public override fun multiply(a: Sampler<T>, k: Number): Sampler<T> = BasicSampler { generator ->
|
||||||
a.sample(generator).map { space { it * k.toDouble() } }
|
a.sample(generator).map { space { it * k.toDouble() } }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -6,7 +6,7 @@ import kotlinx.coroutines.ExperimentalCoroutinesApi
|
|||||||
import kotlinx.coroutines.FlowPreview
|
import kotlinx.coroutines.FlowPreview
|
||||||
import kotlinx.coroutines.flow.Flow
|
import kotlinx.coroutines.flow.Flow
|
||||||
import kotlinx.coroutines.flow.map
|
import kotlinx.coroutines.flow.map
|
||||||
import kotlinx.coroutines.flow.scanReduce
|
import kotlinx.coroutines.flow.runningReduce
|
||||||
import scientifik.kmath.coroutines.mapParallel
|
import scientifik.kmath.coroutines.mapParallel
|
||||||
import scientifik.kmath.operations.*
|
import scientifik.kmath.operations.*
|
||||||
import scientifik.kmath.structures.Buffer
|
import scientifik.kmath.structures.Buffer
|
||||||
@ -16,8 +16,8 @@ import scientifik.kmath.structures.asSequence
|
|||||||
/**
|
/**
|
||||||
* A function, that transforms a buffer of random quantities to some resulting value
|
* A function, that transforms a buffer of random quantities to some resulting value
|
||||||
*/
|
*/
|
||||||
interface Statistic<T, R> {
|
public interface Statistic<T, R> {
|
||||||
suspend operator fun invoke(data: Buffer<T>): R
|
public suspend operator fun invoke(data: Buffer<T>): R
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -26,17 +26,17 @@ interface Statistic<T, R> {
|
|||||||
* @param I - intermediate block type
|
* @param I - intermediate block type
|
||||||
* @param R - result type
|
* @param R - result type
|
||||||
*/
|
*/
|
||||||
interface ComposableStatistic<T, I, R> : Statistic<T, R> {
|
public interface ComposableStatistic<T, I, R> : Statistic<T, R> {
|
||||||
//compute statistic on a single block
|
//compute statistic on a single block
|
||||||
suspend fun computeIntermediate(data: Buffer<T>): I
|
public suspend fun computeIntermediate(data: Buffer<T>): I
|
||||||
|
|
||||||
//Compose two blocks
|
//Compose two blocks
|
||||||
suspend fun composeIntermediate(first: I, second: I): I
|
public suspend fun composeIntermediate(first: I, second: I): I
|
||||||
|
|
||||||
//Transform block to result
|
//Transform block to result
|
||||||
suspend fun toResult(intermediate: I): R
|
public suspend fun toResult(intermediate: I): R
|
||||||
|
|
||||||
override suspend fun invoke(data: Buffer<T>): R = toResult(computeIntermediate(data))
|
public override suspend fun invoke(data: Buffer<T>): R = toResult(computeIntermediate(data))
|
||||||
}
|
}
|
||||||
|
|
||||||
@FlowPreview
|
@FlowPreview
|
||||||
@ -46,7 +46,7 @@ private fun <T, I, R> ComposableStatistic<T, I, R>.flowIntermediate(
|
|||||||
dispatcher: CoroutineDispatcher = Dispatchers.Default
|
dispatcher: CoroutineDispatcher = Dispatchers.Default
|
||||||
): Flow<I> = flow
|
): Flow<I> = flow
|
||||||
.mapParallel(dispatcher) { computeIntermediate(it) }
|
.mapParallel(dispatcher) { computeIntermediate(it) }
|
||||||
.scanReduce(::composeIntermediate)
|
.runningReduce(::composeIntermediate)
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -57,7 +57,7 @@ private fun <T, I, R> ComposableStatistic<T, I, R>.flowIntermediate(
|
|||||||
*/
|
*/
|
||||||
@FlowPreview
|
@FlowPreview
|
||||||
@ExperimentalCoroutinesApi
|
@ExperimentalCoroutinesApi
|
||||||
fun <T, I, R> ComposableStatistic<T, I, R>.flow(
|
public fun <T, I, R> ComposableStatistic<T, I, R>.flow(
|
||||||
flow: Flow<Buffer<T>>,
|
flow: Flow<Buffer<T>>,
|
||||||
dispatcher: CoroutineDispatcher = Dispatchers.Default
|
dispatcher: CoroutineDispatcher = Dispatchers.Default
|
||||||
): Flow<R> = flowIntermediate(flow, dispatcher).map(::toResult)
|
): Flow<R> = flowIntermediate(flow, dispatcher).map(::toResult)
|
||||||
@ -65,32 +65,32 @@ fun <T, I, R> ComposableStatistic<T, I, R>.flow(
|
|||||||
/**
|
/**
|
||||||
* Arithmetic mean
|
* Arithmetic mean
|
||||||
*/
|
*/
|
||||||
class Mean<T>(val space: Space<T>) : ComposableStatistic<T, Pair<T, Int>, T> {
|
public class Mean<T>(public val space: Space<T>) : ComposableStatistic<T, Pair<T, Int>, T> {
|
||||||
override suspend fun computeIntermediate(data: Buffer<T>): Pair<T, Int> =
|
public override suspend fun computeIntermediate(data: Buffer<T>): Pair<T, Int> =
|
||||||
space { sum(data.asIterable()) } to data.size
|
space { sum(data.asIterable()) } to data.size
|
||||||
|
|
||||||
override suspend fun composeIntermediate(first: Pair<T, Int>, second: Pair<T, Int>): Pair<T, Int> =
|
public override suspend fun composeIntermediate(first: Pair<T, Int>, second: Pair<T, Int>): Pair<T, Int> =
|
||||||
space { first.first + second.first } to (first.second + second.second)
|
space { first.first + second.first } to (first.second + second.second)
|
||||||
|
|
||||||
override suspend fun toResult(intermediate: Pair<T, Int>): T =
|
public override suspend fun toResult(intermediate: Pair<T, Int>): T =
|
||||||
space { intermediate.first / intermediate.second }
|
space { intermediate.first / intermediate.second }
|
||||||
|
|
||||||
companion object {
|
public companion object {
|
||||||
//TODO replace with optimized version which respects overflow
|
//TODO replace with optimized version which respects overflow
|
||||||
val real: Mean<Double> = Mean(RealField)
|
public val real: Mean<Double> = Mean(RealField)
|
||||||
val int: Mean<Int> = Mean(IntRing)
|
public val int: Mean<Int> = Mean(IntRing)
|
||||||
val long: Mean<Long> = Mean(LongRing)
|
public val long: Mean<Long> = Mean(LongRing)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Non-composable median
|
* Non-composable median
|
||||||
*/
|
*/
|
||||||
class Median<T>(private val comparator: Comparator<T>) : Statistic<T, T> {
|
public class Median<T>(private val comparator: Comparator<T>) : Statistic<T, T> {
|
||||||
override suspend fun invoke(data: Buffer<T>): T =
|
public override suspend fun invoke(data: Buffer<T>): T =
|
||||||
data.asSequence().sortedWith(comparator).toList()[data.size / 2] //TODO check if this is correct
|
data.asSequence().sortedWith(comparator).toList()[data.size / 2] //TODO check if this is correct
|
||||||
|
|
||||||
companion object {
|
public companion object {
|
||||||
val real: Median<Double> = Median(Comparator { a: Double, b: Double -> a.compareTo(b) })
|
public val real: Median<Double> = Median { a: Double, b: Double -> a.compareTo(b) }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3,32 +3,20 @@ package scientifik.kmath.prob
|
|||||||
import scientifik.kmath.chains.Chain
|
import scientifik.kmath.chains.Chain
|
||||||
import scientifik.kmath.chains.SimpleChain
|
import scientifik.kmath.chains.SimpleChain
|
||||||
|
|
||||||
class UniformDistribution(val range: ClosedFloatingPointRange<Double>) : UnivariateDistribution<Double> {
|
public class UniformDistribution(public val range: ClosedFloatingPointRange<Double>) : UnivariateDistribution<Double> {
|
||||||
|
private val length: Double = range.endInclusive - range.start
|
||||||
|
|
||||||
private val length = range.endInclusive - range.start
|
override fun probability(arg: Double): Double = if (arg in range) 1.0 / length else 0.0
|
||||||
|
|
||||||
override fun probability(arg: Double): Double {
|
override fun sample(generator: RandomGenerator): Chain<Double> =
|
||||||
return if (arg in range) {
|
SimpleChain { range.start + generator.nextDouble() * length }
|
||||||
return 1.0 / length
|
|
||||||
} else {
|
|
||||||
0.0
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun sample(generator: RandomGenerator): Chain<Double> {
|
override fun cumulative(arg: Double): Double = when {
|
||||||
return SimpleChain {
|
|
||||||
range.start + generator.nextDouble() * length
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun cumulative(arg: Double): Double {
|
|
||||||
return when {
|
|
||||||
arg < range.start -> 0.0
|
arg < range.start -> 0.0
|
||||||
arg >= range.endInclusive -> 1.0
|
arg >= range.endInclusive -> 1.0
|
||||||
else -> (arg - range.start) / length
|
else -> (arg - range.start) / length
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
fun Distribution.Companion.uniform(range: ClosedFloatingPointRange<Double>): UniformDistribution =
|
public fun Distribution.Companion.uniform(range: ClosedFloatingPointRange<Double>): UniformDistribution =
|
||||||
UniformDistribution(range)
|
UniformDistribution(range)
|
@ -15,8 +15,8 @@ public abstract class ContinuousSamplerDistribution : Distribution<Double> {
|
|||||||
private inner class ContinuousSamplerChain(val generator: RandomGenerator) : BlockingRealChain() {
|
private inner class ContinuousSamplerChain(val generator: RandomGenerator) : BlockingRealChain() {
|
||||||
private val sampler = buildCMSampler(generator)
|
private val sampler = buildCMSampler(generator)
|
||||||
|
|
||||||
public override fun nextDouble(): Double = sampler.sample()
|
override fun nextDouble(): Double = sampler.sample()
|
||||||
public override fun fork(): Chain<Double> = ContinuousSamplerChain(generator.fork())
|
override fun fork(): Chain<Double> = ContinuousSamplerChain(generator.fork())
|
||||||
}
|
}
|
||||||
|
|
||||||
protected abstract fun buildCMSampler(generator: RandomGenerator): ContinuousSampler
|
protected abstract fun buildCMSampler(generator: RandomGenerator): ContinuousSampler
|
||||||
@ -28,8 +28,8 @@ public abstract class DiscreteSamplerDistribution : Distribution<Int> {
|
|||||||
private inner class ContinuousSamplerChain(val generator: RandomGenerator) : BlockingIntChain() {
|
private inner class ContinuousSamplerChain(val generator: RandomGenerator) : BlockingIntChain() {
|
||||||
private val sampler = buildSampler(generator)
|
private val sampler = buildSampler(generator)
|
||||||
|
|
||||||
public override fun nextInt(): Int = sampler.sample()
|
override fun nextInt(): Int = sampler.sample()
|
||||||
public override fun fork(): Chain<Int> = ContinuousSamplerChain(generator.fork())
|
override fun fork(): Chain<Int> = ContinuousSamplerChain(generator.fork())
|
||||||
}
|
}
|
||||||
|
|
||||||
protected abstract fun buildSampler(generator: RandomGenerator): DiscreteSampler
|
protected abstract fun buildSampler(generator: RandomGenerator): DiscreteSampler
|
||||||
@ -58,9 +58,7 @@ public fun Distribution.Companion.normal(
|
|||||||
return normalSampler(method, provider)
|
return normalSampler(method, provider)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun probability(arg: Double): Double {
|
override fun probability(arg: Double): Double = exp(-arg.pow(2) / 2) / sqrt(PI * 2)
|
||||||
return exp(-arg.pow(2) / 2) / sqrt(PI * 2)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public fun Distribution.Companion.normal(
|
public fun Distribution.Companion.normal(
|
||||||
|
@ -26,14 +26,12 @@ rootProject.name = "kmath"
|
|||||||
include(
|
include(
|
||||||
":kmath-memory",
|
":kmath-memory",
|
||||||
":kmath-core",
|
":kmath-core",
|
||||||
":kmath-functions",
|
// ":kmath-functions",
|
||||||
":kmath-coroutines",
|
":kmath-coroutines",
|
||||||
":kmath-histograms",
|
":kmath-histograms",
|
||||||
":kmath-commons",
|
":kmath-commons",
|
||||||
":kmath-viktor",
|
":kmath-viktor",
|
||||||
":kmath-koma",
|
|
||||||
":kmath-prob",
|
":kmath-prob",
|
||||||
":kmath-io",
|
|
||||||
":kmath-dimensions",
|
":kmath-dimensions",
|
||||||
":kmath-for-real",
|
":kmath-for-real",
|
||||||
":kmath-geometry",
|
":kmath-geometry",
|
||||||
|
Loading…
Reference in New Issue
Block a user