From ec76d5704569260ffa04aab4c44a8cb650053a0a Mon Sep 17 00:00:00 2001 From: Claude Brisson Date: Tue, 20 Jun 2023 13:20:15 +0200 Subject: [PATCH] Reeng of solver classes --- .../jeudego/pairgoth/pairing/HistoryHelper.kt | 16 ------ .../pairgoth/pairing/MacMahonSolver.kt | 29 +++------- .../org/jeudego/pairgoth/pairing/Solver.kt | 53 +++++++++---------- .../jeudego/pairgoth/pairing/SwissSolver.kt | 23 +------- 4 files changed, 35 insertions(+), 86 deletions(-) diff --git a/api-webapp/src/main/kotlin/org/jeudego/pairgoth/pairing/HistoryHelper.kt b/api-webapp/src/main/kotlin/org/jeudego/pairgoth/pairing/HistoryHelper.kt index ebb47b4..b4df064 100644 --- a/api-webapp/src/main/kotlin/org/jeudego/pairgoth/pairing/HistoryHelper.kt +++ b/api-webapp/src/main/kotlin/org/jeudego/pairgoth/pairing/HistoryHelper.kt @@ -15,22 +15,6 @@ open class HistoryHelper(protected val history: List>, computeScore: else -> 0.0 } - fun getCriterionValue(p: Pairable, crit: Criterion): Double { - // Returns generic criterion - // Specific criterion are computed by solvers directly - return when (crit) { - Criterion.NONE -> 0.0 - Criterion.CATEGORY -> TODO() - Criterion.RANK -> p.rank.toDouble() - Criterion.RATING -> p.rating.toDouble() - - Criterion.EXT -> TODO() - Criterion.EXR -> TODO() - Criterion.SDC -> TODO() - Criterion.DC -> TODO() - else -> -1.0 - } - } // Generic helper functions open fun playedTogether(p1: Pairable, p2: Pairable) = paired.contains(Pair(p1.id, p2.id)) open fun colorBalance(p: Pairable) = colorBalance[p.id] diff --git a/api-webapp/src/main/kotlin/org/jeudego/pairgoth/pairing/MacMahonSolver.kt b/api-webapp/src/main/kotlin/org/jeudego/pairgoth/pairing/MacMahonSolver.kt index afeb908..dbcfd26 100644 --- a/api-webapp/src/main/kotlin/org/jeudego/pairgoth/pairing/MacMahonSolver.kt +++ b/api-webapp/src/main/kotlin/org/jeudego/pairgoth/pairing/MacMahonSolver.kt @@ -9,32 +9,19 @@ class MacMahonSolver(round: Int, placementParams: PlacementParams): Solver(round, history, pairables, pairingParams, placementParams) { -// val Pairable.mms get() = mmBase + nbW // TODO real calculation + val Pairable.mmBase: Double get() = rank + 30.0 // TODO use params + val Pairable.mms: Double get() = mmBase + nbW // TODO real calculation // CB TODO - configurable criteria - override fun mainCriterion(p1: Pairable): Int { - TODO("Not yet implemented") - } - - override fun mainCriterionMinMax(): Pair { - TODO("Not yet implemented") - } - + override val Pairable.main get() = mms + override val mainLimits get() = TODO() override fun computeStandingScore(): Map { TODO("Not yet implemented") } - override fun getSpecificCriterionValue(p: Pairable, criterion: Criterion): Double { - // TODO solve this double/int conflict - return when (criterion) { - Criterion.MMS -> TODO() - Criterion.SOSM -> p.sos - Criterion.SOSMM1 -> p.sosm1 - Criterion.SOSMM2 -> p.sosm2 - Criterion.SODOSM -> p.sodos - Criterion.SOSOSM -> p.sosos - Criterion.CUSSM -> p.cums - else -> -1.0 - } + override fun evalCriterion(pairable: Pairable, criterion: Criterion) = when (criterion) { + Criterion.MMS -> pairable.mms + else -> super.evalCriterion(pairable, criterion) } + } diff --git a/api-webapp/src/main/kotlin/org/jeudego/pairgoth/pairing/Solver.kt b/api-webapp/src/main/kotlin/org/jeudego/pairgoth/pairing/Solver.kt index 7db564f..908772c 100644 --- a/api-webapp/src/main/kotlin/org/jeudego/pairgoth/pairing/Solver.kt +++ b/api-webapp/src/main/kotlin/org/jeudego/pairgoth/pairing/Solver.kt @@ -1,6 +1,7 @@ package org.jeudego.pairgoth.pairing import org.jeudego.pairgoth.model.* +import org.jeudego.pairgoth.model.Criterion.* import org.jeudego.pairgoth.model.MainCritParams.SeedMethod.* import org.jeudego.pairgoth.store.Store import org.jgrapht.alg.matching.blossom.v5.KolmogorovWeightedPerfectMatching @@ -51,10 +52,10 @@ sealed class Solver( open fun sort(p: Pairable, q: Pairable): Int { for (criterion in placement.criteria) { - val criterionP = getCriterionValue(p, criterion) - val criterionQ = getCriterionValue(q, criterion) + val criterionP = evalCriterion(p, criterion) + val criterionQ = evalCriterion(q, criterion) if (criterionP != criterionQ) { - return (criterionP - criterionQ).toInt() + return (criterionP * 100 - criterionQ * 100).toInt() } } return 0 @@ -67,27 +68,10 @@ sealed class Solver( pairing.geo.apply(p1, p2) // The main criterion that will be used to define the groups should be defined by subclasses - abstract fun mainCriterion(p1: Pairable): Int - abstract fun mainCriterionMinMax(): Pair + abstract val Pairable.main: Double + abstract val mainLimits: Pair // SOS and variants will be computed based on this score abstract fun computeStandingScore(): Map - // This function needs to be overridden for criterion specific to the current pairing mode - open fun getSpecificCriterionValue(p1: Pairable, criterion: Criterion): Double { - return -1.0 - } - - private fun getCriterionValue(p1: Pairable, criterion: Criterion): Double { - val genericCritVal = historyHelper.getCriterionValue(p1, criterion) - // If the value from the history helper is > 0 it means that it is a generic criterion - // Just returns the value - if (genericCritVal < 0) { - return genericCritVal - } - // Otherwise we have to delegate it to the solver - val critVal = getSpecificCriterionValue(p1, criterion) - if (critVal < 0) throw Error("Couldn't compute criterion value") - return critVal - } fun pair(): List { // check that at this stage, we have an even number of pairables @@ -172,7 +156,7 @@ sealed class Solver( open fun MainCritParams.minimizeScoreDifference(p1: Pairable, p2: Pairable): Double { var score = 0.0 - val scoreRange: Int = numberGroups + val scoreRange: Int = groupsCount // TODO check category equality if category are used in SwissCat val x = abs(p1.group - p2.group).toDouble() / scoreRange.toDouble() val k: Double = pairing.base.nx1 @@ -235,7 +219,7 @@ sealed class Solver( } fun GeographicalParams.apply(p1: Pairable, p2: Pairable): Double { - val placementScoreRange = numberGroups + val placementScoreRange = groupsCount val geoMaxCost = avoidSameGeo @@ -325,11 +309,10 @@ sealed class Solver( //private val standingScore by lazy { computeStandingScore() } // Decide each pairable group based on the main criterion - private val numberGroups by lazy { - val (mainScoreMin, mainScoreMax) = mainCriterionMinMax() - mainScoreMax - mainScoreMin + private val groupsCount get() = (mainLimits.second - mainLimits.first).toInt() + private val _groups by lazy { + pairables.associate { pairable -> Pair(pairable.id, pairable.main.toInt()) } } - private val _groups = pairables.associate { pairable -> Pair(pairable.id, mainCriterion(pairable)) } // pairables sorted using overloadable sort function private val sortedPairables by lazy { @@ -373,4 +356,18 @@ sealed class Solver( val Pairable.sosos: Double get() = historyHelper.sosos[id]!! val Pairable.sodos: Double get() = historyHelper.sodos[id]!! val Pairable.cums: Double get() = historyHelper.cumScore[id]!! + + open fun evalCriterion(pairable: Pairable, criterion: Criterion) = when (criterion) { + NONE -> 0.0 + CATEGORY -> TODO() + RANK -> pairable.rank.toDouble() + RATING -> pairable.rating.toDouble() + NBW -> pairable.nbW + SOSW -> pairable.sos + SOSWM1 -> pairable.sosm1 + SOSWM2 -> pairable.sosm2 + SODOSW -> pairable.sodos + CUSSW -> pairable.cums + else -> throw Error("criterion cannot be evaluated: ${criterion.name}") + } } diff --git a/api-webapp/src/main/kotlin/org/jeudego/pairgoth/pairing/SwissSolver.kt b/api-webapp/src/main/kotlin/org/jeudego/pairgoth/pairing/SwissSolver.kt index a456d44..eb0f2b1 100644 --- a/api-webapp/src/main/kotlin/org/jeudego/pairgoth/pairing/SwissSolver.kt +++ b/api-webapp/src/main/kotlin/org/jeudego/pairgoth/pairing/SwissSolver.kt @@ -10,29 +10,10 @@ class SwissSolver(round: Int, Solver(round, history, pairables, pairingParams, placementParams) { // In a Swiss tournament the main criterion is the number of wins and already computed - override fun mainCriterion(p1: Pairable): Int { - return p1.nbW.toInt() // Rounded Down TODO make it a parameter ? - } - - override fun mainCriterionMinMax(): Pair { - return Pair(0, round-1) - } + override val Pairable.main: Double get() = nbW // Rounded Down TODO make it a parameter ? + override val mainLimits = Pair(0.0, round - 1.0) override fun computeStandingScore(): Map { return historyHelper.wins } - - override fun getSpecificCriterionValue(p: Pairable, criterion: Criterion): Double { - // TODO solve this double/int conflict - return when (criterion) { - Criterion.NBW -> p.nbW - Criterion.SOSW -> p.sos - Criterion.SOSWM1 -> p.sosm1 - Criterion.SOSWM2 -> p.sosm2 - Criterion.SODOSW -> p.sodos - Criterion.SOSOSW -> p.sosos - Criterion.CUSSW -> p.cums - else -> -1.0 - } - } }