Expression simplification

This commit is contained in:
Alexander Nozik 2020-06-11 09:46:42 +03:00
parent 5dc07febe3
commit 0507bfcc24
3 changed files with 60 additions and 17 deletions

View File

@ -25,12 +25,3 @@ interface ExpressionContext<T, E> : Algebra<E> {
*/ */
fun const(value: T): E fun const(value: T): E
} }
fun <T, E> ExpressionContext<T, E>.produce(node: SyntaxTreeNode): E {
return when (node) {
is NumberNode -> error("Single number nodes are not supported")
is SingularNode -> variable(node.value)
is UnaryNode -> unaryOperation(node.operation, produce(node.value))
is BinaryNode -> binaryOperation(node.operation, produce(node.left), produce(node.right))
}
}

View File

@ -1,11 +1,25 @@
package scientifik.kmath.expressions package scientifik.kmath.expressions
import scientifik.kmath.operations.NumericAlgebra
/**
* A syntax tree node for mathematical expressions
*/
sealed class SyntaxTreeNode sealed class SyntaxTreeNode
/**
* A node containing unparsed string
*/
data class SingularNode(val value: String) : SyntaxTreeNode() data class SingularNode(val value: String) : SyntaxTreeNode()
/**
* A node containing a number
*/
data class NumberNode(val value: Number) : SyntaxTreeNode() data class NumberNode(val value: Number) : SyntaxTreeNode()
/**
* A node containing an unary operation
*/
data class UnaryNode(val operation: String, val value: SyntaxTreeNode) : SyntaxTreeNode() { data class UnaryNode(val operation: String, val value: SyntaxTreeNode) : SyntaxTreeNode() {
companion object { companion object {
const val ABS_OPERATION = "abs" const val ABS_OPERATION = "abs"
@ -17,12 +31,22 @@ data class UnaryNode(val operation: String, val value: SyntaxTreeNode) : SyntaxT
} }
} }
/**
* A node containing binary operation
*/
data class BinaryNode(val operation: String, val left: SyntaxTreeNode, val right: SyntaxTreeNode) : SyntaxTreeNode() { data class BinaryNode(val operation: String, val left: SyntaxTreeNode, val right: SyntaxTreeNode) : SyntaxTreeNode() {
companion object { companion object
//TODO add operations
}
} }
//TODO add a function with positional arguments //TODO add a function with positional arguments
//TODO add a function with named arguments //TODO add a function with named arguments
fun <T> NumericAlgebra<T>.compile(node: SyntaxTreeNode): T{
return when (node) {
is NumberNode -> number(node.value)
is SingularNode -> raw(node.value)
is UnaryNode -> unaryOperation(node.operation, compile(node.value))
is BinaryNode -> binaryOperation(node.operation, compile(node.left), compile(node.right))
}
}

View File

@ -7,10 +7,35 @@ annotation class KMathContext
* Marker interface for any algebra * Marker interface for any algebra
*/ */
interface Algebra<T> { interface Algebra<T> {
/**
* Wrap raw string or variable
*/
fun raw(value: String): T = error("Wrapping of '$value' is not supported in $this")
/**
* Dynamic call of unary operation with name [operation] on [arg]
*/
fun unaryOperation(operation: String, arg: T): T fun unaryOperation(operation: String, arg: T): T
/**
* Dynamic call of binary operation [operation] on [left] and [right]
*/
fun binaryOperation(operation: String, left: T, right: T): T fun binaryOperation(operation: String, left: T, right: T): T
} }
/**
* An algebra with numeric representation of members
*/
interface NumericAlgebra<T> : Algebra<T> {
/**
* Wrap a number
*/
fun number(value: Number): T
}
/**
* Call a block with an [Algebra] as receiver
*/
inline operator fun <A : Algebra<*>, R> A.invoke(block: A.() -> R): R = run(block) inline operator fun <A : Algebra<*>, R> A.invoke(block: A.() -> R): R = run(block)
/** /**
@ -87,7 +112,7 @@ interface RingOperations<T> : SpaceOperations<T> {
else -> super.binaryOperation(operation, left, right) else -> super.binaryOperation(operation, left, right)
} }
companion object{ companion object {
const val TIMES_OPERATION = "*" const val TIMES_OPERATION = "*"
} }
} }
@ -95,13 +120,16 @@ interface RingOperations<T> : SpaceOperations<T> {
/** /**
* The same as {@link Space} but with additional multiplication operation * The same as {@link Space} but with additional multiplication operation
*/ */
interface Ring<T> : Space<T>, RingOperations<T> { interface Ring<T> : Space<T>, RingOperations<T>, NumericAlgebra<T> {
/** /**
* neutral operation for multiplication * neutral operation for multiplication
*/ */
val one: T val one: T
// operator fun T.plus(b: Number) = this.plus(b * one) override fun number(value: Number): T = one * value.toDouble()
// those operators are blocked by type conflict in RealField
// operator fun T.plus(b: Number) = this.plus(b * one)
// operator fun Number.plus(b: T) = b + this // operator fun Number.plus(b: T) = b + this
// //
// operator fun T.minus(b: Number) = this.minus(b * one) // operator fun T.minus(b: Number) = this.minus(b * one)
@ -121,7 +149,7 @@ interface FieldOperations<T> : RingOperations<T> {
else -> super.binaryOperation(operation, left, right) else -> super.binaryOperation(operation, left, right)
} }
companion object{ companion object {
const val DIV_OPERATION = "/" const val DIV_OPERATION = "/"
} }
} }