Feature/booleans #341

Merged
altavir merged 13 commits from feature/booleans into dev 2021-05-19 03:36:37 +03:00
67 changed files with 548 additions and 459 deletions

View File

@ -29,6 +29,9 @@
- Separated benchmarks and examples
- Rewritten EJML module without ejml-simple
- Stability of kmath-ast and kmath-kotilngrad promoted to EXPERIMENTAL.
- ColumnarData returns nullable column
- MST is made sealed interface
- Replaced MST.Symbolic by Symbol, Symbol now implements MST
### Deprecated

View File

@ -11,8 +11,6 @@ import kotlinx.benchmark.Scope
import kotlinx.benchmark.State
import space.kscience.kmath.asm.compileToExpression
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.bindSymbol
import space.kscience.kmath.operations.invoke

View File

@ -15,7 +15,7 @@ allprojects {
}
group = "space.kscience"
version = "0.3.0-dev-8"
version = "0.3.0-dev-9"
}
subprojects {

View File

@ -57,7 +57,7 @@ kotlin.sourceSets.all {
tasks.withType<org.jetbrains.kotlin.gradle.tasks.KotlinCompile> {
kotlinOptions{
jvmTarget = "11"
freeCompilerArgs = freeCompilerArgs + "-Xjvm-default=all"
freeCompilerArgs = freeCompilerArgs + "-Xjvm-default=all" + "-Xopt-in=kotlin.RequiresOptIn"
}
}

View File

@ -6,8 +6,8 @@
package space.kscience.kmath.ast
import space.kscience.kmath.expressions.MstField
import space.kscience.kmath.expressions.Symbol.Companion.x
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.bindSymbol
import space.kscience.kmath.operations.invoke

View File

@ -8,8 +8,8 @@ package space.kscience.kmath.ast
import space.kscience.kmath.asm.compileToExpression
import space.kscience.kmath.expressions.derivative
import space.kscience.kmath.expressions.invoke
import space.kscience.kmath.expressions.symbol
import space.kscience.kmath.kotlingrad.toDiffExpression
import space.kscience.kmath.misc.symbol
import space.kscience.kmath.operations.DoubleField
/**

View File

@ -10,7 +10,7 @@ import kotlinx.html.h3
import space.kscience.kmath.commons.optimization.chiSquared
import space.kscience.kmath.commons.optimization.minimize
import space.kscience.kmath.distributions.NormalDistribution
import space.kscience.kmath.misc.symbol
import space.kscience.kmath.expressions.symbol
import space.kscience.kmath.optimization.FunctionOptimization
import space.kscience.kmath.optimization.OptimizationResult
import space.kscience.kmath.real.DoubleVector

View File

@ -6,6 +6,7 @@
package space.kscience.kmath.functions
import space.kscience.kmath.integration.integrate
import space.kscience.kmath.integration.integrator
import space.kscience.kmath.integration.value
import space.kscience.kmath.operations.DoubleField
import kotlin.math.pow
@ -15,7 +16,7 @@ fun main() {
val function: UnivariateFunction<Double> = { x -> 3 * x.pow(2) + 2 * x + 1 }
//get the result of the integration
val result = DoubleField.integrate(0.0..10.0, function = function)
val result = DoubleField.integrator.integrate(0.0..10.0, function = function)
//the value is nullable because in some cases the integration could not succeed
println(result.value)

View File

@ -6,6 +6,7 @@
package space.kscience.kmath.functions
import space.kscience.kmath.integration.integrate
import space.kscience.kmath.integration.integrator
import space.kscience.kmath.integration.value
import space.kscience.kmath.nd.StructureND
import space.kscience.kmath.nd.nd
@ -24,7 +25,7 @@ fun main(): Unit = DoubleField {
val function: (Double) -> StructureND<Double> = { x: Double -> 3 * number(x).pow(2) + 2 * diagonal(x) + 1 }
//get the result of the integration
val result = integrate(0.0..10.0, function = function)
val result = integrator.integrate(0.0..10.0, function = function)
//the value is nullable because in some cases the integration could not succeed
println(result.value)

View File

@ -11,36 +11,32 @@ import space.kscience.kmath.tensors.core.BroadcastDoubleTensorAlgebra
// Dataset normalization
fun main() {
fun main() = BroadcastDoubleTensorAlgebra { // 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)
// 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
)
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)
// 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")
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)}")
// 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
// now we can scale dataset with mean normalization
val datasetScaled = (dataset - mean) / std
// find out mean and std of scaled dataset
// 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)}")
}
println("Mean of scaled:\n${datasetScaled.mean(0, false)}")
println("Mean of scaled:\n${datasetScaled.std(0, false)}")
}

View File

@ -6,92 +6,88 @@
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
import space.kscience.kmath.tensors.core.DoubleTensor
// solving linear system with LUP decomposition
fun main () {
fun main() = BroadcastDoubleTensorAlgebra {// work in context with linear operations
// 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)
)
// 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
)
)
// 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
// calculate y value
val b = a dot trueX
// check out A and b
println("A:\n$a")
println("b:\n$b")
// check out A and b
println("A:\n$a")
println("b:\n$b")
// solve `Ax = b` system using LUP decomposition
// solve `Ax = b` system using LUP decomposition
// get P, L, U such that PA = LU
val (p, l, u) = a.lu()
// 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}")
// 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
*/
/* 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]
// 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) {
revMat[intArrayOf(i, n - 1 - i)] = 1.0
x[intArrayOf(i)] = (b[intArrayOf(i)] - l[i].dot(x).value()) / l[intArrayOf(i, i)]
}
// 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")
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")
}

View File

@ -25,7 +25,7 @@ interface Layer {
// activation layer
open class Activation(
val activation: (DoubleTensor) -> DoubleTensor,
val activationDer: (DoubleTensor) -> DoubleTensor
val activationDer: (DoubleTensor) -> DoubleTensor,
) : Layer {
override fun forward(input: DoubleTensor): DoubleTensor {
return activation(input)
@ -62,7 +62,7 @@ class Sigmoid : Activation(::sigmoid, ::sigmoidDer)
class Dense(
private val inputUnits: Int,
private val outputUnits: Int,
private val learningRate: Double = 0.1
private val learningRate: Double = 0.1,
) : Layer {
private val weights: DoubleTensor = DoubleTensorAlgebra {
@ -74,8 +74,8 @@ class Dense(
private val bias: DoubleTensor = DoubleTensorAlgebra { zeros(intArrayOf(outputUnits)) }
override fun forward(input: DoubleTensor): DoubleTensor {
return BroadcastDoubleTensorAlgebra { (input dot weights) + bias }
override fun forward(input: DoubleTensor): DoubleTensor = BroadcastDoubleTensorAlgebra {
(input dot weights) + bias
}
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
}
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())
}
@ -175,67 +175,65 @@ class NeuralNetwork(private val layers: List<Layer>) {
@OptIn(ExperimentalStdlibApi::class)
fun main() {
BroadcastDoubleTensorAlgebra {
val features = 5
val sampleSize = 250
val trainSize = 180
//val testSize = sampleSize - trainSize
fun main() = BroadcastDoubleTensorAlgebra {
val features = 5
val sampleSize = 250
val trainSize = 180
//val testSize = sampleSize - trainSize
// take sample of features from normal distribution
val x = randomNormal(intArrayOf(sampleSize, features), seed) * 2.5
// take sample of features from normal distribution
val x = randomNormal(intArrayOf(sampleSize, features), seed) * 2.5
x += fromArray(
intArrayOf(5),
doubleArrayOf(0.0, -1.0, -2.5, -3.0, 5.5) // rows means
)
x += fromArray(
intArrayOf(5),
doubleArrayOf(0.0, -1.0, -2.5, -3.0, 5.5) // rows means
)
// define class like '1' if the sum of features > 0 and '0' otherwise
val y = fromArray(
intArrayOf(sampleSize, 1),
DoubleArray(sampleSize) { i ->
if (x[i].sum() > 0.0) {
1.0
} else {
0.0
}
// define class like '1' if the sum of features > 0 and '0' otherwise
val y = fromArray(
intArrayOf(sampleSize, 1),
DoubleArray(sampleSize) { i ->
if (x[i].sum() > 0.0) {
1.0
} else {
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
model.fit(xTrain, yTrain, batchSize = 20, epochs = 10)
// split train ans test
val trainIndices = (0 until trainSize).toList().toIntArray()
val testIndices = (trainSize until sampleSize).toList().toIntArray()
// make prediction
val prediction = model.predict(xTest)
val xTrain = x.rowsByIndices(trainIndices)
val yTrain = y.rowsByIndices(trainIndices)
// process raw prediction via argMax
val predictionLabels = prediction.argMax(1, true)
// find out accuracy
val acc = accuracy(yTest, predictionLabels)
println("Test accuracy:$acc")
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
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")
}

View File

@ -11,68 +11,64 @@ import space.kscience.kmath.tensors.core.BroadcastDoubleTensorAlgebra
// simple PCA
fun main(){
fun main() = BroadcastDoubleTensorAlgebra { // work in context with broadcast methods
val seed = 100500L
// work in context with broadcast methods
BroadcastDoubleTensorAlgebra {
// assume x is range from 0 until 10
val x = fromArray(
intArrayOf(10),
(0 until 10).toList().map { it.toDouble() }.toDoubleArray()
)
// assume x is range from 0 until 10
val x = fromArray(
intArrayOf(10),
(0 until 10).toList().map { it.toDouble() }.toDoubleArray()
)
// take y dependent on x with noise
val y = 2.0 * x + (3.0 + x.randomNormalLike(seed) * 1.5)
// take y dependent on x with noise
val y = 2.0 * x + (3.0 + x.randomNormalLike(seed) * 1.5)
println("x:\n$x")
println("y:\n$y")
println("x:\n$x")
println("y:\n$y")
// stack them into single dataset
val dataset = stack(listOf(x, y)).transpose()
// stack them into single dataset
val dataset = stack(listOf(x, y)).transpose()
// normalize both x and y
val xMean = x.mean()
val yMean = y.mean()
// normalize both x and y
val xMean = x.mean()
val yMean = y.mean()
val xStd = x.std()
val yStd = y.std()
val xStd = x.std()
val yStd = y.std()
val xScaled = (x - xMean) / xStd
val yScaled = (y - yMean) / yStd
val xScaled = (x - xMean) / xStd
val yScaled = (y - yMean) / yStd
// save means ans standard deviations for further recovery
val mean = fromArray(
intArrayOf(2),
doubleArrayOf(xMean, yMean)
)
println("Means:\n$mean")
// save means ans standard deviations for further recovery
val mean = fromArray(
intArrayOf(2),
doubleArrayOf(xMean, yMean)
)
println("Means:\n$mean")
val std = fromArray(
intArrayOf(2),
doubleArrayOf(xStd, yStd)
)
println("Standard deviations:\n$std")
val std = fromArray(
intArrayOf(2),
doubleArrayOf(xStd, yStd)
)
println("Standard deviations:\n$std")
// calculate the covariance matrix of scaled x and y
val covMatrix = cov(listOf(xScaled, yScaled))
println("Covariance matrix:\n$covMatrix")
// calculate the covariance matrix of scaled x and y
val covMatrix = cov(listOf(xScaled, yScaled))
println("Covariance matrix:\n$covMatrix")
// and find out eigenvector of it
val (_, evecs) = covMatrix.symEig()
val v = evecs[0]
println("Eigenvector:\n$v")
// and find out eigenvector of it
val (_, evecs) = covMatrix.symEig()
val v = evecs[0]
println("Eigenvector:\n$v")
// reduce dimension of dataset
val datasetReduced = v dot stack(listOf(xScaled, yScaled))
println("Reduced data:\n$datasetReduced")
// reduce dimension of dataset
val datasetReduced = v dot stack(listOf(xScaled, yScaled))
println("Reduced data:\n$datasetReduced")
// we can restore original data from reduced data.
// for example, find 7th element of dataset
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")
}
// we can restore original data from reduced data.
// for example, find 7th element of dataset
val n = 7
val restored = (datasetReduced[n] dot v.view(intArrayOf(1, 2))) * std + mean
println("Original value:\n${dataset[n]}")
println("Restored value:\n$restored")
}

View File

@ -17,6 +17,7 @@ import com.github.h0tk3y.betterParse.lexer.regexToken
import com.github.h0tk3y.betterParse.parser.ParseResult
import com.github.h0tk3y.betterParse.parser.Parser
import space.kscience.kmath.expressions.MST
import space.kscience.kmath.expressions.StringSymbol
import space.kscience.kmath.operations.FieldOperations
import space.kscience.kmath.operations.GroupOperations
import space.kscience.kmath.operations.PowerOperations
@ -42,7 +43,7 @@ public object ArithmeticsEvaluator : Grammar<MST>() {
private val ws: Token by regexToken("\\s+".toRegex(), ignore = true)
private val number: Parser<MST> by num use { MST.Numeric(text.toDouble()) }
private val singular: Parser<MST> by id use { MST.Symbolic(text) }
private val singular: Parser<MST> by id use { StringSymbol(text) }
private val unaryFunction: Parser<MST> by (id and -lpar and parser(ArithmeticsEvaluator::subSumChain) and -rpar)
.map { (id, term) -> MST.Unary(id.text, term) }

View File

@ -7,6 +7,7 @@ package space.kscience.kmath.ast.rendering
import space.kscience.kmath.ast.rendering.FeaturedMathRenderer.RenderFeature
import space.kscience.kmath.expressions.MST
import space.kscience.kmath.expressions.Symbol
import space.kscience.kmath.misc.UnstableKMathAPI
import space.kscience.kmath.operations.*
import kotlin.reflect.KClass
@ -19,9 +20,8 @@ import kotlin.reflect.KClass
@UnstableKMathAPI
public object PrintSymbolic : RenderFeature {
public override fun render(renderer: FeaturedMathRenderer, node: MST): SymbolSyntax? =
if (node !is MST.Symbolic) null
else
SymbolSyntax(string = node.value)
if (node !is Symbol) null
else SymbolSyntax(string = node.identity)
}
/**
@ -142,7 +142,7 @@ public class PrettyPrintIntegers(public val types: Set<KClass<out Number>>) : Re
@UnstableKMathAPI
public class PrettyPrintPi(public val symbols: Set<String>) : RenderFeature {
public override fun render(renderer: FeaturedMathRenderer, node: MST): SpecialSymbolSyntax? =
if (node !is MST.Symbolic || node.value !in symbols)
if (node !is Symbol || node.identity !in symbols)
null
else
SpecialSymbolSyntax(kind = SpecialSymbolSyntax.Kind.SMALL_PI)

View File

@ -7,8 +7,8 @@ package space.kscience.kmath.ast
import space.kscience.kmath.expressions.MstField
import space.kscience.kmath.expressions.MstRing
import space.kscience.kmath.expressions.Symbol.Companion.x
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.IntRing
import space.kscience.kmath.operations.bindSymbol

View File

@ -6,8 +6,8 @@
package space.kscience.kmath.ast
import space.kscience.kmath.expressions.MstExtendedField
import space.kscience.kmath.expressions.Symbol.Companion.x
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.bindSymbol
import space.kscience.kmath.operations.invoke
@ -17,31 +17,31 @@ import kotlin.test.assertEquals
internal class TestCompilerOperations {
@Test
fun testUnaryPlus() = runCompilerTest {
val expr = MstExtendedField { +bindSymbol(x) }.compileToExpression(DoubleField)
val expr = MstExtendedField { +x }.compileToExpression(DoubleField)
assertEquals(2.0, expr(x to 2.0))
}
@Test
fun testUnaryMinus() = runCompilerTest {
val expr = MstExtendedField { -bindSymbol(x) }.compileToExpression(DoubleField)
val expr = MstExtendedField { -x }.compileToExpression(DoubleField)
assertEquals(-2.0, expr(x to 2.0))
}
@Test
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))
}
@Test
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))
}
@Test
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))
}

View File

@ -6,8 +6,8 @@
package space.kscience.kmath.ast
import space.kscience.kmath.expressions.MstRing
import space.kscience.kmath.expressions.Symbol.Companion.x
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.bindSymbol
import space.kscience.kmath.operations.invoke

View File

@ -7,7 +7,7 @@ package space.kscience.kmath.ast
import space.kscience.kmath.expressions.Expression
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.IntRing

View File

@ -9,22 +9,23 @@ import space.kscience.kmath.estree.internal.ESTreeBuilder
import space.kscience.kmath.expressions.Expression
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.internal.estree.BaseExpression
import space.kscience.kmath.misc.Symbol
import space.kscience.kmath.operations.Algebra
import space.kscience.kmath.operations.NumericAlgebra
import space.kscience.kmath.operations.bindSymbolOrNull
@PublishedApi
internal fun <T> MST.compileWith(algebra: Algebra<T>): Expression<T> {
fun ESTreeBuilder<T>.visit(node: MST): BaseExpression = when (node) {
is Symbolic -> {
val symbol = algebra.bindSymbolOrNull(node.value)
is Symbol -> {
val symbol = algebra.bindSymbolOrNull(node)
if (symbol != null)
constant(symbol)
else
variable(node.value)
variable(node.identity)
}
is Numeric -> constant(node.value)

View File

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

View File

@ -8,9 +8,9 @@ package space.kscience.kmath.wasm.internal
import space.kscience.kmath.expressions.Expression
import space.kscience.kmath.expressions.MST
import space.kscience.kmath.expressions.MST.*
import space.kscience.kmath.expressions.Symbol
import space.kscience.kmath.internal.binaryen.*
import space.kscience.kmath.internal.webassembly.Instance
import space.kscience.kmath.misc.StringSymbol
import space.kscience.kmath.operations.*
import space.kscience.kmath.internal.binaryen.Module as BinaryenModule
import space.kscience.kmath.internal.webassembly.Module as WasmModule
@ -23,20 +23,20 @@ internal sealed class WasmBuilder<T>(
val algebra: Algebra<T>,
val target: MST,
) where T : Number {
val keys: MutableList<String> = mutableListOf()
val keys: MutableList<Symbol> = mutableListOf()
lateinit var ctx: BinaryenModule
open fun visitSymbolic(mst: Symbolic): ExpressionRef {
open fun visitSymbolic(mst: Symbol): ExpressionRef {
try {
algebra.bindSymbol(mst.value)
algebra.bindSymbol(mst)
} catch (ignored: Throwable) {
null
}?.let { return visitNumeric(Numeric(it)) }
var idx = keys.indexOf(mst.value)
var idx = keys.indexOf(mst)
if (idx == -1) {
keys += mst.value
keys += mst
idx = keys.lastIndex
}
@ -54,7 +54,7 @@ internal sealed class WasmBuilder<T>(
open fun createModule(): BinaryenModule = js("new \$module\$binaryen.Module()")
fun visit(mst: MST): ExpressionRef = when (mst) {
is Symbolic -> visitSymbolic(mst)
is Symbol -> visitSymbolic(mst)
is Numeric -> visitNumeric(mst)
is Unary -> when {
@ -96,7 +96,7 @@ internal sealed class WasmBuilder<T>(
})
val i = Instance(c, js("{}") as Any)
val symbols = keys.map(::StringSymbol)
val symbols = keys
keys.clear()
Expression<T> { args ->

View File

@ -8,8 +8,8 @@ package space.kscience.kmath.wasm
import space.kscience.kmath.estree.compileWith
import space.kscience.kmath.expressions.Expression
import space.kscience.kmath.expressions.MST
import space.kscience.kmath.expressions.Symbol
import space.kscience.kmath.expressions.invoke
import space.kscience.kmath.misc.Symbol
import space.kscience.kmath.misc.UnstableKMathAPI
import space.kscience.kmath.operations.DoubleField
import space.kscience.kmath.operations.IntRing

View File

@ -6,7 +6,6 @@
package space.kscience.kmath.ast
import space.kscience.kmath.expressions.*
import space.kscience.kmath.misc.symbol
import space.kscience.kmath.operations.DoubleField
import space.kscience.kmath.operations.ExtendedField
import space.kscience.kmath.operations.bindSymbol

View File

@ -7,7 +7,7 @@ package space.kscience.kmath.ast
import space.kscience.kmath.expressions.Expression
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.IntRing
import space.kscience.kmath.estree.compile as estreeCompile

View File

@ -8,7 +8,7 @@ package space.kscience.kmath.wasm
import space.kscience.kmath.expressions.MstExtendedField
import space.kscience.kmath.expressions.MstRing
import space.kscience.kmath.expressions.invoke
import space.kscience.kmath.misc.symbol
import space.kscience.kmath.expressions.symbol
import space.kscience.kmath.operations.DoubleField
import space.kscience.kmath.operations.IntRing
import space.kscience.kmath.operations.bindSymbol

View File

@ -10,10 +10,11 @@ import space.kscience.kmath.asm.internal.buildName
import space.kscience.kmath.expressions.Expression
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.misc.Symbol
import space.kscience.kmath.operations.Algebra
import space.kscience.kmath.operations.NumericAlgebra
import space.kscience.kmath.operations.bindSymbolOrNull
/**
* Compiles given MST to an Expression using AST compiler.
@ -26,13 +27,13 @@ import space.kscience.kmath.operations.NumericAlgebra
@PublishedApi
internal fun <T : Any> MST.compileWith(type: Class<T>, algebra: Algebra<T>): Expression<T> {
fun AsmBuilder<T>.visit(node: MST): Unit = when (node) {
is Symbolic -> {
val symbol = algebra.bindSymbolOrNull(node.value)
is Symbol -> {
val symbol = algebra.bindSymbolOrNull(node)
if (symbol != null)
loadObjectConstant(symbol as Any)
else
loadVariable(node.value)
loadVariable(node.identity)
}
is Numeric -> loadNumberConstant(node.value)

View File

@ -7,8 +7,8 @@
package space.kscience.kmath.asm.internal
import space.kscience.kmath.misc.StringSymbol
import space.kscience.kmath.misc.Symbol
import space.kscience.kmath.expressions.StringSymbol
import space.kscience.kmath.expressions.Symbol
/**
* Gets value with given [key] or throws [NoSuchElementException] whenever it is not present.

View File

@ -7,7 +7,7 @@ package space.kscience.kmath.ast
import space.kscience.kmath.expressions.Expression
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.IntRing
import space.kscience.kmath.asm.compile as asmCompile

View File

@ -7,7 +7,6 @@ package space.kscience.kmath.commons.expressions
import org.apache.commons.math3.analysis.differentiation.DerivativeStructure
import space.kscience.kmath.expressions.*
import space.kscience.kmath.misc.Symbol
import space.kscience.kmath.misc.UnstableKMathAPI
import space.kscience.kmath.operations.ExtendedField
import space.kscience.kmath.operations.NumbersAddOperations

View File

@ -78,6 +78,6 @@ public class GaussRuleIntegrator(
function: (Double) -> Double,
): Double = GaussRuleIntegrator(numPoints, type).integrate(
UnivariateIntegrand(function, IntegrationRange(range))
).value!!
).valueOrNull!!
}
}

View File

@ -14,13 +14,17 @@ import org.apache.commons.math3.optim.nonlinear.scalar.gradient.NonLinearConjuga
import org.apache.commons.math3.optim.nonlinear.scalar.noderiv.AbstractSimplex
import org.apache.commons.math3.optim.nonlinear.scalar.noderiv.NelderMeadSimplex
import org.apache.commons.math3.optim.nonlinear.scalar.noderiv.SimplexOptimizer
import space.kscience.kmath.expressions.DifferentiableExpression
import space.kscience.kmath.expressions.Expression
import space.kscience.kmath.expressions.SymbolIndexer
import space.kscience.kmath.expressions.derivative
import space.kscience.kmath.misc.Symbol
import space.kscience.kmath.expressions.*
import space.kscience.kmath.misc.UnstableKMathAPI
import space.kscience.kmath.optimization.*
import kotlin.collections.HashMap
import kotlin.collections.List
import kotlin.collections.Map
import kotlin.collections.set
import kotlin.collections.setOf
import kotlin.collections.toList
import kotlin.collections.toMap
import kotlin.collections.toTypedArray
import kotlin.reflect.KClass
public operator fun PointValuePair.component1(): DoubleArray = point

View File

@ -9,7 +9,7 @@ import org.apache.commons.math3.analysis.differentiation.DerivativeStructure
import space.kscience.kmath.commons.expressions.DerivativeStructureField
import space.kscience.kmath.expressions.DifferentiableExpression
import space.kscience.kmath.expressions.Expression
import space.kscience.kmath.misc.Symbol
import space.kscience.kmath.expressions.Symbol
import space.kscience.kmath.optimization.FunctionOptimization
import space.kscience.kmath.optimization.OptimizationResult
import space.kscience.kmath.optimization.noDerivOptimizeWith

View File

@ -5,11 +5,7 @@
package space.kscience.kmath.commons.expressions
import space.kscience.kmath.expressions.binding
import space.kscience.kmath.expressions.derivative
import space.kscience.kmath.expressions.invoke
import space.kscience.kmath.misc.Symbol
import space.kscience.kmath.misc.symbol
import space.kscience.kmath.expressions.*
import kotlin.contracts.InvocationKind
import kotlin.contracts.contract
import kotlin.test.Test

View File

@ -7,6 +7,7 @@ package space.kscience.kmath.commons.integration
import org.junit.jupiter.api.Test
import space.kscience.kmath.integration.integrate
import space.kscience.kmath.integration.value
import space.kscience.kmath.misc.UnstableKMathAPI
import space.kscience.kmath.operations.DoubleField.sin
import kotlin.math.PI
@ -19,7 +20,7 @@ internal class IntegrationTest {
@Test
fun simpson() {
val res = CMIntegrator.simpson().integrate(0.0..2 * PI, function = function)
val res = CMIntegrator.simpson().integrate(0.0..2 * PI, function = function).value
assertTrue { abs(res) < 1e-3 }
}
@ -28,7 +29,7 @@ internal class IntegrationTest {
val res = CMIntegrator.simpson().integrate(0.0..PI, {
targetRelativeAccuracy = 1e-4
targetAbsoluteAccuracy = 1e-4
}, function)
}, function).value
assertTrue { abs(res - 2) < 1e-3 }
assertTrue { abs(res - 2) > 1e-12 }
}

View File

@ -8,7 +8,7 @@ package space.kscience.kmath.commons.optimization
import kotlinx.coroutines.runBlocking
import space.kscience.kmath.commons.expressions.DerivativeStructureExpression
import space.kscience.kmath.distributions.NormalDistribution
import space.kscience.kmath.misc.symbol
import space.kscience.kmath.expressions.symbol
import space.kscience.kmath.optimization.FunctionOptimization
import space.kscience.kmath.stat.RandomGenerator
import kotlin.math.pow

View File

@ -7,7 +7,7 @@ package space.kscience.kmath.complex
import space.kscience.kmath.expressions.FunctionalExpressionField
import space.kscience.kmath.expressions.invoke
import space.kscience.kmath.misc.symbol
import space.kscience.kmath.expressions.symbol
import space.kscience.kmath.operations.bindSymbol
import kotlin.test.Test
import kotlin.test.assertEquals

View File

@ -21,7 +21,7 @@ public class space/kscience/kmath/expressions/AutoDiffValue {
public final class space/kscience/kmath/expressions/DerivationResult {
public fun <init> (Ljava/lang/Object;Ljava/util/Map;Lspace/kscience/kmath/operations/Field;)V
public final fun derivative (Lspace/kscience/kmath/misc/Symbol;)Ljava/lang/Object;
public final fun derivative (Lspace/kscience/kmath/expressions/Symbol;)Ljava/lang/Object;
public final fun div ()Ljava/lang/Object;
public final fun getContext ()Lspace/kscience/kmath/operations/Field;
public final fun getValue ()Ljava/lang/Object;
@ -34,7 +34,7 @@ public abstract interface class space/kscience/kmath/expressions/DifferentiableE
public final class space/kscience/kmath/expressions/DifferentiableExpressionKt {
public static final fun derivative (Lspace/kscience/kmath/expressions/DifferentiableExpression;Ljava/lang/String;)Lspace/kscience/kmath/expressions/Expression;
public static final fun derivative (Lspace/kscience/kmath/expressions/DifferentiableExpression;Ljava/util/List;)Lspace/kscience/kmath/expressions/Expression;
public static final fun derivative (Lspace/kscience/kmath/expressions/DifferentiableExpression;[Lspace/kscience/kmath/misc/Symbol;)Lspace/kscience/kmath/expressions/Expression;
public static final fun derivative (Lspace/kscience/kmath/expressions/DifferentiableExpression;[Lspace/kscience/kmath/expressions/Symbol;)Lspace/kscience/kmath/expressions/Expression;
}
public abstract interface class space/kscience/kmath/expressions/Expression {
@ -55,7 +55,7 @@ public final class space/kscience/kmath/expressions/ExpressionKt {
public abstract class space/kscience/kmath/expressions/FirstDerivativeExpression : space/kscience/kmath/expressions/DifferentiableExpression {
public fun <init> ()V
public final fun derivativeOrNull (Ljava/util/List;)Lspace/kscience/kmath/expressions/Expression;
public abstract fun derivativeOrNull (Lspace/kscience/kmath/misc/Symbol;)Lspace/kscience/kmath/expressions/Expression;
public abstract fun derivativeOrNull (Lspace/kscience/kmath/expressions/Symbol;)Lspace/kscience/kmath/expressions/Expression;
}
public abstract class space/kscience/kmath/expressions/FunctionalExpressionAlgebra : space/kscience/kmath/expressions/ExpressionAlgebra {
@ -146,7 +146,7 @@ public class space/kscience/kmath/expressions/FunctionalExpressionRing : space/k
public fun unaryOperationFunction (Ljava/lang/String;)Lkotlin/jvm/functions/Function1;
}
public abstract class space/kscience/kmath/expressions/MST {
public abstract interface class space/kscience/kmath/expressions/MST {
}
public final class space/kscience/kmath/expressions/MST$Binary : space/kscience/kmath/expressions/MST {
@ -175,17 +175,6 @@ public final class space/kscience/kmath/expressions/MST$Numeric : space/kscience
public fun toString ()Ljava/lang/String;
}
public final class space/kscience/kmath/expressions/MST$Symbolic : space/kscience/kmath/expressions/MST {
public fun <init> (Ljava/lang/String;)V
public final fun component1 ()Ljava/lang/String;
public final fun copy (Ljava/lang/String;)Lspace/kscience/kmath/expressions/MST$Symbolic;
public static synthetic fun copy$default (Lspace/kscience/kmath/expressions/MST$Symbolic;Ljava/lang/String;ILjava/lang/Object;)Lspace/kscience/kmath/expressions/MST$Symbolic;
public fun equals (Ljava/lang/Object;)Z
public final fun getValue ()Ljava/lang/String;
public fun hashCode ()I
public fun toString ()Ljava/lang/String;
}
public final class space/kscience/kmath/expressions/MST$Unary : space/kscience/kmath/expressions/MST {
public fun <init> (Ljava/lang/String;Lspace/kscience/kmath/expressions/MST;)V
public final fun component1 ()Ljava/lang/String;
@ -206,18 +195,6 @@ public final class space/kscience/kmath/expressions/MSTKt {
public static final fun toExpression (Lspace/kscience/kmath/expressions/MST;Lspace/kscience/kmath/operations/Algebra;)Lspace/kscience/kmath/expressions/Expression;
}
public final class space/kscience/kmath/expressions/MstAlgebra : space/kscience/kmath/operations/NumericAlgebra {
public static final field INSTANCE Lspace/kscience/kmath/expressions/MstAlgebra;
public fun binaryOperationFunction (Ljava/lang/String;)Lkotlin/jvm/functions/Function2;
public synthetic fun bindSymbol (Ljava/lang/String;)Ljava/lang/Object;
public fun bindSymbol (Ljava/lang/String;)Lspace/kscience/kmath/expressions/MST$Symbolic;
public synthetic fun bindSymbolOrNull (Ljava/lang/String;)Ljava/lang/Object;
public fun bindSymbolOrNull (Ljava/lang/String;)Lspace/kscience/kmath/expressions/MST$Symbolic;
public synthetic fun number (Ljava/lang/Number;)Ljava/lang/Object;
public fun number (Ljava/lang/Number;)Lspace/kscience/kmath/expressions/MST$Numeric;
public fun unaryOperationFunction (Ljava/lang/String;)Lkotlin/jvm/functions/Function1;
}
public final class space/kscience/kmath/expressions/MstExtendedField : space/kscience/kmath/operations/ExtendedField, space/kscience/kmath/operations/NumericAlgebra {
public static final field INSTANCE Lspace/kscience/kmath/expressions/MstExtendedField;
public synthetic fun acos (Ljava/lang/Object;)Ljava/lang/Object;
@ -236,7 +213,7 @@ public final class space/kscience/kmath/expressions/MstExtendedField : space/ksc
public fun atanh (Lspace/kscience/kmath/expressions/MST;)Lspace/kscience/kmath/expressions/MST$Unary;
public fun binaryOperationFunction (Ljava/lang/String;)Lkotlin/jvm/functions/Function2;
public synthetic fun bindSymbolOrNull (Ljava/lang/String;)Ljava/lang/Object;
public fun bindSymbolOrNull (Ljava/lang/String;)Lspace/kscience/kmath/expressions/MST$Symbolic;
public fun bindSymbolOrNull (Ljava/lang/String;)Lspace/kscience/kmath/expressions/Symbol;
public synthetic fun cos (Ljava/lang/Object;)Ljava/lang/Object;
public fun cos (Lspace/kscience/kmath/expressions/MST;)Lspace/kscience/kmath/expressions/MST$Unary;
public synthetic fun cosh (Ljava/lang/Object;)Ljava/lang/Object;
@ -284,7 +261,7 @@ public final class space/kscience/kmath/expressions/MstField : space/kscience/km
public fun add (Lspace/kscience/kmath/expressions/MST;Lspace/kscience/kmath/expressions/MST;)Lspace/kscience/kmath/expressions/MST$Binary;
public fun binaryOperationFunction (Ljava/lang/String;)Lkotlin/jvm/functions/Function2;
public synthetic fun bindSymbolOrNull (Ljava/lang/String;)Ljava/lang/Object;
public fun bindSymbolOrNull (Ljava/lang/String;)Lspace/kscience/kmath/expressions/MST$Symbolic;
public fun bindSymbolOrNull (Ljava/lang/String;)Lspace/kscience/kmath/expressions/Symbol;
public synthetic fun divide (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
public fun divide (Lspace/kscience/kmath/expressions/MST;Lspace/kscience/kmath/expressions/MST;)Lspace/kscience/kmath/expressions/MST$Binary;
public synthetic fun getOne ()Ljava/lang/Object;
@ -312,7 +289,7 @@ public final class space/kscience/kmath/expressions/MstGroup : space/kscience/km
public fun add (Lspace/kscience/kmath/expressions/MST;Lspace/kscience/kmath/expressions/MST;)Lspace/kscience/kmath/expressions/MST$Binary;
public fun binaryOperationFunction (Ljava/lang/String;)Lkotlin/jvm/functions/Function2;
public synthetic fun bindSymbolOrNull (Ljava/lang/String;)Ljava/lang/Object;
public fun bindSymbolOrNull (Ljava/lang/String;)Lspace/kscience/kmath/expressions/MST$Symbolic;
public fun bindSymbolOrNull (Ljava/lang/String;)Lspace/kscience/kmath/expressions/Symbol;
public synthetic fun getZero ()Ljava/lang/Object;
public fun getZero ()Lspace/kscience/kmath/expressions/MST$Numeric;
public synthetic fun minus (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
@ -328,13 +305,25 @@ public final class space/kscience/kmath/expressions/MstGroup : space/kscience/km
public fun unaryPlus (Lspace/kscience/kmath/expressions/MST;)Lspace/kscience/kmath/expressions/MST$Unary;
}
public final class space/kscience/kmath/expressions/MstNumericAlgebra : space/kscience/kmath/operations/NumericAlgebra {
public static final field INSTANCE Lspace/kscience/kmath/expressions/MstNumericAlgebra;
public fun binaryOperationFunction (Ljava/lang/String;)Lkotlin/jvm/functions/Function2;
public synthetic fun bindSymbol (Ljava/lang/String;)Ljava/lang/Object;
public fun bindSymbol (Ljava/lang/String;)Lspace/kscience/kmath/expressions/Symbol;
public synthetic fun bindSymbolOrNull (Ljava/lang/String;)Ljava/lang/Object;
public fun bindSymbolOrNull (Ljava/lang/String;)Lspace/kscience/kmath/expressions/Symbol;
public synthetic fun number (Ljava/lang/Number;)Ljava/lang/Object;
public fun number (Ljava/lang/Number;)Lspace/kscience/kmath/expressions/MST$Numeric;
public fun unaryOperationFunction (Ljava/lang/String;)Lkotlin/jvm/functions/Function1;
}
public final class space/kscience/kmath/expressions/MstRing : space/kscience/kmath/operations/NumbersAddOperations, space/kscience/kmath/operations/Ring, space/kscience/kmath/operations/ScaleOperations {
public static final field INSTANCE Lspace/kscience/kmath/expressions/MstRing;
public synthetic fun add (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
public fun add (Lspace/kscience/kmath/expressions/MST;Lspace/kscience/kmath/expressions/MST;)Lspace/kscience/kmath/expressions/MST$Binary;
public fun binaryOperationFunction (Ljava/lang/String;)Lkotlin/jvm/functions/Function2;
public synthetic fun bindSymbolOrNull (Ljava/lang/String;)Ljava/lang/Object;
public fun bindSymbolOrNull (Ljava/lang/String;)Lspace/kscience/kmath/expressions/MST$Symbolic;
public fun bindSymbolOrNull (Ljava/lang/String;)Lspace/kscience/kmath/expressions/Symbol;
public synthetic fun getOne ()Ljava/lang/Object;
public fun getOne ()Lspace/kscience/kmath/expressions/MST$Numeric;
public synthetic fun getZero ()Ljava/lang/Object;
@ -356,7 +345,7 @@ public final class space/kscience/kmath/expressions/MstRing : space/kscience/kma
public final class space/kscience/kmath/expressions/SimpleAutoDiffExpression : space/kscience/kmath/expressions/FirstDerivativeExpression {
public fun <init> (Lspace/kscience/kmath/operations/Field;Lkotlin/jvm/functions/Function1;)V
public fun derivativeOrNull (Lspace/kscience/kmath/misc/Symbol;)Lspace/kscience/kmath/expressions/Expression;
public fun derivativeOrNull (Lspace/kscience/kmath/expressions/Symbol;)Lspace/kscience/kmath/expressions/Expression;
public final fun getField ()Lspace/kscience/kmath/operations/Field;
public final fun getFunction ()Lkotlin/jvm/functions/Function1;
public fun invoke (Ljava/util/Map;)Ljava/lang/Object;
@ -445,7 +434,7 @@ public final class space/kscience/kmath/expressions/SimpleAutoDiffKt {
public static final fun cos (Lspace/kscience/kmath/expressions/SimpleAutoDiffField;Lspace/kscience/kmath/expressions/AutoDiffValue;)Lspace/kscience/kmath/expressions/AutoDiffValue;
public static final fun cosh (Lspace/kscience/kmath/expressions/SimpleAutoDiffField;Lspace/kscience/kmath/expressions/AutoDiffValue;)Lspace/kscience/kmath/expressions/AutoDiffValue;
public static final fun exp (Lspace/kscience/kmath/expressions/SimpleAutoDiffField;Lspace/kscience/kmath/expressions/AutoDiffValue;)Lspace/kscience/kmath/expressions/AutoDiffValue;
public static final fun grad (Lspace/kscience/kmath/expressions/DerivationResult;[Lspace/kscience/kmath/misc/Symbol;)Lspace/kscience/kmath/structures/Buffer;
public static final fun grad (Lspace/kscience/kmath/expressions/DerivationResult;[Lspace/kscience/kmath/expressions/Symbol;)Lspace/kscience/kmath/structures/Buffer;
public static final fun ln (Lspace/kscience/kmath/expressions/SimpleAutoDiffField;Lspace/kscience/kmath/expressions/AutoDiffValue;)Lspace/kscience/kmath/expressions/AutoDiffValue;
public static final fun pow (Lspace/kscience/kmath/expressions/SimpleAutoDiffField;Lspace/kscience/kmath/expressions/AutoDiffValue;D)Lspace/kscience/kmath/expressions/AutoDiffValue;
public static final fun pow (Lspace/kscience/kmath/expressions/SimpleAutoDiffField;Lspace/kscience/kmath/expressions/AutoDiffValue;I)Lspace/kscience/kmath/expressions/AutoDiffValue;
@ -461,9 +450,42 @@ public final class space/kscience/kmath/expressions/SimpleAutoDiffKt {
public static final fun tanh (Lspace/kscience/kmath/expressions/SimpleAutoDiffField;Lspace/kscience/kmath/expressions/AutoDiffValue;)Lspace/kscience/kmath/expressions/AutoDiffValue;
}
public final class space/kscience/kmath/expressions/StringSymbol : space/kscience/kmath/expressions/Symbol {
public static final synthetic fun box-impl (Ljava/lang/String;)Lspace/kscience/kmath/expressions/StringSymbol;
public static fun constructor-impl (Ljava/lang/String;)Ljava/lang/String;
public fun equals (Ljava/lang/Object;)Z
public static fun equals-impl (Ljava/lang/String;Ljava/lang/Object;)Z
public static final fun equals-impl0 (Ljava/lang/String;Ljava/lang/String;)Z
public fun getIdentity ()Ljava/lang/String;
public fun hashCode ()I
public static fun hashCode-impl (Ljava/lang/String;)I
public fun toString ()Ljava/lang/String;
public static fun toString-impl (Ljava/lang/String;)Ljava/lang/String;
public final synthetic fun unbox-impl ()Ljava/lang/String;
}
public abstract interface class space/kscience/kmath/expressions/Symbol : space/kscience/kmath/expressions/MST {
public static final field Companion Lspace/kscience/kmath/expressions/Symbol$Companion;
public abstract fun getIdentity ()Ljava/lang/String;
}
public final class space/kscience/kmath/expressions/Symbol$Companion {
public final fun getX-uKgCeAI ()Ljava/lang/String;
public final fun getY-uKgCeAI ()Ljava/lang/String;
public final fun getZ-uKgCeAI ()Ljava/lang/String;
}
public final class space/kscience/kmath/expressions/SymbolIndexerKt {
}
public final class space/kscience/kmath/expressions/SymbolKt {
public static final fun get (Ljava/util/Map;Ljava/lang/String;)Ljava/lang/Object;
public static final fun get (Ljava/util/Map;Lspace/kscience/kmath/expressions/Symbol;)Ljava/lang/Object;
public static final fun getSymbol ()Lkotlin/properties/ReadOnlyProperty;
public static final fun set (Ljava/util/Map;Ljava/lang/String;Ljava/lang/Object;)V
public static final fun set (Ljava/util/Map;Lspace/kscience/kmath/expressions/Symbol;Ljava/lang/Object;)V
}
public final class space/kscience/kmath/linear/BufferedLinearSpace : space/kscience/kmath/linear/LinearSpace {
public fun <init> (Lspace/kscience/kmath/operations/Ring;Lkotlin/jvm/functions/Function2;)V
public fun buildMatrix (IILkotlin/jvm/functions/Function3;)Lspace/kscience/kmath/nd/Structure2D;
@ -500,6 +522,11 @@ public final class space/kscience/kmath/linear/LFeature : space/kscience/kmath/l
public static final field INSTANCE Lspace/kscience/kmath/linear/LFeature;
}
public abstract interface class space/kscience/kmath/linear/LUDecompositionFeature : space/kscience/kmath/linear/MatrixFeature {
public abstract fun getL ()Lspace/kscience/kmath/nd/Structure2D;
public abstract fun getU ()Lspace/kscience/kmath/nd/Structure2D;
}
public abstract interface class space/kscience/kmath/linear/LinearSolver {
public abstract fun inverse (Lspace/kscience/kmath/nd/Structure2D;)Lspace/kscience/kmath/nd/Structure2D;
public abstract fun solve (Lspace/kscience/kmath/nd/Structure2D;Lspace/kscience/kmath/nd/Structure2D;)Lspace/kscience/kmath/nd/Structure2D;
@ -677,39 +704,6 @@ public final class space/kscience/kmath/misc/CumulativeKt {
public abstract interface annotation class space/kscience/kmath/misc/PerformancePitfall : java/lang/annotation/Annotation {
}
public final class space/kscience/kmath/misc/StringSymbol : space/kscience/kmath/misc/Symbol {
public static final synthetic fun box-impl (Ljava/lang/String;)Lspace/kscience/kmath/misc/StringSymbol;
public static fun constructor-impl (Ljava/lang/String;)Ljava/lang/String;
public fun equals (Ljava/lang/Object;)Z
public static fun equals-impl (Ljava/lang/String;Ljava/lang/Object;)Z
public static final fun equals-impl0 (Ljava/lang/String;Ljava/lang/String;)Z
public fun getIdentity ()Ljava/lang/String;
public fun hashCode ()I
public static fun hashCode-impl (Ljava/lang/String;)I
public fun toString ()Ljava/lang/String;
public static fun toString-impl (Ljava/lang/String;)Ljava/lang/String;
public final synthetic fun unbox-impl ()Ljava/lang/String;
}
public abstract interface class space/kscience/kmath/misc/Symbol {
public static final field Companion Lspace/kscience/kmath/misc/Symbol$Companion;
public abstract fun getIdentity ()Ljava/lang/String;
}
public final class space/kscience/kmath/misc/Symbol$Companion {
public final fun getX-tWtZOCg ()Ljava/lang/String;
public final fun getY-tWtZOCg ()Ljava/lang/String;
public final fun getZ-tWtZOCg ()Ljava/lang/String;
}
public final class space/kscience/kmath/misc/SymbolKt {
public static final fun get (Ljava/util/Map;Ljava/lang/String;)Ljava/lang/Object;
public static final fun get (Ljava/util/Map;Lspace/kscience/kmath/misc/Symbol;)Ljava/lang/Object;
public static final fun getSymbol ()Lkotlin/properties/ReadOnlyProperty;
public static final fun set (Ljava/util/Map;Ljava/lang/String;Ljava/lang/Object;)V
public static final fun set (Ljava/util/Map;Lspace/kscience/kmath/misc/Symbol;Ljava/lang/Object;)V
}
public abstract interface annotation class space/kscience/kmath/misc/UnstableKMathAPI : java/lang/annotation/Annotation {
}
@ -1028,8 +1022,8 @@ public final class space/kscience/kmath/operations/AlgebraExtensionsKt {
}
public final class space/kscience/kmath/operations/AlgebraKt {
public static final fun bindSymbol (Lspace/kscience/kmath/operations/Algebra;Lspace/kscience/kmath/misc/Symbol;)Ljava/lang/Object;
public static final fun bindSymbolOrNull (Lspace/kscience/kmath/operations/Algebra;Lspace/kscience/kmath/misc/Symbol;)Ljava/lang/Object;
public static final fun bindSymbol (Lspace/kscience/kmath/operations/Algebra;Lspace/kscience/kmath/expressions/Symbol;)Ljava/lang/Object;
public static final fun bindSymbolOrNull (Lspace/kscience/kmath/operations/Algebra;Lspace/kscience/kmath/expressions/Symbol;)Ljava/lang/Object;
public static final fun invoke (Lspace/kscience/kmath/operations/Algebra;Lkotlin/jvm/functions/Function1;)Ljava/lang/Object;
}
@ -1414,6 +1408,11 @@ public final class space/kscience/kmath/operations/JBigIntegerField : space/ksci
public abstract interface annotation class space/kscience/kmath/operations/KMathContext : java/lang/annotation/Annotation {
}
public final class space/kscience/kmath/operations/LogicAlgebra$Companion {
public final fun getFALSE ()Lspace/kscience/kmath/expressions/Symbol;
public final fun getTRUE ()Lspace/kscience/kmath/expressions/Symbol;
}
public final class space/kscience/kmath/operations/LongRing : space/kscience/kmath/operations/Norm, space/kscience/kmath/operations/NumericAlgebra, space/kscience/kmath/operations/Ring {
public static final field INSTANCE Lspace/kscience/kmath/operations/LongRing;
public fun add (JJ)Ljava/lang/Long;

View File

@ -5,8 +5,8 @@
package space.kscience.kmath.data
import space.kscience.kmath.expressions.Symbol
import space.kscience.kmath.misc.PerformancePitfall
import space.kscience.kmath.misc.Symbol
import space.kscience.kmath.misc.UnstableKMathAPI
import space.kscience.kmath.nd.Structure2D
import space.kscience.kmath.structures.Buffer
@ -19,7 +19,10 @@ import space.kscience.kmath.structures.Buffer
public interface ColumnarData<out T> {
public val size: Int
public operator fun get(symbol: Symbol): Buffer<T>
/**
* Provide a column by symbol or null if column with given symbol is not defined
*/
public operator fun get(symbol: Symbol): Buffer<T>?
}
/**

View File

@ -5,8 +5,8 @@
package space.kscience.kmath.data
import space.kscience.kmath.expressions.Symbol
import space.kscience.kmath.misc.PerformancePitfall
import space.kscience.kmath.misc.Symbol
import space.kscience.kmath.misc.UnstableKMathAPI
import space.kscience.kmath.nd.Structure2D
import space.kscience.kmath.structures.Buffer
@ -27,10 +27,10 @@ public interface XYColumnarData<T, out X : T, out Y : T> : ColumnarData<T> {
*/
public val y: Buffer<Y>
override fun get(symbol: Symbol): Buffer<T> = when (symbol) {
override fun get(symbol: Symbol): Buffer<T>? = when (symbol) {
Symbol.x -> x
Symbol.y -> y
else -> error("A column for symbol $symbol not found")
else -> null
}
}

View File

@ -5,7 +5,7 @@
package space.kscience.kmath.data
import space.kscience.kmath.misc.Symbol
import space.kscience.kmath.expressions.Symbol
import space.kscience.kmath.misc.UnstableKMathAPI
import space.kscience.kmath.structures.Buffer
@ -17,10 +17,10 @@ import space.kscience.kmath.structures.Buffer
public interface XYZColumnarData<T, out X : T, out Y : T, out Z : T> : XYColumnarData<T, X, Y> {
public val z: Buffer<Z>
override fun get(symbol: Symbol): Buffer<T> = when (symbol) {
override fun get(symbol: Symbol): Buffer<T>? = when (symbol) {
Symbol.x -> x
Symbol.y -> y
Symbol.z -> z
else -> error("A column for symbol $symbol not found")
else -> null
}
}

View File

@ -5,9 +5,6 @@
package space.kscience.kmath.expressions
import space.kscience.kmath.misc.StringSymbol
import space.kscience.kmath.misc.Symbol
/**
* Represents expression which structure can be differentiated.
*

View File

@ -5,8 +5,6 @@
package space.kscience.kmath.expressions
import space.kscience.kmath.misc.StringSymbol
import space.kscience.kmath.misc.Symbol
import space.kscience.kmath.operations.Algebra
import kotlin.jvm.JvmName
import kotlin.properties.ReadOnlyProperty

View File

@ -5,7 +5,6 @@
package space.kscience.kmath.expressions
import space.kscience.kmath.misc.StringSymbol
import space.kscience.kmath.operations.*
/**

View File

@ -5,30 +5,23 @@
package space.kscience.kmath.expressions
import space.kscience.kmath.misc.StringSymbol
import space.kscience.kmath.misc.Symbol
import space.kscience.kmath.operations.Algebra
import space.kscience.kmath.operations.NumericAlgebra
import space.kscience.kmath.operations.bindSymbol
/**
* A Mathematical Syntax Tree (MST) node for mathematical expressions.
*
* @author Alexander Nozik
*/
public sealed class MST {
/**
* A node containing raw string.
*
* @property value the value of this node.
*/
public data class Symbolic(val value: String) : MST()
public sealed interface MST {
/**
* A node containing a numeric value or scalar.
*
* @property value the value of this number.
*/
public data class Numeric(val value: Number) : MST()
public data class Numeric(val value: Number) : MST
/**
* A node containing an unary operation.
@ -36,7 +29,7 @@ public sealed class MST {
* @property operation the identifier of operation.
* @property value the argument of this operation.
*/
public data class Unary(val operation: String, val value: MST) : MST()
public data class Unary(val operation: String, val value: MST) : MST
/**
* A node containing binary operation.
@ -45,7 +38,7 @@ public sealed class MST {
* @property left the left operand.
* @property right the right operand.
*/
public data class Binary(val operation: String, val left: MST, val right: MST) : MST()
public data class Binary(val operation: String, val left: MST, val right: MST) : MST
}
// TODO add a function with named arguments
@ -62,7 +55,7 @@ public fun <T> Algebra<T>.evaluate(node: MST): T = when (node) {
is MST.Numeric -> (this as? NumericAlgebra<T>)?.number(node.value)
?: error("Numeric nodes are not supported by $this")
is MST.Symbolic -> bindSymbol(node.value)
is Symbol -> bindSymbol(node)
is MST.Unary -> when {
this is NumericAlgebra && node.value is MST.Numeric -> unaryOperationFunction(node.operation)(number(node.value.value))
@ -83,7 +76,7 @@ public fun <T> Algebra<T>.evaluate(node: MST): T = when (node) {
}
}
internal class InnerAlgebra<T : Any>(val algebra: Algebra<T>, val arguments: Map<Symbol, T>) : NumericAlgebra<T> {
internal class InnerAlgebra<T>(val algebra: Algebra<T>, val arguments: Map<Symbol, T>) : NumericAlgebra<T> {
override fun bindSymbolOrNull(value: String): T? = algebra.bindSymbolOrNull(value) ?: arguments[StringSymbol(value)]
override fun unaryOperation(operation: String, arg: T): T =
@ -108,7 +101,7 @@ internal class InnerAlgebra<T : Any>(val algebra: Algebra<T>, val arguments: Map
/**
* Interprets the [MST] node with this [Algebra] and optional [arguments]
*/
public fun <T : Any> MST.interpret(algebra: Algebra<T>, arguments: Map<Symbol, T>): T =
public fun <T> MST.interpret(algebra: Algebra<T>, arguments: Map<Symbol, T>): T =
InnerAlgebra(algebra, arguments).evaluate(this)
/**
@ -118,7 +111,7 @@ public fun <T : Any> MST.interpret(algebra: Algebra<T>, arguments: Map<Symbol, T
* @param algebra the algebra that provides operations.
* @return the value of expression.
*/
public fun <T : Any> MST.interpret(algebra: Algebra<T>, vararg arguments: Pair<Symbol, T>): T =
public fun <T> MST.interpret(algebra: Algebra<T>, vararg arguments: Pair<Symbol, T>): T =
interpret(algebra, mapOf(*arguments))
/**

View File

@ -11,10 +11,10 @@ import space.kscience.kmath.operations.*
/**
* [Algebra] over [MST] nodes.
*/
public object MstAlgebra : NumericAlgebra<MST> {
public object MstNumericAlgebra : NumericAlgebra<MST> {
public override fun number(value: Number): MST.Numeric = MST.Numeric(value)
public override fun bindSymbolOrNull(value: String): MST.Symbolic = MST.Symbolic(value)
override fun bindSymbol(value: String): MST.Symbolic = bindSymbolOrNull(value)
public override fun bindSymbolOrNull(value: String): Symbol = StringSymbol(value)
override fun bindSymbol(value: String): Symbol = bindSymbolOrNull(value)
public override fun unaryOperationFunction(operation: String): (arg: MST) -> MST.Unary =
{ arg -> MST.Unary(operation, arg) }
@ -29,8 +29,8 @@ public object MstAlgebra : NumericAlgebra<MST> {
public object MstGroup : Group<MST>, NumericAlgebra<MST>, ScaleOperations<MST> {
public override val zero: MST.Numeric = number(0.0)
public override fun number(value: Number): MST.Numeric = MstAlgebra.number(value)
public override fun bindSymbolOrNull(value: String): MST.Symbolic = MstAlgebra.bindSymbolOrNull(value)
public override fun number(value: Number): MST.Numeric = MstNumericAlgebra.number(value)
public override fun bindSymbolOrNull(value: String): Symbol = MstNumericAlgebra.bindSymbolOrNull(value)
public override fun add(a: MST, b: MST): MST.Binary = binaryOperationFunction(GroupOperations.PLUS_OPERATION)(a, b)
public override operator fun MST.unaryPlus(): MST.Unary =
unaryOperationFunction(GroupOperations.PLUS_OPERATION)(this)
@ -45,10 +45,10 @@ public object MstGroup : Group<MST>, NumericAlgebra<MST>, ScaleOperations<MST> {
binaryOperationFunction(RingOperations.TIMES_OPERATION)(a, number(value))
public override fun binaryOperationFunction(operation: String): (left: MST, right: MST) -> MST.Binary =
MstAlgebra.binaryOperationFunction(operation)
MstNumericAlgebra.binaryOperationFunction(operation)
public override fun unaryOperationFunction(operation: String): (arg: MST) -> MST.Unary =
MstAlgebra.unaryOperationFunction(operation)
MstNumericAlgebra.unaryOperationFunction(operation)
}
/**
@ -61,7 +61,7 @@ public object MstRing : Ring<MST>, NumbersAddOperations<MST>, ScaleOperations<MS
public override val one: MST.Numeric = number(1.0)
public override fun number(value: Number): MST.Numeric = MstGroup.number(value)
public override fun bindSymbolOrNull(value: String): MST.Symbolic = MstAlgebra.bindSymbolOrNull(value)
public override fun bindSymbolOrNull(value: String): Symbol = MstNumericAlgebra.bindSymbolOrNull(value)
public override fun add(a: MST, b: MST): MST.Binary = MstGroup.add(a, b)
public override fun scale(a: MST, value: Double): MST.Binary =
@ -78,7 +78,7 @@ public object MstRing : Ring<MST>, NumbersAddOperations<MST>, ScaleOperations<MS
MstGroup.binaryOperationFunction(operation)
public override fun unaryOperationFunction(operation: String): (arg: MST) -> MST.Unary =
MstAlgebra.unaryOperationFunction(operation)
MstNumericAlgebra.unaryOperationFunction(operation)
}
/**
@ -90,7 +90,7 @@ public object MstField : Field<MST>, NumbersAddOperations<MST>, ScaleOperations<
public override inline val zero: MST.Numeric get() = MstRing.zero
public override inline val one: MST.Numeric get() = MstRing.one
public override fun bindSymbolOrNull(value: String): MST.Symbolic = MstAlgebra.bindSymbolOrNull(value)
public override fun bindSymbolOrNull(value: String): Symbol = MstNumericAlgebra.bindSymbolOrNull(value)
public override fun number(value: Number): MST.Numeric = MstRing.number(value)
public override fun add(a: MST, b: MST): MST.Binary = MstRing.add(a, b)
@ -120,7 +120,7 @@ public object MstExtendedField : ExtendedField<MST>, NumericAlgebra<MST> {
public override inline val zero: MST.Numeric get() = MstField.zero
public override inline val one: MST.Numeric get() = MstField.one
public override fun bindSymbolOrNull(value: String): MST.Symbolic = MstAlgebra.bindSymbolOrNull(value)
public override fun bindSymbolOrNull(value: String): Symbol = MstNumericAlgebra.bindSymbolOrNull(value)
public override fun number(value: Number): MST.Numeric = MstRing.number(value)
public override fun sin(arg: MST): MST.Unary = unaryOperationFunction(TrigonometricOperations.SIN_OPERATION)(arg)
public override fun cos(arg: MST): MST.Unary = unaryOperationFunction(TrigonometricOperations.COS_OPERATION)(arg)
@ -158,3 +158,25 @@ public object MstExtendedField : ExtendedField<MST>, NumericAlgebra<MST> {
public override fun unaryOperationFunction(operation: String): (arg: MST) -> MST.Unary =
MstField.unaryOperationFunction(operation)
}
/**
* Logic algebra for [MST]
*/
@UnstableKMathAPI
public object MstLogicAlgebra : LogicAlgebra<MST> {
public override fun bindSymbolOrNull(value: String): MST = super.bindSymbolOrNull(value) ?: StringSymbol(value)
override fun const(boolean: Boolean): Symbol = if (boolean) {
LogicAlgebra.TRUE
} else {
LogicAlgebra.FALSE
}
override fun MST.not(): MST = MST.Unary(Boolean::not.name, this)
override fun MST.and(other: MST): MST = MST.Binary(Boolean::and.name, this, other)
override fun MST.or(other: MST): MST = MST.Binary(Boolean::or.name, this, other)
override fun MST.xor(other: MST): MST = MST.Binary(Boolean::xor.name, this, other)
}

View File

@ -6,7 +6,6 @@
package space.kscience.kmath.expressions
import space.kscience.kmath.linear.Point
import space.kscience.kmath.misc.Symbol
import space.kscience.kmath.misc.UnstableKMathAPI
import space.kscience.kmath.operations.*
import space.kscience.kmath.structures.asBuffer

View File

@ -3,15 +3,16 @@
* 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.misc
package space.kscience.kmath.expressions
import kotlin.jvm.JvmInline
import kotlin.properties.ReadOnlyProperty
/**
* A marker interface for a symbol. A symbol mus have an identity
* A marker interface for a symbol. A symbol must have an identity.
* Ic
*/
public interface Symbol {
public interface Symbol: MST {
/**
* Identity object for the symbol. Two symbols with the same identity are considered to be the same symbol.
*/

View File

@ -6,7 +6,6 @@
package space.kscience.kmath.expressions
import space.kscience.kmath.linear.Point
import space.kscience.kmath.misc.Symbol
import space.kscience.kmath.misc.UnstableKMathAPI
import space.kscience.kmath.nd.Structure2D
import space.kscience.kmath.structures.BufferFactory

View File

@ -5,8 +5,7 @@
package space.kscience.kmath.operations
import space.kscience.kmath.misc.Symbol
import space.kscience.kmath.misc.UnstableKMathAPI
import space.kscience.kmath.expressions.Symbol
/**
* Stub for DSL the [Algebra] is.
@ -85,7 +84,7 @@ public interface Algebra<T> {
* @return an operation.
*/
public fun binaryOperationFunction(operation: String): (left: T, right: T) -> T =
error("Binary operation $operation not defined in $this")
error("Binary operation '$operation' not defined in $this")
/**
* Dynamically invokes a binary operation with the certain name.

View File

@ -0,0 +1,85 @@
/*
* 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.expressions.Symbol
import space.kscience.kmath.expressions.symbol
import space.kscience.kmath.misc.UnstableKMathAPI
/**
* An algebra for generic boolean logic
*/
@UnstableKMathAPI
public interface LogicAlgebra<T : Any> : Algebra<T> {
/**
* Represent constant [Boolean] as [T]
*/
public fun const(boolean: Boolean): T
override fun bindSymbolOrNull(value: String): T? = value.lowercase().toBooleanStrictOrNull()?.let(::const)
override fun unaryOperation(operation: String, arg: T): T = when (operation) {
Boolean::not.name -> arg.not()
else -> super.unaryOperation(operation, arg)
}
override fun unaryOperationFunction(operation: String): (arg: T) -> T = { unaryOperation(operation, it) }
override fun binaryOperation(operation: String, left: T, right: T): T = when (operation) {
Boolean::and.name -> left.and(right)
Boolean::or.name -> left.or(right)
else -> super.binaryOperation(operation, left, right)
}
override fun binaryOperationFunction(operation: String): (left: T, right: T) -> T = { l, r ->
binaryOperation(operation, l, r)
}
/**
* Logic 'not'
*/
public operator fun T.not(): T
/**
* Logic 'and'
*/
public infix fun T.and(other: T): T
/**
* Logic 'or'
*/
public infix fun T.or(other: T): T
/**
* Logic 'xor'
*/
public infix fun T.xor(other: T): T
public companion object {
public val TRUE: Symbol by symbol
public val FALSE: Symbol by symbol
}
}
/**
* An implementation of [LogicAlgebra] for primitive booleans
*/
@UnstableKMathAPI
@Suppress("EXTENSION_SHADOWED_BY_MEMBER")
public object BooleanAlgebra : LogicAlgebra<Boolean> {
override fun const(boolean: Boolean): Boolean = boolean
override fun Boolean.not(): Boolean = !this
override fun Boolean.and(other: Boolean): Boolean = this && other
override fun Boolean.or(other: Boolean): Boolean = this || other
override fun Boolean.xor(other: Boolean): Boolean = this xor other
}

View File

@ -5,9 +5,7 @@
package space.kscience.kmath.expressions
import space.kscience.kmath.misc.symbol
import space.kscience.kmath.operations.DoubleField
import space.kscience.kmath.operations.invoke
import kotlin.test.Test
import kotlin.test.assertEquals
import kotlin.test.assertFails
@ -17,7 +15,7 @@ class ExpressionFieldTest {
@Test
fun testExpression() {
val expression = FunctionalExpressionField(DoubleField).invoke {
val expression = with(FunctionalExpressionField(DoubleField)) {
val x by binding()
x * x + 2 * x + one
}

View File

@ -5,19 +5,32 @@
package space.kscience.kmath.expressions
import space.kscience.kmath.misc.Symbol
import space.kscience.kmath.expressions.Symbol.Companion.x
import space.kscience.kmath.misc.UnstableKMathAPI
import space.kscience.kmath.operations.BooleanAlgebra
import space.kscience.kmath.operations.DoubleField
import space.kscience.kmath.operations.bindSymbol
import space.kscience.kmath.operations.invoke
import kotlin.test.Test
import kotlin.test.assertEquals
internal class InterpretTest {
@Test
fun interpretation() {
val expr = MstField {
val x = bindSymbol(Symbol.x)
x * 2.0 + number(2.0) / x - 16.0
}.toExpression(DoubleField)
expr(Symbol.x to 2.2)
assertEquals(-10.69, expr(x to 2.2), 0.02)
}
@Test
@UnstableKMathAPI
fun booleanAlgebra() {
val expr = MstLogicAlgebra {
x and const(true)
}.toExpression(BooleanAlgebra)
assertEquals(true, expr(x to true))
assertEquals(false, expr(x to false))
}
}

View File

@ -5,8 +5,6 @@
package 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.bindSymbol
import space.kscience.kmath.structures.Buffer

View File

@ -79,4 +79,13 @@ public class OrderedPiecewisePolynomial<T : Comparable<T>>(delimiter: T) :
public fun <T : Comparable<T>, C : Ring<T>> PiecewisePolynomial<T>.value(ring: C, arg: T): T? =
findPiece(arg)?.value(ring, arg)
/**
* Convert this polynomial to a function returning nullable value (null if argument is outside piecewise range).
*/
public fun <T : Comparable<T>, C : Ring<T>> PiecewisePolynomial<T>.asFunction(ring: C): (T) -> T? = { value(ring, it) }
/**
* Convert this polynomial to a function using [defaultValue] for arguments outside the piecewise range.
*/
public fun <T : Comparable<T>, C : Ring<T>> PiecewisePolynomial<T>.asFunction(ring: C, defaultValue: T): (T) -> T =
{ value(ring, it) ?: defaultValue }

View File

@ -6,7 +6,9 @@ package space.kscience.kmath.integration
import space.kscience.kmath.misc.UnstableKMathAPI
import space.kscience.kmath.operations.Field
import space.kscience.kmath.structures.*
import space.kscience.kmath.structures.Buffer
import space.kscience.kmath.structures.asBuffer
import space.kscience.kmath.structures.indices
/**
* Set of univariate integration ranges. First components correspond to ranges themselves, second components to number of
@ -66,31 +68,25 @@ public class GaussIntegrator<T : Any>(
return integrand + IntegrandValue(res) + IntegrandCallsPerformed(integrand.calls + points.size)
}
public companion object {
}
public companion object
}
/**
* Integrate [T]-valued univariate function using provided set of [IntegrandFeature]
* Following features are evaluated:
* Create a Gauss-Legendre integrator for this field
* Following integrand features are accepted:
* * [GaussIntegratorRuleFactory] - A factory for computing the Gauss integration rule. By default uses [GaussLegendreRuleFactory]
* * [IntegrationRange] - the univariate range of integration. By default uses 0..1 interval.
* * [IntegrandMaxCalls] - the maximum number of function calls during integration. For non-iterative rules, always uses the maximum number of points. By default uses 10 points.
* * [UnivariateIntegrandRanges] - Set of ranges and number of points per range. Defaults to given [IntegrationRange] and [IntegrandMaxCalls]
*/
@UnstableKMathAPI
public fun <T : Any> Field<T>.integrate(
vararg features: IntegrandFeature,
function: (Double) -> T,
): UnivariateIntegrand<T> = GaussIntegrator(this).integrate(UnivariateIntegrand(function, *features))
public val <T:Any> Field<T>.integrator: GaussIntegrator<T> get() = GaussIntegrator(this)
/**
* Use [GaussIntegrator.Companion.integrate] to integrate the function in the current algebra with given [range] and [numPoints]
* Integrate using [intervals] segments with Gauss-Legendre rule of [order] order
*/
@UnstableKMathAPI
public fun <T : Any> Field<T>.integrate(
public fun <T : Any> GaussIntegrator<T>.integrate(
range: ClosedRange<Double>,
order: Int = 10,
intervals: Int = 10,
@ -104,7 +100,7 @@ public fun <T : Any> Field<T>.integrate(
val ranges = UnivariateIntegrandRanges(
(0 until intervals).map { i -> (rangeSize * i)..(rangeSize * (i + 1)) to order }
)
return GaussIntegrator(this).integrate(
return integrate(
UnivariateIntegrand(
function,
IntegrationRange(range),

View File

@ -35,37 +35,41 @@ public typealias UnivariateIntegrator<T> = Integrator<UnivariateIntegrand<T>>
@JvmInline
public value class IntegrationRange(public val range: ClosedRange<Double>) : IntegrandFeature
public val <T : Any> UnivariateIntegrand<T>.value: T? get() = getFeature<IntegrandValue<T>>()?.value
/**
* Value of the integrand if it is present or null
*/
public val <T : Any> UnivariateIntegrand<T>.valueOrNull: T? get() = getFeature<IntegrandValue<T>>()?.value
/**
* Value of the integrand or error
*/
public val <T : Any> UnivariateIntegrand<T>.value: T get() = valueOrNull ?: error("No value in the integrand")
/**
* A shortcut method to integrate a [function] in [range] with additional [features].
* The [function] is placed in the end position to allow passing a lambda.
*/
@UnstableKMathAPI
public fun UnivariateIntegrator<Double>.integrate(
public fun <T: Any> UnivariateIntegrator<T>.integrate(
range: ClosedRange<Double>,
vararg features: IntegrandFeature,
function: (Double) -> Double,
): Double = integrate(
UnivariateIntegrand(function, IntegrationRange(range), *features)
).value ?: error("Unexpected: no value after integration.")
function: (Double) -> T,
): UnivariateIntegrand<T> = integrate(UnivariateIntegrand(function, IntegrationRange(range), *features))
/**
* A shortcut method to integrate a [function] in [range] with additional [features].
* The [function] is placed in the end position to allow passing a lambda.
*/
@UnstableKMathAPI
public fun UnivariateIntegrator<Double>.integrate(
public fun <T: Any> UnivariateIntegrator<T>.integrate(
range: ClosedRange<Double>,
featureBuilder: MutableList<IntegrandFeature>.() -> Unit = {},
function: (Double) -> Double,
): Double {
function: (Double) -> T,
): UnivariateIntegrand<T> {
//TODO use dedicated feature builder class instead or add extensions to MutableList<IntegrandFeature>
val features = buildList {
featureBuilder()
add(IntegrationRange(range))
}
return integrate(
UnivariateIntegrand(function, *features.toTypedArray())
).value ?: error("Unexpected: no value after integration.")
return integrate(UnivariateIntegrand(function, *features.toTypedArray()))
}

View File

@ -42,9 +42,11 @@ public class SplineInterpolator<T : Comparable<T>>(
val g = 2.0 * (points.x[i + 1] - points.x[i - 1]) - h[i - 1] * mu[i - 1]
mu[i] = h[i] / g
z[i] =
(3.0 * (points.y[i + 1] * h[i - 1] - points.x[i] * (points.x[i + 1] - points.x[i - 1]) + points.y[i - 1] * h[i]) / (h[i - 1] * h[i])
- h[i - 1] * z[i - 1]) / g
z[i] = (3.0 * (points.y[i + 1] * h[i - 1]
- points.x[i] * (points.x[i + 1] - points.x[i - 1])
+ points.y[i - 1] * h[i]) / (h[i - 1] * h[i])
- h[i - 1] * z[i - 1]
) / g
}
// cubic spline coefficients -- b is linear, c quadratic, d is cubic (original y's are constants)

View File

@ -16,22 +16,22 @@ import kotlin.test.assertEquals
class GaussIntegralTest {
@Test
fun gaussSin() {
val res = DoubleField.integrate(0.0..2 * PI) { x ->
val res = DoubleField.integrator.integrate(0.0..2 * PI) { x ->
sin(x)
}
assertEquals(0.0, res.value!!, 1e-2)
assertEquals(0.0, res.valueOrNull!!, 1e-2)
}
@Test
fun gaussUniform() {
val res = DoubleField.integrate(0.0..100.0) { x ->
val res = DoubleField.integrator.integrate(0.0..100.0) { x ->
if(x in 30.0..50.0){
1.0
} else {
0.0
}
}
assertEquals(20.0, res.value!!, 0.5)
assertEquals(20.0, res.valueOrNull!!, 0.5)
}

View File

@ -7,11 +7,7 @@ package space.kscience.kmath.kotlingrad
import edu.umontreal.kotlingrad.api.SFun
import edu.umontreal.kotlingrad.api.SVar
import space.kscience.kmath.expressions.DifferentiableExpression
import space.kscience.kmath.expressions.MST
import space.kscience.kmath.expressions.MstAlgebra
import space.kscience.kmath.expressions.interpret
import space.kscience.kmath.misc.Symbol
import space.kscience.kmath.expressions.*
import space.kscience.kmath.operations.NumericAlgebra
/**
@ -35,8 +31,8 @@ public class DifferentiableMstExpression<T : Number, A : NumericAlgebra<T>>(
DifferentiableMstExpression(
algebra,
symbols.map(Symbol::identity)
.map(MstAlgebra::bindSymbol)
.map<MST.Symbolic, SVar<KMathNumber<T, A>>>(MST.Symbolic::toSVar)
.map(MstNumericAlgebra::bindSymbol)
.map<Symbol, SVar<KMathNumber<T, A>>>(Symbol::toSVar)
.fold(mst.toSFun(), SFun<KMathNumber<T, A>>::d)
.toMst(),
)

View File

@ -7,9 +7,10 @@ package space.kscience.kmath.kotlingrad
import edu.umontreal.kotlingrad.api.*
import space.kscience.kmath.expressions.MST
import space.kscience.kmath.expressions.MstAlgebra
import space.kscience.kmath.expressions.MstExtendedField
import space.kscience.kmath.expressions.MstExtendedField.unaryMinus
import space.kscience.kmath.expressions.MstNumericAlgebra
import space.kscience.kmath.expressions.Symbol
import space.kscience.kmath.operations.*
/**
@ -18,7 +19,7 @@ import space.kscience.kmath.operations.*
* @receiver The variable.
* @returnAa node.
*/
public fun <X : SFun<X>> SVar<X>.toMst(): MST.Symbolic = MstAlgebra.bindSymbol(name)
public fun <X : SFun<X>> SVar<X>.toMst(): Symbol = MstNumericAlgebra.bindSymbol(name)
/**
* Maps [SVar] to [MST.Numeric] directly.
@ -26,7 +27,7 @@ public fun <X : SFun<X>> SVar<X>.toMst(): MST.Symbolic = MstAlgebra.bindSymbol(n
* @receiver The constant.
* @return A node.
*/
public fun <X : SFun<X>> SConst<X>.toMst(): MST.Numeric = MstAlgebra.number(doubleValue)
public fun <X : SFun<X>> SConst<X>.toMst(): MST.Numeric = MstNumericAlgebra.number(doubleValue)
/**
* Maps [SFun] objects to [MST]. Some unsupported operations like [Derivative] are bound and converted then.
@ -85,7 +86,7 @@ public fun <X : SFun<X>> MST.Numeric.toSConst(): SConst<X> = SConst(value)
* @receiver The node.
* @return A new variable.
*/
internal fun <X : SFun<X>> MST.Symbolic.toSVar(): SVar<X> = SVar(value)
internal fun <X : SFun<X>> Symbol.toSVar(): SVar<X> = SVar(identity)
/**
* Maps [MST] objects to [SFun]. Unsupported operations throw [IllegalStateException].
@ -102,7 +103,7 @@ internal fun <X : SFun<X>> MST.Symbolic.toSVar(): SVar<X> = SVar(value)
*/
public fun <X : SFun<X>> MST.toSFun(): SFun<X> = when (this) {
is MST.Numeric -> toSConst()
is MST.Symbolic -> toSVar()
is Symbol -> toSVar()
is MST.Unary -> when (operation) {
GroupOperations.PLUS_OPERATION -> +value.toSFun<X>()

View File

@ -8,9 +8,9 @@ package space.kscience.kmath.kotlingrad
import edu.umontreal.kotlingrad.api.*
import space.kscience.kmath.asm.compileToExpression
import space.kscience.kmath.ast.parseMath
import space.kscience.kmath.expressions.MstAlgebra
import space.kscience.kmath.expressions.MstNumericAlgebra
import space.kscience.kmath.expressions.Symbol.Companion.x
import space.kscience.kmath.expressions.invoke
import space.kscience.kmath.misc.Symbol.Companion.x
import space.kscience.kmath.operations.DoubleField
import kotlin.test.Test
import kotlin.test.assertEquals
@ -20,7 +20,7 @@ import kotlin.test.fail
internal class AdaptingTests {
@Test
fun symbol() {
val c1 = MstAlgebra.bindSymbol(x.identity)
val c1 = MstNumericAlgebra.bindSymbol(x.identity)
assertEquals(x.identity, c1.toSVar<KMathNumber<Double, DoubleField>>().name)
val c2 = "kitten".parseMath().toSFun<KMathNumber<Double, DoubleField>>()
if (c2 is SVar) assertTrue(c2.name == "kitten") else fail()
@ -28,7 +28,7 @@ internal class AdaptingTests {
@Test
fun number() {
val c1 = MstAlgebra.number(12354324)
val c1 = MstNumericAlgebra.number(12354324)
assertTrue(c1.toSConst<DReal>().doubleValue == 12354324.0)
val c2 = "0.234".parseMath().toSFun<KMathNumber<Double, DoubleField>>()
if (c2 is SConst) assertTrue(c2.doubleValue == 0.234) else fail()
@ -46,7 +46,7 @@ internal class AdaptingTests {
@Test
fun simpleFunctionDerivative() {
val xSVar = MstAlgebra.bindSymbol(x.identity).toSVar<KMathNumber<Double, DoubleField>>()
val xSVar = MstNumericAlgebra.bindSymbol(x.identity).toSVar<KMathNumber<Double, DoubleField>>()
val quadratic = "x^2-4*x-44".parseMath().toSFun<KMathNumber<Double, DoubleField>>()
val actualDerivative = quadratic.d(xSVar).toMst().compileToExpression(DoubleField)
val expectedDerivative = "2*x-4".parseMath().compileToExpression(DoubleField)
@ -55,7 +55,7 @@ internal class AdaptingTests {
@Test
fun moreComplexDerivative() {
val xSVar = MstAlgebra.bindSymbol(x.identity).toSVar<KMathNumber<Double, DoubleField>>()
val xSVar = MstNumericAlgebra.bindSymbol(x.identity).toSVar<KMathNumber<Double, DoubleField>>()
val composition = "-sqrt(sin(x^2)-cos(x)^2-16*x)".parseMath().toSFun<KMathNumber<Double, DoubleField>>()
val actualDerivative = composition.d(xSVar).toMst().compileToExpression(DoubleField)

View File

@ -5,11 +5,7 @@
package space.kscience.kmath.optimization
import space.kscience.kmath.expressions.AutoDiffProcessor
import space.kscience.kmath.expressions.DifferentiableExpression
import space.kscience.kmath.expressions.Expression
import space.kscience.kmath.expressions.ExpressionAlgebra
import space.kscience.kmath.misc.Symbol
import space.kscience.kmath.expressions.*
import space.kscience.kmath.operations.ExtendedField
import space.kscience.kmath.structures.Buffer
import space.kscience.kmath.structures.indices

View File

@ -6,7 +6,7 @@
package space.kscience.kmath.optimization
import space.kscience.kmath.expressions.Expression
import space.kscience.kmath.misc.Symbol
import space.kscience.kmath.expressions.Symbol
import space.kscience.kmath.structures.Buffer
import space.kscience.kmath.structures.indices
import kotlin.math.pow

View File

@ -5,7 +5,7 @@
package space.kscience.kmath.optimization
import space.kscience.kmath.misc.Symbol
import space.kscience.kmath.expressions.Symbol
public interface OptimizationFeature

View File

@ -6,11 +6,7 @@
package space.kscience.kmath.optimization
import space.kscience.kmath.data.ColumnarData
import space.kscience.kmath.expressions.AutoDiffProcessor
import space.kscience.kmath.expressions.DifferentiableExpression
import space.kscience.kmath.expressions.Expression
import space.kscience.kmath.expressions.ExpressionAlgebra
import space.kscience.kmath.misc.Symbol
import space.kscience.kmath.expressions.*
import space.kscience.kmath.misc.UnstableKMathAPI
import space.kscience.kmath.operations.ExtendedField
import space.kscience.kmath.operations.Field

View File

@ -5,7 +5,7 @@ pluginManagement {
maven("https://repo.kotlin.link")
}
val toolsVersion = "0.9.6"
val toolsVersion = "0.9.7"
val kotlinVersion = "1.5.0"
plugins {