ट्रैक
/
Julia
Julia
/
सिलेबस
/
यादृच्छिकता
या

यादृच्छिकता में Julia

2 अभ्यास

यादृच्छिकता के बारे में

बहुत से प्रोग्राम को वास्तविक दुनिया की घटनाओं का अनुकरण करने के लिए (दिखने में) रैंडम वैल्यू की ज़रूरत होती है।

आम और परिचित उदाहरणों में शामिल हैं:

  • सिक्का उछालना: ('H', 'T') में से एक रैंडम वैल्यू।
  • पासा फेंकना: 1 से 6 तक का एक रैंडम पूर्णांक।
  • ताश की गड्डी फेंटना: पत्तों की सूची का एक रैंडम क्रम।

कंप्यूटर से सचमुच रैंडम वैल्यू बनाना आश्चर्यजनक रूप से कठिन तकनीकी चुनौती है, इसलिए आप देख सकते हैं कि इन परिणामों को "स्यूडोरैंडम" कहा जाता है।

ज़रूरी: यह कॉन्सेप्ट क्रिप्टोग्राफिक रूप से सुरक्षित रैंडम संख्याओं को नहीं समझाता, जो कहीं अधिक कठिन चुनौती हैं।

हालाँकि, Julia की स्टैंडर्ड लाइब्रेरी में मौजूद Random मॉड्यूल जैसी अच्छी तरह बनाई गई लाइब्रेरी तेज़ और लचीली होती हैं, और मॉडलिंग, अनुकरण तथा गेम्स के ज़्यादातर उपयोगों के लिए काफी अच्छे परिणाम देती हैं।

Julia रैंडम सुविधाओं को कई जगहों पर बाँटती है:

  • Base में कुछ बुनियादी लेकिन बहुत काम के फंक्शन, जो हमेशा उपलब्ध रहते हैं।
  • Random मॉड्यूल में विकल्पों की अधिक विस्तृत श्रृंखला।
  • ऐसे पैकेजों में और भी विशेष सुविधाएँ, जिन्हें इस्तेमाल से पहले इंस्टॉल करना पड़ता है (और जो Exercism में उपलब्ध नहीं हैं)।

Random स्टैंडर्ड लाइब्रेरी का हिस्सा है और संभवतः पहले से इंस्टॉल होगा, लेकिन इसकी सामग्री को नेमस्पेस में लाने के लिए आपको अपने प्रोग्राम के शुरू में using Random जोड़ना होगा।

rand() फंक्शन

यह फंक्शन क्या करता है, यह आपके दिए गए आर्गुमेंट पर निर्भर करता है। विकल्प बहुत सारे हैं।

बिना किसी आर्गुमेंट के, यह 0 (सम्मिलित) से 1 के बीच एक दशमलव संख्या बनाता है। यह एक uniform वितरण है, जिसमें सभी वैल्यू के होने की संभावना समान होती है, जैसा कि नीचे "वितरणों के साथ काम करना" वाले भाग में बताया गया है।

एक पूर्णांक आर्गुमेंट उस लंबाई का वेक्टर बनाता है।

julia> rand()
0.10261774967264703

julia> rand(5)
5-element Vector{Float64}:
 0.24134501977563894
 0.5664193284851202
 0.9804412082089355
 0.6229551330613335
 0.47589221741904664

किसी और रेंज के लिए, बस परिणाम को उचित तरीके से शिफ्ट और स्केल कर लीजिए।

नीचे का उदाहरण घटाने के लिए broadcasting का उपयोग करता है, जिसे Vector Operations कॉन्सेप्ट में समझाया गया है। .- इस गणित को हर वेक्टर एलिमेंट पर लागू कर देता है।

# numbers between -1.0 and +1.0
julia> (rand(5) .- 0.5) * 2
5-element Vector{Float64}:
 -0.5303906759076336
  0.9635682226775855
 -0.048823697086981754
  0.465842804648374
  0.9880834344780736

केवल एक टाइप को आर्गुमेंट के रूप में देने पर, rand सीमाओं के लिए typemin और typemax का उपयोग करेगा। शायद आप यही नहीं चाहते!

रैंडम पूर्णांकों के लिए, हम एक रेंज दे सकते हैं, और साथ में वैकल्पिक रूप से यह भी कि कितनी वैल्यू बनानी हैं।

julia> rand(Int64)
-9159538335234594326 # not very useful

julia> rand(1:10, 5)
5-element Vector{Int64}:
 1
 1
 1
 4
 7

