Greatly improve performance of clusterization by hinting that min/max should be performed with implied zero value
This commit is contained in:
parent
b1783343bc
commit
acc182eb26
@ -104,7 +104,7 @@ class EnergyCounterRenderer(private val context: BlockEntityRendererProvider.Con
|
||||
|
||||
map[1f] = maximum.formatPower()
|
||||
|
||||
for (cluster in chart.asIterable().clusterize(random)) {
|
||||
for (cluster in chart.asIterable().clusterize(random, zeroBound = true)) {
|
||||
val perc = (cluster.center / maximum).toFloat()
|
||||
|
||||
if (map.keys.none { (it - perc).absoluteValue < 0.08f }) {
|
||||
|
@ -90,6 +90,7 @@ private class MutableCluster<V : Comparable<V>>(var center: V) {
|
||||
private fun <V : Comparable<V>> Iterable<V>.clusterize(
|
||||
random: RandomGenerator,
|
||||
initialClusters: Int = 1,
|
||||
zeroBound: Boolean = false,
|
||||
identity: V,
|
||||
plus: (V, V) -> V,
|
||||
minus: (V, V) -> V,
|
||||
@ -126,8 +127,27 @@ private fun <V : Comparable<V>> Iterable<V>.clusterize(
|
||||
cluster.values.add(wrapped)
|
||||
}
|
||||
|
||||
if (zeroBound) {
|
||||
min = minOf(min, identity)
|
||||
max = maxOf(max, identity)
|
||||
}
|
||||
|
||||
if (min == max) {
|
||||
return listOf(Cluster.Impl(listOf(min), min))
|
||||
} else {
|
||||
// if "clusters" already satisfy constraints...
|
||||
clusters.forEach { it.calculateCenter(identity, plus, minus, divInt, abs) }
|
||||
values.forEach { it.updateError(abs, minus) }
|
||||
|
||||
val maxError = values.maxOf { it.error }
|
||||
|
||||
if (!heuristics(min, max, maxError)) {
|
||||
return clusters.stream()
|
||||
.filter { it.values.isNotEmpty() }
|
||||
.map { Cluster.Impl(it.values.map { it.value }, it.center) }
|
||||
.sorted { o1, o2 -> o2.values.size.compareTo(o1.values.size) } // большие кластеры должны идти первыми
|
||||
.toList()
|
||||
}
|
||||
}
|
||||
|
||||
while (true) {
|
||||
@ -182,8 +202,8 @@ private fun <V : Comparable<V>> Iterable<V>.clusterize(
|
||||
// TODO: could use some tweaking
|
||||
private val DECIMAL_ERROR_TOLERANCE = Decimal("0.02")
|
||||
|
||||
fun Iterable<Decimal>.clusterize(random: RandomGenerator, clusters: Int? = null): List<Cluster<Decimal>> {
|
||||
return clusterize(random, clusters ?: 1, Decimal.ZERO, Decimal::plus, Decimal::minus, Decimal::div, Decimal::absoluteValue) { min, max, error ->
|
||||
fun Iterable<Decimal>.clusterize(random: RandomGenerator, clusters: Int? = null, zeroBound: Boolean = false): List<Cluster<Decimal>> {
|
||||
return clusterize(random, clusters ?: 1, zeroBound, Decimal.ZERO, Decimal::plus, Decimal::minus, Decimal::div, Decimal::absoluteValue) { min, max, error ->
|
||||
if (clusters != null)
|
||||
false
|
||||
else
|
||||
|
@ -456,7 +456,7 @@ private fun formatHistoryChart(
|
||||
val rand = java.util.Random()
|
||||
|
||||
if (maxTransferred.isNotZero && transferredMult > 0.2f) {
|
||||
for (cluster in widget.transferred.clusterize(rand)) {
|
||||
for (cluster in widget.transferred.clusterize(rand, zeroBound = true)) {
|
||||
val perc = (cluster.center / maxTransferred).toFloat() * transferredMult
|
||||
|
||||
if (labelNames.keys.none { (it - perc).absoluteValue < 0.08f })
|
||||
@ -465,7 +465,7 @@ private fun formatHistoryChart(
|
||||
}
|
||||
|
||||
if (maxReceived.isNotZero && receivedMult > 0.2f) {
|
||||
for (cluster in widget.received.clusterize(rand)) {
|
||||
for (cluster in widget.received.clusterize(rand, zeroBound = true)) {
|
||||
val perc = zero + (cluster.center / maxReceived).toFloat() * receivedMult
|
||||
|
||||
if (labelNames.keys.none { (it - perc).absoluteValue < 0.08f })
|
||||
@ -473,7 +473,7 @@ private fun formatHistoryChart(
|
||||
}
|
||||
}
|
||||
|
||||
val clusters = diff.asIterable().clusterize(rand)
|
||||
val clusters = diff.asIterable().clusterize(rand, zeroBound = true)
|
||||
|
||||
for (cluster in clusters) {
|
||||
val perc: Float
|
||||
|
Loading…
Reference in New Issue
Block a user