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ında RandomDevice (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.

Warning

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 generation functions

Base.randFunction
rand([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:9 veya ('x', "y", :z))

  • bir AbstractDict veya AbstractSet nesnesi

  • bir 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 (desteklenmeyen BigInt hariç)
    • 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, ancak T örneklenebilir değilse desteklenmez.
    • tüm <:AbstractChar tü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; S türünde bir değer döndürün. Tuple{Vararg{T}} (bilinmeyen boyut) ve Tuple{1:2} (bir değerle parametrelenmiş) gibi demet türlerinin desteklenmediğini unutmayın.
    • Pair türü, örneğin Pair{X, Y} böylece rand için X ve Y tanımlıysa, rastgele çiftler üretilir.

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.

Julia 1.1

S'nin bir demet olarak desteklenmesi en az Julia 1.1 gerektirir.

Julia 1.11

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.938235
Note

rand(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.

source
Random.rand!Function
rand!([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.5256623915420473
source
Random.bitrandFunction
bitrand([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
 1
source
Base.randnFunction
randn([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.942481877315864

Normal 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.45005

Kullanı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.0538589im
source
Random.randn!Function
randn!([rng=default_rng()], A::AbstractArray) -> A

Diziyi 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.4922456865251828
source
Random.randexpFunction
randexp([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.71835
source
Random.randexp!Function
randexp!([rng=default_rng()], A::AbstractArray) -> A

Diziyi 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.6348266443720407
source
Random.randstringFunction
randstring([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"
Not

chars, rand karakterleri rastgele seçebiliyorsa, Char veya UInt8 türünde herhangi bir karakter koleksiyonu olabilir (daha verimli).

source

Subsequences, permutations and shuffling

Random.randsubseqFunction
randsubseq([rng=default_rng(),] A, p) -> Vector

Verilen 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
 7
source
Random.randsubseq!Function
randsubseq!([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
 7
source
Random.randpermFunction
randperm([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

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
 3
source
Random.randperm!Function
randperm!([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
 3
source
Random.randcycleFunction
randcycle([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

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
 1
source
Random.randcycle!Function
randcycle!([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
 1
source
Random.shuffleFunction
shuffle([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
  7
source
Random.shuffle!Function
shuffle!([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
  7
source

Generators (creation and seeding)

Random.default_rngFunction
Random.default_rng() -> rng

Varsayı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()).

Note

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.

Julia 1.3

Bu işlev Julia 1.3'te tanıtılmıştır.

source
Random.seed!Function
seed!([rng=default_rng()], seed) -> rng
seed!([rng=default_rng()]) -> rng

Rastgele 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
true
source
Random.TaskLocalRNGType
TaskLocalRNG

TaskLocalRNG, 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.

Julia 1.11

Negatif bir tam sayı tohumu ile TaskLocalRNG()'yi tohumlamak en az Julia 1.11 gerektirir.

Julia 1.10

Görev oluşturma, Julia 1.10 itibarıyla ana görevin RNG durumunu ilerletmez.

source
Random.XoshiroType
Xoshiro(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.

Julia 1.11

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
true
source
Random.MersenneTwisterType
MersenneTwister(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.

Julia 1.11

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
true
source
Random.RandomDeviceType
RandomDevice()

Bir RandomDevice RNG nesnesi oluşturur. İki böyle nesne her zaman farklı rastgele sayı akışları üretecektir. Entropi işletim sisteminden elde edilir.

source

Hooking into the Random API

Random işlevselliğini genişletmenin iki çoğunlukla ortogonal yolu vardır:

  1. özel türlerin rastgele değerlerini oluşturma
  2. 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:

  1. SamplerType{T}() türünden T'den örnekler çizen örnekleyiciler uygulamak için kullanılabilir (örneğin, rand(Int)). Bu, türler için Sampler tarafından döndürülen varsayılan değerdir.

  2. 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çin Sampler tarafından döndürülen varsayılandır.

  3. SamplerSimple(self, data) ayrıca, Sampler'ın özel bir yönteminde hesaplanması gereken rastgele önceden hesaplanmış değerleri depolamak için kullanılabilecek ek data alanı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.SamplerType
Sampler(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.

source
Random.SamplerTypeType
SamplerType{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üş.

source
Random.SamplerTrivialType
SamplerTrivial(x)

Verilen x değerini saran bir örnekleyici oluşturur. Bu, değerler için varsayılan geri dönüş yoludur. Bu örnekleyicinin eltypeeltype(x) ile eşittir.

Tavsiye edilen kullanım durumu, önceden hesaplanmış veriler olmadan değerlerden örneklemektir.

source
Random.SamplerSimpleType
SamplerSimple(x, data)

Verilen değer x ve data ile sarmalayan bir örnekleyici oluşturun. Bu örnekleyicinin eltypeeltype(x) ile eşittir.

Tavsiye edilen kullanım durumu, önceden hesaplanmış verilerle değerlerden örneklemektir.

source

Ö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
end

Bu, 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
 3

Verilen 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
end

ve 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)
end

değ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:

  1. herhangi bir rand yöntemi "temel" türler (isbitstype tam sayılar ve Base içindeki kayan nokta türleri) üretiyorsa, bunlar bu özel RNG için tanımlanmalıdır, eğer gerekiyorsa;
  2. diğer belgelenmiş rand yöntemleri bir AbstractRNG kabul 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;
  3. copy iç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), copy uygulanmamalı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:

  1. Sampler(::Type{MyRNG}, ::S, ::Repetition), bu SamplerS türünde bir nesne döndürür.
  2. 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.