kmath-for-real refactoring

This commit is contained in:
Alexander Nozik 2020-11-29 13:32:20 +03:00
parent c21e761a76
commit 5b653f10d7
19 changed files with 310 additions and 94 deletions

View File

@ -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

View File

@ -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()
}
```

View File

@ -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)
}

View File

@ -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()
}

View File

@ -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++

View File

@ -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")
> }
> ```

View File

@ -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))
}

View File

@ -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

View File

@ -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].
*/

View File

@ -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
View 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")
> }
> ```

View File

@ -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"
)
}

View File

@ -0,0 +1,5 @@
# Real number specialization module (`kmath-for-real`)
${features}
${artifact}

View File

@ -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()

View File

@ -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 }

View File

@ -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()
/**

View File

@ -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")
> }
> ```

View File

@ -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,