[英]Can I achieve weighted randomness with a function that returns weighted booleans?
我有一種模仿不公平硬幣的方法。 您可以傳入一個百分比,它會通過返回 boolean 來告訴您是否成功。 所以如果你用.25 調用它,它會在 25% 的時間內返回true
。
我試圖弄清楚我是否可以使用這個 function 來創建一個加權隨機性 function,它的工作原理如下: There is a 25% chance it returns x, a 40% chance it returns y, and a 35% chance it returns z.
這只是一個例子。 我希望 function 可以處理無限數量的字母,但加在一起的百分比應該等於 1。
訣竅是,我希望能夠按照我剛才描述的方式來思考它。 換句話說:
result = function ({.25, x}, {.4, y}, {.35, z})
result
應該是 x 25% 的時間,依此類推。 我可以用我的不公平幣實現這個 function 嗎?
這是我在下面的評論中的措辭。它可能會澄清我的要求:
如果我在這里犯了錯誤,請糾正我的邏輯,但是假設 XY 和 Z 都有。3333...我不能用我的不公平硬幣來傳遞。3333...如果返回 true,那就意味着你得到了結果是 X。 如果返回 false,再次調用我的不公平。5 如果返回 true,則返回 Y,否則返回 Z。如果正確,如果數字 AREN'T.3333 並且如果有,我不知道如何使它工作三個以上
假設你有一個 function unfairCoin(p)
,這是一個 function 以已知概率p
產生正面,否則產生反面。 例如,它可以這樣實現:
function unfairCoin(p) {
return Math.random() < p ? True : false;
}
假設所有涉及的概率總和為 1,這是一個算法,可以解決您的問題給定unfairCoin
:
cumu
設置為 1。p
)並以概率p / cumu
接受項目(例如,通過unfairCoin(p / cumu)
)。 如果該項目被接受,則退回該項目。cumu
中減去p
。該算法的預期時間復雜度取決於概率的順序。 一般來說,該算法的時間復雜度是線性的,但如果將概率按降序排序,則預期時間復雜度是恆定的。
編輯(7 月 30 日):正如我剛剛發現的那樣,Keith Schwarz 在Darts, Dice, and Coins中已經描述了這個精確的算法,在“用有偏差的硬幣模擬加載的模具”中。 該頁面還包含其正確性的證明。
另一種解決方案使用拒絕抽樣,但需要使用公平的硬幣投擲生成隨機 integer:
n
為項目數。 例如,可以使用 J. Lumbroso 的Fast Dice Roller來做到這一點,它只使用公平的硬幣投擲 ( unfairCoin(0.5)
); 請參閱下面的代碼。 選擇給定索引處的項目(從 0 開始)。p
)並以概率p
接受它(例如,通過unfairCoin(p)
)。 如果該項目被接受,則退回該項目; 否則,go 執行步驟 1。該算法的預期時間復雜度取決於最低概率和最高概率之間的差異。
給定每個項目的權重,除了前面給出的算法之外,還有許多其他方法可以做出加權選擇; 請參閱我關於加權選擇算法的說明。
以下是實現快速骰子滾輪的 JavaScript 代碼。 請注意,它使用拒絕事件和循環來確保它是公正的。
function randomInt(minInclusive, maxExclusive) {
var maxInclusive = (maxExclusive - minInclusive) - 1
var x = 1
var y = 0
while(true) {
x = x * 2
var randomBit = (Math.random() < 0.5 ? 0 : 1)
y = y * 2 + randomBit
if(x > maxInclusive) {
if (y <= maxInclusive) { return y + minInclusive }
// Rejection
x = x - maxInclusive - 1
y = y - maxInclusive - 1
}
}
}
另一方面,如果你有一個 function COIN
以未知的概率輸出正面而反之,那么有兩個問題需要解決才能獲得解決方案:
換句話說,任務是將有偏差的硬幣變成裝好的骰子。
讓我們看看如何解決這兩個問題。
假設您有一個 function COIN()
以未知概率輸出正面,否則輸出反面。 (如果已知硬幣產生正面的概率為 0.5,那么您已經擁有一枚公平的硬幣,可以跳過此步驟。)
在這里,我們可以使用 1951 年的馮諾依曼算法,將有偏見的硬幣變成公平的硬幣。 它是這樣工作的:
COIN()
兩次。 現在我們有一個公平的硬幣FAIRCOIN()
。
(請注意,還有其他以這種方式生產公平硬幣的方法,統稱為隨機提取器,但馮諾依曼方法可能是最簡單的。)
現在,將公平硬幣變成骰子的方法要復雜得多。 可以說有很多方法可以解決這個問題,其中最新的稱為快速加載骰子滾輪,它只使用公平的硬幣產生一個加載的骰子(實際上,它平均使用多達 6 次公平的硬幣投擲超過生產每個加載的模具輥的最佳數量)。 該算法實現起來並不簡單,但請參閱我的Python 實現和Fast Loaded Dice Roller的作者的實現。
請注意,要使用快速加載骰子滾輪,您需要將每個概率表示為 integer 權重(例如您的示例中的 25、40、35)。
看看這個:
function weightedRandom(array) {
// expected array: [[percent, var], [percent, var], ...] where sum of percents is 1
var random=Math.random();
var sofar=0;
var index=-1;
for(var i=0; i<array.length; i++) {
if(sofar<random) index=i;
sofar+=array[i][0];
};
return array[index][1];
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.