2013-10-25 6 views
15

में यादृच्छिक संख्या मैं हास्केल में यादृच्छिक संख्या प्राप्त करने का प्रयास कर रहा हूं। (जिसे मैं वर्तमान में सीख रहा हूं और मोनाड्स या आईओ आदि पर नहीं मिला है) समस्या सिस्टम में कार्य है। यादृच्छिक सभी एक आईओ इंट वापस लौटाते हैं, जिसे मैं अपने शेष कोड में उपयोग नहीं कर सकता Int और Float।हास्केल

यहां उद्देश्य एक जोड़ी को एक सूची से चुनना है जहां जोड़ी का पहला एक संभावित प्रवाह का प्रतिनिधित्व करता है। तो मेरी योजना एक संभाव्यता के आधार पर एक जोड़ी चुनने के लिए एक यादृच्छिक संख्या का उपयोग करना था।

+2

यादृच्छिक संख्या अशुद्ध हैं, यही कारण है कि वे 'आईओ' मोनैड के भीतर लपेटे गए हैं। आपने अभी तक क्या प्रयास किया है? कृपया हमें कुछ कोड दिखाएं। –

+2

इस पृष्ठ के निचले भाग में एक अच्छा सरल उदाहरण है http://hackage.haskell.org/package/MonadRandom-0.1.12/docs/Control-Monad-Random.html – mhwombat

+0

न्यूमेरिक.जीएसएल का उपयोग करें। वितरण: https://hackage.haskell.org/package/hmatrix-gsl-stats –

उत्तर

1

यदि आप सच यादृच्छिकता चाहते हैं, तो आप आईओ का उपयोग नहीं करेंगे - ड्रैग की तरह लगता है, लेकिन यह पृथक्करण हास्केल का एक बहुत ही महत्वपूर्ण पहलू है। हालांकि, आप स्वयं द्वारा "बीज" चुनकर और सिस्टम से शुद्ध कार्यों का उपयोग करके सेमी-छद्म-यादृच्छिकता प्राप्त कर सकते हैं। यादृच्छिक जो परिणाम की एक जोड़ी और नए बीज (उदाहरण के लिए "यादृच्छिक") लौटाता है।

21

यह नए हास्केल प्रोग्रामर के लिए एक आम बाधा है। IO से बचने के लिए चाहते हैं, और ऐसा करने में सबसे अच्छा तरीका जानने में कुछ समय लगता है। जानें आप एक हास्केल ट्यूटोरियल में राज्य मोनैड का उपयोग करके यादृच्छिक संख्या उत्पन्न करने के एक तरीके का एक अच्छा स्पष्टीकरण है, लेकिन इसे अभी भी getStdGen या newStdGen का उपयोग करके बीज किया जाना है, जो आईओ में हैं।

साधारण मामलों के लिए आप जैसे

myPureFunction :: Float -> Float 
myPureFunction x = 2 * x 

main :: IO() 
main = do 
    -- num :: Float 
    num <- randomIO :: IO Float 
    -- This "extracts" the float from IO Float and binds it to the name num 
    print $ myPureFunction num 

तो आप देखते हैं, आप main में अपने यादृच्छिक संख्या प्राप्त कर सकते हैं कुछ कर सकते हैं, तो एक शुद्ध समारोह है कि संसाधन करता है कि मूल्य गुजरती हैं।

आप खुद से पूछ सकते हैं कि हास्केल में यादृच्छिक संख्या उत्पन्न करने के लिए यह सब काम क्यों है। कई अच्छे कारण हैं, जिनमें से अधिकांश प्रकार के सिस्टम के साथ करना है। चूंकि यादृच्छिक संख्याओं को उत्पन्न करने के लिए ऑपरेटिंग सिस्टम में StdGen की स्थिति को संशोधित करने की आवश्यकता होती है, इसे IO के अंदर रहना पड़ता है, अन्यथा आपके पास एक शुद्ध फ़ंक्शन हो सकता है जो आपको प्रत्येक बार अलग-अलग परिणाम देता है।

इस काल्पनिक परिदृश्य की कल्पना कीजिए:

myConstant :: Int 
myConstant = unsafePerformIO randomIO 

blowUpTheWorld :: IO() 
blowUpTheWorld = error "Firing all the nukes" 

main :: IO() 
main = do 
    if even myConstant 
     then print "myConstant is even" 
     else blowUpTheWorld 

