轮盘赌selectalgorithm

任何人都可以提供一些轮盘赌selectfunction的伪代码? 我将如何实现这一点:我真的不明白如何阅读这个math符号。我想通用algorithm。

其他答案似乎假设你正在尝试实施轮盘游戏。 我认为你是在进化algorithm中询问轮盘select。

这是一些实现轮盘select的Java代码 。

假设您有10个项目可供select,您可以通过生成一个0到1之间的随机数字来select。您将0到1的范围分成十个非重叠的片段,每个片段与十个项目之一的适合度成比例。 例如,这可能看起来像这样:

0 - 0.3 is item 1 0.3 - 0.4 is item 2 0.4 - 0.5 is item 3 0.5 - 0.57 is item 4 0.57 - 0.63 is item 5 0.63 - 0.68 is item 6 0.68 - 0.8 is item 7 0.8 - 0.85 is item 8 0.85 - 0.98 is item 9 0.98 - 1 is item 10 

这是你的轮盘。 你的随机数在0和1之间是你的旋转。 如果随机数是0.46,则select的项目是项目3.如果是0.92,那么它是项目9。

这里是一些Python代码:

 def roulette_select(population, fitnesses, num): """ Roulette selection, implemented according to: <http://stackoverflow.com/questions/177271/roulette -selection-in-genetic-algorithms/177278#177278> """ total_fitness = float(sum(fitnesses)) rel_fitness = [f/total_fitness for f in fitnesses] # Generate probability intervals for each individual probs = [sum(rel_fitness[:i+1]) for i in range(len(rel_fitness))] # Draw new population new_population = [] for n in xrange(num): r = rand() for (i, individual) in enumerate(population): if r <= probs[i]: new_population.append(individual) break return new_population 

有2个步骤:首先创build一个包含车轮上所有值的数组。 这可以是具有颜色和数字的二维数组,也可以select将红色数字加上100。

然后简单地生成0或1之间的随机数(取决于您的语言是从0还是1开始对数组索引进行编号)以及数组中的最后一个元素。

大多数语言都有内置的随机数字function。 在VB和VBScript ,函数是RND() 。 在JavaScript中是Math.random()

从数组中的该位置获取值,并获得随机轮盘赌编号。

最后说明 :不要忘记种子你的随机数字发生器,否则你会得到相同的抽奖顺序,每次运行程序。

首先,生成你分配的百分比数组,假设p[1..n]并假设总数是所有百分比的总和。

然后得到1到1之间的随机数,比如说r

现在,lua中的algorithm:

 local c = 0 for i = 1,n do c = c + p[i] if r <= c then return i end end 

这是一个非常快速的方式来使用Java中的streamselect。 它使用值作为权重来select数组的索引。 由于math性质,不需要累积重量。

 static int selectRandomWeighted(double[] wts, Random rnd) { int selected = 0; double total = wts[0]; for( int i = 1; i < wts.length; i++ ) { total += wts[i]; if( rnd.nextDouble() <= (wts[i] / total)) selected = i; } return selected; } 

如果数组太大而无法立即初始化,则可以使用Kahan求和或通过双精度来读取这个值。

我想要相同的,所以创build了这个独立的轮盘类。 你给它一系列的权重(以double数组的forms),它会根据加权随机select从数组中返回一个索引。

