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
|
||||
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
|
||||
|
||||
* **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
|
||||
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.
|
||||
|
||||
## 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
|
||||
*/
|
||||
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
|
||||
*/
|
||||
@ -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
|
||||
*/
|
||||
object DoubleField : Field<Double> {
|
||||
object DoubleField : Field<Double>, TrigonometricOperations<Double>, PowerOperations<Double>, ExponentialOperations<Double> {
|
||||
override val zero: Double = 0.0
|
||||
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 val one: Double = 1.0
|
||||
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