, तो आप इस कई बार भाग गया, संभावना है कि आप "फायरिंग सभी परमाणु" अंत होगा रहे हैं। जाहिर है, यह बुरा है। myConstant होना चाहिए, ठीक है, स्थिर, लेकिन हर बार जब आप प्रोग्राम चलाते हैं तो आपको एक अलग मूल्य मिल जाएगा। हास्केल यह गारंटी देना चाहता है कि एक शुद्ध कार्य हमेशा एक ही इनपुट को उसी इनपुट को वापस कर देगा।

यह अभी परेशान हो सकता है, लेकिन यह कार्यात्मक प्रोग्रामर की किट में एक शक्तिशाली उपकरण है।

4

जैसा कि पहले से ही कहा गया है, यादृच्छिक संख्या वास्तव में शुद्ध मान नहीं हो सकती ।

हालांकि, आपको वास्तव में परेशान करने की आवश्यकता नहीं है। बस इसे दूसरी तरफ देखें: अन्य भाषाओं में शुद्ध मूल्यों की तरह ऐसी कोई चीज़ नहीं है, यह हमेशा वास्तविक दुनिया हस्तक्षेप के साथ राज्य करता है जिसके साथ आप काम कर रहे हैं। हास्केल भी IO मोनैड में ऐसा कर सकता है। आपको यह जानने की ज़रूरत नहीं है कि यह वास्तव में कैसे काम करता है, बस यह समझें कि यह प्रक्रियात्मक भाषा में कैसा दिखता है (यद्यपि यहां कुछ समस्याएं हैं)।

