latest dev

This commit is contained in:
Roland Grinis 2021-11-01 17:36:24 +00:00
commit 4216a43470
504 changed files with 19993 additions and 5242 deletions

View File

@ -2,8 +2,8 @@ name: Gradle build
on:
push:
branches: [ dev, master ]
pull_request:
types: [opened, edited]
jobs:
build:
@ -11,23 +11,22 @@ jobs:
matrix:
os: [ macOS-latest, windows-latest ]
runs-on: ${{matrix.os}}
timeout-minutes: 30
timeout-minutes: 40
steps:
- name: Checkout the repo
uses: actions/checkout@v2
- name: Set up JDK 11
uses: DeLaGuardo/setup-graalvm@4.0
with:
graalvm: 21.1.0
graalvm: 21.2.0
java: java11
arch: amd64
- name: Add msys to path
if: matrix.os == 'windows-latest'
run: SETX PATH "%PATH%;C:\msys64\mingw64\bin"
- name: Cache gradle
uses: actions/cache@v2
with:
path: ~/.gradle/caches
path: |
~/.gradle/caches
~/.gradle/wrapper
key: ${{ runner.os }}-gradle-${{ hashFiles('*.gradle.kts') }}
restore-keys: |
${{ runner.os }}-gradle-
@ -38,5 +37,7 @@ jobs:
key: ${{ runner.os }}-gradle-${{ hashFiles('*.gradle.kts') }}
restore-keys: |
${{ runner.os }}-gradle-
- name: Gradle Wrapper Validation
uses: gradle/wrapper-validation-action@v1.0.4
- name: Build
run: ./gradlew build --no-daemon --stacktrace
run: ./gradlew build --build-cache --no-daemon --stacktrace

View File

@ -2,23 +2,27 @@ name: Dokka publication
on:
push:
branches:
- master
branches: [ master ]
jobs:
build:
runs-on: ubuntu-20.04
timeout-minutes: 40
steps:
- name: Checkout the repo
uses: actions/checkout@v2
- name: Set up JDK 11
uses: actions/setup-java@v1
- uses: actions/checkout@v2
- uses: DeLaGuardo/setup-graalvm@4.0
with:
java-version: 11
- name: Build
run: ./gradlew dokkaHtmlMultiModule --no-daemon --no-parallel --stacktrace
- name: Deploy to GitHub Pages
uses: JamesIves/github-pages-deploy-action@4.1.0
graalvm: 21.2.0
java: java11
arch: amd64
- uses: actions/cache@v2
with:
path: ~/.gradle/caches
key: ${{ runner.os }}-gradle-${{ hashFiles('*.gradle.kts') }}
restore-keys: |
${{ runner.os }}-gradle-
- run: ./gradlew dokkaHtmlMultiModule --build-cache --no-daemon --no-parallel --stacktrace
- uses: JamesIves/github-pages-deploy-action@4.1.0
with:
branch: gh-pages
folder: build/dokka/htmlMultiModule

View File

@ -3,8 +3,7 @@ name: Gradle publish
on:
workflow_dispatch:
release:
types:
- created
types: [ created ]
jobs:
publish:
@ -20,16 +19,15 @@ jobs:
- name: Set up JDK 11
uses: DeLaGuardo/setup-graalvm@4.0
with:
graalvm: 21.1.0
graalvm: 21.2.0
java: java11
arch: amd64
- name: Add msys to path
if: matrix.os == 'windows-latest'
run: SETX PATH "%PATH%;C:\msys64\mingw64\bin"
- name: Cache gradle
uses: actions/cache@v2
with:
path: ~/.gradle/caches
path: |
~/.gradle/caches
~/.gradle/wrapper
key: ${{ runner.os }}-gradle-${{ hashFiles('*.gradle.kts') }}
restore-keys: |
${{ runner.os }}-gradle-
@ -40,22 +38,18 @@ jobs:
key: ${{ runner.os }}-gradle-${{ hashFiles('*.gradle.kts') }}
restore-keys: |
${{ runner.os }}-gradle-
- name: Gradle Wrapper Validation
uses: gradle/wrapper-validation-action@v1.0.4
- name: Publish Windows Artifacts
if: matrix.os == 'windows-latest'
shell: cmd
run: >
./gradlew release --no-daemon
-Ppublishing.enabled=true
-Ppublishing.github.user=${{ secrets.PUBLISHING_GITHUB_USER }}
-Ppublishing.github.token=${{ secrets.PUBLISHING_GITHUB_TOKEN }}
-Ppublishing.space.user=${{ secrets.PUBLISHING_SPACE_USER }}
-Ppublishing.space.token=${{ secrets.PUBLISHING_SPACE_TOKEN }}
./gradlew release --no-daemon --build-cache -Ppublishing.enabled=true
-Ppublishing.space.user=${{ secrets.SPACE_APP_ID }}
-Ppublishing.space.token=${{ secrets.SPACE_APP_SECRET }}
- name: Publish Mac Artifacts
if: matrix.os == 'macOS-latest'
run: >
./gradlew release --no-daemon
-Ppublishing.enabled=true
-Ppublishing.platform=macosX64
-Ppublishing.github.user=${{ secrets.PUBLISHING_GITHUB_USER }}
-Ppublishing.github.token=${{ secrets.PUBLISHING_GITHUB_TOKEN }}
-Ppublishing.space.user=${{ secrets.PUBLISHING_SPACE_USER }}
-Ppublishing.space.token=${{ secrets.PUBLISHING_SPACE_TOKEN }}
./gradlew release --no-daemon --build-cache -Ppublishing.enabled=true -Ppublishing.platform=macosX64
-Ppublishing.space.user=${{ secrets.SPACE_APP_ID }}
-Ppublishing.space.token=${{ secrets.SPACE_APP_SECRET }}

View File

@ -1,6 +0,0 @@
<component name="CopyrightManager">
<copyright>
<option name="notice" value="Copyright 2018-2021 KMath contributors.&#10;Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file." />
<option name="myName" value="kmath" />
</copyright>
</component>

View File

@ -1,21 +0,0 @@
<component name="CopyrightManager">
<settings default="kmath">
<module2copyright>
<element module="Apply copyright" copyright="kmath" />
</module2copyright>
<LanguageOptions name="Groovy">
<option name="fileTypeOverride" value="1" />
</LanguageOptions>
<LanguageOptions name="HTML">
<option name="fileTypeOverride" value="1" />
<option name="prefixLines" value="false" />
</LanguageOptions>
<LanguageOptions name="Properties">
<option name="fileTypeOverride" value="1" />
</LanguageOptions>
<LanguageOptions name="XML">
<option name="fileTypeOverride" value="1" />
<option name="prefixLines" value="false" />
</LanguageOptions>
</settings>
</component>

View File

@ -1,4 +0,0 @@
<component name="DependencyValidationManager">
<scope name="Apply copyright"
pattern="!file[*]:*//testData//*&amp;&amp;!file[*]:testData//*&amp;&amp;!file[*]:*.gradle.kts&amp;&amp;!file[*]:*.gradle&amp;&amp;!file[group:kotlin-ultimate]:*/&amp;&amp;!file[kotlin.libraries]:stdlib/api//*"/>
</component>

View File

