Merge branch 'dev' into feature/dynamic-ops-currying
This commit is contained in:
commit
0595950820
@ -14,6 +14,8 @@
|
|||||||
- Chi squared optimization for array-like data in CM
|
- Chi squared optimization for array-like data in CM
|
||||||
- `Fitting` utility object in prob/stat
|
- `Fitting` utility object in prob/stat
|
||||||
- ND4J support module submitting `NDStructure` and `NDAlgebra` over `INDArray`.
|
- ND4J support module submitting `NDStructure` and `NDAlgebra` over `INDArray`.
|
||||||
|
- Coroutine-deterministic Monte-Carlo scope with a random number generator.
|
||||||
|
- Some minor utilities to `kmath-for-real`.
|
||||||
|
|
||||||
### Changed
|
### Changed
|
||||||
- Package changed from `scientifik` to `kscience.kmath`.
|
- Package changed from `scientifik` to `kscience.kmath`.
|
||||||
@ -24,12 +26,14 @@
|
|||||||
- `kmath-ast` doesn't depend on heavy `kotlin-reflect` library.
|
- `kmath-ast` doesn't depend on heavy `kotlin-reflect` library.
|
||||||
- Full autodiff refactoring based on `Symbol`
|
- Full autodiff refactoring based on `Symbol`
|
||||||
- `kmath-prob` renamed to `kmath-stat`
|
- `kmath-prob` renamed to `kmath-stat`
|
||||||
|
- Grid generators moved to `kmath-for-real`
|
||||||
|
|
||||||
### Deprecated
|
### Deprecated
|
||||||
|
|
||||||
### Removed
|
### Removed
|
||||||
- `kmath-koma` module because it doesn't support Kotlin 1.4.
|
- `kmath-koma` module because it doesn't support Kotlin 1.4.
|
||||||
- Support of `legacy` JS backend (we will support only IR)
|
- Support of `legacy` JS backend (we will support only IR)
|
||||||
|
- `toGrid` method.
|
||||||
|
|
||||||
### Fixed
|
### Fixed
|
||||||
- `symbol` method in `MstExtendedField` (https://github.com/mipt-npm/kmath/pull/140)
|
- `symbol` method in `MstExtendedField` (https://github.com/mipt-npm/kmath/pull/140)
|
||||||
|
@ -4,7 +4,7 @@ plugins {
|
|||||||
id("ru.mipt.npm.project")
|
id("ru.mipt.npm.project")
|
||||||
}
|
}
|
||||||
|
|
||||||
internal val kmathVersion: String by extra("0.2.0-dev-3")
|
internal val kmathVersion: String by extra("0.2.0-dev-4")
|
||||||
internal val bintrayRepo: String by extra("kscience")
|
internal val bintrayRepo: String by extra("kscience")
|
||||||
internal val githubProject: String by extra("kmath")
|
internal val githubProject: String by extra("kmath")
|
||||||
|
|
||||||
|
@ -3,6 +3,7 @@ package kscience.kmath.expressions
|
|||||||
import kscience.kmath.operations.Algebra
|
import kscience.kmath.operations.Algebra
|
||||||
import kotlin.jvm.JvmName
|
import kotlin.jvm.JvmName
|
||||||
import kotlin.properties.ReadOnlyProperty
|
import kotlin.properties.ReadOnlyProperty
|
||||||
|
import kotlin.reflect.KProperty
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A marker interface for a symbol. A symbol mus have an identity
|
* A marker interface for a symbol. A symbol mus have an identity
|
||||||
@ -12,6 +13,13 @@ public interface Symbol {
|
|||||||
* Identity object for the symbol. Two symbols with the same identity are considered to be the same symbol.
|
* Identity object for the symbol. Two symbols with the same identity are considered to be the same symbol.
|
||||||
*/
|
*/
|
||||||
public val identity: String
|
public val identity: String
|
||||||
|
|
||||||
|
public companion object : ReadOnlyProperty<Any?, Symbol> {
|
||||||
|
//TODO deprecate and replace by top level function after fix of https://youtrack.jetbrains.com/issue/KT-40121
|
||||||
|
override fun getValue(thisRef: Any?, property: KProperty<*>): Symbol {
|
||||||
|
return StringSymbol(property.name)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -95,9 +103,9 @@ public fun <T, E> ExpressionAlgebra<T, E>.bind(symbol: Symbol): E =
|
|||||||
/**
|
/**
|
||||||
* A delegate to create a symbol with a string identity in this scope
|
* A delegate to create a symbol with a string identity in this scope
|
||||||
*/
|
*/
|
||||||
public val symbol: ReadOnlyProperty<Any?, StringSymbol> = ReadOnlyProperty { _, property ->
|
public val symbol: ReadOnlyProperty<Any?, Symbol> get() = Symbol
|
||||||
StringSymbol(property.name)
|
//TODO does not work directly on native due to https://youtrack.jetbrains.com/issue/KT-40121
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Bind a symbol by name inside the [ExpressionAlgebra]
|
* Bind a symbol by name inside the [ExpressionAlgebra]
|
||||||
|
@ -5,19 +5,19 @@ package kscience.kmath.structures
|
|||||||
*
|
*
|
||||||
* @property array the underlying array.
|
* @property array the underlying array.
|
||||||
*/
|
*/
|
||||||
|
@Suppress("OVERRIDE_BY_INLINE")
|
||||||
public inline class RealBuffer(public val array: DoubleArray) : MutableBuffer<Double> {
|
public inline class RealBuffer(public val array: DoubleArray) : MutableBuffer<Double> {
|
||||||
override val size: Int get() = array.size
|
override val size: Int get() = array.size
|
||||||
|
|
||||||
override operator fun get(index: Int): Double = array[index]
|
override inline operator fun get(index: Int): Double = array[index]
|
||||||
|
|
||||||
override operator fun set(index: Int, value: Double) {
|
override inline operator fun set(index: Int, value: Double) {
|
||||||
array[index] = value
|
array[index] = value
|
||||||
}
|
}
|
||||||
|
|
||||||
override operator fun iterator(): DoubleIterator = array.iterator()
|
override operator fun iterator(): DoubleIterator = array.iterator()
|
||||||
|
|
||||||
override fun copy(): MutableBuffer<Double> =
|
override fun copy(): RealBuffer = RealBuffer(array.copyOf())
|
||||||
RealBuffer(array.copyOf())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -34,6 +34,11 @@ public inline fun RealBuffer(size: Int, init: (Int) -> Double): RealBuffer = Rea
|
|||||||
*/
|
*/
|
||||||
public fun RealBuffer(vararg doubles: Double): RealBuffer = RealBuffer(doubles)
|
public fun RealBuffer(vararg doubles: Double): RealBuffer = RealBuffer(doubles)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Simplified [RealBuffer] to array comparison
|
||||||
|
*/
|
||||||
|
public fun RealBuffer.contentEquals(vararg doubles: Double): Boolean = array.contentEquals(doubles)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns a [DoubleArray] containing all of the elements of this [MutableBuffer].
|
* Returns a [DoubleArray] containing all of the elements of this [MutableBuffer].
|
||||||
*/
|
*/
|
||||||
|
@ -14,8 +14,9 @@ import kotlin.math.sqrt
|
|||||||
|
|
||||||
public typealias RealPoint = Point<Double>
|
public typealias RealPoint = Point<Double>
|
||||||
|
|
||||||
public fun DoubleArray.asVector(): RealVector = RealVector(asBuffer())
|
public fun RealPoint.asVector(): RealVector = RealVector(this)
|
||||||
public fun List<Double>.asVector(): RealVector = RealVector(asBuffer())
|
public fun DoubleArray.asVector(): RealVector = asBuffer().asVector()
|
||||||
|
public fun List<Double>.asVector(): RealVector = asBuffer().asVector()
|
||||||
|
|
||||||
public object VectorL2Norm : Norm<Point<out Number>, Double> {
|
public object VectorL2Norm : Norm<Point<out Number>, Double> {
|
||||||
override fun norm(arg: Point<out Number>): Double = sqrt(arg.asIterable().sumByDouble(Number::toDouble))
|
override fun norm(arg: Point<out Number>): Double = sqrt(arg.asIterable().sumByDouble(Number::toDouble))
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
package kscience.kmath.misc
|
package kscience.kmath.real
|
||||||
|
|
||||||
|
import kscience.kmath.linear.Point
|
||||||
|
import kscience.kmath.structures.asBuffer
|
||||||
import kotlin.math.abs
|
import kotlin.math.abs
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -32,6 +34,9 @@ public fun ClosedFloatingPointRange<Double>.toSequenceWithStep(step: Double): Se
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public infix fun ClosedFloatingPointRange<Double>.step(step: Double): Point<Double> =
|
||||||
|
toSequenceWithStep(step).toList().asBuffer()
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Convert double range to sequence with the fixed number of points
|
* Convert double range to sequence with the fixed number of points
|
||||||
*/
|
*/
|
||||||
@ -39,12 +44,3 @@ public fun ClosedFloatingPointRange<Double>.toSequenceWithPoints(numPoints: Int)
|
|||||||
require(numPoints > 1) { "The number of points should be more than 2" }
|
require(numPoints > 1) { "The number of points should be more than 2" }
|
||||||
return toSequenceWithStep(abs(endInclusive - start) / (numPoints - 1))
|
return toSequenceWithStep(abs(endInclusive - start) / (numPoints - 1))
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Convert double range to array of evenly spaced doubles, where the size of array equals [numPoints]
|
|
||||||
*/
|
|
||||||
@Deprecated("Replace by 'toSequenceWithPoints'")
|
|
||||||
public fun ClosedFloatingPointRange<Double>.toGrid(numPoints: Int): DoubleArray {
|
|
||||||
require(numPoints >= 2) { "Can't create generic grid with less than two points" }
|
|
||||||
return DoubleArray(numPoints) { i -> start + (endInclusive - start) / (numPoints - 1) * i }
|
|
||||||
}
|
|
@ -1,8 +0,0 @@
|
|||||||
package kscience.kmath.real
|
|
||||||
|
|
||||||
import kscience.kmath.structures.RealBuffer
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Simplified [RealBuffer] to array comparison
|
|
||||||
*/
|
|
||||||
public fun RealBuffer.contentEquals(vararg doubles: Double): Boolean = array.contentEquals(doubles)
|
|
@ -0,0 +1,13 @@
|
|||||||
|
package kaceince.kmath.real
|
||||||
|
|
||||||
|
import kscience.kmath.real.step
|
||||||
|
import kotlin.test.Test
|
||||||
|
import kotlin.test.assertEquals
|
||||||
|
|
||||||
|
class GridTest {
|
||||||
|
@Test
|
||||||
|
fun testStepGrid(){
|
||||||
|
val grid = 0.0..1.0 step 0.2
|
||||||
|
assertEquals(6, grid.size)
|
||||||
|
}
|
||||||
|
}
|
@ -1,9 +1,10 @@
|
|||||||
package scientific.kmath.real
|
package kaceince.kmath.real
|
||||||
|
|
||||||
import kscience.kmath.linear.VirtualMatrix
|
import kscience.kmath.linear.VirtualMatrix
|
||||||
import kscience.kmath.linear.build
|
import kscience.kmath.linear.build
|
||||||
import kscience.kmath.real.*
|
import kscience.kmath.real.*
|
||||||
import kscience.kmath.structures.Matrix
|
import kscience.kmath.structures.Matrix
|
||||||
|
import kscience.kmath.structures.contentEquals
|
||||||
import kotlin.test.Test
|
import kotlin.test.Test
|
||||||
import kotlin.test.assertEquals
|
import kotlin.test.assertEquals
|
||||||
import kotlin.test.assertTrue
|
import kotlin.test.assertTrue
|
@ -1,11 +1,14 @@
|
|||||||
package kscience.kmath.linear
|
package kaceince.kmath.real
|
||||||
|
|
||||||
|
import kscience.kmath.linear.MatrixContext
|
||||||
|
import kscience.kmath.linear.asMatrix
|
||||||
|
import kscience.kmath.linear.transpose
|
||||||
import kscience.kmath.operations.invoke
|
import kscience.kmath.operations.invoke
|
||||||
import kscience.kmath.real.RealVector
|
import kscience.kmath.real.RealVector
|
||||||
import kotlin.test.Test
|
import kotlin.test.Test
|
||||||
import kotlin.test.assertEquals
|
import kotlin.test.assertEquals
|
||||||
|
|
||||||
internal class VectorTest {
|
internal class RealVectorTest {
|
||||||
@Test
|
@Test
|
||||||
fun testSum() {
|
fun testSum() {
|
||||||
val vector1 = RealVector(5) { it.toDouble() }
|
val vector1 = RealVector(5) { it.toDouble() }
|
@ -0,0 +1,58 @@
|
|||||||
|
package kscience.kmath.stat
|
||||||
|
|
||||||
|
import kotlinx.coroutines.*
|
||||||
|
import kotlin.coroutines.CoroutineContext
|
||||||
|
import kotlin.coroutines.EmptyCoroutineContext
|
||||||
|
import kotlin.coroutines.coroutineContext
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A scope for a Monte-Carlo computations or multi-coroutine random number generation.
|
||||||
|
* The scope preserves the order of random generator calls as long as all concurrency calls is done via [launch] and [async]
|
||||||
|
* functions.
|
||||||
|
*/
|
||||||
|
public class MCScope(
|
||||||
|
public val coroutineContext: CoroutineContext,
|
||||||
|
public val random: RandomGenerator,
|
||||||
|
)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Launches a supervised Monte-Carlo scope
|
||||||
|
*/
|
||||||
|
public suspend inline fun <T> mcScope(generator: RandomGenerator, block: MCScope.() -> T): T =
|
||||||
|
MCScope(coroutineContext, generator).block()
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Launch mc scope with a given seed
|
||||||
|
*/
|
||||||
|
public suspend inline fun <T> mcScope(seed: Long, block: MCScope.() -> T): T =
|
||||||
|
mcScope(RandomGenerator.default(seed), block)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Specialized launch for [MCScope]. Behaves the same way as regular [CoroutineScope.launch], but also stores the generator fork.
|
||||||
|
* The method itself is not thread safe.
|
||||||
|
*/
|
||||||
|
public inline fun MCScope.launch(
|
||||||
|
context: CoroutineContext = EmptyCoroutineContext,
|
||||||
|
start: CoroutineStart = CoroutineStart.DEFAULT,
|
||||||
|
crossinline block: suspend MCScope.() -> Unit,
|
||||||
|
): Job {
|
||||||
|
val newRandom = random.fork()
|
||||||
|
return CoroutineScope(coroutineContext).launch(context, start) {
|
||||||
|
MCScope(coroutineContext, newRandom).block()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Specialized async for [MCScope]. Behaves the same way as regular [CoroutineScope.async], but also stores the generator fork.
|
||||||
|
* The method itself is not thread safe.
|
||||||
|
*/
|
||||||
|
public inline fun <T> MCScope.async(
|
||||||
|
context: CoroutineContext = EmptyCoroutineContext,
|
||||||
|
start: CoroutineStart = CoroutineStart.DEFAULT,
|
||||||
|
crossinline block: suspend MCScope.() -> T,
|
||||||
|
): Deferred<T> {
|
||||||
|
val newRandom = random.fork()
|
||||||
|
return CoroutineScope(coroutineContext).async(context, start) {
|
||||||
|
MCScope(coroutineContext, newRandom).block()
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,85 @@
|
|||||||
|
package kscience.kmath.stat
|
||||||
|
|
||||||
|
import kotlinx.coroutines.*
|
||||||
|
import java.util.*
|
||||||
|
import kotlin.collections.HashSet
|
||||||
|
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>
|
||||||
|
|
||||||
|
class MCScopeTest {
|
||||||
|
val simpleTest: ATest = {
|
||||||
|
mcScope(1111) {
|
||||||
|
val res = Collections.synchronizedSet(HashSet<RandomResult>())
|
||||||
|
|
||||||
|
launch {
|
||||||
|
//println(random)
|
||||||
|
repeat(10) {
|
||||||
|
delay(10)
|
||||||
|
res.add(RandomResult("first", it, random.nextInt()))
|
||||||
|
}
|
||||||
|
launch {
|
||||||
|
//empty fork
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
launch {
|
||||||
|
//println(random)
|
||||||
|
repeat(10) {
|
||||||
|
delay(10)
|
||||||
|
res.add(RandomResult("second", it, random.nextInt()))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
res
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
val testWithJoin: ATest = {
|
||||||
|
mcScope(1111) {
|
||||||
|
val res = Collections.synchronizedSet(HashSet<RandomResult>())
|
||||||
|
|
||||||
|
val job = launch {
|
||||||
|
repeat(10) {
|
||||||
|
delay(10)
|
||||||
|
res.add(RandomResult("first", it, random.nextInt()))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
launch {
|
||||||
|
repeat(10) {
|
||||||
|
delay(10)
|
||||||
|
if (it == 4) job.join()
|
||||||
|
res.add(RandomResult("second", it, random.nextInt()))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
res
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
fun compareResult(test: ATest) {
|
||||||
|
val res1 = runBlocking(Dispatchers.Default) { test() }
|
||||||
|
val res2 = runBlocking(newSingleThreadContext("test")) { test() }
|
||||||
|
assertEquals(
|
||||||
|
res1.find { it.branch == "first" && it.order == 7 }?.value,
|
||||||
|
res2.find { it.branch == "first" && it.order == 7 }?.value
|
||||||
|
)
|
||||||
|
assertEquals(res1, res2)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun testParallel() {
|
||||||
|
compareResult(simpleTest)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun testConditionalJoin() {
|
||||||
|
compareResult(testWithJoin)
|
||||||
|
}
|
||||||
|
}
|
@ -8,8 +8,8 @@ pluginManagement {
|
|||||||
maven("https://dl.bintray.com/kotlin/kotlinx")
|
maven("https://dl.bintray.com/kotlin/kotlinx")
|
||||||
}
|
}
|
||||||
|
|
||||||
val toolsVersion = "0.6.4-dev-1.4.20-M2"
|
val toolsVersion = "0.7.0"
|
||||||
val kotlinVersion = "1.4.20-M2"
|
val kotlinVersion = "1.4.20"
|
||||||
|
|
||||||
plugins {
|
plugins {
|
||||||
id("kotlinx.benchmark") version "0.2.0-dev-20"
|
id("kotlinx.benchmark") version "0.2.0-dev-20"
|
||||||
@ -17,7 +17,7 @@ pluginManagement {
|
|||||||
id("ru.mipt.npm.mpp") version toolsVersion
|
id("ru.mipt.npm.mpp") version toolsVersion
|
||||||
id("ru.mipt.npm.jvm") version toolsVersion
|
id("ru.mipt.npm.jvm") version toolsVersion
|
||||||
id("ru.mipt.npm.publish") version toolsVersion
|
id("ru.mipt.npm.publish") version toolsVersion
|
||||||
kotlin("jvm") version kotlinVersion
|
kotlin("jvm") version kotlinVersion
|
||||||
kotlin("plugin.allopen") version kotlinVersion
|
kotlin("plugin.allopen") version kotlinVersion
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user