Random Numbers
Julia'da rastgele sayı üretimi varsayılan olarak Xoshiro256++ algoritmasını kullanır ve her Task için bir durum içerir. Diğer RNG türleri, AbstractRNG türünden miras alarak entegre edilebilir; bu türler daha sonra birden fazla rastgele sayı akışı elde etmek için kullanılabilir.
Random paketinden dışa aktarılan PRNG'ler (sahte rastgele sayı üreteçleri) şunlardır:
TaskLocalRNG: şu anda aktif olan Görev-eşel (Task-local) akışının kullanımını temsil eden bir token, ana görevden belirleyici bir şekilde tohumlanmış veya program başlangıcındaRandomDevice(sistem rastgeleliği ile) tarafından tohumlanmıştır.Xoshiro: Xoshiro256++ algoritmasını kullanarak küçük bir durum vektörü ile yüksek performanslı ve yüksek kaliteli rastgele sayı akışları üretir.RandomDevice: OS tarafından sağlanan entropi için. Bu, kriptografik olarak güvenli rastgele sayılar (CS(P)RNG) için kullanılabilir.MersenneTwister: eski Julia sürümlerinde varsayılan olan, alternatif bir yüksek kaliteli PRNG'dir ve oldukça hızlıdır, ancak durum vektörünü depolamak ve rastgele bir dizi oluşturmak için çok daha fazla alan gerektirir.
Çoğu rastgele üretimle ilgili fonksiyon, ilk argüman olarak isteğe bağlı bir AbstractRNG nesnesi alır. Bazıları ayrıca rastgele değerler dizileri oluşturmak için boyut spesifikasyonları dims... (bir demet olarak da verilebilir) alır. Çok iş parçacıklı bir programda, genellikle iş parçacıkları veya görevler için farklı RNG nesneleri kullanmalısınız, böylece iş parçacığı güvenliğini sağlarsınız. Ancak, varsayılan RNG, Julia 1.3 itibarıyla iş parçacığı güvenlidir (1.6 sürümüne kadar iş parçacığı başına RNG kullanarak ve sonrasında görev başına RNG kullanarak).
Verilen RNG'ler aşağıdaki türlerde uniform rastgele sayılar üretebilir: Float16, Float32, Float64, BigFloat, Bool, Int8, UInt8, Int16, UInt16, Int32, UInt32, Int64, UInt64, Int128, UInt128, BigInt (veya bu türlerin karmaşık sayıları). Rastgele kayan nokta sayıları $[0, 1)$ aralığında uniform olarak üretilir. BigInt sınırsız tam sayıları temsil ettiğinden, aralığın belirtilmesi gerekir (örneğin rand(big.(1:6))).
Ayrıca, bazı AbstractFloat ve Complex türleri için normal ve üstel dağılımlar uygulanmıştır, ayrıntılar için randn ve randexp'ya bakın.
Rastgele sayılar üretmek için diğer dağılımlardan, Distributions.jl paketine bakın.
Rastgele sayıların üretilme şekli bir uygulama detayı olarak kabul edildiğinden, hata düzeltmeleri ve hız iyileştirmeleri, bir sürüm değişikliğinden sonra üretilen sayı akışını değiştirebilir. Birim testleri sırasında belirli bir tohum veya üretilen sayı akışına güvenmek bu nedenle önerilmez - bunun yerine söz konusu yöntemlerin özelliklerini test etmeyi düşünün.
Random numbers module
Random.Random — ModuleRastgeleRastgele sayılar üretme desteği. rand, randn, AbstractRNG, MersenneTwister ve RandomDevice sağlar.
Random generation functions
Base.rand — Functionrand([rng=default_rng()], [S], [dims...])S tarafından belirtilen değerler kümesinden rastgele bir öğe veya rastgele öğeler dizisi seçin; S şunlar olabilir:
indekslenebilir bir koleksiyon (örneğin
1:9veya('x', "y", :z))bir
AbstractDictveyaAbstractSetnesnesibir dize (karakterler koleksiyonu olarak kabul edilir), veya
aşağıdaki listeden bir tür, belirtilen değerler kümesine karşılık gelir
- somut tam sayı türleri
typemin(S):typemax(S)aralığından örnek alır (desteklenmeyenBigInthariç) - somut kayan nokta türleri
[0, 1)aralığından örnek alır Complex{T}türündeki somut karmaşık türler,Törneklenebilir bir türse,T'ye karşılık gelen değerler kümesinden bağımsız olarak gerçek ve hayali bileşenlerini alır, ancakTörneklenebilir değilse desteklenmez.- tüm
<:AbstractChartürleri geçerli Unicode skalarları kümesinden örnek alır - kullanıcı tanımlı bir tür ve değerler kümesi; uygulama rehberi için lütfen Random API'ye Bağlanma bölümüne bakın
- bilinen boyutta bir demet türü ve
S'nin her parametresi kendisi örneklenebilir bir türse;Stüründe bir değer döndürün.Tuple{Vararg{T}}(bilinmeyen boyut) veTuple{1:2}(bir değerle parametrelenmiş) gibi demet türlerinin desteklenmediğini unutmayın. Pairtürü, örneğinPair{X, Y}böylecerandiçinXveYtanımlıysa, rastgele çiftler üretilir.
- somut tam sayı türleri
S varsayılan olarak Float64 olarak ayarlanmıştır. Opsiyonel rng dışında yalnızca bir argüman geçirildiğinde ve bu bir Tuple olduğunda, değerler koleksiyonu (S) olarak yorumlanır ve dims olarak değil.
Normal dağılımlı sayılar için randn ve yerinde eşdeğerleri için rand! ve randn! bölümlerine de bakın.
S'nin bir demet olarak desteklenmesi en az Julia 1.1 gerektirir.
S'nin bir Tuple türü olarak desteklenmesi en az Julia 1.11 gerektirir.
Örnekler
julia> rand(Int, 2)
2-element Array{Int64,1}:
1339893410598768192
1575814717733606317
julia> using Random
julia> rand(Xoshiro(0), Dict(1=>2, 3=>4))
3 => 4
julia> rand((2, 3))
3
julia> rand(Float64, (2, 3))
2×3 Array{Float64,2}:
0.999717 0.0143835 0.540787
0.696556 0.783855 0.938235rand(rng, s::Union{AbstractDict,AbstractSet})'nin karmaşıklığı s'nin uzunluğuna bağlı olarak lineerdir, eğer sabit karmaşıklıkta optimize edilmiş bir yöntem mevcut değilse, bu durum Dict, Set ve yoğun BitSet'ler için geçerlidir. Birkaç çağrıdan fazlası için, bunun yerine rand(rng, collect(s)) kullanın veya uygun olduğunda rand(rng, Dict(s)) veya rand(rng, Set(s)) kullanın.
Random.rand! — Functionrand!([rng=default_rng()], A, [S=eltype(A)])Diziyi A'yı rastgele değerlerle doldurur. Eğer S belirtilmişse (S bir tür veya bir koleksiyon olabilir, ayrıntılar için bkz. rand), değerler S'den rastgele seçilir. Bu, copyto!(A, rand(rng, S, size(A))) ile eşdeğerdir, ancak yeni bir dizi ayırmadan.
Örnekler
julia> rand!(Xoshiro(123), zeros(5))
5-element Vector{Float64}:
0.521213795535383
0.5868067574533484
0.8908786980927811
0.19090669902576285
0.5256623915420473Random.bitrand — Functionbitrand([rng=default_rng()], [dims...])Rastgele boolean değerlerden oluşan bir BitArray oluşturur.
Örnekler
julia> bitrand(Xoshiro(123), 10)
10-element BitVector:
0
1
0
1
0
1
0
0
1
1Base.randn — Functionrandn([rng=default_rng()], [T=Float64], [dims...])0 ortalama ve 1 standart sapmaya sahip T türünde normal dağılımlı rastgele bir sayı üretir. Opsiyonel dims argüman(lar)ı verildiğinde, bu türden sayıların dims boyutunda bir dizisini üretir. Julia'nın standart kütüphanesi, rand uygulayan herhangi bir kayan nokta türü için randn'ı destekler; örneğin, Base türleri Float16, Float32, Float64 (varsayılan) ve BigFloat ile birlikte bunların Complex karşıtları.
(T karmaşık olduğunda, değerler, varyansı 1 olan dairesel simetrik karmaşık normal dağılımdan çekilir; bu, reel ve sanal kısımların sıfır ortalama ve 1/2 varyansa sahip bağımsız normal dağılıma sahip olduğu anlamına gelir).
Yerinde işlem yapmak için randn! ile de bakabilirsiniz.
Örnekler
Tek bir rastgele sayı üretme (varsayılan Float64 türü ile):
julia> randn()
-0.942481877315864Normal rastgele sayıların bir matrisini üretme (varsayılan Float64 türü ile):
julia> randn(2,3)
2×3 Matrix{Float64}:
1.18786 -0.678616 1.49463
-0.342792 -0.134299 -1.45005Kullanıcı tanımlı bir tohum ile rastgele sayı üreteci rng'yi ayarlama (tekrarlanabilir sayılar için) ve bunu kullanarak rastgele bir Float32 sayısı veya ComplexF32 rastgele sayılardan oluşan bir matris üretme:
julia> using Random
julia> rng = Xoshiro(123);
julia> randn(rng, Float32)
-0.6457307f0
julia> randn(rng, ComplexF32, (2, 3))
2×3 Matrix{ComplexF32}:
-1.03467-1.14806im 0.693657+0.056538im 0.291442+0.419454im
-0.153912+0.34807im 1.0954-0.948661im -0.543347-0.0538589imRandom.randn! — Functionrandn!([rng=default_rng()], A::AbstractArray) -> ADiziyi A'yı normal dağılıma sahip (ortalama 0, standart sapma 1) rastgele sayılarla doldurur. Ayrıca rand fonksiyonuna da bakın.
Örnekler
julia> randn!(Xoshiro(123), zeros(5))
5-element Vector{Float64}:
-0.6457306721039767
-1.4632513788889214
-1.6236037455860806
-0.21766510678354617
0.4922456865251828Random.randexp — Functionrandexp([rng=default_rng()], [T=Float64], [dims...])1 ölçekli üstel dağılıma göre T türünde rastgele bir sayı üretir. İsteğe bağlı olarak, bu türde rastgele sayıların bir dizisini de üretebilir. Base modülü şu türler için bir uygulama sağlar: Float16, Float32 ve Float64 (varsayılan).
Örnekler
julia> rng = Xoshiro(123);
julia> randexp(rng, Float32)
1.1757717f0
julia> randexp(rng, 3, 3)
3×3 Matrix{Float64}:
1.37766 0.456653 0.236418
3.40007 0.229917 0.0684921
0.48096 0.577481 0.71835Random.randexp! — Functionrandexp!([rng=default_rng()], A::AbstractArray) -> ADiziyi A'yı üstel dağılıma (ölçek 1 ile) göre rastgele sayılarla doldurun.
Örnekler
julia> randexp!(Xoshiro(123), zeros(5))
5-element Vector{Float64}:
1.1757716836348473
1.758884569451514
1.0083623637301151
0.3510644315565272
0.6348266443720407Random.randstring — Functionrandstring([rng=default_rng()], [chars], [len=8])len uzunluğunda, varsayılan olarak büyük ve küçük harfler ile 0-9 rakamlarından oluşan chars karakter setinden oluşan rastgele bir dize oluşturur. İsteğe bağlı rng argümanı, bir rastgele sayı üreteci belirtir, bkz. Rastgele Sayılar.
Örnekler
julia> Random.seed!(3); randstring()
"Lxz5hUwn"
julia> randstring(Xoshiro(3), 'a':'z', 6)
"iyzcsm"
julia> randstring("ACGT")
"TGCTCCTC"chars, rand karakterleri rastgele seçebiliyorsa, Char veya UInt8 türünde herhangi bir karakter koleksiyonu olabilir (daha verimli).
Subsequences, permutations and shuffling
Random.randsubseq — Functionrandsubseq([rng=default_rng(),] A, p) -> VectorVerilen dizi A'nın rastgele bir alt dizisini içeren bir vektör döndürür; burada A'nın her bir elemanı bağımsız olasılık p ile (sırasıyla) dahil edilir. (Karmaşıklık p*length(A) cinsindendir, bu nedenle bu fonksiyon p küçük ve A büyük olsa bile etkilidir.) Teknik olarak, bu süreç A'nın "Bernoulli örneklemesi" olarak bilinir.
Örnekler
julia> randsubseq(Xoshiro(123), 1:8, 0.3)
2-element Vector{Int64}:
4
7Random.randsubseq! — Functionrandsubseq!([rng=default_rng(),] S, A, p)randsubseq gibi, ancak sonuçlar S içinde saklanır (gerekirse boyutu değiştirilir).
Örnekler
julia> S = Int64[];
julia> randsubseq!(Xoshiro(123), S, 1:8, 0.3)
2-element Vector{Int64}:
4
7
julia> S
2-element Vector{Int64}:
4
7Random.randperm — Functionrandperm([rng=default_rng(),] n::Integer)n uzunluğunda rastgele bir permütasyon oluşturur. İsteğe bağlı rng argümanı bir rastgele sayı üreteci belirtir (bkz. Rastgele Sayılar). Sonucun eleman tipi, n'nin tipiyle aynıdır.
Rastgele bir vektörü permüte etmek için shuffle veya shuffle! fonksiyonlarına bakın.
Julia 1.1'de randperm, eltype(v) == typeof(n) olan bir vektör v dönerken, Julia 1.0'da eltype(v) == Int döner.
Örnekler
julia> randperm(Xoshiro(123), 4)
4-element Vector{Int64}:
1
4
2
3Random.randperm! — Functionrandperm!([rng=default_rng(),] A::Array{<:Integer})A içinde length(A) uzunluğunda rastgele bir permütasyon oluşturur. İsteğe bağlı rng argümanı, bir rastgele sayı üreteci belirtir (bkz. Rastgele Sayılar). Rastgele bir vektörü permüte etmek için shuffle veya shuffle! fonksiyonlarına bakın.
Örnekler
julia> randperm!(Xoshiro(123), Vector{Int}(undef, 4))
4-element Vector{Int64}:
1
4
2
3Random.randcycle — Functionrandcycle([rng=default_rng(),] n::Integer)n uzunluğunda rastgele bir döngüsel permütasyon oluşturur. İsteğe bağlı rng argümanı, Rastgele Sayılar bölümünde belirtilen bir rastgele sayı üreteciyi tanımlar. Sonucun eleman tipi, n'nin tipiyle aynıdır.
Burada "döngüsel permütasyon", tüm elemanların tek bir döngü içinde yer aldığı anlamına gelir. Eğer n > 0 ise, $(n-1)!$ olası döngüsel permütasyon vardır ve bunlar eşit olarak örneklenir. Eğer n == 0 ise, randcycle boş bir vektör döner.
randcycle! bu işlevin yerinde bir varyantıdır.
Julia 1.1 ve üzeri sürümlerde, randcycle eltype(v) == typeof(n) olan bir vektör v dönerken, Julia 1.0'da eltype(v) == Int'dir.
Örnekler
julia> randcycle(Xoshiro(123), 6)
6-element Vector{Int64}:
5
4
2
6
3
1Random.randcycle! — Functionrandcycle!([rng=default_rng(),] A::Array{<:Integer})A içinde uzunluğu n = length(A) olan rastgele bir döngüsel permütasyon oluşturur. İsteğe bağlı rng argümanı, Rastgele Sayılar bölümünde belirtilen bir rastgele sayı üreteciyi tanımlar.
Burada "döngüsel permütasyon", tüm elemanların tek bir döngü içinde yer aldığı anlamına gelir. Eğer A boş değilse (n > 0), $(n-1)!$ olası döngüsel permütasyon vardır ve bunlar eşit olarak örneklenir. Eğer A boşsa, randcycle! onu değiştirmeden bırakır.
randcycle bu işlevin yeni bir vektör ayıran bir varyantıdır.
Örnekler
julia> randcycle!(Xoshiro(123), Vector{Int}(undef, 6))
6-element Vector{Int64}:
5
4
2
6
3
1Random.shuffle — Functionshuffle([rng=default_rng(),] v::AbstractArray)v'nin rastgele bir şekilde permütasyona uğramış bir kopyasını döndürür. İsteğe bağlı rng argümanı, bir rastgele sayı üreteci belirtir (bkz. Rastgele Sayılar). v'yi yerinde permütasyona uğratmak için shuffle! fonksiyonuna bakın. Rastgele permütasyona uğramış indeksler elde etmek için randperm fonksiyonuna bakın.
Örnekler
julia> shuffle(Xoshiro(123), Vector(1:10))
10-element Vector{Int64}:
5
4
2
3
6
10
8
1
9
7Random.shuffle! — Functionshuffle!([rng=default_rng(),] v::AbstractArray)Yerinde versiyonu shuffle: v'yi yerinde rastgele permüte eder, isteğe bağlı olarak rastgele sayı üreteci rng sağlanabilir.
Örnekler
julia> shuffle!(Xoshiro(123), Vector(1:10))
10-element Vector{Int64}:
5
4
2
3
6
10
8
1
9
7Generators (creation and seeding)
Random.default_rng — FunctionRandom.default_rng() -> rngVarsayılan küresel rastgele sayı üreteci (RNG) döndürülür; bu, açık bir RNG sağlanmadığında rand ile ilgili işlevler tarafından kullanılır.
Random modülü yüklendiğinde, varsayılan RNG rastgele bir şekilde tohumlanır; bu, her yeni julia oturumu başlatıldığında, rand()'ın ilk çağrısının farklı bir sonuç üretmesi anlamına gelir, aksi takdirde seed!(seed) çağrılmadıkça.
Thread güvenlidir: farklı thread'ler, default_rng() üzerinde rand ile ilgili işlevleri güvenli bir şekilde eşzamanlı olarak çağırabilir, örneğin rand(default_rng()).
Varsayılan RNG'nin türü bir uygulama ayrıntısıdır. Farklı Julia sürümleri arasında, varsayılan RNG'nin her zaman aynı türde olmasını veya belirli bir tohum için aynı rastgele sayı akışını üretmesini beklememelisiniz.
Bu işlev Julia 1.3'te tanıtılmıştır.
Random.seed! — Functionseed!([rng=default_rng()], seed) -> rng
seed!([rng=default_rng()]) -> rngRastgele sayı üreteciyi yeniden tohumlayın: rng, yalnızca bir seed sağlandığında yeniden üretilebilir bir sayı dizisi verecektir. Bazı RNG'ler, RandomDevice gibi, bir tohum kabul etmez. seed! çağrısından sonra, rng, aynı tohumla başlatılmış yeni bir nesne ile eşdeğerdir. Kabul edilen tohumların türleri rng türüne bağlıdır, ancak genel olarak, tam sayı tohumları çalışmalıdır.
Eğer rng belirtilmemişse, paylaşılan görev yerel üretecin durumunu tohumlamayı varsayılan olarak alır.
Örnekler
julia> Random.seed!(1234);
julia> x1 = rand(2)
2-element Vector{Float64}:
0.32597672886359486
0.5490511363155669
julia> Random.seed!(1234);
julia> x2 = rand(2)
2-element Vector{Float64}:
0.32597672886359486
0.5490511363155669
julia> x1 == x2
true
julia> rng = Xoshiro(1234); rand(rng, 2) == x1
true
julia> Xoshiro(1) == Random.seed!(rng, 1)
true
julia> rand(Random.seed!(rng), Bool) # yeniden üretilebilir değil
true
julia> rand(Random.seed!(rng), Bool) # yeniden üretilebilir değil
false
julia> rand(Xoshiro(), Bool) # yeniden üretilebilir değil
trueRandom.AbstractRNG — TypeAbstractRNGMersenneTwister ve RandomDevice gibi rastgele sayı üreteçleri için süpertip.
Random.TaskLocalRNG — TypeTaskLocalRNGTaskLocalRNG, görevi için yerel olan bir duruma sahiptir, ipliği için değil. Görev oluşturulurken, ana görevin durumundan tohumlanır, ancak ana görevin RNG'sinin durumunu ilerletmeden.
Bir avantaj olarak, TaskLocalRNG oldukça hızlıdır ve yarış koşulları hariç, zamanlayıcı kararlarından bağımsız olarak yeniden üretilebilir çok iş parçacıklı simülasyonlara izin verir. Görev oluşturma kararlarında iş parçacığı sayısı kullanılmadığı sürece, simülasyon sonuçları mevcut iş parçacığı / CPU sayısından da bağımsızdır. Rastgele akış, donanım ayrıntılarına bağlı olmamalıdır, sonlandırma ve muhtemelen kelime boyutu hariç.
current_task() tarafından döndürülen görevden başka bir görevin RNG'sini kullanmak veya tohumlamak tanımsız bir davranıştır: çoğu zaman çalışır ve bazen sessizce başarısız olabilir.
TaskLocalRNG()'yi seed! ile tohumlarken, geçirilen tohum, varsa, herhangi bir tam sayı olabilir.
Negatif bir tam sayı tohumu ile TaskLocalRNG()'yi tohumlamak en az Julia 1.11 gerektirir.
Görev oluşturma, Julia 1.10 itibarıyla ana görevin RNG durumunu ilerletmez.
Random.Xoshiro — TypeXoshiro(seed::Union{Integer, AbstractString})
Xoshiro()Xoshiro256++ hızlı bir sahte rastgele sayı üreteci olup, David Blackman ve Sebastiano Vigna tarafından "Scrambled Linear Pseudorandom Number Generators", ACM Trans. Math. Softw., 2021'de tanımlanmıştır. Referans uygulaması https://prng.di.unimi.it adresinde mevcuttur.
Yüksek hızın yanı sıra, Xoshiro'nun küçük bir bellek ayak izi vardır, bu da onu birçok farklı rastgele durumun uzun süre tutulması gereken uygulamalar için uygun hale getirir.
Julia'nın Xoshiro uygulaması, ana kaynaktan yeni sanal PRNG'ler tohumlayan bir toplu üretim moduna sahiptir ve SIMD kullanarak paralel olarak üretim yapar (yani, toplu akış birden fazla iç içe geçmiş xoshiro örneğinden oluşur). Sanal PRNG'ler, toplu isteğin karşılandığı anda atılır (ve yığın tahsisatına neden olmamalıdır).
Eğer bir tohum sağlanmazsa, rastgele üretilmiş bir tohum oluşturulur (sistemden entropi kullanılarak). Zaten mevcut bir Xoshiro nesnesini yeniden tohumlamak için seed! fonksiyonuna bakın.
Negatif bir tamsayı tohumunun geçmesi en az Julia 1.11 gerektirir.
Örnekler
julia> using Random
julia> rng = Xoshiro(1234);
julia> x1 = rand(rng, 2)
2-element Vector{Float64}:
0.32597672886359486
0.5490511363155669
julia> rng = Xoshiro(1234);
julia> x2 = rand(rng, 2)
2-element Vector{Float64}:
0.32597672886359486
0.5490511363155669
julia> x1 == x2
trueRandom.MersenneTwister — TypeMersenneTwister(seed)
MersenneTwister()Bir MersenneTwister RNG nesnesi oluşturun. Farklı RNG nesneleri kendi tohumlarına sahip olabilir, bu da farklı rastgele sayı akışları oluşturmak için yararlı olabilir. seed bir tamsayı, bir dize veya UInt32 tamsayılarının bir vektörü olabilir. Hiçbir tohum sağlanmazsa, rastgele üretilmiş bir tohum oluşturulur (sistemden entropi kullanılarak). Zaten mevcut bir MersenneTwister nesnesinin yeniden tohumlanması için seed! fonksiyonuna bakın.
Negatif bir tamsayı tohumunun geçmesi en az Julia 1.11 gerektirir.
Örnekler
julia> rng = MersenneTwister(123);
julia> x1 = rand(rng, 2)
2-element Vector{Float64}:
0.37453777969575874
0.8735343642013971
julia> x2 = rand(MersenneTwister(123), 2)
2-element Vector{Float64}:
0.37453777969575874
0.8735343642013971
julia> x1 == x2
trueRandom.RandomDevice — TypeRandomDevice()Bir RandomDevice RNG nesnesi oluşturur. İki böyle nesne her zaman farklı rastgele sayı akışları üretecektir. Entropi işletim sisteminden elde edilir.
Hooking into the Random API
Random işlevselliğini genişletmenin iki çoğunlukla ortogonal yolu vardır:
- özel türlerin rastgele değerlerini oluşturma
- yeni jeneratörler oluşturma
The API for 1) is quite functional, but is relatively recent so it may still have to evolve in subsequent releases of the Random module. For example, it's typically sufficient to implement one rand method in order to have all other usual methods work automatically.
The API for 2) is still rudimentary, and may require more work than strictly necessary from the implementor, in order to support usual types of generated values.
Generating random values of custom types
Rastgele değerler üretmek bazı dağılımlar için çeşitli ticaret dengeleri içerebilir. Önceden hesaplanmış değerler, örneğin, ayrık dağılımlar için bir alias table veya tek değişkenli dağılımlar için “squeezing” functions gibi değerler, örnekleme hızını önemli ölçüde artırabilir. Önceden ne kadar bilginin hesaplanması gerektiği, bir dağılımdan çekmeyi planladığımız değerlerin sayısına bağlı olabilir. Ayrıca, bazı rastgele sayı üreteçleri, çeşitli algoritmaların faydalanmak isteyebileceği belirli özelliklere sahip olabilir.
Random modülü, bu sorunları ele alabilecek rastgele değerler elde etmek için özelleştirilebilir bir çerçeve tanımlar. rand'in her çağrısı, yukarıdaki ticaret dengeleri göz önünde bulundurularak özelleştirilebilen bir örnekleyici oluşturur; bu, Sampler'a yöntemler ekleyerek yapılır ve bu yöntemler, rastgele sayı üreteci, dağılımı tanımlayan nesne ve tekrar sayısı için bir öneri üzerinde dağıtım yapabilir. Şu anda, sonuncusu için Val{1} (tek bir örnek için) ve Val{Inf} (keyfi bir sayı için) kullanılmakta olup, Random.Repetition her ikisi için de bir takma addır.
Sampler tarafından döndürülen nesne, rastgele değerleri üretmek için kullanılır. Örnekleme yapılabilen bir değer X için rastgele üretim arayüzünü uygularken, uygulayıcı aşağıdaki yöntemi tanımlamalıdır.
rand(rng, sampler)Sampler(rng, X, repetition) tarafından döndürülen belirli sampler için.
Samplerlere rand(rng, sampler) uygulayan rastgele değerler olarak tanımlanabilir, ancak çoğu uygulama için aşağıdaki önceden tanımlanmış samplerlere yeterli olabilir:
SamplerType{T}()türündenT'den örnekler çizen örnekleyiciler uygulamak için kullanılabilir (örneğin,rand(Int)). Bu, türler içinSamplertarafından döndürülen varsayılan değerdir.SamplerTrivial(self)basit bir sarmalayıcıdır ve[]ile erişilebilir. Önceden hesaplanmış bilgiye ihtiyaç duyulmadığında (örneğin,rand(1:3)) önerilen örnekleyicidir ve değerler içinSamplertarafından döndürülen varsayılandır.SamplerSimple(self, data)ayrıca,Sampler'ın özel bir yönteminde hesaplanması gereken rastgele önceden hesaplanmış değerleri depolamak için kullanılabilecek ekdataalanını içerir.
Herhangi birinin örneklerini sağlıyoruz. Burada algoritma seçimimizin RNG'den bağımsız olduğunu varsayıyoruz, bu nedenle imzalarımızda AbstractRNG kullanıyoruz.
Random.Sampler — TypeSampler(rng, x, repetition = Val(Inf))rng için x'den rastgele değerler üretmek için kullanılabilecek bir örnekleyici nesnesi döndürür.
sp = Sampler(rng, x, repetition) olduğunda, rastgele değerler çekmek için rand(rng, sp) kullanılacak ve buna göre tanımlanmalıdır.
repetition Val(1) veya Val(Inf) olabilir ve uygulanabilir olduğunda ön hesaplama miktarını belirlemek için bir öneri olarak kullanılmalıdır.
Random.SamplerType ve Random.SamplerTrivial varsayılan geri dönüşlerdir tipler ve değerler için, sırasıyla. Random.SamplerSimple yalnızca bu amaç için ekstra türler tanımlamadan önceden hesaplanmış değerleri saklamak için kullanılabilir.
Random.SamplerType — TypeSamplerType{T}()Türler için bir örnekleyici, başka hiçbir bilgi içermiyor. Türlerle çağrıldığında Sampler için varsayılan geri dönüş.
Random.SamplerTrivial — TypeSamplerTrivial(x)Verilen x değerini saran bir örnekleyici oluşturur. Bu, değerler için varsayılan geri dönüş yoludur. Bu örnekleyicinin eltype'ı eltype(x) ile eşittir.
Tavsiye edilen kullanım durumu, önceden hesaplanmış veriler olmadan değerlerden örneklemektir.
Random.SamplerSimple — TypeSamplerSimple(x, data)Verilen değer x ve data ile sarmalayan bir örnekleyici oluşturun. Bu örnekleyicinin eltype'ı eltype(x) ile eşittir.
Tavsiye edilen kullanım durumu, önceden hesaplanmış verilerle değerlerden örneklemektir.
Önceden hesaplamayı değerleri gerçekten üretmekten ayırmak, API'nin bir parçasıdır ve kullanıcıya da açıktır. Örneğin, rand(rng, 1:20)'nin bir döngüde tekrar tekrar çağrılması gerektiğini varsayalım: bu ayrımın avantajlarından yararlanmanın yolu aşağıdaki gibidir:
rng = Xoshiro()
sp = Random.Sampler(rng, 1:20) # or Random.Sampler(Xoshiro, 1:20)
for x in X
n = rand(rng, sp) # similar to n = rand(rng, 1:20)
# use n
endBu, standart kütüphanede de kullanılan mekanizmadır; örneğin, rastgele dizi oluşturmanın varsayılan uygulaması (örneğin rand(1:20, 10) gibi).
Generating values from a type
Verilen bir T türü için, rand(T) tanımlıysa, T türünde bir nesne üretileceği varsayılmaktadır. SamplerType, türler için varsayılan örnekleyicidir. T türündeki değerlerin rastgele üretilmesini tanımlamak için, rand(rng::AbstractRNG, ::Random.SamplerType{T}) yöntemi tanımlanmalı ve rand(rng, T)'nin beklediği değerleri döndürmelidir.
Aşağıdaki örneği ele alalım: 1 ile n arasında numaralandırılmış, n sayıda kenarı olan bir Die türü uyguluyoruz. rand(Die)'nin en az 4 ve en fazla 20 kenara sahip rastgele bir Die üretmesini istiyoruz.
struct Die
nsides::Int # number of sides
end
Random.rand(rng::AbstractRNG, ::Random.SamplerType{Die}) = Die(rand(rng, 4:20))
# output
Die için skalar ve dizi yöntemleri artık beklenildiği gibi çalışıyor:
julia> rand(Die)
Die(5)
julia> rand(Xoshiro(0), Die)
Die(10)
julia> rand(Die, 3)
3-element Vector{Die}:
Die(9)
Die(15)
Die(14)
julia> a = Vector{Die}(undef, 3); rand!(a)
3-element Vector{Die}:
Die(19)
Die(7)
Die(17)A simple sampler without pre-computed data
Burada bir koleksiyon için bir örnekleyici tanımlıyoruz. Önceden hesaplanmış verilere ihtiyaç yoksa, aslında değerler için varsayılan geri dönüş olan SamplerTrivial örnekleyicisi ile uygulanabilir.
Rastgele nesne üretimini S türündeki nesnelerden tanımlamak için aşağıdaki yöntem tanımlanmalıdır: rand(rng::AbstractRNG, sp::Random.SamplerTrivial{S}). Burada, sp basitçe S türündeki bir nesneyi sarmalar ve bu nesneye sp[] ile erişilebilir. Die örneğini devam ettirerek, şimdi rand(d::Die) tanımlamak istiyoruz; bu, d'nin bir yüzüne karşılık gelen bir Int üretmelidir:
julia> Random.rand(rng::AbstractRNG, d::Random.SamplerTrivial{Die}) = rand(rng, 1:d[].nsides);
julia> rand(Die(4))
1
julia> rand(Die(4), 3)
3-element Vector{Any}:
2
3
3Verilen bir koleksiyon türü S için, rand(::S) tanımlıysa, eltype(S) türünde bir nesne üretileceği varsayılmaktadır. Son örnekte, bir Vector{Any} üretilmiştir; bunun nedeni eltype(Die) == Any olmasıdır. Çözüm, Base.eltype(::Type{Die}) = Int tanımlamaktır.
Generating values for an AbstractFloat type
AbstractFloat türleri özel durumlar olarak ele alınır, çünkü varsayılan olarak rastgele değerler tüm tür alanında üretilmez, bunun yerine [0,1) aralığında üretilir. Aşağıdaki yöntem T <: AbstractFloat için uygulanmalıdır: Random.rand(::AbstractRNG, ::Random.SamplerTrivial{Random.CloseOpen01{T}})
An optimized sampler with pre-computed data
Bir ayrık dağılımı düşünün; burada 1:n sayıları, toplamı bir olan belirli olasılıklarla çekilir. Bu dağılımdan birçok değer gerektiğinde, en hızlı yöntem alias table kullanmaktır. Böyle bir tablo oluşturma algoritmasını burada sağlamıyoruz, ancak bunun yerine make_alias_table(probabilities) fonksiyonunun mevcut olduğunu varsayalım ve draw_number(rng, alias_table) fonksiyonu kullanılarak ondan rastgele bir sayı çekilebilir.
Dağılımın şu şekilde tanımlandığını varsayalım:
struct DiscreteDistribution{V <: AbstractVector}
probabilities::V
endve ve her zaman bir takma ad tablosu oluşturmak istediğimizi, gereken değer sayısından bağımsız olarak (bunu aşağıda özelleştirmeyi öğreniyoruz). Yöntemler
Random.eltype(::Type{<:DiscreteDistribution}) = Int
function Random.Sampler(::Type{<:AbstractRNG}, distribution::DiscreteDistribution, ::Repetition)
SamplerSimple(distribution, make_alias_table(distribution.probabilities))
endönceden hesaplanmış verilerle bir örnekleyici döndürmek için tanımlanmalıdır, o zaman
function rand(rng::AbstractRNG, sp::SamplerSimple{<:DiscreteDistribution})
draw_number(rng, sp.data)
enddeğerleri çizmek için kullanılacaktır.
Custom sampler types
SamplerSimple türü, önceden hesaplanmış verilerle çoğu kullanım durumu için yeterlidir. Ancak, özel örnekleyici türlerini nasıl kullanacağınızı göstermek için burada SamplerSimple'a benzer bir şey uyguluyoruz.
Die örneğimize geri dönersek: rand(::Die) bir aralıktan rastgele üretim kullanır, bu nedenle bu optimizasyon için bir fırsat vardır. Özel örnekleyicimize SamplerDie adını veriyoruz.
import Random: Sampler, rand
struct SamplerDie <: Sampler{Int} # generates values of type Int
die::Die
sp::Sampler{Int} # this is an abstract type, so this could be improved
end
Sampler(RNG::Type{<:AbstractRNG}, die::Die, r::Random.Repetition) =
SamplerDie(die, Sampler(RNG, 1:die.nsides, r))
# the `r` parameter will be explained later on
rand(rng::AbstractRNG, sp::SamplerDie) = rand(rng, sp.sp)Artık sp = Sampler(rng, die) ile bir örnekleyici almak ve rng ile ilgili herhangi bir rand çağrısında die yerine sp kullanmak mümkün. Yukarıdaki basit örnekte, die'nin SamplerDie içinde saklanmasına gerek yoktur, ancak pratikte bu genellikle böyle olur.
Tabii ki, bu desen o kadar sık ki, yukarıda kullanılan yardımcı tür, yani Random.SamplerSimple, mevcut ve SamplerDie tanımını yapmamıza gerek kalmıyor: ayrıştırmamızı şu şekilde uygulayabilirdik:
Sampler(RNG::Type{<:AbstractRNG}, die::Die, r::Random.Repetition) =
SamplerSimple(die, Sampler(RNG, 1:die.nsides, r))
rand(rng::AbstractRNG, sp::SamplerSimple{Die}) = rand(rng, sp.data)Burada, sp.data, SamplerSimple yapıcısına yapılan çağrıda ikinci parametreyi ifade eder (bu durumda Sampler(rng, 1:die.nsides, r) ile eşittir), Die nesnesine ise sp[] aracılığıyla erişilebilir.
SamplerDie gibi, herhangi bir özel örnekleyici Sampler{T} alt türü olmalıdır; burada T, üretilen değerlerin türüdür. SamplerSimple(x, data) isa Sampler{eltype(x)} olduğu için, bu SamplerSimple'a ilk argümanın ne olabileceğini kısıtlar (ilk argüman olarak SamplerSimple'ı kullanmanız önerilir; burada x, bir Sampler yöntemi tanımlarken basitçe iletilir). Benzer şekilde, SamplerTrivial(x) isa Sampler{eltype(x)}.
Başka bir yardımcı tür, Random.SamplerTag, diğer durumlar için mevcut, ancak dahili API olarak kabul edilir ve uygun bir deprekasyon olmadan herhangi bir zamanda bozulabilir.
Using distinct algorithms for scalar or array generation
Bazı durumlarda, yalnızca birkaç değer üretmek isteyip istemediğiniz veya büyük sayıda değer üretmek isteyip istemediğiniz, algoritma seçiminde etkili olacaktır. Bu, Sampler yapıcısının üçüncü parametresi ile ele alınır. İki yardımcı tür tanımladığımızı varsayalım, Die için, SamplerDie1 yalnızca birkaç rastgele değer üretmek için kullanılacak ve SamplerDieMany ise birçok değer için kullanılacak. Bu türleri aşağıdaki gibi kullanabiliriz:
Sampler(RNG::Type{<:AbstractRNG}, die::Die, ::Val{1}) = SamplerDie1(...)
Sampler(RNG::Type{<:AbstractRNG}, die::Die, ::Val{Inf}) = SamplerDieMany(...)Elbette, rand bu türler üzerinde de tanımlanmalıdır (yani rand(::AbstractRNG, ::SamplerDie1) ve rand(::AbstractRNG, ::SamplerDieMany)). Her zamanki gibi, özel türler gerekli değilse SamplerTrivial ve SamplerSimple kullanılabilir.
Not: Sampler(rng, x) sadece Sampler(rng, x, Val(Inf)) için bir kısayoldur ve Random.Repetition Union{Val{1}, Val{Inf}} için bir takma addır.
Creating new generators
API henüz net bir şekilde tanımlanmamış, ancak genel bir kural olarak:
- herhangi bir
randyöntemi "temel" türler (isbitstypetam sayılar veBaseiçindeki kayan nokta türleri) üretiyorsa, bunlar bu özel RNG için tanımlanmalıdır, eğer gerekiyorsa; - diğer belgelenmiş
randyöntemleri birAbstractRNGkabul ediyorsa kutudan çıktığı gibi çalışmalıdır, (1) numaralı maddeden hangi yöntemlerin kullanıldığı uygulanmışsa), ancak elbette bu RNG için optimizasyon alanı varsa özelleştirilebilir; copyiçin pseudo-RNG'ler, çağrıldığında aynı şekilde orijinal ile aynı rastgele diziyi üreten bağımsız bir kopya döndürmelidir. Bu mümkün olmadığında (örneğin, donanım tabanlı RNG'ler),copyuygulanmamalıdır.
Concerning 1), a rand method may happen to work automatically, but it's not officially supported and may break without warnings in a subsequent release.
Yeni bir rand metodunu varsayımsal bir MyRNG jeneratörü için tanımlamak ve bir değer spesifikasyonu s (örneğin s == Int veya s == 1:10) tanımlamak için, S==typeof(s) veya S==Type{s} ise s bir türse, daha önce gördüğümüz aynı iki metod tanımlanmalıdır:
Sampler(::Type{MyRNG}, ::S, ::Repetition), buSamplerStüründe bir nesne döndürür.rand(rng::MyRNG, sp::SamplerS)
Sampler(rng::AbstractRNG, ::S, ::Repetition) zaten Random modülünde tanımlı olabilir. Bu durumda, pratikte adım 1)'i atlamak mümkün olacaktır (eğer bu belirli RNG türü için üretimi özelleştirmek isteniyorsa), ancak ilgili SamplerS türü içsel bir detay olarak kabul edilir ve uyarı olmaksızın değiştirilebilir.
Specializing array generation
Bazı durumlarda, belirli bir RNG türü için, rastgele değerler dizisi oluşturmak, daha önce açıklanan ayrıştırma tekniğini kullanmaktan daha verimli olabilir. Bu, örneğin, rastgele değerleri bir diziye yerel olarak yazan MersenneTwister için geçerlidir.
MyRNG için bu özel durumu ve s spesifikasyonunu uygulamak için, S türünde elemanlar üreten aşağıdaki yöntem tanımlanabilir: rand!(rng::MyRNG, a::AbstractArray{S}, ::SamplerS), burada SamplerS, Sampler(MyRNG, s, Val(Inf)) tarafından döndürülen örnekleyicinin türüdür. AbstractArray yerine, işlevselliği yalnızca bir alt tür için uygulamak mümkündür, örneğin Array{S}. rand'ın değiştirici olmayan dizi yöntemi, bu özel durumu otomatik olarak dahili olarak çağıracaktır.
Reproducibility
RNG parametreleri belirli bir tohum ile başlatıldığında, programınızı birden fazla kez çalıştırdığınızda aynı sahte rastgele sayı dizisini yeniden üretebilirsiniz. Ancak, Julia'nın küçük bir sürümü (örneğin 1.3'ten 1.4'e) belirli bir tohumdan üretilen sahte rastgele sayı dizisini değiştirebilir, özellikle MersenneTwister kullanılıyorsa. (Düşük seviyeli bir fonksiyonun ürettiği dizinin değişmemesi durumunda bile, rand gibi, daha yüksek seviyeli fonksiyonların çıktısı randsubseq algoritma güncellemeleri nedeniyle değişebilir.) Gerekçe: sahte rastgele akışların asla değişmeyeceğini garanti etmek, birçok algoritmik iyileştirmeyi engeller.
Eğer rastgele verilerin tam yeniden üretilebilirliğini garanti etmek istiyorsanız, verileri kaydetmek (örneğin, bir bilimsel yayında ek bir ek olarak) tavsiye edilir. (Ayrıca, özellikle bit yeniden üretilebilirliğine ihtiyaç duyuyorsanız, belirli bir Julia sürümünü ve paket manifestosunu da belirtebilirsiniz.)
Yazılım testleri, belirli "rastgele" verilere dayanıyorsa, genellikle verileri kaydetmeli, test koduna gömmeli veya StableRNGs.jl gibi üçüncü taraf paketler kullanmalıdır. Öte yandan, çoğu rastgele veri için geçmesi gereken testler (örneğin, rastgele bir matris A = randn(n,n) için A \ (A*x) ≈ x test etme) çok olasılıksız veriler nedeniyle testin birçok kez çalıştırılmasının başarısızlıkla karşılaşmamasını sağlamak için sabit bir tohum ile bir RNG kullanabilir.
İstatistiksel dağılım, rastgele örneklerin alındığı aynı minor Julia sürümleri arasında garanti edilmektedir.