@ -13,8 +13,10 @@
- Extended operations for ND4J fields
- Jupyter Notebook integration module (kmath-jupyter)
- `@PerformancePitfall` annotation to mark possibly slow API
- Unified architecture for Integration and Optimization using features.
- `BigInt` operation performance improvement and fixes by @zhelenskiy (#328)
- Integration between `MST` and Symja `IExpr`
- Complex power
### Changed
- Exponential operations merged with hyperbolic functions
@ -36,8 +38,17 @@
- Remove Any restriction on polynomials
- Add `out` variance to type parameters of `StructureND` and its implementations where possible
- Rename `DifferentiableMstExpression` to `KotlingradExpression`
- `FeatureSet` now accepts only `Feature`. It is possible to override keys and use interfaces.
- Use `Symbol` factory function instead of `StringSymbol`
- New discoverability pattern: `<Type>.algebra.<nd/etc>`
- Adjusted commons-math API for linear solvers to match conventions.
- Buffer algebra does not require size anymore
- Operations -> Ops
- Default Buffer and ND algebras are now Ops and lack neutral elements (0, 1) as well as algebra-level shapes.
- Tensor algebra takes read-only structures as input and inherits AlgebraND
### Deprecated
- Specialized `DoubleBufferAlgebra`
### Removed
- Nearest in Domain. To be implemented in geometry package.
@ -47,6 +58,7 @@
- Expression algebra builders
- Complex and Quaternion no longer are elements.
- Second generic from DifferentiableExpression
- Algebra elements are completely removed. Use algebra contexts instead.
### Fixed
- Ring inherits RingOperations, not GroupOperations

View File

@ -6,10 +6,10 @@
# KMath
Could be pronounced as `key-math`. The **K**otlin **Math**ematics library was initially intended as a Kotlin-based analog to
Python's NumPy library. Later we found that kotlin is much more flexible language and allows superior architecture
designs. In contrast to `numpy` and `scipy` it is modular and has a lightweight core. The `numpy`-like experience could
be achieved with [kmath-for-real](/kmath-for-real) extension module.
Could be pronounced as `key-math`. The **K**otlin **Math**ematics library was initially intended as a Kotlin-based
analog to Python's NumPy library. Later we found that kotlin is much more flexible language and allows superior
architecture designs. In contrast to `numpy` and `scipy` it is modular and has a lightweight core. The `numpy`-like
experience could be achieved with [kmath-for-real](/kmath-for-real) extension module.
[Documentation site (**WIP**)](https://mipt-npm.github.io/kmath/)
@ -21,26 +21,33 @@ be achieved with [kmath-for-real](/kmath-for-real) extension module.
# Goal
* Provide a flexible and powerful API to work with mathematics abstractions in Kotlin-multiplatform (JVM, JS and Native).
* Provide a flexible and powerful API to work with mathematics abstractions in Kotlin-multiplatform (JVM, JS and Native)
.
* Provide basic multiplatform implementations for those abstractions (without significant performance optimization).
* Provide bindings and wrappers with those abstractions for popular optimized platform libraries.
## Non-goals
* Be like NumPy. It was the idea at the beginning, but we decided that we can do better in terms of API.
* Be like NumPy. It was the idea at the beginning, but we decided that we can do better in API.
* Provide the best performance out of the box. We have specialized libraries for that. Need only API wrappers for them.
* Cover all cases as immediately and in one bundle. We will modularize everything and add new features gradually.
* Provide specialized behavior in the core. API is made generic on purpose, so one needs to specialize for types, like
for `Double` in the core. For that we will have specialization modules like `kmath-for-real`, which will give better
experience for those, who want to work with specific types.
* Provide specialized behavior in the core. API is made generic on purpose, so one needs to specialize for types, like
for `Double` in the core. For that we will have specialization modules like `kmath-for-real`, which will give better
experience for those, who want to work with specific types.
## Features and stability
KMath is a modular library. Different modules provide different features with different API stability guarantees. All core modules are released with the same version, but with different API change policy. The features are described in module definitions below. The module stability could have following levels:
KMath is a modular library. Different modules provide different features with different API stability guarantees. All
core modules are released with the same version, but with different API change policy. The features are described in
module definitions below. The module stability could have the following levels:
* **PROTOTYPE**. On this level there are no compatibility guarantees. All methods and classes form those modules could break any moment. You can still use it, but be sure to fix the specific version.
* **EXPERIMENTAL**. The general API is decided, but some changes could be made. Volatile API is marked with `@UnstableKmathAPI` or other stability warning annotations.
* **DEVELOPMENT**. API breaking generally follows semantic versioning ideology. There could be changes in minor versions, but not in patch versions. API is protected with [binary-compatibility-validator](https://github.com/Kotlin/binary-compatibility-validator) tool.
* **PROTOTYPE**. On this level there are no compatibility guarantees. All methods and classes form those modules could
break any moment. You can still use it, but be sure to fix the specific version.
* **EXPERIMENTAL**. The general API is decided, but some changes could be made. Volatile API is marked
with `@UnstableKmathAPI` or other stability warning annotations.
* **DEVELOPMENT**. API breaking generally follows semantic versioning ideology. There could be changes in minor
versions, but not in patch versions. API is protected
with [binary-compatibility-validator](https://github.com/Kotlin/binary-compatibility-validator) tool.
* **STABLE**. The API stabilized. Breaking changes are allowed only in major releases.
<!--Current feature list is [here](/docs/features.md)-->
@ -132,7 +139,7 @@ KMath is a modular library. Different modules provide different features with di
objects to the expression by providing a context. Expressions can be used for a wide variety of purposes from high
performance calculations to code generation.
> - [domains](kmath-core/src/commonMain/kotlin/space/kscience/kmath/domains) : Domains
> - [autodif](kmath-core/src/commonMain/kotlin/space/kscience/kmath/expressions/SimpleAutoDiff.kt) : Automatic differentiation
> - [autodiff](kmath-core/src/commonMain/kotlin/space/kscience/kmath/expressions/SimpleAutoDiff.kt) : Automatic differentiation
<hr/>
@ -161,7 +168,7 @@ performance calculations to code generation.
<hr/>
* ### [kmath-for-real](kmath-for-real)
> Extension module that should be used to achieve numpy-like behavior.
> 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.
>
@ -222,8 +229,8 @@ One can still use generic algebras though.
> **Maturity**: EXPERIMENTAL
>
> **Features:**
> - [differentiable-mst-expression](kmath-kotlingrad/src/main/kotlin/space/kscience/kmath/kotlingrad/DifferentiableMstExpression.kt) : MST based DifferentiableExpression.
> - [differentiable-mst-expression](kmath-kotlingrad/src/main/kotlin/space/kscience/kmath/kotlingrad/DifferentiableMstExpression.kt) : Conversions between Kotlin∇'s SFun and MST
> - [differentiable-mst-expression](kmath-kotlingrad/src/main/kotlin/space/kscience/kmath/kotlingrad/KotlingradExpression.kt) : MST based DifferentiableExpression.
> - [scalars-adapters](kmath-kotlingrad/src/main/kotlin/space/kscience/kmath/kotlingrad/scalarsAdapters.kt) : Conversions between Kotlin∇'s SFun and MST
<hr/>
@ -264,7 +271,7 @@ One can still use generic algebras though.
>
> **Features:**
> - [tensor algebra](kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/api/TensorAlgebra.kt) : Basic linear algebra operations on tensors (plus, dot, etc.)
> - [tensor algebra with broadcasting](kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/BroadcastDoubleTensorAlgebra.kt) : Basic linear algebra operations implemented with broadcasting.
> - [tensor algebra with broadcasting](kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/BroadcastDoubleTensorAlgebra.kt) : Basic linear algebra operations implemented with broadcasting.
> - [linear algebra operations](kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/api/LinearOpsTensorAlgebra.kt) : Advanced linear algebra operations like LU decomposition, SVD, etc.
<hr/>
@ -278,30 +285,33 @@ One can still use generic algebras though.
## Multi-platform support
KMath is developed as a multi-platform library, which means that most of the interfaces are declared in the
[common source sets](/kmath-core/src/commonMain) and implemented there wherever it is possible. In some cases, features
are delegated to platform-specific implementations even if they could be provided in the common module for performance
reasons. Currently, the Kotlin/JVM is the primary platform, however Kotlin/Native and Kotlin/JS contributions and
KMath is developed as a multi-platform library, which means that most of the interfaces are declared in the
[common source sets](/kmath-core/src/commonMain) and implemented there wherever it is possible. In some cases, features
are delegated to platform-specific implementations even if they could be provided in the common module for performance
reasons. Currently, the Kotlin/JVM is the primary platform, however Kotlin/Native and Kotlin/JS contributions and
feedback are also welcome.
## Performance
Calculation performance is one of major goals of KMath in the future, but in some cases it is impossible to achieve
both performance and flexibility.
Calculation performance is one of major goals of KMath in the future, but in some cases it is impossible to achieve both
performance and flexibility.
We expect to focus on creating convenient universal API first and then work on increasing performance for specific
cases. We expect the worst KMath benchmarks will perform better than native Python, but worse than optimized
native/SciPy (mostly due to boxing operations on primitive numbers). The best performance of optimized parts could be
We expect to focus on creating convenient universal API first and then work on increasing performance for specific
cases. We expect the worst KMath benchmarks will perform better than native Python, but worse than optimized
native/SciPy (mostly due to boxing operations on primitive numbers). The best performance of optimized parts could be
better than SciPy.
## Requirements
KMath currently relies on JDK 11 for compilation and execution of Kotlin-JVM part. We recommend to use GraalVM-CE 11 for execution in order to get better performance.
KMath currently relies on JDK 11 for compilation and execution of Kotlin-JVM part. We recommend to use GraalVM-CE 11 for
execution to get better performance.
### Repositories
Release and development artifacts are accessible from mipt-npm [Space](https://www.jetbrains.com/space/) repository `https://maven.pkg.jetbrains.space/mipt-npm/p/sci/maven` (see documentation of
[Kotlin Multiplatform](https://kotlinlang.org/docs/reference/multiplatform.html) for more details). The repository could be reached through [repo.kotlin.link](https://repo.kotlin.link) proxy:
Release and development artifacts are accessible from mipt-npm [Space](https://www.jetbrains.com/space/)
repository `https://maven.pkg.jetbrains.space/mipt-npm/p/sci/maven` (see documentation of
[Kotlin Multiplatform](https://kotlinlang.org/docs/reference/multiplatform.html) for more details). The repository could
be reached through [repo.kotlin.link](https://repo.kotlin.link) proxy:
```kotlin
repositories {
@ -309,8 +319,8 @@ repositories {
}
dependencies {
api("space.kscience:kmath-core:0.3.0-dev-13")
// api("space.kscience:kmath-core-jvm:0.3.0-dev-13") for jvm-specific version
api("space.kscience:kmath-core:0.3.0-dev-14")
// api("space.kscience:kmath-core-jvm:0.3.0-dev-14") for jvm-specific version
}
```
@ -318,7 +328,7 @@ Gradle `6.0+` is required for multiplatform artifacts.
## Contributing
The project requires a lot of additional work. The most important thing we need is a feedback about what features are
required the most. Feel free to create feature requests. We are also welcome to code contributions,
especially in issues marked with
The project requires a lot of additional work. The most important thing we need is a feedback about what features are
required the most. Feel free to create feature requests. We are also welcome to code contributions, especially in issues
marked with
[waiting for a hero](https://github.com/mipt-npm/kmath/labels/waiting%20for%20a%20hero) label.

View File

@ -36,6 +36,7 @@ kotlin {
implementation(project(":kmath-dimensions"))
implementation(project(":kmath-for-real"))
implementation(project(":kmath-jafama"))
implementation(project(":kmath-tensors"))
implementation("org.jetbrains.kotlinx:kotlinx-benchmark-runtime:0.3.1")
}
}
@ -47,7 +48,8 @@ kotlin {
implementation(project(":kmath-nd4j"))
implementation(project(":kmath-kotlingrad"))
implementation(project(":kmath-viktor"))
implementation("org.nd4j:nd4j-native:1.0.0-beta7")
implementation(projects.kmathMultik)
implementation("org.nd4j:nd4j-native:1.0.0-M1")
// uncomment if your system supports AVX2
// val os = System.getProperty("os.name")
//
@ -81,6 +83,11 @@ benchmark {
include("BufferBenchmark")
}
configurations.register("nd") {
commonConfiguration()
include("NDFieldBenchmark")
}
configurations.register("dot") {
commonConfiguration()
include("DotBenchmark")
@ -105,6 +112,16 @@ benchmark {
commonConfiguration()
include("JafamaBenchmark")
}
configurations.register("viktor") {
commonConfiguration()
include("ViktorBenchmark")
}
configurations.register("viktorLog") {
commonConfiguration()
include("ViktorLogBenchmark")
}
}
// Fix kotlinx-benchmarks bug

View File

@ -1,6 +1,6 @@
/*
* Copyright 2018-2021 KMath contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
* Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
*/
package space.kscience.kmath.benchmarks

View File

@ -1,6 +1,6 @@
/*
* Copyright 2018-2021 KMath contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
* Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
*/
package space.kscience.kmath.benchmarks
@ -11,7 +11,10 @@ import org.openjdk.jmh.annotations.Benchmark
import org.openjdk.jmh.annotations.Scope
import org.openjdk.jmh.annotations.State
import space.kscience.kmath.misc.UnstableKMathAPI
import space.kscience.kmath.operations.*
import space.kscience.kmath.operations.BigIntField
import space.kscience.kmath.operations.JBigIntegerField
import space.kscience.kmath.operations.invoke
import space.kscience.kmath.operations.parseBigInteger
import java.math.BigInteger
@ -19,12 +22,24 @@ import java.math.BigInteger
@State(Scope.Benchmark)
internal class BigIntBenchmark {
val kmSmallNumber = BigIntField.number(100)
val jvmSmallNumber = JBigIntegerField.number(100)
val kmNumber = BigIntField.number(Int.MAX_VALUE)
val jvmNumber = JBigIntegerField.number(Int.MAX_VALUE)
val largeKmNumber = BigIntField { number(11).pow(100_000U) }
val largeJvmNumber: BigInteger = JBigIntegerField { number(11).pow(100_000) }
val kmLargeNumber = BigIntField { number(11).pow(100_000U) }
val jvmLargeNumber: BigInteger = JBigIntegerField { number(11).pow(100_000) }
val bigExponent = 50_000
@Benchmark
fun kmSmallAdd(blackhole: Blackhole) = BigIntField {
blackhole.consume(kmSmallNumber + kmSmallNumber + kmSmallNumber)
}
@Benchmark
fun jvmSmallAdd(blackhole: Blackhole) = JBigIntegerField {
blackhole.consume(jvmSmallNumber + jvmSmallNumber + jvmSmallNumber)
}
@Benchmark
fun kmAdd(blackhole: Blackhole) = BigIntField {
blackhole.consume(kmNumber + kmNumber + kmNumber)
@ -37,12 +52,12 @@ internal class BigIntBenchmark {
@Benchmark
fun kmAddLarge(blackhole: Blackhole) = BigIntField {
blackhole.consume(largeKmNumber + largeKmNumber + largeKmNumber)
blackhole.consume(kmLargeNumber + kmLargeNumber + kmLargeNumber)
}
@Benchmark
fun jvmAddLarge(blackhole: Blackhole) = JBigIntegerField {
blackhole.consume(largeJvmNumber + largeJvmNumber + largeJvmNumber)
blackhole.consume(jvmLargeNumber + jvmLargeNumber + jvmLargeNumber)
}
@Benchmark
@ -52,7 +67,7 @@ internal class BigIntBenchmark {
@Benchmark
fun kmMultiplyLarge(blackhole: Blackhole) = BigIntField {
blackhole.consume(largeKmNumber*largeKmNumber)
blackhole.consume(kmLargeNumber*kmLargeNumber)
}
@Benchmark
@ -62,7 +77,7 @@ internal class BigIntBenchmark {
@Benchmark
fun jvmMultiplyLarge(blackhole: Blackhole) = JBigIntegerField {
blackhole.consume(largeJvmNumber*largeJvmNumber)
blackhole.consume(jvmLargeNumber*jvmLargeNumber)
}
@Benchmark

View File

@ -1,6 +1,6 @@
/*
* Copyright 2018-2021 KMath contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
* Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
*/
package space.kscience.kmath.benchmarks

View File

@ -1,6 +1,6 @@
/*
* Copyright 2018-2021 KMath contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
* Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
*/
package space.kscience.kmath.benchmarks
@ -11,9 +11,10 @@ import kotlinx.benchmark.Scope
import kotlinx.benchmark.State
import space.kscience.kmath.commons.linear.CMLinearSpace
import space.kscience.kmath.ejml.EjmlLinearSpaceDDRM
import space.kscience.kmath.linear.LinearSpace
import space.kscience.kmath.linear.invoke
import space.kscience.kmath.linear.linearSpace
import space.kscience.kmath.operations.DoubleField
import space.kscience.kmath.structures.Buffer
import kotlin.random.Random
@State(Scope.Benchmark)
@ -23,8 +24,12 @@ internal class DotBenchmark {
const val dim = 1000
//creating invertible matrix
val matrix1 = LinearSpace.real.buildMatrix(dim, dim) { i, j -> if (i <= j) random.nextDouble() else 0.0 }
val matrix2 = LinearSpace.real.buildMatrix(dim, dim) { i, j -> if (i <= j) random.nextDouble() else 0.0 }
val matrix1 = DoubleField.linearSpace.buildMatrix(dim, dim) { _, _ ->
random.nextDouble()
}
val matrix2 = DoubleField.linearSpace.buildMatrix(dim, dim) { _, _ ->
random.nextDouble()
}
val cmMatrix1 = CMLinearSpace { matrix1.toCM() }
val cmMatrix2 = CMLinearSpace { matrix2.toCM() }
@ -34,37 +39,32 @@ internal class DotBenchmark {
}
@Benchmark
fun cmDot(blackhole: Blackhole) {
CMLinearSpace.run {
blackhole.consume(cmMatrix1 dot cmMatrix2)
}
fun cmDotWithConversion(blackhole: Blackhole) = CMLinearSpace {
blackhole.consume(matrix1 dot matrix2)
}
@Benchmark
fun ejmlDot(blackhole: Blackhole) {
EjmlLinearSpaceDDRM {
blackhole.consume(ejmlMatrix1 dot ejmlMatrix2)
}
fun cmDot(blackhole: Blackhole) = CMLinearSpace {
blackhole.consume(cmMatrix1 dot cmMatrix2)
}
@Benchmark
fun ejmlDotWithConversion(blackhole: Blackhole) {
EjmlLinearSpaceDDRM {
blackhole.consume(matrix1 dot matrix2)
}
fun ejmlDot(blackhole: Blackhole) = EjmlLinearSpaceDDRM {
blackhole.consume(ejmlMatrix1 dot ejmlMatrix2)
}
@Benchmark
fun bufferedDot(blackhole: Blackhole) {
LinearSpace.auto(DoubleField).invoke {
blackhole.consume(matrix1 dot matrix2)
}
fun ejmlDotWithConversion(blackhole: Blackhole) = EjmlLinearSpaceDDRM {
blackhole.consume(matrix1 dot matrix2)
}
@Benchmark
fun realDot(blackhole: Blackhole) {
LinearSpace.real {
blackhole.consume(matrix1 dot matrix2)
}
fun bufferedDot(blackhole: Blackhole) = with(DoubleField.linearSpace(Buffer.Companion::auto)) {
blackhole.consume(matrix1 dot matrix2)
}
@Benchmark
fun doubleDot(blackhole: Blackhole) = with(DoubleField.linearSpace) {
blackhole.consume(matrix1 dot matrix2)
}
}

View File

@ -1,6 +1,6 @@
/*
* Copyright 2018-2021 KMath contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
* Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
*/
package space.kscience.kmath.benchmarks
@ -75,8 +75,9 @@ internal class ExpressionsInterpretersBenchmark {
private val algebra = DoubleField
private const val times = 1_000_000
private val functional = DoubleField.expressionInExtendedField {
bindSymbol(x) * number(2.0) + number(2.0) / bindSymbol(x) - number(16.0) / sin(bindSymbol(x))
private val functional = DoubleField.expression {
val x = bindSymbol(Symbol.x)
x * number(2.0) + 2.0 / x - 16.0 / sin(x)
}
private val node = MstExtendedField {

View File

@ -1,6 +1,6 @@
/*
* Copyright 2018-2021 KMath contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
* Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
*/
package space.kscience.kmath.benchmarks
@ -13,6 +13,8 @@ import space.kscience.kmath.jafama.JafamaDoubleField
import space.kscience.kmath.jafama.StrictJafamaDoubleField
import space.kscience.kmath.operations.DoubleField
import space.kscience.kmath.operations.invoke
import kotlin.contracts.InvocationKind
import kotlin.contracts.contract
import kotlin.random.Random
@State(Scope.Benchmark)
@ -31,9 +33,10 @@ internal class JafamaBenchmark {
fun strictJafama(blackhole: Blackhole) = invokeBenchmarks(blackhole) { x ->
StrictJafamaDoubleField { x * power(x, 4) * exp(x) / cos(x) + sin(x) }
}
private inline fun invokeBenchmarks(blackhole: Blackhole, expr: (Double) -> Double) {
val rng = Random(0)
repeat(1000000) { blackhole.consume(expr(rng.nextDouble())) }
}
}
private inline fun invokeBenchmarks(blackhole: Blackhole, expr: (Double) -> Double) {
contract { callsInPlace(expr, InvocationKind.AT_LEAST_ONCE) }
val rng = Random(0)
repeat(1000000) { blackhole.consume(expr(rng.nextDouble())) }
}

View File

@ -1,6 +1,6 @@
/*
* Copyright 2018-2021 KMath contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
* Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
*/
package space.kscience.kmath.benchmarks
@ -10,13 +10,12 @@ import kotlinx.benchmark.Blackhole
import kotlinx.benchmark.Scope
import kotlinx.benchmark.State
import space.kscience.kmath.commons.linear.CMLinearSpace
import space.kscience.kmath.commons.linear.inverse
import space.kscience.kmath.commons.linear.lupSolver
import space.kscience.kmath.ejml.EjmlLinearSpaceDDRM
import space.kscience.kmath.linear.InverseMatrixFeature
import space.kscience.kmath.linear.LinearSpace
import space.kscience.kmath.linear.inverseWithLup
import space.kscience.kmath.linear.invoke
import space.kscience.kmath.nd.getFeature
import space.kscience.kmath.linear.linearSpace
import space.kscience.kmath.linear.lupSolver
import space.kscience.kmath.operations.algebra
import kotlin.random.Random
@State(Scope.Benchmark)
@ -25,7 +24,7 @@ internal class MatrixInverseBenchmark {
private val random = Random(1224)
private const val dim = 100
private val space = LinearSpace.real
private val space = Double.algebra.linearSpace
//creating invertible matrix
private val u = space.buildMatrix(dim, dim) { i, j -> if (i <= j) random.nextDouble() else 0.0 }
@ -35,20 +34,20 @@ internal class MatrixInverseBenchmark {
@Benchmark
fun kmathLupInversion(blackhole: Blackhole) {
blackhole.consume(LinearSpace.real.inverseWithLup(matrix))
blackhole.consume(Double.algebra.linearSpace.lupSolver().inverse(matrix))
}
@Benchmark
fun cmLUPInversion(blackhole: Blackhole) {
with(CMLinearSpace) {
blackhole.consume(inverse(matrix))
CMLinearSpace {
blackhole.consume(lupSolver().inverse(matrix))
}
}
@Benchmark
fun ejmlInverse(blackhole: Blackhole) {
with(EjmlLinearSpaceDDRM) {
blackhole.consume(matrix.getFeature<InverseMatrixFeature<Double>>()?.inverse)
EjmlLinearSpaceDDRM {
blackhole.consume(matrix.toEjml().inverse())
}
}
}

View File

@ -1,6 +1,6 @@
/*
* Copyright 2018-2021 KMath contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
* Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
*/
package space.kscience.kmath.benchmarks
@ -9,45 +9,97 @@ import kotlinx.benchmark.Benchmark
import kotlinx.benchmark.Blackhole
import kotlinx.benchmark.Scope
import kotlinx.benchmark.State
import space.kscience.kmath.nd.*
import org.jetbrains.kotlinx.multik.api.Multik
import org.jetbrains.kotlinx.multik.api.ones
import org.jetbrains.kotlinx.multik.ndarray.data.DN
import org.jetbrains.kotlinx.multik.ndarray.data.DataType
import space.kscience.kmath.multik.multikAlgebra
import space.kscience.kmath.nd.BufferedFieldOpsND
import space.kscience.kmath.nd.StructureND
import space.kscience.kmath.nd.ndAlgebra
import space.kscience.kmath.nd.one
import space.kscience.kmath.nd4j.nd4j
import space.kscience.kmath.operations.DoubleField
import space.kscience.kmath.structures.Buffer
import space.kscience.kmath.tensors.core.DoubleTensor
import space.kscience.kmath.tensors.core.one
import space.kscience.kmath.tensors.core.tensorAlgebra
import space.kscience.kmath.viktor.viktorAlgebra
@State(Scope.Benchmark)
internal class NDFieldBenchmark {
@Benchmark
fun autoFieldAdd(blackhole: Blackhole) {
with(autoField) {
var res: StructureND<Double> = one
repeat(n) { res += one }
blackhole.consume(res)
}
fun autoFieldAdd(blackhole: Blackhole) = with(autoField) {
var res: StructureND<Double> = one(shape)
repeat(n) { res += 1.0 }
blackhole.consume(res)
}
@Benchmark
fun specializedFieldAdd(blackhole: Blackhole) {
with(specializedField) {
var res: StructureND<Double> = one
repeat(n) { res += 1.0 }
blackhole.consume(res)
}
fun specializedFieldAdd(blackhole: Blackhole) = with(specializedField) {
var res: StructureND<Double> = one(shape)
repeat(n) { res += 1.0 }
blackhole.consume(res)
}
@Benchmark
fun boxingFieldAdd(blackhole: Blackhole) {
with(genericField) {
var res: StructureND<Double> = one
repeat(n) { res += 1.0 }
blackhole.consume(res)
}
fun boxingFieldAdd(blackhole: Blackhole) = with(genericField) {
var res: StructureND<Double> = one(shape)
repeat(n) { res += 1.0 }
blackhole.consume(res)
}
@Benchmark
fun multikAdd(blackhole: Blackhole) = with(multikField) {
var res: StructureND<Double> = one(shape)
repeat(n) { res += 1.0 }
blackhole.consume(res)
}
@Benchmark
fun viktorAdd(blackhole: Blackhole) = with(viktorField) {
var res: StructureND<Double> = one(shape)
repeat(n) { res += 1.0 }
blackhole.consume(res)
}
@Benchmark
fun tensorAdd(blackhole: Blackhole) = with(Double.tensorAlgebra) {
var res: DoubleTensor = one(shape)
repeat(n) { res = res + 1.0 }
blackhole.consume(res)
}
@Benchmark
fun tensorInPlaceAdd(blackhole: Blackhole) = with(Double.tensorAlgebra) {
val res: DoubleTensor = one(shape)
repeat(n) { res += 1.0 }
blackhole.consume(res)
}
@Benchmark
fun multikInPlaceAdd(blackhole: Blackhole) = with(DoubleField.multikAlgebra) {
val res = Multik.ones<Double, DN>(shape, DataType.DoubleDataType).wrap()
repeat(n) { res += 1.0 }
blackhole.consume(res)
}
// @Benchmark
// fun nd4jAdd(blackhole: Blackhole) = with(nd4jField) {
// var res: StructureND<Double> = one(dim, dim)
// repeat(n) { res += 1.0 }
// blackhole.consume(res)
// }
private companion object {
private const val dim = 1000
private const val n = 100
private val autoField = AlgebraND.auto(DoubleField, dim, dim)
private val specializedField = AlgebraND.real(dim, dim)
private val genericField = AlgebraND.field(DoubleField, Buffer.Companion::boxing, dim, dim)
private val shape = intArrayOf(dim, dim)
private val autoField = BufferedFieldOpsND(DoubleField, Buffer.Companion::auto)
private val specializedField = DoubleField.ndAlgebra
private val genericField = BufferedFieldOpsND(DoubleField, Buffer.Companion::boxing)
private val nd4jField = DoubleField.nd4j
private val multikField = DoubleField.multikAlgebra
private val viktorField = DoubleField.viktorAlgebra
}
}

View File

@ -1,6 +1,6 @@
/*
* Copyright 2018-2021 KMath contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
* Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
*/
package space.kscience.kmath.benchmarks
@ -10,19 +10,17 @@ import kotlinx.benchmark.Blackhole
import kotlinx.benchmark.Scope
import kotlinx.benchmark.State
import org.jetbrains.bio.viktor.F64Array
import space.kscience.kmath.nd.AlgebraND
import space.kscience.kmath.nd.StructureND
import space.kscience.kmath.nd.auto
import space.kscience.kmath.nd.real
import space.kscience.kmath.nd.*
import space.kscience.kmath.operations.DoubleField
import space.kscience.kmath.viktor.ViktorNDField
import space.kscience.kmath.structures.Buffer
import space.kscience.kmath.viktor.ViktorFieldND
@State(Scope.Benchmark)
internal class ViktorBenchmark {
@Benchmark
fun automaticFieldAddition(blackhole: Blackhole) {
with(autoField) {
var res: StructureND<Double> = one
var res: StructureND<Double> = one(shape)
repeat(n) { res += 1.0 }
blackhole.consume(res)
}
@ -31,7 +29,7 @@ internal class ViktorBenchmark {
@Benchmark
fun realFieldAddition(blackhole: Blackhole) {
with(realField) {
var res: StructureND<Double> = one
var res: StructureND<Double> = one(shape)
repeat(n) { res += 1.0 }
blackhole.consume(res)
}
@ -40,7 +38,7 @@ internal class ViktorBenchmark {
@Benchmark
fun viktorFieldAddition(blackhole: Blackhole) {
with(viktorField) {
var res = one
var res = one(shape)
repeat(n) { res += 1.0 }
blackhole.consume(res)
}
@ -57,10 +55,11 @@ internal class ViktorBenchmark {
private companion object {
private const val dim = 1000
private const val n = 100
private val shape = Shape(dim, dim)
// automatically build context most suited for given type.
private val autoField = AlgebraND.auto(DoubleField, dim, dim)
private val realField = AlgebraND.real(dim, dim)
private val viktorField = ViktorNDField(dim, dim)
private val autoField = BufferedFieldOpsND(DoubleField, Buffer.Companion::auto)
private val realField = DoubleField.ndAlgebra
private val viktorField = ViktorFieldND(dim, dim)
}
}

View File

@ -1,6 +1,6 @@
/*
* Copyright 2018-2021 KMath contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
* Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
*/
package space.kscience.kmath.benchmarks
@ -10,19 +10,21 @@ import kotlinx.benchmark.Blackhole
import kotlinx.benchmark.Scope
import kotlinx.benchmark.State
import org.jetbrains.bio.viktor.F64Array
import space.kscience.kmath.nd.AlgebraND
import space.kscience.kmath.nd.auto
import space.kscience.kmath.nd.real
import space.kscience.kmath.nd.BufferedFieldOpsND
import space.kscience.kmath.nd.Shape
import space.kscience.kmath.nd.ndAlgebra
import space.kscience.kmath.nd.one
import space.kscience.kmath.operations.DoubleField
import space.kscience.kmath.structures.Buffer
import space.kscience.kmath.viktor.ViktorFieldND
@State(Scope.Benchmark)
internal class ViktorLogBenchmark {
@Benchmark
fun realFieldLog(blackhole: Blackhole) {
with(realNdField) {
val fortyTwo = produce { 42.0 }
var res = one
with(realField) {
val fortyTwo = structureND(shape) { 42.0 }
var res = one(shape)
repeat(n) { res = ln(fortyTwo) }
blackhole.consume(res)
}
@ -31,7 +33,7 @@ internal class ViktorLogBenchmark {
@Benchmark
fun viktorFieldLog(blackhole: Blackhole) {
with(viktorField) {
val fortyTwo = produce { 42.0 }
val fortyTwo = structureND(shape) { 42.0 }
var res = one
repeat(n) { res = ln(fortyTwo) }
blackhole.consume(res)
@ -49,10 +51,11 @@ internal class ViktorLogBenchmark {
private companion object {
private const val dim = 1000
private const val n = 100
private val shape = Shape(dim, dim)
// automatically build context most suited for given type.
private val autoField = AlgebraND.auto(DoubleField, dim, dim)
private val realNdField = AlgebraND.real(dim, dim)
private val viktorField = ViktorFieldND(intArrayOf(dim, dim))
private val autoField = BufferedFieldOpsND(DoubleField, Buffer.Companion::auto)
private val realField = DoubleField.ndAlgebra
private val viktorField = ViktorFieldND(dim, dim)
}
}

View File

@ -1,3 +1,5 @@
import java.net.URL
plugins {
id("ru.mipt.npm.gradle.project")
kotlin("jupyter.api") apply false
@ -7,15 +9,17 @@ allprojects {
repositories {
maven("https://clojars.org/repo")
maven("https://jitpack.io")
maven("http://logicrunch.research.it.uu.se/maven") {
isAllowInsecureProtocol = true
}
maven("https://oss.sonatype.org/content/repositories/snapshots")
mavenCentral()
}
group = "space.kscience"
version = "0.3.0-dev-14"
version = "0.3.0-dev-17"
}
subprojects {
@ -23,32 +27,46 @@ subprojects {
afterEvaluate {
tasks.withType<org.jetbrains.dokka.gradle.DokkaTaskPartial> {
dependsOn(tasks.getByName("assemble"))
dependsOn(tasks["assemble"])
dokkaSourceSets.all {
val readmeFile = File(this@subprojects.projectDir, "README.md")
if (readmeFile.exists()) includes.from(readmeFile.absolutePath)
externalDocumentationLink("http://ejml.org/javadoc/")
val readmeFile = this@subprojects.projectDir.resolve("README.md")
if (readmeFile.exists()) includes.from(readmeFile)
val kotlinDirPath = "src/$name/kotlin"
val kotlinDir = file(kotlinDirPath)
if (kotlinDir.exists()) sourceLink {
localDirectory.set(kotlinDir)
remoteUrl.set(
URL("https://github.com/mipt-npm/${rootProject.name}/tree/master/${this@subprojects.name}/$kotlinDirPath")
)
}
externalDocumentationLink("https://commons.apache.org/proper/commons-math/javadocs/api-3.6.1/")
externalDocumentationLink("https://deeplearning4j.org/api/latest/")
externalDocumentationLink("https://axelclk.bitbucket.io/symja/javadoc/")
externalDocumentationLink("https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/")
externalDocumentationLink("https://breandan.net/kotlingrad/kotlingrad/", "https://breandan.net/kotlingrad/kotlingrad/kotlingrad/package-list")
externalDocumentationLink(
"https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/",
"https://kotlin.github.io/kotlinx.coroutines/package-list",
)
externalDocumentationLink(
"https://breandan.net/kotlingrad/kotlingrad/",
"https://breandan.net/kotlingrad/kotlingrad/kotlingrad/package-list",
)
}
}
}
}
readme {
readmeTemplate = file("docs/templates/README-TEMPLATE.md")
}
readme.readmeTemplate = file("docs/templates/README-TEMPLATE.md")
ksciencePublish {
github("kmath")
space()
sonatype()
vcs("https://github.com/mipt-npm/kmath")
space(publish = true)
sonatype(publish = true)
}
apiValidation {
nonPublicMarkers.add("space.kscience.kmath.misc.UnstableKMathAPI")
}
apiValidation.nonPublicMarkers.add("space.kscience.kmath.misc.UnstableKMathAPI")

View File

@ -11,7 +11,7 @@ repositories {
dependencies {
api("org.jetbrains.kotlinx:kotlinx-serialization-json:1.1.0")
api("ru.mipt.npm:gradle-tools:0.10.0")
api("ru.mipt.npm:gradle-tools:0.10.2")
api("org.jetbrains.kotlinx:kotlinx-benchmark-plugin:0.3.1")
}

View File

@ -1,6 +1,6 @@
/*
* Copyright 2018-2021 KMath contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
* Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
*/
package space.kscience.kmath.benchmarks

View File

@ -1,6 +1,6 @@
/*
* Copyright 2018-2021 KMath contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
* Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
*/
package space.kscience.kmath.benchmarks

View File

@ -1,6 +1,6 @@
/*
* Copyright 2018-2021 KMath contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
* Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
*/
@file:Suppress("KDocUnresolvedReference")
@ -14,12 +14,12 @@ private fun Appendable.appendEjmlVector(type: String, ejmlMatrixType: String) {
@Language("kotlin") val text = """/**
* [EjmlVector] specialization for [$type].
*/
public class Ejml${type}Vector<out M : $ejmlMatrixType>(public override val origin: M) : EjmlVector<$type, M>(origin) {
public class Ejml${type}Vector<out M : $ejmlMatrixType>(override val origin: M) : EjmlVector<$type, M>(origin) {
init {
require(origin.numRows == 1) { "The origin matrix must have only one row to form a vector" }
}
public override operator fun get(index: Int): $type = origin[0, index]
override operator fun get(index: Int): $type = origin[0, index]
}"""
appendLine(text)
appendLine()
@ -29,8 +29,8 @@ private fun Appendable.appendEjmlMatrix(type: String, ejmlMatrixType: String) {
val text = """/**
* [EjmlMatrix] specialization for [$type].
*/
public class Ejml${type}Matrix<out M : $ejmlMatrixType>(public override val origin: M) : EjmlMatrix<$type, M>(origin) {
public override operator fun get(i: Int, j: Int): $type = origin[i, j]
public class Ejml${type}Matrix<out M : $ejmlMatrixType>(override val origin: M) : EjmlMatrix<$type, M>(origin) {
override operator fun get(i: Int, j: Int): $type = origin[i, j]
}"""
appendLine(text)
appendLine()
@ -54,23 +54,23 @@ public object EjmlLinearSpace${ops} : EjmlLinearSpace<${type}, ${kmathAlgebra},
/**
* The [${kmathAlgebra}] reference.
*/
public override val elementAlgebra: $kmathAlgebra get() = $kmathAlgebra
override val elementAlgebra: $kmathAlgebra get() = $kmathAlgebra
@Suppress("UNCHECKED_CAST")
public override fun Matrix<${type}>.toEjml(): Ejml${type}Matrix<${ejmlMatrixType}> = when {
override fun Matrix<${type}>.toEjml(): Ejml${type}Matrix<${ejmlMatrixType}> = when {
this is Ejml${type}Matrix<*> && origin is $ejmlMatrixType -> this as Ejml${type}Matrix<${ejmlMatrixType}>
else -> buildMatrix(rowNum, colNum) { i, j -> get(i, j) }
}
@Suppress("UNCHECKED_CAST")
public override fun Point<${type}>.toEjml(): Ejml${type}Vector<${ejmlMatrixType}> = when {
override fun Point<${type}>.toEjml(): Ejml${type}Vector<${ejmlMatrixType}> = when {
this is Ejml${type}Vector<*> && origin is $ejmlMatrixType -> this as Ejml${type}Vector<${ejmlMatrixType}>
else -> Ejml${type}Vector(${ejmlMatrixType}(size, 1).also {
(0 until it.numRows).forEach { row -> it[row, 0] = get(row) }
})
}
public override fun buildMatrix(
override fun buildMatrix(
rows: Int,
columns: Int,
initializer: ${kmathAlgebra}.(i: Int, j: Int) -> ${type},
@ -80,7 +80,7 @@ public object EjmlLinearSpace${ops} : EjmlLinearSpace<${type}, ${kmathAlgebra},
}
}.wrapMatrix()
public override fun buildVector(
override fun buildVector(
size: Int,
initializer: ${kmathAlgebra}.(Int) -> ${type},
): Ejml${type}Vector<${ejmlMatrixType}> = Ejml${type}Vector(${ejmlMatrixType}(size, 1).also {
@ -90,21 +90,21 @@ public object EjmlLinearSpace${ops} : EjmlLinearSpace<${type}, ${kmathAlgebra},
private fun <T : ${ejmlMatrixParentTypeMatrix}> T.wrapMatrix() = Ejml${type}Matrix(this)
private fun <T : ${ejmlMatrixParentTypeMatrix}> T.wrapVector() = Ejml${type}Vector(this)
public override fun Matrix<${type}>.unaryMinus(): Matrix<${type}> = this * elementAlgebra { -one }
override fun Matrix<${type}>.unaryMinus(): Matrix<${type}> = this * elementAlgebra { -one }
public override fun Matrix<${type}>.dot(other: Matrix<${type}>): Ejml${type}Matrix<${ejmlMatrixType}> {
override fun Matrix<${type}>.dot(other: Matrix<${type}>): Ejml${type}Matrix<${ejmlMatrixType}> {
val out = ${ejmlMatrixType}(1, 1)
CommonOps_${ops}.mult(toEjml().origin, other.toEjml().origin, out)
return out.wrapMatrix()
}
public override fun Matrix<${type}>.dot(vector: Point<${type}>): Ejml${type}Vector<${ejmlMatrixType}> {
override fun Matrix<${type}>.dot(vector: Point<${type}>): Ejml${type}Vector<${ejmlMatrixType}> {
val out = ${ejmlMatrixType}(1, 1)
CommonOps_${ops}.mult(toEjml().origin, vector.toEjml().origin, out)
return out.wrapVector()
}
public override operator fun Matrix<${type}>.minus(other: Matrix<${type}>): Ejml${type}Matrix<${ejmlMatrixType}> {
override operator fun Matrix<${type}>.minus(other: Matrix<${type}>): Ejml${type}Matrix<${ejmlMatrixType}> {
val out = ${ejmlMatrixType}(1, 1)
CommonOps_${ops}.add(
@ -123,19 +123,19 @@ public object EjmlLinearSpace${ops} : EjmlLinearSpace<${type}, ${kmathAlgebra},
return out.wrapMatrix()
}
public override operator fun Matrix<${type}>.times(value: ${type}): Ejml${type}Matrix<${ejmlMatrixType}> {
override operator fun Matrix<${type}>.times(value: ${type}): Ejml${type}Matrix<${ejmlMatrixType}> {
val res = ${ejmlMatrixType}(1, 1)
CommonOps_${ops}.scale(value, toEjml().origin, res)
return res.wrapMatrix()
}
public override fun Point<${type}>.unaryMinus(): Ejml${type}Vector<${ejmlMatrixType}> {
override fun Point<${type}>.unaryMinus(): Ejml${type}Vector<${ejmlMatrixType}> {
val res = ${ejmlMatrixType}(1, 1)
CommonOps_${ops}.changeSign(toEjml().origin, res)
return res.wrapVector()
}
public override fun Matrix<${type}>.plus(other: Matrix<${type}>): Ejml${type}Matrix<${ejmlMatrixType}> {
override fun Matrix<${type}>.plus(other: Matrix<${type}>): Ejml${type}Matrix<${ejmlMatrixType}> {
val out = ${ejmlMatrixType}(1, 1)
CommonOps_${ops}.add(
@ -154,7 +154,7 @@ public object EjmlLinearSpace${ops} : EjmlLinearSpace<${type}, ${kmathAlgebra},
return out.wrapMatrix()
}
public override fun Point<${type}>.plus(other: Point<${type}>): Ejml${type}Vector<${ejmlMatrixType}> {
override fun Point<${type}>.plus(other: Point<${type}>): Ejml${type}Vector<${ejmlMatrixType}> {
val out = ${ejmlMatrixType}(1, 1)
CommonOps_${ops}.add(
@ -173,7 +173,7 @@ public object EjmlLinearSpace${ops} : EjmlLinearSpace<${type}, ${kmathAlgebra},
return out.wrapVector()
}
public override fun Point<${type}>.minus(other: Point<${type}>): Ejml${type}Vector<${ejmlMatrixType}> {
override fun Point<${type}>.minus(other: Point<${type}>): Ejml${type}Vector<${ejmlMatrixType}> {
val out = ${ejmlMatrixType}(1, 1)
CommonOps_${ops}.add(
@ -192,18 +192,18 @@ public object EjmlLinearSpace${ops} : EjmlLinearSpace<${type}, ${kmathAlgebra},
return out.wrapVector()
}
public override fun ${type}.times(m: Matrix<${type}>): Ejml${type}Matrix<${ejmlMatrixType}> = m * this
override fun ${type}.times(m: Matrix<${type}>): Ejml${type}Matrix<${ejmlMatrixType}> = m * this
public override fun Point<${type}>.times(value: ${type}): Ejml${type}Vector<${ejmlMatrixType}> {
override fun Point<${type}>.times(value: ${type}): Ejml${type}Vector<${ejmlMatrixType}> {
val res = ${ejmlMatrixType}(1, 1)
CommonOps_${ops}.scale(value, toEjml().origin, res)
return res.wrapVector()
}
public override fun ${type}.times(v: Point<${type}>): Ejml${type}Vector<${ejmlMatrixType}> = v * this
override fun ${type}.times(v: Point<${type}>): Ejml${type}Vector<${ejmlMatrixType}> = v * this
@UnstableKMathAPI
public override fun <F : StructureFeature> getFeature(structure: Matrix<${type}>, type: KClass<out F>): F? {
override fun <F : StructureFeature> computeFeature(structure: Matrix<${type}>, type: KClass<out F>): F? {
structure.getFeature(type)?.let { return it }
val origin = structure.toEjml().origin
@ -240,10 +240,10 @@ public object EjmlLinearSpace${ops} : EjmlLinearSpace<${type}, ${kmathAlgebra},
}
override val q: Matrix<${type}> by lazy {
qr.getQ(null, false).wrapMatrix() + OrthogonalFeature
qr.getQ(null, false).wrapMatrix().withFeature(OrthogonalFeature)
}
override val r: Matrix<${type}> by lazy { qr.getR(null, false).wrapMatrix() + UFeature }
override val r: Matrix<${type}> by lazy { qr.getR(null, false).wrapMatrix().withFeature(UFeature) }
}
CholeskyDecompositionFeature::class -> object : CholeskyDecompositionFeature<${type}> {
@ -251,7 +251,7 @@ public object EjmlLinearSpace${ops} : EjmlLinearSpace<${type}, ${kmathAlgebra},
val cholesky =
DecompositionFactory_${ops}.chol(structure.rowNum, true).apply { decompose(origin.copy()) }
cholesky.getT(null).wrapMatrix() + LFeature
cholesky.getT(null).wrapMatrix().withFeature(LFeature)
}
}
@ -261,11 +261,11 @@ public object EjmlLinearSpace${ops} : EjmlLinearSpace<${type}, ${kmathAlgebra},
}
override val l: Matrix<${type}> by lazy {
lup.getLower(null).wrapMatrix() + LFeature
lup.getLower(null).wrapMatrix().withFeature(LFeature)
}
override val u: Matrix<${type}> by lazy {
lup.getUpper(null).wrapMatrix() + UFeature
lup.getUpper(null).wrapMatrix().withFeature(UFeature)
}
override val p: Matrix<${type}> by lazy { lup.getRowPivot(null).wrapMatrix() }
@ -275,10 +275,10 @@ public object EjmlLinearSpace${ops} : EjmlLinearSpace<${type}, ${kmathAlgebra},
}
override val q: Matrix<${type}> by lazy {
qr.getQ(null, false).wrapMatrix() + OrthogonalFeature
qr.getQ(null, false).wrapMatrix().withFeature(OrthogonalFeature)
}
override val r: Matrix<${type}> by lazy { qr.getR(null, false).wrapMatrix() + UFeature }
override val r: Matrix<${type}> by lazy { qr.getR(null, false).wrapMatrix().withFeature(UFeature) }
}
CholeskyDecompositionFeature::class -> object : CholeskyDecompositionFeature<${type}> {
@ -286,7 +286,7 @@ public object EjmlLinearSpace${ops} : EjmlLinearSpace<${type}, ${kmathAlgebra},
val cholesky =
DecompositionFactory_${ops}.cholesky().apply { decompose(origin.copy()) }
(cholesky.getT(null) as ${ejmlMatrixParentTypeMatrix}).wrapMatrix() + LFeature
(cholesky.getT(null) as ${ejmlMatrixParentTypeMatrix}).wrapMatrix().withFeature(LFeature)
}
}
@ -297,11 +297,11 @@ public object EjmlLinearSpace${ops} : EjmlLinearSpace<${type}, ${kmathAlgebra},
}
override val l: Matrix<${type}> by lazy {
lu.getLower(null).wrapMatrix() + LFeature
lu.getLower(null).wrapMatrix().withFeature(LFeature)
}
override val u: Matrix<${type}> by lazy {
lu.getUpper(null).wrapMatrix() + UFeature
lu.getUpper(null).wrapMatrix().withFeature(UFeature)
}
override val inverse: Matrix<${type}> by lazy {
@ -362,7 +362,7 @@ fun ejmlCodegen(outputFile: String): Unit = File(outputFile).run {
writer().use {
it.appendLine("/*")
it.appendLine(" * Copyright 2018-2021 KMath contributors.")
it.appendLine(" * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.")
it.appendLine(" * Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.")
it.appendLine(" */")
it.appendLine()
it.appendLine("/* This file is generated with buildSrc/src/main/kotlin/space/kscience/kmath/ejml/codegen/ejmlCodegen.kt */")

View File

@ -1,85 +1,45 @@
# Algebraic Structures and Algebraic Elements
The mathematical operations in KMath are generally separated from mathematical objects. This means that to perform an
operation, say `+`, one needs two objects of a type `T` and an algebra context, which draws appropriate operation up,
say `Space<T>`. Next one needs to run the actual operation in the context:
The mathematical operations in KMath are generally separated from mathematical objects. This means that to perform an
operation, say `+`, one needs two objects of a type `T` and an algebra context, which draws appropriate operation up,
say `Group<T>`. Next one needs to run the actual operation in the context:
```kotlin
import space.kscience.kmath.operations.*
val a: T = ...
val b: T = ...
val space: Space<T> = ...
val group: Group<T> = ...
val c = space { a + b }
val c = group { a + b }
```
At first glance, this distinction seems to be a needless complication, but in fact one needs to remember that in
mathematics, one could draw up different operations on same objects. For example, one could use different types of
At first glance, this distinction seems to be a needless complication, but in fact one needs to remember that in
mathematics, one could draw up different operations on same objects. For example, one could use different types of
geometry for vectors.
## Algebraic Structures
Mathematical contexts have the following hierarchy:
Primary mathematical contexts have the following hierarchy:
**Algebra** ← **Space****Ring** ← **Field**
`Field <: Ring <: Group <: Algebra`
These interfaces follow real algebraic structures:
- [Space](https://mathworld.wolfram.com/VectorSpace.html) defines addition, its neutral element (i.e. 0) and scalar
multiplication;
- [Ring](http://mathworld.wolfram.com/Ring.html) adds multiplication and its neutral element (i.e. 1);
- [Group](https://mathworld.wolfram.com/Group.html) defines addition, its identity element (i.e., 0) and additive
inverse (-x);
- [Ring](http://mathworld.wolfram.com/Ring.html) adds multiplication and its identity element (i.e., 1);
- [Field](http://mathworld.wolfram.com/Field.html) adds division operation.
A typical implementation of `Field<T>` is the `DoubleField` which works on doubles, and `VectorSpace` for `Space<T>`.
In some cases algebra context can hold additional operations like `exp` or `sin`, and then it inherits appropriate
interface. Also, contexts may have operations, which produce elements outside of the context. For example, `Matrix.dot`
operation produces a matrix with new dimensions, which can be incompatible with initial matrix in terms of linear
operations.
## Algebraic Element
To achieve more familiar behavior (where you apply operations directly to mathematical objects), without involving
contexts KMath submits special type objects called `MathElement`. A `MathElement` is basically some object coupled to
a mathematical context. For example `Complex` is the pair of real numbers representing real and imaginary parts,
but it also holds reference to the `ComplexField` singleton, which allows performing direct operations on `Complex`
numbers without explicit involving the context like:
```kotlin
import space.kscience.kmath.operations.*
// Using elements
val c1 = Complex(1.0, 1.0)
val c2 = Complex(1.0, -1.0)
val c3 = c1 + c2 + 3.0.toComplex()
// Using context
val c4 = ComplexField { c1 + i - 2.0 }
```
Both notations have their pros and cons.
The hierarchy for algebraic elements follows the hierarchy for the corresponding algebraic structures.
**MathElement** ← **SpaceElement****RingElement** ← **FieldElement**
`MathElement<C>` is the generic common ancestor of the class with context.
One major distinction between algebraic elements and algebraic contexts is that elements have three type
parameters:
1. The type of elements, the field operates on.
2. The self-type of the element returned from operation (which has to be an algebraic element).
3. The type of the algebra over first type-parameter.
The middle type is needed for of algebra members do not store context. For example, it is impossible to add a context
to regular `Double`. The element performs automatic conversions from context types and back. One should use context
operations in all performance-critical places. The performance of element operations is not guaranteed.
interface. Also, contexts may have operations, which produce elements outside the context. For example, `Matrix.dot`
operation produces a matrix with new dimensions, which can be incompatible with initial matrix in linear operations.
## Spaces and Fields
KMath submits both contexts and elements for builtin algebraic structures:
KMath introduces contexts for builtin algebraic structures:
```kotlin
import space.kscience.kmath.operations.*
@ -102,13 +62,13 @@ val c2 = ComplexField { c1 - 1.0 } // Returns: Complex(re=0.0, im=2.0)
val c3 = ComplexField { c1 - i * 2.0 }
```
**Note**: In theory it is possible to add behaviors directly to the context, but as for now Kotlin does not support
that. Watch [KT-10468](https://youtrack.jetbrains.com/issue/KT-10468) and
**Note**: In theory it is possible to add behaviors directly to the context, but as for now Kotlin does not support
that. Watch [KT-10468](https://youtrack.jetbrains.com/issue/KT-10468) and
[KEEP-176](https://github.com/Kotlin/KEEP/pull/176) for updates.
## Nested fields
Contexts allow one to build more complex structures. For example, it is possible to create a `Matrix` from complex
Contexts allow one to build more complex structures. For example, it is possible to create a `Matrix` from complex
elements like so:
```kotlin
@ -118,8 +78,9 @@ val element = NDElement.complex(shape = intArrayOf(2, 2)) { index: IntArray ->
```
The `element` in this example is a member of the `Field` of 2D structures, each element of which is a member of its own
`ComplexField`. It is important one does not need to create a special n-d class to hold complex
numbers and implement operations on it, one just needs to provide a field for its elements.
`ComplexField`. It is important one does not need to create a special n-d class to hold complex numbers and implement
operations on it, one just needs to provide a field for its elements.
**Note**: Fields themselves do not solve the problem of JVM boxing, but it is possible to solve with special contexts like
**Note**: Fields themselves do not solve the problem of JVM boxing, but it is possible to solve with special contexts
like
`MemorySpec`.

View File

@ -1,17 +1,20 @@
# Buffers
Buffer is one of main building blocks of kmath. It is a basic interface allowing random-access read and write (with `MutableBuffer`).
There are different types of buffers:
Buffer is one of main building blocks of kmath. It is a basic interface allowing random-access read and write (
with `MutableBuffer`). There are different types of buffers:
* Primitive buffers wrapping like `RealBuffer` which are wrapping primitive arrays.
* Primitive buffers wrapping like `DoubleBuffer` which are wrapping primitive arrays.
* Boxing `ListBuffer` wrapping a list
* Functionally defined `VirtualBuffer` which does not hold a state itself, but provides a function to calculate value
* `MemoryBuffer` allows direct allocation of objects in continuous memory block.
Some kmath features require a `BufferFactory` class to operate properly. A general convention is to use functions defined in
`Buffer` and `MutableBuffer` companion classes. For example factory `Buffer.Companion::auto` in most cases creates the most suitable
buffer for given reified type (for types with custom memory buffer it still better to use their own `MemoryBuffer.create()` factory).
Some kmath features require a `BufferFactory` class to operate properly. A general convention is to use functions
defined in
`Buffer` and `MutableBuffer` companion classes. For example factory `Buffer.Companion::auto` in most cases creates the
most suitable buffer for given reified type (for types with custom memory buffer it still better to use their
own `MemoryBuffer.create()` factory).
## Buffer performance
One should avoid using default boxing buffer wherever it is possible. Try to use primitive buffers or memory buffers instead
One should avoid using default boxing buffer wherever it is possible. Try to use primitive buffers or memory buffers
instead .

View File

@ -1,26 +1,20 @@
# Coding Conventions
KMath code follows general [Kotlin conventions](https://kotlinlang.org/docs/reference/coding-conventions.html), but
with a number of small changes and clarifications.
Generally, KMath code follows general [Kotlin coding conventions](https://kotlinlang.org/docs/reference/coding-conventions.html), but with a number of small changes and clarifications.
## Utility Class Naming
Filename should coincide with a name of one of the classes contained in the file or start with small letter and
describe its contents.
Filename should coincide with a name of one of the classes contained in the file or start with small letter and describe its contents.
The code convention [here](https://kotlinlang.org/docs/reference/coding-conventions.html#source-file-names) says that
file names should start with a capital letter even if file does not contain classes. Yet starting utility classes and
aggregators with a small letter seems to be a good way to visually separate those files.
The code convention [here](https://kotlinlang.org/docs/reference/coding-conventions.html#source-file-names) says that file names should start with a capital letter even if file does not contain classes. Yet starting utility classes and aggregators with a small letter seems to be a good way to visually separate those files.
This convention could be changed in future in a non-breaking way.
## Private Variable Naming
Private variables' names may start with underscore `_` for of the private mutable variable is shadowed by the public
read-only value with the same meaning.
Private variables' names may start with underscore `_` for of the private mutable variable is shadowed by the public read-only value with the same meaning.
This rule does not permit underscores in names, but it is sometimes useful to "underscore" the fact that public and
private versions draw up the same entity. It is allowed only for private variables.
This rule does not permit underscores in names, but it is sometimes useful to "underscore" the fact that public and private versions draw up the same entity. It is allowed only for private variables.
This convention could be changed in future in a non-breaking way.
@ -30,5 +24,4 @@ Use one-liners when they occupy single code window line both for functions and p
`val b: String get() = "fff"`. The same should be performed with multiline expressions when they could be
cleanly separated.
There is no universal consensus whenever use `fun a() = ...` or `fun a() { return ... }`. Yet from reader outlook
one-lines seem to better show that the property or function is easily calculated.
There is no universal consensus whenever use `fun a() = ...` or `fun a() { return ... }`. Yet from reader outlook one-lines seem to better show that the property or function is easily calculated.

View File

@ -2,18 +2,17 @@
## The problem
A known problem for implementing mathematics in statically-typed languages (but not only in them) is that different
sets of mathematical operators can be defined on the same mathematical objects. Sometimes there is no single way to
treat some operations, including basic arithmetic operations, on a Java/Kotlin `Number`. Sometimes there are different ways to
define the same structure, such as Euclidean and elliptic geometry vector spaces over real vectors. Another problem arises when
one wants to add some kind of behavior to an existing entity. In dynamic languages those problems are usually solved
by adding dynamic context-specific behaviors at runtime, but this solution has a lot of drawbacks.
A known problem for implementing mathematics in statically-typed languages (but not only in them) is that different sets
of mathematical operators can be defined on the same mathematical objects. Sometimes there is no single way to treat
some operations, including basic arithmetic operations, on a Java/Kotlin `Number`. Sometimes there are different ways to
define the same structure, such as Euclidean and elliptic geometry vector spaces over real vectors. Another problem
arises when one wants to add some kind of behavior to an existing entity. In dynamic languages those problems are
usually solved by adding dynamic context-specific behaviors at runtime, but this solution has a lot of drawbacks.
## Context-oriented approach
One possible solution to these problems is to divorce numerical representations from behaviors.
For example in Kotlin one can define a separate class which represents some entity without any operations,
ex. a complex number:
One possible solution to these problems is to divorce numerical representations from behaviors. For example in Kotlin
one can define a separate class representing some entity without any operations, ex. a complex number:
```kotlin
data class Complex(val re: Double, val im: Double)
@ -28,9 +27,10 @@ object ComplexOperations {
}
```
In Java, applying such external operations could be very cumbersome, but Kotlin has a unique feature which allows us
implement this naturally: [extensions with receivers](https://kotlinlang.org/docs/reference/extensions.html#extension-functions).
In Kotlin, an operation on complex number could be implemented as:
In Java, applying such external operations could be cumbersome, but Kotlin has a unique feature that allows us
implement this
naturally: [extensions with receivers](https://kotlinlang.org/docs/reference/extensions.html#extension-functions). In
Kotlin, an operation on complex number could be implemented as:
```kotlin
with(ComplexOperations) { c1 + c2 - c3 }
@ -52,20 +52,20 @@ In KMath, contexts are not only responsible for operations, but also for raw obj
### Type classes
An obvious candidate to get more or less the same functionality is the type class, which allows one to bind a behavior to
a specific type without modifying the type itself. On the plus side, type classes do not require explicit context
An obvious candidate to get more or less the same functionality is the type class, which allows one to bind a behavior
to a specific type without modifying the type itself. On the plus side, type classes do not require explicit context
declaration, so the code looks cleaner. On the minus side, if there are different sets of behaviors for the same types,
it is impossible to combine them into one module. Also, unlike type classes, context can have parameters or even
state. For example in KMath, sizes and strides for `NDElement` or `Matrix` could be moved to context to optimize
performance in case of a large amount of structures.
it is impossible to combine them into one module. Also, unlike type classes, context can have parameters or even state.
For example in KMath, sizes and strides for `NDElement` or `Matrix` could be moved to context to optimize performance in
case of a large amount of structures.
### Wildcard imports and importing-on-demand
Sometimes, one may wish to use a single context throughout a file. In this case, is possible to import all members
from a package or file, via `import context.complex.*`. Effectively, this is the same as enclosing an entire file
with a single context. However when using multiple contexts, this technique can introduce operator ambiguity, due to
namespace pollution. If there are multiple scoped contexts which define the same operation, it is still possible to
to import specific operations as needed, without using an explicit context with extension functions, for example:
Sometimes, one may wish to use a single context throughout a file. In this case, is possible to import all members from
a package or file, via `import context.complex.*`. Effectively, this is the same as enclosing an entire file with a
single context. However, when using multiple contexts, this technique can introduce operator ambiguity, due to namespace
pollution. If there are multiple scoped contexts that define the same operation, it is still possible to import
specific operations as needed, without using an explicit context with extension functions, for example:
```
import context.complex.op1

1020
docs/diagrams/core.puml Normal file

File diff suppressed because it is too large Load Diff

View File

@ -1,26 +1,21 @@
# Expressions
**Experimental: this API is in early stage and could change any time**
Expressions is an experimental feature which allows to construct lazily or immediately calculated parametric mathematical
expressions.
Expressions is a feature, which allows constructing lazily or immediately calculated parametric mathematical expressions.
The potential use-cases for it (so far) are following:
* Lazy evaluation (in general simple lambda is better, but there are some border cases)
* lazy evaluation (in general simple lambda is better, but there are some border cases);
* automatic differentiation in single-dimension and in multiple dimensions;
* generation of mathematical syntax trees with subsequent code generation for other languages;
* symbolic computations, especially differentiation (and some other actions with `kmath-symja` integration with Symja's `IExpr`&mdash;integration, simplification, and more);
* visualization with `kmath-jupyter`.
* Automatic differentiation in single-dimension and in multiple dimensions
* Generation of mathematical syntax trees with subsequent code generation for other languages
* Maybe symbolic computations (needs additional research)
The workhorse of this API is `Expression` interface which exposes single `operator fun invoke(arguments: Map<String, T>): T`
method. `ExpressionContext` is used to generate expressions and introduce variables.
The workhorse of this API is `Expression` interface, which exposes single `operator fun invoke(arguments: Map<Symbol, T>): T`
method. `ExpressionAlgebra` is used to generate expressions and introduce variables.
Currently there are two implementations:
* Generic `ExpressionField` in `kmath-core` which allows construction of custom lazy expressions
* Auto-differentiation expression in `kmath-commons` module allows to use full power of `DerivativeStructure`
* Auto-differentiation expression in `kmath-commons` module allows using full power of `DerivativeStructure`
from commons-math. **TODO: add example**

View File

@ -1,14 +0,0 @@
# Features
* [Algebra](algebra.md) - [Context-based](contexts.md) operations on different primitives and structures.
* [NDStructures](nd-structure.md)
* [Linear algebra](linear.md) - Matrices, operations and linear equations solving. To be moved to separate module. Currently supports basic
api and multiple library back-ends.
* [Histograms](histograms.md) - Multidimensional histogram calculation and operations.
* [Expressions](expressions.md)
* Commons math integration

View File

@ -1,4 +1,9 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!--
- Copyright 2018-2021 KMath contributors.
- Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
-->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"

Before

Width:  |  Height:  |  Size: 248 KiB

After

Width:  |  Height:  |  Size: 249 KiB

View File

@ -1,4 +1,9 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!--
- Copyright 2018-2021 KMath contributors.
- Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
-->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"

Before

Width:  |  Height:  |  Size: 18 KiB

After

Width:  |  Height:  |  Size: 19 KiB

View File

@ -1,4 +1,9 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!--
- Copyright 2018-2021 KMath contributors.
- Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
-->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"

Before

Width:  |  Height:  |  Size: 278 KiB

After

Width:  |  Height:  |  Size: 278 KiB

View File

@ -1,4 +1,9 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!--
- Copyright 2018-2021 KMath contributors.
- Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
-->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"

Before

Width:  |  Height:  |  Size: 117 KiB

After

Width:  |  Height:  |  Size: 118 KiB

View File

@ -1,19 +1,31 @@
## Basic linear algebra layout
KMath support for linear algebra organized in a context-oriented way. Meaning that operations are in most cases declared
in context classes, and are not the members of classes that store data. This allows more flexible approach to maintain multiple
back-ends. The new operations added as extensions to contexts instead of being member functions of data structures.
KMath support for linear algebra organized in a context-oriented way, which means that operations are in most cases declared in context classes, and are not the members of classes that store data. This allows more flexible approach to maintain multiple back-ends. The new operations added as extensions to contexts instead of being member functions of data structures.
Two major contexts used for linear algebra and hyper-geometry:
The main context for linear algebra over matrices and vectors is `LinearSpace`, which defines addition and dot products of matrices and vectors:
* `VectorSpace` forms a mathematical space on top of array-like structure (`Buffer` and its type alias `Point` used for geometry).
```kotlin
import space.kscience.kmath.linear.*
* `MatrixContext` forms a space-like context for 2d-structures. It does not store matrix size and therefore does not implement
`Space` interface (it is impossible to create zero element without knowing the matrix size).
LinearSpace.Companion.real {
val vec = buildVector(10) { i -> i.toDouble() }
val mat = buildMatrix(10, 10) { i, j -> i.toDouble() + j }
## Vector spaces
// Addition
vec + vec
mat + mat
// Multiplication by scalar
vec * 2.0
mat * 2.0
## Matrix operations
// Dot product
mat dot vec
mat dot mat
}
```
## Back-end overview
## Backends overview
### EJML
### Commons Math

View File

@ -11,16 +11,16 @@ Let us consider following contexts:
```kotlin
// automatically build context most suited for given type.
val autoField = NDField.auto(DoubleField, dim, dim)
// specialized nd-field for Double. It works as generic Double field as well
// specialized nd-field for Double. It works as generic Double field as well.
val specializedField = NDField.real(dim, dim)
//A generic boxing field. It should be used for objects, not primitives.
val genericField = NDField.buffered(DoubleField, dim, dim)
```
Now let us perform several tests and see which implementation is best suited for each case:
Now let us perform several tests and see, which implementation is best suited for each case:
## Test case
In order to test performance we will take 2d-structures with `dim = 1000` and add a structure filled with `1.0`
To test performance we will take 2d-structures with `dim = 1000` and add a structure filled with `1.0`
to it `n = 1000` times.
## Specialized
@ -35,8 +35,8 @@ The code to run this looks like:
```
The performance of this code is the best of all tests since it inlines all operations and is specialized for operation
with doubles. We will measure everything else relative to this one, so time for this test will be `1x` (real time
on my computer is about 4.5 seconds). The only problem with this approach is that it requires to specify type
from the beginning. Everyone do so anyway, so it is the recommended approach.
on my computer is about 4.5 seconds). The only problem with this approach is that it requires specifying type
from the beginning. Everyone does so anyway, so it is the recommended approach.
## Automatic
Let's do the same with automatic field inference:
@ -49,7 +49,7 @@ Let's do the same with automatic field inference:
}
```
Ths speed of this operation is approximately the same as for specialized case since `NDField.auto` just
returns the same `RealNDField` in this case. Of course it is usually better to use specialized method to be sure.
returns the same `RealNDField` in this case. Of course, it is usually better to use specialized method to be sure.
## Lazy
Lazy field does not produce a structure when asked, instead it generates an empty structure and fills it on-demand
@ -63,7 +63,7 @@ When one calls
}
}
```
The result will be calculated almost immediately but the result will be empty. In order to get the full result
The result will be calculated almost immediately but the result will be empty. To get the full result
structure one needs to call all its elements. In this case computation overhead will be huge. So this field never
should be used if one expects to use the full result structure. Though if one wants only small fraction, it could
save a lot of time.
@ -94,7 +94,7 @@ The boxing field produced by
}
}
```
obviously is the slowest one, because it requires to box and unbox the `double` on each operation. It takes about
is the slowest one, because it requires boxing and unboxing the `double` on each operation. It takes about
`15x` time (**TODO: there seems to be a problem here, it should be slow, but not that slow**). This field should
never be used for primitives.
@ -115,12 +115,14 @@ via extension function.
Usually it is bad idea to compare the direct numerical operation performance in different languages, but it hard to
work completely without frame of reference. In this case, simple numpy code:
```python
import numpy as np
res = np.ones((1000,1000))
for i in range(1000):
res = res + 1.0
```
gives the completion time of about `1.1x`, which means that specialized kotlin code in fact is working faster (I think it is
because better memory management). Of course if one writes `res += 1.0`, the performance will be different,
but it would be differenc case, because numpy overrides `+=` with in-place operations. In-place operations are
but it would be different case, because numpy overrides `+=` with in-place operations. In-place operations are
available in `kmath` with `MutableNDStructure` but there is no field for it (one can still work with mapping
functions).

14
docs/readme.md Normal file
View File

@ -0,0 +1,14 @@
# Documentation
* [Algebra](algebra.md): [context-based](contexts.md) operations on different primitives and structures.
* [NDStructures](nd-structure.md)
* [Linear algebra](linear.md): matrices, operations and linear equations solving. To be moved to separate module.
Currently, supports basic API and multiple library back-ends.
* [Histograms](histograms.md): multidimensional histogram calculation and operations.
* [Expressions](expressions.md)
* Commons math integration

View File

@ -6,10 +6,10 @@
# KMath
Could be pronounced as `key-math`. The **K**otlin **Math**ematics library was initially intended as a Kotlin-based analog to
Python's NumPy library. Later we found that kotlin is much more flexible language and allows superior architecture
designs. In contrast to `numpy` and `scipy` it is modular and has a lightweight core. The `numpy`-like experience could
be achieved with [kmath-for-real](/kmath-for-real) extension module.
Could be pronounced as `key-math`. The **K**otlin **Math**ematics library was initially intended as a Kotlin-based
analog to Python's NumPy library. Later we found that kotlin is much more flexible language and allows superior
architecture designs. In contrast to `numpy` and `scipy` it is modular and has a lightweight core. The `numpy`-like
experience could be achieved with [kmath-for-real](/kmath-for-real) extension module.
[Documentation site (**WIP**)](https://mipt-npm.github.io/kmath/)
@ -21,26 +21,33 @@ be achieved with [kmath-for-real](/kmath-for-real) extension module.
# Goal
* Provide a flexible and powerful API to work with mathematics abstractions in Kotlin-multiplatform (JVM, JS and Native).
* Provide a flexible and powerful API to work with mathematics abstractions in Kotlin-multiplatform (JVM, JS and Native)
.
* Provide basic multiplatform implementations for those abstractions (without significant performance optimization).
* Provide bindings and wrappers with those abstractions for popular optimized platform libraries.
## Non-goals
* Be like NumPy. It was the idea at the beginning, but we decided that we can do better in terms of API.
* Be like NumPy. It was the idea at the beginning, but we decided that we can do better in API.
* Provide the best performance out of the box. We have specialized libraries for that. Need only API wrappers for them.
* Cover all cases as immediately and in one bundle. We will modularize everything and add new features gradually.
* Provide specialized behavior in the core. API is made generic on purpose, so one needs to specialize for types, like
for `Double` in the core. For that we will have specialization modules like `kmath-for-real`, which will give better
experience for those, who want to work with specific types.
* Provide specialized behavior in the core. API is made generic on purpose, so one needs to specialize for types, like
for `Double` in the core. For that we will have specialization modules like `kmath-for-real`, which will give better
experience for those, who want to work with specific types.
## Features and stability
KMath is a modular library. Different modules provide different features with different API stability guarantees. All core modules are released with the same version, but with different API change policy. The features are described in module definitions below. The module stability could have following levels:
KMath is a modular library. Different modules provide different features with different API stability guarantees. All
core modules are released with the same version, but with different API change policy. The features are described in
module definitions below. The module stability could have the following levels:
* **PROTOTYPE**. On this level there are no compatibility guarantees. All methods and classes form those modules could break any moment. You can still use it, but be sure to fix the specific version.
* **EXPERIMENTAL**. The general API is decided, but some changes could be made. Volatile API is marked with `@UnstableKmathAPI` or other stability warning annotations.
* **DEVELOPMENT**. API breaking generally follows semantic versioning ideology. There could be changes in minor versions, but not in patch versions. API is protected with [binary-compatibility-validator](https://github.com/Kotlin/binary-compatibility-validator) tool.
* **PROTOTYPE**. On this level there are no compatibility guarantees. All methods and classes form those modules could
break any moment. You can still use it, but be sure to fix the specific version.
* **EXPERIMENTAL**. The general API is decided, but some changes could be made. Volatile API is marked
with `@UnstableKmathAPI` or other stability warning annotations.
* **DEVELOPMENT**. API breaking generally follows semantic versioning ideology. There could be changes in minor
versions, but not in patch versions. API is protected
with [binary-compatibility-validator](https://github.com/Kotlin/binary-compatibility-validator) tool.
* **STABLE**. The API stabilized. Breaking changes are allowed only in major releases.
<!--Current feature list is [here](/docs/features.md)-->
@ -78,30 +85,33 @@ $modules
## Multi-platform support
KMath is developed as a multi-platform library, which means that most of the interfaces are declared in the
[common source sets](/kmath-core/src/commonMain) and implemented there wherever it is possible. In some cases, features
are delegated to platform-specific implementations even if they could be provided in the common module for performance
reasons. Currently, the Kotlin/JVM is the primary platform, however Kotlin/Native and Kotlin/JS contributions and
KMath is developed as a multi-platform library, which means that most of the interfaces are declared in the
[common source sets](/kmath-core/src/commonMain) and implemented there wherever it is possible. In some cases, features
are delegated to platform-specific implementations even if they could be provided in the common module for performance
reasons. Currently, the Kotlin/JVM is the primary platform, however Kotlin/Native and Kotlin/JS contributions and
feedback are also welcome.
## Performance
Calculation performance is one of major goals of KMath in the future, but in some cases it is impossible to achieve
both performance and flexibility.
Calculation performance is one of major goals of KMath in the future, but in some cases it is impossible to achieve both
performance and flexibility.
We expect to focus on creating convenient universal API first and then work on increasing performance for specific
cases. We expect the worst KMath benchmarks will perform better than native Python, but worse than optimized
native/SciPy (mostly due to boxing operations on primitive numbers). The best performance of optimized parts could be
We expect to focus on creating convenient universal API first and then work on increasing performance for specific
cases. We expect the worst KMath benchmarks will perform better than native Python, but worse than optimized
native/SciPy (mostly due to boxing operations on primitive numbers). The best performance of optimized parts could be
better than SciPy.
## Requirements
KMath currently relies on JDK 11 for compilation and execution of Kotlin-JVM part. We recommend to use GraalVM-CE 11 for execution in order to get better performance.
KMath currently relies on JDK 11 for compilation and execution of Kotlin-JVM part. We recommend to use GraalVM-CE 11 for
execution to get better performance.
### Repositories
Release and development artifacts are accessible from mipt-npm [Space](https://www.jetbrains.com/space/) repository `https://maven.pkg.jetbrains.space/mipt-npm/p/sci/maven` (see documentation of
[Kotlin Multiplatform](https://kotlinlang.org/docs/reference/multiplatform.html) for more details). The repository could be reached through [repo.kotlin.link](https://repo.kotlin.link) proxy:
Release and development artifacts are accessible from mipt-npm [Space](https://www.jetbrains.com/space/)
repository `https://maven.pkg.jetbrains.space/mipt-npm/p/sci/maven` (see documentation of
[Kotlin Multiplatform](https://kotlinlang.org/docs/reference/multiplatform.html) for more details). The repository could
be reached through [repo.kotlin.link](https://repo.kotlin.link) proxy:
```kotlin
repositories {
@ -118,7 +128,7 @@ Gradle `6.0+` is required for multiplatform artifacts.
## Contributing
The project requires a lot of additional work. The most important thing we need is a feedback about what features are
required the most. Feel free to create feature requests. We are also welcome to code contributions,
especially in issues marked with
The project requires a lot of additional work. The most important thing we need is a feedback about what features are
required the most. Feel free to create feature requests. We are also welcome to code contributions, especially in issues
marked with
[waiting for a hero](https://github.com/mipt-npm/kmath/labels/waiting%20for%20a%20hero) label.

View File

@ -20,6 +20,7 @@ dependencies {
implementation(project(":kmath-coroutines"))
implementation(project(":kmath-commons"))
implementation(project(":kmath-complex"))
implementation(project(":kmath-optimization"))
implementation(project(":kmath-stat"))
implementation(project(":kmath-viktor"))
implementation(project(":kmath-dimensions"))
@ -28,6 +29,11 @@ dependencies {
implementation(project(":kmath-tensors"))
implementation(project(":kmath-symja"))
implementation(project(":kmath-for-real"))
//jafama
implementation(project(":kmath-jafama"))
//multik
implementation(projects.kmathMultik)
implementation("org.nd4j:nd4j-native:1.0.0-beta7")
@ -41,11 +47,12 @@ dependencies {
// } else
implementation("org.nd4j:nd4j-native-platform:1.0.0-beta7")
implementation("org.slf4j:slf4j-simple:1.7.30")
// multik implementation
implementation("org.jetbrains.kotlinx:multik-default:0.1.0")
implementation("org.slf4j:slf4j-simple:1.7.32")
// plotting
implementation("space.kscience:plotlykt-server:0.4.0")
//jafama
implementation(project(":kmath-jafama"))
implementation("space.kscience:plotlykt-server:0.5.0")
}
kotlin.sourceSets.all {

View File

@ -1,6 +1,6 @@
/*
* Copyright 2018-2021 KMath contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
* Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
*/
package space.kscience.kmath.ast
@ -10,7 +10,7 @@ import space.kscience.kmath.ast.rendering.LatexSyntaxRenderer
import space.kscience.kmath.ast.rendering.MathMLSyntaxRenderer
import space.kscience.kmath.ast.rendering.renderWithStringBuilder
public fun main() {
fun main() {
val mst = "exp(sqrt(x))-asin(2*x)/(2e10+x^3)/(-12)".parseMath()
val syntax = FeaturedMathRendererWithPostProcess.Default.render(mst)
println("MathSyntax:")

View File

@ -1,6 +1,6 @@
/*
* Copyright 2018-2021 KMath contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
* Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
*/
package space.kscience.kmath.ast

View File

@ -1,6 +1,6 @@
/*
* Copyright 2018-2021 KMath contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
* Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
*/
package space.kscience.kmath.ast
@ -13,8 +13,8 @@ import space.kscience.kmath.kotlingrad.toKotlingradExpression
import space.kscience.kmath.operations.DoubleField
/**
* In this example, x^2-4*x-44 function is differentiated with Kotlin, and the autodiff result is compared with
* valid derivative in a certain point.
* In this example, *x<sup>2</sup> &minus; 4 x &minus; 44* function is differentiated with Kotlin, and the
* derivation result is compared with valid derivative in a certain point.
*/
fun main() {
val actualDerivative = "x^2-4*x-44"

View File

@ -1,6 +1,6 @@
/*
* Copyright 2018-2021 KMath contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
* Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
*/
package space.kscience.kmath.ast
@ -13,8 +13,8 @@ import space.kscience.kmath.operations.DoubleField
import space.kscience.kmath.symja.toSymjaExpression
/**
* In this example, x^2-4*x-44 function is differentiated with Symja, and the autodiff result is compared with
* valid derivative in a certain point.
* In this example, *x<sup>2</sup> &minus; 4 x &minus; 44* function is differentiated with Symja, and the
* derivation result is compared with valid derivative in a certain point.
*/
fun main() {
val actualDerivative = "x^2-4*x-44"

View File

@ -1,32 +1,34 @@
/*
* Copyright 2018-2021 KMath contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
* Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
*/
package space.kscience.kmath.commons.fit
package space.kscience.kmath.fit
import kotlinx.html.br
import kotlinx.html.h3
import space.kscience.kmath.commons.optimization.chiSquared
import space.kscience.kmath.commons.optimization.minimize
import space.kscience.kmath.commons.expressions.DSProcessor
import space.kscience.kmath.commons.optimization.CMOptimizer
import space.kscience.kmath.distributions.NormalDistribution
import space.kscience.kmath.expressions.chiSquaredExpression
import space.kscience.kmath.expressions.symbol
import space.kscience.kmath.optimization.FunctionOptimization
import space.kscience.kmath.optimization.OptimizationResult
import space.kscience.kmath.operations.asIterable
import space.kscience.kmath.operations.toList
import space.kscience.kmath.optimization.FunctionOptimizationTarget
import space.kscience.kmath.optimization.optimizeWith
import space.kscience.kmath.optimization.resultPoint
import space.kscience.kmath.optimization.resultValue
import space.kscience.kmath.real.DoubleVector
import space.kscience.kmath.real.map
import space.kscience.kmath.real.step
import space.kscience.kmath.stat.RandomGenerator
import space.kscience.kmath.structures.asIterable
import space.kscience.kmath.structures.toList
import space.kscience.plotly.*
import space.kscience.plotly.models.ScatterMode
import space.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
// Forward declaration of symbols that will be used in expressions.
private val a by symbol
private val b by symbol
private val c by symbol
@ -43,7 +45,7 @@ operator fun TraceValues.invoke(vector: DoubleVector) {
*/
suspend fun main() {
//A generator for a normally distributed values
val generator = NormalDistribution(2.0, 7.0)
val generator = NormalDistribution(0.0, 1.0)
//A chain/flow of random values with the given seed
val chain = generator.sample(RandomGenerator.default(112667))
@ -54,7 +56,7 @@ suspend fun main() {
//Perform an operation on each x value (much more effective, than numpy)
val y = x.map {
val y = x.map { it ->
val value = it.pow(2) + it + 1
value + chain.next() * sqrt(value)
}
@ -65,17 +67,21 @@ suspend fun main() {
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 = FunctionOptimization.chiSquared(x, y, yErr) { x1 ->
val chi2 = DSProcessor.chiSquaredExpression(x, y, yErr) { arg ->
//bind variables to autodiff context
val a = bindSymbol(a)
val b = bindSymbol(b)
//Include default value for c if it is not provided as a parameter
val c = bindSymbolOrNull(c) ?: one
a * x1.pow(2) + b * x1 + c
a * arg.pow(2) + b * arg + 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 result = chi2.optimizeWith(
CMOptimizer,
mapOf(a to 1.5, b to 0.9, c to 1.0),
FunctionOptimizationTarget.MINIMIZE
)
//display a page with plot and numerical results
val page = Plotly.page {
@ -92,7 +98,7 @@ suspend fun main() {
scatter {
mode = ScatterMode.lines
x(x)
y(x.map { result.point[a]!! * it.pow(2) + result.point[b]!! * it + 1 })
y(x.map { result.resultPoint[a]!! * it.pow(2) + result.resultPoint[b]!! * it + 1 })
name = "fit"
}
}
@ -101,7 +107,7 @@ suspend fun main() {
+"Fit result: $result"
}
h3 {
+"Chi2/dof = ${result.value / (x.size - 3)}"
+"Chi2/dof = ${result.resultValue / (x.size - 3)}"
}
}

View File

@ -0,0 +1,106 @@
/*
* Copyright 2018-2021 KMath contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package space.kscience.kmath.fit
import kotlinx.html.br
import kotlinx.html.h3
import space.kscience.kmath.commons.expressions.DSProcessor
import space.kscience.kmath.data.XYErrorColumnarData
import space.kscience.kmath.distributions.NormalDistribution
import space.kscience.kmath.expressions.Symbol
import space.kscience.kmath.expressions.binding
import space.kscience.kmath.expressions.symbol
import space.kscience.kmath.operations.asIterable
import space.kscience.kmath.operations.toList
import space.kscience.kmath.optimization.QowOptimizer
import space.kscience.kmath.optimization.chiSquaredOrNull
import space.kscience.kmath.optimization.fitWith
import space.kscience.kmath.optimization.resultPoint
import space.kscience.kmath.real.map
import space.kscience.kmath.real.step
import space.kscience.kmath.stat.RandomGenerator
import space.kscience.plotly.*
import space.kscience.plotly.models.ScatterMode
import kotlin.math.abs
import kotlin.math.pow
import kotlin.math.sqrt
// Forward declaration of symbols that will be used in expressions.
private val a by symbol
private val b by symbol
private val c by symbol
/**
* Least squares fie with auto-differentiation. Uses `kmath-commons` and `kmath-for-real` modules.
*/
suspend fun main() {
//A generator for a normally distributed values
val generator = NormalDistribution(0.0, 1.0)
//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 { it ->
val value = it.pow(2) + it + 1
value + chain.next() * 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(abs(it)) }
require(yErr.asIterable().all { it > 0 }) { "All errors must be strictly positive" }
val result = XYErrorColumnarData.of(x, y, yErr).fitWith(
QowOptimizer,
DSProcessor,
mapOf(a to 0.9, b to 1.2, c to 2.0)
) { arg ->
//bind variables to autodiff context
val a by binding
val b by binding
//Include default value for c if it is not provided as a parameter
val c = bindSymbolOrNull(c) ?: one
a * arg.pow(2) + b * arg + c
}
//display a page with plot and numerical results
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.model(result.resultPoint + (Symbol.x to it)) })
name = "fit"
}
}
br()
h3 {
+"Fit result: ${result.resultPoint}"
}
h3 {
+"Chi2/dof = ${result.chiSquaredOrNull!! / (x.size - 3)}"
}
}
page.makeFile()
}

View File

@ -1,6 +1,6 @@
/*
* Copyright 2018-2021 KMath contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
* Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
*/
package space.kscience.kmath.functions

View File

@ -1,6 +1,6 @@
/*
* Copyright 2018-2021 KMath contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
* Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
*/
package space.kscience.kmath.functions

View File

@ -1,6 +1,6 @@
/*
* Copyright 2018-2021 KMath contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
* Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
*/
package space.kscience.kmath.functions
@ -8,8 +8,8 @@ package space.kscience.kmath.functions
import space.kscience.kmath.interpolation.SplineInterpolator
import space.kscience.kmath.interpolation.interpolatePolynomials
import space.kscience.kmath.operations.DoubleField
import space.kscience.kmath.real.map
import space.kscience.kmath.real.step
import space.kscience.kmath.structures.map
import space.kscience.plotly.Plotly
import space.kscience.plotly.UnstablePlotlyAPI
import space.kscience.plotly.makeFile

View File

@ -1,6 +1,6 @@
/*
* Copyright 2018-2021 KMath contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
* Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
*/
package space.kscience.kmath.functions
@ -9,20 +9,21 @@ import space.kscience.kmath.integration.gaussIntegrator
import space.kscience.kmath.integration.integrate
import space.kscience.kmath.integration.value
import space.kscience.kmath.nd.StructureND
import space.kscience.kmath.nd.nd
import space.kscience.kmath.operations.DoubleField
import space.kscience.kmath.nd.structureND
import space.kscience.kmath.nd.withNdAlgebra
import space.kscience.kmath.operations.algebra
import space.kscience.kmath.operations.invoke
fun main(): Unit = DoubleField {
nd(2, 2) {
fun main(): Unit = Double.algebra {
withNdAlgebra(2, 2) {
//Produce a diagonal StructureND
fun diagonal(v: Double) = produce { (i, j) ->
fun diagonal(v: Double) = structureND { (i, j) ->
if (i == j) v else 0.0
}
//Define a function in a nd space
val function: (Double) -> StructureND<Double> = { x: Double -> 3 * number(x).pow(2) + 2 * diagonal(x) + 1 }
val function: (Double) -> StructureND<Double> = { x: Double -> 3 * x.pow(2) + 2 * diagonal(x) + 1 }
//get the result of the integration
val result = gaussIntegrator.integrate(0.0..10.0, function = function)

View File

@ -0,0 +1,15 @@
/*
* Copyright 2018-2021 KMath contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
*/
package space.kscience.kmath.jafama
import space.kscience.kmath.operations.invoke
fun main() {
val a = 2.0
val b = StrictJafamaDoubleField { exp(a) }
println(JafamaDoubleField { b + a })
println(StrictJafamaDoubleField { ln(b) })
}

View File

@ -1,17 +0,0 @@
/*
* Copyright 2018-2021 KMath contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package space.kscience.kmath.jafama
import net.jafama.FastMath
fun main(){
val a = JafamaDoubleField.number(2.0)
val b = StrictJafamaDoubleField.power(FastMath.E,a)
println(JafamaDoubleField.add(b,a))
println(StrictJafamaDoubleField.ln(b))
}

View File

@ -0,0 +1,34 @@
/*
* Copyright 2018-2021 KMath contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
*/
package space.kscience.kmath.linear
import space.kscience.kmath.operations.algebra
import kotlin.random.Random
import kotlin.system.measureTimeMillis
fun main() {
val random = Random(12224)
val dim = 1000
//creating invertible matrix
val matrix1 = Double.algebra.linearSpace.buildMatrix(dim, dim) { i, j ->
if (i <= j) random.nextDouble() else 0.0
}
val matrix2 = Double.algebra.linearSpace.buildMatrix(dim, dim) { i, j ->
if (i <= j) random.nextDouble() else 0.0
}
val time = measureTimeMillis {
with(Double.algebra.linearSpace) {
repeat(10) {
matrix1 dot matrix2
}
}
}
println(time)
}

View File

@ -1,6 +1,6 @@
/*
* Copyright 2018-2021 KMath contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
* Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
*/
package space.kscience.kmath.linear

View File

@ -1,6 +1,6 @@
/*
* Copyright 2018-2021 KMath contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
* Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
*/
package space.kscience.kmath.operations

View File

@ -1,29 +0,0 @@
/*
* Copyright 2018-2021 KMath contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package space.kscience.kmath.operations
import space.kscience.kmath.complex.Complex
import space.kscience.kmath.complex.complex
import space.kscience.kmath.nd.AlgebraND
fun main() {
// 2d element
val element = AlgebraND.complex(2, 2).produce { (i, j) ->
Complex(i.toDouble() - j.toDouble(), i.toDouble() + j.toDouble())
}
println(element)
// 1d element operation
val result = with(AlgebraND.complex(8)) {
val a = produce { (it) -> i * it - it.toDouble() }
val b = 3
val c = Complex(1.0, 1.0)
(a pow b) + c
}
println(result)
}

View File

@ -0,0 +1,41 @@
/*
* Copyright 2018-2021 KMath contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
*/
package space.kscience.kmath.operations
import space.kscience.kmath.complex.Complex
import space.kscience.kmath.complex.algebra
import space.kscience.kmath.complex.bufferAlgebra
import space.kscience.kmath.complex.ndAlgebra
import space.kscience.kmath.nd.BufferND
import space.kscience.kmath.nd.StructureND
import space.kscience.kmath.nd.structureND
fun main() = Complex.algebra {
val complex = 2 + 2 * i
println(complex * 8 - 5 * i)
//flat buffer
val buffer = with(bufferAlgebra){
buffer(8) { Complex(it, -it) }.map { Complex(it.im, it.re) }
}
println(buffer)
// 2d element
val element: BufferND<Complex> = ndAlgebra.structureND(2, 2) { (i, j) ->
Complex(i - j, i + j)
}
println(element)
// 1d element operation
val result: StructureND<Complex> = ndAlgebra{
val a = structureND(8) { (it) -> i * it - it.toDouble() }
val b = 3
val c = Complex(1.0, 1.0)
(a pow b) + c
}
println(result)
}

View File

@ -0,0 +1,24 @@
package space.kscience.kmath.operations
import space.kscience.kmath.commons.linear.CMLinearSpace
import space.kscience.kmath.linear.matrix
import space.kscience.kmath.nd.DoubleBufferND
import space.kscience.kmath.nd.Shape
import space.kscience.kmath.nd.Structure2D
import space.kscience.kmath.nd.ndAlgebra
import space.kscience.kmath.viktor.ViktorStructureND
import space.kscience.kmath.viktor.viktorAlgebra
fun main() {
val viktorStructure: ViktorStructureND = DoubleField.viktorAlgebra.structureND(Shape(2, 2)) { (i, j) ->
if (i == j) 2.0 else 0.0
}
val cmMatrix: Structure2D<Double> = CMLinearSpace.matrix(2, 2)(0.0, 1.0, 0.0, 3.0)
val res: DoubleBufferND = DoubleField.ndAlgebra {
exp(viktorStructure) + 2.0 * cmMatrix
}
println(res)
}

View File

@ -1,6 +1,6 @@
/*
* Copyright 2018-2021 KMath contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
* Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
*/
package space.kscience.kmath.stat

View File

@ -1,6 +1,6 @@
/*
* Copyright 2018-2021 KMath contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
* Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
*/
package space.kscience.kmath.stat
@ -10,9 +10,6 @@ import space.kscience.kmath.chains.Chain
import space.kscience.kmath.chains.collectWithState
import space.kscience.kmath.distributions.NormalDistribution
/**
* The state of distribution averager.
*/
private data class AveragingChainState(var num: Int = 0, var value: Double = 0.0)
/**

View File

@ -1,6 +1,6 @@
/*
* Copyright 2018-2021 KMath contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
* Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
*/
@file:Suppress("unused")
@ -9,10 +9,11 @@ package space.kscience.kmath.structures
import space.kscience.kmath.complex.*
import space.kscience.kmath.linear.transpose
import space.kscience.kmath.nd.AlgebraND
import space.kscience.kmath.nd.StructureND
import space.kscience.kmath.nd.as2D
import space.kscience.kmath.nd.real
import space.kscience.kmath.nd.ndAlgebra
import space.kscience.kmath.nd.structureND
import space.kscience.kmath.operations.DoubleField
import space.kscience.kmath.operations.invoke
import kotlin.system.measureTimeMillis
@ -20,8 +21,8 @@ fun main() {
val dim = 1000
val n = 1000
val realField = AlgebraND.real(dim, dim)
val complexField: ComplexFieldND = AlgebraND.complex(dim, dim)
val realField = DoubleField.ndAlgebra(dim, dim)
val complexField: ComplexFieldND = ComplexField.ndAlgebra(dim, dim)
val realTime = measureTimeMillis {
realField {
@ -49,12 +50,12 @@ fun main() {
fun complexExample() {
//Create a context for 2-d structure with complex values
ComplexField {
nd(4, 8) {
withNdAlgebra(4, 8) {
//a constant real-valued structure
val x = one * 2.5
operator fun Number.plus(other: Complex) = Complex(this.toDouble() + other.re, other.im)
//a structure generator specific to this context
val matrix = produce { (k, l) -> k + l * i }
val matrix = structureND { (k, l) -> k + l * i }
//Perform sum
val sum = matrix + x + 1.0

View File

@ -1,6 +1,6 @@
/*
* Copyright 2018-2021 KMath contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
* Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
*/
package space.kscience.kmath.structures
@ -9,10 +9,10 @@ import kotlinx.coroutines.DelicateCoroutinesApi
import kotlinx.coroutines.GlobalScope
import org.nd4j.linalg.factory.Nd4j
import space.kscience.kmath.nd.*
import space.kscience.kmath.nd4j.Nd4jArrayField
import space.kscience.kmath.nd4j.nd4j
import space.kscience.kmath.operations.DoubleField
import space.kscience.kmath.operations.invoke
import space.kscience.kmath.viktor.ViktorNDField
import space.kscience.kmath.viktor.ViktorFieldND
import kotlin.contracts.InvocationKind
import kotlin.contracts.contract
import kotlin.system.measureTimeMillis
@ -29,37 +29,39 @@ fun main() {
Nd4j.zeros(0)
val dim = 1000
val n = 1000
val shape = Shape(dim, dim)
// automatically build context most suited for given type.
val autoField = AlgebraND.auto(DoubleField, dim, dim)
// specialized nd-field for Double. It works as generic Double field as well
val realField = AlgebraND.real(dim, dim)
val autoField = BufferedFieldOpsND(DoubleField, Buffer.Companion::auto)
// specialized nd-field for Double. It works as generic Double field as well.
val realField = DoubleField.ndAlgebra
//A generic boxing field. It should be used for objects, not primitives.
val boxingField = AlgebraND.field(DoubleField, Buffer.Companion::boxing, dim, dim)
val boxingField = BufferedFieldOpsND(DoubleField, Buffer.Companion::boxing)
// Nd4j specialized field.
val nd4jField = Nd4jArrayField.real(dim, dim)
val nd4jField = DoubleField.nd4j
//viktor field
val viktorField = ViktorNDField(dim, dim)
val viktorField = ViktorFieldND(dim, dim)
//parallel processing based on Java Streams
val parallelField = AlgebraND.realWithStream(dim, dim)
val parallelField = DoubleField.ndStreaming(dim, dim)
measureAndPrint("Boxing addition") {
boxingField {
var res: StructureND<Double> = one
var res: StructureND<Double> = one(shape)
repeat(n) { res += 1.0 }
}
}
measureAndPrint("Specialized addition") {
realField {
var res: StructureND<Double> = one
var res: StructureND<Double> = one(shape)
repeat(n) { res += 1.0 }
}
}
measureAndPrint("Nd4j specialized addition") {
nd4jField {
var res: StructureND<Double> = one
var res: StructureND<Double> = one(shape)
repeat(n) { res += 1.0 }
}
}
@ -80,13 +82,13 @@ fun main() {
measureAndPrint("Automatic field addition") {
autoField {
var res: StructureND<Double> = one
var res: StructureND<Double> = one(shape)
repeat(n) { res += 1.0 }
}
}
measureAndPrint("Lazy addition") {
val res = realField.one.mapAsync(GlobalScope) {
val res = realField.one(shape).mapAsync(GlobalScope) {
var c = 0.0
repeat(n) {
c += 1.0

View File

@ -1,6 +1,6 @@
/*
* Copyright 2018-2021 KMath contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
* Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
*/
package space.kscience.kmath.structures
@ -8,7 +8,7 @@ package space.kscience.kmath.structures
import space.kscience.kmath.nd.*
import space.kscience.kmath.operations.DoubleField
import space.kscience.kmath.operations.ExtendedField
import space.kscience.kmath.operations.NumbersAddOperations
import space.kscience.kmath.operations.NumbersAddOps
import java.util.*
import java.util.stream.IntStream
@ -17,17 +17,17 @@ import java.util.stream.IntStream
* execution.
*/
class StreamDoubleFieldND(override val shape: IntArray) : FieldND<Double, DoubleField>,
NumbersAddOperations<StructureND<Double>>,
NumbersAddOps<StructureND<Double>>,
ExtendedField<StructureND<Double>> {
private val strides = DefaultStrides(shape)
override val elementContext: DoubleField get() = DoubleField
override val zero: BufferND<Double> by lazy { produce { zero } }
override val one: BufferND<Double> by lazy { produce { one } }
override val elementAlgebra: DoubleField get() = DoubleField
override val zero: BufferND<Double> by lazy { structureND(shape) { zero } }
override val one: BufferND<Double> by lazy { structureND(shape) { one } }
override fun number(value: Number): BufferND<Double> {
val d = value.toDouble() // minimize conversions
return produce { d }
return structureND(shape) { d }
}
private val StructureND<Double>.buffer: DoubleBuffer
@ -36,11 +36,11 @@ class StreamDoubleFieldND(override val shape: IntArray) : FieldND<Double, Double
this@StreamDoubleFieldND.shape,
shape
)
this is BufferND && this.strides == this@StreamDoubleFieldND.strides -> this.buffer as DoubleBuffer
this is BufferND && this.indices == this@StreamDoubleFieldND.strides -> this.buffer as DoubleBuffer
else -> DoubleBuffer(strides.linearSize) { offset -> get(strides.index(offset)) }
}
override fun produce(initializer: DoubleField.(IntArray) -> Double): BufferND<Double> {
override fun structureND(shape: Shape, initializer: DoubleField.(IntArray) -> Double): BufferND<Double> {
val array = IntStream.range(0, strides.linearSize).parallel().mapToDouble { offset ->
val index = strides.index(offset)
DoubleField.initializer(index)
@ -69,13 +69,13 @@ class StreamDoubleFieldND(override val shape: IntArray) : FieldND<Double, Double
return BufferND(strides, array.asBuffer())
}
override fun combine(
a: StructureND<Double>,
b: StructureND<Double>,
override fun zip(
left: StructureND<Double>,
right: StructureND<Double>,
transform: DoubleField.(Double, Double) -> Double,
): BufferND<Double> {
val array = IntStream.range(0, strides.linearSize).parallel().mapToDouble { offset ->
DoubleField.transform(a.buffer.array[offset], b.buffer.array[offset])
DoubleField.transform(left.buffer.array[offset], right.buffer.array[offset])
}.toArray()
return BufferND(strides, array.asBuffer())
}
@ -105,4 +105,4 @@ class StreamDoubleFieldND(override val shape: IntArray) : FieldND<Double, Double
override fun atanh(arg: StructureND<Double>): BufferND<Double> = arg.map { atanh(it) }
}
fun AlgebraND.Companion.realWithStream(vararg shape: Int): StreamDoubleFieldND = StreamDoubleFieldND(shape)
fun DoubleField.ndStreaming(vararg shape: Int): StreamDoubleFieldND = StreamDoubleFieldND(shape)

View File

@ -1,6 +1,6 @@
/*
* Copyright 2018-2021 KMath contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
* Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
*/
package space.kscience.kmath.structures
@ -19,24 +19,24 @@ fun main() {
measureTimeMillis {
var res = 0.0
strides.indices().forEach { res = structure[it] }
strides.asSequence().forEach { res = structure[it] }
} // warmup
val time1 = measureTimeMillis {
var res = 0.0
strides.indices().forEach { res = structure[it] }
strides.asSequence().forEach { res = structure[it] }
}
println("Structure reading finished in $time1 millis")
val time2 = measureTimeMillis {
var res = 0.0
strides.indices().forEach { res = buffer[strides.offset(it)] }
strides.asSequence().forEach { res = buffer[strides.offset(it)] }
}
println("Buffer reading finished in $time2 millis")
val time3 = measureTimeMillis {
var res = 0.0
strides.indices().forEach { res = array[strides.offset(it)] }
strides.asSequence().forEach { res = array[strides.offset(it)] }
}
println("Array reading finished in $time3 millis")
}

View File

@ -1,6 +1,6 @@
/*
* Copyright 2018-2021 KMath contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
* Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
*/
package space.kscience.kmath.structures

View File

@ -0,0 +1,23 @@
/*
* Copyright 2018-2021 KMath contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package space.kscience.kmath.structures
import space.kscience.kmath.operations.DoubleField
import space.kscience.kmath.operations.buffer
import space.kscience.kmath.operations.bufferAlgebra
import space.kscience.kmath.operations.withSize
inline fun <reified R : Any> MutableBuffer.Companion.same(
n: Int,
value: R
): MutableBuffer<R> = auto(n) { value }
fun main() {
with(DoubleField.bufferAlgebra.withSize(5)) {
println(number(2.0) + buffer(1, 2, 3, 4, 5))
}
}

View File

@ -1,6 +1,6 @@
/*
* Copyright 2018-2021 KMath contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
* Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
*/
package space.kscience.kmath.structures
@ -19,7 +19,7 @@ private fun DMatrixContext<Double, *>.simple() {
}
private object D5 : Dimension {
override val dim: UInt = 5u
override val dim: Int = 5
}
private fun DMatrixContext<Double, *>.custom() {

View File

@ -1,6 +1,6 @@
/*
* Copyright 2018-2021 KMath contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
* Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
*/
package space.kscience.kmath.tensors

View File

@ -1,23 +1,23 @@
/*
* Copyright 2018-2021 KMath contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
* Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
*/
package space.kscience.kmath.tensors
import space.kscience.kmath.operations.invoke
import space.kscience.kmath.tensors.core.BroadcastDoubleTensorAlgebra
import space.kscience.kmath.tensors.core.tensorAlgebra
import space.kscience.kmath.tensors.core.withBroadcast
// simple PCA
fun main(): Unit = BroadcastDoubleTensorAlgebra { // work in context with broadcast methods
fun main(): Unit = Double.tensorAlgebra.withBroadcast { // work in context with broadcast methods
val seed = 100500L
// assume x is range from 0 until 10
val x = fromArray(
intArrayOf(10),
(0 until 10).toList().map { it.toDouble() }.toDoubleArray()
DoubleArray(10) { it.toDouble() }
)
// take y dependent on x with noise
@ -62,11 +62,11 @@ fun main(): Unit = BroadcastDoubleTensorAlgebra { // work in context with broad
println("Eigenvector:\n$v")
// reduce dimension of dataset
val datasetReduced = v dot stack(listOf(xScaled, yScaled))
val datasetReduced = v dot stack(listOf(xScaled, yScaled))
println("Reduced data:\n$datasetReduced")
// we can restore original data from reduced data.
// for example, find 7th element of dataset
// we can restore original data from reduced data;
// for example, find 7th element of dataset.
val n = 7
val restored = (datasetReduced[n] dot v.view(intArrayOf(1, 2))) * std + mean
println("Original value:\n${dataset[n]}")

View File

@ -1,23 +1,23 @@
/*
* Copyright 2018-2021 KMath contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
* Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
*/
package space.kscience.kmath.tensors
import space.kscience.kmath.operations.invoke
import space.kscience.kmath.tensors.core.BroadcastDoubleTensorAlgebra
import space.kscience.kmath.tensors.core.tensorAlgebra
import space.kscience.kmath.tensors.core.withBroadcast
// Dataset normalization
fun main() = BroadcastDoubleTensorAlgebra { // work in context with broadcast methods
fun main() = Double.tensorAlgebra.withBroadcast { // work in context with broadcast methods
// take dataset of 5-element vectors from normal distribution
val dataset = randomNormal(intArrayOf(100, 5)) * 1.5 // all elements from N(0, 1.5)
dataset += fromArray(
intArrayOf(5),
doubleArrayOf(0.0, 1.0, 1.5, 3.0, 5.0) // rows means
doubleArrayOf(0.0, 1.0, 1.5, 3.0, 5.0) // row means
)
@ -28,7 +28,7 @@ fun main() = BroadcastDoubleTensorAlgebra { // work in context with broadcast m
println("Mean:\n$mean")
println("Standard deviation:\n$std")
// also we can calculate other statistic as minimum and maximum of rows
// also, we can calculate other statistic as minimum and maximum of rows
println("Minimum:\n${dataset.min(0, false)}")
println("Maximum:\n${dataset.max(0, false)}")

View File

@ -1,17 +1,17 @@
/*
* Copyright 2018-2021 KMath contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
* Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
*/
package space.kscience.kmath.tensors
import space.kscience.kmath.operations.invoke
import space.kscience.kmath.tensors.core.BroadcastDoubleTensorAlgebra
import space.kscience.kmath.tensors.core.DoubleTensor
import space.kscience.kmath.tensors.core.tensorAlgebra
import space.kscience.kmath.tensors.core.withBroadcast
// solving linear system with LUP decomposition
fun main() = BroadcastDoubleTensorAlgebra {// work in context with linear operations
fun main() = Double.tensorAlgebra.withBroadcast {// work in context with linear operations
// set true value of x
val trueX = fromArray(
@ -42,7 +42,7 @@ fun main() = BroadcastDoubleTensorAlgebra {// work in context with linear operat
// get P, L, U such that PA = LU
val (p, l, u) = a.lu()
// check that P is permutation matrix
// check P is permutation matrix
println("P:\n$p")
// L is lower triangular matrix and U is upper triangular matrix
println("L:\n$l")

View File

@ -0,0 +1,18 @@
/*
* Copyright 2018-2021 KMath contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
*/
package space.kscience.kmath.tensors
import org.jetbrains.kotlinx.multik.api.Multik
import org.jetbrains.kotlinx.multik.api.ndarray
import space.kscience.kmath.multik.multikAlgebra
import space.kscience.kmath.nd.one
import space.kscience.kmath.operations.DoubleField
fun main(): Unit = with(DoubleField.multikAlgebra) {
val a = Multik.ndarray(intArrayOf(1, 2, 3)).asType<Double>().wrap()
val b = Multik.ndarray(doubleArrayOf(1.0, 2.0, 3.0)).wrap()
one(a.shape) - a + b * 3.0
}

View File

@ -1,6 +1,6 @@
/*
* Copyright 2018-2021 KMath contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
* Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
*/
package space.kscience.kmath.tensors
@ -9,7 +9,7 @@ import space.kscience.kmath.operations.invoke
import space.kscience.kmath.tensors.core.BroadcastDoubleTensorAlgebra
import space.kscience.kmath.tensors.core.DoubleTensor
import space.kscience.kmath.tensors.core.DoubleTensorAlgebra
import space.kscience.kmath.tensors.core.toDoubleArray
import space.kscience.kmath.tensors.core.copyArray
import kotlin.math.sqrt
const val seed = 100500L
@ -111,7 +111,7 @@ class NeuralNetwork(private val layers: List<Layer>) {
private fun softMaxLoss(yPred: DoubleTensor, yTrue: DoubleTensor): DoubleTensor = BroadcastDoubleTensorAlgebra {
val onesForAnswers = yPred.zeroesLike()
yTrue.toDoubleArray().forEachIndexed { index, labelDouble ->
yTrue.copyArray().forEachIndexed { index, labelDouble ->
val label = labelDouble.toInt()
onesForAnswers[intArrayOf(index, label)] = 1.0
}
@ -186,7 +186,7 @@ fun main() = BroadcastDoubleTensorAlgebra {
x += fromArray(
intArrayOf(5),
doubleArrayOf(0.0, -1.0, -2.5, -3.0, 5.5) // rows means
doubleArrayOf(0.0, -1.0, -2.5, -3.0, 5.5) // row means
)

View File

@ -4,10 +4,13 @@
#
kotlin.code.style=official
kotlin.mpp.enableGranularSourceSetsMetadata=true
kotlin.mpp.stability.nowarn=true
kotlin.native.enableDependencyPropagation=false
kotlin.parallel.tasks.in.project=true
#kotlin.mpp.enableGranularSourceSetsMetadata=true
#kotlin.native.enableDependencyPropagation=false
kotlin.jupyter.add.scanner=false
org.gradle.configureondemand=true
org.gradle.jvmargs=-XX:MaxMetaspaceSize=2G
org.gradle.parallel=true

Binary file not shown.

View File

@ -1,5 +1,5 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-7.0-bin.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-7.2-bin.zip
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists

2
gradlew vendored
View File

@ -72,7 +72,7 @@ case "`uname`" in
Darwin* )
darwin=true
;;
MINGW* )
MSYS* | MINGW* )
msys=true
;;
NONSTOP* )

View File

@ -10,7 +10,7 @@ Performance and visualization extensions to MST API.
## Artifact:
The Maven coordinates of this project are `space.kscience:kmath-ast:0.3.0-dev-13`.
The Maven coordinates of this project are `space.kscience:kmath-ast:0.3.0-dev-14`.
**Gradle:**
```gradle
@ -20,7 +20,7 @@ repositories {
}
dependencies {
implementation 'space.kscience:kmath-ast:0.3.0-dev-13'
implementation 'space.kscience:kmath-ast:0.3.0-dev-14'
}
```
**Gradle Kotlin DSL:**
@ -31,7 +31,7 @@ repositories {
}
dependencies {
implementation("space.kscience:kmath-ast:0.3.0-dev-13")
implementation("space.kscience:kmath-ast:0.3.0-dev-14")
}
```
@ -106,7 +106,7 @@ var executable = function (constants, arguments) {
};
```
JS also supports very experimental expression optimization with [WebAssembly](https://webassembly.org/) IR generation.
JS also supports experimental expression optimization with [WebAssembly](https://webassembly.org/) IR generation.
Currently, only expressions inside `DoubleField` and `IntRing` are supported.
```kotlin
@ -161,7 +161,10 @@ public fun main() {
Result LaTeX:
<div style="background-color:white;">
![](https://latex.codecogs.com/gif.latex?%5Coperatorname{exp}%5C,%5Cleft(%5Csqrt{x}%5Cright)-%5Cfrac{%5Cfrac{%5Coperatorname{arcsin}%5C,%5Cleft(2%5C,x%5Cright)}{2%5Ctimes10^{10}%2Bx^{3}}}{12}+x^{2/3})
</div>
Result MathML (can be used with MathJax or other renderers):

View File

@ -45,8 +45,7 @@ kotlin.sourceSets {
jvmMain {
dependencies {
implementation("org.ow2.asm:asm:9.1")
implementation("org.ow2.asm:asm-commons:9.1")
implementation("org.ow2.asm:asm-commons:9.2")
}
}
}

View File

@ -77,7 +77,7 @@ var executable = function (constants, arguments) {
};
```
JS also supports very experimental expression optimization with [WebAssembly](https://webassembly.org/) IR generation.
JS also supports experimental expression optimization with [WebAssembly](https://webassembly.org/) IR generation.
Currently, only expressions inside `DoubleField` and `IntRing` are supported.
```kotlin
@ -132,7 +132,10 @@ public fun main() {
Result LaTeX:
<div style="background-color:white;">
![](https://latex.codecogs.com/gif.latex?%5Coperatorname{exp}%5C,%5Cleft(%5Csqrt{x}%5Cright)-%5Cfrac{%5Cfrac{%5Coperatorname{arcsin}%5C,%5Cleft(2%5C,x%5Cright)}{2%5Ctimes10^{10}%2Bx^{3}}}{12}+x^{2/3})
</div>
Result MathML (can be used with MathJax or other renderers):

View File

@ -1,6 +1,6 @@
/*
* Copyright 2018-2021 KMath contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
* Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
*/
package space.kscience.kmath.ast
@ -17,11 +17,11 @@ import com.github.h0tk3y.betterParse.lexer.regexToken
import com.github.h0tk3y.betterParse.parser.ParseResult
import com.github.h0tk3y.betterParse.parser.Parser
import space.kscience.kmath.expressions.MST
import space.kscience.kmath.expressions.StringSymbol
import space.kscience.kmath.operations.FieldOperations
import space.kscience.kmath.operations.GroupOperations
import space.kscience.kmath.expressions.Symbol
import space.kscience.kmath.operations.FieldOps
import space.kscience.kmath.operations.GroupOps
import space.kscience.kmath.operations.PowerOperations
import space.kscience.kmath.operations.RingOperations
import space.kscience.kmath.operations.RingOps
/**
* better-parse implementation of grammar defined in the ArithmeticsEvaluator.g4.
@ -43,7 +43,7 @@ public object ArithmeticsEvaluator : Grammar<MST>() {
private val ws: Token by regexToken("\\s+".toRegex(), ignore = true)
private val number: Parser<MST> by num use { MST.Numeric(text.toDouble()) }
private val singular: Parser<MST> by id use { StringSymbol(text) }
private val singular: Parser<MST> by id use { Symbol(text) }
private val unaryFunction: Parser<MST> by (id and -lpar and parser(ArithmeticsEvaluator::subSumChain) and -rpar)
.map { (id, term) -> MST.Unary(id.text, term) }
@ -60,7 +60,7 @@ public object ArithmeticsEvaluator : Grammar<MST>() {
.or(binaryFunction)
.or(unaryFunction)
.or(singular)
.or(-minus and parser(ArithmeticsEvaluator::term) map { MST.Unary(GroupOperations.MINUS_OPERATION, it) })
.or(-minus and parser(ArithmeticsEvaluator::term) map { MST.Unary(GroupOps.MINUS_OPERATION, it) })
.or(-lpar and parser(ArithmeticsEvaluator::subSumChain) and -rpar)
private val powChain: Parser<MST> by leftAssociative(term = term, operator = pow) { a, _, b ->
@ -72,9 +72,9 @@ public object ArithmeticsEvaluator : Grammar<MST>() {
operator = div or mul use TokenMatch::type
) { a, op, b ->
if (op == div)
MST.Binary(FieldOperations.DIV_OPERATION, a, b)
MST.Binary(FieldOps.DIV_OPERATION, a, b)
else
MST.Binary(RingOperations.TIMES_OPERATION, a, b)
MST.Binary(RingOps.TIMES_OPERATION, a, b)
}
private val subSumChain: Parser<MST> by leftAssociative(
@ -82,9 +82,9 @@ public object ArithmeticsEvaluator : Grammar<MST>() {
operator = plus or minus use TokenMatch::type
) { a, op, b ->
if (op == plus)
MST.Binary(GroupOperations.PLUS_OPERATION, a, b)
MST.Binary(GroupOps.PLUS_OPERATION, a, b)
else
MST.Binary(GroupOperations.MINUS_OPERATION, a, b)
MST.Binary(GroupOps.MINUS_OPERATION, a, b)
}
override val rootParser: Parser<MST> by subSumChain

View File

@ -1,6 +1,6 @@
/*
* Copyright 2018-2021 KMath contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
* Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
*/
package space.kscience.kmath.ast.rendering
@ -27,7 +27,7 @@ import space.kscience.kmath.misc.UnstableKMathAPI
*/
@UnstableKMathAPI
public object LatexSyntaxRenderer : SyntaxRenderer {
public override fun render(node: MathSyntax, output: Appendable): Unit = output.run {
override fun render(node: MathSyntax, output: Appendable): Unit = output.run {
fun render(syntax: MathSyntax) = render(syntax, output)
when (node) {

View File

@ -1,6 +1,6 @@
/*
* Copyright 2018-2021 KMath contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
* Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
*/
package space.kscience.kmath.ast.rendering
@ -16,7 +16,7 @@ import space.kscience.kmath.misc.UnstableKMathAPI
*/
@UnstableKMathAPI
public object MathMLSyntaxRenderer : SyntaxRenderer {
public override fun render(node: MathSyntax, output: Appendable) {
override fun render(node: MathSyntax, output: Appendable) {
output.append("<math xmlns=\"https://www.w3.org/1998/Math/MathML\"><mrow>")
renderPart(node, output)
output.append("</mrow></math>")

View File

@ -1,6 +1,6 @@
/*
* Copyright 2018-2021 KMath contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
* Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
*/
package space.kscience.kmath.ast.rendering
@ -29,7 +29,7 @@ public fun interface MathRenderer {
*/
@UnstableKMathAPI
public open class FeaturedMathRenderer(public val features: List<RenderFeature>) : MathRenderer {
public override fun render(mst: MST): MathSyntax {
override fun render(mst: MST): MathSyntax {
for (feature in features) feature.render(this, mst)?.let { return it }
throw UnsupportedOperationException("Renderer $this has no appropriate feature to render node $mst.")
}
@ -56,7 +56,7 @@ public open class FeaturedMathRendererWithPostProcess(
features: List<RenderFeature>,
public val stages: List<PostProcessPhase>,
) : FeaturedMathRenderer(features) {
public override fun render(mst: MST): MathSyntax {
override fun render(mst: MST): MathSyntax {
val res = super.render(mst)
for (stage in stages) stage.perform(res)
return res

View File

@ -1,6 +1,6 @@
/*
* Copyright 2018-2021 KMath contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
* Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
*/
package space.kscience.kmath.ast.rendering
@ -8,7 +8,7 @@ package space.kscience.kmath.ast.rendering
import space.kscience.kmath.misc.UnstableKMathAPI
/**
* Mathematical typography syntax node.
* Syntax node for mathematical typography.
*
* @author Iaroslav Postovalov
*/
@ -150,9 +150,9 @@ public data class OperandSyntax(
*/
@UnstableKMathAPI
public data class UnaryOperatorSyntax(
public override val operation: String,
override val operation: String,
public var prefix: MathSyntax,
public override val operand: OperandSyntax,
override val operand: OperandSyntax,
) : UnarySyntax() {
init {
operand.parent = this
@ -166,8 +166,8 @@ public data class UnaryOperatorSyntax(
*/
@UnstableKMathAPI
public data class UnaryPlusSyntax(
public override val operation: String,
public override val operand: OperandSyntax,
override val operation: String,
override val operand: OperandSyntax,
) : UnarySyntax() {
init {
operand.parent = this
@ -181,8 +181,8 @@ public data class UnaryPlusSyntax(
*/
@UnstableKMathAPI
public data class UnaryMinusSyntax(
public override val operation: String,
public override val operand: OperandSyntax,
override val operation: String,
override val operand: OperandSyntax,
) : UnarySyntax() {
init {
operand.parent = this
@ -197,8 +197,8 @@ public data class UnaryMinusSyntax(
*/
@UnstableKMathAPI
public data class RadicalSyntax(
public override val operation: String,
public override val operand: MathSyntax,
override val operation: String,
override val operand: MathSyntax,
) : UnarySyntax() {
init {
operand.parent = this
@ -215,8 +215,8 @@ public data class RadicalSyntax(
*/
@UnstableKMathAPI
public data class ExponentSyntax(
public override val operation: String,
public override val operand: OperandSyntax,
override val operation: String,
override val operand: OperandSyntax,
public var useOperatorForm: Boolean,
) : UnarySyntax() {
init {
@ -233,9 +233,9 @@ public data class ExponentSyntax(
*/
@UnstableKMathAPI
public data class SuperscriptSyntax(
public override val operation: String,
public override val left: MathSyntax,
public override val right: MathSyntax,
override val operation: String,
override val left: MathSyntax,
override val right: MathSyntax,
) : BinarySyntax() {
init {
left.parent = this
@ -252,9 +252,9 @@ public data class SuperscriptSyntax(
*/
@UnstableKMathAPI
public data class SubscriptSyntax(
public override val operation: String,
public override val left: MathSyntax,
public override val right: MathSyntax,
override val operation: String,
override val left: MathSyntax,
override val right: MathSyntax,
) : BinarySyntax() {
init {
left.parent = this
@ -270,10 +270,10 @@ public data class SubscriptSyntax(
*/
@UnstableKMathAPI
public data class BinaryOperatorSyntax(
public override val operation: String,
override val operation: String,
public var prefix: MathSyntax,
public override val left: MathSyntax,
public override val right: MathSyntax,
override val left: MathSyntax,
override val right: MathSyntax,
) : BinarySyntax() {
init {
left.parent = this
@ -290,9 +290,9 @@ public data class BinaryOperatorSyntax(
*/
@UnstableKMathAPI
public data class BinaryPlusSyntax(
public override val operation: String,
public override val left: OperandSyntax,
public override val right: OperandSyntax,
override val operation: String,
override val left: OperandSyntax,
override val right: OperandSyntax,
) : BinarySyntax() {
init {
left.parent = this
@ -301,7 +301,7 @@ public data class BinaryPlusSyntax(
}
/**
* Represents binary, infix subtraction (*42 - 42*).
* Represents binary, infix subtraction (*42 &minus; 42*).
*
* @param left The minuend.
* @param right The subtrahend.
@ -309,9 +309,9 @@ public data class BinaryPlusSyntax(
*/
@UnstableKMathAPI
public data class BinaryMinusSyntax(
public override val operation: String,
public override val left: OperandSyntax,
public override val right: OperandSyntax,
override val operation: String,
override val left: OperandSyntax,
override val right: OperandSyntax,
) : BinarySyntax() {
init {
left.parent = this
@ -329,9 +329,9 @@ public data class BinaryMinusSyntax(
*/
@UnstableKMathAPI
public data class FractionSyntax(
public override val operation: String,
public override val left: OperandSyntax,
public override val right: OperandSyntax,
override val operation: String,
override val left: OperandSyntax,
override val right: OperandSyntax,
public var infix: Boolean,
) : BinarySyntax() {
init {
@ -349,9 +349,9 @@ public data class FractionSyntax(
*/
@UnstableKMathAPI
public data class RadicalWithIndexSyntax(
public override val operation: String,
public override val left: MathSyntax,
public override val right: MathSyntax,
override val operation: String,
override val left: MathSyntax,
override val right: MathSyntax,
) : BinarySyntax() {
init {
left.parent = this
@ -369,9 +369,9 @@ public data class RadicalWithIndexSyntax(
*/
@UnstableKMathAPI
public data class MultiplicationSyntax(
public override val operation: String,
public override val left: OperandSyntax,
public override val right: OperandSyntax,
override val operation: String,
override val left: OperandSyntax,
override val right: OperandSyntax,
public var times: Boolean,
) : BinarySyntax() {
init {

View File

@ -1,6 +1,6 @@
/*
* Copyright 2018-2021 KMath contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
* Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
*/
package space.kscience.kmath.ast.rendering
@ -9,7 +9,7 @@ import space.kscience.kmath.misc.UnstableKMathAPI
/**
* Abstraction of writing [MathSyntax] as a string of an actual markup language. Typical implementation should
* involve traversal of MathSyntax with handling each its subtype.
* involve traversal of MathSyntax with handling each subtype.
*
* @author Iaroslav Postovalov
*/

View File

@ -1,6 +1,6 @@
/*
* Copyright 2018-2021 KMath contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
* Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
*/
package space.kscience.kmath.ast.rendering
@ -13,7 +13,7 @@ import space.kscience.kmath.operations.*
import kotlin.reflect.KClass
/**
* Prints any [Symbol] as a [SymbolSyntax] containing the [Symbol.value] of it.
* Prints any [Symbol] as a [SymbolSyntax] containing the [Symbol.identity] of it.
*
* @author Iaroslav Postovalov
*/
@ -39,7 +39,7 @@ public val PrintNumeric: RenderFeature = RenderFeature { _, node ->
@UnstableKMathAPI
private fun printSignedNumberString(s: String): MathSyntax = if (s.startsWith('-'))
UnaryMinusSyntax(
operation = GroupOperations.MINUS_OPERATION,
operation = GroupOps.MINUS_OPERATION,
operand = OperandSyntax(
operand = NumberSyntax(string = s.removePrefix("-")),
parentheses = true,
@ -49,7 +49,7 @@ else
NumberSyntax(string = s)
/**
* Special printing for numeric types which are printed in form of
* Special printing for numeric types that are printed in form of
* *('-'? (DIGIT+ ('.' DIGIT+)? ('E' '-'? DIGIT+)? | 'Infinity')) | 'NaN'*.
*
* @property types The suitable types.
@ -57,7 +57,7 @@ else
*/
@UnstableKMathAPI
public class PrettyPrintFloats(public val types: Set<KClass<out Number>>) : RenderFeature {
public override fun render(renderer: FeaturedMathRenderer, node: MST): MathSyntax? {
override fun render(renderer: FeaturedMathRenderer, node: MST): MathSyntax? {
if (node !is MST.Numeric || node.value::class !in types) return null
val toString = when (val v = node.value) {
@ -72,7 +72,7 @@ public class PrettyPrintFloats(public val types: Set<KClass<out Number>>) : Rend
val exponent = afterE.toDouble().toString().removeSuffix(".0")
return MultiplicationSyntax(
operation = RingOperations.TIMES_OPERATION,
operation = RingOps.TIMES_OPERATION,
left = OperandSyntax(operand = NumberSyntax(significand), parentheses = true),
right = OperandSyntax(
operand = SuperscriptSyntax(
@ -91,7 +91,7 @@ public class PrettyPrintFloats(public val types: Set<KClass<out Number>>) : Rend
if (toString.startsWith('-'))
return UnaryMinusSyntax(
operation = GroupOperations.MINUS_OPERATION,
operation = GroupOps.MINUS_OPERATION,
operand = OperandSyntax(operand = infty, parentheses = true),
)
@ -110,14 +110,14 @@ public class PrettyPrintFloats(public val types: Set<KClass<out Number>>) : Rend
}
/**
* Special printing for numeric types which are printed in form of *'-'? DIGIT+*.
* Special printing for numeric types that are printed in form of *'-'? DIGIT+*.
*
* @property types The suitable types.
* @author Iaroslav Postovalov
*/
@UnstableKMathAPI
public class PrettyPrintIntegers(public val types: Set<KClass<out Number>>) : RenderFeature {
public override fun render(renderer: FeaturedMathRenderer, node: MST): MathSyntax? =
override fun render(renderer: FeaturedMathRenderer, node: MST): MathSyntax? =
if (node !is MST.Numeric || node.value::class !in types)
null
else
@ -140,7 +140,7 @@ public class PrettyPrintIntegers(public val types: Set<KClass<out Number>>) : Re
*/
@UnstableKMathAPI
public class PrettyPrintPi(public val symbols: Set<String>) : RenderFeature {
public override fun render(renderer: FeaturedMathRenderer, node: MST): MathSyntax? =
override fun render(renderer: FeaturedMathRenderer, node: MST): MathSyntax? =
if (node !is Symbol || node.identity !in symbols)
null
else
@ -155,7 +155,7 @@ public class PrettyPrintPi(public val symbols: Set<String>) : RenderFeature {
}
/**
* Abstract printing of unary operations which discards [MST] if their operation is not in [operations] or its type is
* Abstract printing of unary operations that discards [MST] if their operation is not in [operations] or its type is
* not [MST.Unary].
*
* @param operations the allowed operations. If `null`, any operation is accepted.
@ -176,7 +176,7 @@ public abstract class Unary(public val operations: Collection<String>?) : Render
}
/**
* Abstract printing of unary operations which discards [MST] if their operation is not in [operations] or its type is
* Abstract printing of unary operations that discards [MST] if their operation is not in [operations] or its type is
* not [MST.Binary].
*
* @property operations the allowed operations. If `null`, any operation is accepted.
@ -202,7 +202,7 @@ public abstract class Binary(public val operations: Collection<String>?) : Rende
*/
@UnstableKMathAPI
public class BinaryPlus(operations: Collection<String>?) : Binary(operations) {
public override fun renderBinary(parent: FeaturedMathRenderer, node: MST.Binary): MathSyntax =
override fun renderBinary(parent: FeaturedMathRenderer, node: MST.Binary): MathSyntax =
BinaryPlusSyntax(
operation = node.operation,
left = OperandSyntax(parent.render(node.left), true),
@ -211,9 +211,9 @@ public class BinaryPlus(operations: Collection<String>?) : Binary(operations) {
public companion object {
/**
* The default instance configured with [GroupOperations.PLUS_OPERATION].
* The default instance configured with [GroupOps.PLUS_OPERATION].
*/
public val Default: BinaryPlus = BinaryPlus(setOf(GroupOperations.PLUS_OPERATION))
public val Default: BinaryPlus = BinaryPlus(setOf(GroupOps.PLUS_OPERATION))
}
}
@ -224,7 +224,7 @@ public class BinaryPlus(operations: Collection<String>?) : Binary(operations) {
*/
@UnstableKMathAPI
public class BinaryMinus(operations: Collection<String>?) : Binary(operations) {
public override fun renderBinary(parent: FeaturedMathRenderer, node: MST.Binary): MathSyntax =
override fun renderBinary(parent: FeaturedMathRenderer, node: MST.Binary): MathSyntax =
BinaryMinusSyntax(
operation = node.operation,
left = OperandSyntax(operand = parent.render(node.left), parentheses = true),
@ -233,9 +233,9 @@ public class BinaryMinus(operations: Collection<String>?) : Binary(operations) {
public companion object {
/**
* The default instance configured with [GroupOperations.MINUS_OPERATION].
* The default instance configured with [GroupOps.MINUS_OPERATION].
*/
public val Default: BinaryMinus = BinaryMinus(setOf(GroupOperations.MINUS_OPERATION))
public val Default: BinaryMinus = BinaryMinus(setOf(GroupOps.MINUS_OPERATION))
}
}
@ -246,16 +246,16 @@ public class BinaryMinus(operations: Collection<String>?) : Binary(operations) {
*/
@UnstableKMathAPI
public class UnaryPlus(operations: Collection<String>?) : Unary(operations) {
public override fun renderUnary(parent: FeaturedMathRenderer, node: MST.Unary): MathSyntax = UnaryPlusSyntax(
override fun renderUnary(parent: FeaturedMathRenderer, node: MST.Unary): MathSyntax = UnaryPlusSyntax(
operation = node.operation,
operand = OperandSyntax(operand = parent.render(node.value), parentheses = true),
)
public companion object {
/**
* The default instance configured with [GroupOperations.PLUS_OPERATION].
* The default instance configured with [GroupOps.PLUS_OPERATION].
*/
public val Default: UnaryPlus = UnaryPlus(setOf(GroupOperations.PLUS_OPERATION))
public val Default: UnaryPlus = UnaryPlus(setOf(GroupOps.PLUS_OPERATION))
}
}
@ -266,16 +266,16 @@ public class UnaryPlus(operations: Collection<String>?) : Unary(operations) {
*/
@UnstableKMathAPI
public class UnaryMinus(operations: Collection<String>?) : Unary(operations) {
public override fun renderUnary(parent: FeaturedMathRenderer, node: MST.Unary): MathSyntax = UnaryMinusSyntax(
override fun renderUnary(parent: FeaturedMathRenderer, node: MST.Unary): MathSyntax = UnaryMinusSyntax(
operation = node.operation,
operand = OperandSyntax(operand = parent.render(node.value), parentheses = true),
)
public companion object {
/**
* The default instance configured with [GroupOperations.MINUS_OPERATION].
* The default instance configured with [GroupOps.MINUS_OPERATION].
*/
public val Default: UnaryMinus = UnaryMinus(setOf(GroupOperations.MINUS_OPERATION))
public val Default: UnaryMinus = UnaryMinus(setOf(GroupOps.MINUS_OPERATION))
}
}
@ -286,7 +286,7 @@ public class UnaryMinus(operations: Collection<String>?) : Unary(operations) {
*/
@UnstableKMathAPI
public class Fraction(operations: Collection<String>?) : Binary(operations) {
public override fun renderBinary(parent: FeaturedMathRenderer, node: MST.Binary): MathSyntax = FractionSyntax(
override fun renderBinary(parent: FeaturedMathRenderer, node: MST.Binary): MathSyntax = FractionSyntax(
operation = node.operation,
left = OperandSyntax(operand = parent.render(node.left), parentheses = true),
right = OperandSyntax(operand = parent.render(node.right), parentheses = true),
@ -295,9 +295,9 @@ public class Fraction(operations: Collection<String>?) : Binary(operations) {
public companion object {
/**
* The default instance configured with [FieldOperations.DIV_OPERATION].
* The default instance configured with [FieldOps.DIV_OPERATION].
*/
public val Default: Fraction = Fraction(setOf(FieldOperations.DIV_OPERATION))
public val Default: Fraction = Fraction(setOf(FieldOps.DIV_OPERATION))
}
}
@ -308,7 +308,7 @@ public class Fraction(operations: Collection<String>?) : Binary(operations) {
*/
@UnstableKMathAPI
public class BinaryOperator(operations: Collection<String>?) : Binary(operations) {
public override fun renderBinary(parent: FeaturedMathRenderer, node: MST.Binary): MathSyntax =
override fun renderBinary(parent: FeaturedMathRenderer, node: MST.Binary): MathSyntax =
BinaryOperatorSyntax(
operation = node.operation,
prefix = OperatorNameSyntax(name = node.operation),
@ -331,7 +331,7 @@ public class BinaryOperator(operations: Collection<String>?) : Binary(operations
*/
@UnstableKMathAPI
public class UnaryOperator(operations: Collection<String>?) : Unary(operations) {
public override fun renderUnary(parent: FeaturedMathRenderer, node: MST.Unary): MathSyntax =
override fun renderUnary(parent: FeaturedMathRenderer, node: MST.Unary): MathSyntax =
UnaryOperatorSyntax(
operation = node.operation,
prefix = OperatorNameSyntax(node.operation),
@ -353,7 +353,7 @@ public class UnaryOperator(operations: Collection<String>?) : Unary(operations)
*/
@UnstableKMathAPI
public class Power(operations: Collection<String>?) : Binary(operations) {
public override fun renderBinary(parent: FeaturedMathRenderer, node: MST.Binary): MathSyntax =
override fun renderBinary(parent: FeaturedMathRenderer, node: MST.Binary): MathSyntax =
SuperscriptSyntax(
operation = node.operation,
left = OperandSyntax(parent.render(node.left), true),
@ -373,7 +373,7 @@ public class Power(operations: Collection<String>?) : Binary(operations) {
*/
@UnstableKMathAPI
public class SquareRoot(operations: Collection<String>?) : Unary(operations) {
public override fun renderUnary(parent: FeaturedMathRenderer, node: MST.Unary): MathSyntax =
override fun renderUnary(parent: FeaturedMathRenderer, node: MST.Unary): MathSyntax =
RadicalSyntax(operation = node.operation, operand = parent.render(node.value))
public companion object {
@ -391,7 +391,7 @@ public class SquareRoot(operations: Collection<String>?) : Unary(operations) {
*/
@UnstableKMathAPI
public class Exponent(operations: Collection<String>?) : Unary(operations) {
public override fun renderUnary(parent: FeaturedMathRenderer, node: MST.Unary): MathSyntax = ExponentSyntax(
override fun renderUnary(parent: FeaturedMathRenderer, node: MST.Unary): MathSyntax = ExponentSyntax(
operation = node.operation,
operand = OperandSyntax(operand = parent.render(node.value), parentheses = true),
useOperatorForm = true,
@ -412,7 +412,7 @@ public class Exponent(operations: Collection<String>?) : Unary(operations) {
*/
@UnstableKMathAPI
public class Multiplication(operations: Collection<String>?) : Binary(operations) {
public override fun renderBinary(parent: FeaturedMathRenderer, node: MST.Binary): MathSyntax =
override fun renderBinary(parent: FeaturedMathRenderer, node: MST.Binary): MathSyntax =
MultiplicationSyntax(
operation = node.operation,
left = OperandSyntax(operand = parent.render(node.left), parentheses = true),
@ -422,9 +422,9 @@ public class Multiplication(operations: Collection<String>?) : Binary(operations
public companion object {
/**
* The default instance configured with [RingOperations.TIMES_OPERATION].
* The default instance configured with [RingOps.TIMES_OPERATION].
*/
public val Default: Multiplication = Multiplication(setOf(RingOperations.TIMES_OPERATION))
public val Default: Multiplication = Multiplication(setOf(RingOps.TIMES_OPERATION))
}
}
@ -435,7 +435,7 @@ public class Multiplication(operations: Collection<String>?) : Binary(operations
*/
@UnstableKMathAPI
public class InverseTrigonometricOperations(operations: Collection<String>?) : Unary(operations) {
public override fun renderUnary(parent: FeaturedMathRenderer, node: MST.Unary): MathSyntax =
override fun renderUnary(parent: FeaturedMathRenderer, node: MST.Unary): MathSyntax =
UnaryOperatorSyntax(
operation = node.operation,
prefix = OperatorNameSyntax(name = node.operation.replaceFirst("a", "arc")),
@ -462,7 +462,7 @@ public class InverseTrigonometricOperations(operations: Collection<String>?) : U
*/
@UnstableKMathAPI
public class InverseHyperbolicOperations(operations: Collection<String>?) : Unary(operations) {
public override fun renderUnary(parent: FeaturedMathRenderer, node: MST.Unary): MathSyntax =
override fun renderUnary(parent: FeaturedMathRenderer, node: MST.Unary): MathSyntax =
UnaryOperatorSyntax(
operation = node.operation,
prefix = OperatorNameSyntax(name = node.operation.replaceFirst("a", "ar")),

View File

@ -1,6 +1,6 @@
/*
* Copyright 2018-2021 KMath contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
* Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
*/
package space.kscience.kmath.ast.rendering

View File

@ -1,16 +1,16 @@
/*
* Copyright 2018-2021 KMath contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
* Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
*/
package space.kscience.kmath.ast.rendering
import space.kscience.kmath.ast.rendering.FeaturedMathRendererWithPostProcess.PostProcessPhase
import space.kscience.kmath.misc.UnstableKMathAPI
import space.kscience.kmath.operations.FieldOperations
import space.kscience.kmath.operations.GroupOperations
import space.kscience.kmath.operations.FieldOps
import space.kscience.kmath.operations.GroupOps
import space.kscience.kmath.operations.PowerOperations
import space.kscience.kmath.operations.RingOperations
import space.kscience.kmath.operations.RingOps
/**
* Removes unnecessary times (&times;) symbols from [MultiplicationSyntax].
@ -205,7 +205,7 @@ public val BetterExponent: PostProcessPhase = PostProcessPhase { node ->
@UnstableKMathAPI
public class SimplifyParentheses(public val precedenceFunction: (MathSyntax) -> Int) :
PostProcessPhase {
public override fun perform(node: MathSyntax): Unit = when (node) {
override fun perform(node: MathSyntax): Unit = when (node) {
is NumberSyntax -> Unit
is SymbolSyntax -> Unit
is OperatorNameSyntax -> Unit
@ -306,10 +306,10 @@ public class SimplifyParentheses(public val precedenceFunction: (MathSyntax) ->
is BinarySyntax -> when (it.operation) {
PowerOperations.POW_OPERATION -> 1
RingOperations.TIMES_OPERATION -> 3
FieldOperations.DIV_OPERATION -> 3
GroupOperations.MINUS_OPERATION -> 4
GroupOperations.PLUS_OPERATION -> 4
RingOps.TIMES_OPERATION -> 3
FieldOps.DIV_OPERATION -> 3
GroupOps.MINUS_OPERATION -> 4
GroupOps.PLUS_OPERATION -> 4
else -> 0
}

View File

@ -1,6 +1,6 @@
/*
* Copyright 2018-2021 KMath contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
* Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
*/
package space.kscience.kmath.ast
@ -11,7 +11,6 @@ import space.kscience.kmath.expressions.Symbol.Companion.x
import space.kscience.kmath.expressions.interpret
import space.kscience.kmath.operations.DoubleField
import space.kscience.kmath.operations.IntRing
import space.kscience.kmath.operations.bindSymbol
import space.kscience.kmath.operations.invoke
import kotlin.test.Test
import kotlin.test.assertEquals

View File

@ -1,6 +1,6 @@
/*
* Copyright 2018-2021 KMath contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
* Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
*/
package space.kscience.kmath.ast

View File

@ -1,6 +1,6 @@
/*
* Copyright 2018-2021 KMath contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
* Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
*/
package space.kscience.kmath.ast
@ -9,7 +9,6 @@ import space.kscience.kmath.expressions.MstRing
import space.kscience.kmath.expressions.Symbol.Companion.x
import space.kscience.kmath.expressions.invoke
import space.kscience.kmath.operations.IntRing
import space.kscience.kmath.operations.bindSymbol
import space.kscience.kmath.operations.invoke
import kotlin.test.Test
import kotlin.test.assertEquals

View File

@ -1,6 +1,6 @@
/*
* Copyright 2018-2021 KMath contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
* Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
*/
package space.kscience.kmath.ast

View File

@ -1,6 +1,6 @@
/*
* Copyright 2018-2021 KMath contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
* Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
*/
package space.kscience.kmath.ast

View File

@ -1,6 +1,6 @@
/*
* Copyright 2018-2021 KMath contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
* Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
*/
package space.kscience.kmath.ast.rendering

View File

@ -1,13 +1,13 @@
/*
* Copyright 2018-2021 KMath contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
* Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
*/
package space.kscience.kmath.ast.rendering
import space.kscience.kmath.ast.rendering.TestUtils.testLatex
import space.kscience.kmath.expressions.MST
import space.kscience.kmath.operations.GroupOperations
import space.kscience.kmath.operations.GroupOps
import kotlin.test.Test
internal class TestLatex {
@ -36,7 +36,7 @@ internal class TestLatex {
fun unaryOperator() = testLatex("sin(1)", "\\operatorname{sin}\\,\\left(1\\right)")
@Test
fun unaryPlus() = testLatex(MST.Unary(GroupOperations.PLUS_OPERATION, MST.Numeric(1)), "+1")
fun unaryPlus() = testLatex(MST.Unary(GroupOps.PLUS_OPERATION, MST.Numeric(1)), "+1")
@Test
fun unaryMinus() = testLatex("-x", "-x")

View File

@ -1,13 +1,13 @@
/*
* Copyright 2018-2021 KMath contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
* Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
*/
package space.kscience.kmath.ast.rendering
import space.kscience.kmath.ast.rendering.TestUtils.testMathML
import space.kscience.kmath.expressions.MST
import space.kscience.kmath.operations.GroupOperations
import space.kscience.kmath.operations.GroupOps
import kotlin.test.Test
internal class TestMathML {
@ -47,7 +47,7 @@ internal class TestMathML {
@Test
fun unaryPlus() =
testMathML(MST.Unary(GroupOperations.PLUS_OPERATION, MST.Numeric(1)), "<mo>+</mo><mn>1</mn>")
testMathML(MST.Unary(GroupOps.PLUS_OPERATION, MST.Numeric(1)), "<mo>+</mo><mn>1</mn>")
@Test
fun unaryMinus() = testMathML("-x", "<mo>-</mo><mi>x</mi>")

View File

@ -1,6 +1,6 @@
/*
* Copyright 2018-2021 KMath contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
* Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
*/
package space.kscience.kmath.ast.rendering

View File

@ -1,6 +1,6 @@
/*
* Copyright 2018-2021 KMath contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
* Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
*/
package space.kscience.kmath.ast.rendering

View File

@ -1,6 +1,6 @@
/*
* Copyright 2018-2021 KMath contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
* Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
*/
package space.kscience.kmath.ast

Some files were not shown because too many files have changed in this diff Show More