सबसे पहले आपको कुछ एल्गोरिदम की आवश्यकता है, जिसमें भाषा के साथ कुछ भी करने की ज़रूरत नहीं है। स्पष्ट तरीका सूची में संभावनाओं को जमा करना है, और परिणामी चरण-फ़ंक्शन का उपयोग मानचित्र के रूप में [0, 1 [आपके वांछित मानों से करें।

probsListLookup :: [(Double, a)] -> Double -> a 
probsListLookup pAssoc = look acc'dList 
where acc'dList = scanl1 (\(pa,_) (pn,x) -> (pa+pn,x)) pAssoc 
     look ((pa, x) : pas) rval 
     | rval < pa = look pas rval 
     | otherwise = x 

ध्यान दें कि यह न संभालती गलत निविष्टियों अच्छी तरह से (संभावनाओं 1 आदि को संक्षेप नहीं) और न ही यह कुशल है, प्रत्येक का अनुरोध मूल्य के लिए acc'dList के माध्यम से हे (n) पांव मार। हालांकि, अधिक महत्वपूर्ण है, ध्यान दें कि यह शुद्ध फ़ंक्शन है! जितना संभव हो सके शुद्ध कार्यों का उपयोग करना आम तौर पर एक अच्छा विचार है, और जब यह बिल्कुल जरूरी है तो केवल IO में जाएं। अब की तरह: हमें 0 और 1 के बीच एक Double मान प्राप्त करने की आवश्यकता है। आसान!

main = do 
    lookupVal <- randomRIO (0, 1) 
    print $ probsListLookup [(0.1, 1), (0.2, 2), (0.3, 4), (0.4, 5)] lookupVal 

कम से कम Int की तरह एक बुनियादी प्रकार की नहीं; आप वास्तव में पूरे संभाव्य वितरण पर "शुद्ध गणना" कर सकते हैं। ऐसा करना स्पष्ट रूप से बहुत बोझिल है, लेकिन हास्केल आपको specific monad एस (या in fact comonads) का उपयोग करने की अनुमति देता है ताकि इसे हास्केल आईओ (या किसी भी अशुद्ध भाषा में) में आसान बनाया जा सके लेकिन इनपुट/आउटपुट के खतरे के बिना।

आप इसे सुधार सकते हैं उदा। Data.Map के साथ।

2

मुझे नहीं लगता कि ये उत्तर पूरी तस्वीर हैं। मेरे सिमुलेशन के लिए मैं यादृच्छिक संख्या आलसी उत्पन्न करता हूं और उन्हें एक छोटे से (मेरे मैकबुक पर 1.1 एम) अंतरिक्ष पदचिह्न में सख्ती से चल रहा है।

शायद टिप्पणियां कि यादृच्छिक संख्या केवल आईओ मोनैड में मौजूद हो सकती है, वास्तव में यादृच्छिक संख्याओं को संदर्भित करती है लेकिन छद्म-यादृच्छिक संख्याओं के लिए जो मामला नहीं है और आमतौर पर परिणाम परिणाम पुन: उत्पन्न करने में सक्षम होना चाहते हैं। यहाँ एक उदाहरण है:

module Main (
    main 
) where 

import qualified Data.Vector.Unboxed as V 
import Data.Random.Source.PureMT 
import Data.Random 
import Control.Monad.State 

nItt :: Int 
nItt = 1000000000 

gridSize :: Int 
gridSize = 10 

testData :: Int -> V.Vector Double 
testData m = 
    V.fromList $ 
    evalState (replicateM m (sample (uniform (0 :: Double) 1.0))) 
    (pureMT 2) 

test = V.foldl (+) 0 (testData nItt) 

main = putStrLn $ show test 
6

वहाँ अच्छा जवाब यहाँ हैं, लेकिन मैं एक और अधिक पूरा जवाब बहुत बस हो और हास्केल में यादृच्छिक संख्या का उपयोग करें, एक तरीका है कि कोई मतलब होगा प्रोग्रामर अनिवार्य करने के लिए करने के लिए कैसे पता चलेगा महसूस किया।

import System.Random 
newRand = randomIO :: IO Int 

क्योंकि newRand प्रकार IO Int की है और नहीं Int, यह एक समारोह पैरामीटर के रूप में नहीं किया जा सकता:

पहले, आप एक यादृच्छिक बीज की जरूरत है। (यह हास्केल कार्यों को शुद्ध कार्यों के रूप में संरक्षित करता है जो हमेशा एक ही इनपुट पर एक ही परिणाम लौटाएंगे।)

हालांकि, हम जीएचसीआई में newRand दर्ज कर सकते हैं और प्रत्येक बार एक अद्वितीय यादृच्छिक बीज प्राप्त कर सकते हैं। यह केवल इसलिए संभव है क्योंकि newRand प्रकार IO है और यह मानक (अपरिवर्तनीय) चर या फ़ंक्शन नहीं है।

*Main> newRand 
-958036805781772734 

हम तो इसे कॉपी करके एक समारोह है कि हमारे लिए यादृच्छिक संख्या की एक सूची बनाता है में इस बीज मूल्य चिपका सकते हैं।तब हम निम्नलिखित समारोह को परिभाषित:

randomList :: Int -> [Double] 
randomList seed = randoms (mkStdGen seed) :: [Double] 

और दिए गए बीज में पेस्ट समारोह GHCi में चलाया जाता है जब:

*Main> take 10 randomList (-958036805781772734) 
[0.3173710114340238,0.9038063995872138,0.26811089937893495,0.2091390866782773,0.6351036926797997,0.7343088946561198,0.7964520135357062,0.7536521528870826,0.4695927477527754,0.2940288797844678] 

सूचना कैसे हम 1 (अनन्य) 0 से परिचित मूल्यों को प्राप्त। एक नया यादृच्छिक संख्या उत्पन्न करने के बजाय प्रत्येक पुनरावृत्ति जैसे हम एक अनिवार्य भाषा में करेंगे, हम समय से पहले यादृच्छिक संख्याओं की एक सूची उत्पन्न करते हैं और प्रत्येक क्रमिक पुनरावृत्ति पर सूची की पूंछ के सिर का उपयोग करते हैं। एक उदाहरण:

pythagCheck :: [Double] -> [Double] -> [Int] 
pythagCheck (x:xs) (y:ys) 
    | (a^2) + (b^2) == (c^2) = [a, b, c] 
    | otherwise    = pythagCheck xs ys 
    where aplusb = ceiling (x * 666) 
     a = ceiling (y * (fromIntegral (aplusb - 1))) 
     b = aplusb - a 
     c = 1000 - a - b 

समय से आगे दो सूचियां बनाकर और उन्हें पैरामीटर के रूप में में खिलाने के लिए खोज करने के लिए हमें की अनुमति देता है पायथागॉरियन ट्रिपल जहां एक + बी + सी = 1000 तुम होगा, निश्चित रूप से (एक और केवल!) , प्रत्येक सूची के लिए एक अलग यादृच्छिक बीज का उपयोग करना चाहते हैं:

*Main> newRand 
3869386208656114178 
*Main> newRand 
-5497233178519884041 
*Main> list1 = randomList 3869386208656114178 
*Main> list2 = randomList (-5497233178519884041) 
*Main> pythagCheck list1 list2 
[200,375,425]