Sửa đổi các hàm phân phối ngẫu nhiên :: Làm cho nó ít có khả năng nhận được nhiều giá trị tương tự trong một chuỗi


8

Tôi muốn tạo một chuỗi số cho các hành tinh tạo thủ tục trong khu vực thiên hà. Mỗi hành tinh nên được đặt ngẫu nhiên, tuy nhiên rất khó có khả năng hai hành tinh nằm trực tiếp cạnh nhau. Làm thế nào tôi có thể đạt được điều đó?

Tôi biết rằng bạn có thể sửa đổi cơ hội bằng cách áp dụng chức năng phân phối, nhưng làm cách nào tôi có thể kiểm soát chúng để tạo ra các giá trị cụ thể nhiều hơn / ít khả năng hơn?

Gif hiển thị ý tưởng sửa đổi đường cong xác suất tùy thuộc vào các giá trị đã được tạo.


2
Chỉ cần thêm một khoảng cách tối thiểu sẽ đảm bảo một hành tinh không nằm cạnh một hành tinh khác. Tôi ước tính điều này là đơn giản để bạn có thể giải thích thêm?
Madmenyo

@MennoGouw Vâng, điều đó sẽ giải quyết nó cho trường hợp cụ thể này, mặc dù tôi muốn cải thiện hiểu biết về xác suất nên tôi đang tìm giải pháp "nhẹ nhàng hơn" mà không giới hạn cứng / loại bỏ các số được tạo.
API-Beast

Làm rõ giải pháp "nhẹ nhàng" hơn. Đó là tất cả về việc thiết lập các quy tắc. Khi bạn cần một số quy tắc nhất định để tạo thủ tục, bạn cần thêm các quy tắc này. Nếu bạn có trường hợp đặc biệt, bạn đặt nhiều quy tắc khác nhau cho những điều này.
Madmenyo

Tôi không chắc tại sao bạn không sử dụng một máy phát điện có uy tín lớn về phân phối? (Tôi nghĩ rằng twers Mersenne không tệ.)
Vaillancourt

2
Tôi đồng ý. Bản thân thế hệ ngẫu nhiên không phải là vấn đề. Làm điều này thậm chí có thể phá vỡ trình tạo ngẫu nhiên của bạn bằng cách làm cho nó có thể dự đoán được. Tạo quy tắc là con đường để đi.
tro999 ngày

Câu trả lời:


8

Nếu bạn biết phân phối bạn muốn, bạn có thể sử dụng lấy mẫu từ chối .

Cách đơn giản nhất: Trong biểu đồ trên, chọn điểm ngẫu nhiên cho đến khi bạn tìm thấy một điểm nằm dưới đường cong. Sau đó, chỉ cần sử dụng x-coordine.

Đối với phân phối thực tế, có nhiều cách tiếp cận hợp lý. Ví dụ: đối với số hành tinh itại vị trí pvà một số tham số cường độ k(ví dụ 0.5), hãy xác định hàm f_i(x)=abs(p-x)^k, sau đó sử dụng hàm phân phối g(x)=f_1(x)*f_2(x)*...*f_n(x).

Trong thực tế, tính toán và lưu trữ kết quả của g(x)mảng t( t[x]=g(x)); nhớ giá trị nhìn thấy cao nhất hcũng có. Chọn một vị trí ngẫu nhiên xtrong t, chọn giá trị ngẫu nhiên ygiữa 0h, lặp lại if y>t[x]; nếu không thì giá trị trả về là x.


Bạn có thể đi sâu hơn một chút về việc xác định hàm phân phối không? Phần còn lại nên khá rõ ràng.
API-Beast

Ví dụ: nếu các hành tinh hiện tại ở vị trí 0,1, 0,3 và 0,8, g (x) = (abs (x-0,1) * abs (x-0,3) * abs (x-0,8)) ^ 0,5, trong đó "^" có nghĩa là lũy thừa. (Điều này hơi khác so với công thức trước, nhưng tương đương.) Hàm phân phối này trông gần giống như gif trong câu hỏi của bạn và không dựa trên bất kỳ điều gì cụ thể. (Chuỗi truy vấn cho WolframAlpha: "vẽ từ 0 đến 1 (abs (x-0.1) * abs (x-0.3) * abs (x-0.8)) ^ 0.5")
yarr

