सिक्के के उपयोग से समान रूप से वितरित यादृच्छिक संख्याओं का सृजन


25

आपके पास एक सिक्का है। आप इसे जितनी बार चाहें उतनी बार फ्लिप कर सकते हैं।

आप एक यादृच्छिक संख्या जैसे कि जहाँ उत्पन्न करना चाहते हैं ।एक आर < b आर , एक , जेड +rar<br,a,bZ+

संख्या का वितरण समान होना चाहिए।

यह आसान है अगर :ba=2n

r = a + binary2dec(flip n times write 0 for heads and 1 for tails) 

क्या होगा अगर ?ba2n


हान-होशी एल्गोरिथ्म का उपयोग करें - मूल रूप से अंतराल को दो में विभाजित करें, अपने यादृच्छिक बिट (सिक्का फ्लिप) का उपयोग बेतरतीब ढंग से दो अंतरालों में से एक को चुनने के लिए करें, फिर इस प्रक्रिया को उस तरफ दोहराएं, जब तक आप बिट्स से बाहर नहीं निकल जाते। यह आपको वास्तविक रेखा के विभाजन से समान रूप से वितरित अंतराल प्रदान करेगा। आपके पास जितना अधिक फ़्लिप होगा, अंतराल उतना ही सटीक होगा।
zenna

जवाबों:


13

आप जो खोज रहे हैं, वह अस्वीकृति नमूने या स्वीकार-अस्वीकार पद्धति पर आधारित है (ध्यान दें कि विकी पेज थोड़ा तकनीकी है)।

इस प्रकार की स्थितियों में यह विधि उपयोगी है: आप एक सेट से कुछ यादृच्छिक वस्तु (सेट में एक यादृच्छिक पूर्णांक आपके मामले में) लेना चाहते हैं, लेकिन आप यह नहीं जानते कि यह कैसे करना है, लेकिन आप कर सकते हैं (आपके मामले में, एक बड़ा पहला सेट युक्त सेट से कुछ यादृच्छिक वस्तु लेने [ एक , 2 कश्मीर + एक ] कुछ के लिए कश्मीर ऐसी है कि 2 कश्मीर + एक ; इस से मेल खाती है कश्मीर सिक्का उछालता है)।[a,b][a,2k+a]k2k+abk

ऐसे परिदृश्य में, आप बस बड़े सेट से तत्वों को उठाते रहते हैं जब तक कि आप छोटे सेट में किसी तत्व को अनियमित रूप से नहीं लेते। यदि आपका छोटा सेट आपके बड़े सेट की तुलना में काफी बड़ा है (आपके मामले में, में दो गुना अधिक पूर्णांक होते हैं जैसे कि [ a , b ] , जो काफी अच्छा है), यह कुशल है।[a,2k+a][a,b]

एक वैकल्पिक उदाहरण: मान लीजिए कि आप त्रिज्या के साथ एक सर्कल के अंदर एक यादृच्छिक बिंदु चुनना चाहते हैं। अब, इसके लिए प्रत्यक्ष विधि के साथ आना आसान नहीं है। हम स्वीकार-अस्वीकार पद्धति की ओर मुड़ते हैं: हम सर्कल को घेरने वाले 1x1 वर्ग में बिंदुओं का नमूना लेते हैं, और परीक्षण करते हैं कि संख्या हम सर्कल के अंदर निहित है या नहीं।


3
ध्यान दें कि यदि हम B पर वितरण प्राप्त करने के लिए से नमूनों को अस्वीकार करते हैं , तो पुनरावृत्तियों की अपेक्षित संख्या है | |AB(जैसा कि हम ज्यामितीय वितरण के साथ एक प्रयोग करते हैं)। |A||B|
राफेल

मुझे याद है कि कहीं यह देखने में नहीं आता कि यह तब तक नहीं किया जा सकता जब तक कि सीमा 2 की शक्ति न हो (जैसा कि उचित कारण है, उदाहरण के लिए 1/3 में कोई द्विआधारी विस्तार नहीं है)।
वॉनब्रांड 25'13

