Подтвердить что ты не робот

Алгоритм выбора колеса рулетки

Может ли кто-нибудь предоставить некоторый псевдокод для функции выбора рулетки? Как бы это реализовать: я действительно не понимаю, как читать эту математическую нотацию. Мне нужен общий алгоритм.

4b9b3361

Ответ 1

Другие ответы, похоже, предполагают, что вы пытаетесь реализовать игру в рулетку. Я думаю, что вы спрашиваете о выборе колеса рулетки в эволюционных алгоритмах.

Вот некоторый Java-код, который реализует выбор колесика рулетки.

Предположим, что у вас есть 10 предметов на выбор, и вы выбираете, создавая случайное число от 0 до 1. Вы делите диапазон от 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, то выбранный элемент - это пункт 3. Если он равен 0,92, то это пункт 9.

Ответ 2

Вот немного кода на 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

Ответ 3

Есть два шага к этому: сначала создайте массив со всеми значениями на колесе. Это может быть 2-мерный массив с цветом, а также числом, или вы можете добавить 100 к красным цифрам.

Затем просто сгенерируйте случайное число между 0 или 1 (в зависимости от того, начинает ли ваш язык индексировать индексы массива от 0 или 1) и последний элемент в вашем массиве.

Большинство языков имеют встроенные функции случайных чисел. В VB и VBScript функция RND(). В Javascript это Math.random()

Извлеките значение из этой позиции в массиве, и у вас есть номер случайной рулетки.

Заключительная записка: не забудьте засеять генератор случайных чисел или вы получите одну и ту же последовательность розыгрышей при каждом запуске программы.

Ответ 4

Сначала создайте массив из заданных вами процентов, скажем p[1..n] и предположим, что сумма представляет собой сумму всех процентов.

Затем получим случайное число от 1 до общего, скажем r

Теперь алгоритм в lua:

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

Ответ 5

Вот очень быстрый способ сделать это, используя выбор потока в Java. Он выбирает индексы массива, используя значения в виде весов. Никаких кумулятивных весов, необходимых из-за математических свойств.

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 или прочтение удвоений в качестве итерабельного, если массив был слишком большим для инициализации сразу.

Ответ 6

Мне нужен был тот же самый и созданный этот самостоятельный класс рулетки. Вы даете ему ряд весов (в виде двойного массива), и он просто возвращает индекс из этого массива в соответствии с взвешенным случайным выбором.

Я создал класс, потому что вы можете получить большую скорость, только делая кумулятивные добавления один раз через конструктор. Это код С#, но наслаждайтесь 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 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-е место = 1,0 взвешивание, 2-е место = 0,5, 3-е место = 0,333, 4-е место = 0,25 взвешивания и т.д. И т.д.

Ответ 7

Ну, для колесика American Roulette вам понадобится генерировать случайное целое число от 1 до 38. Есть 36 чисел, 0 и 00.

Одна из больших вещей, которую следует учитывать, заключается в том, что в американской рулетке их много разных ставок, которые можно сделать. Одна ставка может охватывать 1, 2, 3, 4, 5, 6, две разные 12 или 18. Возможно, вы захотите создать список списков, в которых каждый номер имеет дополнительные флаги, чтобы упростить это, или сделать все это в программировании.

Если бы я реализовал его в Python, я бы просто создал Tuple из 0, 00 и от 1 до 36 и использовал random.choice() для каждого вращения.

Ответ 8

Это предполагает некоторый класс "Классификатор", который имеет только условие 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;
}

Ответ 9

Вы можете использовать такую ​​структуру данных, как это:

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

где A - целое число, представляющее карман колеса рулетки, а B - индекс, который идентифицирует хромосому в популяции. Количество карманов пропорционально пропорции пригодности каждой хромосомы:

количество карманов = (фитнес пропорционально) · (масштабный коэффициент)

Затем мы генерируем случайное значение между 0 и размером схемы выбора, и с этим случайным числом мы получаем индекс хромосомы из рулетки.

Мы вычисляем относительную погрешность между соотношением пригодности каждой хромосомы и вероятностью выбора по схеме отбора.

Метод getRouletteWheel возвращает схему выбора, основанную на предыдущей структуре данных.

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;
}

Ответ 10

Я разработал код Java, аналогичный Java Dan Dyer (ссылка на него ранее). Однако мое колесо рулетки выбирает один элемент на основе вектора вероятности (ввода) и возвращает индекс выбранного элемента. Сказав это, следующий код более уместен, если размер выбора является унитарным, и если вы не предполагаете, как вычисляются вероятности и допускается значение нулевой вероятности. Код является самодостаточным и включает в себя тест с 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

Код также проверяет колесо рулетки с нулевой вероятностью.

Ответ 11

Я боюсь, что любой, кто использует встроенный генератор случайных чисел во всех языках программирования, должен знать, что генерируемое число не является 100% случайным. Следует использовать с осторожностью.

Ответ 12

Псевдокод генератора случайных чисел

  • добавить один к последовательному счетчику
  • получить текущее значение последовательного счетчика
  • добавьте значение счетчика по счету количества компьютеров или другому значению небольшого интервала таймера
  • необязательно добавьте числа добавлений, такие как число от внешнего устройства, такого как плазменный генератор или какой-либо другой тип случайных явлений.
  • разделите результат на очень большое простое число 359334085968622831041960188598043661065388726959079837 например.
  • получить некоторые цифры из правого края десятичной точки результата
  • используйте эти цифры как случайное число

Используйте цифры случайных чисел для создания случайных чисел от 1 до 38 (или 37 европейских) для рулетки.