我创build了一个类,因为只需通过构造函数进行一次累加就可以大大提高速度。 这是C#代码,但喜欢速度和简单的C!

 class Roulette { double[] c; double total; Random random; public Roulette(double[] n) { random = new Random(); total = 0; c = new double[n.Length+1]; c[0] = 0; // Create cumulative values for later: for (int i = 0; i < n.Length; i++) { c[i+1] = c[i] + n[i]; total += n[i]; } } public int spin() { double r = random.NextDouble() * total; // Create a random number between 0 and 1 and times by the total we calculated earlier. //int j; for (j = 0; j < c.Length; j++) if (c[j] > r) break; return j-1; // Don't use this - it's slower than the binary search below. //// Binary search for efficiency. Objective is to find index of the number just above r: int a = 0; int b = c.Length - 1; while (b - a > 1) { int mid = (a + b) / 2; if (c[mid] > r) b = mid; else a = mid; } return a; } } 

最初的重量取决于你。 也许这可能是每个成员的适应性,或者是与成员在“前50名”中的位置成反比的价值。 例如:第一名= 1.0加权,第二名= 0.5,第三名= 0.333,第四名= 0.25等等。

那么,对于一个美式轮盘赌,你将需要产生1到38之间的随机整数。有36个数字,一个0和一个00。

但是要考虑的大事之一就是在美国的轮盘赌中,他们可以做很多不同的投注。 一次下注可以覆盖1,2,3,4,5,6,两个不同的12或18,您可能希望创build一个列表,其中每个数字都有附加的flages来简化,或者在编程中完成。

如果我正在Python中实现它,我只需创build一个0,00和1到36的元组,并为每个旋转使用random.choice()。

这假设一些类“分类器”,它只是一个string条件,string消息和双重强度。 只要按照逻辑。

– 保罗

 public static List<Classifier> rouletteSelection(int classifiers) { List<Classifier> classifierList = new LinkedList<Classifier>(); double strengthSum = 0.0; double probabilitySum = 0.0; // add up the strengths of the map Set<String> keySet = ClassifierMap.CLASSIFIER_MAP.keySet(); for (String key : keySet) { /* used for debug to make sure wheel is working. if (strengthSum == 0.0) { ClassifierMap.CLASSIFIER_MAP.get(key).setStrength(8000.0); } */ Classifier classifier = ClassifierMap.CLASSIFIER_MAP.get(key); double strength = classifier.getStrength(); strengthSum = strengthSum + strength; } System.out.println("strengthSum: " + strengthSum); // compute the total probability. this will be 1.00 or close to it. for (String key : keySet) { Classifier classifier = ClassifierMap.CLASSIFIER_MAP.get(key); double probability = (classifier.getStrength() / strengthSum); probabilitySum = probabilitySum + probability; } System.out.println("probabilitySum: " + probabilitySum); while (classifierList.size() < classifiers) { boolean winnerFound = false; double rouletteRandom = random.nextDouble(); double rouletteSum = 0.0; for (String key : keySet) { Classifier classifier = ClassifierMap.CLASSIFIER_MAP.get(key); double probability = (classifier.getStrength() / strengthSum); rouletteSum = rouletteSum + probability; if (rouletteSum > rouletteRandom && (winnerFound == false)) { System.out.println("Winner found: " + probability); classifierList.add(classifier); winnerFound = true; } } } return classifierList; } 

你可以使用这样的数据结构:

 Map<A, B> roulette_wheel_schema = new LinkedHashMap<A, B>() 

其中A是表示轮盘的口袋的整数,并且B是识别种群中的染色体的指标 。 口袋的数量与每个染色体的适应度成正比:

口袋数=(健身比例)·(比例因子)

然后我们产生一个0到select模式大小的随机数,并用这个随机数从轮盘中得到染色体的索引。

我们计算每个染色体的适应性比例与selectschemeselect的概率之间的相对误差。

getRouletteWheel方法返回基于以前数据结构的selectscheme。

 private Map<Integer, Integer> getRouletteWheel( ArrayList<Chromosome_fitnessProportionate> chromosomes, int precision) { /* * The number of pockets on the wheel * * number of pockets in roulette_wheel_schema = probability · * (10^precision) */ Map<Integer, Integer> roulette_wheel_schema = new LinkedHashMap<Integer, Integer>(); double fitness_proportionate = 0.0D; double pockets = 0.0D; int key_counter = -1; double scale_factor = Math .pow(new Double(10.0D), new Double(precision)); for (int index_cromosome = 0; index_cromosome < chromosomes.size(); index_cromosome++){ Chromosome_fitnessProportionate chromosome = chromosomes .get(index_cromosome); fitness_proportionate = chromosome.getFitness_proportionate(); fitness_proportionate *= scale_factor; pockets = Math.rint(fitness_proportionate); System.out.println("... " + index_cromosome + " : " + pockets); for (int j = 0; j < pockets; j++) { roulette_wheel_schema.put(Integer.valueOf(++key_counter), Integer.valueOf(index_cromosome)); } } return roulette_wheel_schema; } 

我制定了一个类似于Dan Dyer的Java代码(前面提到过)。 然而,我的轮盘轮,基于概率向量(input)select单个元素并返回所选元素的索引。 话虽如此,如果select大小是单一的,并且如果您不假定概率是如何计算的,并且允许零概率值,则下面的代码更合适。 该代码是独立的,包括一个testing20轮旋转(运行)。

 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]的执行样本下面:

元素select3,P(s)= 0.1

元素select2,P(s)= 0.6

元素select3,P(s)= 0.1

元素select2,P(s)= 0.6

元素select1,P(s)= 0.1

元素select2,P(s)= 0.6

元素select3,P(s)= 0.1

元素select2,P(s)= 0.6

元素select2,P(s)= 0.6

元素select2,P(s)= 0.6

元素select2,P(s)= 0.6

元素select2,P(s)= 0.6

元素select3,P(s)= 0.1

元素select2,P(s)= 0.6

元素select2,P(s)= 0.6

元素select2,P(s)= 0.6

元素select0,P(s)= 0.2

元素select2,P(s)= 0.6

元素select2,P(s)= 0.6

元素select2,P(s)= 0.6

该代码还以零概率testing轮盘。

恐怕任何人在所有编程语言中使用内置的随机数发生器都必须意识到生成的数字不是100%随机的,所以应谨慎使用。

随机数发生器的伪代码

  • 添加一个顺序计数器
  • 获取顺序计数器的当前值
  • 通过计算机滴答计数或其他一些小的间隔定时器值来添加计数器
  • 可选地添加附加数字,如来自诸如等离子体发生器之类的外部硬件的数字或某种其他types的稍微随机的现象
  • 把结果除以一个非常大的素数359334085968622831041960188598043661065388726959079837
  • 从结果小数点的最右边得到一些数字
  • 使用这些数字作为一个随机数字

使用随机数字数字为轮盘创build1到38(或37欧洲)的随机数字。