Added test. Fixed bug in NumberedPolynomial's DSL.

This commit is contained in:
Gleb Minaev 2022-06-27 17:14:03 +03:00
parent 0ef2258665
commit 043d292eca
4 changed files with 324 additions and 13 deletions

View File

@ -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,

View File

@ -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 })

View File

@ -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"

View File

@ -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"
)
}
}
} }