forked from kscience/kmath
kmath-for-real refactoring
This commit is contained in:
parent
c21e761a76
commit
5b653f10d7
@ -27,6 +27,7 @@
|
||||
- Full autodiff refactoring based on `Symbol`
|
||||
- `kmath-prob` renamed to `kmath-stat`
|
||||
- Grid generators moved to `kmath-for-real`
|
||||
- Use `Point<Double>` instead of specialized type in `kmath-for-real`
|
||||
|
||||
### Deprecated
|
||||
|
||||
|
38
README.md
38
README.md
@ -132,9 +132,17 @@ submit a feature request if you want something to be implemented first.
|
||||
<hr/>
|
||||
|
||||
* ### [kmath-for-real](kmath-for-real)
|
||||
>
|
||||
> Extension module that should be used to achieve numpy-like behavior.
|
||||
All operations are specialized to work with `Double` numbers without declaring algebraic contexts.
|
||||
One can still use generic algebras though.
|
||||
>
|
||||
> **Maturity**: EXPERIMENTAL
|
||||
>
|
||||
> **Features:**
|
||||
> - [RealVector](kmath-for-real/src/commonMain/kotlin/kscience/kmath/real/RealVector.kt) : Numpy-like operations for Buffers/Points
|
||||
> - [RealMatrix](kmath-for-real/src/commonMain/kotlin/kscience/kmath/real/RealMatrix.kt) : Numpy-like operations for 2d real structures
|
||||
> - [grids](kmath-for-real/src/commonMain/kotlin/kscience/kmath/structures/grids.kt) : Uniform grid generators
|
||||
|
||||
<hr/>
|
||||
|
||||
* ### [kmath-functions](kmath-functions)
|
||||
@ -155,6 +163,12 @@ submit a feature request if you want something to be implemented first.
|
||||
> **Maturity**: EXPERIMENTAL
|
||||
<hr/>
|
||||
|
||||
* ### [kmath-kotlingrad](kmath-kotlingrad)
|
||||
>
|
||||
>
|
||||
> **Maturity**: EXPERIMENTAL
|
||||
<hr/>
|
||||
|
||||
* ### [kmath-memory](kmath-memory)
|
||||
>
|
||||
>
|
||||
@ -167,7 +181,7 @@ submit a feature request if you want something to be implemented first.
|
||||
> **Maturity**: EXPERIMENTAL
|
||||
>
|
||||
> **Features:**
|
||||
> - [nd4jarraystrucure](kmath-nd4j/src/commonMain/kotlin/kscience/kmath/operations/Algebra.kt) : NDStructure wrapper for INDArray
|
||||
> - [nd4jarraystructure](kmath-nd4j/src/commonMain/kotlin/kscience/kmath/operations/Algebra.kt) : NDStructure wrapper for INDArray
|
||||
> - [nd4jarrayrings](kmath-nd4j/src/commonMain/kotlin/kscience/kmath/structures/NDStructure.kt) : Rings over Nd4jArrayStructure of Int and Long
|
||||
> - [nd4jarrayfields](kmath-nd4j/src/commonMain/kotlin/kscience/kmath/structures/Buffers.kt) : Fields over Nd4jArrayStructure of Float and Double
|
||||
|
||||
@ -211,20 +225,12 @@ Release artifacts are accessible from bintray with following configuration (see
|
||||
|
||||
```kotlin
|
||||
repositories {
|
||||
jcenter()
|
||||
maven("https://clojars.org/repo")
|
||||
maven("https://dl.bintray.com/egor-bogomolov/astminer/")
|
||||
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/kscience")
|
||||
maven("https://jitpack.io")
|
||||
mavenCentral()
|
||||
}
|
||||
|
||||
dependencies {
|
||||
api("kscience.kmath:kmath-core:0.2.0-dev-3")
|
||||
// api("kscience.kmath:kmath-core-jvm:0.2.0-dev-3") for jvm-specific version
|
||||
api("kscience.kmath:kmath-core:0.2.0-dev-4")
|
||||
// api("kscience.kmath:kmath-core-jvm:0.2.0-dev-4") for jvm-specific version
|
||||
}
|
||||
```
|
||||
|
||||
@ -236,15 +242,7 @@ Development builds are uploaded to the separate repository:
|
||||
|
||||
```kotlin
|
||||
repositories {
|
||||
jcenter()
|
||||
maven("https://clojars.org/repo")
|
||||
maven("https://dl.bintray.com/egor-bogomolov/astminer/")
|
||||
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://jitpack.io")
|
||||
mavenCentral()
|
||||
}
|
||||
```
|
||||
|
||||
|
@ -35,6 +35,9 @@ dependencies {
|
||||
implementation(project(":kmath-dimensions"))
|
||||
implementation(project(":kmath-ejml"))
|
||||
implementation(project(":kmath-nd4j"))
|
||||
|
||||
implementation(project(":kmath-for-real"))
|
||||
|
||||
implementation("org.deeplearning4j:deeplearning4j-core:1.0.0-beta7")
|
||||
implementation("org.nd4j:nd4j-native:1.0.0-beta7")
|
||||
|
||||
@ -51,7 +54,11 @@ dependencies {
|
||||
implementation("org.jetbrains.kotlinx:kotlinx-io:0.2.0-npm-dev-11")
|
||||
implementation("org.jetbrains.kotlinx:kotlinx.benchmark.runtime:0.2.0-dev-20")
|
||||
implementation("org.slf4j:slf4j-simple:1.7.30")
|
||||
"benchmarksImplementation"("org.jetbrains.kotlinx:kotlinx.benchmark.runtime-jvm:0.2.0-dev-8")
|
||||
|
||||
// plotting
|
||||
implementation("kscience.plotlykt:plotlykt-server:0.3.1-dev")
|
||||
|
||||
"benchmarksImplementation"("org.jetbrains.kotlinx:kotlinx.benchmark.runtime-jvm:0.2.0-dev-20")
|
||||
"benchmarksImplementation"(sourceSets.main.get().output + sourceSets.main.get().runtimeClasspath)
|
||||
}
|
||||
|
||||
|
@ -0,0 +1,101 @@
|
||||
package kscience.kmath.commons.fit
|
||||
|
||||
import kotlinx.html.br
|
||||
import kotlinx.html.h3
|
||||
import kscience.kmath.commons.optimization.chiSquared
|
||||
import kscience.kmath.commons.optimization.minimize
|
||||
import kscience.kmath.expressions.symbol
|
||||
import kscience.kmath.real.RealVector
|
||||
import kscience.kmath.real.map
|
||||
import kscience.kmath.real.step
|
||||
import kscience.kmath.stat.*
|
||||
import kscience.kmath.structures.asIterable
|
||||
import kscience.kmath.structures.toList
|
||||
import kscience.plotly.*
|
||||
import kscience.plotly.models.ScatterMode
|
||||
import kscience.plotly.models.TraceValues
|
||||
import kotlin.math.pow
|
||||
import kotlin.math.sqrt
|
||||
|
||||
//Forward declaration of symbols that will be used in expressions.
|
||||
// This declaration is required for
|
||||
private val a by symbol
|
||||
private val b by symbol
|
||||
private val c by symbol
|
||||
|
||||
/**
|
||||
* Shortcut to use buffers in plotly
|
||||
*/
|
||||
operator fun TraceValues.invoke(vector: RealVector) {
|
||||
numbers = vector.asIterable()
|
||||
}
|
||||
|
||||
/**
|
||||
* Least squares fie with auto-differentiation. Uses `kmath-commons` and `kmath-for-real` modules.
|
||||
*/
|
||||
fun main() {
|
||||
|
||||
//A generator for a normally distributed values
|
||||
val generator = Distribution.normal()
|
||||
|
||||
//A chain/flow of random values with the given seed
|
||||
val chain = generator.sample(RandomGenerator.default(112667))
|
||||
|
||||
|
||||
//Create a uniformly distributed x values like numpy.arrange
|
||||
val x = 1.0..100.0 step 1.0
|
||||
|
||||
|
||||
//Perform an operation on each x value (much more effective, than numpy)
|
||||
val y = x.map {
|
||||
val value = it.pow(2) + it + 1
|
||||
value + chain.nextDouble() * sqrt(value)
|
||||
}
|
||||
// this will also work, but less effective:
|
||||
// val y = x.pow(2)+ x + 1 + chain.nextDouble()
|
||||
|
||||
// create same errors for all xs
|
||||
val yErr = y.map { sqrt(it) }//RealVector.same(x.size, sigma)
|
||||
|
||||
// compute differentiable chi^2 sum for given model ax^2 + bx + c
|
||||
val chi2 = Fitting.chiSquared(x, y, yErr) { x1 ->
|
||||
//bind variables to autodiff context
|
||||
val a = bind(a)
|
||||
val b = bind(b)
|
||||
//Include default value for c if it is not provided as a parameter
|
||||
val c = bindOrNull(c) ?: one
|
||||
a * x1.pow(2) + b * x1 + c
|
||||
}
|
||||
|
||||
//minimize the chi^2 in given starting point. Derivatives are not required, they are already included.
|
||||
val result: OptimizationResult<Double> = chi2.minimize(a to 1.5, b to 0.9, c to 1.0)
|
||||
|
||||
val page = Plotly.page {
|
||||
plot {
|
||||
scatter {
|
||||
mode = ScatterMode.markers
|
||||
x(x)
|
||||
y(y)
|
||||
error_y {
|
||||
array = yErr.toList()
|
||||
}
|
||||
name = "data"
|
||||
}
|
||||
scatter {
|
||||
mode = ScatterMode.lines
|
||||
x(x)
|
||||
y(x.map { result.point[a]!! * it.pow(2) + result.point[b]!! * it + 1 })
|
||||
name = "fit"
|
||||
}
|
||||
}
|
||||
br()
|
||||
h3{
|
||||
+"Fit result: $result"
|
||||
}
|
||||
h3{
|
||||
+"Chi2/dof = ${result.value / (x.size - 3)}"
|
||||
}
|
||||
}
|
||||
|
||||
page.makeFile()
|
||||
}
|
@ -1,14 +1,17 @@
|
||||
package kscience.kmath.commons.prob
|
||||
package kscience.kmath.stat
|
||||
|
||||
import kotlinx.coroutines.runBlocking
|
||||
import kscience.kmath.chains.Chain
|
||||
import kscience.kmath.chains.collectWithState
|
||||
import kscience.kmath.stat.Distribution
|
||||
import kscience.kmath.stat.RandomGenerator
|
||||
import kscience.kmath.stat.normal
|
||||
|
||||
/**
|
||||
* The state of distribution averager
|
||||
*/
|
||||
private data class AveragingChainState(var num: Int = 0, var value: Double = 0.0)
|
||||
|
||||
/**
|
||||
* Averaging
|
||||
*/
|
||||
private fun Chain<Double>.mean(): Chain<Double> = collectWithState(AveragingChainState(), { it.copy() }) { chain ->
|
||||
val next = chain.next()
|
||||
num++
|
@ -12,7 +12,7 @@ The core features of KMath:
|
||||
|
||||
> #### Artifact:
|
||||
>
|
||||
> This module artifact: `kscience.kmath:kmath-core:0.2.0-dev-3`.
|
||||
> This module artifact: `kscience.kmath:kmath-core:0.2.0-dev-4`.
|
||||
>
|
||||
> 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)
|
||||
>
|
||||
@ -30,7 +30,7 @@ The core features of KMath:
|
||||
> }
|
||||
>
|
||||
> dependencies {
|
||||
> implementation 'kscience.kmath:kmath-core:0.2.0-dev-3'
|
||||
> implementation 'kscience.kmath:kmath-core:0.2.0-dev-4'
|
||||
> }
|
||||
> ```
|
||||
> **Gradle Kotlin DSL:**
|
||||
@ -44,6 +44,6 @@ The core features of KMath:
|
||||
> }
|
||||
>
|
||||
> dependencies {
|
||||
> implementation("kscience.kmath:kmath-core:0.2.0-dev-3")
|
||||
> implementation("kscience.kmath:kmath-core:0.2.0-dev-4")
|
||||
> }
|
||||
> ```
|
||||
|
@ -15,7 +15,7 @@ public interface VectorSpace<T : Any, S : Space<T>> : Space<Point<T>> {
|
||||
public val space: S
|
||||
override val zero: Point<T> get() = produce { space.zero }
|
||||
|
||||
public fun produce(initializer: (Int) -> T): Point<T>
|
||||
public fun produce(initializer: S.(Int) -> T): Point<T>
|
||||
|
||||
/**
|
||||
* Produce a space-element of this vector space for expressions
|
||||
@ -48,7 +48,7 @@ public interface VectorSpace<T : Any, S : Space<T>> : Space<Point<T>> {
|
||||
public fun <T : Any, S : Space<T>> buffered(
|
||||
size: Int,
|
||||
space: S,
|
||||
bufferFactory: BufferFactory<T> = Buffer.Companion::boxing
|
||||
bufferFactory: BufferFactory<T> = Buffer.Companion::boxing,
|
||||
): BufferVectorSpace<T, S> = BufferVectorSpace(size, space, bufferFactory)
|
||||
|
||||
/**
|
||||
@ -63,8 +63,8 @@ public interface VectorSpace<T : Any, S : Space<T>> : Space<Point<T>> {
|
||||
public class BufferVectorSpace<T : Any, S : Space<T>>(
|
||||
override val size: Int,
|
||||
override val space: S,
|
||||
public val bufferFactory: BufferFactory<T>
|
||||
public val bufferFactory: BufferFactory<T>,
|
||||
) : VectorSpace<T, S> {
|
||||
override fun produce(initializer: (Int) -> T): Buffer<T> = bufferFactory(size, initializer)
|
||||
override fun produce(initializer: S.(Int) -> T): Buffer<T> = bufferFactory(size) { space.initializer(it) }
|
||||
//override fun produceElement(initializer: (Int) -> T): Vector<T, S> = BufferVector(this, produce(initializer))
|
||||
}
|
||||
|
@ -0,0 +1,4 @@
|
||||
package kscience.kmath.misc
|
||||
|
||||
@RequiresOptIn("This API is unstable and could change in future", RequiresOptIn.Level.WARNING)
|
||||
public annotation class UnstableKMathAPI
|
@ -102,6 +102,11 @@ public fun <T> Buffer<T>.asSequence(): Sequence<T> = Sequence(::iterator)
|
||||
*/
|
||||
public fun <T> Buffer<T>.asIterable(): Iterable<T> = Iterable(::iterator)
|
||||
|
||||
/**
|
||||
* Converts this [Buffer] to a new [List]
|
||||
*/
|
||||
public fun <T> Buffer<T>.toList(): List<T> = asSequence().toList()
|
||||
|
||||
/**
|
||||
* Returns an [IntRange] of the valid indices for this [Buffer].
|
||||
*/
|
||||
|
@ -47,7 +47,7 @@ public fun <T> Iterator<T>.asChain(): Chain<T> = SimpleChain { next() }
|
||||
public fun <T> Sequence<T>.asChain(): Chain<T> = iterator().asChain()
|
||||
|
||||
/**
|
||||
* A simple chain of independent tokens
|
||||
* A simple chain of independent tokens. [fork] returns the same chain.
|
||||
*/
|
||||
public class SimpleChain<out R>(private val gen: suspend () -> R) : Chain<R> {
|
||||
public override suspend fun next(): R = gen()
|
||||
|
44
kmath-for-real/README.md
Normal file
44
kmath-for-real/README.md
Normal file
@ -0,0 +1,44 @@
|
||||
# Real number specialization module (`kmath-for-real`)
|
||||
|
||||
- [RealVector](src/commonMain/kotlin/kscience/kmath/real/RealVector.kt) : Numpy-like operations for Buffers/Points
|
||||
- [RealMatrix](src/commonMain/kotlin/kscience/kmath/real/RealMatrix.kt) : Numpy-like operations for 2d real structures
|
||||
- [grids](src/commonMain/kotlin/kscience/kmath/structures/grids.kt) : Uniform grid generators
|
||||
|
||||
|
||||
> #### Artifact:
|
||||
>
|
||||
> This module artifact: `kscience.kmath:kmath-for-real:0.2.0-dev-4`.
|
||||
>
|
||||
> 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)
|
||||
>
|
||||
> 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)
|
||||
>
|
||||
> **Gradle:**
|
||||
>
|
||||
> ```gradle
|
||||
> repositories {
|
||||
> maven { url "https://dl.bintray.com/kotlin/kotlin-eap" }
|
||||
> maven { url 'https://dl.bintray.com/mipt-npm/kscience' }
|
||||
> maven { url 'https://dl.bintray.com/mipt-npm/dev' }
|
||||
> maven { url 'https://dl.bintray.com/hotkeytlt/maven' }
|
||||
|
||||
> }
|
||||
>
|
||||
> dependencies {
|
||||
> implementation 'kscience.kmath:kmath-for-real:0.2.0-dev-4'
|
||||
> }
|
||||
> ```
|
||||
> **Gradle Kotlin DSL:**
|
||||
>
|
||||
> ```kotlin
|
||||
> repositories {
|
||||
> maven("https://dl.bintray.com/kotlin/kotlin-eap")
|
||||
> maven("https://dl.bintray.com/mipt-npm/kscience")
|
||||
> maven("https://dl.bintray.com/mipt-npm/dev")
|
||||
> maven("https://dl.bintray.com/hotkeytlt/maven")
|
||||
> }
|
||||
>
|
||||
> dependencies {
|
||||
> implementation("kscience.kmath:kmath-for-real:0.2.0-dev-4")
|
||||
> }
|
||||
> ```
|
@ -7,3 +7,31 @@ kotlin.sourceSets.commonMain {
|
||||
api(project(":kmath-core"))
|
||||
}
|
||||
}
|
||||
|
||||
readme {
|
||||
description = """
|
||||
Extension module that should be used to achieve numpy-like behavior.
|
||||
All operations are specialized to work with `Double` numbers without declaring algebraic contexts.
|
||||
One can still use generic algebras though.
|
||||
""".trimIndent()
|
||||
maturity = ru.mipt.npm.gradle.Maturity.EXPERIMENTAL
|
||||
propertyByTemplate("artifact", rootProject.file("docs/templates/ARTIFACT-TEMPLATE.md"))
|
||||
|
||||
feature(
|
||||
id = "RealVector",
|
||||
description = "Numpy-like operations for Buffers/Points",
|
||||
ref = "src/commonMain/kotlin/kscience/kmath/real/RealVector.kt"
|
||||
)
|
||||
|
||||
feature(
|
||||
id = "RealMatrix",
|
||||
description = "Numpy-like operations for 2d real structures",
|
||||
ref = "src/commonMain/kotlin/kscience/kmath/real/RealMatrix.kt"
|
||||
)
|
||||
|
||||
feature(
|
||||
id = "grids",
|
||||
description = "Uniform grid generators",
|
||||
ref = "src/commonMain/kotlin/kscience/kmath/structures/grids.kt"
|
||||
)
|
||||
}
|
||||
|
5
kmath-for-real/docs/README-TEMPLATE.md
Normal file
5
kmath-for-real/docs/README-TEMPLATE.md
Normal file
@ -0,0 +1,5 @@
|
||||
# Real number specialization module (`kmath-for-real`)
|
||||
|
||||
${features}
|
||||
|
||||
${artifact}
|
@ -3,6 +3,7 @@ package kscience.kmath.real
|
||||
import kscience.kmath.linear.MatrixContext
|
||||
import kscience.kmath.linear.RealMatrixContext.elementContext
|
||||
import kscience.kmath.linear.VirtualMatrix
|
||||
import kscience.kmath.misc.UnstableKMathAPI
|
||||
import kscience.kmath.operations.invoke
|
||||
import kscience.kmath.operations.sum
|
||||
import kscience.kmath.structures.Buffer
|
||||
@ -36,7 +37,7 @@ public fun Sequence<DoubleArray>.toMatrix(): RealMatrix = toList().let {
|
||||
MatrixContext.real.produce(it.size, it[0].size) { row, col -> it[row][col] }
|
||||
}
|
||||
|
||||
public fun Matrix<Double>.repeatStackVertical(n: Int): RealMatrix =
|
||||
public fun RealMatrix.repeatStackVertical(n: Int): RealMatrix =
|
||||
VirtualMatrix(rowNum * n, colNum) { row, col ->
|
||||
get(if (row == 0) 0 else row % rowNum, col)
|
||||
}
|
||||
@ -45,43 +46,43 @@ public fun Matrix<Double>.repeatStackVertical(n: Int): RealMatrix =
|
||||
* Operations for matrix and real number
|
||||
*/
|
||||
|
||||
public operator fun Matrix<Double>.times(double: Double): RealMatrix =
|
||||
public operator fun RealMatrix.times(double: Double): RealMatrix =
|
||||
MatrixContext.real.produce(rowNum, colNum) { row, col ->
|
||||
this[row, col] * double
|
||||
}
|
||||
|
||||
public operator fun Matrix<Double>.plus(double: Double): RealMatrix =
|
||||
public operator fun RealMatrix.plus(double: Double): RealMatrix =
|
||||
MatrixContext.real.produce(rowNum, colNum) { row, col ->
|
||||
this[row, col] + double
|
||||
}
|
||||
|
||||
public operator fun Matrix<Double>.minus(double: Double): RealMatrix =
|
||||
public operator fun RealMatrix.minus(double: Double): RealMatrix =
|
||||
MatrixContext.real.produce(rowNum, colNum) { row, col ->
|
||||
this[row, col] - double
|
||||
}
|
||||
|
||||
public operator fun Matrix<Double>.div(double: Double): RealMatrix =
|
||||
public operator fun RealMatrix.div(double: Double): RealMatrix =
|
||||
MatrixContext.real.produce(rowNum, colNum) { row, col ->
|
||||
this[row, col] / double
|
||||
}
|
||||
|
||||
public operator fun Double.times(matrix: Matrix<Double>): RealMatrix =
|
||||
public operator fun Double.times(matrix: RealMatrix): RealMatrix =
|
||||
MatrixContext.real.produce(matrix.rowNum, matrix.colNum) { row, col ->
|
||||
this * matrix[row, col]
|
||||
}
|
||||
|
||||
public operator fun Double.plus(matrix: Matrix<Double>): RealMatrix =
|
||||
public operator fun Double.plus(matrix: RealMatrix): RealMatrix =
|
||||
MatrixContext.real.produce(matrix.rowNum, matrix.colNum) { row, col ->
|
||||
this + matrix[row, col]
|
||||
}
|
||||
|
||||
public operator fun Double.minus(matrix: Matrix<Double>): RealMatrix =
|
||||
public operator fun Double.minus(matrix: RealMatrix): RealMatrix =
|
||||
MatrixContext.real.produce(matrix.rowNum, matrix.colNum) { row, col ->
|
||||
this - matrix[row, col]
|
||||
}
|
||||
|
||||
// TODO: does this operation make sense? Should it be 'this/matrix[row, col]'?
|
||||
//operator fun Double.div(matrix: Matrix<Double>) = MatrixContext.real.produce(matrix.rowNum, matrix.colNum) {
|
||||
//operator fun Double.div(matrix: RealMatrix) = MatrixContext.real.produce(matrix.rowNum, matrix.colNum) {
|
||||
// row, col -> matrix[row, col] / this
|
||||
//}
|
||||
|
||||
@ -89,11 +90,11 @@ public operator fun Double.minus(matrix: Matrix<Double>): RealMatrix =
|
||||
* Per-element (!) square and power operations
|
||||
*/
|
||||
|
||||
public fun Matrix<Double>.square(): RealMatrix = MatrixContext.real.produce(rowNum, colNum) { row, col ->
|
||||
public fun RealMatrix.square(): RealMatrix = MatrixContext.real.produce(rowNum, colNum) { row, col ->
|
||||
this[row, col].pow(2)
|
||||
}
|
||||
|
||||
public fun Matrix<Double>.pow(n: Int): RealMatrix = MatrixContext.real.produce(rowNum, colNum) { i, j ->
|
||||
public fun RealMatrix.pow(n: Int): RealMatrix = MatrixContext.real.produce(rowNum, colNum) { i, j ->
|
||||
this[i, j].pow(n)
|
||||
}
|
||||
|
||||
@ -101,20 +102,21 @@ public fun Matrix<Double>.pow(n: Int): RealMatrix = MatrixContext.real.produce(r
|
||||
* Operations on two matrices (per-element!)
|
||||
*/
|
||||
|
||||
public operator fun Matrix<Double>.times(other: Matrix<Double>): RealMatrix =
|
||||
@UnstableKMathAPI
|
||||
public operator fun RealMatrix.times(other: RealMatrix): RealMatrix =
|
||||
MatrixContext.real.produce(rowNum, colNum) { row, col -> this[row, col] * other[row, col] }
|
||||
|
||||
public operator fun Matrix<Double>.plus(other: Matrix<Double>): RealMatrix =
|
||||
public operator fun RealMatrix.plus(other: RealMatrix): RealMatrix =
|
||||
MatrixContext.real.add(this, other)
|
||||
|
||||
public operator fun Matrix<Double>.minus(other: Matrix<Double>): RealMatrix =
|
||||
public operator fun RealMatrix.minus(other: RealMatrix): RealMatrix =
|
||||
MatrixContext.real.produce(rowNum, colNum) { row, col -> this[row, col] - other[row, col] }
|
||||
|
||||
/*
|
||||
* Operations on columns
|
||||
*/
|
||||
|
||||
public inline fun Matrix<Double>.appendColumn(crossinline mapper: (Buffer<Double>) -> Double): Matrix<Double> =
|
||||
public inline fun RealMatrix.appendColumn(crossinline mapper: (Buffer<Double>) -> Double): RealMatrix =
|
||||
MatrixContext.real.produce(rowNum, colNum + 1) { row, col ->
|
||||
if (col < colNum)
|
||||
this[row, col]
|
||||
@ -122,28 +124,28 @@ public inline fun Matrix<Double>.appendColumn(crossinline mapper: (Buffer<Double
|
||||
mapper(rows[row])
|
||||
}
|
||||
|
||||
public fun Matrix<Double>.extractColumns(columnRange: IntRange): RealMatrix =
|
||||
public fun RealMatrix.extractColumns(columnRange: IntRange): RealMatrix =
|
||||
MatrixContext.real.produce(rowNum, columnRange.count()) { row, col ->
|
||||
this[row, columnRange.first + col]
|
||||
}
|
||||
|
||||
public fun Matrix<Double>.extractColumn(columnIndex: Int): RealMatrix =
|
||||
public fun RealMatrix.extractColumn(columnIndex: Int): RealMatrix =
|
||||
extractColumns(columnIndex..columnIndex)
|
||||
|
||||
public fun Matrix<Double>.sumByColumn(): RealBuffer = RealBuffer(colNum) { j ->
|
||||
public fun RealMatrix.sumByColumn(): RealBuffer = RealBuffer(colNum) { j ->
|
||||
val column = columns[j]
|
||||
elementContext { sum(column.asIterable()) }
|
||||
}
|
||||
|
||||
public fun Matrix<Double>.minByColumn(): RealBuffer = RealBuffer(colNum) { j ->
|
||||
public fun RealMatrix.minByColumn(): RealBuffer = RealBuffer(colNum) { j ->
|
||||
columns[j].asIterable().minOrNull() ?: error("Cannot produce min on empty column")
|
||||
}
|
||||
|
||||
public fun Matrix<Double>.maxByColumn(): RealBuffer = RealBuffer(colNum) { j ->
|
||||
public fun RealMatrix.maxByColumn(): RealBuffer = RealBuffer(colNum) { j ->
|
||||
columns[j].asIterable().maxOrNull() ?: error("Cannot produce min on empty column")
|
||||
}
|
||||
|
||||
public fun Matrix<Double>.averageByColumn(): RealBuffer = RealBuffer(colNum) { j ->
|
||||
public fun RealMatrix.averageByColumn(): RealBuffer = RealBuffer(colNum) { j ->
|
||||
columns[j].asIterable().average()
|
||||
}
|
||||
|
||||
@ -151,7 +153,7 @@ public fun Matrix<Double>.averageByColumn(): RealBuffer = RealBuffer(colNum) { j
|
||||
* Operations processing all elements
|
||||
*/
|
||||
|
||||
public fun Matrix<Double>.sum(): Double = elements().map { (_, value) -> value }.sum()
|
||||
public fun Matrix<Double>.min(): Double? = elements().map { (_, value) -> value }.minOrNull()
|
||||
public fun Matrix<Double>.max(): Double? = elements().map { (_, value) -> value }.maxOrNull()
|
||||
public fun Matrix<Double>.average(): Double = elements().map { (_, value) -> value }.average()
|
||||
public fun RealMatrix.sum(): Double = elements().map { (_, value) -> value }.sum()
|
||||
public fun RealMatrix.min(): Double? = elements().map { (_, value) -> value }.minOrNull()
|
||||
public fun RealMatrix.max(): Double? = elements().map { (_, value) -> value }.maxOrNull()
|
||||
public fun RealMatrix.average(): Double = elements().map { (_, value) -> value }.average()
|
||||
|
@ -1,47 +1,63 @@
|
||||
package kscience.kmath.real
|
||||
|
||||
import kscience.kmath.linear.BufferVectorSpace
|
||||
import kscience.kmath.linear.Point
|
||||
import kscience.kmath.linear.VectorSpace
|
||||
import kscience.kmath.operations.Norm
|
||||
import kscience.kmath.operations.RealField
|
||||
import kscience.kmath.operations.SpaceElement
|
||||
import kscience.kmath.structures.Buffer
|
||||
import kscience.kmath.structures.RealBuffer
|
||||
import kscience.kmath.structures.asBuffer
|
||||
import kscience.kmath.structures.asIterable
|
||||
import kotlin.math.pow
|
||||
import kotlin.math.sqrt
|
||||
|
||||
public typealias RealPoint = Point<Double>
|
||||
|
||||
public fun RealPoint.asVector(): RealVector = RealVector(this)
|
||||
public fun DoubleArray.asVector(): RealVector = asBuffer().asVector()
|
||||
public fun List<Double>.asVector(): RealVector = asBuffer().asVector()
|
||||
public typealias RealVector = Point<Double>
|
||||
|
||||
public object VectorL2Norm : Norm<Point<out Number>, Double> {
|
||||
override fun norm(arg: Point<out Number>): Double = sqrt(arg.asIterable().sumByDouble(Number::toDouble))
|
||||
}
|
||||
|
||||
public inline class RealVector(private val point: Point<Double>) :
|
||||
SpaceElement<RealPoint, RealVector, VectorSpace<Double, RealField>>, RealPoint {
|
||||
public override val size: Int get() = point.size
|
||||
public override val context: VectorSpace<Double, RealField> get() = space(point.size)
|
||||
/**
|
||||
* Fill the vector of given [size] with given [value]
|
||||
*/
|
||||
public fun Buffer.Companion.same(size: Int, value: Number): RealVector = real(size) { value.toDouble() }
|
||||
|
||||
public override fun unwrap(): RealPoint = point
|
||||
public override fun RealPoint.wrap(): RealVector = RealVector(this)
|
||||
public override operator fun get(index: Int): Double = point[index]
|
||||
public override operator fun iterator(): Iterator<Double> = point.iterator()
|
||||
// Transformation methods
|
||||
|
||||
public companion object {
|
||||
private val spaceCache: MutableMap<Int, BufferVectorSpace<Double, RealField>> = hashMapOf()
|
||||
public inline fun RealVector.map(transform: (Double) -> Double): RealVector =
|
||||
Buffer.real(size) { transform(get(it)) }
|
||||
|
||||
public inline operator fun invoke(dim: Int, initializer: (Int) -> Double): RealVector =
|
||||
RealVector(RealBuffer(dim, initializer))
|
||||
public inline fun RealVector.mapIndexed(transform: (index: Int, value: Double) -> Double): RealVector =
|
||||
Buffer.real(size) { transform(it, get(it)) }
|
||||
|
||||
public operator fun invoke(vararg values: Double): RealVector = values.asVector()
|
||||
public fun RealVector.pow(p: Double): RealVector = map { it.pow(p) }
|
||||
|
||||
public fun space(dim: Int): BufferVectorSpace<Double, RealField> = spaceCache.getOrPut(dim) {
|
||||
BufferVectorSpace(dim, RealField) { size, init -> Buffer.real(size, init) }
|
||||
}
|
||||
}
|
||||
}
|
||||
public fun RealVector.pow(p: Int): RealVector = map { it.pow(p) }
|
||||
|
||||
public fun exp(vector: RealVector): RealVector = vector.map { kotlin.math.exp(it) }
|
||||
|
||||
public operator fun RealVector.plus(other: RealVector): RealVector =
|
||||
mapIndexed { index, value -> value + other[index] }
|
||||
|
||||
public operator fun RealVector.plus(number: Number): RealVector = map { it + number.toDouble() }
|
||||
|
||||
public operator fun Number.plus(vector: RealVector): RealVector = vector + this
|
||||
|
||||
public operator fun RealVector.unaryMinus(): Buffer<Double> = map { -it }
|
||||
|
||||
public operator fun RealVector.minus(other: RealVector): RealVector =
|
||||
mapIndexed { index, value -> value - other[index] }
|
||||
|
||||
public operator fun RealVector.minus(number: Number): RealVector = map { it - number.toDouble() }
|
||||
|
||||
public operator fun Number.minus(vector: RealVector): RealVector = vector.map { toDouble() - it }
|
||||
|
||||
public operator fun RealVector.times(other: RealVector): RealVector =
|
||||
mapIndexed { index, value -> value * other[index] }
|
||||
|
||||
public operator fun RealVector.times(number: Number): RealVector = map { it * number.toDouble() }
|
||||
|
||||
public operator fun Number.times(vector: RealVector): RealVector = vector * this
|
||||
|
||||
public operator fun RealVector.div(other: RealVector): RealVector =
|
||||
mapIndexed { index, value -> value / other[index] }
|
||||
|
||||
public operator fun RealVector.div(number: Number): RealVector = map { it / number.toDouble() }
|
||||
|
||||
public operator fun Number.div(vector: RealVector): RealVector = vector.map { toDouble() / it }
|
||||
|
@ -1,6 +1,5 @@
|
||||
package kscience.kmath.real
|
||||
|
||||
import kscience.kmath.linear.Point
|
||||
import kscience.kmath.structures.asBuffer
|
||||
import kotlin.math.abs
|
||||
|
||||
@ -34,7 +33,7 @@ public fun ClosedFloatingPointRange<Double>.toSequenceWithStep(step: Double): Se
|
||||
}
|
||||
}
|
||||
|
||||
public infix fun ClosedFloatingPointRange<Double>.step(step: Double): Point<Double> =
|
||||
public infix fun ClosedFloatingPointRange<Double>.step(step: Double): RealVector =
|
||||
toSequenceWithStep(step).toList().asBuffer()
|
||||
|
||||
/**
|
||||
|
@ -2,14 +2,14 @@
|
||||
|
||||
This subproject implements the following features:
|
||||
|
||||
- [nd4jarraystrucure](src/commonMain/kotlin/kscience/kmath/operations/Algebra.kt) : NDStructure wrapper for INDArray
|
||||
- [nd4jarraystructure](src/commonMain/kotlin/kscience/kmath/operations/Algebra.kt) : NDStructure wrapper for INDArray
|
||||
- [nd4jarrayrings](src/commonMain/kotlin/kscience/kmath/structures/NDStructure.kt) : Rings over Nd4jArrayStructure of Int and Long
|
||||
- [nd4jarrayfields](src/commonMain/kotlin/kscience/kmath/structures/Buffers.kt) : Fields over Nd4jArrayStructure of Float and Double
|
||||
|
||||
|
||||
> #### Artifact:
|
||||
>
|
||||
> This module artifact: `kscience.kmath:kmath-nd4j:0.2.0-dev-3`.
|
||||
> This module artifact: `kscience.kmath:kmath-nd4j:0.2.0-dev-4`.
|
||||
>
|
||||
> 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)
|
||||
>
|
||||
@ -27,7 +27,7 @@ This subproject implements the following features:
|
||||
> }
|
||||
>
|
||||
> dependencies {
|
||||
> implementation 'kscience.kmath:kmath-nd4j:0.2.0-dev-3'
|
||||
> implementation 'kscience.kmath:kmath-nd4j:0.2.0-dev-4'
|
||||
> }
|
||||
> ```
|
||||
> **Gradle Kotlin DSL:**
|
||||
@ -41,7 +41,7 @@ This subproject implements the following features:
|
||||
> }
|
||||
>
|
||||
> dependencies {
|
||||
> implementation("kscience.kmath:kmath-nd4j:0.2.0-dev-3")
|
||||
> implementation("kscience.kmath:kmath-nd4j:0.2.0-dev-4")
|
||||
> }
|
||||
> ```
|
||||
|
||||
|
@ -51,7 +51,7 @@ private fun normalSampler(method: NormalSamplerMethod, provider: UniformRandomPr
|
||||
|
||||
public fun Distribution.Companion.normal(
|
||||
method: NormalSamplerMethod = NormalSamplerMethod.Ziggurat
|
||||
): Distribution<Double> = object : ContinuousSamplerDistribution() {
|
||||
): ContinuousSamplerDistribution = object : ContinuousSamplerDistribution() {
|
||||
override fun buildCMSampler(generator: RandomGenerator): ContinuousSampler {
|
||||
val provider = generator.asUniformRandomProvider()
|
||||
return normalSampler(method, provider)
|
||||
@ -60,6 +60,9 @@ public fun Distribution.Companion.normal(
|
||||
override fun probability(arg: Double): Double = exp(-arg.pow(2) / 2) / sqrt(PI * 2)
|
||||
}
|
||||
|
||||
/**
|
||||
* A univariate normal distribution with given [mean] and [sigma]. [method] defines commons-rng generation method
|
||||
*/
|
||||
public fun Distribution.Companion.normal(
|
||||
mean: Double,
|
||||
sigma: Double,
|
||||
|
Loading…
Reference in New Issue
Block a user