2013-01-17 11 views
5

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

कोड पर विचार करें:

<?php 
    // Taken from php.net/shuffle user notes 
    // Shuffles an array order for the sake of foreach while maintaining 
    // key => value associations 
    function shuffle_assoc(&$array) { 
    $keys = array_keys($array); 
    shuffle($keys); 
    foreach($keys as $key) { 
     $new[$key] = $array[$key]; 
    } 
    return $new; 
    } 

    $i = 1000000; // How many tests to perform 

    // This is my rule list. Each key is a simple color 
    // and each value is a probability represented as a percent 
    $rules = array(
    'black' => 20, 
    'white' => 10, 
    'red' => 40, 
    'green' => 5, 
    'blue' => 25, 
); 

    // Initialize the scores array with all 0's 
    // The "outs" will be used when the probability does not 
    // occur in any of the rules 
    $scores = array('outs' => 0); 
    foreach($rules as $k => $v) { 
    $scores[$k] = 0; 
    } 

    $count = count($rules); 

    for($x = 0; $x < $i; $x++) { 
    $rules = shuffle_assoc($rules); 

    foreach($rules as $k => $probability) { 
     $rand = mt_rand(1,100); 
     //$probability = ??; I've tried applying many different operations here to "correct" the probability 

     if($rand > $probability) { 
     continue; 
     } else { 
     $scores[$k]++; 
     continue 2; 
     } 
    } 
    $scores['outs']++; 
    } 


    foreach($scores as $k => $v) { 
    echo "$k: " . (($v/$i)*100) . "% ($v/$i)\n"; 
    } 

?> 

अपेक्षित उत्पादन (छद्म)। नोट प्रतिशत $rules

outs: less than 1% (.../1000000) 
black: 20% (.../1000000) 
white: 10% (.../1000000) 
red: 40% (.../1000000) 
green: 5% (.../1000000) 
blue: 25% (.../1000000) 

उदाहरण आउटपुट के मूल्यों के साथ अनुरूप:,

  • आप देख सकते हैं पाश मैं भीतर:

    outs: 30.7128% (307128/1000000) 
    black: 13.2114% (132114/1000000) 
    white: 6.3381% (63381/1000000) 
    red: 29.5247% (295247/1000000) 
    green: 3.1585% (31585/1000000) 
    blue: 17.0545% (170545/1000000) 
    

    चीजें मैं & बातें की कोशिश की है $probability = ?? का एक टिप्पणी अनुभाग है जिसमें मैंने प्रत्येक के भीतर उपयोग करने की वास्तविक संभावना की गणना करने के विभिन्न स्पष्ट-तरीकों के तरीकों की कोशिश की है तत्व, जिसमें $count (नियमों की गिनती) के साथ खेलना शामिल है, यही कारण है कि वह चर मौजूद है और इसका उपयोग नहीं किया जाता है।

  • यह स्पष्ट रूप से सटीक नहीं होना चाहिए, लेकिन अधिमानतः संख्याओं के छोटे सेट (e.x. 1,000 पुनरावृत्तियों) पर स्थिर परिणाम हैं।

  • यह बहुत अस्पष्ट हो सकता है। +/- 5% का एक अंतर मेरी भावनाओं को चोट नहीं पहुंचाएगा, खासकर पुनरावृत्तियों की छोटी संख्या में, मुझे लगता है कि बड़ी संख्या सिद्धांत यहां खेलने के लिए आता है।

  • आउट की संख्या एक बड़ा सौदा नहीं है जब तक वे 1% -2% से कम न हों। मैंने यह देखने के लिए विभिन्न तरीकों का उपयोग करके बहिष्कारों को खत्म करने का भी प्रयास किया कि क्या अकेले बहिष्कार छेड़छाड़ कर रहे थे, और जब मैंने एक अवसर पर ऐसा किया तो दिलचस्प रूप से पर्याप्त था, मुझे लगभग 20% विभाजित किया गया था (यानी)।

  • इसके अलावा, "बहिष्कार" पर, मैं द्वारा सुंदर बहुत कम बहिष्कार के साथ उचित विभाजन के करीब प्राप्त करने में सक्षम था मूल रूप से पशु-मजबूर कर संभावना "संख्या" (जो है, $rules के मूल्यों) 100 पीछे की ओर से शुरू , लेकिन मैं कभी भी एक सटीक, इष्टतम विधि नहीं ढूंढ पाया। हर बार, मैं एक रंग के परिणाम के करीब आ जाएगा, जो अन्य रंगों को एक छोटे लेकिन ध्यान देने योग्य पैमाने पर छोड़ देगा। इन संख्याओं में कोई आसान-से-समझने वाला सहसंबंध नहीं था और प्रतीत होता है कि यह यादृच्छिक था हालांकि यह स्पष्ट है कि परिणाम संभावनाओं के साथ बड़ी संख्या में अच्छी तरह से खेला जाता है।

मुझे बताएं कि इसकी गणना करने का एक सटीक तरीका है। यह मुझे पागल कर रहा है।

संपादित करें: मैं नीचे दो जवाब से मदद, कि संभावना प्रतिशत जानने से पहले पाश शुरू होता है की आवश्यकता के बिना ऐसा करता है, और कोई अतिरिक्त या नेस्टेड छोरों के साथ मेरे कोड का एक अंतिम रूप संस्करण है, (जो मुझे विशेष रूप से जरूरी है, मुझे लगता है कि मुझे उस हिस्से में अधिक प्रत्यक्ष होना चाहिए) .. प्रत्येक पुनरावृत्ति के अर्थ में, आप उस विशिष्ट पुनरावृत्ति गुणों के आधार पर गतिशील रूप से संभावना को खींच सकते हैं ..सभी जवाब यहां अमूल्य थे, यहाँ अंतिम कोड के अपने संस्करण है: http://pastebin.com/eB3TVP1E

