Bir çift çakışmayan bit vektörü bulma


17

Size k genişliği n bitvector'larının bir listesini veriyorum . Amacınız, listeden ortak 1'si olmayan iki bitvector döndürmek veya böyle bir çiftin olmadığını bildirmektir.k

Örneğin, size verirsem [00110,01100,11000]tek çözüm {00110,11000} . Alternatif olarak, girişin [111,011,110,101] çözümü yoktur. Ve tamamen sıfır bitvector 000...0 ve başka bir elemanını içeren herhangi bir liste eönemsiz bir çözüme sahiptir {e,000...0} .

İşte biraz daha zor bir örnek, çözüm yok (her satır biraz vektör, siyah kareler 1s ve beyaz kareler 0s):

■ ■ ■ ■ □ □ □ □ □ □ □ □ □
■ □ □ □ ■ ■ ■ □ □ □ □ □ □ 
■ □ □ □ □ □ □ ■ ■ ■ □ □ □
■ □ □ □ □ □ □ □ □ □ ■ ■ ■
□ ■ □ □ □ ■ □ □ □ ■ ■ □ □
□ ■ □ □ ■ □ □ □ ■ □ □ □ ■
□ ■ □ □ □ □ ■ ■ □ □ □ ■ □ <-- All row pairs share a black square
□ □ ■ □ □ □ ■ □ ■ □ ■ □ □
□ □ ■ □ □ ■ □ ■ □ □ □ □ ■
□ □ ■ □ ■ □ □ □ □ ■ □ ■ □
□ □ □ ■ ■ □ □ ■ □ □ ■ □ □
□ □ □ ■ □ □ ■ □ □ ■ □ □ ■
□ □ □ ■ □ ■ □ □ ■ □ □ ■ □

Çakışan olmayan iki bitvektör ne kadar verimli bulunabilir veya var olmadığı gösterilebilir?

Sadece olası her çifti karşılaştırdığınız saf algoritma O(n2k) . Daha iyisini yapmak mümkün mü?


Olası bir azalma: Her iki vektör için bir tepe noktası ve karşılık gelen iki vektörün ortak 1'si varsa, iki köşe arasında bir kenar içeren bir grafiğiniz vardır . Grafik çapının 2 olup olmadığını bilmek istersiniz . Ancak O ( n 2 k ) ' dan daha hızlı gitmek zor görünüyor . G2O(n2k)
François

@ FrançoisGodi Üç düğümü ve eksik bir kenarı olan bağlı herhangi bir grafik bileşeni en az iki çapa sahiptir. Bir bitişik liste gösterimi ile zamanı kontrol edilir. O(V)
Craig Gidney

