Compare commits
18 Commits
dev
...
mrFendel/e
Author | SHA1 | Date | |
---|---|---|---|
|
051a3893ec | ||
|
c6e1eb8406 | ||
|
4ba1a1606a | ||
|
d20e532c4f | ||
|
91f5436be5 | ||
|
39244ebc52 | ||
|
31be2b547b | ||
|
d5c3aa563e | ||
|
11cbf7cdc7 | ||
|
1773b49b1f | ||
|
455c9d188d | ||
|
13da33ecde | ||
|
55bcd202bf | ||
|
b8809d1c21 | ||
|
134f265700 | ||
|
74a550effd | ||
|
e7b56e4972 | ||
|
b6b8ac7de5 |
1
.gitignore
vendored
@ -5,7 +5,6 @@ out/
|
|||||||
.idea/
|
.idea/
|
||||||
.vscode/
|
.vscode/
|
||||||
.fleet/
|
.fleet/
|
||||||
.kotlin/
|
|
||||||
|
|
||||||
|
|
||||||
# Avoid ignoring Gradle wrapper jar file (.jar files are usually ignored)
|
# Avoid ignoring Gradle wrapper jar file (.jar files are usually ignored)
|
||||||
|
@ -34,7 +34,7 @@ job("Publish") {
|
|||||||
api.space().projects.automation.deployments.start(
|
api.space().projects.automation.deployments.start(
|
||||||
project = api.projectIdentifier(),
|
project = api.projectIdentifier(),
|
||||||
targetIdentifier = TargetIdentifier.Key(projectName),
|
targetIdentifier = TargetIdentifier.Key(projectName),
|
||||||
version = version + revisionSuffix,
|
version = version+revisionSuffix,
|
||||||
// automatically update deployment status based on the status of a job
|
// automatically update deployment status based on the status of a job
|
||||||
syncWithAutomationJob = true
|
syncWithAutomationJob = true
|
||||||
)
|
)
|
||||||
|
72
CHANGELOG.md
@ -3,7 +3,6 @@
|
|||||||
## Unreleased
|
## Unreleased
|
||||||
|
|
||||||
### Added
|
### Added
|
||||||
- Metropolis-Hastings sampler
|
|
||||||
|
|
||||||
### Changed
|
### Changed
|
||||||
|
|
||||||
@ -15,51 +14,9 @@
|
|||||||
|
|
||||||
### Security
|
### Security
|
||||||
|
|
||||||
## 0.4.0-dev-3 - 2024-02-18
|
|
||||||
|
|
||||||
### Added
|
|
||||||
|
|
||||||
- Reification. Explicit `SafeType` for algebras.
|
|
||||||
- Integer division algebras.
|
|
||||||
- Float32 geometries.
|
|
||||||
- New Attributes-kt module that could be used as stand-alone. It declares. type-safe attributes containers.
|
|
||||||
- Explicit `mutableStructureND` builders for mutable structures.
|
|
||||||
- `Buffer.asList()` zero-copy transformation.
|
|
||||||
- Wasm support.
|
|
||||||
- Parallel implementation of `LinearSpace` for Float64
|
|
||||||
- Parallel buffer factories
|
|
||||||
|
|
||||||
### Changed
|
|
||||||
|
|
||||||
- Buffer copy removed from API (added as an extension).
|
|
||||||
- Default naming for algebra and buffers now uses IntXX/FloatXX notation instead of Java types.
|
|
||||||
- Remove unnecessary inlines in basic algebras.
|
|
||||||
- QuaternionField -> QuaternionAlgebra and does not implement `Field` anymore since it is non-commutative
|
|
||||||
- kmath-geometry is split into `euclidean2d` and `euclidean3d`
|
|
||||||
- Features replaced with Attributes.
|
|
||||||
- Transposed refactored.
|
|
||||||
- Kmath-memory is moved on top of core.
|
|
||||||
|
|
||||||
### Deprecated
|
|
||||||
|
|
||||||
- ND4J engine
|
|
||||||
|
|
||||||
### Removed
|
|
||||||
|
|
||||||
- `asPolynomial` function due to scope pollution
|
|
||||||
- Codegend for ejml (450 lines of codegen for 1000 lines of code is too much)
|
|
||||||
|
|
||||||
### Fixed
|
|
||||||
|
|
||||||
- Median statistics
|
|
||||||
- Complex power of negative real numbers
|
|
||||||
- Add proper mutability for MutableBufferND rows and columns
|
|
||||||
- Generic Float32 and Float64 vectors are used in geometry algebras.
|
|
||||||
|
|
||||||
## 0.3.1 - 2023-04-09
|
## 0.3.1 - 2023-04-09
|
||||||
|
|
||||||
### Added
|
### Added
|
||||||
|
|
||||||
- Wasm support for `memory`, `core`, `complex` and `functions` modules.
|
- Wasm support for `memory`, `core`, `complex` and `functions` modules.
|
||||||
- Generic builders for `BufferND` and `MutableBufferND`
|
- Generic builders for `BufferND` and `MutableBufferND`
|
||||||
- `NamedMatrix` - matrix with symbol-based indexing
|
- `NamedMatrix` - matrix with symbol-based indexing
|
||||||
@ -69,8 +26,6 @@
|
|||||||
- Algebra now has an obligatory `bufferFactory` (#477).
|
- Algebra now has an obligatory `bufferFactory` (#477).
|
||||||
|
|
||||||
### Changed
|
### Changed
|
||||||
|
|
||||||
- Removed marker `Vector` type for geometry
|
|
||||||
- Geometry uses type-safe angles
|
- Geometry uses type-safe angles
|
||||||
- Tensor operations switched to prefix notation
|
- Tensor operations switched to prefix notation
|
||||||
- Row-wise and column-wise ND shapes in the core
|
- Row-wise and column-wise ND shapes in the core
|
||||||
@ -78,19 +33,16 @@
|
|||||||
- Major refactor of tensors (only minor API changes)
|
- Major refactor of tensors (only minor API changes)
|
||||||
- Kotlin 1.8.20
|
- Kotlin 1.8.20
|
||||||
- `LazyStructure` `deffered` -> `async` to comply with coroutines code style
|
- `LazyStructure` `deffered` -> `async` to comply with coroutines code style
|
||||||
- Default `dot` operation in tensor algebra no longer support broadcasting. Instead `matmul` operation is added
|
- Default `dot` operation in tensor algebra no longer support broadcasting. Instead `matmul` operation is added to `DoubleTensorAlgebra`.
|
||||||
to `DoubleTensorAlgebra`.
|
|
||||||
- Multik went MPP
|
- Multik went MPP
|
||||||
|
|
||||||
### Removed
|
### Removed
|
||||||
|
|
||||||
- Trajectory moved to https://github.com/SciProgCentre/maps-kt
|
- Trajectory moved to https://github.com/SciProgCentre/maps-kt
|
||||||
- Polynomials moved to https://github.com/SciProgCentre/kmath-polynomial
|
- Polynomials moved to https://github.com/SciProgCentre/kmath-polynomial
|
||||||
|
|
||||||
## 0.3.0
|
## 0.3.0
|
||||||
|
|
||||||
### Added
|
### Added
|
||||||
|
|
||||||
- `ScaleOperations` interface
|
- `ScaleOperations` interface
|
||||||
- `Field` extends `ScaleOperations`
|
- `Field` extends `ScaleOperations`
|
||||||
- Basic integration API
|
- Basic integration API
|
||||||
@ -115,7 +67,6 @@
|
|||||||
- Compilation to TeX for MST: #254
|
- Compilation to TeX for MST: #254
|
||||||
|
|
||||||
### Changed
|
### Changed
|
||||||
|
|
||||||
- Annotations moved to `space.kscience.kmath`
|
- Annotations moved to `space.kscience.kmath`
|
||||||
- Exponential operations merged with hyperbolic functions
|
- Exponential operations merged with hyperbolic functions
|
||||||
- Space is replaced by Group. Space is reserved for vector spaces.
|
- Space is replaced by Group. Space is reserved for vector spaces.
|
||||||
@ -149,11 +100,9 @@
|
|||||||
- `UnivariateFunction` -> `Function1D`, `MultivariateFunction` -> `FunctionND`
|
- `UnivariateFunction` -> `Function1D`, `MultivariateFunction` -> `FunctionND`
|
||||||
|
|
||||||
### Deprecated
|
### Deprecated
|
||||||
|
|
||||||
- Specialized `DoubleBufferAlgebra`
|
- Specialized `DoubleBufferAlgebra`
|
||||||
|
|
||||||
### Removed
|
### Removed
|
||||||
|
|
||||||
- Nearest in Domain. To be implemented in geometry package.
|
- Nearest in Domain. To be implemented in geometry package.
|
||||||
- Number multiplication and division in main Algebra chain
|
- Number multiplication and division in main Algebra chain
|
||||||
- `contentEquals` from Buffer. It moved to the companion.
|
- `contentEquals` from Buffer. It moved to the companion.
|
||||||
@ -164,14 +113,12 @@
|
|||||||
- Algebra elements are completely removed. Use algebra contexts instead.
|
- Algebra elements are completely removed. Use algebra contexts instead.
|
||||||
|
|
||||||
### Fixed
|
### Fixed
|
||||||
|
|
||||||
- Ring inherits RingOperations, not GroupOperations
|
- Ring inherits RingOperations, not GroupOperations
|
||||||
- Univariate histogram filling
|
- Univariate histogram filling
|
||||||
|
|
||||||
## 0.2.0
|
## 0.2.0
|
||||||
|
|
||||||
### Added
|
### 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)
|
||||||
@ -191,7 +138,6 @@
|
|||||||
- Basic Quaternion vector support in `kmath-complex`.
|
- Basic Quaternion vector support in `kmath-complex`.
|
||||||
|
|
||||||
### Changed
|
### Changed
|
||||||
|
|
||||||
- Package changed from `scientifik` to `space.kscience`
|
- Package changed from `scientifik` to `space.kscience`
|
||||||
- Gradle version: 6.6 -> 6.8.2
|
- 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`)
|
||||||
@ -201,7 +147,7 @@
|
|||||||
- Full autodiff refactoring based on `Symbol`
|
- Full autodiff refactoring based on `Symbol`
|
||||||
- `kmath-prob` renamed to `kmath-stat`
|
- `kmath-prob` renamed to `kmath-stat`
|
||||||
- Grid generators moved to `kmath-for-real`
|
- Grid generators moved to `kmath-for-real`
|
||||||
- Use `Point<Float64>` instead of specialized type in `kmath-for-real`
|
- Use `Point<Double>` instead of specialized type in `kmath-for-real`
|
||||||
- Optimized dot product for buffer matrices moved to `kmath-for-real`
|
- Optimized dot product for buffer matrices moved to `kmath-for-real`
|
||||||
- EjmlMatrix context is an object
|
- EjmlMatrix context is an object
|
||||||
- Matrix LUP `inverse` renamed to `inverseWithLup`
|
- Matrix LUP `inverse` renamed to `inverseWithLup`
|
||||||
@ -216,7 +162,6 @@
|
|||||||
- Add `out` projection to `Buffer` generic
|
- Add `out` projection to `Buffer` generic
|
||||||
|
|
||||||
### Removed
|
### Removed
|
||||||
|
|
||||||
- `kmath-koma` module because it doesn't support Kotlin 1.4.
|
- `kmath-koma` module because it doesn't support Kotlin 1.4.
|
||||||
- Support of `legacy` JS backend (we will support only IR)
|
- Support of `legacy` JS backend (we will support only IR)
|
||||||
- `toGrid` method.
|
- `toGrid` method.
|
||||||
@ -225,24 +170,20 @@
|
|||||||
- StructureND identity and equals
|
- 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)
|
||||||
|
|
||||||
## 0.1.4
|
## 0.1.4
|
||||||
|
|
||||||
### Added
|
### Added
|
||||||
|
|
||||||
- Functional Expressions API
|
- Functional Expressions API
|
||||||
- Mathematical Syntax Tree, its interpreter and API
|
- Mathematical Syntax Tree, its interpreter and API
|
||||||
- String to MST parser (https://github.com/mipt-npm/kmath/pull/120)
|
- String to MST parser (https://github.com/mipt-npm/kmath/pull/120)
|
||||||
- MST to JVM bytecode translator (https://github.com/mipt-npm/kmath/pull/94)
|
- MST to JVM bytecode translator (https://github.com/mipt-npm/kmath/pull/94)
|
||||||
- FloatBuffer (specialized MutableBuffer over FloatArray)
|
- FloatBuffer (specialized MutableBuffer over FloatArray)
|
||||||
- FlaggedBuffer to associate primitive numbers buffer with flags (to mark values infinite or missing, etc.)
|
- FlaggedBuffer to associate primitive numbers buffer with flags (to mark values infinite or missing, etc.)
|
||||||
- Specialized builder functions for all primitive buffers
|
- Specialized builder functions for all primitive buffers like `IntBuffer(25) { it + 1 }` (https://github.com/mipt-npm/kmath/pull/125)
|
||||||
like `IntBuffer(25) { it + 1 }` (https://github.com/mipt-npm/kmath/pull/125)
|
|
||||||
- Interface `NumericAlgebra` where `number` operation is available to convert numbers to algebraic elements
|
- Interface `NumericAlgebra` where `number` operation is available to convert numbers to algebraic elements
|
||||||
- Inverse trigonometric functions support in
|
- Inverse trigonometric functions support in ExtendedField (`asin`, `acos`, `atan`) (https://github.com/mipt-npm/kmath/pull/114)
|
||||||
ExtendedField (`asin`, `acos`, `atan`) (https://github.com/mipt-npm/kmath/pull/114)
|
|
||||||
- New space extensions: `average` and `averageWith`
|
- New space extensions: `average` and `averageWith`
|
||||||
- Local coding conventions
|
- Local coding conventions
|
||||||
- Geometric Domains API in `kmath-core`
|
- Geometric Domains API in `kmath-core`
|
||||||
@ -251,12 +192,10 @@
|
|||||||
- Norm support for `Complex`
|
- Norm support for `Complex`
|
||||||
|
|
||||||
### Changed
|
### Changed
|
||||||
|
|
||||||
- `readAsMemory` now has `throws IOException` in JVM signature.
|
- `readAsMemory` now has `throws IOException` in JVM signature.
|
||||||
- Several functions taking functional types were made `inline`.
|
- Several functions taking functional types were made `inline`.
|
||||||
- Several functions taking functional types now have `callsInPlace` contracts.
|
- Several functions taking functional types now have `callsInPlace` contracts.
|
||||||
- BigInteger and BigDecimal algebra: JBigDecimalField has companion object with default math context; minor
|
- BigInteger and BigDecimal algebra: JBigDecimalField has companion object with default math context; minor optimizations
|
||||||
optimizations
|
|
||||||
- `power(T, Int)` extension function has preconditions and supports `Field<T>`
|
- `power(T, Int)` extension function has preconditions and supports `Field<T>`
|
||||||
- Memory objects have more preconditions (overflow checking)
|
- Memory objects have more preconditions (overflow checking)
|
||||||
- `tg` function is renamed to `tan` (https://github.com/mipt-npm/kmath/pull/114)
|
- `tg` function is renamed to `tan` (https://github.com/mipt-npm/kmath/pull/114)
|
||||||
@ -264,7 +203,6 @@
|
|||||||
- Moved probability distributions to commons-rng and to `kmath-prob`
|
- Moved probability distributions to commons-rng and to `kmath-prob`
|
||||||
|
|
||||||
### Fixed
|
### Fixed
|
||||||
|
|
||||||
- Missing copy method in Memory implementation on JS (https://github.com/mipt-npm/kmath/pull/106)
|
- Missing copy method in Memory implementation on JS (https://github.com/mipt-npm/kmath/pull/106)
|
||||||
- D3.dim value in `kmath-dimensions`
|
- D3.dim value in `kmath-dimensions`
|
||||||
- Multiplication in integer rings in `kmath-core` (https://github.com/mipt-npm/kmath/pull/101)
|
- Multiplication in integer rings in `kmath-core` (https://github.com/mipt-npm/kmath/pull/101)
|
||||||
|
78
README.md
@ -2,7 +2,7 @@
|
|||||||
[![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/SciProgCentre/kmath/workflows/Gradle%20build/badge.svg)
|
![Gradle build](https://github.com/SciProgCentre/kmath/workflows/Gradle%20build/badge.svg)
|
||||||
[![Maven Central](https://img.shields.io/maven-central/v/space.kscience/kmath-core.svg?label=Maven%20Central)](https://search.maven.org/search?q=g:%22space.kscience%22)
|
[![Maven Central](https://img.shields.io/maven-central/v/space.kscience/kmath-core.svg?label=Maven%20Central)](https://search.maven.org/search?q=g:%22space.kscience%22)
|
||||||
[![Space](https://img.shields.io/badge/dynamic/xml?color=orange&label=Space&query=//metadata/versioning/latest&url=https%3A%2F%2Fmaven.pkg.jetbrains.space%2Fmipt-npm%2Fp%2Fsci%2Fmaven%2Fspace%2Fkscience%2Fkmath-core%2Fmaven-metadata.xml)](https://maven.pkg.jetbrains.space/mipt-npm/p/sci/maven/space/kscience/)
|
[![Space](https://img.shields.io/badge/dynamic/xml?color=orange&label=Space&query=//metadata/versioning/latest&url=https%3A%2F%2Fmaven.pkg.jetbrains.space%2Fmipt-npm%2Fp%2Fsci%2Fmaven%2Fspace%2Fkscience%2Fkmath-core%2Fmaven-metadata.xml)](https://maven.pkg.jetbrains.space/spc/p/sci/maven/space/kscience/)
|
||||||
|
|
||||||
# KMath
|
# KMath
|
||||||
|
|
||||||
@ -11,22 +11,18 @@ analog to Python's NumPy library. Later we found that kotlin is much more flexib
|
|||||||
architecture designs. In contrast to `numpy` and `scipy` it is modular and has a lightweight core. The `numpy`-like
|
architecture designs. In contrast to `numpy` and `scipy` it is modular and has a lightweight core. The `numpy`-like
|
||||||
experience could be achieved with [kmath-for-real](/kmath-for-real) extension module.
|
experience could be achieved with [kmath-for-real](/kmath-for-real) extension module.
|
||||||
|
|
||||||
[Documentation site](https://SciProgCentre.github.io/kmath/)
|
[Documentation site (**WIP**)](https://SciProgCentre.github.io/kmath/)
|
||||||
|
|
||||||
## Publications and talks
|
## Publications and talks
|
||||||
|
|
||||||
* [A conceptual article about context-oriented design](https://proandroiddev.com/an-introduction-context-oriented-programming-in-kotlin-2e79d316b0a2)
|
* [A conceptual article about context-oriented design](https://proandroiddev.com/an-introduction-context-oriented-programming-in-kotlin-2e79d316b0a2)
|
||||||
* [Another article about context-oriented design](https://proandroiddev.com/diving-deeper-into-context-oriented-programming-in-kotlin-3ecb4ec38814)
|
* [Another article about context-oriented design](https://proandroiddev.com/diving-deeper-into-context-oriented-programming-in-kotlin-3ecb4ec38814)
|
||||||
* [ACAT 2019 conference paper](https://aip.scitation.org/doi/abs/10.1063/1.5130103)
|
* [ACAT 2019 conference paper](https://aip.scitation.org/doi/abs/10.1063/1.5130103)
|
||||||
* [A talk at KotlinConf 2019 about using kotlin for science](https://youtu.be/LI_5TZ7tnOE?si=4LknX41gl_YeUbIe)
|
|
||||||
* [A talk on architecture at Joker-2021 (in Russian)](https://youtu.be/1bZ2doHiRRM?si=9w953ro9yu98X_KJ)
|
|
||||||
* [The same talk in English](https://youtu.be/yP5DIc2fVwQ?si=louZzQ1dcXV6gP10)
|
|
||||||
* [A seminar on tensor API](https://youtu.be/0H99wUs0xTM?si=6c__04jrByFQtVpo)
|
|
||||||
|
|
||||||
# Goal
|
# Goal
|
||||||
|
|
||||||
* Provide a flexible and powerful API to work with mathematics abstractions in Kotlin-multiplatform (JVM, JS, Native and
|
* Provide a flexible and powerful API to work with mathematics abstractions in Kotlin-multiplatform (JVM, JS and Native)
|
||||||
Wasm).
|
.
|
||||||
* Provide basic multiplatform implementations for those abstractions (without significant performance optimization).
|
* Provide basic multiplatform implementations for those abstractions (without significant performance optimization).
|
||||||
* Provide bindings and wrappers with those abstractions for popular optimized platform libraries.
|
* Provide bindings and wrappers with those abstractions for popular optimized platform libraries.
|
||||||
|
|
||||||
@ -57,21 +53,19 @@ module definitions below. The module stability could have the following levels:
|
|||||||
## Modules
|
## Modules
|
||||||
|
|
||||||
|
|
||||||
### [attributes-kt](attributes-kt)
|
|
||||||
> An API and basic implementation for arranging objects in a continuous memory block.
|
|
||||||
>
|
|
||||||
> **Maturity**: DEVELOPMENT
|
|
||||||
|
|
||||||
### [benchmarks](benchmarks)
|
### [benchmarks](benchmarks)
|
||||||
>
|
>
|
||||||
|
>
|
||||||
> **Maturity**: EXPERIMENTAL
|
> **Maturity**: EXPERIMENTAL
|
||||||
|
|
||||||
### [examples](examples)
|
### [examples](examples)
|
||||||
>
|
>
|
||||||
|
>
|
||||||
> **Maturity**: EXPERIMENTAL
|
> **Maturity**: EXPERIMENTAL
|
||||||
|
|
||||||
### [kmath-ast](kmath-ast)
|
### [kmath-ast](kmath-ast)
|
||||||
>
|
>
|
||||||
|
>
|
||||||
> **Maturity**: EXPERIMENTAL
|
> **Maturity**: EXPERIMENTAL
|
||||||
>
|
>
|
||||||
> **Features:**
|
> **Features:**
|
||||||
@ -82,7 +76,7 @@ module definitions below. The module stability could have the following levels:
|
|||||||
|
|
||||||
|
|
||||||
### [kmath-commons](kmath-commons)
|
### [kmath-commons](kmath-commons)
|
||||||
> Commons math binding for kmath
|
>
|
||||||
>
|
>
|
||||||
> **Maturity**: EXPERIMENTAL
|
> **Maturity**: EXPERIMENTAL
|
||||||
|
|
||||||
@ -111,20 +105,21 @@ objects to the expression by providing a context. Expressions can be used for a
|
|||||||
performance calculations to code generation.
|
performance calculations to code generation.
|
||||||
> - [domains](kmath-core/src/commonMain/kotlin/space/kscience/kmath/domains) : Domains
|
> - [domains](kmath-core/src/commonMain/kotlin/space/kscience/kmath/domains) : Domains
|
||||||
> - [autodiff](kmath-core/src/commonMain/kotlin/space/kscience/kmath/expressions/SimpleAutoDiff.kt) : Automatic differentiation
|
> - [autodiff](kmath-core/src/commonMain/kotlin/space/kscience/kmath/expressions/SimpleAutoDiff.kt) : Automatic differentiation
|
||||||
> - [Parallel linear algebra](kmath-core/#) : Parallel implementation for `LinearAlgebra`
|
|
||||||
|
|
||||||
|
|
||||||
### [kmath-coroutines](kmath-coroutines)
|
### [kmath-coroutines](kmath-coroutines)
|
||||||
>
|
>
|
||||||
|
>
|
||||||
> **Maturity**: EXPERIMENTAL
|
> **Maturity**: EXPERIMENTAL
|
||||||
|
|
||||||
### [kmath-dimensions](kmath-dimensions)
|
### [kmath-dimensions](kmath-dimensions)
|
||||||
> A proof of concept module for adding type-safe dimensions to structures
|
>
|
||||||
>
|
>
|
||||||
> **Maturity**: PROTOTYPE
|
> **Maturity**: PROTOTYPE
|
||||||
|
|
||||||
### [kmath-ejml](kmath-ejml)
|
### [kmath-ejml](kmath-ejml)
|
||||||
>
|
>
|
||||||
|
>
|
||||||
> **Maturity**: PROTOTYPE
|
> **Maturity**: PROTOTYPE
|
||||||
>
|
>
|
||||||
> **Features:**
|
> **Features:**
|
||||||
@ -147,7 +142,7 @@ One can still use generic algebras though.
|
|||||||
|
|
||||||
|
|
||||||
### [kmath-functions](kmath-functions)
|
### [kmath-functions](kmath-functions)
|
||||||
> Functions, integration and interpolation
|
>
|
||||||
>
|
>
|
||||||
> **Maturity**: EXPERIMENTAL
|
> **Maturity**: EXPERIMENTAL
|
||||||
>
|
>
|
||||||
@ -161,16 +156,18 @@ One can still use generic algebras though.
|
|||||||
|
|
||||||
### [kmath-geometry](kmath-geometry)
|
### [kmath-geometry](kmath-geometry)
|
||||||
>
|
>
|
||||||
|
>
|
||||||
> **Maturity**: PROTOTYPE
|
> **Maturity**: PROTOTYPE
|
||||||
|
|
||||||
### [kmath-histograms](kmath-histograms)
|
### [kmath-histograms](kmath-histograms)
|
||||||
>
|
>
|
||||||
|
>
|
||||||
> **Maturity**: PROTOTYPE
|
> **Maturity**: PROTOTYPE
|
||||||
|
|
||||||
### [kmath-jafama](kmath-jafama)
|
### [kmath-jafama](kmath-jafama)
|
||||||
> Jafama integration module
|
|
||||||
>
|
>
|
||||||
> **Maturity**: DEPRECATED
|
>
|
||||||
|
> **Maturity**: PROTOTYPE
|
||||||
>
|
>
|
||||||
> **Features:**
|
> **Features:**
|
||||||
> - [jafama-double](kmath-jafama/src/main/kotlin/space/kscience/kmath/jafama/) : Double ExtendedField implementations based on Jafama
|
> - [jafama-double](kmath-jafama/src/main/kotlin/space/kscience/kmath/jafama/) : Double ExtendedField implementations based on Jafama
|
||||||
@ -178,10 +175,11 @@ One can still use generic algebras though.
|
|||||||
|
|
||||||
### [kmath-jupyter](kmath-jupyter)
|
### [kmath-jupyter](kmath-jupyter)
|
||||||
>
|
>
|
||||||
|
>
|
||||||
> **Maturity**: PROTOTYPE
|
> **Maturity**: PROTOTYPE
|
||||||
|
|
||||||
### [kmath-kotlingrad](kmath-kotlingrad)
|
### [kmath-kotlingrad](kmath-kotlingrad)
|
||||||
> Kotlin∇ integration module
|
>
|
||||||
>
|
>
|
||||||
> **Maturity**: EXPERIMENTAL
|
> **Maturity**: EXPERIMENTAL
|
||||||
>
|
>
|
||||||
@ -196,14 +194,14 @@ One can still use generic algebras though.
|
|||||||
> **Maturity**: DEVELOPMENT
|
> **Maturity**: DEVELOPMENT
|
||||||
|
|
||||||
### [kmath-multik](kmath-multik)
|
### [kmath-multik](kmath-multik)
|
||||||
> JetBrains Multik connector
|
>
|
||||||
>
|
>
|
||||||
> **Maturity**: PROTOTYPE
|
> **Maturity**: PROTOTYPE
|
||||||
|
|
||||||
### [kmath-nd4j](kmath-nd4j)
|
### [kmath-nd4j](kmath-nd4j)
|
||||||
> ND4J NDStructure implementation and according NDAlgebra classes
|
|
||||||
>
|
>
|
||||||
> **Maturity**: DEPRECATED
|
>
|
||||||
|
> **Maturity**: EXPERIMENTAL
|
||||||
>
|
>
|
||||||
> **Features:**
|
> **Features:**
|
||||||
> - [nd4jarraystructure](kmath-nd4j/#) : NDStructure wrapper for INDArray
|
> - [nd4jarraystructure](kmath-nd4j/#) : NDStructure wrapper for INDArray
|
||||||
@ -213,24 +211,27 @@ One can still use generic algebras though.
|
|||||||
|
|
||||||
### [kmath-optimization](kmath-optimization)
|
### [kmath-optimization](kmath-optimization)
|
||||||
>
|
>
|
||||||
|
>
|
||||||
> **Maturity**: EXPERIMENTAL
|
> **Maturity**: EXPERIMENTAL
|
||||||
|
|
||||||
### [kmath-stat](kmath-stat)
|
### [kmath-stat](kmath-stat)
|
||||||
>
|
>
|
||||||
|
>
|
||||||
> **Maturity**: EXPERIMENTAL
|
> **Maturity**: EXPERIMENTAL
|
||||||
|
|
||||||
### [kmath-symja](kmath-symja)
|
### [kmath-symja](kmath-symja)
|
||||||
> Symja integration module
|
>
|
||||||
>
|
>
|
||||||
> **Maturity**: PROTOTYPE
|
> **Maturity**: PROTOTYPE
|
||||||
|
|
||||||
### [kmath-tensorflow](kmath-tensorflow)
|
### [kmath-tensorflow](kmath-tensorflow)
|
||||||
> Google tensorflow connector
|
>
|
||||||
>
|
>
|
||||||
> **Maturity**: PROTOTYPE
|
> **Maturity**: PROTOTYPE
|
||||||
|
|
||||||
### [kmath-tensors](kmath-tensors)
|
### [kmath-tensors](kmath-tensors)
|
||||||
>
|
>
|
||||||
|
>
|
||||||
> **Maturity**: PROTOTYPE
|
> **Maturity**: PROTOTYPE
|
||||||
>
|
>
|
||||||
> **Features:**
|
> **Features:**
|
||||||
@ -240,12 +241,13 @@ One can still use generic algebras though.
|
|||||||
|
|
||||||
|
|
||||||
### [kmath-viktor](kmath-viktor)
|
### [kmath-viktor](kmath-viktor)
|
||||||
> Binding for https://github.com/JetBrains-Research/viktor
|
|
||||||
>
|
>
|
||||||
> **Maturity**: DEPRECATED
|
>
|
||||||
|
> **Maturity**: DEVELOPMENT
|
||||||
|
|
||||||
### [test-utils](test-utils)
|
### [test-utils](test-utils)
|
||||||
>
|
>
|
||||||
|
>
|
||||||
> **Maturity**: EXPERIMENTAL
|
> **Maturity**: EXPERIMENTAL
|
||||||
|
|
||||||
|
|
||||||
@ -254,24 +256,22 @@ One can still use generic algebras though.
|
|||||||
KMath is developed as a multi-platform library, which means that most of the interfaces are declared in the
|
KMath is developed as a multi-platform library, which means that most of the interfaces are declared in the
|
||||||
[common source sets](/kmath-core/src/commonMain) and implemented there wherever it is possible. In some cases, features
|
[common source sets](/kmath-core/src/commonMain) and implemented there wherever it is possible. In some cases, features
|
||||||
are delegated to platform-specific implementations even if they could be provided in the common module for performance
|
are delegated to platform-specific implementations even if they could be provided in the common module for performance
|
||||||
reasons. Currently, Kotlin/JVM is the primary platform, however, Kotlin/Native and Kotlin/JS contributions and
|
reasons. Currently, the Kotlin/JVM is the primary platform, however Kotlin/Native and Kotlin/JS contributions and
|
||||||
feedback are also welcome.
|
feedback are also welcome.
|
||||||
|
|
||||||
## Performance
|
## Performance
|
||||||
|
|
||||||
Calculation of performance is one of the major goals of KMath in the future, but in some cases it is impossible to
|
Calculation performance is one of major goals of KMath in the future, but in some cases it is impossible to achieve both
|
||||||
achieve both
|
|
||||||
performance and flexibility.
|
performance and flexibility.
|
||||||
|
|
||||||
We expect to focus on creating a convenient universal API first and then work on increasing performance for specific
|
We expect to focus on creating convenient universal API first and then work on increasing performance for specific
|
||||||
cases. We expect the worst KMath benchmarks will perform better than native Python, but worse than optimized
|
cases. We expect the worst KMath benchmarks will perform better than native Python, but worse than optimized
|
||||||
native/SciPy (mostly due to boxing operations on primitive numbers). The best performance of optimized parts could be
|
native/SciPy (mostly due to boxing operations on primitive numbers). The best performance of optimized parts could be better than SciPy.
|
||||||
better than SciPy.
|
|
||||||
|
|
||||||
## Requirements
|
## Requirements
|
||||||
|
|
||||||
KMath currently relies on JDK 11 for compilation and execution of Kotlin-JVM part. We recommend using GraalVM-CE or
|
KMath currently relies on JDK 11 for compilation and execution of Kotlin-JVM part. We recommend to use GraalVM-CE 11 for
|
||||||
Oracle GraalVM for execution to get better performance.
|
execution to get better performance.
|
||||||
|
|
||||||
### Repositories
|
### Repositories
|
||||||
|
|
||||||
@ -291,10 +291,10 @@ dependencies {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
Gradle `6.0+` is required for multiplatform artifacts.
|
||||||
|
|
||||||
## Contributing
|
## Contributing
|
||||||
|
|
||||||
The project requires a lot of additional work. The most important thing we need is 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
|
||||||
required the most. Feel free to create feature requests. We are also welcome to code contributions, especially in issues
|
required the most. Feel free to create feature requests. We are also welcome to code contributions, especially in issues
|
||||||
marked
|
marked with [waiting for a hero](https://github.com/SciProgCentre/kmath/labels/waiting%20for%20a%20hero) label.
|
||||||
with [good first issue](hhttps://github.com/SciProgCentre/kmath/issues?q=is%3Aissue+is%3Aopen+label%3A%22good+first+issue%22)
|
|
||||||
label.
|
|
@ -1,21 +0,0 @@
|
|||||||
# Module attributes-kt
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
## Usage
|
|
||||||
|
|
||||||
## Artifact:
|
|
||||||
|
|
||||||
The Maven coordinates of this project are `space.kscience:attributes-kt:0.1.0`.
|
|
||||||
|
|
||||||
**Gradle Kotlin DSL:**
|
|
||||||
```kotlin
|
|
||||||
repositories {
|
|
||||||
maven("https://repo.kotlin.link")
|
|
||||||
mavenCentral()
|
|
||||||
}
|
|
||||||
|
|
||||||
dependencies {
|
|
||||||
implementation("space.kscience:attributes-kt:0.1.0")
|
|
||||||
}
|
|
||||||
```
|
|
@ -1,104 +0,0 @@
|
|||||||
public abstract interface class space/kscience/attributes/Attribute {
|
|
||||||
}
|
|
||||||
|
|
||||||
public abstract interface class space/kscience/attributes/AttributeContainer {
|
|
||||||
public abstract fun getAttributes ()Lspace/kscience/attributes/Attributes;
|
|
||||||
}
|
|
||||||
|
|
||||||
public abstract interface class space/kscience/attributes/AttributeScope {
|
|
||||||
}
|
|
||||||
|
|
||||||
public abstract interface class space/kscience/attributes/AttributeWithDefault : space/kscience/attributes/Attribute {
|
|
||||||
public abstract fun getDefault ()Ljava/lang/Object;
|
|
||||||
}
|
|
||||||
|
|
||||||
public abstract interface class space/kscience/attributes/Attributes {
|
|
||||||
public static final field Companion Lspace/kscience/attributes/Attributes$Companion;
|
|
||||||
public abstract fun equals (Ljava/lang/Object;)Z
|
|
||||||
public fun get (Lspace/kscience/attributes/Attribute;)Ljava/lang/Object;
|
|
||||||
public abstract fun getContent ()Ljava/util/Map;
|
|
||||||
public fun getKeys ()Ljava/util/Set;
|
|
||||||
public abstract fun hashCode ()I
|
|
||||||
public abstract fun toString ()Ljava/lang/String;
|
|
||||||
}
|
|
||||||
|
|
||||||
public final class space/kscience/attributes/Attributes$Companion {
|
|
||||||
public final fun equals (Lspace/kscience/attributes/Attributes;Lspace/kscience/attributes/Attributes;)Z
|
|
||||||
public final fun getEMPTY ()Lspace/kscience/attributes/Attributes;
|
|
||||||
}
|
|
||||||
|
|
||||||
public final class space/kscience/attributes/AttributesBuilder : space/kscience/attributes/Attributes {
|
|
||||||
public final fun add (Lspace/kscience/attributes/SetAttribute;Ljava/lang/Object;)V
|
|
||||||
public final fun build ()Lspace/kscience/attributes/Attributes;
|
|
||||||
public fun equals (Ljava/lang/Object;)Z
|
|
||||||
public fun getContent ()Ljava/util/Map;
|
|
||||||
public fun hashCode ()I
|
|
||||||
public final fun invoke (Lspace/kscience/attributes/Attribute;Ljava/lang/Object;)V
|
|
||||||
public final fun put (Lspace/kscience/attributes/Attribute;Ljava/lang/Object;)V
|
|
||||||
public final fun putAll (Lspace/kscience/attributes/Attributes;)V
|
|
||||||
public final fun remove (Lspace/kscience/attributes/SetAttribute;Ljava/lang/Object;)V
|
|
||||||
public final fun set (Lspace/kscience/attributes/Attribute;Ljava/lang/Object;)V
|
|
||||||
public fun toString ()Ljava/lang/String;
|
|
||||||
}
|
|
||||||
|
|
||||||
public final class space/kscience/attributes/AttributesBuilderKt {
|
|
||||||
public static final fun Attributes (Lkotlin/jvm/functions/Function1;)Lspace/kscience/attributes/Attributes;
|
|
||||||
}
|
|
||||||
|
|
||||||
public final class space/kscience/attributes/AttributesKt {
|
|
||||||
public static final fun Attributes (Lspace/kscience/attributes/Attribute;)Lspace/kscience/attributes/Attributes;
|
|
||||||
public static final fun Attributes (Lspace/kscience/attributes/Attribute;Ljava/lang/Object;)Lspace/kscience/attributes/Attributes;
|
|
||||||
public static final fun getOrDefault (Lspace/kscience/attributes/Attributes;Lspace/kscience/attributes/AttributeWithDefault;)Ljava/lang/Object;
|
|
||||||
public static final fun isEmpty (Lspace/kscience/attributes/Attributes;)Z
|
|
||||||
public static final fun modified (Lspace/kscience/attributes/Attributes;Lkotlin/jvm/functions/Function1;)Lspace/kscience/attributes/Attributes;
|
|
||||||
public static final fun plus (Lspace/kscience/attributes/Attributes;Lspace/kscience/attributes/Attributes;)Lspace/kscience/attributes/Attributes;
|
|
||||||
public static final fun withAttribute (Lspace/kscience/attributes/Attributes;Lspace/kscience/attributes/Attribute;)Lspace/kscience/attributes/Attributes;
|
|
||||||
public static final fun withAttribute (Lspace/kscience/attributes/Attributes;Lspace/kscience/attributes/Attribute;Ljava/lang/Object;)Lspace/kscience/attributes/Attributes;
|
|
||||||
public static final fun withAttributeElement (Lspace/kscience/attributes/Attributes;Lspace/kscience/attributes/SetAttribute;Ljava/lang/Object;)Lspace/kscience/attributes/Attributes;
|
|
||||||
public static final fun withoutAttribute (Lspace/kscience/attributes/Attributes;Lspace/kscience/attributes/Attribute;)Lspace/kscience/attributes/Attributes;
|
|
||||||
public static final fun withoutAttributeElement (Lspace/kscience/attributes/Attributes;Lspace/kscience/attributes/SetAttribute;Ljava/lang/Object;)Lspace/kscience/attributes/Attributes;
|
|
||||||
}
|
|
||||||
|
|
||||||
public abstract interface class space/kscience/attributes/FlagAttribute : space/kscience/attributes/Attribute {
|
|
||||||
}
|
|
||||||
|
|
||||||
public abstract class space/kscience/attributes/PolymorphicAttribute : space/kscience/attributes/Attribute {
|
|
||||||
public synthetic fun <init> (Lkotlin/reflect/KType;Lkotlin/jvm/internal/DefaultConstructorMarker;)V
|
|
||||||
public fun equals (Ljava/lang/Object;)Z
|
|
||||||
public final fun getType-V0oMfBY ()Lkotlin/reflect/KType;
|
|
||||||
public fun hashCode ()I
|
|
||||||
}
|
|
||||||
|
|
||||||
public final class space/kscience/attributes/PolymorphicAttributeKt {
|
|
||||||
public static final fun get (Lspace/kscience/attributes/Attributes;Lkotlin/jvm/functions/Function0;)Ljava/lang/Object;
|
|
||||||
public static final fun set (Lspace/kscience/attributes/AttributesBuilder;Lkotlin/jvm/functions/Function0;Ljava/lang/Object;)V
|
|
||||||
}
|
|
||||||
|
|
||||||
public final class space/kscience/attributes/SafeType {
|
|
||||||
public static final synthetic fun box-impl (Lkotlin/reflect/KType;)Lspace/kscience/attributes/SafeType;
|
|
||||||
public static fun constructor-impl (Lkotlin/reflect/KType;)Lkotlin/reflect/KType;
|
|
||||||
public fun equals (Ljava/lang/Object;)Z
|
|
||||||
public static fun equals-impl (Lkotlin/reflect/KType;Ljava/lang/Object;)Z
|
|
||||||
public static final fun equals-impl0 (Lkotlin/reflect/KType;Lkotlin/reflect/KType;)Z
|
|
||||||
public final fun getKType ()Lkotlin/reflect/KType;
|
|
||||||
public fun hashCode ()I
|
|
||||||
public static fun hashCode-impl (Lkotlin/reflect/KType;)I
|
|
||||||
public fun toString ()Ljava/lang/String;
|
|
||||||
public static fun toString-impl (Lkotlin/reflect/KType;)Ljava/lang/String;
|
|
||||||
public final synthetic fun unbox-impl ()Lkotlin/reflect/KType;
|
|
||||||
}
|
|
||||||
|
|
||||||
public final class space/kscience/attributes/SafeTypeKt {
|
|
||||||
public static final fun getKClass-X0YbwmU (Lkotlin/reflect/KType;)Lkotlin/reflect/KClass;
|
|
||||||
}
|
|
||||||
|
|
||||||
public abstract interface class space/kscience/attributes/SetAttribute : space/kscience/attributes/Attribute {
|
|
||||||
}
|
|
||||||
|
|
||||||
public abstract interface annotation class space/kscience/attributes/UnstableAttributesAPI : java/lang/annotation/Annotation {
|
|
||||||
}
|
|
||||||
|
|
||||||
public abstract interface class space/kscience/attributes/WithType {
|
|
||||||
public abstract fun getType-V0oMfBY ()Lkotlin/reflect/KType;
|
|
||||||
}
|
|
||||||
|
|
@ -1,20 +0,0 @@
|
|||||||
plugins {
|
|
||||||
id("space.kscience.gradle.mpp")
|
|
||||||
`maven-publish`
|
|
||||||
}
|
|
||||||
|
|
||||||
version = rootProject.extra.get("attributesVersion").toString()
|
|
||||||
|
|
||||||
kscience {
|
|
||||||
jvm()
|
|
||||||
js()
|
|
||||||
native()
|
|
||||||
wasm()
|
|
||||||
}
|
|
||||||
|
|
||||||
readme {
|
|
||||||
maturity = space.kscience.gradle.Maturity.DEVELOPMENT
|
|
||||||
description = """
|
|
||||||
An API and basic implementation for arranging objects in a continuous memory block.
|
|
||||||
""".trimIndent()
|
|
||||||
}
|
|
@ -1,29 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2018-2023 KMath contributors.
|
|
||||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package space.kscience.attributes
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A marker interface for an attribute. Attributes are used as keys to access contents of type [T] in the container.
|
|
||||||
*/
|
|
||||||
public interface Attribute<T>
|
|
||||||
|
|
||||||
/**
|
|
||||||
* An attribute that could be either present or absent
|
|
||||||
*/
|
|
||||||
public interface FlagAttribute : Attribute<Unit>
|
|
||||||
|
|
||||||
/**
|
|
||||||
* An attribute with a default value
|
|
||||||
*/
|
|
||||||
public interface AttributeWithDefault<T> : Attribute<T> {
|
|
||||||
public val default: T
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Attribute containing a set of values
|
|
||||||
*/
|
|
||||||
public interface SetAttribute<V> : Attribute<Set<V>>
|
|
||||||
|
|
@ -1,20 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2018-2023 KMath contributors.
|
|
||||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package space.kscience.attributes
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A container for [Attributes]
|
|
||||||
*/
|
|
||||||
public interface AttributeContainer {
|
|
||||||
public val attributes: Attributes
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A scope, where attribute keys could be resolved.
|
|
||||||
* [O] is used only to resolve types in compile-time.
|
|
||||||
*/
|
|
||||||
public interface AttributeScope<O>
|
|
||||||
|
|
@ -1,157 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2018-2023 KMath contributors.
|
|
||||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package space.kscience.attributes
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A set of attributes. The implementation must guarantee that [content] keys correspond to their value types.
|
|
||||||
*/
|
|
||||||
public interface Attributes {
|
|
||||||
/**
|
|
||||||
* Raw content for this [Attributes]
|
|
||||||
*/
|
|
||||||
public val content: Map<out Attribute<*>, Any?>
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Attribute keys contained in this [Attributes]
|
|
||||||
*/
|
|
||||||
public val keys: Set<Attribute<*>> get() = content.keys
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Provide an attribute value. Return null if attribute is not present or if its value is null.
|
|
||||||
*/
|
|
||||||
@Suppress("UNCHECKED_CAST")
|
|
||||||
public operator fun <T> get(attribute: Attribute<T>): T? = content[attribute] as? T
|
|
||||||
|
|
||||||
override fun toString(): String
|
|
||||||
override fun equals(other: Any?): Boolean
|
|
||||||
override fun hashCode(): Int
|
|
||||||
|
|
||||||
public companion object {
|
|
||||||
public val EMPTY: Attributes = object : Attributes {
|
|
||||||
override val content: Map<out Attribute<*>, Any?> get() = emptyMap()
|
|
||||||
|
|
||||||
override fun toString(): String = "Attributes.EMPTY"
|
|
||||||
|
|
||||||
override fun equals(other: Any?): Boolean = (other as? Attributes)?.isEmpty() ?: false
|
|
||||||
|
|
||||||
override fun hashCode(): Int = Unit.hashCode()
|
|
||||||
}
|
|
||||||
|
|
||||||
public fun equals(a1: Attributes, a2: Attributes): Boolean =
|
|
||||||
a1.keys == a2.keys && a1.keys.all { a1[it] == a2[it] }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
internal class MapAttributes(override val content: Map<out Attribute<*>, Any?>) : Attributes {
|
|
||||||
override fun toString(): String = "Attributes(value=${content.entries})"
|
|
||||||
override fun equals(other: Any?): Boolean = other is Attributes && Attributes.equals(this, other)
|
|
||||||
override fun hashCode(): Int = content.hashCode()
|
|
||||||
}
|
|
||||||
|
|
||||||
public fun Attributes.isEmpty(): Boolean = keys.isEmpty()
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get attribute value or default
|
|
||||||
*/
|
|
||||||
public fun <T> Attributes.getOrDefault(attribute: AttributeWithDefault<T>): T = get(attribute) ?: attribute.default
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Check if there is an attribute that matches given key by type and adheres to [predicate].
|
|
||||||
*/
|
|
||||||
@Suppress("UNCHECKED_CAST")
|
|
||||||
public inline fun <T, reified A : Attribute<T>> Attributes.hasAny(predicate: (value: T) -> Boolean): Boolean =
|
|
||||||
content.any { (mapKey, mapValue) -> mapKey is A && predicate(mapValue as T) }
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Check if there is an attribute of given type (subtypes included)
|
|
||||||
*/
|
|
||||||
public inline fun <reified A : Attribute<*>> Attributes.hasAny(): Boolean =
|
|
||||||
content.any { (mapKey, _) -> mapKey is A }
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Check if [Attributes] contains a flag. Multiple keys that are instances of a flag could be present
|
|
||||||
*/
|
|
||||||
public inline fun <reified A : FlagAttribute> Attributes.hasFlag(): Boolean =
|
|
||||||
content.keys.any { it is A }
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Create [Attributes] with an added or replaced attribute key.
|
|
||||||
*/
|
|
||||||
public fun <T, A : Attribute<T>> Attributes.withAttribute(
|
|
||||||
attribute: A,
|
|
||||||
attrValue: T,
|
|
||||||
): Attributes = MapAttributes(content + (attribute to attrValue))
|
|
||||||
|
|
||||||
public fun <A : Attribute<Unit>> Attributes.withAttribute(attribute: A): Attributes =
|
|
||||||
withAttribute(attribute, Unit)
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Create a new [Attributes] by modifying the current one
|
|
||||||
*/
|
|
||||||
public fun <O> Attributes.modified(block: AttributesBuilder<O>.() -> Unit): Attributes = Attributes<O> {
|
|
||||||
putAll(this@modified)
|
|
||||||
block()
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Create new [Attributes] by removing [attribute] key
|
|
||||||
*/
|
|
||||||
public fun Attributes.withoutAttribute(attribute: Attribute<*>): Attributes = MapAttributes(content.minus(attribute))
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Add an element to a [SetAttribute]
|
|
||||||
*/
|
|
||||||
public fun <T, A : SetAttribute<T>> Attributes.withAttributeElement(
|
|
||||||
attribute: A,
|
|
||||||
attrValue: T,
|
|
||||||
): Attributes {
|
|
||||||
val currentSet: Set<T> = get(attribute) ?: emptySet()
|
|
||||||
return MapAttributes(
|
|
||||||
content + (attribute to (currentSet + attrValue))
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Remove an element from [SetAttribute]
|
|
||||||
*/
|
|
||||||
public fun <T, A : SetAttribute<T>> Attributes.withoutAttributeElement(
|
|
||||||
attribute: A,
|
|
||||||
attrValue: T,
|
|
||||||
): Attributes {
|
|
||||||
val currentSet: Set<T> = get(attribute) ?: emptySet()
|
|
||||||
return MapAttributes(content + (attribute to (currentSet - attrValue)))
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Create [Attributes] with a single key
|
|
||||||
*/
|
|
||||||
public fun <T, A : Attribute<T>> Attributes(
|
|
||||||
attribute: A,
|
|
||||||
attrValue: T,
|
|
||||||
): Attributes = MapAttributes(mapOf(attribute to attrValue))
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Create Attributes with a single [Unit] valued attribute
|
|
||||||
*/
|
|
||||||
public fun <A : Attribute<Unit>> Attributes(
|
|
||||||
attribute: A,
|
|
||||||
): Attributes = MapAttributes(mapOf(attribute to Unit))
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Create a new [Attributes] that overlays [other] on top of this set of attributes. New attributes are added.
|
|
||||||
* Existing attribute keys are replaced.
|
|
||||||
*/
|
|
||||||
public operator fun Attributes.plus(other: Attributes): Attributes = when {
|
|
||||||
isEmpty() -> other
|
|
||||||
other.isEmpty() -> this
|
|
||||||
else -> MapAttributes(content + other.content)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Create a new [Attributes] with removed [key] (if it is present).
|
|
||||||
*/
|
|
||||||
public operator fun Attributes.minus(key: Attribute<*>): Attributes =
|
|
||||||
if (content.contains(key)) MapAttributes(content.minus(key)) else this
|
|
@ -1,68 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2018-2023 KMath contributors.
|
|
||||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package space.kscience.attributes
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A builder for [Attributes].
|
|
||||||
* The builder is not thread safe
|
|
||||||
*
|
|
||||||
* @param O type marker of an owner object, for which these attributes are made
|
|
||||||
*/
|
|
||||||
public class AttributesBuilder<out O> internal constructor() : Attributes {
|
|
||||||
|
|
||||||
private val map = mutableMapOf<Attribute<*>, Any?>()
|
|
||||||
|
|
||||||
override fun toString(): String = "Attributes(value=${map.entries})"
|
|
||||||
override fun equals(other: Any?): Boolean = other is Attributes && Attributes.equals(this, other)
|
|
||||||
override fun hashCode(): Int = map.hashCode()
|
|
||||||
|
|
||||||
override val content: Map<out Attribute<*>, Any?> get() = map
|
|
||||||
|
|
||||||
public operator fun <T> set(attribute: Attribute<T>, value: T?) {
|
|
||||||
if (value == null) {
|
|
||||||
map.remove(attribute)
|
|
||||||
} else {
|
|
||||||
map[attribute] = value
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public operator fun <V> Attribute<V>.invoke(value: V?) {
|
|
||||||
set(this, value)
|
|
||||||
}
|
|
||||||
|
|
||||||
public infix fun <V> Attribute<V>.put(value: V?) {
|
|
||||||
set(this, value)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Put all attributes for given [attributes]
|
|
||||||
*/
|
|
||||||
public fun putAll(attributes: Attributes) {
|
|
||||||
map.putAll(attributes.content)
|
|
||||||
}
|
|
||||||
|
|
||||||
public infix fun <V> SetAttribute<V>.add(attrValue: V) {
|
|
||||||
val currentSet: Set<V> = get(this) ?: emptySet()
|
|
||||||
map[this] = currentSet + attrValue
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Remove an element from [SetAttribute]
|
|
||||||
*/
|
|
||||||
public infix fun <V> SetAttribute<V>.remove(attrValue: V) {
|
|
||||||
val currentSet: Set<V> = get(this) ?: emptySet()
|
|
||||||
map[this] = currentSet - attrValue
|
|
||||||
}
|
|
||||||
|
|
||||||
public fun build(): Attributes = MapAttributes(map)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Create [Attributes] with a given [builder]
|
|
||||||
* @param O the type for which attributes are built. The type is used only during compilation phase for static extension dispatch
|
|
||||||
*/
|
|
||||||
public fun <O> Attributes(builder: AttributesBuilder<O>.() -> Unit): Attributes =
|
|
||||||
AttributesBuilder<O>().apply(builder).build()
|
|
@ -1,34 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2018-2023 KMath contributors.
|
|
||||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package space.kscience.attributes
|
|
||||||
|
|
||||||
/**
|
|
||||||
* An attribute that has a type parameter for value
|
|
||||||
* @param type parameter-type
|
|
||||||
*/
|
|
||||||
public abstract class PolymorphicAttribute<T>(public val type: SafeType<T>) : Attribute<T> {
|
|
||||||
override fun equals(other: Any?): Boolean = other != null &&
|
|
||||||
(this::class == other::class) &&
|
|
||||||
(other as? PolymorphicAttribute<*>)?.type == this.type
|
|
||||||
|
|
||||||
override fun hashCode(): Int = this::class.hashCode() + type.hashCode()
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get a polymorphic attribute using attribute factory
|
|
||||||
*/
|
|
||||||
@UnstableAttributesAPI
|
|
||||||
public operator fun <T> Attributes.get(attributeKeyBuilder: () -> PolymorphicAttribute<T>): T? =
|
|
||||||
get(attributeKeyBuilder())
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set a polymorphic attribute using its factory
|
|
||||||
*/
|
|
||||||
@UnstableAttributesAPI
|
|
||||||
public operator fun <O, T> AttributesBuilder<O>.set(attributeKeyBuilder: () -> PolymorphicAttribute<T>, value: T) {
|
|
||||||
set(attributeKeyBuilder(), value)
|
|
||||||
}
|
|
@ -1,35 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2018-2023 KMath contributors.
|
|
||||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package space.kscience.attributes
|
|
||||||
|
|
||||||
import kotlin.jvm.JvmInline
|
|
||||||
import kotlin.reflect.KClass
|
|
||||||
import kotlin.reflect.KType
|
|
||||||
import kotlin.reflect.typeOf
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Safe variant ok Kotlin [KType] that ensures that the type parameter is of the same type as [kType]
|
|
||||||
*
|
|
||||||
* @param kType raw [KType]
|
|
||||||
*/
|
|
||||||
@JvmInline
|
|
||||||
public value class SafeType<out T> @PublishedApi internal constructor(public val kType: KType)
|
|
||||||
|
|
||||||
public inline fun <reified T> safeTypeOf(): SafeType<T> = SafeType(typeOf<T>())
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Derive Kotlin [KClass] from this type and fail if the type is not a class (should not happen)
|
|
||||||
*/
|
|
||||||
@Suppress("UNCHECKED_CAST")
|
|
||||||
@UnstableAttributesAPI
|
|
||||||
public val <T> SafeType<T>.kClass: KClass<T & Any> get() = kType.classifier as KClass<T & Any>
|
|
||||||
|
|
||||||
/**
|
|
||||||
* An interface containing [type] for dynamic type checking.
|
|
||||||
*/
|
|
||||||
public interface WithType<out T> {
|
|
||||||
public val type: SafeType<T>
|
|
||||||
}
|
|
@ -1,17 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2018-2023 KMath contributors.
|
|
||||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package space.kscience.attributes
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Marks declarations that are still experimental in the Attributes-kt APIs, which means that the design of the corresponding
|
|
||||||
* declarations has open issues that may (or may not) lead to their changes in the future. Roughly speaking, there is
|
|
||||||
* a chance of those declarations will be deprecated in the future or the semantics of their behavior may change
|
|
||||||
* in some way that may break some code.
|
|
||||||
*/
|
|
||||||
@MustBeDocumented
|
|
||||||
@Retention(value = AnnotationRetention.BINARY)
|
|
||||||
@RequiresOptIn("This API is unstable and could change in future", RequiresOptIn.Level.WARNING)
|
|
||||||
public annotation class UnstableAttributesAPI
|
|
@ -1,119 +1,4 @@
|
|||||||
# BenchmarksResult
|
# Module benchmarks
|
||||||
|
|
||||||
## Report for benchmark configuration <code>main</code>
|
|
||||||
|
|
||||||
* Run on Java HotSpot(TM) 64-Bit Server VM (build 21.0.4+8-LTS-jvmci-23.1-b41) with Java process:
|
|
||||||
|
|
||||||
```
|
|
||||||
C:\Users\altavir\scoop\apps\graalvm-oracle-21jdk\current\bin\java.exe -XX:ThreadPriorityPolicy=1 -XX:+UnlockExperimentalVMOptions -XX:+EnableJVMCIProduct -XX:-UnlockExperimentalVMOptions -Dfile.encoding=UTF-8 -Duser.country=US -Duser.language=en -Duser.variant
|
|
||||||
```
|
|
||||||
* JMH 1.21 was used in `thrpt` mode with 5 warmup iterations by 10 s and 5 measurement iterations by 10 s.
|
|
||||||
### [ArrayBenchmark](src/jvmMain/kotlin/space/kscience/kmath/benchmarks/ArrayBenchmark.kt)
|
|
||||||
|
|
||||||
| Benchmark | Score |
|
|
||||||
|:---------:|:-----:|
|
|
||||||
|`benchmarkArrayRead`|1.9E+07 ± 2.3E+05 ops/s|
|
|
||||||
|`benchmarkBufferRead`|1.4E+07 ± 8.7E+05 ops/s|
|
|
||||||
|`nativeBufferRead`|1.4E+07 ± 1.3E+06 ops/s|
|
|
||||||
### [BigIntBenchmark](src/jvmMain/kotlin/space/kscience/kmath/benchmarks/BigIntBenchmark.kt)
|
|
||||||
|
|
||||||
| Benchmark | Score |
|
|
||||||
|:---------:|:-----:|
|
|
||||||
|`jvmAdd`|5.1E+07 ± 1.3E+06 ops/s|
|
|
||||||
|`jvmAddLarge`|5.1E+04 ± 8.2E+02 ops/s|
|
|
||||||
|`jvmMultiply`|8.5E+07 ± 9.7E+06 ops/s|
|
|
||||||
|`jvmMultiplyLarge`|2.5E+02 ± 15 ops/s|
|
|
||||||
|`jvmParsing10`|8.7E+06 ± 5.1E+05 ops/s|
|
|
||||||
|`jvmParsing16`|6.4E+06 ± 1.8E+05 ops/s|
|
|
||||||
|`jvmPower`|28 ± 0.79 ops/s|
|
|
||||||
|`jvmSmallAdd`|7.0E+07 ± 4.3E+06 ops/s|
|
|
||||||
|`kmAdd`|4.8E+07 ± 2.2E+06 ops/s|
|
|
||||||
|`kmAddLarge`|3.5E+04 ± 3.7E+03 ops/s|
|
|
||||||
|`kmMultiply`|6.7E+07 ± 1.5E+07 ops/s|
|
|
||||||
|`kmMultiplyLarge`|54 ± 4.2 ops/s|
|
|
||||||
|`kmParsing10`|4.5E+06 ± 8.3E+04 ops/s|
|
|
||||||
|`kmParsing16`|4.9E+06 ± 1.1E+05 ops/s|
|
|
||||||
|`kmPower`|10 ± 0.96 ops/s|
|
|
||||||
|`kmSmallAdd`|4.1E+07 ± 5.9E+05 ops/s|
|
|
||||||
### [BufferBenchmark](src/jvmMain/kotlin/space/kscience/kmath/benchmarks/BufferBenchmark.kt)
|
|
||||||
|
|
||||||
| Benchmark | Score |
|
|
||||||
|:---------:|:-----:|
|
|
||||||
|`bufferViewReadWrite`|5.8E+06 ± 1.6E+05 ops/s|
|
|
||||||
|`bufferViewReadWriteSpecialized`|5.6E+06 ± 2.6E+05 ops/s|
|
|
||||||
|`complexBufferReadWrite`|6.6E+06 ± 2.7E+05 ops/s|
|
|
||||||
|`doubleArrayReadWrite`|7.5E+06 ± 1.0E+06 ops/s|
|
|
||||||
|`doubleBufferReadWrite`|8.0E+06 ± 6.7E+05 ops/s|
|
|
||||||
### [DotBenchmark](src/jvmMain/kotlin/space/kscience/kmath/benchmarks/DotBenchmark.kt)
|
|
||||||
|
|
||||||
| Benchmark | Score |
|
|
||||||
|:---------:|:-----:|
|
|
||||||
|`bufferedDot`|1.3 ± 0.020 ops/s|
|
|
||||||
|`cmDot`|0.47 ± 0.42 ops/s|
|
|
||||||
|`cmDotWithConversion`|0.76 ± 0.13 ops/s|
|
|
||||||
|`ejmlDot`|6.7 ± 0.091 ops/s|
|
|
||||||
|`ejmlDotWithConversion`|6.4 ± 0.82 ops/s|
|
|
||||||
|`multikDot`|40 ± 6.7 ops/s|
|
|
||||||
|`parallelDot`|12 ± 1.8 ops/s|
|
|
||||||
|`tensorDot`|1.2 ± 0.041 ops/s|
|
|
||||||
|`tfDot`|5.9 ± 0.49 ops/s|
|
|
||||||
### [ExpressionsInterpretersBenchmark](src/jvmMain/kotlin/space/kscience/kmath/benchmarks/ExpressionsInterpretersBenchmark.kt)
|
|
||||||
|
|
||||||
| Benchmark | Score |
|
|
||||||
|:---------:|:-----:|
|
|
||||||
|`asmGenericExpression`|29 ± 1.2 ops/s|
|
|
||||||
|`asmPrimitiveExpression`|43 ± 1.3 ops/s|
|
|
||||||
|`asmPrimitiveExpressionArray`|71 ± 0.38 ops/s|
|
|
||||||
|`functionalExpression`|5.6 ± 0.11 ops/s|
|
|
||||||
|`justCalculate`|69 ± 9.0 ops/s|
|
|
||||||
|`mstExpression`|7.1 ± 0.020 ops/s|
|
|
||||||
|`rawExpression`|41 ± 1.5 ops/s|
|
|
||||||
### [IntegrationBenchmark](src/jvmMain/kotlin/space/kscience/kmath/benchmarks/IntegrationBenchmark.kt)
|
|
||||||
|
|
||||||
| Benchmark | Score |
|
|
||||||
|:---------:|:-----:|
|
|
||||||
|`complexIntegration`|3.6E+03 ± 1.9E+02 ops/s|
|
|
||||||
|`doubleIntegration`|3.7E+03 ± 12 ops/s|
|
|
||||||
### [JafamaBenchmark](src/jvmMain/kotlin/space/kscience/kmath/benchmarks/JafamaBenchmark.kt)
|
|
||||||
|
|
||||||
| Benchmark | Score |
|
|
||||||
|:---------:|:-----:|
|
|
||||||
|`core`|38 ± 0.64 ops/s|
|
|
||||||
|`jafama`|52 ± 0.36 ops/s|
|
|
||||||
|`strictJafama`|52 ± 4.0 ops/s|
|
|
||||||
### [MatrixInverseBenchmark](src/jvmMain/kotlin/space/kscience/kmath/benchmarks/MatrixInverseBenchmark.kt)
|
|
||||||
|
|
||||||
| Benchmark | Score |
|
|
||||||
|:---------:|:-----:|
|
|
||||||
|`cmLUPInversion`|2.2E+03 ± 76 ops/s|
|
|
||||||
|`ejmlInverse`|1.3E+03 ± 5.7 ops/s|
|
|
||||||
|`kmathLupInversion`|9.5E+02 ± 1.8E+02 ops/s|
|
|
||||||
|`kmathParallelLupInversion`|9.1E+02 ± 1.4E+02 ops/s|
|
|
||||||
### [NDFieldBenchmark](src/jvmMain/kotlin/space/kscience/kmath/benchmarks/NDFieldBenchmark.kt)
|
|
||||||
|
|
||||||
| Benchmark | Score |
|
|
||||||
|:---------:|:-----:|
|
|
||||||
|`boxingFieldAdd`|7.7 ± 0.79 ops/s|
|
|
||||||
|`multikAdd`|6.5 ± 0.33 ops/s|
|
|
||||||
|`multikInPlaceAdd`|64 ± 0.79 ops/s|
|
|
||||||
|`specializedFieldAdd`|8.0 ± 0.090 ops/s|
|
|
||||||
|`tensorAdd`|9.2 ± 0.053 ops/s|
|
|
||||||
|`tensorInPlaceAdd`|17 ± 10 ops/s|
|
|
||||||
|`viktorAdd`|7.6 ± 1.2 ops/s|
|
|
||||||
### [ViktorBenchmark](src/jvmMain/kotlin/space/kscience/kmath/benchmarks/ViktorBenchmark.kt)
|
|
||||||
|
|
||||||
| Benchmark | Score |
|
|
||||||
|:---------:|:-----:|
|
|
||||||
|`doubleFieldAddition`|7.7 ± 0.34 ops/s|
|
|
||||||
|`rawViktor`|5.9 ± 1.1 ops/s|
|
|
||||||
|`viktorFieldAddition`|7.3 ± 1.1 ops/s|
|
|
||||||
### [ViktorLogBenchmark](src/jvmMain/kotlin/space/kscience/kmath/benchmarks/ViktorLogBenchmark.kt)
|
|
||||||
|
|
||||||
| Benchmark | Score |
|
|
||||||
|:---------:|:-----:|
|
|
||||||
|`rawViktorLog`|1.4 ± 0.076 ops/s|
|
|
||||||
|`realFieldLog`|1.3 ± 0.069 ops/s|
|
|
||||||
|`viktorFieldLog`|1.3 ± 0.032 ops/s|
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -1,14 +1,12 @@
|
|||||||
import com.fasterxml.jackson.module.kotlin.jacksonObjectMapper
|
@file:Suppress("UNUSED_VARIABLE")
|
||||||
import com.fasterxml.jackson.module.kotlin.readValue
|
|
||||||
import kotlinx.benchmark.gradle.BenchmarksExtension
|
import org.jetbrains.kotlin.gradle.tasks.KotlinJvmCompile
|
||||||
import java.time.LocalDateTime
|
import space.kscience.kmath.benchmarks.addBenchmarkProperties
|
||||||
import java.time.ZoneId
|
|
||||||
import java.util.*
|
|
||||||
|
|
||||||
plugins {
|
plugins {
|
||||||
kotlin("multiplatform")
|
kotlin("multiplatform")
|
||||||
alias(spclibs.plugins.kotlin.plugin.allopen)
|
alias(spclibs.plugins.kotlin.plugin.allopen)
|
||||||
alias(spclibs.plugins.kotlinx.benchmark)
|
id("org.jetbrains.kotlinx.benchmark")
|
||||||
}
|
}
|
||||||
|
|
||||||
allOpen.annotation("org.openjdk.jmh.annotations.State")
|
allOpen.annotation("org.openjdk.jmh.annotations.State")
|
||||||
@ -18,6 +16,8 @@ repositories {
|
|||||||
mavenCentral()
|
mavenCentral()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
val multikVersion: String by rootProject.extra
|
||||||
|
|
||||||
kotlin {
|
kotlin {
|
||||||
jvm()
|
jvm()
|
||||||
|
|
||||||
@ -46,7 +46,7 @@ kotlin {
|
|||||||
implementation(project(":kmath-for-real"))
|
implementation(project(":kmath-for-real"))
|
||||||
implementation(project(":kmath-tensors"))
|
implementation(project(":kmath-tensors"))
|
||||||
implementation(project(":kmath-multik"))
|
implementation(project(":kmath-multik"))
|
||||||
implementation(libs.multik.default)
|
implementation("org.jetbrains.kotlinx:multik-default:$multikVersion")
|
||||||
implementation(spclibs.kotlinx.benchmark.runtime)
|
implementation(spclibs.kotlinx.benchmark.runtime)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -152,130 +152,23 @@ benchmark {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
kotlin {
|
kotlin.sourceSets.all {
|
||||||
jvmToolchain(11)
|
with(languageSettings) {
|
||||||
compilerOptions {
|
optIn("kotlin.contracts.ExperimentalContracts")
|
||||||
optIn.addAll(
|
optIn("kotlin.ExperimentalUnsignedTypes")
|
||||||
"space.kscience.kmath.UnstableKMathAPI"
|
optIn("space.kscience.kmath.UnstableKMathAPI")
|
||||||
)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
tasks.withType<KotlinJvmCompile> {
|
||||||
private data class JmhReport(
|
kotlinOptions {
|
||||||
val jmhVersion: String,
|
jvmTarget = "11"
|
||||||
val benchmark: String,
|
freeCompilerArgs = freeCompilerArgs + "-Xjvm-default=all" + "-Xlambdas=indy"
|
||||||
val mode: String,
|
|
||||||
val threads: Int,
|
|
||||||
val forks: Int,
|
|
||||||
val jvm: String,
|
|
||||||
val jvmArgs: List<String>,
|
|
||||||
val jdkVersion: String,
|
|
||||||
val vmName: String,
|
|
||||||
val vmVersion: String,
|
|
||||||
val warmupIterations: Int,
|
|
||||||
val warmupTime: String,
|
|
||||||
val warmupBatchSize: Int,
|
|
||||||
val measurementIterations: Int,
|
|
||||||
val measurementTime: String,
|
|
||||||
val measurementBatchSize: Int,
|
|
||||||
val params: Map<String, String> = emptyMap(),
|
|
||||||
val primaryMetric: PrimaryMetric,
|
|
||||||
val secondaryMetrics: Map<String, SecondaryMetric>,
|
|
||||||
) {
|
|
||||||
interface Metric {
|
|
||||||
val score: Double
|
|
||||||
val scoreError: Double
|
|
||||||
val scoreConfidence: List<Double>
|
|
||||||
val scorePercentiles: Map<Double, Double>
|
|
||||||
val scoreUnit: String
|
|
||||||
}
|
}
|
||||||
|
|
||||||
data class PrimaryMetric(
|
|
||||||
override val score: Double,
|
|
||||||
override val scoreError: Double,
|
|
||||||
override val scoreConfidence: List<Double>,
|
|
||||||
override val scorePercentiles: Map<Double, Double>,
|
|
||||||
override val scoreUnit: String,
|
|
||||||
val rawDataHistogram: List<List<List<List<Double>>>>? = null,
|
|
||||||
val rawData: List<List<Double>>? = null,
|
|
||||||
) : Metric
|
|
||||||
|
|
||||||
data class SecondaryMetric(
|
|
||||||
override val score: Double,
|
|
||||||
override val scoreError: Double,
|
|
||||||
override val scoreConfidence: List<Double>,
|
|
||||||
override val scorePercentiles: Map<Double, Double>,
|
|
||||||
override val scoreUnit: String,
|
|
||||||
val rawData: List<List<Double>>,
|
|
||||||
) : Metric
|
|
||||||
}
|
}
|
||||||
|
|
||||||
readme {
|
readme {
|
||||||
maturity = space.kscience.gradle.Maturity.EXPERIMENTAL
|
maturity = space.kscience.gradle.Maturity.EXPERIMENTAL
|
||||||
|
|
||||||
val jsonMapper = jacksonObjectMapper()
|
|
||||||
|
|
||||||
fun noun(number: Number, singular: String, plural: String) = if (number.toLong() == 1L) singular else plural
|
|
||||||
|
|
||||||
extensions.findByType(BenchmarksExtension::class.java)?.configurations?.forEach { cfg ->
|
|
||||||
val propertyName =
|
|
||||||
"benchmark${cfg.name.replaceFirstChar { if (it.isLowerCase()) it.titlecase(Locale.getDefault()) else it.toString() }}"
|
|
||||||
|
|
||||||
logger.info("Processing benchmark data from benchmark ${cfg.name} into readme property $propertyName")
|
|
||||||
|
|
||||||
val launches = layout.buildDirectory.dir("reports/benchmarks/${cfg.name}").get().asFile
|
|
||||||
if (!launches.exists()) return@forEach
|
|
||||||
|
|
||||||
property(propertyName) {
|
|
||||||
val resDirectory = launches.listFiles()?.maxByOrNull {
|
|
||||||
LocalDateTime.parse(it.name).atZone(ZoneId.systemDefault()).toInstant()
|
|
||||||
}
|
|
||||||
|
|
||||||
if (resDirectory == null || !(resDirectory.resolve("jvm.json")).exists()) {
|
|
||||||
"> **Can't find appropriate benchmark data. Try generating readme files after running benchmarks**."
|
|
||||||
} else {
|
|
||||||
val reports: List<JmhReport> =
|
|
||||||
jsonMapper.readValue<List<JmhReport>>(resDirectory.resolve("jvm.json"))
|
|
||||||
|
|
||||||
buildString {
|
|
||||||
appendLine("## Report for benchmark configuration <code>${cfg.name}</code>")
|
|
||||||
appendLine()
|
|
||||||
val first = reports.first()
|
|
||||||
|
|
||||||
appendLine("* Run on ${first.vmName} (build ${first.vmVersion}) with Java process:")
|
|
||||||
appendLine()
|
|
||||||
appendLine("```")
|
|
||||||
appendLine(
|
|
||||||
"${first.jvm} ${
|
|
||||||
first.jvmArgs.joinToString(" ")
|
|
||||||
}"
|
|
||||||
)
|
|
||||||
appendLine("```")
|
|
||||||
|
|
||||||
appendLine(
|
|
||||||
"* JMH ${first.jmhVersion} was used in `${first.mode}` mode with ${first.warmupIterations} warmup ${
|
|
||||||
noun(first.warmupIterations, "iteration", "iterations")
|
|
||||||
} by ${first.warmupTime} and ${first.measurementIterations} measurement ${
|
|
||||||
noun(first.measurementIterations, "iteration", "iterations")
|
|
||||||
} by ${first.measurementTime}."
|
|
||||||
)
|
|
||||||
|
|
||||||
reports.groupBy { it.benchmark.substringBeforeLast(".") }.forEach { (cl, compare) ->
|
|
||||||
appendLine("### [${cl.substringAfterLast(".")}](src/jvmMain/kotlin/${cl.replace(".","/")}.kt)")
|
|
||||||
appendLine()
|
|
||||||
appendLine("| Benchmark | Score |")
|
|
||||||
appendLine("|:---------:|:-----:|")
|
|
||||||
compare.forEach { report ->
|
|
||||||
val benchmarkName = report.benchmark.substringAfterLast(".")
|
|
||||||
val score = String.format("%.2G", report.primaryMetric.score)
|
|
||||||
val error = String.format("%.2G", report.primaryMetric.scoreError)
|
|
||||||
|
|
||||||
appendLine("|`$benchmarkName`|$score ± $error ${report.primaryMetric.scoreUnit}|")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
addBenchmarkProperties()
|
||||||
|
@ -1,5 +0,0 @@
|
|||||||
# BenchmarksResult
|
|
||||||
|
|
||||||
${benchmarkMain}
|
|
||||||
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2018-2024 KMath contributors.
|
* Copyright 2018-2022 KMath contributors.
|
||||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@ -11,10 +11,9 @@ import kotlinx.benchmark.Scope
|
|||||||
import kotlinx.benchmark.State
|
import kotlinx.benchmark.State
|
||||||
import space.kscience.kmath.UnstableKMathAPI
|
import space.kscience.kmath.UnstableKMathAPI
|
||||||
import space.kscience.kmath.expressions.*
|
import space.kscience.kmath.expressions.*
|
||||||
import space.kscience.kmath.operations.Float64Field
|
import space.kscience.kmath.operations.DoubleField
|
||||||
import space.kscience.kmath.operations.bindSymbol
|
import space.kscience.kmath.operations.bindSymbol
|
||||||
import space.kscience.kmath.operations.invoke
|
import space.kscience.kmath.operations.invoke
|
||||||
import space.kscience.kmath.structures.Float64
|
|
||||||
import kotlin.math.sin
|
import kotlin.math.sin
|
||||||
import kotlin.random.Random
|
import kotlin.random.Random
|
||||||
import space.kscience.kmath.estree.compileToExpression as estreeCompileToExpression
|
import space.kscience.kmath.estree.compileToExpression as estreeCompileToExpression
|
||||||
@ -68,7 +67,7 @@ class ExpressionsInterpretersBenchmark {
|
|||||||
blackhole.consume(sum)
|
blackhole.consume(sum)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun invokeAndSum(expr: Expression<Float64>, blackhole: Blackhole) {
|
private fun invokeAndSum(expr: Expression<Double>, blackhole: Blackhole) {
|
||||||
val random = Random(0)
|
val random = Random(0)
|
||||||
var sum = 0.0
|
var sum = 0.0
|
||||||
val m = HashMap<Symbol, Double>()
|
val m = HashMap<Symbol, Double>()
|
||||||
@ -85,7 +84,7 @@ class ExpressionsInterpretersBenchmark {
|
|||||||
private val x by symbol
|
private val x by symbol
|
||||||
private const val times = 1_000_000
|
private const val times = 1_000_000
|
||||||
|
|
||||||
private val functional = Float64Field.expression {
|
private val functional = DoubleField.expression {
|
||||||
val x = bindSymbol(Symbol.x)
|
val x = bindSymbol(Symbol.x)
|
||||||
x * number(2.0) + 2.0 / x - 16.0 / sin(x)
|
x * number(2.0) + 2.0 / x - 16.0 / sin(x)
|
||||||
}
|
}
|
||||||
@ -94,14 +93,13 @@ class ExpressionsInterpretersBenchmark {
|
|||||||
x * 2.0 + number(2.0) / x - number(16.0) / sin(x)
|
x * 2.0 + number(2.0) / x - number(16.0) / sin(x)
|
||||||
}
|
}
|
||||||
|
|
||||||
private val mst = node.toExpression(Float64Field)
|
private val mst = node.toExpression(DoubleField)
|
||||||
|
|
||||||
@OptIn(UnstableKMathAPI::class)
|
@OptIn(UnstableKMathAPI::class)
|
||||||
private val wasm = node.wasmCompileToExpression(Float64Field)
|
private val wasm = node.wasmCompileToExpression(DoubleField)
|
||||||
private val estree = node.estreeCompileToExpression(Float64Field)
|
private val estree = node.estreeCompileToExpression(DoubleField)
|
||||||
|
|
||||||
private val raw = Expression<Float64> { args ->
|
private val raw = Expression<Double> { args ->
|
||||||
val x = args.getValue(x)
|
val x = args[x]!!
|
||||||
x * 2.0 + 2.0 / x - 16.0 / sin(x)
|
x * 2.0 + 2.0 / x - 16.0 / sin(x)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2018-2024 KMath contributors.
|
* Copyright 2018-2022 KMath contributors.
|
||||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2018-2024 KMath contributors.
|
* Copyright 2018-2022 KMath contributors.
|
||||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@ -67,7 +67,7 @@ internal class BigIntBenchmark {
|
|||||||
|
|
||||||
@Benchmark
|
@Benchmark
|
||||||
fun kmMultiplyLarge(blackhole: Blackhole) = BigIntField {
|
fun kmMultiplyLarge(blackhole: Blackhole) = BigIntField {
|
||||||
blackhole.consume(kmLargeNumber * kmLargeNumber)
|
blackhole.consume(kmLargeNumber*kmLargeNumber)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Benchmark
|
@Benchmark
|
||||||
@ -77,7 +77,7 @@ internal class BigIntBenchmark {
|
|||||||
|
|
||||||
@Benchmark
|
@Benchmark
|
||||||
fun jvmMultiplyLarge(blackhole: Blackhole) = JBigIntegerField {
|
fun jvmMultiplyLarge(blackhole: Blackhole) = JBigIntegerField {
|
||||||
blackhole.consume(jvmLargeNumber * jvmLargeNumber)
|
blackhole.consume(jvmLargeNumber*jvmLargeNumber)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Benchmark
|
@Benchmark
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2018-2024 KMath contributors.
|
* Copyright 2018-2022 KMath contributors.
|
||||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@ -14,7 +14,7 @@ import space.kscience.kmath.complex.ComplexField
|
|||||||
import space.kscience.kmath.complex.complex
|
import space.kscience.kmath.complex.complex
|
||||||
import space.kscience.kmath.operations.invoke
|
import space.kscience.kmath.operations.invoke
|
||||||
import space.kscience.kmath.structures.Buffer
|
import space.kscience.kmath.structures.Buffer
|
||||||
import space.kscience.kmath.structures.Float64Buffer
|
import space.kscience.kmath.structures.DoubleBuffer
|
||||||
import space.kscience.kmath.structures.getDouble
|
import space.kscience.kmath.structures.getDouble
|
||||||
import space.kscience.kmath.structures.permute
|
import space.kscience.kmath.structures.permute
|
||||||
|
|
||||||
@ -33,7 +33,7 @@ internal class BufferBenchmark {
|
|||||||
|
|
||||||
@Benchmark
|
@Benchmark
|
||||||
fun doubleBufferReadWrite(blackhole: Blackhole) {
|
fun doubleBufferReadWrite(blackhole: Blackhole) {
|
||||||
val buffer = Float64Buffer(size) { it.toDouble() }
|
val buffer = DoubleBuffer(size) { it.toDouble() }
|
||||||
var res = 0.0
|
var res = 0.0
|
||||||
(0 until size).forEach {
|
(0 until size).forEach {
|
||||||
res += buffer[it]
|
res += buffer[it]
|
||||||
@ -43,7 +43,7 @@ internal class BufferBenchmark {
|
|||||||
|
|
||||||
@Benchmark
|
@Benchmark
|
||||||
fun bufferViewReadWrite(blackhole: Blackhole) {
|
fun bufferViewReadWrite(blackhole: Blackhole) {
|
||||||
val buffer = Float64Buffer(size) { it.toDouble() }.permute(reversedIndices)
|
val buffer = DoubleBuffer(size) { it.toDouble() }.permute(reversedIndices)
|
||||||
var res = 0.0
|
var res = 0.0
|
||||||
(0 until size).forEach {
|
(0 until size).forEach {
|
||||||
res += buffer[it]
|
res += buffer[it]
|
||||||
@ -53,7 +53,7 @@ internal class BufferBenchmark {
|
|||||||
|
|
||||||
@Benchmark
|
@Benchmark
|
||||||
fun bufferViewReadWriteSpecialized(blackhole: Blackhole) {
|
fun bufferViewReadWriteSpecialized(blackhole: Blackhole) {
|
||||||
val buffer = Float64Buffer(size) { it.toDouble() }.permute(reversedIndices)
|
val buffer = DoubleBuffer(size) { it.toDouble() }.permute(reversedIndices)
|
||||||
var res = 0.0
|
var res = 0.0
|
||||||
(0 until size).forEach {
|
(0 until size).forEach {
|
||||||
res += buffer.getDouble(it)
|
res += buffer.getDouble(it)
|
||||||
@ -75,6 +75,6 @@ internal class BufferBenchmark {
|
|||||||
|
|
||||||
private companion object {
|
private companion object {
|
||||||
private const val size = 100
|
private const val size = 100
|
||||||
private val reversedIndices = IntArray(size) { it }.apply { reverse() }
|
private val reversedIndices = IntArray(size){it}.apply { reverse() }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2018-2024 KMath contributors.
|
* Copyright 2018-2022 KMath contributors.
|
||||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@ -11,11 +11,12 @@ import kotlinx.benchmark.Scope
|
|||||||
import kotlinx.benchmark.State
|
import kotlinx.benchmark.State
|
||||||
import space.kscience.kmath.commons.linear.CMLinearSpace
|
import space.kscience.kmath.commons.linear.CMLinearSpace
|
||||||
import space.kscience.kmath.ejml.EjmlLinearSpaceDDRM
|
import space.kscience.kmath.ejml.EjmlLinearSpaceDDRM
|
||||||
import space.kscience.kmath.linear.Float64ParallelLinearSpace
|
|
||||||
import space.kscience.kmath.linear.invoke
|
import space.kscience.kmath.linear.invoke
|
||||||
import space.kscience.kmath.linear.linearSpace
|
import space.kscience.kmath.linear.linearSpace
|
||||||
import space.kscience.kmath.operations.Float64Field
|
import space.kscience.kmath.operations.DoubleField
|
||||||
|
import space.kscience.kmath.operations.invoke
|
||||||
import space.kscience.kmath.tensorflow.produceWithTF
|
import space.kscience.kmath.tensorflow.produceWithTF
|
||||||
|
import space.kscience.kmath.tensors.core.DoubleTensorAlgebra
|
||||||
import space.kscience.kmath.tensors.core.tensorAlgebra
|
import space.kscience.kmath.tensors.core.tensorAlgebra
|
||||||
import kotlin.random.Random
|
import kotlin.random.Random
|
||||||
|
|
||||||
@ -26,10 +27,10 @@ internal class DotBenchmark {
|
|||||||
const val dim = 1000
|
const val dim = 1000
|
||||||
|
|
||||||
//creating invertible matrix
|
//creating invertible matrix
|
||||||
val matrix1 = Float64Field.linearSpace.buildMatrix(dim, dim) { _, _ ->
|
val matrix1 = DoubleField.linearSpace.buildMatrix(dim, dim) { _, _ ->
|
||||||
random.nextDouble()
|
random.nextDouble()
|
||||||
}
|
}
|
||||||
val matrix2 = Float64Field.linearSpace.buildMatrix(dim, dim) { _, _ ->
|
val matrix2 = DoubleField.linearSpace.buildMatrix(dim, dim) { _, _ ->
|
||||||
random.nextDouble()
|
random.nextDouble()
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -44,7 +45,7 @@ internal class DotBenchmark {
|
|||||||
@Benchmark
|
@Benchmark
|
||||||
fun tfDot(blackhole: Blackhole) {
|
fun tfDot(blackhole: Blackhole) {
|
||||||
blackhole.consume(
|
blackhole.consume(
|
||||||
Float64Field.produceWithTF {
|
DoubleField.produceWithTF {
|
||||||
matrix1 dot matrix1
|
matrix1 dot matrix1
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
@ -70,24 +71,28 @@ internal class DotBenchmark {
|
|||||||
blackhole.consume(matrix1 dot matrix2)
|
blackhole.consume(matrix1 dot matrix2)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Benchmark
|
||||||
|
fun tensorDot(blackhole: Blackhole) = with(DoubleField.tensorAlgebra) {
|
||||||
|
blackhole.consume(matrix1 dot matrix2)
|
||||||
|
}
|
||||||
|
|
||||||
@Benchmark
|
@Benchmark
|
||||||
fun multikDot(blackhole: Blackhole) = with(multikAlgebra) {
|
fun multikDot(blackhole: Blackhole) = with(multikAlgebra) {
|
||||||
blackhole.consume(matrix1 dot matrix2)
|
blackhole.consume(matrix1 dot matrix2)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Benchmark
|
@Benchmark
|
||||||
fun tensorDot(blackhole: Blackhole) = with(Float64Field.tensorAlgebra) {
|
fun bufferedDot(blackhole: Blackhole) = with(DoubleField.linearSpace) {
|
||||||
blackhole.consume(matrix1 dot matrix2)
|
blackhole.consume(matrix1 dot matrix2)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Benchmark
|
@Benchmark
|
||||||
fun bufferedDot(blackhole: Blackhole) = with(Float64Field.linearSpace) {
|
fun doubleDot(blackhole: Blackhole) = with(DoubleField.linearSpace) {
|
||||||
blackhole.consume(matrix1 dot matrix2)
|
blackhole.consume(matrix1 dot matrix2)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Benchmark
|
@Benchmark
|
||||||
fun parallelDot(blackhole: Blackhole) = with(Float64ParallelLinearSpace) {
|
fun doubleTensorDot(blackhole: Blackhole) = DoubleTensorAlgebra.invoke {
|
||||||
blackhole.consume(matrix1 dot matrix2)
|
blackhole.consume(matrix1 dot matrix2)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2018-2024 KMath contributors.
|
* Copyright 2018-2022 KMath contributors.
|
||||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@ -12,10 +12,9 @@ import kotlinx.benchmark.State
|
|||||||
import space.kscience.kmath.asm.compileToExpression
|
import space.kscience.kmath.asm.compileToExpression
|
||||||
import space.kscience.kmath.expressions.*
|
import space.kscience.kmath.expressions.*
|
||||||
import space.kscience.kmath.operations.Algebra
|
import space.kscience.kmath.operations.Algebra
|
||||||
import space.kscience.kmath.operations.Float64Field
|
import space.kscience.kmath.operations.DoubleField
|
||||||
import space.kscience.kmath.operations.bindSymbol
|
import space.kscience.kmath.operations.bindSymbol
|
||||||
import space.kscience.kmath.operations.invoke
|
import space.kscience.kmath.operations.invoke
|
||||||
import space.kscience.kmath.structures.Float64
|
|
||||||
import kotlin.math.sin
|
import kotlin.math.sin
|
||||||
import kotlin.random.Random
|
import kotlin.random.Random
|
||||||
|
|
||||||
@ -84,7 +83,7 @@ internal class ExpressionsInterpretersBenchmark {
|
|||||||
blackhole.consume(sum)
|
blackhole.consume(sum)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun invokeAndSum(expr: Expression<Float64>, blackhole: Blackhole) {
|
private fun invokeAndSum(expr: Expression<Double>, blackhole: Blackhole) {
|
||||||
val random = Random(0)
|
val random = Random(0)
|
||||||
var sum = 0.0
|
var sum = 0.0
|
||||||
val m = HashMap<Symbol, Double>()
|
val m = HashMap<Symbol, Double>()
|
||||||
@ -101,7 +100,7 @@ internal class ExpressionsInterpretersBenchmark {
|
|||||||
private val x by symbol
|
private val x by symbol
|
||||||
private const val times = 1_000_000
|
private const val times = 1_000_000
|
||||||
|
|
||||||
private val functional = Float64Field.expression {
|
private val functional = DoubleField.expression {
|
||||||
val x = bindSymbol(Symbol.x)
|
val x = bindSymbol(Symbol.x)
|
||||||
x * number(2.0) + 2.0 / x - 16.0 / sin(x)
|
x * number(2.0) + 2.0 / x - 16.0 / sin(x)
|
||||||
}
|
}
|
||||||
@ -110,14 +109,14 @@ internal class ExpressionsInterpretersBenchmark {
|
|||||||
x * 2.0 + number(2.0) / x - number(16.0) / sin(x)
|
x * 2.0 + number(2.0) / x - number(16.0) / sin(x)
|
||||||
}
|
}
|
||||||
|
|
||||||
private val mst = node.toExpression(Float64Field)
|
private val mst = node.toExpression(DoubleField)
|
||||||
|
|
||||||
private val asmPrimitive = node.compileToExpression(Float64Field)
|
private val asmPrimitive = node.compileToExpression(DoubleField)
|
||||||
private val xIdx = asmPrimitive.indexer.indexOf(x)
|
private val xIdx = asmPrimitive.indexer.indexOf(x)
|
||||||
|
|
||||||
private val asmGeneric = node.compileToExpression(Float64Field as Algebra<Float64>)
|
private val asmGeneric = node.compileToExpression(DoubleField as Algebra<Double>)
|
||||||
|
|
||||||
private val raw = Expression<Float64> { args ->
|
private val raw = Expression<Double> { args ->
|
||||||
val x = args[x]!!
|
val x = args[x]!!
|
||||||
x * 2.0 + 2.0 / x - 16.0 / sin(x)
|
x * 2.0 + 2.0 / x - 16.0 / sin(x)
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2018-2024 KMath contributors.
|
* Copyright 2018-2023 KMath contributors.
|
||||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@ -24,7 +24,7 @@ internal class IntegrationBenchmark {
|
|||||||
fun doubleIntegration(blackhole: Blackhole) {
|
fun doubleIntegration(blackhole: Blackhole) {
|
||||||
val res = Double.algebra.gaussIntegrator.integrate(0.0..1.0, intervals = 1000) { x: Double ->
|
val res = Double.algebra.gaussIntegrator.integrate(0.0..1.0, intervals = 1000) { x: Double ->
|
||||||
//sin(1 / x)
|
//sin(1 / x)
|
||||||
1 / x
|
1/x
|
||||||
}.value
|
}.value
|
||||||
blackhole.consume(res)
|
blackhole.consume(res)
|
||||||
}
|
}
|
||||||
@ -33,7 +33,7 @@ internal class IntegrationBenchmark {
|
|||||||
fun complexIntegration(blackhole: Blackhole) = with(Complex.algebra) {
|
fun complexIntegration(blackhole: Blackhole) = with(Complex.algebra) {
|
||||||
val res = gaussIntegrator.integrate(0.0..1.0, intervals = 1000) { x: Double ->
|
val res = gaussIntegrator.integrate(0.0..1.0, intervals = 1000) { x: Double ->
|
||||||
// sin(1 / x) + i * cos(1 / x)
|
// sin(1 / x) + i * cos(1 / x)
|
||||||
1 / x - i / x
|
1/x - i/x
|
||||||
}.value
|
}.value
|
||||||
blackhole.consume(res)
|
blackhole.consume(res)
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2018-2024 KMath contributors.
|
* Copyright 2018-2022 KMath contributors.
|
||||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@ -11,8 +11,10 @@ import org.openjdk.jmh.annotations.Scope
|
|||||||
import org.openjdk.jmh.annotations.State
|
import org.openjdk.jmh.annotations.State
|
||||||
import space.kscience.kmath.jafama.JafamaDoubleField
|
import space.kscience.kmath.jafama.JafamaDoubleField
|
||||||
import space.kscience.kmath.jafama.StrictJafamaDoubleField
|
import space.kscience.kmath.jafama.StrictJafamaDoubleField
|
||||||
import space.kscience.kmath.operations.Float64Field
|
import space.kscience.kmath.operations.DoubleField
|
||||||
import space.kscience.kmath.operations.invoke
|
import space.kscience.kmath.operations.invoke
|
||||||
|
import kotlin.contracts.InvocationKind
|
||||||
|
import kotlin.contracts.contract
|
||||||
import kotlin.random.Random
|
import kotlin.random.Random
|
||||||
|
|
||||||
@State(Scope.Benchmark)
|
@State(Scope.Benchmark)
|
||||||
@ -24,7 +26,7 @@ internal class JafamaBenchmark {
|
|||||||
|
|
||||||
@Benchmark
|
@Benchmark
|
||||||
fun core(blackhole: Blackhole) = invokeBenchmarks(blackhole) { x ->
|
fun core(blackhole: Blackhole) = invokeBenchmarks(blackhole) { x ->
|
||||||
Float64Field { x * power(x, 4) * exp(x) / cos(x) + sin(x) }
|
DoubleField { x * power(x, 4) * exp(x) / cos(x) + sin(x) }
|
||||||
}
|
}
|
||||||
|
|
||||||
@Benchmark
|
@Benchmark
|
||||||
@ -34,6 +36,7 @@ internal class JafamaBenchmark {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private inline fun invokeBenchmarks(blackhole: Blackhole, expr: (Double) -> Double) {
|
private inline fun invokeBenchmarks(blackhole: Blackhole, expr: (Double) -> Double) {
|
||||||
|
contract { callsInPlace(expr, InvocationKind.AT_LEAST_ONCE) }
|
||||||
val rng = Random(0)
|
val rng = Random(0)
|
||||||
repeat(1000000) { blackhole.consume(expr(rng.nextDouble())) }
|
repeat(1000000) { blackhole.consume(expr(rng.nextDouble())) }
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2018-2024 KMath contributors.
|
* Copyright 2018-2022 KMath contributors.
|
||||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@ -15,7 +15,6 @@ import space.kscience.kmath.ejml.EjmlLinearSpaceDDRM
|
|||||||
import space.kscience.kmath.linear.invoke
|
import space.kscience.kmath.linear.invoke
|
||||||
import space.kscience.kmath.linear.linearSpace
|
import space.kscience.kmath.linear.linearSpace
|
||||||
import space.kscience.kmath.linear.lupSolver
|
import space.kscience.kmath.linear.lupSolver
|
||||||
import space.kscience.kmath.linear.parallel
|
|
||||||
import space.kscience.kmath.operations.algebra
|
import space.kscience.kmath.operations.algebra
|
||||||
import kotlin.random.Random
|
import kotlin.random.Random
|
||||||
|
|
||||||
@ -39,19 +38,16 @@ internal class MatrixInverseBenchmark {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Benchmark
|
@Benchmark
|
||||||
fun kmathParallelLupInversion(blackhole: Blackhole) {
|
fun cmLUPInversion(blackhole: Blackhole) {
|
||||||
blackhole.consume(Double.algebra.linearSpace.parallel.lupSolver().inverse(matrix))
|
CMLinearSpace {
|
||||||
|
blackhole.consume(lupSolver().inverse(matrix))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Benchmark
|
@Benchmark
|
||||||
fun cmLUPInversion(blackhole: Blackhole) = CMLinearSpace {
|
fun ejmlInverse(blackhole: Blackhole) {
|
||||||
blackhole.consume(lupSolver().inverse(matrix))
|
EjmlLinearSpaceDDRM {
|
||||||
|
blackhole.consume(matrix.toEjml().inverse())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Benchmark
|
|
||||||
fun ejmlInverse(blackhole: Blackhole) = EjmlLinearSpaceDDRM {
|
|
||||||
blackhole.consume(matrix.toEjml().inverted())
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2018-2024 KMath contributors.
|
* Copyright 2018-2022 KMath contributors.
|
||||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@ -16,8 +16,7 @@ import org.jetbrains.kotlinx.multik.ndarray.data.DataType
|
|||||||
import space.kscience.kmath.UnsafeKMathAPI
|
import space.kscience.kmath.UnsafeKMathAPI
|
||||||
import space.kscience.kmath.nd.*
|
import space.kscience.kmath.nd.*
|
||||||
import space.kscience.kmath.nd4j.nd4j
|
import space.kscience.kmath.nd4j.nd4j
|
||||||
import space.kscience.kmath.operations.Float64Field
|
import space.kscience.kmath.operations.DoubleField
|
||||||
import space.kscience.kmath.structures.Float64
|
|
||||||
import space.kscience.kmath.tensors.core.DoubleTensor
|
import space.kscience.kmath.tensors.core.DoubleTensor
|
||||||
import space.kscience.kmath.tensors.core.one
|
import space.kscience.kmath.tensors.core.one
|
||||||
import space.kscience.kmath.tensors.core.tensorAlgebra
|
import space.kscience.kmath.tensors.core.tensorAlgebra
|
||||||
@ -26,40 +25,30 @@ import space.kscience.kmath.viktor.viktorAlgebra
|
|||||||
@State(Scope.Benchmark)
|
@State(Scope.Benchmark)
|
||||||
internal class NDFieldBenchmark {
|
internal class NDFieldBenchmark {
|
||||||
|
|
||||||
private companion object {
|
|
||||||
private const val dim = 1000
|
|
||||||
private const val n = 100
|
|
||||||
private val shape = ShapeND(dim, dim)
|
|
||||||
private val specializedField = Float64Field.ndAlgebra
|
|
||||||
private val genericField = BufferedFieldOpsND(Float64Field)
|
|
||||||
private val nd4jField = Float64Field.nd4j
|
|
||||||
private val viktorField = Float64Field.viktorAlgebra
|
|
||||||
}
|
|
||||||
|
|
||||||
@Benchmark
|
@Benchmark
|
||||||
fun specializedFieldAdd(blackhole: Blackhole) = with(specializedField) {
|
fun specializedFieldAdd(blackhole: Blackhole) = with(specializedField) {
|
||||||
var res: StructureND<Float64> = one(shape)
|
var res: StructureND<Double> = one(shape)
|
||||||
repeat(n) { res += 1.0 }
|
repeat(n) { res += 1.0 }
|
||||||
blackhole.consume(res)
|
blackhole.consume(res)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Benchmark
|
@Benchmark
|
||||||
fun boxingFieldAdd(blackhole: Blackhole) = with(genericField) {
|
fun boxingFieldAdd(blackhole: Blackhole) = with(genericField) {
|
||||||
var res: StructureND<Float64> = one(shape)
|
var res: StructureND<Double> = one(shape)
|
||||||
repeat(n) { res += 1.0 }
|
repeat(n) { res += 1.0 }
|
||||||
blackhole.consume(res)
|
blackhole.consume(res)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Benchmark
|
@Benchmark
|
||||||
fun multikAdd(blackhole: Blackhole) = with(multikAlgebra) {
|
fun multikAdd(blackhole: Blackhole) = with(multikAlgebra) {
|
||||||
var res: StructureND<Float64> = one(shape)
|
var res: StructureND<Double> = one(shape)
|
||||||
repeat(n) { res += 1.0 }
|
repeat(n) { res += 1.0 }
|
||||||
blackhole.consume(res)
|
blackhole.consume(res)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Benchmark
|
@Benchmark
|
||||||
fun viktorAdd(blackhole: Blackhole) = with(viktorField) {
|
fun viktorAdd(blackhole: Blackhole) = with(viktorField) {
|
||||||
var res: StructureND<Float64> = one(shape)
|
var res: StructureND<Double> = one(shape)
|
||||||
repeat(n) { res += 1.0 }
|
repeat(n) { res += 1.0 }
|
||||||
blackhole.consume(res)
|
blackhole.consume(res)
|
||||||
}
|
}
|
||||||
@ -88,10 +77,18 @@ internal class NDFieldBenchmark {
|
|||||||
|
|
||||||
// @Benchmark
|
// @Benchmark
|
||||||
// fun nd4jAdd(blackhole: Blackhole) = with(nd4jField) {
|
// fun nd4jAdd(blackhole: Blackhole) = with(nd4jField) {
|
||||||
// var res: StructureND<Float64> = one(dim, dim)
|
// var res: StructureND<Double> = one(dim, dim)
|
||||||
// repeat(n) { res += 1.0 }
|
// repeat(n) { res += 1.0 }
|
||||||
// blackhole.consume(res)
|
// blackhole.consume(res)
|
||||||
// }
|
// }
|
||||||
|
|
||||||
|
private companion object {
|
||||||
|
private const val dim = 1000
|
||||||
|
private const val n = 100
|
||||||
|
private val shape = ShapeND(dim, dim)
|
||||||
|
private val specializedField = DoubleField.ndAlgebra
|
||||||
|
private val genericField = BufferedFieldOpsND(DoubleField)
|
||||||
|
private val nd4jField = DoubleField.nd4j
|
||||||
|
private val viktorField = DoubleField.viktorAlgebra
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2018-2024 KMath contributors.
|
* Copyright 2018-2022 KMath contributors.
|
||||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@ -12,7 +12,7 @@ import kotlinx.benchmark.State
|
|||||||
import space.kscience.kmath.linear.linearSpace
|
import space.kscience.kmath.linear.linearSpace
|
||||||
import space.kscience.kmath.linear.matrix
|
import space.kscience.kmath.linear.matrix
|
||||||
import space.kscience.kmath.linear.symmetric
|
import space.kscience.kmath.linear.symmetric
|
||||||
import space.kscience.kmath.operations.Float64Field
|
import space.kscience.kmath.operations.DoubleField
|
||||||
import space.kscience.kmath.tensors.core.symEigJacobi
|
import space.kscience.kmath.tensors.core.symEigJacobi
|
||||||
import space.kscience.kmath.tensors.core.symEigSvd
|
import space.kscience.kmath.tensors.core.symEigSvd
|
||||||
import space.kscience.kmath.tensors.core.tensorAlgebra
|
import space.kscience.kmath.tensors.core.tensorAlgebra
|
||||||
@ -24,7 +24,7 @@ internal class TensorAlgebraBenchmark {
|
|||||||
private val random = Random(12224)
|
private val random = Random(12224)
|
||||||
private const val dim = 30
|
private const val dim = 30
|
||||||
|
|
||||||
private val matrix = Float64Field.linearSpace.matrix(dim, dim).symmetric { _, _ -> random.nextDouble() }
|
private val matrix = DoubleField.linearSpace.matrix(dim, dim).symmetric { _, _ -> random.nextDouble() }
|
||||||
}
|
}
|
||||||
|
|
||||||
@Benchmark
|
@Benchmark
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2018-2024 KMath contributors.
|
* Copyright 2018-2022 KMath contributors.
|
||||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@ -14,8 +14,7 @@ import space.kscience.kmath.nd.ShapeND
|
|||||||
import space.kscience.kmath.nd.StructureND
|
import space.kscience.kmath.nd.StructureND
|
||||||
import space.kscience.kmath.nd.ndAlgebra
|
import space.kscience.kmath.nd.ndAlgebra
|
||||||
import space.kscience.kmath.nd.one
|
import space.kscience.kmath.nd.one
|
||||||
import space.kscience.kmath.operations.Float64Field
|
import space.kscience.kmath.operations.DoubleField
|
||||||
import space.kscience.kmath.structures.Float64
|
|
||||||
import space.kscience.kmath.viktor.ViktorFieldND
|
import space.kscience.kmath.viktor.ViktorFieldND
|
||||||
|
|
||||||
@State(Scope.Benchmark)
|
@State(Scope.Benchmark)
|
||||||
@ -24,7 +23,7 @@ internal class ViktorBenchmark {
|
|||||||
@Benchmark
|
@Benchmark
|
||||||
fun doubleFieldAddition(blackhole: Blackhole) {
|
fun doubleFieldAddition(blackhole: Blackhole) {
|
||||||
with(doubleField) {
|
with(doubleField) {
|
||||||
var res: StructureND<Float64> = one(shape)
|
var res: StructureND<Double> = one(shape)
|
||||||
repeat(n) { res += 1.0 }
|
repeat(n) { res += 1.0 }
|
||||||
blackhole.consume(res)
|
blackhole.consume(res)
|
||||||
}
|
}
|
||||||
@ -53,7 +52,7 @@ internal class ViktorBenchmark {
|
|||||||
private val shape = ShapeND(dim, dim)
|
private val shape = ShapeND(dim, dim)
|
||||||
|
|
||||||
// automatically build context most suited for given type.
|
// automatically build context most suited for given type.
|
||||||
private val doubleField = Float64Field.ndAlgebra
|
private val doubleField = DoubleField.ndAlgebra
|
||||||
private val viktorField = ViktorFieldND(dim, dim)
|
private val viktorField = ViktorFieldND(dim, dim)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2018-2024 KMath contributors.
|
* Copyright 2018-2022 KMath contributors.
|
||||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@ -13,7 +13,7 @@ import org.jetbrains.bio.viktor.F64Array
|
|||||||
import space.kscience.kmath.nd.ShapeND
|
import space.kscience.kmath.nd.ShapeND
|
||||||
import space.kscience.kmath.nd.ndAlgebra
|
import space.kscience.kmath.nd.ndAlgebra
|
||||||
import space.kscience.kmath.nd.one
|
import space.kscience.kmath.nd.one
|
||||||
import space.kscience.kmath.operations.Float64Field
|
import space.kscience.kmath.operations.DoubleField
|
||||||
import space.kscience.kmath.viktor.ViktorFieldND
|
import space.kscience.kmath.viktor.ViktorFieldND
|
||||||
|
|
||||||
@State(Scope.Benchmark)
|
@State(Scope.Benchmark)
|
||||||
@ -52,7 +52,7 @@ internal class ViktorLogBenchmark {
|
|||||||
private val shape = ShapeND(dim, dim)
|
private val shape = ShapeND(dim, dim)
|
||||||
|
|
||||||
// automatically build context most suited for given type.
|
// automatically build context most suited for given type.
|
||||||
private val doubleField = Float64Field.ndAlgebra
|
private val doubleField = DoubleField.ndAlgebra
|
||||||
private val viktorField = ViktorFieldND(dim, dim)
|
private val viktorField = ViktorFieldND(dim, dim)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2018-2024 KMath contributors.
|
* Copyright 2018-2022 KMath contributors.
|
||||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
@ -1,13 +1,12 @@
|
|||||||
|
import space.kscience.gradle.isInDevelopment
|
||||||
import space.kscience.gradle.useApache2Licence
|
import space.kscience.gradle.useApache2Licence
|
||||||
import space.kscience.gradle.useSPCTeam
|
import space.kscience.gradle.useSPCTeam
|
||||||
|
|
||||||
plugins {
|
plugins {
|
||||||
alias(spclibs.plugins.kscience.project)
|
id("space.kscience.gradle.project")
|
||||||
alias(spclibs.plugins.kotlinx.kover)
|
id("org.jetbrains.kotlinx.kover") version "0.6.0"
|
||||||
}
|
}
|
||||||
|
|
||||||
val attributesVersion by extra("0.2.0")
|
|
||||||
|
|
||||||
allprojects {
|
allprojects {
|
||||||
repositories {
|
repositories {
|
||||||
maven("https://repo.kotlin.link")
|
maven("https://repo.kotlin.link")
|
||||||
@ -16,7 +15,7 @@ allprojects {
|
|||||||
}
|
}
|
||||||
|
|
||||||
group = "space.kscience"
|
group = "space.kscience"
|
||||||
version = "0.4.1-dev"
|
version = "0.3.1"
|
||||||
}
|
}
|
||||||
|
|
||||||
subprojects {
|
subprojects {
|
||||||
@ -36,7 +35,7 @@ subprojects {
|
|||||||
localDirectory.set(kotlinDir)
|
localDirectory.set(kotlinDir)
|
||||||
|
|
||||||
remoteUrl.set(
|
remoteUrl.set(
|
||||||
uri("https://github.com/SciProgCentre/kmath/tree/master/${this@subprojects.name}/$kotlinDirPath").toURL()
|
java.net.URL("https://github.com/SciProgCentre/kmath/tree/master/${this@subprojects.name}/$kotlinDirPath")
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -65,8 +64,17 @@ ksciencePublish {
|
|||||||
useApache2Licence()
|
useApache2Licence()
|
||||||
useSPCTeam()
|
useSPCTeam()
|
||||||
}
|
}
|
||||||
repository("spc", "https://maven.sciprog.center/kscience")
|
github("kmath", "SciProgCentre")
|
||||||
|
space(
|
||||||
|
if (isInDevelopment) {
|
||||||
|
"https://maven.pkg.jetbrains.space/spc/p/sci/dev"
|
||||||
|
} else {
|
||||||
|
"https://maven.pkg.jetbrains.space/spc/p/sci/maven"
|
||||||
|
}
|
||||||
|
)
|
||||||
sonatype("https://oss.sonatype.org")
|
sonatype("https://oss.sonatype.org")
|
||||||
}
|
}
|
||||||
|
|
||||||
apiValidation.nonPublicMarkers.add("space.kscience.kmath.UnstableKMathAPI")
|
apiValidation.nonPublicMarkers.add("space.kscience.kmath.UnstableKMathAPI")
|
||||||
|
|
||||||
|
val multikVersion by extra("0.2.0")
|
||||||
|
34
buildSrc/build.gradle.kts
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
plugins {
|
||||||
|
`kotlin-dsl`
|
||||||
|
`version-catalog`
|
||||||
|
}
|
||||||
|
|
||||||
|
repositories {
|
||||||
|
mavenLocal()
|
||||||
|
maven("https://repo.kotlin.link")
|
||||||
|
mavenCentral()
|
||||||
|
gradlePluginPortal()
|
||||||
|
}
|
||||||
|
|
||||||
|
val toolsVersion = spclibs.versions.tools.get()
|
||||||
|
val kotlinVersion = spclibs.versions.kotlin.asProvider().get()
|
||||||
|
val benchmarksVersion = spclibs.versions.kotlinx.benchmark.get()
|
||||||
|
|
||||||
|
dependencies {
|
||||||
|
api("space.kscience:gradle-tools:$toolsVersion")
|
||||||
|
//plugins form benchmarks
|
||||||
|
api("org.jetbrains.kotlinx:kotlinx-benchmark-plugin:0.4.7")
|
||||||
|
//api("org.jetbrains.kotlin:kotlin-allopen:$kotlinVersion")
|
||||||
|
//to be used inside build-script only
|
||||||
|
//implementation(spclibs.kotlinx.serialization.json)
|
||||||
|
implementation("com.fasterxml.jackson.module:jackson-module-kotlin:2.14.+")
|
||||||
|
}
|
||||||
|
|
||||||
|
kotlin{
|
||||||
|
jvmToolchain{
|
||||||
|
languageVersion.set(JavaLanguageVersion.of(11))
|
||||||
|
}
|
||||||
|
sourceSets.all {
|
||||||
|
languageSettings.optIn("kotlin.OptIn")
|
||||||
|
}
|
||||||
|
}
|
34
buildSrc/settings.gradle.kts
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2018-2021 KMath contributors.
|
||||||
|
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||||
|
*/
|
||||||
|
rootProject.name = "kmath"
|
||||||
|
|
||||||
|
enableFeaturePreview("TYPESAFE_PROJECT_ACCESSORS")
|
||||||
|
|
||||||
|
dependencyResolutionManagement {
|
||||||
|
val projectProperties = java.util.Properties()
|
||||||
|
file("../gradle.properties").inputStream().use {
|
||||||
|
projectProperties.load(it)
|
||||||
|
}
|
||||||
|
|
||||||
|
projectProperties.forEach { key, value ->
|
||||||
|
extra.set(key.toString(), value)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
val toolsVersion: String = projectProperties["toolsVersion"].toString()
|
||||||
|
|
||||||
|
repositories {
|
||||||
|
mavenLocal()
|
||||||
|
maven("https://repo.kotlin.link")
|
||||||
|
mavenCentral()
|
||||||
|
gradlePluginPortal()
|
||||||
|
}
|
||||||
|
|
||||||
|
versionCatalogs {
|
||||||
|
create("spclibs") {
|
||||||
|
from("space.kscience:version-catalog:$toolsVersion")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,55 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2018-2022 KMath contributors.
|
||||||
|
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package space.kscience.kmath.benchmarks
|
||||||
|
|
||||||
|
data class JmhReport(
|
||||||
|
val jmhVersion: String,
|
||||||
|
val benchmark: String,
|
||||||
|
val mode: String,
|
||||||
|
val threads: Int,
|
||||||
|
val forks: Int,
|
||||||
|
val jvm: String,
|
||||||
|
val jvmArgs: List<String>,
|
||||||
|
val jdkVersion: String,
|
||||||
|
val vmName: String,
|
||||||
|
val vmVersion: String,
|
||||||
|
val warmupIterations: Int,
|
||||||
|
val warmupTime: String,
|
||||||
|
val warmupBatchSize: Int,
|
||||||
|
val measurementIterations: Int,
|
||||||
|
val measurementTime: String,
|
||||||
|
val measurementBatchSize: Int,
|
||||||
|
val params: Map<String, String> = emptyMap(),
|
||||||
|
val primaryMetric: PrimaryMetric,
|
||||||
|
val secondaryMetrics: Map<String, SecondaryMetric>,
|
||||||
|
) {
|
||||||
|
interface Metric {
|
||||||
|
val score: Double
|
||||||
|
val scoreError: Double
|
||||||
|
val scoreConfidence: List<Double>
|
||||||
|
val scorePercentiles: Map<Double, Double>
|
||||||
|
val scoreUnit: String
|
||||||
|
}
|
||||||
|
|
||||||
|
data class PrimaryMetric(
|
||||||
|
override val score: Double,
|
||||||
|
override val scoreError: Double,
|
||||||
|
override val scoreConfidence: List<Double>,
|
||||||
|
override val scorePercentiles: Map<Double, Double>,
|
||||||
|
override val scoreUnit: String,
|
||||||
|
val rawDataHistogram: List<List<List<List<Double>>>>? = null,
|
||||||
|
val rawData: List<List<Double>>? = null,
|
||||||
|
) : Metric
|
||||||
|
|
||||||
|
data class SecondaryMetric(
|
||||||
|
override val score: Double,
|
||||||
|
override val scoreError: Double,
|
||||||
|
override val scoreConfidence: List<Double>,
|
||||||
|
override val scorePercentiles: Map<Double, Double>,
|
||||||
|
override val scoreUnit: String,
|
||||||
|
val rawData: List<List<Double>>,
|
||||||
|
) : Metric
|
||||||
|
}
|
@ -0,0 +1,105 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2018-2022 KMath contributors.
|
||||||
|
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package space.kscience.kmath.benchmarks
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.module.kotlin.jacksonObjectMapper
|
||||||
|
import com.fasterxml.jackson.module.kotlin.readValue
|
||||||
|
import kotlinx.benchmark.gradle.BenchmarksExtension
|
||||||
|
import org.gradle.api.Project
|
||||||
|
import space.kscience.gradle.KScienceReadmeExtension
|
||||||
|
import java.time.LocalDateTime
|
||||||
|
import java.time.ZoneId
|
||||||
|
import java.time.format.DateTimeFormatter
|
||||||
|
import java.time.format.DateTimeFormatterBuilder
|
||||||
|
import java.time.format.SignStyle
|
||||||
|
import java.time.temporal.ChronoField.*
|
||||||
|
import java.util.*
|
||||||
|
|
||||||
|
private val ISO_DATE_TIME: DateTimeFormatter = DateTimeFormatterBuilder().run {
|
||||||
|
parseCaseInsensitive()
|
||||||
|
appendValue(YEAR, 4, 10, SignStyle.EXCEEDS_PAD)
|
||||||
|
appendLiteral('-')
|
||||||
|
appendValue(MONTH_OF_YEAR, 2)
|
||||||
|
appendLiteral('-')
|
||||||
|
appendValue(DAY_OF_MONTH, 2)
|
||||||
|
appendLiteral('T')
|
||||||
|
appendValue(HOUR_OF_DAY, 2)
|
||||||
|
appendLiteral('.')
|
||||||
|
appendValue(MINUTE_OF_HOUR, 2)
|
||||||
|
optionalStart()
|
||||||
|
appendLiteral('.')
|
||||||
|
appendValue(SECOND_OF_MINUTE, 2)
|
||||||
|
optionalStart()
|
||||||
|
appendFraction(NANO_OF_SECOND, 0, 9, true)
|
||||||
|
optionalStart()
|
||||||
|
appendOffsetId()
|
||||||
|
optionalStart()
|
||||||
|
appendLiteral('[')
|
||||||
|
parseCaseSensitive()
|
||||||
|
appendZoneRegionId()
|
||||||
|
appendLiteral(']')
|
||||||
|
toFormatter()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun noun(number: Number, singular: String, plural: String) = if (number.toLong() == 1L) singular else plural
|
||||||
|
|
||||||
|
private val jsonMapper = jacksonObjectMapper()
|
||||||
|
|
||||||
|
fun Project.addBenchmarkProperties() {
|
||||||
|
val benchmarksProject = this
|
||||||
|
rootProject.subprojects.forEach { p ->
|
||||||
|
p.extensions.findByType(KScienceReadmeExtension::class.java)?.run {
|
||||||
|
benchmarksProject.extensions.findByType(BenchmarksExtension::class.java)?.configurations?.forEach { cfg ->
|
||||||
|
property("benchmark${cfg.name.replaceFirstChar { if (it.isLowerCase()) it.titlecase(Locale.getDefault()) else it.toString() }}") {
|
||||||
|
val launches = benchmarksProject.buildDir.resolve("reports/benchmarks/${cfg.name}")
|
||||||
|
|
||||||
|
val resDirectory = launches.listFiles()?.maxByOrNull {
|
||||||
|
LocalDateTime.parse(it.name, ISO_DATE_TIME).atZone(ZoneId.systemDefault()).toInstant()
|
||||||
|
}
|
||||||
|
|
||||||
|
if (resDirectory == null || !(resDirectory.resolve("jvm.json")).exists()) {
|
||||||
|
"> **Can't find appropriate benchmark data. Try generating readme files after running benchmarks**."
|
||||||
|
} else {
|
||||||
|
val reports: List<JmhReport> = jsonMapper.readValue<List<JmhReport>>(resDirectory.resolve("jvm.json"))
|
||||||
|
|
||||||
|
buildString {
|
||||||
|
appendLine("<details>")
|
||||||
|
appendLine("<summary>")
|
||||||
|
appendLine("Report for benchmark configuration <code>${cfg.name}</code>")
|
||||||
|
appendLine("</summary>")
|
||||||
|
appendLine()
|
||||||
|
val first = reports.first()
|
||||||
|
|
||||||
|
appendLine("* Run on ${first.vmName} (build ${first.vmVersion}) with Java process:")
|
||||||
|
appendLine()
|
||||||
|
appendLine("```")
|
||||||
|
appendLine("${first.jvm} ${
|
||||||
|
first.jvmArgs.joinToString(" ")
|
||||||
|
}")
|
||||||
|
appendLine("```")
|
||||||
|
|
||||||
|
appendLine("* JMH ${first.jmhVersion} was used in `${first.mode}` mode with ${first.warmupIterations} warmup ${
|
||||||
|
noun(first.warmupIterations, "iteration", "iterations")
|
||||||
|
} by ${first.warmupTime} and ${first.measurementIterations} measurement ${
|
||||||
|
noun(first.measurementIterations, "iteration", "iterations")
|
||||||
|
} by ${first.measurementTime}.")
|
||||||
|
|
||||||
|
appendLine()
|
||||||
|
appendLine("| Benchmark | Score |")
|
||||||
|
appendLine("|:---------:|:-----:|")
|
||||||
|
|
||||||
|
reports.forEach { report ->
|
||||||
|
appendLine("|`${report.benchmark}`|${report.primaryMetric.score} ± ${report.primaryMetric.scoreError} ${report.primaryMetric.scoreUnit}|")
|
||||||
|
}
|
||||||
|
|
||||||
|
appendLine("</details>")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,427 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2018-2022 KMath contributors.
|
||||||
|
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
@file:Suppress("KDocUnresolvedReference")
|
||||||
|
|
||||||
|
package space.kscience.kmath.ejml.codegen
|
||||||
|
|
||||||
|
import org.intellij.lang.annotations.Language
|
||||||
|
import java.io.File
|
||||||
|
|
||||||
|
private fun Appendable.appendEjmlVector(type: String, ejmlMatrixType: String) {
|
||||||
|
@Language("kotlin") val text = """/**
|
||||||
|
* [EjmlVector] specialization for [$type].
|
||||||
|
*/
|
||||||
|
public class Ejml${type}Vector<out M : $ejmlMatrixType>(override val origin: M) : EjmlVector<$type, M>(origin) {
|
||||||
|
init {
|
||||||
|
require(origin.numRows == 1) { "The origin matrix must have only one row to form a vector" }
|
||||||
|
}
|
||||||
|
|
||||||
|
override operator fun get(index: Int): $type = origin[0, index]
|
||||||
|
}"""
|
||||||
|
appendLine(text)
|
||||||
|
appendLine()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun Appendable.appendEjmlMatrix(type: String, ejmlMatrixType: String) {
|
||||||
|
val text = """/**
|
||||||
|
* [EjmlMatrix] specialization for [$type].
|
||||||
|
*/
|
||||||
|
public class Ejml${type}Matrix<out M : $ejmlMatrixType>(override val origin: M) : EjmlMatrix<$type, M>(origin) {
|
||||||
|
override operator fun get(i: Int, j: Int): $type = origin[i, j]
|
||||||
|
}"""
|
||||||
|
appendLine(text)
|
||||||
|
appendLine()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun Appendable.appendEjmlLinearSpace(
|
||||||
|
type: String,
|
||||||
|
kmathAlgebra: String,
|
||||||
|
ejmlMatrixParentTypeMatrix: String,
|
||||||
|
ejmlMatrixType: String,
|
||||||
|
ejmlMatrixDenseType: String,
|
||||||
|
ops: String,
|
||||||
|
denseOps: String,
|
||||||
|
isDense: Boolean,
|
||||||
|
) {
|
||||||
|
@Language("kotlin") val text = """/**
|
||||||
|
* [EjmlLinearSpace] implementation based on [CommonOps_$ops], [DecompositionFactory_${ops}] operations and
|
||||||
|
* [${ejmlMatrixType}] matrices.
|
||||||
|
*/
|
||||||
|
public object EjmlLinearSpace${ops} : EjmlLinearSpace<${type}, ${kmathAlgebra}, $ejmlMatrixType>() {
|
||||||
|
/**
|
||||||
|
* The [${kmathAlgebra}] reference.
|
||||||
|
*/
|
||||||
|
override val elementAlgebra: $kmathAlgebra get() = $kmathAlgebra
|
||||||
|
|
||||||
|
@Suppress("UNCHECKED_CAST")
|
||||||
|
override fun Matrix<${type}>.toEjml(): Ejml${type}Matrix<${ejmlMatrixType}> = when {
|
||||||
|
this is Ejml${type}Matrix<*> && origin is $ejmlMatrixType -> this as Ejml${type}Matrix<${ejmlMatrixType}>
|
||||||
|
else -> buildMatrix(rowNum, colNum) { i, j -> get(i, j) }
|
||||||
|
}
|
||||||
|
|
||||||
|
@Suppress("UNCHECKED_CAST")
|
||||||
|
override fun Point<${type}>.toEjml(): Ejml${type}Vector<${ejmlMatrixType}> = when {
|
||||||
|
this is Ejml${type}Vector<*> && origin is $ejmlMatrixType -> this as Ejml${type}Vector<${ejmlMatrixType}>
|
||||||
|
else -> Ejml${type}Vector(${ejmlMatrixType}(size, 1).also {
|
||||||
|
(0 until it.numRows).forEach { row -> it[row, 0] = get(row) }
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun buildMatrix(
|
||||||
|
rows: Int,
|
||||||
|
columns: Int,
|
||||||
|
initializer: ${kmathAlgebra}.(i: Int, j: Int) -> ${type},
|
||||||
|
): Ejml${type}Matrix<${ejmlMatrixType}> = ${ejmlMatrixType}(rows, columns).also {
|
||||||
|
(0 until rows).forEach { row ->
|
||||||
|
(0 until columns).forEach { col -> it[row, col] = elementAlgebra.initializer(row, col) }
|
||||||
|
}
|
||||||
|
}.wrapMatrix()
|
||||||
|
|
||||||
|
override fun buildVector(
|
||||||
|
size: Int,
|
||||||
|
initializer: ${kmathAlgebra}.(Int) -> ${type},
|
||||||
|
): Ejml${type}Vector<${ejmlMatrixType}> = Ejml${type}Vector(${ejmlMatrixType}(size, 1).also {
|
||||||
|
(0 until it.numRows).forEach { row -> it[row, 0] = elementAlgebra.initializer(row) }
|
||||||
|
})
|
||||||
|
|
||||||
|
private fun <T : ${ejmlMatrixParentTypeMatrix}> T.wrapMatrix() = Ejml${type}Matrix(this)
|
||||||
|
private fun <T : ${ejmlMatrixParentTypeMatrix}> T.wrapVector() = Ejml${type}Vector(this)
|
||||||
|
|
||||||
|
override fun Matrix<${type}>.unaryMinus(): Matrix<${type}> = this * elementAlgebra { -one }
|
||||||
|
|
||||||
|
override fun Matrix<${type}>.dot(other: Matrix<${type}>): Ejml${type}Matrix<${ejmlMatrixType}> {
|
||||||
|
val out = ${ejmlMatrixType}(1, 1)
|
||||||
|
CommonOps_${ops}.mult(toEjml().origin, other.toEjml().origin, out)
|
||||||
|
return out.wrapMatrix()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun Matrix<${type}>.dot(vector: Point<${type}>): Ejml${type}Vector<${ejmlMatrixType}> {
|
||||||
|
val out = ${ejmlMatrixType}(1, 1)
|
||||||
|
CommonOps_${ops}.mult(toEjml().origin, vector.toEjml().origin, out)
|
||||||
|
return out.wrapVector()
|
||||||
|
}
|
||||||
|
|
||||||
|
override operator fun Matrix<${type}>.minus(other: Matrix<${type}>): Ejml${type}Matrix<${ejmlMatrixType}> {
|
||||||
|
val out = ${ejmlMatrixType}(1, 1)
|
||||||
|
|
||||||
|
CommonOps_${ops}.add(
|
||||||
|
elementAlgebra.one,
|
||||||
|
toEjml().origin,
|
||||||
|
elementAlgebra { -one },
|
||||||
|
other.toEjml().origin,
|
||||||
|
out,${
|
||||||
|
if (isDense) "" else
|
||||||
|
"""
|
||||||
|
null,
|
||||||
|
null,"""
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
return out.wrapMatrix()
|
||||||
|
}
|
||||||
|
|
||||||
|
override operator fun Matrix<${type}>.times(value: ${type}): Ejml${type}Matrix<${ejmlMatrixType}> {
|
||||||
|
val res = ${ejmlMatrixType}(1, 1)
|
||||||
|
CommonOps_${ops}.scale(value, toEjml().origin, res)
|
||||||
|
return res.wrapMatrix()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun Point<${type}>.unaryMinus(): Ejml${type}Vector<${ejmlMatrixType}> {
|
||||||
|
val res = ${ejmlMatrixType}(1, 1)
|
||||||
|
CommonOps_${ops}.changeSign(toEjml().origin, res)
|
||||||
|
return res.wrapVector()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun Matrix<${type}>.plus(other: Matrix<${type}>): Ejml${type}Matrix<${ejmlMatrixType}> {
|
||||||
|
val out = ${ejmlMatrixType}(1, 1)
|
||||||
|
|
||||||
|
CommonOps_${ops}.add(
|
||||||
|
elementAlgebra.one,
|
||||||
|
toEjml().origin,
|
||||||
|
elementAlgebra.one,
|
||||||
|
other.toEjml().origin,
|
||||||
|
out,${
|
||||||
|
if (isDense) "" else
|
||||||
|
"""
|
||||||
|
null,
|
||||||
|
null,"""
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
return out.wrapMatrix()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun Point<${type}>.plus(other: Point<${type}>): Ejml${type}Vector<${ejmlMatrixType}> {
|
||||||
|
val out = ${ejmlMatrixType}(1, 1)
|
||||||
|
|
||||||
|
CommonOps_${ops}.add(
|
||||||
|
elementAlgebra.one,
|
||||||
|
toEjml().origin,
|
||||||
|
elementAlgebra.one,
|
||||||
|
other.toEjml().origin,
|
||||||
|
out,${
|
||||||
|
if (isDense) "" else
|
||||||
|
"""
|
||||||
|
null,
|
||||||
|
null,"""
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
return out.wrapVector()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun Point<${type}>.minus(other: Point<${type}>): Ejml${type}Vector<${ejmlMatrixType}> {
|
||||||
|
val out = ${ejmlMatrixType}(1, 1)
|
||||||
|
|
||||||
|
CommonOps_${ops}.add(
|
||||||
|
elementAlgebra.one,
|
||||||
|
toEjml().origin,
|
||||||
|
elementAlgebra { -one },
|
||||||
|
other.toEjml().origin,
|
||||||
|
out,${
|
||||||
|
if (isDense) "" else
|
||||||
|
"""
|
||||||
|
null,
|
||||||
|
null,"""
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
return out.wrapVector()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun ${type}.times(m: Matrix<${type}>): Ejml${type}Matrix<${ejmlMatrixType}> = m * this
|
||||||
|
|
||||||
|
override fun Point<${type}>.times(value: ${type}): Ejml${type}Vector<${ejmlMatrixType}> {
|
||||||
|
val res = ${ejmlMatrixType}(1, 1)
|
||||||
|
CommonOps_${ops}.scale(value, toEjml().origin, res)
|
||||||
|
return res.wrapVector()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun ${type}.times(v: Point<${type}>): Ejml${type}Vector<${ejmlMatrixType}> = v * this
|
||||||
|
|
||||||
|
@UnstableKMathAPI
|
||||||
|
override fun <F : StructureFeature> computeFeature(structure: Matrix<${type}>, type: KClass<out F>): F? {
|
||||||
|
structure.getFeature(type)?.let { return it }
|
||||||
|
val origin = structure.toEjml().origin
|
||||||
|
|
||||||
|
return when (type) {
|
||||||
|
${
|
||||||
|
if (isDense)
|
||||||
|
""" InverseMatrixFeature::class -> object : InverseMatrixFeature<${type}> {
|
||||||
|
override val inverse: Matrix<${type}> by lazy {
|
||||||
|
val res = origin.copy()
|
||||||
|
CommonOps_${ops}.invert(res)
|
||||||
|
res.wrapMatrix()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
DeterminantFeature::class -> object : DeterminantFeature<${type}> {
|
||||||
|
override val determinant: $type by lazy { CommonOps_${ops}.det(origin) }
|
||||||
|
}
|
||||||
|
|
||||||
|
SingularValueDecompositionFeature::class -> object : SingularValueDecompositionFeature<${type}> {
|
||||||
|
private val svd by lazy {
|
||||||
|
DecompositionFactory_${ops}.svd(origin.numRows, origin.numCols, true, true, false)
|
||||||
|
.apply { decompose(origin.copy()) }
|
||||||
|
}
|
||||||
|
|
||||||
|
override val u: Matrix<${type}> by lazy { svd.getU(null, false).wrapMatrix() }
|
||||||
|
override val s: Matrix<${type}> by lazy { svd.getW(null).wrapMatrix() }
|
||||||
|
override val v: Matrix<${type}> by lazy { svd.getV(null, false).wrapMatrix() }
|
||||||
|
override val singularValues: Point<${type}> by lazy { ${type}Buffer(svd.singularValues) }
|
||||||
|
}
|
||||||
|
|
||||||
|
QRDecompositionFeature::class -> object : QRDecompositionFeature<${type}> {
|
||||||
|
private val qr by lazy {
|
||||||
|
DecompositionFactory_${ops}.qr().apply { decompose(origin.copy()) }
|
||||||
|
}
|
||||||
|
|
||||||
|
override val q: Matrix<${type}> by lazy {
|
||||||
|
qr.getQ(null, false).wrapMatrix().withFeature(OrthogonalFeature)
|
||||||
|
}
|
||||||
|
|
||||||
|
override val r: Matrix<${type}> by lazy { qr.getR(null, false).wrapMatrix().withFeature(UFeature) }
|
||||||
|
}
|
||||||
|
|
||||||
|
CholeskyDecompositionFeature::class -> object : CholeskyDecompositionFeature<${type}> {
|
||||||
|
override val l: Matrix<${type}> by lazy {
|
||||||
|
val cholesky =
|
||||||
|
DecompositionFactory_${ops}.chol(structure.rowNum, true).apply { decompose(origin.copy()) }
|
||||||
|
|
||||||
|
cholesky.getT(null).wrapMatrix().withFeature(LFeature)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
LupDecompositionFeature::class -> object : LupDecompositionFeature<${type}> {
|
||||||
|
private val lup by lazy {
|
||||||
|
DecompositionFactory_${ops}.lu(origin.numRows, origin.numCols).apply { decompose(origin.copy()) }
|
||||||
|
}
|
||||||
|
|
||||||
|
override val l: Matrix<${type}> by lazy {
|
||||||
|
lup.getLower(null).wrapMatrix().withFeature(LFeature)
|
||||||
|
}
|
||||||
|
|
||||||
|
override val u: Matrix<${type}> by lazy {
|
||||||
|
lup.getUpper(null).wrapMatrix().withFeature(UFeature)
|
||||||
|
}
|
||||||
|
|
||||||
|
override val p: Matrix<${type}> by lazy { lup.getRowPivot(null).wrapMatrix() }
|
||||||
|
}""" else """ QRDecompositionFeature::class -> object : QRDecompositionFeature<$type> {
|
||||||
|
private val qr by lazy {
|
||||||
|
DecompositionFactory_${ops}.qr(FillReducing.NONE).apply { decompose(origin.copy()) }
|
||||||
|
}
|
||||||
|
|
||||||
|
override val q: Matrix<${type}> by lazy {
|
||||||
|
qr.getQ(null, false).wrapMatrix().withFeature(OrthogonalFeature)
|
||||||
|
}
|
||||||
|
|
||||||
|
override val r: Matrix<${type}> by lazy { qr.getR(null, false).wrapMatrix().withFeature(UFeature) }
|
||||||
|
}
|
||||||
|
|
||||||
|
CholeskyDecompositionFeature::class -> object : CholeskyDecompositionFeature<${type}> {
|
||||||
|
override val l: Matrix<${type}> by lazy {
|
||||||
|
val cholesky =
|
||||||
|
DecompositionFactory_${ops}.cholesky().apply { decompose(origin.copy()) }
|
||||||
|
|
||||||
|
(cholesky.getT(null) as ${ejmlMatrixParentTypeMatrix}).wrapMatrix().withFeature(LFeature)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
LUDecompositionFeature::class, DeterminantFeature::class, InverseMatrixFeature::class -> object :
|
||||||
|
LUDecompositionFeature<${type}>, DeterminantFeature<${type}>, InverseMatrixFeature<${type}> {
|
||||||
|
private val lu by lazy {
|
||||||
|
DecompositionFactory_${ops}.lu(FillReducing.NONE).apply { decompose(origin.copy()) }
|
||||||
|
}
|
||||||
|
|
||||||
|
override val l: Matrix<${type}> by lazy {
|
||||||
|
lu.getLower(null).wrapMatrix().withFeature(LFeature)
|
||||||
|
}
|
||||||
|
|
||||||
|
override val u: Matrix<${type}> by lazy {
|
||||||
|
lu.getUpper(null).wrapMatrix().withFeature(UFeature)
|
||||||
|
}
|
||||||
|
|
||||||
|
override val inverse: Matrix<${type}> by lazy {
|
||||||
|
var a = origin
|
||||||
|
val inverse = ${ejmlMatrixDenseType}(1, 1)
|
||||||
|
val solver = LinearSolverFactory_${ops}.lu(FillReducing.NONE)
|
||||||
|
if (solver.modifiesA()) a = a.copy()
|
||||||
|
val i = CommonOps_${denseOps}.identity(a.numRows)
|
||||||
|
solver.solve(i, inverse)
|
||||||
|
inverse.wrapMatrix()
|
||||||
|
}
|
||||||
|
|
||||||
|
override val determinant: $type by lazy { elementAlgebra.number(lu.computeDeterminant().real) }
|
||||||
|
}"""
|
||||||
|
}
|
||||||
|
|
||||||
|
else -> null
|
||||||
|
}?.let{
|
||||||
|
type.cast(it)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Solves for *x* in the following equation: *x = [a] <sup>-1</sup> · [b]*.
|
||||||
|
*
|
||||||
|
* @param a the base matrix.
|
||||||
|
* @param b n by p matrix.
|
||||||
|
* @return the solution for *x* that is n by p.
|
||||||
|
*/
|
||||||
|
public fun solve(a: Matrix<${type}>, b: Matrix<${type}>): Ejml${type}Matrix<${ejmlMatrixType}> {
|
||||||
|
val res = ${ejmlMatrixType}(1, 1)
|
||||||
|
CommonOps_${ops}.solve(${ejmlMatrixType}(a.toEjml().origin), ${ejmlMatrixType}(b.toEjml().origin), res)
|
||||||
|
return res.wrapMatrix()
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Solves for *x* in the following equation: *x = [a] <sup>-1</sup> · [b]*.
|
||||||
|
*
|
||||||
|
* @param a the base matrix.
|
||||||
|
* @param b n by p vector.
|
||||||
|
* @return the solution for *x* that is n by p.
|
||||||
|
*/
|
||||||
|
public fun solve(a: Matrix<${type}>, b: Point<${type}>): Ejml${type}Vector<${ejmlMatrixType}> {
|
||||||
|
val res = ${ejmlMatrixType}(1, 1)
|
||||||
|
CommonOps_${ops}.solve(${ejmlMatrixType}(a.toEjml().origin), ${ejmlMatrixType}(b.toEjml().origin), res)
|
||||||
|
return Ejml${type}Vector(res)
|
||||||
|
}
|
||||||
|
}"""
|
||||||
|
appendLine(text)
|
||||||
|
appendLine()
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generates routine EJML classes.
|
||||||
|
*/
|
||||||
|
fun ejmlCodegen(outputFile: String): Unit = File(outputFile).run {
|
||||||
|
parentFile.mkdirs()
|
||||||
|
|
||||||
|
writer().use {
|
||||||
|
it.appendLine("/*")
|
||||||
|
it.appendLine(" * Copyright 2018-2021 KMath contributors.")
|
||||||
|
it.appendLine(" * Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.")
|
||||||
|
it.appendLine(" */")
|
||||||
|
it.appendLine()
|
||||||
|
it.appendLine("/* This file is generated with buildSrc/src/main/kotlin/space/kscience/kmath/ejml/codegen/ejmlCodegen.kt */")
|
||||||
|
it.appendLine()
|
||||||
|
it.appendLine("package space.kscience.kmath.ejml")
|
||||||
|
it.appendLine()
|
||||||
|
it.appendLine("""import org.ejml.data.*
|
||||||
|
import org.ejml.dense.row.CommonOps_DDRM
|
||||||
|
import org.ejml.dense.row.CommonOps_FDRM
|
||||||
|
import org.ejml.dense.row.factory.DecompositionFactory_DDRM
|
||||||
|
import org.ejml.dense.row.factory.DecompositionFactory_FDRM
|
||||||
|
import org.ejml.sparse.FillReducing
|
||||||
|
import org.ejml.sparse.csc.CommonOps_DSCC
|
||||||
|
import org.ejml.sparse.csc.CommonOps_FSCC
|
||||||
|
import org.ejml.sparse.csc.factory.DecompositionFactory_DSCC
|
||||||
|
import org.ejml.sparse.csc.factory.DecompositionFactory_FSCC
|
||||||
|
import org.ejml.sparse.csc.factory.LinearSolverFactory_DSCC
|
||||||
|
import org.ejml.sparse.csc.factory.LinearSolverFactory_FSCC
|
||||||
|
import space.kscience.kmath.linear.*
|
||||||
|
import space.kscience.kmath.linear.Matrix
|
||||||
|
import space.kscience.kmath.UnstableKMathAPI
|
||||||
|
import space.kscience.kmath.nd.StructureFeature
|
||||||
|
import space.kscience.kmath.operations.DoubleField
|
||||||
|
import space.kscience.kmath.operations.FloatField
|
||||||
|
import space.kscience.kmath.operations.invoke
|
||||||
|
import space.kscience.kmath.structures.DoubleBuffer
|
||||||
|
import space.kscience.kmath.structures.FloatBuffer
|
||||||
|
import kotlin.reflect.KClass
|
||||||
|
import kotlin.reflect.cast""")
|
||||||
|
it.appendLine()
|
||||||
|
it.appendEjmlVector("Double", "DMatrix")
|
||||||
|
it.appendEjmlVector("Float", "FMatrix")
|
||||||
|
it.appendEjmlMatrix("Double", "DMatrix")
|
||||||
|
it.appendEjmlMatrix("Float", "FMatrix")
|
||||||
|
it.appendEjmlLinearSpace("Double", "DoubleField", "DMatrix", "DMatrixRMaj", "DMatrixRMaj", "DDRM", "DDRM", true)
|
||||||
|
it.appendEjmlLinearSpace("Float", "FloatField", "FMatrix", "FMatrixRMaj", "FMatrixRMaj", "FDRM", "FDRM", true)
|
||||||
|
|
||||||
|
it.appendEjmlLinearSpace(
|
||||||
|
type = "Double",
|
||||||
|
kmathAlgebra = "DoubleField",
|
||||||
|
ejmlMatrixParentTypeMatrix = "DMatrix",
|
||||||
|
ejmlMatrixType = "DMatrixSparseCSC",
|
||||||
|
ejmlMatrixDenseType = "DMatrixRMaj",
|
||||||
|
ops = "DSCC",
|
||||||
|
denseOps = "DDRM",
|
||||||
|
isDense = false,
|
||||||
|
)
|
||||||
|
|
||||||
|
it.appendEjmlLinearSpace(
|
||||||
|
type = "Float",
|
||||||
|
kmathAlgebra = "FloatField",
|
||||||
|
ejmlMatrixParentTypeMatrix = "FMatrix",
|
||||||
|
ejmlMatrixType = "FMatrixSparseCSC",
|
||||||
|
ejmlMatrixDenseType = "FMatrixRMaj",
|
||||||
|
ops = "FSCC",
|
||||||
|
denseOps = "FDRM",
|
||||||
|
isDense = false,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
@ -17,4 +17,4 @@ own `MemoryBuffer.create()` factory).
|
|||||||
## Buffer performance
|
## Buffer performance
|
||||||
|
|
||||||
One should avoid using default boxing buffer wherever it is possible. Try to use primitive buffers or memory buffers
|
One should avoid using default boxing buffer wherever it is possible. Try to use primitive buffers or memory buffers
|
||||||
instead.
|
instead .
|
||||||
|
@ -1,27 +1,20 @@
|
|||||||
# Coding Conventions
|
# Coding Conventions
|
||||||
|
|
||||||
Generally, KMath code follows
|
Generally, KMath code follows general [Kotlin coding conventions](https://kotlinlang.org/docs/reference/coding-conventions.html), but with a number of small changes and clarifications.
|
||||||
general [Kotlin coding conventions](https://kotlinlang.org/docs/reference/coding-conventions.html), but with a number of
|
|
||||||
small changes and clarifications.
|
|
||||||
|
|
||||||
## Utility Class Naming
|
## Utility Class Naming
|
||||||
|
|
||||||
Filename should coincide with a name of one of the classes contained in the file or start with small letter and describe
|
Filename should coincide with a name of one of the classes contained in the file or start with small letter and describe its contents.
|
||||||
its contents.
|
|
||||||
|
|
||||||
The code convention [here](https://kotlinlang.org/docs/reference/coding-conventions.html#source-file-names) says that
|
The code convention [here](https://kotlinlang.org/docs/reference/coding-conventions.html#source-file-names) says that file names should start with a capital letter even if file does not contain classes. Yet starting utility classes and aggregators with a small letter seems to be a good way to visually separate those files.
|
||||||
file names should start with a capital letter even if file does not contain classes. Yet starting utility classes and
|
|
||||||
aggregators with a small letter seems to be a good way to visually separate those files.
|
|
||||||
|
|
||||||
This convention could be changed in future in a non-breaking way.
|
This convention could be changed in future in a non-breaking way.
|
||||||
|
|
||||||
## Private Variable Naming
|
## Private Variable Naming
|
||||||
|
|
||||||
Private variables' names may start with underscore `_` for of the private mutable variable is shadowed by the public
|
Private variables' names may start with underscore `_` for of the private mutable variable is shadowed by the public read-only value with the same meaning.
|
||||||
read-only value with the same meaning.
|
|
||||||
|
|
||||||
This rule does not permit underscores in names, but it is sometimes useful to "underscore" the fact that public and
|
This rule does not permit underscores in names, but it is sometimes useful to "underscore" the fact that public and private versions draw up the same entity. It is allowed only for private variables.
|
||||||
private versions draw up the same entity. It is allowed only for private variables.
|
|
||||||
|
|
||||||
This convention could be changed in future in a non-breaking way.
|
This convention could be changed in future in a non-breaking way.
|
||||||
|
|
||||||
@ -31,5 +24,4 @@ Use one-liners when they occupy single code window line both for functions and p
|
|||||||
`val b: String get() = "fff"`. The same should be performed with multiline expressions when they could be
|
`val b: String get() = "fff"`. The same should be performed with multiline expressions when they could be
|
||||||
cleanly separated.
|
cleanly separated.
|
||||||
|
|
||||||
There is no universal consensus whenever use `fun a() = ...` or `fun a() { return ... }`. Yet from reader outlook
|
There is no universal consensus whenever use `fun a() = ...` or `fun a() { return ... }`. Yet from reader outlook one-lines seem to better show that the property or function is easily calculated.
|
||||||
one-lines seem to better show that the property or function is easily calculated.
|
|
||||||
|
@ -1,19 +1,16 @@
|
|||||||
# Expressions
|
# Expressions
|
||||||
|
|
||||||
Expressions is a feature, which allows constructing lazily or immediately calculated parametric mathematical
|
Expressions is a feature, which allows constructing lazily or immediately calculated parametric mathematical expressions.
|
||||||
expressions.
|
|
||||||
|
|
||||||
The potential use-cases for it (so far) are following:
|
The potential use-cases for it (so far) are following:
|
||||||
|
|
||||||
* lazy evaluation (in general simple lambda is better, but there are some border cases);
|
* lazy evaluation (in general simple lambda is better, but there are some border cases);
|
||||||
* automatic differentiation in single-dimension and in multiple dimensions;
|
* automatic differentiation in single-dimension and in multiple dimensions;
|
||||||
* generation of mathematical syntax trees with subsequent code generation for other languages;
|
* generation of mathematical syntax trees with subsequent code generation for other languages;
|
||||||
* symbolic computations, especially differentiation (and some other actions with `kmath-symja` integration with
|
* symbolic computations, especially differentiation (and some other actions with `kmath-symja` integration with Symja's `IExpr`—integration, simplification, and more);
|
||||||
Symja's `IExpr`—integration, simplification, and more);
|
|
||||||
* visualization with `kmath-jupyter`.
|
* visualization with `kmath-jupyter`.
|
||||||
|
|
||||||
The workhorse of this API is `Expression` interface, which exposes
|
The workhorse of this API is `Expression` interface, which exposes single `operator fun invoke(arguments: Map<Symbol, T>): T`
|
||||||
single `operator fun invoke(arguments: Map<Symbol, T>): T`
|
|
||||||
method. `ExpressionAlgebra` is used to generate expressions and introduce variables.
|
method. `ExpressionAlgebra` is used to generate expressions and introduce variables.
|
||||||
|
|
||||||
Currently there are two implementations:
|
Currently there are two implementations:
|
||||||
@ -21,4 +18,4 @@ Currently there are two implementations:
|
|||||||
* Generic `ExpressionField` in `kmath-core` which allows construction of custom lazy expressions
|
* Generic `ExpressionField` in `kmath-core` which allows construction of custom lazy expressions
|
||||||
|
|
||||||
* Auto-differentiation expression in `kmath-commons` module allows using full power of `DerivativeStructure`
|
* Auto-differentiation expression in `kmath-commons` module allows using full power of `DerivativeStructure`
|
||||||
from commons-math. **TODO: add example**
|
from commons-math. **TODO: add example**
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
<!--
|
<!--
|
||||||
- Copyright 2018-2024 KMath contributors.
|
- Copyright 2018-2022 KMath contributors.
|
||||||
- Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
- Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||||
-->
|
-->
|
||||||
|
|
||||||
|
Before Width: | Height: | Size: 249 KiB After Width: | Height: | Size: 249 KiB |
@ -1,6 +1,6 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
<!--
|
<!--
|
||||||
- Copyright 2018-2024 KMath contributors.
|
- Copyright 2018-2022 KMath contributors.
|
||||||
- Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
- Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||||
-->
|
-->
|
||||||
|
|
||||||
|
Before Width: | Height: | Size: 19 KiB After Width: | Height: | Size: 19 KiB |
@ -1,6 +1,6 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
<!--
|
<!--
|
||||||
- Copyright 2018-2024 KMath contributors.
|
- Copyright 2018-2022 KMath contributors.
|
||||||
- Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
- Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||||
-->
|
-->
|
||||||
|
|
||||||
|
Before Width: | Height: | Size: 278 KiB After Width: | Height: | Size: 278 KiB |
@ -1,6 +1,6 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
<!--
|
<!--
|
||||||
- Copyright 2018-2024 KMath contributors.
|
- Copyright 2018-2022 KMath contributors.
|
||||||
- Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
- Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||||
-->
|
-->
|
||||||
|
|
||||||
|
Before Width: | Height: | Size: 118 KiB After Width: | Height: | Size: 118 KiB |
@ -1,12 +1,8 @@
|
|||||||
## Basic linear algebra layout
|
## Basic linear algebra layout
|
||||||
|
|
||||||
KMath support for linear algebra organized in a context-oriented way, which means that operations are in most cases
|
KMath support for linear algebra organized in a context-oriented way, which means that operations are in most cases declared in context classes, and are not the members of classes that store data. This allows more flexible approach to maintain multiple back-ends. The new operations added as extensions to contexts instead of being member functions of data structures.
|
||||||
declared in context classes, and are not the members of classes that store data. This allows more flexible approach to
|
|
||||||
maintain multiple back-ends. The new operations added as extensions to contexts instead of being member functions of
|
|
||||||
data structures.
|
|
||||||
|
|
||||||
The main context for linear algebra over matrices and vectors is `LinearSpace`, which defines addition and dot products
|
The main context for linear algebra over matrices and vectors is `LinearSpace`, which defines addition and dot products of matrices and vectors:
|
||||||
of matrices and vectors:
|
|
||||||
|
|
||||||
```kotlin
|
```kotlin
|
||||||
import space.kscience.kmath.linear.*
|
import space.kscience.kmath.linear.*
|
||||||
@ -32,5 +28,4 @@ LinearSpace.Companion.real {
|
|||||||
## Backends overview
|
## Backends overview
|
||||||
|
|
||||||
### EJML
|
### EJML
|
||||||
|
|
||||||
### Commons Math
|
### Commons Math
|
||||||
|
@ -8,7 +8,6 @@ One of the most sought after features of mathematical libraries is the high-perf
|
|||||||
structures. In `kmath` performance depends on which particular context was used for operation.
|
structures. In `kmath` performance depends on which particular context was used for operation.
|
||||||
|
|
||||||
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(DoubleField, dim, dim)
|
val autoField = NDField.auto(DoubleField, dim, dim)
|
||||||
@ -17,7 +16,6 @@ Let us consider following contexts:
|
|||||||
//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(DoubleField, 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:
|
||||||
|
|
||||||
## Test case
|
## Test case
|
||||||
@ -26,27 +24,22 @@ To test performance we will take 2d-structures with `dim = 1000` and add a struc
|
|||||||
to it `n = 1000` times.
|
to it `n = 1000` times.
|
||||||
|
|
||||||
## Specialized
|
## Specialized
|
||||||
|
|
||||||
The code to run this looks like:
|
The code to run this looks like:
|
||||||
|
|
||||||
```kotlin
|
```kotlin
|
||||||
specializedField.run {
|
specializedField.run {
|
||||||
var res: NDBuffer<Float64> = one
|
var res: NDBuffer<Double> = one
|
||||||
repeat(n) {
|
repeat(n) {
|
||||||
res += 1.0
|
res += 1.0
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
The performance of this code is the best of all tests since it inlines all operations and is specialized for operation
|
The performance of this code is the best of all tests since it inlines all operations and is specialized for operation
|
||||||
with doubles. We will measure everything else relative to this one, so time for this test will be `1x` (real time
|
with doubles. We will measure everything else relative to this one, so time for this test will be `1x` (real time
|
||||||
on my computer is about 4.5 seconds). The only problem with this approach is that it requires specifying type
|
on my computer is about 4.5 seconds). The only problem with this approach is that it requires specifying type
|
||||||
from the beginning. Everyone does so anyway, so it is the recommended approach.
|
from the beginning. Everyone does so anyway, so it is the recommended approach.
|
||||||
|
|
||||||
## Automatic
|
## Automatic
|
||||||
|
|
||||||
Let's do the same with automatic field inference:
|
Let's do the same with automatic field inference:
|
||||||
|
|
||||||
```kotlin
|
```kotlin
|
||||||
autoField.run {
|
autoField.run {
|
||||||
var res = one
|
var res = one
|
||||||
@ -55,16 +48,13 @@ Let's do the same with automatic field inference:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
Ths speed of this operation is approximately the same as for specialized case since `NDField.auto` just
|
Ths speed of this operation is approximately the same as for specialized case since `NDField.auto` just
|
||||||
returns the same `RealNDField` in this case. Of course, it is usually better to use specialized method to be sure.
|
returns the same `RealNDField` in this case. Of course, it is usually better to use specialized method to be sure.
|
||||||
|
|
||||||
## Lazy
|
## Lazy
|
||||||
|
|
||||||
Lazy field does not produce a structure when asked, instead it generates an empty structure and fills it on-demand
|
Lazy field does not produce a structure when asked, instead it generates an empty structure and fills it on-demand
|
||||||
using coroutines to parallelize computations.
|
using coroutines to parallelize computations.
|
||||||
When one calls
|
When one calls
|
||||||
|
|
||||||
```kotlin
|
```kotlin
|
||||||
lazyField.run {
|
lazyField.run {
|
||||||
var res = one
|
var res = one
|
||||||
@ -73,14 +63,12 @@ When one calls
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
The result will be calculated almost immediately but the result will be empty. To get the full result
|
The result will be calculated almost immediately but the result will be empty. To get the full result
|
||||||
structure one needs to call all its elements. In this case computation overhead will be huge. So this field never
|
structure one needs to call all its elements. In this case computation overhead will be huge. So this field never
|
||||||
should be used if one expects to use the full result structure. Though if one wants only small fraction, it could
|
should be used if one expects to use the full result structure. Though if one wants only small fraction, it could
|
||||||
save a lot of time.
|
save a lot of time.
|
||||||
|
|
||||||
This field still could be used with reasonable performance if call code is changed:
|
This field still could be used with reasonable performance if call code is changed:
|
||||||
|
|
||||||
```kotlin
|
```kotlin
|
||||||
lazyField.run {
|
lazyField.run {
|
||||||
val res = one.map {
|
val res = one.map {
|
||||||
@ -94,37 +82,30 @@ This field still could be used with reasonable performance if call code is chang
|
|||||||
res.elements().forEach { it.second }
|
res.elements().forEach { it.second }
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
In this case it completes in about `4x-5x` time due to boxing.
|
In this case it completes in about `4x-5x` time due to boxing.
|
||||||
|
|
||||||
## Boxing
|
## Boxing
|
||||||
|
|
||||||
The boxing field produced by
|
The boxing field produced by
|
||||||
|
|
||||||
```kotlin
|
```kotlin
|
||||||
genericField.run {
|
genericField.run {
|
||||||
var res: NDBuffer<Float64> = one
|
var res: NDBuffer<Double> = one
|
||||||
repeat(n) {
|
repeat(n) {
|
||||||
res += 1.0
|
res += 1.0
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
is the slowest one, because it requires boxing and unboxing the `double` on each operation. It takes about
|
is the slowest one, because it requires boxing and unboxing the `double` on each operation. It takes about
|
||||||
`15x` time (**TODO: there seems to be a problem here, it should be slow, but not that slow**). This field should
|
`15x` time (**TODO: there seems to be a problem here, it should be slow, but not that slow**). This field should
|
||||||
never be used for primitives.
|
never be used for primitives.
|
||||||
|
|
||||||
## Element operation
|
## Element operation
|
||||||
|
|
||||||
Let us also check the speed for direct operations on elements:
|
Let us also check the speed for direct operations on elements:
|
||||||
|
|
||||||
```kotlin
|
```kotlin
|
||||||
var res = genericField.one
|
var res = genericField.one
|
||||||
repeat(n) {
|
repeat(n) {
|
||||||
res += 1.0
|
res += 1.0
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
One would expect to be at least as slow as field operation, but in fact, this one takes only `2x` time to complete.
|
One would expect to be at least as slow as field operation, but in fact, this one takes only `2x` time to complete.
|
||||||
It happens, because in this particular case it does not use actual `NDField` but instead calculated directly
|
It happens, because in this particular case it does not use actual `NDField` but instead calculated directly
|
||||||
via extension function.
|
via extension function.
|
||||||
@ -133,7 +114,6 @@ via extension function.
|
|||||||
|
|
||||||
Usually it is bad idea to compare the direct numerical operation performance in different languages, but it hard to
|
Usually it is bad idea to compare the direct numerical operation performance in different languages, but it hard to
|
||||||
work completely without frame of reference. In this case, simple numpy code:
|
work completely without frame of reference. In this case, simple numpy code:
|
||||||
|
|
||||||
```python
|
```python
|
||||||
import numpy as np
|
import numpy as np
|
||||||
|
|
||||||
@ -141,9 +121,7 @@ res = np.ones((1000,1000))
|
|||||||
for i in range(1000):
|
for i in range(1000):
|
||||||
res = res + 1.0
|
res = res + 1.0
|
||||||
```
|
```
|
||||||
|
gives the completion time of about `1.1x`, which means that specialized kotlin code in fact is working faster (I think it is
|
||||||
gives the completion time of about `1.1x`, which means that specialized kotlin code in fact is working faster (I think
|
|
||||||
it is
|
|
||||||
because better memory management). Of course if one writes `res += 1.0`, the performance will be different,
|
because better memory management). Of course if one writes `res += 1.0`, the performance will be different,
|
||||||
but it would be different case, because numpy overrides `+=` with in-place operations. In-place operations are
|
but it would be different case, because numpy overrides `+=` with in-place operations. In-place operations are
|
||||||
available in `kmath` with `MutableNDStructure` but there is no field for it (one can still work with mapping
|
available in `kmath` with `MutableNDStructure` but there is no field for it (one can still work with mapping
|
||||||
|
@ -1,54 +1,27 @@
|
|||||||
# Polynomials and Rational Functions
|
# Polynomials and Rational Functions
|
||||||
|
|
||||||
KMath provides a way to work with uni- and multivariate polynomials and rational functions. It includes full support of
|
KMath provides a way to work with uni- and multivariate polynomials and rational functions. It includes full support of arithmetic operations of integers, **constants** (elements of ring polynomials are build over), variables (for certain multivariate implementations), polynomials and rational functions encapsulated in so-called **polynomial space** and **rational function space** and some other utilities such as algebraic differentiation and substitution.
|
||||||
arithmetic operations of integers, **constants** (elements of ring polynomials are build over), variables (for certain
|
|
||||||
multivariate implementations), polynomials and rational functions encapsulated in so-called **polynomial space** and *
|
|
||||||
*rational function space** and some other utilities such as algebraic differentiation and substitution.
|
|
||||||
|
|
||||||
## Concrete realizations
|
## Concrete realizations
|
||||||
|
|
||||||
There are 3 approaches to represent polynomials:
|
There are 3 approaches to represent polynomials:
|
||||||
|
1. For univariate polynomials one can represent and store polynomial as a list of coefficients for each power of the variable. I.e. polynomial $a_0 + \dots + a_n x^n $ can be represented as a finite sequence $(a_0; \dots; a_n)$. (Compare to sequential definition of polynomials.)
|
||||||
|
2. For multivariate polynomials one can represent and store polynomial as a matching (in programming it is called "map" or "dictionary", in math it is called [functional relation](https://en.wikipedia.org/wiki/Binary_relation#Special_types_of_binary_relations)) of each "**term signature**" (that describes what variables and in what powers appear in the term) with corresponding coefficient of the term. But there are 2 possible approaches of term signature representation:
|
||||||
|
1. One can number all the variables, so term signature can be represented as a sequence describing powers of the variables. I.e. signature of term $c \\; x_0^{d_0} \dots x_n^{d_n} $ (for natural or zero $d_i $) can be represented as a finite sequence $(d_0; \dots; d_n)$.
|
||||||
|
2. One can represent variables as objects ("**labels**"), so term signature can be also represented as a matching of each appeared variable with its power in the term. I.e. signature of term $c \\; x_0^{d_0} \dots x_n^{d_n} $ (for natural non-zero $d_i $) can be represented as a finite matching $(x_0 \to d_1; \dots; x_n \to d_n)$.
|
||||||
|
|
||||||
1. For univariate polynomials one can represent and store polynomial as a list of coefficients for each power of the
|
All that three approaches are implemented by "list", "numbered", and "labeled" versions of polynomials and polynomial spaces respectively. Whereas all rational functions are represented as fractions with corresponding polynomial numerator and denominator, and rational functions' spaces are implemented in the same way as usual field of rational numbers (or more precisely, as any field of fractions over integral domain) should be implemented.
|
||||||
variable. I.e. polynomial $a_0 + \dots + a_n x^n $ can be represented as a finite sequence $(a_0; \dots; a_n)$. (
|
|
||||||
Compare to sequential definition of polynomials.)
|
|
||||||
2. For multivariate polynomials one can represent and store polynomial as a matching (in programming it is called "map"
|
|
||||||
or "dictionary", in math it is
|
|
||||||
called [functional relation](https://en.wikipedia.org/wiki/Binary_relation#Special_types_of_binary_relations)) of
|
|
||||||
each "**term signature**" (that describes what variables and in what powers appear in the term) with corresponding
|
|
||||||
coefficient of the term. But there are 2 possible approaches of term signature representation:
|
|
||||||
1. One can number all the variables, so term signature can be represented as a sequence describing powers of the
|
|
||||||
variables. I.e. signature of term $c \\; x_0^{d_0} \dots x_n^{d_n} $ (for natural or zero $d_i $) can be
|
|
||||||
represented as a finite sequence $(d_0; \dots; d_n)$.
|
|
||||||
2. One can represent variables as objects ("**labels**"), so term signature can be also represented as a matching of
|
|
||||||
each appeared variable with its power in the term. I.e. signature of term $c \\; x_0^{d_0} \dots x_n^{d_n} $ (for
|
|
||||||
natural non-zero $d_i $) can be represented as a finite matching $(x_0 \to d_1; \dots; x_n \to d_n)$.
|
|
||||||
|
|
||||||
All that three approaches are implemented by "list", "numbered", and "labeled" versions of polynomials and polynomial
|
|
||||||
spaces respectively. Whereas all rational functions are represented as fractions with corresponding polynomial numerator
|
|
||||||
and denominator, and rational functions' spaces are implemented in the same way as usual field of rational numbers (or
|
|
||||||
more precisely, as any field of fractions over integral domain) should be implemented.
|
|
||||||
|
|
||||||
So here are a bit of details. Let `C` by type of constants. Then:
|
So here are a bit of details. Let `C` by type of constants. Then:
|
||||||
|
1. `ListPolynomial`, `ListPolynomialSpace`, `ListRationalFunction` and `ListRationalFunctionSpace` implement the first scenario. `ListPolynomial` stores polynomial $a_0 + \dots + a_n x^n $ as a coefficients list `listOf(a_0, ..., a_n)` (of type `List<C>`).
|
||||||
|
|
||||||
1. `ListPolynomial`, `ListPolynomialSpace`, `ListRationalFunction` and `ListRationalFunctionSpace` implement the first
|
They also have variation `ScalableListPolynomialSpace` that replaces former polynomials and implements `ScaleOperations`.
|
||||||
scenario. `ListPolynomial` stores polynomial $a_0 + \dots + a_n x^n $ as a coefficients
|
2. `NumberedPolynomial`, `NumberedPolynomialSpace`, `NumberedRationalFunction` and `NumberedRationalFunctionSpace` implement second scenario. `NumberedPolynomial` stores polynomials as structures of type `Map<List<UInt>, C>`. Signatures are stored as `List<UInt>`. To prevent ambiguity signatures should not end with zeros.
|
||||||
list `listOf(a_0, ..., a_n)` (of type `List<C>`).
|
3. `LabeledPolynomial`, `LabeledPolynomialSpace`, `LabeledRationalFunction` and `LabeledRationalFunctionSpace` implement third scenario using common `Symbol` as variable type. `LabeledPolynomial` stores polynomials as structures of type `Map<Map<Symbol, UInt>, C>`. Signatures are stored as `Map<Symbol, UInt>`. To prevent ambiguity each signature should not map any variable to zero.
|
||||||
|
|
||||||
They also have variation `ScalableListPolynomialSpace` that replaces former polynomials and
|
|
||||||
implements `ScaleOperations`.
|
|
||||||
2. `NumberedPolynomial`, `NumberedPolynomialSpace`, `NumberedRationalFunction` and `NumberedRationalFunctionSpace`
|
|
||||||
implement second scenario. `NumberedPolynomial` stores polynomials as structures of type `Map<List<UInt>, C>`.
|
|
||||||
Signatures are stored as `List<UInt>`. To prevent ambiguity signatures should not end with zeros.
|
|
||||||
3. `LabeledPolynomial`, `LabeledPolynomialSpace`, `LabeledRationalFunction` and `LabeledRationalFunctionSpace` implement
|
|
||||||
third scenario using common `Symbol` as variable type. `LabeledPolynomial` stores polynomials as structures of
|
|
||||||
type `Map<Map<Symbol, UInt>, C>`. Signatures are stored as `Map<Symbol, UInt>`. To prevent ambiguity each signature
|
|
||||||
should not map any variable to zero.
|
|
||||||
|
|
||||||
### Example: `ListPolynomial`
|
### Example: `ListPolynomial`
|
||||||
|
|
||||||
For example, polynomial $2 - 3x + x^2 $ (with `Int` coefficients) is represented
|
For example, polynomial $2 - 3x + x^2 $ (with `Int` coefficients) is represented
|
||||||
|
|
||||||
```kotlin
|
```kotlin
|
||||||
val polynomial: ListPolynomial<Int> = ListPolynomial(listOf(2, -3, 1))
|
val polynomial: ListPolynomial<Int> = ListPolynomial(listOf(2, -3, 1))
|
||||||
// or
|
// or
|
||||||
@ -56,7 +29,6 @@ val polynomial: ListPolynomial<Int> = ListPolynomial(2, -3, 1)
|
|||||||
```
|
```
|
||||||
|
|
||||||
All algebraic operations can be used in corresponding space:
|
All algebraic operations can be used in corresponding space:
|
||||||
|
|
||||||
```kotlin
|
```kotlin
|
||||||
val computationResult = Int.algebra.listPolynomialSpace {
|
val computationResult = Int.algebra.listPolynomialSpace {
|
||||||
ListPolynomial(2, -3, 1) + ListPolynomial(0, 6) == ListPolynomial(2, 3, 1)
|
ListPolynomial(2, -3, 1) + ListPolynomial(0, 6) == ListPolynomial(2, 3, 1)
|
||||||
@ -69,8 +41,7 @@ For more see [examples](../examples/src/main/kotlin/space/kscience/kmath/functio
|
|||||||
|
|
||||||
### Example: `NumberedPolynomial`
|
### Example: `NumberedPolynomial`
|
||||||
|
|
||||||
For example, polynomial $3 + 5 x_1 - 7 x_0^2 x_2 $ (with `Int` coefficients) is represented
|
For example, polynomial $3 + 5 x_1 - 7 x_0^2 x_2 $ (with `Int` coefficients) is represented
|
||||||
|
|
||||||
```kotlin
|
```kotlin
|
||||||
val polynomial: NumberedPolynomial<Int> = NumberedPolynomial(
|
val polynomial: NumberedPolynomial<Int> = NumberedPolynomial(
|
||||||
mapOf(
|
mapOf(
|
||||||
@ -88,7 +59,6 @@ val polynomial: NumberedPolynomial<Int> = NumberedPolynomial(
|
|||||||
```
|
```
|
||||||
|
|
||||||
All algebraic operations can be used in corresponding space:
|
All algebraic operations can be used in corresponding space:
|
||||||
|
|
||||||
```kotlin
|
```kotlin
|
||||||
val computationResult = Int.algebra.numberedPolynomialSpace {
|
val computationResult = Int.algebra.numberedPolynomialSpace {
|
||||||
NumberedPolynomial(
|
NumberedPolynomial(
|
||||||
@ -113,8 +83,7 @@ For more see [examples](../examples/src/main/kotlin/space/kscience/kmath/functio
|
|||||||
|
|
||||||
### Example: `LabeledPolynomial`
|
### Example: `LabeledPolynomial`
|
||||||
|
|
||||||
For example, polynomial $3 + 5 y - 7 x^2 z $ (with `Int` coefficients) is represented
|
For example, polynomial $3 + 5 y - 7 x^2 z $ (with `Int` coefficients) is represented
|
||||||
|
|
||||||
```kotlin
|
```kotlin
|
||||||
val polynomial: LabeledPolynomial<Int> = LabeledPolynomial(
|
val polynomial: LabeledPolynomial<Int> = LabeledPolynomial(
|
||||||
mapOf(
|
mapOf(
|
||||||
@ -132,7 +101,6 @@ val polynomial: LabeledPolynomial<Int> = LabeledPolynomial(
|
|||||||
```
|
```
|
||||||
|
|
||||||
All algebraic operations can be used in corresponding space:
|
All algebraic operations can be used in corresponding space:
|
||||||
|
|
||||||
```kotlin
|
```kotlin
|
||||||
val computationResult = Int.algebra.labeledPolynomialSpace {
|
val computationResult = Int.algebra.labeledPolynomialSpace {
|
||||||
LabeledPolynomial(
|
LabeledPolynomial(
|
||||||
@ -182,42 +150,23 @@ classDiagram
|
|||||||
PolynomialSpaceOfFractions <|-- MultivariatePolynomialSpaceOfFractions
|
PolynomialSpaceOfFractions <|-- MultivariatePolynomialSpaceOfFractions
|
||||||
```
|
```
|
||||||
|
|
||||||
There are implemented `Polynomial` and `RationalFunction` interfaces as abstractions of polynomials and rational
|
There are implemented `Polynomial` and `RationalFunction` interfaces as abstractions of polynomials and rational functions respectively (although, there is not a lot of logic in them) and `PolynomialSpace` and `RationalFunctionSpace` (that implement `Ring` interface) as abstractions of polynomials' and rational functions' spaces respectively. More precisely, that means they allow to declare common logic of interaction with such objects and spaces:
|
||||||
functions respectively (although, there is not a lot of logic in them) and `PolynomialSpace`
|
|
||||||
and `RationalFunctionSpace` (that implement `Ring` interface) as abstractions of polynomials' and rational functions'
|
|
||||||
spaces respectively. More precisely, that means they allow to declare common logic of interaction with such objects and
|
|
||||||
spaces:
|
|
||||||
|
|
||||||
- `Polynomial` does not provide any logic. It is marker interface.
|
- `Polynomial` does not provide any logic. It is marker interface.
|
||||||
- `RationalFunction` provides numerator and denominator of rational function and destructuring declaration for them.
|
- `RationalFunction` provides numerator and denominator of rational function and destructuring declaration for them.
|
||||||
- `PolynomialSpace` provides all possible arithmetic interactions of integers, constants (of type `C`), and
|
- `PolynomialSpace` provides all possible arithmetic interactions of integers, constants (of type `C`), and polynomials (of type `P`) like addition, subtraction, multiplication, and some others and common properties like degree of polynomial.
|
||||||
polynomials (of type `P`) like addition, subtraction, multiplication, and some others and common properties like
|
- `RationalFunctionSpace` provides the same as `PolynomialSpace` but also for rational functions: all possible arithmetic interactions of integers, constants (of type `C`), polynomials (of type `P`), and rational functions (of type `R`) like addition, subtraction, multiplication, division (in some cases), and some others and common properties like degree of polynomial.
|
||||||
degree of polynomial.
|
|
||||||
- `RationalFunctionSpace` provides the same as `PolynomialSpace` but also for rational functions: all possible
|
|
||||||
arithmetic interactions of integers, constants (of type `C`), polynomials (of type `P`), and rational functions (of
|
|
||||||
type `R`) like addition, subtraction, multiplication, division (in some cases), and some others and common properties
|
|
||||||
like degree of polynomial.
|
|
||||||
|
|
||||||
Then to add abstraction of similar behaviour with variables (in multivariate case) there are
|
Then to add abstraction of similar behaviour with variables (in multivariate case) there are implemented `MultivariatePolynomialSpace` and `MultivariateRationalFunctionSpace`. They just include variables (of type `V`) in the interactions of the entities.
|
||||||
implemented `MultivariatePolynomialSpace` and `MultivariateRationalFunctionSpace`. They just include variables (of
|
|
||||||
type `V`) in the interactions of the entities.
|
|
||||||
|
|
||||||
Also, to remove boilerplates there were provided helping subinterfaces and abstract subclasses:
|
Also, to remove boilerplates there were provided helping subinterfaces and abstract subclasses:
|
||||||
|
- `PolynomialSpaceOverRing` allows to replace implementation of interactions of integers and constants with implementations from provided ring over constants (of type `A: Ring<C>`).
|
||||||
- `PolynomialSpaceOverRing` allows to replace implementation of interactions of integers and constants with
|
|
||||||
implementations from provided ring over constants (of type `A: Ring<C>`).
|
|
||||||
- `RationalFunctionSpaceOverRing` — the same but for `RationalFunctionSpace`.
|
- `RationalFunctionSpaceOverRing` — the same but for `RationalFunctionSpace`.
|
||||||
- `RationalFunctionSpaceOverPolynomialSpace` — the same but "the inheritance" includes interactions with
|
- `RationalFunctionSpaceOverPolynomialSpace` — the same but "the inheritance" includes interactions with polynomials from provided `PolynomialSpace`.
|
||||||
polynomials from provided `PolynomialSpace`.
|
- `PolynomialSpaceOfFractions` is actually abstract subclass of `RationalFunctionSpace` that implements all fractions boilerplates with provided (`protected`) constructor of rational functions by polynomial numerator and denominator.
|
||||||
- `PolynomialSpaceOfFractions` is actually abstract subclass of `RationalFunctionSpace` that implements all fractions
|
- `MultivariateRationalFunctionSpaceOverMultivariatePolynomialSpace` and `MultivariatePolynomialSpaceOfFractions` — the same stories of operators inheritance and fractions boilerplates respectively but in multivariate case.
|
||||||
boilerplates with provided (`protected`) constructor of rational functions by polynomial numerator and denominator.
|
|
||||||
- `MultivariateRationalFunctionSpaceOverMultivariatePolynomialSpace` and `MultivariatePolynomialSpaceOfFractions`
|
|
||||||
— the same stories of operators inheritance and fractions boilerplates respectively but in multivariate case.
|
|
||||||
|
|
||||||
## Utilities
|
## Utilities
|
||||||
|
|
||||||
For all kinds of polynomials there are provided (implementation details depend on kind of polynomials) such common
|
For all kinds of polynomials there are provided (implementation details depend on kind of polynomials) such common utilities as:
|
||||||
utilities as:
|
|
||||||
|
|
||||||
1. differentiation and anti-differentiation,
|
1. differentiation and anti-differentiation,
|
||||||
2. substitution, invocation and functional representation.
|
2. substitution, invocation and functional representation.
|
14
docs/templates/ARTIFACT-TEMPLATE.md
vendored
@ -3,11 +3,25 @@
|
|||||||
The Maven coordinates of this project are `${group}:${name}:${version}`.
|
The Maven coordinates of this project are `${group}:${name}:${version}`.
|
||||||
|
|
||||||
**Gradle:**
|
**Gradle:**
|
||||||
|
```groovy
|
||||||
|
repositories {
|
||||||
|
maven { url 'https://repo.kotlin.link' }
|
||||||
|
mavenCentral()
|
||||||
|
// development and snapshot versions
|
||||||
|
maven { url 'https://maven.pkg.jetbrains.space/spc/p/sci/dev' }
|
||||||
|
}
|
||||||
|
|
||||||
|
dependencies {
|
||||||
|
implementation '${group}:${name}:${version}'
|
||||||
|
}
|
||||||
|
```
|
||||||
|
**Gradle Kotlin DSL:**
|
||||||
```kotlin
|
```kotlin
|
||||||
repositories {
|
repositories {
|
||||||
maven("https://repo.kotlin.link")
|
maven("https://repo.kotlin.link")
|
||||||
mavenCentral()
|
mavenCentral()
|
||||||
|
// development and snapshot versions
|
||||||
|
maven("https://maven.pkg.jetbrains.space/spc/p/sci/dev")
|
||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
|
33
docs/templates/README-TEMPLATE.md
vendored
@ -11,22 +11,18 @@ analog to Python's NumPy library. Later we found that kotlin is much more flexib
|
|||||||
architecture designs. In contrast to `numpy` and `scipy` it is modular and has a lightweight core. The `numpy`-like
|
architecture designs. In contrast to `numpy` and `scipy` it is modular and has a lightweight core. The `numpy`-like
|
||||||
experience could be achieved with [kmath-for-real](/kmath-for-real) extension module.
|
experience could be achieved with [kmath-for-real](/kmath-for-real) extension module.
|
||||||
|
|
||||||
[Documentation site](https://SciProgCentre.github.io/kmath/)
|
[Documentation site (**WIP**)](https://SciProgCentre.github.io/kmath/)
|
||||||
|
|
||||||
## Publications and talks
|
## Publications and talks
|
||||||
|
|
||||||
* [A conceptual article about context-oriented design](https://proandroiddev.com/an-introduction-context-oriented-programming-in-kotlin-2e79d316b0a2)
|
* [A conceptual article about context-oriented design](https://proandroiddev.com/an-introduction-context-oriented-programming-in-kotlin-2e79d316b0a2)
|
||||||
* [Another article about context-oriented design](https://proandroiddev.com/diving-deeper-into-context-oriented-programming-in-kotlin-3ecb4ec38814)
|
* [Another article about context-oriented design](https://proandroiddev.com/diving-deeper-into-context-oriented-programming-in-kotlin-3ecb4ec38814)
|
||||||
* [ACAT 2019 conference paper](https://aip.scitation.org/doi/abs/10.1063/1.5130103)
|
* [ACAT 2019 conference paper](https://aip.scitation.org/doi/abs/10.1063/1.5130103)
|
||||||
* [A talk at KotlinConf 2019 about using kotlin for science](https://youtu.be/LI_5TZ7tnOE?si=4LknX41gl_YeUbIe)
|
|
||||||
* [A talk on architecture at Joker-2021 (in Russian)](https://youtu.be/1bZ2doHiRRM?si=9w953ro9yu98X_KJ)
|
|
||||||
* [The same talk in English](https://youtu.be/yP5DIc2fVwQ?si=louZzQ1dcXV6gP10)
|
|
||||||
* [A seminar on tensor API](https://youtu.be/0H99wUs0xTM?si=6c__04jrByFQtVpo)
|
|
||||||
|
|
||||||
# Goal
|
# Goal
|
||||||
|
|
||||||
* Provide a flexible and powerful API to work with mathematics abstractions in Kotlin-multiplatform (JVM, JS, Native and
|
* Provide a flexible and powerful API to work with mathematics abstractions in Kotlin-multiplatform (JVM, JS and Native)
|
||||||
Wasm).
|
.
|
||||||
* Provide basic multiplatform implementations for those abstractions (without significant performance optimization).
|
* Provide basic multiplatform implementations for those abstractions (without significant performance optimization).
|
||||||
* Provide bindings and wrappers with those abstractions for popular optimized platform libraries.
|
* Provide bindings and wrappers with those abstractions for popular optimized platform libraries.
|
||||||
|
|
||||||
@ -63,24 +59,22 @@ ${modules}
|
|||||||
KMath is developed as a multi-platform library, which means that most of the interfaces are declared in the
|
KMath is developed as a multi-platform library, which means that most of the interfaces are declared in the
|
||||||
[common source sets](/kmath-core/src/commonMain) and implemented there wherever it is possible. In some cases, features
|
[common source sets](/kmath-core/src/commonMain) and implemented there wherever it is possible. In some cases, features
|
||||||
are delegated to platform-specific implementations even if they could be provided in the common module for performance
|
are delegated to platform-specific implementations even if they could be provided in the common module for performance
|
||||||
reasons. Currently, Kotlin/JVM is the primary platform, however, Kotlin/Native and Kotlin/JS contributions and
|
reasons. Currently, the Kotlin/JVM is the primary platform, however Kotlin/Native and Kotlin/JS contributions and
|
||||||
feedback are also welcome.
|
feedback are also welcome.
|
||||||
|
|
||||||
## Performance
|
## Performance
|
||||||
|
|
||||||
Calculation of performance is one of the major goals of KMath in the future, but in some cases it is impossible to
|
Calculation performance is one of major goals of KMath in the future, but in some cases it is impossible to achieve both
|
||||||
achieve both
|
|
||||||
performance and flexibility.
|
performance and flexibility.
|
||||||
|
|
||||||
We expect to focus on creating a convenient universal API first and then work on increasing performance for specific
|
We expect to focus on creating convenient universal API first and then work on increasing performance for specific
|
||||||
cases. We expect the worst KMath benchmarks will perform better than native Python, but worse than optimized
|
cases. We expect the worst KMath benchmarks will perform better than native Python, but worse than optimized
|
||||||
native/SciPy (mostly due to boxing operations on primitive numbers). The best performance of optimized parts could be
|
native/SciPy (mostly due to boxing operations on primitive numbers). The best performance of optimized parts could be better than SciPy.
|
||||||
better than SciPy.
|
|
||||||
|
|
||||||
## Requirements
|
## Requirements
|
||||||
|
|
||||||
KMath currently relies on JDK 11 for compilation and execution of Kotlin-JVM part. We recommend using GraalVM-CE or
|
KMath currently relies on JDK 11 for compilation and execution of Kotlin-JVM part. We recommend to use GraalVM-CE 11 for
|
||||||
Oracle GraalVM for execution to get better performance.
|
execution to get better performance.
|
||||||
|
|
||||||
### Repositories
|
### Repositories
|
||||||
|
|
||||||
@ -100,10 +94,11 @@ dependencies {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
Gradle `6.0+` is required for multiplatform artifacts.
|
||||||
|
|
||||||
## Contributing
|
## Contributing
|
||||||
|
|
||||||
The project requires a lot of additional work. The most important thing we need is 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
|
||||||
required the most. Feel free to create feature requests. We are also welcome to code contributions, especially in issues
|
required the most. Feel free to create feature requests. We are also welcome to code contributions, especially in issues
|
||||||
marked
|
marked with
|
||||||
with [good first issue](hhttps://github.com/SciProgCentre/kmath/issues?q=is%3Aissue+is%3Aopen+label%3A%22good+first+issue%22)
|
[waiting for a hero](https://github.com/mipt-npm/kmath/labels/waiting%20for%20a%20hero) label.
|
||||||
label.
|
|
@ -10,6 +10,8 @@ repositories {
|
|||||||
maven("https://maven.pkg.jetbrains.space/kotlin/p/kotlin/kotlin-js-wrappers")
|
maven("https://maven.pkg.jetbrains.space/kotlin/p/kotlin/kotlin-js-wrappers")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
val multikVersion: String by rootProject.extra
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
implementation(project(":kmath-ast"))
|
implementation(project(":kmath-ast"))
|
||||||
implementation(project(":kmath-kotlingrad"))
|
implementation(project(":kmath-kotlingrad"))
|
||||||
@ -31,7 +33,7 @@ dependencies {
|
|||||||
implementation(project(":kmath-jafama"))
|
implementation(project(":kmath-jafama"))
|
||||||
//multik
|
//multik
|
||||||
implementation(project(":kmath-multik"))
|
implementation(project(":kmath-multik"))
|
||||||
implementation(libs.multik.default)
|
implementation("org.jetbrains.kotlinx:multik-default:$multikVersion")
|
||||||
|
|
||||||
//datetime
|
//datetime
|
||||||
implementation("org.jetbrains.kotlinx:kotlinx-datetime:0.4.0")
|
implementation("org.jetbrains.kotlinx:kotlinx-datetime:0.4.0")
|
||||||
@ -50,7 +52,7 @@ dependencies {
|
|||||||
|
|
||||||
implementation("org.slf4j:slf4j-simple:1.7.32")
|
implementation("org.slf4j:slf4j-simple:1.7.32")
|
||||||
// plotting
|
// plotting
|
||||||
implementation("space.kscience:plotlykt-server:0.7.0")
|
implementation("space.kscience:plotlykt-server:0.5.0")
|
||||||
}
|
}
|
||||||
|
|
||||||
kotlin {
|
kotlin {
|
||||||
@ -65,8 +67,8 @@ kotlin {
|
|||||||
}
|
}
|
||||||
|
|
||||||
tasks.withType<KotlinJvmCompile> {
|
tasks.withType<KotlinJvmCompile> {
|
||||||
compilerOptions {
|
kotlinOptions {
|
||||||
freeCompilerArgs.addAll("-Xjvm-default=all", "-Xopt-in=kotlin.RequiresOptIn", "-Xlambdas=indy")
|
freeCompilerArgs = freeCompilerArgs + "-Xjvm-default=all" + "-Xopt-in=kotlin.RequiresOptIn" + "-Xlambdas=indy"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2018-2024 KMath contributors.
|
* Copyright 2018-2022 KMath contributors.
|
||||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2018-2024 KMath contributors.
|
* Copyright 2018-2022 KMath contributors.
|
||||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@ -8,13 +8,13 @@ package space.kscience.kmath.ast
|
|||||||
import space.kscience.kmath.asm.compileToExpression
|
import space.kscience.kmath.asm.compileToExpression
|
||||||
import space.kscience.kmath.expressions.MstExtendedField
|
import space.kscience.kmath.expressions.MstExtendedField
|
||||||
import space.kscience.kmath.expressions.Symbol.Companion.x
|
import space.kscience.kmath.expressions.Symbol.Companion.x
|
||||||
import space.kscience.kmath.operations.Float64Field
|
import space.kscience.kmath.operations.DoubleField
|
||||||
import space.kscience.kmath.operations.invoke
|
import space.kscience.kmath.operations.invoke
|
||||||
|
|
||||||
fun main() {
|
fun main() {
|
||||||
val expr = MstExtendedField {
|
val expr = MstExtendedField {
|
||||||
x * 2.0 + number(2.0) / x - number(16.0) + asinh(x) / sin(x)
|
x * 2.0 + number(2.0) / x - number(16.0) + asinh(x) / sin(x)
|
||||||
}.compileToExpression(Float64Field)
|
}.compileToExpression(DoubleField)
|
||||||
|
|
||||||
val m = DoubleArray(expr.indexer.symbols.size)
|
val m = DoubleArray(expr.indexer.symbols.size)
|
||||||
val xIdx = expr.indexer.indexOf(x)
|
val xIdx = expr.indexer.indexOf(x)
|
||||||
|
@ -1,16 +1,16 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2018-2024 KMath contributors.
|
* Copyright 2018-2022 KMath contributors.
|
||||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package space.kscience.kmath.ast
|
package space.kscience.kmath.ast
|
||||||
|
|
||||||
import space.kscience.kmath.expressions.Symbol.Companion.x
|
|
||||||
import space.kscience.kmath.expressions.derivative
|
import space.kscience.kmath.expressions.derivative
|
||||||
import space.kscience.kmath.expressions.invoke
|
import space.kscience.kmath.expressions.invoke
|
||||||
|
import space.kscience.kmath.expressions.Symbol.Companion.x
|
||||||
import space.kscience.kmath.expressions.toExpression
|
import space.kscience.kmath.expressions.toExpression
|
||||||
import space.kscience.kmath.kotlingrad.toKotlingradExpression
|
import space.kscience.kmath.kotlingrad.toKotlingradExpression
|
||||||
import space.kscience.kmath.operations.Float64Field
|
import space.kscience.kmath.operations.DoubleField
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* In this example, *x<sup>2</sup> − 4 x − 44* function is differentiated with Kotlin∇, and the
|
* In this example, *x<sup>2</sup> − 4 x − 44* function is differentiated with Kotlin∇, and the
|
||||||
@ -19,9 +19,9 @@ import space.kscience.kmath.operations.Float64Field
|
|||||||
fun main() {
|
fun main() {
|
||||||
val actualDerivative = "x^2-4*x-44"
|
val actualDerivative = "x^2-4*x-44"
|
||||||
.parseMath()
|
.parseMath()
|
||||||
.toKotlingradExpression(Float64Field)
|
.toKotlingradExpression(DoubleField)
|
||||||
.derivative(x)
|
.derivative(x)
|
||||||
|
|
||||||
val expectedDerivative = "2*x-4".parseMath().toExpression(Float64Field)
|
val expectedDerivative = "2*x-4".parseMath().toExpression(DoubleField)
|
||||||
check(actualDerivative(x to 123.0) == expectedDerivative(x to 123.0))
|
check(actualDerivative(x to 123.0) == expectedDerivative(x to 123.0))
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2018-2024 KMath contributors.
|
* Copyright 2018-2022 KMath contributors.
|
||||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@ -9,7 +9,7 @@ import space.kscience.kmath.expressions.Symbol.Companion.x
|
|||||||
import space.kscience.kmath.expressions.derivative
|
import space.kscience.kmath.expressions.derivative
|
||||||
import space.kscience.kmath.expressions.invoke
|
import space.kscience.kmath.expressions.invoke
|
||||||
import space.kscience.kmath.expressions.toExpression
|
import space.kscience.kmath.expressions.toExpression
|
||||||
import space.kscience.kmath.operations.Float64Field
|
import space.kscience.kmath.operations.DoubleField
|
||||||
import space.kscience.kmath.symja.toSymjaExpression
|
import space.kscience.kmath.symja.toSymjaExpression
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -19,9 +19,9 @@ import space.kscience.kmath.symja.toSymjaExpression
|
|||||||
fun main() {
|
fun main() {
|
||||||
val actualDerivative = "x^2-4*x-44"
|
val actualDerivative = "x^2-4*x-44"
|
||||||
.parseMath()
|
.parseMath()
|
||||||
.toSymjaExpression(Float64Field)
|
.toSymjaExpression(DoubleField)
|
||||||
.derivative(x)
|
.derivative(x)
|
||||||
|
|
||||||
val expectedDerivative = "2*x-4".parseMath().toExpression(Float64Field)
|
val expectedDerivative = "2*x-4".parseMath().toExpression(DoubleField)
|
||||||
check(actualDerivative(x to 123.0) == expectedDerivative(x to 123.0))
|
check(actualDerivative(x to 123.0) == expectedDerivative(x to 123.0))
|
||||||
}
|
}
|
||||||
|
@ -1,12 +1,11 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2018-2024 KMath contributors.
|
* Copyright 2018-2023 KMath contributors.
|
||||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package space.kscience.kmath.expressions
|
package space.kscience.kmath.expressions
|
||||||
|
|
||||||
import space.kscience.kmath.UnstableKMathAPI
|
import space.kscience.kmath.UnstableKMathAPI
|
||||||
|
|
||||||
// Only kmath-core is needed.
|
// Only kmath-core is needed.
|
||||||
|
|
||||||
// Let's declare some variables
|
// Let's declare some variables
|
||||||
@ -52,7 +51,7 @@ fun main() {
|
|||||||
// >>> 0.0
|
// >>> 0.0
|
||||||
|
|
||||||
// But in case you forgot to specify bound symbol's value, exception is thrown:
|
// But in case you forgot to specify bound symbol's value, exception is thrown:
|
||||||
println(runCatching { someExpression(z to 4.0) })
|
println( runCatching { someExpression(z to 4.0) } )
|
||||||
// >>> Failure(java.lang.IllegalStateException: Symbol 'x' is not supported in ...)
|
// >>> Failure(java.lang.IllegalStateException: Symbol 'x' is not supported in ...)
|
||||||
|
|
||||||
// The reason is that the expression is evaluated lazily,
|
// The reason is that the expression is evaluated lazily,
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2018-2024 KMath contributors.
|
* Copyright 2018-2022 KMath contributors.
|
||||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@ -13,7 +13,10 @@ import space.kscience.kmath.expressions.autodiff
|
|||||||
import space.kscience.kmath.expressions.symbol
|
import space.kscience.kmath.expressions.symbol
|
||||||
import space.kscience.kmath.operations.asIterable
|
import space.kscience.kmath.operations.asIterable
|
||||||
import space.kscience.kmath.operations.toList
|
import space.kscience.kmath.operations.toList
|
||||||
import space.kscience.kmath.optimization.*
|
import space.kscience.kmath.optimization.FunctionOptimizationTarget
|
||||||
|
import space.kscience.kmath.optimization.optimizeWith
|
||||||
|
import space.kscience.kmath.optimization.resultPoint
|
||||||
|
import space.kscience.kmath.optimization.resultValue
|
||||||
import space.kscience.kmath.random.RandomGenerator
|
import space.kscience.kmath.random.RandomGenerator
|
||||||
import space.kscience.kmath.real.DoubleVector
|
import space.kscience.kmath.real.DoubleVector
|
||||||
import space.kscience.kmath.real.map
|
import space.kscience.kmath.real.map
|
||||||
@ -77,9 +80,8 @@ suspend fun main() {
|
|||||||
val result = chi2.optimizeWith(
|
val result = chi2.optimizeWith(
|
||||||
CMOptimizer,
|
CMOptimizer,
|
||||||
mapOf(a to 1.5, b to 0.9, c to 1.0),
|
mapOf(a to 1.5, b to 0.9, c to 1.0),
|
||||||
) {
|
FunctionOptimizationTarget.MINIMIZE
|
||||||
FunctionOptimizationTarget(OptimizationDirection.MINIMIZE)
|
)
|
||||||
}
|
|
||||||
|
|
||||||
//display a page with plot and numerical results
|
//display a page with plot and numerical results
|
||||||
val page = Plotly.page {
|
val page = Plotly.page {
|
||||||
@ -96,7 +98,7 @@ suspend fun main() {
|
|||||||
scatter {
|
scatter {
|
||||||
mode = ScatterMode.lines
|
mode = ScatterMode.lines
|
||||||
x(x)
|
x(x)
|
||||||
y(x.map { result.result[a]!! * it.pow(2) + result.result[b]!! * it + 1 })
|
y(x.map { result.resultPoint[a]!! * it.pow(2) + result.resultPoint[b]!! * it + 1 })
|
||||||
name = "fit"
|
name = "fit"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2018-2024 KMath contributors.
|
* Copyright 2018-2022 KMath contributors.
|
||||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@ -7,7 +7,6 @@ package space.kscience.kmath.fit
|
|||||||
|
|
||||||
import kotlinx.html.br
|
import kotlinx.html.br
|
||||||
import kotlinx.html.h3
|
import kotlinx.html.h3
|
||||||
import space.kscience.attributes.Attributes
|
|
||||||
import space.kscience.kmath.data.XYErrorColumnarData
|
import space.kscience.kmath.data.XYErrorColumnarData
|
||||||
import space.kscience.kmath.distributions.NormalDistribution
|
import space.kscience.kmath.distributions.NormalDistribution
|
||||||
import space.kscience.kmath.expressions.Symbol
|
import space.kscience.kmath.expressions.Symbol
|
||||||
@ -65,7 +64,7 @@ suspend fun main() {
|
|||||||
QowOptimizer,
|
QowOptimizer,
|
||||||
Double.autodiff,
|
Double.autodiff,
|
||||||
mapOf(a to 0.9, b to 1.2, c to 2.0, e to 1.0, d to 1.0, e to 0.0),
|
mapOf(a to 0.9, b to 1.2, c to 2.0, e to 1.0, d to 1.0, e to 0.0),
|
||||||
attributes = Attributes(OptimizationParameters, listOf(a, b, c, d))
|
OptimizationParameters(a, b, c, d)
|
||||||
) { arg ->
|
) { arg ->
|
||||||
//bind variables to autodiff context
|
//bind variables to autodiff context
|
||||||
val a by binding
|
val a by binding
|
||||||
@ -95,13 +94,13 @@ suspend fun main() {
|
|||||||
scatter {
|
scatter {
|
||||||
mode = ScatterMode.lines
|
mode = ScatterMode.lines
|
||||||
x(x)
|
x(x)
|
||||||
y(x.map { result.model(result.startPoint + result.result + (Symbol.x to it)) })
|
y(x.map { result.model(result.startPoint + result.resultPoint + (Symbol.x to it)) })
|
||||||
name = "fit"
|
name = "fit"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
br()
|
br()
|
||||||
h3 {
|
h3 {
|
||||||
+"Fit result: ${result.result}"
|
+"Fit result: ${result.resultPoint}"
|
||||||
}
|
}
|
||||||
h3 {
|
h3 {
|
||||||
+"Chi2/dof = ${result.chiSquaredOrNull!! / result.dof}"
|
+"Chi2/dof = ${result.chiSquaredOrNull!! / result.dof}"
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2018-2024 KMath contributors.
|
* Copyright 2018-2022 KMath contributors.
|
||||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@ -13,16 +13,15 @@ import space.kscience.kmath.complex.algebra
|
|||||||
import space.kscience.kmath.integration.gaussIntegrator
|
import space.kscience.kmath.integration.gaussIntegrator
|
||||||
import space.kscience.kmath.integration.integrate
|
import space.kscience.kmath.integration.integrate
|
||||||
import space.kscience.kmath.integration.value
|
import space.kscience.kmath.integration.value
|
||||||
import space.kscience.kmath.operations.Float64Field
|
import space.kscience.kmath.operations.DoubleField
|
||||||
import space.kscience.kmath.structures.Float64
|
|
||||||
import kotlin.math.pow
|
import kotlin.math.pow
|
||||||
|
|
||||||
fun main() {
|
fun main() {
|
||||||
//Define a function
|
//Define a function
|
||||||
val function: Function1D<Float64> = { x -> 3 * x.pow(2) + 2 * x + 1 }
|
val function: Function1D<Double> = { x -> 3 * x.pow(2) + 2 * x + 1 }
|
||||||
|
|
||||||
//get the result of the integration
|
//get the result of the integration
|
||||||
val result = Float64Field.gaussIntegrator.integrate(0.0..10.0, function = function)
|
val result = DoubleField.gaussIntegrator.integrate(0.0..10.0, function = function)
|
||||||
|
|
||||||
//the value is nullable because in some cases the integration could not succeed
|
//the value is nullable because in some cases the integration could not succeed
|
||||||
println(result.value)
|
println(result.value)
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2018-2024 KMath contributors.
|
* Copyright 2018-2022 KMath contributors.
|
||||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@ -7,8 +7,8 @@ package space.kscience.kmath.functions
|
|||||||
|
|
||||||
import space.kscience.kmath.interpolation.SplineInterpolator
|
import space.kscience.kmath.interpolation.SplineInterpolator
|
||||||
import space.kscience.kmath.interpolation.interpolatePolynomials
|
import space.kscience.kmath.interpolation.interpolatePolynomials
|
||||||
import space.kscience.kmath.operations.Float64Field
|
import space.kscience.kmath.operations.DoubleField
|
||||||
import space.kscience.kmath.structures.Float64
|
import space.kscience.kmath.structures.DoubleBuffer
|
||||||
import space.kscience.plotly.Plotly
|
import space.kscience.plotly.Plotly
|
||||||
import space.kscience.plotly.UnstablePlotlyAPI
|
import space.kscience.plotly.UnstablePlotlyAPI
|
||||||
import space.kscience.plotly.makeFile
|
import space.kscience.plotly.makeFile
|
||||||
@ -24,9 +24,11 @@ fun main() {
|
|||||||
x to sin(x)
|
x to sin(x)
|
||||||
}
|
}
|
||||||
|
|
||||||
val polynomial: PiecewisePolynomial<Float64> = SplineInterpolator(Float64Field).interpolatePolynomials(data)
|
val polynomial: PiecewisePolynomial<Double> = SplineInterpolator(
|
||||||
|
DoubleField, ::DoubleBuffer
|
||||||
|
).interpolatePolynomials(data)
|
||||||
|
|
||||||
val function = polynomial.asFunction(Float64Field, 0.0)
|
val function = polynomial.asFunction(DoubleField, 0.0)
|
||||||
|
|
||||||
val cmInterpolate = org.apache.commons.math3.analysis.interpolation.SplineInterpolator().interpolate(
|
val cmInterpolate = org.apache.commons.math3.analysis.interpolation.SplineInterpolator().interpolate(
|
||||||
data.map { it.first }.toDoubleArray(),
|
data.map { it.first }.toDoubleArray(),
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2018-2024 KMath contributors.
|
* Copyright 2018-2022 KMath contributors.
|
||||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@ -7,10 +7,9 @@ package space.kscience.kmath.functions
|
|||||||
|
|
||||||
import space.kscience.kmath.interpolation.interpolatePolynomials
|
import space.kscience.kmath.interpolation.interpolatePolynomials
|
||||||
import space.kscience.kmath.interpolation.splineInterpolator
|
import space.kscience.kmath.interpolation.splineInterpolator
|
||||||
import space.kscience.kmath.operations.Float64Field
|
import space.kscience.kmath.operations.DoubleField
|
||||||
import space.kscience.kmath.real.map
|
import space.kscience.kmath.real.map
|
||||||
import space.kscience.kmath.real.step
|
import space.kscience.kmath.real.step
|
||||||
import space.kscience.kmath.structures.Float64
|
|
||||||
import space.kscience.plotly.Plotly
|
import space.kscience.plotly.Plotly
|
||||||
import space.kscience.plotly.UnstablePlotlyAPI
|
import space.kscience.plotly.UnstablePlotlyAPI
|
||||||
import space.kscience.plotly.makeFile
|
import space.kscience.plotly.makeFile
|
||||||
@ -19,7 +18,7 @@ import space.kscience.plotly.scatter
|
|||||||
|
|
||||||
@OptIn(UnstablePlotlyAPI::class)
|
@OptIn(UnstablePlotlyAPI::class)
|
||||||
fun main() {
|
fun main() {
|
||||||
val function: Function1D<Float64> = { x ->
|
val function: Function1D<Double> = { x ->
|
||||||
if (x in 30.0..50.0) {
|
if (x in 30.0..50.0) {
|
||||||
1.0
|
1.0
|
||||||
} else {
|
} else {
|
||||||
@ -29,9 +28,9 @@ fun main() {
|
|||||||
val xs = 0.0..100.0 step 0.5
|
val xs = 0.0..100.0 step 0.5
|
||||||
val ys = xs.map(function)
|
val ys = xs.map(function)
|
||||||
|
|
||||||
val polynomial: PiecewisePolynomial<Float64> = Float64Field.splineInterpolator.interpolatePolynomials(xs, ys)
|
val polynomial: PiecewisePolynomial<Double> = DoubleField.splineInterpolator.interpolatePolynomials(xs, ys)
|
||||||
|
|
||||||
val polyFunction = polynomial.asFunction(Float64Field, 0.0)
|
val polyFunction = polynomial.asFunction(DoubleField, 0.0)
|
||||||
|
|
||||||
Plotly.plot {
|
Plotly.plot {
|
||||||
scatter {
|
scatter {
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2018-2024 KMath contributors.
|
* Copyright 2018-2022 KMath contributors.
|
||||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@ -12,7 +12,6 @@ import space.kscience.kmath.nd.StructureND
|
|||||||
import space.kscience.kmath.nd.structureND
|
import space.kscience.kmath.nd.structureND
|
||||||
import space.kscience.kmath.nd.withNdAlgebra
|
import space.kscience.kmath.nd.withNdAlgebra
|
||||||
import space.kscience.kmath.operations.algebra
|
import space.kscience.kmath.operations.algebra
|
||||||
import space.kscience.kmath.structures.Float64
|
|
||||||
import kotlin.math.pow
|
import kotlin.math.pow
|
||||||
|
|
||||||
fun main(): Unit = Double.algebra.withNdAlgebra(2, 2) {
|
fun main(): Unit = Double.algebra.withNdAlgebra(2, 2) {
|
||||||
@ -23,7 +22,7 @@ fun main(): Unit = Double.algebra.withNdAlgebra(2, 2) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
//Define a function in a nd space
|
//Define a function in a nd space
|
||||||
val function: (Double) -> StructureND<Float64> = { x: Double -> 3 * x.pow(2) + 2 * diagonal(x) + 1 }
|
val function: (Double) -> StructureND<Double> = { x: Double -> 3 * x.pow(2) + 2 * diagonal(x) + 1 }
|
||||||
|
|
||||||
//get the result of the integration
|
//get the result of the integration
|
||||||
val result = gaussIntegrator.integrate(0.0..10.0, function = function)
|
val result = gaussIntegrator.integrate(0.0..10.0, function = function)
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2018-2024 KMath contributors.
|
* Copyright 2018-2022 KMath contributors.
|
||||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
@ -1,28 +1,33 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2018-2024 KMath contributors.
|
* Copyright 2018-2022 KMath contributors.
|
||||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package space.kscience.kmath.linear
|
package space.kscience.kmath.linear
|
||||||
|
|
||||||
|
import space.kscience.kmath.operations.algebra
|
||||||
import kotlin.random.Random
|
import kotlin.random.Random
|
||||||
|
import kotlin.time.ExperimentalTime
|
||||||
import kotlin.time.measureTime
|
import kotlin.time.measureTime
|
||||||
|
|
||||||
fun main() = with(Float64ParallelLinearSpace) {
|
@OptIn(ExperimentalTime::class)
|
||||||
|
fun main() {
|
||||||
val random = Random(12224)
|
val random = Random(12224)
|
||||||
val dim = 1000
|
val dim = 1000
|
||||||
|
|
||||||
//creating invertible matrix
|
//creating invertible matrix
|
||||||
val matrix1 = buildMatrix(dim, dim) { i, j ->
|
val matrix1 = Double.algebra.linearSpace.buildMatrix(dim, dim) { i, j ->
|
||||||
if (i <= j) random.nextDouble() else 0.0
|
if (i <= j) random.nextDouble() else 0.0
|
||||||
}
|
}
|
||||||
val matrix2 = buildMatrix(dim, dim) { i, j ->
|
val matrix2 = Double.algebra.linearSpace.buildMatrix(dim, dim) { i, j ->
|
||||||
if (i <= j) random.nextDouble() else 0.0
|
if (i <= j) random.nextDouble() else 0.0
|
||||||
}
|
}
|
||||||
|
|
||||||
val time = measureTime {
|
val time = measureTime {
|
||||||
repeat(30) {
|
with(Double.algebra.linearSpace) {
|
||||||
matrix1 dot matrix2
|
repeat(10) {
|
||||||
|
matrix1 dot matrix2
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,40 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2018-2024 KMath contributors.
|
|
||||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package space.kscience.kmath.linear
|
|
||||||
|
|
||||||
import space.kscience.kmath.commons.linear.CMLinearSpace
|
|
||||||
import space.kscience.kmath.ejml.EjmlLinearSpaceDDRM
|
|
||||||
import space.kscience.kmath.nd.StructureND
|
|
||||||
import space.kscience.kmath.operations.algebra
|
|
||||||
import space.kscience.kmath.structures.Float64
|
|
||||||
import kotlin.random.Random
|
|
||||||
|
|
||||||
fun main() {
|
|
||||||
val dim = 46
|
|
||||||
|
|
||||||
val random = Random(123)
|
|
||||||
|
|
||||||
val u = Float64.algebra.linearSpace.buildMatrix(dim, dim) { i, j -> if (i <= j) random.nextDouble() else 0.0 }
|
|
||||||
|
|
||||||
listOf(CMLinearSpace, EjmlLinearSpaceDDRM).forEach { algebra ->
|
|
||||||
with(algebra) {
|
|
||||||
//create a simmetric matrix
|
|
||||||
val matrix = buildMatrix(dim, dim) { row, col ->
|
|
||||||
if (row >= col) u[row, col] else u[col, row]
|
|
||||||
}
|
|
||||||
val eigen = matrix.getOrComputeAttribute(EIG) ?: error("Failed to compute eigenvalue decomposition")
|
|
||||||
check(
|
|
||||||
StructureND.contentEquals(
|
|
||||||
matrix,
|
|
||||||
eigen.v dot eigen.d dot eigen.v.transposed(),
|
|
||||||
1e-4
|
|
||||||
)
|
|
||||||
) { "$algebra decomposition failed" }
|
|
||||||
println("$algebra eigenvalue decomposition complete and checked" )
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -1,28 +1,27 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2018-2024 KMath contributors.
|
* Copyright 2018-2022 KMath contributors.
|
||||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package space.kscience.kmath.linear
|
package space.kscience.kmath.linear
|
||||||
|
|
||||||
import space.kscience.kmath.real.*
|
import space.kscience.kmath.real.*
|
||||||
import space.kscience.kmath.structures.Float64
|
import space.kscience.kmath.structures.DoubleBuffer
|
||||||
import space.kscience.kmath.structures.Float64Buffer
|
|
||||||
|
|
||||||
fun main() {
|
fun main() {
|
||||||
val x0 = DoubleVector(0.0, 0.0, 0.0)
|
val x0 = DoubleVector(0.0, 0.0, 0.0)
|
||||||
val sigma = DoubleVector(1.0, 1.0, 1.0)
|
val sigma = DoubleVector(1.0, 1.0, 1.0)
|
||||||
|
|
||||||
val gaussian: (Point<Float64>) -> Double = { x ->
|
val gaussian: (Point<Double>) -> Double = { x ->
|
||||||
require(x.size == x0.size)
|
require(x.size == x0.size)
|
||||||
kotlin.math.exp(-((x - x0) / sigma).square().sum())
|
kotlin.math.exp(-((x - x0) / sigma).square().sum())
|
||||||
}
|
}
|
||||||
|
|
||||||
fun ((Point<Float64>) -> Double).grad(x: Point<Float64>): Point<Float64> {
|
fun ((Point<Double>) -> Double).grad(x: Point<Double>): Point<Double> {
|
||||||
require(x.size == x0.size)
|
require(x.size == x0.size)
|
||||||
return Float64Buffer(x.size) { i ->
|
return DoubleBuffer(x.size) { i ->
|
||||||
val h = sigma[i] / 5
|
val h = sigma[i] / 5
|
||||||
val dVector = Float64Buffer(x.size) { if (it == i) h else 0.0 }
|
val dVector = DoubleBuffer(x.size) { if (it == i) h else 0.0 }
|
||||||
val f1 = this(x + dVector / 2)
|
val f1 = this(x + dVector / 2)
|
||||||
val f0 = this(x - dVector / 2)
|
val f0 = this(x - dVector / 2)
|
||||||
(f1 - f0) / h
|
(f1 - f0) / h
|
||||||
|
@ -1,27 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2018-2024 KMath contributors.
|
|
||||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package space.kscience.kmath.linear
|
|
||||||
|
|
||||||
import kotlin.random.Random
|
|
||||||
import kotlin.time.measureTime
|
|
||||||
|
|
||||||
fun main(): Unit = with(Float64LinearSpace) {
|
|
||||||
val random = Random(1224)
|
|
||||||
val dim = 500
|
|
||||||
|
|
||||||
//creating invertible matrix
|
|
||||||
val u = buildMatrix(dim, dim) { i, j -> if (i <= j) random.nextDouble() else 0.0 }
|
|
||||||
val l = buildMatrix(dim, dim) { i, j -> if (i >= j) random.nextDouble() else 0.0 }
|
|
||||||
val matrix = l dot u
|
|
||||||
|
|
||||||
val time = measureTime {
|
|
||||||
repeat(20) {
|
|
||||||
lupSolver().inverse(matrix)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
println(time)
|
|
||||||
}
|
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2018-2024 KMath contributors.
|
* Copyright 2018-2022 KMath contributors.
|
||||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2018-2024 KMath contributors.
|
* Copyright 2018-2022 KMath contributors.
|
||||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2018-2024 KMath contributors.
|
* Copyright 2018-2022 KMath contributors.
|
||||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@ -7,23 +7,21 @@ package space.kscience.kmath.operations
|
|||||||
|
|
||||||
import space.kscience.kmath.commons.linear.CMLinearSpace
|
import space.kscience.kmath.commons.linear.CMLinearSpace
|
||||||
import space.kscience.kmath.linear.matrix
|
import space.kscience.kmath.linear.matrix
|
||||||
import space.kscience.kmath.nd.Float64BufferND
|
import space.kscience.kmath.nd.DoubleBufferND
|
||||||
|
import space.kscience.kmath.nd.ShapeND
|
||||||
import space.kscience.kmath.nd.Structure2D
|
import space.kscience.kmath.nd.Structure2D
|
||||||
import space.kscience.kmath.nd.mutableStructureND
|
|
||||||
import space.kscience.kmath.nd.ndAlgebra
|
import space.kscience.kmath.nd.ndAlgebra
|
||||||
import space.kscience.kmath.structures.Float64
|
import space.kscience.kmath.viktor.ViktorStructureND
|
||||||
import space.kscience.kmath.viktor.viktorAlgebra
|
import space.kscience.kmath.viktor.viktorAlgebra
|
||||||
import kotlin.collections.component1
|
|
||||||
import kotlin.collections.component2
|
|
||||||
|
|
||||||
fun main() {
|
fun main() {
|
||||||
val viktorStructure = Float64Field.viktorAlgebra.mutableStructureND(2, 2) { (i, j) ->
|
val viktorStructure: ViktorStructureND = DoubleField.viktorAlgebra.structureND(ShapeND(2, 2)) { (i, j) ->
|
||||||
if (i == j) 2.0 else 0.0
|
if (i == j) 2.0 else 0.0
|
||||||
}
|
}
|
||||||
|
|
||||||
val cmMatrix: Structure2D<Float64> = CMLinearSpace.matrix(2, 2)(0.0, 1.0, 0.0, 3.0)
|
val cmMatrix: Structure2D<Double> = CMLinearSpace.matrix(2, 2)(0.0, 1.0, 0.0, 3.0)
|
||||||
|
|
||||||
val res: Float64BufferND = Float64Field.ndAlgebra {
|
val res: DoubleBufferND = DoubleField.ndAlgebra {
|
||||||
exp(viktorStructure) + 2.0 * cmMatrix
|
exp(viktorStructure) + 2.0 * cmMatrix
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -0,0 +1,29 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2018-2023 KMath contributors.
|
||||||
|
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package space.kscience.kmath.series
|
||||||
|
|
||||||
|
import space.kscience.kmath.nd.*
|
||||||
|
import space.kscience.kmath.operations.algebra
|
||||||
|
import space.kscience.kmath.operations.bufferAlgebra
|
||||||
|
import space.kscience.kmath.structures.asBuffer
|
||||||
|
|
||||||
|
fun main() = with(Double.algebra.bufferAlgebra.seriesAlgebra()) {
|
||||||
|
val firstSequence: DoubleArray = doubleArrayOf(0.0, 2.0, 3.0, 1.0, 3.0, 0.1, 0.0, 1.0)
|
||||||
|
val secondSequence: DoubleArray = doubleArrayOf(1.0, 0.0, 3.0, 0.0, 0.0, 3.0, 2.0, 0.0, 2.0)
|
||||||
|
|
||||||
|
val seriesOne = firstSequence.asBuffer()
|
||||||
|
val seriesTwo = secondSequence.asBuffer()
|
||||||
|
|
||||||
|
val result = DoubleFieldOpsND.dynamicTimeWarping(seriesOne, seriesTwo)
|
||||||
|
println("Total penalty coefficient: ${result.totalCost}")
|
||||||
|
print("Alignment: ")
|
||||||
|
println(result.alignMatrix)
|
||||||
|
for ((i , j) in result.alignMatrix.indices) {
|
||||||
|
if (result.alignMatrix[i, j] > 0.0) {
|
||||||
|
print("[$i, $j] ")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2018-2024 KMath contributors.
|
* Copyright 2018-2023 KMath contributors.
|
||||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
@ -1,8 +1,3 @@
|
|||||||
/*
|
|
||||||
* Copyright 2018-2024 KMath contributors.
|
|
||||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package space.kscience.kmath.series
|
package space.kscience.kmath.series
|
||||||
|
|
||||||
|
|
||||||
@ -14,18 +9,14 @@ import space.kscience.kmath.operations.toList
|
|||||||
import space.kscience.kmath.stat.KMComparisonResult
|
import space.kscience.kmath.stat.KMComparisonResult
|
||||||
import space.kscience.kmath.stat.ksComparisonStatistic
|
import space.kscience.kmath.stat.ksComparisonStatistic
|
||||||
import space.kscience.kmath.structures.Buffer
|
import space.kscience.kmath.structures.Buffer
|
||||||
import space.kscience.kmath.structures.Float64
|
|
||||||
import space.kscience.kmath.structures.slice
|
import space.kscience.kmath.structures.slice
|
||||||
import space.kscience.plotly.*
|
import space.kscience.plotly.*
|
||||||
import kotlin.math.PI
|
import kotlin.math.PI
|
||||||
|
|
||||||
fun Double.Companion.seriesAlgebra() = Double.algebra.bufferAlgebra.seriesAlgebra()
|
fun main() = with(Double.algebra.bufferAlgebra.seriesAlgebra()) {
|
||||||
|
|
||||||
|
|
||||||
fun main() = with(Double.seriesAlgebra()) {
|
fun Plot.plotSeries(name: String, buffer: Buffer<Double>) {
|
||||||
|
|
||||||
|
|
||||||
fun Plot.plotSeries(name: String, buffer: Buffer<Float64>) {
|
|
||||||
scatter {
|
scatter {
|
||||||
this.name = name
|
this.name = name
|
||||||
x.numbers = buffer.labels
|
x.numbers = buffer.labels
|
||||||
@ -38,17 +29,17 @@ fun main() = with(Double.seriesAlgebra()) {
|
|||||||
|
|
||||||
val s2 = s1.slice(20..50).moveTo(40)
|
val s2 = s1.slice(20..50).moveTo(40)
|
||||||
|
|
||||||
val s3: Buffer<Float64> = s1.zip(s2) { l, r -> l + r } //s1 + s2
|
val s3: Buffer<Double> = s1.zip(s2) { l, r -> l + r } //s1 + s2
|
||||||
val s4 = s3.map { ln(it) }
|
val s4 = s3.map { ln(it) }
|
||||||
|
|
||||||
val kmTest: KMComparisonResult<Float64> = ksComparisonStatistic(s1, s2)
|
val kmTest: KMComparisonResult<Double> = ksComparisonStatistic(s1, s2)
|
||||||
|
|
||||||
Plotly.page {
|
Plotly.page {
|
||||||
h1 { +"This is my plot" }
|
h1 { +"This is my plot" }
|
||||||
p {
|
p{
|
||||||
+"Kolmogorov-smirnov test for s1 and s2: ${kmTest.value}"
|
+"Kolmogorov-smirnov test for s1 and s2: ${kmTest.value}"
|
||||||
}
|
}
|
||||||
plot {
|
plot{
|
||||||
plotSeries("s1", s1)
|
plotSeries("s1", s1)
|
||||||
plotSeries("s2", s2)
|
plotSeries("s2", s2)
|
||||||
plotSeries("s3", s3)
|
plotSeries("s3", s3)
|
||||||
|
@ -1,47 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2018-2023 KMath contributors.
|
|
||||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package space.kscience.kmath.series
|
|
||||||
|
|
||||||
|
|
||||||
import space.kscience.kmath.structures.*
|
|
||||||
import space.kscience.plotly.*
|
|
||||||
import space.kscience.plotly.models.Scatter
|
|
||||||
import space.kscience.plotly.models.ScatterMode
|
|
||||||
import kotlin.random.Random
|
|
||||||
|
|
||||||
fun main(): Unit = with(Double.seriesAlgebra()) {
|
|
||||||
|
|
||||||
val random = Random(1234)
|
|
||||||
|
|
||||||
val arrayOfRandoms = DoubleArray(20) { random.nextDouble() }
|
|
||||||
|
|
||||||
val series1: Float64Buffer = arrayOfRandoms.asBuffer()
|
|
||||||
val series2: Series<Float64> = series1.moveBy(3)
|
|
||||||
|
|
||||||
val res = series2 - series1
|
|
||||||
|
|
||||||
println(res.size)
|
|
||||||
|
|
||||||
println(res)
|
|
||||||
|
|
||||||
fun Plot.series(name: String, buffer: Buffer<Float64>, block: Scatter.() -> Unit = {}) {
|
|
||||||
scatter {
|
|
||||||
this.name = name
|
|
||||||
x.numbers = buffer.offsetIndices
|
|
||||||
y.doubles = buffer.toDoubleArray()
|
|
||||||
block()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Plotly.plot {
|
|
||||||
series("series1", series1)
|
|
||||||
series("series2", series2)
|
|
||||||
series("dif", res) {
|
|
||||||
mode = ScatterMode.lines
|
|
||||||
line.color("magenta")
|
|
||||||
}
|
|
||||||
}.makeFile(resourceLocation = ResourceLocation.REMOTE)
|
|
||||||
}
|
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2018-2024 KMath contributors.
|
* Copyright 2018-2022 KMath contributors.
|
||||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@ -36,28 +36,8 @@ private suspend fun runKMathChained(): Duration {
|
|||||||
return Duration.between(startTime, Instant.now())
|
return Duration.between(startTime, Instant.now())
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun runKMathBlocking(): Duration {
|
|
||||||
val generator = RandomGenerator.fromSource(RandomSource.MT, 123L)
|
|
||||||
val normal = GaussianSampler(7.0, 2.0)
|
|
||||||
val chain = normal.sample(generator)
|
|
||||||
val startTime = Instant.now()
|
|
||||||
var sum = 0.0
|
|
||||||
|
|
||||||
repeat(10000001) { counter ->
|
|
||||||
sum += chain.nextBlocking()
|
|
||||||
|
|
||||||
if (counter % 100000 == 0) {
|
|
||||||
val duration = Duration.between(startTime, Instant.now())
|
|
||||||
val meanValue = sum / counter
|
|
||||||
println("Chain sampler completed $counter elements in $duration: $meanValue")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return Duration.between(startTime, Instant.now())
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun runCMDirect(): Duration {
|
private fun runCMDirect(): Duration {
|
||||||
val rng = RandomSource.MT.create(123L)
|
val rng = RandomSource.create(RandomSource.MT, 123L)
|
||||||
|
|
||||||
val sampler = CMGaussianSampler.of(
|
val sampler = CMGaussianSampler.of(
|
||||||
BoxMullerNormalizedGaussianSampler.of(rng),
|
BoxMullerNormalizedGaussianSampler.of(rng),
|
||||||
@ -87,8 +67,6 @@ private fun runCMDirect(): Duration {
|
|||||||
fun main(): Unit = runBlocking(Dispatchers.Default) {
|
fun main(): Unit = runBlocking(Dispatchers.Default) {
|
||||||
val directJob = async { runCMDirect() }
|
val directJob = async { runCMDirect() }
|
||||||
val chainJob = async { runKMathChained() }
|
val chainJob = async { runKMathChained() }
|
||||||
val blockingJob = async { runKMathBlocking() }
|
|
||||||
println("KMath Chained: ${chainJob.await()}")
|
println("KMath Chained: ${chainJob.await()}")
|
||||||
println("KMath Blocking: ${blockingJob.await()}")
|
|
||||||
println("Apache Direct: ${directJob.await()}")
|
println("Apache Direct: ${directJob.await()}")
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2018-2024 KMath contributors.
|
* Copyright 2018-2022 KMath contributors.
|
||||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@ -10,14 +10,13 @@ import space.kscience.kmath.chains.Chain
|
|||||||
import space.kscience.kmath.chains.combineWithState
|
import space.kscience.kmath.chains.combineWithState
|
||||||
import space.kscience.kmath.distributions.NormalDistribution
|
import space.kscience.kmath.distributions.NormalDistribution
|
||||||
import space.kscience.kmath.random.RandomGenerator
|
import space.kscience.kmath.random.RandomGenerator
|
||||||
import space.kscience.kmath.structures.Float64
|
|
||||||
|
|
||||||
private data class AveragingChainState(var num: Int = 0, var value: Double = 0.0)
|
private data class AveragingChainState(var num: Int = 0, var value: Double = 0.0)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Averaging.
|
* Averaging.
|
||||||
*/
|
*/
|
||||||
private fun Chain<Float64>.mean(): Chain<Float64> = combineWithState(AveragingChainState(), { it.copy() }) { chain ->
|
private fun Chain<Double>.mean(): Chain<Double> = combineWithState(AveragingChainState(), { it.copy() }) { chain ->
|
||||||
val next = chain.next()
|
val next = chain.next()
|
||||||
num++
|
num++
|
||||||
value += next
|
value += next
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2018-2024 KMath contributors.
|
* Copyright 2018-2022 KMath contributors.
|
||||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@ -8,12 +8,12 @@
|
|||||||
package space.kscience.kmath.structures
|
package space.kscience.kmath.structures
|
||||||
|
|
||||||
import space.kscience.kmath.complex.*
|
import space.kscience.kmath.complex.*
|
||||||
import space.kscience.kmath.linear.transposed
|
import space.kscience.kmath.linear.transpose
|
||||||
import space.kscience.kmath.nd.StructureND
|
import space.kscience.kmath.nd.StructureND
|
||||||
import space.kscience.kmath.nd.as2D
|
import space.kscience.kmath.nd.as2D
|
||||||
import space.kscience.kmath.nd.ndAlgebra
|
import space.kscience.kmath.nd.ndAlgebra
|
||||||
import space.kscience.kmath.nd.structureND
|
import space.kscience.kmath.nd.structureND
|
||||||
import space.kscience.kmath.operations.Float64Field
|
import space.kscience.kmath.operations.DoubleField
|
||||||
import space.kscience.kmath.operations.invoke
|
import space.kscience.kmath.operations.invoke
|
||||||
import kotlin.system.measureTimeMillis
|
import kotlin.system.measureTimeMillis
|
||||||
|
|
||||||
@ -21,12 +21,12 @@ fun main() {
|
|||||||
val dim = 1000
|
val dim = 1000
|
||||||
val n = 1000
|
val n = 1000
|
||||||
|
|
||||||
val realField = Float64Field.ndAlgebra(dim, dim)
|
val realField = DoubleField.ndAlgebra(dim, dim)
|
||||||
val complexField: ComplexFieldND = ComplexField.ndAlgebra(dim, dim)
|
val complexField: ComplexFieldND = ComplexField.ndAlgebra(dim, dim)
|
||||||
|
|
||||||
val realTime = measureTimeMillis {
|
val realTime = measureTimeMillis {
|
||||||
realField {
|
realField {
|
||||||
var res: StructureND<Float64> = one
|
var res: StructureND<Double> = one
|
||||||
repeat(n) {
|
repeat(n) {
|
||||||
res += 1.0
|
res += 1.0
|
||||||
}
|
}
|
||||||
@ -60,7 +60,7 @@ fun complexExample() {
|
|||||||
val sum = matrix + x + 1.0
|
val sum = matrix + x + 1.0
|
||||||
|
|
||||||
//Represent the sum as 2d-structure and transpose
|
//Represent the sum as 2d-structure and transpose
|
||||||
sum.as2D().transposed()
|
sum.as2D().transpose()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2018-2024 KMath contributors.
|
* Copyright 2018-2022 KMath contributors.
|
||||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@ -10,7 +10,7 @@ import kotlinx.coroutines.GlobalScope
|
|||||||
import org.nd4j.linalg.factory.Nd4j
|
import org.nd4j.linalg.factory.Nd4j
|
||||||
import space.kscience.kmath.nd.*
|
import space.kscience.kmath.nd.*
|
||||||
import space.kscience.kmath.nd4j.nd4j
|
import space.kscience.kmath.nd4j.nd4j
|
||||||
import space.kscience.kmath.operations.Float64Field
|
import space.kscience.kmath.operations.DoubleField
|
||||||
import space.kscience.kmath.operations.invoke
|
import space.kscience.kmath.operations.invoke
|
||||||
import space.kscience.kmath.viktor.ViktorFieldND
|
import space.kscience.kmath.viktor.ViktorFieldND
|
||||||
import kotlin.contracts.InvocationKind
|
import kotlin.contracts.InvocationKind
|
||||||
@ -33,47 +33,47 @@ fun main() {
|
|||||||
|
|
||||||
|
|
||||||
// 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 doubleField = Float64Field.ndAlgebra
|
val doubleField = DoubleField.ndAlgebra
|
||||||
//A generic field. It should be used for objects, not primitives.
|
//A generic field. It should be used for objects, not primitives.
|
||||||
val genericField = BufferedFieldOpsND(Float64Field)
|
val genericField = BufferedFieldOpsND(DoubleField)
|
||||||
// Nd4j specialized field.
|
// Nd4j specialized field.
|
||||||
val nd4jField = Float64Field.nd4j
|
val nd4jField = DoubleField.nd4j
|
||||||
//viktor field
|
//viktor field
|
||||||
val viktorField = ViktorFieldND(dim, dim)
|
val viktorField = ViktorFieldND(dim, dim)
|
||||||
//parallel processing based on Java Streams
|
//parallel processing based on Java Streams
|
||||||
val parallelField = Float64Field.ndStreaming(dim, dim)
|
val parallelField = DoubleField.ndStreaming(dim, dim)
|
||||||
|
|
||||||
measureAndPrint("Boxing addition") {
|
measureAndPrint("Boxing addition") {
|
||||||
genericField {
|
genericField {
|
||||||
var res: StructureND<Float64> = one(shape)
|
var res: StructureND<Double> = one(shape)
|
||||||
repeat(n) { res += 1.0 }
|
repeat(n) { res += 1.0 }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
measureAndPrint("Specialized addition") {
|
measureAndPrint("Specialized addition") {
|
||||||
doubleField {
|
doubleField {
|
||||||
var res: StructureND<Float64> = one(shape)
|
var res: StructureND<Double> = one(shape)
|
||||||
repeat(n) { res += 1.0 }
|
repeat(n) { res += 1.0 }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
measureAndPrint("Nd4j specialized addition") {
|
measureAndPrint("Nd4j specialized addition") {
|
||||||
nd4jField {
|
nd4jField {
|
||||||
var res: StructureND<Float64> = one(shape)
|
var res: StructureND<Double> = one(shape)
|
||||||
repeat(n) { res += 1.0 }
|
repeat(n) { res += 1.0 }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
measureAndPrint("Viktor addition") {
|
measureAndPrint("Viktor addition") {
|
||||||
viktorField {
|
viktorField {
|
||||||
var res: StructureND<Float64> = 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: StructureND<Float64> = one
|
var res: StructureND<Double> = one
|
||||||
repeat(n) { res += 1.0 }
|
repeat(n) { res += 1.0 }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2018-2024 KMath contributors.
|
* Copyright 2018-2022 KMath contributors.
|
||||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@ -9,7 +9,6 @@ import space.kscience.kmath.PerformancePitfall
|
|||||||
import space.kscience.kmath.nd.*
|
import space.kscience.kmath.nd.*
|
||||||
import space.kscience.kmath.operations.DoubleField
|
import space.kscience.kmath.operations.DoubleField
|
||||||
import space.kscience.kmath.operations.ExtendedField
|
import space.kscience.kmath.operations.ExtendedField
|
||||||
import space.kscience.kmath.operations.Float64Field
|
|
||||||
import space.kscience.kmath.operations.NumbersAddOps
|
import space.kscience.kmath.operations.NumbersAddOps
|
||||||
import java.util.*
|
import java.util.*
|
||||||
import java.util.stream.IntStream
|
import java.util.stream.IntStream
|
||||||
@ -18,67 +17,55 @@ import java.util.stream.IntStream
|
|||||||
* A demonstration implementation of NDField over Real using Java [java.util.stream.DoubleStream] for parallel
|
* A demonstration implementation of NDField over Real using Java [java.util.stream.DoubleStream] for parallel
|
||||||
* execution.
|
* execution.
|
||||||
*/
|
*/
|
||||||
class StreamDoubleFieldND(override val shape: ShapeND) : FieldND<Double, Float64Field>,
|
class StreamDoubleFieldND(override val shape: ShapeND) : FieldND<Double, DoubleField>,
|
||||||
NumbersAddOps<StructureND<Float64>>,
|
NumbersAddOps<StructureND<Double>>,
|
||||||
ExtendedField<StructureND<Float64>> {
|
ExtendedField<StructureND<Double>> {
|
||||||
|
|
||||||
private val strides = ColumnStrides(shape)
|
private val strides = ColumnStrides(shape)
|
||||||
override val elementAlgebra: Float64Field get() = Float64Field
|
override val elementAlgebra: DoubleField get() = DoubleField
|
||||||
override val zero: BufferND<Float64> by lazy { structureND(shape) { zero } }
|
override val zero: BufferND<Double> by lazy { structureND(shape) { zero } }
|
||||||
override val one: BufferND<Float64> by lazy { structureND(shape) { one } }
|
override val one: BufferND<Double> by lazy { structureND(shape) { one } }
|
||||||
|
|
||||||
override fun number(value: Number): BufferND<Float64> {
|
override fun number(value: Number): BufferND<Double> {
|
||||||
val d = value.toDouble() // minimize conversions
|
val d = value.toDouble() // minimize conversions
|
||||||
return structureND(shape) { d }
|
return structureND(shape) { d }
|
||||||
}
|
}
|
||||||
|
|
||||||
@OptIn(PerformancePitfall::class)
|
@OptIn(PerformancePitfall::class)
|
||||||
private val StructureND<Float64>.buffer: Float64Buffer
|
private val StructureND<Double>.buffer: DoubleBuffer
|
||||||
get() = when {
|
get() = when {
|
||||||
shape != this@StreamDoubleFieldND.shape -> throw ShapeMismatchException(
|
!shape.contentEquals(this@StreamDoubleFieldND.shape) -> throw ShapeMismatchException(
|
||||||
this@StreamDoubleFieldND.shape,
|
this@StreamDoubleFieldND.shape,
|
||||||
shape
|
shape
|
||||||
)
|
)
|
||||||
|
|
||||||
this is BufferND && indices == this@StreamDoubleFieldND.strides -> this.buffer as Float64Buffer
|
this is BufferND && indices == this@StreamDoubleFieldND.strides -> this.buffer as DoubleBuffer
|
||||||
else -> Float64Buffer(strides.linearSize) { offset -> get(strides.index(offset)) }
|
else -> DoubleBuffer(strides.linearSize) { offset -> get(strides.index(offset)) }
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun structureND(shape: ShapeND, initializer: Float64Field.(IntArray) -> Double): BufferND<Float64> {
|
override fun structureND(shape: ShapeND, initializer: DoubleField.(IntArray) -> Double): BufferND<Double> {
|
||||||
val array = IntStream.range(0, strides.linearSize).parallel().mapToDouble { offset ->
|
|
||||||
val index = strides.index(offset)
|
|
||||||
Float64Field.initializer(index)
|
|
||||||
}.toArray()
|
|
||||||
|
|
||||||
return BufferND(strides, array.asBuffer())
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun mutableStructureND(
|
|
||||||
shape: ShapeND,
|
|
||||||
initializer: DoubleField.(IntArray) -> Double,
|
|
||||||
): MutableBufferND<Float64> {
|
|
||||||
val array = IntStream.range(0, strides.linearSize).parallel().mapToDouble { offset ->
|
val array = IntStream.range(0, strides.linearSize).parallel().mapToDouble { offset ->
|
||||||
val index = strides.index(offset)
|
val index = strides.index(offset)
|
||||||
DoubleField.initializer(index)
|
DoubleField.initializer(index)
|
||||||
}.toArray()
|
}.toArray()
|
||||||
|
|
||||||
return MutableBufferND(strides, array.asBuffer())
|
|
||||||
}
|
|
||||||
|
|
||||||
@OptIn(PerformancePitfall::class)
|
|
||||||
override fun StructureND<Float64>.map(
|
|
||||||
transform: Float64Field.(Double) -> Double,
|
|
||||||
): BufferND<Float64> {
|
|
||||||
val array = Arrays.stream(buffer.array).parallel().map { Float64Field.transform(it) }.toArray()
|
|
||||||
return BufferND(strides, array.asBuffer())
|
return BufferND(strides, array.asBuffer())
|
||||||
}
|
}
|
||||||
|
|
||||||
@OptIn(PerformancePitfall::class)
|
@OptIn(PerformancePitfall::class)
|
||||||
override fun StructureND<Float64>.mapIndexed(
|
override fun StructureND<Double>.map(
|
||||||
transform: Float64Field.(index: IntArray, Double) -> Double,
|
transform: DoubleField.(Double) -> Double,
|
||||||
): BufferND<Float64> {
|
): BufferND<Double> {
|
||||||
|
val array = Arrays.stream(buffer.array).parallel().map { DoubleField.transform(it) }.toArray()
|
||||||
|
return BufferND(strides, array.asBuffer())
|
||||||
|
}
|
||||||
|
|
||||||
|
@OptIn(PerformancePitfall::class)
|
||||||
|
override fun StructureND<Double>.mapIndexed(
|
||||||
|
transform: DoubleField.(index: IntArray, Double) -> Double,
|
||||||
|
): BufferND<Double> {
|
||||||
val array = IntStream.range(0, strides.linearSize).parallel().mapToDouble { offset ->
|
val array = IntStream.range(0, strides.linearSize).parallel().mapToDouble { offset ->
|
||||||
Float64Field.transform(
|
DoubleField.transform(
|
||||||
strides.index(offset),
|
strides.index(offset),
|
||||||
buffer.array[offset]
|
buffer.array[offset]
|
||||||
)
|
)
|
||||||
@ -89,39 +76,39 @@ class StreamDoubleFieldND(override val shape: ShapeND) : FieldND<Double, Float64
|
|||||||
|
|
||||||
@OptIn(PerformancePitfall::class)
|
@OptIn(PerformancePitfall::class)
|
||||||
override fun zip(
|
override fun zip(
|
||||||
left: StructureND<Float64>,
|
left: StructureND<Double>,
|
||||||
right: StructureND<Float64>,
|
right: StructureND<Double>,
|
||||||
transform: Float64Field.(Double, Double) -> Double,
|
transform: DoubleField.(Double, Double) -> Double,
|
||||||
): BufferND<Float64> {
|
): BufferND<Double> {
|
||||||
val array = IntStream.range(0, strides.linearSize).parallel().mapToDouble { offset ->
|
val array = IntStream.range(0, strides.linearSize).parallel().mapToDouble { offset ->
|
||||||
Float64Field.transform(left.buffer.array[offset], right.buffer.array[offset])
|
DoubleField.transform(left.buffer.array[offset], right.buffer.array[offset])
|
||||||
}.toArray()
|
}.toArray()
|
||||||
return BufferND(strides, array.asBuffer())
|
return BufferND(strides, array.asBuffer())
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun StructureND<Float64>.unaryMinus(): StructureND<Float64> = map { -it }
|
override fun StructureND<Double>.unaryMinus(): StructureND<Double> = map { -it }
|
||||||
|
|
||||||
override fun scale(a: StructureND<Float64>, value: Double): StructureND<Float64> = a.map { it * value }
|
override fun scale(a: StructureND<Double>, value: Double): StructureND<Double> = a.map { it * value }
|
||||||
|
|
||||||
override fun power(arg: StructureND<Float64>, pow: Number): BufferND<Float64> = arg.map { power(it, pow) }
|
override fun power(arg: StructureND<Double>, pow: Number): BufferND<Double> = arg.map { power(it, pow) }
|
||||||
|
|
||||||
override fun exp(arg: StructureND<Float64>): BufferND<Float64> = arg.map { exp(it) }
|
override fun exp(arg: StructureND<Double>): BufferND<Double> = arg.map { exp(it) }
|
||||||
|
|
||||||
override fun ln(arg: StructureND<Float64>): BufferND<Float64> = arg.map { ln(it) }
|
override fun ln(arg: StructureND<Double>): BufferND<Double> = arg.map { ln(it) }
|
||||||
|
|
||||||
override fun sin(arg: StructureND<Float64>): BufferND<Float64> = arg.map { sin(it) }
|
override fun sin(arg: StructureND<Double>): BufferND<Double> = arg.map { sin(it) }
|
||||||
override fun cos(arg: StructureND<Float64>): BufferND<Float64> = arg.map { cos(it) }
|
override fun cos(arg: StructureND<Double>): BufferND<Double> = arg.map { cos(it) }
|
||||||
override fun tan(arg: StructureND<Float64>): BufferND<Float64> = arg.map { tan(it) }
|
override fun tan(arg: StructureND<Double>): BufferND<Double> = arg.map { tan(it) }
|
||||||
override fun asin(arg: StructureND<Float64>): BufferND<Float64> = arg.map { asin(it) }
|
override fun asin(arg: StructureND<Double>): BufferND<Double> = arg.map { asin(it) }
|
||||||
override fun acos(arg: StructureND<Float64>): BufferND<Float64> = arg.map { acos(it) }
|
override fun acos(arg: StructureND<Double>): BufferND<Double> = arg.map { acos(it) }
|
||||||
override fun atan(arg: StructureND<Float64>): BufferND<Float64> = arg.map { atan(it) }
|
override fun atan(arg: StructureND<Double>): BufferND<Double> = arg.map { atan(it) }
|
||||||
|
|
||||||
override fun sinh(arg: StructureND<Float64>): BufferND<Float64> = arg.map { sinh(it) }
|
override fun sinh(arg: StructureND<Double>): BufferND<Double> = arg.map { sinh(it) }
|
||||||
override fun cosh(arg: StructureND<Float64>): BufferND<Float64> = arg.map { cosh(it) }
|
override fun cosh(arg: StructureND<Double>): BufferND<Double> = arg.map { cosh(it) }
|
||||||
override fun tanh(arg: StructureND<Float64>): BufferND<Float64> = arg.map { tanh(it) }
|
override fun tanh(arg: StructureND<Double>): BufferND<Double> = arg.map { tanh(it) }
|
||||||
override fun asinh(arg: StructureND<Float64>): BufferND<Float64> = arg.map { asinh(it) }
|
override fun asinh(arg: StructureND<Double>): BufferND<Double> = arg.map { asinh(it) }
|
||||||
override fun acosh(arg: StructureND<Float64>): BufferND<Float64> = arg.map { acosh(it) }
|
override fun acosh(arg: StructureND<Double>): BufferND<Double> = arg.map { acosh(it) }
|
||||||
override fun atanh(arg: StructureND<Float64>): BufferND<Float64> = arg.map { atanh(it) }
|
override fun atanh(arg: StructureND<Double>): BufferND<Double> = arg.map { atanh(it) }
|
||||||
}
|
}
|
||||||
|
|
||||||
fun Float64Field.ndStreaming(vararg shape: Int): StreamDoubleFieldND = StreamDoubleFieldND(ShapeND(shape))
|
fun DoubleField.ndStreaming(vararg shape: Int): StreamDoubleFieldND = StreamDoubleFieldND(ShapeND(shape))
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2018-2024 KMath contributors.
|
* Copyright 2018-2022 KMath contributors.
|
||||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@ -16,7 +16,7 @@ import kotlin.system.measureTimeMillis
|
|||||||
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 = Float64Buffer(array)
|
val buffer = DoubleBuffer(array)
|
||||||
val strides = ColumnStrides(ShapeND(n, n))
|
val strides = ColumnStrides(ShapeND(n, n))
|
||||||
val structure = BufferND(strides, buffer)
|
val structure = BufferND(strides, buffer)
|
||||||
|
|
||||||
|
@ -1,23 +1,25 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2018-2024 KMath contributors.
|
* Copyright 2018-2022 KMath contributors.
|
||||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package space.kscience.kmath.structures
|
package space.kscience.kmath.structures
|
||||||
|
|
||||||
import space.kscience.kmath.nd.BufferND
|
import space.kscience.kmath.nd.BufferND
|
||||||
|
import space.kscience.kmath.nd.ShapeND
|
||||||
|
import space.kscience.kmath.nd.StructureND
|
||||||
import space.kscience.kmath.operations.mapToBuffer
|
import space.kscience.kmath.operations.mapToBuffer
|
||||||
import kotlin.system.measureTimeMillis
|
import kotlin.system.measureTimeMillis
|
||||||
|
|
||||||
private inline fun <T, reified R : Any> BufferND<T>.mapToBufferND(
|
private inline fun <T, reified R : Any> BufferND<T>.mapToBufferND(
|
||||||
bufferFactory: BufferFactory<R> = BufferFactory(),
|
bufferFactory: BufferFactory<R> = BufferFactory.auto(),
|
||||||
crossinline block: (T) -> R,
|
crossinline block: (T) -> R,
|
||||||
): BufferND<R> = BufferND(indices, buffer.mapToBuffer(bufferFactory, block))
|
): BufferND<R> = BufferND(indices, buffer.mapToBuffer(bufferFactory, block))
|
||||||
|
|
||||||
@Suppress("UNUSED_VARIABLE")
|
@Suppress("UNUSED_VARIABLE")
|
||||||
fun main() {
|
fun main() {
|
||||||
val n = 6000
|
val n = 6000
|
||||||
val structure = BufferND(n, n) { 1.0 }
|
val structure = StructureND.buffered(ShapeND(n, n), Buffer.Companion::auto) { 1.0 }
|
||||||
structure.mapToBufferND { it + 1 } // warm-up
|
structure.mapToBufferND { it + 1 } // warm-up
|
||||||
val time1 = measureTimeMillis { val res = structure.mapToBufferND { it + 1 } }
|
val time1 = measureTimeMillis { val res = structure.mapToBufferND { it + 1 } }
|
||||||
println("Structure mapping finished in $time1 millis")
|
println("Structure mapping finished in $time1 millis")
|
||||||
@ -30,10 +32,10 @@ fun main() {
|
|||||||
|
|
||||||
println("Array mapping finished in $time2 millis")
|
println("Array mapping finished in $time2 millis")
|
||||||
|
|
||||||
val buffer = Float64Buffer(DoubleArray(n * n) { 1.0 })
|
val buffer = DoubleBuffer(DoubleArray(n * n) { 1.0 })
|
||||||
|
|
||||||
val time3 = measureTimeMillis {
|
val time3 = measureTimeMillis {
|
||||||
val target = Float64Buffer(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
|
||||||
}
|
}
|
||||||
|
@ -1,23 +1,23 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2018-2024 KMath contributors.
|
* Copyright 2018-2022 KMath contributors.
|
||||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package space.kscience.kmath.structures
|
package space.kscience.kmath.structures
|
||||||
|
|
||||||
import space.kscience.kmath.operations.Float64Field
|
import space.kscience.kmath.operations.DoubleField
|
||||||
import space.kscience.kmath.operations.buffer
|
import space.kscience.kmath.operations.buffer
|
||||||
import space.kscience.kmath.operations.bufferAlgebra
|
import space.kscience.kmath.operations.bufferAlgebra
|
||||||
import space.kscience.kmath.operations.withSize
|
import space.kscience.kmath.operations.withSize
|
||||||
|
|
||||||
inline fun <reified R : Any> MutableBuffer.Companion.same(
|
inline fun <reified R : Any> MutableBuffer.Companion.same(
|
||||||
n: Int,
|
n: Int,
|
||||||
value: R,
|
value: R
|
||||||
): MutableBuffer<R> = MutableBuffer(n) { value }
|
): MutableBuffer<R> = auto(n) { value }
|
||||||
|
|
||||||
|
|
||||||
fun main() {
|
fun main() {
|
||||||
with(Float64Field.bufferAlgebra.withSize(5)) {
|
with(DoubleField.bufferAlgebra.withSize(5)) {
|
||||||
println(number(2.0) + buffer(1, 2, 3, 4, 5))
|
println(number(2.0) + buffer(1, 2, 3, 4, 5))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,26 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2018-2023 KMath contributors.
|
|
||||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package space.kscience.kmath.structures
|
|
||||||
|
|
||||||
import space.kscience.kmath.PerformancePitfall
|
|
||||||
import space.kscience.kmath.nd.*
|
|
||||||
import space.kscience.kmath.operations.algebra
|
|
||||||
|
|
||||||
@OptIn(PerformancePitfall::class)
|
|
||||||
fun main(): Unit = with(Double.algebra.ndAlgebra) {
|
|
||||||
val structure: MutableStructure2D<Float64> = mutableStructureND(ShapeND(2, 2)) { (i, j) ->
|
|
||||||
i.toDouble() + j.toDouble()
|
|
||||||
}.as2D()
|
|
||||||
|
|
||||||
structure[0, 1] = -2.0
|
|
||||||
|
|
||||||
val structure2 = mutableStructureND(2, 2) { (i, j) -> i.toDouble() + j.toDouble() }.as2D()
|
|
||||||
|
|
||||||
structure2[0, 1] = 2.0
|
|
||||||
|
|
||||||
|
|
||||||
println(structure + structure2)
|
|
||||||
}
|
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2018-2024 KMath contributors.
|
* Copyright 2018-2022 KMath contributors.
|
||||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@ -15,7 +15,7 @@ private fun DMatrixContext<Double, *>.simple() {
|
|||||||
val m2 = produce<D3, D2> { i, j -> (i + j).toDouble() }
|
val m2 = produce<D3, D2> { i, j -> (i + j).toDouble() }
|
||||||
|
|
||||||
//Dimension-safe addition
|
//Dimension-safe addition
|
||||||
m1.transposed() + m2
|
m1.transpose() + m2
|
||||||
}
|
}
|
||||||
|
|
||||||
private object D5 : Dimension {
|
private object D5 : Dimension {
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2018-2024 KMath contributors.
|
* Copyright 2018-2023 KMath contributors.
|
||||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@ -31,7 +31,7 @@ fun main() {
|
|||||||
|
|
||||||
val exampleNumber = 1
|
val exampleNumber = 1
|
||||||
|
|
||||||
var y_hat = funcDifficultForLm(t_example, p_example, exampleNumber)
|
var y_hat = funcDifficultForLm(t_example, p_example, exampleNumber)
|
||||||
|
|
||||||
var p_init = DoubleTensorAlgebra.zeros(ShapeND(intArrayOf(Nparams, 1))).as2D()
|
var p_init = DoubleTensorAlgebra.zeros(ShapeND(intArrayOf(Nparams, 1))).as2D()
|
||||||
for (i in 0 until Nparams) {
|
for (i in 0 until Nparams) {
|
||||||
@ -51,8 +51,7 @@ fun main() {
|
|||||||
val opts = doubleArrayOf(3.0, 10000.0, 1e-6, 1e-6, 1e-6, 1e-6, 1e-2, 11.0, 9.0, 1.0)
|
val opts = doubleArrayOf(3.0, 10000.0, 1e-6, 1e-6, 1e-6, 1e-6, 1e-2, 11.0, 9.0, 1.0)
|
||||||
// val opts = doubleArrayOf(3.0, 10000.0, 1e-6, 1e-6, 1e-6, 1e-6, 1e-3, 11.0, 9.0, 1.0)
|
// val opts = doubleArrayOf(3.0, 10000.0, 1e-6, 1e-6, 1e-6, 1e-6, 1e-3, 11.0, 9.0, 1.0)
|
||||||
|
|
||||||
val inputData = LMInput(
|
val inputData = LMInput(::funcDifficultForLm,
|
||||||
::funcDifficultForLm,
|
|
||||||
p_init.as2D(),
|
p_init.as2D(),
|
||||||
t,
|
t,
|
||||||
y_dat,
|
y_dat,
|
||||||
@ -65,8 +64,7 @@ fun main() {
|
|||||||
doubleArrayOf(opts[6], opts[7], opts[8]),
|
doubleArrayOf(opts[6], opts[7], opts[8]),
|
||||||
opts[9].toInt(),
|
opts[9].toInt(),
|
||||||
10,
|
10,
|
||||||
1
|
1)
|
||||||
)
|
|
||||||
|
|
||||||
val result = DoubleTensorAlgebra.levenbergMarquardt(inputData)
|
val result = DoubleTensorAlgebra.levenbergMarquardt(inputData)
|
||||||
|
|
||||||
@ -78,7 +76,7 @@ fun main() {
|
|||||||
println()
|
println()
|
||||||
|
|
||||||
println("Y true and y received:")
|
println("Y true and y received:")
|
||||||
var y_hat_after = funcDifficultForLm(t_example, result.resultParameters, exampleNumber)
|
var y_hat_after = funcDifficultForLm(t_example, result.resultParameters, exampleNumber)
|
||||||
for (i in 0 until y_hat.shape.component1()) {
|
for (i in 0 until y_hat.shape.component1()) {
|
||||||
val x = (y_hat[i, 0] * 10000).roundToInt() / 10000.0
|
val x = (y_hat[i, 0] * 10000).roundToInt() / 10000.0
|
||||||
val y = (y_hat_after[i, 0] * 10000).roundToInt() / 10000.0
|
val y = (y_hat_after[i, 0] * 10000).roundToInt() / 10000.0
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2018-2024 KMath contributors.
|
* Copyright 2018-2023 KMath contributors.
|
||||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@ -18,8 +18,7 @@ import kotlin.math.roundToInt
|
|||||||
|
|
||||||
fun main() {
|
fun main() {
|
||||||
val startedData = getStartDataForFuncEasy()
|
val startedData = getStartDataForFuncEasy()
|
||||||
val inputData = LMInput(
|
val inputData = LMInput(::funcEasyForLm,
|
||||||
::funcEasyForLm,
|
|
||||||
DoubleTensorAlgebra.ones(ShapeND(intArrayOf(4, 1))).as2D(),
|
DoubleTensorAlgebra.ones(ShapeND(intArrayOf(4, 1))).as2D(),
|
||||||
startedData.t,
|
startedData.t,
|
||||||
startedData.y_dat,
|
startedData.y_dat,
|
||||||
@ -32,8 +31,7 @@ fun main() {
|
|||||||
doubleArrayOf(startedData.opts[6], startedData.opts[7], startedData.opts[8]),
|
doubleArrayOf(startedData.opts[6], startedData.opts[7], startedData.opts[8]),
|
||||||
startedData.opts[9].toInt(),
|
startedData.opts[9].toInt(),
|
||||||
10,
|
10,
|
||||||
startedData.example_number
|
startedData.example_number)
|
||||||
)
|
|
||||||
|
|
||||||
val result = DoubleTensorAlgebra.levenbergMarquardt(inputData)
|
val result = DoubleTensorAlgebra.levenbergMarquardt(inputData)
|
||||||
|
|
||||||
@ -45,7 +43,7 @@ fun main() {
|
|||||||
println()
|
println()
|
||||||
|
|
||||||
println("Y true and y received:")
|
println("Y true and y received:")
|
||||||
var y_hat_after = funcDifficultForLm(startedData.t, result.resultParameters, startedData.example_number)
|
var y_hat_after = funcDifficultForLm(startedData.t, result.resultParameters, startedData.example_number)
|
||||||
for (i in 0 until startedData.y_dat.shape.component1()) {
|
for (i in 0 until startedData.y_dat.shape.component1()) {
|
||||||
val x = (startedData.y_dat[i, 0] * 10000).roundToInt() / 10000.0
|
val x = (startedData.y_dat[i, 0] * 10000).roundToInt() / 10000.0
|
||||||
val y = (y_hat_after[i, 0] * 10000).roundToInt() / 10000.0
|
val y = (y_hat_after[i, 0] * 10000).roundToInt() / 10000.0
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2018-2024 KMath contributors.
|
* Copyright 2018-2023 KMath contributors.
|
||||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@ -15,7 +15,6 @@ import space.kscience.kmath.tensors.core.DoubleTensorAlgebra
|
|||||||
import space.kscience.kmath.tensors.core.LMInput
|
import space.kscience.kmath.tensors.core.LMInput
|
||||||
import space.kscience.kmath.tensors.core.levenbergMarquardt
|
import space.kscience.kmath.tensors.core.levenbergMarquardt
|
||||||
import kotlin.math.roundToInt
|
import kotlin.math.roundToInt
|
||||||
|
|
||||||
fun main() {
|
fun main() {
|
||||||
val NData = 100
|
val NData = 100
|
||||||
var t_example = DoubleTensorAlgebra.ones(ShapeND(intArrayOf(NData, 1))).as2D()
|
var t_example = DoubleTensorAlgebra.ones(ShapeND(intArrayOf(NData, 1))).as2D()
|
||||||
@ -31,7 +30,7 @@ fun main() {
|
|||||||
|
|
||||||
val exampleNumber = 1
|
val exampleNumber = 1
|
||||||
|
|
||||||
var y_hat = funcMiddleForLm(t_example, p_example, exampleNumber)
|
var y_hat = funcMiddleForLm(t_example, p_example, exampleNumber)
|
||||||
|
|
||||||
var p_init = DoubleTensorAlgebra.zeros(ShapeND(intArrayOf(Nparams, 1))).as2D()
|
var p_init = DoubleTensorAlgebra.zeros(ShapeND(intArrayOf(Nparams, 1))).as2D()
|
||||||
for (i in 0 until Nparams) {
|
for (i in 0 until Nparams) {
|
||||||
@ -50,8 +49,7 @@ fun main() {
|
|||||||
p_min = p_min.div(1.0 / 50.0)
|
p_min = p_min.div(1.0 / 50.0)
|
||||||
val opts = doubleArrayOf(3.0, 7000.0, 1e-5, 1e-5, 1e-5, 1e-5, 1e-5, 11.0, 9.0, 1.0)
|
val opts = doubleArrayOf(3.0, 7000.0, 1e-5, 1e-5, 1e-5, 1e-5, 1e-5, 11.0, 9.0, 1.0)
|
||||||
|
|
||||||
val inputData = LMInput(
|
val inputData = LMInput(::funcMiddleForLm,
|
||||||
::funcMiddleForLm,
|
|
||||||
p_init.as2D(),
|
p_init.as2D(),
|
||||||
t,
|
t,
|
||||||
y_dat,
|
y_dat,
|
||||||
@ -64,8 +62,7 @@ fun main() {
|
|||||||
doubleArrayOf(opts[6], opts[7], opts[8]),
|
doubleArrayOf(opts[6], opts[7], opts[8]),
|
||||||
opts[9].toInt(),
|
opts[9].toInt(),
|
||||||
10,
|
10,
|
||||||
1
|
1)
|
||||||
)
|
|
||||||
|
|
||||||
val result = DoubleTensorAlgebra.levenbergMarquardt(inputData)
|
val result = DoubleTensorAlgebra.levenbergMarquardt(inputData)
|
||||||
|
|
||||||
@ -77,7 +74,7 @@ fun main() {
|
|||||||
println()
|
println()
|
||||||
|
|
||||||
|
|
||||||
var y_hat_after = funcMiddleForLm(t_example, result.resultParameters, exampleNumber)
|
var y_hat_after = funcMiddleForLm(t_example, result.resultParameters, exampleNumber)
|
||||||
for (i in 0 until y_hat.shape.component1()) {
|
for (i in 0 until y_hat.shape.component1()) {
|
||||||
val x = (y_hat[i, 0] * 10000).roundToInt() / 10000.0
|
val x = (y_hat[i, 0] * 10000).roundToInt() / 10000.0
|
||||||
val y = (y_hat_after[i, 0] * 10000).roundToInt() / 10000.0
|
val y = (y_hat_after[i, 0] * 10000).roundToInt() / 10000.0
|
||||||
|
@ -1,29 +1,23 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2018-2024 KMath contributors.
|
* Copyright 2018-2023 KMath contributors.
|
||||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package space.kscience.kmath.tensors.LevenbergMarquardt.StreamingLm
|
package space.kscience.kmath.tensors.LevenbergMarquardt.StreamingLm
|
||||||
|
|
||||||
import kotlinx.coroutines.delay
|
import kotlinx.coroutines.delay
|
||||||
import kotlinx.coroutines.flow.Flow
|
import kotlinx.coroutines.flow.*
|
||||||
import kotlinx.coroutines.flow.flow
|
import space.kscience.kmath.nd.*
|
||||||
import space.kscience.kmath.nd.MutableStructure2D
|
|
||||||
import space.kscience.kmath.nd.ShapeND
|
|
||||||
import space.kscience.kmath.nd.as2D
|
|
||||||
import space.kscience.kmath.nd.component1
|
|
||||||
import space.kscience.kmath.structures.Float64
|
|
||||||
import space.kscience.kmath.tensors.LevenbergMarquardt.StartDataLm
|
import space.kscience.kmath.tensors.LevenbergMarquardt.StartDataLm
|
||||||
import space.kscience.kmath.tensors.core.BroadcastDoubleTensorAlgebra.zeros
|
import space.kscience.kmath.tensors.core.BroadcastDoubleTensorAlgebra.zeros
|
||||||
import space.kscience.kmath.tensors.core.DoubleTensorAlgebra
|
import space.kscience.kmath.tensors.core.DoubleTensorAlgebra
|
||||||
import space.kscience.kmath.tensors.core.LMInput
|
import space.kscience.kmath.tensors.core.LMInput
|
||||||
import space.kscience.kmath.tensors.core.levenbergMarquardt
|
import space.kscience.kmath.tensors.core.levenbergMarquardt
|
||||||
import kotlin.random.Random
|
import kotlin.random.Random
|
||||||
|
import kotlin.reflect.KFunction3
|
||||||
|
|
||||||
fun streamLm(
|
fun streamLm(lm_func: (MutableStructure2D<Double>, MutableStructure2D<Double>, Int) -> (MutableStructure2D<Double>),
|
||||||
lm_func: (MutableStructure2D<Float64>, MutableStructure2D<Float64>, Int) -> (MutableStructure2D<Float64>),
|
startData: StartDataLm, launchFrequencyInMs: Long, numberOfLaunches: Int): Flow<MutableStructure2D<Double>> = flow{
|
||||||
startData: StartDataLm, launchFrequencyInMs: Long, numberOfLaunches: Int,
|
|
||||||
): Flow<MutableStructure2D<Float64>> = flow {
|
|
||||||
|
|
||||||
var example_number = startData.example_number
|
var example_number = startData.example_number
|
||||||
var p_init = startData.p_init
|
var p_init = startData.p_init
|
||||||
@ -38,8 +32,7 @@ fun streamLm(
|
|||||||
var steps = numberOfLaunches
|
var steps = numberOfLaunches
|
||||||
val isEndless = (steps <= 0)
|
val isEndless = (steps <= 0)
|
||||||
|
|
||||||
val inputData = LMInput(
|
val inputData = LMInput(lm_func,
|
||||||
lm_func,
|
|
||||||
p_init,
|
p_init,
|
||||||
t,
|
t,
|
||||||
y_dat,
|
y_dat,
|
||||||
@ -52,8 +45,7 @@ fun streamLm(
|
|||||||
doubleArrayOf(opts[6], opts[7], opts[8]),
|
doubleArrayOf(opts[6], opts[7], opts[8]),
|
||||||
opts[9].toInt(),
|
opts[9].toInt(),
|
||||||
10,
|
10,
|
||||||
example_number
|
example_number)
|
||||||
)
|
|
||||||
|
|
||||||
while (isEndless || steps > 0) {
|
while (isEndless || steps > 0) {
|
||||||
val result = DoubleTensorAlgebra.levenbergMarquardt(inputData)
|
val result = DoubleTensorAlgebra.levenbergMarquardt(inputData)
|
||||||
@ -65,7 +57,7 @@ fun streamLm(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun generateNewYDat(y_dat: MutableStructure2D<Float64>, delta: Double): MutableStructure2D<Float64> {
|
fun generateNewYDat(y_dat: MutableStructure2D<Double>, delta: Double): MutableStructure2D<Double>{
|
||||||
val n = y_dat.shape.component1()
|
val n = y_dat.shape.component1()
|
||||||
val y_dat_new = zeros(ShapeND(intArrayOf(n, 1))).as2D()
|
val y_dat_new = zeros(ShapeND(intArrayOf(n, 1))).as2D()
|
||||||
for (i in 0 until n) {
|
for (i in 0 until n) {
|
||||||
|
@ -1,19 +1,18 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2018-2024 KMath contributors.
|
* Copyright 2018-2023 KMath contributors.
|
||||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package space.kscience.kmath.tensors.LevenbergMarquardt.StreamingLm
|
package space.kscience.kmath.tensors.LevenbergMarquardt.StreamingLm
|
||||||
|
|
||||||
import space.kscience.kmath.nd.component1
|
import space.kscience.kmath.nd.*
|
||||||
import space.kscience.kmath.tensors.LevenbergMarquardt.funcDifficultForLm
|
import space.kscience.kmath.tensors.LevenbergMarquardt.*
|
||||||
import space.kscience.kmath.tensors.LevenbergMarquardt.getStartDataForFuncDifficult
|
|
||||||
import kotlin.math.roundToInt
|
import kotlin.math.roundToInt
|
||||||
|
|
||||||
suspend fun main() {
|
suspend fun main(){
|
||||||
val startData = getStartDataForFuncDifficult()
|
val startData = getStartDataForFuncDifficult()
|
||||||
// Создание потока:
|
// Создание потока:
|
||||||
val lmFlow = streamLm(::funcDifficultForLm, startData, 0, 100)
|
val lmFlow = streamLm(::funcDifficultForLm, startData, 0, 100)
|
||||||
var initialTime = System.currentTimeMillis()
|
var initialTime = System.currentTimeMillis()
|
||||||
var lastTime: Long
|
var lastTime: Long
|
||||||
val launches = mutableListOf<Long>()
|
val launches = mutableListOf<Long>()
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2018-2024 KMath contributors.
|
* Copyright 2018-2023 KMath contributors.
|
||||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@ -9,7 +9,6 @@ import space.kscience.kmath.nd.MutableStructure2D
|
|||||||
import space.kscience.kmath.nd.ShapeND
|
import space.kscience.kmath.nd.ShapeND
|
||||||
import space.kscience.kmath.nd.as2D
|
import space.kscience.kmath.nd.as2D
|
||||||
import space.kscience.kmath.nd.component1
|
import space.kscience.kmath.nd.component1
|
||||||
import space.kscience.kmath.structures.Float64
|
|
||||||
import space.kscience.kmath.tensors.core.BroadcastDoubleTensorAlgebra
|
import space.kscience.kmath.tensors.core.BroadcastDoubleTensorAlgebra
|
||||||
import space.kscience.kmath.tensors.core.BroadcastDoubleTensorAlgebra.div
|
import space.kscience.kmath.tensors.core.BroadcastDoubleTensorAlgebra.div
|
||||||
import space.kscience.kmath.tensors.core.DoubleTensorAlgebra
|
import space.kscience.kmath.tensors.core.DoubleTensorAlgebra
|
||||||
@ -19,25 +18,21 @@ import space.kscience.kmath.tensors.core.DoubleTensorAlgebra.Companion.pow
|
|||||||
import space.kscience.kmath.tensors.core.DoubleTensorAlgebra.Companion.times
|
import space.kscience.kmath.tensors.core.DoubleTensorAlgebra.Companion.times
|
||||||
import space.kscience.kmath.tensors.core.asDoubleTensor
|
import space.kscience.kmath.tensors.core.asDoubleTensor
|
||||||
|
|
||||||
public data class StartDataLm(
|
public data class StartDataLm (
|
||||||
var lm_matx_y_dat: MutableStructure2D<Float64>,
|
var lm_matx_y_dat: MutableStructure2D<Double>,
|
||||||
var example_number: Int,
|
var example_number: Int,
|
||||||
var p_init: MutableStructure2D<Float64>,
|
var p_init: MutableStructure2D<Double>,
|
||||||
var t: MutableStructure2D<Float64>,
|
var t: MutableStructure2D<Double>,
|
||||||
var y_dat: MutableStructure2D<Float64>,
|
var y_dat: MutableStructure2D<Double>,
|
||||||
var weight: Double,
|
var weight: Double,
|
||||||
var dp: MutableStructure2D<Float64>,
|
var dp: MutableStructure2D<Double>,
|
||||||
var p_min: MutableStructure2D<Float64>,
|
var p_min: MutableStructure2D<Double>,
|
||||||
var p_max: MutableStructure2D<Float64>,
|
var p_max: MutableStructure2D<Double>,
|
||||||
var consts: MutableStructure2D<Float64>,
|
var consts: MutableStructure2D<Double>,
|
||||||
var opts: DoubleArray,
|
var opts: DoubleArray
|
||||||
)
|
)
|
||||||
|
|
||||||
fun funcEasyForLm(
|
fun funcEasyForLm(t: MutableStructure2D<Double>, p: MutableStructure2D<Double>, exampleNumber: Int): MutableStructure2D<Double> {
|
||||||
t: MutableStructure2D<Float64>,
|
|
||||||
p: MutableStructure2D<Float64>,
|
|
||||||
exampleNumber: Int,
|
|
||||||
): MutableStructure2D<Float64> {
|
|
||||||
val m = t.shape.component1()
|
val m = t.shape.component1()
|
||||||
var y_hat = DoubleTensorAlgebra.zeros(ShapeND(intArrayOf(m, 1)))
|
var y_hat = DoubleTensorAlgebra.zeros(ShapeND(intArrayOf(m, 1)))
|
||||||
|
|
||||||
@ -45,13 +40,15 @@ fun funcEasyForLm(
|
|||||||
y_hat = DoubleTensorAlgebra.exp((t.times(-1.0 / p[1, 0]))).times(p[0, 0]) + t.times(p[2, 0]).times(
|
y_hat = DoubleTensorAlgebra.exp((t.times(-1.0 / p[1, 0]))).times(p[0, 0]) + t.times(p[2, 0]).times(
|
||||||
DoubleTensorAlgebra.exp((t.times(-1.0 / p[3, 0])))
|
DoubleTensorAlgebra.exp((t.times(-1.0 / p[3, 0])))
|
||||||
)
|
)
|
||||||
} else if (exampleNumber == 2) {
|
}
|
||||||
|
else if (exampleNumber == 2) {
|
||||||
val mt = t.max()
|
val mt = t.max()
|
||||||
y_hat = (t.times(1.0 / mt)).times(p[0, 0]) +
|
y_hat = (t.times(1.0 / mt)).times(p[0, 0]) +
|
||||||
(t.times(1.0 / mt)).pow(2).times(p[1, 0]) +
|
(t.times(1.0 / mt)).pow(2).times(p[1, 0]) +
|
||||||
(t.times(1.0 / mt)).pow(3).times(p[2, 0]) +
|
(t.times(1.0 / mt)).pow(3).times(p[2, 0]) +
|
||||||
(t.times(1.0 / mt)).pow(4).times(p[3, 0])
|
(t.times(1.0 / mt)).pow(4).times(p[3, 0])
|
||||||
} else if (exampleNumber == 3) {
|
}
|
||||||
|
else if (exampleNumber == 3) {
|
||||||
y_hat = DoubleTensorAlgebra.exp((t.times(-1.0 / p[1, 0])))
|
y_hat = DoubleTensorAlgebra.exp((t.times(-1.0 / p[1, 0])))
|
||||||
.times(p[0, 0]) + DoubleTensorAlgebra.sin((t.times(1.0 / p[3, 0]))).times(p[2, 0])
|
.times(p[0, 0]) + DoubleTensorAlgebra.sin((t.times(1.0 / p[3, 0]))).times(p[2, 0])
|
||||||
}
|
}
|
||||||
@ -59,40 +56,32 @@ fun funcEasyForLm(
|
|||||||
return y_hat.as2D()
|
return y_hat.as2D()
|
||||||
}
|
}
|
||||||
|
|
||||||
fun funcMiddleForLm(
|
fun funcMiddleForLm(t: MutableStructure2D<Double>, p: MutableStructure2D<Double>, exampleNumber: Int): MutableStructure2D<Double> {
|
||||||
t: MutableStructure2D<Float64>,
|
|
||||||
p: MutableStructure2D<Float64>,
|
|
||||||
exampleNumber: Int,
|
|
||||||
): MutableStructure2D<Float64> {
|
|
||||||
val m = t.shape.component1()
|
val m = t.shape.component1()
|
||||||
var y_hat = DoubleTensorAlgebra.zeros(ShapeND(intArrayOf(m, 1)))
|
var y_hat = DoubleTensorAlgebra.zeros(ShapeND(intArrayOf (m, 1)))
|
||||||
|
|
||||||
val mt = t.max()
|
val mt = t.max()
|
||||||
for (i in 0 until p.shape.component1()) {
|
for(i in 0 until p.shape.component1()){
|
||||||
y_hat += (t.times(1.0 / mt)).times(p[i, 0])
|
y_hat += (t.times(1.0 / mt)).times(p[i, 0])
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i in 0 until 5) {
|
for(i in 0 until 5){
|
||||||
y_hat = funcEasyForLm(y_hat.as2D(), p, exampleNumber).asDoubleTensor()
|
y_hat = funcEasyForLm(y_hat.as2D(), p, exampleNumber).asDoubleTensor()
|
||||||
}
|
}
|
||||||
|
|
||||||
return y_hat.as2D()
|
return y_hat.as2D()
|
||||||
}
|
}
|
||||||
|
|
||||||
fun funcDifficultForLm(
|
fun funcDifficultForLm(t: MutableStructure2D<Double>, p: MutableStructure2D<Double>, exampleNumber: Int): MutableStructure2D<Double> {
|
||||||
t: MutableStructure2D<Float64>,
|
|
||||||
p: MutableStructure2D<Float64>,
|
|
||||||
exampleNumber: Int,
|
|
||||||
): MutableStructure2D<Float64> {
|
|
||||||
val m = t.shape.component1()
|
val m = t.shape.component1()
|
||||||
var y_hat = DoubleTensorAlgebra.zeros(ShapeND(intArrayOf(m, 1)))
|
var y_hat = DoubleTensorAlgebra.zeros(ShapeND(intArrayOf (m, 1)))
|
||||||
|
|
||||||
val mt = t.max()
|
val mt = t.max()
|
||||||
for (i in 0 until p.shape.component1()) {
|
for(i in 0 until p.shape.component1()){
|
||||||
y_hat = y_hat.plus((t.times(1.0 / mt)).times(p[i, 0]))
|
y_hat = y_hat.plus( (t.times(1.0 / mt)).times(p[i, 0]) )
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i in 0 until 4) {
|
for(i in 0 until 4){
|
||||||
y_hat = funcEasyForLm((y_hat.as2D() + t).as2D(), p, exampleNumber).asDoubleTensor()
|
y_hat = funcEasyForLm((y_hat.as2D() + t).as2D(), p, exampleNumber).asDoubleTensor()
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -100,7 +89,7 @@ fun funcDifficultForLm(
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
fun getStartDataForFuncDifficult(): StartDataLm {
|
fun getStartDataForFuncDifficult(): StartDataLm {
|
||||||
val NData = 200
|
val NData = 200
|
||||||
var t_example = DoubleTensorAlgebra.ones(ShapeND(intArrayOf(NData, 1))).as2D()
|
var t_example = DoubleTensorAlgebra.ones(ShapeND(intArrayOf(NData, 1))).as2D()
|
||||||
for (i in 0 until NData) {
|
for (i in 0 until NData) {
|
||||||
@ -115,7 +104,7 @@ fun getStartDataForFuncDifficult(): StartDataLm {
|
|||||||
|
|
||||||
val exampleNumber = 1
|
val exampleNumber = 1
|
||||||
|
|
||||||
var y_hat = funcDifficultForLm(t_example, p_example, exampleNumber)
|
var y_hat = funcDifficultForLm(t_example, p_example, exampleNumber)
|
||||||
|
|
||||||
var p_init = DoubleTensorAlgebra.zeros(ShapeND(intArrayOf(Nparams, 1))).as2D()
|
var p_init = DoubleTensorAlgebra.zeros(ShapeND(intArrayOf(Nparams, 1))).as2D()
|
||||||
for (i in 0 until Nparams) {
|
for (i in 0 until Nparams) {
|
||||||
@ -140,7 +129,7 @@ fun getStartDataForFuncDifficult(): StartDataLm {
|
|||||||
return StartDataLm(y_dat, 1, p_init, t, y_dat, weight, dp, p_min.as2D(), p_max.as2D(), consts, opts)
|
return StartDataLm(y_dat, 1, p_init, t, y_dat, weight, dp, p_min.as2D(), p_max.as2D(), consts, opts)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getStartDataForFuncMiddle(): StartDataLm {
|
fun getStartDataForFuncMiddle(): StartDataLm {
|
||||||
val NData = 100
|
val NData = 100
|
||||||
var t_example = DoubleTensorAlgebra.ones(ShapeND(intArrayOf(NData, 1))).as2D()
|
var t_example = DoubleTensorAlgebra.ones(ShapeND(intArrayOf(NData, 1))).as2D()
|
||||||
for (i in 0 until NData) {
|
for (i in 0 until NData) {
|
||||||
@ -155,7 +144,7 @@ fun getStartDataForFuncMiddle(): StartDataLm {
|
|||||||
|
|
||||||
val exampleNumber = 1
|
val exampleNumber = 1
|
||||||
|
|
||||||
var y_hat = funcMiddleForLm(t_example, p_example, exampleNumber)
|
var y_hat = funcMiddleForLm(t_example, p_example, exampleNumber)
|
||||||
|
|
||||||
var p_init = DoubleTensorAlgebra.zeros(ShapeND(intArrayOf(Nparams, 1))).as2D()
|
var p_init = DoubleTensorAlgebra.zeros(ShapeND(intArrayOf(Nparams, 1))).as2D()
|
||||||
for (i in 0 until Nparams) {
|
for (i in 0 until Nparams) {
|
||||||
|
@ -1,11 +1,12 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2018-2024 KMath contributors.
|
* Copyright 2018-2022 KMath contributors.
|
||||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package space.kscience.kmath.tensors
|
package space.kscience.kmath.tensors
|
||||||
|
|
||||||
import space.kscience.kmath.nd.ShapeND
|
import space.kscience.kmath.nd.ShapeND
|
||||||
|
import space.kscience.kmath.nd.contentEquals
|
||||||
import space.kscience.kmath.operations.invoke
|
import space.kscience.kmath.operations.invoke
|
||||||
import space.kscience.kmath.tensors.core.DoubleTensor
|
import space.kscience.kmath.tensors.core.DoubleTensor
|
||||||
import space.kscience.kmath.tensors.core.DoubleTensorAlgebra
|
import space.kscience.kmath.tensors.core.DoubleTensorAlgebra
|
||||||
@ -61,7 +62,7 @@ fun main() {
|
|||||||
// figure out MSE of approximation
|
// figure out MSE of approximation
|
||||||
fun mse(yTrue: DoubleTensor, yPred: DoubleTensor): Double {
|
fun mse(yTrue: DoubleTensor, yPred: DoubleTensor): Double {
|
||||||
require(yTrue.shape.size == 1)
|
require(yTrue.shape.size == 1)
|
||||||
require(yTrue.shape == yPred.shape)
|
require(yTrue.shape contentEquals yPred.shape)
|
||||||
|
|
||||||
val diff = yTrue - yPred
|
val diff = yTrue - yPred
|
||||||
return sqrt(diff.dot(diff)).value()
|
return sqrt(diff.dot(diff)).value()
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2018-2024 KMath contributors.
|
* Copyright 2018-2022 KMath contributors.
|
||||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2018-2024 KMath contributors.
|
* Copyright 2018-2022 KMath contributors.
|
||||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2018-2024 KMath contributors.
|
* Copyright 2018-2022 KMath contributors.
|
||||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2018-2024 KMath contributors.
|
* Copyright 2018-2022 KMath contributors.
|
||||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@ -10,13 +10,12 @@ import org.jetbrains.kotlinx.multik.api.ndarray
|
|||||||
import org.jetbrains.kotlinx.multik.default.DefaultEngine
|
import org.jetbrains.kotlinx.multik.default.DefaultEngine
|
||||||
import space.kscience.kmath.multik.MultikDoubleAlgebra
|
import space.kscience.kmath.multik.MultikDoubleAlgebra
|
||||||
import space.kscience.kmath.nd.one
|
import space.kscience.kmath.nd.one
|
||||||
import space.kscience.kmath.structures.Float64
|
|
||||||
|
|
||||||
|
|
||||||
val multikAlgebra = MultikDoubleAlgebra(DefaultEngine())
|
val multikAlgebra = MultikDoubleAlgebra(DefaultEngine())
|
||||||
|
|
||||||
fun main(): Unit = with(multikAlgebra) {
|
fun main(): Unit = with(multikAlgebra) {
|
||||||
val a = Multik.ndarray(intArrayOf(1, 2, 3)).asType<Float64>().wrap()
|
val a = Multik.ndarray(intArrayOf(1, 2, 3)).asType<Double>().wrap()
|
||||||
val b = Multik.ndarray(doubleArrayOf(1.0, 2.0, 3.0)).wrap()
|
val b = Multik.ndarray(doubleArrayOf(1.0, 2.0, 3.0)).wrap()
|
||||||
one(a.shape) - a + b * 3.0
|
one(a.shape) - a + b * 3.0
|
||||||
}
|
}
|
||||||
|
@ -1,11 +1,12 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2018-2024 KMath contributors.
|
* Copyright 2018-2022 KMath contributors.
|
||||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package space.kscience.kmath.tensors
|
package space.kscience.kmath.tensors
|
||||||
|
|
||||||
import space.kscience.kmath.nd.ShapeND
|
import space.kscience.kmath.nd.ShapeND
|
||||||
|
import space.kscience.kmath.nd.contentEquals
|
||||||
import space.kscience.kmath.operations.asIterable
|
import space.kscience.kmath.operations.asIterable
|
||||||
import space.kscience.kmath.operations.invoke
|
import space.kscience.kmath.operations.invoke
|
||||||
import space.kscience.kmath.tensors.core.*
|
import space.kscience.kmath.tensors.core.*
|
||||||
@ -93,7 +94,7 @@ class Dense(
|
|||||||
|
|
||||||
// simple accuracy equal to the proportion of correct answers
|
// simple accuracy equal to the proportion of correct answers
|
||||||
fun accuracy(yPred: DoubleTensor, yTrue: DoubleTensor): Double {
|
fun accuracy(yPred: DoubleTensor, yTrue: DoubleTensor): Double {
|
||||||
check(yPred.shape == yTrue.shape)
|
check(yPred.shape contentEquals yTrue.shape)
|
||||||
val n = yPred.shape[0]
|
val n = yPred.shape[0]
|
||||||
var correctCnt = 0
|
var correctCnt = 0
|
||||||
for (i in 0 until n) {
|
for (i in 0 until n) {
|
||||||
|
@ -5,9 +5,12 @@
|
|||||||
kotlin.code.style=official
|
kotlin.code.style=official
|
||||||
kotlin.mpp.stability.nowarn=true
|
kotlin.mpp.stability.nowarn=true
|
||||||
kotlin.native.ignoreDisabledTargets=true
|
kotlin.native.ignoreDisabledTargets=true
|
||||||
|
|
||||||
org.gradle.configureondemand=true
|
org.gradle.configureondemand=true
|
||||||
org.gradle.jvmargs=-Xmx4096m
|
org.gradle.jvmargs=-Xmx4096m
|
||||||
|
|
||||||
|
toolsVersion=0.14.8-kotlin-1.8.20
|
||||||
|
|
||||||
|
|
||||||
org.gradle.parallel=true
|
org.gradle.parallel=true
|
||||||
org.gradle.workers.max=4
|
org.gradle.workers.max=4
|
||||||
|
|
||||||
toolsVersion=0.15.4-kotlin-2.0.0
|
|
@ -1,14 +0,0 @@
|
|||||||
[versions]
|
|
||||||
|
|
||||||
commons-rng = "1.6"
|
|
||||||
multik = "0.2.3"
|
|
||||||
|
|
||||||
[libraries]
|
|
||||||
|
|
||||||
commons-rng-simple = { module = "org.apache.commons:commons-rng-simple", version.ref = "commons-rng" }
|
|
||||||
commons-rng-sampling = { module = "org.apache.commons:commons-rng-sampling", version.ref = "commons-rng" }
|
|
||||||
|
|
||||||
multik-core = { module = "org.jetbrains.kotlinx:multik-core", version.ref = "multik" }
|
|
||||||
multik-default = { module = "org.jetbrains.kotlinx:multik-default", version.ref = "multik" }
|
|
||||||
|
|
||||||
[plugins]
|
|
2
gradle/wrapper/gradle-wrapper.properties
vendored
@ -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-8.7-bin.zip
|
distributionUrl=https\://services.gradle.org/distributions/gradle-8.1.1-bin.zip
|
||||||
zipStoreBase=GRADLE_USER_HOME
|
zipStoreBase=GRADLE_USER_HOME
|
||||||
zipStorePath=wrapper/dists
|
zipStorePath=wrapper/dists
|
||||||
|
@ -10,8 +10,19 @@ Extensions to MST API: transformations, dynamic compilation and visualization.
|
|||||||
|
|
||||||
## Artifact:
|
## Artifact:
|
||||||
|
|
||||||
The Maven coordinates of this project are `space.kscience:kmath-ast:0.4.0`.
|
The Maven coordinates of this project are `space.kscience:kmath-ast:0.4.0-dev-1`.
|
||||||
|
|
||||||
|
**Gradle Groovy:**
|
||||||
|
```groovy
|
||||||
|
repositories {
|
||||||
|
maven { url 'https://repo.kotlin.link' }
|
||||||
|
mavenCentral()
|
||||||
|
}
|
||||||
|
|
||||||
|
dependencies {
|
||||||
|
implementation 'space.kscience:kmath-ast:0.4.0-dev-1'
|
||||||
|
}
|
||||||
|
```
|
||||||
**Gradle Kotlin DSL:**
|
**Gradle Kotlin DSL:**
|
||||||
```kotlin
|
```kotlin
|
||||||
repositories {
|
repositories {
|
||||||
@ -20,33 +31,27 @@ repositories {
|
|||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
implementation("space.kscience:kmath-ast:0.4.0")
|
implementation("space.kscience:kmath-ast:0.4.0-dev-1")
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
## Parsing expressions
|
## Parsing expressions
|
||||||
|
|
||||||
In this module there is a parser from human-readable strings like `"x^3-x+3"` (in the more
|
In this module there is a parser from human-readable strings like `"x^3-x+3"` (in the more specific [grammar](reference/ArithmeticsEvaluator.g4)) to MST instances.
|
||||||
specific [grammar](reference/ArithmeticsEvaluator.g4)) to MST instances.
|
|
||||||
|
|
||||||
Supported literals:
|
Supported literals:
|
||||||
|
|
||||||
1. Constants and variables (consist of latin letters, digits and underscores, can't start with digit): `x`, `_Abc2`.
|
1. Constants and variables (consist of latin letters, digits and underscores, can't start with digit): `x`, `_Abc2`.
|
||||||
2. Numbers: `123`, `1.02`, `1e10`, `1e-10`, `1.0e+3`—all parsed either as `kotlin.Long` or `kotlin.Double`.
|
2. Numbers: `123`, `1.02`, `1e10`, `1e-10`, `1.0e+3`—all parsed either as `kotlin.Long` or `kotlin.Double`.
|
||||||
|
|
||||||
Supported binary operators (from the highest precedence to the lowest one):
|
Supported binary operators (from the highest precedence to the lowest one):
|
||||||
|
|
||||||
1. `^`
|
1. `^`
|
||||||
2. `*`, `/`
|
2. `*`, `/`
|
||||||
3. `+`, `-`
|
3. `+`, `-`
|
||||||
|
|
||||||
Supported unary operator:
|
Supported unary operator:
|
||||||
|
|
||||||
1. `-`, e. g. `-x`
|
1. `-`, e. g. `-x`
|
||||||
|
|
||||||
Arbitrary unary and binary functions are also supported: names consist of latin letters, digits and underscores, can't
|
Arbitrary unary and binary functions are also supported: names consist of latin letters, digits and underscores, can't start with digit. Examples:
|
||||||
start with digit. Examples:
|
|
||||||
|
|
||||||
1. `sin(x)`
|
1. `sin(x)`
|
||||||
2. `add(x, y)`
|
2. `add(x, y)`
|
||||||
|
|
||||||
@ -111,15 +116,12 @@ public final class CompiledExpression_-386104628_0 implements DoubleExpression {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
Setting JVM system property `space.kscience.kmath.ast.dump.generated.classes` to `1` makes the translator dump class
|
Setting JVM system property `space.kscience.kmath.ast.dump.generated.classes` to `1` makes the translator dump class files to program's working directory, so they can be reviewed manually.
|
||||||
files to program's working directory, so they can be reviewed manually.
|
|
||||||
|
|
||||||
#### Limitations
|
#### Limitations
|
||||||
|
|
||||||
- The same classes may be generated and loaded twice, so it is recommended to cache compiled expressions to avoid class
|
- The same classes may be generated and loaded twice, so it is recommended to cache compiled expressions to avoid class loading overhead.
|
||||||
loading overhead.
|
- This API is not supported by non-dynamic JVM implementations like TeaVM or GraalVM Native Image because they may not support class loaders.
|
||||||
- This API is not supported by non-dynamic JVM implementations like TeaVM or GraalVM Native Image because they may not
|
|
||||||
support class loaders.
|
|
||||||
|
|
||||||
### On JS
|
### On JS
|
||||||
|
|
||||||
@ -197,8 +199,7 @@ public fun main() {
|
|||||||
|
|
||||||
Result LaTeX:
|
Result LaTeX:
|
||||||
|
|
||||||
$$\operatorname{exp}\\,\left(\sqrt{x}\right)-\frac{\frac{\operatorname{arcsin}\\,\left(2\\,x\right)
|
$$\operatorname{exp}\\,\left(\sqrt{x}\right)-\frac{\frac{\operatorname{arcsin}\\,\left(2\\,x\right)}{2\times10^{10}+x^{3}}}{12}+x^{2/3}$$
|
||||||
}{2\times10^{10}+x^{3}}}{12}+x^{2/3}$$
|
|
||||||
|
|
||||||
Result MathML (can be used with MathJax or other renderers):
|
Result MathML (can be used with MathJax or other renderers):
|
||||||
|
|
||||||
|
@ -2,22 +2,9 @@ plugins {
|
|||||||
id("space.kscience.gradle.mpp")
|
id("space.kscience.gradle.mpp")
|
||||||
}
|
}
|
||||||
|
|
||||||
kscience {
|
kscience{
|
||||||
jvm()
|
jvm()
|
||||||
js{
|
js()
|
||||||
nodejs {
|
|
||||||
testTask {
|
|
||||||
useMocha().timeout = "0"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
browser {
|
|
||||||
useCommonJs()
|
|
||||||
testTask {
|
|
||||||
useMocha().timeout = "0"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
native()
|
native()
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
@ -31,17 +18,30 @@ kscience {
|
|||||||
|
|
||||||
dependencies(jsMain) {
|
dependencies(jsMain) {
|
||||||
implementation(npm("astring", "1.7.5"))
|
implementation(npm("astring", "1.7.5"))
|
||||||
implementation(npm("binaryen", "117.0.0"))
|
implementation(npm("binaryen", "101.0.0"))
|
||||||
implementation(npm("js-base64", "3.6.1"))
|
implementation(npm("js-base64", "3.6.1"))
|
||||||
}
|
}
|
||||||
|
|
||||||
dependencies(jvmMain) {
|
dependencies(jvmMain){
|
||||||
implementation("org.ow2.asm:asm-commons:9.2")
|
implementation("org.ow2.asm:asm-commons:9.2")
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
kotlin {
|
kotlin {
|
||||||
|
js {
|
||||||
|
nodejs {
|
||||||
|
testTask {
|
||||||
|
useMocha().timeout = "0"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
browser {
|
||||||
|
testTask {
|
||||||
|
useMocha().timeout = "0"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
sourceSets {
|
sourceSets {
|
||||||
filter { it.name.contains("test", true) }
|
filter { it.name.contains("test", true) }
|
||||||
|