SORU
10 HAZİRAN 2015, ÇARŞAMBA


Karakter vektör rasgele örnek, birbiri önek olmadan

(Sıfır-sıfır) max_len basamaklı ikili sayılar olan bir karakter vektör, pool, düşünün.

max_len <- 4
pool <- unlist(lapply(seq_len(max_len), function(x) 
  do.call(paste0, expand.grid(rep(list(c('0', '1')), x)))))

pool
##  [1] "0"    "1"    "00"   "10"   "01"   "11"   "000"  "100"  "010"  "110" 
## [11] "001"  "101"  "011"  "111"  "0000" "1000" "0100" "1100" "0010" "1010"
## [21] "0110" "1110" "0001" "1001" "0101" "1101" "0011" "1011" "0111" "1111"

İsterim örnek n Bu elemanları, kısıtlama yok ve numune elemanları prefixes herhangi bir diğer örnek elemanları (Yani eğer biz örnek 1101 biz ban 1, 11 110 iken, eğer biz örnek 1 biz ban bu öğelerin başında 1 gibi 10, 11, 100, vb.).

Aşağıdaki n büyük (veya 2^max_len yaklaştığında) benim girişimi while ama tabii ki bu yavaş kullanıyor.

set.seed(1)
n <- 10
chosen <- sample(pool, n)
while(any(rowSums(outer(paste0('^', chosen), chosen, Vectorize(grepl))) > 1)) {
  prefixes <- rowSums(outer(paste0('^', chosen), chosen, Vectorize(grepl))) > 1
  pool <- pool[rowSums(Vectorize(grepl, 'pattern')(
    paste0('^', chosen[!prefixes]), pool)) == 0]
  chosen <- c(chosen[!prefixes], sample(pool, sum(prefixes)))
}

chosen
## [1] "0100" "0101" "0001" "0011" "1000" "111"  "0000" "0110" "1100" "0111"

Bu biraz başlangıçta pool yetersiz elemanlar pool kalmadı boyutu toplam örnek almak n demek olan bu öğeleri kaldırarak geliştirilebilir. E. g., max_len = 4 n > 9, biz derhal çıkarın 0 1 pool, o zamandan bu yana da dahil olmak üzere, maksimum örnek olurdu 9 (0 ve sekiz 4-karakter elemanları ile başlayan 1 1 ve sekiz 4-karakter elemanları ile başlayan 0).

Bu mantığa göre, o zaman bir şey pool ilk örnek alarak önce gelen unsurlar gibi ihmal edebiliriz:

pool <- pool[
  nchar(pool) > tail(which(n > (2^max_len - rev(2^(0:max_len))[-1]   1)), 1)]

Herkes daha iyi bir yaklaşım olduğunu düşünmüyor musunuz? Bir şey çok daha basit bakan gibi hissediyorum.


EDİT

Niyetimi açıklamak için, kavşaklar ve ipuçları düğümleri olduğu dallar, bir dizi olarak havuz (pool elemanları) tasvir edeceğim. Aşağıdaki resimde sarı düğüm (yani 010) çizilmiş olduğunu varsayalım. Şimdi, tüm kırmızı "düğümleri 0, 01, 010, havuzundan kaldırılır oluşur.", şube Bu "öneki" zaten zaten o. (bizim örnekte düğüm düğüm yasaklayan örnekleme ile kastedilen budur ^em>önekibizim örnek düğümler).

enter image description here

Eğer örnek düğüm oldu yarı yolda bir dal gibi 01 olarak aşağıdaki şekilde, daha sonra tüm kırmızı düğümleri (0, 01, 010, 011) izin verilmeyen bu yana 0 önekleri 01 ve 01 önekleri hem 010 ve 011.

enter image description here

Örnek olmak istememya1ya0 her junction (yani yürüyen dalları yazı tura at çatal) - ceza hem de örnek olarak: (1) anne (veya büyük anne-babalar, vb.) ya çocuk (Torun, vb.) bu düğüm zaten örnek değil; ve (2) üzerine örnekleme düğüm düğüm orada yeterli büyüklükte istenilen örnek n elde kalan olacak.

Eğer 010 ilk tercihi ise ikinci rakam yukarıda, siyah düğüm at her düğüm hala (şu anda) geçerli, n <= 4 varsayıyoruz. Örneğin, eğer n==4 ve numune düğüm 1 sonraki (ve bu yüzden bizim tüyo birlikte 01 ve 1), Biz sonradan vermemek düğüm 00 (nedeniyle Kural 2 yukarıda) ama hala almak 000 001 vererek bize 4 elemanlı örnek. Diğer yandan n==5, eğer düğüm 1 Bu aşamada izin verilmeyen olurdu.

CEVAP
11 HAZİRAN 2015, PERŞEMBE


İntro

Bu diğer yanıt gerçekleştirdik dize algoritma sayısal bir çeşididir. Daha hızlıdır ve ya havuz sıralama oluşturma gerektirmez.

Algoritma Anahat