ऊपर दिए rand(1:10, 5) उदाहरण में ध्यान दीजिए कि (संयोग से) कुछ वैल्यू दोहराई गई हैं, क्योंकि हर बार चुनाव स्वतंत्र होता है। इसे "रिप्लेसमेंट के साथ सैंपलिंग" कहते हैं, जिस पर नीचे और विस्तार से चर्चा की गई है।

किसी रेंज में दशमलव वैल्यू के लिए, आपको आमतौर पर स्टेप साइज़ बताना पड़ेगा। वरना डिफॉल्ट स्टेप 1.0 रहेगा, जो शायद ही कभी काम आता है।

julia> rand(2.4:0.01:3.2, 4)
4-element Vector{Float64}:
 3.19
 2.53
 3.14
 3.13

वैकल्पिक रूप से, कोई ऐरे या टपल दीजिए, और rand एक रैंडम एलिमेंट लौटाएगा:

julia> rand([4, 9, 16, 25])
16

# coin flip
julia> rand(['H', 'T'])
'H': ASCII/Unicode U+0048 (category Lu: Letter, uppercase)

# mixed types in tuple
julia> rand( (1, 3.2, "name"), 2 )
2-element Vector{Any}:
 1
  "name"

रिप्लेसमेंट के साथ या बिना सैंपलिंग

कल्पना कीजिए कि हमारे पास एक थैला है जिसमें 3 लाल गेंदें और 4 हरी गेंदें हैं, और हम थैले से बेतरतीब ढंग से एक गेंद निकालते हैं। दूसरी गेंद निकालने के लिए दो तरीके हैं:

  1. पहली गेंद को थैले में वापस डाल दीजिए और दूसरी निकालने से पहले सब कुछ अच्छी तरह हिला दीजिए। अब गेंदों की संख्या पहले जितनी ही (7) है, और लाल तथा हरी का अनुपात भी वही रहता है।
  2. दूसरी गेंद निकालने से पहले पहली गेंद को मेज़ पर रख दीजिए। अब थैले में केवल 6 गेंदें हैं, और लाल तथा हरी का अनुपात पहली गेंद के रंग पर निर्भर करता है।

पहली स्थिति रिप्लेसमेंट के साथ है, दूसरी उसके बिना, और दोनों अलग-अलग परिणाम देती हैं।

Julia में रिप्लेसमेंट के बिना सैंपलिंग का अनुकरण करने के लिए कुछ विकल्प हैं।

सबसे आसान तरीका (और Exercism में तो यही एकमात्र विकल्प है), Random.shuffle() से एलिमेंट्स को रैंडम क्रम में लगाइए, फिर पहले n एलिमेंट्स इस्तेमाल कीजिए। छोटी समस्याओं के लिए यह ठीक है, लेकिन बड़े संग्रहों के लिए यह ठीक से काम नहीं कर सकता: shuffle को पूरा ऐरे बनाना पड़ता है, भले ही आपको उसका छोटा-सा हिस्सा ही चाहिए हो।

रिप्लेसमेंट के साथ सैंपलिंग "ठीक से" करने के लिए, StatsBase.jl पैकेज इंस्टॉल कीजिए। यह पूरी तरह से विकल्पों से भरा sample() फंक्शन देता है।

हम उम्मीद कर सकते हैं कि भविष्य में किसी रिलीज़ में ऐसी ही सुविधा Random में जोड़ दी जाएगी, ताकि यह स्टैंडर्ड लाइब्रेरी का हिस्सा बन जाए (इस दस्तावेज़ के कोड नमूने Julia 1.11 के साथ जाँचे गए हैं)।

वितरणों के साथ काम करना

अब तक हमने उन मामलों पर ध्यान दिया है जिनमें सभी परिणामों की संभावना समान होती है। जैसे, rand(1:100) से 1 से 100 तक कोई भी पूर्णांक समान संभावना से मिल सकता है।

वास्तविक दुनिया की बहुत सी स्थितियाँ इससे कहीं अधिक जटिल होती हैं। इसलिए सांख्यिकीविदों ने "वास्तविक दुनिया" के परिणामों को गणितीय रूप से बताने के लिए तरह-तरह के distributions बनाए हैं।

यूनिफॉर्म वितरण

ऊपर बताया गया rand() फंक्शन तब उपयोग होता है जब सभी प्रायिकताएँ समान हों। इसे [uniform][uniform-distribution] वितरण कहते हैं।

