Merge branch 'dev' into feature/mp-samplers

# Conflicts:
#	examples/src/main/kotlin/space/kscience/kmath/commons/fit/fitWithAutoDiff.kt
#	examples/src/main/kotlin/space/kscience/kmath/stat/DistributionBenchmark.kt
#	examples/src/main/kotlin/space/kscience/kmath/stat/DistributionDemo.kt
#	kmath-commons/src/test/kotlin/space/kscience/kmath/commons/optimization/OptimizeTest.kt
#	kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/Buffer.kt
#	kmath-coroutines/src/commonMain/kotlin/kscience/kmath/chains/BlockingRealChain.kt
#	kmath-stat/src/commonMain/kotlin/kscience/kmath/stat/SamplerAlgebra.kt
#	kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/Distribution.kt
#	kmath-stat/src/commonMain/kotlin/space/kscience/kmath/stat/RandomChain.kt
#	kmath-stat/src/jvmMain/kotlin/space/kscience/kmath/stat/distributions.kt
This commit is contained in:
Iaroslav Postovalov 2021-03-31 01:48:26 +07:00
commit f26cad6d18
No known key found for this signature in database
GPG Key ID: 46E15E4A31B3BCD7
336 changed files with 9073 additions and 8650 deletions

View File

@ -3,105 +3,34 @@ name: Gradle build
on: [ push ] on: [ push ]
jobs: jobs:
build-ubuntu: build:
runs-on: ubuntu-20.04 strategy:
matrix:
os: [ macOS-latest, windows-latest ]
runs-on: ${{matrix.os}}
steps: steps:
- uses: actions/checkout@v2 - name: Checkout the repo
uses: actions/checkout@v2
- name: Set up JDK 11 - name: Set up JDK 11
uses: actions/setup-java@v1 uses: actions/setup-java@v1
with: with:
java-version: 11 java-version: 11
- name: Grant execute permission for gradlew
run: chmod +x gradlew
- name: Install Chrome
run: |
sudo apt install -y libappindicator1 fonts-liberation
wget https://dl.google.com/linux/direct/google-chrome-stable_current_amd64.deb
sudo dpkg -i google-chrome*.deb
- name: Cache gradle
uses: actions/cache@v2
with:
path: |
.gradle
build
~/.gradle
key: gradle
restore-keys: gradle
- name: Cache konan
uses: actions/cache@v2
with:
path: |
~/.konan/dependencies
~/.konan/kotlin-native-prebuilt-linux-*
key: ${{ runner.os }}-konan
restore-keys: ${{ runner.os }}-konan
- name: Build with Gradle
run: ./gradlew -Dorg.gradle.daemon=false --build-cache build
build-osx:
runs-on: macos-latest
steps:
- uses: actions/checkout@v2
- name: Set up JDK 11
uses: actions/setup-java@v1
with:
java-version: 11
- name: Grant execute permission for gradlew
run: chmod +x gradlew
- name: Cache gradle
uses: actions/cache@v2
with:
path: |
.gradle
build
~/.gradle
key: gradle
restore-keys: gradle
- name: Cache konan
uses: actions/cache@v2
with:
path: |
~/.konan/dependencies
~/.konan/kotlin-native-prebuilt-macos-*
key: ${{ runner.os }}-konan
restore-keys: ${{ runner.os }}-konan
- name: Build with Gradle
run: sudo ./gradlew -Dorg.gradle.daemon=false --build-cache build
build-windows:
runs-on: windows-latest
steps:
- uses: actions/checkout@v2
- name: Set up JDK 11
uses: actions/setup-java@v1
with:
java-version: 11
- name: Grant execute permission for gradlew
run: chmod +x gradlew
- name: Add msys to path - name: Add msys to path
if: matrix.os == 'windows-latest'
run: SETX PATH "%PATH%;C:\msys64\mingw64\bin" run: SETX PATH "%PATH%;C:\msys64\mingw64\bin"
- name: Cache gradle - name: Cache gradle
uses: actions/cache@v2 uses: actions/cache@v2
with: with:
path: | path: ~/.gradle/caches
.gradle key: ${{ runner.os }}-gradle-${{ hashFiles('*.gradle.kts') }}
build restore-keys: |
~/.gradle ${{ runner.os }}-gradle-
key: ${{ runner.os }}-gradle
restore-keys: ${{ runner.os }}-gradle
- name: Cache konan - name: Cache konan
uses: actions/cache@v2 uses: actions/cache@v2
with: with:
path: | path: ~/.konan
~/.konan/dependencies key: ${{ runner.os }}-gradle-${{ hashFiles('*.gradle.kts') }}
~/.konan/kotlin-native-prebuilt-mingw-* restore-keys: |
key: ${{ runner.os }}-konan ${{ runner.os }}-gradle-
restore-keys: ${{ runner.os }}-konan - name: Build
- name: Build with Gradle run: ./gradlew build --no-daemon --stacktrace
run: ./gradlew --build-cache build

40
.github/workflows/pages.yml vendored Normal file
View File

@ -0,0 +1,40 @@
name: Dokka publication
on:
push:
branches:
- master
jobs:
build:
runs-on: ubuntu-20.04
steps:
- name: Checkout the repo
uses: actions/checkout@v2
- name: Set up JDK 11
uses: actions/setup-java@v1
with:
java-version: 11
- name: Cache gradle
uses: actions/cache@v2
with:
path: ~/.gradle/caches
key: ubuntu-20.04-gradle-${{ hashFiles('*.gradle.kts') }}
restore-keys: |
ubuntu-20.04-gradle-
- name: Cache konan
uses: actions/cache@v2
with:
path: ~/.konan
key: ${{ runner.os }}-gradle-${{ hashFiles('*.gradle.kts') }}
restore-keys: |
${{ runner.os }}-gradle-
- name: Build
run: |
./gradlew dokkaHtmlMultiModule --no-daemon --no-parallel --stacktrace
mv build/dokka/htmlMultiModule/-modules.html build/dokka/htmlMultiModule/index.html
- name: Deploy to GitHub Pages
uses: JamesIves/github-pages-deploy-action@4.1.0
with:
branch: gh-pages
folder: build/dokka/htmlMultiModule

View File

@ -1,117 +1,59 @@
name: Bintray Publish name: Gradle publish
on: on:
workflow_dispatch:
release: release:
types: types:
- created - created
jobs: jobs:
build-ubuntu: publish:
runs-on: ubuntu-20.04 environment:
name: publish
strategy:
matrix:
os: [ macOS-latest, windows-latest ]
runs-on: ${{matrix.os}}
steps: steps:
- uses: actions/checkout@v2 - name: Checkout the repo
uses: actions/checkout@v2
- name: Set up JDK 11 - name: Set up JDK 11
uses: actions/setup-java@v1 uses: actions/setup-java@v1
with: with:
java-version: 11 java-version: 11
- name: Grant execute permission for gradlew
run: chmod +x gradlew
- name: Install Chrome
run: |
sudo apt install -y libappindicator1 fonts-liberation
wget https://dl.google.com/linux/direct/google-chrome-stable_current_amd64.deb
sudo dpkg -i google-chrome*.deb
- name: Cache gradle
uses: actions/cache@v2
with:
path: |
.gradle
build
~/.gradle
key: gradle
restore-keys: gradle
- name: Cache konan
uses: actions/cache@v2
with:
path: |
~/.konan/dependencies
~/.konan/kotlin-native-prebuilt-linux-*
key: ${{ runner.os }}-konan
restore-keys: ${{ runner.os }}-konan
- name: Build with Gradle
run: ./gradlew -Dorg.gradle.daemon=false --build-cache build
- name: Run release task
run: ./gradlew release -PbintrayUser=${{ secrets.BINTRAY_USER }} -PbintrayApiKey=${{ secrets.BINTRAY_KEY }}
build-osx:
runs-on: macos-latest
steps:
- uses: actions/checkout@v2
- name: Set up JDK 11
uses: actions/setup-java@v1
with:
java-version: 11
- name: Grant execute permission for gradlew
run: chmod +x gradlew
- name: Cache gradle
uses: actions/cache@v2
with:
path: |
.gradle
build
~/.gradle
key: gradle
restore-keys: gradle
- name: Cache konan
uses: actions/cache@v2
with:
path: |
~/.konan/dependencies
~/.konan/kotlin-native-prebuilt-macos-*
key: ${{ runner.os }}-konan
restore-keys: ${{ runner.os }}-konan
- name: Build with Gradle
run: sudo ./gradlew -Dorg.gradle.daemon=false --build-cache build
- name: Run release task
run: ./gradlew release -PbintrayUser=${{ secrets.BINTRAY_USER }} -PbintrayApiKey=${{ secrets.BINTRAY_KEY }}
build-windows:
runs-on: windows-latest
steps:
- uses: actions/checkout@v2
- name: Set up JDK 11
uses: actions/setup-java@v1
with:
java-version: 11
- name: Grant execute permission for gradlew
run: chmod +x gradlew
- name: Add msys to path - name: Add msys to path
if: matrix.os == 'windows-latest'
run: SETX PATH "%PATH%;C:\msys64\mingw64\bin" run: SETX PATH "%PATH%;C:\msys64\mingw64\bin"
- name: Cache gradle - name: Cache gradle
uses: actions/cache@v2 uses: actions/cache@v2
with: with:
path: | path: ~/.gradle/caches
.gradle key: ${{ runner.os }}-gradle-${{ hashFiles('*.gradle.kts') }}
build restore-keys: |
~/.gradle ${{ runner.os }}-gradle-
key: ${{ runner.os }}-gradle
restore-keys: ${{ runner.os }}-gradle
- name: Cache konan - name: Cache konan
uses: actions/cache@v2 uses: actions/cache@v2
with: with:
path: | path: ~/.konan
~/.konan/dependencies key: ${{ runner.os }}-gradle-${{ hashFiles('*.gradle.kts') }}
~/.konan/kotlin-native-prebuilt-mingw-* restore-keys: |
key: ${{ runner.os }}-konan ${{ runner.os }}-gradle-
restore-keys: ${{ runner.os }}-konan - name: Publish Windows Artifacts
- name: Build with Gradle if: matrix.os == 'windows-latest'
run: ./gradlew --build-cache build run: >
- name: Run release task ./gradlew release --no-daemon
run: ./gradlew release -PbintrayUser=${{ secrets.BINTRAY_USER }} -PbintrayApiKey=${{ secrets.BINTRAY_KEY }} -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 }}
- 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 }}

5
.gitignore vendored
View File

@ -2,9 +2,14 @@
build/ build/
out/ out/
.idea/ .idea/
.vscode/
# Avoid ignoring Gradle wrapper jar file (.jar files are usually ignored) # Avoid ignoring Gradle wrapper jar file (.jar files are usually ignored)
!gradle-wrapper.jar !gradle-wrapper.jar
# Cache of project # Cache of project
.gradletasknamecache .gradletasknamecache
# Generated by javac -h and runtime
*.class
*.log

View File

