KMP library for tensors #300
@ -13,6 +13,7 @@
|
|||||||
- Buffer factories for primitives moved to MutableBuffer.Companion
|
- Buffer factories for primitives moved to MutableBuffer.Companion
|
||||||
- NDStructure and NDAlgebra to StructureND and AlgebraND respectively
|
- NDStructure and NDAlgebra to StructureND and AlgebraND respectively
|
||||||
- Real -> Double
|
- Real -> Double
|
||||||
|
- DataSets are moved from functions to core
|
||||||
|
|
||||||
### Deprecated
|
### Deprecated
|
||||||
|
|
||||||
|
11
README.md
11
README.md
@ -1,9 +1,8 @@
|
|||||||
[![JetBrains Research](https://jb.gg/badges/research.svg)](https://confluence.jetbrains.com/display/ALL/JetBrains+on+GitHub)
|
[![JetBrains Research](https://jb.gg/badges/research.svg)](https://confluence.jetbrains.com/display/ALL/JetBrains+on+GitHub)
|
||||||
[![DOI](https://zenodo.org/badge/129486382.svg)](https://zenodo.org/badge/latestdoi/129486382)
|
[![DOI](https://zenodo.org/badge/129486382.svg)](https://zenodo.org/badge/latestdoi/129486382)
|
||||||
|
|
||||||
![Gradle build](https://github.com/mipt-npm/kmath/workflows/Gradle%20build/badge.svg)
|
![Gradle build](https://github.com/mipt-npm/kmath/workflows/Gradle%20build/badge.svg)
|
||||||
|
[![Maven Central](https://img.shields.io/maven-central/v/space.kscience/kmath-core.svg?label=Maven%20Central)](https://search.maven.org/search?q=g:%22space.kscience%22)
|
||||||
[![Maven Central](https://img.shields.io/maven-central/v/space.kscience/kmath-core.svg?label=Maven%20Central)](https://search.maven.org/search?q=g:%22space.kscience%22%20AND%20a:%22kmath-core%22)
|
[![Space](https://img.shields.io/maven-metadata/v?label=Space&metadataUrl=https%3A%2F%2Fmaven.pkg.jetbrains.space%2Fmipt-npm%2Fp%2Fsci%2Fmaven%2Fkscience%2Fkmath%2Fkmath-core%2Fmaven-metadata.xml)](https://maven.pkg.jetbrains.space/mipt-npm/p/sci/maven/space/kscience/)
|
||||||
|
|
||||||
# KMath
|
# KMath
|
||||||
|
|
||||||
@ -147,6 +146,12 @@ performance calculations to code generation.
|
|||||||
>
|
>
|
||||||
>
|
>
|
||||||
> **Maturity**: PROTOTYPE
|
> **Maturity**: PROTOTYPE
|
||||||
|
>
|
||||||
|
> **Features:**
|
||||||
|
> - [ejml-vector](kmath-ejml/src/main/kotlin/space/kscience/kmath/ejml/EjmlVector.kt) : The Point implementation using SimpleMatrix.
|
||||||
|
> - [ejml-matrix](kmath-ejml/src/main/kotlin/space/kscience/kmath/ejml/EjmlMatrix.kt) : The Matrix implementation using SimpleMatrix.
|
||||||
|
> - [ejml-linear-space](kmath-ejml/src/main/kotlin/space/kscience/kmath/ejml/EjmlLinearSpace.kt) : The LinearSpace implementation using SimpleMatrix.
|
||||||
|
|
||||||
<hr/>
|
<hr/>
|
||||||
|
|
||||||
* ### [kmath-for-real](kmath-for-real)
|
* ### [kmath-for-real](kmath-for-real)
|
||||||
|
@ -1,4 +1,6 @@
|
|||||||
|
import org.jetbrains.dokka.gradle.DokkaTask
|
||||||
import ru.mipt.npm.gradle.KSciencePublishingPlugin
|
import ru.mipt.npm.gradle.KSciencePublishingPlugin
|
||||||
|
import java.net.URL
|
||||||
|
|
||||||
plugins {
|
plugins {
|
||||||
id("ru.mipt.npm.gradle.project")
|
id("ru.mipt.npm.gradle.project")
|
||||||
@ -10,21 +12,38 @@ allprojects {
|
|||||||
maven("https://clojars.org/repo")
|
maven("https://clojars.org/repo")
|
||||||
maven("https://dl.bintray.com/egor-bogomolov/astminer/")
|
maven("https://dl.bintray.com/egor-bogomolov/astminer/")
|
||||||
maven("https://dl.bintray.com/hotkeytlt/maven")
|
maven("https://dl.bintray.com/hotkeytlt/maven")
|
||||||
maven("https://dl.bintray.com/kotlin/kotlin-eap")
|
|
||||||
maven("https://dl.bintray.com/kotlin/kotlinx")
|
|
||||||
maven("https://dl.bintray.com/mipt-npm/dev")
|
|
||||||
maven("https://dl.bintray.com/mipt-npm/kscience")
|
|
||||||
maven("https://jitpack.io")
|
maven("https://jitpack.io")
|
||||||
maven("http://logicrunch.research.it.uu.se/maven/")
|
maven("http://logicrunch.research.it.uu.se/maven/")
|
||||||
mavenCentral()
|
mavenCentral()
|
||||||
}
|
}
|
||||||
|
|
||||||
group = "space.kscience"
|
group = "space.kscience"
|
||||||
version = "0.3.0-dev-3"
|
version = "0.3.0-dev-4"
|
||||||
}
|
}
|
||||||
|
|
||||||
subprojects {
|
subprojects {
|
||||||
if (name.startsWith("kmath")) apply<KSciencePublishingPlugin>()
|
if (name.startsWith("kmath")) apply<KSciencePublishingPlugin>()
|
||||||
|
|
||||||
|
afterEvaluate {
|
||||||
|
tasks.withType<DokkaTask> {
|
||||||
|
dokkaSourceSets.all {
|
||||||
|
val readmeFile = File(this@subprojects.projectDir, "./README.md")
|
||||||
|
if (readmeFile.exists())
|
||||||
|
includes.setFrom(includes + readmeFile.absolutePath)
|
||||||
|
|
||||||
|
arrayOf(
|
||||||
|
"http://ejml.org/javadoc/",
|
||||||
|
"https://commons.apache.org/proper/commons-math/javadocs/api-3.6.1/",
|
||||||
|
"https://deeplearning4j.org/api/latest/"
|
||||||
|
).map { URL("${it}package-list") to URL(it) }.forEach { (a, b) ->
|
||||||
|
externalDocumentationLink {
|
||||||
|
packageListUrl.set(a)
|
||||||
|
url.set(b)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
readme {
|
readme {
|
||||||
|
62
docs/templates/ARTIFACT-TEMPLATE.md
vendored
62
docs/templates/ARTIFACT-TEMPLATE.md
vendored
@ -1,34 +1,28 @@
|
|||||||
> #### Artifact:
|
## Artifact:
|
||||||
>
|
|
||||||
> This module artifact: `${group}:${name}:${version}`.
|
The Maven coordinates of this project are `${group}:${name}:${version}`.
|
||||||
>
|
|
||||||
> Bintray release version: [ ![Download](https://api.bintray.com/packages/mipt-npm/kscience/${name}/images/download.svg) ](https://bintray.com/mipt-npm/kscience/${name}/_latestVersion)
|
**Gradle:**
|
||||||
>
|
```gradle
|
||||||
> Bintray development version: [ ![Download](https://api.bintray.com/packages/mipt-npm/dev/${name}/images/download.svg) ](https://bintray.com/mipt-npm/dev/${name}/_latestVersion)
|
repositories {
|
||||||
>
|
maven { url 'https://repo.kotlin.link' }
|
||||||
> **Gradle:**
|
maven { url 'https://dl.bintray.com/hotkeytlt/maven' }
|
||||||
>
|
maven { url "https://dl.bintray.com/kotlin/kotlin-eap" } // include for builds based on kotlin-eap
|
||||||
> ```gradle
|
}
|
||||||
> repositories {
|
|
||||||
> maven { url 'https://repo.kotlin.link' }
|
dependencies {
|
||||||
> maven { url 'https://dl.bintray.com/hotkeytlt/maven' }
|
implementation '${group}:${name}:${version}'
|
||||||
> maven { url "https://dl.bintray.com/kotlin/kotlin-eap" } // include for builds based on kotlin-eap
|
}
|
||||||
> }
|
```
|
||||||
>
|
**Gradle Kotlin DSL:**
|
||||||
> dependencies {
|
```kotlin
|
||||||
> implementation '${group}:${name}:${version}'
|
repositories {
|
||||||
> }
|
maven("https://repo.kotlin.link")
|
||||||
> ```
|
maven("https://dl.bintray.com/kotlin/kotlin-eap") // include for builds based on kotlin-eap
|
||||||
> **Gradle Kotlin DSL:**
|
maven("https://dl.bintray.com/hotkeytlt/maven") // required for a
|
||||||
>
|
}
|
||||||
> ```kotlin
|
|
||||||
> repositories {
|
dependencies {
|
||||||
> maven("https://repo.kotlin.link")
|
implementation("${group}:${name}:${version}")
|
||||||
> maven("https://dl.bintray.com/kotlin/kotlin-eap") // include for builds based on kotlin-eap
|
}
|
||||||
> maven("https://dl.bintray.com/hotkeytlt/maven") // required for a
|
```
|
||||||
> }
|
|
||||||
>
|
|
||||||
> dependencies {
|
|
||||||
> implementation("${group}:${name}:${version}")
|
|
||||||
> }
|
|
||||||
> ```
|
|
5
docs/templates/README-TEMPLATE.md
vendored
5
docs/templates/README-TEMPLATE.md
vendored
@ -1,9 +1,8 @@
|
|||||||
[![JetBrains Research](https://jb.gg/badges/research.svg)](https://confluence.jetbrains.com/display/ALL/JetBrains+on+GitHub)
|
[![JetBrains Research](https://jb.gg/badges/research.svg)](https://confluence.jetbrains.com/display/ALL/JetBrains+on+GitHub)
|
||||||
[![DOI](https://zenodo.org/badge/129486382.svg)](https://zenodo.org/badge/latestdoi/129486382)
|
[![DOI](https://zenodo.org/badge/129486382.svg)](https://zenodo.org/badge/latestdoi/129486382)
|
||||||
|
|
||||||
![Gradle build](https://github.com/mipt-npm/kmath/workflows/Gradle%20build/badge.svg)
|
![Gradle build](https://github.com/mipt-npm/kmath/workflows/Gradle%20build/badge.svg)
|
||||||
|
[![Maven Central](https://img.shields.io/maven-central/v/space.kscience/kmath-core.svg?label=Maven%20Central)](https://search.maven.org/search?q=g:%22space.kscience%22)
|
||||||
[![Maven Central](https://img.shields.io/maven-central/v/space.kscience/kmath-core.svg?label=Maven%20Central)](https://search.maven.org/search?q=g:%22space.kscience%22%20AND%20a:%22kmath-core%22)
|
[![Space](https://img.shields.io/maven-metadata/v?label=Space&metadataUrl=https%3A%2F%2Fmaven.pkg.jetbrains.space%2Fmipt-npm%2Fp%2Fsci%2Fmaven%2Fkscience%2Fkmath%2Fkmath-core%2Fmaven-metadata.xml)](https://maven.pkg.jetbrains.space/mipt-npm/p/sci/maven/space/kscience/)
|
||||||
|
|
||||||
# KMath
|
# KMath
|
||||||
|
|
||||||
|
@ -106,6 +106,7 @@ kotlin.sourceSets.all {
|
|||||||
with(languageSettings) {
|
with(languageSettings) {
|
||||||
useExperimentalAnnotation("kotlin.contracts.ExperimentalContracts")
|
useExperimentalAnnotation("kotlin.contracts.ExperimentalContracts")
|
||||||
useExperimentalAnnotation("kotlin.ExperimentalUnsignedTypes")
|
useExperimentalAnnotation("kotlin.ExperimentalUnsignedTypes")
|
||||||
|
useExperimentalAnnotation("space.kscience.kmath.misc.UnstableKMathAPI")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -9,7 +9,7 @@ import space.kscience.kmath.ast.mstInField
|
|||||||
import space.kscience.kmath.expressions.Expression
|
import space.kscience.kmath.expressions.Expression
|
||||||
import space.kscience.kmath.expressions.expressionInField
|
import space.kscience.kmath.expressions.expressionInField
|
||||||
import space.kscience.kmath.expressions.invoke
|
import space.kscience.kmath.expressions.invoke
|
||||||
import space.kscience.kmath.expressions.symbol
|
import space.kscience.kmath.misc.symbol
|
||||||
import space.kscience.kmath.operations.DoubleField
|
import space.kscience.kmath.operations.DoubleField
|
||||||
import space.kscience.kmath.operations.bindSymbol
|
import space.kscience.kmath.operations.bindSymbol
|
||||||
import kotlin.random.Random
|
import kotlin.random.Random
|
||||||
|
@ -3,8 +3,8 @@ package space.kscience.kmath.ast
|
|||||||
import space.kscience.kmath.asm.compile
|
import space.kscience.kmath.asm.compile
|
||||||
import space.kscience.kmath.expressions.derivative
|
import space.kscience.kmath.expressions.derivative
|
||||||
import space.kscience.kmath.expressions.invoke
|
import space.kscience.kmath.expressions.invoke
|
||||||
import space.kscience.kmath.expressions.symbol
|
|
||||||
import space.kscience.kmath.kotlingrad.differentiable
|
import space.kscience.kmath.kotlingrad.differentiable
|
||||||
|
import space.kscience.kmath.misc.symbol
|
||||||
import space.kscience.kmath.operations.DoubleField
|
import space.kscience.kmath.operations.DoubleField
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -7,11 +7,14 @@ import kscience.plotly.models.ScatterMode
|
|||||||
import kscience.plotly.models.TraceValues
|
import kscience.plotly.models.TraceValues
|
||||||
import space.kscience.kmath.commons.optimization.chiSquared
|
import space.kscience.kmath.commons.optimization.chiSquared
|
||||||
import space.kscience.kmath.commons.optimization.minimize
|
import space.kscience.kmath.commons.optimization.minimize
|
||||||
import space.kscience.kmath.expressions.symbol
|
import space.kscience.kmath.misc.symbol
|
||||||
|
import space.kscience.kmath.optimization.FunctionOptimization
|
||||||
|
import space.kscience.kmath.optimization.OptimizationResult
|
||||||
import space.kscience.kmath.real.DoubleVector
|
import space.kscience.kmath.real.DoubleVector
|
||||||
import space.kscience.kmath.real.map
|
import space.kscience.kmath.real.map
|
||||||
import space.kscience.kmath.real.step
|
import space.kscience.kmath.real.step
|
||||||
import space.kscience.kmath.stat.*
|
import space.kscience.kmath.stat.RandomGenerator
|
||||||
|
import space.kscience.kmath.stat.distributions.NormalDistribution
|
||||||
import space.kscience.kmath.structures.asIterable
|
import space.kscience.kmath.structures.asIterable
|
||||||
import space.kscience.kmath.structures.toList
|
import space.kscience.kmath.structures.toList
|
||||||
import kotlin.math.pow
|
import kotlin.math.pow
|
||||||
@ -33,10 +36,9 @@ operator fun TraceValues.invoke(vector: DoubleVector) {
|
|||||||
/**
|
/**
|
||||||
* Least squares fie with auto-differentiation. Uses `kmath-commons` and `kmath-for-real` modules.
|
* Least squares fie with auto-differentiation. Uses `kmath-commons` and `kmath-for-real` modules.
|
||||||
*/
|
*/
|
||||||
fun main() {
|
suspend fun main() {
|
||||||
|
|
||||||
//A generator for a normally distributed values
|
//A generator for a normally distributed values
|
||||||
val generator = Distribution.normal()
|
val generator = NormalDistribution(2.0, 7.0)
|
||||||
|
|
||||||
//A chain/flow of random values with the given seed
|
//A chain/flow of random values with the given seed
|
||||||
val chain = generator.sample(RandomGenerator.default(112667))
|
val chain = generator.sample(RandomGenerator.default(112667))
|
||||||
@ -49,7 +51,7 @@ fun main() {
|
|||||||
//Perform an operation on each x value (much more effective, than numpy)
|
//Perform an operation on each x value (much more effective, than numpy)
|
||||||
val y = x.map {
|
val y = x.map {
|
||||||
val value = it.pow(2) + it + 1
|
val value = it.pow(2) + it + 1
|
||||||
value + chain.nextDouble() * sqrt(value)
|
value + chain.next() * sqrt(value)
|
||||||
}
|
}
|
||||||
// this will also work, but less effective:
|
// this will also work, but less effective:
|
||||||
// val y = x.pow(2)+ x + 1 + chain.nextDouble()
|
// val y = x.pow(2)+ x + 1 + chain.nextDouble()
|
||||||
@ -58,7 +60,7 @@ fun main() {
|
|||||||
val yErr = y.map { sqrt(it) }//RealVector.same(x.size, sigma)
|
val yErr = y.map { sqrt(it) }//RealVector.same(x.size, sigma)
|
||||||
|
|
||||||
// compute differentiable chi^2 sum for given model ax^2 + bx + c
|
// compute differentiable chi^2 sum for given model ax^2 + bx + c
|
||||||
val chi2 = Fitting.chiSquared(x, y, yErr) { x1 ->
|
val chi2 = FunctionOptimization.chiSquared(x, y, yErr) { x1 ->
|
||||||
//bind variables to autodiff context
|
//bind variables to autodiff context
|
||||||
val a = bind(a)
|
val a = bind(a)
|
||||||
val b = bind(b)
|
val b = bind(b)
|
||||||
|
@ -1,23 +1,24 @@
|
|||||||
package kscience.kmath.commons.prob
|
package space.kscience.kmath.stat
|
||||||
|
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
import kotlinx.coroutines.async
|
import kotlinx.coroutines.async
|
||||||
import kotlinx.coroutines.runBlocking
|
import kotlinx.coroutines.runBlocking
|
||||||
import org.apache.commons.rng.sampling.distribution.ZigguratNormalizedGaussianSampler
|
import space.kscience.kmath.stat.samplers.GaussianSampler
|
||||||
import org.apache.commons.rng.simple.RandomSource
|
import org.apache.commons.rng.simple.RandomSource
|
||||||
import space.kscience.kmath.stat.*
|
|
||||||
import java.time.Duration
|
import java.time.Duration
|
||||||
import java.time.Instant
|
import java.time.Instant
|
||||||
|
import org.apache.commons.rng.sampling.distribution.GaussianSampler as CMGaussianSampler
|
||||||
|
import org.apache.commons.rng.sampling.distribution.ZigguratNormalizedGaussianSampler as CMZigguratNormalizedGaussianSampler
|
||||||
|
|
||||||
private fun runChain(): Duration {
|
private suspend fun runKMathChained(): Duration {
|
||||||
val generator = RandomGenerator.fromSource(RandomSource.MT, 123L)
|
val generator = RandomGenerator.fromSource(RandomSource.MT, 123L)
|
||||||
val normal = Distribution.normal(NormalSamplerMethod.Ziggurat)
|
val normal = GaussianSampler.of(7.0, 2.0)
|
||||||
val chain = normal.sample(generator)
|
val chain = normal.sample(generator).blocking()
|
||||||
val startTime = Instant.now()
|
val startTime = Instant.now()
|
||||||
var sum = 0.0
|
var sum = 0.0
|
||||||
|
|
||||||
repeat(10000001) { counter ->
|
repeat(10000001) { counter ->
|
||||||
sum += chain.nextDouble()
|
sum += chain.next()
|
||||||
|
|
||||||
if (counter % 100000 == 0) {
|
if (counter % 100000 == 0) {
|
||||||
val duration = Duration.between(startTime, Instant.now())
|
val duration = Duration.between(startTime, Instant.now())
|
||||||
@ -29,9 +30,15 @@ private fun runChain(): Duration {
|
|||||||
return Duration.between(startTime, Instant.now())
|
return Duration.between(startTime, Instant.now())
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun runDirect(): Duration {
|
private fun runApacheDirect(): Duration {
|
||||||
val provider = RandomSource.create(RandomSource.MT, 123L)
|
val rng = RandomSource.create(RandomSource.MT, 123L)
|
||||||
val sampler = ZigguratNormalizedGaussianSampler(provider)
|
|
||||||
|
val sampler = CMGaussianSampler.of(
|
||||||
|
CMZigguratNormalizedGaussianSampler.of(rng),
|
||||||
|
7.0,
|
||||||
|
2.0
|
||||||
|
)
|
||||||
|
|
||||||
val startTime = Instant.now()
|
val startTime = Instant.now()
|
||||||
var sum = 0.0
|
var sum = 0.0
|
||||||
|
|
||||||
@ -51,11 +58,9 @@ private fun runDirect(): Duration {
|
|||||||
/**
|
/**
|
||||||
* Comparing chain sampling performance with direct sampling performance
|
* Comparing chain sampling performance with direct sampling performance
|
||||||
*/
|
*/
|
||||||
fun main() {
|
fun main(): Unit = runBlocking(Dispatchers.Default) {
|
||||||
runBlocking(Dispatchers.Default) {
|
val chainJob = async { runKMathChained() }
|
||||||
val chainJob = async { runChain() }
|
val directJob = async { runApacheDirect() }
|
||||||
val directJob = async { runDirect() }
|
println("KMath Chained: ${chainJob.await()}")
|
||||||
println("Chain: ${chainJob.await()}")
|
println("Apache Direct: ${directJob.await()}")
|
||||||
println("Direct: ${directJob.await()}")
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -3,14 +3,15 @@ package space.kscience.kmath.stat
|
|||||||
import kotlinx.coroutines.runBlocking
|
import kotlinx.coroutines.runBlocking
|
||||||
import space.kscience.kmath.chains.Chain
|
import space.kscience.kmath.chains.Chain
|
||||||
import space.kscience.kmath.chains.collectWithState
|
import space.kscience.kmath.chains.collectWithState
|
||||||
|
import space.kscience.kmath.stat.distributions.NormalDistribution
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The state of distribution averager
|
* The state of distribution averager.
|
||||||
*/
|
*/
|
||||||
private data class AveragingChainState(var num: Int = 0, var value: Double = 0.0)
|
private data class AveragingChainState(var num: Int = 0, var value: Double = 0.0)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Averaging
|
* Averaging.
|
||||||
*/
|
*/
|
||||||
private fun Chain<Double>.mean(): Chain<Double> = collectWithState(AveragingChainState(), { it.copy() }) { chain ->
|
private fun Chain<Double>.mean(): Chain<Double> = collectWithState(AveragingChainState(), { it.copy() }) { chain ->
|
||||||
val next = chain.next()
|
val next = chain.next()
|
||||||
@ -21,7 +22,7 @@ private fun Chain<Double>.mean(): Chain<Double> = collectWithState(AveragingChai
|
|||||||
|
|
||||||
|
|
||||||
fun main() {
|
fun main() {
|
||||||
val normal = Distribution.normal()
|
val normal = NormalDistribution(0.0, 2.0)
|
||||||
val chain = normal.sample(RandomGenerator.default).mean()
|
val chain = normal.sample(RandomGenerator.default).mean()
|
||||||
|
|
||||||
runBlocking {
|
runBlocking {
|
||||||
|
@ -4,5 +4,5 @@ kotlin.mpp.stability.nowarn=true
|
|||||||
kotlin.native.enableDependencyPropagation=false
|
kotlin.native.enableDependencyPropagation=false
|
||||||
kotlin.parallel.tasks.in.project=true
|
kotlin.parallel.tasks.in.project=true
|
||||||
org.gradle.configureondemand=true
|
org.gradle.configureondemand=true
|
||||||
org.gradle.jvmargs=-XX:MaxMetaspaceSize=2G
|
org.gradle.jvmargs=-XX:MaxMetaspaceSize=9G
|
||||||
org.gradle.parallel=true
|
org.gradle.parallel=true
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
# Abstract Syntax Tree Expression Representation and Operations (`kmath-ast`)
|
# Module kmath-ast
|
||||||
|
|
||||||
This subproject implements the following features:
|
Abstract syntax tree expression representation and related optimizations.
|
||||||
|
|
||||||
- [expression-language](src/jvmMain/kotlin/space/kscience/kmath/ast/parser.kt) : Expression language and its parser
|
- [expression-language](src/jvmMain/kotlin/space/kscience/kmath/ast/parser.kt) : Expression language and its parser
|
||||||
- [mst](src/commonMain/kotlin/space/kscience/kmath/ast/MST.kt) : MST (Mathematical Syntax Tree) as expression language's syntax intermediate representation
|
- [mst](src/commonMain/kotlin/space/kscience/kmath/ast/MST.kt) : MST (Mathematical Syntax Tree) as expression language's syntax intermediate representation
|
||||||
@ -10,40 +10,34 @@ This subproject implements the following features:
|
|||||||
- [mst-js-codegen](src/jsMain/kotlin/space/kscience/kmath/estree/estree.kt) : Dynamic MST to JS compiler
|
- [mst-js-codegen](src/jsMain/kotlin/space/kscience/kmath/estree/estree.kt) : Dynamic MST to JS compiler
|
||||||
|
|
||||||
|
|
||||||
> #### Artifact:
|
## Artifact:
|
||||||
>
|
|
||||||
> This module artifact: `space.kscience:kmath-ast:0.3.0-dev-3`.
|
The Maven coordinates of this project are `space.kscience:kmath-ast:0.3.0-dev-3`.
|
||||||
>
|
|
||||||
> Bintray release version: [ ![Download](https://api.bintray.com/packages/mipt-npm/kscience/kmath-ast/images/download.svg) ](https://bintray.com/mipt-npm/kscience/kmath-ast/_latestVersion)
|
**Gradle:**
|
||||||
>
|
```gradle
|
||||||
> Bintray development version: [ ![Download](https://api.bintray.com/packages/mipt-npm/dev/kmath-ast/images/download.svg) ](https://bintray.com/mipt-npm/dev/kmath-ast/_latestVersion)
|
repositories {
|
||||||
>
|
maven { url 'https://repo.kotlin.link' }
|
||||||
> **Gradle:**
|
maven { url 'https://dl.bintray.com/hotkeytlt/maven' }
|
||||||
>
|
maven { url "https://dl.bintray.com/kotlin/kotlin-eap" } // include for builds based on kotlin-eap
|
||||||
> ```gradle
|
}
|
||||||
> repositories {
|
|
||||||
> maven { url 'https://repo.kotlin.link' }
|
dependencies {
|
||||||
> maven { url 'https://dl.bintray.com/hotkeytlt/maven' }
|
implementation 'space.kscience:kmath-ast:0.3.0-dev-3'
|
||||||
> maven { url "https://dl.bintray.com/kotlin/kotlin-eap" } // include for builds based on kotlin-eap
|
}
|
||||||
> }
|
```
|
||||||
>
|
**Gradle Kotlin DSL:**
|
||||||
> dependencies {
|
```kotlin
|
||||||
> implementation 'space.kscience:kmath-ast:0.3.0-dev-3'
|
repositories {
|
||||||
> }
|
maven("https://repo.kotlin.link")
|
||||||
> ```
|
maven("https://dl.bintray.com/kotlin/kotlin-eap") // include for builds based on kotlin-eap
|
||||||
> **Gradle Kotlin DSL:**
|
maven("https://dl.bintray.com/hotkeytlt/maven") // required for a
|
||||||
>
|
}
|
||||||
> ```kotlin
|
|
||||||
> repositories {
|
dependencies {
|
||||||
> maven("https://repo.kotlin.link")
|
implementation("space.kscience:kmath-ast:0.3.0-dev-3")
|
||||||
> maven("https://dl.bintray.com/kotlin/kotlin-eap") // include for builds based on kotlin-eap
|
}
|
||||||
> maven("https://dl.bintray.com/hotkeytlt/maven") // required for a
|
```
|
||||||
> }
|
|
||||||
>
|
|
||||||
> dependencies {
|
|
||||||
> implementation("space.kscience:kmath-ast:0.3.0-dev-3")
|
|
||||||
> }
|
|
||||||
> ```
|
|
||||||
|
|
||||||
## Dynamic expression code generation
|
## Dynamic expression code generation
|
||||||
|
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
# Abstract Syntax Tree Expression Representation and Operations (`kmath-ast`)
|
# Module kmath-ast
|
||||||
|
|
||||||
This subproject implements the following features:
|
Abstract syntax tree expression representation and related optimizations.
|
||||||
|
|
||||||
${features}
|
${features}
|
||||||
|
|
||||||
|
@ -1,6 +1,8 @@
|
|||||||
package space.kscience.kmath.ast
|
package space.kscience.kmath.ast
|
||||||
|
|
||||||
import space.kscience.kmath.expressions.*
|
import space.kscience.kmath.expressions.*
|
||||||
|
import space.kscience.kmath.misc.StringSymbol
|
||||||
|
import space.kscience.kmath.misc.Symbol
|
||||||
import space.kscience.kmath.operations.*
|
import space.kscience.kmath.operations.*
|
||||||
import kotlin.contracts.InvocationKind
|
import kotlin.contracts.InvocationKind
|
||||||
import kotlin.contracts.contract
|
import kotlin.contracts.contract
|
||||||
|
@ -3,7 +3,7 @@ package space.kscience.kmath.estree.internal
|
|||||||
import space.kscience.kmath.estree.internal.astring.generate
|
import space.kscience.kmath.estree.internal.astring.generate
|
||||||
import space.kscience.kmath.estree.internal.estree.*
|
import space.kscience.kmath.estree.internal.estree.*
|
||||||
import space.kscience.kmath.expressions.Expression
|
import space.kscience.kmath.expressions.Expression
|
||||||
import space.kscience.kmath.expressions.Symbol
|
import space.kscience.kmath.misc.Symbol
|
||||||
|
|
||||||
internal class ESTreeBuilder<T>(val bodyCallback: ESTreeBuilder<T>.() -> BaseExpression) {
|
internal class ESTreeBuilder<T>(val bodyCallback: ESTreeBuilder<T>.() -> BaseExpression) {
|
||||||
private class GeneratedExpression<T>(val executable: dynamic, val constants: Array<dynamic>) : Expression<T> {
|
private class GeneratedExpression<T>(val executable: dynamic, val constants: Array<dynamic>) : Expression<T> {
|
||||||
|
@ -2,8 +2,8 @@
|
|||||||
|
|
||||||
package space.kscience.kmath.asm.internal
|
package space.kscience.kmath.asm.internal
|
||||||
|
|
||||||
import space.kscience.kmath.expressions.StringSymbol
|
import space.kscience.kmath.misc.StringSymbol
|
||||||
import space.kscience.kmath.expressions.Symbol
|
import space.kscience.kmath.misc.Symbol
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets value with given [key] or throws [NoSuchElementException] whenever it is not present.
|
* Gets value with given [key] or throws [NoSuchElementException] whenever it is not present.
|
||||||
|
@ -2,6 +2,8 @@ package space.kscience.kmath.commons.expressions
|
|||||||
|
|
||||||
import org.apache.commons.math3.analysis.differentiation.DerivativeStructure
|
import org.apache.commons.math3.analysis.differentiation.DerivativeStructure
|
||||||
import space.kscience.kmath.expressions.*
|
import space.kscience.kmath.expressions.*
|
||||||
|
import space.kscience.kmath.misc.StringSymbol
|
||||||
|
import space.kscience.kmath.misc.Symbol
|
||||||
import space.kscience.kmath.misc.UnstableKMathAPI
|
import space.kscience.kmath.misc.UnstableKMathAPI
|
||||||
import space.kscience.kmath.operations.ExtendedField
|
import space.kscience.kmath.operations.ExtendedField
|
||||||
import space.kscience.kmath.operations.NumbersAddOperations
|
import space.kscience.kmath.operations.NumbersAddOperations
|
||||||
|
@ -3,6 +3,7 @@ package space.kscience.kmath.commons.linear
|
|||||||
import org.apache.commons.math3.linear.*
|
import org.apache.commons.math3.linear.*
|
||||||
import space.kscience.kmath.linear.*
|
import space.kscience.kmath.linear.*
|
||||||
import space.kscience.kmath.misc.UnstableKMathAPI
|
import space.kscience.kmath.misc.UnstableKMathAPI
|
||||||
|
import space.kscience.kmath.nd.StructureFeature
|
||||||
import space.kscience.kmath.operations.DoubleField
|
import space.kscience.kmath.operations.DoubleField
|
||||||
import space.kscience.kmath.structures.DoubleBuffer
|
import space.kscience.kmath.structures.DoubleBuffer
|
||||||
import kotlin.reflect.KClass
|
import kotlin.reflect.KClass
|
||||||
@ -89,7 +90,7 @@ public object CMLinearSpace : LinearSpace<Double, DoubleField> {
|
|||||||
v * this
|
v * this
|
||||||
|
|
||||||
@UnstableKMathAPI
|
@UnstableKMathAPI
|
||||||
override fun <F : Any> getFeature(structure: Matrix<Double>, type: KClass<F>): F? {
|
override fun <F : StructureFeature> getFeature(structure: Matrix<Double>, type: KClass<out F>): F? {
|
||||||
//Return the feature if it is intrinsic to the structure
|
//Return the feature if it is intrinsic to the structure
|
||||||
structure.getFeature(type)?.let { return it }
|
structure.getFeature(type)?.let { return it }
|
||||||
|
|
||||||
|
@ -9,22 +9,36 @@ import org.apache.commons.math3.optim.nonlinear.scalar.gradient.NonLinearConjuga
|
|||||||
import org.apache.commons.math3.optim.nonlinear.scalar.noderiv.AbstractSimplex
|
import org.apache.commons.math3.optim.nonlinear.scalar.noderiv.AbstractSimplex
|
||||||
import org.apache.commons.math3.optim.nonlinear.scalar.noderiv.NelderMeadSimplex
|
import org.apache.commons.math3.optim.nonlinear.scalar.noderiv.NelderMeadSimplex
|
||||||
import org.apache.commons.math3.optim.nonlinear.scalar.noderiv.SimplexOptimizer
|
import org.apache.commons.math3.optim.nonlinear.scalar.noderiv.SimplexOptimizer
|
||||||
import space.kscience.kmath.expressions.*
|
import space.kscience.kmath.expressions.DifferentiableExpression
|
||||||
import space.kscience.kmath.stat.OptimizationFeature
|
import space.kscience.kmath.expressions.Expression
|
||||||
import space.kscience.kmath.stat.OptimizationProblem
|
import space.kscience.kmath.expressions.SymbolIndexer
|
||||||
import space.kscience.kmath.stat.OptimizationProblemFactory
|
import space.kscience.kmath.expressions.derivative
|
||||||
import space.kscience.kmath.stat.OptimizationResult
|
import space.kscience.kmath.misc.Symbol
|
||||||
|
import space.kscience.kmath.misc.UnstableKMathAPI
|
||||||
|
import space.kscience.kmath.optimization.*
|
||||||
import kotlin.reflect.KClass
|
import kotlin.reflect.KClass
|
||||||
|
|
||||||
public operator fun PointValuePair.component1(): DoubleArray = point
|
public operator fun PointValuePair.component1(): DoubleArray = point
|
||||||
public operator fun PointValuePair.component2(): Double = value
|
public operator fun PointValuePair.component2(): Double = value
|
||||||
|
|
||||||
public class CMOptimizationProblem(override val symbols: List<Symbol>) :
|
@OptIn(UnstableKMathAPI::class)
|
||||||
OptimizationProblem<Double>, SymbolIndexer, OptimizationFeature {
|
public class CMOptimization(
|
||||||
|
override val symbols: List<Symbol>,
|
||||||
|
) : FunctionOptimization<Double>, NoDerivFunctionOptimization<Double>, SymbolIndexer, OptimizationFeature {
|
||||||
|
|
||||||
private val optimizationData: HashMap<KClass<out OptimizationData>, OptimizationData> = HashMap()
|
private val optimizationData: HashMap<KClass<out OptimizationData>, OptimizationData> = HashMap()
|
||||||
private var optimizatorBuilder: (() -> MultivariateOptimizer)? = null
|
private var optimizerBuilder: (() -> MultivariateOptimizer)? = null
|
||||||
public var convergenceChecker: ConvergenceChecker<PointValuePair> = SimpleValueChecker(DEFAULT_RELATIVE_TOLERANCE,
|
public var convergenceChecker: ConvergenceChecker<PointValuePair> = SimpleValueChecker(
|
||||||
DEFAULT_ABSOLUTE_TOLERANCE, DEFAULT_MAX_ITER)
|
DEFAULT_RELATIVE_TOLERANCE,
|
||||||
|
DEFAULT_ABSOLUTE_TOLERANCE,
|
||||||
|
DEFAULT_MAX_ITER
|
||||||
|
)
|
||||||
|
|
||||||
|
override var maximize: Boolean
|
||||||
|
get() = optimizationData[GoalType::class] == GoalType.MAXIMIZE
|
||||||
|
set(value) {
|
||||||
|
optimizationData[GoalType::class] = if (value) GoalType.MAXIMIZE else GoalType.MINIMIZE
|
||||||
|
}
|
||||||
|
|
||||||
public fun addOptimizationData(data: OptimizationData) {
|
public fun addOptimizationData(data: OptimizationData) {
|
||||||
optimizationData[data::class] = data
|
optimizationData[data::class] = data
|
||||||
@ -40,7 +54,7 @@ public class CMOptimizationProblem(override val symbols: List<Symbol>) :
|
|||||||
addOptimizationData(InitialGuess(map.toDoubleArray()))
|
addOptimizationData(InitialGuess(map.toDoubleArray()))
|
||||||
}
|
}
|
||||||
|
|
||||||
public override fun expression(expression: Expression<Double>): Unit {
|
public override fun function(expression: Expression<Double>): Unit {
|
||||||
val objectiveFunction = ObjectiveFunction {
|
val objectiveFunction = ObjectiveFunction {
|
||||||
val args = it.toMap()
|
val args = it.toMap()
|
||||||
expression(args)
|
expression(args)
|
||||||
@ -48,8 +62,8 @@ public class CMOptimizationProblem(override val symbols: List<Symbol>) :
|
|||||||
addOptimizationData(objectiveFunction)
|
addOptimizationData(objectiveFunction)
|
||||||
}
|
}
|
||||||
|
|
||||||
public override fun diffExpression(expression: DifferentiableExpression<Double, Expression<Double>>) {
|
public override fun diffFunction(expression: DifferentiableExpression<Double, Expression<Double>>) {
|
||||||
expression(expression)
|
function(expression)
|
||||||
val gradientFunction = ObjectiveFunctionGradient {
|
val gradientFunction = ObjectiveFunctionGradient {
|
||||||
val args = it.toMap()
|
val args = it.toMap()
|
||||||
DoubleArray(symbols.size) { index ->
|
DoubleArray(symbols.size) { index ->
|
||||||
@ -57,8 +71,8 @@ public class CMOptimizationProblem(override val symbols: List<Symbol>) :
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
addOptimizationData(gradientFunction)
|
addOptimizationData(gradientFunction)
|
||||||
if (optimizatorBuilder == null) {
|
if (optimizerBuilder == null) {
|
||||||
optimizatorBuilder = {
|
optimizerBuilder = {
|
||||||
NonLinearConjugateGradientOptimizer(
|
NonLinearConjugateGradientOptimizer(
|
||||||
NonLinearConjugateGradientOptimizer.Formula.FLETCHER_REEVES,
|
NonLinearConjugateGradientOptimizer.Formula.FLETCHER_REEVES,
|
||||||
convergenceChecker
|
convergenceChecker
|
||||||
@ -70,8 +84,8 @@ public class CMOptimizationProblem(override val symbols: List<Symbol>) :
|
|||||||
public fun simplex(simplex: AbstractSimplex) {
|
public fun simplex(simplex: AbstractSimplex) {
|
||||||
addOptimizationData(simplex)
|
addOptimizationData(simplex)
|
||||||
//Set optimization builder to simplex if it is not present
|
//Set optimization builder to simplex if it is not present
|
||||||
if (optimizatorBuilder == null) {
|
if (optimizerBuilder == null) {
|
||||||
optimizatorBuilder = { SimplexOptimizer(convergenceChecker) }
|
optimizerBuilder = { SimplexOptimizer(convergenceChecker) }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -84,7 +98,7 @@ public class CMOptimizationProblem(override val symbols: List<Symbol>) :
|
|||||||
}
|
}
|
||||||
|
|
||||||
public fun optimizer(block: () -> MultivariateOptimizer) {
|
public fun optimizer(block: () -> MultivariateOptimizer) {
|
||||||
optimizatorBuilder = block
|
optimizerBuilder = block
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun update(result: OptimizationResult<Double>) {
|
override fun update(result: OptimizationResult<Double>) {
|
||||||
@ -92,19 +106,19 @@ public class CMOptimizationProblem(override val symbols: List<Symbol>) :
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun optimize(): OptimizationResult<Double> {
|
override fun optimize(): OptimizationResult<Double> {
|
||||||
val optimizer = optimizatorBuilder?.invoke() ?: error("Optimizer not defined")
|
val optimizer = optimizerBuilder?.invoke() ?: error("Optimizer not defined")
|
||||||
val (point, value) = optimizer.optimize(*optimizationData.values.toTypedArray())
|
val (point, value) = optimizer.optimize(*optimizationData.values.toTypedArray())
|
||||||
return OptimizationResult(point.toMap(), value, setOf(this))
|
return OptimizationResult(point.toMap(), value, setOf(this))
|
||||||
}
|
}
|
||||||
|
|
||||||
public companion object : OptimizationProblemFactory<Double, CMOptimizationProblem> {
|
public companion object : OptimizationProblemFactory<Double, CMOptimization> {
|
||||||
public const val DEFAULT_RELATIVE_TOLERANCE: Double = 1e-4
|
public const val DEFAULT_RELATIVE_TOLERANCE: Double = 1e-4
|
||||||
public const val DEFAULT_ABSOLUTE_TOLERANCE: Double = 1e-4
|
public const val DEFAULT_ABSOLUTE_TOLERANCE: Double = 1e-4
|
||||||
public const val DEFAULT_MAX_ITER: Int = 1000
|
public const val DEFAULT_MAX_ITER: Int = 1000
|
||||||
|
|
||||||
override fun build(symbols: List<Symbol>): CMOptimizationProblem = CMOptimizationProblem(symbols)
|
override fun build(symbols: List<Symbol>): CMOptimization = CMOptimization(symbols)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public fun CMOptimizationProblem.initialGuess(vararg pairs: Pair<Symbol, Double>): Unit = initialGuess(pairs.toMap())
|
public fun CMOptimization.initialGuess(vararg pairs: Pair<Symbol, Double>): Unit = initialGuess(pairs.toMap())
|
||||||
public fun CMOptimizationProblem.simplexSteps(vararg pairs: Pair<Symbol, Double>): Unit = simplexSteps(pairs.toMap())
|
public fun CMOptimization.simplexSteps(vararg pairs: Pair<Symbol, Double>): Unit = simplexSteps(pairs.toMap())
|
@ -1,21 +1,21 @@
|
|||||||
package space.kscience.kmath.commons.optimization
|
package space.kscience.kmath.commons.optimization
|
||||||
|
|
||||||
import org.apache.commons.math3.analysis.differentiation.DerivativeStructure
|
import org.apache.commons.math3.analysis.differentiation.DerivativeStructure
|
||||||
import org.apache.commons.math3.optim.nonlinear.scalar.GoalType
|
|
||||||
import space.kscience.kmath.commons.expressions.DerivativeStructureField
|
import space.kscience.kmath.commons.expressions.DerivativeStructureField
|
||||||
import space.kscience.kmath.expressions.DifferentiableExpression
|
import space.kscience.kmath.expressions.DifferentiableExpression
|
||||||
import space.kscience.kmath.expressions.Expression
|
import space.kscience.kmath.expressions.Expression
|
||||||
import space.kscience.kmath.expressions.Symbol
|
import space.kscience.kmath.misc.Symbol
|
||||||
import space.kscience.kmath.stat.Fitting
|
import space.kscience.kmath.optimization.FunctionOptimization
|
||||||
import space.kscience.kmath.stat.OptimizationResult
|
import space.kscience.kmath.optimization.OptimizationResult
|
||||||
import space.kscience.kmath.stat.optimizeWith
|
import space.kscience.kmath.optimization.noDerivOptimizeWith
|
||||||
|
import space.kscience.kmath.optimization.optimizeWith
|
||||||
import space.kscience.kmath.structures.Buffer
|
import space.kscience.kmath.structures.Buffer
|
||||||
import space.kscience.kmath.structures.asBuffer
|
import space.kscience.kmath.structures.asBuffer
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Generate a chi squared expression from given x-y-sigma data and inline model. Provides automatic differentiation
|
* Generate a chi squared expression from given x-y-sigma data and inline model. Provides automatic differentiation
|
||||||
*/
|
*/
|
||||||
public fun Fitting.chiSquared(
|
public fun FunctionOptimization.Companion.chiSquared(
|
||||||
x: Buffer<Double>,
|
x: Buffer<Double>,
|
||||||
y: Buffer<Double>,
|
y: Buffer<Double>,
|
||||||
yErr: Buffer<Double>,
|
yErr: Buffer<Double>,
|
||||||
@ -25,7 +25,7 @@ public fun Fitting.chiSquared(
|
|||||||
/**
|
/**
|
||||||
* Generate a chi squared expression from given x-y-sigma data and inline model. Provides automatic differentiation
|
* Generate a chi squared expression from given x-y-sigma data and inline model. Provides automatic differentiation
|
||||||
*/
|
*/
|
||||||
public fun Fitting.chiSquared(
|
public fun FunctionOptimization.Companion.chiSquared(
|
||||||
x: Iterable<Double>,
|
x: Iterable<Double>,
|
||||||
y: Iterable<Double>,
|
y: Iterable<Double>,
|
||||||
yErr: Iterable<Double>,
|
yErr: Iterable<Double>,
|
||||||
@ -43,25 +43,26 @@ public fun Fitting.chiSquared(
|
|||||||
*/
|
*/
|
||||||
public fun Expression<Double>.optimize(
|
public fun Expression<Double>.optimize(
|
||||||
vararg symbols: Symbol,
|
vararg symbols: Symbol,
|
||||||
configuration: CMOptimizationProblem.() -> Unit,
|
configuration: CMOptimization.() -> Unit,
|
||||||
): OptimizationResult<Double> = optimizeWith(CMOptimizationProblem, symbols = symbols, configuration)
|
): OptimizationResult<Double> = noDerivOptimizeWith(CMOptimization, symbols = symbols, configuration)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Optimize differentiable expression
|
* Optimize differentiable expression
|
||||||
*/
|
*/
|
||||||
public fun DifferentiableExpression<Double, Expression<Double>>.optimize(
|
public fun DifferentiableExpression<Double, Expression<Double>>.optimize(
|
||||||
vararg symbols: Symbol,
|
vararg symbols: Symbol,
|
||||||
configuration: CMOptimizationProblem.() -> Unit,
|
configuration: CMOptimization.() -> Unit,
|
||||||
): OptimizationResult<Double> = optimizeWith(CMOptimizationProblem, symbols = symbols, configuration)
|
): OptimizationResult<Double> = optimizeWith(CMOptimization, symbols = symbols, configuration)
|
||||||
|
|
||||||
public fun DifferentiableExpression<Double, Expression<Double>>.minimize(
|
public fun DifferentiableExpression<Double, Expression<Double>>.minimize(
|
||||||
vararg startPoint: Pair<Symbol, Double>,
|
vararg startPoint: Pair<Symbol, Double>,
|
||||||
configuration: CMOptimizationProblem.() -> Unit = {},
|
configuration: CMOptimization.() -> Unit = {},
|
||||||
): OptimizationResult<Double> {
|
): OptimizationResult<Double> {
|
||||||
require(startPoint.isNotEmpty()) { "Must provide a list of symbols for optimization" }
|
val symbols = startPoint.map { it.first }.toTypedArray()
|
||||||
val problem = CMOptimizationProblem(startPoint.map { it.first }).apply(configuration)
|
return optimize(*symbols){
|
||||||
problem.diffExpression(this)
|
maximize = false
|
||||||
problem.initialGuess(startPoint.toMap())
|
initialGuess(startPoint.toMap())
|
||||||
problem.goal(GoalType.MINIMIZE)
|
diffFunction(this@minimize)
|
||||||
return problem.optimize()
|
configuration()
|
||||||
|
}
|
||||||
}
|
}
|
@ -1,6 +1,10 @@
|
|||||||
package space.kscience.kmath.commons.expressions
|
package space.kscience.kmath.commons.expressions
|
||||||
|
|
||||||
import space.kscience.kmath.expressions.*
|
import space.kscience.kmath.expressions.binding
|
||||||
|
import space.kscience.kmath.expressions.derivative
|
||||||
|
import space.kscience.kmath.expressions.invoke
|
||||||
|
import space.kscience.kmath.misc.Symbol
|
||||||
|
import space.kscience.kmath.misc.symbol
|
||||||
import kotlin.contracts.InvocationKind
|
import kotlin.contracts.InvocationKind
|
||||||
import kotlin.contracts.contract
|
import kotlin.contracts.contract
|
||||||
import kotlin.test.Test
|
import kotlin.test.Test
|
||||||
|
@ -1,13 +1,13 @@
|
|||||||
package space.kscience.kmath.commons.optimization
|
package space.kscience.kmath.commons.optimization
|
||||||
|
|
||||||
import org.junit.jupiter.api.Test
|
import kotlinx.coroutines.runBlocking
|
||||||
import space.kscience.kmath.commons.expressions.DerivativeStructureExpression
|
import space.kscience.kmath.commons.expressions.DerivativeStructureExpression
|
||||||
import space.kscience.kmath.expressions.symbol
|
import space.kscience.kmath.misc.symbol
|
||||||
import space.kscience.kmath.stat.Distribution
|
import space.kscience.kmath.optimization.FunctionOptimization
|
||||||
import space.kscience.kmath.stat.Fitting
|
|
||||||
import space.kscience.kmath.stat.RandomGenerator
|
import space.kscience.kmath.stat.RandomGenerator
|
||||||
import space.kscience.kmath.stat.normal
|
import space.kscience.kmath.stat.distributions.NormalDistribution
|
||||||
import kotlin.math.pow
|
import kotlin.math.pow
|
||||||
|
import kotlin.test.Test
|
||||||
|
|
||||||
internal class OptimizeTest {
|
internal class OptimizeTest {
|
||||||
val x by symbol
|
val x by symbol
|
||||||
@ -34,28 +34,29 @@ internal class OptimizeTest {
|
|||||||
simplexSteps(x to 2.0, y to 0.5)
|
simplexSteps(x to 2.0, y to 0.5)
|
||||||
//this sets simplex optimizer
|
//this sets simplex optimizer
|
||||||
}
|
}
|
||||||
|
|
||||||
println(result.point)
|
println(result.point)
|
||||||
println(result.value)
|
println(result.value)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun testCmFit() {
|
fun testCmFit() = runBlocking {
|
||||||
val a by symbol
|
val a by symbol
|
||||||
val b by symbol
|
val b by symbol
|
||||||
val c by symbol
|
val c by symbol
|
||||||
|
|
||||||
val sigma = 1.0
|
val sigma = 1.0
|
||||||
val generator = Distribution.normal(0.0, sigma)
|
val generator = NormalDistribution(0.0, sigma)
|
||||||
val chain = generator.sample(RandomGenerator.default(112667))
|
val chain = generator.sample(RandomGenerator.default(112667))
|
||||||
val x = (1..100).map(Int::toDouble)
|
val x = (1..100).map(Int::toDouble)
|
||||||
|
|
||||||
val y = x.map {
|
val y = x.map {
|
||||||
it.pow(2) + it + 1 + chain.nextDouble()
|
it.pow(2) + it + 1 + chain.next()
|
||||||
}
|
}
|
||||||
|
|
||||||
val yErr = List(x.size) { sigma }
|
val yErr = List(x.size) { sigma }
|
||||||
|
|
||||||
val chi2 = Fitting.chiSquared(x, y, yErr) { x1 ->
|
val chi2 = FunctionOptimization.chiSquared(x, y, yErr) { x1 ->
|
||||||
val cWithDefault = bindSymbolOrNull(c) ?: one
|
val cWithDefault = bindSymbolOrNull(c) ?: one
|
||||||
bind(a) * x1.pow(2) + bind(b) * x1 + cWithDefault
|
bind(a) * x1.pow(2) + bind(b) * x1 + cWithDefault
|
||||||
}
|
}
|
||||||
@ -64,5 +65,4 @@ internal class OptimizeTest {
|
|||||||
println(result)
|
println(result)
|
||||||
println("Chi2/dof = ${result.value / (x.size - 3)}")
|
println("Chi2/dof = ${result.value / (x.size - 3)}")
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
@ -1,42 +1,36 @@
|
|||||||
# The Core Module (`kmath-core`)
|
# Module kmath-complex
|
||||||
|
|
||||||
Complex and hypercomplex number systems in KMath:
|
Complex and hypercomplex number systems in KMath.
|
||||||
|
|
||||||
- [complex](src/commonMain/kotlin/space/kscience/kmath/complex/Complex.kt) : Complex Numbers
|
- [complex](src/commonMain/kotlin/space/kscience/kmath/complex/Complex.kt) : Complex Numbers
|
||||||
- [quaternion](src/commonMain/kotlin/space/kscience/kmath/complex/Quaternion.kt) : Quaternions
|
- [quaternion](src/commonMain/kotlin/space/kscience/kmath/complex/Quaternion.kt) : Quaternions
|
||||||
|
|
||||||
|
|
||||||
> #### Artifact:
|
## Artifact:
|
||||||
>
|
|
||||||
> This module artifact: `space.kscience:kmath-complex:0.3.0-dev-3`.
|
The Maven coordinates of this project are `space.kscience:kmath-complex:0.3.0-dev-3`.
|
||||||
>
|
|
||||||
> Bintray release version: [ ![Download](https://api.bintray.com/packages/mipt-npm/kscience/kmath-complex/images/download.svg) ](https://bintray.com/mipt-npm/kscience/kmath-complex/_latestVersion)
|
**Gradle:**
|
||||||
>
|
```gradle
|
||||||
> Bintray development version: [ ![Download](https://api.bintray.com/packages/mipt-npm/dev/kmath-complex/images/download.svg) ](https://bintray.com/mipt-npm/dev/kmath-complex/_latestVersion)
|
repositories {
|
||||||
>
|
maven { url 'https://repo.kotlin.link' }
|
||||||
> **Gradle:**
|
maven { url 'https://dl.bintray.com/hotkeytlt/maven' }
|
||||||
>
|
maven { url "https://dl.bintray.com/kotlin/kotlin-eap" } // include for builds based on kotlin-eap
|
||||||
> ```gradle
|
}
|
||||||
> repositories {
|
|
||||||
> maven { url 'https://repo.kotlin.link' }
|
dependencies {
|
||||||
> maven { url 'https://dl.bintray.com/hotkeytlt/maven' }
|
implementation 'space.kscience:kmath-complex:0.3.0-dev-3'
|
||||||
> maven { url "https://dl.bintray.com/kotlin/kotlin-eap" } // include for builds based on kotlin-eap
|
}
|
||||||
> }
|
```
|
||||||
>
|
**Gradle Kotlin DSL:**
|
||||||
> dependencies {
|
```kotlin
|
||||||
> implementation 'space.kscience:kmath-complex:0.3.0-dev-3'
|
repositories {
|
||||||
> }
|
maven("https://repo.kotlin.link")
|
||||||
> ```
|
maven("https://dl.bintray.com/kotlin/kotlin-eap") // include for builds based on kotlin-eap
|
||||||
> **Gradle Kotlin DSL:**
|
maven("https://dl.bintray.com/hotkeytlt/maven") // required for a
|
||||||
>
|
}
|
||||||
> ```kotlin
|
|
||||||
> repositories {
|
dependencies {
|
||||||
> maven("https://repo.kotlin.link")
|
implementation("space.kscience:kmath-complex:0.3.0-dev-3")
|
||||||
> maven("https://dl.bintray.com/kotlin/kotlin-eap") // include for builds based on kotlin-eap
|
}
|
||||||
> maven("https://dl.bintray.com/hotkeytlt/maven") // required for a
|
```
|
||||||
> }
|
|
||||||
>
|
|
||||||
> dependencies {
|
|
||||||
> implementation("space.kscience:kmath-complex:0.3.0-dev-3")
|
|
||||||
> }
|
|
||||||
> ```
|
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
# The Core Module (`kmath-core`)
|
# Module kmath-complex
|
||||||
|
|
||||||
Complex and hypercomplex number systems in KMath:
|
Complex and hypercomplex number systems in KMath.
|
||||||
|
|
||||||
${features}
|
${features}
|
||||||
|
|
||||||
|
@ -3,7 +3,7 @@ package space.kscience.kmath.complex
|
|||||||
import space.kscience.kmath.expressions.FunctionalExpressionField
|
import space.kscience.kmath.expressions.FunctionalExpressionField
|
||||||
import space.kscience.kmath.expressions.bindSymbol
|
import space.kscience.kmath.expressions.bindSymbol
|
||||||
import space.kscience.kmath.expressions.invoke
|
import space.kscience.kmath.expressions.invoke
|
||||||
import space.kscience.kmath.expressions.symbol
|
import space.kscience.kmath.misc.symbol
|
||||||
import kotlin.test.Test
|
import kotlin.test.Test
|
||||||
import kotlin.test.assertEquals
|
import kotlin.test.assertEquals
|
||||||
|
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
# The Core Module (`kmath-core`)
|
# Module kmath-core
|
||||||
|
|
||||||
The core features of KMath:
|
The core interfaces of KMath.
|
||||||
|
|
||||||
- [algebras](src/commonMain/kotlin/space/kscience/kmath/operations/Algebra.kt) : Algebraic structures like rings, spaces and fields.
|
- [algebras](src/commonMain/kotlin/space/kscience/kmath/operations/Algebra.kt) : Algebraic structures like rings, spaces and fields.
|
||||||
- [nd](src/commonMain/kotlin/space/kscience/kmath/structures/StructureND.kt) : Many-dimensional structures and operations on them.
|
- [nd](src/commonMain/kotlin/space/kscience/kmath/structures/StructureND.kt) : Many-dimensional structures and operations on them.
|
||||||
@ -13,37 +13,31 @@ performance calculations to code generation.
|
|||||||
- [autodif](src/commonMain/kotlin/space/kscience/kmath/expressions/SimpleAutoDiff.kt) : Automatic differentiation
|
- [autodif](src/commonMain/kotlin/space/kscience/kmath/expressions/SimpleAutoDiff.kt) : Automatic differentiation
|
||||||
|
|
||||||
|
|
||||||
> #### Artifact:
|
## Artifact:
|
||||||
>
|
|
||||||
> This module artifact: `space.kscience:kmath-core:0.3.0-dev-3`.
|
The Maven coordinates of this project are `space.kscience:kmath-core:0.3.0-dev-3`.
|
||||||
>
|
|
||||||
> Bintray release version: [ ![Download](https://api.bintray.com/packages/mipt-npm/kscience/kmath-core/images/download.svg) ](https://bintray.com/mipt-npm/kscience/kmath-core/_latestVersion)
|
**Gradle:**
|
||||||
>
|
```gradle
|
||||||
> Bintray development version: [ ![Download](https://api.bintray.com/packages/mipt-npm/dev/kmath-core/images/download.svg) ](https://bintray.com/mipt-npm/dev/kmath-core/_latestVersion)
|
repositories {
|
||||||
>
|
maven { url 'https://repo.kotlin.link' }
|
||||||
> **Gradle:**
|
maven { url 'https://dl.bintray.com/hotkeytlt/maven' }
|
||||||
>
|
maven { url "https://dl.bintray.com/kotlin/kotlin-eap" } // include for builds based on kotlin-eap
|
||||||
> ```gradle
|
}
|
||||||
> repositories {
|
|
||||||
> maven { url 'https://repo.kotlin.link' }
|
dependencies {
|
||||||
> maven { url 'https://dl.bintray.com/hotkeytlt/maven' }
|
implementation 'space.kscience:kmath-core:0.3.0-dev-3'
|
||||||
> maven { url "https://dl.bintray.com/kotlin/kotlin-eap" } // include for builds based on kotlin-eap
|
}
|
||||||
> }
|
```
|
||||||
>
|
**Gradle Kotlin DSL:**
|
||||||
> dependencies {
|
```kotlin
|
||||||
> implementation 'space.kscience:kmath-core:0.3.0-dev-3'
|
repositories {
|
||||||
> }
|
maven("https://repo.kotlin.link")
|
||||||
> ```
|
maven("https://dl.bintray.com/kotlin/kotlin-eap") // include for builds based on kotlin-eap
|
||||||
> **Gradle Kotlin DSL:**
|
maven("https://dl.bintray.com/hotkeytlt/maven") // required for a
|
||||||
>
|
}
|
||||||
> ```kotlin
|
|
||||||
> repositories {
|
dependencies {
|
||||||
> maven("https://repo.kotlin.link")
|
implementation("space.kscience:kmath-core:0.3.0-dev-3")
|
||||||
> maven("https://dl.bintray.com/kotlin/kotlin-eap") // include for builds based on kotlin-eap
|
}
|
||||||
> maven("https://dl.bintray.com/hotkeytlt/maven") // required for a
|
```
|
||||||
> }
|
|
||||||
>
|
|
||||||
> dependencies {
|
|
||||||
> implementation("space.kscience:kmath-core:0.3.0-dev-3")
|
|
||||||
> }
|
|
||||||
> ```
|
|
||||||
|
@ -1,3 +1,18 @@
|
|||||||
|
public final class space/kscience/kmath/data/ColumnarDataKt {
|
||||||
|
}
|
||||||
|
|
||||||
|
public final class space/kscience/kmath/data/XYColumnarData$DefaultImpls {
|
||||||
|
public static fun get (Lspace/kscience/kmath/data/XYColumnarData;Lspace/kscience/kmath/misc/Symbol;)Lspace/kscience/kmath/structures/Buffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
public final class space/kscience/kmath/data/XYColumnarDataKt {
|
||||||
|
public static synthetic fun asXYData$default (Lspace/kscience/kmath/nd/Structure2D;IIILjava/lang/Object;)Lspace/kscience/kmath/data/XYColumnarData;
|
||||||
|
}
|
||||||
|
|
||||||
|
public final class space/kscience/kmath/data/XYZColumnarData$DefaultImpls {
|
||||||
|
public static fun get (Lspace/kscience/kmath/data/XYZColumnarData;Lspace/kscience/kmath/misc/Symbol;)Lspace/kscience/kmath/structures/Buffer;
|
||||||
|
}
|
||||||
|
|
||||||
public abstract interface class space/kscience/kmath/domains/Domain {
|
public abstract interface class space/kscience/kmath/domains/Domain {
|
||||||
public abstract fun contains (Lspace/kscience/kmath/structures/Buffer;)Z
|
public abstract fun contains (Lspace/kscience/kmath/structures/Buffer;)Z
|
||||||
public abstract fun getDimension ()I
|
public abstract fun getDimension ()I
|
||||||
@ -14,7 +29,7 @@ public class space/kscience/kmath/expressions/AutoDiffValue {
|
|||||||
|
|
||||||
public final class space/kscience/kmath/expressions/DerivationResult {
|
public final class space/kscience/kmath/expressions/DerivationResult {
|
||||||
public fun <init> (Ljava/lang/Object;Ljava/util/Map;Lspace/kscience/kmath/operations/Field;)V
|
public fun <init> (Ljava/lang/Object;Ljava/util/Map;Lspace/kscience/kmath/operations/Field;)V
|
||||||
public final fun derivative (Lspace/kscience/kmath/expressions/Symbol;)Ljava/lang/Object;
|
public final fun derivative (Lspace/kscience/kmath/misc/Symbol;)Ljava/lang/Object;
|
||||||
public final fun div ()Ljava/lang/Object;
|
public final fun div ()Ljava/lang/Object;
|
||||||
public final fun getContext ()Lspace/kscience/kmath/operations/Field;
|
public final fun getContext ()Lspace/kscience/kmath/operations/Field;
|
||||||
public final fun getValue ()Ljava/lang/Object;
|
public final fun getValue ()Ljava/lang/Object;
|
||||||
@ -27,7 +42,7 @@ public abstract interface class space/kscience/kmath/expressions/DifferentiableE
|
|||||||
public final class space/kscience/kmath/expressions/DifferentiableExpressionKt {
|
public final class space/kscience/kmath/expressions/DifferentiableExpressionKt {
|
||||||
public static final fun derivative (Lspace/kscience/kmath/expressions/DifferentiableExpression;Ljava/lang/String;)Lspace/kscience/kmath/expressions/Expression;
|
public static final fun derivative (Lspace/kscience/kmath/expressions/DifferentiableExpression;Ljava/lang/String;)Lspace/kscience/kmath/expressions/Expression;
|
||||||
public static final fun derivative (Lspace/kscience/kmath/expressions/DifferentiableExpression;Ljava/util/List;)Lspace/kscience/kmath/expressions/Expression;
|
public static final fun derivative (Lspace/kscience/kmath/expressions/DifferentiableExpression;Ljava/util/List;)Lspace/kscience/kmath/expressions/Expression;
|
||||||
public static final fun derivative (Lspace/kscience/kmath/expressions/DifferentiableExpression;[Lspace/kscience/kmath/expressions/Symbol;)Lspace/kscience/kmath/expressions/Expression;
|
public static final fun derivative (Lspace/kscience/kmath/expressions/DifferentiableExpression;[Lspace/kscience/kmath/misc/Symbol;)Lspace/kscience/kmath/expressions/Expression;
|
||||||
}
|
}
|
||||||
|
|
||||||
public abstract interface class space/kscience/kmath/expressions/Expression {
|
public abstract interface class space/kscience/kmath/expressions/Expression {
|
||||||
@ -36,7 +51,7 @@ public abstract interface class space/kscience/kmath/expressions/Expression {
|
|||||||
|
|
||||||
public abstract interface class space/kscience/kmath/expressions/ExpressionAlgebra : space/kscience/kmath/operations/Algebra {
|
public abstract interface class space/kscience/kmath/expressions/ExpressionAlgebra : space/kscience/kmath/operations/Algebra {
|
||||||
public abstract fun bindSymbol (Ljava/lang/String;)Ljava/lang/Object;
|
public abstract fun bindSymbol (Ljava/lang/String;)Ljava/lang/Object;
|
||||||
public abstract fun bindSymbolOrNull (Lspace/kscience/kmath/expressions/Symbol;)Ljava/lang/Object;
|
public abstract fun bindSymbolOrNull (Lspace/kscience/kmath/misc/Symbol;)Ljava/lang/Object;
|
||||||
public abstract fun const (Ljava/lang/Object;)Ljava/lang/Object;
|
public abstract fun const (Ljava/lang/Object;)Ljava/lang/Object;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -56,18 +71,17 @@ public final class space/kscience/kmath/expressions/ExpressionBuildersKt {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public final class space/kscience/kmath/expressions/ExpressionKt {
|
public final class space/kscience/kmath/expressions/ExpressionKt {
|
||||||
public static final fun bindSymbol (Lspace/kscience/kmath/expressions/ExpressionAlgebra;Lspace/kscience/kmath/expressions/Symbol;)Ljava/lang/Object;
|
public static final fun bindSymbol (Lspace/kscience/kmath/expressions/ExpressionAlgebra;Lspace/kscience/kmath/misc/Symbol;)Ljava/lang/Object;
|
||||||
public static final fun binding (Lspace/kscience/kmath/expressions/ExpressionAlgebra;)Lkotlin/properties/ReadOnlyProperty;
|
public static final fun binding (Lspace/kscience/kmath/expressions/ExpressionAlgebra;)Lkotlin/properties/ReadOnlyProperty;
|
||||||
public static final fun callByString (Lspace/kscience/kmath/expressions/Expression;[Lkotlin/Pair;)Ljava/lang/Object;
|
public static final fun callByString (Lspace/kscience/kmath/expressions/Expression;[Lkotlin/Pair;)Ljava/lang/Object;
|
||||||
public static final fun callBySymbol (Lspace/kscience/kmath/expressions/Expression;[Lkotlin/Pair;)Ljava/lang/Object;
|
public static final fun callBySymbol (Lspace/kscience/kmath/expressions/Expression;[Lkotlin/Pair;)Ljava/lang/Object;
|
||||||
public static final fun getSymbol ()Lkotlin/properties/ReadOnlyProperty;
|
|
||||||
public static final fun invoke (Lspace/kscience/kmath/expressions/Expression;)Ljava/lang/Object;
|
public static final fun invoke (Lspace/kscience/kmath/expressions/Expression;)Ljava/lang/Object;
|
||||||
}
|
}
|
||||||
|
|
||||||
public abstract class space/kscience/kmath/expressions/FirstDerivativeExpression : space/kscience/kmath/expressions/DifferentiableExpression {
|
public abstract class space/kscience/kmath/expressions/FirstDerivativeExpression : space/kscience/kmath/expressions/DifferentiableExpression {
|
||||||
public fun <init> ()V
|
public fun <init> ()V
|
||||||
public final fun derivativeOrNull (Ljava/util/List;)Lspace/kscience/kmath/expressions/Expression;
|
public final fun derivativeOrNull (Ljava/util/List;)Lspace/kscience/kmath/expressions/Expression;
|
||||||
public abstract fun derivativeOrNull (Lspace/kscience/kmath/expressions/Symbol;)Lspace/kscience/kmath/expressions/Expression;
|
public abstract fun derivativeOrNull (Lspace/kscience/kmath/misc/Symbol;)Lspace/kscience/kmath/expressions/Expression;
|
||||||
}
|
}
|
||||||
|
|
||||||
public abstract class space/kscience/kmath/expressions/FunctionalExpressionAlgebra : space/kscience/kmath/expressions/ExpressionAlgebra {
|
public abstract class space/kscience/kmath/expressions/FunctionalExpressionAlgebra : space/kscience/kmath/expressions/ExpressionAlgebra {
|
||||||
@ -77,8 +91,8 @@ public abstract class space/kscience/kmath/expressions/FunctionalExpressionAlgeb
|
|||||||
public fun binaryOperationFunction (Ljava/lang/String;)Lkotlin/jvm/functions/Function2;
|
public fun binaryOperationFunction (Ljava/lang/String;)Lkotlin/jvm/functions/Function2;
|
||||||
public synthetic fun bindSymbol (Ljava/lang/String;)Ljava/lang/Object;
|
public synthetic fun bindSymbol (Ljava/lang/String;)Ljava/lang/Object;
|
||||||
public fun bindSymbol (Ljava/lang/String;)Lspace/kscience/kmath/expressions/Expression;
|
public fun bindSymbol (Ljava/lang/String;)Lspace/kscience/kmath/expressions/Expression;
|
||||||
public synthetic fun bindSymbolOrNull (Lspace/kscience/kmath/expressions/Symbol;)Ljava/lang/Object;
|
public synthetic fun bindSymbolOrNull (Lspace/kscience/kmath/misc/Symbol;)Ljava/lang/Object;
|
||||||
public fun bindSymbolOrNull (Lspace/kscience/kmath/expressions/Symbol;)Lspace/kscience/kmath/expressions/Expression;
|
public fun bindSymbolOrNull (Lspace/kscience/kmath/misc/Symbol;)Lspace/kscience/kmath/expressions/Expression;
|
||||||
public synthetic fun const (Ljava/lang/Object;)Ljava/lang/Object;
|
public synthetic fun const (Ljava/lang/Object;)Ljava/lang/Object;
|
||||||
public fun const (Ljava/lang/Object;)Lspace/kscience/kmath/expressions/Expression;
|
public fun const (Ljava/lang/Object;)Lspace/kscience/kmath/expressions/Expression;
|
||||||
public final fun getAlgebra ()Lspace/kscience/kmath/operations/Algebra;
|
public final fun getAlgebra ()Lspace/kscience/kmath/operations/Algebra;
|
||||||
@ -203,7 +217,7 @@ public class space/kscience/kmath/expressions/FunctionalExpressionRing : space/k
|
|||||||
|
|
||||||
public final class space/kscience/kmath/expressions/SimpleAutoDiffExpression : space/kscience/kmath/expressions/FirstDerivativeExpression {
|
public final class space/kscience/kmath/expressions/SimpleAutoDiffExpression : space/kscience/kmath/expressions/FirstDerivativeExpression {
|
||||||
public fun <init> (Lspace/kscience/kmath/operations/Field;Lkotlin/jvm/functions/Function1;)V
|
public fun <init> (Lspace/kscience/kmath/operations/Field;Lkotlin/jvm/functions/Function1;)V
|
||||||
public fun derivativeOrNull (Lspace/kscience/kmath/expressions/Symbol;)Lspace/kscience/kmath/expressions/Expression;
|
public fun derivativeOrNull (Lspace/kscience/kmath/misc/Symbol;)Lspace/kscience/kmath/expressions/Expression;
|
||||||
public final fun getField ()Lspace/kscience/kmath/operations/Field;
|
public final fun getField ()Lspace/kscience/kmath/operations/Field;
|
||||||
public final fun getFunction ()Lkotlin/jvm/functions/Function1;
|
public final fun getFunction ()Lkotlin/jvm/functions/Function1;
|
||||||
public fun invoke (Ljava/util/Map;)Ljava/lang/Object;
|
public fun invoke (Ljava/util/Map;)Ljava/lang/Object;
|
||||||
@ -264,8 +278,8 @@ public class space/kscience/kmath/expressions/SimpleAutoDiffField : space/kscien
|
|||||||
public fun binaryOperationFunction (Ljava/lang/String;)Lkotlin/jvm/functions/Function2;
|
public fun binaryOperationFunction (Ljava/lang/String;)Lkotlin/jvm/functions/Function2;
|
||||||
public synthetic fun bindSymbol (Ljava/lang/String;)Ljava/lang/Object;
|
public synthetic fun bindSymbol (Ljava/lang/String;)Ljava/lang/Object;
|
||||||
public fun bindSymbol (Ljava/lang/String;)Lspace/kscience/kmath/expressions/AutoDiffValue;
|
public fun bindSymbol (Ljava/lang/String;)Lspace/kscience/kmath/expressions/AutoDiffValue;
|
||||||
public synthetic fun bindSymbolOrNull (Lspace/kscience/kmath/expressions/Symbol;)Ljava/lang/Object;
|
public synthetic fun bindSymbolOrNull (Lspace/kscience/kmath/misc/Symbol;)Ljava/lang/Object;
|
||||||
public fun bindSymbolOrNull (Lspace/kscience/kmath/expressions/Symbol;)Lspace/kscience/kmath/expressions/AutoDiffValue;
|
public fun bindSymbolOrNull (Lspace/kscience/kmath/misc/Symbol;)Lspace/kscience/kmath/expressions/AutoDiffValue;
|
||||||
public synthetic fun const (Ljava/lang/Object;)Ljava/lang/Object;
|
public synthetic fun const (Ljava/lang/Object;)Ljava/lang/Object;
|
||||||
public fun const (Ljava/lang/Object;)Lspace/kscience/kmath/expressions/AutoDiffValue;
|
public fun const (Ljava/lang/Object;)Lspace/kscience/kmath/expressions/AutoDiffValue;
|
||||||
public final fun const (Lkotlin/jvm/functions/Function1;)Lspace/kscience/kmath/expressions/AutoDiffValue;
|
public final fun const (Lkotlin/jvm/functions/Function1;)Lspace/kscience/kmath/expressions/AutoDiffValue;
|
||||||
@ -332,7 +346,7 @@ public final class space/kscience/kmath/expressions/SimpleAutoDiffKt {
|
|||||||
public static final fun cos (Lspace/kscience/kmath/expressions/SimpleAutoDiffField;Lspace/kscience/kmath/expressions/AutoDiffValue;)Lspace/kscience/kmath/expressions/AutoDiffValue;
|
public static final fun cos (Lspace/kscience/kmath/expressions/SimpleAutoDiffField;Lspace/kscience/kmath/expressions/AutoDiffValue;)Lspace/kscience/kmath/expressions/AutoDiffValue;
|
||||||
public static final fun cosh (Lspace/kscience/kmath/expressions/SimpleAutoDiffField;Lspace/kscience/kmath/expressions/AutoDiffValue;)Lspace/kscience/kmath/expressions/AutoDiffValue;
|
public static final fun cosh (Lspace/kscience/kmath/expressions/SimpleAutoDiffField;Lspace/kscience/kmath/expressions/AutoDiffValue;)Lspace/kscience/kmath/expressions/AutoDiffValue;
|
||||||
public static final fun exp (Lspace/kscience/kmath/expressions/SimpleAutoDiffField;Lspace/kscience/kmath/expressions/AutoDiffValue;)Lspace/kscience/kmath/expressions/AutoDiffValue;
|
public static final fun exp (Lspace/kscience/kmath/expressions/SimpleAutoDiffField;Lspace/kscience/kmath/expressions/AutoDiffValue;)Lspace/kscience/kmath/expressions/AutoDiffValue;
|
||||||
public static final fun grad (Lspace/kscience/kmath/expressions/DerivationResult;[Lspace/kscience/kmath/expressions/Symbol;)Lspace/kscience/kmath/structures/Buffer;
|
public static final fun grad (Lspace/kscience/kmath/expressions/DerivationResult;[Lspace/kscience/kmath/misc/Symbol;)Lspace/kscience/kmath/structures/Buffer;
|
||||||
public static final fun ln (Lspace/kscience/kmath/expressions/SimpleAutoDiffField;Lspace/kscience/kmath/expressions/AutoDiffValue;)Lspace/kscience/kmath/expressions/AutoDiffValue;
|
public static final fun ln (Lspace/kscience/kmath/expressions/SimpleAutoDiffField;Lspace/kscience/kmath/expressions/AutoDiffValue;)Lspace/kscience/kmath/expressions/AutoDiffValue;
|
||||||
public static final fun pow (Lspace/kscience/kmath/expressions/SimpleAutoDiffField;Lspace/kscience/kmath/expressions/AutoDiffValue;D)Lspace/kscience/kmath/expressions/AutoDiffValue;
|
public static final fun pow (Lspace/kscience/kmath/expressions/SimpleAutoDiffField;Lspace/kscience/kmath/expressions/AutoDiffValue;D)Lspace/kscience/kmath/expressions/AutoDiffValue;
|
||||||
public static final fun pow (Lspace/kscience/kmath/expressions/SimpleAutoDiffField;Lspace/kscience/kmath/expressions/AutoDiffValue;I)Lspace/kscience/kmath/expressions/AutoDiffValue;
|
public static final fun pow (Lspace/kscience/kmath/expressions/SimpleAutoDiffField;Lspace/kscience/kmath/expressions/AutoDiffValue;I)Lspace/kscience/kmath/expressions/AutoDiffValue;
|
||||||
@ -348,79 +362,13 @@ public final class space/kscience/kmath/expressions/SimpleAutoDiffKt {
|
|||||||
public static final fun tanh (Lspace/kscience/kmath/expressions/SimpleAutoDiffField;Lspace/kscience/kmath/expressions/AutoDiffValue;)Lspace/kscience/kmath/expressions/AutoDiffValue;
|
public static final fun tanh (Lspace/kscience/kmath/expressions/SimpleAutoDiffField;Lspace/kscience/kmath/expressions/AutoDiffValue;)Lspace/kscience/kmath/expressions/AutoDiffValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
public final class space/kscience/kmath/expressions/SimpleSymbolIndexer : space/kscience/kmath/expressions/SymbolIndexer {
|
|
||||||
public static final synthetic fun box-impl (Ljava/util/List;)Lspace/kscience/kmath/expressions/SimpleSymbolIndexer;
|
|
||||||
public static fun constructor-impl (Ljava/util/List;)Ljava/util/List;
|
|
||||||
public fun equals (Ljava/lang/Object;)Z
|
|
||||||
public static fun equals-impl (Ljava/util/List;Ljava/lang/Object;)Z
|
|
||||||
public static final fun equals-impl0 (Ljava/util/List;Ljava/util/List;)Z
|
|
||||||
public fun get (Ljava/util/List;Lspace/kscience/kmath/expressions/Symbol;)Ljava/lang/Object;
|
|
||||||
public fun get (Lspace/kscience/kmath/nd/Structure2D;Lspace/kscience/kmath/expressions/Symbol;Lspace/kscience/kmath/expressions/Symbol;)Ljava/lang/Object;
|
|
||||||
public fun get (Lspace/kscience/kmath/structures/Buffer;Lspace/kscience/kmath/expressions/Symbol;)Ljava/lang/Object;
|
|
||||||
public fun get ([DLspace/kscience/kmath/expressions/Symbol;)D
|
|
||||||
public fun get ([Ljava/lang/Object;Lspace/kscience/kmath/expressions/Symbol;)Ljava/lang/Object;
|
|
||||||
public static fun get-impl (Ljava/util/List;Ljava/util/List;Lspace/kscience/kmath/expressions/Symbol;)Ljava/lang/Object;
|
|
||||||
public static fun get-impl (Ljava/util/List;Lspace/kscience/kmath/nd/Structure2D;Lspace/kscience/kmath/expressions/Symbol;Lspace/kscience/kmath/expressions/Symbol;)Ljava/lang/Object;
|
|
||||||
public static fun get-impl (Ljava/util/List;Lspace/kscience/kmath/structures/Buffer;Lspace/kscience/kmath/expressions/Symbol;)Ljava/lang/Object;
|
|
||||||
public static fun get-impl (Ljava/util/List;[DLspace/kscience/kmath/expressions/Symbol;)D
|
|
||||||
public static fun get-impl (Ljava/util/List;[Ljava/lang/Object;Lspace/kscience/kmath/expressions/Symbol;)Ljava/lang/Object;
|
|
||||||
public fun getSymbols ()Ljava/util/List;
|
|
||||||
public fun hashCode ()I
|
|
||||||
public static fun hashCode-impl (Ljava/util/List;)I
|
|
||||||
public fun indexOf (Lspace/kscience/kmath/expressions/Symbol;)I
|
|
||||||
public static fun indexOf-impl (Ljava/util/List;Lspace/kscience/kmath/expressions/Symbol;)I
|
|
||||||
public fun toDoubleArray (Ljava/util/Map;)[D
|
|
||||||
public static fun toDoubleArray-impl (Ljava/util/List;Ljava/util/Map;)[D
|
|
||||||
public fun toList (Ljava/util/Map;)Ljava/util/List;
|
|
||||||
public static fun toList-impl (Ljava/util/List;Ljava/util/Map;)Ljava/util/List;
|
|
||||||
public fun toMap ([D)Ljava/util/Map;
|
|
||||||
public static fun toMap-impl (Ljava/util/List;[D)Ljava/util/Map;
|
|
||||||
public fun toPoint (Ljava/util/Map;Lkotlin/jvm/functions/Function2;)Lspace/kscience/kmath/structures/Buffer;
|
|
||||||
public static fun toPoint-impl (Ljava/util/List;Ljava/util/Map;Lkotlin/jvm/functions/Function2;)Lspace/kscience/kmath/structures/Buffer;
|
|
||||||
public fun toString ()Ljava/lang/String;
|
|
||||||
public static fun toString-impl (Ljava/util/List;)Ljava/lang/String;
|
|
||||||
public final synthetic fun unbox-impl ()Ljava/util/List;
|
|
||||||
}
|
|
||||||
|
|
||||||
public final class space/kscience/kmath/expressions/StringSymbol : space/kscience/kmath/expressions/Symbol {
|
|
||||||
public static final synthetic fun box-impl (Ljava/lang/String;)Lspace/kscience/kmath/expressions/StringSymbol;
|
|
||||||
public static fun constructor-impl (Ljava/lang/String;)Ljava/lang/String;
|
|
||||||
public fun equals (Ljava/lang/Object;)Z
|
|
||||||
public static fun equals-impl (Ljava/lang/String;Ljava/lang/Object;)Z
|
|
||||||
public static final fun equals-impl0 (Ljava/lang/String;Ljava/lang/String;)Z
|
|
||||||
public fun getIdentity ()Ljava/lang/String;
|
|
||||||
public fun hashCode ()I
|
|
||||||
public static fun hashCode-impl (Ljava/lang/String;)I
|
|
||||||
public fun toString ()Ljava/lang/String;
|
|
||||||
public static fun toString-impl (Ljava/lang/String;)Ljava/lang/String;
|
|
||||||
public final synthetic fun unbox-impl ()Ljava/lang/String;
|
|
||||||
}
|
|
||||||
|
|
||||||
public abstract interface class space/kscience/kmath/expressions/Symbol {
|
|
||||||
public abstract fun getIdentity ()Ljava/lang/String;
|
|
||||||
}
|
|
||||||
|
|
||||||
public abstract interface class space/kscience/kmath/expressions/SymbolIndexer {
|
|
||||||
public abstract fun get (Ljava/util/List;Lspace/kscience/kmath/expressions/Symbol;)Ljava/lang/Object;
|
|
||||||
public abstract fun get (Lspace/kscience/kmath/nd/Structure2D;Lspace/kscience/kmath/expressions/Symbol;Lspace/kscience/kmath/expressions/Symbol;)Ljava/lang/Object;
|
|
||||||
public abstract fun get (Lspace/kscience/kmath/structures/Buffer;Lspace/kscience/kmath/expressions/Symbol;)Ljava/lang/Object;
|
|
||||||
public abstract fun get ([DLspace/kscience/kmath/expressions/Symbol;)D
|
|
||||||
public abstract fun get ([Ljava/lang/Object;Lspace/kscience/kmath/expressions/Symbol;)Ljava/lang/Object;
|
|
||||||
public abstract fun getSymbols ()Ljava/util/List;
|
|
||||||
public abstract fun indexOf (Lspace/kscience/kmath/expressions/Symbol;)I
|
|
||||||
public abstract fun toDoubleArray (Ljava/util/Map;)[D
|
|
||||||
public abstract fun toList (Ljava/util/Map;)Ljava/util/List;
|
|
||||||
public abstract fun toMap ([D)Ljava/util/Map;
|
|
||||||
public abstract fun toPoint (Ljava/util/Map;Lkotlin/jvm/functions/Function2;)Lspace/kscience/kmath/structures/Buffer;
|
|
||||||
}
|
|
||||||
|
|
||||||
public final class space/kscience/kmath/expressions/SymbolIndexer$DefaultImpls {
|
public final class space/kscience/kmath/expressions/SymbolIndexer$DefaultImpls {
|
||||||
public static fun get (Lspace/kscience/kmath/expressions/SymbolIndexer;Ljava/util/List;Lspace/kscience/kmath/expressions/Symbol;)Ljava/lang/Object;
|
public static fun get (Lspace/kscience/kmath/expressions/SymbolIndexer;Ljava/util/List;Lspace/kscience/kmath/misc/Symbol;)Ljava/lang/Object;
|
||||||
public static fun get (Lspace/kscience/kmath/expressions/SymbolIndexer;Lspace/kscience/kmath/nd/Structure2D;Lspace/kscience/kmath/expressions/Symbol;Lspace/kscience/kmath/expressions/Symbol;)Ljava/lang/Object;
|
public static fun get (Lspace/kscience/kmath/expressions/SymbolIndexer;Lspace/kscience/kmath/nd/Structure2D;Lspace/kscience/kmath/misc/Symbol;Lspace/kscience/kmath/misc/Symbol;)Ljava/lang/Object;
|
||||||
public static fun get (Lspace/kscience/kmath/expressions/SymbolIndexer;Lspace/kscience/kmath/structures/Buffer;Lspace/kscience/kmath/expressions/Symbol;)Ljava/lang/Object;
|
public static fun get (Lspace/kscience/kmath/expressions/SymbolIndexer;Lspace/kscience/kmath/structures/Buffer;Lspace/kscience/kmath/misc/Symbol;)Ljava/lang/Object;
|
||||||
public static fun get (Lspace/kscience/kmath/expressions/SymbolIndexer;[DLspace/kscience/kmath/expressions/Symbol;)D
|
public static fun get (Lspace/kscience/kmath/expressions/SymbolIndexer;[DLspace/kscience/kmath/misc/Symbol;)D
|
||||||
public static fun get (Lspace/kscience/kmath/expressions/SymbolIndexer;[Ljava/lang/Object;Lspace/kscience/kmath/expressions/Symbol;)Ljava/lang/Object;
|
public static fun get (Lspace/kscience/kmath/expressions/SymbolIndexer;[Ljava/lang/Object;Lspace/kscience/kmath/misc/Symbol;)Ljava/lang/Object;
|
||||||
public static fun indexOf (Lspace/kscience/kmath/expressions/SymbolIndexer;Lspace/kscience/kmath/expressions/Symbol;)I
|
public static fun indexOf (Lspace/kscience/kmath/expressions/SymbolIndexer;Lspace/kscience/kmath/misc/Symbol;)I
|
||||||
public static fun toDoubleArray (Lspace/kscience/kmath/expressions/SymbolIndexer;Ljava/util/Map;)[D
|
public static fun toDoubleArray (Lspace/kscience/kmath/expressions/SymbolIndexer;Ljava/util/Map;)[D
|
||||||
public static fun toList (Lspace/kscience/kmath/expressions/SymbolIndexer;Ljava/util/Map;)Ljava/util/List;
|
public static fun toList (Lspace/kscience/kmath/expressions/SymbolIndexer;Ljava/util/Map;)Ljava/util/List;
|
||||||
public static fun toMap (Lspace/kscience/kmath/expressions/SymbolIndexer;[D)Ljava/util/Map;
|
public static fun toMap (Lspace/kscience/kmath/expressions/SymbolIndexer;[D)Ljava/util/Map;
|
||||||
@ -428,8 +376,6 @@ public final class space/kscience/kmath/expressions/SymbolIndexer$DefaultImpls {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public final class space/kscience/kmath/expressions/SymbolIndexerKt {
|
public final class space/kscience/kmath/expressions/SymbolIndexerKt {
|
||||||
public static final fun withSymbols (Ljava/util/Collection;Lkotlin/jvm/functions/Function1;)Ljava/lang/Object;
|
|
||||||
public static final fun withSymbols ([Lspace/kscience/kmath/expressions/Symbol;Lkotlin/jvm/functions/Function1;)Ljava/lang/Object;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public final class space/kscience/kmath/linear/BufferedLinearSpace : space/kscience/kmath/linear/LinearSpace {
|
public final class space/kscience/kmath/linear/BufferedLinearSpace : space/kscience/kmath/linear/LinearSpace {
|
||||||
@ -575,7 +521,7 @@ public final class space/kscience/kmath/linear/MatrixBuilderKt {
|
|||||||
public static final fun row (Lspace/kscience/kmath/linear/LinearSpace;[Ljava/lang/Object;)Lspace/kscience/kmath/nd/Structure2D;
|
public static final fun row (Lspace/kscience/kmath/linear/LinearSpace;[Ljava/lang/Object;)Lspace/kscience/kmath/nd/Structure2D;
|
||||||
}
|
}
|
||||||
|
|
||||||
public abstract interface class space/kscience/kmath/linear/MatrixFeature {
|
public abstract interface class space/kscience/kmath/linear/MatrixFeature : space/kscience/kmath/nd/StructureFeature {
|
||||||
}
|
}
|
||||||
|
|
||||||
public final class space/kscience/kmath/linear/MatrixFeaturesKt {
|
public final class space/kscience/kmath/linear/MatrixFeaturesKt {
|
||||||
@ -672,6 +618,35 @@ public final class space/kscience/kmath/misc/CumulativeKt {
|
|||||||
public static final fun cumulativeSumOfLong (Lkotlin/sequences/Sequence;)Lkotlin/sequences/Sequence;
|
public static final fun cumulativeSumOfLong (Lkotlin/sequences/Sequence;)Lkotlin/sequences/Sequence;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public final class space/kscience/kmath/misc/StringSymbol : space/kscience/kmath/misc/Symbol {
|
||||||
|
public static final synthetic fun box-impl (Ljava/lang/String;)Lspace/kscience/kmath/misc/StringSymbol;
|
||||||
|
public static fun constructor-impl (Ljava/lang/String;)Ljava/lang/String;
|
||||||
|
public fun equals (Ljava/lang/Object;)Z
|
||||||
|
public static fun equals-impl (Ljava/lang/String;Ljava/lang/Object;)Z
|
||||||
|
public static final fun equals-impl0 (Ljava/lang/String;Ljava/lang/String;)Z
|
||||||
|
public fun getIdentity ()Ljava/lang/String;
|
||||||
|
public fun hashCode ()I
|
||||||
|
public static fun hashCode-impl (Ljava/lang/String;)I
|
||||||
|
public fun toString ()Ljava/lang/String;
|
||||||
|
public static fun toString-impl (Ljava/lang/String;)Ljava/lang/String;
|
||||||
|
public final synthetic fun unbox-impl ()Ljava/lang/String;
|
||||||
|
}
|
||||||
|
|
||||||
|
public abstract interface class space/kscience/kmath/misc/Symbol {
|
||||||
|
public static final field Companion Lspace/kscience/kmath/misc/Symbol$Companion;
|
||||||
|
public abstract fun getIdentity ()Ljava/lang/String;
|
||||||
|
}
|
||||||
|
|
||||||
|
public final class space/kscience/kmath/misc/Symbol$Companion {
|
||||||
|
public final fun getX-tWtZOCg ()Ljava/lang/String;
|
||||||
|
public final fun getY-tWtZOCg ()Ljava/lang/String;
|
||||||
|
public final fun getZ-tWtZOCg ()Ljava/lang/String;
|
||||||
|
}
|
||||||
|
|
||||||
|
public final class space/kscience/kmath/misc/SymbolKt {
|
||||||
|
public static final fun getSymbol ()Lkotlin/properties/ReadOnlyProperty;
|
||||||
|
}
|
||||||
|
|
||||||
public abstract interface annotation class space/kscience/kmath/misc/UnstableKMathAPI : java/lang/annotation/Annotation {
|
public abstract interface annotation class space/kscience/kmath/misc/UnstableKMathAPI : java/lang/annotation/Annotation {
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1086,11 +1061,15 @@ public final class space/kscience/kmath/nd/Strides$DefaultImpls {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public abstract interface class space/kscience/kmath/nd/Structure1D : space/kscience/kmath/nd/StructureND, space/kscience/kmath/structures/Buffer {
|
public abstract interface class space/kscience/kmath/nd/Structure1D : space/kscience/kmath/nd/StructureND, space/kscience/kmath/structures/Buffer {
|
||||||
|
public static final field Companion Lspace/kscience/kmath/nd/Structure1D$Companion;
|
||||||
public abstract fun get ([I)Ljava/lang/Object;
|
public abstract fun get ([I)Ljava/lang/Object;
|
||||||
public abstract fun getDimension ()I
|
public abstract fun getDimension ()I
|
||||||
public abstract fun iterator ()Ljava/util/Iterator;
|
public abstract fun iterator ()Ljava/util/Iterator;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public final class space/kscience/kmath/nd/Structure1D$Companion {
|
||||||
|
}
|
||||||
|
|
||||||
public final class space/kscience/kmath/nd/Structure1D$DefaultImpls {
|
public final class space/kscience/kmath/nd/Structure1D$DefaultImpls {
|
||||||
public static fun get (Lspace/kscience/kmath/nd/Structure1D;[I)Ljava/lang/Object;
|
public static fun get (Lspace/kscience/kmath/nd/Structure1D;[I)Ljava/lang/Object;
|
||||||
public static fun getDimension (Lspace/kscience/kmath/nd/Structure1D;)I
|
public static fun getDimension (Lspace/kscience/kmath/nd/Structure1D;)I
|
||||||
@ -1132,6 +1111,9 @@ public final class space/kscience/kmath/nd/Structure2DKt {
|
|||||||
public static final fun as2D (Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/Structure2D;
|
public static final fun as2D (Lspace/kscience/kmath/nd/StructureND;)Lspace/kscience/kmath/nd/Structure2D;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public abstract interface class space/kscience/kmath/nd/StructureFeature {
|
||||||
|
}
|
||||||
|
|
||||||
public abstract interface class space/kscience/kmath/nd/StructureND {
|
public abstract interface class space/kscience/kmath/nd/StructureND {
|
||||||
public static final field Companion Lspace/kscience/kmath/nd/StructureND$Companion;
|
public static final field Companion Lspace/kscience/kmath/nd/StructureND$Companion;
|
||||||
public abstract fun elements ()Lkotlin/sequences/Sequence;
|
public abstract fun elements ()Lkotlin/sequences/Sequence;
|
||||||
@ -1201,7 +1183,7 @@ public final class space/kscience/kmath/operations/AlgebraExtensionsKt {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public final class space/kscience/kmath/operations/AlgebraKt {
|
public final class space/kscience/kmath/operations/AlgebraKt {
|
||||||
public static final fun bindSymbol (Lspace/kscience/kmath/operations/Algebra;Lspace/kscience/kmath/expressions/Symbol;)Ljava/lang/Object;
|
public static final fun bindSymbol (Lspace/kscience/kmath/operations/Algebra;Lspace/kscience/kmath/misc/Symbol;)Ljava/lang/Object;
|
||||||
public static final fun invoke (Lspace/kscience/kmath/operations/Algebra;Lkotlin/jvm/functions/Function1;)Ljava/lang/Object;
|
public static final fun invoke (Lspace/kscience/kmath/operations/Algebra;Lkotlin/jvm/functions/Function1;)Ljava/lang/Object;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2140,6 +2122,7 @@ public final class space/kscience/kmath/structures/BufferKt {
|
|||||||
public final class space/kscience/kmath/structures/BufferOperationKt {
|
public final class space/kscience/kmath/structures/BufferOperationKt {
|
||||||
public static final fun asIterable (Lspace/kscience/kmath/structures/Buffer;)Ljava/lang/Iterable;
|
public static final fun asIterable (Lspace/kscience/kmath/structures/Buffer;)Ljava/lang/Iterable;
|
||||||
public static final fun asSequence (Lspace/kscience/kmath/structures/Buffer;)Lkotlin/sequences/Sequence;
|
public static final fun asSequence (Lspace/kscience/kmath/structures/Buffer;)Lkotlin/sequences/Sequence;
|
||||||
|
public static final fun fold (Lspace/kscience/kmath/structures/Buffer;Ljava/lang/Object;Lkotlin/jvm/functions/Function2;)Ljava/lang/Object;
|
||||||
public static final fun toList (Lspace/kscience/kmath/structures/Buffer;)Ljava/util/List;
|
public static final fun toList (Lspace/kscience/kmath/structures/Buffer;)Ljava/util/List;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
# The Core Module (`kmath-core`)
|
# Module kmath-core
|
||||||
|
|
||||||
The core features of KMath:
|
The core interfaces of KMath.
|
||||||
|
|
||||||
${features}
|
${features}
|
||||||
|
|
||||||
|
@ -0,0 +1,34 @@
|
|||||||
|
package space.kscience.kmath.data
|
||||||
|
|
||||||
|
import space.kscience.kmath.misc.Symbol
|
||||||
|
import space.kscience.kmath.misc.UnstableKMathAPI
|
||||||
|
import space.kscience.kmath.nd.Structure2D
|
||||||
|
import space.kscience.kmath.structures.Buffer
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A column-based data set with all columns of the same size (not necessary fixed in time).
|
||||||
|
* The column could be retrieved by a [get] operation.
|
||||||
|
*/
|
||||||
|
@UnstableKMathAPI
|
||||||
|
public interface ColumnarData<out T> {
|
||||||
|
public val size: Int
|
||||||
|
|
||||||
|
public operator fun get(symbol: Symbol): Buffer<T>
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A zero-copy method to represent a [Structure2D] as a two-column x-y data.
|
||||||
|
* There could more than two columns in the structure.
|
||||||
|
*/
|
||||||
|
@UnstableKMathAPI
|
||||||
|
public fun <T> Structure2D<T>.asColumnarData(mapping: Map<Symbol, Int>): ColumnarData<T> {
|
||||||
|
require(shape[1] >= mapping.maxOf { it.value }) { "Column index out of bounds" }
|
||||||
|
return object : ColumnarData<T> {
|
||||||
|
override val size: Int get() = shape[0]
|
||||||
|
override fun get(symbol: Symbol): Buffer<T> {
|
||||||
|
val index = mapping[symbol] ?: error("No column mapping for symbol $symbol")
|
||||||
|
return columns[index]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,55 @@
|
|||||||
|
package space.kscience.kmath.data
|
||||||
|
|
||||||
|
import space.kscience.kmath.misc.Symbol
|
||||||
|
import space.kscience.kmath.misc.UnstableKMathAPI
|
||||||
|
import space.kscience.kmath.nd.Structure2D
|
||||||
|
import space.kscience.kmath.structures.Buffer
|
||||||
|
import kotlin.math.max
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The buffer of X values.
|
||||||
|
*/
|
||||||
|
@UnstableKMathAPI
|
||||||
|
public interface XYColumnarData<T, out X : T, out Y : T> : ColumnarData<T> {
|
||||||
|
/**
|
||||||
|
* The buffer of X values
|
||||||
|
*/
|
||||||
|
public val x: Buffer<X>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The buffer of Y values.
|
||||||
|
*/
|
||||||
|
public val y: Buffer<Y>
|
||||||
|
|
||||||
|
override fun get(symbol: Symbol): Buffer<T> = when (symbol) {
|
||||||
|
Symbol.x -> x
|
||||||
|
Symbol.y -> y
|
||||||
|
else -> error("A column for symbol $symbol not found")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Suppress("FunctionName")
|
||||||
|
@UnstableKMathAPI
|
||||||
|
public fun <T, X : T, Y : T> XYColumnarData(x: Buffer<X>, y: Buffer<Y>): XYColumnarData<T, X, Y> {
|
||||||
|
require(x.size == y.size) { "Buffer size mismatch. x buffer size is ${x.size}, y buffer size is ${y.size}" }
|
||||||
|
return object : XYColumnarData<T, X, Y> {
|
||||||
|
override val size: Int = x.size
|
||||||
|
override val x: Buffer<X> = x
|
||||||
|
override val y: Buffer<Y> = y
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A zero-copy method to represent a [Structure2D] as a two-column x-y data.
|
||||||
|
* There could more than two columns in the structure.
|
||||||
|
*/
|
||||||
|
@UnstableKMathAPI
|
||||||
|
public fun <T> Structure2D<T>.asXYData(xIndex: Int = 0, yIndex: Int = 1): XYColumnarData<T, T, T> {
|
||||||
|
require(shape[1] >= max(xIndex, yIndex)) { "Column index out of bounds" }
|
||||||
|
return object : XYColumnarData<T, T, T> {
|
||||||
|
override val size: Int get() = this@asXYData.shape[0]
|
||||||
|
override val x: Buffer<T> get() = columns[xIndex]
|
||||||
|
override val y: Buffer<T> get() = columns[yIndex]
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,21 @@
|
|||||||
|
package space.kscience.kmath.data
|
||||||
|
|
||||||
|
import space.kscience.kmath.misc.Symbol
|
||||||
|
import space.kscience.kmath.misc.UnstableKMathAPI
|
||||||
|
import space.kscience.kmath.structures.Buffer
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A [XYColumnarData] with guaranteed [x], [y] and [z] columns designated by corresponding symbols.
|
||||||
|
* Inherits [XYColumnarData].
|
||||||
|
*/
|
||||||
|
@UnstableKMathAPI
|
||||||
|
public interface XYZColumnarData<T, out X : T, out Y : T, out Z : T> : XYColumnarData<T, X, Y> {
|
||||||
|
public val z: Buffer<Z>
|
||||||
|
|
||||||
|
override fun get(symbol: Symbol): Buffer<T> = when (symbol) {
|
||||||
|
Symbol.x -> x
|
||||||
|
Symbol.y -> y
|
||||||
|
Symbol.z -> z
|
||||||
|
else -> error("A column for symbol $symbol not found")
|
||||||
|
}
|
||||||
|
}
|
@ -24,7 +24,6 @@ import space.kscience.kmath.misc.UnstableKMathAPI
|
|||||||
*/
|
*/
|
||||||
@UnstableKMathAPI
|
@UnstableKMathAPI
|
||||||
public interface DoubleDomain : Domain<Double> {
|
public interface DoubleDomain : Domain<Double> {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Global lower edge
|
* Global lower edge
|
||||||
* @param num axis number
|
* @param num axis number
|
||||||
|
@ -1,5 +1,8 @@
|
|||||||
package space.kscience.kmath.expressions
|
package space.kscience.kmath.expressions
|
||||||
|
|
||||||
|
import space.kscience.kmath.misc.StringSymbol
|
||||||
|
import space.kscience.kmath.misc.Symbol
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Represents expression which structure can be differentiated.
|
* Represents expression which structure can be differentiated.
|
||||||
*
|
*
|
||||||
|
@ -1,26 +1,11 @@
|
|||||||
package space.kscience.kmath.expressions
|
package space.kscience.kmath.expressions
|
||||||
|
|
||||||
|
import space.kscience.kmath.misc.StringSymbol
|
||||||
|
import space.kscience.kmath.misc.Symbol
|
||||||
import space.kscience.kmath.operations.Algebra
|
import space.kscience.kmath.operations.Algebra
|
||||||
import kotlin.jvm.JvmName
|
import kotlin.jvm.JvmName
|
||||||
import kotlin.properties.ReadOnlyProperty
|
import kotlin.properties.ReadOnlyProperty
|
||||||
|
|
||||||
/**
|
|
||||||
* A marker interface for a symbol. A symbol mus have an identity
|
|
||||||
*/
|
|
||||||
public interface Symbol {
|
|
||||||
/**
|
|
||||||
* Identity object for the symbol. Two symbols with the same identity are considered to be the same symbol.
|
|
||||||
*/
|
|
||||||
public val identity: String
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A [Symbol] with a [String] identity
|
|
||||||
*/
|
|
||||||
public inline class StringSymbol(override val identity: String) : Symbol {
|
|
||||||
override fun toString(): String = identity
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An elementary function that could be invoked on a map of arguments.
|
* An elementary function that could be invoked on a map of arguments.
|
||||||
*
|
*
|
||||||
@ -92,13 +77,6 @@ public interface ExpressionAlgebra<in T, E> : Algebra<E> {
|
|||||||
public fun <T, E> ExpressionAlgebra<T, E>.bindSymbol(symbol: Symbol): E =
|
public fun <T, E> ExpressionAlgebra<T, E>.bindSymbol(symbol: Symbol): E =
|
||||||
bindSymbolOrNull(symbol) ?: error("Symbol $symbol could not be bound to $this")
|
bindSymbolOrNull(symbol) ?: error("Symbol $symbol could not be bound to $this")
|
||||||
|
|
||||||
/**
|
|
||||||
* A delegate to create a symbol with a string identity in this scope
|
|
||||||
*/
|
|
||||||
public val symbol: ReadOnlyProperty<Any?, Symbol> = ReadOnlyProperty { _, property ->
|
|
||||||
StringSymbol(property.name)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Bind a symbol by name inside the [ExpressionAlgebra]
|
* Bind a symbol by name inside the [ExpressionAlgebra]
|
||||||
*/
|
*/
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
package space.kscience.kmath.expressions
|
package space.kscience.kmath.expressions
|
||||||
|
|
||||||
|
import space.kscience.kmath.misc.Symbol
|
||||||
import space.kscience.kmath.operations.*
|
import space.kscience.kmath.operations.*
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
package space.kscience.kmath.expressions
|
package space.kscience.kmath.expressions
|
||||||
|
|
||||||
import space.kscience.kmath.linear.Point
|
import space.kscience.kmath.linear.Point
|
||||||
|
import space.kscience.kmath.misc.Symbol
|
||||||
import space.kscience.kmath.misc.UnstableKMathAPI
|
import space.kscience.kmath.misc.UnstableKMathAPI
|
||||||
import space.kscience.kmath.operations.*
|
import space.kscience.kmath.operations.*
|
||||||
import space.kscience.kmath.structures.asBuffer
|
import space.kscience.kmath.structures.asBuffer
|
||||||
|
@ -1,6 +1,8 @@
|
|||||||
package space.kscience.kmath.expressions
|
package space.kscience.kmath.expressions
|
||||||
|
|
||||||
import space.kscience.kmath.linear.Point
|
import space.kscience.kmath.linear.Point
|
||||||
|
import space.kscience.kmath.misc.Symbol
|
||||||
|
import space.kscience.kmath.misc.UnstableKMathAPI
|
||||||
import space.kscience.kmath.nd.Structure2D
|
import space.kscience.kmath.nd.Structure2D
|
||||||
import space.kscience.kmath.structures.BufferFactory
|
import space.kscience.kmath.structures.BufferFactory
|
||||||
|
|
||||||
@ -8,6 +10,7 @@ import space.kscience.kmath.structures.BufferFactory
|
|||||||
* An environment to easy transform indexed variables to symbols and back.
|
* An environment to easy transform indexed variables to symbols and back.
|
||||||
* TODO requires multi-receivers to be beautiful
|
* TODO requires multi-receivers to be beautiful
|
||||||
*/
|
*/
|
||||||
|
@UnstableKMathAPI
|
||||||
public interface SymbolIndexer {
|
public interface SymbolIndexer {
|
||||||
public val symbols: List<Symbol>
|
public val symbols: List<Symbol>
|
||||||
public fun indexOf(symbol: Symbol): Int = symbols.indexOf(symbol)
|
public fun indexOf(symbol: Symbol): Int = symbols.indexOf(symbol)
|
||||||
@ -49,13 +52,16 @@ public interface SymbolIndexer {
|
|||||||
public fun Map<Symbol, Double>.toDoubleArray(): DoubleArray = DoubleArray(symbols.size) { getValue(symbols[it]) }
|
public fun Map<Symbol, Double>.toDoubleArray(): DoubleArray = DoubleArray(symbols.size) { getValue(symbols[it]) }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@UnstableKMathAPI
|
||||||
public inline class SimpleSymbolIndexer(override val symbols: List<Symbol>) : SymbolIndexer
|
public inline class SimpleSymbolIndexer(override val symbols: List<Symbol>) : SymbolIndexer
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Execute the block with symbol indexer based on given symbol order
|
* Execute the block with symbol indexer based on given symbol order
|
||||||
*/
|
*/
|
||||||
|
@UnstableKMathAPI
|
||||||
public inline fun <R> withSymbols(vararg symbols: Symbol, block: SymbolIndexer.() -> R): R =
|
public inline fun <R> withSymbols(vararg symbols: Symbol, block: SymbolIndexer.() -> R): R =
|
||||||
with(SimpleSymbolIndexer(symbols.toList()), block)
|
with(SimpleSymbolIndexer(symbols.toList()), block)
|
||||||
|
|
||||||
|
@UnstableKMathAPI
|
||||||
public inline fun <R> withSymbols(symbols: Collection<Symbol>, block: SymbolIndexer.() -> R): R =
|
public inline fun <R> withSymbols(symbols: Collection<Symbol>, block: SymbolIndexer.() -> R): R =
|
||||||
with(SimpleSymbolIndexer(symbols.toList()), block)
|
with(SimpleSymbolIndexer(symbols.toList()), block)
|
@ -3,7 +3,10 @@ package space.kscience.kmath.linear
|
|||||||
import space.kscience.kmath.nd.as1D
|
import space.kscience.kmath.nd.as1D
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A group of methods to resolve equation A dot X = B, where A and B are matrices or vectors
|
* A group of methods to solve for *X* in equation *X = A <sup>-1</sup> · B*, where *A* and *B* are matrices or
|
||||||
|
* vectors.
|
||||||
|
*
|
||||||
|
* @param T the type of items.
|
||||||
*/
|
*/
|
||||||
public interface LinearSolver<T : Any> {
|
public interface LinearSolver<T : Any> {
|
||||||
/**
|
/**
|
||||||
@ -23,7 +26,7 @@ public interface LinearSolver<T : Any> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Convert matrix to vector if it is possible
|
* Convert matrix to vector if it is possible.
|
||||||
*/
|
*/
|
||||||
public fun <T : Any> Matrix<T>.asVector(): Point<T> =
|
public fun <T : Any> Matrix<T>.asVector(): Point<T> =
|
||||||
if (this.colNum == 1)
|
if (this.colNum == 1)
|
||||||
@ -31,4 +34,11 @@ public fun <T : Any> Matrix<T>.asVector(): Point<T> =
|
|||||||
else
|
else
|
||||||
error("Can't convert matrix with more than one column to vector")
|
error("Can't convert matrix with more than one column to vector")
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates an n × 1 [VirtualMatrix], where n is the size of the given buffer.
|
||||||
|
*
|
||||||
|
* @param T the type of elements contained in the buffer.
|
||||||
|
* @receiver a buffer.
|
||||||
|
* @return the new matrix.
|
||||||
|
*/
|
||||||
public fun <T : Any> Point<T>.asMatrix(): VirtualMatrix<T> = VirtualMatrix(size, 1) { i, _ -> get(i) }
|
public fun <T : Any> Point<T>.asMatrix(): VirtualMatrix<T> = VirtualMatrix(size, 1) { i, _ -> get(i) }
|
||||||
|
@ -18,6 +18,8 @@ public typealias MutableMatrix<T> = MutableStructure2D<T>
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Alias or using [Buffer] as a point/vector in a many-dimensional space.
|
* Alias or using [Buffer] as a point/vector in a many-dimensional space.
|
||||||
|
*
|
||||||
|
* @param T the type of elements contained in the buffer.
|
||||||
*/
|
*/
|
||||||
public typealias Point<T> = Buffer<T>
|
public typealias Point<T> = Buffer<T>
|
||||||
|
|
||||||
@ -165,7 +167,7 @@ public interface LinearSpace<T : Any, out A : Ring<T>> {
|
|||||||
* @return a feature object or `null` if it isn't present.
|
* @return a feature object or `null` if it isn't present.
|
||||||
*/
|
*/
|
||||||
@UnstableKMathAPI
|
@UnstableKMathAPI
|
||||||
public fun <F : Any> getFeature(structure: Matrix<T>, type: KClass<F>): F? = structure.getFeature(type)
|
public fun <F : StructureFeature> getFeature(structure: Matrix<T>, type: KClass<out F>): F? = structure.getFeature(type)
|
||||||
|
|
||||||
public companion object {
|
public companion object {
|
||||||
|
|
||||||
@ -195,7 +197,7 @@ public interface LinearSpace<T : Any, out A : Ring<T>> {
|
|||||||
* @return a feature object or `null` if it isn't present.
|
* @return a feature object or `null` if it isn't present.
|
||||||
*/
|
*/
|
||||||
@UnstableKMathAPI
|
@UnstableKMathAPI
|
||||||
public inline fun <T : Any, reified F : Any> LinearSpace<T, *>.getFeature(structure: Matrix<T>): F? =
|
public inline fun <T : Any, reified F : StructureFeature> LinearSpace<T, *>.getFeature(structure: Matrix<T>): F? =
|
||||||
getFeature(structure, F::class)
|
getFeature(structure, F::class)
|
||||||
|
|
||||||
|
|
||||||
|
@ -1,10 +1,12 @@
|
|||||||
package space.kscience.kmath.linear
|
package space.kscience.kmath.linear
|
||||||
|
|
||||||
|
import space.kscience.kmath.nd.StructureFeature
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A marker interface representing some properties of matrices or additional transformations of them. Features are used
|
* A marker interface representing some properties of matrices or additional transformations of them. Features are used
|
||||||
* to optimize matrix operations performance in some cases or retrieve the APIs.
|
* to optimize matrix operations performance in some cases or retrieve the APIs.
|
||||||
*/
|
*/
|
||||||
public interface MatrixFeature
|
public interface MatrixFeature: StructureFeature
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Matrices with this feature are considered to have only diagonal non-null elements.
|
* Matrices with this feature are considered to have only diagonal non-null elements.
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
package space.kscience.kmath.linear
|
package space.kscience.kmath.linear
|
||||||
|
|
||||||
import space.kscience.kmath.misc.UnstableKMathAPI
|
import space.kscience.kmath.misc.UnstableKMathAPI
|
||||||
|
import space.kscience.kmath.nd.StructureFeature
|
||||||
import space.kscience.kmath.nd.getFeature
|
import space.kscience.kmath.nd.getFeature
|
||||||
import space.kscience.kmath.operations.Ring
|
import space.kscience.kmath.operations.Ring
|
||||||
import kotlin.reflect.KClass
|
import kotlin.reflect.KClass
|
||||||
@ -20,7 +21,7 @@ public class MatrixWrapper<T : Any> internal constructor(
|
|||||||
*/
|
*/
|
||||||
@UnstableKMathAPI
|
@UnstableKMathAPI
|
||||||
@Suppress("UNCHECKED_CAST")
|
@Suppress("UNCHECKED_CAST")
|
||||||
override fun <T : Any> getFeature(type: KClass<T>): T? = features.singleOrNull { type.isInstance(it) } as? T
|
override fun <F : StructureFeature> getFeature(type: KClass<out F>): F? = features.singleOrNull { type.isInstance(it) } as? F
|
||||||
?: origin.getFeature(type)
|
?: origin.getFeature(type)
|
||||||
|
|
||||||
override fun toString(): String {
|
override fun toString(): String {
|
||||||
|
@ -0,0 +1,34 @@
|
|||||||
|
package space.kscience.kmath.misc
|
||||||
|
|
||||||
|
import kotlin.properties.ReadOnlyProperty
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A marker interface for a symbol. A symbol mus have an identity
|
||||||
|
*/
|
||||||
|
public interface Symbol {
|
||||||
|
/**
|
||||||
|
* Identity object for the symbol. Two symbols with the same identity are considered to be the same symbol.
|
||||||
|
*/
|
||||||
|
public val identity: String
|
||||||
|
|
||||||
|
public companion object{
|
||||||
|
public val x: StringSymbol = StringSymbol("x")
|
||||||
|
public val y: StringSymbol = StringSymbol("y")
|
||||||
|
public val z: StringSymbol = StringSymbol("z")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A [Symbol] with a [String] identity
|
||||||
|
*/
|
||||||
|
public inline class StringSymbol(override val identity: String) : Symbol {
|
||||||
|
override fun toString(): String = identity
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A delegate to create a symbol with a string identity in this scope
|
||||||
|
*/
|
||||||
|
public val symbol: ReadOnlyProperty<Any?, Symbol> = ReadOnlyProperty { _, property ->
|
||||||
|
StringSymbol(property.name)
|
||||||
|
}
|
@ -67,7 +67,8 @@ public interface AlgebraND<T, C : Algebra<T>> {
|
|||||||
* @return a feature object or `null` if it isn't present.
|
* @return a feature object or `null` if it isn't present.
|
||||||
*/
|
*/
|
||||||
@UnstableKMathAPI
|
@UnstableKMathAPI
|
||||||
public fun <F : Any> getFeature(structure: StructureND<T>, type: KClass<F>): F? = structure.getFeature(type)
|
public fun <F : StructureFeature> getFeature(structure: StructureND<T>, type: KClass<out F>): F? =
|
||||||
|
structure.getFeature(type)
|
||||||
|
|
||||||
public companion object
|
public companion object
|
||||||
}
|
}
|
||||||
@ -81,7 +82,7 @@ public interface AlgebraND<T, C : Algebra<T>> {
|
|||||||
* @return a feature object or `null` if it isn't present.
|
* @return a feature object or `null` if it isn't present.
|
||||||
*/
|
*/
|
||||||
@UnstableKMathAPI
|
@UnstableKMathAPI
|
||||||
public inline fun <T : Any, reified F : Any> AlgebraND<T, *>.getFeature(structure: StructureND<T>): F? =
|
public inline fun <T : Any, reified F : StructureFeature> AlgebraND<T, *>.getFeature(structure: StructureND<T>): F? =
|
||||||
getFeature(structure, F::class)
|
getFeature(structure, F::class)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -17,6 +17,8 @@ public interface Structure1D<T> : StructureND<T>, Buffer<T> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public override operator fun iterator(): Iterator<T> = (0 until size).asSequence().map(::get).iterator()
|
public override operator fun iterator(): Iterator<T> = (0 until size).asSequence().map(::get).iterator()
|
||||||
|
|
||||||
|
public companion object
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -97,7 +97,7 @@ private inline class Structure2DWrapper<T>(val structure: StructureND<T>) : Stru
|
|||||||
override operator fun get(i: Int, j: Int): T = structure[i, j]
|
override operator fun get(i: Int, j: Int): T = structure[i, j]
|
||||||
|
|
||||||
@UnstableKMathAPI
|
@UnstableKMathAPI
|
||||||
override fun <F : Any> getFeature(type: KClass<F>): F? = structure.getFeature(type)
|
override fun <F : StructureFeature> getFeature(type: KClass<out F>): F? = structure.getFeature(type)
|
||||||
|
|
||||||
override fun elements(): Sequence<Pair<IntArray, T>> = structure.elements()
|
override fun elements(): Sequence<Pair<IntArray, T>> = structure.elements()
|
||||||
}
|
}
|
||||||
|
@ -7,6 +7,8 @@ import kotlin.jvm.JvmName
|
|||||||
import kotlin.native.concurrent.ThreadLocal
|
import kotlin.native.concurrent.ThreadLocal
|
||||||
import kotlin.reflect.KClass
|
import kotlin.reflect.KClass
|
||||||
|
|
||||||
|
public interface StructureFeature
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Represents n-dimensional structure, i.e. multidimensional container of items of the same type and size. The number
|
* Represents n-dimensional structure, i.e. multidimensional container of items of the same type and size. The number
|
||||||
* of dimensions and items in an array is defined by its shape, which is a sequence of non-negative integers that
|
* of dimensions and items in an array is defined by its shape, which is a sequence of non-negative integers that
|
||||||
@ -48,7 +50,7 @@ public interface StructureND<T> {
|
|||||||
* If the feature is not present, null is returned.
|
* If the feature is not present, null is returned.
|
||||||
*/
|
*/
|
||||||
@UnstableKMathAPI
|
@UnstableKMathAPI
|
||||||
public fun <F : Any> getFeature(type: KClass<F>): F? = null
|
public fun <F : StructureFeature> getFeature(type: KClass<out F>): F? = null
|
||||||
|
|
||||||
public companion object {
|
public companion object {
|
||||||
/**
|
/**
|
||||||
@ -144,7 +146,7 @@ public interface StructureND<T> {
|
|||||||
public operator fun <T> StructureND<T>.get(vararg index: Int): T = get(index)
|
public operator fun <T> StructureND<T>.get(vararg index: Int): T = get(index)
|
||||||
|
|
||||||
@UnstableKMathAPI
|
@UnstableKMathAPI
|
||||||
public inline fun <reified T : Any> StructureND<*>.getFeature(): T? = getFeature(T::class)
|
public inline fun <reified T : StructureFeature> StructureND<*>.getFeature(): T? = getFeature(T::class)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Represents mutable [StructureND].
|
* Represents mutable [StructureND].
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
package space.kscience.kmath.operations
|
package space.kscience.kmath.operations
|
||||||
|
|
||||||
import space.kscience.kmath.expressions.Symbol
|
import space.kscience.kmath.misc.Symbol
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Stub for DSL the [Algebra] is.
|
* Stub for DSL the [Algebra] is.
|
||||||
@ -100,8 +100,8 @@ public fun <T : Any> Algebra<T>.bindSymbol(symbol: Symbol): T = bindSymbol(symbo
|
|||||||
public inline operator fun <A : Algebra<*>, R> A.invoke(block: A.() -> R): R = run(block)
|
public inline operator fun <A : Algebra<*>, R> A.invoke(block: A.() -> R): R = run(block)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Represents linear space without neutral element, i.e. algebraic structure with associative, binary operation [add]
|
* Represents group without neutral element (also known as inverse semigroup), i.e. algebraic structure with
|
||||||
* and scalar multiplication [multiply].
|
* associative, binary operation [add].
|
||||||
*
|
*
|
||||||
* @param T the type of element of this semispace.
|
* @param T the type of element of this semispace.
|
||||||
*/
|
*/
|
||||||
@ -177,7 +177,7 @@ public interface GroupOperations<T> : Algebra<T> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Represents linear space with neutral element, i.e. algebraic structure with associative, binary operation [add].
|
* Represents group, i.e. algebraic structure with associative, binary operation [add].
|
||||||
*
|
*
|
||||||
* @param T the type of element of this semispace.
|
* @param T the type of element of this semispace.
|
||||||
*/
|
*/
|
||||||
@ -189,8 +189,8 @@ public interface Group<T> : GroupOperations<T> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Represents rng, i.e. algebraic structure with associative, binary, commutative operation [add] and associative,
|
* Represents ring without multiplicative and additive identities, i.e. algebraic structure with
|
||||||
* operation [multiply] distributive over [add].
|
* associative, binary, commutative operation [add] and associative, operation [multiply] distributive over [add].
|
||||||
*
|
*
|
||||||
* @param T the type of element of this semiring.
|
* @param T the type of element of this semiring.
|
||||||
*/
|
*/
|
||||||
@ -238,7 +238,7 @@ public interface Ring<T> : Group<T>, RingOperations<T> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Represents field without identity elements, i.e. algebraic structure with associative, binary, commutative operations
|
* Represents field without without multiplicative and additive identities, i.e. algebraic structure with associative, binary, commutative operations
|
||||||
* [add] and [multiply]; binary operation [divide] as multiplication of left operand by reciprocal of right one.
|
* [add] and [multiply]; binary operation [divide] as multiplication of left operand by reciprocal of right one.
|
||||||
*
|
*
|
||||||
* @param T the type of element of this semifield.
|
* @param T the type of element of this semifield.
|
||||||
@ -276,10 +276,11 @@ public interface FieldOperations<T> : RingOperations<T> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Represents field, i.e. algebraic structure with three operations: associative "addition" and "multiplication",
|
* Represents field, i.e. algebraic structure with three operations: associative, commutative addition and
|
||||||
* and "division" and their neutral elements.
|
* multiplication, and division. **This interface differs from the eponymous mathematical definition: fields in KMath
|
||||||
|
* also support associative multiplication by scalar.**
|
||||||
*
|
*
|
||||||
* @param T the type of element of this semifield.
|
* @param T the type of element of this field.
|
||||||
*/
|
*/
|
||||||
public interface Field<T> : Ring<T>, FieldOperations<T>, ScaleOperations<T>, NumericAlgebra<T> {
|
public interface Field<T> : Ring<T>, FieldOperations<T>, ScaleOperations<T>, NumericAlgebra<T> {
|
||||||
override fun number(value: Number): T = scale(one, value.toDouble())
|
override fun number(value: Number): T = scale(one, value.toDouble())
|
||||||
|
@ -12,8 +12,8 @@ import kotlin.math.max
|
|||||||
import kotlin.math.min
|
import kotlin.math.min
|
||||||
import kotlin.math.sign
|
import kotlin.math.sign
|
||||||
|
|
||||||
public typealias Magnitude = UIntArray
|
private typealias Magnitude = UIntArray
|
||||||
public typealias TBase = ULong
|
private typealias TBase = ULong
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Kotlin Multiplatform implementation of Big Integer numbers (KBigInteger).
|
* Kotlin Multiplatform implementation of Big Integer numbers (KBigInteger).
|
||||||
@ -241,18 +241,18 @@ public class BigInt internal constructor(
|
|||||||
)
|
)
|
||||||
|
|
||||||
private fun compareMagnitudes(mag1: Magnitude, mag2: Magnitude): Int {
|
private fun compareMagnitudes(mag1: Magnitude, mag2: Magnitude): Int {
|
||||||
when {
|
return when {
|
||||||
mag1.size > mag2.size -> return 1
|
mag1.size > mag2.size -> 1
|
||||||
mag1.size < mag2.size -> return -1
|
mag1.size < mag2.size -> -1
|
||||||
|
|
||||||
else -> {
|
else -> {
|
||||||
for (i in mag1.size - 1 downTo 0) {
|
for (i in mag1.size - 1 downTo 0) return when {
|
||||||
if (mag1[i] > mag2[i]) {
|
mag1[i] > mag2[i] -> 1
|
||||||
return 1
|
mag1[i] < mag2[i] -> -1
|
||||||
} else if (mag1[i] < mag2[i]) {
|
else -> continue
|
||||||
return -1
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
return 0
|
0
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -302,10 +302,11 @@ public class BigInt internal constructor(
|
|||||||
var carry = 0uL
|
var carry = 0uL
|
||||||
|
|
||||||
for (i in mag.indices) {
|
for (i in mag.indices) {
|
||||||
val cur: ULong = carry + mag[i].toULong() * x.toULong()
|
val cur = carry + mag[i].toULong() * x.toULong()
|
||||||
result[i] = (cur and BASE).toUInt()
|
result[i] = (cur and BASE).toUInt()
|
||||||
carry = cur shr BASE_SIZE
|
carry = cur shr BASE_SIZE
|
||||||
}
|
}
|
||||||
|
|
||||||
result[resultLength - 1] = (carry and BASE).toUInt()
|
result[resultLength - 1] = (carry and BASE).toUInt()
|
||||||
|
|
||||||
return stripLeadingZeros(result)
|
return stripLeadingZeros(result)
|
||||||
@ -358,6 +359,9 @@ private fun stripLeadingZeros(mag: Magnitude): Magnitude {
|
|||||||
return mag.sliceArray(IntRange(0, resSize))
|
return mag.sliceArray(IntRange(0, resSize))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the absolute value of the given value [x].
|
||||||
|
*/
|
||||||
public fun abs(x: BigInt): BigInt = x.abs()
|
public fun abs(x: BigInt): BigInt = x.abs()
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -40,7 +40,6 @@ public interface Buffer<out T> {
|
|||||||
public operator fun iterator(): Iterator<T>
|
public operator fun iterator(): Iterator<T>
|
||||||
|
|
||||||
public companion object {
|
public companion object {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Check the element-by-element match of content of two buffers.
|
* Check the element-by-element match of content of two buffers.
|
||||||
*/
|
*/
|
||||||
@ -110,7 +109,6 @@ public interface MutableBuffer<T> : Buffer<T> {
|
|||||||
public fun copy(): MutableBuffer<T>
|
public fun copy(): MutableBuffer<T>
|
||||||
|
|
||||||
public companion object {
|
public companion object {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a [DoubleBuffer] with the specified [size], where each element is calculated by calling the specified
|
* Creates a [DoubleBuffer] with the specified [size], where each element is calculated by calling the specified
|
||||||
* [initializer] function.
|
* [initializer] function.
|
||||||
|
@ -70,6 +70,15 @@ public inline fun <T : Any, reified R : Any> Buffer<T>.mapIndexed(
|
|||||||
crossinline block: (index: Int, value: T) -> R,
|
crossinline block: (index: Int, value: T) -> R,
|
||||||
): Buffer<R> = bufferFactory(size) { block(it, get(it)) }
|
): Buffer<R> = bufferFactory(size) { block(it, get(it)) }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fold given buffer according to [operation]
|
||||||
|
*/
|
||||||
|
public inline fun <T : Any, R> Buffer<T>.fold(initial: R, operation: (acc: R, T) -> R): R {
|
||||||
|
var accumulator = initial
|
||||||
|
for (index in this.indices) accumulator = operation(accumulator, get(index))
|
||||||
|
return accumulator
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Zip two buffers using given [transform].
|
* Zip two buffers using given [transform].
|
||||||
*/
|
*/
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
package space.kscience.kmath.expressions
|
package space.kscience.kmath.expressions
|
||||||
|
|
||||||
|
import space.kscience.kmath.misc.symbol
|
||||||
import space.kscience.kmath.operations.DoubleField
|
import space.kscience.kmath.operations.DoubleField
|
||||||
import space.kscience.kmath.operations.invoke
|
import space.kscience.kmath.operations.invoke
|
||||||
import kotlin.test.Test
|
import kotlin.test.Test
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
package space.kscience.kmath.expressions
|
package space.kscience.kmath.expressions
|
||||||
|
|
||||||
|
import space.kscience.kmath.misc.Symbol
|
||||||
|
import space.kscience.kmath.misc.symbol
|
||||||
import space.kscience.kmath.operations.DoubleField
|
import space.kscience.kmath.operations.DoubleField
|
||||||
import space.kscience.kmath.structures.Buffer
|
import space.kscience.kmath.structures.Buffer
|
||||||
import space.kscience.kmath.structures.asBuffer
|
import space.kscience.kmath.structures.asBuffer
|
||||||
|
@ -38,13 +38,12 @@ class NumberNDFieldTest {
|
|||||||
(i * 10 + j).toDouble()
|
(i * 10 + j).toDouble()
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i in 0..2) {
|
for (i in 0..2)
|
||||||
for (j in 0..2) {
|
for (j in 0..2) {
|
||||||
val expected = (i * 10 + j).toDouble()
|
val expected = (i * 10 + j).toDouble()
|
||||||
assertEquals(expected, array[i, j], "Error at index [$i, $j]")
|
assertEquals(expected, array[i, j], "Error at index [$i, $j]")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun testExternalFunction() {
|
fun testExternalFunction() {
|
||||||
|
@ -1,12 +1,13 @@
|
|||||||
package space.kscience.kmath.chains
|
package space.kscience.kmath.chains
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Performance optimized chain for real values
|
* Chunked, specialized chain for real values.
|
||||||
*/
|
*/
|
||||||
public abstract class BlockingDoubleChain : Chain<Double> {
|
public interface BlockingDoubleChain : Chain<Double> {
|
||||||
public abstract fun nextDouble(): Double
|
public override suspend fun next(): Double
|
||||||
|
|
||||||
override suspend fun next(): Double = nextDouble()
|
/**
|
||||||
|
* Returns an [DoubleArray] chunk of [size] values of [next].
|
||||||
public fun nextBlock(size: Int): DoubleArray = DoubleArray(size) { nextDouble() }
|
*/
|
||||||
|
public suspend fun nextBlock(size: Int): DoubleArray = DoubleArray(size) { next() }
|
||||||
}
|
}
|
||||||
|
@ -3,10 +3,7 @@ package space.kscience.kmath.chains
|
|||||||
/**
|
/**
|
||||||
* Performance optimized chain for integer values
|
* Performance optimized chain for integer values
|
||||||
*/
|
*/
|
||||||
public abstract class BlockingIntChain : Chain<Int> {
|
public interface BlockingIntChain : Chain<Int> {
|
||||||
public abstract fun nextInt(): Int
|
public override suspend fun next(): Int
|
||||||
|
public suspend fun nextBlock(size: Int): IntArray = IntArray(size) { next() }
|
||||||
override suspend fun next(): Int = nextInt()
|
|
||||||
|
|
||||||
public fun nextBlock(size: Int): IntArray = IntArray(size) { nextInt() }
|
|
||||||
}
|
}
|
||||||
|
@ -63,12 +63,10 @@ public class MarkovChain<out R : Any>(private val seed: suspend () -> R, private
|
|||||||
|
|
||||||
public fun value(): R? = value
|
public fun value(): R? = value
|
||||||
|
|
||||||
public 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
|
||||||
return newValue
|
newValue
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public override fun fork(): Chain<R> = MarkovChain(seed = { value ?: seed() }, gen = gen)
|
public override fun fork(): Chain<R> = MarkovChain(seed = { value ?: seed() }, gen = gen)
|
||||||
@ -90,12 +88,10 @@ public class StatefulChain<S, out R>(
|
|||||||
|
|
||||||
public fun value(): R? = value
|
public fun value(): R? = value
|
||||||
|
|
||||||
public 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
|
||||||
return newValue
|
newValue
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public override fun fork(): Chain<R> = StatefulChain(forkState(state), seed, forkState, gen)
|
public override fun fork(): Chain<R> = StatefulChain(forkState(state), seed, forkState, gen)
|
||||||
|
@ -28,7 +28,7 @@ public fun <T> Flow<T>.chunked(bufferSize: Int, bufferFactory: BufferFactory<T>)
|
|||||||
var counter = 0
|
var counter = 0
|
||||||
|
|
||||||
this@chunked.collect { element ->
|
this@chunked.collect { element ->
|
||||||
list.add(element)
|
list += element
|
||||||
counter++
|
counter++
|
||||||
|
|
||||||
if (counter == bufferSize) {
|
if (counter == bufferSize) {
|
||||||
|
@ -48,11 +48,9 @@ public class RingBuffer<T>(
|
|||||||
/**
|
/**
|
||||||
* A safe snapshot operation
|
* A safe snapshot operation
|
||||||
*/
|
*/
|
||||||
public suspend fun snapshot(): Buffer<T> {
|
public suspend fun snapshot(): Buffer<T> = mutex.withLock {
|
||||||
mutex.withLock {
|
|
||||||
val copy = buffer.copy()
|
val copy = buffer.copy()
|
||||||
return VirtualBuffer(size) { i -> copy[startIndex.forward(i)] as T }
|
VirtualBuffer(size) { i -> copy[startIndex.forward(i)] as T }
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public suspend fun push(element: T) {
|
public suspend fun push(element: T) {
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
package kscience.dimensions
|
package space.kscience.dimensions
|
||||||
|
|
||||||
import space.kscience.kmath.dimensions.D2
|
import space.kscience.kmath.dimensions.D2
|
||||||
import space.kscience.kmath.dimensions.D3
|
import space.kscience.kmath.dimensions.D3
|
||||||
|
@ -1,43 +1,37 @@
|
|||||||
# ejml-simple support (`kmath-ejml`)
|
# Module kmath-ejml
|
||||||
|
|
||||||
This subproject implements the following features:
|
EJML based linear algebra implementation.
|
||||||
|
|
||||||
- [ejml-vector](src/main/kotlin/space/kscience/kmath/ejml/EjmlVector.kt) : The Point implementation using SimpleMatrix.
|
- [ejml-vector](src/main/kotlin/space/kscience/kmath/ejml/EjmlVector.kt) : The Point implementation using SimpleMatrix.
|
||||||
- [ejml-matrix](src/main/kotlin/space/kscience/kmath/ejml/EjmlMatrix.kt) : The Matrix implementation using SimpleMatrix.
|
- [ejml-matrix](src/main/kotlin/space/kscience/kmath/ejml/EjmlMatrix.kt) : The Matrix implementation using SimpleMatrix.
|
||||||
- [ejml-linear-space](src/main/kotlin/space/kscience/kmath/ejml/EjmlLinearSpace.kt) : The LinearSpace implementation using SimpleMatrix.
|
- [ejml-linear-space](src/main/kotlin/space/kscience/kmath/ejml/EjmlLinearSpace.kt) : The LinearSpace implementation using SimpleMatrix.
|
||||||
|
|
||||||
|
|
||||||
> #### Artifact:
|
## Artifact:
|
||||||
>
|
|
||||||
> This module artifact: `space.kscience:kmath-ejml:0.3.0-dev-3`.
|
The Maven coordinates of this project are `space.kscience:kmath-ejml:0.3.0-dev-3`.
|
||||||
>
|
|
||||||
> Bintray release version: [ ![Download](https://api.bintray.com/packages/mipt-npm/kscience/kmath-ejml/images/download.svg) ](https://bintray.com/mipt-npm/kscience/kmath-ejml/_latestVersion)
|
**Gradle:**
|
||||||
>
|
```gradle
|
||||||
> Bintray development version: [ ![Download](https://api.bintray.com/packages/mipt-npm/dev/kmath-ejml/images/download.svg) ](https://bintray.com/mipt-npm/dev/kmath-ejml/_latestVersion)
|
repositories {
|
||||||
>
|
maven { url 'https://repo.kotlin.link' }
|
||||||
> **Gradle:**
|
maven { url 'https://dl.bintray.com/hotkeytlt/maven' }
|
||||||
>
|
maven { url "https://dl.bintray.com/kotlin/kotlin-eap" } // include for builds based on kotlin-eap
|
||||||
> ```gradle
|
}
|
||||||
> repositories {
|
|
||||||
> maven { url 'https://repo.kotlin.link' }
|
dependencies {
|
||||||
> maven { url 'https://dl.bintray.com/hotkeytlt/maven' }
|
implementation 'space.kscience:kmath-ejml:0.3.0-dev-3'
|
||||||
> maven { url "https://dl.bintray.com/kotlin/kotlin-eap" } // include for builds based on kotlin-eap
|
}
|
||||||
> }
|
```
|
||||||
>
|
**Gradle Kotlin DSL:**
|
||||||
> dependencies {
|
```kotlin
|
||||||
> implementation 'space.kscience:kmath-ejml:0.3.0-dev-3'
|
repositories {
|
||||||
> }
|
maven("https://repo.kotlin.link")
|
||||||
> ```
|
maven("https://dl.bintray.com/kotlin/kotlin-eap") // include for builds based on kotlin-eap
|
||||||
> **Gradle Kotlin DSL:**
|
maven("https://dl.bintray.com/hotkeytlt/maven") // required for a
|
||||||
>
|
}
|
||||||
> ```kotlin
|
|
||||||
> repositories {
|
dependencies {
|
||||||
> maven("https://repo.kotlin.link")
|
implementation("space.kscience:kmath-ejml:0.3.0-dev-3")
|
||||||
> maven("https://dl.bintray.com/kotlin/kotlin-eap") // include for builds based on kotlin-eap
|
}
|
||||||
> maven("https://dl.bintray.com/hotkeytlt/maven") // required for a
|
```
|
||||||
> }
|
|
||||||
>
|
|
||||||
> dependencies {
|
|
||||||
> implementation("space.kscience:kmath-ejml:0.3.0-dev-3")
|
|
||||||
> }
|
|
||||||
> ```
|
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
# ejml-simple support (`kmath-ejml`)
|
# Module kmath-ejml
|
||||||
|
|
||||||
This subproject implements the following features:
|
EJML based linear algebra implementation.
|
||||||
|
|
||||||
${features}
|
${features}
|
||||||
|
|
||||||
|
@ -4,6 +4,7 @@ import org.ejml.dense.row.factory.DecompositionFactory_DDRM
|
|||||||
import org.ejml.simple.SimpleMatrix
|
import org.ejml.simple.SimpleMatrix
|
||||||
import space.kscience.kmath.linear.*
|
import space.kscience.kmath.linear.*
|
||||||
import space.kscience.kmath.misc.UnstableKMathAPI
|
import space.kscience.kmath.misc.UnstableKMathAPI
|
||||||
|
import space.kscience.kmath.nd.StructureFeature
|
||||||
import space.kscience.kmath.nd.getFeature
|
import space.kscience.kmath.nd.getFeature
|
||||||
import space.kscience.kmath.operations.DoubleField
|
import space.kscience.kmath.operations.DoubleField
|
||||||
import space.kscience.kmath.structures.DoubleBuffer
|
import space.kscience.kmath.structures.DoubleBuffer
|
||||||
@ -95,7 +96,7 @@ public object EjmlLinearSpace : LinearSpace<Double, DoubleField> {
|
|||||||
v.toEjml().origin.scale(this).wrapVector()
|
v.toEjml().origin.scale(this).wrapVector()
|
||||||
|
|
||||||
@UnstableKMathAPI
|
@UnstableKMathAPI
|
||||||
public override fun <F : Any> getFeature(structure: Matrix<Double>, type: KClass<F>): F? {
|
public override fun <F : StructureFeature> getFeature(structure: Matrix<Double>, type: KClass<out F>): F? {
|
||||||
//Return the feature if it is intrinsic to the structure
|
//Return the feature if it is intrinsic to the structure
|
||||||
structure.getFeature(type)?.let { return it }
|
structure.getFeature(type)?.let { return it }
|
||||||
|
|
||||||
|
@ -1,41 +1,37 @@
|
|||||||
# Real number specialization module (`kmath-for-real`)
|
# Module kmath-for-real
|
||||||
|
|
||||||
|
Specialization of KMath APIs for Double numbers.
|
||||||
|
|
||||||
- [DoubleVector](src/commonMain/kotlin/space/kscience/kmath/real/DoubleVector.kt) : Numpy-like operations for Buffers/Points
|
- [DoubleVector](src/commonMain/kotlin/space/kscience/kmath/real/DoubleVector.kt) : Numpy-like operations for Buffers/Points
|
||||||
- [DoubleMatrix](src/commonMain/kotlin/space/kscience/kmath/real/DoubleMatrix.kt) : Numpy-like operations for 2d real structures
|
- [DoubleMatrix](src/commonMain/kotlin/space/kscience/kmath/real/DoubleMatrix.kt) : Numpy-like operations for 2d real structures
|
||||||
- [grids](src/commonMain/kotlin/space/kscience/kmath/structures/grids.kt) : Uniform grid generators
|
- [grids](src/commonMain/kotlin/space/kscience/kmath/structures/grids.kt) : Uniform grid generators
|
||||||
|
|
||||||
|
|
||||||
> #### Artifact:
|
## Artifact:
|
||||||
>
|
|
||||||
> This module artifact: `space.kscience:kmath-for-real:0.3.0-dev-3`.
|
The Maven coordinates of this project are `space.kscience:kmath-for-real:0.3.0-dev-3`.
|
||||||
>
|
|
||||||
> Bintray release version: [ ![Download](https://api.bintray.com/packages/mipt-npm/kscience/kmath-for-real/images/download.svg) ](https://bintray.com/mipt-npm/kscience/kmath-for-real/_latestVersion)
|
**Gradle:**
|
||||||
>
|
```gradle
|
||||||
> Bintray development version: [ ![Download](https://api.bintray.com/packages/mipt-npm/dev/kmath-for-real/images/download.svg) ](https://bintray.com/mipt-npm/dev/kmath-for-real/_latestVersion)
|
repositories {
|
||||||
>
|
maven { url 'https://repo.kotlin.link' }
|
||||||
> **Gradle:**
|
maven { url 'https://dl.bintray.com/hotkeytlt/maven' }
|
||||||
>
|
maven { url "https://dl.bintray.com/kotlin/kotlin-eap" } // include for builds based on kotlin-eap
|
||||||
> ```gradle
|
}
|
||||||
> repositories {
|
|
||||||
> maven { url 'https://repo.kotlin.link' }
|
dependencies {
|
||||||
> maven { url 'https://dl.bintray.com/hotkeytlt/maven' }
|
implementation 'space.kscience:kmath-for-real:0.3.0-dev-3'
|
||||||
> maven { url "https://dl.bintray.com/kotlin/kotlin-eap" } // include for builds based on kotlin-eap
|
}
|
||||||
> }
|
```
|
||||||
>
|
**Gradle Kotlin DSL:**
|
||||||
> dependencies {
|
```kotlin
|
||||||
> implementation 'space.kscience:kmath-for-real:0.3.0-dev-3'
|
repositories {
|
||||||
> }
|
maven("https://repo.kotlin.link")
|
||||||
> ```
|
maven("https://dl.bintray.com/kotlin/kotlin-eap") // include for builds based on kotlin-eap
|
||||||
> **Gradle Kotlin DSL:**
|
maven("https://dl.bintray.com/hotkeytlt/maven") // required for a
|
||||||
>
|
}
|
||||||
> ```kotlin
|
|
||||||
> repositories {
|
dependencies {
|
||||||
> maven("https://repo.kotlin.link")
|
implementation("space.kscience:kmath-for-real:0.3.0-dev-3")
|
||||||
> maven("https://dl.bintray.com/kotlin/kotlin-eap") // include for builds based on kotlin-eap
|
}
|
||||||
> maven("https://dl.bintray.com/hotkeytlt/maven") // required for a
|
```
|
||||||
> }
|
|
||||||
>
|
|
||||||
> dependencies {
|
|
||||||
> implementation("space.kscience:kmath-for-real:0.3.0-dev-3")
|
|
||||||
> }
|
|
||||||
> ```
|
|
||||||
|
@ -1,4 +1,6 @@
|
|||||||
# Real number specialization module (`kmath-for-real`)
|
# Module kmath-for-real
|
||||||
|
|
||||||
|
Specialization of KMath APIs for Double numbers.
|
||||||
|
|
||||||
${features}
|
${features}
|
||||||
|
|
||||||
|
@ -6,17 +6,13 @@ import space.kscience.kmath.operations.Norm
|
|||||||
import space.kscience.kmath.structures.Buffer
|
import space.kscience.kmath.structures.Buffer
|
||||||
import space.kscience.kmath.structures.MutableBuffer.Companion.double
|
import space.kscience.kmath.structures.MutableBuffer.Companion.double
|
||||||
import space.kscience.kmath.structures.asBuffer
|
import space.kscience.kmath.structures.asBuffer
|
||||||
import space.kscience.kmath.structures.asIterable
|
import space.kscience.kmath.structures.fold
|
||||||
import space.kscience.kmath.structures.indices
|
import space.kscience.kmath.structures.indices
|
||||||
import kotlin.math.pow
|
import kotlin.math.pow
|
||||||
import kotlin.math.sqrt
|
import kotlin.math.sqrt
|
||||||
|
|
||||||
public typealias DoubleVector = Point<Double>
|
public typealias DoubleVector = Point<Double>
|
||||||
|
|
||||||
public object VectorL2Norm : Norm<Point<out Number>, Double> {
|
|
||||||
override fun norm(arg: Point<out Number>): Double = sqrt(arg.asIterable().sumByDouble(Number::toDouble))
|
|
||||||
}
|
|
||||||
|
|
||||||
@Suppress("FunctionName")
|
@Suppress("FunctionName")
|
||||||
public fun DoubleVector(vararg doubles: Double): DoubleVector = doubles.asBuffer()
|
public fun DoubleVector(vararg doubles: Double): DoubleVector = doubles.asBuffer()
|
||||||
|
|
||||||
@ -103,3 +99,9 @@ public fun DoubleVector.sum(): Double {
|
|||||||
}
|
}
|
||||||
return res
|
return res
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public object VectorL2Norm : Norm<DoubleVector, Double> {
|
||||||
|
override fun norm(arg: DoubleVector): Double = sqrt(arg.fold(0.0) { acc: Double, d: Double -> acc + d.pow(2) })
|
||||||
|
}
|
||||||
|
|
||||||
|
public val DoubleVector.norm: Double get() = VectorL2Norm.norm(this)
|
@ -1,7 +1,41 @@
|
|||||||
package space.kscience.kmath.real
|
package space.kscience.kmath.real
|
||||||
|
|
||||||
import space.kscience.kmath.structures.asBuffer
|
import space.kscience.kmath.misc.UnstableKMathAPI
|
||||||
import kotlin.math.abs
|
import space.kscience.kmath.structures.Buffer
|
||||||
|
import space.kscience.kmath.structures.DoubleBuffer
|
||||||
|
import kotlin.math.floor
|
||||||
|
|
||||||
|
public val ClosedFloatingPointRange<Double>.length: Double get() = endInclusive - start
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a Buffer-based grid with equally distributed [numberOfPoints] points. The range could be increasing or decreasing.
|
||||||
|
* If range has a zero size, then the buffer consisting of [numberOfPoints] equal values is returned.
|
||||||
|
*/
|
||||||
|
public fun Buffer.Companion.fromRange(range: ClosedFloatingPointRange<Double>, numberOfPoints: Int): DoubleBuffer {
|
||||||
|
require(numberOfPoints >= 2) { "Number of points in grid must be more than 1" }
|
||||||
|
val normalizedRange = when {
|
||||||
|
range.endInclusive > range.start -> range
|
||||||
|
range.endInclusive < range.start -> range.endInclusive..range.start
|
||||||
|
else -> return DoubleBuffer(numberOfPoints) { range.start }
|
||||||
|
}
|
||||||
|
val step = normalizedRange.length / (numberOfPoints - 1)
|
||||||
|
return DoubleBuffer(numberOfPoints) { normalizedRange.start + step * it }
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a Buffer-based grid with equally distributed points with a fixed [step]. The range could be increasing or decreasing.
|
||||||
|
* If the step is larger than the range size, single point is returned.
|
||||||
|
*/
|
||||||
|
public fun Buffer.Companion.withFixedStep(range: ClosedFloatingPointRange<Double>, step: Double): DoubleBuffer {
|
||||||
|
require(step > 0) { "The grid step must be positive" }
|
||||||
|
val normalizedRange = when {
|
||||||
|
range.endInclusive > range.start -> range
|
||||||
|
range.endInclusive < range.start -> range.endInclusive..range.start
|
||||||
|
else -> return DoubleBuffer(range.start)
|
||||||
|
}
|
||||||
|
val numberOfPoints = floor(normalizedRange.length / step).toInt() + 1
|
||||||
|
return DoubleBuffer(numberOfPoints) { normalizedRange.start + step * it }
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Convert double range to sequence.
|
* Convert double range to sequence.
|
||||||
@ -11,35 +45,5 @@ import kotlin.math.abs
|
|||||||
*
|
*
|
||||||
* If step is negative, the same goes from upper boundary downwards
|
* If step is negative, the same goes from upper boundary downwards
|
||||||
*/
|
*/
|
||||||
public fun ClosedFloatingPointRange<Double>.toSequenceWithStep(step: Double): Sequence<Double> = when {
|
@UnstableKMathAPI
|
||||||
step == 0.0 -> error("Zero step in double progression")
|
public infix fun ClosedFloatingPointRange<Double>.step(step: Double): DoubleBuffer = Buffer.withFixedStep(this, step)
|
||||||
|
|
||||||
step > 0 -> sequence {
|
|
||||||
var current = start
|
|
||||||
|
|
||||||
while (current <= endInclusive) {
|
|
||||||
yield(current)
|
|
||||||
current += step
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
else -> sequence {
|
|
||||||
var current = endInclusive
|
|
||||||
|
|
||||||
while (current >= start) {
|
|
||||||
yield(current)
|
|
||||||
current += step
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public infix fun ClosedFloatingPointRange<Double>.step(step: Double): DoubleVector =
|
|
||||||
toSequenceWithStep(step).toList().asBuffer()
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Convert double range to sequence with the fixed number of points
|
|
||||||
*/
|
|
||||||
public fun ClosedFloatingPointRange<Double>.toSequenceWithPoints(numPoints: Int): Sequence<Double> {
|
|
||||||
require(numPoints > 1) { "The number of points should be more than 2" }
|
|
||||||
return toSequenceWithStep(abs(endInclusive - start) / (numPoints - 1))
|
|
||||||
}
|
|
@ -1,13 +1,18 @@
|
|||||||
package kaceince.kmath.real
|
package kaceince.kmath.real
|
||||||
|
|
||||||
|
import space.kscience.kmath.real.DoubleVector
|
||||||
|
import space.kscience.kmath.real.minus
|
||||||
|
import space.kscience.kmath.real.norm
|
||||||
import space.kscience.kmath.real.step
|
import space.kscience.kmath.real.step
|
||||||
import kotlin.test.Test
|
import kotlin.test.Test
|
||||||
import kotlin.test.assertEquals
|
import kotlin.test.assertEquals
|
||||||
|
import kotlin.test.assertTrue
|
||||||
|
|
||||||
class GridTest {
|
class GridTest {
|
||||||
@Test
|
@Test
|
||||||
fun testStepGrid() {
|
fun testStepGrid() {
|
||||||
val grid = 0.0..1.0 step 0.2
|
val grid = 0.0..1.0 step 0.2
|
||||||
assertEquals(6, grid.size)
|
assertEquals(6, grid.size)
|
||||||
|
assertTrue { (grid - DoubleVector(0.0, 0.2, 0.4, 0.6, 0.8, 1.0)).norm < 1e-4 }
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,6 +1,6 @@
|
|||||||
# Functions (`kmath-functions`)
|
# Module kmath-functions
|
||||||
|
|
||||||
Functions and interpolations:
|
Functions and interpolations.
|
||||||
|
|
||||||
- [piecewise](Piecewise functions.) : src/commonMain/kotlin/space/kscience/kmath/functions/Piecewise.kt
|
- [piecewise](Piecewise functions.) : src/commonMain/kotlin/space/kscience/kmath/functions/Piecewise.kt
|
||||||
- [polynomials](Polynomial functions.) : src/commonMain/kotlin/space/kscience/kmath/functions/Polynomial.kt
|
- [polynomials](Polynomial functions.) : src/commonMain/kotlin/space/kscience/kmath/functions/Polynomial.kt
|
||||||
@ -8,37 +8,31 @@ Functions and interpolations:
|
|||||||
- [spline interpolation](Cubic spline XY interpolator.) : src/commonMain/kotlin/space/kscience/kmath/interpolation/SplineInterpolator.kt
|
- [spline interpolation](Cubic spline XY interpolator.) : src/commonMain/kotlin/space/kscience/kmath/interpolation/SplineInterpolator.kt
|
||||||
|
|
||||||
|
|
||||||
> #### Artifact:
|
## Artifact:
|
||||||
>
|
|
||||||
> This module artifact: `space.kscience:kmath-functions:0.3.0-dev-3`.
|
The Maven coordinates of this project are `space.kscience:kmath-functions:0.3.0-dev-3`.
|
||||||
>
|
|
||||||
> Bintray release version: [ ![Download](https://api.bintray.com/packages/mipt-npm/kscience/kmath-functions/images/download.svg) ](https://bintray.com/mipt-npm/kscience/kmath-functions/_latestVersion)
|
**Gradle:**
|
||||||
>
|
```gradle
|
||||||
> Bintray development version: [ ![Download](https://api.bintray.com/packages/mipt-npm/dev/kmath-functions/images/download.svg) ](https://bintray.com/mipt-npm/dev/kmath-functions/_latestVersion)
|
repositories {
|
||||||
>
|
maven { url 'https://repo.kotlin.link' }
|
||||||
> **Gradle:**
|
maven { url 'https://dl.bintray.com/hotkeytlt/maven' }
|
||||||
>
|
maven { url "https://dl.bintray.com/kotlin/kotlin-eap" } // include for builds based on kotlin-eap
|
||||||
> ```gradle
|
}
|
||||||
> repositories {
|
|
||||||
> maven { url 'https://repo.kotlin.link' }
|
dependencies {
|
||||||
> maven { url 'https://dl.bintray.com/hotkeytlt/maven' }
|
implementation 'space.kscience:kmath-functions:0.3.0-dev-3'
|
||||||
> maven { url "https://dl.bintray.com/kotlin/kotlin-eap" } // include for builds based on kotlin-eap
|
}
|
||||||
> }
|
```
|
||||||
>
|
**Gradle Kotlin DSL:**
|
||||||
> dependencies {
|
```kotlin
|
||||||
> implementation 'space.kscience:kmath-functions:0.3.0-dev-3'
|
repositories {
|
||||||
> }
|
maven("https://repo.kotlin.link")
|
||||||
> ```
|
maven("https://dl.bintray.com/kotlin/kotlin-eap") // include for builds based on kotlin-eap
|
||||||
> **Gradle Kotlin DSL:**
|
maven("https://dl.bintray.com/hotkeytlt/maven") // required for a
|
||||||
>
|
}
|
||||||
> ```kotlin
|
|
||||||
> repositories {
|
dependencies {
|
||||||
> maven("https://repo.kotlin.link")
|
implementation("space.kscience:kmath-functions:0.3.0-dev-3")
|
||||||
> maven("https://dl.bintray.com/kotlin/kotlin-eap") // include for builds based on kotlin-eap
|
}
|
||||||
> maven("https://dl.bintray.com/hotkeytlt/maven") // required for a
|
```
|
||||||
> }
|
|
||||||
>
|
|
||||||
> dependencies {
|
|
||||||
> implementation("space.kscience:kmath-functions:0.3.0-dev-3")
|
|
||||||
> }
|
|
||||||
> ```
|
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
# Functions (`kmath-functions`)
|
# Module kmath-functions
|
||||||
|
|
||||||
Functions and interpolations:
|
Functions and interpolations.
|
||||||
|
|
||||||
${features}
|
${features}
|
||||||
|
|
||||||
|
@ -2,14 +2,28 @@ package space.kscience.kmath.functions
|
|||||||
|
|
||||||
import space.kscience.kmath.operations.Ring
|
import space.kscience.kmath.operations.Ring
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents piecewise-defined function.
|
||||||
|
*
|
||||||
|
* @param T the piece key type.
|
||||||
|
* @param R the sub-function type.
|
||||||
|
*/
|
||||||
public fun interface Piecewise<T, R> {
|
public fun interface Piecewise<T, R> {
|
||||||
|
/**
|
||||||
|
* Returns the appropriate sub-function for given piece key.
|
||||||
|
*/
|
||||||
public fun findPiece(arg: T): R?
|
public fun findPiece(arg: T): R?
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents piecewise-defined function where all the sub-functions are polynomials.
|
||||||
|
*/
|
||||||
public fun interface PiecewisePolynomial<T : Any> : Piecewise<T, Polynomial<T>>
|
public fun interface PiecewisePolynomial<T : Any> : Piecewise<T, Polynomial<T>>
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Ordered list of pieces in piecewise function
|
* Basic [Piecewise] implementation where all the pieces are ordered by the [Comparable] type instances.
|
||||||
|
*
|
||||||
|
* @param T the comparable piece key type.
|
||||||
*/
|
*/
|
||||||
public class OrderedPiecewisePolynomial<T : Comparable<T>>(delimiter: T) :
|
public class OrderedPiecewisePolynomial<T : Comparable<T>>(delimiter: T) :
|
||||||
PiecewisePolynomial<T> {
|
PiecewisePolynomial<T> {
|
||||||
@ -17,22 +31,30 @@ public class OrderedPiecewisePolynomial<T : Comparable<T>>(delimiter: T) :
|
|||||||
private val pieces: MutableList<Polynomial<T>> = arrayListOf()
|
private val pieces: MutableList<Polynomial<T>> = arrayListOf()
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Dynamically add a piece to the "right" side (beyond maximum argument value of previous piece)
|
* Dynamically adds a piece to the right side (beyond maximum argument value of previous piece)
|
||||||
* @param right new rightmost position. If is less then current rightmost position, a error is thrown.
|
*
|
||||||
|
* @param right new rightmost position. If is less then current rightmost position, an error is thrown.
|
||||||
|
* @param piece the sub-function.
|
||||||
*/
|
*/
|
||||||
public fun putRight(right: T, piece: Polynomial<T>) {
|
public fun putRight(right: T, piece: Polynomial<T>) {
|
||||||
require(right > delimiters.last()) { "New delimiter should be to the right of old one" }
|
require(right > delimiters.last()) { "New delimiter should be to the right of old one" }
|
||||||
delimiters.add(right)
|
delimiters += right
|
||||||
pieces.add(piece)
|
pieces += piece
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Dynamically adds a piece to the left side (beyond maximum argument value of previous piece)
|
||||||
|
*
|
||||||
|
* @param left the new leftmost position. If is less then current rightmost position, an error is thrown.
|
||||||
|
* @param piece the sub-function.
|
||||||
|
*/
|
||||||
public fun putLeft(left: T, piece: Polynomial<T>) {
|
public fun putLeft(left: T, piece: Polynomial<T>) {
|
||||||
require(left < delimiters.first()) { "New delimiter should be to the left of old one" }
|
require(left < delimiters.first()) { "New delimiter should be to the left of old one" }
|
||||||
delimiters.add(0, left)
|
delimiters.add(0, left)
|
||||||
pieces.add(0, piece)
|
pieces.add(0, piece)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun findPiece(arg: T): Polynomial<T>? {
|
public override fun findPiece(arg: T): Polynomial<T>? {
|
||||||
if (arg < delimiters.first() || arg >= delimiters.last())
|
if (arg < delimiters.first() || arg >= delimiters.last())
|
||||||
return null
|
return null
|
||||||
else {
|
else {
|
||||||
@ -46,7 +68,8 @@ public class OrderedPiecewisePolynomial<T : Comparable<T>>(delimiter: T) :
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return a value of polynomial function with given [ring] an given [arg] or null if argument is outside of piecewise definition.
|
* Return a value of polynomial function with given [ring] an given [arg] or null if argument is outside of piecewise
|
||||||
|
* definition.
|
||||||
*/
|
*/
|
||||||
public fun <T : Comparable<T>, C : Ring<T>> PiecewisePolynomial<T>.value(ring: C, arg: T): T? =
|
public fun <T : Comparable<T>, C : Ring<T>> PiecewisePolynomial<T>.value(ring: C, arg: T): T? =
|
||||||
findPiece(arg)?.value(ring, arg)
|
findPiece(arg)?.value(ring, arg)
|
||||||
|
@ -10,16 +10,26 @@ import kotlin.math.max
|
|||||||
import kotlin.math.pow
|
import kotlin.math.pow
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Polynomial coefficients without fixation on specific context they are applied to
|
* Polynomial coefficients model without fixation on specific context they are applied to.
|
||||||
* @param coefficients constant is the leftmost coefficient
|
*
|
||||||
|
* @param coefficients constant is the leftmost coefficient.
|
||||||
*/
|
*/
|
||||||
public inline class Polynomial<T : Any>(public val coefficients: List<T>)
|
public inline class Polynomial<T : Any>(public val coefficients: List<T>)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a [Polynomial] instance with given [coefficients].
|
||||||
|
*/
|
||||||
@Suppress("FunctionName")
|
@Suppress("FunctionName")
|
||||||
public fun <T : Any> Polynomial(vararg coefficients: T): Polynomial<T> = Polynomial(coefficients.toList())
|
public fun <T : Any> Polynomial(vararg coefficients: T): Polynomial<T> = Polynomial(coefficients.toList())
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Evaluates the value of the given double polynomial for given double argument.
|
||||||
|
*/
|
||||||
public fun Polynomial<Double>.value(): Double = coefficients.reduceIndexed { index, acc, d -> acc + d.pow(index) }
|
public fun Polynomial<Double>.value(): Double = coefficients.reduceIndexed { index, acc, d -> acc + d.pow(index) }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Evaluates the value of the given polynomial for given argument.
|
||||||
|
*/
|
||||||
public fun <T : Any, C : Ring<T>> Polynomial<T>.value(ring: C, arg: T): T = ring {
|
public fun <T : Any, C : Ring<T>> Polynomial<T>.value(ring: C, arg: T): T = ring {
|
||||||
if (coefficients.isEmpty()) return@ring zero
|
if (coefficients.isEmpty()) return@ring zero
|
||||||
var res = coefficients.first()
|
var res = coefficients.first()
|
||||||
@ -35,19 +45,23 @@ public fun <T : Any, C : Ring<T>> Polynomial<T>.value(ring: C, arg: T): T = ring
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Represent the polynomial as a regular context-less function
|
* Represent the polynomial as a regular context-less function.
|
||||||
*/
|
*/
|
||||||
public fun <T : Any, C : Ring<T>> Polynomial<T>.asFunction(ring: C): (T) -> T = { value(ring, it) }
|
public fun <T : Any, C : Ring<T>> Polynomial<T>.asFunction(ring: C): (T) -> T = { value(ring, it) }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An algebra for polynomials
|
* Space of polynomials.
|
||||||
|
*
|
||||||
|
* @param T the type of operated polynomials.
|
||||||
|
* @param C the intersection of [Ring] of [T] and [ScaleOperations] of [T].
|
||||||
|
* @param ring the [C] instance.
|
||||||
*/
|
*/
|
||||||
public class PolynomialSpace<T : Any, C>(
|
public class PolynomialSpace<T : Any, C>(
|
||||||
private val ring: C,
|
private val ring: C,
|
||||||
) : Group<Polynomial<T>>, ScaleOperations<Polynomial<T>> where C : Ring<T>, C : ScaleOperations<T> {
|
) : Group<Polynomial<T>>, ScaleOperations<Polynomial<T>> where C : Ring<T>, C : ScaleOperations<T> {
|
||||||
public override val zero: Polynomial<T> = Polynomial(emptyList())
|
public override val zero: Polynomial<T> = Polynomial(emptyList())
|
||||||
|
|
||||||
override fun Polynomial<T>.unaryMinus(): Polynomial<T> = with(ring) {
|
override fun Polynomial<T>.unaryMinus(): Polynomial<T> = ring {
|
||||||
Polynomial(coefficients.map { -it })
|
Polynomial(coefficients.map { -it })
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -64,6 +78,9 @@ public class PolynomialSpace<T : Any, C>(
|
|||||||
public override fun scale(a: Polynomial<T>, value: Double): Polynomial<T> =
|
public override fun scale(a: Polynomial<T>, value: Double): Polynomial<T> =
|
||||||
ring { Polynomial(List(a.coefficients.size) { index -> a.coefficients[index] * value }) }
|
ring { Polynomial(List(a.coefficients.size) { index -> a.coefficients[index] * value }) }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Evaluates the polynomial for the given value [arg].
|
||||||
|
*/
|
||||||
public operator fun Polynomial<T>.invoke(arg: T): T = value(ring, arg)
|
public operator fun Polynomial<T>.invoke(arg: T): T = value(ring, arg)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,11 +1,11 @@
|
|||||||
package space.kscience.kmath.integration
|
package space.kscience.kmath.integration
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A general interface for all integrators
|
* A general interface for all integrators.
|
||||||
*/
|
*/
|
||||||
public interface Integrator<I : Integrand> {
|
public interface Integrator<I : Integrand> {
|
||||||
/**
|
/**
|
||||||
* Run one integration pass and return a new [Integrand] with a new set of features
|
* Runs one integration pass and return a new [Integrand] with a new set of features.
|
||||||
*/
|
*/
|
||||||
public fun integrate(integrand: I): I
|
public fun integrate(integrand: I): I
|
||||||
}
|
}
|
@ -1,45 +1,50 @@
|
|||||||
|
@file:OptIn(UnstableKMathAPI::class)
|
||||||
|
|
||||||
package space.kscience.kmath.interpolation
|
package space.kscience.kmath.interpolation
|
||||||
|
|
||||||
|
import space.kscience.kmath.data.XYColumnarData
|
||||||
import space.kscience.kmath.functions.PiecewisePolynomial
|
import space.kscience.kmath.functions.PiecewisePolynomial
|
||||||
import space.kscience.kmath.functions.value
|
import space.kscience.kmath.functions.value
|
||||||
|
import space.kscience.kmath.misc.UnstableKMathAPI
|
||||||
import space.kscience.kmath.operations.Ring
|
import space.kscience.kmath.operations.Ring
|
||||||
import space.kscience.kmath.structures.Buffer
|
import space.kscience.kmath.structures.Buffer
|
||||||
import space.kscience.kmath.structures.asBuffer
|
import space.kscience.kmath.structures.asBuffer
|
||||||
|
|
||||||
public fun interface Interpolator<X, Y> {
|
public fun interface Interpolator<T, X : T, Y : T> {
|
||||||
public fun interpolate(points: XYPointSet<X, Y>): (X) -> Y
|
public fun interpolate(points: XYColumnarData<T, X, Y>): (X) -> Y
|
||||||
}
|
}
|
||||||
|
|
||||||
public interface PolynomialInterpolator<T : Comparable<T>> : Interpolator<T, T> {
|
public interface PolynomialInterpolator<T : Comparable<T>> : Interpolator<T, T, T> {
|
||||||
public val algebra: Ring<T>
|
public val algebra: Ring<T>
|
||||||
|
|
||||||
public fun getDefaultValue(): T = error("Out of bounds")
|
public fun getDefaultValue(): T = error("Out of bounds")
|
||||||
|
|
||||||
public fun interpolatePolynomials(points: XYPointSet<T, T>): PiecewisePolynomial<T>
|
public fun interpolatePolynomials(points: XYColumnarData<T, T, T>): PiecewisePolynomial<T>
|
||||||
|
|
||||||
override fun interpolate(points: XYPointSet<T, T>): (T) -> T = { x ->
|
override fun interpolate(points: XYColumnarData<T, T, T>): (T) -> T = { x ->
|
||||||
interpolatePolynomials(points).value(algebra, x) ?: getDefaultValue()
|
interpolatePolynomials(points).value(algebra, x) ?: getDefaultValue()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public fun <T : Comparable<T>> PolynomialInterpolator<T>.interpolatePolynomials(
|
public fun <T : Comparable<T>> PolynomialInterpolator<T>.interpolatePolynomials(
|
||||||
x: Buffer<T>,
|
x: Buffer<T>,
|
||||||
y: Buffer<T>,
|
y: Buffer<T>,
|
||||||
): PiecewisePolynomial<T> {
|
): PiecewisePolynomial<T> {
|
||||||
val pointSet = BufferXYPointSet(x, y)
|
val pointSet = XYColumnarData(x, y)
|
||||||
return interpolatePolynomials(pointSet)
|
return interpolatePolynomials(pointSet)
|
||||||
}
|
}
|
||||||
|
|
||||||
public fun <T : Comparable<T>> PolynomialInterpolator<T>.interpolatePolynomials(
|
public fun <T : Comparable<T>> PolynomialInterpolator<T>.interpolatePolynomials(
|
||||||
data: Map<T, T>,
|
data: Map<T, T>,
|
||||||
): PiecewisePolynomial<T> {
|
): PiecewisePolynomial<T> {
|
||||||
val pointSet = BufferXYPointSet(data.keys.toList().asBuffer(), data.values.toList().asBuffer())
|
val pointSet = XYColumnarData(data.keys.toList().asBuffer(), data.values.toList().asBuffer())
|
||||||
return interpolatePolynomials(pointSet)
|
return interpolatePolynomials(pointSet)
|
||||||
}
|
}
|
||||||
|
|
||||||
public fun <T : Comparable<T>> PolynomialInterpolator<T>.interpolatePolynomials(
|
public fun <T : Comparable<T>> PolynomialInterpolator<T>.interpolatePolynomials(
|
||||||
data: List<Pair<T, T>>,
|
data: List<Pair<T, T>>,
|
||||||
): PiecewisePolynomial<T> {
|
): PiecewisePolynomial<T> {
|
||||||
val pointSet = BufferXYPointSet(data.map { it.first }.asBuffer(), data.map { it.second }.asBuffer())
|
val pointSet = XYColumnarData(data.map { it.first }.asBuffer(), data.map { it.second }.asBuffer())
|
||||||
return interpolatePolynomials(pointSet)
|
return interpolatePolynomials(pointSet)
|
||||||
}
|
}
|
||||||
|
@ -1,16 +1,25 @@
|
|||||||
package space.kscience.kmath.interpolation
|
package space.kscience.kmath.interpolation
|
||||||
|
|
||||||
|
import space.kscience.kmath.data.XYColumnarData
|
||||||
import space.kscience.kmath.functions.OrderedPiecewisePolynomial
|
import space.kscience.kmath.functions.OrderedPiecewisePolynomial
|
||||||
import space.kscience.kmath.functions.PiecewisePolynomial
|
import space.kscience.kmath.functions.PiecewisePolynomial
|
||||||
import space.kscience.kmath.functions.Polynomial
|
import space.kscience.kmath.functions.Polynomial
|
||||||
|
import space.kscience.kmath.misc.UnstableKMathAPI
|
||||||
import space.kscience.kmath.operations.Field
|
import space.kscience.kmath.operations.Field
|
||||||
import space.kscience.kmath.operations.invoke
|
import space.kscience.kmath.operations.invoke
|
||||||
|
|
||||||
|
@OptIn(UnstableKMathAPI::class)
|
||||||
|
internal fun <T : Comparable<T>> insureSorted(points: XYColumnarData<*, T, *>) {
|
||||||
|
for (i in 0 until points.size - 1)
|
||||||
|
require(points.x[i + 1] > points.x[i]) { "Input data is not sorted at index $i" }
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Reference JVM implementation: https://github.com/apache/commons-math/blob/master/src/main/java/org/apache/commons/math4/analysis/interpolation/LinearInterpolator.java
|
* Reference JVM implementation: https://github.com/apache/commons-math/blob/master/src/main/java/org/apache/commons/math4/analysis/interpolation/LinearInterpolator.java
|
||||||
*/
|
*/
|
||||||
public class LinearInterpolator<T : Comparable<T>>(public override val algebra: Field<T>) : PolynomialInterpolator<T> {
|
public class LinearInterpolator<T : Comparable<T>>(public override val algebra: Field<T>) : PolynomialInterpolator<T> {
|
||||||
public override fun interpolatePolynomials(points: XYPointSet<T, T>): PiecewisePolynomial<T> = algebra {
|
@OptIn(UnstableKMathAPI::class)
|
||||||
|
public override fun interpolatePolynomials(points: XYColumnarData<T, T, T>): PiecewisePolynomial<T> = algebra {
|
||||||
require(points.size > 0) { "Point array should not be empty" }
|
require(points.size > 0) { "Point array should not be empty" }
|
||||||
insureSorted(points)
|
insureSorted(points)
|
||||||
|
|
||||||
|
@ -1,15 +1,20 @@
|
|||||||
package space.kscience.kmath.interpolation
|
package space.kscience.kmath.interpolation
|
||||||
|
|
||||||
|
import space.kscience.kmath.data.XYColumnarData
|
||||||
import space.kscience.kmath.functions.OrderedPiecewisePolynomial
|
import space.kscience.kmath.functions.OrderedPiecewisePolynomial
|
||||||
import space.kscience.kmath.functions.PiecewisePolynomial
|
import space.kscience.kmath.functions.PiecewisePolynomial
|
||||||
import space.kscience.kmath.functions.Polynomial
|
import space.kscience.kmath.functions.Polynomial
|
||||||
|
import space.kscience.kmath.misc.UnstableKMathAPI
|
||||||
import space.kscience.kmath.operations.Field
|
import space.kscience.kmath.operations.Field
|
||||||
import space.kscience.kmath.operations.invoke
|
import space.kscience.kmath.operations.invoke
|
||||||
import space.kscience.kmath.structures.MutableBufferFactory
|
import space.kscience.kmath.structures.MutableBufferFactory
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Generic spline interpolator. Not recommended for performance critical places, use platform-specific and type specific ones.
|
* Generic spline interpolator. Not recommended for performance critical places, use platform-specific and type
|
||||||
* Based on https://github.com/apache/commons-math/blob/eb57d6d457002a0bb5336d789a3381a24599affe/src/main/java/org/apache/commons/math4/analysis/interpolation/SplineInterpolator.java
|
* specific ones.
|
||||||
|
*
|
||||||
|
* Based on
|
||||||
|
* https://github.com/apache/commons-math/blob/eb57d6d457002a0bb5336d789a3381a24599affe/src/main/java/org/apache/commons/math4/analysis/interpolation/SplineInterpolator.java
|
||||||
*/
|
*/
|
||||||
public class SplineInterpolator<T : Comparable<T>>(
|
public class SplineInterpolator<T : Comparable<T>>(
|
||||||
public override val algebra: Field<T>,
|
public override val algebra: Field<T>,
|
||||||
@ -17,7 +22,8 @@ public class SplineInterpolator<T : Comparable<T>>(
|
|||||||
) : PolynomialInterpolator<T> {
|
) : PolynomialInterpolator<T> {
|
||||||
//TODO possibly optimize zeroed buffers
|
//TODO possibly optimize zeroed buffers
|
||||||
|
|
||||||
public override fun interpolatePolynomials(points: XYPointSet<T, T>): PiecewisePolynomial<T> = algebra {
|
@OptIn(UnstableKMathAPI::class)
|
||||||
|
public override fun interpolatePolynomials(points: XYColumnarData<T, T, T>): PiecewisePolynomial<T> = algebra {
|
||||||
require(points.size >= 3) { "Can't use spline interpolator with less than 3 points" }
|
require(points.size >= 3) { "Can't use spline interpolator with less than 3 points" }
|
||||||
insureSorted(points)
|
insureSorted(points)
|
||||||
// Number of intervals. The number of data points is n + 1.
|
// Number of intervals. The number of data points is n + 1.
|
||||||
|
@ -1,53 +0,0 @@
|
|||||||
package space.kscience.kmath.interpolation
|
|
||||||
|
|
||||||
import space.kscience.kmath.nd.Structure2D
|
|
||||||
import space.kscience.kmath.structures.Buffer
|
|
||||||
|
|
||||||
public interface XYPointSet<X, Y> {
|
|
||||||
public val size: Int
|
|
||||||
public val x: Buffer<X>
|
|
||||||
public val y: Buffer<Y>
|
|
||||||
}
|
|
||||||
|
|
||||||
public interface XYZPointSet<X, Y, Z> : XYPointSet<X, Y> {
|
|
||||||
public val z: Buffer<Z>
|
|
||||||
}
|
|
||||||
|
|
||||||
internal fun <T : Comparable<T>> insureSorted(points: XYPointSet<T, *>) {
|
|
||||||
for (i in 0 until points.size - 1)
|
|
||||||
require(points.x[i + 1] > points.x[i]) { "Input data is not sorted at index $i" }
|
|
||||||
}
|
|
||||||
|
|
||||||
public class NDStructureColumn<T>(public val structure: Structure2D<T>, public val column: Int) : Buffer<T> {
|
|
||||||
public override val size: Int
|
|
||||||
get() = structure.rowNum
|
|
||||||
|
|
||||||
init {
|
|
||||||
require(column < structure.colNum) { "Column index is outside of structure column range" }
|
|
||||||
}
|
|
||||||
|
|
||||||
public override operator fun get(index: Int): T = structure[index, column]
|
|
||||||
public override operator fun iterator(): Iterator<T> = sequence { repeat(size) { yield(get(it)) } }.iterator()
|
|
||||||
}
|
|
||||||
|
|
||||||
public class BufferXYPointSet<X, Y>(
|
|
||||||
public override val x: Buffer<X>,
|
|
||||||
public override val y: Buffer<Y>,
|
|
||||||
) : XYPointSet<X, Y> {
|
|
||||||
public override val size: Int
|
|
||||||
get() = x.size
|
|
||||||
|
|
||||||
init {
|
|
||||||
require(x.size == y.size) { "Sizes of x and y buffers should be the same" }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public fun <T> Structure2D<T>.asXYPointSet(): XYPointSet<T, T> {
|
|
||||||
require(shape[1] == 2) { "Structure second dimension should be of size 2" }
|
|
||||||
|
|
||||||
return object : XYPointSet<T, T> {
|
|
||||||
override val size: Int get() = this@asXYPointSet.shape[0]
|
|
||||||
override val x: Buffer<T> get() = NDStructureColumn(this@asXYPointSet, 0)
|
|
||||||
override val y: Buffer<T> get() = NDStructureColumn(this@asXYPointSet, 1)
|
|
||||||
}
|
|
||||||
}
|
|
@ -5,7 +5,7 @@ import space.kscience.kmath.ast.MST
|
|||||||
import space.kscience.kmath.ast.MstAlgebra
|
import space.kscience.kmath.ast.MstAlgebra
|
||||||
import space.kscience.kmath.ast.MstExpression
|
import space.kscience.kmath.ast.MstExpression
|
||||||
import space.kscience.kmath.expressions.DifferentiableExpression
|
import space.kscience.kmath.expressions.DifferentiableExpression
|
||||||
import space.kscience.kmath.expressions.Symbol
|
import space.kscience.kmath.misc.Symbol
|
||||||
import space.kscience.kmath.operations.NumericAlgebra
|
import space.kscience.kmath.operations.NumericAlgebra
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -18,8 +18,10 @@ import space.kscience.kmath.operations.NumericAlgebra
|
|||||||
* @param A the [NumericAlgebra] of [T].
|
* @param A the [NumericAlgebra] of [T].
|
||||||
* @property expr the underlying [MstExpression].
|
* @property expr the underlying [MstExpression].
|
||||||
*/
|
*/
|
||||||
public inline class DifferentiableMstExpression<T, A>(public val expr: MstExpression<T, A>) :
|
public inline class DifferentiableMstExpression<T: Number, A>(
|
||||||
DifferentiableExpression<T, MstExpression<T, A>> where A : NumericAlgebra<T>, T : Number {
|
public val expr: MstExpression<T, A>,
|
||||||
|
) : DifferentiableExpression<T, MstExpression<T, A>> where A : NumericAlgebra<T> {
|
||||||
|
|
||||||
public constructor(algebra: A, mst: MST) : this(MstExpression(algebra, mst))
|
public constructor(algebra: A, mst: MST) : this(MstExpression(algebra, mst))
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1,46 +1,40 @@
|
|||||||
# ND4J NDStructure implementation (`kmath-nd4j`)
|
# Module kmath-nd4j
|
||||||
|
|
||||||
This subproject implements the following features:
|
ND4J based implementations of KMath abstractions.
|
||||||
|
|
||||||
- [nd4jarraystructure](#) : NDStructure wrapper for INDArray
|
- [nd4jarraystructure](#) : NDStructure wrapper for INDArray
|
||||||
- [nd4jarrayrings](#) : Rings over Nd4jArrayStructure of Int and Long
|
- [nd4jarrayrings](#) : Rings over Nd4jArrayStructure of Int and Long
|
||||||
- [nd4jarrayfields](#) : Fields over Nd4jArrayStructure of Float and Double
|
- [nd4jarrayfields](#) : Fields over Nd4jArrayStructure of Float and Double
|
||||||
|
|
||||||
|
|
||||||
> #### Artifact:
|
## Artifact:
|
||||||
>
|
|
||||||
> This module artifact: `space.kscience:kmath-nd4j:0.3.0-dev-3`.
|
The Maven coordinates of this project are `space.kscience:kmath-nd4j:0.3.0-dev-3`.
|
||||||
>
|
|
||||||
> Bintray release version: [ ![Download](https://api.bintray.com/packages/mipt-npm/kscience/kmath-nd4j/images/download.svg) ](https://bintray.com/mipt-npm/kscience/kmath-nd4j/_latestVersion)
|
**Gradle:**
|
||||||
>
|
```gradle
|
||||||
> Bintray development version: [ ![Download](https://api.bintray.com/packages/mipt-npm/dev/kmath-nd4j/images/download.svg) ](https://bintray.com/mipt-npm/dev/kmath-nd4j/_latestVersion)
|
repositories {
|
||||||
>
|
maven { url 'https://repo.kotlin.link' }
|
||||||
> **Gradle:**
|
maven { url 'https://dl.bintray.com/hotkeytlt/maven' }
|
||||||
>
|
maven { url "https://dl.bintray.com/kotlin/kotlin-eap" } // include for builds based on kotlin-eap
|
||||||
> ```gradle
|
}
|
||||||
> repositories {
|
|
||||||
> maven { url 'https://repo.kotlin.link' }
|
dependencies {
|
||||||
> maven { url 'https://dl.bintray.com/hotkeytlt/maven' }
|
implementation 'space.kscience:kmath-nd4j:0.3.0-dev-3'
|
||||||
> maven { url "https://dl.bintray.com/kotlin/kotlin-eap" } // include for builds based on kotlin-eap
|
}
|
||||||
> }
|
```
|
||||||
>
|
**Gradle Kotlin DSL:**
|
||||||
> dependencies {
|
```kotlin
|
||||||
> implementation 'space.kscience:kmath-nd4j:0.3.0-dev-3'
|
repositories {
|
||||||
> }
|
maven("https://repo.kotlin.link")
|
||||||
> ```
|
maven("https://dl.bintray.com/kotlin/kotlin-eap") // include for builds based on kotlin-eap
|
||||||
> **Gradle Kotlin DSL:**
|
maven("https://dl.bintray.com/hotkeytlt/maven") // required for a
|
||||||
>
|
}
|
||||||
> ```kotlin
|
|
||||||
> repositories {
|
dependencies {
|
||||||
> maven("https://repo.kotlin.link")
|
implementation("space.kscience:kmath-nd4j:0.3.0-dev-3")
|
||||||
> maven("https://dl.bintray.com/kotlin/kotlin-eap") // include for builds based on kotlin-eap
|
}
|
||||||
> maven("https://dl.bintray.com/hotkeytlt/maven") // required for a
|
```
|
||||||
> }
|
|
||||||
>
|
|
||||||
> dependencies {
|
|
||||||
> implementation("space.kscience:kmath-nd4j:0.3.0-dev-3")
|
|
||||||
> }
|
|
||||||
> ```
|
|
||||||
|
|
||||||
## Examples
|
## Examples
|
||||||
|
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
# ND4J NDStructure implementation (`kmath-nd4j`)
|
# Module kmath-nd4j
|
||||||
|
|
||||||
This subproject implements the following features:
|
ND4J based implementations of KMath abstractions.
|
||||||
|
|
||||||
${features}
|
${features}
|
||||||
|
|
||||||
|
@ -3,14 +3,6 @@ plugins {
|
|||||||
}
|
}
|
||||||
|
|
||||||
kotlin.sourceSets {
|
kotlin.sourceSets {
|
||||||
all {
|
|
||||||
languageSettings.apply {
|
|
||||||
useExperimentalAnnotation("kotlinx.coroutines.FlowPreview")
|
|
||||||
useExperimentalAnnotation("kotlinx.coroutines.ExperimentalCoroutinesApi")
|
|
||||||
useExperimentalAnnotation("kotlinx.coroutines.ObsoleteCoroutinesApi")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
commonMain {
|
commonMain {
|
||||||
dependencies {
|
dependencies {
|
||||||
api(project(":kmath-coroutines"))
|
api(project(":kmath-coroutines"))
|
||||||
|
@ -0,0 +1,89 @@
|
|||||||
|
package space.kscience.kmath.optimization
|
||||||
|
|
||||||
|
import space.kscience.kmath.expressions.AutoDiffProcessor
|
||||||
|
import space.kscience.kmath.expressions.DifferentiableExpression
|
||||||
|
import space.kscience.kmath.expressions.Expression
|
||||||
|
import space.kscience.kmath.expressions.ExpressionAlgebra
|
||||||
|
import space.kscience.kmath.misc.Symbol
|
||||||
|
import space.kscience.kmath.operations.ExtendedField
|
||||||
|
import space.kscience.kmath.structures.Buffer
|
||||||
|
import space.kscience.kmath.structures.indices
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A likelihood function optimization problem with provided derivatives
|
||||||
|
*/
|
||||||
|
public interface FunctionOptimization<T : Any> : Optimization<T> {
|
||||||
|
/**
|
||||||
|
* The optimization direction. If true search for function maximum, if false, search for the minimum
|
||||||
|
*/
|
||||||
|
public var maximize: Boolean
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Define the initial guess for the optimization problem
|
||||||
|
*/
|
||||||
|
public fun initialGuess(map: Map<Symbol, T>)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set a differentiable expression as objective function as function and gradient provider
|
||||||
|
*/
|
||||||
|
public fun diffFunction(expression: DifferentiableExpression<T, Expression<T>>)
|
||||||
|
|
||||||
|
public companion object {
|
||||||
|
/**
|
||||||
|
* Generate a chi squared expression from given x-y-sigma data and inline model. Provides automatic differentiation
|
||||||
|
*/
|
||||||
|
public fun <T : Any, I : Any, A> chiSquared(
|
||||||
|
autoDiff: AutoDiffProcessor<T, I, A, Expression<T>>,
|
||||||
|
x: Buffer<T>,
|
||||||
|
y: Buffer<T>,
|
||||||
|
yErr: Buffer<T>,
|
||||||
|
model: A.(I) -> I,
|
||||||
|
): DifferentiableExpression<T, Expression<T>> where A : ExtendedField<I>, A : ExpressionAlgebra<T, I> {
|
||||||
|
require(x.size == y.size) { "X and y buffers should be of the same size" }
|
||||||
|
require(y.size == yErr.size) { "Y and yErr buffer should of the same size" }
|
||||||
|
|
||||||
|
return autoDiff.process {
|
||||||
|
var sum = zero
|
||||||
|
|
||||||
|
x.indices.forEach {
|
||||||
|
val xValue = const(x[it])
|
||||||
|
val yValue = const(y[it])
|
||||||
|
val yErrValue = const(yErr[it])
|
||||||
|
val modelValue = model(xValue)
|
||||||
|
sum += ((yValue - modelValue) / yErrValue).pow(2)
|
||||||
|
}
|
||||||
|
|
||||||
|
sum
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Define a chi-squared-based objective function
|
||||||
|
*/
|
||||||
|
public fun <T: Any, I : Any, A> FunctionOptimization<T>.chiSquared(
|
||||||
|
autoDiff: AutoDiffProcessor<T, I, A, Expression<T>>,
|
||||||
|
x: Buffer<T>,
|
||||||
|
y: Buffer<T>,
|
||||||
|
yErr: Buffer<T>,
|
||||||
|
model: A.(I) -> I,
|
||||||
|
) where A : ExtendedField<I>, A : ExpressionAlgebra<T, I> {
|
||||||
|
val chiSquared = FunctionOptimization.chiSquared(autoDiff, x, y, yErr, model)
|
||||||
|
diffFunction(chiSquared)
|
||||||
|
maximize = false
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Optimize differentiable expression using specific [OptimizationProblemFactory]
|
||||||
|
*/
|
||||||
|
public fun <T : Any, F : FunctionOptimization<T>> DifferentiableExpression<T, Expression<T>>.optimizeWith(
|
||||||
|
factory: OptimizationProblemFactory<T, F>,
|
||||||
|
vararg symbols: Symbol,
|
||||||
|
configuration: F.() -> Unit,
|
||||||
|
): OptimizationResult<T> {
|
||||||
|
require(symbols.isNotEmpty()) { "Must provide a list of symbols for optimization" }
|
||||||
|
val problem = factory(symbols.toList(), configuration)
|
||||||
|
problem.diffFunction(this)
|
||||||
|
return problem.optimize()
|
||||||
|
}
|
@ -0,0 +1,69 @@
|
|||||||
|
package space.kscience.kmath.optimization
|
||||||
|
|
||||||
|
import space.kscience.kmath.expressions.Expression
|
||||||
|
import space.kscience.kmath.misc.Symbol
|
||||||
|
import space.kscience.kmath.structures.Buffer
|
||||||
|
import space.kscience.kmath.structures.indices
|
||||||
|
import kotlin.math.pow
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A likelihood function optimization problem
|
||||||
|
*/
|
||||||
|
public interface NoDerivFunctionOptimization<T : Any> : Optimization<T> {
|
||||||
|
/**
|
||||||
|
* The optimization direction. If true search for function maximum, if false, search for the minimum
|
||||||
|
*/
|
||||||
|
public var maximize: Boolean
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Define the initial guess for the optimization problem
|
||||||
|
*/
|
||||||
|
public fun initialGuess(map: Map<Symbol, T>)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set an objective function expression
|
||||||
|
*/
|
||||||
|
public fun function(expression: Expression<T>)
|
||||||
|
|
||||||
|
public companion object {
|
||||||
|
/**
|
||||||
|
* Generate a chi squared expression from given x-y-sigma model represented by an expression. Does not provide derivatives
|
||||||
|
*/
|
||||||
|
public fun chiSquared(
|
||||||
|
x: Buffer<Double>,
|
||||||
|
y: Buffer<Double>,
|
||||||
|
yErr: Buffer<Double>,
|
||||||
|
model: Expression<Double>,
|
||||||
|
xSymbol: Symbol = Symbol.x,
|
||||||
|
): Expression<Double> {
|
||||||
|
require(x.size == y.size) { "X and y buffers should be of the same size" }
|
||||||
|
require(y.size == yErr.size) { "Y and yErr buffer should of the same size" }
|
||||||
|
|
||||||
|
return Expression { arguments ->
|
||||||
|
x.indices.sumByDouble {
|
||||||
|
val xValue = x[it]
|
||||||
|
val yValue = y[it]
|
||||||
|
val yErrValue = yErr[it]
|
||||||
|
val modifiedArgs = arguments + (xSymbol to xValue)
|
||||||
|
val modelValue = model(modifiedArgs)
|
||||||
|
((yValue - modelValue) / yErrValue).pow(2)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Optimize expression without derivatives using specific [OptimizationProblemFactory]
|
||||||
|
*/
|
||||||
|
public fun <T : Any, F : NoDerivFunctionOptimization<T>> Expression<T>.noDerivOptimizeWith(
|
||||||
|
factory: OptimizationProblemFactory<T, F>,
|
||||||
|
vararg symbols: Symbol,
|
||||||
|
configuration: F.() -> Unit,
|
||||||
|
): OptimizationResult<T> {
|
||||||
|
require(symbols.isNotEmpty()) { "Must provide a list of symbols for optimization" }
|
||||||
|
val problem = factory(symbols.toList(), configuration)
|
||||||
|
problem.function(this)
|
||||||
|
return problem.optimize()
|
||||||
|
}
|
@ -0,0 +1,44 @@
|
|||||||
|
package space.kscience.kmath.optimization
|
||||||
|
|
||||||
|
import space.kscience.kmath.misc.Symbol
|
||||||
|
|
||||||
|
public interface OptimizationFeature
|
||||||
|
|
||||||
|
public class OptimizationResult<T>(
|
||||||
|
public val point: Map<Symbol, T>,
|
||||||
|
public val value: T,
|
||||||
|
public val features: Set<OptimizationFeature> = emptySet(),
|
||||||
|
) {
|
||||||
|
override fun toString(): String {
|
||||||
|
return "OptimizationResult(point=$point, value=$value)"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public operator fun <T> OptimizationResult<T>.plus(
|
||||||
|
feature: OptimizationFeature,
|
||||||
|
): OptimizationResult<T> = OptimizationResult(point, value, features + feature)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An optimization problem builder over [T] variables
|
||||||
|
*/
|
||||||
|
public interface Optimization<T : Any> {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Update the problem from previous optimization run
|
||||||
|
*/
|
||||||
|
public fun update(result: OptimizationResult<T>)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Make an optimization run
|
||||||
|
*/
|
||||||
|
public fun optimize(): OptimizationResult<T>
|
||||||
|
}
|
||||||
|
|
||||||
|
public fun interface OptimizationProblemFactory<T : Any, out P : Optimization<T>> {
|
||||||
|
public fun build(symbols: List<Symbol>): P
|
||||||
|
}
|
||||||
|
|
||||||
|
public operator fun <T : Any, P : Optimization<T>> OptimizationProblemFactory<T, P>.invoke(
|
||||||
|
symbols: List<Symbol>,
|
||||||
|
block: P.() -> Unit,
|
||||||
|
): P = build(symbols).apply(block)
|
@ -0,0 +1,40 @@
|
|||||||
|
package space.kscience.kmath.optimization
|
||||||
|
|
||||||
|
import space.kscience.kmath.data.ColumnarData
|
||||||
|
import space.kscience.kmath.expressions.AutoDiffProcessor
|
||||||
|
import space.kscience.kmath.expressions.DifferentiableExpression
|
||||||
|
import space.kscience.kmath.expressions.Expression
|
||||||
|
import space.kscience.kmath.expressions.ExpressionAlgebra
|
||||||
|
import space.kscience.kmath.misc.Symbol
|
||||||
|
import space.kscience.kmath.misc.UnstableKMathAPI
|
||||||
|
import space.kscience.kmath.operations.ExtendedField
|
||||||
|
import space.kscience.kmath.operations.Field
|
||||||
|
|
||||||
|
@UnstableKMathAPI
|
||||||
|
public interface XYFit<T : Any> : Optimization<T> {
|
||||||
|
|
||||||
|
public val algebra: Field<T>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set X-Y data for this fit optionally including x and y errors
|
||||||
|
*/
|
||||||
|
public fun data(
|
||||||
|
dataSet: ColumnarData<T>,
|
||||||
|
xSymbol: Symbol,
|
||||||
|
ySymbol: Symbol,
|
||||||
|
xErrSymbol: Symbol? = null,
|
||||||
|
yErrSymbol: Symbol? = null,
|
||||||
|
)
|
||||||
|
|
||||||
|
public fun model(model: (T) -> DifferentiableExpression<T, *>)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the differentiable model for this fit
|
||||||
|
*/
|
||||||
|
public fun <I : Any, A> model(
|
||||||
|
autoDiff: AutoDiffProcessor<T, I, A, Expression<T>>,
|
||||||
|
modelFunction: A.(I) -> I,
|
||||||
|
): Unit where A : ExtendedField<I>, A : ExpressionAlgebra<T, I> = model { arg ->
|
||||||
|
autoDiff.process { modelFunction(const(arg)) }
|
||||||
|
}
|
||||||
|
}
|
@ -1,17 +1,29 @@
|
|||||||
package space.kscience.kmath.stat
|
package space.kscience.kmath.stat
|
||||||
|
|
||||||
|
import kotlinx.coroutines.flow.first
|
||||||
import space.kscience.kmath.chains.Chain
|
import space.kscience.kmath.chains.Chain
|
||||||
import space.kscience.kmath.chains.collect
|
import space.kscience.kmath.chains.collect
|
||||||
import space.kscience.kmath.structures.Buffer
|
import space.kscience.kmath.structures.Buffer
|
||||||
import space.kscience.kmath.structures.BufferFactory
|
import space.kscience.kmath.structures.BufferFactory
|
||||||
import space.kscience.kmath.structures.DoubleBuffer
|
import space.kscience.kmath.structures.IntBuffer
|
||||||
|
import space.kscience.kmath.structures.MutableBuffer
|
||||||
|
import kotlin.jvm.JvmName
|
||||||
|
|
||||||
public interface Sampler<T : Any> {
|
/**
|
||||||
|
* Sampler that generates chains of values of type [T].
|
||||||
|
*/
|
||||||
|
public fun interface Sampler<T : Any> {
|
||||||
|
/**
|
||||||
|
* Generates a chain of samples.
|
||||||
|
*
|
||||||
|
* @param generator the randomness provider.
|
||||||
|
* @return the new chain.
|
||||||
|
*/
|
||||||
public fun sample(generator: RandomGenerator): Chain<T>
|
public fun sample(generator: RandomGenerator): Chain<T>
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A distribution of typed objects
|
* A distribution of typed objects.
|
||||||
*/
|
*/
|
||||||
public interface Distribution<T : Any> : Sampler<T> {
|
public interface Distribution<T : Any> : Sampler<T> {
|
||||||
/**
|
/**
|
||||||
@ -20,11 +32,7 @@ public interface Distribution<T : Any> : Sampler<T> {
|
|||||||
*/
|
*/
|
||||||
public fun probability(arg: T): Double
|
public fun probability(arg: T): Double
|
||||||
|
|
||||||
/**
|
public override fun sample(generator: RandomGenerator): Chain<T>
|
||||||
* Create a chain of samples from this distribution.
|
|
||||||
* The chain is not guaranteed to be stateless, but different sample chains should be independent.
|
|
||||||
*/
|
|
||||||
override fun sample(generator: RandomGenerator): Chain<T>
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An empty companion. Distribution factories should be written as its extensions
|
* An empty companion. Distribution factories should be written as its extensions
|
||||||
@ -63,16 +71,27 @@ public fun <T : Any> Sampler<T>.sampleBuffer(
|
|||||||
//clear list from previous run
|
//clear list from previous run
|
||||||
tmp.clear()
|
tmp.clear()
|
||||||
//Fill list
|
//Fill list
|
||||||
repeat(size) {
|
repeat(size) { tmp += chain.next() }
|
||||||
tmp.add(chain.next())
|
|
||||||
}
|
|
||||||
//return new buffer with elements from tmp
|
//return new buffer with elements from tmp
|
||||||
bufferFactory(size) { tmp[it] }
|
bufferFactory(size) { tmp[it] }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Generate a bunch of samples from real distributions
|
* Samples one value from this [Sampler].
|
||||||
*/
|
*/
|
||||||
|
public suspend fun <T : Any> Sampler<T>.next(generator: RandomGenerator): T = sample(generator).first()
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generates [size] real samples and chunks them into some buffers.
|
||||||
|
*/
|
||||||
|
@JvmName("sampleRealBuffer")
|
||||||
public fun Sampler<Double>.sampleBuffer(generator: RandomGenerator, size: Int): Chain<Buffer<Double>> =
|
public fun Sampler<Double>.sampleBuffer(generator: RandomGenerator, size: Int): Chain<Buffer<Double>> =
|
||||||
sampleBuffer(generator, size, ::DoubleBuffer)
|
sampleBuffer(generator, size, MutableBuffer.Companion::double)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generates [size] integer samples and chunks them into some buffers.
|
||||||
|
*/
|
||||||
|
@JvmName("sampleIntBuffer")
|
||||||
|
public fun Sampler<Int>.sampleBuffer(generator: RandomGenerator, size: Int): Chain<Buffer<Int>> =
|
||||||
|
sampleBuffer(generator, size, ::IntBuffer)
|
||||||
|
@ -14,7 +14,7 @@ public interface NamedDistribution<T> : Distribution<Map<String, T>>
|
|||||||
public class FactorizedDistribution<T>(public val distributions: Collection<NamedDistribution<T>>) :
|
public class FactorizedDistribution<T>(public val distributions: Collection<NamedDistribution<T>>) :
|
||||||
NamedDistribution<T> {
|
NamedDistribution<T> {
|
||||||
override fun probability(arg: Map<String, T>): Double =
|
override fun probability(arg: Map<String, T>): Double =
|
||||||
distributions.fold(1.0) { acc, distr -> acc * distr.probability(arg) }
|
distributions.fold(1.0) { acc, dist -> acc * dist.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) }
|
||||||
@ -38,6 +38,6 @@ public class DistributionBuilder<T : Any> {
|
|||||||
private val distributions = ArrayList<NamedDistribution<T>>()
|
private val distributions = ArrayList<NamedDistribution<T>>()
|
||||||
|
|
||||||
public infix fun String.to(distribution: Distribution<T>) {
|
public infix fun String.to(distribution: Distribution<T>) {
|
||||||
distributions.add(NamedDistributionWrapper(this, distribution))
|
distributions += NamedDistributionWrapper(this, distribution)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,63 +0,0 @@
|
|||||||
package space.kscience.kmath.stat
|
|
||||||
|
|
||||||
import space.kscience.kmath.expressions.*
|
|
||||||
import space.kscience.kmath.operations.ExtendedField
|
|
||||||
import space.kscience.kmath.structures.Buffer
|
|
||||||
import space.kscience.kmath.structures.indices
|
|
||||||
import kotlin.math.pow
|
|
||||||
|
|
||||||
public object Fitting {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Generate a chi squared expression from given x-y-sigma data and inline model. Provides automatic differentiation
|
|
||||||
*/
|
|
||||||
public fun <T : Any, I : Any, A> chiSquared(
|
|
||||||
autoDiff: AutoDiffProcessor<T, I, A, Expression<T>>,
|
|
||||||
x: Buffer<T>,
|
|
||||||
y: Buffer<T>,
|
|
||||||
yErr: Buffer<T>,
|
|
||||||
model: A.(I) -> I,
|
|
||||||
): DifferentiableExpression<T, Expression<T>> where A : ExtendedField<I>, A : ExpressionAlgebra<T, I> {
|
|
||||||
require(x.size == y.size) { "X and y buffers should be of the same size" }
|
|
||||||
require(y.size == yErr.size) { "Y and yErr buffer should of the same size" }
|
|
||||||
|
|
||||||
return autoDiff.process {
|
|
||||||
var sum = zero
|
|
||||||
|
|
||||||
x.indices.forEach {
|
|
||||||
val xValue = const(x[it])
|
|
||||||
val yValue = const(y[it])
|
|
||||||
val yErrValue = const(yErr[it])
|
|
||||||
val modelValue = model(xValue)
|
|
||||||
sum += ((yValue - modelValue) / yErrValue).pow(2)
|
|
||||||
}
|
|
||||||
|
|
||||||
sum
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Generate a chi squared expression from given x-y-sigma model represented by an expression. Does not provide derivatives
|
|
||||||
*/
|
|
||||||
public fun chiSquared(
|
|
||||||
x: Buffer<Double>,
|
|
||||||
y: Buffer<Double>,
|
|
||||||
yErr: Buffer<Double>,
|
|
||||||
model: Expression<Double>,
|
|
||||||
xSymbol: Symbol = StringSymbol("x"),
|
|
||||||
): Expression<Double> {
|
|
||||||
require(x.size == y.size) { "X and y buffers should be of the same size" }
|
|
||||||
require(y.size == yErr.size) { "Y and yErr buffer should of the same size" }
|
|
||||||
|
|
||||||
return Expression { arguments ->
|
|
||||||
x.indices.sumByDouble {
|
|
||||||
val xValue = x[it]
|
|
||||||
val yValue = y[it]
|
|
||||||
val yErrValue = yErr[it]
|
|
||||||
val modifiedArgs = arguments + (xSymbol to xValue)
|
|
||||||
val modelValue = model(modifiedArgs)
|
|
||||||
((yValue - modelValue) / yErrValue).pow(2)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,88 +0,0 @@
|
|||||||
package space.kscience.kmath.stat
|
|
||||||
|
|
||||||
import space.kscience.kmath.expressions.DifferentiableExpression
|
|
||||||
import space.kscience.kmath.expressions.Expression
|
|
||||||
import space.kscience.kmath.expressions.Symbol
|
|
||||||
|
|
||||||
public interface OptimizationFeature
|
|
||||||
|
|
||||||
public class OptimizationResult<T>(
|
|
||||||
public val point: Map<Symbol, T>,
|
|
||||||
public val value: T,
|
|
||||||
public val features: Set<OptimizationFeature> = emptySet(),
|
|
||||||
) {
|
|
||||||
override fun toString(): String {
|
|
||||||
return "OptimizationResult(point=$point, value=$value)"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public operator fun <T> OptimizationResult<T>.plus(
|
|
||||||
feature: OptimizationFeature,
|
|
||||||
): OptimizationResult<T> = OptimizationResult(point, value, features + feature)
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A configuration builder for optimization problem
|
|
||||||
*/
|
|
||||||
public interface OptimizationProblem<T : Any> {
|
|
||||||
/**
|
|
||||||
* Define the initial guess for the optimization problem
|
|
||||||
*/
|
|
||||||
public fun initialGuess(map: Map<Symbol, T>)
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set an objective function expression
|
|
||||||
*/
|
|
||||||
public fun expression(expression: Expression<T>)
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set a differentiable expression as objective function as function and gradient provider
|
|
||||||
*/
|
|
||||||
public fun diffExpression(expression: DifferentiableExpression<T, Expression<T>>)
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Update the problem from previous optimization run
|
|
||||||
*/
|
|
||||||
public fun update(result: OptimizationResult<T>)
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Make an optimization run
|
|
||||||
*/
|
|
||||||
public fun optimize(): OptimizationResult<T>
|
|
||||||
}
|
|
||||||
|
|
||||||
public fun interface OptimizationProblemFactory<T : Any, out P : OptimizationProblem<T>> {
|
|
||||||
public fun build(symbols: List<Symbol>): P
|
|
||||||
}
|
|
||||||
|
|
||||||
public operator fun <T : Any, P : OptimizationProblem<T>> OptimizationProblemFactory<T, P>.invoke(
|
|
||||||
symbols: List<Symbol>,
|
|
||||||
block: P.() -> Unit,
|
|
||||||
): P = build(symbols).apply(block)
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Optimize expression without derivatives using specific [OptimizationProblemFactory]
|
|
||||||
*/
|
|
||||||
public fun <T : Any, F : OptimizationProblem<T>> Expression<T>.optimizeWith(
|
|
||||||
factory: OptimizationProblemFactory<T, F>,
|
|
||||||
vararg symbols: Symbol,
|
|
||||||
configuration: F.() -> Unit,
|
|
||||||
): OptimizationResult<T> {
|
|
||||||
require(symbols.isNotEmpty()) { "Must provide a list of symbols for optimization" }
|
|
||||||
val problem = factory(symbols.toList(), configuration)
|
|
||||||
problem.expression(this)
|
|
||||||
return problem.optimize()
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Optimize differentiable expression using specific [OptimizationProblemFactory]
|
|
||||||
*/
|
|
||||||
public fun <T : Any, F : OptimizationProblem<T>> DifferentiableExpression<T, Expression<T>>.optimizeWith(
|
|
||||||
factory: OptimizationProblemFactory<T, F>,
|
|
||||||
vararg symbols: Symbol,
|
|
||||||
configuration: F.() -> Unit,
|
|
||||||
): OptimizationResult<T> {
|
|
||||||
require(symbols.isNotEmpty()) { "Must provide a list of symbols for optimization" }
|
|
||||||
val problem = factory(symbols.toList(), configuration)
|
|
||||||
problem.diffExpression(this)
|
|
||||||
return problem.optimize()
|
|
||||||
}
|
|
@ -1,17 +1,22 @@
|
|||||||
package space.kscience.kmath.stat
|
package space.kscience.kmath.stat
|
||||||
|
|
||||||
|
import space.kscience.kmath.chains.BlockingDoubleChain
|
||||||
|
import space.kscience.kmath.chains.BlockingIntChain
|
||||||
import space.kscience.kmath.chains.Chain
|
import space.kscience.kmath.chains.Chain
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A possibly stateful chain producing random values.
|
* A possibly stateful chain producing random values.
|
||||||
|
*
|
||||||
|
* @property generator the underlying [RandomGenerator] instance.
|
||||||
*/
|
*/
|
||||||
public class RandomChain<out R>(
|
public class RandomChain<out R>(
|
||||||
public val generator: RandomGenerator,
|
public val generator: RandomGenerator,
|
||||||
private val gen: suspend RandomGenerator.() -> R,
|
private val gen: suspend RandomGenerator.() -> R
|
||||||
) : Chain<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)
|
||||||
}
|
}
|
||||||
|
|
||||||
public 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)
|
||||||
|
public fun Chain<Double>.blocking(): BlockingDoubleChain = object : Chain<Double> by this, BlockingDoubleChain {}
|
||||||
|
public fun Chain<Int>.blocking(): BlockingIntChain = object : Chain<Int> by this, BlockingIntChain {}
|
||||||
|
@ -82,6 +82,8 @@ public interface RandomGenerator {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Implements [RandomGenerator] by delegating all operations to [Random].
|
* Implements [RandomGenerator] by delegating all operations to [Random].
|
||||||
|
*
|
||||||
|
* @property random the underlying [Random] object.
|
||||||
*/
|
*/
|
||||||
public class DefaultGenerator(public val random: Random = Random) : RandomGenerator {
|
public class DefaultGenerator(public val random: Random = Random) : RandomGenerator {
|
||||||
public override fun nextBoolean(): Boolean = random.nextBoolean()
|
public override fun nextBoolean(): Boolean = random.nextBoolean()
|
||||||
|
@ -8,16 +8,28 @@ import space.kscience.kmath.operations.Group
|
|||||||
import space.kscience.kmath.operations.ScaleOperations
|
import space.kscience.kmath.operations.ScaleOperations
|
||||||
import space.kscience.kmath.operations.invoke
|
import space.kscience.kmath.operations.invoke
|
||||||
|
|
||||||
public class BasicSampler<T : Any>(public val chainBuilder: (RandomGenerator) -> Chain<T>) : Sampler<T> {
|
/**
|
||||||
public override fun sample(generator: RandomGenerator): Chain<T> = chainBuilder(generator)
|
* Implements [Sampler] by sampling only certain [value].
|
||||||
}
|
*
|
||||||
|
* @property value the value to sample.
|
||||||
|
*/
|
||||||
public class ConstantSampler<T : Any>(public val value: T) : Sampler<T> {
|
public class ConstantSampler<T : Any>(public val value: T) : Sampler<T> {
|
||||||
public 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
|
* Implements [Sampler] by delegating sampling to value of [chainBuilder].
|
||||||
|
*
|
||||||
|
* @property chainBuilder the provider of [Chain].
|
||||||
|
*/
|
||||||
|
public class BasicSampler<T : Any>(public val chainBuilder: (RandomGenerator) -> Chain<T>) : Sampler<T> {
|
||||||
|
public override fun sample(generator: RandomGenerator): Chain<T> = chainBuilder(generator)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A space of samplers. Allows to perform simple operations on distributions.
|
||||||
|
*
|
||||||
|
* @property algebra the space to provide addition and scalar multiplication for [T].
|
||||||
*/
|
*/
|
||||||
public class SamplerSpace<T : Any, S>(public val algebra: S) : Group<Sampler<T>>,
|
public class SamplerSpace<T : Any, S>(public val algebra: S) : Group<Sampler<T>>,
|
||||||
ScaleOperations<Sampler<T>> where S : Group<T>, S : ScaleOperations<T> {
|
ScaleOperations<Sampler<T>> where S : Group<T>, S : ScaleOperations<T> {
|
||||||
@ -29,8 +41,10 @@ public class SamplerSpace<T : Any, S>(public val algebra: S) : Group<Sampler<T>>
|
|||||||
}
|
}
|
||||||
|
|
||||||
public override fun scale(a: Sampler<T>, value: Double): Sampler<T> = BasicSampler { generator ->
|
public override fun scale(a: Sampler<T>, value: Double): Sampler<T> = BasicSampler { generator ->
|
||||||
a.sample(generator).map { algebra { it * value } }
|
a.sample(generator).map { a ->
|
||||||
|
algebra { a * value }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun Sampler<T>.unaryMinus(): Sampler<T> = scale(this, -1.0)
|
public override fun Sampler<T>.unaryMinus(): Sampler<T> = scale(this, -1.0)
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,41 @@
|
|||||||
|
package space.kscience.kmath.stat.distributions
|
||||||
|
|
||||||
|
import space.kscience.kmath.chains.Chain
|
||||||
|
import space.kscience.kmath.stat.RandomGenerator
|
||||||
|
import space.kscience.kmath.stat.UnivariateDistribution
|
||||||
|
import space.kscience.kmath.stat.internal.InternalErf
|
||||||
|
import space.kscience.kmath.stat.samplers.GaussianSampler
|
||||||
|
import space.kscience.kmath.stat.samplers.NormalizedGaussianSampler
|
||||||
|
import space.kscience.kmath.stat.samplers.ZigguratNormalizedGaussianSampler
|
||||||
|
import kotlin.math.*
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Implements [UnivariateDistribution] for the normal (gaussian) distribution.
|
||||||
|
*/
|
||||||
|
public inline class NormalDistribution(public val sampler: GaussianSampler) : UnivariateDistribution<Double> {
|
||||||
|
public constructor(
|
||||||
|
mean: Double,
|
||||||
|
standardDeviation: Double,
|
||||||
|
normalized: NormalizedGaussianSampler = ZigguratNormalizedGaussianSampler.of(),
|
||||||
|
) : this(GaussianSampler.of(mean, standardDeviation, normalized))
|
||||||
|
|
||||||
|
public override fun probability(arg: Double): Double {
|
||||||
|
val x1 = (arg - sampler.mean) / sampler.standardDeviation
|
||||||
|
return exp(-0.5 * x1 * x1 - (ln(sampler.standardDeviation) + 0.5 * ln(2 * PI)))
|
||||||
|
}
|
||||||
|
|
||||||
|
public override fun sample(generator: RandomGenerator): Chain<Double> = sampler.sample(generator)
|
||||||
|
|
||||||
|
public override fun cumulative(arg: Double): Double {
|
||||||
|
val dev = arg - sampler.mean
|
||||||
|
|
||||||
|
return when {
|
||||||
|
abs(dev) > 40 * sampler.standardDeviation -> if (dev < 0) 0.0 else 1.0
|
||||||
|
else -> 0.5 * InternalErf.erfc(-dev / (sampler.standardDeviation * SQRT2))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private companion object {
|
||||||
|
private val SQRT2 = sqrt(2.0)
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,15 @@
|
|||||||
|
package space.kscience.kmath.stat.internal
|
||||||
|
|
||||||
|
import kotlin.math.abs
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Based on Commons Math implementation.
|
||||||
|
* See [https://commons.apache.org/proper/commons-math/javadocs/api-3.3/org/apache/commons/math3/special/Erf.html].
|
||||||
|
*/
|
||||||
|
internal object InternalErf {
|
||||||
|
fun erfc(x: Double): Double {
|
||||||
|
if (abs(x) > 40) return if (x > 0) 0.0 else 2.0
|
||||||
|
val ret = InternalGamma.regularizedGammaQ(0.5, x * x, 10000)
|
||||||
|
return if (x < 0) 2 - ret else ret
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,238 @@
|
|||||||
|
package space.kscience.kmath.stat.internal
|
||||||
|
|
||||||
|
import kotlin.math.*
|
||||||
|
|
||||||
|
private abstract class ContinuedFraction protected constructor() {
|
||||||
|
protected abstract fun getA(n: Int, x: Double): Double
|
||||||
|
protected abstract fun getB(n: Int, x: Double): Double
|
||||||
|
|
||||||
|
fun evaluate(x: Double, maxIterations: Int): Double {
|
||||||
|
val small = 1e-50
|
||||||
|
var hPrev = getA(0, x)
|
||||||
|
if (hPrev == 0.0 || abs(0.0 - hPrev) <= small) hPrev = small
|
||||||
|
var n = 1
|
||||||
|
var dPrev = 0.0
|
||||||
|
var cPrev = hPrev
|
||||||
|
var hN = hPrev
|
||||||
|
|
||||||
|
while (n < maxIterations) {
|
||||||
|
val a = getA(n, x)
|
||||||
|
val b = getB(n, x)
|
||||||
|
var dN = a + b * dPrev
|
||||||
|
if (dN == 0.0 || abs(0.0 - dN) <= small) dN = small
|
||||||
|
var cN = a + b / cPrev
|
||||||
|
if (cN == 0.0 || abs(0.0 - cN) <= small) cN = small
|
||||||
|
dN = 1 / dN
|
||||||
|
val deltaN = cN * dN
|
||||||
|
hN = hPrev * deltaN
|
||||||
|
check(!hN.isInfinite()) { "hN is infinite" }
|
||||||
|
check(!hN.isNaN()) { "hN is NaN" }
|
||||||
|
if (abs(deltaN - 1.0) < 10e-9) break
|
||||||
|
dPrev = dN
|
||||||
|
cPrev = cN
|
||||||
|
hPrev = hN
|
||||||
|
n++
|
||||||
|
}
|
||||||
|
|
||||||
|
check(n < maxIterations) { "n is more than maxIterations" }
|
||||||
|
return hN
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal object InternalGamma {
|
||||||
|
const val LANCZOS_G = 607.0 / 128.0
|
||||||
|
|
||||||
|
private val LANCZOS = doubleArrayOf(
|
||||||
|
0.99999999999999709182,
|
||||||
|
57.156235665862923517,
|
||||||
|
-59.597960355475491248,
|
||||||
|
14.136097974741747174,
|
||||||
|
-0.49191381609762019978,
|
||||||
|
.33994649984811888699e-4,
|
||||||
|
.46523628927048575665e-4,
|
||||||
|
-.98374475304879564677e-4,
|
||||||
|
.15808870322491248884e-3,
|
||||||
|
-.21026444172410488319e-3,
|
||||||
|
.21743961811521264320e-3,
|
||||||
|
-.16431810653676389022e-3,
|
||||||
|
.84418223983852743293e-4,
|
||||||
|
-.26190838401581408670e-4,
|
||||||
|
.36899182659531622704e-5
|
||||||
|
)
|
||||||
|
|
||||||
|
private val HALF_LOG_2_PI = 0.5 * ln(2.0 * PI)
|
||||||
|
private const val INV_GAMMA1P_M1_A0 = .611609510448141581788E-08
|
||||||
|
private const val INV_GAMMA1P_M1_A1 = .624730830116465516210E-08
|
||||||
|
private const val INV_GAMMA1P_M1_B1 = .203610414066806987300E+00
|
||||||
|
private const val INV_GAMMA1P_M1_B2 = .266205348428949217746E-01
|
||||||
|
private const val INV_GAMMA1P_M1_B3 = .493944979382446875238E-03
|
||||||
|
private const val INV_GAMMA1P_M1_B4 = -.851419432440314906588E-05
|
||||||
|
private const val INV_GAMMA1P_M1_B5 = -.643045481779353022248E-05
|
||||||
|
private const val INV_GAMMA1P_M1_B6 = .992641840672773722196E-06
|
||||||
|
private const val INV_GAMMA1P_M1_B7 = -.607761895722825260739E-07
|
||||||
|
private const val INV_GAMMA1P_M1_B8 = .195755836614639731882E-09
|
||||||
|
private const val INV_GAMMA1P_M1_P0 = .6116095104481415817861E-08
|
||||||
|
private const val INV_GAMMA1P_M1_P1 = .6871674113067198736152E-08
|
||||||
|
private const val INV_GAMMA1P_M1_P2 = .6820161668496170657918E-09
|
||||||
|
private const val INV_GAMMA1P_M1_P3 = .4686843322948848031080E-10
|
||||||
|
private const val INV_GAMMA1P_M1_P4 = .1572833027710446286995E-11
|
||||||
|
private const val INV_GAMMA1P_M1_P5 = -.1249441572276366213222E-12
|
||||||
|
private const val INV_GAMMA1P_M1_P6 = .4343529937408594255178E-14
|
||||||
|
private const val INV_GAMMA1P_M1_Q1 = .3056961078365221025009E+00
|
||||||
|
private const val INV_GAMMA1P_M1_Q2 = .5464213086042296536016E-01
|
||||||
|
private const val INV_GAMMA1P_M1_Q3 = .4956830093825887312020E-02
|
||||||
|
private const val INV_GAMMA1P_M1_Q4 = .2692369466186361192876E-03
|
||||||
|
private const val INV_GAMMA1P_M1_C = -.422784335098467139393487909917598E+00
|
||||||
|
private const val INV_GAMMA1P_M1_C0 = .577215664901532860606512090082402E+00
|
||||||
|
private const val INV_GAMMA1P_M1_C1 = -.655878071520253881077019515145390E+00
|
||||||
|
private const val INV_GAMMA1P_M1_C2 = -.420026350340952355290039348754298E-01
|
||||||
|
private const val INV_GAMMA1P_M1_C3 = .166538611382291489501700795102105E+00
|
||||||
|
private const val INV_GAMMA1P_M1_C4 = -.421977345555443367482083012891874E-01
|
||||||
|
private const val INV_GAMMA1P_M1_C5 = -.962197152787697356211492167234820E-02
|
||||||
|
private const val INV_GAMMA1P_M1_C6 = .721894324666309954239501034044657E-02
|
||||||
|
private const val INV_GAMMA1P_M1_C7 = -.116516759185906511211397108401839E-02
|
||||||
|
private const val INV_GAMMA1P_M1_C8 = -.215241674114950972815729963053648E-03
|
||||||
|
private const val INV_GAMMA1P_M1_C9 = .128050282388116186153198626328164E-03
|
||||||
|
private const val INV_GAMMA1P_M1_C10 = -.201348547807882386556893914210218E-04
|
||||||
|
private const val INV_GAMMA1P_M1_C11 = -.125049348214267065734535947383309E-05
|
||||||
|
private const val INV_GAMMA1P_M1_C12 = .113302723198169588237412962033074E-05
|
||||||
|
private const val INV_GAMMA1P_M1_C13 = -.205633841697760710345015413002057E-06
|
||||||
|
|
||||||
|
fun logGamma(x: Double): Double = when {
|
||||||
|
x.isNaN() || x <= 0.0 -> Double.NaN
|
||||||
|
x < 0.5 -> logGamma1p(x) - ln(x)
|
||||||
|
x <= 2.5 -> logGamma1p(x - 0.5 - 0.5)
|
||||||
|
|
||||||
|
x <= 8.0 -> {
|
||||||
|
val n = floor(x - 1.5).toInt()
|
||||||
|
val prod = (1..n).fold(1.0, { prod, i -> prod * (x - i) })
|
||||||
|
logGamma1p(x - (n + 1)) + ln(prod)
|
||||||
|
}
|
||||||
|
|
||||||
|
else -> {
|
||||||
|
val tmp = x + LANCZOS_G + .5
|
||||||
|
(x + .5) * ln(tmp) - tmp + HALF_LOG_2_PI + ln(lanczos(x) / x)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun regularizedGammaP(
|
||||||
|
a: Double,
|
||||||
|
x: Double,
|
||||||
|
maxIterations: Int = Int.MAX_VALUE
|
||||||
|
): Double = when {
|
||||||
|
a.isNaN() || x.isNaN() || a <= 0.0 || x < 0.0 -> Double.NaN
|
||||||
|
x == 0.0 -> 0.0
|
||||||
|
x >= a + 1 -> 1.0 - regularizedGammaQ(a, x, maxIterations)
|
||||||
|
|
||||||
|
else -> {
|
||||||
|
// calculate series
|
||||||
|
var n = 0.0 // current element index
|
||||||
|
var an = 1.0 / a // n-th element in the series
|
||||||
|
var sum = an // partial sum
|
||||||
|
|
||||||
|
while (abs(an / sum) > 10e-15 && n < maxIterations && sum < Double.POSITIVE_INFINITY) {
|
||||||
|
// compute next element in the series
|
||||||
|
n += 1.0
|
||||||
|
an *= x / (a + n)
|
||||||
|
|
||||||
|
// update partial sum
|
||||||
|
sum += an
|
||||||
|
}
|
||||||
|
|
||||||
|
when {
|
||||||
|
n >= maxIterations -> throw error("Maximal iterations is exceeded $maxIterations")
|
||||||
|
sum.isInfinite() -> 1.0
|
||||||
|
else -> exp(-x + a * ln(x) - logGamma(a)) * sum
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun regularizedGammaQ(
|
||||||
|
a: Double,
|
||||||
|
x: Double,
|
||||||
|
maxIterations: Int = Int.MAX_VALUE
|
||||||
|
): Double = when {
|
||||||
|
a.isNaN() || x.isNaN() || a <= 0.0 || x < 0.0 -> Double.NaN
|
||||||
|
x == 0.0 -> 1.0
|
||||||
|
x < a + 1.0 -> 1.0 - regularizedGammaP(a, x, maxIterations)
|
||||||
|
|
||||||
|
else -> 1.0 / object : ContinuedFraction() {
|
||||||
|
override fun getA(n: Int, x: Double): Double = 2.0 * n + 1.0 - a + x
|
||||||
|
override fun getB(n: Int, x: Double): Double = n * (a - n)
|
||||||
|
}.evaluate(x, maxIterations) * exp(-x + a * ln(x) - logGamma(a))
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun lanczos(x: Double): Double =
|
||||||
|
(LANCZOS.size - 1 downTo 1).sumByDouble { LANCZOS[it] / (x + it) } + LANCZOS[0]
|
||||||
|
|
||||||
|
private fun invGamma1pm1(x: Double): Double {
|
||||||
|
require(x >= -0.5)
|
||||||
|
require(x <= 1.5)
|
||||||
|
val ret: Double
|
||||||
|
val t = if (x <= 0.5) x else x - 0.5 - 0.5
|
||||||
|
|
||||||
|
if (t < 0.0) {
|
||||||
|
val a = INV_GAMMA1P_M1_A0 + t * INV_GAMMA1P_M1_A1
|
||||||
|
var b = INV_GAMMA1P_M1_B8
|
||||||
|
b = INV_GAMMA1P_M1_B7 + t * b
|
||||||
|
b = INV_GAMMA1P_M1_B6 + t * b
|
||||||
|
b = INV_GAMMA1P_M1_B5 + t * b
|
||||||
|
b = INV_GAMMA1P_M1_B4 + t * b
|
||||||
|
b = INV_GAMMA1P_M1_B3 + t * b
|
||||||
|
b = INV_GAMMA1P_M1_B2 + t * b
|
||||||
|
b = INV_GAMMA1P_M1_B1 + t * b
|
||||||
|
b = 1.0 + t * b
|
||||||
|
var c = INV_GAMMA1P_M1_C13 + t * (a / b)
|
||||||
|
c = INV_GAMMA1P_M1_C12 + t * c
|
||||||
|
c = INV_GAMMA1P_M1_C11 + t * c
|
||||||
|
c = INV_GAMMA1P_M1_C10 + t * c
|
||||||
|
c = INV_GAMMA1P_M1_C9 + t * c
|
||||||
|
c = INV_GAMMA1P_M1_C8 + t * c
|
||||||
|
c = INV_GAMMA1P_M1_C7 + t * c
|
||||||
|
c = INV_GAMMA1P_M1_C6 + t * c
|
||||||
|
c = INV_GAMMA1P_M1_C5 + t * c
|
||||||
|
c = INV_GAMMA1P_M1_C4 + t * c
|
||||||
|
c = INV_GAMMA1P_M1_C3 + t * c
|
||||||
|
c = INV_GAMMA1P_M1_C2 + t * c
|
||||||
|
c = INV_GAMMA1P_M1_C1 + t * c
|
||||||
|
c = INV_GAMMA1P_M1_C + t * c
|
||||||
|
ret = (if (x > 0.5) t * c / x else x * (c + 0.5 + 0.5))
|
||||||
|
} else {
|
||||||
|
var p = INV_GAMMA1P_M1_P6
|
||||||
|
p = INV_GAMMA1P_M1_P5 + t * p
|
||||||
|
p = INV_GAMMA1P_M1_P4 + t * p
|
||||||
|
p = INV_GAMMA1P_M1_P3 + t * p
|
||||||
|
p = INV_GAMMA1P_M1_P2 + t * p
|
||||||
|
p = INV_GAMMA1P_M1_P1 + t * p
|
||||||
|
p = INV_GAMMA1P_M1_P0 + t * p
|
||||||
|
var q = INV_GAMMA1P_M1_Q4
|
||||||
|
q = INV_GAMMA1P_M1_Q3 + t * q
|
||||||
|
q = INV_GAMMA1P_M1_Q2 + t * q
|
||||||
|
q = INV_GAMMA1P_M1_Q1 + t * q
|
||||||
|
q = 1.0 + t * q
|
||||||
|
var c = INV_GAMMA1P_M1_C13 + p / q * t
|
||||||
|
c = INV_GAMMA1P_M1_C12 + t * c
|
||||||
|
c = INV_GAMMA1P_M1_C11 + t * c
|
||||||
|
c = INV_GAMMA1P_M1_C10 + t * c
|
||||||
|
c = INV_GAMMA1P_M1_C9 + t * c
|
||||||
|
c = INV_GAMMA1P_M1_C8 + t * c
|
||||||
|
c = INV_GAMMA1P_M1_C7 + t * c
|
||||||
|
c = INV_GAMMA1P_M1_C6 + t * c
|
||||||
|
c = INV_GAMMA1P_M1_C5 + t * c
|
||||||
|
c = INV_GAMMA1P_M1_C4 + t * c
|
||||||
|
c = INV_GAMMA1P_M1_C3 + t * c
|
||||||
|
c = INV_GAMMA1P_M1_C2 + t * c
|
||||||
|
c = INV_GAMMA1P_M1_C1 + t * c
|
||||||
|
c = INV_GAMMA1P_M1_C0 + t * c
|
||||||
|
ret = (if (x > 0.5) t / x * (c - 0.5 - 0.5) else x * c)
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun logGamma1p(x: Double): Double {
|
||||||
|
require(x >= -0.5)
|
||||||
|
require(x <= 1.5)
|
||||||
|
return -ln1p(invGamma1pm1(x))
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,70 @@
|
|||||||
|
package space.kscience.kmath.stat.internal
|
||||||
|
|
||||||
|
import kotlin.math.ln
|
||||||
|
import kotlin.math.min
|
||||||
|
|
||||||
|
internal object InternalUtils {
|
||||||
|
private val FACTORIALS = longArrayOf(
|
||||||
|
1L, 1L, 2L,
|
||||||
|
6L, 24L, 120L,
|
||||||
|
720L, 5040L, 40320L,
|
||||||
|
362880L, 3628800L, 39916800L,
|
||||||
|
479001600L, 6227020800L, 87178291200L,
|
||||||
|
1307674368000L, 20922789888000L, 355687428096000L,
|
||||||
|
6402373705728000L, 121645100408832000L, 2432902008176640000L
|
||||||
|
)
|
||||||
|
|
||||||
|
private const val BEGIN_LOG_FACTORIALS = 2
|
||||||
|
|
||||||
|
fun factorial(n: Int): Long = FACTORIALS[n]
|
||||||
|
|
||||||
|
fun validateProbabilities(probabilities: DoubleArray?): Double {
|
||||||
|
require(!(probabilities == null || probabilities.isEmpty())) { "Probabilities must not be empty." }
|
||||||
|
|
||||||
|
val sumProb = probabilities.sumByDouble { prob ->
|
||||||
|
require(!(prob < 0 || prob.isInfinite() || prob.isNaN())) { "Invalid probability: $prob" }
|
||||||
|
prob
|
||||||
|
}
|
||||||
|
|
||||||
|
require(!(sumProb.isInfinite() || sumProb <= 0)) { "Invalid sum of probabilities: $sumProb" }
|
||||||
|
return sumProb
|
||||||
|
}
|
||||||
|
|
||||||
|
class FactorialLog private constructor(numValues: Int, cache: DoubleArray?) {
|
||||||
|
private val logFactorials: DoubleArray = DoubleArray(numValues)
|
||||||
|
|
||||||
|
init {
|
||||||
|
val endCopy: Int
|
||||||
|
|
||||||
|
if (cache != null && cache.size > BEGIN_LOG_FACTORIALS) {
|
||||||
|
// Copy available values.
|
||||||
|
endCopy = min(cache.size, numValues)
|
||||||
|
|
||||||
|
cache.copyInto(
|
||||||
|
logFactorials,
|
||||||
|
BEGIN_LOG_FACTORIALS,
|
||||||
|
BEGIN_LOG_FACTORIALS, endCopy
|
||||||
|
)
|
||||||
|
} else
|
||||||
|
// All values to be computed
|
||||||
|
endCopy = BEGIN_LOG_FACTORIALS
|
||||||
|
|
||||||
|
// Compute remaining values.
|
||||||
|
(endCopy until numValues).forEach { i ->
|
||||||
|
if (i < FACTORIALS.size)
|
||||||
|
logFactorials[i] = ln(FACTORIALS[i].toDouble())
|
||||||
|
else
|
||||||
|
logFactorials[i] = logFactorials[i - 1] + ln(i.toDouble())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun value(n: Int): Double {
|
||||||
|
if (n < logFactorials.size) return logFactorials[n]
|
||||||
|
return if (n < FACTORIALS.size) ln(FACTORIALS[n].toDouble()) else InternalGamma.logGamma(n + 1.0)
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
fun create(): FactorialLog = FactorialLog(0, null)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,73 @@
|
|||||||
|
package space.kscience.kmath.stat.samplers
|
||||||
|
|
||||||
|
import space.kscience.kmath.chains.Chain
|
||||||
|
import space.kscience.kmath.stat.RandomGenerator
|
||||||
|
import space.kscience.kmath.stat.Sampler
|
||||||
|
import space.kscience.kmath.stat.chain
|
||||||
|
import space.kscience.kmath.stat.internal.InternalUtils
|
||||||
|
import kotlin.math.ln
|
||||||
|
import kotlin.math.pow
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sampling from an [exponential distribution](http://mathworld.wolfram.com/ExponentialDistribution.html).
|
||||||
|
*
|
||||||
|
* Based on Commons RNG implementation.
|
||||||
|
* See [https://commons.apache.org/proper/commons-rng/commons-rng-sampling/apidocs/org/apache/commons/rng/sampling/distribution/AhrensDieterExponentialSampler.html].
|
||||||
|
*/
|
||||||
|
public class AhrensDieterExponentialSampler private constructor(public val mean: Double) : Sampler<Double> {
|
||||||
|
public override fun sample(generator: RandomGenerator): Chain<Double> = generator.chain {
|
||||||
|
// Step 1:
|
||||||
|
var a = 0.0
|
||||||
|
var u = nextDouble()
|
||||||
|
|
||||||
|
// Step 2 and 3:
|
||||||
|
while (u < 0.5) {
|
||||||
|
a += EXPONENTIAL_SA_QI[0]
|
||||||
|
u *= 2.0
|
||||||
|
}
|
||||||
|
|
||||||
|
// Step 4 (now u >= 0.5):
|
||||||
|
u += u - 1
|
||||||
|
// Step 5:
|
||||||
|
if (u <= EXPONENTIAL_SA_QI[0]) return@chain mean * (a + u)
|
||||||
|
// Step 6:
|
||||||
|
var i = 0 // Should be 1, be we iterate before it in while using 0.
|
||||||
|
var u2 = nextDouble()
|
||||||
|
var umin = u2
|
||||||
|
|
||||||
|
// Step 7 and 8:
|
||||||
|
do {
|
||||||
|
++i
|
||||||
|
u2 = nextDouble()
|
||||||
|
if (u2 < umin) umin = u2
|
||||||
|
// Step 8:
|
||||||
|
} while (u > EXPONENTIAL_SA_QI[i]) // Ensured to exit since EXPONENTIAL_SA_QI[MAX] = 1.
|
||||||
|
|
||||||
|
mean * (a + umin * EXPONENTIAL_SA_QI[0])
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun toString(): String = "Ahrens-Dieter Exponential deviate"
|
||||||
|
|
||||||
|
public companion object {
|
||||||
|
private val EXPONENTIAL_SA_QI by lazy { DoubleArray(16) }
|
||||||
|
|
||||||
|
init {
|
||||||
|
/**
|
||||||
|
* Filling EXPONENTIAL_SA_QI table.
|
||||||
|
* Note that we don't want qi = 0 in the table.
|
||||||
|
*/
|
||||||
|
val ln2 = ln(2.0)
|
||||||
|
var qi = 0.0
|
||||||
|
|
||||||
|
EXPONENTIAL_SA_QI.indices.forEach { i ->
|
||||||
|
qi += ln2.pow(i + 1.0) / InternalUtils.factorial(i + 1)
|
||||||
|
EXPONENTIAL_SA_QI[i] = qi
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public fun of(mean: Double): AhrensDieterExponentialSampler {
|
||||||
|
require(mean > 0) { "mean is not strictly positive: $mean" }
|
||||||
|
return AhrensDieterExponentialSampler(mean)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,120 @@
|
|||||||
|
package space.kscience.kmath.stat.samplers
|
||||||
|
|
||||||
|
import space.kscience.kmath.chains.Chain
|
||||||
|
import space.kscience.kmath.stat.RandomGenerator
|
||||||
|
import space.kscience.kmath.stat.Sampler
|
||||||
|
import space.kscience.kmath.stat.chain
|
||||||
|
import space.kscience.kmath.stat.next
|
||||||
|
import kotlin.math.*
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sampling from the [gamma distribution](http://mathworld.wolfram.com/GammaDistribution.html).
|
||||||
|
* - For 0 < alpha < 1:
|
||||||
|
* Ahrens, J. H. and Dieter, U., Computer methods for sampling from gamma, beta, Poisson and binomial distributions, Computing, 12, 223-246, 1974.
|
||||||
|
* - For alpha >= 1:
|
||||||
|
* Marsaglia and Tsang, A Simple Method for Generating Gamma Variables. ACM Transactions on Mathematical Software, Volume 26 Issue 3, September, 2000.
|
||||||
|
*
|
||||||
|
* Based on Commons RNG implementation.
|
||||||
|
*
|
||||||
|
* See [https://commons.apache.org/proper/commons-rng/commons-rng-sampling/apidocs/org/apache/commons/rng/sampling/distribution/AhrensDieterMarsagliaTsangGammaSampler.html].
|
||||||
|
*/
|
||||||
|
public class AhrensDieterMarsagliaTsangGammaSampler private constructor(
|
||||||
|
alpha: 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
|
||||||
|
) : Sampler<Double> {
|
||||||
|
init {
|
||||||
|
require(alpha > 0) { "alpha is not strictly positive: $alpha" }
|
||||||
|
require(theta > 0) { "theta is not strictly positive: $theta" }
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun toString(): String = "Ahrens-Dieter-Marsaglia-Tsang Gamma deviate"
|
||||||
|
}
|
||||||
|
|
||||||
|
private class AhrensDieterGammaSampler(alpha: Double, theta: Double) :
|
||||||
|
BaseGammaSampler(alpha, theta) {
|
||||||
|
private val oneOverAlpha: Double = 1.0 / alpha
|
||||||
|
private val bGSOptim: Double = 1.0 + alpha / E
|
||||||
|
|
||||||
|
override fun sample(generator: RandomGenerator): Chain<Double> = generator.chain {
|
||||||
|
var x: Double
|
||||||
|
|
||||||
|
// [1]: p. 228, Algorithm GS.
|
||||||
|
while (true) {
|
||||||
|
// Step 1:
|
||||||
|
val u = generator.nextDouble()
|
||||||
|
val p = bGSOptim * u
|
||||||
|
|
||||||
|
if (p <= 1) {
|
||||||
|
// Step 2:
|
||||||
|
x = p.pow(oneOverAlpha)
|
||||||
|
val u2 = generator.nextDouble()
|
||||||
|
|
||||||
|
if (u2 > exp(-x)) // Reject.
|
||||||
|
continue
|
||||||
|
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
// Step 3:
|
||||||
|
x = -ln((bGSOptim - p) * oneOverAlpha)
|
||||||
|
val u2: Double = generator.nextDouble()
|
||||||
|
if (u2 <= x.pow(alpha - 1.0)) break
|
||||||
|
// Reject and continue.
|
||||||
|
}
|
||||||
|
|
||||||
|
x * theta
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private class MarsagliaTsangGammaSampler(alpha: Double, theta: Double) :
|
||||||
|
BaseGammaSampler(alpha, theta) {
|
||||||
|
private val dOptim: Double
|
||||||
|
private val cOptim: Double
|
||||||
|
private val gaussian: NormalizedGaussianSampler
|
||||||
|
|
||||||
|
init {
|
||||||
|
gaussian = ZigguratNormalizedGaussianSampler.of()
|
||||||
|
dOptim = alpha - ONE_THIRD
|
||||||
|
cOptim = ONE_THIRD / sqrt(dOptim)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun sample(generator: RandomGenerator): Chain<Double> = generator.chain {
|
||||||
|
var v: Double
|
||||||
|
|
||||||
|
while (true) {
|
||||||
|
val x = gaussian.next(generator)
|
||||||
|
val oPcTx = 1 + cOptim * x
|
||||||
|
v = oPcTx * oPcTx * oPcTx
|
||||||
|
if (v <= 0) continue
|
||||||
|
val x2 = x * x
|
||||||
|
val u = generator.nextDouble()
|
||||||
|
// Squeeze.
|
||||||
|
if (u < 1 - 0.0331 * x2 * x2) break
|
||||||
|
if (ln(u) < 0.5 * x2 + dOptim * (1 - v + ln(v))) break
|
||||||
|
}
|
||||||
|
|
||||||
|
theta * dOptim * v
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
private const val ONE_THIRD = 1.0 / 3.0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public override fun sample(generator: RandomGenerator): Chain<Double> = delegate.sample(generator)
|
||||||
|
public override fun toString(): String = delegate.toString()
|
||||||
|
|
||||||
|
public companion object {
|
||||||
|
public fun of(
|
||||||
|
alpha: Double,
|
||||||
|
theta: Double
|
||||||
|
): Sampler<Double> = AhrensDieterMarsagliaTsangGammaSampler(alpha, theta)
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,286 @@
|
|||||||
|
package space.kscience.kmath.stat.samplers
|
||||||
|
|
||||||
|
import space.kscience.kmath.chains.Chain
|
||||||
|
import space.kscience.kmath.stat.RandomGenerator
|
||||||
|
import space.kscience.kmath.stat.Sampler
|
||||||
|
import space.kscience.kmath.stat.chain
|
||||||
|
import space.kscience.kmath.stat.internal.InternalUtils
|
||||||
|
import kotlin.math.ceil
|
||||||
|
import kotlin.math.max
|
||||||
|
import kotlin.math.min
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Distribution sampler that uses the Alias method. It can be used to sample from n values each with an associated
|
||||||
|
* probability. This implementation is based on the detailed explanation of the alias method by Keith Schartz and
|
||||||
|
* implements Vose's algorithm.
|
||||||
|
*
|
||||||
|
* Vose, M.D., A linear algorithm for generating random numbers with a given distribution, IEEE Transactions on
|
||||||
|
* Software Engineering, 17, 972-975, 1991. he algorithm will sample values in O(1) time after a pre-processing step
|
||||||
|
* of O(n) time.
|
||||||
|
*
|
||||||
|
* The alias tables are constructed using fraction probabilities with an assumed denominator of 253. In the generic
|
||||||
|
* case sampling uses UniformRandomProvider.nextInt(int) and the upper 53-bits from UniformRandomProvider.nextLong().
|
||||||
|
*
|
||||||
|
* Zero padding the input probabilities can be used to make more sampling more efficient. Any zero entry will always be
|
||||||
|
* aliased removing the requirement to compute a long. Increased sampling speed comes at the cost of increased storage
|
||||||
|
* space. The algorithm requires approximately 12 bytes of storage per input probability, that is n * 12 for size n.
|
||||||
|
* Zero-padding only requires 4 bytes of storage per padded value as the probability is known to be zero.
|
||||||
|
*
|
||||||
|
* An optimisation is performed for small table sizes that are a power of 2. In this case the sampling uses 1 or 2
|
||||||
|
* calls from UniformRandomProvider.nextInt() to generate up to 64-bits for creation of an 11-bit index and 53-bits
|
||||||
|
* for the long. This optimisation requires a generator with a high cycle length for the lower order bits.
|
||||||
|
*
|
||||||
|
* Larger table sizes that are a power of 2 will benefit from fast algorithms for UniformRandomProvider.nextInt(int)
|
||||||
|
* that exploit the power of 2.
|
||||||
|
*
|
||||||
|
* Based on Commons RNG implementation.
|
||||||
|
* See [https://commons.apache.org/proper/commons-rng/commons-rng-sampling/apidocs/org/apache/commons/rng/sampling/distribution/AliasMethodDiscreteSampler.html].
|
||||||
|
*/
|
||||||
|
public open class AliasMethodDiscreteSampler private constructor(
|
||||||
|
// Deliberate direct storage of input arrays
|
||||||
|
protected val probability: LongArray,
|
||||||
|
protected val alias: IntArray
|
||||||
|
) : Sampler<Int> {
|
||||||
|
|
||||||
|
private class SmallTableAliasMethodDiscreteSampler(
|
||||||
|
probability: LongArray,
|
||||||
|
alias: IntArray
|
||||||
|
) : AliasMethodDiscreteSampler(probability, alias) {
|
||||||
|
// Assume the table size is a power of 2 and create the mask
|
||||||
|
private val mask: Int = alias.size - 1
|
||||||
|
|
||||||
|
override fun sample(generator: RandomGenerator): Chain<Int> = generator.chain {
|
||||||
|
val bits = generator.nextInt()
|
||||||
|
// Isolate lower bits
|
||||||
|
val j = bits and mask
|
||||||
|
|
||||||
|
// Optimisation for zero-padded input tables
|
||||||
|
if (j >= probability.size)
|
||||||
|
// No probability must use the alias
|
||||||
|
return@chain alias[j]
|
||||||
|
|
||||||
|
// Create a uniform random deviate as a long.
|
||||||
|
// This replicates functionality from the o.a.c.rng.core.utils.NumberFactory.makeLong
|
||||||
|
val longBits = generator.nextInt().toLong() shl 32 or (bits.toLong() and hex_ffffffff)
|
||||||
|
// Choose between the two. Use a 53-bit long for the probability.
|
||||||
|
if (longBits ushr 11 < probability[j]) j else alias[j]
|
||||||
|
}
|
||||||
|
|
||||||
|
private companion object {
|
||||||
|
private const val hex_ffffffff = 4294967295L
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public override fun sample(generator: RandomGenerator): Chain<Int> = generator.chain {
|
||||||
|
// This implements the algorithm as per Vose (1991):
|
||||||
|
// v = uniform() in [0, 1)
|
||||||
|
// j = uniform(n) in [0, n)
|
||||||
|
// if v < prob[j] then
|
||||||
|
// return j
|
||||||
|
// else
|
||||||
|
// return alias[j]
|
||||||
|
val j = generator.nextInt(alias.size)
|
||||||
|
|
||||||
|
// Optimisation for zero-padded input tables
|
||||||
|
// No probability must use the alias
|
||||||
|
if (j >= probability.size) return@chain alias[j]
|
||||||
|
|
||||||
|
// Note: We could check the probability before computing a deviate.
|
||||||
|
// p(j) == 0 => alias[j]
|
||||||
|
// p(j) == 1 => j
|
||||||
|
// However it is assumed these edge cases are rare:
|
||||||
|
//
|
||||||
|
// The probability table will be 1 for approximately 1/n samples, i.e. only the
|
||||||
|
// last unpaired probability. This is only worth checking for when the table size (n)
|
||||||
|
// is small. But in that case the user should zero-pad the table for performance.
|
||||||
|
//
|
||||||
|
// The probability table will be 0 when an input probability was zero. We
|
||||||
|
// will assume this is also rare if modelling a discrete distribution where
|
||||||
|
// all samples are possible. The edge case for zero-padded tables is handled above.
|
||||||
|
|
||||||
|
// Choose between the two. Use a 53-bit long for the probability.
|
||||||
|
if (generator.nextLong() ushr 11 < probability[j]) j else alias[j]
|
||||||
|
}
|
||||||
|
|
||||||
|
public override fun toString(): String = "Alias method"
|
||||||
|
|
||||||
|
public companion object {
|
||||||
|
private const val DEFAULT_ALPHA = 0
|
||||||
|
private const val ZERO = 0.0
|
||||||
|
private const val ONE_AS_NUMERATOR = 1L shl 53
|
||||||
|
private const val CONVERT_TO_NUMERATOR: Double = ONE_AS_NUMERATOR.toDouble()
|
||||||
|
private const val MAX_SMALL_POWER_2_SIZE = 1 shl 11
|
||||||
|
|
||||||
|
public fun of(
|
||||||
|
probabilities: DoubleArray,
|
||||||
|
alpha: Int = DEFAULT_ALPHA
|
||||||
|
): Sampler<Int> {
|
||||||
|
// The Alias method balances N categories with counts around the mean into N sections,
|
||||||
|
// each allocated 'mean' observations.
|
||||||
|
//
|
||||||
|
// Consider 4 categories with counts 6,3,2,1. The histogram can be balanced into a
|
||||||
|
// 2D array as 4 sections with a height of the mean:
|
||||||
|
//
|
||||||
|
// 6
|
||||||
|
// 6
|
||||||
|
// 6
|
||||||
|
// 63 => 6366 --
|
||||||
|
// 632 6326 |-- mean
|
||||||
|
// 6321 6321 --
|
||||||
|
//
|
||||||
|
// section abcd
|
||||||
|
//
|
||||||
|
// Each section is divided as:
|
||||||
|
// a: 6=1/1
|
||||||
|
// b: 3=1/1
|
||||||
|
// c: 2=2/3; 6=1/3 (6 is the alias)
|
||||||
|
// d: 1=1/3; 6=2/3 (6 is the alias)
|
||||||
|
//
|
||||||
|
// The sample is obtained by randomly selecting a section, then choosing which category
|
||||||
|
// from the pair based on a uniform random deviate.
|
||||||
|
val sumProb = InternalUtils.validateProbabilities(probabilities)
|
||||||
|
// Allow zero-padding
|
||||||
|
val n = computeSize(probabilities.size, alpha)
|
||||||
|
// Partition into small and large by splitting on the average.
|
||||||
|
val mean = sumProb / n
|
||||||
|
// The cardinality of smallSize + largeSize = n.
|
||||||
|
// So fill the same array from either end.
|
||||||
|
val indices = IntArray(n)
|
||||||
|
var large = n
|
||||||
|
var small = 0
|
||||||
|
|
||||||
|
probabilities.indices.forEach { i ->
|
||||||
|
if (probabilities[i] >= mean) indices[--large] = i else indices[small++] = i
|
||||||
|
}
|
||||||
|
|
||||||
|
small = fillRemainingIndices(probabilities.size, indices, small)
|
||||||
|
// This may be smaller than the input length if the probabilities were already padded.
|
||||||
|
val nonZeroIndex = findLastNonZeroIndex(probabilities)
|
||||||
|
// The probabilities are modified so use a copy.
|
||||||
|
// Note: probabilities are required only up to last nonZeroIndex
|
||||||
|
val remainingProbabilities = probabilities.copyOf(nonZeroIndex + 1)
|
||||||
|
// Allocate the final tables.
|
||||||
|
// Probability table may be truncated (when zero padded).
|
||||||
|
// The alias table is full length.
|
||||||
|
val probability = LongArray(remainingProbabilities.size)
|
||||||
|
val alias = IntArray(n)
|
||||||
|
|
||||||
|
// This loop uses each large in turn to fill the alias table for small probabilities that
|
||||||
|
// do not reach the requirement to fill an entire section alone (i.e. p < mean).
|
||||||
|
// Since the sum of the small should be less than the sum of the large it should use up
|
||||||
|
// all the small first. However floating point round-off can result in
|
||||||
|
// misclassification of items as small or large. The Vose algorithm handles this using
|
||||||
|
// a while loop conditioned on the size of both sets and a subsequent loop to use
|
||||||
|
// unpaired items.
|
||||||
|
while (large != n && small != 0) {
|
||||||
|
// Index of the small and the large probabilities.
|
||||||
|
val j = indices[--small]
|
||||||
|
val k = indices[large++]
|
||||||
|
|
||||||
|
// Optimisation for zero-padded input:
|
||||||
|
// p(j) = 0 above the last nonZeroIndex
|
||||||
|
if (j > nonZeroIndex)
|
||||||
|
// The entire amount for the section is taken from the alias.
|
||||||
|
remainingProbabilities[k] -= mean
|
||||||
|
else {
|
||||||
|
val pj = remainingProbabilities[j]
|
||||||
|
// Item j is a small probability that is below the mean.
|
||||||
|
// Compute the weight of the section for item j: pj / mean.
|
||||||
|
// This is scaled by 2^53 and the ceiling function used to round-up
|
||||||
|
// the probability to a numerator of a fraction in the range [1,2^53].
|
||||||
|
// Ceiling ensures non-zero values.
|
||||||
|
probability[j] = ceil(CONVERT_TO_NUMERATOR * (pj / mean)).toLong()
|
||||||
|
// The remaining amount for the section is taken from the alias.
|
||||||
|
// Effectively: probabilities[k] -= (mean - pj)
|
||||||
|
remainingProbabilities[k] += pj - mean
|
||||||
|
}
|
||||||
|
|
||||||
|
// If not j then the alias is k
|
||||||
|
alias[j] = k
|
||||||
|
|
||||||
|
// Add the remaining probability from large to the appropriate list.
|
||||||
|
if (remainingProbabilities[k] >= mean) indices[--large] = k else indices[small++] = k
|
||||||
|
}
|
||||||
|
|
||||||
|
// Final loop conditions to consume unpaired items.
|
||||||
|
// Note: The large set should never be non-empty but this can occur due to round-off
|
||||||
|
// error so consume from both.
|
||||||
|
fillTable(probability, alias, indices, 0, small)
|
||||||
|
fillTable(probability, alias, indices, large, n)
|
||||||
|
|
||||||
|
// Change the algorithm for small power of 2 sized tables
|
||||||
|
return if (isSmallPowerOf2(n))
|
||||||
|
SmallTableAliasMethodDiscreteSampler(probability, alias)
|
||||||
|
else
|
||||||
|
AliasMethodDiscreteSampler(probability, alias)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun fillRemainingIndices(length: Int, indices: IntArray, small: Int): Int {
|
||||||
|
var updatedSmall = small
|
||||||
|
(length until indices.size).forEach { i -> indices[updatedSmall++] = i }
|
||||||
|
return updatedSmall
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun findLastNonZeroIndex(probabilities: DoubleArray): Int {
|
||||||
|
// No bounds check is performed when decrementing as the array contains at least one
|
||||||
|
// value above zero.
|
||||||
|
var nonZeroIndex = probabilities.size - 1
|
||||||
|
while (probabilities[nonZeroIndex] == ZERO) nonZeroIndex--
|
||||||
|
return nonZeroIndex
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun computeSize(length: Int, alpha: Int): Int {
|
||||||
|
// If No padding
|
||||||
|
if (alpha < 0) return length
|
||||||
|
// Use the number of leading zeros function to find the next power of 2,
|
||||||
|
// i.e. ceil(log2(x))
|
||||||
|
var pow2 = 32 - numberOfLeadingZeros(length - 1)
|
||||||
|
// Increase by the alpha. Clip this to limit to a positive integer (2^30)
|
||||||
|
pow2 = min(30, pow2 + alpha)
|
||||||
|
// Use max to handle a length above the highest possible power of 2
|
||||||
|
return max(length, 1 shl pow2)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun fillTable(
|
||||||
|
probability: LongArray,
|
||||||
|
alias: IntArray,
|
||||||
|
indices: IntArray,
|
||||||
|
start: Int,
|
||||||
|
end: Int
|
||||||
|
) = (start until end).forEach { i ->
|
||||||
|
val index = indices[i]
|
||||||
|
probability[index] = ONE_AS_NUMERATOR
|
||||||
|
alias[index] = index
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun isSmallPowerOf2(n: Int): Boolean = n <= MAX_SMALL_POWER_2_SIZE && n and n - 1 == 0
|
||||||
|
|
||||||
|
private fun numberOfLeadingZeros(i: Int): Int {
|
||||||
|
var mutI = i
|
||||||
|
if (mutI <= 0) return if (mutI == 0) 32 else 0
|
||||||
|
var n = 31
|
||||||
|
|
||||||
|
if (mutI >= 1 shl 16) {
|
||||||
|
n -= 16
|
||||||
|
mutI = mutI ushr 16
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mutI >= 1 shl 8) {
|
||||||
|
n -= 8
|
||||||
|
mutI = mutI ushr 8
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mutI >= 1 shl 4) {
|
||||||
|
n -= 4
|
||||||
|
mutI = mutI ushr 4
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mutI >= 1 shl 2) {
|
||||||
|
n -= 2
|
||||||
|
mutI = mutI ushr 2
|
||||||
|
}
|
||||||
|
|
||||||
|
return n - (mutI ushr 1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,48 @@
|
|||||||
|
package space.kscience.kmath.stat.samplers
|
||||||
|
|
||||||
|
import space.kscience.kmath.chains.Chain
|
||||||
|
import space.kscience.kmath.stat.RandomGenerator
|
||||||
|
import space.kscience.kmath.stat.Sampler
|
||||||
|
import space.kscience.kmath.stat.chain
|
||||||
|
import kotlin.math.*
|
||||||
|
|
||||||
|
/**
|
||||||
|
* [Box-Muller algorithm](https://en.wikipedia.org/wiki/Box%E2%80%93Muller_transform) for sampling from a Gaussian
|
||||||
|
* distribution.
|
||||||
|
*
|
||||||
|
* Based on Commons RNG implementation.
|
||||||
|
* See [https://commons.apache.org/proper/commons-rng/commons-rng-sampling/apidocs/org/apache/commons/rng/sampling/distribution/BoxMullerNormalizedGaussianSampler.html].
|
||||||
|
*/
|
||||||
|
public class BoxMullerNormalizedGaussianSampler private constructor() : NormalizedGaussianSampler, Sampler<Double> {
|
||||||
|
private var nextGaussian: Double = Double.NaN
|
||||||
|
|
||||||
|
public override fun sample(generator: RandomGenerator): Chain<Double> = generator.chain {
|
||||||
|
val random: Double
|
||||||
|
|
||||||
|
if (nextGaussian.isNaN()) {
|
||||||
|
// Generate a pair of Gaussian numbers.
|
||||||
|
val x = nextDouble()
|
||||||
|
val y = nextDouble()
|
||||||
|
val alpha = 2 * PI * x
|
||||||
|
val r = sqrt(-2 * ln(y))
|
||||||
|
// Return the first element of the generated pair.
|
||||||
|
random = r * cos(alpha)
|
||||||
|
// Keep second element of the pair for next invocation.
|
||||||
|
nextGaussian = r * sin(alpha)
|
||||||
|
} else {
|
||||||
|
// Use the second element of the pair (generated at the
|
||||||
|
// previous invocation).
|
||||||
|
random = nextGaussian
|
||||||
|
// Both elements of the pair have been used.
|
||||||
|
nextGaussian = Double.NaN
|
||||||
|
}
|
||||||
|
|
||||||
|
random
|
||||||
|
}
|
||||||
|
|
||||||
|
public override fun toString(): String = "Box-Muller normalized Gaussian deviate"
|
||||||
|
|
||||||
|
public companion object {
|
||||||
|
public fun of(): BoxMullerNormalizedGaussianSampler = BoxMullerNormalizedGaussianSampler()
|
||||||
|
}
|
||||||
|
}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user