20

Có ai có thể cung cấp một số mã giả cho chức năng chọn roulette không? Làm thế nào tôi sẽ thực hiện điều này: Tôi không thực sự hiểu làm thế nào để đọc ký hiệu toán học này.Tôi muốn thuật toán chung này.Thuật toán lựa chọn bánh xe Roulette

+1

Thẻ đã chỉnh sửa. Ai đó đã xóa thẻ "di truyền" khỏi bản sửa đổi đầu tiên của câu hỏi này, làm cho nó ít rõ ràng hơn những gì đã được hỏi. –

+1

unsigned int num = :: rand()% 37; –

Trả lời

4

Có 2 bước để thực hiện điều này: Trước tiên hãy tạo một mảng với tất cả các giá trị trên bánh xe. Đây có thể là mảng 2 chiều với màu sắc cũng như số, hoặc bạn có thể chọn thêm 100 vào số màu đỏ.

Sau đó, chỉ cần tạo một số ngẫu nhiên từ 0 hoặc 1 (tùy thuộc vào việc ngôn ngữ của bạn bắt đầu đánh số chỉ mục mảng từ 0 hoặc 1) và phần tử cuối cùng trong mảng của bạn.

Hầu hết các ngôn ngữ đều có các hàm số ngẫu nhiên tích hợp. Trong VB và VBScript chức năng là RND(). Trong Javascript, nó là Math.random()

Lấy giá trị từ vị trí đó trong mảng và bạn có số roulette ngẫu nhiên của mình.

Lưu ý cuối cùng: đừng quên gieo trình tạo số ngẫu nhiên của bạn hoặc bạn sẽ nhận được cùng một chuỗi số lần vẽ mỗi khi bạn chạy chương trình.

-5

Random Number Generator mã giả

  • thêm một đến một bộ đếm tuần tự
  • nhận được giá trị hiện tại của bộ đếm tuần tự
  • thêm giá trị truy cập bằng máy tính đánh dấu đếm hoặc một số khác giá trị bộ đếm khoảng thời gian nhỏ
  • tùy chọn thêm số bổ sung, như số từ phần ngoài của phần cứng như máy phát điện plasma hoặc một số ot loại của mình về hiện tượng hơi ngẫu nhiên
  • chia kết quả của một số nguyên tố rất lớn 359334085968622831041960188598043661065388726959079837 ví dụ
  • nhận được một số chữ số từ xa bên phải dấu thập phân của kết quả
  • sử dụng các chữ số như một ngẫu nhiên số

Sử dụng số ngẫu nhiên để tạo số ngẫu nhiên từ 1 đến 38 (hoặc 37 Châu Âu) cho roulette.

+5

Tôi nghĩ rằng các số ngẫu nhiên đã được giải quyết trong mọi ngôn ngữ lập trình, và quá trình này không còn phải được thực hiện bằng tay. Tại sao bạn không đề cập đến hệ thống dây điện lên tất cả các nửa-adders trong khi bạn đang ở đó? – Karl

1

Vâng, đối với một bánh xe American Roulette, bạn sẽ cần phải tạo ra một số nguyên ngẫu nhiên giữa 1 và 38. Có 36 con số, một 0 và 00.

Một trong những điều lớn để xem xét, mặc dù, là trong roulette Mỹ, họ có nhiều cược khác nhau có thể được thực hiện. Một cược duy nhất có thể bao gồm 1, 2, 3, 4, 5, 6, hai 12s khác nhau hoặc 18. Bạn có thể tạo danh sách các danh sách trong đó mỗi số có các đoạn bổ sung để đơn giản hóa hoặc làm tất cả trong chương trình .

Nếu tôi đang triển khai nó bằng Python, tôi sẽ tạo một Tuple 0, 00 và 1 đến 36 và sử dụng random.choice() cho mỗi vòng quay.

44

Các câu trả lời khác dường như giả định rằng bạn đang cố gắng triển khai trò chơi roulette. Tôi nghĩ rằng bạn đang hỏi về lựa chọn bánh xe roulette trong các thuật toán tiến hóa.

Here is some Java code thực hiện lựa chọn bánh xe roulette.

