Feature: Polynomials and rational functions #469
@ -331,13 +331,13 @@ public class NumberedPolynomialSpace<C, A : Ring<C>>(
|
|||||||
* the result is `-1`.
|
* the result is `-1`.
|
||||||
*/
|
*/
|
||||||
public val NumberedPolynomial<C>.lastVariable: Int
|
public val NumberedPolynomial<C>.lastVariable: Int
|
||||||
get() = coefficients.entries.maxOfOrNull { (degs, _) -> degs.lastIndex } ?: -1
|
get() = coefficients.keys.maxOfOrNull { degs -> degs.lastIndex } ?: -1
|
||||||
/**
|
/**
|
||||||
* Degree of the polynomial, [see also](https://en.wikipedia.org/wiki/Degree_of_a_polynomial). If the polynomial is
|
* Degree of the polynomial, [see also](https://en.wikipedia.org/wiki/Degree_of_a_polynomial). If the polynomial is
|
||||||
* zero, degree is -1.
|
* zero, degree is -1.
|
||||||
*/
|
*/
|
||||||
override val NumberedPolynomial<C>.degree: Int
|
override val NumberedPolynomial<C>.degree: Int
|
||||||
get() = coefficients.entries.maxOfOrNull { (degs, _) -> degs.sum().toInt() } ?: -1
|
get() = coefficients.keys.maxOfOrNull { degs -> degs.sum().toInt() } ?: -1
|
||||||
/**
|
/**
|
||||||
* List that associates indices of variables (that appear in the polynomial in positive exponents) with their most
|
* List that associates indices of variables (that appear in the polynomial in positive exponents) with their most
|
||||||
* exponents in which the variables are appeared in the polynomial.
|
* exponents in which the variables are appeared in the polynomial.
|
||||||
@ -348,7 +348,7 @@ public class NumberedPolynomialSpace<C, A : Ring<C>>(
|
|||||||
public val NumberedPolynomial<C>.degrees: List<UInt>
|
public val NumberedPolynomial<C>.degrees: List<UInt>
|
||||||
get() =
|
get() =
|
||||||
MutableList(lastVariable + 1) { 0u }.apply {
|
MutableList(lastVariable + 1) { 0u }.apply {
|
||||||
coefficients.entries.forEach { (degs, _) ->
|
coefficients.keys.forEach { degs ->
|
||||||
degs.forEachIndexed { index, deg ->
|
degs.forEachIndexed { index, deg ->
|
||||||
this[index] = max(this[index], deg)
|
this[index] = max(this[index], deg)
|
||||||
}
|
}
|
||||||
@ -358,13 +358,13 @@ public class NumberedPolynomialSpace<C, A : Ring<C>>(
|
|||||||
* Counts degree of the polynomial by the specified [variable].
|
* Counts degree of the polynomial by the specified [variable].
|
||||||
*/
|
*/
|
||||||
public fun NumberedPolynomial<C>.degreeBy(variable: Int): UInt =
|
public fun NumberedPolynomial<C>.degreeBy(variable: Int): UInt =
|
||||||
coefficients.entries.maxOfOrNull { (degs, _) -> degs.getOrElse(variable) { 0u } } ?: 0u
|
coefficients.keys.maxOfOrNull { degs -> degs.getOrElse(variable) { 0u } } ?: 0u
|
||||||
/**
|
/**
|
||||||
* Counts degree of the polynomial by the specified [variables].
|
* Counts degree of the polynomial by the specified [variables].
|
||||||
*/
|
*/
|
||||||
public fun NumberedPolynomial<C>.degreeBy(variables: Collection<Int>): UInt =
|
public fun NumberedPolynomial<C>.degreeBy(variables: Collection<Int>): UInt =
|
||||||
coefficients.entries.maxOfOrNull { (degs, _) ->
|
coefficients.keys.maxOfOrNull { degs ->
|
||||||
degs.withIndex().filter { (index, _) -> index in variables }.sumOf { it.value }
|
degs.withIndex().fold(0u) { acc, (index, value) -> if (index in variables) acc + value else acc }
|
||||||
} ?: 0u
|
} ?: 0u
|
||||||
/**
|
/**
|
||||||
* Count of variables occurring in the polynomial with positive power. If there is no such variable,
|
* Count of variables occurring in the polynomial with positive power. If there is no such variable,
|
||||||
|
@ -283,6 +283,7 @@ public class NumberedPolynomialTermSignatureBuilder {
|
|||||||
* Declaring another power of the same variable will increase its degree by received degree.
|
* Declaring another power of the same variable will increase its degree by received degree.
|
||||||
*/
|
*/
|
||||||
public infix fun Int.inPowerOf(deg: UInt) {
|
public infix fun Int.inPowerOf(deg: UInt) {
|
||||||
|
if (deg == 0u) return
|
||||||
val index = this - 1
|
val index = this - 1
|
||||||
if (index > signature.lastIndex) {
|
if (index > signature.lastIndex) {
|
||||||
signature.addAll(List(index - signature.lastIndex - 1) { 0u })
|
signature.addAll(List(index - signature.lastIndex - 1) { 0u })
|
||||||
|
@ -23,8 +23,8 @@ class NumberedConstructorsTest {
|
|||||||
),
|
),
|
||||||
Int.algebra.numberedPolynomialSpace {
|
Int.algebra.numberedPolynomialSpace {
|
||||||
NumberedPolynomial {
|
NumberedPolynomial {
|
||||||
5 { 1 inPowerOf 2u; 3 inPowerOf 3u }
|
5 { 1 pow 2u; 3 pow 3u }
|
||||||
(-6) { 2 inPowerOf 1u }
|
(-6) { 2 pow 1u }
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"test 1"
|
"test 1"
|
||||||
@ -47,8 +47,20 @@ class NumberedConstructorsTest {
|
|||||||
),
|
),
|
||||||
Int.algebra.numberedPolynomialSpace {
|
Int.algebra.numberedPolynomialSpace {
|
||||||
NumberedPolynomial {
|
NumberedPolynomial {
|
||||||
5 { 1 inPowerOf 1u; 1 inPowerOf 1u }
|
5 { 1 pow 1u; 1 pow 1u }
|
||||||
(-6) { 1 inPowerOf 2u }
|
(-6) { 1 pow 2u }
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"test 3"
|
||||||
|
)
|
||||||
|
assertEquals(
|
||||||
|
NumberedPolynomialAsIs(
|
||||||
|
listOf(2u) to -1,
|
||||||
|
),
|
||||||
|
Int.algebra.numberedPolynomialSpace {
|
||||||
|
NumberedPolynomial {
|
||||||
|
5 { 1 pow 1u; 1 pow 1u }
|
||||||
|
(-6) { 1 pow 2u; 3 pow 0u }
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"test 3"
|
"test 3"
|
||||||
|
@ -9,9 +9,7 @@ package space.kscience.kmath.functions
|
|||||||
|
|
||||||
import space.kscience.kmath.misc.UnstableKMathAPI
|
import space.kscience.kmath.misc.UnstableKMathAPI
|
||||||
import space.kscience.kmath.test.misc.*
|
import space.kscience.kmath.test.misc.*
|
||||||
import kotlin.test.Test
|
import kotlin.test.*
|
||||||
import kotlin.test.assertEquals
|
|
||||||
import kotlin.test.assertSame
|
|
||||||
|
|
||||||
|
|
||||||
@UnstableKMathAPI
|
@UnstableKMathAPI
|
||||||
@ -1365,4 +1363,304 @@ class NumberedPolynomialTest {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@Test
|
||||||
|
fun test_lastVariable() {
|
||||||
|
val o = Rational(0)
|
||||||
|
RationalField.numberedPolynomialSpace {
|
||||||
|
assertEquals(
|
||||||
|
-1,
|
||||||
|
NumberedPolynomial {}.lastVariable,
|
||||||
|
"test 1"
|
||||||
|
)
|
||||||
|
assertEquals(
|
||||||
|
-1,
|
||||||
|
NumberedPolynomial {
|
||||||
|
o {}
|
||||||
|
}.lastVariable,
|
||||||
|
"test 2"
|
||||||
|
)
|
||||||
|
assertEquals(
|
||||||
|
2,
|
||||||
|
NumberedPolynomial {
|
||||||
|
o { 1 pow 1u; 2 pow 2u; 3 pow 3u }
|
||||||
|
}.lastVariable,
|
||||||
|
"test 3"
|
||||||
|
)
|
||||||
|
assertEquals(
|
||||||
|
3,
|
||||||
|
NumberedPolynomial {
|
||||||
|
o { 1 pow 0u; 2 pow 1u; 3 pow 2u; 4 pow 1u; 5 pow 0u }
|
||||||
|
}.also { println(it) }.lastVariable,
|
||||||
|
"test 4"
|
||||||
|
)
|
||||||
|
assertEquals(
|
||||||
|
2,
|
||||||
|
NumberedPolynomial {
|
||||||
|
o {}
|
||||||
|
o { 2 pow 1u }
|
||||||
|
o { 1 pow 2u; 3 pow 1u }
|
||||||
|
}.lastVariable,
|
||||||
|
"test 5"
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@Test
|
||||||
|
fun test_degree() {
|
||||||
|
val o = Rational(0)
|
||||||
|
RationalField.numberedPolynomialSpace {
|
||||||
|
assertEquals(
|
||||||
|
-1,
|
||||||
|
NumberedPolynomial {}.degree,
|
||||||
|
"test 1"
|
||||||
|
)
|
||||||
|
assertEquals(
|
||||||
|
0,
|
||||||
|
NumberedPolynomial {
|
||||||
|
o {}
|
||||||
|
}.degree,
|
||||||
|
"test 2"
|
||||||
|
)
|
||||||
|
assertEquals(
|
||||||
|
6,
|
||||||
|
NumberedPolynomial {
|
||||||
|
o { 1 pow 1u; 2 pow 2u; 3 pow 3u }
|
||||||
|
}.degree,
|
||||||
|
"test 3"
|
||||||
|
)
|
||||||
|
assertEquals(
|
||||||
|
4,
|
||||||
|
NumberedPolynomial {
|
||||||
|
o { 1 pow 0u; 2 pow 1u; 3 pow 2u; 4 pow 1u; 5 pow 0u }
|
||||||
|
}.degree,
|
||||||
|
"test 4"
|
||||||
|
)
|
||||||
|
assertEquals(
|
||||||
|
3,
|
||||||
|
NumberedPolynomial {
|
||||||
|
o {}
|
||||||
|
o { 2 pow 1u }
|
||||||
|
o { 1 pow 2u; 3 pow 1u }
|
||||||
|
}.degree,
|
||||||
|
"test 5"
|
||||||
|
)
|
||||||
|
assertEquals(
|
||||||
|
4,
|
||||||
|
NumberedPolynomial {
|
||||||
|
o {}
|
||||||
|
o { 2 pow 1u }
|
||||||
|
o { 1 pow 2u; 3 pow 1u }
|
||||||
|
o { 4 pow 4u }
|
||||||
|
}.degree,
|
||||||
|
"test 6"
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@Test
|
||||||
|
fun test_countOfVariables() {
|
||||||
|
val o = Rational(0)
|
||||||
|
RationalField.numberedPolynomialSpace {
|
||||||
|
assertEquals(
|
||||||
|
listOf(),
|
||||||
|
NumberedPolynomial {}.degrees,
|
||||||
|
"test 1"
|
||||||
|
)
|
||||||
|
assertEquals(
|
||||||
|
listOf(),
|
||||||
|
NumberedPolynomial {
|
||||||
|
o {}
|
||||||
|
}.degrees,
|
||||||
|
"test 2"
|
||||||
|
)
|
||||||
|
assertEquals(
|
||||||
|
listOf(1u, 2u, 3u),
|
||||||
|
NumberedPolynomial {
|
||||||
|
o { 1 pow 1u; 2 pow 2u; 3 pow 3u }
|
||||||
|
}.degrees,
|
||||||
|
"test 3"
|
||||||
|
)
|
||||||
|
assertEquals(
|
||||||
|
listOf(0u, 1u, 2u, 1u),
|
||||||
|
NumberedPolynomial {
|
||||||
|
o { 1 pow 0u; 2 pow 1u; 3 pow 2u; 4 pow 1u; 5 pow 0u }
|
||||||
|
}.degrees,
|
||||||
|
"test 4"
|
||||||
|
)
|
||||||
|
assertEquals(
|
||||||
|
listOf(2u, 1u, 1u),
|
||||||
|
NumberedPolynomial {
|
||||||
|
o {}
|
||||||
|
o { 2 pow 1u }
|
||||||
|
o { 1 pow 2u; 3 pow 1u }
|
||||||
|
}.degrees,
|
||||||
|
"test 5"
|
||||||
|
)
|
||||||
|
assertEquals(
|
||||||
|
listOf(2u, 2u, 2u, 4u),
|
||||||
|
NumberedPolynomial {
|
||||||
|
o {}
|
||||||
|
o { 1 pow 1u; 2 pow 2u }
|
||||||
|
o { 2 pow 1u; 3 pow 2u }
|
||||||
|
o { 1 pow 2u; 3 pow 1u }
|
||||||
|
o { 4 pow 4u }
|
||||||
|
}.degrees,
|
||||||
|
"test 6"
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@Test
|
||||||
|
fun test_degreeBy() {
|
||||||
|
val o = Rational(0)
|
||||||
|
RationalField.numberedPolynomialSpace {
|
||||||
|
fun NumberedPolynomial<Rational>.collectDegrees(limit: Int = lastVariable + 2): List<UInt> = List(limit) { degreeBy(it) }
|
||||||
|
assertEquals(
|
||||||
|
listOf(0u),
|
||||||
|
NumberedPolynomial {}.collectDegrees(),
|
||||||
|
"test 1"
|
||||||
|
)
|
||||||
|
assertEquals(
|
||||||
|
listOf(0u),
|
||||||
|
NumberedPolynomial {
|
||||||
|
o {}
|
||||||
|
}.collectDegrees(),
|
||||||
|
"test 2"
|
||||||
|
)
|
||||||
|
assertEquals(
|
||||||
|
listOf(1u, 2u, 3u, 0u),
|
||||||
|
NumberedPolynomial {
|
||||||
|
o { 1 pow 1u; 2 pow 2u; 3 pow 3u }
|
||||||
|
}.collectDegrees(),
|
||||||
|
"test 3"
|
||||||
|
)
|
||||||
|
assertEquals(
|
||||||
|
listOf(0u, 1u, 2u, 1u, 0u),
|
||||||
|
NumberedPolynomial {
|
||||||
|
o { 1 pow 0u; 2 pow 1u; 3 pow 2u; 4 pow 1u; 5 pow 0u }
|
||||||
|
}.collectDegrees(),
|
||||||
|
"test 4"
|
||||||
|
)
|
||||||
|
assertEquals(
|
||||||
|
listOf(2u, 1u, 1u, 0u),
|
||||||
|
NumberedPolynomial {
|
||||||
|
o {}
|
||||||
|
o { 2 pow 1u }
|
||||||
|
o { 1 pow 2u; 3 pow 1u }
|
||||||
|
}.collectDegrees(),
|
||||||
|
"test 5"
|
||||||
|
)
|
||||||
|
assertEquals(
|
||||||
|
listOf(2u, 2u, 2u, 4u, 0u),
|
||||||
|
NumberedPolynomial {
|
||||||
|
o {}
|
||||||
|
o { 1 pow 1u; 2 pow 2u }
|
||||||
|
o { 2 pow 1u; 3 pow 2u }
|
||||||
|
o { 1 pow 2u; 3 pow 1u }
|
||||||
|
o { 4 pow 4u }
|
||||||
|
}.collectDegrees(),
|
||||||
|
"test 6"
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@Test
|
||||||
|
fun test_degreeBy_Collection() {
|
||||||
|
val o = Rational(0)
|
||||||
|
RationalField.numberedPolynomialSpace {
|
||||||
|
fun NumberedPolynomial<Rational>.checkDegreeBy(message: String? = null) {
|
||||||
|
val lastVariable = lastVariable
|
||||||
|
val indexCollectionSequence: Sequence<List<Int>> = sequence {
|
||||||
|
val appearances = MutableList(lastVariable + 2) { 0 }
|
||||||
|
while (true) {
|
||||||
|
yield(
|
||||||
|
buildList {
|
||||||
|
for ((variable, count) in appearances.withIndex()) repeat(count) { add(variable) }
|
||||||
|
}
|
||||||
|
)
|
||||||
|
val indexChange = appearances.indexOfFirst { it < 4 }
|
||||||
|
if (indexChange == -1) break
|
||||||
|
appearances[indexChange] += 1
|
||||||
|
for (index in 0 until indexChange) appearances[index] = 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (indexCollection in indexCollectionSequence) {
|
||||||
|
val expected = coefficients.keys.maxOfOrNull { degs -> degs.slice(indexCollection.distinct().filter { it in degs.indices }).sum() } ?: 0u
|
||||||
|
val actual = degreeBy(indexCollection)
|
||||||
|
if (actual != expected)
|
||||||
|
fail("${message ?: ""} Incorrect answer for variable collection $indexCollection: expected $expected, actual $actual")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
NumberedPolynomial {}.checkDegreeBy("test 1")
|
||||||
|
NumberedPolynomial {
|
||||||
|
o {}
|
||||||
|
}.checkDegreeBy("test 2")
|
||||||
|
NumberedPolynomial {
|
||||||
|
o { 1 pow 1u; 2 pow 2u; 3 pow 3u }
|
||||||
|
}.checkDegreeBy("test 3")
|
||||||
|
NumberedPolynomial {
|
||||||
|
o { 1 pow 0u; 2 pow 1u; 3 pow 2u; 4 pow 1u; 5 pow 0u }
|
||||||
|
}.checkDegreeBy("test 4")
|
||||||
|
NumberedPolynomial {
|
||||||
|
o {}
|
||||||
|
o { 2 pow 1u }
|
||||||
|
o { 1 pow 2u; 3 pow 1u }
|
||||||
|
}.checkDegreeBy("test 5")
|
||||||
|
NumberedPolynomial {
|
||||||
|
o {}
|
||||||
|
o { 1 pow 1u; 2 pow 2u }
|
||||||
|
o { 2 pow 1u; 3 pow 2u }
|
||||||
|
o { 1 pow 2u; 3 pow 1u }
|
||||||
|
o { 4 pow 4u }
|
||||||
|
}.checkDegreeBy("test 6")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@Test
|
||||||
|
fun test_degrees() {
|
||||||
|
val o = Rational(0)
|
||||||
|
RationalField.numberedPolynomialSpace {
|
||||||
|
assertEquals(
|
||||||
|
0,
|
||||||
|
NumberedPolynomial {}.countOfVariables,
|
||||||
|
"test 1"
|
||||||
|
)
|
||||||
|
assertEquals(
|
||||||
|
0,
|
||||||
|
NumberedPolynomial {
|
||||||
|
o {}
|
||||||
|
}.countOfVariables,
|
||||||
|
"test 2"
|
||||||
|
)
|
||||||
|
assertEquals(
|
||||||
|
3,
|
||||||
|
NumberedPolynomial {
|
||||||
|
o { 1 pow 1u; 2 pow 2u; 3 pow 3u }
|
||||||
|
}.countOfVariables,
|
||||||
|
"test 3"
|
||||||
|
)
|
||||||
|
assertEquals(
|
||||||
|
3,
|
||||||
|
NumberedPolynomial {
|
||||||
|
o { 1 pow 0u; 2 pow 1u; 3 pow 2u; 4 pow 1u; 5 pow 0u }
|
||||||
|
}.countOfVariables,
|
||||||
|
"test 4"
|
||||||
|
)
|
||||||
|
assertEquals(
|
||||||
|
3,
|
||||||
|
NumberedPolynomial {
|
||||||
|
o {}
|
||||||
|
o { 2 pow 1u }
|
||||||
|
o { 1 pow 2u; 3 pow 1u }
|
||||||
|
}.countOfVariables,
|
||||||
|
"test 5"
|
||||||
|
)
|
||||||
|
assertEquals(
|
||||||
|
4,
|
||||||
|
NumberedPolynomial {
|
||||||
|
o {}
|
||||||
|
o { 1 pow 1u; 2 pow 2u }
|
||||||
|
o { 2 pow 1u; 3 pow 2u }
|
||||||
|
o { 1 pow 2u; 3 pow 1u }
|
||||||
|
o { 4 pow 4u }
|
||||||
|
}.countOfVariables,
|
||||||
|
"test 6"
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
Loading…
Reference in New Issue
Block a user