forked from kscience/kmath
Expressions!
This commit is contained in:
parent
8da54786a0
commit
c344380120
@ -11,16 +11,16 @@ and `scipy` it is modular and has a lightweight core.
|
|||||||
* **Array-like structures** Full support of numpy-like ndarray including mixed arithmetic operations and function operations
|
* **Array-like structures** Full support of numpy-like ndarray including mixed arithmetic operations and function operations
|
||||||
on arrays and numbers just like it works in python (with benefit of static type checking).
|
on arrays and numbers just like it works in python (with benefit of static type checking).
|
||||||
|
|
||||||
|
* **Expressions** Expressions are one of the ultimate goals of kmath. It is planned to be able to write some mathematical
|
||||||
|
expression once an then apply it to different types of objects by providing different context. Exception could be used
|
||||||
|
for a wide variety of purposes from high performance calculations to code generation.
|
||||||
|
|
||||||
## Planned features
|
## Planned features
|
||||||
|
|
||||||
* **Common mathematics** It is planned to gradually wrap most parts of [Apache commons-math](http://commons.apache.org/proper/commons-math/)
|
* **Common mathematics** It is planned to gradually wrap most parts of [Apache commons-math](http://commons.apache.org/proper/commons-math/)
|
||||||
library in kotlin code and maybe rewrite some parts to better suite kotlin programming paradigm. There is no fixed priority list for that. Feel free
|
library in kotlin code and maybe rewrite some parts to better suite kotlin programming paradigm. There is no fixed priority list for that. Feel free
|
||||||
to submit a future request if you want something to be done first.
|
to submit a future request if you want something to be done first.
|
||||||
|
|
||||||
* **Expressions** Expressions are one of the ultimate goals of kmath. It is planned to be able to write some mathematical
|
|
||||||
expression once an then apply it to different types of objects by providing different context. Exception could be used
|
|
||||||
for a wide variety of purposes from high performance calculations to code generation.
|
|
||||||
|
|
||||||
* **Messaging** A mathematical notation to support multilanguage and multinod communication for mathematical tasks.
|
* **Messaging** A mathematical notation to support multilanguage and multinod communication for mathematical tasks.
|
||||||
|
|
||||||
## Multi-platform support
|
## Multi-platform support
|
||||||
|
@ -0,0 +1,62 @@
|
|||||||
|
package scientifik.kmath.expressions
|
||||||
|
|
||||||
|
import scientifik.kmath.operations.Field
|
||||||
|
import scientifik.kmath.operations.Space
|
||||||
|
|
||||||
|
|
||||||
|
interface Expression<T> {
|
||||||
|
operator fun invoke(arguments: Map<String, T>): T
|
||||||
|
}
|
||||||
|
|
||||||
|
operator fun <T> Expression<T>.invoke(vararg pairs: Pair<String, T>): T = invoke(mapOf(*pairs))
|
||||||
|
|
||||||
|
interface ExpressionContext<T> {
|
||||||
|
fun variable(name: String, default: T? = null): Expression<T>
|
||||||
|
|
||||||
|
fun const(value: T): Expression<T>
|
||||||
|
}
|
||||||
|
|
||||||
|
internal class VariableExpression<T>(val name: String, val default: T? = null) : Expression<T> {
|
||||||
|
override fun invoke(arguments: Map<String, T>): T {
|
||||||
|
return arguments[name] ?: default ?: error("The parameter not found: $name")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal class ConstantExpression<T>(val value: T) : Expression<T> {
|
||||||
|
override fun invoke(arguments: Map<String, T>): T = value
|
||||||
|
}
|
||||||
|
|
||||||
|
internal class SumExpression<T>(val context: Space<T>, val first: Expression<T>, val second: Expression<T>) : Expression<T> {
|
||||||
|
override fun invoke(arguments: Map<String, T>): T = context.add(first.invoke(arguments), second.invoke(arguments))
|
||||||
|
}
|
||||||
|
|
||||||
|
internal class ProductExpression<T>(val context: Field<T>, val first: Expression<T>, val second: Expression<T>) : Expression<T> {
|
||||||
|
override fun invoke(arguments: Map<String, T>): T = context.multiply(first.invoke(arguments), second.invoke(arguments))
|
||||||
|
}
|
||||||
|
|
||||||
|
internal class ConstProductExpession<T>(val context: Field<T>, val expr: Expression<T>, val const: Double) : Expression<T> {
|
||||||
|
override fun invoke(arguments: Map<String, T>): T = context.multiply(expr.invoke(arguments), const)
|
||||||
|
}
|
||||||
|
|
||||||
|
internal class DivExpession<T>(val context: Field<T>, val expr: Expression<T>, val second: Expression<T>) : Expression<T> {
|
||||||
|
override fun invoke(arguments: Map<String, T>): T = context.divide(expr.invoke(arguments), second.invoke(arguments))
|
||||||
|
}
|
||||||
|
|
||||||
|
class FieldExpressionContext<T>(val field: Field<T>) : Field<Expression<T>>, ExpressionContext<T> {
|
||||||
|
|
||||||
|
override val zero: Expression<T> = ConstantExpression(field.zero)
|
||||||
|
|
||||||
|
override val one: Expression<T> = ConstantExpression(field.one)
|
||||||
|
|
||||||
|
override fun const(value: T): Expression<T> = ConstantExpression(value)
|
||||||
|
|
||||||
|
override fun variable(name: String, default: T?): Expression<T> = VariableExpression(name, default)
|
||||||
|
|
||||||
|
override fun add(a: Expression<T>, b: Expression<T>): Expression<T> = SumExpression(field, a, b)
|
||||||
|
|
||||||
|
override fun multiply(a: Expression<T>, k: Double): Expression<T> = ConstProductExpession(field, a, k)
|
||||||
|
|
||||||
|
override fun multiply(a: Expression<T>, b: Expression<T>): Expression<T> = ProductExpression(field, a, b)
|
||||||
|
|
||||||
|
override fun divide(a: Expression<T>, b: Expression<T>): Expression<T> = DivExpession(field, a, b)
|
||||||
|
}
|
@ -29,7 +29,7 @@ object RealField : Field<Real>, TrigonometricOperations<Real>, PowerOperations<R
|
|||||||
*
|
*
|
||||||
* TODO could be replaced by inline class in kotlin 1.3 if it would allow to avoid boxing
|
* TODO could be replaced by inline class in kotlin 1.3 if it would allow to avoid boxing
|
||||||
*/
|
*/
|
||||||
class Real(val value: Double) : Number(), FieldElement<Real, RealField> {
|
data class Real(val value: Double) : Number(), FieldElement<Real, RealField> {
|
||||||
/*
|
/*
|
||||||
* The class uses composition instead of inheritance since Double is final
|
* The class uses composition instead of inheritance since Double is final
|
||||||
*/
|
*/
|
||||||
@ -94,10 +94,19 @@ data class Complex(val re: Double, val im: Double) : FieldElement<Complex, Compl
|
|||||||
/**
|
/**
|
||||||
* A field for double without boxing. Does not produce appropriate field element
|
* A field for double without boxing. Does not produce appropriate field element
|
||||||
*/
|
*/
|
||||||
object DoubleField : Field<Double> {
|
object DoubleField : Field<Double>, TrigonometricOperations<Double>, PowerOperations<Double>, ExponentialOperations<Double> {
|
||||||
override val zero: Double = 0.0
|
override val zero: Double = 0.0
|
||||||
override fun add(a: Double, b: Double): Double = a + b
|
override fun add(a: Double, b: Double): Double = a + b
|
||||||
override fun multiply(a: Double, @Suppress("PARAMETER_NAME_CHANGED_ON_OVERRIDE") b: Double): Double = a * b
|
override fun multiply(a: Double, @Suppress("PARAMETER_NAME_CHANGED_ON_OVERRIDE") b: Double): Double = a * b
|
||||||
override val one: Double = 1.0
|
override val one: Double = 1.0
|
||||||
override fun divide(a: Double, b: Double): Double = a / b
|
override fun divide(a: Double, b: Double): Double = a / b
|
||||||
|
|
||||||
|
override fun sin(arg: Double): Double = kotlin.math.sin(arg)
|
||||||
|
override fun cos(arg: Double): Double = kotlin.math.cos(arg)
|
||||||
|
|
||||||
|
override fun power(arg: Double, pow: Double): Double = arg.pow(pow)
|
||||||
|
|
||||||
|
override fun exp(arg: Double): Double =kotlin.math.exp(arg)
|
||||||
|
|
||||||
|
override fun ln(arg: Double): Double = kotlin.math.ln(arg)
|
||||||
}
|
}
|
@ -0,0 +1,18 @@
|
|||||||
|
package scientifik.kmath.expressions
|
||||||
|
|
||||||
|
import scientifik.kmath.operations.DoubleField
|
||||||
|
import kotlin.test.Test
|
||||||
|
import kotlin.test.assertEquals
|
||||||
|
|
||||||
|
class FieldExpressionContextTest {
|
||||||
|
@Test
|
||||||
|
fun testExpression() {
|
||||||
|
val context = FieldExpressionContext(DoubleField)
|
||||||
|
val expression = with(context) {
|
||||||
|
val x = variable("x", 2.0)
|
||||||
|
x * x + 2 * x + 1.0 * one
|
||||||
|
}
|
||||||
|
assertEquals(expression("x" to 1.0), 4.0)
|
||||||
|
assertEquals(expression(), 9.0)
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user