Tamsayı numaraları ikili temsil etmek için kullanabileceğimiz büyük havuzu neslin sorunu ve değerler sıralı eleme kolaylaştıran dizeler. max_len==3 ile örneğin, sayı 1-- - doldurma gösterir (ondalık) 4 anlamına alabiliriz. Ayrıca, eğer bu numara da alırsak ortadan kaldırılması gereken sayı 4 4 2 ^ x - 1 arasındadır karar veririz. Burada x sayı dolgu elemanları (2 harf), numaralar ortadan kaldırmak arasında 4 4 2 ^ 2 - 1 (veya arasında 4 ve 7 ifade 100, 110 ve 111).

Sorun maç için tam olarak algoritma bazı bölümleri için ayrı olarak ikili potansiyel olarak aynı olacağını numaraları davranıyorsun beri Küçük bir kırışıklık ihtiyacımız var. Örneğin, 100, 10- ve 1-- aynı sayıda, ama farklı düzeni içinde tedavi edilmesi gerekir. max_len==3 bir dünyada, 8 Olası numaraları, ama 14 olası bir beyan var:

0 - 000: 0--, 00-
1 - 001:
2 - 010: 01-
3 - 011:
4 - 100: 1--, 10-
5 - 101:
6 - 110: 11-
7 - 111:

0 ve 4 üç olası kodlamalar, 2 ve 6 iki tane var, Ve Tüm Diğerleri sadece bir tane var. Birden çok temsili ile rakamlar için seçimi yüksek olasılık gösteren bir tamsayı havuz kaç numarasını içerir izleme mekanizması oluşturmak istiyoruz. İstediğimiz ağırlıkları belirtmek için sayının sonunda birkaç parça ekleyerek bunu yapabiliriz. Sayımız olur (iki bit burada kullanıyoruz):

jbaum | int | bin | bin.enc | int.enc    
  0-- |   0 | 000 |   00000 |       0
  00- |   0 | 000 |   00001 |       1      
  000 |   0 | 000 |   00010 |       2      
  001 |   1 | 001 |   00100 |       3      
  01- |   2 | 010 |   01000 |       4  
  010 |   2 | 010 |   01001 |       5  
  011 |   3 | 011 |   01101 |       6  
  1-- |   4 | 100 |   10000 |       7  
  10- |   4 | 100 |   10001 |       8  
  100 |   4 | 100 |   10010 |       9  
  101 |   5 | 101 |   10100 |      10  
  11- |   6 | 110 |   11000 |      11   
  110 |   6 | 110 |   11001 |      12   
  111 |   7 | 111 |   11100 |      13

Bir kaç yararlı özellikleri:

  • enc.bits kaç kodlama için ihtiyacımız var (bu durumda iki) temsil eder
  • int.enc %% enc.bits sayı çok açıkça belirtilmiş olduğunu söyler
  • int.enc %/% enc.bits int döndürür
  • int * 2 ^ enc.bits explicitly.specified int.enc döndürür

explicitly.specified burada her zaman en az bir rakamla belirtilmiş olduğundan bizim uygulama 0 72 *arasında olduğunu unutmayın. Biz artık tamamen veri yapısını tek tamsayılar kullanarak temsil eden bir kodlama var. Tam sayılar örnek ve istenen sonuçlar, doğru ağırlık, vb üretebilir. Bu yaklaşımın bir sınırlama R 32 bit tamsayı kullandığımız ve max_len==25 kadar havuzlar için kendimizi sınırlamak çok kodlama için bazı bit rezerve etmeliyiz. Eğer tamsayı çift duyarlıklı kayan nokta ile belirtilen kullandıysanız büyük gidebilirsin, ama yapmadık.

Kaçınarak Yinelenen Alır

Aynı değeri iki kez almak istemiyoruz sağlamak için iki zor yolu vardır

  1. Değerleri seçmek için kullanılabilir kalır ne iz, ve örnek olanlardan rastgele
  2. Rastgele tüm olası değerler arasından örnek ve değer önceden seçilmiş olup olmadığını, ve eğer varsa, örnek tekrar kontrol edin

İlk seçenek temiz gibi görünüyor olsa da, aslında çok pahalı bir hesaplama. Ya tarama değerleri seçilmiş bir vektör yapıyor, ya da küçülen bir vektör olmayan diskalifiye değerleri içeren oluşturmak gerektirir. Daralma seçenek yalnızca daha verimli vektör tarama eğer bu vektör yapılan psikiyatrist tarafından referans ile C kodu, ama o zaman bile gerektirir tekrarlanan çeviriler potansiyel olarak büyük bir kısmını vektör ve C. gerektirir

Burada yöntem #2 kullanın. Bu bize rastgele shuffle olası değerler evreni bir kez izin verir, ve daha sonra sırayla her bir değer seçin, diskalifiye oldu, ve eğer varsa kontrol edin, bir tane daha alma vb. Bu değer bizim kodlama olarak seçilmiş olup olmadığını kontrol etmek saçmadır, çünkü çalışır;sıralanmış bir tablo değeri tek başına dayalı bir değerin konumunu çıkarabiliriz. Biz sıralanmış bir tablo kaydı, her değer durumu ve ya Güncelleme ya da doğrudan dizin erişim yoluyla devlet (hayır tarama gerekli) arama.