@Strilanc Tabii, eğer bir çözüm yoksa, grafik tamamlanmıştır (çap = 1'den daha açık, haklısınız), ancak bitişik liste temsilinin hesaplanması uzun olabilir.
François

makinenizin kelime genişliğinden daha mı küçük? k
Raphael

1
@TomvanderZanden Bu, veri yapısının muhtemelen dayandığı değişmezleri ihlal edecek gibi görünüyor. Özellikle, bu eşitlik geçişli olmalıdır. Zaten bir trie kullanmayı düşünüyorum ve sorgu
bitmask

Yanıtlar:


10

Isınma: rastgele bitvektörler

Bir ısınma olarak, her bir bitvektörün rasgele olarak eşit olarak seçildiği durumla başlayabiliriz. Sonra sorunun O ( n 1,6 dk. ( K , lg n) olarak çözülebileceği ortaya çıktı. sürede(daha kesin olarak, 1.6 lg 3 ile değiştirilebilir).O(n1.6min(k,lgn))1.6lg3

Sorunun aşağıdaki iki kümesi varyantını ele alacağız:

Verilen kümeler S,T{0,1}k olmayan bir üst üste binen çifte vardır burada bitvectors bölgesinin belirlenmesi .sS,tT

Bunu çözmenin temel tekniği böl ve ele geçir. Burada birbölme ve fethetme kullanan O ( n 1.6 k ) zaman algoritması:O(n1.6k)

  1. Bölünmüş ve T birinci bit konumuna göre. Başka bir deyişle, form S 0 = { s S : s 0 = 0 } , S 1 = { s S : s 0 = 1 } , T 0 = { t T : t 0 = 0 } , T 1 = { t T : tSTS0={sS:s0=0}S1={sS:s0=1}T0={tT:t0=0} .T1={tT:t0=1}

  2. Şimdi, , S 0 , T 1 ve T 1 , S 0'dan üst üste binmeyen bir çifti tekrarlayın . Herhangi bir özyinelemeli çağrı çakışan olmayan bir çift bulursa, çıktıyı verin, aksi takdirde "Çakışan çift yok" çıktısını alın.S0,T0S0,T1T1,S0

Tüm bitvektörler rastgele seçildiği için ve | T b | | T | / 2 . Böylece, üç özyinelemeli çağrı var ve sorunun boyutunu iki faktör azalttık (her iki kümenin boyutu da iki faktör azaltılır). Lg dakika sonra ( | S|Sb||S|/2|Tb||T|/2lgmin(|S|,|T|) böler, iki set bir boyutu 1 aşağı ve sorun lineer zamanda çözülebilir. Biz çizgileri boyunca bir nüks ilişkisi elde | T , ki bu çözeltisi T ( n ) = O ( n 1.6 k ) . İki setli durumda çalışma süresi daha kesin olarak hesaplandığında, çalışma süresinin O ( dk ( | S | , | T | ) 0,6 maks ( | S | , | ) k ) olduğunu görüyoruzT(n)=3T(n/2)+O(nk)T(n)=O(n1.6k)O(min(|S|,|T|)0.6max(|S|,|T|)k) .

Bu, olduğunda, üst üste binmeyen bir çiftin var olma olasılığının katlanarak küçük olduğuna dikkat çekerek daha da geliştirilebilir . Özel olarak, X , Y , iki rasgele vektörler, onlardır örtüşmeyen bu olasılık vardır ( 3 / 4 ) k . Eğer | S | = | T | = N , orada , n 2 , böylece bağlanmış bir birlik bu tür çift, bir üst üste çifti mevcut ihtimali en fazla olan n- 2 ( 3k2.5lgn+100x,y(3/4)k|S|=|T|=nn2, hemen "Çakışan çift yoktur" (bu yanlış olma olasılığı ihmal edilebilir derecede küçüktür) derhal dönebiliriz, aksi takdirde yukarıdaki algoritmayı çalıştırırız. . Zaman k 2.5 lg , n + 100 , bu2,5 lg n + 100 isen2(3/4)kk2.5lgn+100 . Yani, bir ön işleme adımı olarak, eğer k1/2100k2.5lgn+100

Böylece (veya O ( dk ( | S | , | T | ) 0.6 max ( | S | , | T | ) min (O(n1.6min(k,lgn)) yukarıda önerilen iki-grup varyant için), bitvektörlerin rastgele düzgün bir şekilde seçildiği özel durum için.O(min(|S|,|T|)0.6max(|S|,|T|)min(k,lgn))

Tabii ki, bu en kötü durum analizi değil. Rastgele bitvektörler en kötü durumdan çok daha kolaydır - ama belki de genel duruma uygulayabileceğimiz bazı fikirler almak için bir ısınma olarak ele alalım.

Isınma dersleri

Yukarıdaki ısınmadan birkaç ders öğrenebiliriz. İlk olarak, böl ve fethet (biraz pozisyonda bölme) yararlı görünüyor. İkincisi, bir bit pozisyonunao konumda olabildiğince fazla 1 '; 0 ne kadar fazlaolursa, alt sorun boyutunda o kadar az azalma olur.10

Üçüncüsü, bu, 'in yoğunluğu küçüldükçe sorunun daha da zorlaştığını gösterir - bitvektörler arasında çok az 1 ' varsa (çoğunlukla 0 'lar), her bölünme azaldıkça problem oldukça zor görünüyor alt problemlerin boyutu biraz. Bu yüzden, yoğunluk tanımlamak Í olan bit ondalık sayı 1 (yani, tüm üzerinden n- k bit) ve bit pozisyonunun yoğunluğu I olan bitvectors fraksiyonu olduğu 1 pozisyonunda i110Δ1nki1i .

Çok düşük yoğunlukta kullanım

Bir sonraki adım olarak, yoğunluk çok küçükse ne olacağını merak edebiliriz. Her bit pozisyonundaki yoğunluk 1 / than'dan küçükse, , örtüşmeyen bir çiftin var olduğu garanti edilir: örtüşmeyen bir çiftin var olması gerektiğini gösteren (yapıcı olmayan) bir varlık argümanı vardır. Bu onu bulmamıza yardımcı olmaz, ama en azından var olduğunu biliyoruz.1/k

Neden böyle? Diyelim ki bir çift bitvector , eğer x i = y i = 1 ise , bit konumu i ile kaplıdır . Çakışan her bitvektör çiftinin bir bit konumu ile kaplanması gerektiğini unutmayın. Şimdi, belirli bir bit konumunu i sabitlersek, o bit konumu tarafından kaplanabilecek çift sayısı en fazla ( n Δ ( i ) ) 2 < n 2 / k olur . Tüm k boyunca toplamax,yixi=yi=1i(nΔ(i))2<n2/kkBit pozisyonlarında, bir bit pozisyonu tarafından kapsanan toplam çift sayısının <n2 . Bu, herhangi bir bit konumu tarafından kapsanmayan bir çiftin olması gerektiği anlamına gelir, bu da bu çiftin çakışmasız olduğunu ima eder. Bu nedenle, yoğunluk her bit pozisyonunda yeterince düşükse, örtüşmeyen bir çift mutlaka vardır.

Ancak, böyle bir örtüşmeyen çifti bulmak için hızlı bir algoritma tanımlamakta bir kayıp var, bu rejimde, bir kişinin var olduğu garanti edilmesine rağmen. Ben hemen bir alt karesel bir bağımlılığı olan çalışma süresi doğuracak herhangi bir teknik görmüyorum n . Yani, bu sorunu düşünmek için biraz zaman harcamak istiyorsanız, bu odaklanmak için güzel bir özel durum.

Genel durum algoritmasına doğru

Genel durumda, doğal bir sezgisel tarama şöyle görünmektedir: en fazla 1 '(yani, en yüksek yoğunlukta) olan bit konumunu seçin ve üzerine bölün. Diğer bir deyişle:i1

  1. Δ ( i ) değerini maksimize eden bir bit konumu bulun .iΔ(i)

  2. Bölünmüş ve T bit pozisyonu dayalı i . Başka bir deyişle, form S 0 = { s S : s i = 0 } , S 1 = { s S : s i = 1 } , T 0 = { t T : t i = 0 } , T 1 = { tSTiS0={sS:si=0}S1={sS:si=1}T0={tT:ti=0} .T1={tT:ti=1}

  3. Şimdi, , S 0 , T 1 ve T 1 , S 0'dan üst üste binmeyen bir çifti tekrarlayınS0,T0S0,T1T1,S0. Herhangi bir özyinelemeli çağrı çakışan olmayan bir çift bulursa, çıktıyı verin, aksi takdirde "Çakışan çift yok" çıktısını alın.

Zorluk en kötü durumda performansını analiz etmektir.

Bir ön işleme adımı olarak, önce her bit konumunun yoğunluğunu hesapladığımızı varsayalım. Ayrıca, eğer , heri için, ön işleme adımının "Çakışan bir çift var" olduğunu varsayın (bunun örtüşen bir çifte bir örnek sergilemediğinin farkındayım, ama bunu ayrı bir meydan okuma olarak bir kenara bırakalım). Bütün bunlarO(nk) 'da yapılabilirΔ(i)<1/kiO(nk) zamanında yapılabilir. Yoğunluk bilgisi, yinelemeli çağrılar yaptığımız gibi verimli bir şekilde muhafaza edilebilir; çalışma süresine baskın katkıda bulunmayacaktır.

Bu prosedürün çalışma süresi ne olacak? Emin değilim, ama burada yardımcı olabilecek birkaç gözlem var. Yineleme her seviyesi ile sorun boyutunu azaltır bitvektörler (örneğin,nbitvektörlerdenn-n/n/kn bitvektörler). Bu nedenle, özyineleme sadecenn/k derin seviyeler. Ancak, ben özyineleme ağacında yaprakların sayısını saymak için nasıl hemen emin değilim (az bir sürü vardır3k ayrılır), bu yüzden bunun hangi çalışma süresine yol açacağından emin değilim.3k


reklam düşük yoğunluk: bu bir tür güvercin deliği argümanı gibi görünüyor. Belki genel fikrinizi kullanırsak (sütunu en çok olanlarla ayırırsak ), daha iyi sınırlar alırız çünkü -case (dinlemiyoruz) zaten "en" olanlardan kurtulur? (S1,T1)
Raphael

Toplam sayısı yararlı bir parametre olabilir. Ağacı kesmek için kullanabileceğimiz bir alt sınır gösterdiniz; üst sınırları da gösterebilir miyiz? Örneğin, daha fazla olanlar varsa, en azından c çakışmaları var. ckc
Raphael

Bu arada, ilk ayrımı nasıl yapmamızı önerirsin; keyfi? Neden sadece tüm girdi kümesini bazı sütun wrt bölmek değil ? Biz sadece Recurse gerek 0 -Örnek (bir tane paylaşan kişiler arasında hiçbir çözüm yoktur i ). İle verir beklenti, içinde T ( n ) = T ( n / 2 ) + O ( n, k ) bir sınırı O ( n, k ) (eğer k sabit). Genel bir sınır için, en azından kurtulabileceğimizi (önerdiğiniz alt sınır kesimini varsayarak)i0iT(n)=T(n/2)+O(nk)O(nk)kO(nk)en kötü durum sınırına bağlıolduğu anlaşılan her bölünmeye sahip k elemanları. Yoksa bir şey mi kaçırıyorum? n/kO(nk)
Raphael

Ah, bu yanlış, elbette, 0-1 uyumsuzluklarını dikkate almadığı için. Kahvaltıdan önce düşünmeye çalıştığım şey sanırım.
Raphael

@ Raphael, iki sorun var: (a) vektörler çoğunlukla sıfır olabilir, bu yüzden 50-50'lik bir bölünme elde edemezsiniz; nüks daha çok , (b) daha da önemlisi, 0-alt kümesinde sadece tekrarlamak yeterli değildir; ayrıca, 0-alt-kümesinden bir vektör ile 1-alt-kümesinden bir vektör arasındaki eşleşmeleri incelemeniz gerekir, böylece ek bir özyineleme yapılır. (Sanırım bunu doğru anladım.)T(n)=T((nn/k)k)+O(nk)
DW

8

Matris çarpımı kullanarak olduğunda daha hızlı çözümnk

Diyelim ki . Amacımız O ( n 2 k ) = O ( n 3 ) çalışma süresinden daha iyisini yapmaktır .n=kO(n2k)=O(n3)

Bitvektörleri ve bit konumlarını bir grafikteki düğümler olarak düşünebiliriz. Bitvector bu konumda bir 1 olduğunda, bir bitvector düğümü ile bir bit konumu düğümü arasında bir kenar vardır. Elde edilen grafik (bir tarafta bitvector-temsil düğümleri ve diğer bitposition-temsil düğümleri) ikili olup, sahip düğümleri.n+k=2n

Komşuluk matrisi verilen iki köşe arasında iki atlama yol varsa bir grafik, söyleyebileceğimiz karesi alınarak M ve elde edilen matris, bu iki köşe arasında bir "kenar" (kare matris içinde kenarın girişi yani var olmadığını kontrol sıfırdan farklıdır). Bizim amacımız için, kare bitişiklik matrisine sıfır girişi örtüşmeyen bir çift bitvektöre (yani bir çözüme) karşılık gelir. Herhangi bir sıfır olmaması çözüm olmadığı anlamına gelir.M M

Bir nxn matrisinin karesi zamanında yapılabilir, burada ω , 2.373'ün altındadır ve 2 olarak tahmin edilir .O(nω)ω2.3732

Yani algoritma:

  • Convert the bitvectors and bit positions into a bipartite graph with n+k nodes and at most nk edges. This takes O(nk) time.
  • Compute the adjacency matrix of the graph. This takes O((n+k)2) time and space.
  • Square the adjacency matrix. This takes O((n+k)ω) time.
  • Search the bitvector section of the adjacency matrix for zero entries. This takes O(n2) time.

n=kO((n+k)ω)=O(nω)O(n3)

kn. As long as kΩ(nω2) and kO(n2ω1), then (n+k)ω is better than n2k. For w2.373 that translates to n0.731kn1.373 (asymptotically). If w limits to 2, then the bounds widen towards nϵkn2ϵ.


1. This is also better than the naive solution if k=Ω(n) but k=o(n1.457). 2. If kn, a heuristic could be: pick a random subset of n bit positions, restrict to those bit positions and use matrix multiplication to enumerate all pairs that don't overlap in those n bit positions; for each such pair, check if it solves the original problem. If there aren't many pairs that don't overlap in those n bit positions, this provides a speedup over the naive algorithm. However I don't know a good upper bound on the number of such pairs.
D.W.

4

This is equivalent to finding a bit vector which is a subset of the complement of another vector; ie its 1's occur only where 0's occur in the other.

If k (or the number of 1's) is small, you can get O(n2k) time by simply generating all the subsets of the complement of each bitvector and putting them in a trie (using backtracking). If a bitvector is found in the trie (we can check each before complement-subset insertion) then we have a non-overlapping pair.

If the number of 1's or 0's is bounded to an even lower number than k, then the exponent can be replaced by that. The subset-indexing can be on either each vector or its complement, so long as probing uses the opposite.

There's also a scheme for superset-finding in a trie that only stores each vector only once, but does bit-skipping during probes for what I believe is similar aggregate complexity; ie it has o(k) insertion but o(2k) searches.


thanks. The complexity of your solution is n2(1p)k, where p is the probability of 1's in the bitvector. A couple of implementation details: though this is a slight improvement, there's no need to compute and store the complements in the trie. Just following the complementary branches when checking for a non-overlapping match is enough. And, taking the 0's directly as wildcards, no special wildcard is needed, either.
Mauro Lacy

2

Represent the bit vectors as an n×k matrix M. Take i and j between 1 and n.

(MMT)ij=lMilMjl.

(MMT)ij, the dot product of the ith and jth vector, is non-zero if, and only if, vectors i and j share a common 1. So, to find a solution, compute MMT and return the position of a zero entry, if such an entry exists.

Complexity

Using naive multiplication, this requires O(n2k) arithmetic operations. If n=k, it takes O(n2.37) operations using the utterly impractical Coppersmith-Winograd algorithm, or O(n2.8) using the Strassen algorithm. If k=O(n0.302), then the problem may be solved using n2+o(1) operations.


How is this different from Strilanc's answer?
D.W.

1
@D.W. Using an n-by-k matrix instead of an (n+k)-by-(n+k) matrix is an improvement. Also it mentions a way to cut off the factor of k when k << n, so that might be useful.
Craig Gidney
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.