@ -2,6 +2,32 @@
## [Unreleased] ## [Unreleased]
### Added ### Added
- ScaleOperations interface
- Field extends ScaleOperations
- Basic integration API
### Changed
- Exponential operations merged with hyperbolic functions
- Space is replaced by Group. Space is reserved for vector spaces.
- VectorSpace is now a vector space
- Buffer factories for primitives moved to MutableBuffer.Companion
- NDStructure and NDAlgebra to StructureND and AlgebraND respectively
- Real -> Double
- DataSets are moved from functions to core
### Deprecated
### Removed
- Nearest in Domain. To be implemented in geometry package.
- Number multiplication and division in main Algebra chain
- `contentEquals` from Buffer. It moved to the companion.
### Fixed
### Security
## [0.2.0]
### Added
- `fun` annotation for SAM interfaces in library - `fun` annotation for SAM interfaces in library
- Explicit `public` visibility for all public APIs - Explicit `public` visibility for all public APIs
- Better trigonometric and hyperbolic functions for `AutoDiffField` (https://github.com/mipt-npm/kmath/pull/140) - Better trigonometric and hyperbolic functions for `AutoDiffField` (https://github.com/mipt-npm/kmath/pull/140)
@ -21,11 +47,11 @@
- Basic Quaternion vector support in `kmath-complex`. - Basic Quaternion vector support in `kmath-complex`.
### Changed ### Changed
- Package changed from `scientifik` to `kscience.kmath` - Package changed from `scientifik` to `space.kscience`
- Gradle version: 6.6 -> 6.8 - Gradle version: 6.6 -> 6.8.2
- Minor exceptions refactor (throwing `IllegalArgumentException` by argument checks instead of `IllegalStateException`) - Minor exceptions refactor (throwing `IllegalArgumentException` by argument checks instead of `IllegalStateException`)
- `Polynomial` secondary constructor made function - `Polynomial` secondary constructor made function
- Kotlin version: 1.3.72 -> 1.4.21 - Kotlin version: 1.3.72 -> 1.4.30
- `kmath-ast` doesn't depend on heavy `kotlin-reflect` library - `kmath-ast` doesn't depend on heavy `kotlin-reflect` library
- Full autodiff refactoring based on `Symbol` - Full autodiff refactoring based on `Symbol`
- `kmath-prob` renamed to `kmath-stat` - `kmath-prob` renamed to `kmath-stat`
@ -41,6 +67,8 @@
- Refactor histograms. They are marked as prototype - Refactor histograms. They are marked as prototype
- `Complex` and related features moved to a separate module `kmath-complex` - `Complex` and related features moved to a separate module `kmath-complex`
- Refactor AlgebraElement - Refactor AlgebraElement
- `symbol` method in `Algebra` renamed to `bindSymbol` to avoid ambiguity
- Add `out` projection to `Buffer` generic
### Deprecated ### Deprecated
@ -50,6 +78,7 @@
- `toGrid` method. - `toGrid` method.
- Public visibility of `BufferAccessor2D` - Public visibility of `BufferAccessor2D`
- `Real` class - `Real` class
- StructureND identity and equals
### Fixed ### Fixed
- `symbol` method in `MstExtendedField` (https://github.com/mipt-npm/kmath/pull/140) - `symbol` method in `MstExtendedField` (https://github.com/mipt-npm/kmath/pull/140)

View File

@ -1,11 +1,8 @@
[![JetBrains Research](https://jb.gg/badges/research.svg)](https://confluence.jetbrains.com/display/ALL/JetBrains+on+GitHub) [![JetBrains Research](https://jb.gg/badges/research.svg)](https://confluence.jetbrains.com/display/ALL/JetBrains+on+GitHub)
[![DOI](https://zenodo.org/badge/129486382.svg)](https://zenodo.org/badge/latestdoi/129486382) [![DOI](https://zenodo.org/badge/129486382.svg)](https://zenodo.org/badge/latestdoi/129486382)
![Gradle build](https://github.com/mipt-npm/kmath/workflows/Gradle%20build/badge.svg) ![Gradle build](https://github.com/mipt-npm/kmath/workflows/Gradle%20build/badge.svg)
[![Maven Central](https://img.shields.io/maven-central/v/space.kscience/kmath-core.svg?label=Maven%20Central)](https://search.maven.org/search?q=g:%22space.kscience%22)
Bintray: [ ![Download](https://api.bintray.com/packages/mipt-npm/kscience/kmath-core/images/download.svg) ](https://bintray.com/mipt-npm/kscience/kmath-core/_latestVersion) [![Space](https://img.shields.io/maven-metadata/v?label=Space&metadataUrl=https%3A%2F%2Fmaven.pkg.jetbrains.space%2Fmipt-npm%2Fp%2Fsci%2Fmaven%2Fkscience%2Fkmath%2Fkmath-core%2Fmaven-metadata.xml)](https://maven.pkg.jetbrains.space/mipt-npm/p/sci/maven/space/kscience/)
Bintray-dev: [ ![Download](https://api.bintray.com/packages/mipt-npm/dev/kmath-core/images/download.svg) ](https://bintray.com/mipt-npm/dev/kmath-core/_latestVersion)
# KMath # KMath
@ -89,12 +86,12 @@ KMath is a modular library. Different modules provide different features with di
> **Maturity**: PROTOTYPE > **Maturity**: PROTOTYPE
> >
> **Features:** > **Features:**
> - [expression-language](kmath-ast/src/jvmMain/kotlin/kscience/kmath/ast/parser.kt) : Expression language and its parser > - [expression-language](kmath-ast/src/jvmMain/kotlin/space/kscience/kmath/ast/parser.kt) : Expression language and its parser
> - [mst](kmath-ast/src/commonMain/kotlin/kscience/kmath/ast/MST.kt) : MST (Mathematical Syntax Tree) as expression language's syntax intermediate representation > - [mst](kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/MST.kt) : MST (Mathematical Syntax Tree) as expression language's syntax intermediate representation
> - [mst-building](kmath-ast/src/commonMain/kotlin/kscience/kmath/ast/MstAlgebra.kt) : MST building algebraic structure > - [mst-building](kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/MstAlgebra.kt) : MST building algebraic structure
> - [mst-interpreter](kmath-ast/src/commonMain/kotlin/kscience/kmath/ast/MST.kt) : MST interpreter > - [mst-interpreter](kmath-ast/src/commonMain/kotlin/space/kscience/kmath/ast/MST.kt) : MST interpreter
> - [mst-jvm-codegen](kmath-ast/src/jvmMain/kotlin/kscience/kmath/asm/asm.kt) : Dynamic MST to JVM bytecode compiler > - [mst-jvm-codegen](kmath-ast/src/jvmMain/kotlin/space/kscience/kmath/asm/asm.kt) : Dynamic MST to JVM bytecode compiler
> - [mst-js-codegen](kmath-ast/src/jsMain/kotlin/kscience/kmath/estree/estree.kt) : Dynamic MST to JS compiler > - [mst-js-codegen](kmath-ast/src/jsMain/kotlin/space/kscience/kmath/estree/estree.kt) : Dynamic MST to JS compiler
<hr/> <hr/>
@ -110,8 +107,8 @@ KMath is a modular library. Different modules provide different features with di
> **Maturity**: PROTOTYPE > **Maturity**: PROTOTYPE
> >
> **Features:** > **Features:**
> - [complex](kmath-complex/src/commonMain/kotlin/kscience/kmath/complex/Complex.kt) : Complex Numbers > - [complex](kmath-complex/src/commonMain/kotlin/space/kscience/kmath/complex/Complex.kt) : Complex Numbers
> - [quaternion](kmath-complex/src/commonMain/kotlin/kscience/kmath/complex/Quaternion.kt) : Quaternions > - [quaternion](kmath-complex/src/commonMain/kotlin/space/kscience/kmath/complex/Quaternion.kt) : Quaternions
<hr/> <hr/>
@ -121,15 +118,15 @@ KMath is a modular library. Different modules provide different features with di
> **Maturity**: DEVELOPMENT > **Maturity**: DEVELOPMENT
> >
> **Features:** > **Features:**
> - [algebras](kmath-core/src/commonMain/kotlin/kscience/kmath/operations/Algebra.kt) : Algebraic structures like rings, spaces and fields. > - [algebras](kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/Algebra.kt) : Algebraic structures like rings, spaces and fields.
> - [nd](kmath-core/src/commonMain/kotlin/kscience/kmath/structures/NDStructure.kt) : Many-dimensional structures and operations on them. > - [nd](kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/StructureND.kt) : Many-dimensional structures and operations on them.
> - [linear](kmath-core/src/commonMain/kotlin/kscience/kmath/operations/Algebra.kt) : Basic linear algebra operations (sums, products, etc.), backed by the `Space` API. Advanced linear algebra operations like matrix inversion and LU decomposition. > - [linear](kmath-core/src/commonMain/kotlin/space/kscience/kmath/operations/Algebra.kt) : Basic linear algebra operations (sums, products, etc.), backed by the `Space` API. Advanced linear algebra operations like matrix inversion and LU decomposition.
> - [buffers](kmath-core/src/commonMain/kotlin/kscience/kmath/structures/Buffers.kt) : One-dimensional structure > - [buffers](kmath-core/src/commonMain/kotlin/space/kscience/kmath/structures/Buffers.kt) : One-dimensional structure
> - [expressions](kmath-core/src/commonMain/kotlin/kscience/kmath/expressions) : By writing a single mathematical expression once, users will be able to apply different types of > - [expressions](kmath-core/src/commonMain/kotlin/space/kscience/kmath/expressions) : By writing a single mathematical expression once, users will be able to apply different types of
objects to the expression by providing a context. Expressions can be used for a wide variety of purposes from high 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. performance calculations to code generation.
> - [domains](kmath-core/src/commonMain/kotlin/kscience/kmath/domains) : Domains > - [domains](kmath-core/src/commonMain/kotlin/space/kscience/kmath/domains) : Domains
> - [autodif](kmath-core/src/commonMain/kotlin/kscience/kmath/expressions/SimpleAutoDiff.kt) : Automatic differentiation > - [autodif](kmath-core/src/commonMain/kotlin/space/kscience/kmath/expressions/SimpleAutoDiff.kt) : Automatic differentiation
<hr/> <hr/>
@ -149,6 +146,12 @@ performance calculations to code generation.
> >
> >
> **Maturity**: PROTOTYPE > **Maturity**: PROTOTYPE
>
> **Features:**
> - [ejml-vector](kmath-ejml/src/main/kotlin/space/kscience/kmath/ejml/EjmlVector.kt) : The Point implementation using SimpleMatrix.
> - [ejml-matrix](kmath-ejml/src/main/kotlin/space/kscience/kmath/ejml/EjmlMatrix.kt) : The Matrix implementation using SimpleMatrix.
> - [ejml-linear-space](kmath-ejml/src/main/kotlin/space/kscience/kmath/ejml/EjmlLinearSpace.kt) : The LinearSpace implementation using SimpleMatrix.
<hr/> <hr/>
* ### [kmath-for-real](kmath-for-real) * ### [kmath-for-real](kmath-for-real)
@ -159,9 +162,9 @@ One can still use generic algebras though.
> **Maturity**: EXPERIMENTAL > **Maturity**: EXPERIMENTAL
> >
> **Features:** > **Features:**
> - [RealVector](kmath-for-real/src/commonMain/kotlin/kscience/kmath/real/RealVector.kt) : Numpy-like operations for Buffers/Points > - [DoubleVector](kmath-for-real/src/commonMain/kotlin/space/kscience/kmath/real/DoubleVector.kt) : Numpy-like operations for Buffers/Points
> - [RealMatrix](kmath-for-real/src/commonMain/kotlin/kscience/kmath/real/RealMatrix.kt) : Numpy-like operations for 2d real structures > - [DoubleMatrix](kmath-for-real/src/commonMain/kotlin/space/kscience/kmath/real/DoubleMatrix.kt) : Numpy-like operations for 2d real structures
> - [grids](kmath-for-real/src/commonMain/kotlin/kscience/kmath/structures/grids.kt) : Uniform grid generators > - [grids](kmath-for-real/src/commonMain/kotlin/space/kscience/kmath/structures/grids.kt) : Uniform grid generators
<hr/> <hr/>
@ -171,10 +174,10 @@ One can still use generic algebras though.
> **Maturity**: PROTOTYPE > **Maturity**: PROTOTYPE
> >
> **Features:** > **Features:**
> - [piecewise](kmath-functions/Piecewise functions.) : src/commonMain/kotlin/kscience/kmath/functions/Piecewise.kt > - [piecewise](kmath-functions/Piecewise functions.) : src/commonMain/kotlin/space/kscience/kmath/functions/Piecewise.kt
> - [polynomials](kmath-functions/Polynomial functions.) : src/commonMain/kotlin/kscience/kmath/functions/Polynomial.kt > - [polynomials](kmath-functions/Polynomial functions.) : src/commonMain/kotlin/space/kscience/kmath/functions/Polynomial.kt
> - [linear interpolation](kmath-functions/Linear XY interpolator.) : src/commonMain/kotlin/kscience/kmath/interpolation/LinearInterpolator.kt > - [linear interpolation](kmath-functions/Linear XY interpolator.) : src/commonMain/kotlin/space/kscience/kmath/interpolation/LinearInterpolator.kt
> - [spline interpolation](kmath-functions/Cubic spline XY interpolator.) : src/commonMain/kotlin/kscience/kmath/interpolation/SplineInterpolator.kt > - [spline interpolation](kmath-functions/Cubic spline XY interpolator.) : src/commonMain/kotlin/space/kscience/kmath/interpolation/SplineInterpolator.kt
<hr/> <hr/>
@ -208,9 +211,9 @@ One can still use generic algebras though.
> **Maturity**: EXPERIMENTAL > **Maturity**: EXPERIMENTAL
> >
> **Features:** > **Features:**
> - [nd4jarraystructure](kmath-nd4j/src/commonMain/kotlin/kscience/kmath/operations/Algebra.kt) : NDStructure wrapper for INDArray > - [nd4jarraystructure](kmath-nd4j/#) : NDStructure wrapper for INDArray
> - [nd4jarrayrings](kmath-nd4j/src/commonMain/kotlin/kscience/kmath/structures/NDStructure.kt) : Rings over Nd4jArrayStructure of Int and Long > - [nd4jarrayrings](kmath-nd4j/#) : Rings over Nd4jArrayStructure of Int and Long
> - [nd4jarrayfields](kmath-nd4j/src/commonMain/kotlin/kscience/kmath/structures/Buffers.kt) : Fields over Nd4jArrayStructure of Float and Double > - [nd4jarrayfields](kmath-nd4j/#) : Fields over Nd4jArrayStructure of Float and Double
<hr/> <hr/>
@ -247,33 +250,22 @@ better than SciPy.
### Repositories ### Repositories
Release artifacts are accessible from bintray with following configuration (see documentation of 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): [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 ```kotlin
repositories { repositories {
maven("https://dl.bintray.com/mipt-npm/kscience") maven("https://repo.kotlin.link")
// maven("https://dl.bintray.com/mipt-npm/dev") for dev versions
} }
dependencies { dependencies {
api("kscience.kmath:kmath-core:0.2.0-dev-7") api("space.kscience:kmath-core:0.3.0-dev-3")
// api("kscience.kmath:kmath-core-jvm:0.2.0-dev-7") for jvm-specific version // api("kscience.kmath:kmath-core-jvm:0.3.0-dev-3") for jvm-specific version
} }
``` ```
Gradle `6.0+` is required for multiplatform artifacts. Gradle `6.0+` is required for multiplatform artifacts.
#### Development
Development builds are uploaded to the separate repository:
```kotlin
repositories {
maven("https://dl.bintray.com/mipt-npm/dev")
}
```
## Contributing ## Contributing
The project requires a lot of additional work. The most important thing we need is a feedback about what features are The project requires a lot of additional work. The most important thing we need is a feedback about what features are

View File

@ -1,34 +1,49 @@
import ru.mipt.npm.gradle.KSciencePublishPlugin import org.jetbrains.dokka.gradle.DokkaTask
import ru.mipt.npm.gradle.KSciencePublishingPlugin
import java.net.URL
plugins { plugins {
id("ru.mipt.npm.project") id("ru.mipt.npm.gradle.project")
} }
internal val kmathVersion: String by extra("0.2.0-dev-7")
internal val bintrayRepo: String by extra("kscience")
internal val githubProject: String by extra("kmath")
allprojects { allprojects {
repositories { repositories {
jcenter() jcenter()
maven("https://clojars.org/repo") maven("https://clojars.org/repo")
maven("https://dl.bintray.com/egor-bogomolov/astminer/") maven("https://dl.bintray.com/egor-bogomolov/astminer/")
maven("https://dl.bintray.com/hotkeytlt/maven") maven("https://dl.bintray.com/hotkeytlt/maven")
maven("https://dl.bintray.com/kotlin/kotlin-eap")
maven("https://dl.bintray.com/kotlin/kotlinx")
maven("https://dl.bintray.com/mipt-npm/dev")
maven("https://dl.bintray.com/mipt-npm/kscience")
maven("https://jitpack.io") maven("https://jitpack.io")
maven("http://logicrunch.research.it.uu.se/maven/") maven("http://logicrunch.research.it.uu.se/maven/")
mavenCentral() mavenCentral()
} }
group = "kscience.kmath" group = "space.kscience"
version = kmathVersion version = "0.3.0-dev-4"
} }
subprojects { subprojects {
if (name.startsWith("kmath")) apply<KSciencePublishPlugin>() if (name.startsWith("kmath")) apply<KSciencePublishingPlugin>()
afterEvaluate {
tasks.withType<DokkaTask> {
dokkaSourceSets.all {
val readmeFile = File(this@subprojects.projectDir, "./README.md")
if (readmeFile.exists())
includes.setFrom(includes + readmeFile.absolutePath)
arrayOf(
"http://ejml.org/javadoc/",
"https://commons.apache.org/proper/commons-math/javadocs/api-3.6.1/",
"https://deeplearning4j.org/api/latest/"
).map { URL("${it}package-list") to URL(it) }.forEach { (a, b) ->
externalDocumentationLink {
packageListUrl.set(a)
url.set(b)
}
}
}
}
}
} }
readme { readme {
@ -36,5 +51,11 @@ readme {
} }
ksciencePublish { ksciencePublish {
spaceRepo = "https://maven.pkg.jetbrains.space/mipt-npm/p/sci/maven" github("kmath")
} space()
sonatype()
}
apiValidation {
nonPublicMarkers.add("space.kscience.kmath.misc.UnstableKMathAPI")
}

View File

@ -5,7 +5,7 @@ operation, say `+`, one needs two objects of a type `T` and an algebra context,
say `Space<T>`. Next one needs to run the actual operation in the context: say `Space<T>`. Next one needs to run the actual operation in the context:
```kotlin ```kotlin
import kscience.kmath.operations.* import space.kscience.kmath.operations.*
val a: T = ... val a: T = ...
val b: T = ... val b: T = ...
@ -31,7 +31,7 @@ multiplication;
- [Ring](http://mathworld.wolfram.com/Ring.html) adds multiplication and its neutral element (i.e. 1); - [Ring](http://mathworld.wolfram.com/Ring.html) adds multiplication and its neutral element (i.e. 1);
- [Field](http://mathworld.wolfram.com/Field.html) adds division operation. - [Field](http://mathworld.wolfram.com/Field.html) adds division operation.
A typical implementation of `Field<T>` is the `RealField` which works on doubles, and `VectorSpace` for `Space<T>`. 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 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` interface. Also, contexts may have operations, which produce elements outside of the context. For example, `Matrix.dot`
@ -47,7 +47,7 @@ but it also holds reference to the `ComplexField` singleton, which allows perfor
numbers without explicit involving the context like: numbers without explicit involving the context like:
```kotlin ```kotlin
import kscience.kmath.operations.* import space.kscience.kmath.operations.*
// Using elements // Using elements
val c1 = Complex(1.0, 1.0) val c1 = Complex(1.0, 1.0)
@ -82,7 +82,7 @@ operations in all performance-critical places. The performance of element operat
KMath submits both contexts and elements for builtin algebraic structures: KMath submits both contexts and elements for builtin algebraic structures:
```kotlin ```kotlin
import kscience.kmath.operations.* import space.kscience.kmath.operations.*
val c1 = Complex(1.0, 2.0) val c1 = Complex(1.0, 2.0)
val c2 = ComplexField.i val c2 = ComplexField.i
@ -95,7 +95,7 @@ val c3 = ComplexField { c1 + c2 }
Also, `ComplexField` features special operations to mix complex and real numbers, for example: Also, `ComplexField` features special operations to mix complex and real numbers, for example:
```kotlin ```kotlin
import kscience.kmath.operations.* import space.kscience.kmath.operations.*
val c1 = Complex(1.0, 2.0) val c1 = Complex(1.0, 2.0)
val c2 = ComplexField { c1 - 1.0 } // Returns: Complex(re=0.0, im=2.0) val c2 = ComplexField { c1 - 1.0 } // Returns: Complex(re=0.0, im=2.0)

View File

@ -13,27 +13,30 @@
version="1.1"><metadata version="1.1"><metadata
id="metadata8"><rdf:RDF><cc:Work id="metadata8"><rdf:RDF><cc:Work
rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" /></cc:Work></rdf:RDF></metadata><defs rdf:resource="http://purl.org/dc/dcmitype/StillImage"/></cc:Work></rdf:RDF></metadata>
id="defs6"><clipPath <defs
id="defs6"><clipPath
id="clipPath24" id="clipPath24"
clipPathUnits="userSpaceOnUse"><path clipPathUnits="userSpaceOnUse"><path
id="path22" id="path22"
d="M 0,1590 H 6720 V 4400 H 0 Z" /></clipPath><clipPath d="M 0,1590 H 6720 V 4400 H 0 Z" /></clipPath>
id="clipPath36" <clipPath
clipPathUnits="userSpaceOnUse"><path id="clipPath36"
clipPathUnits="userSpaceOnUse"><path
id="path34" id="path34"
d="M 3410,0 H 6720 V 1590 H 3410 Z" /></clipPath></defs><g d="M 3410,0 H 6720 V 1590 H 3410 Z" /></clipPath></defs>
transform="matrix(1.3333333,0,0,-1.3333333,0,586.66667)" <g
id="g10"><g transform="matrix(1.3333333,0,0,-1.3333333,0,586.66667)"
id="g10"><g
transform="scale(0.1)" transform="scale(0.1)"
id="g12"><path id="g12"><path
id="path14" id="path14"
style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none" style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none"
d="m 1299.34,651.602 h 4653.75 v 3208.87 H 1299.34 Z" /><path d="m 1299.34,651.602 h 4653.75 v 3208.87 H 1299.34 Z" /><path
id="path16" id="path16"
style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none" style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none"
d="m 1651.48,1093.71 h 4076.99 v 114.609 H 1651.48 Z" /><g d="m 1651.48,1093.71 h 4076.99 v 114.609 H 1651.48 Z"/><g
id="g18"><g id="g18"><g
clip-path="url(#clipPath24)" clip-path="url(#clipPath24)"
id="g20"><g id="g20"><g
transform="matrix(6720,0,0,2810.4,0,1589.6)" transform="matrix(6720,0,0,2810.4,0,1589.6)"
@ -45,7 +48,7 @@
style="image-rendering:optimizeSpeed" style="image-rendering:optimizeSpeed"
height="1" height="1"
width="1" /></g></g></g><g width="1" /></g></g></g><g
id="g30"><g id="g30"><g
clip-path="url(#clipPath36)" clip-path="url(#clipPath36)"
id="g32"><g id="g32"><g
transform="matrix(3312,0,0,1591.2,3410,-1.19998)" transform="matrix(3312,0,0,1591.2,3410,-1.19998)"

Before

Width:  |  Height:  |  Size: 248 KiB

After

Width:  |  Height:  |  Size: 248 KiB

View File

@ -13,35 +13,37 @@
version="1.1"><metadata version="1.1"><metadata
id="metadata8"><rdf:RDF><cc:Work id="metadata8"><rdf:RDF><cc:Work
rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" /></cc:Work></rdf:RDF></metadata><defs rdf:resource="http://purl.org/dc/dcmitype/StillImage"/></cc:Work></rdf:RDF></metadata>
id="defs6"><clipPath <defs
id="defs6"><clipPath
id="clipPath32" id="clipPath32"
clipPathUnits="userSpaceOnUse"><path clipPathUnits="userSpaceOnUse"><path
id="path30" id="path30"
d="M 1780,1750 H 3830 V 3800 H 1780 Z" /></clipPath></defs><g d="M 1780,1750 H 3830 V 3800 H 1780 Z" /></clipPath></defs>
transform="matrix(1.3333333,0,0,-1.3333333,0,633.33333)" <g
id="g10"><g transform="matrix(1.3333333,0,0,-1.3333333,0,633.33333)"
id="g10"><g
transform="scale(0.1)" transform="scale(0.1)"
id="g12"><path id="g12"><path
id="path14" id="path14"
style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none" style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none"
d="M 318.789,2616.17 6643.05,4723.79 c 239.45,79.76 496.44,-48.75 576.29,-288.17 79.8,-239.41 -48.72,-496.4 -288.13,-576.21 L 606.949,1751.84 c -239.449,-79.81 -496.437,48.71 -576.2888,288.12 -79.8008,239.45 48.7187,496.45 288.1288,576.21 z" /><path d="M 318.789,2616.17 6643.05,4723.79 c 239.45,79.76 496.44,-48.75 576.29,-288.17 79.8,-239.41 -48.72,-496.4 -288.13,-576.21 L 606.949,1751.84 c -239.449,-79.81 -496.437,48.71 -576.2888,288.12 -79.8008,239.45 48.7187,496.45 288.1288,576.21 z" /><path
id="path16" id="path16"
style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none" style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none"
d="M 3751.56,538.199 6636.91,4443.95 c 109.22,147.89 316.21,178.98 464.11,69.76 147.89,-109.22 178.98,-316.21 69.76,-464.06 L 4285.43,143.91 C 4176.17,-3.98047 3969.18,-35.0781 3821.29,74.1406 3673.44,183.359 3642.3,390.309 3751.56,538.199 Z" /><path d="M 3751.56,538.199 6636.91,4443.95 c 109.22,147.89 316.21,178.98 464.11,69.76 147.89,-109.22 178.98,-316.21 69.76,-464.06 L 4285.43,143.91 C 4176.17,-3.98047 3969.18,-35.0781 3821.29,74.1406 3673.44,183.359 3642.3,390.309 3751.56,538.199 Z"/><path
id="path18" id="path18"
style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none" style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none"
d="M 1400.43,708.48 H 6418.24 V 4168.4 H 1400.43 Z" /><path d="M 1400.43,708.48 H 6418.24 V 4168.4 H 1400.43 Z"/><path
id="path20" id="path20"
style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none" style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none"
d="m 6145.16,1753.83 h -358.6 V 3271.02 L 5158.28,1753.83 H 5005 L 4379.69,3271.02 V 1753.83 h -358.6 v 2044.53 h 505.79 l 554.68,-1345.63 557.97,1345.63 h 505.63 z" /><path d="m 6145.16,1753.83 h -358.6 V 3271.02 L 5158.28,1753.83 H 5005 L 4379.69,3271.02 V 1753.83 h -358.6 v 2044.53 h 505.79 l 554.68,-1345.63 557.97,1345.63 h 505.63 z"/><path
id="path22" id="path22"
style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none" style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none"
d="m 1780.12,1185.24 h 4395.94 v 123.551 H 1780.12 Z" /><path d="m 1780.12,1185.24 h 4395.94 v 123.551 H 1780.12 Z"/><path
id="path24" id="path24"
style="fill:none;stroke:#000000;stroke-width:22.00740051;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" style="fill:none;stroke:#000000;stroke-width:22.00740051;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="m 1780.12,3798.09 c 0,-2044.73 0,-2044.73 0,-2044.73 H 3824.84 L 2806.17,2778.24 3824.84,3798.09" /><g d="m 1780.12,3798.09 c 0,-2044.73 0,-2044.73 0,-2044.73 H 3824.84 L 2806.17,2778.24 3824.84,3798.09"/><g
id="g26"><g id="g26"><g
clip-path="url(#clipPath32)" clip-path="url(#clipPath32)"
id="g28"><g id="g28"><g
transform="matrix(2052,0,0,2052,1780,1748)" transform="matrix(2052,0,0,2052,1780,1748)"

Before

Width:  |  Height:  |  Size: 18 KiB

After

Width:  |  Height:  |  Size: 18 KiB

View File

@ -13,35 +13,40 @@
version="1.1"><metadata version="1.1"><metadata
id="metadata8"><rdf:RDF><cc:Work id="metadata8"><rdf:RDF><cc:Work
rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" /></cc:Work></rdf:RDF></metadata><defs rdf:resource="http://purl.org/dc/dcmitype/StillImage"/></cc:Work></rdf:RDF></metadata>
id="defs6"><clipPath <defs
id="defs6"><clipPath
id="clipPath24" id="clipPath24"
clipPathUnits="userSpaceOnUse"><path clipPathUnits="userSpaceOnUse"><path
id="path22" id="path22"
d="M 0,3010 H 6470 V 4280 H 0 Z" /></clipPath><clipPath d="M 0,3010 H 6470 V 4280 H 0 Z" /></clipPath>
id="clipPath36" <clipPath
clipPathUnits="userSpaceOnUse"><path id="clipPath36"
clipPathUnits="userSpaceOnUse"><path
id="path34" id="path34"
d="M 0,1590 H 7000 V 3010 H 0 Z" /></clipPath><clipPath d="M 0,1590 H 7000 V 3010 H 0 Z" /></clipPath>
id="clipPath48" <clipPath
clipPathUnits="userSpaceOnUse"><path id="clipPath48"
clipPathUnits="userSpaceOnUse"><path
id="path46" id="path46"
d="m 0,1580 h 6470 v 10 H 0 Z" /></clipPath><clipPath d="m 0,1580 h 6470 v 10 H 0 Z" /></clipPath>
id="clipPath60" <clipPath
clipPathUnits="userSpaceOnUse"><path id="clipPath60"
clipPathUnits="userSpaceOnUse"><path
id="path58" id="path58"
d="M 3280,0 H 6460 V 1580 H 3280 Z" /></clipPath></defs><g d="M 3280,0 H 6460 V 1580 H 3280 Z" /></clipPath></defs>
transform="matrix(1.3333333,0,0,-1.3333333,0,570.66667)" <g
id="g10"><g transform="matrix(1.3333333,0,0,-1.3333333,0,570.66667)"
id="g10"><g
transform="scale(0.1)" transform="scale(0.1)"
id="g12"><path id="g12"><path
id="path14" id="path14"
style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none" style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none"
d="m 791.328,957.73 h 6401.56 V 3245.31 H 791.328 Z" /><path d="m 791.328,957.73 h 6401.56 V 3245.31 H 791.328 Z" /><path
id="path16" id="path16"
style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none" style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none"
d="m 1049.45,1214.42 h 2988.24 v 86.9883 H 1049.45 Z" /><g d="m 1049.45,1214.42 h 2988.24 v 86.9883 H 1049.45 Z"/><g
id="g18"><g id="g18"><g
clip-path="url(#clipPath24)" clip-path="url(#clipPath24)"
id="g20"><g id="g20"><g
transform="matrix(6470.4,0,0,1272,0,3008)" transform="matrix(6470.4,0,0,1272,0,3008)"
@ -53,7 +58,7 @@
style="image-rendering:optimizeSpeed" style="image-rendering:optimizeSpeed"
height="1" height="1"
width="1" /></g></g></g><g width="1" /></g></g></g><g
id="g30"><g id="g30"><g
clip-path="url(#clipPath36)" clip-path="url(#clipPath36)"
id="g32"><g id="g32"><g
transform="matrix(7000.8,0,0,1420.8,0,1589.2)" transform="matrix(7000.8,0,0,1420.8,0,1589.2)"
@ -65,7 +70,7 @@
style="image-rendering:optimizeSpeed" style="image-rendering:optimizeSpeed"
height="1" height="1"
width="1" /></g></g></g><g width="1" /></g></g></g><g
id="g42"><g id="g42"><g
clip-path="url(#clipPath48)" clip-path="url(#clipPath48)"
id="g44"><g id="g44"><g
transform="matrix(6470.4,0,0,12,0,1578)" transform="matrix(6470.4,0,0,12,0,1578)"
@ -77,7 +82,7 @@
style="image-rendering:optimizeSpeed" style="image-rendering:optimizeSpeed"
height="1" height="1"
width="1" /></g></g></g><g width="1" /></g></g></g><g
id="g54"><g id="g54"><g
clip-path="url(#clipPath60)" clip-path="url(#clipPath60)"
id="g56"><g id="g56"><g
transform="matrix(3180,0,0,1581.6,3280,-1.59972)" transform="matrix(3180,0,0,1581.6,3280,-1.59972)"

Before

Width:  |  Height:  |  Size: 278 KiB

After

Width:  |  Height:  |  Size: 278 KiB

View File

@ -13,123 +13,144 @@
version="1.1"><metadata version="1.1"><metadata
id="metadata8"><rdf:RDF><cc:Work id="metadata8"><rdf:RDF><cc:Work
rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" /></cc:Work></rdf:RDF></metadata><defs rdf:resource="http://purl.org/dc/dcmitype/StillImage"/></cc:Work></rdf:RDF></metadata>
id="defs6"><clipPath <defs
id="defs6"><clipPath
id="clipPath40" id="clipPath40"
clipPathUnits="userSpaceOnUse"><path clipPathUnits="userSpaceOnUse"><path
id="path38" id="path38"
d="m 2370,2780 h 1370 v 10 H 2370 Z" /></clipPath><clipPath d="m 2370,2780 h 1370 v 10 H 2370 Z" /></clipPath>
id="clipPath52" <clipPath
clipPathUnits="userSpaceOnUse"><path id="clipPath52"
clipPathUnits="userSpaceOnUse"><path
id="path50" id="path50"
d="m 5630,2780 h 860 v 10 h -860 z" /></clipPath><clipPath d="m 5630,2780 h 860 v 10 h -860 z" /></clipPath>
id="clipPath64" <clipPath
clipPathUnits="userSpaceOnUse"><path id="clipPath64"
clipPathUnits="userSpaceOnUse"><path
id="path62" id="path62"
d="m 970,2690 h 1300 v 90 H 970 Z" /></clipPath><clipPath d="m 970,2690 h 1300 v 90 H 970 Z" /></clipPath>
id="clipPath76" <clipPath
clipPathUnits="userSpaceOnUse"><path id="clipPath76"
clipPathUnits="userSpaceOnUse"><path
id="path74" id="path74"
d="m 2370,2690 h 1370 v 90 H 2370 Z" /></clipPath><clipPath d="m 2370,2690 h 1370 v 90 H 2370 Z" /></clipPath>
id="clipPath88" <clipPath
clipPathUnits="userSpaceOnUse"><path id="clipPath88"
clipPathUnits="userSpaceOnUse"><path
id="path86" id="path86"
d="m 5630,2690 h 860 v 90 h -860 z" /></clipPath><clipPath d="m 5630,2690 h 860 v 90 h -860 z" /></clipPath>
id="clipPath100" <clipPath
clipPathUnits="userSpaceOnUse"><path id="clipPath100"
clipPathUnits="userSpaceOnUse"><path
id="path98" id="path98"
d="m 970,2460 h 1300 v 230 H 970 Z" /></clipPath><clipPath d="m 970,2460 h 1300 v 230 H 970 Z" /></clipPath>
id="clipPath112" <clipPath
clipPathUnits="userSpaceOnUse"><path id="clipPath112"
clipPathUnits="userSpaceOnUse"><path
id="path110" id="path110"
d="m 2370,2460 h 1370 v 230 H 2370 Z" /></clipPath><clipPath d="m 2370,2460 h 1370 v 230 H 2370 Z" /></clipPath>
id="clipPath124" <clipPath
clipPathUnits="userSpaceOnUse"><path id="clipPath124"
clipPathUnits="userSpaceOnUse"><path
id="path122" id="path122"
d="m 4900,2460 h 620 v 230 h -620 z" /></clipPath><clipPath d="m 4900,2460 h 620 v 230 h -620 z" /></clipPath>
id="clipPath136" <clipPath
clipPathUnits="userSpaceOnUse"><path id="clipPath136"
clipPathUnits="userSpaceOnUse"><path
id="path134" id="path134"
d="m 5630,2460 h 860 v 230 h -860 z" /></clipPath><clipPath d="m 5630,2460 h 860 v 230 h -860 z" /></clipPath>
id="clipPath148" <clipPath
clipPathUnits="userSpaceOnUse"><path id="clipPath148"
clipPathUnits="userSpaceOnUse"><path
id="path146" id="path146"
d="m 970,1480 h 1300 v 980 H 970 Z" /></clipPath><clipPath d="m 970,1480 h 1300 v 980 H 970 Z" /></clipPath>
id="clipPath160" <clipPath
clipPathUnits="userSpaceOnUse"><path id="clipPath160"
clipPathUnits="userSpaceOnUse"><path
id="path158" id="path158"
d="m 2370,1480 h 1370 v 980 H 2370 Z" /></clipPath><clipPath d="m 2370,1480 h 1370 v 980 H 2370 Z" /></clipPath>
id="clipPath172" <clipPath
clipPathUnits="userSpaceOnUse"><path id="clipPath172"
clipPathUnits="userSpaceOnUse"><path
id="path170" id="path170"
d="m 3920,1480 h 860 v 980 h -860 z" /></clipPath><clipPath d="m 3920,1480 h 860 v 980 h -860 z" /></clipPath>
id="clipPath184" <clipPath
clipPathUnits="userSpaceOnUse"><path id="clipPath184"
clipPathUnits="userSpaceOnUse"><path
id="path182" id="path182"
d="m 4900,1480 h 620 v 980 h -620 z" /></clipPath><clipPath d="m 4900,1480 h 620 v 980 h -620 z" /></clipPath>
id="clipPath196" <clipPath
clipPathUnits="userSpaceOnUse"><path id="clipPath196"
clipPathUnits="userSpaceOnUse"><path
id="path194" id="path194"
d="m 5630,1480 h 860 v 980 h -860 z" /></clipPath><clipPath d="m 5630,1480 h 860 v 980 h -860 z" /></clipPath>
id="clipPath208" <clipPath
clipPathUnits="userSpaceOnUse"><path id="clipPath208"
clipPathUnits="userSpaceOnUse"><path
id="path206" id="path206"
d="m 2370,1470 h 1370 v 10 H 2370 Z" /></clipPath><clipPath d="m 2370,1470 h 1370 v 10 H 2370 Z" /></clipPath>
id="clipPath220" <clipPath
clipPathUnits="userSpaceOnUse"><path id="clipPath220"
clipPathUnits="userSpaceOnUse"><path
id="path218" id="path218"
d="m 3920,1470 h 860 v 10 h -860 z" /></clipPath><clipPath d="m 3920,1470 h 860 v 10 h -860 z" /></clipPath>
id="clipPath232" <clipPath
clipPathUnits="userSpaceOnUse"><path id="clipPath232"
clipPathUnits="userSpaceOnUse"><path
id="path230" id="path230"
d="m 4900,1470 h 620 v 10 h -620 z" /></clipPath><clipPath d="m 4900,1470 h 620 v 10 h -620 z" /></clipPath>
id="clipPath244" <clipPath
clipPathUnits="userSpaceOnUse"><path id="clipPath244"
clipPathUnits="userSpaceOnUse"><path
id="path242" id="path242"
d="m 5630,1470 h 860 v 10 h -860 z" /></clipPath><clipPath d="m 5630,1470 h 860 v 10 h -860 z" /></clipPath>
id="clipPath256" <clipPath
clipPathUnits="userSpaceOnUse"><path id="clipPath256"
clipPathUnits="userSpaceOnUse"><path
id="path254" id="path254"
d="m 3920,1450 h 860 v 20 h -860 z" /></clipPath><clipPath d="m 3920,1450 h 860 v 20 h -860 z" /></clipPath>
id="clipPath268" <clipPath
clipPathUnits="userSpaceOnUse"><path id="clipPath268"
clipPathUnits="userSpaceOnUse"><path
id="path266" id="path266"
d="m 4900,1450 h 620 v 20 h -620 z" /></clipPath></defs><g d="m 4900,1450 h 620 v 20 h -620 z" /></clipPath></defs>
transform="matrix(1.3333333,0,0,-1.3333333,0,529.33333)" <g
id="g10"><g transform="matrix(1.3333333,0,0,-1.3333333,0,529.33333)"
id="g10"><g
transform="scale(0.1)" transform="scale(0.1)"
id="g12"><path id="g12"><path
id="path14" id="path14"
style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none" style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none"
d="M 265.859,2205.39 5500.51,3949.84 c 198.16,66.06 410.9,-40.31 476.99,-238.51 66.05,-198.17 -40.31,-410.86 -238.48,-476.92 L 504.379,1489.96 c -198.168,-66.05 -410.8985,40.31 -476.9571,238.48 -66.0938,198.16 40.2773,410.9 238.4371,476.95 z" /><path d="M 265.859,2205.39 5500.51,3949.84 c 198.16,66.06 410.9,-40.31 476.99,-238.51 66.05,-198.17 -40.31,-410.86 -238.48,-476.92 L 504.379,1489.96 c -198.168,-66.05 -410.8985,40.31 -476.9571,238.48 -66.0938,198.16 40.2773,410.9 238.4371,476.95 z" /><path
id="path16" id="path16"
style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none" style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none"
d="m 3096.33,444.379 2388.2,3232.811 c 90.43,122.38 261.76,148.12 384.18,57.73 122.38,-90.39 148.13,-261.72 57.74,-384.1 L 3538.2,117.969 C 3447.77,-4.41016 3276.45,-30.1602 3154.06,60.2305 3031.64,150.66 3005.9,321.949 3096.33,444.379 Z" /><path d="m 3096.33,444.379 2388.2,3232.811 c 90.43,122.38 261.76,148.12 384.18,57.73 122.38,-90.39 148.13,-261.72 57.74,-384.1 L 3538.2,117.969 C 3447.77,-4.41016 3276.45,-30.1602 3154.06,60.2305 3031.64,150.66 3005.9,321.949 3096.33,444.379 Z"/><path
id="path18" id="path18"
style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none" style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none"
d="m 734.691,901.211 h 5982.5 v 2109.69 h -5982.5 z" /><path d="m 734.691,901.211 h 5982.5 v 2109.69 h -5982.5 z"/><path
id="path20" id="path20"
style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none" style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none"
d="m 3724.45,1489.53 h -225.93 v 956.09 l -395.94,-956.09 h -96.56 l -394.07,956.09 v -956.09 h -225.93 v 1288.28 h 318.59 l 349.69,-847.97 351.4,847.97 h 318.75 z" /><path d="m 3724.45,1489.53 h -225.93 v 956.09 l -395.94,-956.09 h -96.56 l -394.07,956.09 v -956.09 h -225.93 v 1288.28 h 318.59 l 349.69,-847.97 351.4,847.97 h 318.75 z"/><path
id="path22" id="path22"
style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none" style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none"
d="M 4767.23,1489.53 H 4564.41 V 1590 c -72.11,-82.42 -172.5,-123.59 -301.25,-123.59 -85,0 -160.39,27.34 -226.09,82.03 -65.62,54.68 -98.44,130.31 -98.44,226.87 0,99.14 32.5,174.46 97.5,225.94 65.08,51.56 140.78,77.34 227.03,77.34 132.58,0 233.01,-39.92 301.25,-119.68 v 139.06 c 0,54.06 -19.96,96.48 -59.84,127.34 -39.92,30.94 -92.73,46.41 -158.44,46.41 -104.29,0 -196.33,-39.3 -276.09,-117.81 L 3986.91,2295 c 105.63,100.39 236.29,150.62 392.04,150.62 114.68,0 208.04,-27.1 280.15,-81.24 72.07,-54.07 108.13,-139.65 108.13,-256.72 z m -424.85,115.94 c 101.64,0 175.67,32.19 222.03,96.56 v 140.94 c -46.36,64.37 -120.39,96.56 -222.03,96.56 -58.04,0 -105.74,-15.47 -143.12,-46.41 -37.31,-30.85 -55.94,-71.36 -55.94,-121.56 0,-50.23 18.63,-90.47 55.94,-120.78 37.38,-30.23 85.08,-45.31 143.12,-45.31 z" /><path d="M 4767.23,1489.53 H 4564.41 V 1590 c -72.11,-82.42 -172.5,-123.59 -301.25,-123.59 -85,0 -160.39,27.34 -226.09,82.03 -65.62,54.68 -98.44,130.31 -98.44,226.87 0,99.14 32.5,174.46 97.5,225.94 65.08,51.56 140.78,77.34 227.03,77.34 132.58,0 233.01,-39.92 301.25,-119.68 v 139.06 c 0,54.06 -19.96,96.48 -59.84,127.34 -39.92,30.94 -92.73,46.41 -158.44,46.41 -104.29,0 -196.33,-39.3 -276.09,-117.81 L 3986.91,2295 c 105.63,100.39 236.29,150.62 392.04,150.62 114.68,0 208.04,-27.1 280.15,-81.24 72.07,-54.07 108.13,-139.65 108.13,-256.72 z m -424.85,115.94 c 101.64,0 175.67,32.19 222.03,96.56 v 140.94 c -46.36,64.37 -120.39,96.56 -222.03,96.56 -58.04,0 -105.74,-15.47 -143.12,-46.41 -37.31,-30.85 -55.94,-71.36 -55.94,-121.56 0,-50.23 18.63,-90.47 55.94,-120.78 37.38,-30.23 85.08,-45.31 143.12,-45.31 z"/><path
id="path24" id="path24"
style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none" style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none"
d="m 5308.32,1466.41 c -78.55,0 -138.12,20.58 -178.75,61.71 -40.55,41.26 -60.78,100.47 -60.78,177.66 v 538.91 h -154.53 v 177.65 h 154.53 v 255 h 202.81 v -255 h 189.22 V 2244.69 H 5271.6 v -488.6 c 0,-33.55 7.7,-60.31 23.13,-80.31 15.5,-19.92 37.42,-29.84 65.78,-29.84 41.13,0 71.4,10.94 90.78,32.81 l 48.28,-152.5 c -42.5,-39.88 -106.25,-59.84 -191.25,-59.84 z" /><path d="m 5308.32,1466.41 c -78.55,0 -138.12,20.58 -178.75,61.71 -40.55,41.26 -60.78,100.47 -60.78,177.66 v 538.91 h -154.53 v 177.65 h 154.53 v 255 h 202.81 v -255 h 189.22 V 2244.69 H 5271.6 v -488.6 c 0,-33.55 7.7,-60.31 23.13,-80.31 15.5,-19.92 37.42,-29.84 65.78,-29.84 41.13,0 71.4,10.94 90.78,32.81 l 48.28,-152.5 c -42.5,-39.88 -106.25,-59.84 -191.25,-59.84 z"/><path
id="path26" id="path26"
style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none" style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none"
d="m 6477.38,1489.53 h -202.65 v 587.19 c 0,68.2 -16.49,116.8 -49.38,145.78 -32.81,28.95 -79.49,43.44 -140,43.44 -47.62,0 -92.65,-12.27 -135.15,-36.72 -42.5,-24.49 -77.31,-54.06 -104.38,-88.75 v -650.94 h -202.66 v 1288.28 h 202.66 V 2295 c 34.77,41.13 81.45,76.48 140,106.09 58.63,29.69 122.07,44.53 190.31,44.53 200.82,0 301.25,-98.55 301.25,-295.62 z" /><path d="m 6477.38,1489.53 h -202.65 v 587.19 c 0,68.2 -16.49,116.8 -49.38,145.78 -32.81,28.95 -79.49,43.44 -140,43.44 -47.62,0 -92.65,-12.27 -135.15,-36.72 -42.5,-24.49 -77.31,-54.06 -104.38,-88.75 v -650.94 h -202.66 v 1288.28 h 202.66 V 2295 c 34.77,41.13 81.45,76.48 140,106.09 58.63,29.69 122.07,44.53 190.31,44.53 200.82,0 301.25,-98.55 301.25,-295.62 z"/><path
id="path28" id="path28"
style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none" style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none"
d="m 973.949,1128.48 h 2769.84 v 80.6211 H 973.949 Z" /><path d="m 973.949,1128.48 h 2769.84 v 80.6211 H 973.949 Z"/><path
id="path30" id="path30"
style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none" style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none"
d="m 978.828,2781.72 c 0,-1292.5 0,-1292.5 0,-1292.5 H 2262.3 l -639.45,647.85 639.45,644.65" /><path d="m 978.828,2781.72 c 0,-1292.5 0,-1292.5 0,-1292.5 H 2262.3 l -639.45,647.85 639.45,644.65"/><path
id="path32" id="path32"
style="fill:none;stroke:#000000;stroke-width:13.86260033;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" style="fill:none;stroke:#000000;stroke-width:13.86260033;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="m 978.828,2781.72 c 0,-1292.5 0,-1292.5 0,-1292.5 H 2262.3 l -639.45,647.85 639.45,644.65" /><g d="m 978.828,2781.72 c 0,-1292.5 0,-1292.5 0,-1292.5 H 2262.3 l -639.45,647.85 639.45,644.65"/><g
id="g34"><g id="g34"><g
clip-path="url(#clipPath40)" clip-path="url(#clipPath40)"
id="g36"><g id="g36"><g
transform="matrix(1370.4,0,0,12,2370,2778)" transform="matrix(1370.4,0,0,12,2370,2778)"
@ -141,7 +162,7 @@
style="image-rendering:optimizeSpeed" style="image-rendering:optimizeSpeed"
height="1" height="1"
width="1" /></g></g></g><g width="1" /></g></g></g><g
id="g46"><g id="g46"><g
clip-path="url(#clipPath52)" clip-path="url(#clipPath52)"
id="g48"><g id="g48"><g
transform="matrix(861.6,0,0,12,5630,2778)" transform="matrix(861.6,0,0,12,5630,2778)"
@ -153,7 +174,7 @@
style="image-rendering:optimizeSpeed" style="image-rendering:optimizeSpeed"
height="1" height="1"
width="1" /></g></g></g><g width="1" /></g></g></g><g
id="g58"><g id="g58"><g
clip-path="url(#clipPath64)" clip-path="url(#clipPath64)"
id="g60"><g id="g60"><g
transform="matrix(1300.8,0,0,91.2,970,2688.8)" transform="matrix(1300.8,0,0,91.2,970,2688.8)"
@ -165,7 +186,7 @@
style="image-rendering:optimizeSpeed" style="image-rendering:optimizeSpeed"
height="1" height="1"
width="1" /></g></g></g><g width="1" /></g></g></g><g
id="g70"><g id="g70"><g
clip-path="url(#clipPath76)" clip-path="url(#clipPath76)"
id="g72"><g id="g72"><g
transform="matrix(1370.4,0,0,91.2,2370,2688.8)" transform="matrix(1370.4,0,0,91.2,2370,2688.8)"
@ -177,7 +198,7 @@
style="image-rendering:optimizeSpeed" style="image-rendering:optimizeSpeed"
height="1" height="1"
width="1" /></g></g></g><g width="1" /></g></g></g><g
id="g82"><g id="g82"><g
clip-path="url(#clipPath88)" clip-path="url(#clipPath88)"
id="g84"><g id="g84"><g
transform="matrix(861.6,0,0,91.2,5630,2688.8)" transform="matrix(861.6,0,0,91.2,5630,2688.8)"
@ -189,7 +210,7 @@
style="image-rendering:optimizeSpeed" style="image-rendering:optimizeSpeed"
height="1" height="1"
width="1" /></g></g></g><g width="1" /></g></g></g><g
id="g94"><g id="g94"><g
clip-path="url(#clipPath100)" clip-path="url(#clipPath100)"
id="g96"><g id="g96"><g
transform="matrix(1300.8,0,0,230.4,970,2459.6)" transform="matrix(1300.8,0,0,230.4,970,2459.6)"
@ -201,7 +222,7 @@
style="image-rendering:optimizeSpeed" style="image-rendering:optimizeSpeed"
height="1" height="1"
width="1" /></g></g></g><g width="1" /></g></g></g><g
id="g106"><g id="g106"><g
clip-path="url(#clipPath112)" clip-path="url(#clipPath112)"
id="g108"><g id="g108"><g
transform="matrix(1370.4,0,0,230.4,2370,2459.6)" transform="matrix(1370.4,0,0,230.4,2370,2459.6)"
@ -213,7 +234,7 @@
style="image-rendering:optimizeSpeed" style="image-rendering:optimizeSpeed"
height="1" height="1"
width="1" /></g></g></g><g width="1" /></g></g></g><g
id="g118"><g id="g118"><g
clip-path="url(#clipPath124)" clip-path="url(#clipPath124)"
id="g120"><g id="g120"><g
transform="matrix(621.6,0,0,230.4,4900,2459.6)" transform="matrix(621.6,0,0,230.4,4900,2459.6)"
@ -225,7 +246,7 @@
style="image-rendering:optimizeSpeed" style="image-rendering:optimizeSpeed"
height="1" height="1"
width="1" /></g></g></g><g width="1" /></g></g></g><g
id="g130"><g id="g130"><g
clip-path="url(#clipPath136)" clip-path="url(#clipPath136)"
id="g132"><g id="g132"><g
transform="matrix(861.6,0,0,230.4,5630,2459.6)" transform="matrix(861.6,0,0,230.4,5630,2459.6)"
@ -237,7 +258,7 @@
style="image-rendering:optimizeSpeed" style="image-rendering:optimizeSpeed"
height="1" height="1"
width="1" /></g></g></g><g width="1" /></g></g></g><g
id="g142"><g id="g142"><g
clip-path="url(#clipPath148)" clip-path="url(#clipPath148)"
id="g144"><g id="g144"><g
transform="matrix(1300.8,0,0,981.6,970,1478.4)" transform="matrix(1300.8,0,0,981.6,970,1478.4)"
@ -249,7 +270,7 @@
style="image-rendering:optimizeSpeed" style="image-rendering:optimizeSpeed"
height="1" height="1"
width="1" /></g></g></g><g width="1" /></g></g></g><g
id="g154"><g id="g154"><g
clip-path="url(#clipPath160)" clip-path="url(#clipPath160)"
id="g156"><g id="g156"><g
transform="matrix(1370.4,0,0,981.6,2370,1478.4)" transform="matrix(1370.4,0,0,981.6,2370,1478.4)"
@ -261,7 +282,7 @@
style="image-rendering:optimizeSpeed" style="image-rendering:optimizeSpeed"
height="1" height="1"
width="1" /></g></g></g><g width="1" /></g></g></g><g
id="g166"><g id="g166"><g
clip-path="url(#clipPath172)" clip-path="url(#clipPath172)"
id="g168"><g id="g168"><g
transform="matrix(861.6,0,0,981.6,3920,1478.4)" transform="matrix(861.6,0,0,981.6,3920,1478.4)"
@ -273,7 +294,7 @@
style="image-rendering:optimizeSpeed" style="image-rendering:optimizeSpeed"
height="1" height="1"
width="1" /></g></g></g><g width="1" /></g></g></g><g
id="g178"><g id="g178"><g
clip-path="url(#clipPath184)" clip-path="url(#clipPath184)"
id="g180"><g id="g180"><g
transform="matrix(621.6,0,0,981.6,4900,1478.4)" transform="matrix(621.6,0,0,981.6,4900,1478.4)"
@ -285,7 +306,7 @@
style="image-rendering:optimizeSpeed" style="image-rendering:optimizeSpeed"
height="1" height="1"
width="1" /></g></g></g><g width="1" /></g></g></g><g
id="g190"><g id="g190"><g
clip-path="url(#clipPath196)" clip-path="url(#clipPath196)"
id="g192"><g id="g192"><g
transform="matrix(861.6,0,0,981.6,5630,1478.4)" transform="matrix(861.6,0,0,981.6,5630,1478.4)"
@ -297,7 +318,7 @@
style="image-rendering:optimizeSpeed" style="image-rendering:optimizeSpeed"
height="1" height="1"
width="1" /></g></g></g><g width="1" /></g></g></g><g
id="g202"><g id="g202"><g
clip-path="url(#clipPath208)" clip-path="url(#clipPath208)"
id="g204"><g id="g204"><g
transform="matrix(1370.4,0,0,12,2370,1468)" transform="matrix(1370.4,0,0,12,2370,1468)"
@ -309,7 +330,7 @@
style="image-rendering:optimizeSpeed" style="image-rendering:optimizeSpeed"
height="1" height="1"
width="1" /></g></g></g><g width="1" /></g></g></g><g
id="g214"><g id="g214"><g
clip-path="url(#clipPath220)" clip-path="url(#clipPath220)"
id="g216"><g id="g216"><g
transform="matrix(861.6,0,0,12,3920,1468)" transform="matrix(861.6,0,0,12,3920,1468)"
@ -321,7 +342,7 @@
style="image-rendering:optimizeSpeed" style="image-rendering:optimizeSpeed"
height="1" height="1"
width="1" /></g></g></g><g width="1" /></g></g></g><g
id="g226"><g id="g226"><g
clip-path="url(#clipPath232)" clip-path="url(#clipPath232)"
id="g228"><g id="g228"><g
transform="matrix(621.6,0,0,12,4900,1468)" transform="matrix(621.6,0,0,12,4900,1468)"
@ -333,7 +354,7 @@
style="image-rendering:optimizeSpeed" style="image-rendering:optimizeSpeed"
height="1" height="1"
width="1" /></g></g></g><g width="1" /></g></g></g><g
id="g238"><g id="g238"><g
clip-path="url(#clipPath244)" clip-path="url(#clipPath244)"
id="g240"><g id="g240"><g
transform="matrix(861.6,0,0,12,5630,1468)" transform="matrix(861.6,0,0,12,5630,1468)"
@ -345,7 +366,7 @@
style="image-rendering:optimizeSpeed" style="image-rendering:optimizeSpeed"
height="1" height="1"
width="1" /></g></g></g><g width="1" /></g></g></g><g
id="g250"><g id="g250"><g
clip-path="url(#clipPath256)" clip-path="url(#clipPath256)"
id="g252"><g id="g252"><g
transform="matrix(861.6,0,0,21.6,3920,1448.4)" transform="matrix(861.6,0,0,21.6,3920,1448.4)"
@ -357,7 +378,7 @@
style="image-rendering:optimizeSpeed" style="image-rendering:optimizeSpeed"
height="1" height="1"
width="1" /></g></g></g><g width="1" /></g></g></g><g
id="g262"><g id="g262"><g
clip-path="url(#clipPath268)" clip-path="url(#clipPath268)"
id="g264"><g id="g264"><g
transform="matrix(621.6,0,0,21.6,4900,1448.4)" transform="matrix(621.6,0,0,21.6,4900,1448.4)"

Before

Width:  |  Height:  |  Size: 117 KiB

After

Width:  |  Height:  |  Size: 117 KiB

View File

@ -10,11 +10,11 @@ structures. In `kmath` performance depends on which particular context was used
Let us consider following contexts: Let us consider following contexts:
```kotlin ```kotlin
// automatically build context most suited for given type. // automatically build context most suited for given type.
val autoField = NDField.auto(RealField, dim, dim) 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) val specializedField = NDField.real(dim, dim)
//A generic boxing field. It should be used for objects, not primitives. //A generic boxing field. It should be used for objects, not primitives.
val genericField = NDField.buffered(RealField, dim, dim) 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:

View File

@ -1,37 +1,28 @@
> #### Artifact: ## Artifact:
>
> This module artifact: `${group}:${name}:${version}`. The Maven coordinates of this project are `${group}:${name}:${version}`.
>
> Bintray release version: [ ![Download](https://api.bintray.com/packages/mipt-npm/kscience/${name}/images/download.svg) ](https://bintray.com/mipt-npm/kscience/${name}/_latestVersion) **Gradle:**
> ```gradle
> Bintray development version: [ ![Download](https://api.bintray.com/packages/mipt-npm/dev/${name}/images/download.svg) ](https://bintray.com/mipt-npm/dev/${name}/_latestVersion) repositories {
> maven { url 'https://repo.kotlin.link' }
> **Gradle:** maven { url 'https://dl.bintray.com/hotkeytlt/maven' }
> maven { url "https://dl.bintray.com/kotlin/kotlin-eap" } // include for builds based on kotlin-eap
> ```gradle }
> repositories {
> maven { url "https://dl.bintray.com/kotlin/kotlin-eap" } dependencies {
> maven { url 'https://dl.bintray.com/mipt-npm/kscience' } implementation '${group}:${name}:${version}'
> maven { url 'https://dl.bintray.com/mipt-npm/dev' } }
> maven { url 'https://dl.bintray.com/hotkeytlt/maven' } ```
> **Gradle Kotlin DSL:**
> } ```kotlin
> repositories {
> dependencies { maven("https://repo.kotlin.link")
> implementation '${group}:${name}:${version}' maven("https://dl.bintray.com/kotlin/kotlin-eap") // include for builds based on kotlin-eap
> } maven("https://dl.bintray.com/hotkeytlt/maven") // required for a
> ``` }
> **Gradle Kotlin DSL:**
> dependencies {
> ```kotlin implementation("${group}:${name}:${version}")
> repositories { }
> maven("https://dl.bintray.com/kotlin/kotlin-eap") ```
> maven("https://dl.bintray.com/mipt-npm/kscience")
> maven("https://dl.bintray.com/mipt-npm/dev")
> maven("https://dl.bintray.com/hotkeytlt/maven")
> }
>
> dependencies {
> implementation("${group}:${name}:${version}")
> }
> ```

View File

@ -1,11 +1,8 @@
[![JetBrains Research](https://jb.gg/badges/research.svg)](https://confluence.jetbrains.com/display/ALL/JetBrains+on+GitHub) [![JetBrains Research](https://jb.gg/badges/research.svg)](https://confluence.jetbrains.com/display/ALL/JetBrains+on+GitHub)
[![DOI](https://zenodo.org/badge/129486382.svg)](https://zenodo.org/badge/latestdoi/129486382) [![DOI](https://zenodo.org/badge/129486382.svg)](https://zenodo.org/badge/latestdoi/129486382)
![Gradle build](https://github.com/mipt-npm/kmath/workflows/Gradle%20build/badge.svg) ![Gradle build](https://github.com/mipt-npm/kmath/workflows/Gradle%20build/badge.svg)
[![Maven Central](https://img.shields.io/maven-central/v/space.kscience/kmath-core.svg?label=Maven%20Central)](https://search.maven.org/search?q=g:%22space.kscience%22)
Bintray: [ ![Download](https://api.bintray.com/packages/mipt-npm/kscience/kmath-core/images/download.svg) ](https://bintray.com/mipt-npm/kscience/kmath-core/_latestVersion) [![Space](https://img.shields.io/maven-metadata/v?label=Space&metadataUrl=https%3A%2F%2Fmaven.pkg.jetbrains.space%2Fmipt-npm%2Fp%2Fsci%2Fmaven%2Fkscience%2Fkmath%2Fkmath-core%2Fmaven-metadata.xml)](https://maven.pkg.jetbrains.space/mipt-npm/p/sci/maven/space/kscience/)
Bintray-dev: [ ![Download](https://api.bintray.com/packages/mipt-npm/dev/kmath-core/images/download.svg) ](https://bintray.com/mipt-npm/dev/kmath-core/_latestVersion)
# KMath # KMath
@ -97,33 +94,22 @@ better than SciPy.
### Repositories ### Repositories
Release artifacts are accessible from bintray with following configuration (see documentation of 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): [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 ```kotlin
repositories { repositories {
maven("https://dl.bintray.com/mipt-npm/kscience") maven("https://repo.kotlin.link")
// maven("https://dl.bintray.com/mipt-npm/dev") for dev versions
} }
dependencies { dependencies {
api("kscience.kmath:kmath-core:$version") api("${group}:kmath-core:$version")
// api("kscience.kmath:kmath-core-jvm:$version") for jvm-specific version // api("kscience.kmath:kmath-core-jvm:$version") for jvm-specific version
} }
``` ```
Gradle `6.0+` is required for multiplatform artifacts. Gradle `6.0+` is required for multiplatform artifacts.
#### Development
Development builds are uploaded to the separate repository:
```kotlin
repositories {
maven("https://dl.bintray.com/mipt-npm/dev")
}
```
## Contributing ## Contributing
The project requires a lot of additional work. The most important thing we need is a feedback about what features are The project requires a lot of additional work. The most important thing we need is a feedback about what features are

View File

@ -1,7 +1,6 @@
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
plugins { plugins {
java
kotlin("jvm") kotlin("jvm")
kotlin("plugin.allopen") kotlin("plugin.allopen")
id("kotlinx.benchmark") id("kotlinx.benchmark")
@ -12,6 +11,7 @@ sourceSets.register("benchmarks")
repositories { repositories {
jcenter() jcenter()
maven("https://repo.kotlin.link")
maven("https://clojars.org/repo") maven("https://clojars.org/repo")
maven("https://dl.bintray.com/egor-bogomolov/astminer/") maven("https://dl.bintray.com/egor-bogomolov/astminer/")
maven("https://dl.bintray.com/hotkeytlt/maven") maven("https://dl.bintray.com/hotkeytlt/maven")
@ -69,6 +69,14 @@ benchmark {
targets.register("benchmarks") targets.register("benchmarks")
// This one matches sourceSet name above // This one matches sourceSet name above
configurations.register("buffer") {
warmups = 1 // number of warmup iterations
iterations = 3 // number of iterations
iterationTime = 500 // time in seconds per iteration
iterationTimeUnit = "ms" // time unity for iterationTime, default is seconds
include("BufferBenchmark")
}
configurations.register("dot") { configurations.register("dot") {
warmups = 1 // number of warmup iterations warmups = 1 // number of warmup iterations
iterations = 3 // number of iterations iterations = 3 // number of iterations
@ -76,6 +84,22 @@ benchmark {
iterationTimeUnit = "ms" // time unity for iterationTime, default is seconds iterationTimeUnit = "ms" // time unity for iterationTime, default is seconds
include("DotBenchmark") include("DotBenchmark")
} }
configurations.register("expressions") {
warmups = 1 // number of warmup iterations
iterations = 3 // number of iterations
iterationTime = 500 // time in seconds per iteration
iterationTimeUnit = "ms" // time unity for iterationTime, default is seconds
include("ExpressionsInterpretersBenchmark")
}
configurations.register("matrixInverse") {
warmups = 1 // number of warmup iterations
iterations = 3 // number of iterations
iterationTime = 500 // time in seconds per iteration
iterationTimeUnit = "ms" // time unity for iterationTime, default is seconds
include("MatrixInverseBenchmark")
}
} }
kotlin.sourceSets.all { kotlin.sourceSets.all {
@ -89,6 +113,6 @@ tasks.withType<KotlinCompile> {
kotlinOptions.jvmTarget = "11" kotlinOptions.jvmTarget = "11"
} }
readme{ readme {
maturity = ru.mipt.npm.gradle.Maturity.EXPERIMENTAL maturity = ru.mipt.npm.gradle.Maturity.EXPERIMENTAL
} }

View File

@ -1,34 +0,0 @@
package kscience.kmath.benchmarks
import org.openjdk.jmh.annotations.Benchmark
import org.openjdk.jmh.annotations.Scope
import org.openjdk.jmh.annotations.State
import java.nio.IntBuffer
@State(Scope.Benchmark)
internal class ArrayBenchmark {
@Benchmark
fun benchmarkArrayRead() {
var res = 0
for (i in 1..size) res += array[size - i]
}
@Benchmark
fun benchmarkBufferRead() {
var res = 0
for (i in 1..size) res += arrayBuffer[size - i]
}
@Benchmark
fun nativeBufferRead() {
var res = 0
for (i in 1..size) res += nativeBuffer[size - i]
}
companion object {
const val size: Int = 1000
val array: IntArray = IntArray(size) { it }
val arrayBuffer: IntBuffer = IntBuffer.wrap(array)
val nativeBuffer: IntBuffer = IntBuffer.allocate(size).also { for (i in 0 until size) it.put(i, i) }
}
}

View File

@ -1,34 +0,0 @@
package kscience.kmath.benchmarks
import kscience.kmath.complex.Complex
import kscience.kmath.complex.complex
import kscience.kmath.structures.MutableBuffer
import kscience.kmath.structures.RealBuffer
import org.openjdk.jmh.annotations.Benchmark
import org.openjdk.jmh.annotations.Scope
import org.openjdk.jmh.annotations.State
@State(Scope.Benchmark)
internal class BufferBenchmark {
@Benchmark
fun genericRealBufferReadWrite() {
val buffer = RealBuffer(size) { it.toDouble() }
(0 until size).forEach {
buffer[it]
}
}
@Benchmark
fun complexBufferReadWrite() {
val buffer = MutableBuffer.complex(size / 2) { Complex(it.toDouble(), -it.toDouble()) }
(0 until size / 2).forEach {
buffer[it]
}
}
companion object {
const val size: Int = 100
}
}

View File

@ -1,67 +0,0 @@
package kscience.kmath.benchmarks
import kotlinx.benchmark.Benchmark
import kscience.kmath.commons.linear.CMMatrixContext
import kscience.kmath.ejml.EjmlMatrixContext
import kscience.kmath.linear.BufferMatrixContext
import kscience.kmath.linear.Matrix
import kscience.kmath.linear.RealMatrixContext
import kscience.kmath.operations.RealField
import kscience.kmath.operations.invoke
import kscience.kmath.structures.Buffer
import org.openjdk.jmh.annotations.Scope
import org.openjdk.jmh.annotations.State
import kotlin.random.Random
@State(Scope.Benchmark)
internal class DotBenchmark {
companion object {
val random = Random(12224)
val dim = 1000
//creating invertible matrix
val matrix1 = Matrix.real(dim, dim) { i, j -> if (i <= j) random.nextDouble() else 0.0 }
val matrix2 = Matrix.real(dim, dim) { i, j -> if (i <= j) random.nextDouble() else 0.0 }
val cmMatrix1 = CMMatrixContext { matrix1.toCM() }
val cmMatrix2 = CMMatrixContext { matrix2.toCM() }
val ejmlMatrix1 = EjmlMatrixContext { matrix1.toEjml() }
val ejmlMatrix2 = EjmlMatrixContext { matrix2.toEjml() }
}
@Benchmark
fun cmDot() {
CMMatrixContext {
cmMatrix1 dot cmMatrix2
}
}
@Benchmark
fun ejmlDot() {
EjmlMatrixContext {
ejmlMatrix1 dot ejmlMatrix2
}
}
@Benchmark
fun ejmlDotWithConversion() {
EjmlMatrixContext {
matrix1 dot matrix2
}
}
@Benchmark
fun bufferedDot() {
BufferMatrixContext(RealField, Buffer.Companion::real).invoke {
matrix1 dot matrix2
}
}
@Benchmark
fun realDot() {
RealMatrixContext {
matrix1 dot matrix2
}
}
}

View File

@ -1,65 +0,0 @@
package kscience.kmath.benchmarks
import kscience.kmath.asm.compile
import kscience.kmath.ast.MstField
import kscience.kmath.ast.mstInField
import kscience.kmath.expressions.Expression
import kscience.kmath.expressions.expressionInField
import kscience.kmath.expressions.invoke
import kscience.kmath.expressions.symbol
import kscience.kmath.operations.Field
import kscience.kmath.operations.RealField
import org.openjdk.jmh.annotations.Benchmark
import org.openjdk.jmh.annotations.Scope
import org.openjdk.jmh.annotations.State
import kotlin.random.Random
@State(Scope.Benchmark)
internal class ExpressionsInterpretersBenchmark {
private val algebra: Field<Double> = RealField
@Benchmark
fun functionalExpression() {
val expr = algebra.expressionInField {
symbol("x") * const(2.0) + const(2.0) / symbol("x") - const(16.0)
}
invokeAndSum(expr)
}
@Benchmark
fun mstExpression() {
val expr = algebra.mstInField {
symbol("x") * 2.0 + 2.0 / symbol("x") - 16.0
}
invokeAndSum(expr)
}
@Benchmark
fun asmExpression() {
val expr = algebra.mstInField {
MstField.symbol("x") * 2.0 + 2.0 / MstField.symbol("x") - 16.0
}.compile()
invokeAndSum(expr)
}
@Benchmark
fun rawExpression() {
val x by symbol
val expr = Expression<Double> { args -> args.getValue(x) * 2.0 + 2.0 / args.getValue(x) - 16.0 }
invokeAndSum(expr)
}
private fun invokeAndSum(expr: Expression<Double>) {
val random = Random(0)
var sum = 0.0
repeat(1000000) {
sum += expr("x" to random.nextDouble())
}
println(sum)
}
}

View File

@ -1,48 +0,0 @@
package kscience.kmath.benchmarks
import kotlinx.benchmark.Benchmark
import kscience.kmath.commons.linear.CMMatrixContext
import kscience.kmath.commons.linear.CMMatrixContext.dot
import kscience.kmath.commons.linear.inverse
import kscience.kmath.ejml.EjmlMatrixContext
import kscience.kmath.ejml.inverse
import kscience.kmath.linear.Matrix
import kscience.kmath.linear.MatrixContext
import kscience.kmath.linear.inverseWithLup
import kscience.kmath.linear.real
import kscience.kmath.operations.invoke
import org.openjdk.jmh.annotations.Scope
import org.openjdk.jmh.annotations.State
import kotlin.random.Random
@State(Scope.Benchmark)
internal class LinearAlgebraBenchmark {
companion object {
val random = Random(1224)
val dim = 100
//creating invertible matrix
val u = Matrix.real(dim, dim) { i, j -> if (i <= j) random.nextDouble() else 0.0 }
val l = Matrix.real(dim, dim) { i, j -> if (i >= j) random.nextDouble() else 0.0 }
val matrix = l dot u
}
@Benchmark
fun kmathLupInversion() {
MatrixContext.real.inverseWithLup(matrix)
}
@Benchmark
fun cmLUPInversion() {
CMMatrixContext {
inverse(matrix)
}
}
@Benchmark
fun ejmlInverse() {
EjmlMatrixContext {
inverse(matrix)
}
}
}

View File

@ -1,45 +0,0 @@
package kscience.kmath.benchmarks
import kscience.kmath.nd.*
import kscience.kmath.operations.RealField
import kscience.kmath.operations.invoke
import kscience.kmath.structures.Buffer
import org.openjdk.jmh.annotations.Benchmark
import org.openjdk.jmh.annotations.Scope
import org.openjdk.jmh.annotations.State
@State(Scope.Benchmark)
internal class NDFieldBenchmark {
@Benchmark
fun autoFieldAdd() {
autoField {
var res: NDStructure<Double> = one
repeat(n) { res += one }
}
}
@Benchmark
fun specializedFieldAdd() {
specializedField {
var res: NDStructure<Double> = one
repeat(n) { res += 1.0 }
}
}
@Benchmark
fun boxingFieldAdd() {
genericField {
var res: NDStructure<Double> = one
repeat(n) { res += 1.0 }
}
}
companion object {
const val dim: Int = 1000
const val n: Int = 100
val autoField = NDAlgebra.auto(RealField, dim, dim)
val specializedField: RealNDField = NDAlgebra.real(dim, dim)
val genericField = NDAlgebra.field(RealField, Buffer.Companion::boxing, dim, dim)
}
}

View File

@ -1,52 +0,0 @@
package kscience.kmath.benchmarks
import kscience.kmath.nd.*
import kscience.kmath.operations.RealField
import kscience.kmath.operations.invoke
import kscience.kmath.viktor.ViktorNDField
import org.jetbrains.bio.viktor.F64Array
import org.openjdk.jmh.annotations.Benchmark
import org.openjdk.jmh.annotations.Scope
import org.openjdk.jmh.annotations.State
@State(Scope.Benchmark)
internal class ViktorBenchmark {
final val dim: Int = 1000
final val n: Int = 100
// automatically build context most suited for given type.
final val autoField: NDField<Double, RealField> = NDAlgebra.auto(RealField, dim, dim)
final val realField: RealNDField = NDAlgebra.real(dim, dim)
final val viktorField: ViktorNDField = ViktorNDField(dim, dim)
@Benchmark
fun automaticFieldAddition() {
autoField {
var res: NDStructure<Double> = one
repeat(n) { res += 1.0 }
}
}
@Benchmark
fun realFieldAddition() {
realField {
var res: NDStructure<Double> = one
repeat(n) { res += 1.0 }
}
}
@Benchmark
fun viktorFieldAddition() {
viktorField {
var res = one
repeat(n) { res += 1.0 }
}
}
@Benchmark
fun rawViktor() {
val one = F64Array.full(init = 1.0, shape = intArrayOf(dim, dim))
var res = one
repeat(n) { res = res + one }
}
}

View File

@ -1,49 +0,0 @@
package kscience.kmath.benchmarks
import kscience.kmath.nd.*
import kscience.kmath.operations.RealField
import kscience.kmath.operations.invoke
import kscience.kmath.viktor.ViktorNDField
import org.jetbrains.bio.viktor.F64Array
import org.openjdk.jmh.annotations.Benchmark
import org.openjdk.jmh.annotations.Scope
import org.openjdk.jmh.annotations.State
@State(Scope.Benchmark)
internal class ViktorLogBenchmark {
final val dim: Int = 1000
final val n: Int = 100
// automatically build context most suited for given type.
final val autoField: NDField<Double, RealField> = NDAlgebra.auto(RealField, dim, dim)
final val realField: RealNDField = NDAlgebra.real(dim, dim)
final val viktorField: ViktorNDField = ViktorNDField(intArrayOf(dim, dim))
@Benchmark
fun realFieldLog() {
realField {
val fortyTwo = produce { 42.0 }
var res = one
repeat(n) { res = ln(fortyTwo) }
}
}
@Benchmark
fun viktorFieldLog() {
viktorField {
val fortyTwo = produce { 42.0 }
var res = one
repeat(n) { res = ln(fortyTwo) }
}
}
@Benchmark
fun rawViktorLog() {
val fortyTwo = F64Array.full(dim, dim, init = 42.0)
var res: F64Array
repeat(n) {
res = fortyTwo.log()
}
}
}

View File

@ -0,0 +1,38 @@
package space.kscience.kmath.benchmarks
import kotlinx.benchmark.Benchmark
import kotlinx.benchmark.Blackhole
import kotlinx.benchmark.Scope
import kotlinx.benchmark.State
import java.nio.IntBuffer
@State(Scope.Benchmark)
internal class ArrayBenchmark {
@Benchmark
fun benchmarkArrayRead(blackhole: Blackhole) {
var res = 0
for (i in 1..size) res += array[size - i]
blackhole.consume(res)
}
@Benchmark
fun benchmarkBufferRead(blackhole: Blackhole) {
var res = 0
for (i in 1..size) res += arrayBuffer[size - i]
blackhole.consume(res)
}
@Benchmark
fun nativeBufferRead(blackhole: Blackhole) {
var res = 0
for (i in 1..size) res += nativeBuffer[size - i]
blackhole.consume(res)
}
private companion object {
private const val size = 1000
private val array = IntArray(size) { it }
private val arrayBuffer = IntBuffer.wrap(array)
private val nativeBuffer = IntBuffer.allocate(size).also { for (i in 0 until size) it.put(i, i) }
}
}

View File

@ -0,0 +1,34 @@
package space.kscience.kmath.benchmarks
import kotlinx.benchmark.Benchmark
import kotlinx.benchmark.Scope
import kotlinx.benchmark.State
import space.kscience.kmath.complex.Complex
import space.kscience.kmath.complex.complex
import space.kscience.kmath.structures.DoubleBuffer
import space.kscience.kmath.structures.MutableBuffer
@State(Scope.Benchmark)
internal class BufferBenchmark {
@Benchmark
fun genericDoubleBufferReadWrite() {
val buffer = DoubleBuffer(size) { it.toDouble() }
(0 until size).forEach {
buffer[it]
}
}
@Benchmark
fun complexBufferReadWrite() {
val buffer = MutableBuffer.complex(size / 2) { Complex(it.toDouble(), -it.toDouble()) }
(0 until size / 2).forEach {
buffer[it]
}
}
private companion object {
private const val size = 100
}
}

View File

@ -0,0 +1,65 @@
package space.kscience.kmath.benchmarks
import kotlinx.benchmark.Benchmark
import kotlinx.benchmark.Blackhole
import kotlinx.benchmark.Scope
import kotlinx.benchmark.State
import space.kscience.kmath.commons.linear.CMLinearSpace
import space.kscience.kmath.ejml.EjmlLinearSpace
import space.kscience.kmath.linear.LinearSpace
import space.kscience.kmath.linear.invoke
import space.kscience.kmath.operations.DoubleField
import kotlin.random.Random
@State(Scope.Benchmark)
internal class DotBenchmark {
companion object {
val random = Random(12224)
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 cmMatrix1 = CMLinearSpace { matrix1.toCM() }
val cmMatrix2 = CMLinearSpace { matrix2.toCM() }
val ejmlMatrix1 = EjmlLinearSpace { matrix1.toEjml() }
val ejmlMatrix2 = EjmlLinearSpace { matrix2.toEjml() }
}
@Benchmark
fun cmDot(blackhole: Blackhole) {
CMLinearSpace.run {
blackhole.consume(cmMatrix1 dot cmMatrix2)
}
}
@Benchmark
fun ejmlDot(blackhole: Blackhole) {
EjmlLinearSpace {
blackhole.consume(ejmlMatrix1 dot ejmlMatrix2)
}
}
@Benchmark
fun ejmlDotWithConversion(blackhole: Blackhole) {
EjmlLinearSpace {
blackhole.consume(matrix1 dot matrix2)
}
}
@Benchmark
fun bufferedDot(blackhole: Blackhole) {
LinearSpace.auto(DoubleField).invoke {
blackhole.consume(matrix1 dot matrix2)
}
}
@Benchmark
fun realDot(blackhole: Blackhole) {
LinearSpace.real {
blackhole.consume(matrix1 dot matrix2)
}
}
}

View File

@ -0,0 +1,74 @@
package space.kscience.kmath.benchmarks
import kotlinx.benchmark.Benchmark
import kotlinx.benchmark.Blackhole
import kotlinx.benchmark.Scope
import kotlinx.benchmark.State
import space.kscience.kmath.asm.compile
import space.kscience.kmath.ast.mstInField
import space.kscience.kmath.expressions.Expression
import space.kscience.kmath.expressions.expressionInField
import space.kscience.kmath.expressions.invoke
import space.kscience.kmath.misc.symbol
import space.kscience.kmath.operations.DoubleField
import space.kscience.kmath.operations.bindSymbol
import kotlin.random.Random
@State(Scope.Benchmark)
internal class ExpressionsInterpretersBenchmark {
@Benchmark
fun functionalExpression(blackhole: Blackhole) {
val expr = algebra.expressionInField {
val x = bindSymbol(x)
x * const(2.0) + const(2.0) / x - const(16.0)
}
invokeAndSum(expr, blackhole)
}
@Benchmark
fun mstExpression(blackhole: Blackhole) {
val expr = algebra.mstInField {
val x = bindSymbol(x)
x * 2.0 + number(2.0) / x - 16.0
}
invokeAndSum(expr, blackhole)
}
@Benchmark
fun asmExpression(blackhole: Blackhole) {
val expr = algebra.mstInField {
val x = bindSymbol(x)
x * 2.0 + number(2.0) / x - 16.0
}.compile()
invokeAndSum(expr, blackhole)
}
@Benchmark
fun rawExpression(blackhole: Blackhole) {
val expr = Expression<Double> { args ->
val x = args.getValue(x)
x * 2.0 + 2.0 / x - 16.0
}
invokeAndSum(expr, blackhole)
}
private fun invokeAndSum(expr: Expression<Double>, blackhole: Blackhole) {
val random = Random(0)
var sum = 0.0
repeat(1000000) {
sum += expr(x to random.nextDouble())
}
blackhole.consume(sum)
}
private companion object {
private val algebra = DoubleField
private val x by symbol
}
}

View File

@ -0,0 +1,48 @@
package space.kscience.kmath.benchmarks
import kotlinx.benchmark.Benchmark
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.ejml.EjmlLinearSpace
import space.kscience.kmath.ejml.inverse
import space.kscience.kmath.linear.LinearSpace
import space.kscience.kmath.linear.inverseWithLup
import space.kscience.kmath.linear.invoke
import kotlin.random.Random
@State(Scope.Benchmark)
internal class MatrixInverseBenchmark {
companion object {
val random = Random(1224)
const val dim = 100
private val space = LinearSpace.real
//creating invertible matrix
val u = space.buildMatrix(dim, dim) { i, j -> if (i <= j) random.nextDouble() else 0.0 }
val l = space.buildMatrix(dim, dim) { i, j -> if (i >= j) random.nextDouble() else 0.0 }
val matrix = space { l dot u }
}
@Benchmark
fun kmathLupInversion(blackhole: Blackhole) {
blackhole.consume(LinearSpace.real.inverseWithLup(matrix))
}
@Benchmark
fun cmLUPInversion(blackhole: Blackhole) {
with(CMLinearSpace) {
blackhole.consume(inverse(matrix))
}
}
@Benchmark
fun ejmlInverse(blackhole: Blackhole) {
with(EjmlLinearSpace) {
blackhole.consume(inverse(matrix))
}
}
}

View File

@ -0,0 +1,48 @@
package space.kscience.kmath.benchmarks
import kotlinx.benchmark.Benchmark
import kotlinx.benchmark.Blackhole
import kotlinx.benchmark.Scope
import kotlinx.benchmark.State
import space.kscience.kmath.nd.*
import space.kscience.kmath.operations.DoubleField
import space.kscience.kmath.structures.Buffer
@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)
}
}
@Benchmark
fun specializedFieldAdd(blackhole: Blackhole) {
with(specializedField) {
var res: StructureND<Double> = one
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)
}
}
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)
}
}

View File

@ -0,0 +1,61 @@
package space.kscience.kmath.benchmarks
import kotlinx.benchmark.Benchmark
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.operations.DoubleField
import space.kscience.kmath.viktor.ViktorNDField
@State(Scope.Benchmark)
internal class ViktorBenchmark {
@Benchmark
fun automaticFieldAddition(blackhole: Blackhole) {
with(autoField) {
var res: StructureND<Double> = one
repeat(n) { res += 1.0 }
blackhole.consume(res)
}
}
@Benchmark
fun realFieldAddition(blackhole: Blackhole) {
with(realField) {
var res: StructureND<Double> = one
repeat(n) { res += 1.0 }
blackhole.consume(res)
}
}
@Benchmark
fun viktorFieldAddition(blackhole: Blackhole) {
with(viktorField) {
var res = one
repeat(n) { res += 1.0 }
blackhole.consume(res)
}
}
@Benchmark
fun rawViktor(blackhole: Blackhole) {
val one = F64Array.full(init = 1.0, shape = intArrayOf(dim, dim))
var res = one
repeat(n) { res = res + one }
blackhole.consume(res)
}
private companion object {
private const val dim = 1000
private const val n = 100
// 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)
}
}

View File

@ -0,0 +1,53 @@
package space.kscience.kmath.benchmarks
import kotlinx.benchmark.Benchmark
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.operations.DoubleField
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
repeat(n) { res = ln(fortyTwo) }
blackhole.consume(res)
}
}
@Benchmark
fun viktorFieldLog(blackhole: Blackhole) {
with(viktorField) {
val fortyTwo = produce { 42.0 }
var res = one
repeat(n) { res = ln(fortyTwo) }
blackhole.consume(res)
}
}
@Benchmark
fun rawViktorLog(blackhole: Blackhole) {
val fortyTwo = F64Array.full(dim, dim, init = 42.0)
lateinit var res: F64Array
repeat(n) { res = fortyTwo.log() }
blackhole.consume(res)
}
private companion object {
private const val dim = 1000
private const val n = 100
// 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))
}
}

View File

@ -1,24 +0,0 @@
package kscience.kmath.ast
import kscience.kmath.asm.compile
import kscience.kmath.expressions.derivative
import kscience.kmath.expressions.invoke
import kscience.kmath.expressions.symbol
import kscience.kmath.kotlingrad.differentiable
import kscience.kmath.operations.RealField
/**
* In this example, x^2-4*x-44 function is differentiated with Kotlin, and the autodiff result is compared with
* valid derivative.
*/
fun main() {
val x by symbol
val actualDerivative = MstExpression(RealField, "x^2-4*x-44".parseMath())
.differentiable()
.derivative(x)
.compile()
val expectedDerivative = MstExpression(RealField, "2*x-4".parseMath()).compile()
assert(actualDerivative("x" to 123.0) == expectedDerivative("x" to 123.0))
}

View File

@ -1,103 +0,0 @@
package kscience.kmath.structures
import kscience.kmath.misc.UnstableKMathAPI
import kscience.kmath.nd.*
import kscience.kmath.operations.ExtendedField
import kscience.kmath.operations.RealField
import kscience.kmath.operations.RingWithNumbers
import java.util.*
import java.util.stream.IntStream
/**
* A demonstration implementation of NDField over Real using Java [DoubleStream] for parallel execution
*/
@OptIn(UnstableKMathAPI::class)
class StreamRealNDField(
override val shape: IntArray,
) : NDField<Double, RealField>,
RingWithNumbers<NDStructure<Double>>,
ExtendedField<NDStructure<Double>> {
private val strides = DefaultStrides(shape)
override val elementContext: RealField get() = RealField
override val zero: NDBuffer<Double> by lazy { produce { zero } }
override val one: NDBuffer<Double> by lazy { produce { one } }
override fun number(value: Number): NDBuffer<Double> {
val d = value.toDouble() // minimize conversions
return produce { d }
}
private val NDStructure<Double>.buffer: RealBuffer
get() = when {
!shape.contentEquals(this@StreamRealNDField.shape) -> throw ShapeMismatchException(
this@StreamRealNDField.shape,
shape
)
this is NDBuffer && this.strides == this@StreamRealNDField.strides -> this.buffer as RealBuffer
else -> RealBuffer(strides.linearSize) { offset -> get(strides.index(offset)) }
}
override fun produce(initializer: RealField.(IntArray) -> Double): NDBuffer<Double> {
val array = IntStream.range(0, strides.linearSize).parallel().mapToDouble { offset ->
val index = strides.index(offset)
RealField.initializer(index)
}.toArray()
return NDBuffer(strides, array.asBuffer())
}
override fun NDStructure<Double>.map(
transform: RealField.(Double) -> Double,
): NDBuffer<Double> {
val array = Arrays.stream(buffer.array).parallel().map { RealField.transform(it) }.toArray()
return NDBuffer(strides, array.asBuffer())
}
override fun NDStructure<Double>.mapIndexed(
transform: RealField.(index: IntArray, Double) -> Double,
): NDBuffer<Double> {
val array = IntStream.range(0, strides.linearSize).parallel().mapToDouble { offset ->
RealField.transform(
strides.index(offset),
buffer.array[offset]
)
}.toArray()
return NDBuffer(strides, array.asBuffer())
}
override fun combine(
a: NDStructure<Double>,
b: NDStructure<Double>,
transform: RealField.(Double, Double) -> Double,
): NDBuffer<Double> {
val array = IntStream.range(0, strides.linearSize).parallel().mapToDouble { offset ->
RealField.transform(a.buffer.array[offset], b.buffer.array[offset])
}.toArray()
return NDBuffer(strides, array.asBuffer())
}
override fun power(arg: NDStructure<Double>, pow: Number): NDBuffer<Double> = arg.map() { power(it, pow) }
override fun exp(arg: NDStructure<Double>): NDBuffer<Double> = arg.map() { exp(it) }
override fun ln(arg: NDStructure<Double>): NDBuffer<Double> = arg.map() { ln(it) }
override fun sin(arg: NDStructure<Double>): NDBuffer<Double> = arg.map() { sin(it) }
override fun cos(arg: NDStructure<Double>): NDBuffer<Double> = arg.map() { cos(it) }
override fun tan(arg: NDStructure<Double>): NDBuffer<Double> = arg.map() { tan(it) }
override fun asin(arg: NDStructure<Double>): NDBuffer<Double> = arg.map() { asin(it) }
override fun acos(arg: NDStructure<Double>): NDBuffer<Double> = arg.map() { acos(it) }
override fun atan(arg: NDStructure<Double>): NDBuffer<Double> = arg.map() { atan(it) }
override fun sinh(arg: NDStructure<Double>): NDBuffer<Double> = arg.map() { sinh(it) }
override fun cosh(arg: NDStructure<Double>): NDBuffer<Double> = arg.map() { cosh(it) }
override fun tanh(arg: NDStructure<Double>): NDBuffer<Double> = arg.map() { tanh(it) }
override fun asinh(arg: NDStructure<Double>): NDBuffer<Double> = arg.map() { asinh(it) }
override fun acosh(arg: NDStructure<Double>): NDBuffer<Double> = arg.map() { acosh(it) }
override fun atanh(arg: NDStructure<Double>): NDBuffer<Double> = arg.map() { atanh(it) }
}
fun NDAlgebra.Companion.realWithStream(vararg shape: Int): StreamRealNDField = StreamRealNDField(shape)

View File

@ -0,0 +1,15 @@
package space.kscience.kmath.ast
import space.kscience.kmath.expressions.invoke
import space.kscience.kmath.operations.DoubleField
fun main() {
val expr = DoubleField.mstInField {
val x = bindSymbol("x")
x * 2.0 + number(2.0) / x - 16.0
}
repeat(10000000) {
expr.invoke("x" to 1.0)
}
}

View File

@ -0,0 +1,24 @@
package space.kscience.kmath.ast
import space.kscience.kmath.asm.compile
import space.kscience.kmath.expressions.derivative
import space.kscience.kmath.expressions.invoke
import space.kscience.kmath.kotlingrad.differentiable
import space.kscience.kmath.misc.symbol
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.
*/
fun main() {
val x by symbol
val actualDerivative = MstExpression(DoubleField, "x^2-4*x-44".parseMath())
.differentiable()
.derivative(x)
.compile()
val expectedDerivative = MstExpression(DoubleField, "2*x-4".parseMath()).compile()
assert(actualDerivative("x" to 123.0) == expectedDerivative("x" to 123.0))
}

View File

@ -0,0 +1,28 @@
package space.kscience.kmath.linear
import space.kscience.kmath.real.*
import space.kscience.kmath.structures.DoubleBuffer
fun main() {
val x0 = DoubleVector(0.0, 0.0, 0.0)
val sigma = DoubleVector(1.0, 1.0, 1.0)
val gaussian: (Point<Double>) -> Double = { x ->
require(x.size == x0.size)
kotlin.math.exp(-((x - x0) / sigma).square().sum())
}
fun ((Point<Double>) -> Double).grad(x: Point<Double>): Point<Double> {
require(x.size == x0.size)
return DoubleBuffer(x.size) { i ->
val h = sigma[i] / 5
val dVector = DoubleBuffer(x.size) { if (it == i) h else 0.0 }
val f1 = invoke(x + dVector / 2)
val f0 = invoke(x - dVector / 2)
(f1 - f0) / h
}
}
println(gaussian.grad(x0))
}

View File

@ -1,4 +1,4 @@
package kscience.kmath.operations package space.kscience.kmath.operations
fun main() { fun main() {
val res = BigIntField { number(1) * 2 } val res = BigIntField { number(1) * 2 }

View File

@ -1,18 +1,18 @@
package kscience.kmath.operations package space.kscience.kmath.operations
import kscience.kmath.complex.Complex import space.kscience.kmath.complex.Complex
import kscience.kmath.complex.complex import space.kscience.kmath.complex.complex
import kscience.kmath.nd.NDAlgebra import space.kscience.kmath.nd.AlgebraND
fun main() { fun main() {
// 2d element // 2d element
val element = NDAlgebra.complex(2, 2).produce { (i, j) -> val element = AlgebraND.complex(2, 2).produce { (i, j) ->
Complex(i.toDouble() - j.toDouble(), i.toDouble() + j.toDouble()) Complex(i.toDouble() - j.toDouble(), i.toDouble() + j.toDouble())
} }
println(element) println(element)
// 1d element operation // 1d element operation
val result = with(NDAlgebra.complex(8)) { val result = with(AlgebraND.complex(8)) {
val a = produce { (it) -> i * it - it.toDouble() } val a = produce { (it) -> i * it - it.toDouble() }
val b = 3 val b = 3
val c = Complex(1.0, 1.0) val c = Complex(1.0, 1.0)

View File

@ -1,26 +1,26 @@
@file:Suppress("unused") @file:Suppress("unused")
package kscience.kmath.structures package space.kscience.kmath.structures
import kscience.kmath.complex.* import space.kscience.kmath.complex.*
import kscience.kmath.linear.transpose import space.kscience.kmath.linear.transpose
import kscience.kmath.nd.NDAlgebra import space.kscience.kmath.nd.AlgebraND
import kscience.kmath.nd.NDStructure import space.kscience.kmath.nd.StructureND
import kscience.kmath.nd.as2D import space.kscience.kmath.nd.as2D
import kscience.kmath.nd.real import space.kscience.kmath.nd.real
import kscience.kmath.operations.invoke import space.kscience.kmath.operations.invoke
import kotlin.system.measureTimeMillis import kotlin.system.measureTimeMillis
fun main() { fun main() {
val dim = 1000 val dim = 1000
val n = 1000 val n = 1000
val realField = NDAlgebra.real(dim, dim) val realField = AlgebraND.real(dim, dim)
val complexField: ComplexNDField = NDAlgebra.complex(dim, dim) val complexField: ComplexFieldND = AlgebraND.complex(dim, dim)
val realTime = measureTimeMillis { val realTime = measureTimeMillis {
realField { realField {
var res: NDStructure<Double> = one var res: StructureND<Double> = one
repeat(n) { repeat(n) {
res += 1.0 res += 1.0
} }
@ -31,7 +31,7 @@ fun main() {
val complexTime = measureTimeMillis { val complexTime = measureTimeMillis {
complexField { complexField {
var res: NDStructure<Complex> = one var res: StructureND<Complex> = one
repeat(n) { repeat(n) {
res += 1.0 res += 1.0
} }

View File

@ -1,12 +1,12 @@
package kscience.kmath.structures package space.kscience.kmath.structures
import kotlinx.coroutines.GlobalScope import kotlinx.coroutines.GlobalScope
import kscience.kmath.nd.*
import kscience.kmath.nd4j.Nd4jArrayField
import kscience.kmath.operations.RealField
import kscience.kmath.operations.invoke
import kscience.kmath.viktor.ViktorNDField
import org.nd4j.linalg.factory.Nd4j import org.nd4j.linalg.factory.Nd4j
import space.kscience.kmath.nd.*
import space.kscience.kmath.nd4j.Nd4jArrayField
import space.kscience.kmath.operations.DoubleField
import space.kscience.kmath.operations.invoke
import space.kscience.kmath.viktor.ViktorNDField
import kotlin.contracts.InvocationKind import kotlin.contracts.InvocationKind
import kotlin.contracts.contract import kotlin.contracts.contract
import kotlin.system.measureTimeMillis import kotlin.system.measureTimeMillis
@ -24,56 +24,56 @@ fun main() {
val n = 1000 val n = 1000
// automatically build context most suited for given type. // automatically build context most suited for given type.
val autoField = NDAlgebra.auto(RealField, dim, dim) val autoField = AlgebraND.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 realField = NDAlgebra.real(dim, dim) val realField = AlgebraND.real(dim, dim)
//A generic boxing field. It should be used for objects, not primitives. //A generic boxing field. It should be used for objects, not primitives.
val boxingField = NDAlgebra.field(RealField, Buffer.Companion::boxing, dim, dim) val boxingField = AlgebraND.field(DoubleField, Buffer.Companion::boxing, dim, dim)
// Nd4j specialized field. // Nd4j specialized field.
val nd4jField = Nd4jArrayField.real(dim, dim) val nd4jField = Nd4jArrayField.real(dim, dim)
//viktor field //viktor field
val viktorField = ViktorNDField(dim,dim) val viktorField = ViktorNDField(dim, dim)
//parallel processing based on Java Streams //parallel processing based on Java Streams
val parallelField = NDAlgebra.realWithStream(dim,dim) val parallelField = AlgebraND.realWithStream(dim, dim)
measureAndPrint("Boxing addition") { measureAndPrint("Boxing addition") {
boxingField { boxingField {
var res: NDStructure<Double> = one var res: StructureND<Double> = one
repeat(n) { res += 1.0 } repeat(n) { res += 1.0 }
} }
} }
measureAndPrint("Specialized addition") { measureAndPrint("Specialized addition") {
realField { realField {
var res: NDStructure<Double> = one var res: StructureND<Double> = one
repeat(n) { res += 1.0 } repeat(n) { res += 1.0 }
} }
} }
measureAndPrint("Nd4j specialized addition") { measureAndPrint("Nd4j specialized addition") {
nd4jField { nd4jField {
var res: NDStructure<Double> = one var res: StructureND<Double> = one
repeat(n) { res += 1.0 } repeat(n) { res += 1.0 }
} }
} }
measureAndPrint("Viktor addition") { measureAndPrint("Viktor addition") {
viktorField { viktorField {
var res: NDStructure<Double> = one var res: StructureND<Double> = one
repeat(n) { res += 1.0 } repeat(n) { res += 1.0 }
} }
} }
measureAndPrint("Parallel stream addition") { measureAndPrint("Parallel stream addition") {
parallelField { parallelField {
var res: NDStructure<Double> = one var res: StructureND<Double> = one
repeat(n) { res += 1.0 } repeat(n) { res += 1.0 }
} }
} }
measureAndPrint("Automatic field addition") { measureAndPrint("Automatic field addition") {
autoField { autoField {
var res: NDStructure<Double> = one var res: StructureND<Double> = one
repeat(n) { res += 1.0 } repeat(n) { res += 1.0 }
} }
} }

View File

@ -0,0 +1,107 @@
package space.kscience.kmath.structures
import space.kscience.kmath.misc.UnstableKMathAPI
import space.kscience.kmath.nd.*
import space.kscience.kmath.operations.DoubleField
import space.kscience.kmath.operations.ExtendedField
import space.kscience.kmath.operations.NumbersAddOperations
import java.util.*
import java.util.stream.IntStream
/**
* A demonstration implementation of NDField over Real using Java [DoubleStream] for parallel execution
*/
@OptIn(UnstableKMathAPI::class)
class StreamDoubleFieldND(
override val shape: IntArray,
) : FieldND<Double, DoubleField>,
NumbersAddOperations<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 fun number(value: Number): BufferND<Double> {
val d = value.toDouble() // minimize conversions
return produce { d }
}
private val StructureND<Double>.buffer: DoubleBuffer
get() = when {
!shape.contentEquals(this@StreamDoubleFieldND.shape) -> throw ShapeMismatchException(
this@StreamDoubleFieldND.shape,
shape
)
this is BufferND && this.strides == 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> {
val array = IntStream.range(0, strides.linearSize).parallel().mapToDouble { offset ->
val index = strides.index(offset)
DoubleField.initializer(index)
}.toArray()
return BufferND(strides, array.asBuffer())
}
override fun StructureND<Double>.map(
transform: DoubleField.(Double) -> Double,
): BufferND<Double> {
val array = Arrays.stream(buffer.array).parallel().map { DoubleField.transform(it) }.toArray()
return BufferND(strides, array.asBuffer())
}
override fun StructureND<Double>.mapIndexed(
transform: DoubleField.(index: IntArray, Double) -> Double,
): BufferND<Double> {
val array = IntStream.range(0, strides.linearSize).parallel().mapToDouble { offset ->
DoubleField.transform(
strides.index(offset),
buffer.array[offset]
)
}.toArray()
return BufferND(strides, array.asBuffer())
}
override fun combine(
a: StructureND<Double>,
b: 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])
}.toArray()
return BufferND(strides, array.asBuffer())
}
override fun StructureND<Double>.unaryMinus(): StructureND<Double> = map { -it }
override fun scale(a: StructureND<Double>, value: Double): StructureND<Double> = a.map { it * value }
override fun power(arg: StructureND<Double>, pow: Number): BufferND<Double> = arg.map { power(it, pow) }
override fun exp(arg: StructureND<Double>): BufferND<Double> = arg.map { exp(it) }
override fun ln(arg: StructureND<Double>): BufferND<Double> = arg.map { ln(it) }
override fun sin(arg: StructureND<Double>): BufferND<Double> = arg.map { sin(it) }
override fun cos(arg: StructureND<Double>): BufferND<Double> = arg.map { cos(it) }
override fun tan(arg: StructureND<Double>): BufferND<Double> = arg.map { tan(it) }
override fun asin(arg: StructureND<Double>): BufferND<Double> = arg.map { asin(it) }
override fun acos(arg: StructureND<Double>): BufferND<Double> = arg.map { acos(it) }
override fun atan(arg: StructureND<Double>): BufferND<Double> = arg.map { atan(it) }
override fun sinh(arg: StructureND<Double>): BufferND<Double> = arg.map { sinh(it) }
override fun cosh(arg: StructureND<Double>): BufferND<Double> = arg.map { cosh(it) }
override fun tanh(arg: StructureND<Double>): BufferND<Double> = arg.map { tanh(it) }
override fun asinh(arg: StructureND<Double>): BufferND<Double> = arg.map { asinh(it) }
override fun acosh(arg: StructureND<Double>): BufferND<Double> = arg.map { acosh(it) }
override fun atanh(arg: StructureND<Double>): BufferND<Double> = arg.map { atanh(it) }
}
fun AlgebraND.Companion.realWithStream(vararg shape: Int): StreamDoubleFieldND = StreamDoubleFieldND(shape)

View File

@ -1,15 +1,16 @@
package kscience.kmath.structures package space.kscience.kmath.structures
import kscience.kmath.nd.DefaultStrides import space.kscience.kmath.nd.BufferND
import kscience.kmath.nd.NDBuffer import space.kscience.kmath.nd.DefaultStrides
import kotlin.system.measureTimeMillis import kotlin.system.measureTimeMillis
@Suppress("ASSIGNED_BUT_NEVER_ACCESSED_VARIABLE")
fun main() { fun main() {
val n = 6000 val n = 6000
val array = DoubleArray(n * n) { 1.0 } val array = DoubleArray(n * n) { 1.0 }
val buffer = RealBuffer(array) val buffer = DoubleBuffer(array)
val strides = DefaultStrides(intArrayOf(n, n)) val strides = DefaultStrides(intArrayOf(n, n))
val structure = NDBuffer(strides, buffer) val structure = BufferND(strides, buffer)
measureTimeMillis { measureTimeMillis {
var res = 0.0 var res = 0.0

View File

@ -1,12 +1,13 @@
package kscience.kmath.structures package space.kscience.kmath.structures
import kscience.kmath.nd.NDStructure import space.kscience.kmath.nd.StructureND
import kscience.kmath.nd.mapToBuffer import space.kscience.kmath.nd.mapToBuffer
import kotlin.system.measureTimeMillis import kotlin.system.measureTimeMillis
@Suppress("UNUSED_VARIABLE")
fun main() { fun main() {
val n = 6000 val n = 6000
val structure = NDStructure.build(intArrayOf(n, n), Buffer.Companion::auto) { 1.0 } val structure = StructureND.buffered(intArrayOf(n, n), Buffer.Companion::auto) { 1.0 }
structure.mapToBuffer { it + 1 } // warm-up structure.mapToBuffer { it + 1 } // warm-up
val time1 = measureTimeMillis { val res = structure.mapToBuffer { it + 1 } } val time1 = measureTimeMillis { val res = structure.mapToBuffer { it + 1 } }
println("Structure mapping finished in $time1 millis") println("Structure mapping finished in $time1 millis")
@ -19,10 +20,10 @@ fun main() {
println("Array mapping finished in $time2 millis") println("Array mapping finished in $time2 millis")
val buffer = RealBuffer(DoubleArray(n * n) { 1.0 }) val buffer = DoubleBuffer(DoubleArray(n * n) { 1.0 })
val time3 = measureTimeMillis { val time3 = measureTimeMillis {
val target = RealBuffer(DoubleArray(n * n)) val target = DoubleBuffer(DoubleArray(n * n))
val res = array.forEachIndexed { index, value -> val res = array.forEachIndexed { index, value ->
target[index] = value + 1 target[index] = value + 1
} }

View File

@ -1,11 +1,11 @@
package kscience.kmath.structures package space.kscience.kmath.structures
import kscience.kmath.dimensions.D2 import space.kscience.kmath.dimensions.D2
import kscience.kmath.dimensions.D3 import space.kscience.kmath.dimensions.D3
import kscience.kmath.dimensions.DMatrixContext import space.kscience.kmath.dimensions.DMatrixContext
import kscience.kmath.dimensions.Dimension import space.kscience.kmath.dimensions.Dimension
private fun DMatrixContext<Double>.simple() { private fun DMatrixContext<Double, *>.simple() {
val m1 = produce<D2, D3> { i, j -> (i + j).toDouble() } val m1 = produce<D2, D3> { i, j -> (i + j).toDouble() }
val m2 = produce<D3, D2> { i, j -> (i + j).toDouble() } val m2 = produce<D3, D2> { i, j -> (i + j).toDouble() }
@ -17,7 +17,7 @@ private object D5 : Dimension {
override val dim: UInt = 5u override val dim: UInt = 5u
} }
private fun DMatrixContext<Double>.custom() { private fun DMatrixContext<Double, *>.custom() {
val m1 = produce<D2, D5> { i, j -> (i + j).toDouble() } val m1 = produce<D2, D5> { i, j -> (i + j).toDouble() }
val m2 = produce<D5, D2> { i, j -> (i - j).toDouble() } val m2 = produce<D5, D2> { i, j -> (i - j).toDouble() }
val m3 = produce<D2, D2> { i, j -> (i - j).toDouble() } val m3 = produce<D2, D2> { i, j -> (i - j).toDouble() }

View File

@ -3,6 +3,6 @@ kotlin.mpp.enableGranularSourceSetsMetadata=true
kotlin.mpp.stability.nowarn=true kotlin.mpp.stability.nowarn=true
kotlin.native.enableDependencyPropagation=false kotlin.native.enableDependencyPropagation=false
kotlin.parallel.tasks.in.project=true kotlin.parallel.tasks.in.project=true
org.gradle.jvmargs=-XX:MaxMetaspaceSize=512m org.gradle.configureondemand=true
org.gradle.jvmargs=-XX:MaxMetaspaceSize=9G
org.gradle.parallel=true org.gradle.parallel=true
systemProp.org.gradle.internal.publish.checksums.insecure=true

View File

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

View File

@ -1,52 +1,43 @@
# Abstract Syntax Tree Expression Representation and Operations (`kmath-ast`) # Module kmath-ast
This subproject implements the following features: Abstract syntax tree expression representation and related optimizations.
- [expression-language](src/jvmMain/kotlin/kscience/kmath/ast/parser.kt) : Expression language and its parser - [expression-language](src/jvmMain/kotlin/space/kscience/kmath/ast/parser.kt) : Expression language and its parser
- [mst](src/commonMain/kotlin/kscience/kmath/ast/MST.kt) : MST (Mathematical Syntax Tree) as expression language's syntax intermediate representation - [mst](src/commonMain/kotlin/space/kscience/kmath/ast/MST.kt) : MST (Mathematical Syntax Tree) as expression language's syntax intermediate representation
- [mst-building](src/commonMain/kotlin/kscience/kmath/ast/MstAlgebra.kt) : MST building algebraic structure - [mst-building](src/commonMain/kotlin/space/kscience/kmath/ast/MstAlgebra.kt) : MST building algebraic structure
- [mst-interpreter](src/commonMain/kotlin/kscience/kmath/ast/MST.kt) : MST interpreter - [mst-interpreter](src/commonMain/kotlin/space/kscience/kmath/ast/MST.kt) : MST interpreter
- [mst-jvm-codegen](src/jvmMain/kotlin/kscience/kmath/asm/asm.kt) : Dynamic MST to JVM bytecode compiler - [mst-jvm-codegen](src/jvmMain/kotlin/space/kscience/kmath/asm/asm.kt) : Dynamic MST to JVM bytecode compiler
- [mst-js-codegen](src/jsMain/kotlin/kscience/kmath/estree/estree.kt) : Dynamic MST to JS compiler - [mst-js-codegen](src/jsMain/kotlin/space/kscience/kmath/estree/estree.kt) : Dynamic MST to JS compiler
> #### Artifact: ## Artifact:
>
> This module artifact: `kscience.kmath:kmath-ast:0.2.0-dev-7`. The Maven coordinates of this project are `space.kscience:kmath-ast:0.3.0-dev-3`.
>
> Bintray release version: [ ![Download](https://api.bintray.com/packages/mipt-npm/kscience/kmath-ast/images/download.svg) ](https://bintray.com/mipt-npm/kscience/kmath-ast/_latestVersion) **Gradle:**
> ```gradle
> Bintray development version: [ ![Download](https://api.bintray.com/packages/mipt-npm/dev/kmath-ast/images/download.svg) ](https://bintray.com/mipt-npm/dev/kmath-ast/_latestVersion) repositories {
> maven { url 'https://repo.kotlin.link' }
> **Gradle:** maven { url 'https://dl.bintray.com/hotkeytlt/maven' }
> maven { url "https://dl.bintray.com/kotlin/kotlin-eap" } // include for builds based on kotlin-eap
> ```gradle }
> repositories {
> maven { url "https://dl.bintray.com/kotlin/kotlin-eap" } dependencies {
> maven { url 'https://dl.bintray.com/mipt-npm/kscience' } implementation 'space.kscience:kmath-ast:0.3.0-dev-3'
> maven { url 'https://dl.bintray.com/mipt-npm/dev' } }
> maven { url 'https://dl.bintray.com/hotkeytlt/maven' } ```
> **Gradle Kotlin DSL:**
> } ```kotlin
> repositories {
> dependencies { maven("https://repo.kotlin.link")
> implementation 'kscience.kmath:kmath-ast:0.2.0-dev-7' maven("https://dl.bintray.com/kotlin/kotlin-eap") // include for builds based on kotlin-eap
> } maven("https://dl.bintray.com/hotkeytlt/maven") // required for a
> ``` }
> **Gradle Kotlin DSL:**
> dependencies {
> ```kotlin implementation("space.kscience:kmath-ast:0.3.0-dev-3")
> repositories { }
> maven("https://dl.bintray.com/kotlin/kotlin-eap") ```
> maven("https://dl.bintray.com/mipt-npm/kscience")
> maven("https://dl.bintray.com/mipt-npm/dev")
> maven("https://dl.bintray.com/hotkeytlt/maven")
> }
>
> dependencies {
> implementation("kscience.kmath:kmath-ast:0.2.0-dev-7")
> }
> ```
## Dynamic expression code generation ## Dynamic expression code generation
@ -58,19 +49,19 @@ a special implementation of `Expression<T>` with implemented `invoke` function.
For example, the following builder: For example, the following builder:
```kotlin ```kotlin
RealField.mstInField { symbol("x") + 2 }.compile() DoubleField.mstInField { symbol("x") + 2 }.compile()
``` ```
… leads to generation of bytecode, which can be decompiled to the following Java class: … leads to generation of bytecode, which can be decompiled to the following Java class:
```java ```java
package kscience.kmath.asm.generated; package space.kscience.kmath.asm.generated;
import java.util.Map; import java.util.Map;
import kotlin.jvm.functions.Function2; import kotlin.jvm.functions.Function2;
import kscience.kmath.asm.internal.MapIntrinsics; import space.kscience.kmath.asm.internal.MapIntrinsics;
import kscience.kmath.expressions.Expression; import space.kscience.kmath.expressions.Expression;
import kscience.kmath.expressions.Symbol; import space.kscience.kmath.expressions.Symbol;
public final class AsmCompiledExpression_45045_0 implements Expression<Double> { public final class AsmCompiledExpression_45045_0 implements Expression<Double> {
private final Object[] constants; private final Object[] constants;
@ -91,8 +82,8 @@ public final class AsmCompiledExpression_45045_0 implements Expression<Double> {
This API extends MST and MstExpression, so you may optimize as both of them: This API extends MST and MstExpression, so you may optimize as both of them:
```kotlin ```kotlin
RealField.mstInField { symbol("x") + 2 }.compile() DoubleField.mstInField { symbol("x") + 2 }.compile()
RealField.expression("x+2".parseMath()) DoubleField.expression("x+2".parseMath())
``` ```
#### Known issues #### Known issues
@ -106,7 +97,7 @@ RealField.expression("x+2".parseMath())
A similar feature is also available on JS. A similar feature is also available on JS.
```kotlin ```kotlin
RealField.mstInField { symbol("x") + 2 }.compile() DoubleField.mstInField { symbol("x") + 2 }.compile()
``` ```
The code above returns expression implemented with such a JS function: The code above returns expression implemented with such a JS function:

View File

@ -1,7 +1,7 @@
import ru.mipt.npm.gradle.Maturity import ru.mipt.npm.gradle.Maturity
plugins { plugins {
id("ru.mipt.npm.mpp") id("ru.mipt.npm.gradle.mpp")
} }
kotlin.js { kotlin.js {
@ -33,19 +33,24 @@ kotlin.sourceSets {
jsMain { jsMain {
dependencies { dependencies {
implementation(npm("astring", "1.4.3")) implementation(npm("astring", "1.7.0"))
} }
} }
jvmMain { jvmMain {
dependencies { dependencies {
api("com.github.h0tk3y.betterParse:better-parse:0.4.0") api("com.github.h0tk3y.betterParse:better-parse:0.4.1")
implementation("org.ow2.asm:asm:9.0") implementation("org.ow2.asm:asm:9.1")
implementation("org.ow2.asm:asm-commons:9.0") implementation("org.ow2.asm:asm-commons:9.1")
} }
} }
} }
//Workaround for https://github.com/Kotlin/dokka/issues/1455
tasks.dokkaHtml {
dependsOn(tasks.build)
}
readme { readme {
maturity = Maturity.PROTOTYPE maturity = Maturity.PROTOTYPE
propertyByTemplate("artifact", rootProject.file("docs/templates/ARTIFACT-TEMPLATE.md")) propertyByTemplate("artifact", rootProject.file("docs/templates/ARTIFACT-TEMPLATE.md"))
@ -53,36 +58,36 @@ readme {
feature( feature(
id = "expression-language", id = "expression-language",
description = "Expression language and its parser", description = "Expression language and its parser",
ref = "src/jvmMain/kotlin/kscience/kmath/ast/parser.kt" ref = "src/jvmMain/kotlin/space/kscience/kmath/ast/parser.kt"
) )
feature( feature(
id = "mst", id = "mst",
description = "MST (Mathematical Syntax Tree) as expression language's syntax intermediate representation", description = "MST (Mathematical Syntax Tree) as expression language's syntax intermediate representation",
ref = "src/commonMain/kotlin/kscience/kmath/ast/MST.kt" ref = "src/commonMain/kotlin/space/kscience/kmath/ast/MST.kt"
) )
feature( feature(
id = "mst-building", id = "mst-building",
description = "MST building algebraic structure", description = "MST building algebraic structure",
ref = "src/commonMain/kotlin/kscience/kmath/ast/MstAlgebra.kt" ref = "src/commonMain/kotlin/space/kscience/kmath/ast/MstAlgebra.kt"
) )
feature( feature(
id = "mst-interpreter", id = "mst-interpreter",
description = "MST interpreter", description = "MST interpreter",
ref = "src/commonMain/kotlin/kscience/kmath/ast/MST.kt" ref = "src/commonMain/kotlin/space/kscience/kmath/ast/MST.kt"
) )
feature( feature(
id = "mst-jvm-codegen", id = "mst-jvm-codegen",
description = "Dynamic MST to JVM bytecode compiler", description = "Dynamic MST to JVM bytecode compiler",
ref = "src/jvmMain/kotlin/kscience/kmath/asm/asm.kt" ref = "src/jvmMain/kotlin/space/kscience/kmath/asm/asm.kt"
) )
feature( feature(
id = "mst-js-codegen", id = "mst-js-codegen",
description = "Dynamic MST to JS compiler", description = "Dynamic MST to JS compiler",
ref = "src/jsMain/kotlin/kscience/kmath/estree/estree.kt" ref = "src/jsMain/kotlin/space/kscience/kmath/estree/estree.kt"
) )
} }

View File

@ -1,6 +1,6 @@
# Abstract Syntax Tree Expression Representation and Operations (`kmath-ast`) # Module kmath-ast
This subproject implements the following features: Abstract syntax tree expression representation and related optimizations.
${features} ${features}
@ -16,19 +16,19 @@ a special implementation of `Expression<T>` with implemented `invoke` function.
For example, the following builder: For example, the following builder:
```kotlin ```kotlin
RealField.mstInField { symbol("x") + 2 }.compile() DoubleField.mstInField { symbol("x") + 2 }.compile()
``` ```
… leads to generation of bytecode, which can be decompiled to the following Java class: … leads to generation of bytecode, which can be decompiled to the following Java class:
```java ```java
package kscience.kmath.asm.generated; package space.kscience.kmath.asm.generated;
import java.util.Map; import java.util.Map;
import kotlin.jvm.functions.Function2; import kotlin.jvm.functions.Function2;
import kscience.kmath.asm.internal.MapIntrinsics; import space.kscience.kmath.asm.internal.MapIntrinsics;
import kscience.kmath.expressions.Expression; import space.kscience.kmath.expressions.Expression;
import kscience.kmath.expressions.Symbol; import space.kscience.kmath.expressions.Symbol;
public final class AsmCompiledExpression_45045_0 implements Expression<Double> { public final class AsmCompiledExpression_45045_0 implements Expression<Double> {
private final Object[] constants; private final Object[] constants;
@ -49,8 +49,8 @@ public final class AsmCompiledExpression_45045_0 implements Expression<Double> {
This API extends MST and MstExpression, so you may optimize as both of them: This API extends MST and MstExpression, so you may optimize as both of them:
```kotlin ```kotlin
RealField.mstInField { symbol("x") + 2 }.compile() DoubleField.mstInField { symbol("x") + 2 }.compile()
RealField.expression("x+2".parseMath()) DoubleField.expression("x+2".parseMath())
``` ```
#### Known issues #### Known issues
@ -64,7 +64,7 @@ RealField.expression("x+2".parseMath())
A similar feature is also available on JS. A similar feature is also available on JS.
```kotlin ```kotlin
RealField.mstInField { symbol("x") + 2 }.compile() DoubleField.mstInField { symbol("x") + 2 }.compile()
``` ```
The code above returns expression implemented with such a JS function: The code above returns expression implemented with such a JS function:

View File

@ -1,7 +1,7 @@
package kscience.kmath.ast package space.kscience.kmath.ast
import kscience.kmath.operations.Algebra import space.kscience.kmath.operations.Algebra
import kscience.kmath.operations.NumericAlgebra import space.kscience.kmath.operations.NumericAlgebra
/** /**
* A Mathematical Syntax Tree (MST) node for mathematical expressions. * A Mathematical Syntax Tree (MST) node for mathematical expressions.
@ -55,7 +55,7 @@ public fun <T> Algebra<T>.evaluate(node: MST): T = when (node) {
is MST.Numeric -> (this as? NumericAlgebra<T>)?.number(node.value) is MST.Numeric -> (this as? NumericAlgebra<T>)?.number(node.value)
?: error("Numeric nodes are not supported by $this") ?: error("Numeric nodes are not supported by $this")
is MST.Symbolic -> symbol(node.value) is MST.Symbolic -> bindSymbol(node.value)
is MST.Unary -> when { is MST.Unary -> when {
this is NumericAlgebra && node.value is MST.Numeric -> unaryOperationFunction(node.operation)(number(node.value.value)) this is NumericAlgebra && node.value is MST.Numeric -> unaryOperationFunction(node.operation)(number(node.value.value))

View File

@ -1,14 +1,14 @@
package kscience.kmath.ast package space.kscience.kmath.ast
import kscience.kmath.misc.UnstableKMathAPI import space.kscience.kmath.misc.UnstableKMathAPI
import kscience.kmath.operations.* import space.kscience.kmath.operations.*
/** /**
* [Algebra] over [MST] nodes. * [Algebra] over [MST] nodes.
*/ */
public object MstAlgebra : NumericAlgebra<MST> { public object MstAlgebra : NumericAlgebra<MST> {
public override fun number(value: Number): MST.Numeric = MST.Numeric(value) public override fun number(value: Number): MST.Numeric = MST.Numeric(value)
public override fun symbol(value: String): MST.Symbolic = MST.Symbolic(value) public override fun bindSymbol(value: String): MST.Symbolic = MST.Symbolic(value)
public override fun unaryOperationFunction(operation: String): (arg: MST) -> MST.Unary = public override fun unaryOperationFunction(operation: String): (arg: MST) -> MST.Unary =
{ arg -> MST.Unary(operation, arg) } { arg -> MST.Unary(operation, arg) }
@ -18,25 +18,25 @@ public object MstAlgebra : NumericAlgebra<MST> {
} }
/** /**
* [Space] over [MST] nodes. * [Group] over [MST] nodes.
*/ */
public object MstSpace : Space<MST>, NumericAlgebra<MST> { public object MstGroup : Group<MST>, NumericAlgebra<MST>, ScaleOperations<MST> {
public override val zero: MST.Numeric by lazy { number(0.0) } public override val zero: MST.Numeric = number(0.0)
public override fun number(value: Number): MST.Numeric = MstAlgebra.number(value) public override fun number(value: Number): MST.Numeric = MstAlgebra.number(value)
public override fun symbol(value: String): MST.Symbolic = MstAlgebra.symbol(value) public override fun bindSymbol(value: String): MST.Symbolic = MstAlgebra.bindSymbol(value)
public override fun add(a: MST, b: MST): MST.Binary = binaryOperationFunction(SpaceOperations.PLUS_OPERATION)(a, b) public override fun add(a: MST, b: MST): MST.Binary = binaryOperationFunction(GroupOperations.PLUS_OPERATION)(a, b)
public override operator fun MST.unaryPlus(): MST.Unary = public override operator fun MST.unaryPlus(): MST.Unary =
unaryOperationFunction(SpaceOperations.PLUS_OPERATION)(this) unaryOperationFunction(GroupOperations.PLUS_OPERATION)(this)
public override operator fun MST.unaryMinus(): MST.Unary = public override operator fun MST.unaryMinus(): MST.Unary =
unaryOperationFunction(SpaceOperations.MINUS_OPERATION)(this) unaryOperationFunction(GroupOperations.MINUS_OPERATION)(this)
public override operator fun MST.minus(b: MST): MST.Binary = public override operator fun MST.minus(b: MST): MST.Binary =
binaryOperationFunction(SpaceOperations.MINUS_OPERATION)(this, b) binaryOperationFunction(GroupOperations.MINUS_OPERATION)(this, b)
public override fun multiply(a: MST, k: Number): MST.Binary = public override fun scale(a: MST, value: Double): MST.Binary =
binaryOperationFunction(RingOperations.TIMES_OPERATION)(a, number(k)) binaryOperationFunction(RingOperations.TIMES_OPERATION)(a, number(value))
public override fun binaryOperationFunction(operation: String): (left: MST, right: MST) -> MST.Binary = public override fun binaryOperationFunction(operation: String): (left: MST, right: MST) -> MST.Binary =
MstAlgebra.binaryOperationFunction(operation) MstAlgebra.binaryOperationFunction(operation)
@ -49,25 +49,26 @@ public object MstSpace : Space<MST>, NumericAlgebra<MST> {
* [Ring] over [MST] nodes. * [Ring] over [MST] nodes.
*/ */
@OptIn(UnstableKMathAPI::class) @OptIn(UnstableKMathAPI::class)
public object MstRing : Ring<MST>, RingWithNumbers<MST> { public object MstRing : Ring<MST>, NumbersAddOperations<MST>, ScaleOperations<MST> {
public override val zero: MST.Numeric public override val zero: MST.Numeric get() = MstGroup.zero
get() = MstSpace.zero public override val one: MST.Numeric = number(1.0)
public override val one: MST.Numeric by lazy { number(1.0) } public override fun number(value: Number): MST.Numeric = MstGroup.number(value)
public override fun bindSymbol(value: String): MST.Symbolic = MstAlgebra.bindSymbol(value)
public override fun add(a: MST, b: MST): MST.Binary = MstGroup.add(a, b)
public override fun scale(a: MST, value: Double): MST.Binary =
MstGroup.binaryOperationFunction(RingOperations.TIMES_OPERATION)(a, MstGroup.number(value))
public override fun number(value: Number): MST.Numeric = MstSpace.number(value)
public override fun symbol(value: String): MST.Symbolic = MstSpace.symbol(value)
public override fun add(a: MST, b: MST): MST.Binary = MstSpace.add(a, b)
public override fun multiply(a: MST, k: Number): MST.Binary = MstSpace.multiply(a, k)
public override fun multiply(a: MST, b: MST): MST.Binary = public override fun multiply(a: MST, b: MST): MST.Binary =
binaryOperationFunction(RingOperations.TIMES_OPERATION)(a, b) binaryOperationFunction(RingOperations.TIMES_OPERATION)(a, b)
public override operator fun MST.unaryPlus(): MST.Unary = MstSpace { +this@unaryPlus } public override operator fun MST.unaryPlus(): MST.Unary = MstGroup { +this@unaryPlus }
public override operator fun MST.unaryMinus(): MST.Unary = MstSpace { -this@unaryMinus } public override operator fun MST.unaryMinus(): MST.Unary = MstGroup { -this@unaryMinus }
public override operator fun MST.minus(b: MST): MST.Binary = MstSpace { this@minus - b } public override operator fun MST.minus(b: MST): MST.Binary = MstGroup { this@minus - b }
public override fun binaryOperationFunction(operation: String): (left: MST, right: MST) -> MST.Binary = public override fun binaryOperationFunction(operation: String): (left: MST, right: MST) -> MST.Binary =
MstSpace.binaryOperationFunction(operation) MstGroup.binaryOperationFunction(operation)
public override fun unaryOperationFunction(operation: String): (arg: MST) -> MST.Unary = public override fun unaryOperationFunction(operation: String): (arg: MST) -> MST.Unary =
MstAlgebra.unaryOperationFunction(operation) MstAlgebra.unaryOperationFunction(operation)
@ -77,17 +78,18 @@ public object MstRing : Ring<MST>, RingWithNumbers<MST> {
* [Field] over [MST] nodes. * [Field] over [MST] nodes.
*/ */
@OptIn(UnstableKMathAPI::class) @OptIn(UnstableKMathAPI::class)
public object MstField : Field<MST>, RingWithNumbers<MST> { public object MstField : Field<MST>, NumbersAddOperations<MST>, ScaleOperations<MST> {
public override val zero: MST.Numeric public override val zero: MST.Numeric get() = MstRing.zero
get() = MstRing.zero
public override val one: MST.Numeric public override val one: MST.Numeric get() = MstRing.one
get() = MstRing.one
public override fun symbol(value: String): MST.Symbolic = MstRing.symbol(value) public override fun bindSymbol(value: String): MST.Symbolic = MstAlgebra.bindSymbol(value)
public override fun number(value: Number): MST.Numeric = MstRing.number(value) public override fun number(value: Number): MST.Numeric = MstRing.number(value)
public override fun add(a: MST, b: MST): MST.Binary = MstRing.add(a, b) public override fun add(a: MST, b: MST): MST.Binary = MstRing.add(a, b)
public override fun multiply(a: MST, k: Number): MST.Binary = MstRing.multiply(a, k)
public override fun scale(a: MST, value: Double): MST.Binary =
MstGroup.binaryOperationFunction(RingOperations.TIMES_OPERATION)(a, MstGroup.number(value))
public override fun multiply(a: MST, b: MST): MST.Binary = MstRing.multiply(a, b) public override fun multiply(a: MST, b: MST): MST.Binary = MstRing.multiply(a, b)
public override fun divide(a: MST, b: MST): MST.Binary = public override fun divide(a: MST, b: MST): MST.Binary =
binaryOperationFunction(FieldOperations.DIV_OPERATION)(a, b) binaryOperationFunction(FieldOperations.DIV_OPERATION)(a, b)
@ -107,13 +109,10 @@ public object MstField : Field<MST>, RingWithNumbers<MST> {
* [ExtendedField] over [MST] nodes. * [ExtendedField] over [MST] nodes.
*/ */
public object MstExtendedField : ExtendedField<MST>, NumericAlgebra<MST> { public object MstExtendedField : ExtendedField<MST>, NumericAlgebra<MST> {
public override val zero: MST.Numeric public override val zero: MST.Numeric get() = MstField.zero
get() = MstField.zero public override val one: MST.Numeric get() = MstField.one
public override val one: MST.Numeric public override fun bindSymbol(value: String): MST.Symbolic = MstAlgebra.bindSymbol(value)
get() = MstField.one
public override fun symbol(value: String): MST.Symbolic = MstField.symbol(value)
public override fun number(value: Number): MST.Numeric = MstRing.number(value) public override fun number(value: Number): MST.Numeric = MstRing.number(value)
public override fun sin(arg: MST): MST.Unary = unaryOperationFunction(TrigonometricOperations.SIN_OPERATION)(arg) public override fun sin(arg: MST): MST.Unary = unaryOperationFunction(TrigonometricOperations.SIN_OPERATION)(arg)
public override fun cos(arg: MST): MST.Unary = unaryOperationFunction(TrigonometricOperations.COS_OPERATION)(arg) public override fun cos(arg: MST): MST.Unary = unaryOperationFunction(TrigonometricOperations.COS_OPERATION)(arg)
@ -121,14 +120,17 @@ public object MstExtendedField : ExtendedField<MST>, NumericAlgebra<MST> {
public override fun asin(arg: MST): MST.Unary = unaryOperationFunction(TrigonometricOperations.ASIN_OPERATION)(arg) public override fun asin(arg: MST): MST.Unary = unaryOperationFunction(TrigonometricOperations.ASIN_OPERATION)(arg)
public override fun acos(arg: MST): MST.Unary = unaryOperationFunction(TrigonometricOperations.ACOS_OPERATION)(arg) public override fun acos(arg: MST): MST.Unary = unaryOperationFunction(TrigonometricOperations.ACOS_OPERATION)(arg)
public override fun atan(arg: MST): MST.Unary = unaryOperationFunction(TrigonometricOperations.ATAN_OPERATION)(arg) public override fun atan(arg: MST): MST.Unary = unaryOperationFunction(TrigonometricOperations.ATAN_OPERATION)(arg)
public override fun sinh(arg: MST): MST.Unary = unaryOperationFunction(HyperbolicOperations.SINH_OPERATION)(arg) public override fun sinh(arg: MST): MST.Unary = unaryOperationFunction(ExponentialOperations.SINH_OPERATION)(arg)
public override fun cosh(arg: MST): MST.Unary = unaryOperationFunction(HyperbolicOperations.COSH_OPERATION)(arg) public override fun cosh(arg: MST): MST.Unary = unaryOperationFunction(ExponentialOperations.COSH_OPERATION)(arg)
public override fun tanh(arg: MST): MST.Unary = unaryOperationFunction(HyperbolicOperations.TANH_OPERATION)(arg) public override fun tanh(arg: MST): MST.Unary = unaryOperationFunction(ExponentialOperations.TANH_OPERATION)(arg)
public override fun asinh(arg: MST): MST.Unary = unaryOperationFunction(HyperbolicOperations.ASINH_OPERATION)(arg) public override fun asinh(arg: MST): MST.Unary = unaryOperationFunction(ExponentialOperations.ASINH_OPERATION)(arg)
public override fun acosh(arg: MST): MST.Unary = unaryOperationFunction(HyperbolicOperations.ACOSH_OPERATION)(arg) public override fun acosh(arg: MST): MST.Unary = unaryOperationFunction(ExponentialOperations.ACOSH_OPERATION)(arg)
public override fun atanh(arg: MST): MST.Unary = unaryOperationFunction(HyperbolicOperations.ATANH_OPERATION)(arg) public override fun atanh(arg: MST): MST.Unary = unaryOperationFunction(ExponentialOperations.ATANH_OPERATION)(arg)
public override fun add(a: MST, b: MST): MST.Binary = MstField.add(a, b) public override fun add(a: MST, b: MST): MST.Binary = MstField.add(a, b)
public override fun multiply(a: MST, k: Number): MST.Binary = MstField.multiply(a, k)
public override fun scale(a: MST, value: Double): MST =
binaryOperation(GroupOperations.PLUS_OPERATION, a, number(value))
public override fun multiply(a: MST, b: MST): MST.Binary = MstField.multiply(a, b) public override fun multiply(a: MST, b: MST): MST.Binary = MstField.multiply(a, b)
public override fun divide(a: MST, b: MST): MST.Binary = MstField.divide(a, b) public override fun divide(a: MST, b: MST): MST.Binary = MstField.divide(a, b)
public override operator fun MST.unaryPlus(): MST.Unary = MstField { +this@unaryPlus } public override operator fun MST.unaryPlus(): MST.Unary = MstField { +this@unaryPlus }

View File

@ -1,7 +1,9 @@
package kscience.kmath.ast package space.kscience.kmath.ast
import kscience.kmath.expressions.* import space.kscience.kmath.expressions.*
import kscience.kmath.operations.* import space.kscience.kmath.misc.StringSymbol
import space.kscience.kmath.misc.Symbol
import space.kscience.kmath.operations.*
import kotlin.contracts.InvocationKind import kotlin.contracts.InvocationKind
import kotlin.contracts.contract import kotlin.contracts.contract
@ -15,14 +17,23 @@ import kotlin.contracts.contract
*/ */
public class MstExpression<T, out A : Algebra<T>>(public val algebra: A, public val mst: MST) : Expression<T> { public class MstExpression<T, out A : Algebra<T>>(public val algebra: A, public val mst: MST) : Expression<T> {
private inner class InnerAlgebra(val arguments: Map<Symbol, T>) : NumericAlgebra<T> { private inner class InnerAlgebra(val arguments: Map<Symbol, T>) : NumericAlgebra<T> {
override fun symbol(value: String): T = try { override fun bindSymbol(value: String): T = try {
algebra.symbol(value) algebra.bindSymbol(value)
} catch (ignored: IllegalStateException) { } catch (ignored: IllegalStateException) {
null null
} ?: arguments.getValue(StringSymbol(value)) } ?: arguments.getValue(StringSymbol(value))
override fun unaryOperationFunction(operation: String): (arg: T) -> T = algebra.unaryOperationFunction(operation) override fun unaryOperation(operation: String, arg: T): T =
override fun binaryOperationFunction(operation: String): (left: T, right: T) -> T = algebra.binaryOperationFunction(operation) algebra.unaryOperation(operation, arg)
override fun binaryOperation(operation: String, left: T, right: T): T =
algebra.binaryOperation(operation, left, right)
override fun unaryOperationFunction(operation: String): (arg: T) -> T =
algebra.unaryOperationFunction(operation)
override fun binaryOperationFunction(operation: String): (left: T, right: T) -> T =
algebra.binaryOperationFunction(operation)
@Suppress("UNCHECKED_CAST") @Suppress("UNCHECKED_CAST")
override fun number(value: Number): T = if (algebra is NumericAlgebra<*>) override fun number(value: Number): T = if (algebra is NumericAlgebra<*>)
@ -45,13 +56,13 @@ public inline fun <reified T : Any, A : Algebra<T>, E : Algebra<MST>> A.mst(
): MstExpression<T, A> = MstExpression(this, mstAlgebra.block()) ): MstExpression<T, A> = MstExpression(this, mstAlgebra.block())
/** /**
* Builds [MstExpression] over [Space]. * Builds [MstExpression] over [Group].
* *
* @author Alexander Nozik * @author Alexander Nozik
*/ */
public inline fun <reified T : Any, A : Space<T>> A.mstInSpace(block: MstSpace.() -> MST): MstExpression<T, A> { public inline fun <reified T : Any, A : Group<T>> A.mstInGroup(block: MstGroup.() -> MST): MstExpression<T, A> {
contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) } contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) }
return MstExpression(this, MstSpace.block()) return MstExpression(this, MstGroup.block())
} }
/** /**
@ -85,13 +96,13 @@ public inline fun <reified T : Any, A : ExtendedField<T>> A.mstInExtendedField(b
} }
/** /**
* Builds [MstExpression] over [FunctionalExpressionSpace]. * Builds [MstExpression] over [FunctionalExpressionGroup].
* *
* @author Alexander Nozik * @author Alexander Nozik
*/ */
public inline fun <reified T : Any, A : Space<T>> FunctionalExpressionSpace<T, A>.mstInSpace(block: MstSpace.() -> MST): MstExpression<T, A> { public inline fun <reified T : Any, A : Group<T>> FunctionalExpressionGroup<T, A>.mstInGroup(block: MstGroup.() -> MST): MstExpression<T, A> {
contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) } contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) }
return algebra.mstInSpace(block) return algebra.mstInGroup(block)
} }
/** /**

View File

@ -1,3 +0,0 @@
package kscience.kmath.estree.internal.astring
internal typealias Generator = Any

View File

@ -1,7 +0,0 @@
package kscience.kmath.estree.internal.stream
import kscience.kmath.estree.internal.emitter.Emitter
internal open external class Stream : Emitter {
open fun pipe(dest: Any, options: Any): Any
}

View File

@ -1,20 +1,20 @@
package kscience.kmath.estree package space.kscience.kmath.estree
import kscience.kmath.ast.MST import space.kscience.kmath.ast.MST
import kscience.kmath.ast.MST.* import space.kscience.kmath.ast.MST.*
import kscience.kmath.ast.MstExpression import space.kscience.kmath.ast.MstExpression
import kscience.kmath.estree.internal.ESTreeBuilder import space.kscience.kmath.estree.internal.ESTreeBuilder
import kscience.kmath.estree.internal.estree.BaseExpression import space.kscience.kmath.estree.internal.estree.BaseExpression
import kscience.kmath.expressions.Expression import space.kscience.kmath.expressions.Expression
import kscience.kmath.operations.Algebra import space.kscience.kmath.operations.Algebra
import kscience.kmath.operations.NumericAlgebra import space.kscience.kmath.operations.NumericAlgebra
@PublishedApi @PublishedApi
internal fun <T> MST.compileWith(algebra: Algebra<T>): Expression<T> { internal fun <T> MST.compileWith(algebra: Algebra<T>): Expression<T> {
fun ESTreeBuilder<T>.visit(node: MST): BaseExpression = when (node) { fun ESTreeBuilder<T>.visit(node: MST): BaseExpression = when (node) {
is Symbolic -> { is Symbolic -> {
val symbol = try { val symbol = try {
algebra.symbol(node.value) algebra.bindSymbol(node.value)
} catch (ignored: IllegalStateException) { } catch (ignored: IllegalStateException) {
null null
} }

View File

@ -1,9 +1,9 @@
package kscience.kmath.estree.internal package space.kscience.kmath.estree.internal
import kscience.kmath.estree.internal.astring.generate import space.kscience.kmath.estree.internal.astring.generate
import kscience.kmath.estree.internal.estree.* import space.kscience.kmath.estree.internal.estree.*
import kscience.kmath.expressions.Expression import space.kscience.kmath.expressions.Expression
import kscience.kmath.expressions.Symbol import space.kscience.kmath.misc.Symbol
internal class ESTreeBuilder<T>(val bodyCallback: ESTreeBuilder<T>.() -> BaseExpression) { internal class ESTreeBuilder<T>(val bodyCallback: ESTreeBuilder<T>.() -> BaseExpression) {
private class GeneratedExpression<T>(val executable: dynamic, val constants: Array<dynamic>) : Expression<T> { private class GeneratedExpression<T>(val executable: dynamic, val constants: Array<dynamic>) : Expression<T> {

View File

@ -1,9 +1,9 @@
@file:JsModule("astring") @file:JsModule("astring")
@file:JsNonModule @file:JsNonModule
package kscience.kmath.estree.internal.astring package space.kscience.kmath.estree.internal.astring
import kscience.kmath.estree.internal.estree.BaseNode import space.kscience.kmath.estree.internal.estree.BaseNode
internal external interface Options { internal external interface Options {
var indent: String? var indent: String?

View File

@ -0,0 +1,3 @@
package space.kscience.kmath.estree.internal.astring
internal typealias Generator = Any

View File

@ -1,4 +1,4 @@
package kscience.kmath.estree.internal.emitter package space.kscience.kmath.estree.internal.emitter
internal open external class Emitter { internal open external class Emitter {
constructor(obj: Any) constructor(obj: Any)

View File

@ -1,4 +1,4 @@
package kscience.kmath.estree.internal.estree package space.kscience.kmath.estree.internal.estree
internal fun Program(sourceType: String, vararg body: dynamic) = object : Program { internal fun Program(sourceType: String, vararg body: dynamic) = object : Program {
override var type = "Program" override var type = "Program"

View File

@ -1,4 +1,4 @@
package kscience.kmath.estree.internal.estree package space.kscience.kmath.estree.internal.estree
import kotlin.js.RegExp import kotlin.js.RegExp

View File

@ -0,0 +1,7 @@
package space.kscience.kmath.estree.internal.stream
import space.kscience.kmath.estree.internal.emitter.Emitter
internal open external class Stream : Emitter {
open fun pipe(dest: Any, options: Any): Any
}

View File

@ -1,4 +1,4 @@
package kscience.kmath.estree.internal.tsstdlib package space.kscience.kmath.estree.internal.tsstdlib
internal external interface IteratorYieldResult<TYield> { internal external interface IteratorYieldResult<TYield> {
var done: Boolean? var done: Boolean?

View File

@ -1,6 +1,6 @@
@file:Suppress("UNUSED_TYPEALIAS_PARAMETER", "DEPRECATION") @file:Suppress("UNUSED_TYPEALIAS_PARAMETER", "DEPRECATION")
package kscience.kmath.estree.internal.tsstdlib package space.kscience.kmath.estree.internal.tsstdlib
import kotlin.js.RegExp import kotlin.js.RegExp

View File

@ -1,41 +0,0 @@
package kscience.kmath.estree
import kscience.kmath.ast.mstInExtendedField
import kscience.kmath.ast.mstInField
import kscience.kmath.ast.mstInSpace
import kscience.kmath.expressions.invoke
import kscience.kmath.operations.RealField
import kotlin.random.Random
import kotlin.test.Test
import kotlin.test.assertEquals
internal class TestESTreeOperationsSupport {
@Test
fun testUnaryOperationInvocation() {
val expression = RealField.mstInSpace { -symbol("x") }.compile()
val res = expression("x" to 2.0)
assertEquals(-2.0, res)
}
@Test
fun testBinaryOperationInvocation() {
val expression = RealField.mstInSpace { -symbol("x") + number(1.0) }.compile()
val res = expression("x" to 2.0)
assertEquals(-1.0, res)
}
@Test
fun testConstProductInvocation() {
val res = RealField.mstInField { symbol("x") * 2 }("x" to 2.0)
assertEquals(4.0, res)
}
@Test
fun testMultipleCalls() {
val e = RealField.mstInExtendedField { sin(symbol("x")).pow(4) - 6 * symbol("x") / tanh(symbol("x")) }.compile()
val r = Random(0)
var s = 0.0
repeat(1000000) { s += e("x" to r.nextDouble()) }
println(s)
}
}

View File

@ -1,54 +0,0 @@
package kscience.kmath.estree
import kscience.kmath.ast.mstInField
import kscience.kmath.expressions.invoke
import kscience.kmath.operations.RealField
import kotlin.test.Test
import kotlin.test.assertEquals
internal class TestESTreeSpecialization {
@Test
fun testUnaryPlus() {
val expr = RealField.mstInField { unaryOperationFunction("+")(symbol("x")) }.compile()
assertEquals(2.0, expr("x" to 2.0))
}
@Test
fun testUnaryMinus() {
val expr = RealField.mstInField { unaryOperationFunction("-")(symbol("x")) }.compile()
assertEquals(-2.0, expr("x" to 2.0))
}
@Test
fun testAdd() {
val expr = RealField.mstInField { binaryOperationFunction("+")(symbol("x"), symbol("x")) }.compile()
assertEquals(4.0, expr("x" to 2.0))
}
@Test
fun testSine() {
val expr = RealField.mstInField { unaryOperationFunction("sin")(symbol("x")) }.compile()
assertEquals(0.0, expr("x" to 0.0))
}
@Test
fun testMinus() {
val expr = RealField.mstInField { binaryOperationFunction("-")(symbol("x"), symbol("x")) }.compile()
assertEquals(0.0, expr("x" to 2.0))
}
@Test
fun testDivide() {
val expr = RealField.mstInField { binaryOperationFunction("/")(symbol("x"), symbol("x")) }.compile()
assertEquals(1.0, expr("x" to 2.0))
}
@Test
fun testPower() {
val expr = RealField
.mstInField { binaryOperationFunction("pow")(symbol("x"), number(2)) }
.compile()
assertEquals(4.0, expr("x" to 2.0))
}
}

View File

@ -1,41 +1,41 @@
package kscience.kmath.estree package space.kscience.kmath.estree
import kscience.kmath.ast.* import space.kscience.kmath.ast.*
import kscience.kmath.complex.ComplexField import space.kscience.kmath.complex.ComplexField
import kscience.kmath.complex.toComplex import space.kscience.kmath.complex.toComplex
import kscience.kmath.expressions.invoke import space.kscience.kmath.expressions.invoke
import kscience.kmath.operations.ByteRing import space.kscience.kmath.operations.ByteRing
import kscience.kmath.operations.RealField import space.kscience.kmath.operations.DoubleField
import kotlin.test.Test import kotlin.test.Test
import kotlin.test.assertEquals import kotlin.test.assertEquals
internal class TestESTreeConsistencyWithInterpreter { internal class TestESTreeConsistencyWithInterpreter {
@Test @Test
fun mstSpace() { fun mstSpace() {
val res1 = MstSpace.mstInSpace { val res1 = MstGroup.mstInGroup {
binaryOperationFunction("+")( binaryOperationFunction("+")(
unaryOperationFunction("+")( unaryOperationFunction("+")(
number(3.toByte()) - (number(2.toByte()) + (multiply( number(3.toByte()) - (number(2.toByte()) + (scale(
add(number(1), number(1)), add(number(1), number(1)),
2 2.0
) + number(1.toByte()) * 3.toByte() - number(1.toByte()))) ) + number(1.toByte()) * 3.toByte() - number(1.toByte())))
), ),
number(1) number(1)
) + symbol("x") + zero ) + bindSymbol("x") + zero
}("x" to MST.Numeric(2)) }("x" to MST.Numeric(2))
val res2 = MstSpace.mstInSpace { val res2 = MstGroup.mstInGroup {
binaryOperationFunction("+")( binaryOperationFunction("+")(
unaryOperationFunction("+")( unaryOperationFunction("+")(
number(3.toByte()) - (number(2.toByte()) + (multiply( number(3.toByte()) - (number(2.toByte()) + (scale(
add(number(1), number(1)), add(number(1), number(1)),
2 2.0
) + number(1.toByte()) * 3.toByte() - number(1.toByte()))) ) + number(1.toByte()) * 3.toByte() - number(1.toByte())))
), ),
number(1) number(1)
) + symbol("x") + zero ) + bindSymbol("x") + zero
}.compile()("x" to MST.Numeric(2)) }.compile()("x" to MST.Numeric(2))
assertEquals(res1, res2) assertEquals(res1, res2)
@ -46,9 +46,9 @@ internal class TestESTreeConsistencyWithInterpreter {
val res1 = ByteRing.mstInRing { val res1 = ByteRing.mstInRing {
binaryOperationFunction("+")( binaryOperationFunction("+")(
unaryOperationFunction("+")( unaryOperationFunction("+")(
(symbol("x") - (2.toByte() + (multiply( (bindSymbol("x") - (2.toByte() + (scale(
add(number(1), number(1)), add(number(1), number(1)),
2 2.0
) + 1.toByte()))) * 3.0 - 1.toByte() ) + 1.toByte()))) * 3.0 - 1.toByte()
), ),
@ -59,9 +59,9 @@ internal class TestESTreeConsistencyWithInterpreter {
val res2 = ByteRing.mstInRing { val res2 = ByteRing.mstInRing {
binaryOperationFunction("+")( binaryOperationFunction("+")(
unaryOperationFunction("+")( unaryOperationFunction("+")(
(symbol("x") - (2.toByte() + (multiply( (bindSymbol("x") - (2.toByte() + (scale(
add(number(1), number(1)), add(number(1), number(1)),
2 2.0
) + 1.toByte()))) * 3.0 - 1.toByte() ) + 1.toByte()))) * 3.0 - 1.toByte()
), ),
number(1) number(1)
@ -73,17 +73,17 @@ internal class TestESTreeConsistencyWithInterpreter {
@Test @Test
fun realField() { fun realField() {
val res1 = RealField.mstInField { val res1 = DoubleField.mstInField {
+(3 - 2 + 2 * number(1) + 1.0) + binaryOperationFunction("+")( +(3 - 2 + 2 * number(1) + 1.0) + binaryOperationFunction("+")(
(3.0 - (symbol("x") + (multiply(add(number(1.0), number(1.0)), 2) + 1.0))) * 3 - 1.0 (3.0 - (bindSymbol("x") + (scale(add(number(1.0), number(1.0)), 2.0) + 1.0))) * 3 - 1.0
+ number(1), + number(1),
number(1) / 2 + number(2.0) * one number(1) / 2 + number(2.0) * one
) + zero ) + zero
}("x" to 2.0) }("x" to 2.0)
val res2 = RealField.mstInField { val res2 = DoubleField.mstInField {
+(3 - 2 + 2 * number(1) + 1.0) + binaryOperationFunction("+")( +(3 - 2 + 2 * number(1) + 1.0) + binaryOperationFunction("+")(
(3.0 - (symbol("x") + (multiply(add(number(1.0), number(1.0)), 2) + 1.0))) * 3 - 1.0 (3.0 - (bindSymbol("x") + (scale(add(number(1.0), number(1.0)), 2.0) + 1.0))) * 3 - 1.0
+ number(1), + number(1),
number(1) / 2 + number(2.0) * one number(1) / 2 + number(2.0) * one
) + zero ) + zero
@ -96,7 +96,7 @@ internal class TestESTreeConsistencyWithInterpreter {
fun complexField() { fun complexField() {
val res1 = ComplexField.mstInField { val res1 = ComplexField.mstInField {
+(3 - 2 + 2 * number(1) + 1.0) + binaryOperationFunction("+")( +(3 - 2 + 2 * number(1) + 1.0) + binaryOperationFunction("+")(
(3.0 - (symbol("x") + (multiply(add(number(1.0), number(1.0)), 2) + 1.0))) * 3 - 1.0 (3.0 - (bindSymbol("x") + (scale(add(number(1.0), number(1.0)), 2.0) + 1.0))) * 3 - 1.0
+ number(1), + number(1),
number(1) / 2 + number(2.0) * one number(1) / 2 + number(2.0) * one
) + zero ) + zero
@ -104,7 +104,7 @@ internal class TestESTreeConsistencyWithInterpreter {
val res2 = ComplexField.mstInField { val res2 = ComplexField.mstInField {
+(3 - 2 + 2 * number(1) + 1.0) + binaryOperationFunction("+")( +(3 - 2 + 2 * number(1) + 1.0) + binaryOperationFunction("+")(
(3.0 - (symbol("x") + (multiply(add(number(1.0), number(1.0)), 2) + 1.0))) * 3 - 1.0 (3.0 - (bindSymbol("x") + (scale(add(number(1.0), number(1.0)), 2.0) + 1.0))) * 3 - 1.0
+ number(1), + number(1),
number(1) / 2 + number(2.0) * one number(1) / 2 + number(2.0) * one
) + zero ) + zero

View File

@ -0,0 +1,43 @@
package space.kscience.kmath.estree
import space.kscience.kmath.ast.mstInExtendedField
import space.kscience.kmath.ast.mstInField
import space.kscience.kmath.ast.mstInGroup
import space.kscience.kmath.expressions.invoke
import space.kscience.kmath.operations.DoubleField
import kotlin.random.Random
import kotlin.test.Test
import kotlin.test.assertEquals
internal class TestESTreeOperationsSupport {
@Test
fun testUnaryOperationInvocation() {
val expression = DoubleField.mstInGroup { -bindSymbol("x") }.compile()
val res = expression("x" to 2.0)
assertEquals(-2.0, res)
}
@Test
fun testBinaryOperationInvocation() {
val expression = DoubleField.mstInGroup { -bindSymbol("x") + number(1.0) }.compile()
val res = expression("x" to 2.0)
assertEquals(-1.0, res)
}
@Test
fun testConstProductInvocation() {
val res = DoubleField.mstInField { bindSymbol("x") * 2 }("x" to 2.0)
assertEquals(4.0, res)
}
@Test
fun testMultipleCalls() {
val e =
DoubleField.mstInExtendedField { sin(bindSymbol("x")).pow(4) - 6 * bindSymbol("x") / tanh(bindSymbol("x")) }
.compile()
val r = Random(0)
var s = 0.0
repeat(1000000) { s += e("x" to r.nextDouble()) }
println(s)
}
}

View File

@ -0,0 +1,54 @@
package space.kscience.kmath.estree
import space.kscience.kmath.ast.mstInField
import space.kscience.kmath.expressions.invoke
import space.kscience.kmath.operations.DoubleField
import kotlin.test.Test
import kotlin.test.assertEquals
internal class TestESTreeSpecialization {
@Test
fun testUnaryPlus() {
val expr = DoubleField.mstInField { unaryOperationFunction("+")(bindSymbol("x")) }.compile()
assertEquals(2.0, expr("x" to 2.0))
}
@Test
fun testUnaryMinus() {
val expr = DoubleField.mstInField { unaryOperationFunction("-")(bindSymbol("x")) }.compile()
assertEquals(-2.0, expr("x" to 2.0))
}
@Test
fun testAdd() {
val expr = DoubleField.mstInField { binaryOperationFunction("+")(bindSymbol("x"), bindSymbol("x")) }.compile()
assertEquals(4.0, expr("x" to 2.0))
}
@Test
fun testSine() {
val expr = DoubleField.mstInField { unaryOperationFunction("sin")(bindSymbol("x")) }.compile()
assertEquals(0.0, expr("x" to 0.0))
}
@Test
fun testMinus() {
val expr = DoubleField.mstInField { binaryOperationFunction("-")(bindSymbol("x"), bindSymbol("x")) }.compile()
assertEquals(0.0, expr("x" to 2.0))
}
@Test
fun testDivide() {
val expr = DoubleField.mstInField { binaryOperationFunction("/")(bindSymbol("x"), bindSymbol("x")) }.compile()
assertEquals(1.0, expr("x" to 2.0))
}
@Test
fun testPower() {
val expr = DoubleField
.mstInField { binaryOperationFunction("pow")(bindSymbol("x"), number(2)) }
.compile()
assertEquals(4.0, expr("x" to 2.0))
}
}

View File

@ -1,8 +1,8 @@
package kscience.kmath.estree package space.kscience.kmath.estree
import kscience.kmath.ast.mstInRing import space.kscience.kmath.ast.mstInRing
import kscience.kmath.expressions.invoke import space.kscience.kmath.expressions.invoke
import kscience.kmath.operations.ByteRing import space.kscience.kmath.operations.ByteRing
import kotlin.test.Test import kotlin.test.Test
import kotlin.test.assertEquals import kotlin.test.assertEquals
import kotlin.test.assertFailsWith import kotlin.test.assertFailsWith
@ -10,13 +10,13 @@ import kotlin.test.assertFailsWith
internal class TestESTreeVariables { internal class TestESTreeVariables {
@Test @Test
fun testVariable() { fun testVariable() {
val expr = ByteRing.mstInRing { symbol("x") }.compile() val expr = ByteRing.mstInRing { bindSymbol("x") }.compile()
assertEquals(1.toByte(), expr("x" to 1.toByte())) assertEquals(1.toByte(), expr("x" to 1.toByte()))
} }
@Test @Test
fun testUndefinedVariableFails() { fun testUndefinedVariableFails() {
val expr = ByteRing.mstInRing { symbol("x") }.compile() val expr = ByteRing.mstInRing { bindSymbol("x") }.compile()
assertFailsWith<NoSuchElementException> { expr() } assertFailsWith<NoSuchElementException> { expr() }
} }
} }

View File

@ -1,13 +1,13 @@
package kscience.kmath.asm package space.kscience.kmath.asm
import kscience.kmath.asm.internal.AsmBuilder import space.kscience.kmath.asm.internal.AsmBuilder
import kscience.kmath.asm.internal.buildName import space.kscience.kmath.asm.internal.buildName
import kscience.kmath.ast.MST import space.kscience.kmath.ast.MST
import kscience.kmath.ast.MST.* import space.kscience.kmath.ast.MST.*
import kscience.kmath.ast.MstExpression import space.kscience.kmath.ast.MstExpression
import kscience.kmath.expressions.Expression import space.kscience.kmath.expressions.Expression
import kscience.kmath.operations.Algebra import space.kscience.kmath.operations.Algebra
import kscience.kmath.operations.NumericAlgebra import space.kscience.kmath.operations.NumericAlgebra
/** /**
* Compiles given MST to an Expression using AST compiler. * Compiles given MST to an Expression using AST compiler.
@ -22,7 +22,7 @@ internal fun <T : Any> MST.compileWith(type: Class<T>, algebra: Algebra<T>): Exp
fun AsmBuilder<T>.visit(node: MST): Unit = when (node) { fun AsmBuilder<T>.visit(node: MST): Unit = when (node) {
is Symbolic -> { is Symbolic -> {
val symbol = try { val symbol = try {
algebra.symbol(node.value) algebra.bindSymbol(node.value)
} catch (ignored: IllegalStateException) { } catch (ignored: IllegalStateException) {
null null
} }

View File

@ -1,15 +1,14 @@
package kscience.kmath.asm.internal package space.kscience.kmath.asm.internal
import kscience.kmath.asm.internal.AsmBuilder.ClassLoader
import kscience.kmath.ast.MST
import kscience.kmath.expressions.Expression
import org.objectweb.asm.* import org.objectweb.asm.*
import org.objectweb.asm.Opcodes.* import org.objectweb.asm.Opcodes.*
import org.objectweb.asm.Type.* import org.objectweb.asm.Type.*
import org.objectweb.asm.commons.InstructionAdapter import org.objectweb.asm.commons.InstructionAdapter
import space.kscience.kmath.asm.internal.AsmBuilder.ClassLoader
import space.kscience.kmath.ast.MST
import space.kscience.kmath.expressions.Expression
import java.lang.invoke.MethodHandles import java.lang.invoke.MethodHandles
import java.lang.invoke.MethodType import java.lang.invoke.MethodType
import java.lang.reflect.Modifier
import java.util.stream.Collectors.toMap import java.util.stream.Collectors.toMap
import kotlin.contracts.InvocationKind import kotlin.contracts.InvocationKind
import kotlin.contracts.contract import kotlin.contracts.contract
@ -310,7 +309,7 @@ internal class AsmBuilder<T>(
/** /**
* ASM type for [Expression]. * ASM type for [Expression].
*/ */
val EXPRESSION_TYPE: Type by lazy { getObjectType("kscience/kmath/expressions/Expression") } val EXPRESSION_TYPE: Type by lazy { getObjectType("space/kscience/kmath/expressions/Expression") }
/** /**
* ASM type for [java.util.Map]. * ASM type for [java.util.Map].
@ -335,11 +334,11 @@ internal class AsmBuilder<T>(
/** /**
* ASM type for MapIntrinsics. * ASM type for MapIntrinsics.
*/ */
val MAP_INTRINSICS_TYPE: Type by lazy { getObjectType("kscience/kmath/asm/internal/MapIntrinsics") } val MAP_INTRINSICS_TYPE: Type by lazy { getObjectType("space/kscience/kmath/asm/internal/MapIntrinsics") }
/** /**
* ASM Type for [kscience.kmath.expressions.Symbol]. * ASM Type for [kscience.kmath.expressions.Symbol].
*/ */
val SYMBOL_TYPE: Type by lazy { getObjectType("kscience/kmath/expressions/Symbol") } val SYMBOL_TYPE: Type by lazy { getObjectType("space/kscience/kmath/expressions/Symbol") }
} }
} }

View File

@ -1,9 +1,9 @@
package kscience.kmath.asm.internal package space.kscience.kmath.asm.internal
import kscience.kmath.ast.MST
import kscience.kmath.expressions.Expression
import org.objectweb.asm.* import org.objectweb.asm.*
import org.objectweb.asm.commons.InstructionAdapter import org.objectweb.asm.commons.InstructionAdapter
import space.kscience.kmath.ast.MST
import space.kscience.kmath.expressions.Expression
import kotlin.contracts.InvocationKind import kotlin.contracts.InvocationKind
import kotlin.contracts.contract import kotlin.contracts.contract
@ -86,7 +86,7 @@ internal inline fun ClassWriter.visitField(
descriptor: String, descriptor: String,
signature: String?, signature: String?,
value: Any?, value: Any?,
block: FieldVisitor.() -> Unit block: FieldVisitor.() -> Unit,
): FieldVisitor { ): FieldVisitor {
contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) } contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) }
return visitField(access, name, descriptor, signature, value).apply(block) return visitField(access, name, descriptor, signature, value).apply(block)

View File

@ -1,9 +1,9 @@
@file:JvmName("MapIntrinsics") @file:JvmName("MapIntrinsics")
package kscience.kmath.asm.internal package space.kscience.kmath.asm.internal
import kscience.kmath.expressions.StringSymbol import space.kscience.kmath.misc.StringSymbol
import kscience.kmath.expressions.Symbol import space.kscience.kmath.misc.Symbol
/** /**
* Gets value with given [key] or throws [NoSuchElementException] whenever it is not present. * Gets value with given [key] or throws [NoSuchElementException] whenever it is not present.

View File

@ -1,6 +1,6 @@
// TODO move to common when https://github.com/h0tk3y/better-parse/pull/33 is merged // TODO move to common when https://github.com/h0tk3y/better-parse/pull/37 is merged
package kscience.kmath.ast package space.kscience.kmath.ast
import com.github.h0tk3y.betterParse.combinators.* import com.github.h0tk3y.betterParse.combinators.*
import com.github.h0tk3y.betterParse.grammar.Grammar import com.github.h0tk3y.betterParse.grammar.Grammar
@ -13,10 +13,10 @@ import com.github.h0tk3y.betterParse.lexer.literalToken
import com.github.h0tk3y.betterParse.lexer.regexToken import com.github.h0tk3y.betterParse.lexer.regexToken
import com.github.h0tk3y.betterParse.parser.ParseResult import com.github.h0tk3y.betterParse.parser.ParseResult
import com.github.h0tk3y.betterParse.parser.Parser import com.github.h0tk3y.betterParse.parser.Parser
import kscience.kmath.operations.FieldOperations import space.kscience.kmath.operations.FieldOperations
import kscience.kmath.operations.PowerOperations import space.kscience.kmath.operations.GroupOperations
import kscience.kmath.operations.RingOperations import space.kscience.kmath.operations.PowerOperations
import kscience.kmath.operations.SpaceOperations import space.kscience.kmath.operations.RingOperations
/** /**
* better-parse implementation of grammar defined in the ArithmeticsEvaluator.g4. * better-parse implementation of grammar defined in the ArithmeticsEvaluator.g4.
@ -25,8 +25,8 @@ import kscience.kmath.operations.SpaceOperations
*/ */
public object ArithmeticsEvaluator : Grammar<MST>() { public object ArithmeticsEvaluator : Grammar<MST>() {
// TODO replace with "...".toRegex() when better-parse 0.4.1 is released // TODO replace with "...".toRegex() when better-parse 0.4.1 is released
private val num: Token by regexToken("[\\d.]+(?:[eE][-+]?\\d+)?") private val num: Token by regexToken("[\\d.]+(?:[eE][-+]?\\d+)?".toRegex())
private val id: Token by regexToken("[a-z_A-Z][\\da-z_A-Z]*") private val id: Token by regexToken("[a-z_A-Z][\\da-z_A-Z]*".toRegex())
private val lpar: Token by literalToken("(") private val lpar: Token by literalToken("(")
private val rpar: Token by literalToken(")") private val rpar: Token by literalToken(")")
private val comma: Token by literalToken(",") private val comma: Token by literalToken(",")
@ -35,7 +35,7 @@ public object ArithmeticsEvaluator : Grammar<MST>() {
private val div: Token by literalToken("/") private val div: Token by literalToken("/")
private val minus: Token by literalToken("-") private val minus: Token by literalToken("-")
private val plus: Token by literalToken("+") private val plus: Token by literalToken("+")
private val ws: Token by regexToken("\\s+", ignore = true) private val ws: Token by regexToken("\\s+".toRegex(), ignore = true)
private val number: Parser<MST> by num use { MST.Numeric(text.toDouble()) } private val number: Parser<MST> by num use { MST.Numeric(text.toDouble()) }
private val singular: Parser<MST> by id use { MST.Symbolic(text) } private val singular: Parser<MST> by id use { MST.Symbolic(text) }
@ -55,7 +55,7 @@ public object ArithmeticsEvaluator : Grammar<MST>() {
.or(binaryFunction) .or(binaryFunction)
.or(unaryFunction) .or(unaryFunction)
.or(singular) .or(singular)
.or(-minus and parser(ArithmeticsEvaluator::term) map { MST.Unary(SpaceOperations.MINUS_OPERATION, it) }) .or(-minus and parser(ArithmeticsEvaluator::term) map { MST.Unary(GroupOperations.MINUS_OPERATION, it) })
.or(-lpar and parser(ArithmeticsEvaluator::subSumChain) and -rpar) .or(-lpar and parser(ArithmeticsEvaluator::subSumChain) and -rpar)
private val powChain: Parser<MST> by leftAssociative(term = term, operator = pow) { a, _, b -> private val powChain: Parser<MST> by leftAssociative(term = term, operator = pow) { a, _, b ->
@ -77,9 +77,9 @@ public object ArithmeticsEvaluator : Grammar<MST>() {
operator = plus or minus use TokenMatch::type operator = plus or minus use TokenMatch::type
) { a, op, b -> ) { a, op, b ->
if (op == plus) if (op == plus)
MST.Binary(SpaceOperations.PLUS_OPERATION, a, b) MST.Binary(GroupOperations.PLUS_OPERATION, a, b)
else else
MST.Binary(SpaceOperations.MINUS_OPERATION, a, b) MST.Binary(GroupOperations.MINUS_OPERATION, a, b)
} }
override val rootParser: Parser<MST> by subSumChain override val rootParser: Parser<MST> by subSumChain

View File

@ -1,41 +0,0 @@
package kscience.kmath.asm
import kscience.kmath.ast.mstInExtendedField
import kscience.kmath.ast.mstInField
import kscience.kmath.ast.mstInSpace
import kscience.kmath.expressions.invoke
import kscience.kmath.operations.RealField
import kotlin.random.Random
import kotlin.test.Test
import kotlin.test.assertEquals
internal class TestAsmOperationsSupport {
@Test
fun testUnaryOperationInvocation() {
val expression = RealField.mstInSpace { -symbol("x") }.compile()
val res = expression("x" to 2.0)
assertEquals(-2.0, res)
}
@Test
fun testBinaryOperationInvocation() {
val expression = RealField.mstInSpace { -symbol("x") + number(1.0) }.compile()
val res = expression("x" to 2.0)
assertEquals(-1.0, res)
}
@Test
fun testConstProductInvocation() {
val res = RealField.mstInField { symbol("x") * 2 }("x" to 2.0)
assertEquals(4.0, res)
}
@Test
fun testMultipleCalls() {
val e = RealField.mstInExtendedField { sin(symbol("x")).pow(4) - 6 * symbol("x") / tanh(symbol("x")) }.compile()
val r = Random(0)
var s = 0.0
repeat(1000000) { s += e("x" to r.nextDouble()) }
println(s)
}
}

View File

@ -1,54 +0,0 @@
package kscience.kmath.asm
import kscience.kmath.ast.mstInField
import kscience.kmath.expressions.invoke
import kscience.kmath.operations.RealField
import kotlin.test.Test
import kotlin.test.assertEquals
internal class TestAsmSpecialization {
@Test
fun testUnaryPlus() {
val expr = RealField.mstInField { unaryOperationFunction("+")(symbol("x")) }.compile()
assertEquals(2.0, expr("x" to 2.0))
}
@Test
fun testUnaryMinus() {
val expr = RealField.mstInField { unaryOperationFunction("-")(symbol("x")) }.compile()
assertEquals(-2.0, expr("x" to 2.0))
}
@Test
fun testAdd() {
val expr = RealField.mstInField { binaryOperationFunction("+")(symbol("x"), symbol("x")) }.compile()
assertEquals(4.0, expr("x" to 2.0))
}
@Test
fun testSine() {
val expr = RealField.mstInField { unaryOperationFunction("sin")(symbol("x")) }.compile()
assertEquals(0.0, expr("x" to 0.0))
}
@Test
fun testMinus() {
val expr = RealField.mstInField { binaryOperationFunction("-")(symbol("x"), symbol("x")) }.compile()
assertEquals(0.0, expr("x" to 2.0))
}
@Test
fun testDivide() {
val expr = RealField.mstInField { binaryOperationFunction("/")(symbol("x"), symbol("x")) }.compile()
assertEquals(1.0, expr("x" to 2.0))
}
@Test
fun testPower() {
val expr = RealField
.mstInField { binaryOperationFunction("pow")(symbol("x"), number(2)) }
.compile()
assertEquals(4.0, expr("x" to 2.0))
}
}

View File

@ -1,40 +1,41 @@
package kscience.kmath.asm package space.kscience.kmath.asm
import kscience.kmath.ast.* import space.kscience.kmath.ast.*
import kscience.kmath.complex.* import space.kscience.kmath.complex.ComplexField
import kscience.kmath.expressions.invoke import space.kscience.kmath.complex.toComplex
import kscience.kmath.operations.ByteRing import space.kscience.kmath.expressions.invoke
import kscience.kmath.operations.RealField import space.kscience.kmath.operations.ByteRing
import space.kscience.kmath.operations.DoubleField
import kotlin.test.Test import kotlin.test.Test
import kotlin.test.assertEquals import kotlin.test.assertEquals
internal class TestAsmConsistencyWithInterpreter { internal class TestAsmConsistencyWithInterpreter {
@Test @Test
fun mstSpace() { fun mstSpace() {
val res1 = MstSpace.mstInSpace { val res1 = MstGroup.mstInGroup {
binaryOperationFunction("+")( binaryOperationFunction("+")(
unaryOperationFunction("+")( unaryOperationFunction("+")(
number(3.toByte()) - (number(2.toByte()) + (multiply( number(3.toByte()) - (number(2.toByte()) + (scale(
add(number(1), number(1)), add(number(1), number(1)),
2 2.0
) + number(1.toByte()) * 3.toByte() - number(1.toByte()))) ) + number(1.toByte()) * 3.toByte() - number(1.toByte())))
), ),
number(1) number(1)
) + symbol("x") + zero ) + bindSymbol("x") + zero
}("x" to MST.Numeric(2)) }("x" to MST.Numeric(2))
val res2 = MstSpace.mstInSpace { val res2 = MstGroup.mstInGroup {
binaryOperationFunction("+")( binaryOperationFunction("+")(
unaryOperationFunction("+")( unaryOperationFunction("+")(
number(3.toByte()) - (number(2.toByte()) + (multiply( number(3.toByte()) - (number(2.toByte()) + (scale(
add(number(1), number(1)), add(number(1), number(1)),
2 2.0
) + number(1.toByte()) * 3.toByte() - number(1.toByte()))) ) + number(1.toByte()) * 3.toByte() - number(1.toByte())))
), ),
number(1) number(1)
) + symbol("x") + zero ) + bindSymbol("x") + zero
}.compile()("x" to MST.Numeric(2)) }.compile()("x" to MST.Numeric(2))
assertEquals(res1, res2) assertEquals(res1, res2)
@ -45,9 +46,9 @@ internal class TestAsmConsistencyWithInterpreter {
val res1 = ByteRing.mstInRing { val res1 = ByteRing.mstInRing {
binaryOperationFunction("+")( binaryOperationFunction("+")(
unaryOperationFunction("+")( unaryOperationFunction("+")(
(symbol("x") - (2.toByte() + (multiply( (bindSymbol("x") - (2.toByte() + (scale(
add(number(1), number(1)), add(number(1), number(1)),
2 2.0
) + 1.toByte()))) * 3.0 - 1.toByte() ) + 1.toByte()))) * 3.0 - 1.toByte()
), ),
@ -58,9 +59,9 @@ internal class TestAsmConsistencyWithInterpreter {
val res2 = ByteRing.mstInRing { val res2 = ByteRing.mstInRing {
binaryOperationFunction("+")( binaryOperationFunction("+")(
unaryOperationFunction("+")( unaryOperationFunction("+")(
(symbol("x") - (2.toByte() + (multiply( (bindSymbol("x") - (2.toByte() + (scale(
add(number(1), number(1)), add(number(1), number(1)),
2 2.0
) + 1.toByte()))) * 3.0 - 1.toByte() ) + 1.toByte()))) * 3.0 - 1.toByte()
), ),
number(1) number(1)
@ -72,17 +73,17 @@ internal class TestAsmConsistencyWithInterpreter {
@Test @Test
fun realField() { fun realField() {
val res1 = RealField.mstInField { val res1 = DoubleField.mstInField {
+(3 - 2 + 2 * number(1) + 1.0) + binaryOperationFunction("+")( +(3 - 2 + 2 * number(1) + 1.0) + binaryOperationFunction("+")(
(3.0 - (symbol("x") + (multiply(add(number(1.0), number(1.0)), 2) + 1.0))) * 3 - 1.0 (3.0 - (bindSymbol("x") + (scale(add(number(1.0), number(1.0)), 2.0) + 1.0))) * 3 - 1.0
+ number(1), + number(1),
number(1) / 2 + number(2.0) * one number(1) / 2 + number(2.0) * one
) + zero ) + zero
}("x" to 2.0) }("x" to 2.0)
val res2 = RealField.mstInField { val res2 = DoubleField.mstInField {
+(3 - 2 + 2 * number(1) + 1.0) + binaryOperationFunction("+")( +(3 - 2 + 2 * number(1) + 1.0) + binaryOperationFunction("+")(
(3.0 - (symbol("x") + (multiply(add(number(1.0), number(1.0)), 2) + 1.0))) * 3 - 1.0 (3.0 - (bindSymbol("x") + (scale(add(number(1.0), number(1.0)), 2.0) + 1.0))) * 3 - 1.0
+ number(1), + number(1),
number(1) / 2 + number(2.0) * one number(1) / 2 + number(2.0) * one
) + zero ) + zero
@ -95,7 +96,7 @@ internal class TestAsmConsistencyWithInterpreter {
fun complexField() { fun complexField() {
val res1 = ComplexField.mstInField { val res1 = ComplexField.mstInField {
+(3 - 2 + 2 * number(1) + 1.0) + binaryOperationFunction("+")( +(3 - 2 + 2 * number(1) + 1.0) + binaryOperationFunction("+")(
(3.0 - (symbol("x") + (multiply(add(number(1.0), number(1.0)), 2) + 1.0))) * 3 - 1.0 (3.0 - (bindSymbol("x") + (scale(add(number(1.0), number(1.0)), 2.0) + 1.0))) * 3 - 1.0
+ number(1), + number(1),
number(1) / 2 + number(2.0) * one number(1) / 2 + number(2.0) * one
) + zero ) + zero
@ -103,7 +104,7 @@ internal class TestAsmConsistencyWithInterpreter {
val res2 = ComplexField.mstInField { val res2 = ComplexField.mstInField {
+(3 - 2 + 2 * number(1) + 1.0) + binaryOperationFunction("+")( +(3 - 2 + 2 * number(1) + 1.0) + binaryOperationFunction("+")(
(3.0 - (symbol("x") + (multiply(add(number(1.0), number(1.0)), 2) + 1.0))) * 3 - 1.0 (3.0 - (bindSymbol("x") + (scale(add(number(1.0), number(1.0)), 2.0) + 1.0))) * 3 - 1.0
+ number(1), + number(1),
number(1) / 2 + number(2.0) * one number(1) / 2 + number(2.0) * one
) + zero ) + zero

View File

@ -0,0 +1,43 @@
package space.kscience.kmath.asm
import space.kscience.kmath.ast.mstInExtendedField
import space.kscience.kmath.ast.mstInField
import space.kscience.kmath.ast.mstInGroup
import space.kscience.kmath.expressions.invoke
import space.kscience.kmath.operations.DoubleField
import kotlin.random.Random
import kotlin.test.Test
import kotlin.test.assertEquals
internal class TestAsmOperationsSupport {
@Test
fun testUnaryOperationInvocation() {
val expression = DoubleField.mstInGroup { -bindSymbol("x") }.compile()
val res = expression("x" to 2.0)
assertEquals(-2.0, res)
}
@Test
fun testBinaryOperationInvocation() {
val expression = DoubleField.mstInGroup { -bindSymbol("x") + number(1.0) }.compile()
val res = expression("x" to 2.0)
assertEquals(-1.0, res)
}
@Test
fun testConstProductInvocation() {
val res = DoubleField.mstInField { bindSymbol("x") * 2 }("x" to 2.0)
assertEquals(4.0, res)
}
@Test
fun testMultipleCalls() {
val e =
DoubleField.mstInExtendedField { sin(bindSymbol("x")).pow(4) - 6 * bindSymbol("x") / tanh(bindSymbol("x")) }
.compile()
val r = Random(0)
var s = 0.0
repeat(1000000) { s += e("x" to r.nextDouble()) }
println(s)
}
}

View File

@ -0,0 +1,54 @@
package space.kscience.kmath.asm
import space.kscience.kmath.ast.mstInField
import space.kscience.kmath.expressions.invoke
import space.kscience.kmath.operations.DoubleField
import kotlin.test.Test
import kotlin.test.assertEquals
internal class TestAsmSpecialization {
@Test
fun testUnaryPlus() {
val expr = DoubleField.mstInField { unaryOperationFunction("+")(bindSymbol("x")) }.compile()
assertEquals(2.0, expr("x" to 2.0))
}
@Test
fun testUnaryMinus() {
val expr = DoubleField.mstInField { unaryOperationFunction("-")(bindSymbol("x")) }.compile()
assertEquals(-2.0, expr("x" to 2.0))
}
@Test
fun testAdd() {
val expr = DoubleField.mstInField { binaryOperationFunction("+")(bindSymbol("x"), bindSymbol("x")) }.compile()
assertEquals(4.0, expr("x" to 2.0))
}
@Test
fun testSine() {
val expr = DoubleField.mstInField { unaryOperationFunction("sin")(bindSymbol("x")) }.compile()
assertEquals(0.0, expr("x" to 0.0))
}
@Test
fun testMinus() {
val expr = DoubleField.mstInField { binaryOperationFunction("-")(bindSymbol("x"), bindSymbol("x")) }.compile()
assertEquals(0.0, expr("x" to 2.0))
}
@Test
fun testDivide() {
val expr = DoubleField.mstInField { binaryOperationFunction("/")(bindSymbol("x"), bindSymbol("x")) }.compile()
assertEquals(1.0, expr("x" to 2.0))
}
@Test
fun testPower() {
val expr = DoubleField
.mstInField { binaryOperationFunction("pow")(bindSymbol("x"), number(2)) }
.compile()
assertEquals(4.0, expr("x" to 2.0))
}
}

View File

@ -1,8 +1,8 @@
package kscience.kmath.asm package space.kscience.kmath.asm
import kscience.kmath.ast.mstInRing import space.kscience.kmath.ast.mstInRing
import kscience.kmath.expressions.invoke import space.kscience.kmath.expressions.invoke
import kscience.kmath.operations.ByteRing import space.kscience.kmath.operations.ByteRing
import kotlin.test.Test import kotlin.test.Test
import kotlin.test.assertEquals import kotlin.test.assertEquals
import kotlin.test.assertFailsWith import kotlin.test.assertFailsWith
@ -10,13 +10,13 @@ import kotlin.test.assertFailsWith
internal class TestAsmVariables { internal class TestAsmVariables {
@Test @Test
fun testVariable() { fun testVariable() {
val expr = ByteRing.mstInRing { symbol("x") }.compile() val expr = ByteRing.mstInRing { bindSymbol("x") }.compile()
assertEquals(1.toByte(), expr("x" to 1.toByte())) assertEquals(1.toByte(), expr("x" to 1.toByte()))
} }
@Test @Test
fun testUndefinedVariableFails() { fun testUndefinedVariableFails() {
val expr = ByteRing.mstInRing { symbol("x") }.compile() val expr = ByteRing.mstInRing { bindSymbol("x") }.compile()
assertFailsWith<NoSuchElementException> { expr() } assertFailsWith<NoSuchElementException> { expr() }
} }
} }

View File

@ -1,12 +1,12 @@
package kscience.kmath.ast package space.kscience.kmath.ast
import kscience.kmath.operations.Field import space.kscience.kmath.operations.DoubleField
import kscience.kmath.operations.RealField import space.kscience.kmath.operations.Field
import kotlin.test.Test import kotlin.test.Test
import kotlin.test.assertEquals import kotlin.test.assertEquals
internal class ParserPrecedenceTest { internal class ParserPrecedenceTest {
private val f: Field<Double> = RealField private val f: Field<Double> = DoubleField
@Test @Test
fun test1(): Unit = assertEquals(6.0, f.evaluate("2*2+2".parseMath())) fun test1(): Unit = assertEquals(6.0, f.evaluate("2*2+2".parseMath()))

View File

@ -1,10 +1,10 @@
package kscience.kmath.ast package space.kscience.kmath.ast
import kscience.kmath.complex.Complex import space.kscience.kmath.complex.Complex
import kscience.kmath.complex.ComplexField import space.kscience.kmath.complex.ComplexField
import kscience.kmath.expressions.invoke import space.kscience.kmath.expressions.invoke
import kscience.kmath.operations.Algebra import space.kscience.kmath.operations.Algebra
import kscience.kmath.operations.RealField import space.kscience.kmath.operations.DoubleField
import kotlin.test.Test import kotlin.test.Test
import kotlin.test.assertEquals import kotlin.test.assertEquals
@ -33,14 +33,14 @@ internal class ParserTest {
@Test @Test
fun `evaluate MST with unary function`() { fun `evaluate MST with unary function`() {
val mst = "sin(0)".parseMath() val mst = "sin(0)".parseMath()
val res = RealField.evaluate(mst) val res = DoubleField.evaluate(mst)
assertEquals(0.0, res) assertEquals(0.0, res)
} }
@Test @Test
fun `evaluate MST with binary function`() { fun `evaluate MST with binary function`() {
val magicalAlgebra = object : Algebra<String> { val magicalAlgebra = object : Algebra<String> {
override fun symbol(value: String): String = value override fun bindSymbol(value: String): String = value
override fun unaryOperationFunction(operation: String): (arg: String) -> String { override fun unaryOperationFunction(operation: String): (arg: String) -> String {
throw NotImplementedError() throw NotImplementedError()

View File

@ -1,5 +1,5 @@
plugins { plugins {
id("ru.mipt.npm.jvm") id("ru.mipt.npm.gradle.jvm")
} }
description = "Commons math binding for kmath" description = "Commons math binding for kmath"
@ -12,6 +12,6 @@ dependencies {
api("org.apache.commons:commons-math3:3.6.1") api("org.apache.commons:commons-math3:3.6.1")
} }
readme{ readme {
maturity = ru.mipt.npm.gradle.Maturity.EXPERIMENTAL maturity = ru.mipt.npm.gradle.Maturity.EXPERIMENTAL
} }

View File

@ -1,118 +0,0 @@
package kscience.kmath.commons.linear
import kscience.kmath.linear.*
import kscience.kmath.misc.UnstableKMathAPI
import kscience.kmath.structures.RealBuffer
import org.apache.commons.math3.linear.*
import kotlin.reflect.KClass
import kotlin.reflect.cast
public inline class CMMatrix(public val origin: RealMatrix) : Matrix<Double> {
public override val rowNum: Int get() = origin.rowDimension
public override val colNum: Int get() = origin.columnDimension
@UnstableKMathAPI
override fun <T : Any> getFeature(type: KClass<T>): T? = when (type) {
DiagonalFeature::class -> if (origin is DiagonalMatrix) DiagonalFeature else null
DeterminantFeature::class, LupDecompositionFeature::class -> object :
DeterminantFeature<Double>,
LupDecompositionFeature<Double> {
private val lup by lazy { LUDecomposition(origin) }
override val determinant: Double by lazy { lup.determinant }
override val l: Matrix<Double> by lazy { CMMatrix(lup.l) + LFeature }
override val u: Matrix<Double> by lazy { CMMatrix(lup.u) + UFeature }
override val p: Matrix<Double> by lazy { CMMatrix(lup.p) }
}
CholeskyDecompositionFeature::class -> object : CholeskyDecompositionFeature<Double> {
override val l: Matrix<Double> by lazy {
val cholesky = CholeskyDecomposition(origin)
CMMatrix(cholesky.l) + LFeature
}
}
QRDecompositionFeature::class -> object : QRDecompositionFeature<Double> {
private val qr by lazy { QRDecomposition(origin) }
override val q: Matrix<Double> by lazy { CMMatrix(qr.q) + OrthogonalFeature }
override val r: Matrix<Double> by lazy { CMMatrix(qr.r) + UFeature }
}
SingularValueDecompositionFeature::class -> object : SingularValueDecompositionFeature<Double> {
private val sv by lazy { SingularValueDecomposition(origin) }
override val u: Matrix<Double> by lazy { CMMatrix(sv.u) }
override val s: Matrix<Double> by lazy { CMMatrix(sv.s) }
override val v: Matrix<Double> by lazy { CMMatrix(sv.v) }
override val singularValues: Point<Double> by lazy { RealBuffer(sv.singularValues) }
}
else -> null
}?.let(type::cast)
public override operator fun get(i: Int, j: Int): Double = origin.getEntry(i, j)
}
public fun RealMatrix.asMatrix(): CMMatrix = CMMatrix(this)
public class CMVector(public val origin: RealVector) : Point<Double> {
public override val size: Int get() = origin.dimension
public override operator fun get(index: Int): Double = origin.getEntry(index)
public override operator fun iterator(): Iterator<Double> = origin.toArray().iterator()
}
public fun Point<Double>.toCM(): CMVector = if (this is CMVector) this else {
val array = DoubleArray(size) { this[it] }
CMVector(ArrayRealVector(array))
}
public fun RealVector.toPoint(): CMVector = CMVector(this)
public object CMMatrixContext : MatrixContext<Double, CMMatrix> {
public override fun produce(rows: Int, columns: Int, initializer: (i: Int, j: Int) -> Double): CMMatrix {
val array = Array(rows) { i -> DoubleArray(columns) { j -> initializer(i, j) } }
return CMMatrix(Array2DRowRealMatrix(array))
}
@OptIn(UnstableKMathAPI::class)
public fun Matrix<Double>.toCM(): CMMatrix = when (val matrix = origin) {
is CMMatrix -> matrix
else -> {
//TODO add feature analysis
val array = Array(rowNum) { i -> DoubleArray(colNum) { j -> get(i, j) } }
CMMatrix(Array2DRowRealMatrix(array))
}
}
public override fun Matrix<Double>.dot(other: Matrix<Double>): CMMatrix =
CMMatrix(toCM().origin.multiply(other.toCM().origin))
public override fun Matrix<Double>.dot(vector: Point<Double>): CMVector =
CMVector(toCM().origin.preMultiply(vector.toCM().origin))
public override operator fun Matrix<Double>.unaryMinus(): CMMatrix =
produce(rowNum, colNum) { i, j -> -get(i, j) }
public override fun add(a: Matrix<Double>, b: Matrix<Double>): CMMatrix =
CMMatrix(a.toCM().origin.multiply(b.toCM().origin))
public override operator fun Matrix<Double>.minus(b: Matrix<Double>): CMMatrix =
CMMatrix(toCM().origin.subtract(b.toCM().origin))
public override fun multiply(a: Matrix<Double>, k: Number): CMMatrix =
CMMatrix(a.toCM().origin.scalarMultiply(k.toDouble()))
public override operator fun Matrix<Double>.times(value: Double): CMMatrix =
produce(rowNum, colNum) { i, j -> get(i, j) * value }
}
public operator fun CMMatrix.plus(other: CMMatrix): CMMatrix =
CMMatrix(origin.add(other.origin))
public operator fun CMMatrix.minus(other: CMMatrix): CMMatrix =
CMMatrix(origin.subtract(other.origin))
public infix fun CMMatrix.dot(other: CMMatrix): CMMatrix =
CMMatrix(origin.multiply(other.origin))

View File

@ -1,10 +1,12 @@
package kscience.kmath.commons.expressions package space.kscience.kmath.commons.expressions
import kscience.kmath.expressions.*
import kscience.kmath.misc.UnstableKMathAPI
import kscience.kmath.operations.ExtendedField
import kscience.kmath.operations.RingWithNumbers
import org.apache.commons.math3.analysis.differentiation.DerivativeStructure import org.apache.commons.math3.analysis.differentiation.DerivativeStructure
import space.kscience.kmath.expressions.*
import space.kscience.kmath.misc.StringSymbol
import space.kscience.kmath.misc.Symbol
import space.kscience.kmath.misc.UnstableKMathAPI
import space.kscience.kmath.operations.ExtendedField
import space.kscience.kmath.operations.NumbersAddOperations
/** /**
* A field over commons-math [DerivativeStructure]. * A field over commons-math [DerivativeStructure].
@ -16,7 +18,8 @@ import org.apache.commons.math3.analysis.differentiation.DerivativeStructure
public class DerivativeStructureField( public class DerivativeStructureField(
public val order: Int, public val order: Int,
bindings: Map<Symbol, Double>, bindings: Map<Symbol, Double>,
) : ExtendedField<DerivativeStructure>, ExpressionAlgebra<Double, DerivativeStructure>, RingWithNumbers<DerivativeStructure> { ) : ExtendedField<DerivativeStructure>, ExpressionAlgebra<Double, DerivativeStructure>,
NumbersAddOperations<DerivativeStructure> {
public val numberOfVariables: Int = bindings.size public val numberOfVariables: Int = bindings.size
public override val zero: DerivativeStructure by lazy { DerivativeStructure(numberOfVariables, order) } public override val zero: DerivativeStructure by lazy { DerivativeStructure(numberOfVariables, order) }
@ -48,11 +51,11 @@ public class DerivativeStructureField(
override fun const(value: Double): DerivativeStructure = DerivativeStructure(numberOfVariables, order, value) override fun const(value: Double): DerivativeStructure = DerivativeStructure(numberOfVariables, order, value)
public override fun bindOrNull(symbol: Symbol): DerivativeStructureSymbol? = variables[symbol.identity] public override fun bindSymbolOrNull(symbol: Symbol): DerivativeStructureSymbol? = variables[symbol.identity]
public fun bind(symbol: Symbol): DerivativeStructureSymbol = variables.getValue(symbol.identity) public fun bind(symbol: Symbol): DerivativeStructureSymbol = variables.getValue(symbol.identity)
override fun symbol(value: String): DerivativeStructureSymbol = bind(StringSymbol(value)) override fun bindSymbol(value: String): DerivativeStructureSymbol = bind(StringSymbol(value))
public fun DerivativeStructure.derivative(symbols: List<Symbol>): Double { public fun DerivativeStructure.derivative(symbols: List<Symbol>): Double {
require(symbols.size <= order) { "The order of derivative ${symbols.size} exceeds computed order $order" } require(symbols.size <= order) { "The order of derivative ${symbols.size} exceeds computed order $order" }
@ -62,13 +65,11 @@ public class DerivativeStructureField(
public fun DerivativeStructure.derivative(vararg symbols: Symbol): Double = derivative(symbols.toList()) public fun DerivativeStructure.derivative(vararg symbols: Symbol): Double = derivative(symbols.toList())
override fun DerivativeStructure.unaryMinus(): DerivativeStructure = negate()
public override fun add(a: DerivativeStructure, b: DerivativeStructure): DerivativeStructure = a.add(b) public override fun add(a: DerivativeStructure, b: DerivativeStructure): DerivativeStructure = a.add(b)
public override fun multiply(a: DerivativeStructure, k: Number): DerivativeStructure = when (k) { public override fun scale(a: DerivativeStructure, value: Double): DerivativeStructure = a.multiply(value)
is Double -> a.multiply(k)
is Int -> a.multiply(k)
else -> a.multiply(k.toDouble())
}
public override fun multiply(a: DerivativeStructure, b: DerivativeStructure): DerivativeStructure = a.multiply(b) public override fun multiply(a: DerivativeStructure, b: DerivativeStructure): DerivativeStructure = a.multiply(b)
public override fun divide(a: DerivativeStructure, b: DerivativeStructure): DerivativeStructure = a.divide(b) public override fun divide(a: DerivativeStructure, b: DerivativeStructure): DerivativeStructure = a.divide(b)

View File

@ -0,0 +1,92 @@
package space.kscience.kmath.commons.integration
import org.apache.commons.math3.analysis.integration.IterativeLegendreGaussIntegrator
import org.apache.commons.math3.analysis.integration.SimpsonIntegrator
import space.kscience.kmath.integration.*
import space.kscience.kmath.misc.UnstableKMathAPI
/**
* Integration wrapper for Common-maths UnivariateIntegrator
*/
public class CMIntegrator(
private val defaultMaxCalls: Int = 200,
public val integratorBuilder: (Integrand) -> org.apache.commons.math3.analysis.integration.UnivariateIntegrator,
) : UnivariateIntegrator<Double> {
public class TargetRelativeAccuracy(public val value: Double) : IntegrandFeature
public class TargetAbsoluteAccuracy(public val value: Double) : IntegrandFeature
public class MinIterations(public val value: Int) : IntegrandFeature
public class MaxIterations(public val value: Int) : IntegrandFeature
override fun integrate(integrand: UnivariateIntegrand<Double>): UnivariateIntegrand<Double> {
val integrator = integratorBuilder(integrand)
val maxCalls = integrand.getFeature<IntegrandMaxCalls>()?.maxCalls ?: defaultMaxCalls
val remainingCalls = maxCalls - integrand.calls
val range = integrand.getFeature<IntegrationRange<Double>>()?.range
?: error("Integration range is not provided")
val res = integrator.integrate(remainingCalls, integrand.function, range.start, range.endInclusive)
return integrand +
IntegrandValue(res) +
IntegrandAbsoluteAccuracy(integrator.absoluteAccuracy) +
IntegrandRelativeAccuracy(integrator.relativeAccuracy) +
IntegrandCalls(integrator.evaluations + integrand.calls)
}
public companion object {
/**
* Create a Simpson integrator based on [SimpsonIntegrator]
*/
public fun simpson(defaultMaxCalls: Int = 200): CMIntegrator = CMIntegrator(defaultMaxCalls) { integrand ->
val absoluteAccuracy = integrand.getFeature<TargetAbsoluteAccuracy>()?.value
?: SimpsonIntegrator.DEFAULT_ABSOLUTE_ACCURACY
val relativeAccuracy = integrand.getFeature<TargetRelativeAccuracy>()?.value
?: SimpsonIntegrator.DEFAULT_ABSOLUTE_ACCURACY
val minIterations = integrand.getFeature<MinIterations>()?.value
?: SimpsonIntegrator.DEFAULT_MIN_ITERATIONS_COUNT
val maxIterations = integrand.getFeature<MaxIterations>()?.value
?: SimpsonIntegrator.SIMPSON_MAX_ITERATIONS_COUNT
SimpsonIntegrator(relativeAccuracy, absoluteAccuracy, minIterations, maxIterations)
}
/**
* Create a Gauss-Legandre integrator based on [IterativeLegendreGaussIntegrator]
*/
public fun legandre(numPoints: Int, defaultMaxCalls: Int = numPoints * 5): CMIntegrator =
CMIntegrator(defaultMaxCalls) { integrand ->
val absoluteAccuracy = integrand.getFeature<TargetAbsoluteAccuracy>()?.value
?: IterativeLegendreGaussIntegrator.DEFAULT_ABSOLUTE_ACCURACY
val relativeAccuracy = integrand.getFeature<TargetRelativeAccuracy>()?.value
?: IterativeLegendreGaussIntegrator.DEFAULT_ABSOLUTE_ACCURACY
val minIterations = integrand.getFeature<MinIterations>()?.value
?: IterativeLegendreGaussIntegrator.DEFAULT_MIN_ITERATIONS_COUNT
val maxIterations = integrand.getFeature<MaxIterations>()?.value
?: IterativeLegendreGaussIntegrator.DEFAULT_MAX_ITERATIONS_COUNT
IterativeLegendreGaussIntegrator(
numPoints,
relativeAccuracy,
absoluteAccuracy,
minIterations,
maxIterations
)
}
}
}
@UnstableKMathAPI
public var MutableList<IntegrandFeature>.targetAbsoluteAccuracy: Double?
get() = filterIsInstance<CMIntegrator.TargetAbsoluteAccuracy>().lastOrNull()?.value
set(value) {
value?.let { add(CMIntegrator.TargetAbsoluteAccuracy(value)) }
}
@UnstableKMathAPI
public var MutableList<IntegrandFeature>.targetRelativeAccuracy: Double?
get() = filterIsInstance<CMIntegrator.TargetRelativeAccuracy>().lastOrNull()?.value
set(value) {
value?.let { add(CMIntegrator.TargetRelativeAccuracy(value)) }
}

View File

@ -0,0 +1,94 @@
/*
* Copyright 2015 Alexander Nozik.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package space.kscience.kmath.commons.integration
import org.apache.commons.math3.analysis.integration.gauss.GaussIntegrator
import org.apache.commons.math3.analysis.integration.gauss.GaussIntegratorFactory
import space.kscience.kmath.integration.*
/**
* A simple one-pass integrator based on Gauss rule
*/
public class GaussRuleIntegrator(
private val numpoints: Int,
private var type: GaussRule = GaussRule.LEGANDRE,
) : UnivariateIntegrator<Double> {
override fun integrate(integrand: UnivariateIntegrand<Double>): UnivariateIntegrand<Double> {
val range = integrand.getFeature<IntegrationRange<Double>>()?.range
?: error("Integration range is not provided")
val integrator: GaussIntegrator = getIntegrator(range)
//TODO check performance
val res: Double = integrator.integrate(integrand.function)
return integrand + IntegrandValue(res) + IntegrandCalls(integrand.calls + numpoints)
}
private fun getIntegrator(range: ClosedRange<Double>): GaussIntegrator {
return when (type) {
GaussRule.LEGANDRE -> factory.legendre(
numpoints,
range.start,
range.endInclusive
)
GaussRule.LEGANDREHP -> factory.legendreHighPrecision(
numpoints,
range.start,
range.endInclusive
)
GaussRule.UNIFORM -> GaussIntegrator(
getUniformRule(
range.start,
range.endInclusive,
numpoints
)
)
}
}
private fun getUniformRule(
min: Double,
max: Double,
numPoints: Int,
): org.apache.commons.math3.util.Pair<DoubleArray, DoubleArray> {
assert(numPoints > 2)
val points = DoubleArray(numPoints)
val weights = DoubleArray(numPoints)
val step = (max - min) / (numPoints - 1)
points[0] = min
for (i in 1 until numPoints) {
points[i] = points[i - 1] + step
weights[i] = step
}
return org.apache.commons.math3.util.Pair<DoubleArray, DoubleArray>(points, weights)
}
public enum class GaussRule {
UNIFORM, LEGANDRE, LEGANDREHP
}
public companion object {
private val factory: GaussIntegratorFactory = GaussIntegratorFactory()
public fun integrate(
range: ClosedRange<Double>,
numPoints: Int = 100,
type: GaussRule = GaussRule.LEGANDRE,
function: (Double) -> Double,
): Double = GaussRuleIntegrator(numPoints, type).integrate(
UnivariateIntegrand(function, IntegrationRange(range))
).value!!
}
}

View File

@ -0,0 +1,141 @@
package space.kscience.kmath.commons.linear
import org.apache.commons.math3.linear.*
import space.kscience.kmath.linear.*
import space.kscience.kmath.misc.UnstableKMathAPI
import space.kscience.kmath.nd.StructureFeature
import space.kscience.kmath.operations.DoubleField
import space.kscience.kmath.structures.DoubleBuffer
import kotlin.reflect.KClass
import kotlin.reflect.cast
public inline class CMMatrix(public val origin: RealMatrix) : Matrix<Double> {
public override val rowNum: Int get() = origin.rowDimension
public override val colNum: Int get() = origin.columnDimension
public override operator fun get(i: Int, j: Int): Double = origin.getEntry(i, j)
}
public inline class CMVector(public val origin: RealVector) : Point<Double> {
public override val size: Int get() = origin.dimension
public override operator fun get(index: Int): Double = origin.getEntry(index)
public override operator fun iterator(): Iterator<Double> = origin.toArray().iterator()
}
public fun RealVector.toPoint(): CMVector = CMVector(this)
public object CMLinearSpace : LinearSpace<Double, DoubleField> {
override val elementAlgebra: DoubleField get() = DoubleField
public override fun buildMatrix(
rows: Int,
columns: Int,
initializer: DoubleField.(i: Int, j: Int) -> Double,
): CMMatrix {
val array = Array(rows) { i -> DoubleArray(columns) { j -> DoubleField.initializer(i, j) } }
return CMMatrix(Array2DRowRealMatrix(array))
}
@OptIn(UnstableKMathAPI::class)
public fun Matrix<Double>.toCM(): CMMatrix = when (val matrix = origin) {
is CMMatrix -> matrix
else -> {
//TODO add feature analysis
val array = Array(rowNum) { i -> DoubleArray(colNum) { j -> get(i, j) } }
Array2DRowRealMatrix(array).wrap()
}
}
public fun Point<Double>.toCM(): CMVector = if (this is CMVector) this else {
val array = DoubleArray(size) { this[it] }
ArrayRealVector(array).wrap()
}
internal fun RealMatrix.wrap(): CMMatrix = CMMatrix(this)
internal fun RealVector.wrap(): CMVector = CMVector(this)
override fun buildVector(size: Int, initializer: DoubleField.(Int) -> Double): Point<Double> =
ArrayRealVector(DoubleArray(size) { DoubleField.initializer(it) }).wrap()
override fun Matrix<Double>.plus(other: Matrix<Double>): CMMatrix =
toCM().origin.add(other.toCM().origin).wrap()
override fun Point<Double>.plus(other: Point<Double>): CMVector =
toCM().origin.add(other.toCM().origin).wrap()
override fun Point<Double>.minus(other: Point<Double>): CMVector =
toCM().origin.subtract(other.toCM().origin).wrap()
public override fun Matrix<Double>.dot(other: Matrix<Double>): CMMatrix =
toCM().origin.multiply(other.toCM().origin).wrap()
public override fun Matrix<Double>.dot(vector: Point<Double>): CMVector =
toCM().origin.preMultiply(vector.toCM().origin).wrap()
public override operator fun Matrix<Double>.minus(other: Matrix<Double>): CMMatrix =
toCM().origin.subtract(other.toCM().origin).wrap()
public override operator fun Matrix<Double>.times(value: Double): CMMatrix =
toCM().origin.scalarMultiply(value).wrap()
override fun Double.times(m: Matrix<Double>): CMMatrix =
m * this
override fun Point<Double>.times(value: Double): CMVector =
toCM().origin.mapMultiply(value).wrap()
override fun Double.times(v: Point<Double>): CMVector =
v * this
@UnstableKMathAPI
override fun <F : StructureFeature> getFeature(structure: Matrix<Double>, type: KClass<out F>): F? {
//Return the feature if it is intrinsic to the structure
structure.getFeature(type)?.let { return it }
val origin = structure.toCM().origin
return when (type) {
DiagonalFeature::class -> if (origin is DiagonalMatrix) DiagonalFeature else null
DeterminantFeature::class, LupDecompositionFeature::class -> object :
DeterminantFeature<Double>,
LupDecompositionFeature<Double> {
private val lup by lazy { LUDecomposition(origin) }
override val determinant: Double by lazy { lup.determinant }
override val l: Matrix<Double> by lazy { CMMatrix(lup.l) + LFeature }
override val u: Matrix<Double> by lazy { CMMatrix(lup.u) + UFeature }
override val p: Matrix<Double> by lazy { CMMatrix(lup.p) }
}
CholeskyDecompositionFeature::class -> object : CholeskyDecompositionFeature<Double> {
override val l: Matrix<Double> by lazy {
val cholesky = CholeskyDecomposition(origin)
CMMatrix(cholesky.l) + LFeature
}
}
QRDecompositionFeature::class -> object : QRDecompositionFeature<Double> {
private val qr by lazy { QRDecomposition(origin) }
override val q: Matrix<Double> by lazy { CMMatrix(qr.q) + OrthogonalFeature }
override val r: Matrix<Double> by lazy { CMMatrix(qr.r) + UFeature }
}
SingularValueDecompositionFeature::class -> object : SingularValueDecompositionFeature<Double> {
private val sv by lazy { SingularValueDecomposition(origin) }
override val u: Matrix<Double> by lazy { CMMatrix(sv.u) }
override val s: Matrix<Double> by lazy { CMMatrix(sv.s) }
override val v: Matrix<Double> by lazy { CMMatrix(sv.v) }
override val singularValues: Point<Double> by lazy { DoubleBuffer(sv.singularValues) }
}
else -> null
}?.let(type::cast)
}
}
public operator fun CMMatrix.plus(other: CMMatrix): CMMatrix = CMMatrix(origin.add(other.origin))
public operator fun CMMatrix.minus(other: CMMatrix): CMMatrix = CMMatrix(origin.subtract(other.origin))
public infix fun CMMatrix.dot(other: CMMatrix): CMMatrix = CMMatrix(origin.multiply(other.origin))

View File

@ -1,8 +1,8 @@
package kscience.kmath.commons.linear package space.kscience.kmath.commons.linear
import kscience.kmath.linear.Matrix
import kscience.kmath.linear.Point
import org.apache.commons.math3.linear.* import org.apache.commons.math3.linear.*
import space.kscience.kmath.linear.Matrix
import space.kscience.kmath.linear.Point
public enum class CMDecomposition { public enum class CMDecomposition {
LUP, LUP,
@ -12,9 +12,9 @@ public enum class CMDecomposition {
CHOLESKY CHOLESKY
} }
public fun CMMatrixContext.solver( public fun CMLinearSpace.solver(
a: Matrix<Double>, a: Matrix<Double>,
decomposition: CMDecomposition = CMDecomposition.LUP decomposition: CMDecomposition = CMDecomposition.LUP,
): DecompositionSolver = when (decomposition) { ): DecompositionSolver = when (decomposition) {
CMDecomposition.LUP -> LUDecomposition(a.toCM().origin).solver CMDecomposition.LUP -> LUDecomposition(a.toCM().origin).solver
CMDecomposition.RRQR -> RRQRDecomposition(a.toCM().origin).solver CMDecomposition.RRQR -> RRQRDecomposition(a.toCM().origin).solver
@ -23,19 +23,19 @@ public fun CMMatrixContext.solver(
CMDecomposition.CHOLESKY -> CholeskyDecomposition(a.toCM().origin).solver CMDecomposition.CHOLESKY -> CholeskyDecomposition(a.toCM().origin).solver
} }
public fun CMMatrixContext.solve( public fun CMLinearSpace.solve(
a: Matrix<Double>, a: Matrix<Double>,
b: Matrix<Double>, b: Matrix<Double>,
decomposition: CMDecomposition = CMDecomposition.LUP decomposition: CMDecomposition = CMDecomposition.LUP,
): CMMatrix = solver(a, decomposition).solve(b.toCM().origin).asMatrix() ): CMMatrix = solver(a, decomposition).solve(b.toCM().origin).wrap()
public fun CMMatrixContext.solve( public fun CMLinearSpace.solve(
a: Matrix<Double>, a: Matrix<Double>,
b: Point<Double>, b: Point<Double>,
decomposition: CMDecomposition = CMDecomposition.LUP decomposition: CMDecomposition = CMDecomposition.LUP,
): CMVector = solver(a, decomposition).solve(b.toCM().origin).toPoint() ): CMVector = solver(a, decomposition).solve(b.toCM().origin).toPoint()
public fun CMMatrixContext.inverse( public fun CMLinearSpace.inverse(
a: Matrix<Double>, a: Matrix<Double>,
decomposition: CMDecomposition = CMDecomposition.LUP decomposition: CMDecomposition = CMDecomposition.LUP,
): CMMatrix = solver(a, decomposition).inverse.asMatrix() ): CMMatrix = solver(a, decomposition).inverse.wrap()

View File

@ -1,10 +1,5 @@
package kscience.kmath.commons.optimization package space.kscience.kmath.commons.optimization
import kscience.kmath.expressions.*
import kscience.kmath.stat.OptimizationFeature
import kscience.kmath.stat.OptimizationProblem
import kscience.kmath.stat.OptimizationProblemFactory
import kscience.kmath.stat.OptimizationResult
import org.apache.commons.math3.optim.* import org.apache.commons.math3.optim.*
import org.apache.commons.math3.optim.nonlinear.scalar.GoalType import org.apache.commons.math3.optim.nonlinear.scalar.GoalType
import org.apache.commons.math3.optim.nonlinear.scalar.MultivariateOptimizer import org.apache.commons.math3.optim.nonlinear.scalar.MultivariateOptimizer
@ -14,17 +9,36 @@ import org.apache.commons.math3.optim.nonlinear.scalar.gradient.NonLinearConjuga
import org.apache.commons.math3.optim.nonlinear.scalar.noderiv.AbstractSimplex import org.apache.commons.math3.optim.nonlinear.scalar.noderiv.AbstractSimplex
import org.apache.commons.math3.optim.nonlinear.scalar.noderiv.NelderMeadSimplex import org.apache.commons.math3.optim.nonlinear.scalar.noderiv.NelderMeadSimplex
import org.apache.commons.math3.optim.nonlinear.scalar.noderiv.SimplexOptimizer import org.apache.commons.math3.optim.nonlinear.scalar.noderiv.SimplexOptimizer
import space.kscience.kmath.expressions.DifferentiableExpression
import space.kscience.kmath.expressions.Expression
import space.kscience.kmath.expressions.SymbolIndexer
import space.kscience.kmath.expressions.derivative
import space.kscience.kmath.misc.Symbol
import space.kscience.kmath.misc.UnstableKMathAPI
import space.kscience.kmath.optimization.*
import kotlin.reflect.KClass import kotlin.reflect.KClass
public operator fun PointValuePair.component1(): DoubleArray = point public operator fun PointValuePair.component1(): DoubleArray = point
public operator fun PointValuePair.component2(): Double = value public operator fun PointValuePair.component2(): Double = value
public class CMOptimizationProblem(override val symbols: List<Symbol>, ) : @OptIn(UnstableKMathAPI::class)
OptimizationProblem<Double>, SymbolIndexer, OptimizationFeature { public class CMOptimization(
override val symbols: List<Symbol>,
) : FunctionOptimization<Double>, NoDerivFunctionOptimization<Double>, SymbolIndexer, OptimizationFeature {
private val optimizationData: HashMap<KClass<out OptimizationData>, OptimizationData> = HashMap() private val optimizationData: HashMap<KClass<out OptimizationData>, OptimizationData> = HashMap()
private var optimizatorBuilder: (() -> MultivariateOptimizer)? = null private var optimizerBuilder: (() -> MultivariateOptimizer)? = null
public var convergenceChecker: ConvergenceChecker<PointValuePair> = SimpleValueChecker(DEFAULT_RELATIVE_TOLERANCE, public var convergenceChecker: ConvergenceChecker<PointValuePair> = SimpleValueChecker(
DEFAULT_ABSOLUTE_TOLERANCE, DEFAULT_MAX_ITER) DEFAULT_RELATIVE_TOLERANCE,
DEFAULT_ABSOLUTE_TOLERANCE,
DEFAULT_MAX_ITER
)
override var maximize: Boolean
get() = optimizationData[GoalType::class] == GoalType.MAXIMIZE
set(value) {
optimizationData[GoalType::class] = if (value) GoalType.MAXIMIZE else GoalType.MINIMIZE
}
public fun addOptimizationData(data: OptimizationData) { public fun addOptimizationData(data: OptimizationData) {
optimizationData[data::class] = data optimizationData[data::class] = data
@ -40,7 +54,7 @@ public class CMOptimizationProblem(override val symbols: List<Symbol>, ) :
addOptimizationData(InitialGuess(map.toDoubleArray())) addOptimizationData(InitialGuess(map.toDoubleArray()))
} }
public override fun expression(expression: Expression<Double>): Unit { public override fun function(expression: Expression<Double>): Unit {
val objectiveFunction = ObjectiveFunction { val objectiveFunction = ObjectiveFunction {
val args = it.toMap() val args = it.toMap()
expression(args) expression(args)
@ -48,8 +62,8 @@ public class CMOptimizationProblem(override val symbols: List<Symbol>, ) :
addOptimizationData(objectiveFunction) addOptimizationData(objectiveFunction)
} }
public override fun diffExpression(expression: DifferentiableExpression<Double, Expression<Double>>) { public override fun diffFunction(expression: DifferentiableExpression<Double, Expression<Double>>) {
expression(expression) function(expression)
val gradientFunction = ObjectiveFunctionGradient { val gradientFunction = ObjectiveFunctionGradient {
val args = it.toMap() val args = it.toMap()
DoubleArray(symbols.size) { index -> DoubleArray(symbols.size) { index ->
@ -57,8 +71,8 @@ public class CMOptimizationProblem(override val symbols: List<Symbol>, ) :
} }
} }
addOptimizationData(gradientFunction) addOptimizationData(gradientFunction)
if (optimizatorBuilder == null) { if (optimizerBuilder == null) {
optimizatorBuilder = { optimizerBuilder = {
NonLinearConjugateGradientOptimizer( NonLinearConjugateGradientOptimizer(
NonLinearConjugateGradientOptimizer.Formula.FLETCHER_REEVES, NonLinearConjugateGradientOptimizer.Formula.FLETCHER_REEVES,
convergenceChecker convergenceChecker
@ -70,8 +84,8 @@ public class CMOptimizationProblem(override val symbols: List<Symbol>, ) :
public fun simplex(simplex: AbstractSimplex) { public fun simplex(simplex: AbstractSimplex) {
addOptimizationData(simplex) addOptimizationData(simplex)
//Set optimization builder to simplex if it is not present //Set optimization builder to simplex if it is not present
if (optimizatorBuilder == null) { if (optimizerBuilder == null) {
optimizatorBuilder = { SimplexOptimizer(convergenceChecker) } optimizerBuilder = { SimplexOptimizer(convergenceChecker) }
} }
} }
@ -84,7 +98,7 @@ public class CMOptimizationProblem(override val symbols: List<Symbol>, ) :
} }
public fun optimizer(block: () -> MultivariateOptimizer) { public fun optimizer(block: () -> MultivariateOptimizer) {
optimizatorBuilder = block optimizerBuilder = block
} }
override fun update(result: OptimizationResult<Double>) { override fun update(result: OptimizationResult<Double>) {
@ -92,19 +106,19 @@ public class CMOptimizationProblem(override val symbols: List<Symbol>, ) :
} }
override fun optimize(): OptimizationResult<Double> { override fun optimize(): OptimizationResult<Double> {
val optimizer = optimizatorBuilder?.invoke() ?: error("Optimizer not defined") val optimizer = optimizerBuilder?.invoke() ?: error("Optimizer not defined")
val (point, value) = optimizer.optimize(*optimizationData.values.toTypedArray()) val (point, value) = optimizer.optimize(*optimizationData.values.toTypedArray())
return OptimizationResult(point.toMap(), value, setOf(this)) return OptimizationResult(point.toMap(), value, setOf(this))
} }
public companion object : OptimizationProblemFactory<Double, CMOptimizationProblem> { public companion object : OptimizationProblemFactory<Double, CMOptimization> {
public const val DEFAULT_RELATIVE_TOLERANCE: Double = 1e-4 public const val DEFAULT_RELATIVE_TOLERANCE: Double = 1e-4
public const val DEFAULT_ABSOLUTE_TOLERANCE: Double = 1e-4 public const val DEFAULT_ABSOLUTE_TOLERANCE: Double = 1e-4
public const val DEFAULT_MAX_ITER: Int = 1000 public const val DEFAULT_MAX_ITER: Int = 1000
override fun build(symbols: List<Symbol>): CMOptimizationProblem = CMOptimizationProblem(symbols) override fun build(symbols: List<Symbol>): CMOptimization = CMOptimization(symbols)
} }
} }
public fun CMOptimizationProblem.initialGuess(vararg pairs: Pair<Symbol, Double>): Unit = initialGuess(pairs.toMap()) public fun CMOptimization.initialGuess(vararg pairs: Pair<Symbol, Double>): Unit = initialGuess(pairs.toMap())
public fun CMOptimizationProblem.simplexSteps(vararg pairs: Pair<Symbol, Double>): Unit = simplexSteps(pairs.toMap()) public fun CMOptimization.simplexSteps(vararg pairs: Pair<Symbol, Double>): Unit = simplexSteps(pairs.toMap())

View File

@ -1,21 +1,21 @@
package kscience.kmath.commons.optimization package space.kscience.kmath.commons.optimization
import kscience.kmath.commons.expressions.DerivativeStructureField
import kscience.kmath.expressions.DifferentiableExpression
import kscience.kmath.expressions.Expression
import kscience.kmath.expressions.Symbol
import kscience.kmath.stat.Fitting
import kscience.kmath.stat.OptimizationResult
import kscience.kmath.stat.optimizeWith
import kscience.kmath.structures.Buffer
import kscience.kmath.structures.asBuffer
import org.apache.commons.math3.analysis.differentiation.DerivativeStructure import org.apache.commons.math3.analysis.differentiation.DerivativeStructure
import org.apache.commons.math3.optim.nonlinear.scalar.GoalType import space.kscience.kmath.commons.expressions.DerivativeStructureField
import space.kscience.kmath.expressions.DifferentiableExpression
import space.kscience.kmath.expressions.Expression
import space.kscience.kmath.misc.Symbol
import space.kscience.kmath.optimization.FunctionOptimization
import space.kscience.kmath.optimization.OptimizationResult
import space.kscience.kmath.optimization.noDerivOptimizeWith
import space.kscience.kmath.optimization.optimizeWith
import space.kscience.kmath.structures.Buffer
import space.kscience.kmath.structures.asBuffer
/** /**
* Generate a chi squared expression from given x-y-sigma data and inline model. Provides automatic differentiation * Generate a chi squared expression from given x-y-sigma data and inline model. Provides automatic differentiation
*/ */
public fun Fitting.chiSquared( public fun FunctionOptimization.Companion.chiSquared(
x: Buffer<Double>, x: Buffer<Double>,
y: Buffer<Double>, y: Buffer<Double>,
yErr: Buffer<Double>, yErr: Buffer<Double>,
@ -25,7 +25,7 @@ public fun Fitting.chiSquared(
/** /**
* Generate a chi squared expression from given x-y-sigma data and inline model. Provides automatic differentiation * Generate a chi squared expression from given x-y-sigma data and inline model. Provides automatic differentiation
*/ */
public fun Fitting.chiSquared( public fun FunctionOptimization.Companion.chiSquared(
x: Iterable<Double>, x: Iterable<Double>,
y: Iterable<Double>, y: Iterable<Double>,
yErr: Iterable<Double>, yErr: Iterable<Double>,
@ -43,25 +43,26 @@ public fun Fitting.chiSquared(
*/ */
public fun Expression<Double>.optimize( public fun Expression<Double>.optimize(
vararg symbols: Symbol, vararg symbols: Symbol,
configuration: CMOptimizationProblem.() -> Unit, configuration: CMOptimization.() -> Unit,
): OptimizationResult<Double> = optimizeWith(CMOptimizationProblem, symbols = symbols, configuration) ): OptimizationResult<Double> = noDerivOptimizeWith(CMOptimization, symbols = symbols, configuration)
/** /**
* Optimize differentiable expression * Optimize differentiable expression
*/ */
public fun DifferentiableExpression<Double, Expression<Double>>.optimize( public fun DifferentiableExpression<Double, Expression<Double>>.optimize(
vararg symbols: Symbol, vararg symbols: Symbol,
configuration: CMOptimizationProblem.() -> Unit, configuration: CMOptimization.() -> Unit,
): OptimizationResult<Double> = optimizeWith(CMOptimizationProblem, symbols = symbols, configuration) ): OptimizationResult<Double> = optimizeWith(CMOptimization, symbols = symbols, configuration)
public fun DifferentiableExpression<Double, Expression<Double>>.minimize( public fun DifferentiableExpression<Double, Expression<Double>>.minimize(
vararg startPoint: Pair<Symbol, Double>, vararg startPoint: Pair<Symbol, Double>,
configuration: CMOptimizationProblem.() -> Unit = {}, configuration: CMOptimization.() -> Unit = {},
): OptimizationResult<Double> { ): OptimizationResult<Double> {
require(startPoint.isNotEmpty()) { "Must provide a list of symbols for optimization" } val symbols = startPoint.map { it.first }.toTypedArray()
val problem = CMOptimizationProblem(startPoint.map { it.first }).apply(configuration) return optimize(*symbols){
problem.diffExpression(this) maximize = false
problem.initialGuess(startPoint.toMap()) initialGuess(startPoint.toMap())
problem.goal(GoalType.MINIMIZE) diffFunction(this@minimize)
return problem.optimize() configuration()
}
} }

View File

@ -1,6 +1,6 @@
package kscience.kmath.commons.random package space.kscience.kmath.commons.random
import kscience.kmath.stat.RandomGenerator import space.kscience.kmath.stat.RandomGenerator
public class CMRandomGeneratorWrapper( public class CMRandomGeneratorWrapper(
public val factory: (IntArray) -> RandomGenerator, public val factory: (IntArray) -> RandomGenerator,

View File

@ -1,13 +1,14 @@
package kscience.kmath.commons.transform package space.kscience.kmath.commons.transform
import kotlinx.coroutines.FlowPreview import kotlinx.coroutines.FlowPreview
import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.map import kotlinx.coroutines.flow.map
import kscience.kmath.complex.*
import kscience.kmath.streaming.chunked
import kscience.kmath.streaming.spread
import kscience.kmath.structures.*
import org.apache.commons.math3.transform.* import org.apache.commons.math3.transform.*
import space.kscience.kmath.complex.Complex
import space.kscience.kmath.streaming.chunked
import space.kscience.kmath.streaming.spread
import space.kscience.kmath.structures.*
/** /**
@ -17,7 +18,7 @@ public object Transformations {
private fun Buffer<Complex>.toArray(): Array<org.apache.commons.math3.complex.Complex> = private fun Buffer<Complex>.toArray(): Array<org.apache.commons.math3.complex.Complex> =
Array(size) { org.apache.commons.math3.complex.Complex(get(it).re, get(it).im) } Array(size) { org.apache.commons.math3.complex.Complex(get(it).re, get(it).im) }
private fun Buffer<Double>.asArray() = if (this is RealBuffer) { private fun Buffer<Double>.asArray() = if (this is DoubleBuffer) {
array array
} else { } else {
DoubleArray(size) { i -> get(i) } DoubleArray(size) { i -> get(i) }
@ -33,34 +34,34 @@ public object Transformations {
public fun fourier( public fun fourier(
normalization: DftNormalization = DftNormalization.STANDARD, normalization: DftNormalization = DftNormalization.STANDARD,
direction: TransformType = TransformType.FORWARD direction: TransformType = TransformType.FORWARD,
): SuspendBufferTransform<Complex, Complex> = { ): SuspendBufferTransform<Complex, Complex> = {
FastFourierTransformer(normalization).transform(it.toArray(), direction).asBuffer() FastFourierTransformer(normalization).transform(it.toArray(), direction).asBuffer()
} }
public fun realFourier( public fun realFourier(
normalization: DftNormalization = DftNormalization.STANDARD, normalization: DftNormalization = DftNormalization.STANDARD,
direction: TransformType = TransformType.FORWARD direction: TransformType = TransformType.FORWARD,
): SuspendBufferTransform<Double, Complex> = { ): SuspendBufferTransform<Double, Complex> = {
FastFourierTransformer(normalization).transform(it.asArray(), direction).asBuffer() FastFourierTransformer(normalization).transform(it.asArray(), direction).asBuffer()
} }
public fun sine( public fun sine(
normalization: DstNormalization = DstNormalization.STANDARD_DST_I, normalization: DstNormalization = DstNormalization.STANDARD_DST_I,
direction: TransformType = TransformType.FORWARD direction: TransformType = TransformType.FORWARD,
): SuspendBufferTransform<Double, Double> = { ): SuspendBufferTransform<Double, Double> = {
FastSineTransformer(normalization).transform(it.asArray(), direction).asBuffer() FastSineTransformer(normalization).transform(it.asArray(), direction).asBuffer()
} }
public fun cosine( public fun cosine(
normalization: DctNormalization = DctNormalization.STANDARD_DCT_I, normalization: DctNormalization = DctNormalization.STANDARD_DCT_I,
direction: TransformType = TransformType.FORWARD direction: TransformType = TransformType.FORWARD,
): SuspendBufferTransform<Double, Double> = { ): SuspendBufferTransform<Double, Double> = {
FastCosineTransformer(normalization).transform(it.asArray(), direction).asBuffer() FastCosineTransformer(normalization).transform(it.asArray(), direction).asBuffer()
} }
public fun hadamard( public fun hadamard(
direction: TransformType = TransformType.FORWARD direction: TransformType = TransformType.FORWARD,
): SuspendBufferTransform<Double, Double> = { ): SuspendBufferTransform<Double, Double> = {
FastHadamardTransformer().transform(it.asArray(), direction).asBuffer() FastHadamardTransformer().transform(it.asArray(), direction).asBuffer()
} }
@ -72,7 +73,7 @@ public object Transformations {
@FlowPreview @FlowPreview
public fun Flow<Buffer<Complex>>.FFT( public fun Flow<Buffer<Complex>>.FFT(
normalization: DftNormalization = DftNormalization.STANDARD, normalization: DftNormalization = DftNormalization.STANDARD,
direction: TransformType = TransformType.FORWARD direction: TransformType = TransformType.FORWARD,
): Flow<Buffer<Complex>> { ): Flow<Buffer<Complex>> {
val transform = Transformations.fourier(normalization, direction) val transform = Transformations.fourier(normalization, direction)
return map { transform(it) } return map { transform(it) }
@ -82,7 +83,7 @@ public fun Flow<Buffer<Complex>>.FFT(
@JvmName("realFFT") @JvmName("realFFT")
public fun Flow<Buffer<Double>>.FFT( public fun Flow<Buffer<Double>>.FFT(
normalization: DftNormalization = DftNormalization.STANDARD, normalization: DftNormalization = DftNormalization.STANDARD,
direction: TransformType = TransformType.FORWARD direction: TransformType = TransformType.FORWARD,
): Flow<Buffer<Complex>> { ): Flow<Buffer<Complex>> {
val transform = Transformations.realFourier(normalization, direction) val transform = Transformations.realFourier(normalization, direction)
return map(transform) return map(transform)
@ -96,7 +97,7 @@ public fun Flow<Buffer<Double>>.FFT(
public fun Flow<Double>.FFT( public fun Flow<Double>.FFT(
bufferSize: Int = Int.MAX_VALUE, bufferSize: Int = Int.MAX_VALUE,
normalization: DftNormalization = DftNormalization.STANDARD, normalization: DftNormalization = DftNormalization.STANDARD,
direction: TransformType = TransformType.FORWARD direction: TransformType = TransformType.FORWARD,
): Flow<Complex> = chunked(bufferSize).FFT(normalization, direction).spread() ): Flow<Complex> = chunked(bufferSize).FFT(normalization, direction).spread()
/** /**

View File

@ -1,6 +1,10 @@
package kscience.kmath.commons.expressions package space.kscience.kmath.commons.expressions
import kscience.kmath.expressions.* import space.kscience.kmath.expressions.binding
import space.kscience.kmath.expressions.derivative
import space.kscience.kmath.expressions.invoke
import space.kscience.kmath.misc.Symbol
import space.kscience.kmath.misc.symbol
import kotlin.contracts.InvocationKind import kotlin.contracts.InvocationKind
import kotlin.contracts.contract import kotlin.contracts.contract
import kotlin.test.Test import kotlin.test.Test
@ -24,13 +28,13 @@ internal class AutoDiffTest {
fun derivativeStructureFieldTest() { fun derivativeStructureFieldTest() {
diff(2, x to 1.0, y to 1.0) { diff(2, x to 1.0, y to 1.0) {
val x = bind(x)//by binding() val x = bind(x)//by binding()
val y = symbol("y") val y = bindSymbol("y")
val z = x * (-sin(x * y) + y) + 2.0 val z = x * (-sin(x * y) + y) + 2.0
println(z.derivative(x)) println(z.derivative(x))
println(z.derivative(y,x)) println(z.derivative(y, x))
assertEquals(z.derivative(x, y), z.derivative(y, x)) assertEquals(z.derivative(x, y), z.derivative(y, x))
//check that improper order cause failure //check that improper order cause failure
assertFails { z.derivative(x,x,y) } assertFails { z.derivative(x, x, y) }
} }
} }

View File

@ -0,0 +1,30 @@
package space.kscience.kmath.commons.integration
import org.junit.jupiter.api.Test
import space.kscience.kmath.integration.integrate
import space.kscience.kmath.misc.UnstableKMathAPI
import space.kscience.kmath.operations.DoubleField.sin
import kotlin.math.PI
import kotlin.math.abs
import kotlin.test.assertTrue
@UnstableKMathAPI
internal class IntegrationTest {
private val function: (Double) -> Double = { sin(it) }
@Test
fun simpson() {
val res = CMIntegrator.simpson().integrate(0.0..2 * PI, function)
assertTrue { abs(res) < 1e-3 }
}
@Test
fun customSimpson() {
val res = CMIntegrator.simpson().integrate(0.0..PI, function) {
targetRelativeAccuracy = 1e-4
targetAbsoluteAccuracy = 1e-4
}
assertTrue { abs(res - 2) < 1e-3 }
assertTrue { abs(res - 2) > 1e-12 }
}
}

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