7

(तकनीकी: उत्तर संख्या का चयन फिट बैठता )ax<b

जब से तुम कई बार के रूप में अपने सिक्का फ्लिप करने के रूप में आप चाहते हैं की अनुमति है, तो आप अपने संभावना प्राप्त कर सकते हैं के रूप में बंद के रूप में आप-इच्छा वर्दी के एक अंश को चुनकर (बाइनरी मूलांक का उपयोग कर: आप फ्लिप बिंदु के बाद प्रत्येक अंक) और गुणा के लिए सिक्का आर द्वारा बा 0 और [ba-1] (एक पूर्णांक के लिए नीचे गोलाई) के बीच एक नंबर पाने के लिए। इस नंबर को इसमें जोड़ें और आपका काम हो गया।r[0,1]rbaa

उदाहरण : कहते हैं । बाइनरी में 1/3 0.0101010101 है .... फिर, यदि आपका फ्लिप 0 से 0.010101 के बीच है ... आपका पिक बी है । अगर यह beween 0.010101 .. और 0.10101010 है ... अपने पिकअप हो जाएगा एक + 1 , और नहीं तो यह हो जाएगा एक + 2ba=3ba+1a+2

यदि आप अपने सिक्के को बार फ्लिप करते हैं तो और बी के बीच के प्रत्येक नंबर को प्रायिकता 1 के साथ चुना जाएगाtab1ba±2(t+1)


1
यह एक समान वितरण नहीं देता है। कुछ अनुप्रयोगों (जैसे क्रिप्टो, कभी-कभी) के लिए, यह बहुत बुरा हो सकता है।
गिल्स एसओ- बुराई को रोकना '

3
@ गिल्स: जब तक परिणाम बदलना संभव न हो, तब तक फ्लिप करके पूरी तरह से समान वितरण देना तय किया जा सकता है। यह सबसे कुशल उत्तर है।
नील जी

@ नील मुझे पता है कि इसे ठीक किया जा सकता है, लेकिन इसे ठीक करना उत्तर का एक महत्वपूर्ण हिस्सा होगा।
गिलेस एसओ- बुराई को रोकना '

2
@ गिल्स: आप सही कह रहे हैं। उन्होंने कहा कि यह कहना है कि आप अगर आप जबकि फ्लिप एक पूरी तरह से समान वितरण का उत्पादन कर सकते जवाब को संशोधित कर सकता है । सबसे अच्छे औसत मामले और सबसे खराब समय के लिए मुझसे +1। (ba)(f+2t1)(ba)(f2t1)
नील जी

@ नील, यह "निश्चित" नहीं हो सकता है, क्योंकि पूर्णांकों का एक बड़ा सेट है, जिसमें एक द्विआधारी अंश नहीं है।
वॉनब्रांड

7

2 बड़ी रेंज की अगली बड़ी शक्ति में एक संख्या चुनें, और से अधिक के उत्तर छोड़ें ।ba

n = b-a;
N = round_to_next_larger_power_of_2(n)
while (1) {
  x = random(0 included to N excluded);
  if (x < n) break;
}
r = a + x;

4
और यह काम क्यों करता है?
राफेल

@ राफेल क्या आपको संदेह है, या आप केवल पोस्टर को अधिक विस्तार से समझाना चाहते हैं?
सुरेश

1
@ सुरेश: बाद वाला। छद्म कोड को थोड़ा पॉलिश किया जा सकता है, लेकिन यह अन्य उत्तरदाताओं को समझाता है। औचित्य के बिना, यह जवाब अपने आप में बहुत अधिक लायक नहीं है।
राफेल

6