गाऊसी वितरण

इसे "सामान्य" वितरण या "घंटी के आकार" का वक्र भी कहते हैं, और यह मापी गई वैल्यू में अनिश्चितता बताने का एक बहुत आम तरीका है।

उदाहरण के लिए, मान लीजिए आपकी फैक्ट्री ने अभी 10,000 बोल्ट खरीदे हैं जो एक जैसे होने चाहिए। आप उन्हें संभालने के लिए फैक्ट्री का रोबोट सेट करना चाहते हैं, इसलिए आप 100 बोल्ट का नमूना तौलते हैं और पाते हैं कि उनका औसत (या mean) वज़न 4.731g है। इसका यह अर्थ निकलना बेहद असंभव है कि सबका वज़न ठीक 4.731g ही है। हो सकता है आप पाएँ कि वैल्यू 4.627 से 4.794g तक हैं, लेकिन 4.731g के आसपास इकट्ठा हैं।

यह Gaussian distribution है, जिसमें प्रायिकता माध्य पर सबसे ऊँची होती है और दोनों तरफ सममित रूप से घटती जाती है (इसीलिए "घंटी के आकार" का)। सॉफ़्टवेयर में इसका अनुकरण करने के लिए हमें वक्र की चौड़ाई बताने का कोई तरीका चाहिए (आमतौर पर, महँगे बोल्ट सस्ते बोल्टों की तुलना में माध्य के आसपास अधिक कसकर इकट्ठा होते हैं!)。

परंपरा के अनुसार, यह standard deviation से किया जाता है: छोटी वैल्यू तेज़ और संकरे वक्र के लिए, बड़ी वैल्यू नीचे और चौड़े वक्र के लिए। गणितज्ञों को यूनानी अक्षर बहुत पसंद हैं, इसलिए हम माध्य दिखाने के लिए μ ('mu') और स्टैंडर्ड डेविएशन दिखाने के लिए σ ('sigma') का उपयोग करते हैं। इसलिए, अगर आप पढ़ें कि "95% वैल्यू μ के 2σ के भीतर हैं" या "हिग्स बोसॉन 5-sigma विश्वास के साथ पाया गया है", तो ऐसी बातें स्टैंडर्ड डेविएशन से जुड़ी होती हैं।

इस बारे में और बातें Statistics कॉन्सेप्ट में होंगी।

randn() फंक्शन

"रैंडम नॉर्मल" का छोटा रूप, यह rand() के दशमलव वाले रूप जैसा ही है, बस इसमें वैल्यू माध्य 0 और स्टैंडर्ड डेविएशन 1 वाले गाऊसी वितरण के अनुसार बँटी होती हैं।

फिर से, आप randn के मूल आउटपुट को स्टैंडर्ड डेविएशन के लिए स्केल करना और माध्य के लिए खिसकाना चाह सकते हैं। नीचे का उदाहरण इसे माध्य 30 और स्टैंडर्ड डेविएशन 5 में बदलता है।

julia> raw = randn(5)
5-element Vector{Float64}:
  3.0762588867281475
  1.5101100620253902
 -0.5914858221637778
  0.684175554069735
 -0.8416433926114673

julia> raw * 5 .+ 30
5-element Vector{Float64}:
 45.38129443364074
 37.55055031012695
 27.04257088918111
 33.420877770348675
 25.791783036942665

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

Random मॉड्यूल

यह मॉड्यूल अगले स्तर की सुविधाएँ रखता है, जिन्हें Julia के डिफॉल्ट कॉन्फिगरेशन का आकार कम रखने के लिए Base से बाहर रखा गया है।

Random Base के rand और randn के साथ बदलाव करने वाले रूप भी जोड़ता है, rand! और randn!।

एक उपयोगी जोड़ randstring है, जो दी गई लंबाई की एक स्ट्रिंग बनाता है। डिफॉल्ट रूप से यह बड़े और छोटे अक्षरों के साथ 0 से 9 तक के अंकों का उपयोग करता है, लेकिन और विकल्प भी बताए जा सकते हैं।

julia> using Random

julia> randstring(20)
"BoJnIxrS33pJiWggXZQV"

इसके अलावा, एक bitrand फंक्शन है जो बताई गई लंबाई का रैंडम BitArray बनाता है।

julia> bitrand(5)
julia> bitrand(5)
5-element BitVector:
 1
 1
 0
 0
 1

शफल और परमुटेशन