Wow, chức năng đó là khá mát mẻ. Không biết rằng một chức năng như thế thực sự đơn giản như vậy :) Liên kết cho người lười biếng: bit.ly/1pWOZMJ
API-Beast

1

Tôi không chắc vấn đề được chỉ định đầy đủ bởi câu hỏi, nhưng tôi có thể cung cấp một số ý tưởng đơn giản, thứ hai trong số này sẽ cung cấp các con số gần đúng với những gì hình ảnh của bạn cho biết bạn muốn.

Dù bằng cách nào bạn có thể nhận ra hàm phân phối đang thay đổi sau mỗi số được tạo và có bộ nhớ (nghĩa là không phảiMarkovian ) và một trong hai phương thức này có thể chứng minh không thực tế khi 'bộ nhớ' (số lượng số được rút ra trước đó) rất lớn.

  1. Đơn giản:
    Tạo số ngẫu nhiên tạo thành phân phối phẳng, so sánh với số người đã vẽ trước đó, lặp lại nếu 'quá gần'

  2. Câu trả lời này giống với con số của bạn hơn (giả sử chúng tôi muốn rút ra từ 0..1):

    • tạo một danh sách theo thứ tự mới, chèn 0 và 1
    • tạo số ngẫu nhiên từ hàm phân phối phẳng: N_0
      • thêm số này vào danh sách
    • trong cuộc gọi tiếp theo, hãy vẽ một số khác N_1,
    • nếu N_1> N_0
      • vẽ một số ngẫu nhiên Gaussian mới với giá trị trung bình = 1 và độ lệch chuẩn o của bất cứ thứ gì bạn muốn, một số nhỏ hơn (so với 1-N_1) sẽ giữ các số ngẫu nhiên cách xa nhau. Điều này sẽ không đảm bảo khoảng cách tối thiểu giữa các lần rút, nhưng một lần nữa, con số của bạn dường như cũng không.
    • trường hợp ngược lại của N_1 <N_0 xử lý tương tự
    • trong các lần rút tiếp theo, hãy tiếp tục tạo một số ngẫu nhiên (N_i) từ phân phối phẳng
    • duyệt qua danh sách của bạn để xem hai số nào được rút trước đó, số mới nằm giữa (N_-, N_ +)
    • tạo một số ngẫu nhiên Gaussian mới với giá trị trung bình (N_- + N _ +) / 2
    • thêm số phân phối phẳng (N_i) vào danh sách (danh sách được sắp xếp) của bạn

thùng điểm cuối là một trường hợp đặc biệt, nhưng nó đủ đơn giản để bạn xem cách xử lý chúng.


0

Hãy nghĩ về sự khác biệt giữa 1 con xúc xắc3 con xúc xắc . 1 Dice cung cấp cho bạn một xác suất đồng đều cho tất cả các giá trị, trong khi 3 súc sắc sẽ có xu hướng có xác suất cao hơn cho các giá trị ở giữa.

Càng nhiều "xúc xắc" trong phương trình của bạn, cơ hội của bạn để có được một cái gì đó về phía trung tâm càng mạnh mẽ. Vì vậy, hãy xác định một hàm có thể xử lý đồng đều bất kỳ số nào :

// Takes a random number between floor and ceil
// pow defines how strongly these results should gravitate towards the middle
// We also define a function TrueRand(floor, ceil) elsewhere where you should substitute your own random function
int CenterRandom(int floor, int ceil, int pow = 3)
{
    if(ceil == floor)
        return ceil; // don't care to compare

    int total = 0;
    for(int x = 0; x < pow; x++)
    {
       total += TrueRand(floor, ceil);
    }
    return total / pow;
}

Bây giờ chúng ta có thể định nghĩa một hàm ví dụ để sử dụng điều này:

// Distribues a number of points between floor and ceil
// We assume a function PlotPoint(int) exists to aid in creating the planet, etc...
void DistributePoints(int floor, int ceil, int numPoints)
{
    // Could easily output this in the function parameters, but language wasn't specified
    int[numPoints] breaks;
    int numBreaks = 0;

    // Special case for first pair
    breaks[0] = CenterRandom(floor, ceil);
    numBreaks++;

    for(int x = 0; x < numPoints - 1; x++)
    {
        // Generate a random number linearly, this will be used for picking
        // This way we have a greater chance of choosing a random value between larger pairs
        int picker = TrueRandom(floor, ceil);

        // Now we first find the pair of points that our picker exists on
        // For simplicity, we handle the first and last pair separately

        if(picker >= floor && picker < breaks[0])
        {
            breaks[x] = CenterRandom(floor, breaks[0] - 1);
        }
        for(int i = 0; i < numBreaks; i++)
        {
            if(picker > breaks[i] && picker < breaks[i+1])
            {
                breaks[x] = CenterRandom(breaks[i] + 1, breaks[i+1] - 1);
            }
        }
        if(picker > breaks[numBreaks] && picker <= ceil)
        {
            breaks[x] = CenterRandom(breaks[numBreaks] + 1, ceil);
        }

        PlotPoint(breaks[x]); // Plot the point
    }
}

Bây giờ điều đầu tiên cần lưu ý là mã này thực sự không kiểm tra xem bộ chọn có khớp với một trong các điểm không. Nếu vậy thì nó sẽ không tạo ra một điểm, có thể là thứ bạn có thể thích.

Để giải thích những gì đang diễn ra ở đây là CenterRandom tạo ra một đường cong hình chuông. Hàm này chia mặt phẳng thành nhiều đường cong hình chuông, mỗi điểm cho một cặp điểm. Bộ chọn cho chúng ta biết đường cong hình chuông nào sẽ được tạo ra. Vì chúng tôi chọn tuyến tính, chúng tôi có thể đảm bảo rằng các cặp có khoảng cách lớn hơn giữa chúng sẽ được chọn thường xuyên hơn, nhưng chúng tôi vẫn để nó hoàn toàn ngẫu nhiên.

Hy vọng điều này chỉ cho bạn đi đúng hướng.


0

Tôi biết bạn đang hỏi về một chuỗi các vị trí ngẫu nhiên, nhưng nếu bạn không bị hạn chế tạo tập hợp theo tuần tự, có một cách tiếp cận khác: tạo một tập hợp các điểm có khoảng cách mong muốn.

Những gì tôi nghĩ bạn muốn là một tập hợp các hành tinh có khoảng cách hợp lý với một số ngẫu nhiên. Thay vì tạo các vị trí hành tinh bằng trình tạo số ngẫu nhiên, hãy tạo khoảng cách hành tinh với trình tạo số ngẫu nhiên. Điều này sẽ cho phép bạn trực tiếp kiểm soát phân phối khoảng cách, bằng cách sử dụng trình tạo số ngẫu nhiên chọn từ phân phối đó. Điều này là đơn giản trong 1 chiều.

Trong 2 chiều, tôi đã thấy một số cách tiếp cận tạo ra tiếng ồn màu xanh lam nhưng tôi không biết cách tạo khoảng cách với phân phối tùy ý. Bài viết này trình bày về cách dùng thử tiêu chuẩn và thử từ chối nếu nó quá gần với cách tiếp cận, nhưng bạn có thể tạo ra tất cả chúng cùng một lúc, với giải pháp mềm hơn bằng cách đặt tất cả các điểm của bạn, sau đó sử dụng Lloyd Relaxation để di chuyển tất cả các hành tinh sang nhiều hơn vị trí mong muốn. Nó sẽ di chuyển các hành tinh quá gần nhau ra xa hơn. Wang gạch đệ quy là một cách tiếp cận khác có thể hữu ích. Tờ giấy nàymở rộng vấn đề để tạo ra các hành tinh có một mật độ và một số vật thể khác như các tiểu hành tinh có mật độ khác. Bạn cũng có thể tạo ra tiếng ồn màu xanh bằng cách sử dụng chuỗi Fourier; Tôi không chắc. Cách tiếp cận chuỗi Fourier cũng sẽ cho phép bạn sử dụng các phân phối tùy ý thay vì chỉ có nhiễu xanh.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.