किसी ने भी इसका उल्लेख नहीं किया है, इसलिए मुझे औपचारिक रूप से यह साबित करने दें कि यदि एक ऐसा डोमेन है जिसका आकार दो की शक्ति नहीं है, तो बारीक रूप से कई उचित सिक्के टॉसे डी के समान रूप से यादृच्छिक सदस्य उत्पन्न करने के लिए पर्याप्त नहीं हैं । मान लीजिए कि आप डी का सदस्य बनाने के लिए k के सिक्कों का उपयोग करते हैं । प्रत्येक के लिए डी , संभावना है कि अपने एल्गोरिथ्म उत्पन्न फार्म की है एक / 2 कश्मीर कुछ पूर्णांक के लिए एक । अंकगणित के मूल सिद्धांत से पता चलता है कि / 2 k1 / | डी | DDkDdDdA/2kAA/2k1/|D|

आप जनरेट करना चाहते हैं के स्वतंत्र वर्दी नमूने डी , तो सिक्के के अपेक्षित संख्या में tosses आप (इष्टतम एल्गोरिथ्म के तहत) की जरूरत है मोटे तौर पर किया जाता है n लॉग ऑन 2 | D | । अधिक आम तौर पर, यदि आप एन्ट्रापी एच के वितरण से उत्पन्न करना चाहते हैं, तो आपको अपेक्षा में लगभग एन एच यादृच्छिक बिट्स की आवश्यकता होती है। इसे प्राप्त करने वाला एक एल्गोरिथ्म अंकगणितीय डिकोडिंग है, जो यादृच्छिक बिट्स के (ओस्टेंसिक रूप से) अनंत क्रम पर लागू होता है।nDnlog2|D|HnH


3

यदि बा 2 की शक्ति नहीं है, तो परिणाम प्राप्त करने के लिए आपको कई सिक्कों को पलटना पड़ सकता है। आपको कभी भी परिणाम नहीं मिल सकता है, लेकिन यह चरम में होने की संभावना नहीं है।

तरीके

सबसे सरल विधि [a, a + 2 ^ n) में एक संख्या उत्पन्न करना है, जहां 2 ^ n> = ba, जब तक कि कोई एक [a, b) में नहीं उतरता। आप इस विधि से बहुत सारी एन्ट्रापी फेंक देते हैं।

एक अधिक महंगी विधि आपको सभी एन्ट्रॉपी रखने की अनुमति देती है, लेकिन बहुत महंगी हो जाती है, क्योंकि सिक्के के फ्लिप्स / डाइस रोल की संख्या बढ़ जाती है। सहज रूप से यह सिक्के के गुच्छे को द्विआधारी संख्या के अंकों के रूप में दशमलव बिंदु के दाईं ओर मानने जैसा है, उस संख्या को आधार 2 से आधार एबी के बाद परिवर्तित करना और उस संख्या के अंकों को वापस करना जैसा कि वे 'अटक' जाते हैं।

उदाहरण

निम्न कोड एक उचित n- पक्षीय मर के रोल को एक उचित m- पक्षीय मर के रोल में परिवर्तित करता है (आपके मामले में n = 2, m = ab), सीमांत लागत बढ़ने के साथ रोल की संख्या बढ़ जाती है। मनमानी परिशुद्धता के साथ एक तर्कसंगत संख्या प्रकार की आवश्यकता पर ध्यान दें। एक अच्छी संपत्ति यह है कि एन-साइडेड से एम-साइडेड और एन-साइडेड में परिवर्तित होने से मूल स्ट्रीम वापस आ जाएगी, हालांकि अंकों के अटक जाने के कारण शायद कुछ जोड़े में देरी होती है।