Giả sử bạn có 10 mục để chọn và bạn chọn bằng cách tạo số ngẫu nhiên từ 0 đến 1. Bạn chia phạm vi từ 0 đến 1 thành mười phân đoạn không chồng chéo, mỗi phần tỷ lệ với thể dục của một trong mười mặt hàng. Ví dụ: điều này có thể trông giống như sau:

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 

Đây là bánh xe roulette của bạn. Số ngẫu nhiên của bạn giữa 0 và 1 là spin của bạn. Nếu số ngẫu nhiên là 0.46, thì mục được chọn là mục 3. Nếu đó là 0.92, thì đó là mục 9.

+1

Đây là một trong những nhanh nhất tôi đã gặp chưa. Rất đẹp. –

+0

Không ai nói về việc thay thế mục đã chọn để mục đã chọn không được chọn lại. Bất kỳ giải pháp cho điều này? –

+1

@AnikIslamAbhi theo như tôi đang quan tâm lựa chọn bánh xe roulette giả định rằng mỗi mục có thể được chọn nhiều hơn một lần. Nếu bạn ngẫu nhiên 'N' lần (trong đó' N' là số dân) bạn sẽ lấy chính xác cùng một tập hợp sau khi chọn. –

4

Đầu tiên, tạo một mảng tỷ lệ phần trăm bạn đã gán, giả sử p[1..n] và giả định tổng là tổng của tất cả các tỷ lệ phần trăm.

Sau đó lấy một số ngẫu nhiên giữa 1 tổng, chúng ta hãy nói r

Bây giờ, các thuật toán trong lua:

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

này giả định một số lớp "Phân loại" mà chỉ có một điều kiện String, String tin nhắn và sức mạnh gấp đôi. Chỉ cần làm theo logic.

- Paul

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

Dưới đây là một chút mã 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 
+1

sẽ làm việc này, ngay cả khi một số giá trị tập thể dục là tiêu cực ?? – mkuse

+0

Không, nó sẽ không. Nhưng bạn phải tự hỏi, vì tập thể dục tương ứng với xác suất vẽ mẫu đó, không có thứ gì như xác suất tiêu cực khi vẽ mẫu, vậy bạn sẽ mong đợi loại hành vi nào? – noio

+0

Điều tôi muốn nói là, tôi có một chức năng thể dục mang lại những giá trị tiêu cực. Giả sử tôi đang giải quyết một vấn đề trong đó tập thể dục là 'lỗi', tức là. sự khác biệt của giá trị đích với giá trị thu được của GA. Trong trường hợp này, chức năng thể dục sẽ tạo ra các giá trị âm. Làm thế nào để xây dựng nó thành một bánh xe tinh tế? – mkuse

1

Bạn có thể sử dụng một cấu trúc dữ liệu như thế này:

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

trong đó A là một số nguyên đại diện cho một túi bánh xe roulette và B là chỉ mục xác định nhiễm sắc thể trong dân số. Số lượng túi là tỉ lệ với tương thể dục của mỗi nhiễm sắc thể:

số túi = (thể dục tương ứng) · (yếu tố quy mô)

Sau đó, chúng tôi tạo ra một ngẫu nhiên giữa 0 và kích thước của vùng chọn giản đồ và với số ngẫu nhiên này, chúng tôi lấy chỉ số của nhiễm sắc thể từ roulette.

Chúng tôi tính toán sai số tương đối giữa tỷ lệ thể dục của mỗi nhiễm sắc thể và xác suất được chọn bởi lược đồ lựa chọn.

Phương thức getRouletteWheel trả về sơ đồ lựa chọn dựa trên cấu trúc dữ liệu trước đó.

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

Tôi muốn như vậy và vì vậy tạo lớp Roulette độc ​​lập này. Bạn cung cấp cho nó một loạt các trọng số (dưới dạng một mảng kép), và nó sẽ đơn giản trả về một chỉ mục từ mảng đó theo một lựa chọn ngẫu nhiên có trọng số.

Tôi đã tạo một lớp vì bạn có thể tăng tốc độ lớn bằng cách chỉ thực hiện các bổ sung tích lũy một lần thông qua hàm tạo.Đó là mã C#, nhưng hãy tận hưởng C như tốc độ và sự đơn giản!

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

