Feature: Polynomials and rational functions #469
@ -331,13 +331,13 @@ public class NumberedPolynomialSpace<C, A : Ring<C>>(
|
||||
* the result is `-1`.
|
||||
*/
|
||||
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
|
||||
* zero, degree is -1.
|
||||
*/
|
||||
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
|
||||
* 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>
|
||||
get() =
|
||||
MutableList(lastVariable + 1) { 0u }.apply {
|
||||
coefficients.entries.forEach { (degs, _) ->
|
||||
coefficients.keys.forEach { degs ->
|
||||
degs.forEachIndexed { 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].
|
||||
*/
|
||||
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].
|
||||
*/
|
||||
public fun NumberedPolynomial<C>.degreeBy(variables: Collection<Int>): UInt =
|
||||
coefficients.entries.maxOfOrNull { (degs, _) ->
|
||||
degs.withIndex().filter { (index, _) -> index in variables }.sumOf { it.value }
|
||||
coefficients.keys.maxOfOrNull { degs ->
|
||||
degs.withIndex().fold(0u) { acc, (index, value) -> if (index in variables) acc + value else acc }
|
||||
} ?: 0u
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
public infix fun Int.inPowerOf(deg: UInt) {
|
||||
if (deg == 0u) return
|
||||
val index = this - 1
|
||||
if (index > signature.lastIndex) {
|
||||
signature.addAll(List(index - signature.lastIndex - 1) { 0u })
|
||||
|
@ -23,8 +23,8 @@ class NumberedConstructorsTest {
|
||||
),
|
||||
Int.algebra.numberedPolynomialSpace {
|
||||
NumberedPolynomial {
|
||||
5 { 1 inPowerOf 2u; 3 inPowerOf 3u }
|
||||
(-6) { 2 inPowerOf 1u }
|
||||
5 { 1 pow 2u; 3 pow 3u }
|
||||
(-6) { 2 pow 1u }
|
||||
}
|
||||
},
|
||||
"test 1"
|
||||
@ -47,8 +47,20 @@ class NumberedConstructorsTest {
|
||||
),
|
||||
Int.algebra.numberedPolynomialSpace {
|
||||
NumberedPolynomial {
|
||||
5 { 1 inPowerOf 1u; 1 inPowerOf 1u }
|
||||
(-6) { 1 inPowerOf 2u }
|
||||
5 { 1 pow 1u; 1 pow 1u }
|
||||
(-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"
|
||||
|
@ -9,9 +9,7 @@ package space.kscience.kmath.functions
|
||||
|
||||
import space.kscience.kmath.misc.UnstableKMathAPI
|
||||
import space.kscience.kmath.test.misc.*
|
||||
import kotlin.test.Test
|
||||
import kotlin.test.assertEquals
|
||||
import kotlin.test.assertSame
|
||||
import kotlin.test.*
|
||||
|
||||
|
||||
@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