20
.github/workflows/build.yml
vendored
@ -1,6 +1,9 @@
|
|||||||
name: Gradle build
|
name: Gradle build
|
||||||
|
|
||||||
on: [ push ]
|
on:
|
||||||
|
push:
|
||||||
|
branches: [ dev, master ]
|
||||||
|
pull_request:
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
build:
|
build:
|
||||||
@ -8,23 +11,22 @@ jobs:
|
|||||||
matrix:
|
matrix:
|
||||||
os: [ macOS-latest, windows-latest ]
|
os: [ macOS-latest, windows-latest ]
|
||||||
runs-on: ${{matrix.os}}
|
runs-on: ${{matrix.os}}
|
||||||
timeout-minutes: 30
|
timeout-minutes: 40
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout the repo
|
- name: Checkout the repo
|
||||||
uses: actions/checkout@v2
|
uses: actions/checkout@v2
|
||||||
- name: Set up JDK 11
|
- name: Set up JDK 11
|
||||||
uses: DeLaGuardo/setup-graalvm@4.0
|
uses: DeLaGuardo/setup-graalvm@4.0
|
||||||
with:
|
with:
|
||||||
graalvm: 21.1.0
|
graalvm: 21.2.0
|
||||||
java: java11
|
java: java11
|
||||||
arch: amd64
|
arch: amd64
|
||||||
- name: Add msys to path
|
|
||||||
if: matrix.os == 'windows-latest'
|
|
||||||
run: SETX PATH "%PATH%;C:\msys64\mingw64\bin"
|
|
||||||
- name: Cache gradle
|
- name: Cache gradle
|
||||||
uses: actions/cache@v2
|
uses: actions/cache@v2
|
||||||
with:
|
with:
|
||||||
path: ~/.gradle/caches
|
path: |
|
||||||
|
~/.gradle/caches
|
||||||
|
~/.gradle/wrapper
|
||||||
key: ${{ runner.os }}-gradle-${{ hashFiles('*.gradle.kts') }}
|
key: ${{ runner.os }}-gradle-${{ hashFiles('*.gradle.kts') }}
|
||||||
restore-keys: |
|
restore-keys: |
|
||||||
${{ runner.os }}-gradle-
|
${{ runner.os }}-gradle-
|
||||||
@ -35,5 +37,7 @@ jobs:
|
|||||||
key: ${{ runner.os }}-gradle-${{ hashFiles('*.gradle.kts') }}
|
key: ${{ runner.os }}-gradle-${{ hashFiles('*.gradle.kts') }}
|
||||||
restore-keys: |
|
restore-keys: |
|
||||||
${{ runner.os }}-gradle-
|
${{ runner.os }}-gradle-
|
||||||
|
- name: Gradle Wrapper Validation
|
||||||
|
uses: gradle/wrapper-validation-action@v1.0.4
|
||||||
- name: Build
|
- name: Build
|
||||||
run: ./gradlew build --no-daemon --stacktrace
|
run: ./gradlew build --build-cache --no-daemon --stacktrace
|
||||||
|
26
.github/workflows/pages.yml
vendored
@ -2,23 +2,27 @@ name: Dokka publication
|
|||||||
|
|
||||||
on:
|
on:
|
||||||
push:
|
push:
|
||||||
branches:
|
branches: [ master ]
|
||||||
- master
|
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
build:
|
build:
|
||||||
runs-on: ubuntu-20.04
|
runs-on: ubuntu-20.04
|
||||||
|
timeout-minutes: 40
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout the repo
|
- uses: actions/checkout@v2
|
||||||
uses: actions/checkout@v2
|
- uses: DeLaGuardo/setup-graalvm@4.0
|
||||||
- name: Set up JDK 11
|
|
||||||
uses: actions/setup-java@v1
|
|
||||||
with:
|
with:
|
||||||
java-version: 11
|
graalvm: 21.2.0
|
||||||
- name: Build
|
java: java11
|
||||||
run: ./gradlew dokkaHtmlMultiModule --no-daemon --no-parallel --stacktrace
|
arch: amd64
|
||||||
- name: Deploy to GitHub Pages
|
- uses: actions/cache@v2
|
||||||
uses: JamesIves/github-pages-deploy-action@4.1.0
|
with:
|
||||||
|
path: ~/.gradle/caches
|
||||||
|
key: ${{ runner.os }}-gradle-${{ hashFiles('*.gradle.kts') }}
|
||||||
|
restore-keys: |
|
||||||
|
${{ runner.os }}-gradle-
|
||||||
|
- run: ./gradlew dokkaHtmlMultiModule --build-cache --no-daemon --no-parallel --stacktrace
|
||||||
|
- uses: JamesIves/github-pages-deploy-action@4.1.0
|
||||||
with:
|
with:
|
||||||
branch: gh-pages
|
branch: gh-pages
|
||||||
folder: build/dokka/htmlMultiModule
|
folder: build/dokka/htmlMultiModule
|
||||||
|
34
.github/workflows/publish.yml
vendored
@ -3,8 +3,7 @@ name: Gradle publish
|
|||||||
on:
|
on:
|
||||||
workflow_dispatch:
|
workflow_dispatch:
|
||||||
release:
|
release:
|
||||||
types:
|
types: [ created ]
|
||||||
- created
|
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
publish:
|
publish:
|
||||||
@ -20,16 +19,15 @@ jobs:
|
|||||||
- name: Set up JDK 11
|
- name: Set up JDK 11
|
||||||
uses: DeLaGuardo/setup-graalvm@4.0
|
uses: DeLaGuardo/setup-graalvm@4.0
|
||||||
with:
|
with:
|
||||||
graalvm: 21.1.0
|
graalvm: 21.2.0
|
||||||
java: java11
|
java: java11
|
||||||
arch: amd64
|
arch: amd64
|
||||||
- name: Add msys to path
|
|
||||||
if: matrix.os == 'windows-latest'
|
|
||||||
run: SETX PATH "%PATH%;C:\msys64\mingw64\bin"
|
|
||||||
- name: Cache gradle
|
- name: Cache gradle
|
||||||
uses: actions/cache@v2
|
uses: actions/cache@v2
|
||||||
with:
|
with:
|
||||||
path: ~/.gradle/caches
|
path: |
|
||||||
|
~/.gradle/caches
|
||||||
|
~/.gradle/wrapper
|
||||||
key: ${{ runner.os }}-gradle-${{ hashFiles('*.gradle.kts') }}
|
key: ${{ runner.os }}-gradle-${{ hashFiles('*.gradle.kts') }}
|
||||||
restore-keys: |
|
restore-keys: |
|
||||||
${{ runner.os }}-gradle-
|
${{ runner.os }}-gradle-
|
||||||
@ -40,22 +38,18 @@ jobs:
|
|||||||
key: ${{ runner.os }}-gradle-${{ hashFiles('*.gradle.kts') }}
|
key: ${{ runner.os }}-gradle-${{ hashFiles('*.gradle.kts') }}
|
||||||
restore-keys: |
|
restore-keys: |
|
||||||
${{ runner.os }}-gradle-
|
${{ runner.os }}-gradle-
|
||||||
|
- name: Gradle Wrapper Validation
|
||||||
|
uses: gradle/wrapper-validation-action@v1.0.4
|
||||||
- name: Publish Windows Artifacts
|
- name: Publish Windows Artifacts
|
||||||
if: matrix.os == 'windows-latest'
|
if: matrix.os == 'windows-latest'
|
||||||
|
shell: cmd
|
||||||
run: >
|
run: >
|
||||||
./gradlew release --no-daemon
|
./gradlew release --no-daemon --build-cache -Ppublishing.enabled=true
|
||||||
-Ppublishing.enabled=true
|
-Ppublishing.space.user=${{ secrets.SPACE_APP_ID }}
|
||||||
-Ppublishing.github.user=${{ secrets.PUBLISHING_GITHUB_USER }}
|
-Ppublishing.space.token=${{ secrets.SPACE_APP_SECRET }}
|
||||||
-Ppublishing.github.token=${{ secrets.PUBLISHING_GITHUB_TOKEN }}
|
|
||||||
-Ppublishing.space.user=${{ secrets.PUBLISHING_SPACE_USER }}
|
|
||||||
-Ppublishing.space.token=${{ secrets.PUBLISHING_SPACE_TOKEN }}
|
|
||||||
- name: Publish Mac Artifacts
|
- name: Publish Mac Artifacts
|
||||||
if: matrix.os == 'macOS-latest'
|
if: matrix.os == 'macOS-latest'
|
||||||
run: >
|
run: >
|
||||||
./gradlew release --no-daemon
|
./gradlew release --no-daemon --build-cache -Ppublishing.enabled=true -Ppublishing.platform=macosX64
|
||||||
-Ppublishing.enabled=true
|
-Ppublishing.space.user=${{ secrets.SPACE_APP_ID }}
|
||||||
-Ppublishing.platform=macosX64
|
-Ppublishing.space.token=${{ secrets.SPACE_APP_SECRET }}
|
||||||
-Ppublishing.github.user=${{ secrets.PUBLISHING_GITHUB_USER }}
|
|
||||||
-Ppublishing.github.token=${{ secrets.PUBLISHING_GITHUB_TOKEN }}
|
|
||||||
-Ppublishing.space.user=${{ secrets.PUBLISHING_SPACE_USER }}
|
|
||||||
-Ppublishing.space.token=${{ secrets.PUBLISHING_SPACE_TOKEN }}
|
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
<component name="CopyrightManager">
|
<component name="CopyrightManager">
|
||||||
<copyright>
|
<copyright>
|
||||||
<option name="notice" value="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." />
|
<option name="notice" value="Copyright 2018-2021 KMath contributors. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file." />
|
||||||
<option name="myName" value="kmath" />
|
<option name="myName" value="kmath" />
|
||||||
</copyright>
|
</copyright>
|
||||||
</component>
|
</component>
|
||||||
|
38
CHANGELOG.md
@ -2,32 +2,49 @@
|
|||||||
|
|
||||||
## [Unreleased]
|
## [Unreleased]
|
||||||
### Added
|
### Added
|
||||||
- ScaleOperations interface
|
- `ScaleOperations` interface
|
||||||
- Field extends ScaleOperations
|
- `Field` extends `ScaleOperations`
|
||||||
- Basic integration API
|
- Basic integration API
|
||||||
- Basic MPP distributions and samplers
|
- Basic MPP distributions and samplers
|
||||||
- bindSymbolOrNull
|
- `bindSymbolOrNull`
|
||||||
- Blocking chains and Statistics
|
- Blocking chains and Statistics
|
||||||
- Multiplatform integration
|
- Multiplatform integration
|
||||||
- Integration for any Field element
|
- Integration for any Field element
|
||||||
- Extended operations for ND4J fields
|
- Extended operations for ND4J fields
|
||||||
- Jupyter Notebook integration module (kmath-jupyter)
|
- Jupyter Notebook integration module (kmath-jupyter)
|
||||||
|
- `@PerformancePitfall` annotation to mark possibly slow API
|
||||||
|
- Unified architecture for Integration and Optimization using features.
|
||||||
|
- `BigInt` operation performance improvement and fixes by @zhelenskiy (#328)
|
||||||
|
- Integration between `MST` and Symja `IExpr`
|
||||||
|
- Complex power
|
||||||
|
|
||||||
### Changed
|
### Changed
|
||||||
- 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.
|
||||||
- VectorSpace is now a vector space
|
- VectorSpace is now a vector space
|
||||||
- Buffer factories for primitives moved to MutableBuffer.Companion
|
- Buffer factories for primitives moved to MutableBuffer.Companion
|
||||||
- NDStructure and NDAlgebra to StructureND and AlgebraND respectively
|
- Rename `NDStructure` and `NDAlgebra` to `StructureND` and `AlgebraND` respectively
|
||||||
- Real -> Double
|
- `Real` -> `Double`
|
||||||
- DataSets are moved from functions to core
|
- DataSets are moved from functions to core
|
||||||
- Redesign advanced Chain API
|
- Redesign advanced Chain API
|
||||||
- Redesign MST. Remove MSTExpression.
|
- Redesign `MST`. Remove `MstExpression`.
|
||||||
- Move MST to core
|
- Move `MST` to core
|
||||||
- Separated benchmarks and examples
|
- Separated benchmarks and examples
|
||||||
- Rewritten EJML module without ejml-simple
|
- Rewrite `kmath-ejml` without `ejml-simple` artifact, support sparse matrices
|
||||||
|
- Promote stability of kmath-ast and kmath-kotlingrad to EXPERIMENTAL.
|
||||||
|
- ColumnarData returns nullable column
|
||||||
|
- `MST` is made sealed interface
|
||||||
|
- Replace `MST.Symbolic` by `Symbol`, `Symbol` now implements MST
|
||||||
|
- Remove Any restriction on polynomials
|
||||||
|
- Add `out` variance to type parameters of `StructureND` and its implementations where possible
|
||||||
|
- Rename `DifferentiableMstExpression` to `KotlingradExpression`
|
||||||
|
- `FeatureSet` now accepts only `Feature`. It is possible to override keys and use interfaces.
|
||||||
|
- Use `Symbol` factory function instead of `StringSymbol`
|
||||||
|
- New discoverability pattern: `<Type>.algebra.<nd/etc>`
|
||||||
|
- Adjusted commons-math API for linear solvers to match conventions.
|
||||||
|
|
||||||
### Deprecated
|
### Deprecated
|
||||||
|
- Specialized `DoubleBufferAlgebra`
|
||||||
|
|
||||||
### Removed
|
### Removed
|
||||||
- Nearest in Domain. To be implemented in geometry package.
|
- Nearest in Domain. To be implemented in geometry package.
|
||||||
@ -35,10 +52,13 @@
|
|||||||
- `contentEquals` from Buffer. It moved to the companion.
|
- `contentEquals` from Buffer. It moved to the companion.
|
||||||
- MSTExpression
|
- MSTExpression
|
||||||
- Expression algebra builders
|
- Expression algebra builders
|
||||||
- Comples and Quaternion no longer are elements.
|
- Complex and Quaternion no longer are elements.
|
||||||
|
- Second generic from DifferentiableExpression
|
||||||
|
- Algebra elements are completely removed. Use algebra contexts instead.
|
||||||
|
|
||||||
### Fixed
|
### Fixed
|
||||||
- Ring inherits RingOperations, not GroupOperations
|
- Ring inherits RingOperations, not GroupOperations
|
||||||
|
- Univariate histogram filling
|
||||||
|
|
||||||
### Security
|
### Security
|
||||||
|
|
||||||
|
201
LICENSE
@ -1,201 +0,0 @@
|
|||||||
Apache License
|
|
||||||
Version 2.0, January 2004
|
|
||||||
http://www.apache.org/licenses/
|
|
||||||
|
|
||||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
|
||||||
|
|
||||||
1. Definitions.
|
|
||||||
|
|
||||||
"License" shall mean the terms and conditions for use, reproduction,
|
|
||||||
and distribution as defined by Sections 1 through 9 of this document.
|
|
||||||
|
|
||||||
"Licensor" shall mean the copyright owner or entity authorized by
|
|
||||||
the copyright owner that is granting the License.
|
|
||||||
|
|
||||||
"Legal Entity" shall mean the union of the acting entity and all
|
|
||||||
other entities that control, are controlled by, or are under common
|
|
||||||
control with that entity. For the purposes of this definition,
|
|
||||||
"control" means (i) the power, direct or indirect, to cause the
|
|
||||||
direction or management of such entity, whether by contract or
|
|
||||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
|
||||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
|
||||||
|
|
||||||
"You" (or "Your") shall mean an individual or Legal Entity
|
|
||||||
exercising permissions granted by this License.
|
|
||||||
|
|
||||||
"Source" form shall mean the preferred form for making modifications,
|
|
||||||
including but not limited to software source code, documentation
|
|
||||||
source, and configuration files.
|
|
||||||
|
|
||||||
"Object" form shall mean any form resulting from mechanical
|
|
||||||
transformation or translation of a Source form, including but
|
|
||||||
not limited to compiled object code, generated documentation,
|
|
||||||
and conversions to other media types.
|
|
||||||
|
|
||||||
"Work" shall mean the work of authorship, whether in Source or
|
|
||||||
Object form, made available under the License, as indicated by a
|
|
||||||
copyright notice that is included in or attached to the work
|
|
||||||
(an example is provided in the Appendix below).
|
|
||||||
|
|
||||||
"Derivative Works" shall mean any work, whether in Source or Object
|
|
||||||
form, that is based on (or derived from) the Work and for which the
|
|
||||||
editorial revisions, annotations, elaborations, or other modifications
|
|
||||||
represent, as a whole, an original work of authorship. For the purposes
|
|
||||||
of this License, Derivative Works shall not include works that remain
|
|
||||||
separable from, or merely link (or bind by name) to the interfaces of,
|
|
||||||
the Work and Derivative Works thereof.
|
|
||||||
|
|
||||||
"Contribution" shall mean any work of authorship, including
|
|
||||||
the original version of the Work and any modifications or additions
|
|
||||||
to that Work or Derivative Works thereof, that is intentionally
|
|
||||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
|
||||||
or by an individual or Legal Entity authorized to submit on behalf of
|
|
||||||
the copyright owner. For the purposes of this definition, "submitted"
|
|
||||||
means any form of electronic, verbal, or written communication sent
|
|
||||||
to the Licensor or its representatives, including but not limited to
|
|
||||||
communication on electronic mailing lists, source code control systems,
|
|
||||||
and issue tracking systems that are managed by, or on behalf of, the
|
|
||||||
Licensor for the purpose of discussing and improving the Work, but
|
|
||||||
excluding communication that is conspicuously marked or otherwise
|
|
||||||
designated in writing by the copyright owner as "Not a Contribution."
|
|
||||||
|
|
||||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
|
||||||
on behalf of whom a Contribution has been received by Licensor and
|
|
||||||
subsequently incorporated within the Work.
|
|
||||||
|
|
||||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
|
||||||
this License, each Contributor hereby grants to You a perpetual,
|
|
||||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
|
||||||
copyright license to reproduce, prepare Derivative Works of,
|
|
||||||
publicly display, publicly perform, sublicense, and distribute the
|
|
||||||
Work and such Derivative Works in Source or Object form.
|
|
||||||
|
|
||||||
3. Grant of Patent License. Subject to the terms and conditions of
|
|
||||||
this License, each Contributor hereby grants to You a perpetual,
|
|
||||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
|
||||||
(except as stated in this section) patent license to make, have made,
|
|
||||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
|
||||||
where such license applies only to those patent claims licensable
|
|
||||||
by such Contributor that are necessarily infringed by their
|
|
||||||
Contribution(s) alone or by combination of their Contribution(s)
|
|
||||||
with the Work to which such Contribution(s) was submitted. If You
|
|
||||||
institute patent litigation against any entity (including a
|
|
||||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
|
||||||
or a Contribution incorporated within the Work constitutes direct
|
|
||||||
or contributory patent infringement, then any patent licenses
|
|
||||||
granted to You under this License for that Work shall terminate
|
|
||||||
as of the date such litigation is filed.
|
|
||||||
|
|
||||||
4. Redistribution. You may reproduce and distribute copies of the
|
|
||||||
Work or Derivative Works thereof in any medium, with or without
|
|
||||||
modifications, and in Source or Object form, provided that You
|
|
||||||
meet the following conditions:
|
|
||||||
|
|
||||||
(a) You must give any other recipients of the Work or
|
|
||||||
Derivative Works a copy of this License; and
|
|
||||||
|
|
||||||
(b) You must cause any modified files to carry prominent notices
|
|
||||||
stating that You changed the files; and
|
|
||||||
|
|
||||||
(c) You must retain, in the Source form of any Derivative Works
|
|
||||||
that You distribute, all copyright, patent, trademark, and
|
|
||||||
attribution notices from the Source form of the Work,
|
|
||||||
excluding those notices that do not pertain to any part of
|
|
||||||
the Derivative Works; and
|
|
||||||
|
|
||||||
(d) If the Work includes a "NOTICE" text file as part of its
|
|
||||||
distribution, then any Derivative Works that You distribute must
|
|
||||||
include a readable copy of the attribution notices contained
|
|
||||||
within such NOTICE file, excluding those notices that do not
|
|
||||||
pertain to any part of the Derivative Works, in at least one
|
|
||||||
of the following places: within a NOTICE text file distributed
|
|
||||||
as part of the Derivative Works; within the Source form or
|
|
||||||
documentation, if provided along with the Derivative Works; or,
|
|
||||||
within a display generated by the Derivative Works, if and
|
|
||||||
wherever such third-party notices normally appear. The contents
|
|
||||||
of the NOTICE file are for informational purposes only and
|
|
||||||
do not modify the License. You may add Your own attribution
|
|
||||||
notices within Derivative Works that You distribute, alongside
|
|
||||||
or as an addendum to the NOTICE text from the Work, provided
|
|
||||||
that such additional attribution notices cannot be construed
|
|
||||||
as modifying the License.
|
|
||||||
|
|
||||||
You may add Your own copyright statement to Your modifications and
|
|
||||||
may provide additional or different license terms and conditions
|
|
||||||
for use, reproduction, or distribution of Your modifications, or
|
|
||||||
for any such Derivative Works as a whole, provided Your use,
|
|
||||||
reproduction, and distribution of the Work otherwise complies with
|
|
||||||
the conditions stated in this License.
|
|
||||||
|
|
||||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
|
||||||
any Contribution intentionally submitted for inclusion in the Work
|
|
||||||
by You to the Licensor shall be under the terms and conditions of
|
|
||||||
this License, without any additional terms or conditions.
|
|
||||||
Notwithstanding the above, nothing herein shall supersede or modify
|
|
||||||
the terms of any separate license agreement you may have executed
|
|
||||||
with Licensor regarding such Contributions.
|
|
||||||
|
|
||||||
6. Trademarks. This License does not grant permission to use the trade
|
|
||||||
names, trademarks, service marks, or product names of the Licensor,
|
|
||||||
except as required for reasonable and customary use in describing the
|
|
||||||
origin of the Work and reproducing the content of the NOTICE file.
|
|
||||||
|
|
||||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
|
||||||
agreed to in writing, Licensor provides the Work (and each
|
|
||||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
|
||||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
|
||||||
implied, including, without limitation, any warranties or conditions
|
|
||||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
|
||||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
|
||||||
appropriateness of using or redistributing the Work and assume any
|
|
||||||
risks associated with Your exercise of permissions under this License.
|
|
||||||
|
|
||||||
8. Limitation of Liability. In no event and under no legal theory,
|
|
||||||
whether in tort (including negligence), contract, or otherwise,
|
|
||||||
unless required by applicable law (such as deliberate and grossly
|
|
||||||
negligent acts) or agreed to in writing, shall any Contributor be
|
|
||||||
liable to You for damages, including any direct, indirect, special,
|
|
||||||
incidental, or consequential damages of any character arising as a
|
|
||||||
result of this License or out of the use or inability to use the
|
|
||||||
Work (including but not limited to damages for loss of goodwill,
|
|
||||||
work stoppage, computer failure or malfunction, or any and all
|
|
||||||
other commercial damages or losses), even if such Contributor
|
|
||||||
has been advised of the possibility of such damages.
|
|
||||||
|
|
||||||
9. Accepting Warranty or Additional Liability. While redistributing
|
|
||||||
the Work or Derivative Works thereof, You may choose to offer,
|
|
||||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
|
||||||
or other liability obligations and/or rights consistent with this
|
|
||||||
License. However, in accepting such obligations, You may act only
|
|
||||||
on Your own behalf and on Your sole responsibility, not on behalf
|
|
||||||
of any other Contributor, and only if You agree to indemnify,
|
|
||||||
defend, and hold each Contributor harmless for any liability
|
|
||||||
incurred by, or claims asserted against, such Contributor by reason
|
|
||||||
of your accepting any such warranty or additional liability.
|
|
||||||
|
|
||||||
END OF TERMS AND CONDITIONS
|
|
||||||
|
|
||||||
APPENDIX: How to apply the Apache License to your work.
|
|
||||||
|
|
||||||
To apply the Apache License to your work, attach the following
|
|
||||||
boilerplate notice, with the fields enclosed by brackets "[]"
|
|
||||||
replaced with your own identifying information. (Don't include
|
|
||||||
the brackets!) The text should be enclosed in the appropriate
|
|
||||||
comment syntax for the file format. We also recommend that a
|
|
||||||
file or class name and description of purpose be included on the
|
|
||||||
same "printed page" as the copyright notice for easier
|
|
||||||
identification within third-party archives.
|
|
||||||
|
|
||||||
Copyright [yyyy] [name of copyright owner]
|
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
you may not use this file except in compliance with the License.
|
|
||||||
You may obtain a copy of the License at
|
|
||||||
|
|
||||||
http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
|
|
||||||
Unless required by applicable law or agreed to in writing, software
|
|
||||||
distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
See the License for the specific language governing permissions and
|
|
||||||
limitations under the License.
|
|
107
README.md
@ -2,14 +2,14 @@
|
|||||||
[![DOI](https://zenodo.org/badge/129486382.svg)](https://zenodo.org/badge/latestdoi/129486382)
|
[![DOI](https://zenodo.org/badge/129486382.svg)](https://zenodo.org/badge/latestdoi/129486382)
|
||||||
![Gradle build](https://github.com/mipt-npm/kmath/workflows/Gradle%20build/badge.svg)
|
![Gradle build](https://github.com/mipt-npm/kmath/workflows/Gradle%20build/badge.svg)
|
||||||
[![Maven Central](https://img.shields.io/maven-central/v/space.kscience/kmath-core.svg?label=Maven%20Central)](https://search.maven.org/search?q=g:%22space.kscience%22)
|
[![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/maven-metadata/v?label=Space&metadataUrl=https%3A%2F%2Fmaven.pkg.jetbrains.space%2Fmipt-npm%2Fp%2Fsci%2Fmaven%2Fkscience%2Fkmath%2Fkmath-core%2Fmaven-metadata.xml)](https://maven.pkg.jetbrains.space/mipt-npm/p/sci/maven/space/kscience/)
|
[![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/)
|
||||||
|
|
||||||
# KMath
|
# KMath
|
||||||
|
|
||||||
Could be pronounced as `key-math`. The **K**otlin **Math**ematics library was initially intended as a Kotlin-based analog to
|
Could be pronounced as `key-math`. The **K**otlin **Math**ematics library was initially intended as a Kotlin-based
|
||||||
Python's NumPy library. Later we found that kotlin is much more flexible language and allows superior architecture
|
analog to Python's NumPy library. Later we found that kotlin is much more flexible language and allows superior
|
||||||
designs. In contrast to `numpy` and `scipy` it is modular and has a lightweight core. The `numpy`-like experience could
|
architecture designs. In contrast to `numpy` and `scipy` it is modular and has a lightweight core. The `numpy`-like
|
||||||
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 (**WIP**)](https://mipt-npm.github.io/kmath/)
|
[Documentation site (**WIP**)](https://mipt-npm.github.io/kmath/)
|
||||||
|
|
||||||
@ -21,26 +21,33 @@ be achieved with [kmath-for-real](/kmath-for-real) extension module.
|
|||||||
|
|
||||||
# Goal
|
# Goal
|
||||||
|
|
||||||
* Provide a flexible and powerful API to work with mathematics abstractions in Kotlin-multiplatform (JVM, JS and Native).
|
* Provide a flexible and powerful API to work with mathematics abstractions in Kotlin-multiplatform (JVM, JS and Native)
|
||||||
|
.
|
||||||
* Provide basic multiplatform implementations for those abstractions (without significant performance optimization).
|
* Provide 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.
|
||||||
|
|
||||||
## Non-goals
|
## Non-goals
|
||||||
|
|
||||||
* Be like NumPy. It was the idea at the beginning, but we decided that we can do better in terms of API.
|
* Be like NumPy. It was the idea at the beginning, but we decided that we can do better in API.
|
||||||
* Provide the best performance out of the box. We have specialized libraries for that. Need only API wrappers for them.
|
* Provide the best performance out of the box. We have specialized libraries for that. Need only API wrappers for them.
|
||||||
* Cover all cases as immediately and in one bundle. We will modularize everything and add new features gradually.
|
* Cover all cases as immediately and in one bundle. We will modularize everything and add new features gradually.
|
||||||
* Provide specialized behavior in the core. API is made generic on purpose, so one needs to specialize for types, like
|
* Provide specialized behavior in the core. API is made generic on purpose, so one needs to specialize for types, like
|
||||||
for `Double` in the core. For that we will have specialization modules like `kmath-for-real`, which will give better
|
for `Double` in the core. For that we will have specialization modules like `kmath-for-real`, which will give better
|
||||||
experience for those, who want to work with specific types.
|
experience for those, who want to work with specific types.
|
||||||
|
|
||||||
## Features and stability
|
## Features and stability
|
||||||
|
|
||||||
KMath is a modular library. Different modules provide different features with different API stability guarantees. All core modules are released with the same version, but with different API change policy. The features are described in module definitions below. The module stability could have following levels:
|
KMath is a modular library. Different modules provide different features with different API stability guarantees. All
|
||||||
|
core modules are released with the same version, but with different API change policy. The features are described in
|
||||||
|
module definitions below. The module stability could have the following levels:
|
||||||
|
|
||||||
* **PROTOTYPE**. On this level there are no compatibility guarantees. All methods and classes form those modules could break any moment. You can still use it, but be sure to fix the specific version.
|
* **PROTOTYPE**. On this level there are no compatibility guarantees. All methods and classes form those modules could
|
||||||
* **EXPERIMENTAL**. The general API is decided, but some changes could be made. Volatile API is marked with `@UnstableKmathAPI` or other stability warning annotations.
|
break any moment. You can still use it, but be sure to fix the specific version.
|
||||||
* **DEVELOPMENT**. API breaking genrally follows semantic versioning ideology. There could be changes in minor versions, but not in patch versions. API is protected with [binary-compatibility-validator](https://github.com/Kotlin/binary-compatibility-validator) tool.
|
* **EXPERIMENTAL**. The general API is decided, but some changes could be made. Volatile API is marked
|
||||||
|
with `@UnstableKmathAPI` or other stability warning annotations.
|
||||||
|
* **DEVELOPMENT**. API breaking generally follows semantic versioning ideology. There could be changes in minor
|
||||||
|
versions, but not in patch versions. API is protected
|
||||||
|
with [binary-compatibility-validator](https://github.com/Kotlin/binary-compatibility-validator) tool.
|
||||||
* **STABLE**. The API stabilized. Breaking changes are allowed only in major releases.
|
* **STABLE**. The API stabilized. Breaking changes are allowed only in major releases.
|
||||||
|
|
||||||
<!--Current feature list is [here](/docs/features.md)-->
|
<!--Current feature list is [here](/docs/features.md)-->
|
||||||
@ -132,7 +139,7 @@ KMath is a modular library. Different modules provide different features with di
|
|||||||
objects to the expression by providing a context. Expressions can be used for a wide variety of purposes from high
|
objects to the expression by providing a context. Expressions can be used for a wide variety of purposes from high
|
||||||
performance calculations to code generation.
|
performance calculations to code generation.
|
||||||
> - [domains](kmath-core/src/commonMain/kotlin/space/kscience/kmath/domains) : Domains
|
> - [domains](kmath-core/src/commonMain/kotlin/space/kscience/kmath/domains) : Domains
|
||||||
> - [autodif](kmath-core/src/commonMain/kotlin/space/kscience/kmath/expressions/SimpleAutoDiff.kt) : Automatic differentiation
|
> - [autodiff](kmath-core/src/commonMain/kotlin/space/kscience/kmath/expressions/SimpleAutoDiff.kt) : Automatic differentiation
|
||||||
|
|
||||||
<hr/>
|
<hr/>
|
||||||
|
|
||||||
@ -161,7 +168,7 @@ performance calculations to code generation.
|
|||||||
<hr/>
|
<hr/>
|
||||||
|
|
||||||
* ### [kmath-for-real](kmath-for-real)
|
* ### [kmath-for-real](kmath-for-real)
|
||||||
> Extension module that should be used to achieve numpy-like behavior.
|
> Extension module that should be used to achieve numpy-like behavior.
|
||||||
All operations are specialized to work with `Double` numbers without declaring algebraic contexts.
|
All operations are specialized to work with `Double` numbers without declaring algebraic contexts.
|
||||||
One can still use generic algebras though.
|
One can still use generic algebras though.
|
||||||
>
|
>
|
||||||
@ -175,7 +182,7 @@ One can still use generic algebras though.
|
|||||||
<hr/>
|
<hr/>
|
||||||
|
|
||||||
* ### [kmath-functions](kmath-functions)
|
* ### [kmath-functions](kmath-functions)
|
||||||
> Functions, integration and interpolation
|
>
|
||||||
>
|
>
|
||||||
> **Maturity**: EXPERIMENTAL
|
> **Maturity**: EXPERIMENTAL
|
||||||
>
|
>
|
||||||
@ -200,6 +207,16 @@ One can still use generic algebras though.
|
|||||||
> **Maturity**: PROTOTYPE
|
> **Maturity**: PROTOTYPE
|
||||||
<hr/>
|
<hr/>
|
||||||
|
|
||||||
|
* ### [kmath-jafama](kmath-jafama)
|
||||||
|
>
|
||||||
|
>
|
||||||
|
> **Maturity**: PROTOTYPE
|
||||||
|
>
|
||||||
|
> **Features:**
|
||||||
|
> - [jafama-double](kmath-jafama/src/main/kotlin/space/kscience/kmath/jafama/) : Double ExtendedField implementations based on Jafama
|
||||||
|
|
||||||
|
<hr/>
|
||||||
|
|
||||||
* ### [kmath-jupyter](kmath-jupyter)
|
* ### [kmath-jupyter](kmath-jupyter)
|
||||||
>
|
>
|
||||||
>
|
>
|
||||||
@ -209,17 +226,22 @@ One can still use generic algebras though.
|
|||||||
* ### [kmath-kotlingrad](kmath-kotlingrad)
|
* ### [kmath-kotlingrad](kmath-kotlingrad)
|
||||||
>
|
>
|
||||||
>
|
>
|
||||||
> **Maturity**: PROTOTYPE
|
> **Maturity**: EXPERIMENTAL
|
||||||
|
>
|
||||||
|
> **Features:**
|
||||||
|
> - [differentiable-mst-expression](kmath-kotlingrad/src/main/kotlin/space/kscience/kmath/kotlingrad/KotlingradExpression.kt) : MST based DifferentiableExpression.
|
||||||
|
> - [scalars-adapters](kmath-kotlingrad/src/main/kotlin/space/kscience/kmath/kotlingrad/scalarsAdapters.kt) : Conversions between Kotlin∇'s SFun and MST
|
||||||
|
|
||||||
<hr/>
|
<hr/>
|
||||||
|
|
||||||
* ### [kmath-memory](kmath-memory)
|
* ### [kmath-memory](kmath-memory)
|
||||||
> An API and basic implementation for arranging objects in a continous memory block.
|
> An API and basic implementation for arranging objects in a continuous memory block.
|
||||||
>
|
>
|
||||||
> **Maturity**: DEVELOPMENT
|
> **Maturity**: DEVELOPMENT
|
||||||
<hr/>
|
<hr/>
|
||||||
|
|
||||||
* ### [kmath-nd4j](kmath-nd4j)
|
* ### [kmath-nd4j](kmath-nd4j)
|
||||||
> ND4J NDStructure implementation and according NDAlgebra classes
|
>
|
||||||
>
|
>
|
||||||
> **Maturity**: EXPERIMENTAL
|
> **Maturity**: EXPERIMENTAL
|
||||||
>
|
>
|
||||||
@ -236,6 +258,12 @@ One can still use generic algebras though.
|
|||||||
> **Maturity**: EXPERIMENTAL
|
> **Maturity**: EXPERIMENTAL
|
||||||
<hr/>
|
<hr/>
|
||||||
|
|
||||||
|
* ### [kmath-symja](kmath-symja)
|
||||||
|
>
|
||||||
|
>
|
||||||
|
> **Maturity**: PROTOTYPE
|
||||||
|
<hr/>
|
||||||
|
|
||||||
* ### [kmath-tensors](kmath-tensors)
|
* ### [kmath-tensors](kmath-tensors)
|
||||||
>
|
>
|
||||||
>
|
>
|
||||||
@ -243,7 +271,7 @@ One can still use generic algebras though.
|
|||||||
>
|
>
|
||||||
> **Features:**
|
> **Features:**
|
||||||
> - [tensor algebra](kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/api/TensorAlgebra.kt) : Basic linear algebra operations on tensors (plus, dot, etc.)
|
> - [tensor algebra](kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/api/TensorAlgebra.kt) : Basic linear algebra operations on tensors (plus, dot, etc.)
|
||||||
> - [tensor algebra with broadcasting](kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/algebras/BroadcastDoubleTensorAlgebra.kt) : Basic linear algebra operations implemented with broadcasting.
|
> - [tensor algebra with broadcasting](kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/core/BroadcastDoubleTensorAlgebra.kt) : Basic linear algebra operations implemented with broadcasting.
|
||||||
> - [linear algebra operations](kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/api/LinearOpsTensorAlgebra.kt) : Advanced linear algebra operations like LU decomposition, SVD, etc.
|
> - [linear algebra operations](kmath-tensors/src/commonMain/kotlin/space/kscience/kmath/tensors/api/LinearOpsTensorAlgebra.kt) : Advanced linear algebra operations like LU decomposition, SVD, etc.
|
||||||
|
|
||||||
<hr/>
|
<hr/>
|
||||||
@ -257,30 +285,33 @@ One can still use generic algebras though.
|
|||||||
|
|
||||||
## Multi-platform support
|
## Multi-platform support
|
||||||
|
|
||||||
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, the 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 performance is one of major goals of KMath in the future, but in some cases it is impossible to achieve
|
Calculation performance is one of major goals of KMath in the future, but in some cases it is impossible to achieve both
|
||||||
both performance and flexibility.
|
performance and flexibility.
|
||||||
|
|
||||||
We expect to focus on creating 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 to use GraalVM-CE 11 for execution in order to get better performance.
|
KMath currently relies on JDK 11 for compilation and execution of Kotlin-JVM part. We recommend to use GraalVM-CE 11 for
|
||||||
|
execution to get better performance.
|
||||||
|
|
||||||
### Repositories
|
### Repositories
|
||||||
|
|
||||||
Release and development artifacts are accessible from mipt-npm [Space](https://www.jetbrains.com/space/) repository `https://maven.pkg.jetbrains.space/mipt-npm/p/sci/maven` (see documentation of
|
Release and development artifacts are accessible from mipt-npm [Space](https://www.jetbrains.com/space/)
|
||||||
[Kotlin Multiplatform](https://kotlinlang.org/docs/reference/multiplatform.html) for more details). The repository could be reached through [repo.kotlin.link](https://repo.kotlin.link) proxy:
|
repository `https://maven.pkg.jetbrains.space/mipt-npm/p/sci/maven` (see documentation of
|
||||||
|
[Kotlin Multiplatform](https://kotlinlang.org/docs/reference/multiplatform.html) for more details). The repository could
|
||||||
|
be reached through [repo.kotlin.link](https://repo.kotlin.link) proxy:
|
||||||
|
|
||||||
```kotlin
|
```kotlin
|
||||||
repositories {
|
repositories {
|
||||||
@ -288,8 +319,8 @@ repositories {
|
|||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
api("space.kscience:kmath-core:0.3.0-dev-8")
|
api("space.kscience:kmath-core:0.3.0-dev-14")
|
||||||
// api("space.kscience:kmath-core-jvm:0.3.0-dev-8") for jvm-specific version
|
// api("space.kscience:kmath-core-jvm:0.3.0-dev-14") for jvm-specific version
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
@ -297,7 +328,7 @@ 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 a feedback about what features are
|
The project requires a lot of additional work. The most important thing we need is a feedback about what features are
|
||||||
required the most. Feel free to create feature requests. We are also welcome to code contributions,
|
required the most. Feel free to create feature requests. We are also welcome to code contributions, especially in issues
|
||||||
especially in issues marked with
|
marked with
|
||||||
[waiting for a hero](https://github.com/mipt-npm/kmath/labels/waiting%20for%20a%20hero) label.
|
[waiting for a hero](https://github.com/mipt-npm/kmath/labels/waiting%20for%20a%20hero) label.
|
||||||
|
@ -1,3 +1,7 @@
|
|||||||
|
@file:Suppress("UNUSED_VARIABLE")
|
||||||
|
|
||||||
|
import space.kscience.kmath.benchmarks.addBenchmarkProperties
|
||||||
|
|
||||||
plugins {
|
plugins {
|
||||||
kotlin("multiplatform")
|
kotlin("multiplatform")
|
||||||
kotlin("plugin.allopen")
|
kotlin("plugin.allopen")
|
||||||
@ -12,6 +16,7 @@ repositories {
|
|||||||
maven("https://repo.kotlin.link")
|
maven("https://repo.kotlin.link")
|
||||||
maven("https://clojars.org/repo")
|
maven("https://clojars.org/repo")
|
||||||
maven("https://jitpack.io")
|
maven("https://jitpack.io")
|
||||||
|
|
||||||
maven("http://logicrunch.research.it.uu.se/maven") {
|
maven("http://logicrunch.research.it.uu.se/maven") {
|
||||||
isAllowInsecureProtocol = true
|
isAllowInsecureProtocol = true
|
||||||
}
|
}
|
||||||
@ -30,7 +35,9 @@ kotlin {
|
|||||||
implementation(project(":kmath-stat"))
|
implementation(project(":kmath-stat"))
|
||||||
implementation(project(":kmath-dimensions"))
|
implementation(project(":kmath-dimensions"))
|
||||||
implementation(project(":kmath-for-real"))
|
implementation(project(":kmath-for-real"))
|
||||||
implementation("org.jetbrains.kotlinx:kotlinx-benchmark-runtime:0.3.0")
|
implementation(project(":kmath-jafama"))
|
||||||
|
implementation(project(":kmath-tensors"))
|
||||||
|
implementation("org.jetbrains.kotlinx:kotlinx-benchmark-runtime:0.3.1")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -41,8 +48,7 @@ kotlin {
|
|||||||
implementation(project(":kmath-nd4j"))
|
implementation(project(":kmath-nd4j"))
|
||||||
implementation(project(":kmath-kotlingrad"))
|
implementation(project(":kmath-kotlingrad"))
|
||||||
implementation(project(":kmath-viktor"))
|
implementation(project(":kmath-viktor"))
|
||||||
implementation("org.nd4j:nd4j-native:1.0.0-beta7")
|
implementation("org.nd4j:nd4j-native:1.0.0-M1")
|
||||||
|
|
||||||
// uncomment if your system supports AVX2
|
// uncomment if your system supports AVX2
|
||||||
// val os = System.getProperty("os.name")
|
// val os = System.getProperty("os.name")
|
||||||
//
|
//
|
||||||
@ -76,6 +82,11 @@ benchmark {
|
|||||||
include("BufferBenchmark")
|
include("BufferBenchmark")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
configurations.register("nd") {
|
||||||
|
commonConfiguration()
|
||||||
|
include("NDFieldBenchmark")
|
||||||
|
}
|
||||||
|
|
||||||
configurations.register("dot") {
|
configurations.register("dot") {
|
||||||
commonConfiguration()
|
commonConfiguration()
|
||||||
include("DotBenchmark")
|
include("DotBenchmark")
|
||||||
@ -95,6 +106,21 @@ benchmark {
|
|||||||
commonConfiguration()
|
commonConfiguration()
|
||||||
include("BigIntBenchmark")
|
include("BigIntBenchmark")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
configurations.register("jafamaDouble") {
|
||||||
|
commonConfiguration()
|
||||||
|
include("JafamaBenchmark")
|
||||||
|
}
|
||||||
|
|
||||||
|
configurations.register("viktor") {
|
||||||
|
commonConfiguration()
|
||||||
|
include("ViktorBenchmark")
|
||||||
|
}
|
||||||
|
|
||||||
|
configurations.register("viktorLog") {
|
||||||
|
commonConfiguration()
|
||||||
|
include("ViktorLogBenchmark")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Fix kotlinx-benchmarks bug
|
// Fix kotlinx-benchmarks bug
|
||||||
@ -124,3 +150,5 @@ tasks.withType<org.jetbrains.kotlin.gradle.tasks.KotlinCompile> {
|
|||||||
readme {
|
readme {
|
||||||
maturity = ru.mipt.npm.gradle.Maturity.EXPERIMENTAL
|
maturity = ru.mipt.npm.gradle.Maturity.EXPERIMENTAL
|
||||||
}
|
}
|
||||||
|
|
||||||
|
addBenchmarkProperties()
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2018-2021 KMath contributors.
|
* Copyright 2018-2021 KMath contributors.
|
||||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
* Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package space.kscience.kmath.benchmarks
|
package space.kscience.kmath.benchmarks
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2018-2021 KMath contributors.
|
* Copyright 2018-2021 KMath contributors.
|
||||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
* Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package space.kscience.kmath.benchmarks
|
package space.kscience.kmath.benchmarks
|
||||||
@ -10,22 +10,36 @@ import kotlinx.benchmark.Blackhole
|
|||||||
import org.openjdk.jmh.annotations.Benchmark
|
import org.openjdk.jmh.annotations.Benchmark
|
||||||
import org.openjdk.jmh.annotations.Scope
|
import org.openjdk.jmh.annotations.Scope
|
||||||
import org.openjdk.jmh.annotations.State
|
import org.openjdk.jmh.annotations.State
|
||||||
import space.kscience.kmath.operations.BigInt
|
import space.kscience.kmath.misc.UnstableKMathAPI
|
||||||
import space.kscience.kmath.operations.BigIntField
|
import space.kscience.kmath.operations.BigIntField
|
||||||
import space.kscience.kmath.operations.JBigIntegerField
|
import space.kscience.kmath.operations.JBigIntegerField
|
||||||
import space.kscience.kmath.operations.invoke
|
import space.kscience.kmath.operations.invoke
|
||||||
|
import space.kscience.kmath.operations.parseBigInteger
|
||||||
|
import java.math.BigInteger
|
||||||
|
|
||||||
private fun BigInt.pow(power: Int): BigInt = modPow(BigIntField.number(power), BigInt.ZERO)
|
|
||||||
|
|
||||||
|
@UnstableKMathAPI
|
||||||
@State(Scope.Benchmark)
|
@State(Scope.Benchmark)
|
||||||
internal class BigIntBenchmark {
|
internal class BigIntBenchmark {
|
||||||
|
|
||||||
|
val kmSmallNumber = BigIntField.number(100)
|
||||||
|
val jvmSmallNumber = JBigIntegerField.number(100)
|
||||||
val kmNumber = BigIntField.number(Int.MAX_VALUE)
|
val kmNumber = BigIntField.number(Int.MAX_VALUE)
|
||||||
val jvmNumber = JBigIntegerField.number(Int.MAX_VALUE)
|
val jvmNumber = JBigIntegerField.number(Int.MAX_VALUE)
|
||||||
val largeKmNumber = BigIntField { number(11).pow(100_000) }
|
val kmLargeNumber = BigIntField { number(11).pow(100_000U) }
|
||||||
val largeJvmNumber = JBigIntegerField { number(11).pow(100_000) }
|
val jvmLargeNumber: BigInteger = JBigIntegerField { number(11).pow(100_000) }
|
||||||
val bigExponent = 50_000
|
val bigExponent = 50_000
|
||||||
|
|
||||||
|
@Benchmark
|
||||||
|
fun kmSmallAdd(blackhole: Blackhole) = BigIntField {
|
||||||
|
blackhole.consume(kmSmallNumber + kmSmallNumber + kmSmallNumber)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Benchmark
|
||||||
|
fun jvmSmallAdd(blackhole: Blackhole) = JBigIntegerField {
|
||||||
|
blackhole.consume(jvmSmallNumber + jvmSmallNumber + jvmSmallNumber)
|
||||||
|
}
|
||||||
|
|
||||||
@Benchmark
|
@Benchmark
|
||||||
fun kmAdd(blackhole: Blackhole) = BigIntField {
|
fun kmAdd(blackhole: Blackhole) = BigIntField {
|
||||||
blackhole.consume(kmNumber + kmNumber + kmNumber)
|
blackhole.consume(kmNumber + kmNumber + kmNumber)
|
||||||
@ -36,6 +50,16 @@ internal class BigIntBenchmark {
|
|||||||
blackhole.consume(jvmNumber + jvmNumber + jvmNumber)
|
blackhole.consume(jvmNumber + jvmNumber + jvmNumber)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Benchmark
|
||||||
|
fun kmAddLarge(blackhole: Blackhole) = BigIntField {
|
||||||
|
blackhole.consume(kmLargeNumber + kmLargeNumber + kmLargeNumber)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Benchmark
|
||||||
|
fun jvmAddLarge(blackhole: Blackhole) = JBigIntegerField {
|
||||||
|
blackhole.consume(jvmLargeNumber + jvmLargeNumber + jvmLargeNumber)
|
||||||
|
}
|
||||||
|
|
||||||
@Benchmark
|
@Benchmark
|
||||||
fun kmMultiply(blackhole: Blackhole) = BigIntField {
|
fun kmMultiply(blackhole: Blackhole) = BigIntField {
|
||||||
blackhole.consume(kmNumber * kmNumber * kmNumber)
|
blackhole.consume(kmNumber * kmNumber * kmNumber)
|
||||||
@ -43,7 +67,7 @@ internal class BigIntBenchmark {
|
|||||||
|
|
||||||
@Benchmark
|
@Benchmark
|
||||||
fun kmMultiplyLarge(blackhole: Blackhole) = BigIntField {
|
fun kmMultiplyLarge(blackhole: Blackhole) = BigIntField {
|
||||||
blackhole.consume(largeKmNumber*largeKmNumber)
|
blackhole.consume(kmLargeNumber*kmLargeNumber)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Benchmark
|
@Benchmark
|
||||||
@ -53,16 +77,36 @@ internal class BigIntBenchmark {
|
|||||||
|
|
||||||
@Benchmark
|
@Benchmark
|
||||||
fun jvmMultiplyLarge(blackhole: Blackhole) = JBigIntegerField {
|
fun jvmMultiplyLarge(blackhole: Blackhole) = JBigIntegerField {
|
||||||
blackhole.consume(largeJvmNumber*largeJvmNumber)
|
blackhole.consume(jvmLargeNumber*jvmLargeNumber)
|
||||||
}
|
}
|
||||||
|
|
||||||
// @Benchmark
|
@Benchmark
|
||||||
// fun kmPower(blackhole: Blackhole) = BigIntField {
|
fun kmPower(blackhole: Blackhole) = BigIntField {
|
||||||
// blackhole.consume(kmNumber.pow(bigExponent))
|
blackhole.consume(kmNumber.pow(bigExponent.toUInt()))
|
||||||
// }
|
}
|
||||||
//
|
|
||||||
// @Benchmark
|
@Benchmark
|
||||||
// fun jvmPower(blackhole: Blackhole) = JBigIntegerField {
|
fun jvmPower(blackhole: Blackhole) = JBigIntegerField {
|
||||||
// blackhole.consume(jvmNumber.pow(bigExponent))
|
blackhole.consume(jvmNumber.pow(bigExponent))
|
||||||
// }
|
}
|
||||||
|
|
||||||
|
@Benchmark
|
||||||
|
fun kmParsing16(blackhole: Blackhole) = JBigIntegerField {
|
||||||
|
blackhole.consume("0x7f57ed8b89c29a3b9a85c7a5b84ca3929c7b7488593".parseBigInteger())
|
||||||
|
}
|
||||||
|
|
||||||
|
@Benchmark
|
||||||
|
fun kmParsing10(blackhole: Blackhole) = JBigIntegerField {
|
||||||
|
blackhole.consume("236656783929183747565738292847574838922010".parseBigInteger())
|
||||||
|
}
|
||||||
|
|
||||||
|
@Benchmark
|
||||||
|
fun jvmParsing10(blackhole: Blackhole) = JBigIntegerField {
|
||||||
|
blackhole.consume("236656783929183747565738292847574838922010".toBigInteger(10))
|
||||||
|
}
|
||||||
|
|
||||||
|
@Benchmark
|
||||||
|
fun jvmParsing16(blackhole: Blackhole) = JBigIntegerField {
|
||||||
|
blackhole.consume("7f57ed8b89c29a3b9a85c7a5b84ca3929c7b7488593".toBigInteger(16))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2018-2021 KMath contributors.
|
* Copyright 2018-2021 KMath contributors.
|
||||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
* Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package space.kscience.kmath.benchmarks
|
package space.kscience.kmath.benchmarks
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2018-2021 KMath contributors.
|
* Copyright 2018-2021 KMath contributors.
|
||||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
* Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package space.kscience.kmath.benchmarks
|
package space.kscience.kmath.benchmarks
|
||||||
@ -11,9 +11,10 @@ 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.LinearSpace
|
|
||||||
import space.kscience.kmath.linear.invoke
|
import space.kscience.kmath.linear.invoke
|
||||||
|
import space.kscience.kmath.linear.linearSpace
|
||||||
import space.kscience.kmath.operations.DoubleField
|
import space.kscience.kmath.operations.DoubleField
|
||||||
|
import space.kscience.kmath.structures.Buffer
|
||||||
import kotlin.random.Random
|
import kotlin.random.Random
|
||||||
|
|
||||||
@State(Scope.Benchmark)
|
@State(Scope.Benchmark)
|
||||||
@ -23,8 +24,12 @@ internal class DotBenchmark {
|
|||||||
const val dim = 1000
|
const val dim = 1000
|
||||||
|
|
||||||
//creating invertible matrix
|
//creating invertible matrix
|
||||||
val matrix1 = LinearSpace.real.buildMatrix(dim, dim) { i, j -> if (i <= j) random.nextDouble() else 0.0 }
|
val matrix1 = DoubleField.linearSpace.buildMatrix(dim, dim) { _, _ ->
|
||||||
val matrix2 = LinearSpace.real.buildMatrix(dim, dim) { i, j -> if (i <= j) random.nextDouble() else 0.0 }
|
random.nextDouble()
|
||||||
|
}
|
||||||
|
val matrix2 = DoubleField.linearSpace.buildMatrix(dim, dim) { _, _ ->
|
||||||
|
random.nextDouble()
|
||||||
|
}
|
||||||
|
|
||||||
val cmMatrix1 = CMLinearSpace { matrix1.toCM() }
|
val cmMatrix1 = CMLinearSpace { matrix1.toCM() }
|
||||||
val cmMatrix2 = CMLinearSpace { matrix2.toCM() }
|
val cmMatrix2 = CMLinearSpace { matrix2.toCM() }
|
||||||
@ -34,37 +39,32 @@ internal class DotBenchmark {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Benchmark
|
@Benchmark
|
||||||
fun cmDot(blackhole: Blackhole) {
|
fun cmDotWithConversion(blackhole: Blackhole) = CMLinearSpace {
|
||||||
CMLinearSpace.run {
|
blackhole.consume(matrix1 dot matrix2)
|
||||||
blackhole.consume(cmMatrix1 dot cmMatrix2)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Benchmark
|
@Benchmark
|
||||||
fun ejmlDot(blackhole: Blackhole) {
|
fun cmDot(blackhole: Blackhole) = CMLinearSpace {
|
||||||
EjmlLinearSpaceDDRM {
|
blackhole.consume(cmMatrix1 dot cmMatrix2)
|
||||||
blackhole.consume(ejmlMatrix1 dot ejmlMatrix2)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Benchmark
|
@Benchmark
|
||||||
fun ejmlDotWithConversion(blackhole: Blackhole) {
|
fun ejmlDot(blackhole: Blackhole) = EjmlLinearSpaceDDRM {
|
||||||
EjmlLinearSpaceDDRM {
|
blackhole.consume(ejmlMatrix1 dot ejmlMatrix2)
|
||||||
blackhole.consume(matrix1 dot matrix2)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Benchmark
|
@Benchmark
|
||||||
fun bufferedDot(blackhole: Blackhole) {
|
fun ejmlDotWithConversion(blackhole: Blackhole) = EjmlLinearSpaceDDRM {
|
||||||
LinearSpace.auto(DoubleField).invoke {
|
blackhole.consume(matrix1 dot matrix2)
|
||||||
blackhole.consume(matrix1 dot matrix2)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Benchmark
|
@Benchmark
|
||||||
fun realDot(blackhole: Blackhole) {
|
fun bufferedDot(blackhole: Blackhole) = with(DoubleField.linearSpace(Buffer.Companion::auto)) {
|
||||||
LinearSpace.real {
|
blackhole.consume(matrix1 dot matrix2)
|
||||||
blackhole.consume(matrix1 dot matrix2)
|
}
|
||||||
}
|
|
||||||
|
@Benchmark
|
||||||
|
fun doubleDot(blackhole: Blackhole) = with(DoubleField.linearSpace) {
|
||||||
|
blackhole.consume(matrix1 dot matrix2)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2018-2021 KMath contributors.
|
* Copyright 2018-2021 KMath contributors.
|
||||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
* Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package space.kscience.kmath.benchmarks
|
package space.kscience.kmath.benchmarks
|
||||||
@ -11,27 +11,54 @@ import kotlinx.benchmark.Scope
|
|||||||
import kotlinx.benchmark.State
|
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.misc.Symbol
|
|
||||||
import space.kscience.kmath.misc.symbol
|
|
||||||
import space.kscience.kmath.operations.DoubleField
|
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 kotlin.math.sin
|
||||||
import kotlin.random.Random
|
import kotlin.random.Random
|
||||||
|
|
||||||
@State(Scope.Benchmark)
|
@State(Scope.Benchmark)
|
||||||
internal class ExpressionsInterpretersBenchmark {
|
internal class ExpressionsInterpretersBenchmark {
|
||||||
|
/**
|
||||||
|
* Benchmark case for [Expression] created with [expressionInExtendedField].
|
||||||
|
*/
|
||||||
@Benchmark
|
@Benchmark
|
||||||
fun functionalExpression(blackhole: Blackhole) = invokeAndSum(functional, blackhole)
|
fun functionalExpression(blackhole: Blackhole) = invokeAndSum(functional, blackhole)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Benchmark case for [Expression] created with [toExpression].
|
||||||
|
*/
|
||||||
@Benchmark
|
@Benchmark
|
||||||
fun mstExpression(blackhole: Blackhole) = invokeAndSum(mst, blackhole)
|
fun mstExpression(blackhole: Blackhole) = invokeAndSum(mst, blackhole)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Benchmark case for [Expression] created with [compileToExpression].
|
||||||
|
*/
|
||||||
@Benchmark
|
@Benchmark
|
||||||
fun asmExpression(blackhole: Blackhole) = invokeAndSum(asm, blackhole)
|
fun asmExpression(blackhole: Blackhole) = invokeAndSum(asm, blackhole)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Benchmark case for [Expression] implemented manually with `kotlin.math` functions.
|
||||||
|
*/
|
||||||
@Benchmark
|
@Benchmark
|
||||||
fun rawExpression(blackhole: Blackhole) = invokeAndSum(raw, blackhole)
|
fun rawExpression(blackhole: Blackhole) = invokeAndSum(raw, blackhole)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Benchmark case for direct computation w/o [Expression].
|
||||||
|
*/
|
||||||
|
@Benchmark
|
||||||
|
fun justCalculate(blackhole: Blackhole) {
|
||||||
|
val random = Random(0)
|
||||||
|
var sum = 0.0
|
||||||
|
|
||||||
|
repeat(times) {
|
||||||
|
val x = random.nextDouble()
|
||||||
|
sum += x * 2.0 + 2.0 / x - 16.0 / sin(x)
|
||||||
|
}
|
||||||
|
|
||||||
|
blackhole.consume(sum)
|
||||||
|
}
|
||||||
|
|
||||||
private fun invokeAndSum(expr: Expression<Double>, 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
|
||||||
@ -44,23 +71,25 @@ internal class ExpressionsInterpretersBenchmark {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private companion object {
|
private companion object {
|
||||||
private val x: Symbol by symbol
|
private val x by symbol
|
||||||
private val algebra: DoubleField = DoubleField
|
private val algebra = DoubleField
|
||||||
private const val times = 1_000_000
|
private const val times = 1_000_000
|
||||||
|
|
||||||
private val functional: Expression<Double> = DoubleField.expressionInExtendedField {
|
private val functional = DoubleField.expression {
|
||||||
bindSymbol(x) * number(2.0) + number(2.0) / bindSymbol(x) - number(16.0) / sin(bindSymbol(x))
|
val x = bindSymbol(Symbol.x)
|
||||||
|
x * number(2.0) + 2.0 / x - 16.0 / sin(x)
|
||||||
}
|
}
|
||||||
|
|
||||||
private val node = MstExtendedField {
|
private val node = MstExtendedField {
|
||||||
bindSymbol(x) * 2.0 + number(2.0) / bindSymbol(x) - number(16.0) / sin(bindSymbol(x))
|
x * 2.0 + number(2.0) / x - number(16.0) / sin(x)
|
||||||
}
|
}
|
||||||
|
|
||||||
private val mst: Expression<Double> = node.toExpression(DoubleField)
|
private val mst = node.toExpression(DoubleField)
|
||||||
private val asm: Expression<Double> = node.compileToExpression(DoubleField)
|
private val asm = node.compileToExpression(DoubleField)
|
||||||
|
|
||||||
private val raw: Expression<Double> = Expression { args ->
|
private val raw = Expression<Double> { args ->
|
||||||
args.getValue(x) * 2.0 + 2.0 / args.getValue(x) - 16.0 / kotlin.math.sin(args.getValue(x))
|
val x = args[x]!!
|
||||||
|
x * 2.0 + 2.0 / x - 16.0 / sin(x)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,42 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2018-2021 KMath contributors.
|
||||||
|
* Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package space.kscience.kmath.benchmarks
|
||||||
|
|
||||||
|
import kotlinx.benchmark.Blackhole
|
||||||
|
import org.openjdk.jmh.annotations.Benchmark
|
||||||
|
import org.openjdk.jmh.annotations.Scope
|
||||||
|
import org.openjdk.jmh.annotations.State
|
||||||
|
import space.kscience.kmath.jafama.JafamaDoubleField
|
||||||
|
import space.kscience.kmath.jafama.StrictJafamaDoubleField
|
||||||
|
import space.kscience.kmath.operations.DoubleField
|
||||||
|
import space.kscience.kmath.operations.invoke
|
||||||
|
import kotlin.contracts.InvocationKind
|
||||||
|
import kotlin.contracts.contract
|
||||||
|
import kotlin.random.Random
|
||||||
|
|
||||||
|
@State(Scope.Benchmark)
|
||||||
|
internal class JafamaBenchmark {
|
||||||
|
@Benchmark
|
||||||
|
fun jafama(blackhole: Blackhole) = invokeBenchmarks(blackhole) { x ->
|
||||||
|
JafamaDoubleField { x * power(x, 4) * exp(x) / cos(x) + sin(x) }
|
||||||
|
}
|
||||||
|
|
||||||
|
@Benchmark
|
||||||
|
fun core(blackhole: Blackhole) = invokeBenchmarks(blackhole) { x ->
|
||||||
|
DoubleField { x * power(x, 4) * exp(x) / cos(x) + sin(x) }
|
||||||
|
}
|
||||||
|
|
||||||
|
@Benchmark
|
||||||
|
fun strictJafama(blackhole: Blackhole) = invokeBenchmarks(blackhole) { x ->
|
||||||
|
StrictJafamaDoubleField { x * power(x, 4) * exp(x) / cos(x) + sin(x) }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private inline fun invokeBenchmarks(blackhole: Blackhole, expr: (Double) -> Double) {
|
||||||
|
contract { callsInPlace(expr, InvocationKind.AT_LEAST_ONCE) }
|
||||||
|
val rng = Random(0)
|
||||||
|
repeat(1000000) { blackhole.consume(expr(rng.nextDouble())) }
|
||||||
|
}
|
@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2018-2021 KMath contributors.
|
* Copyright 2018-2021 KMath contributors.
|
||||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
* Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package space.kscience.kmath.benchmarks
|
package space.kscience.kmath.benchmarks
|
||||||
@ -10,13 +10,12 @@ import kotlinx.benchmark.Blackhole
|
|||||||
import kotlinx.benchmark.Scope
|
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.commons.linear.inverse
|
import space.kscience.kmath.commons.linear.lupSolver
|
||||||
import space.kscience.kmath.ejml.EjmlLinearSpaceDDRM
|
import space.kscience.kmath.ejml.EjmlLinearSpaceDDRM
|
||||||
import space.kscience.kmath.linear.InverseMatrixFeature
|
|
||||||
import space.kscience.kmath.linear.LinearSpace
|
|
||||||
import space.kscience.kmath.linear.inverseWithLup
|
|
||||||
import space.kscience.kmath.linear.invoke
|
import space.kscience.kmath.linear.invoke
|
||||||
import space.kscience.kmath.nd.getFeature
|
import space.kscience.kmath.linear.linearSpace
|
||||||
|
import space.kscience.kmath.linear.lupSolver
|
||||||
|
import space.kscience.kmath.operations.algebra
|
||||||
import kotlin.random.Random
|
import kotlin.random.Random
|
||||||
|
|
||||||
@State(Scope.Benchmark)
|
@State(Scope.Benchmark)
|
||||||
@ -25,7 +24,7 @@ internal class MatrixInverseBenchmark {
|
|||||||
private val random = Random(1224)
|
private val random = Random(1224)
|
||||||
private const val dim = 100
|
private const val dim = 100
|
||||||
|
|
||||||
private val space = LinearSpace.real
|
private val space = Double.algebra.linearSpace
|
||||||
|
|
||||||
//creating invertible matrix
|
//creating invertible matrix
|
||||||
private val u = space.buildMatrix(dim, dim) { i, j -> if (i <= j) random.nextDouble() else 0.0 }
|
private val u = space.buildMatrix(dim, dim) { i, j -> if (i <= j) random.nextDouble() else 0.0 }
|
||||||
@ -35,20 +34,20 @@ internal class MatrixInverseBenchmark {
|
|||||||
|
|
||||||
@Benchmark
|
@Benchmark
|
||||||
fun kmathLupInversion(blackhole: Blackhole) {
|
fun kmathLupInversion(blackhole: Blackhole) {
|
||||||
blackhole.consume(LinearSpace.real.inverseWithLup(matrix))
|
blackhole.consume(Double.algebra.linearSpace.lupSolver().inverse(matrix))
|
||||||
}
|
}
|
||||||
|
|
||||||
@Benchmark
|
@Benchmark
|
||||||
fun cmLUPInversion(blackhole: Blackhole) {
|
fun cmLUPInversion(blackhole: Blackhole) {
|
||||||
with(CMLinearSpace) {
|
CMLinearSpace {
|
||||||
blackhole.consume(inverse(matrix))
|
blackhole.consume(lupSolver().inverse(matrix))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Benchmark
|
@Benchmark
|
||||||
fun ejmlInverse(blackhole: Blackhole) {
|
fun ejmlInverse(blackhole: Blackhole) {
|
||||||
with(EjmlLinearSpaceDDRM) {
|
EjmlLinearSpaceDDRM {
|
||||||
blackhole.consume(matrix.getFeature<InverseMatrixFeature<Double>>()?.inverse)
|
blackhole.consume(matrix.toEjml().inverse())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2018-2021 KMath contributors.
|
* Copyright 2018-2021 KMath contributors.
|
||||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
* Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package space.kscience.kmath.benchmarks
|
package space.kscience.kmath.benchmarks
|
||||||
@ -9,45 +9,66 @@ import kotlinx.benchmark.Benchmark
|
|||||||
import kotlinx.benchmark.Blackhole
|
import kotlinx.benchmark.Blackhole
|
||||||
import kotlinx.benchmark.Scope
|
import kotlinx.benchmark.Scope
|
||||||
import kotlinx.benchmark.State
|
import kotlinx.benchmark.State
|
||||||
import space.kscience.kmath.nd.*
|
import space.kscience.kmath.nd.StructureND
|
||||||
|
import space.kscience.kmath.nd.autoNdAlgebra
|
||||||
|
import space.kscience.kmath.nd.ndAlgebra
|
||||||
|
import space.kscience.kmath.nd4j.nd4j
|
||||||
import space.kscience.kmath.operations.DoubleField
|
import space.kscience.kmath.operations.DoubleField
|
||||||
import space.kscience.kmath.structures.Buffer
|
import space.kscience.kmath.structures.Buffer
|
||||||
|
import space.kscience.kmath.tensors.core.DoubleTensor
|
||||||
|
import space.kscience.kmath.tensors.core.ones
|
||||||
|
import space.kscience.kmath.tensors.core.tensorAlgebra
|
||||||
|
|
||||||
@State(Scope.Benchmark)
|
@State(Scope.Benchmark)
|
||||||
internal class NDFieldBenchmark {
|
internal class NDFieldBenchmark {
|
||||||
@Benchmark
|
@Benchmark
|
||||||
fun autoFieldAdd(blackhole: Blackhole) {
|
fun autoFieldAdd(blackhole: Blackhole) = with(autoField) {
|
||||||
with(autoField) {
|
var res: StructureND<Double> = one
|
||||||
var res: StructureND<Double> = one
|
repeat(n) { res += one }
|
||||||
repeat(n) { res += one }
|
blackhole.consume(res)
|
||||||
blackhole.consume(res)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Benchmark
|
@Benchmark
|
||||||
fun specializedFieldAdd(blackhole: Blackhole) {
|
fun specializedFieldAdd(blackhole: Blackhole) = with(specializedField) {
|
||||||
with(specializedField) {
|
var res: StructureND<Double> = one
|
||||||
var res: StructureND<Double> = one
|
repeat(n) { res += 1.0 }
|
||||||
repeat(n) { res += 1.0 }
|
blackhole.consume(res)
|
||||||
blackhole.consume(res)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Benchmark
|
@Benchmark
|
||||||
fun boxingFieldAdd(blackhole: Blackhole) {
|
fun boxingFieldAdd(blackhole: Blackhole) = with(genericField) {
|
||||||
with(genericField) {
|
var res: StructureND<Double> = one
|
||||||
var res: StructureND<Double> = one
|
repeat(n) { res += 1.0 }
|
||||||
repeat(n) { res += 1.0 }
|
blackhole.consume(res)
|
||||||
blackhole.consume(res)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Benchmark
|
||||||
|
fun tensorAdd(blackhole: Blackhole) = with(Double.tensorAlgebra) {
|
||||||
|
var res: DoubleTensor = ones(dim, dim)
|
||||||
|
repeat(n) { res = res + 1.0 }
|
||||||
|
blackhole.consume(res)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Benchmark
|
||||||
|
fun tensorInPlaceAdd(blackhole: Blackhole) = with(Double.tensorAlgebra) {
|
||||||
|
val res: DoubleTensor = ones(dim, dim)
|
||||||
|
repeat(n) { res += 1.0 }
|
||||||
|
blackhole.consume(res)
|
||||||
|
}
|
||||||
|
|
||||||
|
// @Benchmark
|
||||||
|
// fun nd4jAdd(blackhole: Blackhole) = with(nd4jField) {
|
||||||
|
// var res: StructureND<Double> = one
|
||||||
|
// repeat(n) { res += 1.0 }
|
||||||
|
// blackhole.consume(res)
|
||||||
|
// }
|
||||||
|
|
||||||
private companion object {
|
private companion object {
|
||||||
private const val dim = 1000
|
private const val dim = 1000
|
||||||
private const val n = 100
|
private const val n = 100
|
||||||
private val autoField = AlgebraND.auto(DoubleField, dim, dim)
|
private val autoField = DoubleField.autoNdAlgebra(dim, dim)
|
||||||
private val specializedField = AlgebraND.real(dim, dim)
|
private val specializedField = DoubleField.ndAlgebra(dim, dim)
|
||||||
private val genericField = AlgebraND.field(DoubleField, Buffer.Companion::boxing, dim, dim)
|
private val genericField = DoubleField.ndAlgebra(Buffer.Companion::boxing, dim, dim)
|
||||||
|
private val nd4jField = DoubleField.nd4j(dim, dim)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2018-2021 KMath contributors.
|
* Copyright 2018-2021 KMath contributors.
|
||||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
* Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package space.kscience.kmath.benchmarks
|
package space.kscience.kmath.benchmarks
|
||||||
@ -10,10 +10,9 @@ import kotlinx.benchmark.Blackhole
|
|||||||
import kotlinx.benchmark.Scope
|
import kotlinx.benchmark.Scope
|
||||||
import kotlinx.benchmark.State
|
import kotlinx.benchmark.State
|
||||||
import org.jetbrains.bio.viktor.F64Array
|
import org.jetbrains.bio.viktor.F64Array
|
||||||
import space.kscience.kmath.nd.AlgebraND
|
|
||||||
import space.kscience.kmath.nd.StructureND
|
import space.kscience.kmath.nd.StructureND
|
||||||
import space.kscience.kmath.nd.auto
|
import space.kscience.kmath.nd.autoNdAlgebra
|
||||||
import space.kscience.kmath.nd.real
|
import space.kscience.kmath.nd.ndAlgebra
|
||||||
import space.kscience.kmath.operations.DoubleField
|
import space.kscience.kmath.operations.DoubleField
|
||||||
import space.kscience.kmath.viktor.ViktorNDField
|
import space.kscience.kmath.viktor.ViktorNDField
|
||||||
|
|
||||||
@ -59,8 +58,8 @@ internal class ViktorBenchmark {
|
|||||||
private const val n = 100
|
private const val n = 100
|
||||||
|
|
||||||
// automatically build context most suited for given type.
|
// automatically build context most suited for given type.
|
||||||
private val autoField = AlgebraND.auto(DoubleField, dim, dim)
|
private val autoField = DoubleField.autoNdAlgebra(dim, dim)
|
||||||
private val realField = AlgebraND.real(dim, dim)
|
private val realField = DoubleField.ndAlgebra(dim, dim)
|
||||||
private val viktorField = ViktorNDField(dim, dim)
|
private val viktorField = ViktorNDField(dim, dim)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2018-2021 KMath contributors.
|
* Copyright 2018-2021 KMath contributors.
|
||||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
* Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package space.kscience.kmath.benchmarks
|
package space.kscience.kmath.benchmarks
|
||||||
@ -10,9 +10,8 @@ import kotlinx.benchmark.Blackhole
|
|||||||
import kotlinx.benchmark.Scope
|
import kotlinx.benchmark.Scope
|
||||||
import kotlinx.benchmark.State
|
import kotlinx.benchmark.State
|
||||||
import org.jetbrains.bio.viktor.F64Array
|
import org.jetbrains.bio.viktor.F64Array
|
||||||
import space.kscience.kmath.nd.AlgebraND
|
import space.kscience.kmath.nd.autoNdAlgebra
|
||||||
import space.kscience.kmath.nd.auto
|
import space.kscience.kmath.nd.ndAlgebra
|
||||||
import space.kscience.kmath.nd.real
|
|
||||||
import space.kscience.kmath.operations.DoubleField
|
import space.kscience.kmath.operations.DoubleField
|
||||||
import space.kscience.kmath.viktor.ViktorFieldND
|
import space.kscience.kmath.viktor.ViktorFieldND
|
||||||
|
|
||||||
@ -51,8 +50,8 @@ internal class ViktorLogBenchmark {
|
|||||||
private const val n = 100
|
private const val n = 100
|
||||||
|
|
||||||
// automatically build context most suited for given type.
|
// automatically build context most suited for given type.
|
||||||
private val autoField = AlgebraND.auto(DoubleField, dim, dim)
|
private val autoField = DoubleField.autoNdAlgebra(dim, dim)
|
||||||
private val realNdField = AlgebraND.real(dim, dim)
|
private val realNdField = DoubleField.ndAlgebra(dim, dim)
|
||||||
private val viktorField = ViktorFieldND(intArrayOf(dim, dim))
|
private val viktorField = ViktorFieldND(intArrayOf(dim, dim))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
import java.net.URL
|
||||||
|
|
||||||
plugins {
|
plugins {
|
||||||
id("ru.mipt.npm.gradle.project")
|
id("ru.mipt.npm.gradle.project")
|
||||||
kotlin("jupyter.api") apply false
|
kotlin("jupyter.api") apply false
|
||||||
@ -7,15 +9,17 @@ allprojects {
|
|||||||
repositories {
|
repositories {
|
||||||
maven("https://clojars.org/repo")
|
maven("https://clojars.org/repo")
|
||||||
maven("https://jitpack.io")
|
maven("https://jitpack.io")
|
||||||
|
|
||||||
maven("http://logicrunch.research.it.uu.se/maven") {
|
maven("http://logicrunch.research.it.uu.se/maven") {
|
||||||
isAllowInsecureProtocol = true
|
isAllowInsecureProtocol = true
|
||||||
}
|
}
|
||||||
maven("https://maven.pkg.jetbrains.space/public/p/kotlinx-html/maven")
|
|
||||||
|
maven("https://oss.sonatype.org/content/repositories/snapshots")
|
||||||
mavenCentral()
|
mavenCentral()
|
||||||
}
|
}
|
||||||
|
|
||||||
group = "space.kscience"
|
group = "space.kscience"
|
||||||
version = "0.3.0-dev-8"
|
version = "0.3.0-dev-16"
|
||||||
}
|
}
|
||||||
|
|
||||||
subprojects {
|
subprojects {
|
||||||
@ -23,31 +27,46 @@ subprojects {
|
|||||||
|
|
||||||
afterEvaluate {
|
afterEvaluate {
|
||||||
tasks.withType<org.jetbrains.dokka.gradle.DokkaTaskPartial> {
|
tasks.withType<org.jetbrains.dokka.gradle.DokkaTaskPartial> {
|
||||||
dependsOn(tasks.getByName("assemble"))
|
dependsOn(tasks["assemble"])
|
||||||
|
|
||||||
dokkaSourceSets.all {
|
dokkaSourceSets.all {
|
||||||
val readmeFile = File(this@subprojects.projectDir, "README.md")
|
val readmeFile = this@subprojects.projectDir.resolve("README.md")
|
||||||
if (readmeFile.exists()) includes.from(readmeFile.absolutePath)
|
if (readmeFile.exists()) includes.from(readmeFile)
|
||||||
externalDocumentationLink("http://ejml.org/javadoc/")
|
val kotlinDirPath = "src/$name/kotlin"
|
||||||
|
val kotlinDir = file(kotlinDirPath)
|
||||||
|
|
||||||
|
if (kotlinDir.exists()) sourceLink {
|
||||||
|
localDirectory.set(kotlinDir)
|
||||||
|
|
||||||
|
remoteUrl.set(
|
||||||
|
URL("https://github.com/mipt-npm/${rootProject.name}/tree/master/${this@subprojects.name}/$kotlinDirPath")
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
externalDocumentationLink("https://commons.apache.org/proper/commons-math/javadocs/api-3.6.1/")
|
externalDocumentationLink("https://commons.apache.org/proper/commons-math/javadocs/api-3.6.1/")
|
||||||
externalDocumentationLink("https://deeplearning4j.org/api/latest/")
|
externalDocumentationLink("https://deeplearning4j.org/api/latest/")
|
||||||
externalDocumentationLink("https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/")
|
externalDocumentationLink("https://axelclk.bitbucket.io/symja/javadoc/")
|
||||||
externalDocumentationLink("https://breandan.net/kotlingrad/kotlingrad/", "https://breandan.net/kotlingrad/kotlingrad/kotlingrad/package-list")
|
|
||||||
|
externalDocumentationLink(
|
||||||
|
"https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/",
|
||||||
|
"https://kotlin.github.io/kotlinx.coroutines/package-list",
|
||||||
|
)
|
||||||
|
|
||||||
|
externalDocumentationLink(
|
||||||
|
"https://breandan.net/kotlingrad/kotlingrad/",
|
||||||
|
"https://breandan.net/kotlingrad/kotlingrad/kotlingrad/package-list",
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
readme {
|
readme.readmeTemplate = file("docs/templates/README-TEMPLATE.md")
|
||||||
readmeTemplate = file("docs/templates/README-TEMPLATE.md")
|
|
||||||
}
|
|
||||||
|
|
||||||
ksciencePublish {
|
ksciencePublish {
|
||||||
github("kmath")
|
vcs("https://github.com/mipt-npm/kmath")
|
||||||
space()
|
space(publish = true)
|
||||||
sonatype()
|
sonatype(publish = true)
|
||||||
}
|
}
|
||||||
|
|
||||||
apiValidation {
|
apiValidation.nonPublicMarkers.add("space.kscience.kmath.misc.UnstableKMathAPI")
|
||||||
nonPublicMarkers.add("space.kscience.kmath.misc.UnstableKMathAPI")
|
|
||||||
}
|
|
||||||
|
20
buildSrc/build.gradle.kts
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
plugins {
|
||||||
|
`kotlin-dsl`
|
||||||
|
kotlin("plugin.serialization") version "1.4.31"
|
||||||
|
}
|
||||||
|
|
||||||
|
repositories {
|
||||||
|
maven("https://repo.kotlin.link")
|
||||||
|
mavenCentral()
|
||||||
|
gradlePluginPortal()
|
||||||
|
}
|
||||||
|
|
||||||
|
dependencies {
|
||||||
|
api("org.jetbrains.kotlinx:kotlinx-serialization-json:1.1.0")
|
||||||
|
api("ru.mipt.npm:gradle-tools:0.10.2")
|
||||||
|
api("org.jetbrains.kotlinx:kotlinx-benchmark-plugin:0.3.1")
|
||||||
|
}
|
||||||
|
|
||||||
|
kotlin.sourceSets.all {
|
||||||
|
languageSettings.useExperimentalAnnotation("kotlin.ExperimentalStdlibApi")
|
||||||
|
}
|
@ -0,0 +1,60 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2018-2021 KMath contributors.
|
||||||
|
* Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package space.kscience.kmath.benchmarks
|
||||||
|
|
||||||
|
import kotlinx.serialization.Serializable
|
||||||
|
|
||||||
|
@Serializable
|
||||||
|
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
|
||||||
|
}
|
||||||
|
|
||||||
|
@Serializable
|
||||||
|
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
|
||||||
|
|
||||||
|
@Serializable
|
||||||
|
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,100 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2018-2021 KMath contributors.
|
||||||
|
* Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package space.kscience.kmath.benchmarks
|
||||||
|
|
||||||
|
import kotlinx.benchmark.gradle.BenchmarksExtension
|
||||||
|
import kotlinx.serialization.*
|
||||||
|
import kotlinx.serialization.json.*
|
||||||
|
import org.gradle.api.Project
|
||||||
|
import ru.mipt.npm.gradle.KScienceReadmeExtension
|
||||||
|
import java.time.*
|
||||||
|
import java.time.format.*
|
||||||
|
import java.time.temporal.ChronoField.*
|
||||||
|
|
||||||
|
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
|
||||||
|
|
||||||
|
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(Char::uppercase)}") {
|
||||||
|
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) {
|
||||||
|
"> **Can't find appropriate benchmark data. Try generating readme files after running benchmarks**."
|
||||||
|
} else {
|
||||||
|
val reports =
|
||||||
|
Json.decodeFromString<List<JmhReport>>(resDirectory.resolve("jvm.json").readText())
|
||||||
|
|
||||||
|
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,425 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2018-2021 KMath contributors.
|
||||||
|
* Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
@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)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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.misc.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,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
@ -1,85 +1,45 @@
|
|||||||
# Algebraic Structures and Algebraic Elements
|
# Algebraic Structures and Algebraic Elements
|
||||||
|
|
||||||
The mathematical operations in KMath are generally separated from mathematical objects. This means that to perform an
|
The mathematical operations in KMath are generally separated from mathematical objects. This means that to perform an
|
||||||
operation, say `+`, one needs two objects of a type `T` and an algebra context, which draws appropriate operation up,
|
operation, say `+`, one needs two objects of a type `T` and an algebra context, which draws appropriate operation up,
|
||||||
say `Space<T>`. Next one needs to run the actual operation in the context:
|
say `Group<T>`. Next one needs to run the actual operation in the context:
|
||||||
|
|
||||||
```kotlin
|
```kotlin
|
||||||
import space.kscience.kmath.operations.*
|
import space.kscience.kmath.operations.*
|
||||||
|
|
||||||
val a: T = ...
|
val a: T = ...
|
||||||
val b: T = ...
|
val b: T = ...
|
||||||
val space: Space<T> = ...
|
val group: Group<T> = ...
|
||||||
|
|
||||||
val c = space { a + b }
|
val c = group { a + b }
|
||||||
```
|
```
|
||||||
|
|
||||||
At first glance, this distinction seems to be a needless complication, but in fact one needs to remember that in
|
At first glance, this distinction seems to be a needless complication, but in fact one needs to remember that in
|
||||||
mathematics, one could draw up different operations on same objects. For example, one could use different types of
|
mathematics, one could draw up different operations on same objects. For example, one could use different types of
|
||||||
geometry for vectors.
|
geometry for vectors.
|
||||||
|
|
||||||
## Algebraic Structures
|
## Algebraic Structures
|
||||||
|
|
||||||
Mathematical contexts have the following hierarchy:
|
Primary mathematical contexts have the following hierarchy:
|
||||||
|
|
||||||
**Algebra** ← **Space** ← **Ring** ← **Field**
|
`Field <: Ring <: Group <: Algebra`
|
||||||
|
|
||||||
These interfaces follow real algebraic structures:
|
These interfaces follow real algebraic structures:
|
||||||
|
|
||||||
- [Space](https://mathworld.wolfram.com/VectorSpace.html) defines addition, its neutral element (i.e. 0) and scalar
|
- [Group](https://mathworld.wolfram.com/Group.html) defines addition, its identity element (i.e., 0) and additive
|
||||||
multiplication;
|
inverse (-x);
|
||||||
- [Ring](http://mathworld.wolfram.com/Ring.html) adds multiplication and its neutral element (i.e. 1);
|
- [Ring](http://mathworld.wolfram.com/Ring.html) adds multiplication and its identity element (i.e., 1);
|
||||||
- [Field](http://mathworld.wolfram.com/Field.html) adds division operation.
|
- [Field](http://mathworld.wolfram.com/Field.html) adds division operation.
|
||||||
|
|
||||||
A typical implementation of `Field<T>` is the `DoubleField` which works on doubles, and `VectorSpace` for `Space<T>`.
|
A typical implementation of `Field<T>` is the `DoubleField` which works on doubles, and `VectorSpace` for `Space<T>`.
|
||||||
|
|
||||||
In some cases algebra context can hold additional operations like `exp` or `sin`, and then it inherits appropriate
|
In some cases algebra context can hold additional operations like `exp` or `sin`, and then it inherits appropriate
|
||||||
interface. Also, contexts may have operations, which produce elements outside of the context. For example, `Matrix.dot`
|
interface. Also, contexts may have operations, which produce elements outside the context. For example, `Matrix.dot`
|
||||||
operation produces a matrix with new dimensions, which can be incompatible with initial matrix in terms of linear
|
operation produces a matrix with new dimensions, which can be incompatible with initial matrix in linear operations.
|
||||||
operations.
|
|
||||||
|
|
||||||
## Algebraic Element
|
|
||||||
|
|
||||||
To achieve more familiar behavior (where you apply operations directly to mathematical objects), without involving
|
|
||||||
contexts KMath submits special type objects called `MathElement`. A `MathElement` is basically some object coupled to
|
|
||||||
a mathematical context. For example `Complex` is the pair of real numbers representing real and imaginary parts,
|
|
||||||
but it also holds reference to the `ComplexField` singleton, which allows performing direct operations on `Complex`
|
|
||||||
numbers without explicit involving the context like:
|
|
||||||
|
|
||||||
```kotlin
|
|
||||||
import space.kscience.kmath.operations.*
|
|
||||||
|
|
||||||
// Using elements
|
|
||||||
val c1 = Complex(1.0, 1.0)
|
|
||||||
val c2 = Complex(1.0, -1.0)
|
|
||||||
val c3 = c1 + c2 + 3.0.toComplex()
|
|
||||||
|
|
||||||
// Using context
|
|
||||||
val c4 = ComplexField { c1 + i - 2.0 }
|
|
||||||
```
|
|
||||||
|
|
||||||
Both notations have their pros and cons.
|
|
||||||
|
|
||||||
The hierarchy for algebraic elements follows the hierarchy for the corresponding algebraic structures.
|
|
||||||
|
|
||||||
**MathElement** ← **SpaceElement** ← **RingElement** ← **FieldElement**
|
|
||||||
|
|
||||||
`MathElement<C>` is the generic common ancestor of the class with context.
|
|
||||||
|
|
||||||
One major distinction between algebraic elements and algebraic contexts is that elements have three type
|
|
||||||
parameters:
|
|
||||||
|
|
||||||
1. The type of elements, the field operates on.
|
|
||||||
2. The self-type of the element returned from operation (which has to be an algebraic element).
|
|
||||||
3. The type of the algebra over first type-parameter.
|
|
||||||
|
|
||||||
The middle type is needed for of algebra members do not store context. For example, it is impossible to add a context
|
|
||||||
to regular `Double`. The element performs automatic conversions from context types and back. One should use context
|
|
||||||
operations in all performance-critical places. The performance of element operations is not guaranteed.
|
|
||||||
|
|
||||||
## Spaces and Fields
|
## Spaces and Fields
|
||||||
|
|
||||||
KMath submits both contexts and elements for builtin algebraic structures:
|
KMath introduces contexts for builtin algebraic structures:
|
||||||
|
|
||||||
```kotlin
|
```kotlin
|
||||||
import space.kscience.kmath.operations.*
|
import space.kscience.kmath.operations.*
|
||||||
@ -102,13 +62,13 @@ val c2 = ComplexField { c1 - 1.0 } // Returns: Complex(re=0.0, im=2.0)
|
|||||||
val c3 = ComplexField { c1 - i * 2.0 }
|
val c3 = ComplexField { c1 - i * 2.0 }
|
||||||
```
|
```
|
||||||
|
|
||||||
**Note**: In theory it is possible to add behaviors directly to the context, but as for now Kotlin does not support
|
**Note**: In theory it is possible to add behaviors directly to the context, but as for now Kotlin does not support
|
||||||
that. Watch [KT-10468](https://youtrack.jetbrains.com/issue/KT-10468) and
|
that. Watch [KT-10468](https://youtrack.jetbrains.com/issue/KT-10468) and
|
||||||
[KEEP-176](https://github.com/Kotlin/KEEP/pull/176) for updates.
|
[KEEP-176](https://github.com/Kotlin/KEEP/pull/176) for updates.
|
||||||
|
|
||||||
## Nested fields
|
## Nested fields
|
||||||
|
|
||||||
Contexts allow one to build more complex structures. For example, it is possible to create a `Matrix` from complex
|
Contexts allow one to build more complex structures. For example, it is possible to create a `Matrix` from complex
|
||||||
elements like so:
|
elements like so:
|
||||||
|
|
||||||
```kotlin
|
```kotlin
|
||||||
@ -118,8 +78,9 @@ val element = NDElement.complex(shape = intArrayOf(2, 2)) { index: IntArray ->
|
|||||||
```
|
```
|
||||||
|
|
||||||
The `element` in this example is a member of the `Field` of 2D structures, each element of which is a member of its own
|
The `element` in this example is a member of the `Field` of 2D structures, each element of which is a member of its own
|
||||||
`ComplexField`. It is important one does not need to create a special n-d class to hold complex
|
`ComplexField`. It is important one does not need to create a special n-d class to hold complex numbers and implement
|
||||||
numbers and implement operations on it, one just needs to provide a field for its elements.
|
operations on it, one just needs to provide a field for its elements.
|
||||||
|
|
||||||
**Note**: Fields themselves do not solve the problem of JVM boxing, but it is possible to solve with special contexts like
|
**Note**: Fields themselves do not solve the problem of JVM boxing, but it is possible to solve with special contexts
|
||||||
|
like
|
||||||
`MemorySpec`.
|
`MemorySpec`.
|
||||||
|
@ -1,17 +1,20 @@
|
|||||||
# Buffers
|
# Buffers
|
||||||
|
|
||||||
Buffer is one of main building blocks of kmath. It is a basic interface allowing random-access read and write (with `MutableBuffer`).
|
Buffer is one of main building blocks of kmath. It is a basic interface allowing random-access read and write (
|
||||||
There are different types of buffers:
|
with `MutableBuffer`). There are different types of buffers:
|
||||||
|
|
||||||
* Primitive buffers wrapping like `RealBuffer` which are wrapping primitive arrays.
|
* Primitive buffers wrapping like `DoubleBuffer` which are wrapping primitive arrays.
|
||||||
* Boxing `ListBuffer` wrapping a list
|
* Boxing `ListBuffer` wrapping a list
|
||||||
* Functionally defined `VirtualBuffer` which does not hold a state itself, but provides a function to calculate value
|
* Functionally defined `VirtualBuffer` which does not hold a state itself, but provides a function to calculate value
|
||||||
* `MemoryBuffer` allows direct allocation of objects in continuous memory block.
|
* `MemoryBuffer` allows direct allocation of objects in continuous memory block.
|
||||||
|
|
||||||
Some kmath features require a `BufferFactory` class to operate properly. A general convention is to use functions defined in
|
Some kmath features require a `BufferFactory` class to operate properly. A general convention is to use functions
|
||||||
`Buffer` and `MutableBuffer` companion classes. For example factory `Buffer.Companion::auto` in most cases creates the most suitable
|
defined in
|
||||||
buffer for given reified type (for types with custom memory buffer it still better to use their own `MemoryBuffer.create()` factory).
|
`Buffer` and `MutableBuffer` companion classes. For example factory `Buffer.Companion::auto` in most cases creates the
|
||||||
|
most suitable buffer for given reified type (for types with custom memory buffer it still better to use their
|
||||||
|
own `MemoryBuffer.create()` factory).
|
||||||
|
|
||||||
## Buffer performance
|
## Buffer performance
|
||||||
|
|
||||||
One should avoid using default boxing buffer wherever it is possible. Try to use primitive buffers or memory buffers instead
|
One should avoid using default boxing buffer wherever it is possible. Try to use primitive buffers or memory buffers
|
||||||
|
instead .
|
||||||
|
@ -1,26 +1,20 @@
|
|||||||
# Coding Conventions
|
# Coding Conventions
|
||||||
|
|
||||||
KMath code follows general [Kotlin conventions](https://kotlinlang.org/docs/reference/coding-conventions.html), but
|
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.
|
||||||
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
|
Filename should coincide with a name of one of the classes contained in the file or start with small letter and describe its contents.
|
||||||
describe 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.
|
||||||
|
|
||||||
@ -30,5 +24,4 @@ Use one-liners when they occupy single code window line both for functions and p
|
|||||||
`val b: String get() = "fff"`. The same should be performed with multiline expressions when they could be
|
`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.
|
|
||||||
|
@ -2,18 +2,17 @@
|
|||||||
|
|
||||||
## The problem
|
## The problem
|
||||||
|
|
||||||
A known problem for implementing mathematics in statically-typed languages (but not only in them) is that different
|
A known problem for implementing mathematics in statically-typed languages (but not only in them) is that different sets
|
||||||
sets of mathematical operators can be defined on the same mathematical objects. Sometimes there is no single way to
|
of mathematical operators can be defined on the same mathematical objects. Sometimes there is no single way to treat
|
||||||
treat some operations, including basic arithmetic operations, on a Java/Kotlin `Number`. Sometimes there are different ways to
|
some operations, including basic arithmetic operations, on a Java/Kotlin `Number`. Sometimes there are different ways to
|
||||||
define the same structure, such as Euclidean and elliptic geometry vector spaces over real vectors. Another problem arises when
|
define the same structure, such as Euclidean and elliptic geometry vector spaces over real vectors. Another problem
|
||||||
one wants to add some kind of behavior to an existing entity. In dynamic languages those problems are usually solved
|
arises when one wants to add some kind of behavior to an existing entity. In dynamic languages those problems are
|
||||||
by adding dynamic context-specific behaviors at runtime, but this solution has a lot of drawbacks.
|
usually solved by adding dynamic context-specific behaviors at runtime, but this solution has a lot of drawbacks.
|
||||||
|
|
||||||
## Context-oriented approach
|
## Context-oriented approach
|
||||||
|
|
||||||
One possible solution to these problems is to divorce numerical representations from behaviors.
|
One possible solution to these problems is to divorce numerical representations from behaviors. For example in Kotlin
|
||||||
For example in Kotlin one can define a separate class which represents some entity without any operations,
|
one can define a separate class representing some entity without any operations, ex. a complex number:
|
||||||
ex. a complex number:
|
|
||||||
|
|
||||||
```kotlin
|
```kotlin
|
||||||
data class Complex(val re: Double, val im: Double)
|
data class Complex(val re: Double, val im: Double)
|
||||||
@ -28,9 +27,10 @@ object ComplexOperations {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
In Java, applying such external operations could be very cumbersome, but Kotlin has a unique feature which allows us
|
In Java, applying such external operations could be cumbersome, but Kotlin has a unique feature that allows us
|
||||||
implement this naturally: [extensions with receivers](https://kotlinlang.org/docs/reference/extensions.html#extension-functions).
|
implement this
|
||||||
In Kotlin, an operation on complex number could be implemented as:
|
naturally: [extensions with receivers](https://kotlinlang.org/docs/reference/extensions.html#extension-functions). In
|
||||||
|
Kotlin, an operation on complex number could be implemented as:
|
||||||
|
|
||||||
```kotlin
|
```kotlin
|
||||||
with(ComplexOperations) { c1 + c2 - c3 }
|
with(ComplexOperations) { c1 + c2 - c3 }
|
||||||
@ -52,20 +52,20 @@ In KMath, contexts are not only responsible for operations, but also for raw obj
|
|||||||
|
|
||||||
### Type classes
|
### Type classes
|
||||||
|
|
||||||
An obvious candidate to get more or less the same functionality is the type class, which allows one to bind a behavior to
|
An obvious candidate to get more or less the same functionality is the type class, which allows one to bind a behavior
|
||||||
a specific type without modifying the type itself. On the plus side, type classes do not require explicit context
|
to a specific type without modifying the type itself. On the plus side, type classes do not require explicit context
|
||||||
declaration, so the code looks cleaner. On the minus side, if there are different sets of behaviors for the same types,
|
declaration, so the code looks cleaner. On the minus side, if there are different sets of behaviors for the same types,
|
||||||
it is impossible to combine them into one module. Also, unlike type classes, context can have parameters or even
|
it is impossible to combine them into one module. Also, unlike type classes, context can have parameters or even state.
|
||||||
state. For example in KMath, sizes and strides for `NDElement` or `Matrix` could be moved to context to optimize
|
For example in KMath, sizes and strides for `NDElement` or `Matrix` could be moved to context to optimize performance in
|
||||||
performance in case of a large amount of structures.
|
case of a large amount of structures.
|
||||||
|
|
||||||
### Wildcard imports and importing-on-demand
|
### Wildcard imports and importing-on-demand
|
||||||
|
|
||||||
Sometimes, one may wish to use a single context throughout a file. In this case, is possible to import all members
|
Sometimes, one may wish to use a single context throughout a file. In this case, is possible to import all members from
|
||||||
from a package or file, via `import context.complex.*`. Effectively, this is the same as enclosing an entire file
|
a package or file, via `import context.complex.*`. Effectively, this is the same as enclosing an entire file with a
|
||||||
with a single context. However when using multiple contexts, this technique can introduce operator ambiguity, due to
|
single context. However, when using multiple contexts, this technique can introduce operator ambiguity, due to namespace
|
||||||
namespace pollution. If there are multiple scoped contexts which define the same operation, it is still possible to
|
pollution. If there are multiple scoped contexts that define the same operation, it is still possible to import
|
||||||
to import specific operations as needed, without using an explicit context with extension functions, for example:
|
specific operations as needed, without using an explicit context with extension functions, for example:
|
||||||
|
|
||||||
```
|
```
|
||||||
import context.complex.op1
|
import context.complex.op1
|
||||||
|
1020
docs/diagrams/core.puml
Normal file
@ -1,26 +1,21 @@
|
|||||||
# Expressions
|
# Expressions
|
||||||
|
|
||||||
**Experimental: this API is in early stage and could change any time**
|
Expressions is a feature, which allows constructing lazily or immediately calculated parametric mathematical expressions.
|
||||||
|
|
||||||
Expressions is an experimental feature which allows to construct lazily or immediately calculated parametric mathematical
|
|
||||||
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;
|
||||||
|
* generation of mathematical syntax trees with subsequent code generation for other languages;
|
||||||
|
* symbolic computations, especially differentiation (and some other actions with `kmath-symja` integration with Symja's `IExpr`—integration, simplification, and more);
|
||||||
|
* visualization with `kmath-jupyter`.
|
||||||
|
|
||||||
* Automatic differentiation in single-dimension and in multiple dimensions
|
The workhorse of this API is `Expression` interface, which exposes single `operator fun invoke(arguments: Map<Symbol, T>): T`
|
||||||
|
method. `ExpressionAlgebra` is used to generate expressions and introduce variables.
|
||||||
* Generation of mathematical syntax trees with subsequent code generation for other languages
|
|
||||||
|
|
||||||
* Maybe symbolic computations (needs additional research)
|
|
||||||
|
|
||||||
The workhorse of this API is `Expression` interface which exposes single `operator fun invoke(arguments: Map<String, T>): T`
|
|
||||||
method. `ExpressionContext` is used to generate expressions and introduce variables.
|
|
||||||
|
|
||||||
Currently there are two implementations:
|
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 to use full power of `DerivativeStructure`
|
* Auto-differentiation expression in `kmath-commons` module allows using full power of `DerivativeStructure`
|
||||||
from commons-math. **TODO: add example**
|
from commons-math. **TODO: add example**
|
||||||
|
@ -1,14 +0,0 @@
|
|||||||
# Features
|
|
||||||
|
|
||||||
* [Algebra](algebra.md) - [Context-based](contexts.md) operations on different primitives and structures.
|
|
||||||
|
|
||||||
* [NDStructures](nd-structure.md)
|
|
||||||
|
|
||||||
* [Linear algebra](linear.md) - Matrices, operations and linear equations solving. To be moved to separate module. Currently supports basic
|
|
||||||
api and multiple library back-ends.
|
|
||||||
|
|
||||||
* [Histograms](histograms.md) - Multidimensional histogram calculation and operations.
|
|
||||||
|
|
||||||
* [Expressions](expressions.md)
|
|
||||||
|
|
||||||
* Commons math integration
|
|
@ -1,4 +1,9 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
|
<!--
|
||||||
|
- Copyright 2018-2021 KMath contributors.
|
||||||
|
- Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
|
||||||
|
-->
|
||||||
|
|
||||||
<svg
|
<svg
|
||||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||||
xmlns:cc="http://creativecommons.org/ns#"
|
xmlns:cc="http://creativecommons.org/ns#"
|
||||||
|
Before Width: | Height: | Size: 248 KiB After Width: | Height: | Size: 249 KiB |
@ -1,4 +1,9 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
|
<!--
|
||||||
|
- Copyright 2018-2021 KMath contributors.
|
||||||
|
- Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
|
||||||
|
-->
|
||||||
|
|
||||||
<svg
|
<svg
|
||||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||||
xmlns:cc="http://creativecommons.org/ns#"
|
xmlns:cc="http://creativecommons.org/ns#"
|
||||||
|
Before Width: | Height: | Size: 18 KiB After Width: | Height: | Size: 19 KiB |
@ -1,4 +1,9 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
|
<!--
|
||||||
|
- Copyright 2018-2021 KMath contributors.
|
||||||
|
- Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
|
||||||
|
-->
|
||||||
|
|
||||||
<svg
|
<svg
|
||||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||||
xmlns:cc="http://creativecommons.org/ns#"
|
xmlns:cc="http://creativecommons.org/ns#"
|
||||||
|
Before Width: | Height: | Size: 278 KiB After Width: | Height: | Size: 278 KiB |
@ -1,4 +1,9 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
|
<!--
|
||||||
|
- Copyright 2018-2021 KMath contributors.
|
||||||
|
- Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
|
||||||
|
-->
|
||||||
|
|
||||||
<svg
|
<svg
|
||||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||||
xmlns:cc="http://creativecommons.org/ns#"
|
xmlns:cc="http://creativecommons.org/ns#"
|
||||||
|
Before Width: | Height: | Size: 117 KiB After Width: | Height: | Size: 118 KiB |
@ -1,19 +1,31 @@
|
|||||||
## Basic linear algebra layout
|
## Basic linear algebra layout
|
||||||
|
|
||||||
KMath support for linear algebra organized in a context-oriented way. Meaning that operations are in most cases declared
|
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.
|
||||||
in context classes, and are not the members of classes that store data. This allows more flexible approach to maintain multiple
|
|
||||||
back-ends. The new operations added as extensions to contexts instead of being member functions of data structures.
|
|
||||||
|
|
||||||
Two major contexts used for linear algebra and hyper-geometry:
|
The main context for linear algebra over matrices and vectors is `LinearSpace`, which defines addition and dot products of matrices and vectors:
|
||||||
|
|
||||||
* `VectorSpace` forms a mathematical space on top of array-like structure (`Buffer` and its type alias `Point` used for geometry).
|
```kotlin
|
||||||
|
import space.kscience.kmath.linear.*
|
||||||
|
|
||||||
* `MatrixContext` forms a space-like context for 2d-structures. It does not store matrix size and therefore does not implement
|
LinearSpace.Companion.real {
|
||||||
`Space` interface (it is impossible to create zero element without knowing the matrix size).
|
val vec = buildVector(10) { i -> i.toDouble() }
|
||||||
|
val mat = buildMatrix(10, 10) { i, j -> i.toDouble() + j }
|
||||||
|
|
||||||
## Vector spaces
|
// Addition
|
||||||
|
vec + vec
|
||||||
|
mat + mat
|
||||||
|
|
||||||
|
// Multiplication by scalar
|
||||||
|
vec * 2.0
|
||||||
|
mat * 2.0
|
||||||
|
|
||||||
## Matrix operations
|
// Dot product
|
||||||
|
mat dot vec
|
||||||
|
mat dot mat
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
## Back-end overview
|
## Backends overview
|
||||||
|
|
||||||
|
### EJML
|
||||||
|
### Commons Math
|
||||||
|
@ -11,16 +11,16 @@ 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)
|
||||||
// specialized nd-field for Double. It works as generic Double field as well
|
// specialized nd-field for Double. It works as generic Double field as well.
|
||||||
val specializedField = NDField.real(dim, dim)
|
val specializedField = NDField.real(dim, dim)
|
||||||
//A generic boxing field. It should be used for objects, not primitives.
|
//A generic boxing field. It should be used for objects, not primitives.
|
||||||
val genericField = NDField.buffered(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
|
||||||
|
|
||||||
In order to test performance we will take 2d-structures with `dim = 1000` and add a structure filled with `1.0`
|
To test performance we will take 2d-structures with `dim = 1000` and add a structure filled with `1.0`
|
||||||
to it `n = 1000` times.
|
to it `n = 1000` times.
|
||||||
|
|
||||||
## Specialized
|
## Specialized
|
||||||
@ -35,8 +35,8 @@ The code to run this looks like:
|
|||||||
```
|
```
|
||||||
The performance of this code is the best of all tests since it inlines all operations and is specialized for operation
|
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 to specify 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 do 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:
|
||||||
@ -49,7 +49,7 @@ Let's do the same with automatic field inference:
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
Ths speed of this operation is approximately the same as for specialized case since `NDField.auto` just
|
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
|
||||||
@ -63,7 +63,7 @@ When one calls
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
The result will be calculated almost immediately but the result will be empty. In order to get the full result
|
The result will be calculated almost immediately but the result will be empty. To get the full result
|
||||||
structure one needs to call all its elements. In this case computation overhead will be huge. So this field never
|
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.
|
||||||
@ -94,7 +94,7 @@ The boxing field produced by
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
obviously is the slowest one, because it requires to box and unbox the `double` on each operation. It takes about
|
is the slowest one, because it requires boxing and unboxing the `double` on each operation. It takes about
|
||||||
`15x` time (**TODO: there seems to be a problem here, it should be slow, but not that slow**). This field should
|
`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.
|
||||||
|
|
||||||
@ -115,12 +115,14 @@ via extension function.
|
|||||||
Usually it is bad idea to compare the direct numerical operation performance in different languages, but it hard to
|
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
|
||||||
|
|
||||||
res = np.ones((1000,1000))
|
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 differenc case, because numpy overrides `+=` with in-place operations. In-place operations are
|
but it would be different case, because numpy overrides `+=` with in-place operations. In-place operations are
|
||||||
available in `kmath` with `MutableNDStructure` but there is no field for it (one can still work with mapping
|
available in `kmath` with `MutableNDStructure` but there is no field for it (one can still work with mapping
|
||||||
functions).
|
functions).
|
14
docs/readme.md
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
# Documentation
|
||||||
|
|
||||||
|
* [Algebra](algebra.md): [context-based](contexts.md) operations on different primitives and structures.
|
||||||
|
|
||||||
|
* [NDStructures](nd-structure.md)
|
||||||
|
|
||||||
|
* [Linear algebra](linear.md): matrices, operations and linear equations solving. To be moved to separate module.
|
||||||
|
Currently, supports basic API and multiple library back-ends.
|
||||||
|
|
||||||
|
* [Histograms](histograms.md): multidimensional histogram calculation and operations.
|
||||||
|
|
||||||
|
* [Expressions](expressions.md)
|
||||||
|
|
||||||
|
* Commons math integration
|
68
docs/templates/README-TEMPLATE.md
vendored
@ -2,14 +2,14 @@
|
|||||||
[![DOI](https://zenodo.org/badge/129486382.svg)](https://zenodo.org/badge/latestdoi/129486382)
|
[![DOI](https://zenodo.org/badge/129486382.svg)](https://zenodo.org/badge/latestdoi/129486382)
|
||||||
![Gradle build](https://github.com/mipt-npm/kmath/workflows/Gradle%20build/badge.svg)
|
![Gradle build](https://github.com/mipt-npm/kmath/workflows/Gradle%20build/badge.svg)
|
||||||
[![Maven Central](https://img.shields.io/maven-central/v/space.kscience/kmath-core.svg?label=Maven%20Central)](https://search.maven.org/search?q=g:%22space.kscience%22)
|
[![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/maven-metadata/v?label=Space&metadataUrl=https%3A%2F%2Fmaven.pkg.jetbrains.space%2Fmipt-npm%2Fp%2Fsci%2Fmaven%2Fkscience%2Fkmath%2Fkmath-core%2Fmaven-metadata.xml)](https://maven.pkg.jetbrains.space/mipt-npm/p/sci/maven/space/kscience/)
|
[![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/)
|
||||||
|
|
||||||
# KMath
|
# KMath
|
||||||
|
|
||||||
Could be pronounced as `key-math`. The **K**otlin **Math**ematics library was initially intended as a Kotlin-based analog to
|
Could be pronounced as `key-math`. The **K**otlin **Math**ematics library was initially intended as a Kotlin-based
|
||||||
Python's NumPy library. Later we found that kotlin is much more flexible language and allows superior architecture
|
analog to Python's NumPy library. Later we found that kotlin is much more flexible language and allows superior
|
||||||
designs. In contrast to `numpy` and `scipy` it is modular and has a lightweight core. The `numpy`-like experience could
|
architecture designs. In contrast to `numpy` and `scipy` it is modular and has a lightweight core. The `numpy`-like
|
||||||
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 (**WIP**)](https://mipt-npm.github.io/kmath/)
|
[Documentation site (**WIP**)](https://mipt-npm.github.io/kmath/)
|
||||||
|
|
||||||
@ -21,26 +21,33 @@ be achieved with [kmath-for-real](/kmath-for-real) extension module.
|
|||||||
|
|
||||||
# Goal
|
# Goal
|
||||||
|
|
||||||
* Provide a flexible and powerful API to work with mathematics abstractions in Kotlin-multiplatform (JVM, JS and Native).
|
* Provide a flexible and powerful API to work with mathematics abstractions in Kotlin-multiplatform (JVM, JS and Native)
|
||||||
|
.
|
||||||
* Provide basic multiplatform implementations for those abstractions (without significant performance optimization).
|
* Provide 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.
|
||||||
|
|
||||||
## Non-goals
|
## Non-goals
|
||||||
|
|
||||||
* Be like NumPy. It was the idea at the beginning, but we decided that we can do better in terms of API.
|
* Be like NumPy. It was the idea at the beginning, but we decided that we can do better in API.
|
||||||
* Provide the best performance out of the box. We have specialized libraries for that. Need only API wrappers for them.
|
* Provide the best performance out of the box. We have specialized libraries for that. Need only API wrappers for them.
|
||||||
* Cover all cases as immediately and in one bundle. We will modularize everything and add new features gradually.
|
* Cover all cases as immediately and in one bundle. We will modularize everything and add new features gradually.
|
||||||
* Provide specialized behavior in the core. API is made generic on purpose, so one needs to specialize for types, like
|
* Provide specialized behavior in the core. API is made generic on purpose, so one needs to specialize for types, like
|
||||||
for `Double` in the core. For that we will have specialization modules like `kmath-for-real`, which will give better
|
for `Double` in the core. For that we will have specialization modules like `kmath-for-real`, which will give better
|
||||||
experience for those, who want to work with specific types.
|
experience for those, who want to work with specific types.
|
||||||
|
|
||||||
## Features and stability
|
## Features and stability
|
||||||
|
|
||||||
KMath is a modular library. Different modules provide different features with different API stability guarantees. All core modules are released with the same version, but with different API change policy. The features are described in module definitions below. The module stability could have following levels:
|
KMath is a modular library. Different modules provide different features with different API stability guarantees. All
|
||||||
|
core modules are released with the same version, but with different API change policy. The features are described in
|
||||||
|
module definitions below. The module stability could have the following levels:
|
||||||
|
|
||||||
* **PROTOTYPE**. On this level there are no compatibility guarantees. All methods and classes form those modules could break any moment. You can still use it, but be sure to fix the specific version.
|
* **PROTOTYPE**. On this level there are no compatibility guarantees. All methods and classes form those modules could
|
||||||
* **EXPERIMENTAL**. The general API is decided, but some changes could be made. Volatile API is marked with `@UnstableKmathAPI` or other stability warning annotations.
|
break any moment. You can still use it, but be sure to fix the specific version.
|
||||||
* **DEVELOPMENT**. API breaking genrally follows semantic versioning ideology. There could be changes in minor versions, but not in patch versions. API is protected with [binary-compatibility-validator](https://github.com/Kotlin/binary-compatibility-validator) tool.
|
* **EXPERIMENTAL**. The general API is decided, but some changes could be made. Volatile API is marked
|
||||||
|
with `@UnstableKmathAPI` or other stability warning annotations.
|
||||||
|
* **DEVELOPMENT**. API breaking generally follows semantic versioning ideology. There could be changes in minor
|
||||||
|
versions, but not in patch versions. API is protected
|
||||||
|
with [binary-compatibility-validator](https://github.com/Kotlin/binary-compatibility-validator) tool.
|
||||||
* **STABLE**. The API stabilized. Breaking changes are allowed only in major releases.
|
* **STABLE**. The API stabilized. Breaking changes are allowed only in major releases.
|
||||||
|
|
||||||
<!--Current feature list is [here](/docs/features.md)-->
|
<!--Current feature list is [here](/docs/features.md)-->
|
||||||
@ -78,30 +85,33 @@ $modules
|
|||||||
|
|
||||||
## Multi-platform support
|
## Multi-platform support
|
||||||
|
|
||||||
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, the 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 performance is one of major goals of KMath in the future, but in some cases it is impossible to achieve
|
Calculation performance is one of major goals of KMath in the future, but in some cases it is impossible to achieve both
|
||||||
both performance and flexibility.
|
performance and flexibility.
|
||||||
|
|
||||||
We expect to focus on creating 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 to use GraalVM-CE 11 for execution in order to get better performance.
|
KMath currently relies on JDK 11 for compilation and execution of Kotlin-JVM part. We recommend to use GraalVM-CE 11 for
|
||||||
|
execution to get better performance.
|
||||||
|
|
||||||
### Repositories
|
### Repositories
|
||||||
|
|
||||||
Release and development artifacts are accessible from mipt-npm [Space](https://www.jetbrains.com/space/) repository `https://maven.pkg.jetbrains.space/mipt-npm/p/sci/maven` (see documentation of
|
Release and development artifacts are accessible from mipt-npm [Space](https://www.jetbrains.com/space/)
|
||||||
[Kotlin Multiplatform](https://kotlinlang.org/docs/reference/multiplatform.html) for more details). The repository could be reached through [repo.kotlin.link](https://repo.kotlin.link) proxy:
|
repository `https://maven.pkg.jetbrains.space/mipt-npm/p/sci/maven` (see documentation of
|
||||||
|
[Kotlin Multiplatform](https://kotlinlang.org/docs/reference/multiplatform.html) for more details). The repository could
|
||||||
|
be reached through [repo.kotlin.link](https://repo.kotlin.link) proxy:
|
||||||
|
|
||||||
```kotlin
|
```kotlin
|
||||||
repositories {
|
repositories {
|
||||||
@ -118,7 +128,7 @@ 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 a feedback about what features are
|
The project requires a lot of additional work. The most important thing we need is a feedback about what features are
|
||||||
required the most. Feel free to create feature requests. We are also welcome to code contributions,
|
required the most. Feel free to create feature requests. We are also welcome to code contributions, especially in issues
|
||||||
especially in issues marked with
|
marked with
|
||||||
[waiting for a hero](https://github.com/mipt-npm/kmath/labels/waiting%20for%20a%20hero) label.
|
[waiting for a hero](https://github.com/mipt-npm/kmath/labels/waiting%20for%20a%20hero) label.
|
||||||
|
@ -20,13 +20,14 @@ dependencies {
|
|||||||
implementation(project(":kmath-coroutines"))
|
implementation(project(":kmath-coroutines"))
|
||||||
implementation(project(":kmath-commons"))
|
implementation(project(":kmath-commons"))
|
||||||
implementation(project(":kmath-complex"))
|
implementation(project(":kmath-complex"))
|
||||||
|
implementation(project(":kmath-optimization"))
|
||||||
implementation(project(":kmath-stat"))
|
implementation(project(":kmath-stat"))
|
||||||
implementation(project(":kmath-viktor"))
|
implementation(project(":kmath-viktor"))
|
||||||
implementation(project(":kmath-dimensions"))
|
implementation(project(":kmath-dimensions"))
|
||||||
implementation(project(":kmath-ejml"))
|
implementation(project(":kmath-ejml"))
|
||||||
implementation(project(":kmath-nd4j"))
|
implementation(project(":kmath-nd4j"))
|
||||||
implementation(project(":kmath-tensors"))
|
implementation(project(":kmath-tensors"))
|
||||||
|
implementation(project(":kmath-symja"))
|
||||||
implementation(project(":kmath-for-real"))
|
implementation(project(":kmath-for-real"))
|
||||||
|
|
||||||
implementation("org.nd4j:nd4j-native:1.0.0-beta7")
|
implementation("org.nd4j:nd4j-native:1.0.0-beta7")
|
||||||
@ -41,9 +42,11 @@ dependencies {
|
|||||||
// } else
|
// } else
|
||||||
implementation("org.nd4j:nd4j-native-platform:1.0.0-beta7")
|
implementation("org.nd4j:nd4j-native-platform:1.0.0-beta7")
|
||||||
|
|
||||||
implementation("org.slf4j:slf4j-simple:1.7.30")
|
implementation("org.slf4j:slf4j-simple:1.7.31")
|
||||||
// plotting
|
// plotting
|
||||||
implementation("space.kscience:plotlykt-server:0.4.0-dev-2")
|
implementation("space.kscience:plotlykt-server:0.4.2")
|
||||||
|
//jafama
|
||||||
|
implementation(project(":kmath-jafama"))
|
||||||
}
|
}
|
||||||
|
|
||||||
kotlin.sourceSets.all {
|
kotlin.sourceSets.all {
|
||||||
@ -57,7 +60,7 @@ kotlin.sourceSets.all {
|
|||||||
tasks.withType<org.jetbrains.kotlin.gradle.tasks.KotlinCompile> {
|
tasks.withType<org.jetbrains.kotlin.gradle.tasks.KotlinCompile> {
|
||||||
kotlinOptions{
|
kotlinOptions{
|
||||||
jvmTarget = "11"
|
jvmTarget = "11"
|
||||||
freeCompilerArgs = freeCompilerArgs + "-Xjvm-default=all"
|
freeCompilerArgs = freeCompilerArgs + "-Xjvm-default=all" + "-Xopt-in=kotlin.RequiresOptIn"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2018-2021 KMath contributors.
|
* Copyright 2018-2021 KMath contributors.
|
||||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
* Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package space.kscience.kmath.ast
|
package space.kscience.kmath.ast
|
||||||
@ -10,7 +10,7 @@ import space.kscience.kmath.ast.rendering.LatexSyntaxRenderer
|
|||||||
import space.kscience.kmath.ast.rendering.MathMLSyntaxRenderer
|
import space.kscience.kmath.ast.rendering.MathMLSyntaxRenderer
|
||||||
import space.kscience.kmath.ast.rendering.renderWithStringBuilder
|
import space.kscience.kmath.ast.rendering.renderWithStringBuilder
|
||||||
|
|
||||||
public fun main() {
|
fun main() {
|
||||||
val mst = "exp(sqrt(x))-asin(2*x)/(2e10+x^3)/(-12)".parseMath()
|
val mst = "exp(sqrt(x))-asin(2*x)/(2e10+x^3)/(-12)".parseMath()
|
||||||
val syntax = FeaturedMathRendererWithPostProcess.Default.render(mst)
|
val syntax = FeaturedMathRendererWithPostProcess.Default.render(mst)
|
||||||
println("MathSyntax:")
|
println("MathSyntax:")
|
||||||
|
@ -1,20 +1,18 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2018-2021 KMath contributors.
|
* Copyright 2018-2021 KMath contributors.
|
||||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
* Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package space.kscience.kmath.ast
|
package space.kscience.kmath.ast
|
||||||
|
|
||||||
import space.kscience.kmath.expressions.MstField
|
import space.kscience.kmath.expressions.MstField
|
||||||
|
import space.kscience.kmath.expressions.Symbol.Companion.x
|
||||||
import space.kscience.kmath.expressions.interpret
|
import space.kscience.kmath.expressions.interpret
|
||||||
import space.kscience.kmath.misc.Symbol.Companion.x
|
|
||||||
import space.kscience.kmath.operations.DoubleField
|
import space.kscience.kmath.operations.DoubleField
|
||||||
import space.kscience.kmath.operations.bindSymbol
|
|
||||||
import space.kscience.kmath.operations.invoke
|
import space.kscience.kmath.operations.invoke
|
||||||
|
|
||||||
fun main() {
|
fun main() {
|
||||||
val expr = MstField {
|
val expr = MstField {
|
||||||
val x = bindSymbol(x)
|
|
||||||
x * 2.0 + number(2.0) / x - 16.0
|
x * 2.0 + number(2.0) / x - 16.0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,29 +1,27 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2018-2021 KMath contributors.
|
* Copyright 2018-2021 KMath contributors.
|
||||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
* Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package space.kscience.kmath.ast
|
package space.kscience.kmath.ast
|
||||||
|
|
||||||
import space.kscience.kmath.asm.compileToExpression
|
|
||||||
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.kotlingrad.toDiffExpression
|
import space.kscience.kmath.expressions.Symbol.Companion.x
|
||||||
import space.kscience.kmath.misc.symbol
|
import space.kscience.kmath.expressions.toExpression
|
||||||
|
import space.kscience.kmath.kotlingrad.toKotlingradExpression
|
||||||
import space.kscience.kmath.operations.DoubleField
|
import space.kscience.kmath.operations.DoubleField
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* In this example, x^2-4*x-44 function is differentiated with Kotlin∇, and the autodiff result is compared with
|
* In this example, *x<sup>2</sup> − 4 x − 44* function is differentiated with Kotlin∇, and the
|
||||||
* valid derivative.
|
* derivation result is compared with valid derivative in a certain point.
|
||||||
*/
|
*/
|
||||||
fun main() {
|
fun main() {
|
||||||
val x by symbol
|
val actualDerivative = "x^2-4*x-44"
|
||||||
|
.parseMath()
|
||||||
val actualDerivative = "x^2-4*x-44".parseMath()
|
.toKotlingradExpression(DoubleField)
|
||||||
.toDiffExpression(DoubleField)
|
|
||||||
.derivative(x)
|
.derivative(x)
|
||||||
|
|
||||||
|
val expectedDerivative = "2*x-4".parseMath().toExpression(DoubleField)
|
||||||
val expectedDerivative = "2*x-4".parseMath().compileToExpression(DoubleField)
|
check(actualDerivative(x to 123.0) == expectedDerivative(x to 123.0))
|
||||||
assert(actualDerivative(x to 123.0) == expectedDerivative(x to 123.0))
|
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,27 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2018-2021 KMath contributors.
|
||||||
|
* Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package space.kscience.kmath.ast
|
||||||
|
|
||||||
|
import space.kscience.kmath.expressions.Symbol.Companion.x
|
||||||
|
import space.kscience.kmath.expressions.derivative
|
||||||
|
import space.kscience.kmath.expressions.invoke
|
||||||
|
import space.kscience.kmath.expressions.toExpression
|
||||||
|
import space.kscience.kmath.operations.DoubleField
|
||||||
|
import space.kscience.kmath.symja.toSymjaExpression
|
||||||
|
|
||||||
|
/**
|
||||||
|
* In this example, *x<sup>2</sup> − 4 x − 44* function is differentiated with Symja, and the
|
||||||
|
* derivation result is compared with valid derivative in a certain point.
|
||||||
|
*/
|
||||||
|
fun main() {
|
||||||
|
val actualDerivative = "x^2-4*x-44"
|
||||||
|
.parseMath()
|
||||||
|
.toSymjaExpression(DoubleField)
|
||||||
|
.derivative(x)
|
||||||
|
|
||||||
|
val expectedDerivative = "2*x-4".parseMath().toExpression(DoubleField)
|
||||||
|
check(actualDerivative(x to 123.0) == expectedDerivative(x to 123.0))
|
||||||
|
}
|
@ -1,32 +1,34 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2018-2021 KMath contributors.
|
* Copyright 2018-2021 KMath contributors.
|
||||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
* Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package space.kscience.kmath.commons.fit
|
package space.kscience.kmath.fit
|
||||||
|
|
||||||
import kotlinx.html.br
|
import kotlinx.html.br
|
||||||
import kotlinx.html.h3
|
import kotlinx.html.h3
|
||||||
import space.kscience.kmath.commons.optimization.chiSquared
|
import space.kscience.kmath.commons.expressions.DSProcessor
|
||||||
import space.kscience.kmath.commons.optimization.minimize
|
import space.kscience.kmath.commons.optimization.CMOptimizer
|
||||||
import space.kscience.kmath.distributions.NormalDistribution
|
import space.kscience.kmath.distributions.NormalDistribution
|
||||||
import space.kscience.kmath.misc.symbol
|
import space.kscience.kmath.expressions.chiSquaredExpression
|
||||||
import space.kscience.kmath.optimization.FunctionOptimization
|
import space.kscience.kmath.expressions.symbol
|
||||||
import space.kscience.kmath.optimization.OptimizationResult
|
import space.kscience.kmath.operations.asIterable
|
||||||
|
import space.kscience.kmath.operations.toList
|
||||||
|
import space.kscience.kmath.optimization.FunctionOptimizationTarget
|
||||||
|
import space.kscience.kmath.optimization.optimizeWith
|
||||||
|
import space.kscience.kmath.optimization.resultPoint
|
||||||
|
import space.kscience.kmath.optimization.resultValue
|
||||||
import space.kscience.kmath.real.DoubleVector
|
import space.kscience.kmath.real.DoubleVector
|
||||||
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.stat.RandomGenerator
|
import space.kscience.kmath.stat.RandomGenerator
|
||||||
import space.kscience.kmath.structures.asIterable
|
|
||||||
import space.kscience.kmath.structures.toList
|
|
||||||
import space.kscience.plotly.*
|
import space.kscience.plotly.*
|
||||||
import space.kscience.plotly.models.ScatterMode
|
import space.kscience.plotly.models.ScatterMode
|
||||||
import space.kscience.plotly.models.TraceValues
|
import space.kscience.plotly.models.TraceValues
|
||||||
import kotlin.math.pow
|
import kotlin.math.pow
|
||||||
import kotlin.math.sqrt
|
import kotlin.math.sqrt
|
||||||
|
|
||||||
//Forward declaration of symbols that will be used in expressions.
|
// Forward declaration of symbols that will be used in expressions.
|
||||||
// This declaration is required for
|
|
||||||
private val a by symbol
|
private val a by symbol
|
||||||
private val b by symbol
|
private val b by symbol
|
||||||
private val c by symbol
|
private val c by symbol
|
||||||
@ -43,7 +45,7 @@ operator fun TraceValues.invoke(vector: DoubleVector) {
|
|||||||
*/
|
*/
|
||||||
suspend fun main() {
|
suspend fun main() {
|
||||||
//A generator for a normally distributed values
|
//A generator for a normally distributed values
|
||||||
val generator = NormalDistribution(2.0, 7.0)
|
val generator = NormalDistribution(0.0, 1.0)
|
||||||
|
|
||||||
//A chain/flow of random values with the given seed
|
//A chain/flow of random values with the given seed
|
||||||
val chain = generator.sample(RandomGenerator.default(112667))
|
val chain = generator.sample(RandomGenerator.default(112667))
|
||||||
@ -54,7 +56,7 @@ suspend fun main() {
|
|||||||
|
|
||||||
|
|
||||||
//Perform an operation on each x value (much more effective, than numpy)
|
//Perform an operation on each x value (much more effective, than numpy)
|
||||||
val y = x.map {
|
val y = x.map { it ->
|
||||||
val value = it.pow(2) + it + 1
|
val value = it.pow(2) + it + 1
|
||||||
value + chain.next() * sqrt(value)
|
value + chain.next() * sqrt(value)
|
||||||
}
|
}
|
||||||
@ -65,17 +67,21 @@ suspend fun main() {
|
|||||||
val yErr = y.map { sqrt(it) }//RealVector.same(x.size, sigma)
|
val yErr = y.map { sqrt(it) }//RealVector.same(x.size, sigma)
|
||||||
|
|
||||||
// compute differentiable chi^2 sum for given model ax^2 + bx + c
|
// compute differentiable chi^2 sum for given model ax^2 + bx + c
|
||||||
val chi2 = FunctionOptimization.chiSquared(x, y, yErr) { x1 ->
|
val chi2 = DSProcessor.chiSquaredExpression(x, y, yErr) { arg ->
|
||||||
//bind variables to autodiff context
|
//bind variables to autodiff context
|
||||||
val a = bindSymbol(a)
|
val a = bindSymbol(a)
|
||||||
val b = bindSymbol(b)
|
val b = bindSymbol(b)
|
||||||
//Include default value for c if it is not provided as a parameter
|
//Include default value for c if it is not provided as a parameter
|
||||||
val c = bindSymbolOrNull(c) ?: one
|
val c = bindSymbolOrNull(c) ?: one
|
||||||
a * x1.pow(2) + b * x1 + c
|
a * arg.pow(2) + b * arg + c
|
||||||
}
|
}
|
||||||
|
|
||||||
//minimize the chi^2 in given starting point. Derivatives are not required, they are already included.
|
//minimize the chi^2 in given starting point. Derivatives are not required, they are already included.
|
||||||
val result: OptimizationResult<Double> = chi2.minimize(a to 1.5, b to 0.9, c to 1.0)
|
val result = chi2.optimizeWith(
|
||||||
|
CMOptimizer,
|
||||||
|
mapOf(a to 1.5, b to 0.9, c to 1.0),
|
||||||
|
FunctionOptimizationTarget.MINIMIZE
|
||||||
|
)
|
||||||
|
|
||||||
//display a page with plot and numerical results
|
//display a page with plot and numerical results
|
||||||
val page = Plotly.page {
|
val page = Plotly.page {
|
||||||
@ -92,7 +98,7 @@ suspend fun main() {
|
|||||||
scatter {
|
scatter {
|
||||||
mode = ScatterMode.lines
|
mode = ScatterMode.lines
|
||||||
x(x)
|
x(x)
|
||||||
y(x.map { result.point[a]!! * it.pow(2) + result.point[b]!! * it + 1 })
|
y(x.map { result.resultPoint[a]!! * it.pow(2) + result.resultPoint[b]!! * it + 1 })
|
||||||
name = "fit"
|
name = "fit"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -101,7 +107,7 @@ suspend fun main() {
|
|||||||
+"Fit result: $result"
|
+"Fit result: $result"
|
||||||
}
|
}
|
||||||
h3 {
|
h3 {
|
||||||
+"Chi2/dof = ${result.value / (x.size - 3)}"
|
+"Chi2/dof = ${result.resultValue / (x.size - 3)}"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
106
examples/src/main/kotlin/space/kscience/kmath/fit/qowFit.kt
Normal file
@ -0,0 +1,106 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2018-2021 KMath contributors.
|
||||||
|
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package space.kscience.kmath.fit
|
||||||
|
|
||||||
|
import kotlinx.html.br
|
||||||
|
import kotlinx.html.h3
|
||||||
|
import space.kscience.kmath.commons.expressions.DSProcessor
|
||||||
|
import space.kscience.kmath.data.XYErrorColumnarData
|
||||||
|
import space.kscience.kmath.distributions.NormalDistribution
|
||||||
|
import space.kscience.kmath.expressions.Symbol
|
||||||
|
import space.kscience.kmath.expressions.binding
|
||||||
|
import space.kscience.kmath.expressions.symbol
|
||||||
|
import space.kscience.kmath.operations.asIterable
|
||||||
|
import space.kscience.kmath.operations.toList
|
||||||
|
import space.kscience.kmath.optimization.QowOptimizer
|
||||||
|
import space.kscience.kmath.optimization.chiSquaredOrNull
|
||||||
|
import space.kscience.kmath.optimization.fitWith
|
||||||
|
import space.kscience.kmath.optimization.resultPoint
|
||||||
|
import space.kscience.kmath.real.map
|
||||||
|
import space.kscience.kmath.real.step
|
||||||
|
import space.kscience.kmath.stat.RandomGenerator
|
||||||
|
import space.kscience.plotly.*
|
||||||
|
import space.kscience.plotly.models.ScatterMode
|
||||||
|
import kotlin.math.abs
|
||||||
|
import kotlin.math.pow
|
||||||
|
import kotlin.math.sqrt
|
||||||
|
|
||||||
|
// Forward declaration of symbols that will be used in expressions.
|
||||||
|
private val a by symbol
|
||||||
|
private val b by symbol
|
||||||
|
private val c by symbol
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Least squares fie with auto-differentiation. Uses `kmath-commons` and `kmath-for-real` modules.
|
||||||
|
*/
|
||||||
|
suspend fun main() {
|
||||||
|
//A generator for a normally distributed values
|
||||||
|
val generator = NormalDistribution(0.0, 1.0)
|
||||||
|
|
||||||
|
//A chain/flow of random values with the given seed
|
||||||
|
val chain = generator.sample(RandomGenerator.default(112667))
|
||||||
|
|
||||||
|
|
||||||
|
//Create a uniformly distributed x values like numpy.arrange
|
||||||
|
val x = 1.0..100.0 step 1.0
|
||||||
|
|
||||||
|
|
||||||
|
//Perform an operation on each x value (much more effective, than numpy)
|
||||||
|
val y = x.map { it ->
|
||||||
|
val value = it.pow(2) + it + 1
|
||||||
|
value + chain.next() * sqrt(value)
|
||||||
|
}
|
||||||
|
// this will also work, but less effective:
|
||||||
|
// val y = x.pow(2)+ x + 1 + chain.nextDouble()
|
||||||
|
|
||||||
|
// create same errors for all xs
|
||||||
|
val yErr = y.map { sqrt(abs(it)) }
|
||||||
|
require(yErr.asIterable().all { it > 0 }) { "All errors must be strictly positive" }
|
||||||
|
|
||||||
|
val result = XYErrorColumnarData.of(x, y, yErr).fitWith(
|
||||||
|
QowOptimizer,
|
||||||
|
DSProcessor,
|
||||||
|
mapOf(a to 0.9, b to 1.2, c to 2.0)
|
||||||
|
) { arg ->
|
||||||
|
//bind variables to autodiff context
|
||||||
|
val a by binding
|
||||||
|
val b by binding
|
||||||
|
//Include default value for c if it is not provided as a parameter
|
||||||
|
val c = bindSymbolOrNull(c) ?: one
|
||||||
|
a * arg.pow(2) + b * arg + c
|
||||||
|
}
|
||||||
|
|
||||||
|
//display a page with plot and numerical results
|
||||||
|
val page = Plotly.page {
|
||||||
|
plot {
|
||||||
|
scatter {
|
||||||
|
mode = ScatterMode.markers
|
||||||
|
x(x)
|
||||||
|
y(y)
|
||||||
|
error_y {
|
||||||
|
array = yErr.toList()
|
||||||
|
}
|
||||||
|
name = "data"
|
||||||
|
}
|
||||||
|
scatter {
|
||||||
|
mode = ScatterMode.lines
|
||||||
|
x(x)
|
||||||
|
y(x.map { result.model(result.resultPoint + (Symbol.x to it)) })
|
||||||
|
name = "fit"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
br()
|
||||||
|
h3 {
|
||||||
|
+"Fit result: ${result.resultPoint}"
|
||||||
|
}
|
||||||
|
h3 {
|
||||||
|
+"Chi2/dof = ${result.chiSquaredOrNull!! / (x.size - 3)}"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
page.makeFile()
|
||||||
|
}
|
@ -1,10 +1,11 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2018-2021 KMath contributors.
|
* Copyright 2018-2021 KMath contributors.
|
||||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
* Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package space.kscience.kmath.functions
|
package space.kscience.kmath.functions
|
||||||
|
|
||||||
|
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.DoubleField
|
import space.kscience.kmath.operations.DoubleField
|
||||||
@ -15,7 +16,7 @@ fun main() {
|
|||||||
val function: UnivariateFunction<Double> = { x -> 3 * x.pow(2) + 2 * x + 1 }
|
val function: UnivariateFunction<Double> = { x -> 3 * x.pow(2) + 2 * x + 1 }
|
||||||
|
|
||||||
//get the result of the integration
|
//get the result of the integration
|
||||||
val result = DoubleField.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)
|
||||||
|
@ -0,0 +1,54 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2018-2021 KMath contributors.
|
||||||
|
* Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package space.kscience.kmath.functions
|
||||||
|
|
||||||
|
import space.kscience.kmath.interpolation.SplineInterpolator
|
||||||
|
import space.kscience.kmath.interpolation.interpolatePolynomials
|
||||||
|
import space.kscience.kmath.operations.DoubleField
|
||||||
|
import space.kscience.kmath.structures.DoubleBuffer
|
||||||
|
import space.kscience.plotly.Plotly
|
||||||
|
import space.kscience.plotly.UnstablePlotlyAPI
|
||||||
|
import space.kscience.plotly.makeFile
|
||||||
|
import space.kscience.plotly.models.functionXY
|
||||||
|
import space.kscience.plotly.scatter
|
||||||
|
import kotlin.math.PI
|
||||||
|
import kotlin.math.sin
|
||||||
|
|
||||||
|
@OptIn(UnstablePlotlyAPI::class)
|
||||||
|
fun main() {
|
||||||
|
val data = (0..10).map {
|
||||||
|
val x = it.toDouble() / 5 * PI
|
||||||
|
x to sin(x)
|
||||||
|
}
|
||||||
|
|
||||||
|
val polynomial: PiecewisePolynomial<Double> = SplineInterpolator(
|
||||||
|
DoubleField, ::DoubleBuffer
|
||||||
|
).interpolatePolynomials(data)
|
||||||
|
|
||||||
|
val function = polynomial.asFunction(DoubleField, 0.0)
|
||||||
|
|
||||||
|
val cmInterpolate = org.apache.commons.math3.analysis.interpolation.SplineInterpolator().interpolate(
|
||||||
|
data.map { it.first }.toDoubleArray(),
|
||||||
|
data.map { it.second }.toDoubleArray()
|
||||||
|
)
|
||||||
|
|
||||||
|
Plotly.plot {
|
||||||
|
scatter {
|
||||||
|
name = "interpolated"
|
||||||
|
x.numbers = data.map { it.first }
|
||||||
|
y.numbers = x.doubles.map { function(it) }
|
||||||
|
}
|
||||||
|
scatter {
|
||||||
|
name = "original"
|
||||||
|
functionXY(0.0..(2 * PI), 0.1) { sin(it) }
|
||||||
|
}
|
||||||
|
scatter {
|
||||||
|
name = "cm"
|
||||||
|
x.numbers = data.map { it.first }
|
||||||
|
y.numbers = x.doubles.map { cmInterpolate.value(it) }
|
||||||
|
}
|
||||||
|
}.makeFile()
|
||||||
|
}
|
@ -0,0 +1,45 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2018-2021 KMath contributors.
|
||||||
|
* Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package space.kscience.kmath.functions
|
||||||
|
|
||||||
|
import space.kscience.kmath.interpolation.SplineInterpolator
|
||||||
|
import space.kscience.kmath.interpolation.interpolatePolynomials
|
||||||
|
import space.kscience.kmath.operations.DoubleField
|
||||||
|
import space.kscience.kmath.real.map
|
||||||
|
import space.kscience.kmath.real.step
|
||||||
|
import space.kscience.plotly.Plotly
|
||||||
|
import space.kscience.plotly.UnstablePlotlyAPI
|
||||||
|
import space.kscience.plotly.makeFile
|
||||||
|
import space.kscience.plotly.models.functionXY
|
||||||
|
import space.kscience.plotly.scatter
|
||||||
|
|
||||||
|
@OptIn(UnstablePlotlyAPI::class)
|
||||||
|
fun main() {
|
||||||
|
val function: UnivariateFunction<Double> = { x ->
|
||||||
|
if (x in 30.0..50.0) {
|
||||||
|
1.0
|
||||||
|
} else {
|
||||||
|
0.0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
val xs = 0.0..100.0 step 0.5
|
||||||
|
val ys = xs.map(function)
|
||||||
|
|
||||||
|
val polynomial: PiecewisePolynomial<Double> = SplineInterpolator.double.interpolatePolynomials(xs, ys)
|
||||||
|
|
||||||
|
val polyFunction = polynomial.asFunction(DoubleField, 0.0)
|
||||||
|
|
||||||
|
Plotly.plot {
|
||||||
|
scatter {
|
||||||
|
name = "interpolated"
|
||||||
|
functionXY(25.0..55.0, 0.1) { polyFunction(it) }
|
||||||
|
}
|
||||||
|
scatter {
|
||||||
|
name = "original"
|
||||||
|
functionXY(25.0..55.0, 0.1) { function(it) }
|
||||||
|
}
|
||||||
|
}.makeFile()
|
||||||
|
}
|
@ -1,19 +1,20 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2018-2021 KMath contributors.
|
* Copyright 2018-2021 KMath contributors.
|
||||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
* Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package space.kscience.kmath.functions
|
package space.kscience.kmath.functions
|
||||||
|
|
||||||
|
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.nd.StructureND
|
import space.kscience.kmath.nd.StructureND
|
||||||
import space.kscience.kmath.nd.nd
|
import space.kscience.kmath.nd.withNdAlgebra
|
||||||
import space.kscience.kmath.operations.DoubleField
|
import space.kscience.kmath.operations.algebra
|
||||||
import space.kscience.kmath.operations.invoke
|
import space.kscience.kmath.operations.invoke
|
||||||
|
|
||||||
fun main(): Unit = DoubleField {
|
fun main(): Unit = Double.algebra {
|
||||||
nd(2, 2) {
|
withNdAlgebra(2, 2) {
|
||||||
|
|
||||||
//Produce a diagonal StructureND
|
//Produce a diagonal StructureND
|
||||||
fun diagonal(v: Double) = produce { (i, j) ->
|
fun diagonal(v: Double) = produce { (i, j) ->
|
||||||
@ -21,10 +22,10 @@ fun main(): Unit = DoubleField {
|
|||||||
}
|
}
|
||||||
|
|
||||||
//Define a function in a nd space
|
//Define a function in a nd space
|
||||||
val function: (Double) -> StructureND<Double> = { x: Double -> 3 * number(x).pow(2) + 2 * diagonal(x) + 1 }
|
val function: (Double) -> StructureND<Double> = { x: Double -> 3 * x.pow(2) + 2 * diagonal(x) + 1 }
|
||||||
|
|
||||||
//get the result of the integration
|
//get the result of the integration
|
||||||
val result = integrate(0.0..10.0, function = function)
|
val result = 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)
|
||||||
|
@ -0,0 +1,15 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2018-2021 KMath contributors.
|
||||||
|
* Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package space.kscience.kmath.jafama
|
||||||
|
|
||||||
|
import space.kscience.kmath.operations.invoke
|
||||||
|
|
||||||
|
fun main() {
|
||||||
|
val a = 2.0
|
||||||
|
val b = StrictJafamaDoubleField { exp(a) }
|
||||||
|
println(JafamaDoubleField { b + a })
|
||||||
|
println(StrictJafamaDoubleField { ln(b) })
|
||||||
|
}
|
@ -0,0 +1,34 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2018-2021 KMath contributors.
|
||||||
|
* Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package space.kscience.kmath.linear
|
||||||
|
|
||||||
|
import space.kscience.kmath.operations.algebra
|
||||||
|
import kotlin.random.Random
|
||||||
|
import kotlin.system.measureTimeMillis
|
||||||
|
|
||||||
|
fun main() {
|
||||||
|
val random = Random(12224)
|
||||||
|
val dim = 1000
|
||||||
|
|
||||||
|
//creating invertible matrix
|
||||||
|
val matrix1 = Double.algebra.linearSpace.buildMatrix(dim, dim) { i, j ->
|
||||||
|
if (i <= j) random.nextDouble() else 0.0
|
||||||
|
}
|
||||||
|
val matrix2 = Double.algebra.linearSpace.buildMatrix(dim, dim) { i, j ->
|
||||||
|
if (i <= j) random.nextDouble() else 0.0
|
||||||
|
}
|
||||||
|
|
||||||
|
val time = measureTimeMillis {
|
||||||
|
with(Double.algebra.linearSpace) {
|
||||||
|
repeat(10) {
|
||||||
|
matrix1 dot matrix2
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
println(time)
|
||||||
|
|
||||||
|
}
|
@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2018-2021 KMath contributors.
|
* Copyright 2018-2021 KMath contributors.
|
||||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
* Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package space.kscience.kmath.linear
|
package space.kscience.kmath.linear
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2018-2021 KMath contributors.
|
* Copyright 2018-2021 KMath contributors.
|
||||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
* Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package space.kscience.kmath.operations
|
package space.kscience.kmath.operations
|
||||||
|
@ -1,29 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2018-2021 KMath contributors.
|
|
||||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package space.kscience.kmath.operations
|
|
||||||
|
|
||||||
import space.kscience.kmath.complex.Complex
|
|
||||||
import space.kscience.kmath.complex.complex
|
|
||||||
import space.kscience.kmath.nd.AlgebraND
|
|
||||||
|
|
||||||
fun main() {
|
|
||||||
// 2d element
|
|
||||||
val element = AlgebraND.complex(2, 2).produce { (i, j) ->
|
|
||||||
Complex(i.toDouble() - j.toDouble(), i.toDouble() + j.toDouble())
|
|
||||||
}
|
|
||||||
println(element)
|
|
||||||
|
|
||||||
// 1d element operation
|
|
||||||
val result = with(AlgebraND.complex(8)) {
|
|
||||||
val a = produce { (it) -> i * it - it.toDouble() }
|
|
||||||
val b = 3
|
|
||||||
val c = Complex(1.0, 1.0)
|
|
||||||
|
|
||||||
(a pow b) + c
|
|
||||||
}
|
|
||||||
|
|
||||||
println(result)
|
|
||||||
}
|
|
@ -0,0 +1,41 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2018-2021 KMath contributors.
|
||||||
|
* Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package space.kscience.kmath.operations
|
||||||
|
|
||||||
|
import space.kscience.kmath.complex.Complex
|
||||||
|
import space.kscience.kmath.complex.algebra
|
||||||
|
import space.kscience.kmath.complex.bufferAlgebra
|
||||||
|
import space.kscience.kmath.complex.ndAlgebra
|
||||||
|
import space.kscience.kmath.nd.BufferND
|
||||||
|
import space.kscience.kmath.nd.StructureND
|
||||||
|
|
||||||
|
fun main() = Complex.algebra {
|
||||||
|
val complex = 2 + 2 * i
|
||||||
|
println(complex * 8 - 5 * i)
|
||||||
|
|
||||||
|
//flat buffer
|
||||||
|
val buffer = bufferAlgebra(8).run {
|
||||||
|
buffer { Complex(it, -it) }.map { Complex(it.im, it.re) }
|
||||||
|
}
|
||||||
|
println(buffer)
|
||||||
|
|
||||||
|
|
||||||
|
// 2d element
|
||||||
|
val element: BufferND<Complex> = ndAlgebra(2, 2).produce { (i, j) ->
|
||||||
|
Complex(i - j, i + j)
|
||||||
|
}
|
||||||
|
println(element)
|
||||||
|
|
||||||
|
// 1d element operation
|
||||||
|
val result: StructureND<Complex> = ndAlgebra(8).run {
|
||||||
|
val a = produce { (it) -> i * it - it.toDouble() }
|
||||||
|
val b = 3
|
||||||
|
val c = Complex(1.0, 1.0)
|
||||||
|
|
||||||
|
(a pow b) + c
|
||||||
|
}
|
||||||
|
println(result)
|
||||||
|
}
|
@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2018-2021 KMath contributors.
|
* Copyright 2018-2021 KMath contributors.
|
||||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
* Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package space.kscience.kmath.stat
|
package space.kscience.kmath.stat
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2018-2021 KMath contributors.
|
* Copyright 2018-2021 KMath contributors.
|
||||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
* Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package space.kscience.kmath.stat
|
package space.kscience.kmath.stat
|
||||||
@ -10,9 +10,6 @@ import space.kscience.kmath.chains.Chain
|
|||||||
import space.kscience.kmath.chains.collectWithState
|
import space.kscience.kmath.chains.collectWithState
|
||||||
import space.kscience.kmath.distributions.NormalDistribution
|
import space.kscience.kmath.distributions.NormalDistribution
|
||||||
|
|
||||||
/**
|
|
||||||
* The state of distribution averager.
|
|
||||||
*/
|
|
||||||
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)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2018-2021 KMath contributors.
|
* Copyright 2018-2021 KMath contributors.
|
||||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
* Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@file:Suppress("unused")
|
@file:Suppress("unused")
|
||||||
@ -9,10 +9,10 @@ package space.kscience.kmath.structures
|
|||||||
|
|
||||||
import space.kscience.kmath.complex.*
|
import space.kscience.kmath.complex.*
|
||||||
import space.kscience.kmath.linear.transpose
|
import space.kscience.kmath.linear.transpose
|
||||||
import space.kscience.kmath.nd.AlgebraND
|
|
||||||
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.real
|
import space.kscience.kmath.nd.ndAlgebra
|
||||||
|
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
|
||||||
|
|
||||||
@ -20,8 +20,8 @@ fun main() {
|
|||||||
val dim = 1000
|
val dim = 1000
|
||||||
val n = 1000
|
val n = 1000
|
||||||
|
|
||||||
val realField = AlgebraND.real(dim, dim)
|
val realField = DoubleField.ndAlgebra(dim, dim)
|
||||||
val complexField: ComplexFieldND = AlgebraND.complex(dim, dim)
|
val complexField: ComplexFieldND = ComplexField.ndAlgebra(dim, dim)
|
||||||
|
|
||||||
val realTime = measureTimeMillis {
|
val realTime = measureTimeMillis {
|
||||||
realField {
|
realField {
|
||||||
@ -49,7 +49,7 @@ fun main() {
|
|||||||
fun complexExample() {
|
fun complexExample() {
|
||||||
//Create a context for 2-d structure with complex values
|
//Create a context for 2-d structure with complex values
|
||||||
ComplexField {
|
ComplexField {
|
||||||
nd(4, 8) {
|
withNdAlgebra(4, 8) {
|
||||||
//a constant real-valued structure
|
//a constant real-valued structure
|
||||||
val x = one * 2.5
|
val x = one * 2.5
|
||||||
operator fun Number.plus(other: Complex) = Complex(this.toDouble() + other.re, other.im)
|
operator fun Number.plus(other: Complex) = Complex(this.toDouble() + other.re, other.im)
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2018-2021 KMath contributors.
|
* Copyright 2018-2021 KMath contributors.
|
||||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
* Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package space.kscience.kmath.structures
|
package space.kscience.kmath.structures
|
||||||
@ -8,7 +8,9 @@ package space.kscience.kmath.structures
|
|||||||
import kotlinx.coroutines.DelicateCoroutinesApi
|
import kotlinx.coroutines.DelicateCoroutinesApi
|
||||||
import kotlinx.coroutines.GlobalScope
|
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.StructureND
|
||||||
|
import space.kscience.kmath.nd.autoNdAlgebra
|
||||||
|
import space.kscience.kmath.nd.ndAlgebra
|
||||||
import space.kscience.kmath.nd4j.Nd4jArrayField
|
import space.kscience.kmath.nd4j.Nd4jArrayField
|
||||||
import space.kscience.kmath.operations.DoubleField
|
import space.kscience.kmath.operations.DoubleField
|
||||||
import space.kscience.kmath.operations.invoke
|
import space.kscience.kmath.operations.invoke
|
||||||
@ -31,17 +33,17 @@ fun main() {
|
|||||||
val n = 1000
|
val n = 1000
|
||||||
|
|
||||||
// automatically build context most suited for given type.
|
// automatically build context most suited for given type.
|
||||||
val autoField = AlgebraND.auto(DoubleField, dim, dim)
|
val autoField = DoubleField.autoNdAlgebra(dim, dim)
|
||||||
// specialized nd-field for Double. It works as generic Double field as well
|
// specialized nd-field for Double. It works as generic Double field as well.
|
||||||
val realField = AlgebraND.real(dim, dim)
|
val realField = DoubleField.ndAlgebra(dim, dim)
|
||||||
//A generic boxing field. It should be used for objects, not primitives.
|
//A generic boxing field. It should be used for objects, not primitives.
|
||||||
val boxingField = AlgebraND.field(DoubleField, Buffer.Companion::boxing, dim, dim)
|
val boxingField = DoubleField.ndAlgebra(Buffer.Companion::boxing, dim, dim)
|
||||||
// Nd4j specialized field.
|
// Nd4j specialized field.
|
||||||
val nd4jField = Nd4jArrayField.real(dim, dim)
|
val nd4jField = Nd4jArrayField.real(dim, dim)
|
||||||
//viktor field
|
//viktor field
|
||||||
val viktorField = ViktorNDField(dim, dim)
|
val viktorField = ViktorNDField(dim, dim)
|
||||||
//parallel processing based on Java Streams
|
//parallel processing based on Java Streams
|
||||||
val parallelField = AlgebraND.realWithStream(dim, dim)
|
val parallelField = DoubleField.ndStreaming(dim, dim)
|
||||||
|
|
||||||
measureAndPrint("Boxing addition") {
|
measureAndPrint("Boxing addition") {
|
||||||
boxingField {
|
boxingField {
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2018-2021 KMath contributors.
|
* Copyright 2018-2021 KMath contributors.
|
||||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
* Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package space.kscience.kmath.structures
|
package space.kscience.kmath.structures
|
||||||
@ -105,4 +105,4 @@ class StreamDoubleFieldND(override val shape: IntArray) : FieldND<Double, Double
|
|||||||
override fun atanh(arg: StructureND<Double>): BufferND<Double> = arg.map { atanh(it) }
|
override fun atanh(arg: StructureND<Double>): BufferND<Double> = arg.map { atanh(it) }
|
||||||
}
|
}
|
||||||
|
|
||||||
fun AlgebraND.Companion.realWithStream(vararg shape: Int): StreamDoubleFieldND = StreamDoubleFieldND(shape)
|
fun DoubleField.ndStreaming(vararg shape: Int): StreamDoubleFieldND = StreamDoubleFieldND(shape)
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2018-2021 KMath contributors.
|
* Copyright 2018-2021 KMath contributors.
|
||||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
* Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package space.kscience.kmath.structures
|
package space.kscience.kmath.structures
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2018-2021 KMath contributors.
|
* Copyright 2018-2021 KMath contributors.
|
||||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
* Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package space.kscience.kmath.structures
|
package space.kscience.kmath.structures
|
||||||
|
@ -0,0 +1,22 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2018-2021 KMath contributors.
|
||||||
|
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package space.kscience.kmath.structures
|
||||||
|
|
||||||
|
import space.kscience.kmath.operations.DoubleField
|
||||||
|
import space.kscience.kmath.operations.buffer
|
||||||
|
import space.kscience.kmath.operations.bufferAlgebra
|
||||||
|
|
||||||
|
inline fun <reified R : Any> MutableBuffer.Companion.same(
|
||||||
|
n: Int,
|
||||||
|
value: R
|
||||||
|
): MutableBuffer<R> = auto(n) { value }
|
||||||
|
|
||||||
|
|
||||||
|
fun main() {
|
||||||
|
with(DoubleField.bufferAlgebra(5)) {
|
||||||
|
println(number(2.0) + buffer(1, 2, 3, 4, 5))
|
||||||
|
}
|
||||||
|
}
|
@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2018-2021 KMath contributors.
|
* Copyright 2018-2021 KMath contributors.
|
||||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
* Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package space.kscience.kmath.structures
|
package space.kscience.kmath.structures
|
||||||
@ -19,7 +19,7 @@ private fun DMatrixContext<Double, *>.simple() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private object D5 : Dimension {
|
private object D5 : Dimension {
|
||||||
override val dim: UInt = 5u
|
override val dim: Int = 5
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun DMatrixContext<Double, *>.custom() {
|
private fun DMatrixContext<Double, *>.custom() {
|
||||||
|
@ -1,46 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2018-2021 KMath contributors.
|
|
||||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package space.kscience.kmath.tensors
|
|
||||||
|
|
||||||
import space.kscience.kmath.operations.invoke
|
|
||||||
import space.kscience.kmath.tensors.core.BroadcastDoubleTensorAlgebra
|
|
||||||
|
|
||||||
|
|
||||||
// Dataset normalization
|
|
||||||
|
|
||||||
fun main() {
|
|
||||||
|
|
||||||
// work in context with broadcast methods
|
|
||||||
BroadcastDoubleTensorAlgebra {
|
|
||||||
// take dataset of 5-element vectors from normal distribution
|
|
||||||
val dataset = randomNormal(intArrayOf(100, 5)) * 1.5 // all elements from N(0, 1.5)
|
|
||||||
|
|
||||||
dataset += fromArray(
|
|
||||||
intArrayOf(5),
|
|
||||||
doubleArrayOf(0.0, 1.0, 1.5, 3.0, 5.0) // rows means
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
// find out mean and standard deviation of each column
|
|
||||||
val mean = dataset.mean(0, false)
|
|
||||||
val std = dataset.std(0, false)
|
|
||||||
|
|
||||||
println("Mean:\n$mean")
|
|
||||||
println("Standard deviation:\n$std")
|
|
||||||
|
|
||||||
// also we can calculate other statistic as minimum and maximum of rows
|
|
||||||
println("Minimum:\n${dataset.min(0, false)}")
|
|
||||||
println("Maximum:\n${dataset.max(0, false)}")
|
|
||||||
|
|
||||||
// now we can scale dataset with mean normalization
|
|
||||||
val datasetScaled = (dataset - mean) / std
|
|
||||||
|
|
||||||
// find out mean and std of scaled dataset
|
|
||||||
|
|
||||||
println("Mean of scaled:\n${datasetScaled.mean(0, false)}")
|
|
||||||
println("Mean of scaled:\n${datasetScaled.std(0, false)}")
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,97 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2018-2021 KMath contributors.
|
|
||||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package space.kscience.kmath.tensors
|
|
||||||
|
|
||||||
import space.kscience.kmath.operations.invoke
|
|
||||||
import space.kscience.kmath.tensors.core.DoubleTensor
|
|
||||||
import space.kscience.kmath.tensors.core.BroadcastDoubleTensorAlgebra
|
|
||||||
|
|
||||||
// solving linear system with LUP decomposition
|
|
||||||
|
|
||||||
fun main () {
|
|
||||||
|
|
||||||
// work in context with linear operations
|
|
||||||
BroadcastDoubleTensorAlgebra {
|
|
||||||
|
|
||||||
// set true value of x
|
|
||||||
val trueX = fromArray(
|
|
||||||
intArrayOf(4),
|
|
||||||
doubleArrayOf(-2.0, 1.5, 6.8, -2.4)
|
|
||||||
)
|
|
||||||
|
|
||||||
// and A matrix
|
|
||||||
val a = fromArray(
|
|
||||||
intArrayOf(4, 4),
|
|
||||||
doubleArrayOf(
|
|
||||||
0.5, 10.5, 4.5, 1.0,
|
|
||||||
8.5, 0.9, 12.8, 0.1,
|
|
||||||
5.56, 9.19, 7.62, 5.45,
|
|
||||||
1.0, 2.0, -3.0, -2.5
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
||||||
// calculate y value
|
|
||||||
val b = a dot trueX
|
|
||||||
|
|
||||||
// check out A and b
|
|
||||||
println("A:\n$a")
|
|
||||||
println("b:\n$b")
|
|
||||||
|
|
||||||
// solve `Ax = b` system using LUP decomposition
|
|
||||||
|
|
||||||
// get P, L, U such that PA = LU
|
|
||||||
val (p, l, u) = a.lu()
|
|
||||||
|
|
||||||
// check that P is permutation matrix
|
|
||||||
println("P:\n$p")
|
|
||||||
// L is lower triangular matrix and U is upper triangular matrix
|
|
||||||
println("L:\n$l")
|
|
||||||
println("U:\n$u")
|
|
||||||
// and PA = LU
|
|
||||||
println("PA:\n${p dot a}")
|
|
||||||
println("LU:\n${l dot u}")
|
|
||||||
|
|
||||||
/* Ax = b;
|
|
||||||
PAx = Pb;
|
|
||||||
LUx = Pb;
|
|
||||||
let y = Ux, then
|
|
||||||
Ly = Pb -- this system can be easily solved, since the matrix L is lower triangular;
|
|
||||||
Ux = y can be solved the same way, since the matrix L is upper triangular
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// this function returns solution x of a system lx = b, l should be lower triangular
|
|
||||||
fun solveLT(l: DoubleTensor, b: DoubleTensor): DoubleTensor {
|
|
||||||
val n = l.shape[0]
|
|
||||||
val x = zeros(intArrayOf(n))
|
|
||||||
for (i in 0 until n){
|
|
||||||
x[intArrayOf(i)] = (b[intArrayOf(i)] - l[i].dot(x).value()) / l[intArrayOf(i, i)]
|
|
||||||
}
|
|
||||||
return x
|
|
||||||
}
|
|
||||||
|
|
||||||
val y = solveLT(l, p dot b)
|
|
||||||
|
|
||||||
// solveLT(l, b) function can be easily adapted for upper triangular matrix by the permutation matrix revMat
|
|
||||||
// create it by placing ones on side diagonal
|
|
||||||
val revMat = u.zeroesLike()
|
|
||||||
val n = revMat.shape[0]
|
|
||||||
for (i in 0 until n) {
|
|
||||||
revMat[intArrayOf(i, n - 1 - i)] = 1.0
|
|
||||||
}
|
|
||||||
|
|
||||||
// solution of system ux = b, u should be upper triangular
|
|
||||||
fun solveUT(u: DoubleTensor, b: DoubleTensor): DoubleTensor = revMat dot solveLT(
|
|
||||||
revMat dot u dot revMat, revMat dot b
|
|
||||||
)
|
|
||||||
|
|
||||||
val x = solveUT(u, y)
|
|
||||||
|
|
||||||
println("True x:\n$trueX")
|
|
||||||
println("x founded with LU method:\n$x")
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2018-2021 KMath contributors.
|
* Copyright 2018-2021 KMath contributors.
|
||||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
* Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package space.kscience.kmath.tensors
|
package space.kscience.kmath.tensors
|
||||||
|
@ -1,78 +1,74 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2018-2021 KMath contributors.
|
* Copyright 2018-2021 KMath contributors.
|
||||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
* Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package space.kscience.kmath.tensors
|
package space.kscience.kmath.tensors
|
||||||
|
|
||||||
import space.kscience.kmath.operations.invoke
|
import space.kscience.kmath.tensors.core.tensorAlgebra
|
||||||
import space.kscience.kmath.tensors.core.BroadcastDoubleTensorAlgebra
|
import space.kscience.kmath.tensors.core.withBroadcast
|
||||||
|
|
||||||
|
|
||||||
// simple PCA
|
// simple PCA
|
||||||
|
|
||||||
fun main(){
|
fun main(): Unit = Double.tensorAlgebra.withBroadcast { // work in context with broadcast methods
|
||||||
val seed = 100500L
|
val seed = 100500L
|
||||||
|
|
||||||
// work in context with broadcast methods
|
// assume x is range from 0 until 10
|
||||||
BroadcastDoubleTensorAlgebra {
|
val x = fromArray(
|
||||||
|
intArrayOf(10),
|
||||||
|
DoubleArray(10) { it.toDouble() }
|
||||||
|
)
|
||||||
|
|
||||||
// assume x is range from 0 until 10
|
// take y dependent on x with noise
|
||||||
val x = fromArray(
|
val y = 2.0 * x + (3.0 + x.randomNormalLike(seed) * 1.5)
|
||||||
intArrayOf(10),
|
|
||||||
(0 until 10).toList().map { it.toDouble() }.toDoubleArray()
|
|
||||||
)
|
|
||||||
|
|
||||||
// take y dependent on x with noise
|
println("x:\n$x")
|
||||||
val y = 2.0 * x + (3.0 + x.randomNormalLike(seed) * 1.5)
|
println("y:\n$y")
|
||||||
|
|
||||||
println("x:\n$x")
|
// stack them into single dataset
|
||||||
println("y:\n$y")
|
val dataset = stack(listOf(x, y)).transpose()
|
||||||
|
|
||||||
// stack them into single dataset
|
// normalize both x and y
|
||||||
val dataset = stack(listOf(x, y)).transpose()
|
val xMean = x.mean()
|
||||||
|
val yMean = y.mean()
|
||||||
|
|
||||||
// normalize both x and y
|
val xStd = x.std()
|
||||||
val xMean = x.mean()
|
val yStd = y.std()
|
||||||
val yMean = y.mean()
|
|
||||||
|
|
||||||
val xStd = x.std()
|
val xScaled = (x - xMean) / xStd
|
||||||
val yStd = y.std()
|
val yScaled = (y - yMean) / yStd
|
||||||
|
|
||||||
val xScaled = (x - xMean) / xStd
|
// save means ans standard deviations for further recovery
|
||||||
val yScaled = (y - yMean) / yStd
|
val mean = fromArray(
|
||||||
|
intArrayOf(2),
|
||||||
|
doubleArrayOf(xMean, yMean)
|
||||||
|
)
|
||||||
|
println("Means:\n$mean")
|
||||||
|
|
||||||
// save means ans standard deviations for further recovery
|
val std = fromArray(
|
||||||
val mean = fromArray(
|
intArrayOf(2),
|
||||||
intArrayOf(2),
|
doubleArrayOf(xStd, yStd)
|
||||||
doubleArrayOf(xMean, yMean)
|
)
|
||||||
)
|
println("Standard deviations:\n$std")
|
||||||
println("Means:\n$mean")
|
|
||||||
|
|
||||||
val std = fromArray(
|
// calculate the covariance matrix of scaled x and y
|
||||||
intArrayOf(2),
|
val covMatrix = cov(listOf(xScaled, yScaled))
|
||||||
doubleArrayOf(xStd, yStd)
|
println("Covariance matrix:\n$covMatrix")
|
||||||
)
|
|
||||||
println("Standard deviations:\n$std")
|
|
||||||
|
|
||||||
// calculate the covariance matrix of scaled x and y
|
// and find out eigenvector of it
|
||||||
val covMatrix = cov(listOf(xScaled, yScaled))
|
val (_, evecs) = covMatrix.symEig()
|
||||||
println("Covariance matrix:\n$covMatrix")
|
val v = evecs[0]
|
||||||
|
println("Eigenvector:\n$v")
|
||||||
|
|
||||||
// and find out eigenvector of it
|
// reduce dimension of dataset
|
||||||
val (_, evecs) = covMatrix.symEig()
|
val datasetReduced = v dot stack(listOf(xScaled, yScaled))
|
||||||
val v = evecs[0]
|
println("Reduced data:\n$datasetReduced")
|
||||||
println("Eigenvector:\n$v")
|
|
||||||
|
|
||||||
// reduce dimension of dataset
|
// we can restore original data from reduced data;
|
||||||
val datasetReduced = v dot stack(listOf(xScaled, yScaled))
|
// for example, find 7th element of dataset.
|
||||||
println("Reduced data:\n$datasetReduced")
|
val n = 7
|
||||||
|
val restored = (datasetReduced[n] dot v.view(intArrayOf(1, 2))) * std + mean
|
||||||
// we can restore original data from reduced data.
|
println("Original value:\n${dataset[n]}")
|
||||||
// for example, find 7th element of dataset
|
println("Restored value:\n$restored")
|
||||||
val n = 7
|
|
||||||
val restored = (datasetReduced[n] dot v.view(intArrayOf(1, 2))) * std + mean
|
|
||||||
println("Original value:\n${dataset[n]}")
|
|
||||||
println("Restored value:\n$restored")
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,42 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2018-2021 KMath contributors.
|
||||||
|
* Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package space.kscience.kmath.tensors
|
||||||
|
|
||||||
|
import space.kscience.kmath.tensors.core.tensorAlgebra
|
||||||
|
import space.kscience.kmath.tensors.core.withBroadcast
|
||||||
|
|
||||||
|
|
||||||
|
// Dataset normalization
|
||||||
|
|
||||||
|
fun main() = Double.tensorAlgebra.withBroadcast { // work in context with broadcast methods
|
||||||
|
// take dataset of 5-element vectors from normal distribution
|
||||||
|
val dataset = randomNormal(intArrayOf(100, 5)) * 1.5 // all elements from N(0, 1.5)
|
||||||
|
|
||||||
|
dataset += fromArray(
|
||||||
|
intArrayOf(5),
|
||||||
|
doubleArrayOf(0.0, 1.0, 1.5, 3.0, 5.0) // row means
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
// find out mean and standard deviation of each column
|
||||||
|
val mean = dataset.mean(0, false)
|
||||||
|
val std = dataset.std(0, false)
|
||||||
|
|
||||||
|
println("Mean:\n$mean")
|
||||||
|
println("Standard deviation:\n$std")
|
||||||
|
|
||||||
|
// also, we can calculate other statistic as minimum and maximum of rows
|
||||||
|
println("Minimum:\n${dataset.min(0, false)}")
|
||||||
|
println("Maximum:\n${dataset.max(0, false)}")
|
||||||
|
|
||||||
|
// now we can scale dataset with mean normalization
|
||||||
|
val datasetScaled = (dataset - mean) / std
|
||||||
|
|
||||||
|
// find out mean and std of scaled dataset
|
||||||
|
|
||||||
|
println("Mean of scaled:\n${datasetScaled.mean(0, false)}")
|
||||||
|
println("Mean of scaled:\n${datasetScaled.std(0, false)}")
|
||||||
|
}
|
@ -0,0 +1,93 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2018-2021 KMath contributors.
|
||||||
|
* Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package space.kscience.kmath.tensors
|
||||||
|
|
||||||
|
import space.kscience.kmath.tensors.core.DoubleTensor
|
||||||
|
import space.kscience.kmath.tensors.core.tensorAlgebra
|
||||||
|
import space.kscience.kmath.tensors.core.withBroadcast
|
||||||
|
|
||||||
|
// solving linear system with LUP decomposition
|
||||||
|
|
||||||
|
fun main() = Double.tensorAlgebra.withBroadcast {// work in context with linear operations
|
||||||
|
|
||||||
|
// set true value of x
|
||||||
|
val trueX = fromArray(
|
||||||
|
intArrayOf(4),
|
||||||
|
doubleArrayOf(-2.0, 1.5, 6.8, -2.4)
|
||||||
|
)
|
||||||
|
|
||||||
|
// and A matrix
|
||||||
|
val a = fromArray(
|
||||||
|
intArrayOf(4, 4),
|
||||||
|
doubleArrayOf(
|
||||||
|
0.5, 10.5, 4.5, 1.0,
|
||||||
|
8.5, 0.9, 12.8, 0.1,
|
||||||
|
5.56, 9.19, 7.62, 5.45,
|
||||||
|
1.0, 2.0, -3.0, -2.5
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
// calculate y value
|
||||||
|
val b = a dot trueX
|
||||||
|
|
||||||
|
// check out A and b
|
||||||
|
println("A:\n$a")
|
||||||
|
println("b:\n$b")
|
||||||
|
|
||||||
|
// solve `Ax = b` system using LUP decomposition
|
||||||
|
|
||||||
|
// get P, L, U such that PA = LU
|
||||||
|
val (p, l, u) = a.lu()
|
||||||
|
|
||||||
|
// check P is permutation matrix
|
||||||
|
println("P:\n$p")
|
||||||
|
// L is lower triangular matrix and U is upper triangular matrix
|
||||||
|
println("L:\n$l")
|
||||||
|
println("U:\n$u")
|
||||||
|
// and PA = LU
|
||||||
|
println("PA:\n${p dot a}")
|
||||||
|
println("LU:\n${l dot u}")
|
||||||
|
|
||||||
|
/* Ax = b;
|
||||||
|
PAx = Pb;
|
||||||
|
LUx = Pb;
|
||||||
|
let y = Ux, then
|
||||||
|
Ly = Pb -- this system can be easily solved, since the matrix L is lower triangular;
|
||||||
|
Ux = y can be solved the same way, since the matrix L is upper triangular
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// this function returns solution x of a system lx = b, l should be lower triangular
|
||||||
|
fun solveLT(l: DoubleTensor, b: DoubleTensor): DoubleTensor {
|
||||||
|
val n = l.shape[0]
|
||||||
|
val x = zeros(intArrayOf(n))
|
||||||
|
for (i in 0 until n) {
|
||||||
|
x[intArrayOf(i)] = (b[intArrayOf(i)] - l[i].dot(x).value()) / l[intArrayOf(i, i)]
|
||||||
|
}
|
||||||
|
return x
|
||||||
|
}
|
||||||
|
|
||||||
|
val y = solveLT(l, p dot b)
|
||||||
|
|
||||||
|
// solveLT(l, b) function can be easily adapted for upper triangular matrix by the permutation matrix revMat
|
||||||
|
// create it by placing ones on side diagonal
|
||||||
|
val revMat = u.zeroesLike()
|
||||||
|
val n = revMat.shape[0]
|
||||||
|
for (i in 0 until n) {
|
||||||
|
revMat[intArrayOf(i, n - 1 - i)] = 1.0
|
||||||
|
}
|
||||||
|
|
||||||
|
// solution of system ux = b, u should be upper triangular
|
||||||
|
fun solveUT(u: DoubleTensor, b: DoubleTensor): DoubleTensor = revMat dot solveLT(
|
||||||
|
revMat dot u dot revMat, revMat dot b
|
||||||
|
)
|
||||||
|
|
||||||
|
val x = solveUT(u, y)
|
||||||
|
|
||||||
|
println("True x:\n$trueX")
|
||||||
|
println("x founded with LU method:\n$x")
|
||||||
|
}
|
@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2018-2021 KMath contributors.
|
* Copyright 2018-2021 KMath contributors.
|
||||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
* Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package space.kscience.kmath.tensors
|
package space.kscience.kmath.tensors
|
||||||
@ -25,7 +25,7 @@ interface Layer {
|
|||||||
// activation layer
|
// activation layer
|
||||||
open class Activation(
|
open class Activation(
|
||||||
val activation: (DoubleTensor) -> DoubleTensor,
|
val activation: (DoubleTensor) -> DoubleTensor,
|
||||||
val activationDer: (DoubleTensor) -> DoubleTensor
|
val activationDer: (DoubleTensor) -> DoubleTensor,
|
||||||
) : Layer {
|
) : Layer {
|
||||||
override fun forward(input: DoubleTensor): DoubleTensor {
|
override fun forward(input: DoubleTensor): DoubleTensor {
|
||||||
return activation(input)
|
return activation(input)
|
||||||
@ -62,7 +62,7 @@ class Sigmoid : Activation(::sigmoid, ::sigmoidDer)
|
|||||||
class Dense(
|
class Dense(
|
||||||
private val inputUnits: Int,
|
private val inputUnits: Int,
|
||||||
private val outputUnits: Int,
|
private val outputUnits: Int,
|
||||||
private val learningRate: Double = 0.1
|
private val learningRate: Double = 0.1,
|
||||||
) : Layer {
|
) : Layer {
|
||||||
|
|
||||||
private val weights: DoubleTensor = DoubleTensorAlgebra {
|
private val weights: DoubleTensor = DoubleTensorAlgebra {
|
||||||
@ -74,8 +74,8 @@ class Dense(
|
|||||||
|
|
||||||
private val bias: DoubleTensor = DoubleTensorAlgebra { zeros(intArrayOf(outputUnits)) }
|
private val bias: DoubleTensor = DoubleTensorAlgebra { zeros(intArrayOf(outputUnits)) }
|
||||||
|
|
||||||
override fun forward(input: DoubleTensor): DoubleTensor {
|
override fun forward(input: DoubleTensor): DoubleTensor = BroadcastDoubleTensorAlgebra {
|
||||||
return BroadcastDoubleTensorAlgebra { (input dot weights) + bias }
|
(input dot weights) + bias
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun backward(input: DoubleTensor, outputError: DoubleTensor): DoubleTensor = DoubleTensorAlgebra {
|
override fun backward(input: DoubleTensor, outputError: DoubleTensor): DoubleTensor = DoubleTensorAlgebra {
|
||||||
@ -116,7 +116,7 @@ class NeuralNetwork(private val layers: List<Layer>) {
|
|||||||
onesForAnswers[intArrayOf(index, label)] = 1.0
|
onesForAnswers[intArrayOf(index, label)] = 1.0
|
||||||
}
|
}
|
||||||
|
|
||||||
val softmaxValue = yPred.exp() / yPred.exp().sum(dim = 1, keepDim = true)
|
val softmaxValue = yPred.exp() / yPred.exp().sum(dim = 1, keepDim = true)
|
||||||
|
|
||||||
(-onesForAnswers + softmaxValue) / (yPred.shape[0].toDouble())
|
(-onesForAnswers + softmaxValue) / (yPred.shape[0].toDouble())
|
||||||
}
|
}
|
||||||
@ -175,67 +175,65 @@ class NeuralNetwork(private val layers: List<Layer>) {
|
|||||||
|
|
||||||
|
|
||||||
@OptIn(ExperimentalStdlibApi::class)
|
@OptIn(ExperimentalStdlibApi::class)
|
||||||
fun main() {
|
fun main() = BroadcastDoubleTensorAlgebra {
|
||||||
BroadcastDoubleTensorAlgebra {
|
val features = 5
|
||||||
val features = 5
|
val sampleSize = 250
|
||||||
val sampleSize = 250
|
val trainSize = 180
|
||||||
val trainSize = 180
|
//val testSize = sampleSize - trainSize
|
||||||
//val testSize = sampleSize - trainSize
|
|
||||||
|
|
||||||
// take sample of features from normal distribution
|
// take sample of features from normal distribution
|
||||||
val x = randomNormal(intArrayOf(sampleSize, features), seed) * 2.5
|
val x = randomNormal(intArrayOf(sampleSize, features), seed) * 2.5
|
||||||
|
|
||||||
x += fromArray(
|
x += fromArray(
|
||||||
intArrayOf(5),
|
intArrayOf(5),
|
||||||
doubleArrayOf(0.0, -1.0, -2.5, -3.0, 5.5) // rows means
|
doubleArrayOf(0.0, -1.0, -2.5, -3.0, 5.5) // row means
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
// define class like '1' if the sum of features > 0 and '0' otherwise
|
// define class like '1' if the sum of features > 0 and '0' otherwise
|
||||||
val y = fromArray(
|
val y = fromArray(
|
||||||
intArrayOf(sampleSize, 1),
|
intArrayOf(sampleSize, 1),
|
||||||
DoubleArray(sampleSize) { i ->
|
DoubleArray(sampleSize) { i ->
|
||||||
if (x[i].sum() > 0.0) {
|
if (x[i].sum() > 0.0) {
|
||||||
1.0
|
1.0
|
||||||
} else {
|
} else {
|
||||||
0.0
|
0.0
|
||||||
}
|
|
||||||
}
|
}
|
||||||
)
|
|
||||||
|
|
||||||
// split train ans test
|
|
||||||
val trainIndices = (0 until trainSize).toList().toIntArray()
|
|
||||||
val testIndices = (trainSize until sampleSize).toList().toIntArray()
|
|
||||||
|
|
||||||
val xTrain = x.rowsByIndices(trainIndices)
|
|
||||||
val yTrain = y.rowsByIndices(trainIndices)
|
|
||||||
|
|
||||||
val xTest = x.rowsByIndices(testIndices)
|
|
||||||
val yTest = y.rowsByIndices(testIndices)
|
|
||||||
|
|
||||||
// build model
|
|
||||||
val layers = buildList {
|
|
||||||
add(Dense(features, 64))
|
|
||||||
add(ReLU())
|
|
||||||
add(Dense(64, 16))
|
|
||||||
add(ReLU())
|
|
||||||
add(Dense(16, 2))
|
|
||||||
add(Sigmoid())
|
|
||||||
}
|
}
|
||||||
val model = NeuralNetwork(layers)
|
)
|
||||||
|
|
||||||
// fit it with train data
|
// split train ans test
|
||||||
model.fit(xTrain, yTrain, batchSize = 20, epochs = 10)
|
val trainIndices = (0 until trainSize).toList().toIntArray()
|
||||||
|
val testIndices = (trainSize until sampleSize).toList().toIntArray()
|
||||||
|
|
||||||
// make prediction
|
val xTrain = x.rowsByIndices(trainIndices)
|
||||||
val prediction = model.predict(xTest)
|
val yTrain = y.rowsByIndices(trainIndices)
|
||||||
|
|
||||||
// process raw prediction via argMax
|
val xTest = x.rowsByIndices(testIndices)
|
||||||
val predictionLabels = prediction.argMax(1, true)
|
val yTest = y.rowsByIndices(testIndices)
|
||||||
|
|
||||||
// find out accuracy
|
|
||||||
val acc = accuracy(yTest, predictionLabels)
|
|
||||||
println("Test accuracy:$acc")
|
|
||||||
|
|
||||||
|
// build model
|
||||||
|
val layers = buildList {
|
||||||
|
add(Dense(features, 64))
|
||||||
|
add(ReLU())
|
||||||
|
add(Dense(64, 16))
|
||||||
|
add(ReLU())
|
||||||
|
add(Dense(16, 2))
|
||||||
|
add(Sigmoid())
|
||||||
}
|
}
|
||||||
|
val model = NeuralNetwork(layers)
|
||||||
|
|
||||||
|
// fit it with train data
|
||||||
|
model.fit(xTrain, yTrain, batchSize = 20, epochs = 10)
|
||||||
|
|
||||||
|
// make prediction
|
||||||
|
val prediction = model.predict(xTest)
|
||||||
|
|
||||||
|
// process raw prediction via argMax
|
||||||
|
val predictionLabels = prediction.argMax(1, true)
|
||||||
|
|
||||||
|
// find out accuracy
|
||||||
|
val acc = accuracy(yTest, predictionLabels)
|
||||||
|
println("Test accuracy:$acc")
|
||||||
|
|
||||||
}
|
}
|
@ -4,10 +4,13 @@
|
|||||||
#
|
#
|
||||||
|
|
||||||
kotlin.code.style=official
|
kotlin.code.style=official
|
||||||
kotlin.mpp.enableGranularSourceSetsMetadata=true
|
|
||||||
kotlin.mpp.stability.nowarn=true
|
kotlin.mpp.stability.nowarn=true
|
||||||
kotlin.native.enableDependencyPropagation=false
|
|
||||||
kotlin.parallel.tasks.in.project=true
|
#kotlin.mpp.enableGranularSourceSetsMetadata=true
|
||||||
|
#kotlin.native.enableDependencyPropagation=false
|
||||||
|
|
||||||
|
kotlin.jupyter.add.scanner=false
|
||||||
|
|
||||||
org.gradle.configureondemand=true
|
org.gradle.configureondemand=true
|
||||||
org.gradle.jvmargs=-XX:MaxMetaspaceSize=2G
|
org.gradle.jvmargs=-XX:MaxMetaspaceSize=2G
|
||||||
org.gradle.parallel=true
|
org.gradle.parallel=true
|
||||||
|
BIN
gradle/wrapper/gradle-wrapper.jar
vendored
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-7.0-bin.zip
|
distributionUrl=https\://services.gradle.org/distributions/gradle-7.1.1-bin.zip
|
||||||
zipStoreBase=GRADLE_USER_HOME
|
zipStoreBase=GRADLE_USER_HOME
|
||||||
zipStorePath=wrapper/dists
|
zipStorePath=wrapper/dists
|
||||||
|
2
gradlew
vendored
@ -72,7 +72,7 @@ case "`uname`" in
|
|||||||
Darwin* )
|
Darwin* )
|
||||||
darwin=true
|
darwin=true
|
||||||
;;
|
;;
|
||||||
MINGW* )
|
MSYS* | MINGW* )
|
||||||
msys=true
|
msys=true
|
||||||
;;
|
;;
|
||||||
NONSTOP* )
|
NONSTOP* )
|
||||||
|
@ -10,7 +10,7 @@ Performance and visualization extensions to MST API.
|
|||||||
|
|
||||||
## Artifact:
|
## Artifact:
|
||||||
|
|
||||||
The Maven coordinates of this project are `space.kscience:kmath-ast:0.3.0-dev-8`.
|
The Maven coordinates of this project are `space.kscience:kmath-ast:0.3.0-dev-14`.
|
||||||
|
|
||||||
**Gradle:**
|
**Gradle:**
|
||||||
```gradle
|
```gradle
|
||||||
@ -20,7 +20,7 @@ repositories {
|
|||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
implementation 'space.kscience:kmath-ast:0.3.0-dev-8'
|
implementation 'space.kscience:kmath-ast:0.3.0-dev-14'
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
**Gradle Kotlin DSL:**
|
**Gradle Kotlin DSL:**
|
||||||
@ -31,7 +31,7 @@ repositories {
|
|||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
implementation("space.kscience:kmath-ast:0.3.0-dev-8")
|
implementation("space.kscience:kmath-ast:0.3.0-dev-14")
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
@ -45,11 +45,12 @@ special implementation of `Expression<T>` with implemented `invoke` function.
|
|||||||
For example, the following builder:
|
For example, the following builder:
|
||||||
|
|
||||||
```kotlin
|
```kotlin
|
||||||
|
import space.kscience.kmath.expressions.Symbol.Companion.x
|
||||||
import space.kscience.kmath.expressions.*
|
import space.kscience.kmath.expressions.*
|
||||||
import space.kscience.kmath.operations.*
|
import space.kscience.kmath.operations.*
|
||||||
import space.kscience.kmath.asm.*
|
import space.kscience.kmath.asm.*
|
||||||
|
|
||||||
MstField { bindSymbol("x") + 2 }.compileToExpression(DoubleField)
|
MstField { x + 2 }.compileToExpression(DoubleField)
|
||||||
```
|
```
|
||||||
|
|
||||||
... leads to generation of bytecode, which can be decompiled to the following Java class:
|
... leads to generation of bytecode, which can be decompiled to the following Java class:
|
||||||
@ -89,11 +90,12 @@ public final class AsmCompiledExpression_45045_0 implements Expression<Double> {
|
|||||||
A similar feature is also available on JS.
|
A similar feature is also available on JS.
|
||||||
|
|
||||||
```kotlin
|
```kotlin
|
||||||
|
import space.kscience.kmath.expressions.Symbol.Companion.x
|
||||||
import space.kscience.kmath.expressions.*
|
import space.kscience.kmath.expressions.*
|
||||||
import space.kscience.kmath.operations.*
|
import space.kscience.kmath.operations.*
|
||||||
import space.kscience.kmath.estree.*
|
import space.kscience.kmath.estree.*
|
||||||
|
|
||||||
MstField { bindSymbol("x") + 2 }.compileToExpression(DoubleField)
|
MstField { x + 2 }.compileToExpression(DoubleField)
|
||||||
```
|
```
|
||||||
|
|
||||||
The code above returns expression implemented with such a JS function:
|
The code above returns expression implemented with such a JS function:
|
||||||
@ -104,15 +106,16 @@ var executable = function (constants, arguments) {
|
|||||||
};
|
};
|
||||||
```
|
```
|
||||||
|
|
||||||
JS also supports very experimental expression optimization with [WebAssembly](https://webassembly.org/) IR generation.
|
JS also supports experimental expression optimization with [WebAssembly](https://webassembly.org/) IR generation.
|
||||||
Currently, only expressions inside `DoubleField` and `IntRing` are supported.
|
Currently, only expressions inside `DoubleField` and `IntRing` are supported.
|
||||||
|
|
||||||
```kotlin
|
```kotlin
|
||||||
|
import space.kscience.kmath.expressions.Symbol.Companion.x
|
||||||
import space.kscience.kmath.expressions.*
|
import space.kscience.kmath.expressions.*
|
||||||
import space.kscience.kmath.operations.*
|
import space.kscience.kmath.operations.*
|
||||||
import space.kscience.kmath.wasm.*
|
import space.kscience.kmath.wasm.*
|
||||||
|
|
||||||
MstField { bindSymbol("x") + 2 }.compileToExpression(DoubleField)
|
MstField { x + 2 }.compileToExpression(DoubleField)
|
||||||
```
|
```
|
||||||
|
|
||||||
An example of emitted Wasm IR in the form of WAT:
|
An example of emitted Wasm IR in the form of WAT:
|
||||||
@ -158,7 +161,10 @@ public fun main() {
|
|||||||
|
|
||||||
Result LaTeX:
|
Result LaTeX:
|
||||||
|
|
||||||
|
<div style="background-color:white;">
|
||||||
|
|
||||||
![](https://latex.codecogs.com/gif.latex?%5Coperatorname{exp}%5C,%5Cleft(%5Csqrt{x}%5Cright)-%5Cfrac{%5Cfrac{%5Coperatorname{arcsin}%5C,%5Cleft(2%5C,x%5Cright)}{2%5Ctimes10^{10}%2Bx^{3}}}{12}+x^{2/3})
|
![](https://latex.codecogs.com/gif.latex?%5Coperatorname{exp}%5C,%5Cleft(%5Csqrt{x}%5Cright)-%5Cfrac{%5Cfrac{%5Coperatorname{arcsin}%5C,%5Cleft(2%5C,x%5Cright)}{2%5Ctimes10^{10}%2Bx^{3}}}{12}+x^{2/3})
|
||||||
|
</div>
|
||||||
|
|
||||||
Result MathML (can be used with MathJax or other renderers):
|
Result MathML (can be used with MathJax or other renderers):
|
||||||
|
|
||||||
|
@ -37,17 +37,15 @@ kotlin.sourceSets {
|
|||||||
|
|
||||||
jsMain {
|
jsMain {
|
||||||
dependencies {
|
dependencies {
|
||||||
implementation(npm("astring", "1.7.4"))
|
implementation(npm("astring", "1.7.5"))
|
||||||
implementation(npm("binaryen", "100.0"))
|
implementation(npm("binaryen", "101.0.0"))
|
||||||
implementation(npm("js-base64", "3.6.0"))
|
implementation(npm("js-base64", "3.6.1"))
|
||||||
implementation(npm("webassembly", "0.11.0"))
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
jvmMain {
|
jvmMain {
|
||||||
dependencies {
|
dependencies {
|
||||||
implementation("org.ow2.asm:asm:9.1")
|
implementation("org.ow2.asm:asm-commons:9.2")
|
||||||
implementation("org.ow2.asm:asm-commons:9.1")
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -63,25 +61,21 @@ readme {
|
|||||||
|
|
||||||
feature(
|
feature(
|
||||||
id = "expression-language",
|
id = "expression-language",
|
||||||
description = "Expression language and its parser",
|
|
||||||
ref = "src/commonMain/kotlin/space/kscience/kmath/ast/parser.kt"
|
ref = "src/commonMain/kotlin/space/kscience/kmath/ast/parser.kt"
|
||||||
)
|
) { "Expression language and its parser" }
|
||||||
|
|
||||||
feature(
|
feature(
|
||||||
id = "mst-jvm-codegen",
|
id = "mst-jvm-codegen",
|
||||||
description = "Dynamic MST to JVM bytecode compiler",
|
|
||||||
ref = "src/jvmMain/kotlin/space/kscience/kmath/asm/asm.kt"
|
ref = "src/jvmMain/kotlin/space/kscience/kmath/asm/asm.kt"
|
||||||
)
|
) { "Dynamic MST to JVM bytecode compiler" }
|
||||||
|
|
||||||
feature(
|
feature(
|
||||||
id = "mst-js-codegen",
|
id = "mst-js-codegen",
|
||||||
description = "Dynamic MST to JS compiler",
|
|
||||||
ref = "src/jsMain/kotlin/space/kscience/kmath/estree/estree.kt"
|
ref = "src/jsMain/kotlin/space/kscience/kmath/estree/estree.kt"
|
||||||
)
|
) { "Dynamic MST to JS compiler" }
|
||||||
|
|
||||||
feature(
|
feature(
|
||||||
id = "rendering",
|
id = "rendering",
|
||||||
description = "Extendable MST rendering",
|
|
||||||
ref = "src/commonMain/kotlin/space/kscience/kmath/ast/rendering/MathRenderer.kt"
|
ref = "src/commonMain/kotlin/space/kscience/kmath/ast/rendering/MathRenderer.kt"
|
||||||
)
|
) { "Extendable MST rendering" }
|
||||||
}
|
}
|
||||||
|
@ -16,11 +16,12 @@ special implementation of `Expression<T>` with implemented `invoke` function.
|
|||||||
For example, the following builder:
|
For example, the following builder:
|
||||||
|
|
||||||
```kotlin
|
```kotlin
|
||||||
|
import space.kscience.kmath.expressions.Symbol.Companion.x
|
||||||
import space.kscience.kmath.expressions.*
|
import space.kscience.kmath.expressions.*
|
||||||
import space.kscience.kmath.operations.*
|
import space.kscience.kmath.operations.*
|
||||||
import space.kscience.kmath.asm.*
|
import space.kscience.kmath.asm.*
|
||||||
|
|
||||||
MstField { bindSymbol("x") + 2 }.compileToExpression(DoubleField)
|
MstField { x + 2 }.compileToExpression(DoubleField)
|
||||||
```
|
```
|
||||||
|
|
||||||
... leads to generation of bytecode, which can be decompiled to the following Java class:
|
... leads to generation of bytecode, which can be decompiled to the following Java class:
|
||||||
@ -60,11 +61,12 @@ public final class AsmCompiledExpression_45045_0 implements Expression<Double> {
|
|||||||
A similar feature is also available on JS.
|
A similar feature is also available on JS.
|
||||||
|
|
||||||
```kotlin
|
```kotlin
|
||||||
|
import space.kscience.kmath.expressions.Symbol.Companion.x
|
||||||
import space.kscience.kmath.expressions.*
|
import space.kscience.kmath.expressions.*
|
||||||
import space.kscience.kmath.operations.*
|
import space.kscience.kmath.operations.*
|
||||||
import space.kscience.kmath.estree.*
|
import space.kscience.kmath.estree.*
|
||||||
|
|
||||||
MstField { bindSymbol("x") + 2 }.compileToExpression(DoubleField)
|
MstField { x + 2 }.compileToExpression(DoubleField)
|
||||||
```
|
```
|
||||||
|
|
||||||
The code above returns expression implemented with such a JS function:
|
The code above returns expression implemented with such a JS function:
|
||||||
@ -75,15 +77,16 @@ var executable = function (constants, arguments) {
|
|||||||
};
|
};
|
||||||
```
|
```
|
||||||
|
|
||||||
JS also supports very experimental expression optimization with [WebAssembly](https://webassembly.org/) IR generation.
|
JS also supports experimental expression optimization with [WebAssembly](https://webassembly.org/) IR generation.
|
||||||
Currently, only expressions inside `DoubleField` and `IntRing` are supported.
|
Currently, only expressions inside `DoubleField` and `IntRing` are supported.
|
||||||
|
|
||||||
```kotlin
|
```kotlin
|
||||||
|
import space.kscience.kmath.expressions.Symbol.Companion.x
|
||||||
import space.kscience.kmath.expressions.*
|
import space.kscience.kmath.expressions.*
|
||||||
import space.kscience.kmath.operations.*
|
import space.kscience.kmath.operations.*
|
||||||
import space.kscience.kmath.wasm.*
|
import space.kscience.kmath.wasm.*
|
||||||
|
|
||||||
MstField { bindSymbol("x") + 2 }.compileToExpression(DoubleField)
|
MstField { x + 2 }.compileToExpression(DoubleField)
|
||||||
```
|
```
|
||||||
|
|
||||||
An example of emitted Wasm IR in the form of WAT:
|
An example of emitted Wasm IR in the form of WAT:
|
||||||
@ -129,7 +132,10 @@ public fun main() {
|
|||||||
|
|
||||||
Result LaTeX:
|
Result LaTeX:
|
||||||
|
|
||||||
|
<div style="background-color:white;">
|
||||||
|
|
||||||
![](https://latex.codecogs.com/gif.latex?%5Coperatorname{exp}%5C,%5Cleft(%5Csqrt{x}%5Cright)-%5Cfrac{%5Cfrac{%5Coperatorname{arcsin}%5C,%5Cleft(2%5C,x%5Cright)}{2%5Ctimes10^{10}%2Bx^{3}}}{12}+x^{2/3})
|
![](https://latex.codecogs.com/gif.latex?%5Coperatorname{exp}%5C,%5Cleft(%5Csqrt{x}%5Cright)-%5Cfrac{%5Cfrac{%5Coperatorname{arcsin}%5C,%5Cleft(2%5C,x%5Cright)}{2%5Ctimes10^{10}%2Bx^{3}}}{12}+x^{2/3})
|
||||||
|
</div>
|
||||||
|
|
||||||
Result MathML (can be used with MathJax or other renderers):
|
Result MathML (can be used with MathJax or other renderers):
|
||||||
|
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2018-2021 KMath contributors.
|
* Copyright 2018-2021 KMath contributors.
|
||||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
* Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package space.kscience.kmath.ast
|
package space.kscience.kmath.ast
|
||||||
@ -17,6 +17,7 @@ import com.github.h0tk3y.betterParse.lexer.regexToken
|
|||||||
import com.github.h0tk3y.betterParse.parser.ParseResult
|
import com.github.h0tk3y.betterParse.parser.ParseResult
|
||||||
import com.github.h0tk3y.betterParse.parser.Parser
|
import com.github.h0tk3y.betterParse.parser.Parser
|
||||||
import space.kscience.kmath.expressions.MST
|
import space.kscience.kmath.expressions.MST
|
||||||
|
import space.kscience.kmath.expressions.Symbol
|
||||||
import space.kscience.kmath.operations.FieldOperations
|
import space.kscience.kmath.operations.FieldOperations
|
||||||
import space.kscience.kmath.operations.GroupOperations
|
import space.kscience.kmath.operations.GroupOperations
|
||||||
import space.kscience.kmath.operations.PowerOperations
|
import space.kscience.kmath.operations.PowerOperations
|
||||||
@ -42,7 +43,7 @@ public object ArithmeticsEvaluator : Grammar<MST>() {
|
|||||||
private val ws: Token by regexToken("\\s+".toRegex(), ignore = true)
|
private val ws: Token by regexToken("\\s+".toRegex(), ignore = true)
|
||||||
|
|
||||||
private val number: Parser<MST> by num use { MST.Numeric(text.toDouble()) }
|
private val number: Parser<MST> by num use { MST.Numeric(text.toDouble()) }
|
||||||
private val singular: Parser<MST> by id use { MST.Symbolic(text) }
|
private val singular: Parser<MST> by id use { Symbol(text) }
|
||||||
|
|
||||||
private val unaryFunction: Parser<MST> by (id and -lpar and parser(ArithmeticsEvaluator::subSumChain) and -rpar)
|
private val unaryFunction: Parser<MST> by (id and -lpar and parser(ArithmeticsEvaluator::subSumChain) and -rpar)
|
||||||
.map { (id, term) -> MST.Unary(id.text, term) }
|
.map { (id, term) -> MST.Unary(id.text, term) }
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2018-2021 KMath contributors.
|
* Copyright 2018-2021 KMath contributors.
|
||||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
* Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package space.kscience.kmath.ast.rendering
|
package space.kscience.kmath.ast.rendering
|
||||||
@ -27,7 +27,7 @@ import space.kscience.kmath.misc.UnstableKMathAPI
|
|||||||
*/
|
*/
|
||||||
@UnstableKMathAPI
|
@UnstableKMathAPI
|
||||||
public object LatexSyntaxRenderer : SyntaxRenderer {
|
public object LatexSyntaxRenderer : SyntaxRenderer {
|
||||||
public override fun render(node: MathSyntax, output: Appendable): Unit = output.run {
|
override fun render(node: MathSyntax, output: Appendable): Unit = output.run {
|
||||||
fun render(syntax: MathSyntax) = render(syntax, output)
|
fun render(syntax: MathSyntax) = render(syntax, output)
|
||||||
|
|
||||||
when (node) {
|
when (node) {
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2018-2021 KMath contributors.
|
* Copyright 2018-2021 KMath contributors.
|
||||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
* Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package space.kscience.kmath.ast.rendering
|
package space.kscience.kmath.ast.rendering
|
||||||
@ -16,7 +16,7 @@ import space.kscience.kmath.misc.UnstableKMathAPI
|
|||||||
*/
|
*/
|
||||||
@UnstableKMathAPI
|
@UnstableKMathAPI
|
||||||
public object MathMLSyntaxRenderer : SyntaxRenderer {
|
public object MathMLSyntaxRenderer : SyntaxRenderer {
|
||||||
public override fun render(node: MathSyntax, output: Appendable) {
|
override fun render(node: MathSyntax, output: Appendable) {
|
||||||
output.append("<math xmlns=\"https://www.w3.org/1998/Math/MathML\"><mrow>")
|
output.append("<math xmlns=\"https://www.w3.org/1998/Math/MathML\"><mrow>")
|
||||||
renderPart(node, output)
|
renderPart(node, output)
|
||||||
output.append("</mrow></math>")
|
output.append("</mrow></math>")
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2018-2021 KMath contributors.
|
* Copyright 2018-2021 KMath contributors.
|
||||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
* Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package space.kscience.kmath.ast.rendering
|
package space.kscience.kmath.ast.rendering
|
||||||
@ -29,7 +29,7 @@ public fun interface MathRenderer {
|
|||||||
*/
|
*/
|
||||||
@UnstableKMathAPI
|
@UnstableKMathAPI
|
||||||
public open class FeaturedMathRenderer(public val features: List<RenderFeature>) : MathRenderer {
|
public open class FeaturedMathRenderer(public val features: List<RenderFeature>) : MathRenderer {
|
||||||
public override fun render(mst: MST): MathSyntax {
|
override fun render(mst: MST): MathSyntax {
|
||||||
for (feature in features) feature.render(this, mst)?.let { return it }
|
for (feature in features) feature.render(this, mst)?.let { return it }
|
||||||
throw UnsupportedOperationException("Renderer $this has no appropriate feature to render node $mst.")
|
throw UnsupportedOperationException("Renderer $this has no appropriate feature to render node $mst.")
|
||||||
}
|
}
|
||||||
@ -54,9 +54,9 @@ public open class FeaturedMathRenderer(public val features: List<RenderFeature>)
|
|||||||
@UnstableKMathAPI
|
@UnstableKMathAPI
|
||||||
public open class FeaturedMathRendererWithPostProcess(
|
public open class FeaturedMathRendererWithPostProcess(
|
||||||
features: List<RenderFeature>,
|
features: List<RenderFeature>,
|
||||||
public val stages: List<PostProcessStage>,
|
public val stages: List<PostProcessPhase>,
|
||||||
) : FeaturedMathRenderer(features) {
|
) : FeaturedMathRenderer(features) {
|
||||||
public override fun render(mst: MST): MathSyntax {
|
override fun render(mst: MST): MathSyntax {
|
||||||
val res = super.render(mst)
|
val res = super.render(mst)
|
||||||
for (stage in stages) stage.perform(res)
|
for (stage in stages) stage.perform(res)
|
||||||
return res
|
return res
|
||||||
@ -65,7 +65,7 @@ public open class FeaturedMathRendererWithPostProcess(
|
|||||||
/**
|
/**
|
||||||
* Logical unit of [MathSyntax] post-processing.
|
* Logical unit of [MathSyntax] post-processing.
|
||||||
*/
|
*/
|
||||||
public fun interface PostProcessStage {
|
public fun interface PostProcessPhase {
|
||||||
/**
|
/**
|
||||||
* Performs the specified action over [MathSyntax].
|
* Performs the specified action over [MathSyntax].
|
||||||
*/
|
*/
|
||||||
@ -102,7 +102,7 @@ public open class FeaturedMathRendererWithPostProcess(
|
|||||||
|
|
||||||
// Printing terminal nodes as string
|
// Printing terminal nodes as string
|
||||||
PrintNumeric,
|
PrintNumeric,
|
||||||
PrintSymbolic,
|
PrintSymbol,
|
||||||
),
|
),
|
||||||
listOf(
|
listOf(
|
||||||
BetterExponent,
|
BetterExponent,
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2018-2021 KMath contributors.
|
* Copyright 2018-2021 KMath contributors.
|
||||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
* Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package space.kscience.kmath.ast.rendering
|
package space.kscience.kmath.ast.rendering
|
||||||
@ -8,7 +8,7 @@ package space.kscience.kmath.ast.rendering
|
|||||||
import space.kscience.kmath.misc.UnstableKMathAPI
|
import space.kscience.kmath.misc.UnstableKMathAPI
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Mathematical typography syntax node.
|
* Syntax node for mathematical typography.
|
||||||
*
|
*
|
||||||
* @author Iaroslav Postovalov
|
* @author Iaroslav Postovalov
|
||||||
*/
|
*/
|
||||||
@ -150,9 +150,9 @@ public data class OperandSyntax(
|
|||||||
*/
|
*/
|
||||||
@UnstableKMathAPI
|
@UnstableKMathAPI
|
||||||
public data class UnaryOperatorSyntax(
|
public data class UnaryOperatorSyntax(
|
||||||
public override val operation: String,
|
override val operation: String,
|
||||||
public var prefix: MathSyntax,
|
public var prefix: MathSyntax,
|
||||||
public override val operand: OperandSyntax,
|
override val operand: OperandSyntax,
|
||||||
) : UnarySyntax() {
|
) : UnarySyntax() {
|
||||||
init {
|
init {
|
||||||
operand.parent = this
|
operand.parent = this
|
||||||
@ -166,8 +166,8 @@ public data class UnaryOperatorSyntax(
|
|||||||
*/
|
*/
|
||||||
@UnstableKMathAPI
|
@UnstableKMathAPI
|
||||||
public data class UnaryPlusSyntax(
|
public data class UnaryPlusSyntax(
|
||||||
public override val operation: String,
|
override val operation: String,
|
||||||
public override val operand: OperandSyntax,
|
override val operand: OperandSyntax,
|
||||||
) : UnarySyntax() {
|
) : UnarySyntax() {
|
||||||
init {
|
init {
|
||||||
operand.parent = this
|
operand.parent = this
|
||||||
@ -181,8 +181,8 @@ public data class UnaryPlusSyntax(
|
|||||||
*/
|
*/
|
||||||
@UnstableKMathAPI
|
@UnstableKMathAPI
|
||||||
public data class UnaryMinusSyntax(
|
public data class UnaryMinusSyntax(
|
||||||
public override val operation: String,
|
override val operation: String,
|
||||||
public override val operand: OperandSyntax,
|
override val operand: OperandSyntax,
|
||||||
) : UnarySyntax() {
|
) : UnarySyntax() {
|
||||||
init {
|
init {
|
||||||
operand.parent = this
|
operand.parent = this
|
||||||
@ -197,8 +197,8 @@ public data class UnaryMinusSyntax(
|
|||||||
*/
|
*/
|
||||||
@UnstableKMathAPI
|
@UnstableKMathAPI
|
||||||
public data class RadicalSyntax(
|
public data class RadicalSyntax(
|
||||||
public override val operation: String,
|
override val operation: String,
|
||||||
public override val operand: MathSyntax,
|
override val operand: MathSyntax,
|
||||||
) : UnarySyntax() {
|
) : UnarySyntax() {
|
||||||
init {
|
init {
|
||||||
operand.parent = this
|
operand.parent = this
|
||||||
@ -215,8 +215,8 @@ public data class RadicalSyntax(
|
|||||||
*/
|
*/
|
||||||
@UnstableKMathAPI
|
@UnstableKMathAPI
|
||||||
public data class ExponentSyntax(
|
public data class ExponentSyntax(
|
||||||
public override val operation: String,
|
override val operation: String,
|
||||||
public override val operand: OperandSyntax,
|
override val operand: OperandSyntax,
|
||||||
public var useOperatorForm: Boolean,
|
public var useOperatorForm: Boolean,
|
||||||
) : UnarySyntax() {
|
) : UnarySyntax() {
|
||||||
init {
|
init {
|
||||||
@ -233,9 +233,9 @@ public data class ExponentSyntax(
|
|||||||
*/
|
*/
|
||||||
@UnstableKMathAPI
|
@UnstableKMathAPI
|
||||||
public data class SuperscriptSyntax(
|
public data class SuperscriptSyntax(
|
||||||
public override val operation: String,
|
override val operation: String,
|
||||||
public override val left: MathSyntax,
|
override val left: MathSyntax,
|
||||||
public override val right: MathSyntax,
|
override val right: MathSyntax,
|
||||||
) : BinarySyntax() {
|
) : BinarySyntax() {
|
||||||
init {
|
init {
|
||||||
left.parent = this
|
left.parent = this
|
||||||
@ -252,9 +252,9 @@ public data class SuperscriptSyntax(
|
|||||||
*/
|
*/
|
||||||
@UnstableKMathAPI
|
@UnstableKMathAPI
|
||||||
public data class SubscriptSyntax(
|
public data class SubscriptSyntax(
|
||||||
public override val operation: String,
|
override val operation: String,
|
||||||
public override val left: MathSyntax,
|
override val left: MathSyntax,
|
||||||
public override val right: MathSyntax,
|
override val right: MathSyntax,
|
||||||
) : BinarySyntax() {
|
) : BinarySyntax() {
|
||||||
init {
|
init {
|
||||||
left.parent = this
|
left.parent = this
|
||||||
@ -270,10 +270,10 @@ public data class SubscriptSyntax(
|
|||||||
*/
|
*/
|
||||||
@UnstableKMathAPI
|
@UnstableKMathAPI
|
||||||
public data class BinaryOperatorSyntax(
|
public data class BinaryOperatorSyntax(
|
||||||
public override val operation: String,
|
override val operation: String,
|
||||||
public var prefix: MathSyntax,
|
public var prefix: MathSyntax,
|
||||||
public override val left: MathSyntax,
|
override val left: MathSyntax,
|
||||||
public override val right: MathSyntax,
|
override val right: MathSyntax,
|
||||||
) : BinarySyntax() {
|
) : BinarySyntax() {
|
||||||
init {
|
init {
|
||||||
left.parent = this
|
left.parent = this
|
||||||
@ -290,9 +290,9 @@ public data class BinaryOperatorSyntax(
|
|||||||
*/
|
*/
|
||||||
@UnstableKMathAPI
|
@UnstableKMathAPI
|
||||||
public data class BinaryPlusSyntax(
|
public data class BinaryPlusSyntax(
|
||||||
public override val operation: String,
|
override val operation: String,
|
||||||
public override val left: OperandSyntax,
|
override val left: OperandSyntax,
|
||||||
public override val right: OperandSyntax,
|
override val right: OperandSyntax,
|
||||||
) : BinarySyntax() {
|
) : BinarySyntax() {
|
||||||
init {
|
init {
|
||||||
left.parent = this
|
left.parent = this
|
||||||
@ -301,7 +301,7 @@ public data class BinaryPlusSyntax(
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Represents binary, infix subtraction (*42 - 42*).
|
* Represents binary, infix subtraction (*42 − 42*).
|
||||||
*
|
*
|
||||||
* @param left The minuend.
|
* @param left The minuend.
|
||||||
* @param right The subtrahend.
|
* @param right The subtrahend.
|
||||||
@ -309,9 +309,9 @@ public data class BinaryPlusSyntax(
|
|||||||
*/
|
*/
|
||||||
@UnstableKMathAPI
|
@UnstableKMathAPI
|
||||||
public data class BinaryMinusSyntax(
|
public data class BinaryMinusSyntax(
|
||||||
public override val operation: String,
|
override val operation: String,
|
||||||
public override val left: OperandSyntax,
|
override val left: OperandSyntax,
|
||||||
public override val right: OperandSyntax,
|
override val right: OperandSyntax,
|
||||||
) : BinarySyntax() {
|
) : BinarySyntax() {
|
||||||
init {
|
init {
|
||||||
left.parent = this
|
left.parent = this
|
||||||
@ -329,9 +329,9 @@ public data class BinaryMinusSyntax(
|
|||||||
*/
|
*/
|
||||||
@UnstableKMathAPI
|
@UnstableKMathAPI
|
||||||
public data class FractionSyntax(
|
public data class FractionSyntax(
|
||||||
public override val operation: String,
|
override val operation: String,
|
||||||
public override val left: OperandSyntax,
|
override val left: OperandSyntax,
|
||||||
public override val right: OperandSyntax,
|
override val right: OperandSyntax,
|
||||||
public var infix: Boolean,
|
public var infix: Boolean,
|
||||||
) : BinarySyntax() {
|
) : BinarySyntax() {
|
||||||
init {
|
init {
|
||||||
@ -349,9 +349,9 @@ public data class FractionSyntax(
|
|||||||
*/
|
*/
|
||||||
@UnstableKMathAPI
|
@UnstableKMathAPI
|
||||||
public data class RadicalWithIndexSyntax(
|
public data class RadicalWithIndexSyntax(
|
||||||
public override val operation: String,
|
override val operation: String,
|
||||||
public override val left: MathSyntax,
|
override val left: MathSyntax,
|
||||||
public override val right: MathSyntax,
|
override val right: MathSyntax,
|
||||||
) : BinarySyntax() {
|
) : BinarySyntax() {
|
||||||
init {
|
init {
|
||||||
left.parent = this
|
left.parent = this
|
||||||
@ -369,9 +369,9 @@ public data class RadicalWithIndexSyntax(
|
|||||||
*/
|
*/
|
||||||
@UnstableKMathAPI
|
@UnstableKMathAPI
|
||||||
public data class MultiplicationSyntax(
|
public data class MultiplicationSyntax(
|
||||||
public override val operation: String,
|
override val operation: String,
|
||||||
public override val left: OperandSyntax,
|
override val left: OperandSyntax,
|
||||||
public override val right: OperandSyntax,
|
override val right: OperandSyntax,
|
||||||
public var times: Boolean,
|
public var times: Boolean,
|
||||||
) : BinarySyntax() {
|
) : BinarySyntax() {
|
||||||
init {
|
init {
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2018-2021 KMath contributors.
|
* Copyright 2018-2021 KMath contributors.
|
||||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
* Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package space.kscience.kmath.ast.rendering
|
package space.kscience.kmath.ast.rendering
|
||||||
@ -9,7 +9,7 @@ import space.kscience.kmath.misc.UnstableKMathAPI
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Abstraction of writing [MathSyntax] as a string of an actual markup language. Typical implementation should
|
* Abstraction of writing [MathSyntax] as a string of an actual markup language. Typical implementation should
|
||||||
* involve traversal of MathSyntax with handling each its subtype.
|
* involve traversal of MathSyntax with handling each subtype.
|
||||||
*
|
*
|
||||||
* @author Iaroslav Postovalov
|
* @author Iaroslav Postovalov
|
||||||
*/
|
*/
|
||||||
|
@ -1,27 +1,26 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2018-2021 KMath contributors.
|
* Copyright 2018-2021 KMath contributors.
|
||||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
* Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package space.kscience.kmath.ast.rendering
|
package space.kscience.kmath.ast.rendering
|
||||||
|
|
||||||
import space.kscience.kmath.ast.rendering.FeaturedMathRenderer.RenderFeature
|
import space.kscience.kmath.ast.rendering.FeaturedMathRenderer.RenderFeature
|
||||||
import space.kscience.kmath.expressions.MST
|
import space.kscience.kmath.expressions.MST
|
||||||
|
import space.kscience.kmath.expressions.Symbol
|
||||||
import space.kscience.kmath.misc.UnstableKMathAPI
|
import space.kscience.kmath.misc.UnstableKMathAPI
|
||||||
import space.kscience.kmath.operations.*
|
import space.kscience.kmath.operations.*
|
||||||
import kotlin.reflect.KClass
|
import kotlin.reflect.KClass
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Prints any [MST.Symbolic] as a [SymbolSyntax] containing the [MST.Symbolic.value] of it.
|
* Prints any [Symbol] as a [SymbolSyntax] containing the [Symbol.identity] of it.
|
||||||
*
|
*
|
||||||
* @author Iaroslav Postovalov
|
* @author Iaroslav Postovalov
|
||||||
*/
|
*/
|
||||||
@UnstableKMathAPI
|
@UnstableKMathAPI
|
||||||
public object PrintSymbolic : RenderFeature {
|
public val PrintSymbol: RenderFeature = RenderFeature { _, node ->
|
||||||
public override fun render(renderer: FeaturedMathRenderer, node: MST): SymbolSyntax? =
|
if (node !is Symbol) null
|
||||||
if (node !is MST.Symbolic) null
|
else SymbolSyntax(string = node.identity)
|
||||||
else
|
|
||||||
SymbolSyntax(string = node.value)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -30,8 +29,8 @@ public object PrintSymbolic : RenderFeature {
|
|||||||
* @author Iaroslav Postovalov
|
* @author Iaroslav Postovalov
|
||||||
*/
|
*/
|
||||||
@UnstableKMathAPI
|
@UnstableKMathAPI
|
||||||
public object PrintNumeric : RenderFeature {
|
public val PrintNumeric: RenderFeature = RenderFeature { _, node ->
|
||||||
public override fun render(renderer: FeaturedMathRenderer, node: MST): NumberSyntax? = if (node !is MST.Numeric)
|
if (node !is MST.Numeric)
|
||||||
null
|
null
|
||||||
else
|
else
|
||||||
NumberSyntax(string = node.value.toString())
|
NumberSyntax(string = node.value.toString())
|
||||||
@ -50,7 +49,7 @@ else
|
|||||||
NumberSyntax(string = s)
|
NumberSyntax(string = s)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Special printing for numeric types which are printed in form of
|
* Special printing for numeric types that are printed in form of
|
||||||
* *('-'? (DIGIT+ ('.' DIGIT+)? ('E' '-'? DIGIT+)? | 'Infinity')) | 'NaN'*.
|
* *('-'? (DIGIT+ ('.' DIGIT+)? ('E' '-'? DIGIT+)? | 'Infinity')) | 'NaN'*.
|
||||||
*
|
*
|
||||||
* @property types The suitable types.
|
* @property types The suitable types.
|
||||||
@ -58,7 +57,7 @@ else
|
|||||||
*/
|
*/
|
||||||
@UnstableKMathAPI
|
@UnstableKMathAPI
|
||||||
public class PrettyPrintFloats(public val types: Set<KClass<out Number>>) : RenderFeature {
|
public class PrettyPrintFloats(public val types: Set<KClass<out Number>>) : RenderFeature {
|
||||||
public override fun render(renderer: FeaturedMathRenderer, node: MST): MathSyntax? {
|
override fun render(renderer: FeaturedMathRenderer, node: MST): MathSyntax? {
|
||||||
if (node !is MST.Numeric || node.value::class !in types) return null
|
if (node !is MST.Numeric || node.value::class !in types) return null
|
||||||
|
|
||||||
val toString = when (val v = node.value) {
|
val toString = when (val v = node.value) {
|
||||||
@ -111,14 +110,14 @@ public class PrettyPrintFloats(public val types: Set<KClass<out Number>>) : Rend
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Special printing for numeric types which are printed in form of *'-'? DIGIT+*.
|
* Special printing for numeric types that are printed in form of *'-'? DIGIT+*.
|
||||||
*
|
*
|
||||||
* @property types The suitable types.
|
* @property types The suitable types.
|
||||||
* @author Iaroslav Postovalov
|
* @author Iaroslav Postovalov
|
||||||
*/
|
*/
|
||||||
@UnstableKMathAPI
|
@UnstableKMathAPI
|
||||||
public class PrettyPrintIntegers(public val types: Set<KClass<out Number>>) : RenderFeature {
|
public class PrettyPrintIntegers(public val types: Set<KClass<out Number>>) : RenderFeature {
|
||||||
public override fun render(renderer: FeaturedMathRenderer, node: MST): MathSyntax? =
|
override fun render(renderer: FeaturedMathRenderer, node: MST): MathSyntax? =
|
||||||
if (node !is MST.Numeric || node.value::class !in types)
|
if (node !is MST.Numeric || node.value::class !in types)
|
||||||
null
|
null
|
||||||
else
|
else
|
||||||
@ -141,8 +140,8 @@ public class PrettyPrintIntegers(public val types: Set<KClass<out Number>>) : Re
|
|||||||
*/
|
*/
|
||||||
@UnstableKMathAPI
|
@UnstableKMathAPI
|
||||||
public class PrettyPrintPi(public val symbols: Set<String>) : RenderFeature {
|
public class PrettyPrintPi(public val symbols: Set<String>) : RenderFeature {
|
||||||
public override fun render(renderer: FeaturedMathRenderer, node: MST): SpecialSymbolSyntax? =
|
override fun render(renderer: FeaturedMathRenderer, node: MST): MathSyntax? =
|
||||||
if (node !is MST.Symbolic || node.value !in symbols)
|
if (node !is Symbol || node.identity !in symbols)
|
||||||
null
|
null
|
||||||
else
|
else
|
||||||
SpecialSymbolSyntax(kind = SpecialSymbolSyntax.Kind.SMALL_PI)
|
SpecialSymbolSyntax(kind = SpecialSymbolSyntax.Kind.SMALL_PI)
|
||||||
@ -156,7 +155,7 @@ public class PrettyPrintPi(public val symbols: Set<String>) : RenderFeature {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Abstract printing of unary operations which discards [MST] if their operation is not in [operations] or its type is
|
* Abstract printing of unary operations that discards [MST] if their operation is not in [operations] or its type is
|
||||||
* not [MST.Unary].
|
* not [MST.Unary].
|
||||||
*
|
*
|
||||||
* @param operations the allowed operations. If `null`, any operation is accepted.
|
* @param operations the allowed operations. If `null`, any operation is accepted.
|
||||||
@ -177,7 +176,7 @@ public abstract class Unary(public val operations: Collection<String>?) : Render
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Abstract printing of unary operations which discards [MST] if their operation is not in [operations] or its type is
|
* Abstract printing of unary operations that discards [MST] if their operation is not in [operations] or its type is
|
||||||
* not [MST.Binary].
|
* not [MST.Binary].
|
||||||
*
|
*
|
||||||
* @property operations the allowed operations. If `null`, any operation is accepted.
|
* @property operations the allowed operations. If `null`, any operation is accepted.
|
||||||
@ -203,7 +202,7 @@ public abstract class Binary(public val operations: Collection<String>?) : Rende
|
|||||||
*/
|
*/
|
||||||
@UnstableKMathAPI
|
@UnstableKMathAPI
|
||||||
public class BinaryPlus(operations: Collection<String>?) : Binary(operations) {
|
public class BinaryPlus(operations: Collection<String>?) : Binary(operations) {
|
||||||
public override fun renderBinary(parent: FeaturedMathRenderer, node: MST.Binary): BinaryPlusSyntax =
|
override fun renderBinary(parent: FeaturedMathRenderer, node: MST.Binary): MathSyntax =
|
||||||
BinaryPlusSyntax(
|
BinaryPlusSyntax(
|
||||||
operation = node.operation,
|
operation = node.operation,
|
||||||
left = OperandSyntax(parent.render(node.left), true),
|
left = OperandSyntax(parent.render(node.left), true),
|
||||||
@ -225,7 +224,7 @@ public class BinaryPlus(operations: Collection<String>?) : Binary(operations) {
|
|||||||
*/
|
*/
|
||||||
@UnstableKMathAPI
|
@UnstableKMathAPI
|
||||||
public class BinaryMinus(operations: Collection<String>?) : Binary(operations) {
|
public class BinaryMinus(operations: Collection<String>?) : Binary(operations) {
|
||||||
public override fun renderBinary(parent: FeaturedMathRenderer, node: MST.Binary): BinaryMinusSyntax =
|
override fun renderBinary(parent: FeaturedMathRenderer, node: MST.Binary): MathSyntax =
|
||||||
BinaryMinusSyntax(
|
BinaryMinusSyntax(
|
||||||
operation = node.operation,
|
operation = node.operation,
|
||||||
left = OperandSyntax(operand = parent.render(node.left), parentheses = true),
|
left = OperandSyntax(operand = parent.render(node.left), parentheses = true),
|
||||||
@ -247,7 +246,7 @@ public class BinaryMinus(operations: Collection<String>?) : Binary(operations) {
|
|||||||
*/
|
*/
|
||||||
@UnstableKMathAPI
|
@UnstableKMathAPI
|
||||||
public class UnaryPlus(operations: Collection<String>?) : Unary(operations) {
|
public class UnaryPlus(operations: Collection<String>?) : Unary(operations) {
|
||||||
public override fun renderUnary(parent: FeaturedMathRenderer, node: MST.Unary): UnaryPlusSyntax = UnaryPlusSyntax(
|
override fun renderUnary(parent: FeaturedMathRenderer, node: MST.Unary): MathSyntax = UnaryPlusSyntax(
|
||||||
operation = node.operation,
|
operation = node.operation,
|
||||||
operand = OperandSyntax(operand = parent.render(node.value), parentheses = true),
|
operand = OperandSyntax(operand = parent.render(node.value), parentheses = true),
|
||||||
)
|
)
|
||||||
@ -267,7 +266,7 @@ public class UnaryPlus(operations: Collection<String>?) : Unary(operations) {
|
|||||||
*/
|
*/
|
||||||
@UnstableKMathAPI
|
@UnstableKMathAPI
|
||||||
public class UnaryMinus(operations: Collection<String>?) : Unary(operations) {
|
public class UnaryMinus(operations: Collection<String>?) : Unary(operations) {
|
||||||
public override fun renderUnary(parent: FeaturedMathRenderer, node: MST.Unary): UnaryMinusSyntax = UnaryMinusSyntax(
|
override fun renderUnary(parent: FeaturedMathRenderer, node: MST.Unary): MathSyntax = UnaryMinusSyntax(
|
||||||
operation = node.operation,
|
operation = node.operation,
|
||||||
operand = OperandSyntax(operand = parent.render(node.value), parentheses = true),
|
operand = OperandSyntax(operand = parent.render(node.value), parentheses = true),
|
||||||
)
|
)
|
||||||
@ -287,7 +286,7 @@ public class UnaryMinus(operations: Collection<String>?) : Unary(operations) {
|
|||||||
*/
|
*/
|
||||||
@UnstableKMathAPI
|
@UnstableKMathAPI
|
||||||
public class Fraction(operations: Collection<String>?) : Binary(operations) {
|
public class Fraction(operations: Collection<String>?) : Binary(operations) {
|
||||||
public override fun renderBinary(parent: FeaturedMathRenderer, node: MST.Binary): FractionSyntax = FractionSyntax(
|
override fun renderBinary(parent: FeaturedMathRenderer, node: MST.Binary): MathSyntax = FractionSyntax(
|
||||||
operation = node.operation,
|
operation = node.operation,
|
||||||
left = OperandSyntax(operand = parent.render(node.left), parentheses = true),
|
left = OperandSyntax(operand = parent.render(node.left), parentheses = true),
|
||||||
right = OperandSyntax(operand = parent.render(node.right), parentheses = true),
|
right = OperandSyntax(operand = parent.render(node.right), parentheses = true),
|
||||||
@ -309,7 +308,7 @@ public class Fraction(operations: Collection<String>?) : Binary(operations) {
|
|||||||
*/
|
*/
|
||||||
@UnstableKMathAPI
|
@UnstableKMathAPI
|
||||||
public class BinaryOperator(operations: Collection<String>?) : Binary(operations) {
|
public class BinaryOperator(operations: Collection<String>?) : Binary(operations) {
|
||||||
public override fun renderBinary(parent: FeaturedMathRenderer, node: MST.Binary): BinaryOperatorSyntax =
|
override fun renderBinary(parent: FeaturedMathRenderer, node: MST.Binary): MathSyntax =
|
||||||
BinaryOperatorSyntax(
|
BinaryOperatorSyntax(
|
||||||
operation = node.operation,
|
operation = node.operation,
|
||||||
prefix = OperatorNameSyntax(name = node.operation),
|
prefix = OperatorNameSyntax(name = node.operation),
|
||||||
@ -332,7 +331,7 @@ public class BinaryOperator(operations: Collection<String>?) : Binary(operations
|
|||||||
*/
|
*/
|
||||||
@UnstableKMathAPI
|
@UnstableKMathAPI
|
||||||
public class UnaryOperator(operations: Collection<String>?) : Unary(operations) {
|
public class UnaryOperator(operations: Collection<String>?) : Unary(operations) {
|
||||||
public override fun renderUnary(parent: FeaturedMathRenderer, node: MST.Unary): UnaryOperatorSyntax =
|
override fun renderUnary(parent: FeaturedMathRenderer, node: MST.Unary): MathSyntax =
|
||||||
UnaryOperatorSyntax(
|
UnaryOperatorSyntax(
|
||||||
operation = node.operation,
|
operation = node.operation,
|
||||||
prefix = OperatorNameSyntax(node.operation),
|
prefix = OperatorNameSyntax(node.operation),
|
||||||
@ -354,7 +353,7 @@ public class UnaryOperator(operations: Collection<String>?) : Unary(operations)
|
|||||||
*/
|
*/
|
||||||
@UnstableKMathAPI
|
@UnstableKMathAPI
|
||||||
public class Power(operations: Collection<String>?) : Binary(operations) {
|
public class Power(operations: Collection<String>?) : Binary(operations) {
|
||||||
public override fun renderBinary(parent: FeaturedMathRenderer, node: MST.Binary): SuperscriptSyntax =
|
override fun renderBinary(parent: FeaturedMathRenderer, node: MST.Binary): MathSyntax =
|
||||||
SuperscriptSyntax(
|
SuperscriptSyntax(
|
||||||
operation = node.operation,
|
operation = node.operation,
|
||||||
left = OperandSyntax(parent.render(node.left), true),
|
left = OperandSyntax(parent.render(node.left), true),
|
||||||
@ -374,7 +373,7 @@ public class Power(operations: Collection<String>?) : Binary(operations) {
|
|||||||
*/
|
*/
|
||||||
@UnstableKMathAPI
|
@UnstableKMathAPI
|
||||||
public class SquareRoot(operations: Collection<String>?) : Unary(operations) {
|
public class SquareRoot(operations: Collection<String>?) : Unary(operations) {
|
||||||
public override fun renderUnary(parent: FeaturedMathRenderer, node: MST.Unary): RadicalSyntax =
|
override fun renderUnary(parent: FeaturedMathRenderer, node: MST.Unary): MathSyntax =
|
||||||
RadicalSyntax(operation = node.operation, operand = parent.render(node.value))
|
RadicalSyntax(operation = node.operation, operand = parent.render(node.value))
|
||||||
|
|
||||||
public companion object {
|
public companion object {
|
||||||
@ -392,7 +391,7 @@ public class SquareRoot(operations: Collection<String>?) : Unary(operations) {
|
|||||||
*/
|
*/
|
||||||
@UnstableKMathAPI
|
@UnstableKMathAPI
|
||||||
public class Exponent(operations: Collection<String>?) : Unary(operations) {
|
public class Exponent(operations: Collection<String>?) : Unary(operations) {
|
||||||
public override fun renderUnary(parent: FeaturedMathRenderer, node: MST.Unary): ExponentSyntax = ExponentSyntax(
|
override fun renderUnary(parent: FeaturedMathRenderer, node: MST.Unary): MathSyntax = ExponentSyntax(
|
||||||
operation = node.operation,
|
operation = node.operation,
|
||||||
operand = OperandSyntax(operand = parent.render(node.value), parentheses = true),
|
operand = OperandSyntax(operand = parent.render(node.value), parentheses = true),
|
||||||
useOperatorForm = true,
|
useOperatorForm = true,
|
||||||
@ -413,7 +412,7 @@ public class Exponent(operations: Collection<String>?) : Unary(operations) {
|
|||||||
*/
|
*/
|
||||||
@UnstableKMathAPI
|
@UnstableKMathAPI
|
||||||
public class Multiplication(operations: Collection<String>?) : Binary(operations) {
|
public class Multiplication(operations: Collection<String>?) : Binary(operations) {
|
||||||
public override fun renderBinary(parent: FeaturedMathRenderer, node: MST.Binary): MultiplicationSyntax =
|
override fun renderBinary(parent: FeaturedMathRenderer, node: MST.Binary): MathSyntax =
|
||||||
MultiplicationSyntax(
|
MultiplicationSyntax(
|
||||||
operation = node.operation,
|
operation = node.operation,
|
||||||
left = OperandSyntax(operand = parent.render(node.left), parentheses = true),
|
left = OperandSyntax(operand = parent.render(node.left), parentheses = true),
|
||||||
@ -436,7 +435,7 @@ public class Multiplication(operations: Collection<String>?) : Binary(operations
|
|||||||
*/
|
*/
|
||||||
@UnstableKMathAPI
|
@UnstableKMathAPI
|
||||||
public class InverseTrigonometricOperations(operations: Collection<String>?) : Unary(operations) {
|
public class InverseTrigonometricOperations(operations: Collection<String>?) : Unary(operations) {
|
||||||
public override fun renderUnary(parent: FeaturedMathRenderer, node: MST.Unary): UnaryOperatorSyntax =
|
override fun renderUnary(parent: FeaturedMathRenderer, node: MST.Unary): MathSyntax =
|
||||||
UnaryOperatorSyntax(
|
UnaryOperatorSyntax(
|
||||||
operation = node.operation,
|
operation = node.operation,
|
||||||
prefix = OperatorNameSyntax(name = node.operation.replaceFirst("a", "arc")),
|
prefix = OperatorNameSyntax(name = node.operation.replaceFirst("a", "arc")),
|
||||||
@ -463,7 +462,7 @@ public class InverseTrigonometricOperations(operations: Collection<String>?) : U
|
|||||||
*/
|
*/
|
||||||
@UnstableKMathAPI
|
@UnstableKMathAPI
|
||||||
public class InverseHyperbolicOperations(operations: Collection<String>?) : Unary(operations) {
|
public class InverseHyperbolicOperations(operations: Collection<String>?) : Unary(operations) {
|
||||||
public override fun renderUnary(parent: FeaturedMathRenderer, node: MST.Unary): UnaryOperatorSyntax =
|
override fun renderUnary(parent: FeaturedMathRenderer, node: MST.Unary): MathSyntax =
|
||||||
UnaryOperatorSyntax(
|
UnaryOperatorSyntax(
|
||||||
operation = node.operation,
|
operation = node.operation,
|
||||||
prefix = OperatorNameSyntax(name = node.operation.replaceFirst("a", "ar")),
|
prefix = OperatorNameSyntax(name = node.operation.replaceFirst("a", "ar")),
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2018-2021 KMath contributors.
|
* Copyright 2018-2021 KMath contributors.
|
||||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
* Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package space.kscience.kmath.ast.rendering
|
package space.kscience.kmath.ast.rendering
|
||||||
|
@ -1,10 +1,11 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2018-2021 KMath contributors.
|
* Copyright 2018-2021 KMath contributors.
|
||||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
* Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package space.kscience.kmath.ast.rendering
|
package space.kscience.kmath.ast.rendering
|
||||||
|
|
||||||
|
import space.kscience.kmath.ast.rendering.FeaturedMathRendererWithPostProcess.PostProcessPhase
|
||||||
import space.kscience.kmath.misc.UnstableKMathAPI
|
import space.kscience.kmath.misc.UnstableKMathAPI
|
||||||
import space.kscience.kmath.operations.FieldOperations
|
import space.kscience.kmath.operations.FieldOperations
|
||||||
import space.kscience.kmath.operations.GroupOperations
|
import space.kscience.kmath.operations.GroupOperations
|
||||||
@ -17,8 +18,8 @@ import space.kscience.kmath.operations.RingOperations
|
|||||||
* @author Iaroslav Postovalov
|
* @author Iaroslav Postovalov
|
||||||
*/
|
*/
|
||||||
@UnstableKMathAPI
|
@UnstableKMathAPI
|
||||||
public object BetterMultiplication : FeaturedMathRendererWithPostProcess.PostProcessStage {
|
public val BetterMultiplication: PostProcessPhase = PostProcessPhase { node ->
|
||||||
public override fun perform(node: MathSyntax): Unit = when (node) {
|
fun perform(node: MathSyntax): Unit = when (node) {
|
||||||
is NumberSyntax -> Unit
|
is NumberSyntax -> Unit
|
||||||
is SymbolSyntax -> Unit
|
is SymbolSyntax -> Unit
|
||||||
is OperatorNameSyntax -> Unit
|
is OperatorNameSyntax -> Unit
|
||||||
@ -81,6 +82,8 @@ public object BetterMultiplication : FeaturedMathRendererWithPostProcess.PostPro
|
|||||||
perform(node.right)
|
perform(node.right)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
perform(node)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -89,68 +92,68 @@ public object BetterMultiplication : FeaturedMathRendererWithPostProcess.PostPro
|
|||||||
* @author Iaroslav Postovalov
|
* @author Iaroslav Postovalov
|
||||||
*/
|
*/
|
||||||
@UnstableKMathAPI
|
@UnstableKMathAPI
|
||||||
public object BetterFraction : FeaturedMathRendererWithPostProcess.PostProcessStage {
|
public val BetterFraction: PostProcessPhase = PostProcessPhase { node ->
|
||||||
private fun perform0(node: MathSyntax, infix: Boolean = false): Unit = when (node) {
|
fun perform(node: MathSyntax, infix: Boolean = false): Unit = when (node) {
|
||||||
is NumberSyntax -> Unit
|
is NumberSyntax -> Unit
|
||||||
is SymbolSyntax -> Unit
|
is SymbolSyntax -> Unit
|
||||||
is OperatorNameSyntax -> Unit
|
is OperatorNameSyntax -> Unit
|
||||||
is SpecialSymbolSyntax -> Unit
|
is SpecialSymbolSyntax -> Unit
|
||||||
is OperandSyntax -> perform0(node.operand, infix)
|
is OperandSyntax -> perform(node.operand, infix)
|
||||||
|
|
||||||
is UnaryOperatorSyntax -> {
|
is UnaryOperatorSyntax -> {
|
||||||
perform0(node.prefix, infix)
|
perform(node.prefix, infix)
|
||||||
perform0(node.operand, infix)
|
perform(node.operand, infix)
|
||||||
}
|
}
|
||||||
|
|
||||||
is UnaryPlusSyntax -> perform0(node.operand, infix)
|
is UnaryPlusSyntax -> perform(node.operand, infix)
|
||||||
is UnaryMinusSyntax -> perform0(node.operand, infix)
|
is UnaryMinusSyntax -> perform(node.operand, infix)
|
||||||
is RadicalSyntax -> perform0(node.operand, infix)
|
is RadicalSyntax -> perform(node.operand, infix)
|
||||||
is ExponentSyntax -> perform0(node.operand, infix)
|
is ExponentSyntax -> perform(node.operand, infix)
|
||||||
|
|
||||||
is SuperscriptSyntax -> {
|
is SuperscriptSyntax -> {
|
||||||
perform0(node.left, true)
|
perform(node.left, true)
|
||||||
perform0(node.right, true)
|
perform(node.right, true)
|
||||||
}
|
}
|
||||||
|
|
||||||
is SubscriptSyntax -> {
|
is SubscriptSyntax -> {
|
||||||
perform0(node.left, true)
|
perform(node.left, true)
|
||||||
perform0(node.right, true)
|
perform(node.right, true)
|
||||||
}
|
}
|
||||||
|
|
||||||
is BinaryOperatorSyntax -> {
|
is BinaryOperatorSyntax -> {
|
||||||
perform0(node.prefix, infix)
|
perform(node.prefix, infix)
|
||||||
perform0(node.left, infix)
|
perform(node.left, infix)
|
||||||
perform0(node.right, infix)
|
perform(node.right, infix)
|
||||||
}
|
}
|
||||||
|
|
||||||
is BinaryPlusSyntax -> {
|
is BinaryPlusSyntax -> {
|
||||||
perform0(node.left, infix)
|
perform(node.left, infix)
|
||||||
perform0(node.right, infix)
|
perform(node.right, infix)
|
||||||
}
|
}
|
||||||
|
|
||||||
is BinaryMinusSyntax -> {
|
is BinaryMinusSyntax -> {
|
||||||
perform0(node.left, infix)
|
perform(node.left, infix)
|
||||||
perform0(node.right, infix)
|
perform(node.right, infix)
|
||||||
}
|
}
|
||||||
|
|
||||||
is FractionSyntax -> {
|
is FractionSyntax -> {
|
||||||
node.infix = infix
|
node.infix = infix
|
||||||
perform0(node.left, infix)
|
perform(node.left, infix)
|
||||||
perform0(node.right, infix)
|
perform(node.right, infix)
|
||||||
}
|
}
|
||||||
|
|
||||||
is RadicalWithIndexSyntax -> {
|
is RadicalWithIndexSyntax -> {
|
||||||
perform0(node.left, true)
|
perform(node.left, true)
|
||||||
perform0(node.right, true)
|
perform(node.right, true)
|
||||||
}
|
}
|
||||||
|
|
||||||
is MultiplicationSyntax -> {
|
is MultiplicationSyntax -> {
|
||||||
perform0(node.left, infix)
|
perform(node.left, infix)
|
||||||
perform0(node.right, infix)
|
perform(node.right, infix)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public override fun perform(node: MathSyntax): Unit = perform0(node)
|
perform(node)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -160,39 +163,37 @@ public object BetterFraction : FeaturedMathRendererWithPostProcess.PostProcessSt
|
|||||||
* @author Iaroslav Postovalov
|
* @author Iaroslav Postovalov
|
||||||
*/
|
*/
|
||||||
@UnstableKMathAPI
|
@UnstableKMathAPI
|
||||||
public object BetterExponent : FeaturedMathRendererWithPostProcess.PostProcessStage {
|
public val BetterExponent: PostProcessPhase = PostProcessPhase { node ->
|
||||||
private fun perform0(node: MathSyntax): Boolean {
|
fun perform(node: MathSyntax): Boolean {
|
||||||
return when (node) {
|
return when (node) {
|
||||||
is NumberSyntax -> false
|
is NumberSyntax -> false
|
||||||
is SymbolSyntax -> false
|
is SymbolSyntax -> false
|
||||||
is OperatorNameSyntax -> false
|
is OperatorNameSyntax -> false
|
||||||
is SpecialSymbolSyntax -> false
|
is SpecialSymbolSyntax -> false
|
||||||
is OperandSyntax -> perform0(node.operand)
|
is OperandSyntax -> perform(node.operand)
|
||||||
is UnaryOperatorSyntax -> perform0(node.prefix) || perform0(node.operand)
|
is UnaryOperatorSyntax -> perform(node.prefix) || perform(node.operand)
|
||||||
is UnaryPlusSyntax -> perform0(node.operand)
|
is UnaryPlusSyntax -> perform(node.operand)
|
||||||
is UnaryMinusSyntax -> perform0(node.operand)
|
is UnaryMinusSyntax -> perform(node.operand)
|
||||||
is RadicalSyntax -> true
|
is RadicalSyntax -> true
|
||||||
|
|
||||||
is ExponentSyntax -> {
|
is ExponentSyntax -> {
|
||||||
val r = perform0(node.operand)
|
val r = perform(node.operand)
|
||||||
node.useOperatorForm = r
|
node.useOperatorForm = r
|
||||||
r
|
r
|
||||||
}
|
}
|
||||||
|
|
||||||
is SuperscriptSyntax -> true
|
is SuperscriptSyntax -> true
|
||||||
is SubscriptSyntax -> true
|
is SubscriptSyntax -> true
|
||||||
is BinaryOperatorSyntax -> perform0(node.prefix) || perform0(node.left) || perform0(node.right)
|
is BinaryOperatorSyntax -> perform(node.prefix) || perform(node.left) || perform(node.right)
|
||||||
is BinaryPlusSyntax -> perform0(node.left) || perform0(node.right)
|
is BinaryPlusSyntax -> perform(node.left) || perform(node.right)
|
||||||
is BinaryMinusSyntax -> perform0(node.left) || perform0(node.right)
|
is BinaryMinusSyntax -> perform(node.left) || perform(node.right)
|
||||||
is FractionSyntax -> true
|
is FractionSyntax -> true
|
||||||
is RadicalWithIndexSyntax -> true
|
is RadicalWithIndexSyntax -> true
|
||||||
is MultiplicationSyntax -> perform0(node.left) || perform0(node.right)
|
is MultiplicationSyntax -> perform(node.left) || perform(node.right)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public override fun perform(node: MathSyntax) {
|
perform(node)
|
||||||
perform0(node)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -203,8 +204,8 @@ public object BetterExponent : FeaturedMathRendererWithPostProcess.PostProcessSt
|
|||||||
*/
|
*/
|
||||||
@UnstableKMathAPI
|
@UnstableKMathAPI
|
||||||
public class SimplifyParentheses(public val precedenceFunction: (MathSyntax) -> Int) :
|
public class SimplifyParentheses(public val precedenceFunction: (MathSyntax) -> Int) :
|
||||||
FeaturedMathRendererWithPostProcess.PostProcessStage {
|
PostProcessPhase {
|
||||||
public override fun perform(node: MathSyntax): Unit = when (node) {
|
override fun perform(node: MathSyntax): Unit = when (node) {
|
||||||
is NumberSyntax -> Unit
|
is NumberSyntax -> Unit
|
||||||
is SymbolSyntax -> Unit
|
is SymbolSyntax -> Unit
|
||||||
is OperatorNameSyntax -> Unit
|
is OperatorNameSyntax -> Unit
|
@ -1,17 +1,16 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2018-2021 KMath contributors.
|
* Copyright 2018-2021 KMath contributors.
|
||||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
* Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package space.kscience.kmath.ast
|
package space.kscience.kmath.ast
|
||||||
|
|
||||||
import space.kscience.kmath.expressions.MstField
|
import space.kscience.kmath.expressions.MstField
|
||||||
import space.kscience.kmath.expressions.MstRing
|
import space.kscience.kmath.expressions.MstRing
|
||||||
|
import space.kscience.kmath.expressions.Symbol.Companion.x
|
||||||
import space.kscience.kmath.expressions.interpret
|
import space.kscience.kmath.expressions.interpret
|
||||||
import space.kscience.kmath.misc.Symbol.Companion.x
|
|
||||||
import space.kscience.kmath.operations.DoubleField
|
import space.kscience.kmath.operations.DoubleField
|
||||||
import space.kscience.kmath.operations.IntRing
|
import space.kscience.kmath.operations.IntRing
|
||||||
import space.kscience.kmath.operations.bindSymbol
|
|
||||||
import space.kscience.kmath.operations.invoke
|
import space.kscience.kmath.operations.invoke
|
||||||
import kotlin.test.Test
|
import kotlin.test.Test
|
||||||
import kotlin.test.assertEquals
|
import kotlin.test.assertEquals
|
||||||
@ -22,7 +21,7 @@ internal class TestCompilerConsistencyWithInterpreter {
|
|||||||
val mst = MstRing {
|
val mst = MstRing {
|
||||||
binaryOperationFunction("+")(
|
binaryOperationFunction("+")(
|
||||||
unaryOperationFunction("+")(
|
unaryOperationFunction("+")(
|
||||||
(bindSymbol(x) - (2.toByte() + (scale(
|
(x - (2.toByte() + (scale(
|
||||||
add(number(1), number(1)),
|
add(number(1), number(1)),
|
||||||
2.0,
|
2.0,
|
||||||
) + 1.toByte()))) * 3.0 - 1.toByte()
|
) + 1.toByte()))) * 3.0 - 1.toByte()
|
||||||
@ -42,7 +41,7 @@ internal class TestCompilerConsistencyWithInterpreter {
|
|||||||
fun doubleField() = runCompilerTest {
|
fun doubleField() = runCompilerTest {
|
||||||
val mst = MstField {
|
val mst = MstField {
|
||||||
+(3 - 2 + 2 * number(1) + 1.0) + binaryOperationFunction("+")(
|
+(3 - 2 + 2 * number(1) + 1.0) + binaryOperationFunction("+")(
|
||||||
(3.0 - (bindSymbol(x) + (scale(add(number(1.0), number(1.0)), 2.0) + 1.0))) * 3 - 1.0
|
(3.0 - (x + (scale(add(number(1.0), number(1.0)), 2.0) + 1.0))) * 3 - 1.0
|
||||||
+ number(1),
|
+ number(1),
|
||||||
number(1) / 2 + number(2.0) * one,
|
number(1) / 2 + number(2.0) * one,
|
||||||
) + zero
|
) + zero
|
||||||
|
@ -1,15 +1,14 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2018-2021 KMath contributors.
|
* Copyright 2018-2021 KMath contributors.
|
||||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
* Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package space.kscience.kmath.ast
|
package space.kscience.kmath.ast
|
||||||
|
|
||||||
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.invoke
|
import space.kscience.kmath.expressions.invoke
|
||||||
import space.kscience.kmath.misc.Symbol.Companion.x
|
|
||||||
import space.kscience.kmath.operations.DoubleField
|
import space.kscience.kmath.operations.DoubleField
|
||||||
import space.kscience.kmath.operations.bindSymbol
|
|
||||||
import space.kscience.kmath.operations.invoke
|
import space.kscience.kmath.operations.invoke
|
||||||
import kotlin.test.Test
|
import kotlin.test.Test
|
||||||
import kotlin.test.assertEquals
|
import kotlin.test.assertEquals
|
||||||
@ -17,49 +16,49 @@ import kotlin.test.assertEquals
|
|||||||
internal class TestCompilerOperations {
|
internal class TestCompilerOperations {
|
||||||
@Test
|
@Test
|
||||||
fun testUnaryPlus() = runCompilerTest {
|
fun testUnaryPlus() = runCompilerTest {
|
||||||
val expr = MstExtendedField { +bindSymbol(x) }.compileToExpression(DoubleField)
|
val expr = MstExtendedField { +x }.compileToExpression(DoubleField)
|
||||||
assertEquals(2.0, expr(x to 2.0))
|
assertEquals(2.0, expr(x to 2.0))
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun testUnaryMinus() = runCompilerTest {
|
fun testUnaryMinus() = runCompilerTest {
|
||||||
val expr = MstExtendedField { -bindSymbol(x) }.compileToExpression(DoubleField)
|
val expr = MstExtendedField { -x }.compileToExpression(DoubleField)
|
||||||
assertEquals(-2.0, expr(x to 2.0))
|
assertEquals(-2.0, expr(x to 2.0))
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun testAdd() = runCompilerTest {
|
fun testAdd() = runCompilerTest {
|
||||||
val expr = MstExtendedField { bindSymbol(x) + bindSymbol(x) }.compileToExpression(DoubleField)
|
val expr = MstExtendedField { x + x }.compileToExpression(DoubleField)
|
||||||
assertEquals(4.0, expr(x to 2.0))
|
assertEquals(4.0, expr(x to 2.0))
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun testSine() = runCompilerTest {
|
fun testSine() = runCompilerTest {
|
||||||
val expr = MstExtendedField { sin(bindSymbol(x)) }.compileToExpression(DoubleField)
|
val expr = MstExtendedField { sin(x) }.compileToExpression(DoubleField)
|
||||||
assertEquals(0.0, expr(x to 0.0))
|
assertEquals(0.0, expr(x to 0.0))
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun testCosine() = runCompilerTest {
|
fun testCosine() = runCompilerTest {
|
||||||
val expr = MstExtendedField { cos(bindSymbol(x)) }.compileToExpression(DoubleField)
|
val expr = MstExtendedField { cos(x) }.compileToExpression(DoubleField)
|
||||||
assertEquals(1.0, expr(x to 0.0))
|
assertEquals(1.0, expr(x to 0.0))
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun testSubtract() = runCompilerTest {
|
fun testSubtract() = runCompilerTest {
|
||||||
val expr = MstExtendedField { bindSymbol(x) - bindSymbol(x) }.compileToExpression(DoubleField)
|
val expr = MstExtendedField { x - x }.compileToExpression(DoubleField)
|
||||||
assertEquals(0.0, expr(x to 2.0))
|
assertEquals(0.0, expr(x to 2.0))
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun testDivide() = runCompilerTest {
|
fun testDivide() = runCompilerTest {
|
||||||
val expr = MstExtendedField { bindSymbol(x) / bindSymbol(x) }.compileToExpression(DoubleField)
|
val expr = MstExtendedField { x / x }.compileToExpression(DoubleField)
|
||||||
assertEquals(1.0, expr(x to 2.0))
|
assertEquals(1.0, expr(x to 2.0))
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun testPower() = runCompilerTest {
|
fun testPower() = runCompilerTest {
|
||||||
val expr = MstExtendedField { bindSymbol(x) pow 2 }.compileToExpression(DoubleField)
|
val expr = MstExtendedField { x pow 2 }.compileToExpression(DoubleField)
|
||||||
assertEquals(4.0, expr(x to 2.0))
|
assertEquals(4.0, expr(x to 2.0))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,15 +1,14 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2018-2021 KMath contributors.
|
* Copyright 2018-2021 KMath contributors.
|
||||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
* Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package space.kscience.kmath.ast
|
package space.kscience.kmath.ast
|
||||||
|
|
||||||
import space.kscience.kmath.expressions.MstRing
|
import space.kscience.kmath.expressions.MstRing
|
||||||
|
import space.kscience.kmath.expressions.Symbol.Companion.x
|
||||||
import space.kscience.kmath.expressions.invoke
|
import space.kscience.kmath.expressions.invoke
|
||||||
import space.kscience.kmath.misc.Symbol.Companion.x
|
|
||||||
import space.kscience.kmath.operations.IntRing
|
import space.kscience.kmath.operations.IntRing
|
||||||
import space.kscience.kmath.operations.bindSymbol
|
|
||||||
import space.kscience.kmath.operations.invoke
|
import space.kscience.kmath.operations.invoke
|
||||||
import kotlin.test.Test
|
import kotlin.test.Test
|
||||||
import kotlin.test.assertEquals
|
import kotlin.test.assertEquals
|
||||||
@ -18,13 +17,13 @@ import kotlin.test.assertFailsWith
|
|||||||
internal class TestCompilerVariables {
|
internal class TestCompilerVariables {
|
||||||
@Test
|
@Test
|
||||||
fun testVariable() = runCompilerTest {
|
fun testVariable() = runCompilerTest {
|
||||||
val expr = MstRing { bindSymbol(x) }.compileToExpression(IntRing)
|
val expr = MstRing { x }.compileToExpression(IntRing)
|
||||||
assertEquals(1, expr(x to 1))
|
assertEquals(1, expr(x to 1))
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun testUndefinedVariableFails() = runCompilerTest {
|
fun testUndefinedVariableFails() = runCompilerTest {
|
||||||
val expr = MstRing { bindSymbol(x) }.compileToExpression(IntRing)
|
val expr = MstRing { x }.compileToExpression(IntRing)
|
||||||
assertFailsWith<NoSuchElementException> { expr() }
|
assertFailsWith<NoSuchElementException> { expr() }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2018-2021 KMath contributors.
|
* Copyright 2018-2021 KMath contributors.
|
||||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
* Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package space.kscience.kmath.ast
|
package space.kscience.kmath.ast
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2018-2021 KMath contributors.
|
* Copyright 2018-2021 KMath contributors.
|
||||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
* Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package space.kscience.kmath.ast
|
package space.kscience.kmath.ast
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2018-2021 KMath contributors.
|
* Copyright 2018-2021 KMath contributors.
|
||||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
* Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package space.kscience.kmath.ast.rendering
|
package space.kscience.kmath.ast.rendering
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2018-2021 KMath contributors.
|
* Copyright 2018-2021 KMath contributors.
|
||||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
* Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package space.kscience.kmath.ast.rendering
|
package space.kscience.kmath.ast.rendering
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2018-2021 KMath contributors.
|
* Copyright 2018-2021 KMath contributors.
|
||||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
* Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package space.kscience.kmath.ast.rendering
|
package space.kscience.kmath.ast.rendering
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2018-2021 KMath contributors.
|
* Copyright 2018-2021 KMath contributors.
|
||||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
* Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package space.kscience.kmath.ast.rendering
|
package space.kscience.kmath.ast.rendering
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2018-2021 KMath contributors.
|
* Copyright 2018-2021 KMath contributors.
|
||||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
* Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package space.kscience.kmath.ast.rendering
|
package space.kscience.kmath.ast.rendering
|
||||||
|
@ -1,13 +1,13 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2018-2021 KMath contributors.
|
* Copyright 2018-2021 KMath contributors.
|
||||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
* Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package space.kscience.kmath.ast
|
package space.kscience.kmath.ast
|
||||||
|
|
||||||
import space.kscience.kmath.expressions.Expression
|
import space.kscience.kmath.expressions.Expression
|
||||||
import space.kscience.kmath.expressions.MST
|
import space.kscience.kmath.expressions.MST
|
||||||
import space.kscience.kmath.misc.Symbol
|
import space.kscience.kmath.expressions.Symbol
|
||||||
import space.kscience.kmath.operations.DoubleField
|
import space.kscience.kmath.operations.DoubleField
|
||||||
import space.kscience.kmath.operations.IntRing
|
import space.kscience.kmath.operations.IntRing
|
||||||
|
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2018-2021 KMath contributors.
|
* Copyright 2018-2021 KMath contributors.
|
||||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
* Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package space.kscience.kmath.ast.rendering
|
package space.kscience.kmath.ast.rendering
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2018-2021 KMath contributors.
|
* Copyright 2018-2021 KMath contributors.
|
||||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
* Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package space.kscience.kmath.estree
|
package space.kscience.kmath.estree
|
||||||
@ -9,22 +9,23 @@ import space.kscience.kmath.estree.internal.ESTreeBuilder
|
|||||||
import space.kscience.kmath.expressions.Expression
|
import space.kscience.kmath.expressions.Expression
|
||||||
import space.kscience.kmath.expressions.MST
|
import space.kscience.kmath.expressions.MST
|
||||||
import space.kscience.kmath.expressions.MST.*
|
import space.kscience.kmath.expressions.MST.*
|
||||||
|
import space.kscience.kmath.expressions.Symbol
|
||||||
import space.kscience.kmath.expressions.invoke
|
import space.kscience.kmath.expressions.invoke
|
||||||
import space.kscience.kmath.internal.estree.BaseExpression
|
import space.kscience.kmath.internal.estree.BaseExpression
|
||||||
import space.kscience.kmath.misc.Symbol
|
|
||||||
import space.kscience.kmath.operations.Algebra
|
import space.kscience.kmath.operations.Algebra
|
||||||
import space.kscience.kmath.operations.NumericAlgebra
|
import space.kscience.kmath.operations.NumericAlgebra
|
||||||
|
import space.kscience.kmath.operations.bindSymbolOrNull
|
||||||
|
|
||||||
@PublishedApi
|
@PublishedApi
|
||||||
internal fun <T> MST.compileWith(algebra: Algebra<T>): Expression<T> {
|
internal fun <T> MST.compileWith(algebra: Algebra<T>): Expression<T> {
|
||||||
fun ESTreeBuilder<T>.visit(node: MST): BaseExpression = when (node) {
|
fun ESTreeBuilder<T>.visit(node: MST): BaseExpression = when (node) {
|
||||||
is Symbolic -> {
|
is Symbol -> {
|
||||||
val symbol = algebra.bindSymbolOrNull(node.value)
|
val symbol = algebra.bindSymbolOrNull(node)
|
||||||
|
|
||||||
if (symbol != null)
|
if (symbol != null)
|
||||||
constant(symbol)
|
constant(symbol)
|
||||||
else
|
else
|
||||||
variable(node.value)
|
variable(node.identity)
|
||||||
}
|
}
|
||||||
|
|
||||||
is Numeric -> constant(node.value)
|
is Numeric -> constant(node.value)
|
||||||
|