Trọng lượng ban đầu tùy thuộc vào bạn. Có thể đó là thể lực của mỗi thành viên, hoặc một giá trị tỷ lệ nghịch với vị trí của thành viên trong "top 50". Ví dụ: vị trí số 1 = 1.0 trọng số, vị trí thứ 2 = 0,5, vị trí thứ 3 = 0,33, vị trí thứ 4 = 0,25 trọng số, v.v.

3

Đây là cách thực sự nhanh chóng bằng cách sử dụng lựa chọn luồng trong Java. Nó chọn các chỉ số của một mảng bằng cách sử dụng các giá trị như trọng số. Không có trọng số tích lũy cần thiết do mathematical properties.

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

Điều này có thể được cải thiện thêm bằng cách sử dụng Kahan summation hoặc đọc qua đôi khi có thể lặp lại nếu mảng quá lớn để khởi tạo cùng một lúc.

+0

Đó là một giải pháp thú vị. Tôi cũng đã đưa ra một câu trả lời trong cùng một giờ như bạn, mặc dù câu hỏi được năm tuổi (có thể bạn đã nhìn thấy bài của tôi). Dù sao, tôi yêu của bạn bởi vì nó quá ngắn, nhưng tôi nghĩ rằng tôi có thể hiệu quả hơn do hiệu quả O (log2 n) thay vì O (n) của bạn. –

+0

Tôi nghĩ bạn đã gặp phải câu hỏi khiến tôi đăng câu trả lời của mình. Dù sao, tổng tích luỹ ban đầu của bạn vẫn nhận 'O (n)'. Tôi nghĩ rằng đó chắc chắn là một ràng buộc thấp hơn bất kể :) –

+0

Chỉ lần đầu tiên trong hàm tạo. Trong trường hợp thế giới thực, bạn sẽ thực hiện rất nhiều 'vòng quay roulette' (tức là tìm kiếm nhiều cặp bố mẹ khác nhau). Đó là nơi O (log2 n) đi vào hoạt động khi chỉ có phương thức spin() được gọi sau đó. –

-4

Tôi sợ rằng bất kỳ ai sử dụng trình tạo số ngẫu nhiên được xây dựng trong tất cả các ngôn ngữ lập trình phải lưu ý rằng số được tạo không phải là ngẫu nhiên 100%. Nên được sử dụng thận trọng.

+0

Cảm ơn bạn đã cung cấp thông tin quý giá. –

0

Tôi đã làm việc ra một mã Java tương tự như của Dan Dyer (tham chiếu trước đó). Tuy nhiên, bánh xe roulette của tôi, chọn một phần tử đơn dựa trên một vector xác suất (đầu vào) và trả về chỉ mục của phần tử đã chọn. Có nói rằng, đoạn mã sau là phù hợp hơn nếu kích thước lựa chọn là đơn nhất và nếu bạn không cho rằng xác suất được tính như thế nào và giá trị xác suất bằng không được cho phép. Mã này là khép kín và bao gồm một thử nghiệm với 20 bánh quay (để chạy).

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

Dưới đây là một mẫu thực hiện cho một P vector proba = [0.2,0.1,0.6,0.1], WheelElements = [0,1,2,3]:

phần tử được lựa chọn 3, P (s) = 0,1

phần tử được lựa chọn 2, P (s) = 0,6

phần tử được lựa chọn 3, P (s) = 0,1

phần tử được lựa chọn 2, P (s) = 0,6

phần tử được lựa chọn 1, P (s) = 0,1

phần tử được lựa chọn 2, P (s) = 0,6

phần tử được lựa chọn 3, P (s) = 0,1

phần tử được lựa chọn 2, P (s) = 0,6

phần tử được lựa chọn 2, P (s) = 0,6

phần tử được lựa chọn 2, P (s) = 0,6

phần tử được lựa chọn 2, P (s) = 0. 6

phần tử được lựa chọn 2, P (s) = 0,6

phần tử được lựa chọn 3, P (s) = 0,1

phần tử được lựa chọn 2, P (s) = 0,6

phần tử được lựa chọn 2 , P (s) = 0.6

Phần tử được chọn 2, P (s) = 0.6

Yếu tố chọn 0, P (s) = 0,2

phần tử được lựa chọn 2, P (s) = 0,6

phần tử được lựa chọn 2, P (s) = 0,6

phần tử được lựa chọn 2 , P (s) = 0.6

Mã này cũng kiểm tra một bánh xe roulette với xác suất bằng không.

Các vấn đề liên quan