Örnekler

Temel R Bu algoritma uygulaması olarak kullanılabilira gist. Bu özel uygulama sadece tam çizer çeker. İşte 10 örnek çizer max_len==4 bir havuzu 8 element:

# each column represents a draw from a `max_len==4` pool

set.seed(6); replicate(10, sample0110b(4, 8))
     [,1]   [,2]   [,3]   [,4]   [,5]   [,6]   [,7]   [,8]   [,9]   [,10] 
[1,] "1000" "1"    "0011" "0010" "100"  "0011" "0"    "011"  "0100" "1011"
[2,] "111"  "0000" "1101" "0000" "0110" "0100" "1000" "00"   "0101" "1001"
[3,] "0011" "0110" "1001" "0100" "0000" "0101" "1101" "1111" "10"   "1100"
[4,] "0100" "0010" "0000" "0101" "1101" "101"  "1011" "1101" "0110" "1101"
[5,] "101"  "0100" "1100" "1100" "0101" "1001" "1001" "1000" "1111" "1111"
[6,] "110"  "0111" "1011" "111"  "1011" "110"  "1111" "0100" "0011" "000" 
[7,] "0101" "0101" "111"  "011"  "1010" "1000" "1100" "101"  "0001" "0101"
[8,] "011"  "0001" "01"   "1010" "0011" "1110" "1110" "1001" "110"  "1000"

Biz de aslında iki uygulamaları o dayanıyordu yöntem #1 için önleme çoğaltır, bir baz R, ve C, ama bile C sürüm değil mi bu kadar hızlı yeni sürüm baz R n büyük. Bu fonksiyonu eksik çizmek için yeteneği çizer uygulamak, onları burada referans için sunduğumuz bu yüzden:

Karşılaştırmalı testleri

Burada kriterler milisaniye olarak bu/A. Times Q sonucunda ortaya çıkan birkaç işlev karşılaştıran bir set. brodie.b sürümü bu cevap olarak açıklanmıştır. brodie orijinal uygulama brodie.C bazı C. ile aslı, Tüm bu komple örnekleri için gereksinim zorunlu değildir. brodie.str diğer cevap dizesindeki sürümüdür.

   size    n  jbaum josilber  frank tensibai brodie.b brodie brodie.C brodie.str
1     4   10     11        1      3        1        1      1        1          0
2     4   50      -        -      -        1        -      -        -          1
3     4  100      -        -      -        1        -      -        -          0
4     4  256      -        -      -        1        -      -        -          1
5     4 1000      -        -      -        1        -      -        -          1
6     8   10      1      290      6        3        2      2        1          1
7     8   50    388        -      8        8        3      4        3          4
8     8  100  2,506        -     13       18        6      7        5          5
9     8  256      -        -     22       27       13     14       12          6
10    8 1000      -        -      -       27        -      -        -          7
11   16   10      -        -    615      688       31     61       19        424
12   16   50      -        -  2,123    2,497       28    276       19      1,764
13   16  100      -        -  4,202    4,807       30    451       23      3,166
14   16  256      -        - 11,822   11,942       40  1,077       43      8,717
15   16 1000      -        - 38,132   44,591       83  3,345      130     27,768

Nispeten daha büyük havuzlar için bu ölçekler

system.time(sample0110b(18, 100000))
   user  system elapsed 
  8.441   0.079   8.527 

Kriter notlar:

  • frank ve brodie (brodie eksi.str) karşılaştırmalar (aşağıya bakınız) etkileyecek havuzları, öncesi nesil herhangi bir gerektirmez
  • Josilber LP versiyonu
  • jbaum OP örneğidir
  • tensibai biraz eğer havuz boşsa başarısız yerine çıkmak için değiştirilir
  • -python, çok çalıştırmak için değil tamamen tampon için hesap / ile mukayese edilemez
  • - ya olanaksız ya da seçenekleri zaman oldukça çok yavaş temsil eder

Zamanlamaları eklemeyin çizim havuzları (0.8, 2.5, 401 milisaniye sırasıyla boyutu 4, 8 ve 16) için gerekli olan jbaum, josilber ve brodie.str çalışır, ya da sıralama onları (0.1, 2.7, 3700 milisaniye için boyutu 4, 8 ve 16), çizmek için ek olarak brodie.str için gerekli olan. Olsun bu eklemek istediğiniz veya belirli bir havuz işlevi çalıştırmak ne kadar bağlıdır. Ayrıca, neredeyse kesinlikle üretme havuzları sıralama daha iyi yolları vardır.

Bu microbenchmark üç çalışan orta zaman. Kodavailable as a gistgerçi not, *, sample01101, *sample0110101 sample01 fonksiyonları önceden yüklemek gerekir.

Bunu Paylaş:
  • Google+
  • E-Posta
Etiketler:

YORUMLAR

SPONSOR VİDEO

Rastgele Yazarlar

  • Kanaal van Dj0fifty

    Kanaal van D

    28 EKİM 2011
  • dougownsall

    dougownsall

    7 EKİM 2007
  • RayperEnglishKnight

    RayperEnglis

    24 Kasım 2008