किसी Vector के एलिमेंट्स को बेतरतीब ढंग से शफल करने के लिए हमारे पास shuffle है; साथ ही shuffle! भी है जो इनपुट वेक्टर को उसी जगह बदल देता है।

julia> v = ['A', '1', '2', 'J', 'Q', 'K'];

julia> shuffle(v)
6-element Vector{Char}:
 'K': ASCII/Unicode U+004B (category Lu: Letter, uppercase)
 '1': ASCII/Unicode U+0031 (category Nd: Number, decimal digit)
 'A': ASCII/Unicode U+0041 (category Lu: Letter, uppercase)
 'J': ASCII/Unicode U+004A (category Lu: Letter, uppercase)
 '2': ASCII/Unicode U+0032 (category Nd: Number, decimal digit)
 'Q': ASCII/Unicode U+0051 (category Lu: Letter, uppercase)

# shuffles are random:
julia> shuffle(v)
6-element Vector{Char}:
 '2': ASCII/Unicode U+0032 (category Nd: Number, decimal digit)
 'K': ASCII/Unicode U+004B (category Lu: Letter, uppercase)
 'A': ASCII/Unicode U+0041 (category Lu: Letter, uppercase)
 'Q': ASCII/Unicode U+0051 (category Lu: Letter, uppercase)
 'J': ASCII/Unicode U+004A (category Lu: Letter, uppercase)
 '1': ASCII/Unicode U+0031 (category Nd: Number, decimal digit)

कभी-कभी शफल किए गए इंडेक्स रखना काम आता है। इसके लिए randperm(n) इस्तेमाल कीजिए, जहाँ n अनुक्रम की लंबाई है।

julia> randperm(6)
6-element Vector{Int64}:
 6
 2
 4
 1
 3
 5

वास्तव में, ऊपर का उदाहरण shuffle(1:6) जैसे ही परिणाम देता है।

इससे जुड़े फंक्शनों में randsubseq है, जो तय प्रायिकता के साथ एलिमेंट्स निकालता है, और randcycle है, जो चक्रीय परमुटेशन बनाता है। इनके लिए कुछ खास जानकारी चाहिए, इसलिए अगर आपकी दिलचस्पी हो तो डॉक्युमेंटेशन देख लीजिए।

सीड और एल्गोरिदम

कई रैंडम नंबर जनरेटर (RNG) एल्गोरिदम मानक रूप से Random में मौजूद हैं, और उचित गणितीय कौशल रखने वाला कोई भी और जोड़ सकता है। ऐसी चीज़ें इस दस्तावेज़ के दायरे से कहीं बाहर हैं!

RNG के साथ काम करने का एक और आम कारण seed बताना है, जिससे "रैंडम" आउटपुट का क्रम एक रन से अगले रन तक दोहराने योग्य बन जाता है।

ऐसा दोहराव प्रोडक्शन कोड में उचित नहीं है, लेकिन यह टेस्टिंग और डीबगिंग में मदद कर सकता है।

अन्य पैकेज

Exercism के बाहर, रैंडमनेस, प्रायिकता और सांख्यिकी से जुड़े कई इंस्टॉल करने योग्य पैकेज हैं। थोड़ी और जानकारी के लिए Statistics कॉन्सेप्ट देखिए।

StatsBase.jl पैकेज

StatsBase के ज़्यादातर फंक्शन काफी तकनीकी हैं और इस दस्तावेज़ से जुड़े नहीं हैं।

अपवाद StatsBase.sample है, जो रिप्लेसमेंट के साथ या बिना सैंपलिंग का पूरा कार्यान्वयन देता है (ऊपर का भाग देखिए)। भारित (गैर-यूनिफॉर्म) सैंपलिंग के लिए भी फंक्शन हैं।

Distributions.jl पैकेज

uniform और normal (या गाऊसी) वितरण ऊपर बताए गए हैं।

Random मॉड्यूल में randexp भी है, जो Exponential Distribution से सैंपल करता है, जो (बहुत आम) Poisson Distribution से जुड़ा है।

बहुत अधिक विकल्पों के लिए Distributions.jl पैकेज है, उन लोगों के लिए जिनकी सांख्यिकी में उचित पृष्ठभूमि है।

GitHub के ज़रिए संपादित करें यह लिंक नई विंडो या टैब में खुलता है।

यादृच्छिकता सीखिए

अभ्यास लॉक है

यादृच्छिकता पर अभ्यास करने के लिए 1 और अभ्यास अनलॉक कीजिए