我编写了一个类似于 Dan Dyer 的 Java 代码(前面提到过)。然而,我的轮盘赌根据概率向量(输入)选择单个元素并返回所选元素的索引。
话虽如此,如果选择大小是单一的并且您不假设如何计算概率并且允许零概率值,则以下代码更合适。该代码是独立的,包括一个带有 20 次轮子旋转的测试(运行)。
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Random;
import java.util.logging.Level;
import java.util.logging.Logger;
/**
* Roulette-wheel Test version.
* Features a probability vector input with possibly null probability values.
* Appropriate for adaptive operator selection such as Probability Matching
* or Adaptive Pursuit, (Dynamic) Multi-armed Bandit.
* @version October 2015.
* @author Hakim Mitiche
*/
public class RouletteWheel {
/**
* Selects an element probabilistically.
* @param wheelProbabilities elements probability vector.
* @param rng random generator object
* @return selected element index
* @throws java.lang.Exception
*/
public int select(List<Double> wheelProbabilities, Random rng)
throws Exception{
double[] cumulativeProba = new double[wheelProbabilities.size()];
cumulativeProba[0] = wheelProbabilities.get(0);
for (int i = 1; i < wheelProbabilities.size(); i++)
{
double proba = wheelProbabilities.get(i);
cumulativeProba[i] = cumulativeProba[i - 1] + proba;
}
int last = wheelProbabilities.size()-1;
if (cumulativeProba[last] != 1.0)
{
throw new Exception("The probabilities does not sum up to one ("
+ "sum="+cumulativeProba[last]);
}
double r = rng.nextDouble();
int selected = Arrays.binarySearch(cumulativeProba, r);
if (selected < 0)
{
/* Convert negative insertion point to array index.
to find the correct cumulative proba range index.
*/
selected = Math.abs(selected + 1);
}
/* skip indexes of elements with Zero probability,
go backward to matching index*/
int i = selected;
while (wheelProbabilities.get(i) == 0.0){
System.out.print(i+" selected, correction");
i--;
if (i<0) i=last;
}
selected = i;
return selected;
}
public static void main(String[] args){
RouletteWheel rw = new RouletteWheel();
int rept = 20;
List<Double> P = new ArrayList<>(4);
P.add(0.2);
P.add(0.1);
P.add(0.6);
P.add(0.1);
Random rng = new Random();
for (int i = 0 ; i < rept; i++){
try {
int s = rw.select(P, rng);
System.out.println("Element selected "+s+ ", P(s)="+P.get(s));
} catch (Exception ex) {
Logger.getLogger(RouletteWheel.class.getName()).log(Level.SEVERE, null, ex);
}
}
P.clear();
P.add(0.2);
P.add(0.0);
P.add(0.5);
P.add(0.0);
P.add(0.1);
P.add(0.2);
//rng = new Random();
for (int i = 0 ; i < rept; i++){
try {
int s = rw.select(P, rng);
System.out.println("Element selected "+s+ ", P(s)="+P.get(s));
} catch (Exception ex) {
Logger.getLogger(RouletteWheel.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
/**
* {@inheritDoc}
* @return
*/
@Override
public String toString()
{
return "Roulette Wheel Selection";
}
}
下面是概率向量 P=[0.2,0.1,0.6,0.1] 的执行示例,
WheelElements = [0,1,2,3]:
元素选择 3,P(s)=0.1
元素选择 2,P(s)=0.6
元素选择 3,P(s)=0.1
元素选择 2,P(s)=0.6
元素选择 1,P(s)=0.1
元素选择 2,P(s)=0.6
元素选择 3,P(s)=0.1
元素选择 2,P(s)=0.6
元素选择 2,P(s)=0.6
元素选择 2,P(s)=0.6
元素选择 2,P(s)=0.6
元素选择 2,P(s)=0.6
元素选择 3,P(s)=0.1
元素选择 2,P(s)=0.6
元素选择 2,P(s)=0.6
元素选择 2,P(s)=0.6
元素选择 0,P(s)=0.2
元素选择 2,P(s)=0.6
元素选择 2,P(s)=0.6
元素选择 2,P(s)=0.6
代码还以零概率测试轮盘赌。