wip on Markov chain

pull/53/head
Zlatin Balevsky 2020-10-20 16:19:36 +01:00
parent 315f29c668
commit 8798e83ab7
No known key found for this signature in database
GPG Key ID: A72832072D525E41
1 changed files with 48 additions and 47 deletions

View File

@ -2,7 +2,7 @@ package com.muwire.core.hostcache
import java.math.RoundingMode import java.math.RoundingMode
import static com.muwire.core.connection.ConnectionAttemptStatus.* import com.muwire.core.connection.ConnectionAttemptStatus
import groovy.sql.GroovyRowResult import groovy.sql.GroovyRowResult
@ -19,6 +19,9 @@ class HostMCProfile {
private final BigDecimal RS, RR, RF private final BigDecimal RS, RR, RF
private final BigDecimal FS, FR, FF private final BigDecimal FS, FR, FF
// start with S
ConnectionAttemptStatus state = ConnectionAttemptStatus.SUCCESSFUL
/** /**
* constructs an "optimistic" predictor for newly discovered hosts. * constructs an "optimistic" predictor for newly discovered hosts.
*/ */
@ -62,52 +65,50 @@ class HostMCProfile {
FF.setScale(SCALE, MODE) FF.setScale(SCALE, MODE)
} }
/** ConnectionAttemptStatus transition() {
* @param current status of this host
* @param nextStatus the next status of this host SortedMap<BigDecimal, ConnectionAttemptStatus> ignitionMap = new TreeMap<>()
* @return probability of such status switch(state) {
*/ case ConnectionAttemptStatus.SUCCESSFUL :
private BigDecimal transition(def currentStatus, def nextStatus) { ignitionMap.put(SS, ConnectionAttemptStatus.SUCCESSFUL)
switch(currentStatus) { ignitionMap.put(SR, ConnectionAttemptStatus.REJECTED)
case SUCCESSFUL : ignitionMap.put(SF, ConnectionAttemptStatus.FAILED)
switch(nextStatus) { break
case SUCCESSFUL : return SS case ConnectionAttemptStatus.REJECTED :
case REJECTED : return SR ignitionMap.put(RS, ConnectionAttemptStatus.SUCCESSFUL)
case FAILED : return SF ignitionMap.put(RR, ConnectionAttemptStatus.REJECTED)
} ignitionMap.put(RF, ConnectionAttemptStatus.FAILED)
case REJECTED : break
switch(nextStatus) { case ConnectionAttemptStatus.FAILED:
case SUCCESSFUL : return RS ignitionMap.put(FS, ConnectionAttemptStatus.SUCCESSFUL)
case REJECTED : return RR ignitionMap.put(FR, ConnectionAttemptStatus.REJECTED)
case FAILED : return RF ignitionMap.put(FF, ConnectionAttemptStatus.FAILED)
} break
case FAILED :
switch(nextStatus) {
case SUCCESSFUL : return FS
case REJECTED : return FR
case FAILED : return FF
}
}
} }
/** BigDecimal[] probs = new BigDecimal[3]
* @param lastStatus last observed status ConnectionAttemptStatus[] states = new ConnectionAttemptStatus[3]
* @param periods how many periods ago
* @return probability of next status being SUCCESSFUL Iterator<BigDecimal> iter = ignitionMap.keySet().iterator()
*/ probs[0] = iter.next()
public BigDecimal connectSuccessProbability(def lastStatus, int periods) { states[0] = ignitionMap.get(probs[0])
if (periods == 0) { probs[1] = iter.next()
return transition(lastStatus, SUCCESSFUL) states[1] = ignitionMap.get(probs[1])
} else { probs[2] = iter.next()
def toSuccess = transition(lastStatus, SUCCESSFUL) states[2] = ignitionMap.get(probs[2])
def toReject = transition(lastStatus, REJECTED)
def toFail = transition(lastStatus, FAILED) probs[1] += probs[0]
final newPeriods = periods - 1 probs[2] += probs[1]
BigDecimal rv = toSuccess * connectSuccessProbability(SUCCESSFUL, newPeriods) +
toReject * connectSuccessProbability(REJECTED, newPeriods) + final double random = Math.random()
toFail * connectSuccessProbability(FAILED, newPeriods) if (random < probs[0])
rv.setScale(SCALE, MODE) state = states[0]
return rv else if (random < probs[1])
} state = states[1]
else
state = states[2]
state
} }
} }