public static IEnumerable<BigInteger> DigitConversion(this IEnumerable<BigInteger> inputStream, BigInteger modIn, BigInteger modOut) {
    //note: values are implicitly scaled so the first unfixed digit of the output ranges from 0 to 1
    Rational b = 0; //offset of the chosen range
    Rational d = 1; //size of the chosen range
    foreach (var r in inputStream) {
        //narrow the chosen range towards the real value represented by the input
        d /= modIn;
        b += d * r;
        //check for output digits that have become fixed
        while (true) {
            var i1 = (b * modOut).Floor();
            var i2 = ((b + d) * modOut).Floor(); //note: ideally b+d-epsilon, but another iteration makes that correction unnecessary
            if (i1 != i2) break; //digit became fixed?
            //fix the next output digit (rescale the range to make next digit range from 0 to 1)
            d *= modOut;
            b *= modOut;
            b -= i1;
            yield return i1;
        }
    }
}

"लेकिन यह चरम में होने की संभावना नहीं है" - इस घटना के लिए संभावना ; हम कहते हैं कि यह "लगभग निश्चित रूप से" नहीं होता है। 0
राफेल

2

एक बाइनरी दशमलव उत्पन्न करें। इसे स्पष्ट रूप से संग्रहीत करने के बजाय, केवल न्यूनतम और अधिकतम संभव मानों पर नज़र रखें। एक बार जब वे मान एक ही पूर्णांक में आते हैं, तो उस पूर्णांक को वापस कर दें। कोड का स्केच नीचे है।

(संपादित करें) फुलर स्पष्टीकरण: आप प्रत्येक से 1/3 प्रायिकता के साथ 1 से 3 तक एक यादृच्छिक पूर्णांक उत्पन्न करना चाहते हैं। हम एक यादृच्छिक बाइनरी दशमलव वास्तविक, x को रेंज (0, 1) में उत्पन्न करके करते हैं। यदि x <1/3, 1 लौटाएं, तो यदि x <2/3 वापसी 2, और वापसी 3। x के लिए अंक उत्पन्न करने के बजाय स्पष्ट रूप से, हम सिर्फ x के न्यूनतम और अधिकतम संभव मानों का ट्रैक रखते हैं। प्रारंभ में, x का न्यूनतम मान 0 और अधिकतम होता है। 1. यदि आप पहले सिर को फ्लिप करते हैं तो दशमलव बिंदु के पीछे x का पहला अंक (बाइनरी में) 1. x का न्यूनतम संभव मान (बाइनरी में) तब 0.100 हो जाता है = १/२ और अधिकतम ०.१११११११११ = १ है। अब यदि आपका अगला फ्लिप है तो x ०.१० से शुरू होता है। न्यूनतम संभव मान 0.1000000 = 1/2 है और अधिकतम 0.1011111 = 3/4 है। X का न्यूनतम संभव मान 1/2 है इसलिए आप वहां जानते हैं ' 1 की वापसी का कोई मौका नहीं है क्योंकि x <1/3 की आवश्यकता है। आप अभी भी 2 वापस कर सकते हैं यदि x समाप्त हो रहा है 1/2 <x <2/3 या 3 यदि 2/3 <x <3/4। अब मान लीजिए तीसरा फ्लिप पूंछ है। फिर x को 0.100 से शुरू करना चाहिए। न्यूनतम = 0.10000000 = 1/2 और अधिकतम = 0.100111111 = 5/8। अब चूंकि 1/3 <1/2 <5/8 <2/3 हम जानते हैं कि x को अंतराल (1/3, 2/3) में गिरना चाहिए, इसलिए हम x के अंक उत्पन्न करना बंद कर सकते हैं और सिर्फ 2 वापस कर सकते हैं।

कोड अनिवार्य रूप से ऐसा करता है सिवाय x को 0 और 1 के उत्पन्न करने के बजाय यह a और b के बीच x उत्पन्न करता है, लेकिन सिद्धांत समान है।

def gen(a, b):
  min_possible = a
  max_possible = b

  while True:
    floor_min_possible = floor(min_possible)
    floor_max_possible = floor(max_possible)
    if max_possible.is_integer():
      floor_max_possible -= 1

    if floor_max_possible == floor_min_possible:
      return floor_max_possible

    mid = (min_possible + max_possible)/2
    if coin_flip():
      min_possible = mid
    else:
      max_possible = mid

