From 8798e83ab7c4421c0430a0f20841d3288d200987 Mon Sep 17 00:00:00 2001 From: Zlatin Balevsky Date: Tue, 20 Oct 2020 16:19:36 +0100 Subject: [PATCH] wip on Markov chain --- .../core/hostcache/HostMCProfile.groovy | 95 ++++++++++--------- 1 file changed, 48 insertions(+), 47 deletions(-) diff --git a/core/src/main/groovy/com/muwire/core/hostcache/HostMCProfile.groovy b/core/src/main/groovy/com/muwire/core/hostcache/HostMCProfile.groovy index e17af07a..0f53b3d9 100644 --- a/core/src/main/groovy/com/muwire/core/hostcache/HostMCProfile.groovy +++ b/core/src/main/groovy/com/muwire/core/hostcache/HostMCProfile.groovy @@ -2,7 +2,7 @@ package com.muwire.core.hostcache import java.math.RoundingMode -import static com.muwire.core.connection.ConnectionAttemptStatus.* +import com.muwire.core.connection.ConnectionAttemptStatus import groovy.sql.GroovyRowResult @@ -19,6 +19,9 @@ class HostMCProfile { private final BigDecimal RS, RR, RF private final BigDecimal FS, FR, FF + // start with S + ConnectionAttemptStatus state = ConnectionAttemptStatus.SUCCESSFUL + /** * constructs an "optimistic" predictor for newly discovered hosts. */ @@ -62,52 +65,50 @@ class HostMCProfile { FF.setScale(SCALE, MODE) } - /** - * @param current status of this host - * @param nextStatus the next status of this host - * @return probability of such status - */ - private BigDecimal transition(def currentStatus, def nextStatus) { - switch(currentStatus) { - case SUCCESSFUL : - switch(nextStatus) { - case SUCCESSFUL : return SS - case REJECTED : return SR - case FAILED : return SF - } - case REJECTED : - switch(nextStatus) { - case SUCCESSFUL : return RS - case REJECTED : return RR - case FAILED : return RF - } - case FAILED : - switch(nextStatus) { - case SUCCESSFUL : return FS - case REJECTED : return FR - case FAILED : return FF - } - } - } - - /** - * @param lastStatus last observed status - * @param periods how many periods ago - * @return probability of next status being SUCCESSFUL - */ - public BigDecimal connectSuccessProbability(def lastStatus, int periods) { - if (periods == 0) { - return transition(lastStatus, SUCCESSFUL) - } else { - def toSuccess = transition(lastStatus, SUCCESSFUL) - def toReject = transition(lastStatus, REJECTED) - def toFail = transition(lastStatus, FAILED) - final newPeriods = periods - 1 - BigDecimal rv = toSuccess * connectSuccessProbability(SUCCESSFUL, newPeriods) + - toReject * connectSuccessProbability(REJECTED, newPeriods) + - toFail * connectSuccessProbability(FAILED, newPeriods) - rv.setScale(SCALE, MODE) - return rv + ConnectionAttemptStatus transition() { + + SortedMap ignitionMap = new TreeMap<>() + switch(state) { + case ConnectionAttemptStatus.SUCCESSFUL : + ignitionMap.put(SS, ConnectionAttemptStatus.SUCCESSFUL) + ignitionMap.put(SR, ConnectionAttemptStatus.REJECTED) + ignitionMap.put(SF, ConnectionAttemptStatus.FAILED) + break + case ConnectionAttemptStatus.REJECTED : + ignitionMap.put(RS, ConnectionAttemptStatus.SUCCESSFUL) + ignitionMap.put(RR, ConnectionAttemptStatus.REJECTED) + ignitionMap.put(RF, ConnectionAttemptStatus.FAILED) + break + case ConnectionAttemptStatus.FAILED: + ignitionMap.put(FS, ConnectionAttemptStatus.SUCCESSFUL) + ignitionMap.put(FR, ConnectionAttemptStatus.REJECTED) + ignitionMap.put(FF, ConnectionAttemptStatus.FAILED) + break } + + BigDecimal[] probs = new BigDecimal[3] + ConnectionAttemptStatus[] states = new ConnectionAttemptStatus[3] + + Iterator iter = ignitionMap.keySet().iterator() + probs[0] = iter.next() + states[0] = ignitionMap.get(probs[0]) + probs[1] = iter.next() + states[1] = ignitionMap.get(probs[1]) + probs[2] = iter.next() + states[2] = ignitionMap.get(probs[2]) + + probs[1] += probs[0] + probs[2] += probs[1] + + final double random = Math.random() + if (random < probs[0]) + state = states[0] + else if (random < probs[1]) + state = states[1] + else + state = states[2] + + state } + }