+3

आश्चर्य, किसी ने कोई प्रश्न पोस्ट करने से पहले अपने शोध किया। मैं तुम्हें पसंद करता हूं। –

+0

तो आपको बस इतना ही उचित आवश्यकता है? या क्या मैं कुछ न कुछ भूल रहा हूं? मैं इससे पहले कुछ इस तरह से संघर्ष किया। –

+1

आप चाबियाँ क्यों घुमा रहे हैं? आप हर कुंजी के साथ यादृच्छिक संख्या क्यों बना रहे हैं? आप एल्गोरिदम को अधिक जटिल बना रहे हैं। प्रत्येक इंडेक्स के लिए बस यादृच्छिक संख्या 1 से 100 चुनें, फिर पता लगाएं कि कौन सा नियम लागू होना चाहिए, यानी 0-19 काला है, 20-29 सफेद है, 30-69 लाल है, 70-74 हरा है, 75-99 नीला है । – mellamokb

उत्तर

2

जैक विचार अपने कोड में लागू (यदि संभावनाओं का योग> 100 है इस काम नहीं करेगा):

php fiddle

<?php 
    // Taken from php.net/shuffle user notes 
    // Shuffles an array order for the sake of foreach while maintaining 
    // key => value associations 
    function shuffle_assoc(&$array) { 
    $keys = array_keys($array); 
    shuffle($keys); 
    foreach($keys as $key) { 
     $new[$key] = $array[$key]; 
    } 
    return $new; 
    } 

    $i = 1000000; // How many tests to perform 

    // This is my rule list. Each key is a simple color 
    // and each value is a probability represented as a percent 
    $rules = array(
    'black' => 20, 
    'white' => 10, 
    'red' => 40, 
    'green' => 5, 
    'blue' => 25, 
); 

    // Initialize the scores array with all 0's 
    // The "outs" will be used when the probability does not 
    // occur in any of the rules 
    $scores = array('outs' => 0); 
    foreach($rules as $k => $v) { 
    $scores[$k] = 0; 
    } 

    $count = count($rules); 
//$limits is what Jack called $rules_norm 
$limits=array(); 
$limit=0; 
foreach($rules as $k=>$v) 
{ 
    $limit+=$v; 
    $limits[$k]=$limit; 
} 
    for($x = 0; $x < $i; $x++) { 
     $rand = mt_rand(1,100); 
foreach($limits as $k=>$v) 
{ 
    if($v>=$rand) 
    { 
     $scores[$k]++; 
     continue(2); 
    } 

} 
    $scores['outs']++; 
    } 


    foreach($scores as $k => $v) { 
    echo "$k: " . (($v/$i)*100) . "% ($v/$i)\n"; 
    } 

?> 
+0

यह पूरी तरह से काम करता है। मुझे काम करने के लिए जैक का विचार नहीं मिल सका क्योंकि मैं अभी भी प्रत्येक 'foreach' के भीतर एक यादृच्छिक संख्या उत्पन्न कर रहा था, न कि प्रत्येक पुनरावृत्ति (' के लिए ') के भीतर, जो इसे एक तरह से जंगली तरीके से अलग कर रहा था जिस तरह से मैं भी नहीं चाहता समझने की कोशिश करना शुरू करें।मैं संदर्भ के लिए जोड़ना चाहता हूं कि जब यह संभावना 100% से कम हो, तो 100% से कम होने पर, यह अनुपस्थित व्यवहार कर सकता है, जबकि अनुपलब्ध संभावना "बाहरी" पर जाती है, जो वास्तव में मेरे विशिष्ट मामले में बहुत उपयोगी होती है। –

4

बस परिणामों को सामान्यीकृत, उन्हें जमा करें और फिर आप कर चुके हैं।

क्या मेरा मतलब है:

  • योग सभी संभावनाओं सरणी की कुल प्राप्त करने के हर आइटम के लिए दिया जाता है (जो आपके मामले में 100 है, लेकिन यह आसानी से generalizable है) कुल के लिए
  • डिवाइड हर संभावना
उदाहरण के लिए

तो:

$rules = array(
    'black' => 20, 
    'white' => 10, 
    'red' => 40, 
    'green' => 5, 
    'blue' => 25, 
); 

के लिए सामान्यीकृत किया जाएगा:

$rules_norm = array(
    'black' => 0.2, 
    'white' => 0.1, 
    'red' => 0.4, 
    'green' => 0.05, 
    'blue' => 0.25, 
); 
  • अब परिणाम जमा ताकि $rules_norm में प्रत्येक तत्व के लिए आप सभी पिछले तत्व के साथ साथ वर्तमान एक के योग की गणना।

तो:

$rules_norm = array(
    'black' => 0.2, 
    'white' => 0.3, 
    'red' => 0.7, 
    'green' => 0.75, 
    'blue' => 1.0, 
); 
अब इस के साथ

तुम सिर्फ सीमा [0,1) में एक यादृच्छिक नाव संख्या निकालने और चुनें परिणाम के अनुसार जो तत्व बढ़ रहे हैं कर सकते हैं: एक तत्व के स्कोर को बढ़ाने के लिए बस से शुरू सरणी में पहले एक और बढ़ाने के ऐसे ही एक है कि $rand > $rules_norm[k]

संबंधित मुद्दे