टिप्पणी: मैंने इस कोड को स्वीकार / अस्वीकार पद्धति और दोनों समान वितरणों के खिलाफ परीक्षण किया। इस कोड को स्वीकार करने के अलावा कम सिक्के के उतार-चढ़ाव की आवश्यकता होती है, जब बी को छोड़कर - एक की अगली शक्ति के करीब है 2. एक्स यदि आप एक = 0, बी = 62 उत्पन्न करना चाहते हैं तो स्वीकार / अस्वीकार बेहतर करता है। मैं यह साबित करने में सक्षम था कि यह कोड स्वीकार / अस्वीकार करने की तुलना में औसतन 2 से अधिक सिक्का फ़्लिप नहीं कर सकता है। मेरे पढ़ने से, ऐसा लगता है कि नुथ और याओ (1976) ने इस समस्या को हल करने के लिए एक विधि दी और यह साबित कर दिया कि उनकी विधि अपेक्षित संख्या में सिक्का फ़्लिप करने के लिए इष्टतम है। उन्होंने आगे साबित किया कि वितरण की शैनन एंट्रोपी से फ्लैप की अपेक्षित संख्या अधिक होनी चाहिए। मुझे हालांकि पेपर के पाठ की एक प्रति नहीं मिली, लेकिन यह देखने के लिए उत्सुक होंगे कि उनका तरीका क्या है। (अपडेट: अभी यहां नुथ याओ 1976 का प्रदर्शन मिला है:http://www.nrbook.com/devroye/Devroye_files/chapter_fifteen_1.pdf लेकिन मैंने अभी तक इसे नहीं पढ़ा है)। किसी ने इस धागे में हान होशी का भी उल्लेख किया है जो अधिक सामान्य प्रतीत होता है और पक्षपाती सिक्के का उपयोग करके इसे हल करता है। साहित्य की अच्छी चर्चा के लिए http://paper.ijcsns.org/07_book/200909/20090930.pdf देखें (2009)।



1

इस मामले के लिए एक प्रस्तावित समाधान है जब बी - 2 ए के बराबर नहीं है। यह निश्चित संख्या में चरणों में काम करने वाला है (उम्मीदवारों को दूर फेंकने की आवश्यकता नहीं है जो आपकी अपेक्षित सीमा से बाहर हैं)।

हालाँकि, मुझे यह सही नहीं है। कृपया आलोचना करें और इस यादृच्छिक संख्या जनरेटर (यदि कोई हो) में सटीक गैर-एकरूपता का वर्णन करने में सहायता करें और इसे कैसे मापें / इसकी मात्रा निर्धारित करें।

सबसे पहले समान रूप से वितरित यादृच्छिक संख्याओं को उत्पन्न करने के समतुल्य समस्या में परिवर्तित करें [0, z-1] जहां z = b - a।

इसके अलावा, m = 2 ^ k 2> = z की सबसे छोटी शक्ति है।

उपरोक्त समाधान के अनुसार, हमारे पास पहले से ही समान रूप से वितरित यादृच्छिक संख्या जनरेटर आर (एम) रेंज में [0, एम -1] है (के सिक्कों को उछालकर, प्रत्येक बिट के लिए एक)।

    Keep a random seed s and initialize with s = R(m).   

    function random [0, z-1] :
        x = R(m) + s 
        while x >= z:
            x -= z
        s = x
        return x

जबकि लूप अधिकतम 3 बार चलता है, निश्चित चरणों में अगले यादृच्छिक संख्या (सबसे अच्छा मामला = सबसे खराब स्थिति) देता है।

संख्याओं के लिए एक परीक्षण कार्यक्रम देखें [0,2] यहाँ: http://pastebin.com/zuDD2V6H


z=3m=41/2,1/4,1/4

कृपया छद्म कोड के साथ-साथ लिंक कोड को और अधिक बारीकी से देखें। यह 0, 1, और 2 को समान आवृत्ति के साथ उत्सर्जित करता है ...
vpathak

01/21/4

आप पूरे फ़ंक्शन को एक पंक्ति से बदल सकते हैं: रिटर्न s = (s + R (m))% z;
युवल फिल्मस

1

सैद्धांतिक रूप से इष्टतम एल्गोरिथ्म

यहाँ मेरे द्वारा पोस्ट किए गए दूसरे उत्तर का सुधार है। अन्य उत्तर का यह लाभ है कि एक असतत वितरण को दूसरे से उत्पन्न करने के अधिक सामान्य मामले तक विस्तार करना आसान है। वास्तव में, अन्य उत्तर हान और होशी के कारण एल्गोरिथ्म का एक विशेष मामला है।

यहाँ मैं जिस एल्गोरिथ्म का वर्णन करूँगा वह नूथ और याओ (1976) पर आधारित है। अपने पेपर में, उन्होंने यह भी साबित किया कि यह एल्गोरिथ्म सिक्का के न्यूनतम संभावित अपेक्षित संख्या प्राप्त करता है।

इसे समझने के लिए, अन्य उत्तरों द्वारा वर्णित अस्वीकृति नमूना पद्धति पर विचार करें। एक उदाहरण के रूप में, मान लें कि आप 5 में से एक संख्या को समान रूप से उत्पन्न करना चाहते हैं [0, 4]। 2 की अगली शक्ति 8 है, इसलिए आप 3 बार सिक्का फ्लिप करें और 8. तक एक यादृच्छिक संख्या उत्पन्न करें। यदि संख्या 0 से 4 है, तो इसे वापस लौटाएं। अन्यथा, आप इसे फेंक देते हैं और 8 तक एक और संख्या उत्पन्न करते हैं और फिर से प्रयास करते हैं जब तक कि आप सफल न हों। लेकिन जब आप संख्या बाहर फेंकते हैं, तो आप बस कुछ एन्ट्रोपी बर्बाद करते हैं। आप भविष्य में सिक्का की संख्या को कम करने के लिए आपके द्वारा फेंके गए नंबर पर शर्त के बजाय इसकी अपेक्षा कर सकते हैं। लगातार, एक बार जब आप संख्या [0, 7] उत्पन्न करते हैं, अगर यह [0, 4] है, तो वापस लौटें। अन्यथा, यह 5, 6 या 7 है, और आप प्रत्येक मामले में कुछ अलग करते हैं। यदि यह 5 है, तो सिक्के को फिर से फ्लिप करें और फ्लिप के आधार पर या तो 0 या 1 वापस करें। अगर यह 6 है, सिक्का पलटें और 2 या 3 लौटें। यदि यह 7 है, तो सिक्का पलटें; यदि यह सिर है, तो 4 लौटें, अगर यह पूंछ शुरू हो।

हमारे शुरुआती असफल प्रयास से बचे हुए प्रवेश ने हमें 3 मामले (5, 6 या 7) दिए। यदि हम इसे बाहर फेंक देते हैं, तो हम log2 (3) सिक्का निकालते हैं। हम इसके बजाय इसे रखते हैं, और इसे 6 संभावित मामलों (5H, 5T, 6H, 6T, 7H, 7T) को उत्पन्न करने के लिए एक और फ्लिप के परिणाम के साथ जोड़ते हैं, जो हमें तुरंत सफलता की संभावना 5/6 के साथ एक अंतिम उत्तर उत्पन्न करने के लिए फिर से कोशिश करते हैं। ।

यहाँ कोड है:

# returns an int from [0, b)
def __gen(b):
  rand_num = 0
  num_choices = 1

  while True:
    num_choices *= 2
    rand_num *= 2
    if coin.flip():
      rand_num += 1

    if num_choices >= b:
      if rand_num < b:
        return rand_num
      num_choices -= b
      rand_num -= b

# returns an int from [a, b)
def gen(a, b):
  return a + __gen(b - a)
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.