From 888ebfc175906a83584a5fdb0305d6045d5ada9a Mon Sep 17 00:00:00 2001 From: faberf Date: Tue, 15 Oct 2024 15:46:14 +0200 Subject: [PATCH] removed normalization functionality from score fusion --- .../query/aggregate/WeightedScoreFusion.kt | 53 +++++++------------ .../aggregate/WeightedScoreFusionFactory.kt | 3 +- 2 files changed, 20 insertions(+), 36 deletions(-) diff --git a/vitrivr-engine-query/src/main/kotlin/org/vitrivr/engine/query/aggregate/WeightedScoreFusion.kt b/vitrivr-engine-query/src/main/kotlin/org/vitrivr/engine/query/aggregate/WeightedScoreFusion.kt index d1ff30a8e..e83b3b41c 100644 --- a/vitrivr-engine-query/src/main/kotlin/org/vitrivr/engine/query/aggregate/WeightedScoreFusion.kt +++ b/vitrivr-engine-query/src/main/kotlin/org/vitrivr/engine/query/aggregate/WeightedScoreFusion.kt @@ -16,13 +16,12 @@ import kotlin.math.pow class WeightedScoreFusion( override val inputs: List>, weights: List, - val p: Float, - val normalize: Boolean + val p: Float ) : Aggregator { private val weights: List = when { weights.size > inputs.size -> weights.subList(0, inputs.size - 1) - weights.size < inputs.size -> weights + List(inputs.size - weights.size) {1f} + weights.size < inputs.size -> weights + List(inputs.size - weights.size) { 1f } else -> weights } @@ -42,7 +41,7 @@ class WeightedScoreFusion( val inputs = inputs.map { it.toFlow(scope).toList() } - //check if there is more than one populated input, return early if not + // Check if there is more than one populated input, return early if not if (inputs.filter { it.isNotEmpty() }.size < 2) { inputs.asSequence().flatten().forEach { emit(it) } return@flow @@ -51,53 +50,39 @@ class WeightedScoreFusion( val scoreMap = mutableMapOf>>() for ((index, retrieveds) in inputs.withIndex()) { - for (retrieved in retrieveds) { - - if (!scoreMap.containsKey(retrieved.id)) { - scoreMap[retrieved.id] = mutableListOf() - } - + scoreMap.computeIfAbsent(retrieved.id) { mutableListOf() } scoreMap[retrieved.id]!!.add(index to retrieved) - } - } - for((_, retrieveds) in scoreMap) { + for ((_, retrieveds) in scoreMap) { - var score : Float - var first : Retrievable + var score: Float + val first: Retrievable - if (p == Float.POSITIVE_INFINITY){ - score = retrieveds.map { ((it.second.filteredAttribute(ScoreAttribute::class.java))?.score ?: 0f) }.max() + if (p == Float.POSITIVE_INFINITY) { + // Max score selection when p = infinity + score = retrieveds.map { (it.second.filteredAttribute(ScoreAttribute::class.java)?.score ?: 0f) } + .maxOrNull() ?: 0f first = retrieveds.first().second - } - else{ - val normalization = (retrieveds.map { weights[it.first] }.sum()).pow(1/p) - - if (normalization == 0f){ - score = 0f - } - else { - score = retrieveds.map { - ((it.second.filteredAttribute(ScoreAttribute::class.java))?.score ?: 0f).pow(p) * weights[it.first] - }.sum().pow(1 / p) - if (normalize) score /= normalization - } + } else { + // Compute weighted p-norm score without normalization + score = retrieveds.map { + (it.second.filteredAttribute(ScoreAttribute::class.java)?.score ?: 0f).pow(p) * weights[it.first] + }.sum().pow(1 / p) + first = retrieveds.first().second } - //make a copy and override score + // Create a copy and override the score val retrieved = first.copy() retrieved.filteredAttribute(ScoreAttribute::class.java) retrieved.addAttribute(ScoreAttribute.Unbound(score)) emit(retrieved) - } - } } -} \ No newline at end of file +} diff --git a/vitrivr-engine-query/src/main/kotlin/org/vitrivr/engine/query/aggregate/WeightedScoreFusionFactory.kt b/vitrivr-engine-query/src/main/kotlin/org/vitrivr/engine/query/aggregate/WeightedScoreFusionFactory.kt index 1d60a6e9a..a315d6bd1 100644 --- a/vitrivr-engine-query/src/main/kotlin/org/vitrivr/engine/query/aggregate/WeightedScoreFusionFactory.kt +++ b/vitrivr-engine-query/src/main/kotlin/org/vitrivr/engine/query/aggregate/WeightedScoreFusionFactory.kt @@ -17,10 +17,9 @@ class WeightedScoreFusionFactory : AggregatorFactory { ): Aggregator { val weights = context[name, "weights"]?.split(",")?.mapNotNull { s -> s.trim().toFloatOrNull() } ?: emptyList() val p = context[name, "p"]?.toFloatOrNull() ?: 1f - val normalize = context[name, "normalize"]?.toBoolean() ?: true if (p == Float.POSITIVE_INFINITY && weights.isNotEmpty()) { logger.warn { "Weights are ignored when p is set to infinity" } } - return WeightedScoreFusion(inputs, weights, p, normalize) + return WeightedScoreFusion(inputs, weights, p) } } \ No newline at end of file