Feature: Polynomials and rational functions #469

Merged
lounres merged 132 commits from feature/polynomials into dev 2022-07-28 18:04:06 +03:00
4 changed files with 126 additions and 158 deletions
Showing only changes of commit 9aa131a9c6 - Show all commits

View File

@ -5,6 +5,7 @@
package space.kscience.kmath.functions package space.kscience.kmath.functions
import space.kscience.kmath.expressions.Symbol
import space.kscience.kmath.operations.* import space.kscience.kmath.operations.*
import kotlin.contracts.InvocationKind import kotlin.contracts.InvocationKind
import kotlin.contracts.contract import kotlin.contracts.contract
@ -40,9 +41,9 @@ internal constructor(
* ) to (-6) * ) to (-6)
* ) * )
* ``` * ```
* where `a`, `b` and `c` are corresponding [Variable] objects. * where `a`, `b` and `c` are corresponding [Symbol] objects.
*/ */
public val coefficients: Map<Map<Variable, UInt>, C> public val coefficients: Map<Map<Symbol, UInt>, C>
) : AbstractPolynomial<C> { ) : AbstractPolynomial<C> {
override fun toString(): String = "LabeledPolynomial$coefficients" override fun toString(): String = "LabeledPolynomial$coefficients"
} }
@ -67,7 +68,7 @@ internal fun labeledPolynomialError(message: Any): Nothing = throw LabeledPolyno
/** /**
* Returns the same degrees description of the monomial, but without zero degrees. * Returns the same degrees description of the monomial, but without zero degrees.
*/ */
internal fun Map<Variable, UInt>.cleanUp() = filterValues { it > 0U } internal fun Map<Symbol, UInt>.cleanUp() = filterValues { it > 0U }
// endregion // endregion
@ -75,10 +76,10 @@ internal fun Map<Variable, UInt>.cleanUp() = filterValues { it > 0U }
//context(LabeledPolynomialSpace<C, Ring<C>>) //context(LabeledPolynomialSpace<C, Ring<C>>)
//@Suppress("FunctionName") //@Suppress("FunctionName")
//internal fun <C> LabeledPolynomial(coefs: Map<Map<Variable, UInt>, C>, toCheckInput: Boolean = false) : LabeledPolynomial<C> { //internal fun <C> LabeledPolynomial(coefs: Map<Map<Symbol, UInt>, C>, toCheckInput: Boolean = false) : LabeledPolynomial<C> {
// if (!toCheckInput) return LabeledPolynomial(coefs) // if (!toCheckInput) return LabeledPolynomial(coefs)
// //
// val fixedCoefs = mutableMapOf<Map<Variable, UInt>, C>() // val fixedCoefs = mutableMapOf<Map<Symbol, UInt>, C>()
// //
// for (entry in coefs) { // for (entry in coefs) {
// val key = entry.key.cleanUp() // val key = entry.key.cleanUp()
@ -93,10 +94,10 @@ internal fun Map<Variable, UInt>.cleanUp() = filterValues { it > 0U }
// //
//context(LabeledPolynomialSpace<C, Ring<C>>) //context(LabeledPolynomialSpace<C, Ring<C>>)
//@Suppress("FunctionName") //@Suppress("FunctionName")
//internal fun <C> LabeledPolynomial(pairs: Collection<Pair<Map<Variable, UInt>, C>>, toCheckInput: Boolean = false) : LabeledPolynomial<C> { //internal fun <C> LabeledPolynomial(pairs: Collection<Pair<Map<Symbol, UInt>, C>>, toCheckInput: Boolean = false) : LabeledPolynomial<C> {
// if (!toCheckInput) return LabeledPolynomial(pairs.toMap()) // if (!toCheckInput) return LabeledPolynomial(pairs.toMap())
// //
// val fixedCoefs = mutableMapOf<Map<Variable, UInt>, C>() // val fixedCoefs = mutableMapOf<Map<Symbol, UInt>, C>()
// //
// for (entry in pairs) { // for (entry in pairs) {
// val key = entry.first.cleanUp() // val key = entry.first.cleanUp()
@ -112,20 +113,20 @@ internal fun Map<Variable, UInt>.cleanUp() = filterValues { it > 0U }
//// TODO: Do not know how to make it without context receivers //// TODO: Do not know how to make it without context receivers
//context(LabeledPolynomialSpace<C, Ring<C>>) //context(LabeledPolynomialSpace<C, Ring<C>>)
//@Suppress("FunctionName") //@Suppress("FunctionName")
//public fun <C> LabeledPolynomial(coefs: Map<Map<Variable, UInt>, C>) : LabeledPolynomial<C> = LabeledPolynomial(coefs, toCheckInput = true) //public fun <C> LabeledPolynomial(coefs: Map<Map<Symbol, UInt>, C>) : LabeledPolynomial<C> = LabeledPolynomial(coefs, toCheckInput = true)
// //
//context(LabeledPolynomialSpace<C, Ring<C>>) //context(LabeledPolynomialSpace<C, Ring<C>>)
//@Suppress("FunctionName") //@Suppress("FunctionName")
//public fun <C> LabeledPolynomial(pairs: Collection<Pair<Map<Variable, UInt>, C>>) : LabeledPolynomial<C> = LabeledPolynomial(pairs, toCheckInput = true) //public fun <C> LabeledPolynomial(pairs: Collection<Pair<Map<Symbol, UInt>, C>>) : LabeledPolynomial<C> = LabeledPolynomial(pairs, toCheckInput = true)
// //
//context(LabeledPolynomialSpace<C, Ring<C>>) //context(LabeledPolynomialSpace<C, Ring<C>>)
//@Suppress("FunctionName") //@Suppress("FunctionName")
//public fun <C> LabeledPolynomial(vararg pairs: Pair<Map<Variable, UInt>, C>) : LabeledPolynomial<C> = LabeledPolynomial(pairs.toList(), toCheckInput = true) //public fun <C> LabeledPolynomial(vararg pairs: Pair<Map<Symbol, UInt>, C>) : LabeledPolynomial<C> = LabeledPolynomial(pairs.toList(), toCheckInput = true)
// //
//context(LabeledPolynomialSpace<C, Ring<C>>) //context(LabeledPolynomialSpace<C, Ring<C>>)
//public fun <C> Variable.asLabeledPolynomial() : LabeledPolynomial<C> = LabeledPolynomial(mapOf(mapOf(this to 1u) to constantOne)) //public fun <C> Symbol.asLabeledPolynomial() : LabeledPolynomial<C> = LabeledPolynomial(mapOf(mapOf(this to 1u) to constantOne))
public fun <C> C.asLabeledPolynomial() : LabeledPolynomial<C> = LabeledPolynomial(mapOf(emptyMap<Variable, UInt>() to this)) public fun <C> C.asLabeledPolynomial() : LabeledPolynomial<C> = LabeledPolynomial(mapOf(emptyMap<Symbol, UInt>() to this))
// endregion // endregion
@ -140,24 +141,24 @@ public class LabeledPolynomialSpace<C, A : Ring<C>>(
public override val ring: A, public override val ring: A,
) : AbstractPolynomialSpaceOverRing<C, LabeledPolynomial<C>, A> { ) : AbstractPolynomialSpaceOverRing<C, LabeledPolynomial<C>, A> {
// region Variable-integer relation // region Symbol-integer relation
public operator fun Variable.plus(other: Int): LabeledPolynomial<C> = public operator fun Symbol.plus(other: Int): LabeledPolynomial<C> =
if (other == 0) LabeledPolynomial<C>(mapOf( if (other == 0) LabeledPolynomial<C>(mapOf(
mapOf(this@plus to 1U) to constantOne, mapOf(this@plus to 1U) to constantOne,
)) ))
else LabeledPolynomial<C>(mapOf( else LabeledPolynomial<C>(mapOf(
mapOf(this@plus to 1U) to constantOne, mapOf(this@plus to 1U) to constantOne,
emptyMap<Variable, UInt>() to constantOne * other, emptyMap<Symbol, UInt>() to constantOne * other,
)) ))
public operator fun Variable.minus(other: Int): LabeledPolynomial<C> = public operator fun Symbol.minus(other: Int): LabeledPolynomial<C> =
if (other == 0) LabeledPolynomial<C>(mapOf( if (other == 0) LabeledPolynomial<C>(mapOf(
mapOf(this@minus to 1U) to -constantOne, mapOf(this@minus to 1U) to -constantOne,
)) ))
else LabeledPolynomial<C>(mapOf( else LabeledPolynomial<C>(mapOf(
mapOf(this@minus to 1U) to -constantOne, mapOf(this@minus to 1U) to -constantOne,
emptyMap<Variable, UInt>() to constantOne * other, emptyMap<Symbol, UInt>() to constantOne * other,
)) ))
public operator fun Variable.times(other: Int): LabeledPolynomial<C> = public operator fun Symbol.times(other: Int): LabeledPolynomial<C> =
if (other == 0) zero if (other == 0) zero
else LabeledPolynomial<C>(mapOf( else LabeledPolynomial<C>(mapOf(
mapOf(this to 1U) to constantOne * other, mapOf(this to 1U) to constantOne * other,
@ -165,23 +166,23 @@ public class LabeledPolynomialSpace<C, A : Ring<C>>(
// endregion // endregion
// region Integer-variable relation // region Integer-variable relation
public operator fun Int.plus(other: Variable): LabeledPolynomial<C> = public operator fun Int.plus(other: Symbol): LabeledPolynomial<C> =
if (this == 0) LabeledPolynomial<C>(mapOf( if (this == 0) LabeledPolynomial<C>(mapOf(
mapOf(other to 1U) to constantOne, mapOf(other to 1U) to constantOne,
)) ))
else LabeledPolynomial<C>(mapOf( else LabeledPolynomial<C>(mapOf(
mapOf(other to 1U) to constantOne, mapOf(other to 1U) to constantOne,
emptyMap<Variable, UInt>() to constantOne * this@plus, emptyMap<Symbol, UInt>() to constantOne * this@plus,
)) ))
public operator fun Int.minus(other: Variable): LabeledPolynomial<C> = public operator fun Int.minus(other: Symbol): LabeledPolynomial<C> =
if (this == 0) LabeledPolynomial<C>(mapOf( if (this == 0) LabeledPolynomial<C>(mapOf(
mapOf(other to 1U) to -constantOne, mapOf(other to 1U) to -constantOne,
)) ))
else LabeledPolynomial<C>(mapOf( else LabeledPolynomial<C>(mapOf(
mapOf(other to 1U) to -constantOne, mapOf(other to 1U) to -constantOne,
emptyMap<Variable, UInt>() to constantOne * this@minus, emptyMap<Symbol, UInt>() to constantOne * this@minus,
)) ))
public operator fun Int.times(other: Variable): LabeledPolynomial<C> = public operator fun Int.times(other: Symbol): LabeledPolynomial<C> =
if (this == 0) zero if (this == 0) zero
else LabeledPolynomial<C>(mapOf( else LabeledPolynomial<C>(mapOf(
mapOf(other to 1U) to constantOne * this@times, mapOf(other to 1U) to constantOne * this@times,
@ -201,7 +202,7 @@ public class LabeledPolynomialSpace<C, A : Ring<C>>(
coefficients coefficients
.toMutableMap() .toMutableMap()
.apply { .apply {
val degs = emptyMap<Variable, UInt>() val degs = emptyMap<Symbol, UInt>()
val result = getOrElse(degs) { constantZero } + other val result = getOrElse(degs) { constantZero } + other
@ -221,7 +222,7 @@ public class LabeledPolynomialSpace<C, A : Ring<C>>(
coefficients coefficients
.toMutableMap() .toMutableMap()
.apply { .apply {
val degs = emptyMap<Variable, UInt>() val degs = emptyMap<Symbol, UInt>()
val result = getOrElse(degs) { constantZero } - other val result = getOrElse(degs) { constantZero } - other
@ -257,7 +258,7 @@ public class LabeledPolynomialSpace<C, A : Ring<C>>(
other.coefficients other.coefficients
.toMutableMap() .toMutableMap()
.apply { .apply {
val degs = emptyMap<Variable, UInt>() val degs = emptyMap<Symbol, UInt>()
val result = this@plus + getOrElse(degs) { constantZero } val result = this@plus + getOrElse(degs) { constantZero }
@ -277,7 +278,7 @@ public class LabeledPolynomialSpace<C, A : Ring<C>>(
other.coefficients other.coefficients
.toMutableMap() .toMutableMap()
.apply { .apply {
val degs = emptyMap<Variable, UInt>() val degs = emptyMap<Symbol, UInt>()
val result = this@minus - getOrElse(degs) { constantZero } val result = this@minus - getOrElse(degs) { constantZero }
@ -301,47 +302,47 @@ public class LabeledPolynomialSpace<C, A : Ring<C>>(
// endregion // endregion
// region Constant-variable relation // region Constant-variable relation
public operator fun C.plus(other: Variable): LabeledPolynomial<C> = public operator fun C.plus(other: Symbol): LabeledPolynomial<C> =
if (isZero()) LabeledPolynomial<C>(mapOf( if (isZero()) LabeledPolynomial<C>(mapOf(
mapOf(other to 1U) to constantOne, mapOf(other to 1U) to constantOne,
)) ))
else LabeledPolynomial<C>(mapOf( else LabeledPolynomial<C>(mapOf(
mapOf(other to 1U) to constantOne, mapOf(other to 1U) to constantOne,
emptyMap<Variable, UInt>() to this@plus, emptyMap<Symbol, UInt>() to this@plus,
)) ))
public operator fun C.minus(other: Variable): LabeledPolynomial<C> = public operator fun C.minus(other: Symbol): LabeledPolynomial<C> =
if (isZero()) LabeledPolynomial<C>(mapOf( if (isZero()) LabeledPolynomial<C>(mapOf(
mapOf(other to 1U) to -constantOne, mapOf(other to 1U) to -constantOne,
)) ))
else LabeledPolynomial<C>(mapOf( else LabeledPolynomial<C>(mapOf(
mapOf(other to 1U) to -constantOne, mapOf(other to 1U) to -constantOne,
emptyMap<Variable, UInt>() to this@minus, emptyMap<Symbol, UInt>() to this@minus,
)) ))
public operator fun C.times(other: Variable): LabeledPolynomial<C> = public operator fun C.times(other: Symbol): LabeledPolynomial<C> =
if (isZero()) zero if (isZero()) zero
else LabeledPolynomial<C>(mapOf( else LabeledPolynomial<C>(mapOf(
mapOf(other to 1U) to this@times, mapOf(other to 1U) to this@times,
)) ))
// endregion // endregion
// region Variable-constant relation // region Symbol-constant relation
public operator fun Variable.plus(other: C): LabeledPolynomial<C> = public operator fun Symbol.plus(other: C): LabeledPolynomial<C> =
if (other.isZero()) LabeledPolynomial<C>(mapOf( if (other.isZero()) LabeledPolynomial<C>(mapOf(
mapOf(this@plus to 1U) to constantOne, mapOf(this@plus to 1U) to constantOne,
)) ))
else LabeledPolynomial<C>(mapOf( else LabeledPolynomial<C>(mapOf(
mapOf(this@plus to 1U) to constantOne, mapOf(this@plus to 1U) to constantOne,
emptyMap<Variable, UInt>() to other, emptyMap<Symbol, UInt>() to other,
)) ))
public operator fun Variable.minus(other: C): LabeledPolynomial<C> = public operator fun Symbol.minus(other: C): LabeledPolynomial<C> =
if (other.isZero()) LabeledPolynomial<C>(mapOf( if (other.isZero()) LabeledPolynomial<C>(mapOf(
mapOf(this@minus to 1U) to -constantOne, mapOf(this@minus to 1U) to -constantOne,
)) ))
else LabeledPolynomial<C>(mapOf( else LabeledPolynomial<C>(mapOf(
mapOf(this@minus to 1U) to -constantOne, mapOf(this@minus to 1U) to -constantOne,
emptyMap<Variable, UInt>() to other, emptyMap<Symbol, UInt>() to other,
)) ))
public operator fun Variable.times(other: C): LabeledPolynomial<C> = public operator fun Symbol.times(other: C): LabeledPolynomial<C> =
if (other.isZero()) zero if (other.isZero()) zero
else LabeledPolynomial<C>(mapOf( else LabeledPolynomial<C>(mapOf(
mapOf(this@times to 1U) to other, mapOf(this@times to 1U) to other,
@ -355,11 +356,11 @@ public class LabeledPolynomialSpace<C, A : Ring<C>>(
override operator fun C.plus(other: LabeledPolynomial<C>): LabeledPolynomial<C> = override operator fun C.plus(other: LabeledPolynomial<C>): LabeledPolynomial<C> =
if (this.isZero()) other if (this.isZero()) other
else with(other.coefficients) { else with(other.coefficients) {
if (isEmpty()) LabeledPolynomial<C>(mapOf(emptyMap<Variable, UInt>() to this@plus)) if (isEmpty()) LabeledPolynomial<C>(mapOf(emptyMap<Symbol, UInt>() to this@plus))
else LabeledPolynomial<C>( else LabeledPolynomial<C>(
toMutableMap() toMutableMap()
.apply { .apply {
val degs = emptyMap<Variable, UInt>() val degs = emptyMap<Symbol, UInt>()
val result = this@plus + getOrElse(degs) { constantZero } val result = this@plus + getOrElse(degs) { constantZero }
@ -374,13 +375,13 @@ public class LabeledPolynomialSpace<C, A : Ring<C>>(
override operator fun C.minus(other: LabeledPolynomial<C>): LabeledPolynomial<C> = override operator fun C.minus(other: LabeledPolynomial<C>): LabeledPolynomial<C> =
if (this.isZero()) other if (this.isZero()) other
else with(other.coefficients) { else with(other.coefficients) {
if (isEmpty()) LabeledPolynomial<C>(mapOf(emptyMap<Variable, UInt>() to this@minus)) if (isEmpty()) LabeledPolynomial<C>(mapOf(emptyMap<Symbol, UInt>() to this@minus))
else LabeledPolynomial<C>( else LabeledPolynomial<C>(
toMutableMap() toMutableMap()
.apply { .apply {
forEach { (degs, c) -> if(degs.isNotEmpty()) this[degs] = -c } forEach { (degs, c) -> if(degs.isNotEmpty()) this[degs] = -c }
val degs = emptyMap<Variable, UInt>() val degs = emptyMap<Symbol, UInt>()
val result = this@minus - getOrElse(degs) { constantZero } val result = this@minus - getOrElse(degs) { constantZero }
@ -409,11 +410,11 @@ public class LabeledPolynomialSpace<C, A : Ring<C>>(
override operator fun LabeledPolynomial<C>.plus(other: C): LabeledPolynomial<C> = override operator fun LabeledPolynomial<C>.plus(other: C): LabeledPolynomial<C> =
if (other.isZero()) this if (other.isZero()) this
else with(coefficients) { else with(coefficients) {
if (isEmpty()) LabeledPolynomial<C>(mapOf(emptyMap<Variable, UInt>() to other)) if (isEmpty()) LabeledPolynomial<C>(mapOf(emptyMap<Symbol, UInt>() to other))
else LabeledPolynomial<C>( else LabeledPolynomial<C>(
toMutableMap() toMutableMap()
.apply { .apply {
val degs = emptyMap<Variable, UInt>() val degs = emptyMap<Symbol, UInt>()
val result = getOrElse(degs) { constantZero } + other val result = getOrElse(degs) { constantZero } + other
@ -428,13 +429,13 @@ public class LabeledPolynomialSpace<C, A : Ring<C>>(
override operator fun LabeledPolynomial<C>.minus(other: C): LabeledPolynomial<C> = override operator fun LabeledPolynomial<C>.minus(other: C): LabeledPolynomial<C> =
if (other.isZero()) this if (other.isZero()) this
else with(coefficients) { else with(coefficients) {
if (isEmpty()) LabeledPolynomial<C>(mapOf(emptyMap<Variable, UInt>() to other)) if (isEmpty()) LabeledPolynomial<C>(mapOf(emptyMap<Symbol, UInt>() to other))
else LabeledPolynomial<C>( else LabeledPolynomial<C>(
toMutableMap() toMutableMap()
.apply { .apply {
forEach { (degs, c) -> if(degs.isNotEmpty()) this[degs] = -c } forEach { (degs, c) -> if(degs.isNotEmpty()) this[degs] = -c }
val degs = emptyMap<Variable, UInt>() val degs = emptyMap<Symbol, UInt>()
val result = getOrElse(degs) { constantZero } - other val result = getOrElse(degs) { constantZero } - other
@ -456,8 +457,8 @@ public class LabeledPolynomialSpace<C, A : Ring<C>>(
) )
// endregion // endregion
// region Variable-variable relation // region Symbol-variable relation
public operator fun Variable.plus(other: Variable): LabeledPolynomial<C> = public operator fun Symbol.plus(other: Symbol): LabeledPolynomial<C> =
if (this == other) LabeledPolynomial<C>(mapOf( if (this == other) LabeledPolynomial<C>(mapOf(
mapOf(this to 1U) to constantOne * 2 mapOf(this to 1U) to constantOne * 2
)) ))
@ -465,13 +466,13 @@ public class LabeledPolynomialSpace<C, A : Ring<C>>(
mapOf(this to 1U) to constantOne, mapOf(this to 1U) to constantOne,
mapOf(other to 1U) to constantOne, mapOf(other to 1U) to constantOne,
)) ))
public operator fun Variable.minus(other: Variable): LabeledPolynomial<C> = public operator fun Symbol.minus(other: Symbol): LabeledPolynomial<C> =
if (this == other) zero if (this == other) zero
else LabeledPolynomial<C>(mapOf( else LabeledPolynomial<C>(mapOf(
mapOf(this to 1U) to constantOne, mapOf(this to 1U) to constantOne,
mapOf(other to 1U) to -constantOne, mapOf(other to 1U) to -constantOne,
)) ))
public operator fun Variable.times(other: Variable): LabeledPolynomial<C> = public operator fun Symbol.times(other: Symbol): LabeledPolynomial<C> =
if (this == other) LabeledPolynomial<C>(mapOf( if (this == other) LabeledPolynomial<C>(mapOf(
mapOf(this to 2U) to constantOne mapOf(this to 2U) to constantOne
)) ))
@ -480,8 +481,8 @@ public class LabeledPolynomialSpace<C, A : Ring<C>>(
)) ))
// endregion // endregion
// region Variable-polynomial relation // region Symbol-polynomial relation
public operator fun Variable.plus(other: LabeledPolynomial<C>): LabeledPolynomial<C> = public operator fun Symbol.plus(other: LabeledPolynomial<C>): LabeledPolynomial<C> =
with(other.coefficients) { with(other.coefficients) {
if (isEmpty()) LabeledPolynomial<C>(mapOf(mapOf(this@plus to 1u) to constantOne)) if (isEmpty()) LabeledPolynomial<C>(mapOf(mapOf(this@plus to 1u) to constantOne))
else LabeledPolynomial<C>( else LabeledPolynomial<C>(
@ -496,7 +497,7 @@ public class LabeledPolynomialSpace<C, A : Ring<C>>(
} }
) )
} }
public operator fun Variable.minus(other: LabeledPolynomial<C>): LabeledPolynomial<C> = public operator fun Symbol.minus(other: LabeledPolynomial<C>): LabeledPolynomial<C> =
with(other.coefficients) { with(other.coefficients) {
if (isEmpty()) LabeledPolynomial<C>(mapOf(mapOf(this@minus to 1u) to constantOne)) if (isEmpty()) LabeledPolynomial<C>(mapOf(mapOf(this@minus to 1u) to constantOne))
else LabeledPolynomial<C>( else LabeledPolynomial<C>(
@ -513,7 +514,7 @@ public class LabeledPolynomialSpace<C, A : Ring<C>>(
} }
) )
} }
public operator fun Variable.times(other: LabeledPolynomial<C>): LabeledPolynomial<C> = public operator fun Symbol.times(other: LabeledPolynomial<C>): LabeledPolynomial<C> =
LabeledPolynomial<C>( LabeledPolynomial<C>(
other.coefficients other.coefficients
.mapKeys { (degs, _) -> degs.toMutableMap().also{ it[this] = if (this in it) it[this]!! + 1U else 1U } } .mapKeys { (degs, _) -> degs.toMutableMap().also{ it[this] = if (this in it) it[this]!! + 1U else 1U } }
@ -521,7 +522,7 @@ public class LabeledPolynomialSpace<C, A : Ring<C>>(
// endregion // endregion
// region Polynomial-variable relation // region Polynomial-variable relation
public operator fun LabeledPolynomial<C>.plus(other: Variable): LabeledPolynomial<C> = public operator fun LabeledPolynomial<C>.plus(other: Symbol): LabeledPolynomial<C> =
with(coefficients) { with(coefficients) {
if (isEmpty()) LabeledPolynomial<C>(mapOf(mapOf(other to 1u) to constantOne)) if (isEmpty()) LabeledPolynomial<C>(mapOf(mapOf(other to 1u) to constantOne))
else LabeledPolynomial<C>( else LabeledPolynomial<C>(
@ -536,7 +537,7 @@ public class LabeledPolynomialSpace<C, A : Ring<C>>(
} }
) )
} }
public operator fun LabeledPolynomial<C>.minus(other: Variable): LabeledPolynomial<C> = public operator fun LabeledPolynomial<C>.minus(other: Symbol): LabeledPolynomial<C> =
with(coefficients) { with(coefficients) {
if (isEmpty()) LabeledPolynomial<C>(mapOf(mapOf(other to 1u) to constantOne)) if (isEmpty()) LabeledPolynomial<C>(mapOf(mapOf(other to 1u) to constantOne))
else LabeledPolynomial<C>( else LabeledPolynomial<C>(
@ -551,7 +552,7 @@ public class LabeledPolynomialSpace<C, A : Ring<C>>(
} }
) )
} }
public operator fun LabeledPolynomial<C>.times(other: Variable): LabeledPolynomial<C> = public operator fun LabeledPolynomial<C>.times(other: Symbol): LabeledPolynomial<C> =
LabeledPolynomial<C>( LabeledPolynomial<C>(
coefficients coefficients
.mapKeys { (degs, _) -> degs.toMutableMap().also{ it[other] = if (other in it) it[other]!! + 1U else 1U } } .mapKeys { (degs, _) -> degs.toMutableMap().also{ it[other] = if (other in it) it[other]!! + 1U else 1U } }
@ -610,11 +611,11 @@ public class LabeledPolynomialSpace<C, A : Ring<C>>(
/** /**
* Instance of zero polynomial (zero of the polynomial ring). * Instance of zero polynomial (zero of the polynomial ring).
*/ */
override val zero: LabeledPolynomial<C> = LabeledPolynomial<C>(mapOf(emptyMap<Variable, UInt>() to constantZero)) override val zero: LabeledPolynomial<C> = LabeledPolynomial<C>(mapOf(emptyMap<Symbol, UInt>() to constantZero))
/** /**
* Instance of unit polynomial (unit of the polynomial ring). * Instance of unit polynomial (unit of the polynomial ring).
*/ */
override val one: LabeledPolynomial<C> = LabeledPolynomial<C>(mapOf(emptyMap<Variable, UInt>() to constantOne)) override val one: LabeledPolynomial<C> = LabeledPolynomial<C>(mapOf(emptyMap<Symbol, UInt>() to constantOne))
/** /**
* Checks equality of the polynomials. * Checks equality of the polynomials.
@ -642,7 +643,7 @@ public class LabeledPolynomialSpace<C, A : Ring<C>>(
* As consequence all values in the map are positive integers. Also, if the polynomial is constant, the map is empty. * As consequence all values in the map are positive integers. Also, if the polynomial is constant, the map is empty.
* And keys of the map is the same as in [variables]. * And keys of the map is the same as in [variables].
*/ */
public val LabeledPolynomial<C>.degrees: Map<Variable, UInt> public val LabeledPolynomial<C>.degrees: Map<Symbol, UInt>
get() = get() =
buildMap { buildMap {
coefficients.entries.forEach { (degs, c) -> coefficients.entries.forEach { (degs, c) ->
@ -654,7 +655,7 @@ public class LabeledPolynomialSpace<C, A : Ring<C>>(
/** /**
* Set of all variables that appear in the polynomial in positive exponents. * Set of all variables that appear in the polynomial in positive exponents.
*/ */
public val LabeledPolynomial<C>.variables: Set<Variable> public val LabeledPolynomial<C>.variables: Set<Symbol>
get() = get() =
buildSet { buildSet {
coefficients.entries.forEach { (degs, c) -> if (c.isNotZero()) addAll(degs.keys) } coefficients.entries.forEach { (degs, c) -> if (c.isNotZero()) addAll(degs.keys) }
@ -695,29 +696,29 @@ public class LabeledPolynomialSpace<C, A : Ring<C>>(
} }
// @Suppress("NOTHING_TO_INLINE") // @Suppress("NOTHING_TO_INLINE")
// public inline fun LabeledPolynomial<C>.substitute(argument: Map<Variable, C>): LabeledPolynomial<C> = this.substitute(ring, argument) // public inline fun LabeledPolynomial<C>.substitute(argument: Map<Symbol, C>): LabeledPolynomial<C> = this.substitute(ring, argument)
// @Suppress("NOTHING_TO_INLINE") // @Suppress("NOTHING_TO_INLINE")
// @JvmName("substitutePolynomial") // @JvmName("substitutePolynomial")
// public inline fun LabeledPolynomial<C>.substitute(argument: Map<Variable, LabeledPolynomial<C>>): LabeledPolynomial<C> = this.substitute(ring, argument) // public inline fun LabeledPolynomial<C>.substitute(argument: Map<Symbol, LabeledPolynomial<C>>): LabeledPolynomial<C> = this.substitute(ring, argument)
// //
// @Suppress("NOTHING_TO_INLINE") // @Suppress("NOTHING_TO_INLINE")
// public inline fun LabeledPolynomial<C>.asFunction(): (Map<Variable, C>) -> LabeledPolynomial<C> = { this.substitute(ring, it) } // public inline fun LabeledPolynomial<C>.asFunction(): (Map<Symbol, C>) -> LabeledPolynomial<C> = { this.substitute(ring, it) }
// @Suppress("NOTHING_TO_INLINE") // @Suppress("NOTHING_TO_INLINE")
// public inline fun LabeledPolynomial<C>.asFunctionOnConstants(): (Map<Variable, C>) -> LabeledPolynomial<C> = { this.substitute(ring, it) } // public inline fun LabeledPolynomial<C>.asFunctionOnConstants(): (Map<Symbol, C>) -> LabeledPolynomial<C> = { this.substitute(ring, it) }
// @Suppress("NOTHING_TO_INLINE") // @Suppress("NOTHING_TO_INLINE")
// public inline fun LabeledPolynomial<C>.asFunctionOnPolynomials(): (Map<Variable, LabeledPolynomial<C>>) -> LabeledPolynomial<C> = { this.substitute(ring, it) } // public inline fun LabeledPolynomial<C>.asFunctionOnPolynomials(): (Map<Symbol, LabeledPolynomial<C>>) -> LabeledPolynomial<C> = { this.substitute(ring, it) }
// //
// @Suppress("NOTHING_TO_INLINE") // @Suppress("NOTHING_TO_INLINE")
// public inline operator fun LabeledPolynomial<C>.invoke(argument: Map<Variable, C>): LabeledPolynomial<C> = this.substitute(ring, argument) // public inline operator fun LabeledPolynomial<C>.invoke(argument: Map<Symbol, C>): LabeledPolynomial<C> = this.substitute(ring, argument)
// @Suppress("NOTHING_TO_INLINE") // @Suppress("NOTHING_TO_INLINE")
// @JvmName("invokePolynomial") // @JvmName("invokePolynomial")
// public inline operator fun LabeledPolynomial<C>.invoke(argument: Map<Variable, LabeledPolynomial<C>>): LabeledPolynomial<C> = this.substitute(ring, argument) // public inline operator fun LabeledPolynomial<C>.invoke(argument: Map<Symbol, LabeledPolynomial<C>>): LabeledPolynomial<C> = this.substitute(ring, argument)
// endregion // endregion
// region Utilities // region Utilities
// TODO: Move to region internal utilities with context receiver // TODO: Move to region internal utilities with context receiver
@JvmName("applyAndRemoveZerosInternal") @JvmName("applyAndRemoveZerosInternal")
internal fun MutableMap<Map<Variable, UInt>, C>.applyAndRemoveZeros(block: MutableMap<Map<Variable, UInt>, C>.() -> Unit) : MutableMap<Map<Variable, UInt>, C> { internal fun MutableMap<Map<Symbol, UInt>, C>.applyAndRemoveZeros(block: MutableMap<Map<Symbol, UInt>, C>.() -> Unit) : MutableMap<Map<Symbol, UInt>, C> {
contract { contract {
callsInPlace(block, InvocationKind.EXACTLY_ONCE) callsInPlace(block, InvocationKind.EXACTLY_ONCE)
} }
@ -725,10 +726,10 @@ public class LabeledPolynomialSpace<C, A : Ring<C>>(
for ((degs, c) in this) if (c.isZero()) this.remove(degs) for ((degs, c) in this) if (c.isZero()) this.remove(degs)
return this return this
} }
internal fun Map<Map<Variable, UInt>, C>.applyAndRemoveZeros(block: MutableMap<Map<Variable, UInt>, C>.() -> Unit) : Map<Map<Variable, UInt>, C> = internal fun Map<Map<Symbol, UInt>, C>.applyAndRemoveZeros(block: MutableMap<Map<Symbol, UInt>, C>.() -> Unit) : Map<Map<Symbol, UInt>, C> =
toMutableMap().applyAndRemoveZeros(block) toMutableMap().applyAndRemoveZeros(block)
@OptIn(ExperimentalTypeInference::class) @OptIn(ExperimentalTypeInference::class)
internal inline fun buildCoefficients(@BuilderInference builderAction: MutableMap<Map<Variable, UInt>, C>.() -> Unit): Map<Map<Variable, UInt>, C> { internal inline fun buildCoefficients(@BuilderInference builderAction: MutableMap<Map<Symbol, UInt>, C>.() -> Unit): Map<Map<Symbol, UInt>, C> {
contract { callsInPlace(builderAction, InvocationKind.EXACTLY_ONCE) } contract { callsInPlace(builderAction, InvocationKind.EXACTLY_ONCE) }
return buildMap { return buildMap {
builderAction() builderAction()
@ -736,7 +737,7 @@ public class LabeledPolynomialSpace<C, A : Ring<C>>(
} }
} }
@OptIn(ExperimentalTypeInference::class) @OptIn(ExperimentalTypeInference::class)
internal inline fun buildCoefficients(capacity: Int, @BuilderInference builderAction: MutableMap<Map<Variable, UInt>, C>.() -> Unit): Map<Map<Variable, UInt>, C> { internal inline fun buildCoefficients(capacity: Int, @BuilderInference builderAction: MutableMap<Map<Symbol, UInt>, C>.() -> Unit): Map<Map<Symbol, UInt>, C> {
contract { callsInPlace(builderAction, InvocationKind.EXACTLY_ONCE) } contract { callsInPlace(builderAction, InvocationKind.EXACTLY_ONCE) }
return buildMap(capacity) { return buildMap(capacity) {
builderAction() builderAction()

View File

@ -5,6 +5,7 @@
package space.kscience.kmath.functions package space.kscience.kmath.functions
import space.kscience.kmath.expressions.Symbol
import space.kscience.kmath.operations.Ring import space.kscience.kmath.operations.Ring
import space.kscience.kmath.operations.invoke import space.kscience.kmath.operations.invoke
@ -62,22 +63,22 @@ internal fun labeledRationalFunctionError(message: Any): Nothing = throw Labeled
// ) // )
// TODO: Rewrite former constructors as fabrics // TODO: Rewrite former constructors as fabrics
//constructor(numeratorCoefficients: Map<Map<Variable, Int>, C>, denominatorCoefficients: Map<Map<Variable, Int>, C>) : this( //constructor(numeratorCoefficients: Map<Map<Symbol, Int>, C>, denominatorCoefficients: Map<Map<Symbol, Int>, C>) : this(
//LabeledPolynomial(numeratorCoefficients), //LabeledPolynomial(numeratorCoefficients),
//LabeledPolynomial(denominatorCoefficients) //LabeledPolynomial(denominatorCoefficients)
//) //)
// //
//constructor(numeratorCoefficients: Collection<Pair<Map<Variable, Int>, C>>, denominatorCoefficients: Collection<Pair<Map<Variable, Int>, C>>) : this( //constructor(numeratorCoefficients: Collection<Pair<Map<Symbol, Int>, C>>, denominatorCoefficients: Collection<Pair<Map<Symbol, Int>, C>>) : this(
//LabeledPolynomial(numeratorCoefficients), //LabeledPolynomial(numeratorCoefficients),
//LabeledPolynomial(denominatorCoefficients) //LabeledPolynomial(denominatorCoefficients)
//) //)
// //
//constructor(numerator: LabeledPolynomial<C>) : this(numerator, numerator.getOne()) //constructor(numerator: LabeledPolynomial<C>) : this(numerator, numerator.getOne())
//constructor(numeratorCoefficients: Map<Map<Variable, Int>, C>) : this( //constructor(numeratorCoefficients: Map<Map<Symbol, Int>, C>) : this(
//LabeledPolynomial(numeratorCoefficients) //LabeledPolynomial(numeratorCoefficients)
//) //)
// //
//constructor(numeratorCoefficients: Collection<Pair<Map<Variable, Int>, C>>) : this( //constructor(numeratorCoefficients: Collection<Pair<Map<Symbol, Int>, C>>) : this(
//LabeledPolynomial(numeratorCoefficients) //LabeledPolynomial(numeratorCoefficients)
//) //)
@ -338,11 +339,11 @@ public class LabeledRationalFunctionSpace<C, A: Ring<C>>(
* As consequence all values in the map are positive integers. Also, if the polynomial is constant, the map is empty. * As consequence all values in the map are positive integers. Also, if the polynomial is constant, the map is empty.
* And keys of the map is the same as in [variables]. * And keys of the map is the same as in [variables].
*/ */
public val LabeledPolynomial<C>.degrees: Map<Variable, UInt> get() = polynomialRing { degrees } public val LabeledPolynomial<C>.degrees: Map<Symbol, UInt> get() = polynomialRing { degrees }
/** /**
* Set of all variables that appear in the polynomial in positive exponents. * Set of all variables that appear in the polynomial in positive exponents.
*/ */
public val LabeledPolynomial<C>.variables: Set<Variable> get() = polynomialRing { variables } public val LabeledPolynomial<C>.variables: Set<Symbol> get() = polynomialRing { variables }
/** /**
* Count of all variables that appear in the polynomial in positive exponents. * Count of all variables that appear in the polynomial in positive exponents.
*/ */
@ -353,7 +354,7 @@ public class LabeledRationalFunctionSpace<C, A: Ring<C>>(
/** /**
* Count of all variables that appear in the polynomial in positive exponents. * Count of all variables that appear in the polynomial in positive exponents.
*/ */
public val LabeledRationalFunction<C>.variables: Set<Variable> public val LabeledRationalFunction<C>.variables: Set<Symbol>
get() = numerator.variables union denominator.variables get() = numerator.variables union denominator.variables
/** /**
* Count of all variables that appear in the polynomial in positive exponents. * Count of all variables that appear in the polynomial in positive exponents.
@ -381,21 +382,21 @@ public class LabeledRationalFunctionSpace<C, A: Ring<C>>(
denominator * other denominator * other
) )
// operator fun invoke(arg: Map<Variable, C>): LabeledRationalFunction<C> = // operator fun invoke(arg: Map<Symbol, C>): LabeledRationalFunction<C> =
// LabeledRationalFunction( // LabeledRationalFunction(
// numerator(arg), // numerator(arg),
// denominator(arg) // denominator(arg)
// ) // )
// //
// @JvmName("invokeLabeledPolynomial") // @JvmName("invokeLabeledPolynomial")
// operator fun invoke(arg: Map<Variable, LabeledPolynomial<C>>): LabeledRationalFunction<C> = // operator fun invoke(arg: Map<Symbol, LabeledPolynomial<C>>): LabeledRationalFunction<C> =
// LabeledRationalFunction( // LabeledRationalFunction(
// numerator(arg), // numerator(arg),
// denominator(arg) // denominator(arg)
// ) // )
// //
// @JvmName("invokeLabeledRationalFunction") // @JvmName("invokeLabeledRationalFunction")
// operator fun invoke(arg: Map<Variable, LabeledRationalFunction<C>>): LabeledRationalFunction<C> { // operator fun invoke(arg: Map<Symbol, LabeledRationalFunction<C>>): LabeledRationalFunction<C> {
// var num = numerator invokeRFTakeNumerator arg // var num = numerator invokeRFTakeNumerator arg
// var den = denominator invokeRFTakeNumerator arg // var den = denominator invokeRFTakeNumerator arg
// for (variable in variables) if (variable in arg) { // for (variable in variables) if (variable in arg) {
@ -410,56 +411,56 @@ public class LabeledRationalFunctionSpace<C, A: Ring<C>>(
// //
// override fun toString(): String = toString(emptyMap()) // override fun toString(): String = toString(emptyMap())
// //
// fun toString(names: Map<Variable, String> = emptyMap()): String = // fun toString(names: Map<Symbol, String> = emptyMap()): String =
// when (true) { // when (true) {
// numerator.isZero() -> "0" // numerator.isZero() -> "0"
// denominator.isOne() -> numerator.toString(names) // denominator.isOne() -> numerator.toString(names)
// else -> "${numerator.toStringWithBrackets(names)}/${denominator.toStringWithBrackets(names)}" // else -> "${numerator.toStringWithBrackets(names)}/${denominator.toStringWithBrackets(names)}"
// } // }
// //
// fun toString(namer: (Variable) -> String): String = // fun toString(namer: (Symbol) -> String): String =
// when (true) { // when (true) {
// numerator.isZero() -> "0" // numerator.isZero() -> "0"
// denominator.isOne() -> numerator.toString(namer) // denominator.isOne() -> numerator.toString(namer)
// else -> "${numerator.toStringWithBrackets(namer)}/${denominator.toStringWithBrackets(namer)}" // else -> "${numerator.toStringWithBrackets(namer)}/${denominator.toStringWithBrackets(namer)}"
// } // }
// //
// fun toStringWithBrackets(names: Map<Variable, String> = emptyMap()): String = // fun toStringWithBrackets(names: Map<Symbol, String> = emptyMap()): String =
// when (true) { // when (true) {
// numerator.isZero() -> "0" // numerator.isZero() -> "0"
// denominator.isOne() -> numerator.toStringWithBrackets(names) // denominator.isOne() -> numerator.toStringWithBrackets(names)
// else -> "(${numerator.toStringWithBrackets(names)}/${denominator.toStringWithBrackets(names)})" // else -> "(${numerator.toStringWithBrackets(names)}/${denominator.toStringWithBrackets(names)})"
// } // }
// //
// fun toStringWithBrackets(namer: (Variable) -> String): String = // fun toStringWithBrackets(namer: (Symbol) -> String): String =
// when (true) { // when (true) {
// numerator.isZero() -> "0" // numerator.isZero() -> "0"
// denominator.isOne() -> numerator.toStringWithBrackets(namer) // denominator.isOne() -> numerator.toStringWithBrackets(namer)
// else -> "(${numerator.toStringWithBrackets(namer)}/${denominator.toStringWithBrackets(namer)})" // else -> "(${numerator.toStringWithBrackets(namer)}/${denominator.toStringWithBrackets(namer)})"
// } // }
// //
// fun toReversedString(names: Map<Variable, String> = emptyMap()): String = // fun toReversedString(names: Map<Symbol, String> = emptyMap()): String =
// when (true) { // when (true) {
// numerator.isZero() -> "0" // numerator.isZero() -> "0"
// denominator.isOne() -> numerator.toReversedString(names) // denominator.isOne() -> numerator.toReversedString(names)
// else -> "${numerator.toReversedStringWithBrackets(names)}/${denominator.toReversedStringWithBrackets(names)}" // else -> "${numerator.toReversedStringWithBrackets(names)}/${denominator.toReversedStringWithBrackets(names)}"
// } // }
// //
// fun toReversedString(namer: (Variable) -> String): String = // fun toReversedString(namer: (Symbol) -> String): String =
// when (true) { // when (true) {
// numerator.isZero() -> "0" // numerator.isZero() -> "0"
// denominator.isOne() -> numerator.toReversedString(namer) // denominator.isOne() -> numerator.toReversedString(namer)
// else -> "${numerator.toReversedStringWithBrackets(namer)}/${denominator.toReversedStringWithBrackets(namer)}" // else -> "${numerator.toReversedStringWithBrackets(namer)}/${denominator.toReversedStringWithBrackets(namer)}"
// } // }
// //
// fun toReversedStringWithBrackets(names: Map<Variable, String> = emptyMap()): String = // fun toReversedStringWithBrackets(names: Map<Symbol, String> = emptyMap()): String =
// when (true) { // when (true) {
// numerator.isZero() -> "0" // numerator.isZero() -> "0"
// denominator.isOne() -> numerator.toReversedStringWithBrackets(names) // denominator.isOne() -> numerator.toReversedStringWithBrackets(names)
// else -> "(${numerator.toReversedStringWithBrackets(names)}/${denominator.toReversedStringWithBrackets(names)})" // else -> "(${numerator.toReversedStringWithBrackets(names)}/${denominator.toReversedStringWithBrackets(names)})"
// } // }
// //
// fun toReversedStringWithBrackets(namer: (Variable) -> String): String = // fun toReversedStringWithBrackets(namer: (Symbol) -> String): String =
// when (true) { // when (true) {
// numerator.isZero() -> "0" // numerator.isZero() -> "0"
// denominator.isOne() -> numerator.toReversedStringWithBrackets(namer) // denominator.isOne() -> numerator.toReversedStringWithBrackets(namer)

View File

@ -1,38 +0,0 @@
package space.kscience.kmath.functions
import kotlin.reflect.KProperty
/**
* Represents class of labeled variables like usual
* `x`, `y`, `z`, `a`, `b`, `n`, `m`, etc.
*
* Variables does not contain any information about field (or ring, ets.) they are considered in
* and therefore about coefficient.
*
* @property name Is the label or name of variable. For `x` it is `"x"`, for `n` &ndash; `"n"`, etc.
*/
public data class Variable (val name: String) : Comparable<Variable> {
/**
* Represents the variable as a string.
*
* @return Only name of the variable.
*/
override fun toString(): String = name
/**
* Compares two variables.
* Comparison is realised by comparison of variables' names.
*
* Used in [LabeledPolynomial] and [LabeledRationalFunction] to sort monomials in
* [LabeledPolynomial.toString] and [LabeledRationalFunction.toString] in lexicographic order.
*
* @see Comparable.compareTo
* @sample LabeledPolynomial.monomialComparator
* @return Only name of the variable.
*/
override fun compareTo(other: Variable): Int = name.compareTo(other.name)
public companion object {
public operator fun getValue(thisRef: Any?, property: KProperty<*>) : Variable = Variable(property.name)
}
}

View File

@ -5,10 +5,14 @@
package space.kscience.kmath.functions package space.kscience.kmath.functions
import space.kscience.kmath.expressions.Symbol
import space.kscience.kmath.misc.UnstableKMathAPI import space.kscience.kmath.misc.UnstableKMathAPI
import space.kscience.kmath.operations.* import space.kscience.kmath.operations.Field
import kotlin.contracts.* import space.kscience.kmath.operations.Ring
import kotlin.math.max import space.kscience.kmath.operations.invoke
import kotlin.contracts.ExperimentalContracts
import kotlin.contracts.InvocationKind
import kotlin.contracts.contract
// TODO: Docs // TODO: Docs
@ -31,10 +35,10 @@ import kotlin.math.max
// //
//// endregion //// endregion
//// region Variables //// region Symbols
// //
//context(LabeledPolynomialSpace<C, A>) //context(LabeledPolynomialSpace<C, A>)
//fun <C, A: Ring<C>> power(arg: Variable, pow: UInt): LabeledPolynomial<C> = //fun <C, A: Ring<C>> power(arg: Symbol, pow: UInt): LabeledPolynomial<C> =
// if (pow == 0U) one // if (pow == 0U) one
// else LabeledPolynomial<C>(mapOf( // else LabeledPolynomial<C>(mapOf(
// mapOf(arg to pow) to constantOne // mapOf(arg to pow) to constantOne
@ -45,7 +49,7 @@ import kotlin.math.max
//// region Polynomials //// region Polynomials
// //
//context(LabeledPolynomialSpace<C, A>) //context(LabeledPolynomialSpace<C, A>)
//fun <C, A: Ring<C>> number(value: Int): LabeledPolynomial<C> = ring { LabeledPolynomial<C>(mapOf(emptyMap<Variable, UInt>() to number<C>(value))) } //fun <C, A: Ring<C>> number(value: Int): LabeledPolynomial<C> = ring { LabeledPolynomial<C>(mapOf(emptyMap<Symbol, UInt>() to number<C>(value))) }
// //
//context(LabeledPolynomialSpace<C, A>) //context(LabeledPolynomialSpace<C, A>)
//fun <C, A: Ring<C>> multiplyWithPower(base: LabeledPolynomial<C>, arg: LabeledPolynomial<C>, pow: UInt): LabeledPolynomial<C> = //fun <C, A: Ring<C>> multiplyWithPower(base: LabeledPolynomial<C>, arg: LabeledPolynomial<C>, pow: UInt): LabeledPolynomial<C> =
@ -97,7 +101,7 @@ public inline fun <C, A : Ring<C>, R> A.labeledPolynomial(block: LabeledPolynomi
// * Consider that monomials are sorted in lexicographic order. // * Consider that monomials are sorted in lexicographic order.
// */ // */
//context(LabeledPolynomialSpace<C, A>) //context(LabeledPolynomialSpace<C, A>)
//fun <C, A: Ring<C>> LabeledPolynomial<C>.represent(names: Map<Variable, String> = emptyMap()): String = //fun <C, A: Ring<C>> LabeledPolynomial<C>.represent(names: Map<Symbol, String> = emptyMap()): String =
// coefficients.entries // coefficients.entries
// .sortedWith { o1, o2 -> LabeledPolynomial.monomialComparator.compare(o1.key, o2.key) } // .sortedWith { o1, o2 -> LabeledPolynomial.monomialComparator.compare(o1.key, o2.key) }
// .asSequence() // .asSequence()
@ -130,7 +134,7 @@ public inline fun <C, A : Ring<C>, R> A.labeledPolynomial(block: LabeledPolynomi
// * Consider that monomials are sorted in lexicographic order. // * Consider that monomials are sorted in lexicographic order.
// */ // */
//context(LabeledPolynomialSpace<C, A>) //context(LabeledPolynomialSpace<C, A>)
//fun <C, A: Ring<C>> LabeledPolynomial<C>.represent(namer: (Variable) -> String): String = //fun <C, A: Ring<C>> LabeledPolynomial<C>.represent(namer: (Symbol) -> String): String =
// coefficients.entries // coefficients.entries
// .sortedWith { o1, o2 -> LabeledPolynomial.monomialComparator.compare(o1.key, o2.key) } // .sortedWith { o1, o2 -> LabeledPolynomial.monomialComparator.compare(o1.key, o2.key) }
// .asSequence() // .asSequence()
@ -163,7 +167,7 @@ public inline fun <C, A : Ring<C>, R> A.labeledPolynomial(block: LabeledPolynomi
// * Consider that monomials are sorted in lexicographic order. // * Consider that monomials are sorted in lexicographic order.
// */ // */
//context(LabeledPolynomialSpace<C, A>) //context(LabeledPolynomialSpace<C, A>)
//fun <C, A: Ring<C>> LabeledPolynomial<C>.representWithBrackets(names: Map<Variable, String> = emptyMap()): String = //fun <C, A: Ring<C>> LabeledPolynomial<C>.representWithBrackets(names: Map<Symbol, String> = emptyMap()): String =
// with(represent(names)) { if (coefficients.count() == 1) this else "($this)" } // with(represent(names)) { if (coefficients.count() == 1) this else "($this)" }
// //
///** ///**
@ -172,7 +176,7 @@ public inline fun <C, A : Ring<C>, R> A.labeledPolynomial(block: LabeledPolynomi
// * Consider that monomials are sorted in lexicographic order. // * Consider that monomials are sorted in lexicographic order.
// */ // */
//context(LabeledPolynomialSpace<C, A>) //context(LabeledPolynomialSpace<C, A>)
//fun <C, A: Ring<C>> LabeledPolynomial<C>.representWithBrackets(namer: (Variable) -> String): String = //fun <C, A: Ring<C>> LabeledPolynomial<C>.representWithBrackets(namer: (Symbol) -> String): String =
// with(represent(namer)) { if (coefficients.count() == 1) this else "($this)" } // with(represent(namer)) { if (coefficients.count() == 1) this else "($this)" }
// //
///** ///**
@ -180,7 +184,7 @@ public inline fun <C, A : Ring<C>, R> A.labeledPolynomial(block: LabeledPolynomi
// * Consider that monomials are sorted in **reversed** lexicographic order. // * Consider that monomials are sorted in **reversed** lexicographic order.
// */ // */
//context(LabeledPolynomialSpace<C, A>) //context(LabeledPolynomialSpace<C, A>)
//fun <C, A: Ring<C>> LabeledPolynomial<C>.representReversed(names: Map<Variable, String> = emptyMap()): String = //fun <C, A: Ring<C>> LabeledPolynomial<C>.representReversed(names: Map<Symbol, String> = emptyMap()): String =
// coefficients.entries // coefficients.entries
// .sortedWith { o1, o2 -> -LabeledPolynomial.monomialComparator.compare(o1.key, o2.key) } // .sortedWith { o1, o2 -> -LabeledPolynomial.monomialComparator.compare(o1.key, o2.key) }
// .asSequence() // .asSequence()
@ -213,7 +217,7 @@ public inline fun <C, A : Ring<C>, R> A.labeledPolynomial(block: LabeledPolynomi
// * Consider that monomials are sorted in **reversed** lexicographic order. // * Consider that monomials are sorted in **reversed** lexicographic order.
// */ // */
//context(LabeledPolynomialSpace<C, A>) //context(LabeledPolynomialSpace<C, A>)
//fun <C, A: Ring<C>> LabeledPolynomial<C>.representReversed(namer: (Variable) -> String): String = //fun <C, A: Ring<C>> LabeledPolynomial<C>.representReversed(namer: (Symbol) -> String): String =
// coefficients.entries // coefficients.entries
// .sortedWith { o1, o2 -> -LabeledPolynomial.monomialComparator.compare(o1.key, o2.key) } // .sortedWith { o1, o2 -> -LabeledPolynomial.monomialComparator.compare(o1.key, o2.key) }
// .asSequence() // .asSequence()
@ -246,7 +250,7 @@ public inline fun <C, A : Ring<C>, R> A.labeledPolynomial(block: LabeledPolynomi
// * Consider that monomials are sorted in **reversed** lexicographic order. // * Consider that monomials are sorted in **reversed** lexicographic order.
// */ // */
//context(LabeledPolynomialSpace<C, A>) //context(LabeledPolynomialSpace<C, A>)
//fun <C, A: Ring<C>> LabeledPolynomial<C>.representReversedWithBrackets(names: Map<Variable, String> = emptyMap()): String = //fun <C, A: Ring<C>> LabeledPolynomial<C>.representReversedWithBrackets(names: Map<Symbol, String> = emptyMap()): String =
// with(representReversed(names)) { if (coefficients.count() == 1) this else "($this)" } // with(representReversed(names)) { if (coefficients.count() == 1) this else "($this)" }
// //
///** ///**
@ -255,7 +259,7 @@ public inline fun <C, A : Ring<C>, R> A.labeledPolynomial(block: LabeledPolynomi
// * Consider that monomials are sorted in **reversed** lexicographic order. // * Consider that monomials are sorted in **reversed** lexicographic order.
// */ // */
//context(LabeledPolynomialSpace<C, A>) //context(LabeledPolynomialSpace<C, A>)
//fun <C, A: Ring<C>> LabeledPolynomial<C>.representReversedWithBrackets(namer: (Variable) -> String): String = //fun <C, A: Ring<C>> LabeledPolynomial<C>.representReversedWithBrackets(namer: (Symbol) -> String): String =
// with(representReversed(namer)) { if (coefficients.count() == 1) this else "($this)" } // with(representReversed(namer)) { if (coefficients.count() == 1) this else "($this)" }
// //
//// endregion //// endregion
@ -279,7 +283,7 @@ public inline fun <C, A : Ring<C>, R> A.labeledPolynomial(block: LabeledPolynomi
//// region Polynomial substitution and functional representation //// region Polynomial substitution and functional representation
// //
//public fun <C> LabeledPolynomial<C>.substitute(ring: Ring<C>, args: Map<Variable, C>): LabeledPolynomial<C> = ring { //public fun <C> LabeledPolynomial<C>.substitute(ring: Ring<C>, args: Map<Symbol, C>): LabeledPolynomial<C> = ring {
// if (coefficients.isEmpty()) return this@substitute // if (coefficients.isEmpty()) return this@substitute
// LabeledPolynomial<C>( // LabeledPolynomial<C>(
// buildMap { // buildMap {
@ -297,7 +301,7 @@ public inline fun <C, A : Ring<C>, R> A.labeledPolynomial(block: LabeledPolynomi
//// TODO: Replace with optimisation: the [result] may be unboxed, and all operations may be performed as soon as //// TODO: Replace with optimisation: the [result] may be unboxed, and all operations may be performed as soon as
//// possible on it //// possible on it
//@JvmName("substitutePolynomial") //@JvmName("substitutePolynomial")
//fun <C> LabeledPolynomial<C>.substitute(ring: Ring<C>, arg: Map<Variable, LabeledPolynomial<C>>) : LabeledPolynomial<C> = //fun <C> LabeledPolynomial<C>.substitute(ring: Ring<C>, arg: Map<Symbol, LabeledPolynomial<C>>) : LabeledPolynomial<C> =
// ring.labeledPolynomial { // ring.labeledPolynomial {
// if (coefficients.isEmpty()) return zero // if (coefficients.isEmpty()) return zero
// coefficients // coefficients
@ -315,10 +319,10 @@ public inline fun <C, A : Ring<C>, R> A.labeledPolynomial(block: LabeledPolynomi
// //
//// TODO: Substitute rational function //// TODO: Substitute rational function
// //
//fun <C, A : Ring<C>> LabeledPolynomial<C>.asFunctionOver(ring: A): (Map<Variable, C>) -> LabeledPolynomial<C> = //fun <C, A : Ring<C>> LabeledPolynomial<C>.asFunctionOver(ring: A): (Map<Symbol, C>) -> LabeledPolynomial<C> =
// { substitute(ring, it) } // { substitute(ring, it) }
// //
//fun <C, A : Ring<C>> LabeledPolynomial<C>.asPolynomialFunctionOver(ring: A): (Map<Variable, LabeledPolynomial<C>>) -> LabeledPolynomial<C> = //fun <C, A : Ring<C>> LabeledPolynomial<C>.asPolynomialFunctionOver(ring: A): (Map<Symbol, LabeledPolynomial<C>>) -> LabeledPolynomial<C> =
// { substitute(ring, it) } // { substitute(ring, it) }
// //
//// endregion //// endregion
@ -331,7 +335,7 @@ public inline fun <C, A : Ring<C>, R> A.labeledPolynomial(block: LabeledPolynomi
@UnstableKMathAPI @UnstableKMathAPI
public fun <C, A : Ring<C>> LabeledPolynomial<C>.derivativeWithRespectTo( public fun <C, A : Ring<C>> LabeledPolynomial<C>.derivativeWithRespectTo(
algebra: A, algebra: A,
variable: Variable, variable: Symbol,
): LabeledPolynomial<C> = algebra { ): LabeledPolynomial<C> = algebra {
LabeledPolynomial<C>( LabeledPolynomial<C>(
buildMap(coefficients.size) { buildMap(coefficients.size) {
@ -360,7 +364,7 @@ public fun <C, A : Ring<C>> LabeledPolynomial<C>.derivativeWithRespectTo(
@UnstableKMathAPI @UnstableKMathAPI
public fun <C, A : Ring<C>> LabeledPolynomial<C>.derivativeWithRespectTo( public fun <C, A : Ring<C>> LabeledPolynomial<C>.derivativeWithRespectTo(
algebra: A, algebra: A,
variables: Collection<Variable>, variables: Collection<Symbol>,
): LabeledPolynomial<C> = algebra { ): LabeledPolynomial<C> = algebra {
val cleanedVariables = variables.toSet() val cleanedVariables = variables.toSet()
if (cleanedVariables.isEmpty()) return this@derivativeWithRespectTo if (cleanedVariables.isEmpty()) return this@derivativeWithRespectTo
@ -391,7 +395,7 @@ public fun <C, A : Ring<C>> LabeledPolynomial<C>.derivativeWithRespectTo(
@UnstableKMathAPI @UnstableKMathAPI
public fun <C, A : Ring<C>> LabeledPolynomial<C>.nthDerivativeWithRespectTo( public fun <C, A : Ring<C>> LabeledPolynomial<C>.nthDerivativeWithRespectTo(
algebra: A, algebra: A,
variable: Variable, variable: Symbol,
order: UInt order: UInt
): LabeledPolynomial<C> = algebra { ): LabeledPolynomial<C> = algebra {
if (order == 0u) return this@nthDerivativeWithRespectTo if (order == 0u) return this@nthDerivativeWithRespectTo
@ -425,7 +429,7 @@ public fun <C, A : Ring<C>> LabeledPolynomial<C>.nthDerivativeWithRespectTo(
@UnstableKMathAPI @UnstableKMathAPI
public fun <C, A : Ring<C>> LabeledPolynomial<C>.nthDerivativeWithRespectTo( public fun <C, A : Ring<C>> LabeledPolynomial<C>.nthDerivativeWithRespectTo(
algebra: A, algebra: A,
variablesAndOrders: Map<Variable, UInt>, variablesAndOrders: Map<Symbol, UInt>,
): LabeledPolynomial<C> = algebra { ): LabeledPolynomial<C> = algebra {
val filteredVariablesAndOrders = variablesAndOrders.filterValues { it != 0u } val filteredVariablesAndOrders = variablesAndOrders.filterValues { it != 0u }
if (filteredVariablesAndOrders.isEmpty()) return this@nthDerivativeWithRespectTo if (filteredVariablesAndOrders.isEmpty()) return this@nthDerivativeWithRespectTo
@ -462,13 +466,13 @@ public fun <C, A : Ring<C>> LabeledPolynomial<C>.nthDerivativeWithRespectTo(
@UnstableKMathAPI @UnstableKMathAPI
public fun <C, A : Field<C>> LabeledPolynomial<C>.antiderivativeWithRespectTo( public fun <C, A : Field<C>> LabeledPolynomial<C>.antiderivativeWithRespectTo(
algebra: A, algebra: A,
variable: Variable, variable: Symbol,
): LabeledPolynomial<C> = algebra { ): LabeledPolynomial<C> = algebra {
LabeledPolynomial<C>( LabeledPolynomial<C>(
buildMap(coefficients.size) { buildMap(coefficients.size) {
coefficients coefficients
.forEach { (degs, c) -> .forEach { (degs, c) ->
val newDegs = buildMap<Variable, UInt>(degs.size + 1) { val newDegs = buildMap<Symbol, UInt>(degs.size + 1) {
put(variable, 1u) put(variable, 1u)
for ((vari, deg) in degs) put(vari, deg + getOrElse(vari) { 0u }) for ((vari, deg) in degs) put(vari, deg + getOrElse(vari) { 0u })
} }
@ -487,7 +491,7 @@ public fun <C, A : Field<C>> LabeledPolynomial<C>.antiderivativeWithRespectTo(
@UnstableKMathAPI @UnstableKMathAPI
public fun <C, A : Field<C>> LabeledPolynomial<C>.antiderivativeWithRespectTo( public fun <C, A : Field<C>> LabeledPolynomial<C>.antiderivativeWithRespectTo(
algebra: A, algebra: A,
variables: Collection<Variable>, variables: Collection<Symbol>,
): LabeledPolynomial<C> = algebra { ): LabeledPolynomial<C> = algebra {
val cleanedVariables = variables.toSet() val cleanedVariables = variables.toSet()
if (cleanedVariables.isEmpty()) return this@antiderivativeWithRespectTo if (cleanedVariables.isEmpty()) return this@antiderivativeWithRespectTo
@ -495,7 +499,7 @@ public fun <C, A : Field<C>> LabeledPolynomial<C>.antiderivativeWithRespectTo(
buildMap(coefficients.size) { buildMap(coefficients.size) {
coefficients coefficients
.forEach { (degs, c) -> .forEach { (degs, c) ->
val newDegs = buildMap<Variable, UInt>(degs.size + 1) { val newDegs = buildMap<Symbol, UInt>(degs.size + 1) {
for (variable in cleanedVariables) put(variable, 1u) for (variable in cleanedVariables) put(variable, 1u)
for ((vari, deg) in degs) put(vari, deg + getOrElse(vari) { 0u }) for ((vari, deg) in degs) put(vari, deg + getOrElse(vari) { 0u })
} }
@ -514,7 +518,7 @@ public fun <C, A : Field<C>> LabeledPolynomial<C>.antiderivativeWithRespectTo(
@UnstableKMathAPI @UnstableKMathAPI
public fun <C, A : Field<C>> LabeledPolynomial<C>.nthAntiderivativeWithRespectTo( public fun <C, A : Field<C>> LabeledPolynomial<C>.nthAntiderivativeWithRespectTo(
algebra: A, algebra: A,
variable: Variable, variable: Symbol,
order: UInt order: UInt
): LabeledPolynomial<C> = algebra { ): LabeledPolynomial<C> = algebra {
if (order == 0u) return this@nthAntiderivativeWithRespectTo if (order == 0u) return this@nthAntiderivativeWithRespectTo
@ -522,7 +526,7 @@ public fun <C, A : Field<C>> LabeledPolynomial<C>.nthAntiderivativeWithRespectTo
buildMap(coefficients.size) { buildMap(coefficients.size) {
coefficients coefficients
.forEach { (degs, c) -> .forEach { (degs, c) ->
val newDegs = buildMap<Variable, UInt>(degs.size + 1) { val newDegs = buildMap<Symbol, UInt>(degs.size + 1) {
put(variable, order) put(variable, order)
for ((vari, deg) in degs) put(vari, deg + getOrElse(vari) { 0u }) for ((vari, deg) in degs) put(vari, deg + getOrElse(vari) { 0u })
} }
@ -544,7 +548,7 @@ public fun <C, A : Field<C>> LabeledPolynomial<C>.nthAntiderivativeWithRespectTo
@UnstableKMathAPI @UnstableKMathAPI
public fun <C, A : Field<C>> LabeledPolynomial<C>.nthAntiderivativeWithRespectTo( public fun <C, A : Field<C>> LabeledPolynomial<C>.nthAntiderivativeWithRespectTo(
algebra: A, algebra: A,
variablesAndOrders: Map<Variable, UInt>, variablesAndOrders: Map<Symbol, UInt>,
): LabeledPolynomial<C> = algebra { ): LabeledPolynomial<C> = algebra {
val filteredVariablesAndOrders = variablesAndOrders.filterValues { it != 0u } val filteredVariablesAndOrders = variablesAndOrders.filterValues { it != 0u }
if (filteredVariablesAndOrders.isEmpty()) return this@nthAntiderivativeWithRespectTo if (filteredVariablesAndOrders.isEmpty()) return this@nthAntiderivativeWithRespectTo
@ -552,7 +556,7 @@ public fun <C, A : Field<C>> LabeledPolynomial<C>.nthAntiderivativeWithRespectTo
buildMap(coefficients.size) { buildMap(coefficients.size) {
coefficients coefficients
.forEach { (degs, c) -> .forEach { (degs, c) ->
val newDegs = buildMap<Variable, UInt>(degs.size + 1) { val newDegs = buildMap<Symbol, UInt>(degs.size + 1) {
for ((variable, order) in filteredVariablesAndOrders) put(variable, order) for ((variable, order) in filteredVariablesAndOrders) put(variable, order)
for ((vari, deg) in degs) put(vari, deg + getOrElse(vari) { 0u }) for ((vari, deg) in degs) put(vari, deg + getOrElse(vari) { 0u })
} }