बड़े सेट में कम हेमिंग दूरी के साथ कुशलता से बाइनरी स्ट्रिंग्स पाते हैं


80

मुसीबत:

अहस्ताक्षरित 32-बिट पूर्णांक, एक अहस्ताक्षरित 32-बिट पूर्णांक इनपुट मान और एक अधिकतम हैमिंगिंग दूरी की एक बड़ी (~ 100 मिलियन) सूची को देखते हुए , सभी सूची सदस्यों को वापस करें जो इनपुट मूल्य के निर्दिष्ट हेमिंग दूरी के भीतर हैं।

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

उदाहरण:

For a maximum Hamming Distance of 1 (values typically will be quite small)

And input: 
00001000100000000000000001111101

The values:
01001000100000000000000001111101 
00001000100000000010000001111101 

should match because there is only 1 position in which the bits are different.

11001000100000000010000001111101

should not match because 3 bit positions are different.

मेरे विचार अब तक:

0 की हेमिंग दूरी के पतित मामले के लिए, बस एक क्रमबद्ध सूची का उपयोग करें और विशिष्ट इनपुट मान के लिए एक द्विआधारी खोज करें।

अगर हमिंग की दूरी केवल 1 होगी, तो मैं मूल इनपुट में प्रत्येक बिट को फ्लिप कर सकता हूं और उपरोक्त 32 बार दोहरा सकता हूं।

मैं कैसे कुशलता से (पूरी सूची को स्कैन किए बिना) सूची सदस्यों को एक हेमिंग दूरी> 1 के साथ खोज सकता हूं।


उम्मीद की गई हैमिंग दूरी के आधार पर मानदंड बदलने के बारे में, एक आवर्तक फ़ंक्शन ऐसा कर सकता है। अगला कदम दो सूची के मिलन के लिए होगा।
XecP277

इस समस्या पर हाल ही में एक कागज़ बनाया गया है: बड़े पैमाने पर हमिंग दूरी क्वेरी प्रसंस्करण
हमार

@ एरिक ने कहा कि "1 की अधिकतम हेमिंग दूरी के लिए (मान आमतौर पर काफी छोटा होगा)" । क्या आप बता सकते हैं कि "काफी छोटा" क्या मतलब है?
स्टेफन पोचमैन

@ एरिक इसके अलावा, ~ 100 मिलियन नंबर सभी अद्वितीय थे, या डुप्लिकेट थे?
स्टीफन पोचमैन

@StefanPochmann: कोई डुप्लिकेट नहीं हैं। ब्याज की सबसे बड़ी दूरी 4-5 होगी।
एरिक जे।

जवाबों:


111

प्रश्न: हम्मिंग दूरी d (x, y) के बारे में क्या जानते हैं?

उत्तर:

  1. यह गैर-नकारात्मक है: d (x, y): 0
  2. समान इनपुट के लिए यह केवल शून्य है: d (x, y) = 0 y x = y
  3. यह सममित है: d (x, y) = d (y, x)
  4. यह त्रिभुज असमानता का पालन करता है , d (x, z) x d (x, y) + d (y, z)

प्रश्न: हम क्यों परवाह करते हैं?

उत्तर: क्योंकि यह मतलब है कि आलोचनात्मक अंतर एक है मीट्रिक एक के लिए मीट्रिक स्थान । मीट्रिक रिक्त स्थान को अनुक्रमित करने के लिए एल्गोरिदम हैं।

तुम भी "स्थानिक अनुक्रमण" सामान्य रूप में, ज्ञान के साथ सशस्त्र के लिए एल्गोरिदम देख सकते हैं कि आपके अंतरिक्ष इयूक्लिडियन नहीं है बल्कि यह है एक मीट्रिक स्पेस। इस विषय पर कई पुस्तकें एक मीट्रिक का उपयोग करके स्ट्रिंग अनुक्रमणिका को कवर करती हैं जैसे कि हैमिंग दूरी।

फुटनोट: यदि आप निश्चित चौड़ाई के तार की हैमिंग दूरी की तुलना कर रहे हैं, तो आप असेंबली या प्रोसेसर इंट्रिनिक्स का उपयोग करके एक महत्वपूर्ण प्रदर्शन सुधार प्राप्त करने में सक्षम हो सकते हैं। उदाहरण के लिए, जीसीसी ( मैनुअल ) के साथ आप ऐसा करते हैं:

static inline int distance(unsigned x, unsigned y)
{
    return __builtin_popcount(x^y);
}

यदि आप जीसीसी को सूचित करते हैं कि आप एसएसई 4 ए के साथ एक कंप्यूटर के लिए संकलन कर रहे हैं, तो मेरा मानना ​​है कि यह सिर्फ एक जोड़े को कम करना चाहिए।

संपादित करें: कई स्रोतों के अनुसार, यह सामान्य मुखौटा / शिफ्ट / ऐड कोड की तुलना में कभी-कभी धीमा होता है। बेंचमार्किंग से पता चलता है कि मेरे सिस्टम पर, C वर्जन आउटपरफॉर्म के GCC __builtin_popcountद्वारा लगभग 160% है।

परिशिष्ट: मैं स्वयं इस समस्या के बारे में उत्सुक था, इसलिए मैंने तीन कार्यान्वयनों को रेखांकित किया: रैखिक खोज, बीके वृक्ष, और वीपी वृक्ष। ध्यान दें कि वीपी और बीके पेड़ बहुत समान हैं। बीके के पेड़ में एक नोड के बच्चे उन पेड़ों के "गोले" होते हैं जिनमें पेड़ के केंद्र से प्रत्येक निश्चित दूरी होती है। VP ट्री में एक नोड के दो बच्चे होते हैं, एक नोड के केंद्र पर केंद्रित एक क्षेत्र के भीतर सभी बिंदुओं से युक्त होता है और दूसरा बच्चा बाहर के सभी बिंदुओं से युक्त होता है। तो आप कई महीन के बजाय दो बहुत मोटे "गोले" के साथ वीपी नोड को बीके नोड के रूप में सोच सकते हैं।

परिणाम मेरे 3.2 गीगाहर्ट्ज़ पीसी पर कैप्चर किए गए थे, और एल्गोरिदम कई कोर (जो आसान होना चाहिए) का उपयोग करने का प्रयास नहीं करते हैं। मैंने 100M छद्म आयामी पूर्णांक का एक डेटाबेस आकार चुना। परिणाम १.०० प्रश्नों की औसत दूरी १.५, और १०० प्रश्नों के लिए ६.१० और रैखिक खोज के लिए हैं।

  • डेटाबेस: 100M छद्म आयामी पूर्णांक
  • परीक्षणों की संख्या: दूरी 1..5 के लिए 1000, दूरी 6..10 और रैखिक के लिए 100
  • परिणाम: क्वेरी हिट का औसत # (बहुत अनुमानित)
  • गति: प्रति सेकंड प्रश्नों की संख्या
  • कवरेज: प्रति क्वेरी डेटाबेस की औसत प्रतिशतता
                - बीके ट्री - - वीपी ट्री - - रैखिक -
डिस्ट परिणाम स्पीड कोव स्पीड कोव स्पीड कोव
1 0.90 3800 0.048% 4200 0.048%
2 11 300 0.68% 330 0.65%
3 130 56 3.8% 63 3.4%
4 970 18 12% 22 10%
5 5700 8.5 26% 10 22%
6 2.6e4 5.2 42% 6.0 37%
7 1.1e5 3.7 60% 4.1 54%
8 3.5e5 3.0 74% 3.2 70%
9 1.0e6 2.6 85% 2.7 82%
10 2.5e6 2.3 91% 2.4 90%
कोई भी 2.2 100%

अपनी टिप्पणी में, आपने उल्लेख किया:

मुझे लगता है कि बीके-पेड़ों को अलग-अलग रूट नोड्स के साथ बीके-पेड़ों का एक गुच्छा पैदा करके और उन्हें फैलाने से बेहतर किया जा सकता है।

मुझे लगता है कि यही कारण है कि वीपी पेड़ बीके पेड़ से बेहतर (थोड़ा) प्रदर्शन करता है। "Shallower" के बजाय "गहरा" होने के कारण, यह कम अंक के मुकाबले महीन-दाने वाली तुलना का उपयोग करने के बजाय अधिक बिंदुओं के खिलाफ तुलना करता है। मुझे संदेह है कि उच्च आयामी स्थानों में अंतर अधिक चरम हैं।

एक अंतिम टिप: पेड़ में लीफ नोड्स एक रैखिक स्कैन के लिए पूर्णांकों के समतल सरणियाँ होनी चाहिए। छोटे सेट (शायद 1000 अंक या उससे कम) के लिए यह तेज और अधिक मेमोरी कुशल होगा।


9
हुर्रे! मेरा 10k प्रतिनिधि यहाँ है ;-)
डिट्रिच एप

मैंने मीट्रिक स्थान पर विचार किया, लेकिन मैंने इसे खारिज कर दिया जब मुझे एहसास हुआ कि सब कुछ एक साथ कितना करीब है। स्पष्ट रूप से, बीके-पेड़ सिर्फ जानवर बल है, और इसलिए यह एक अनुकूलन नहीं होगा। एम-ट्री और वीपी-ट्री एक अनुकूलन नहीं होंगे क्योंकि सब कुछ एक साथ कितना करीब है। (4 की एक हामिंग दूरी दो की दूरी से मेल खाती है, जबकि 2 की एक हामिंग दूरी रूट दो की दूरी से मेल खाती है।)
नील जी।

1
निश्चित आकार के पूर्णांकों के लिए हैमिंग की दूरी L1 मानदंड के समान होती है, यदि आप पूर्णांक को बिट्स के तार मानते हैं। अन्यथा, दो तारों के बीच "मानक" एल 1 मान तत्वों के बीच सकारात्मक दूरी का योग है।
मोकोशा

2
@DietrichEpp यह सबसे आश्चर्यजनक उत्तरों में से एक है जो मैंने कभी एसओ पर पाया है। मैं यह पूछने वाला था कि सूचकांक बनाने में कितना समय लगता है, लेकिन फिर मैंने आपको कोड पोस्ट करते हुए देखा। उत्तर: 3.5Ghz i7-3770K पर, 1M आइटम BK ट्री 0.034s में बनाया गया है, और 100M आइटम BK वृक्ष 13s में बनाया गया है। वीपी पेड़ों को बनाने में लगभग 4 गुना अधिक समय लगता है, और मेरे प्रशंसकों को जोर से घूमना शुरू हो जाता है।
मार्क ई। हासे

2
@StefanPochmann: आपको लगता है कि "टिप्पणी जोड़ें" बटन के साथ "एक और उत्तर जोड़ें" बटन उलझन में है। पृष्ठ के नीचे देखें, आपको "एक और उत्तर जोड़ें" बटन मिलेगा।
डिट्रीच एप ईपी

13

मैंने एक समाधान लिखा जहां मैं 2 32 बिट्स के बिटसेट में इनपुट संख्याओं का प्रतिनिधित्व करता हूं , इसलिए मैं O (1) में जांच कर सकता हूं कि इनपुट में एक निश्चित संख्या है या नहीं। फिर एक queried संख्या और अधिकतम दूरी के लिए, मैं पुनः उस दूरी के भीतर सभी संख्याओं को उत्पन्न करता हूं और उन्हें बिटसेट के खिलाफ जांचता हूं।

अधिकतम दूरी 5 के लिए उदाहरण के लिए, यह 242825 संख्या है ( योग d = 0 से 5 {32 चुनें d} )। तुलना के लिए, उदाहरण के लिए डिट्रीच ईप का वीपी-ट्री समाधान 100 मिलियन नंबरों में से 22%, यानी 22 मिलियन नंबरों के माध्यम से जाता है।

मैंने अपने समाधान को जोड़ने और उसके साथ तुलना करने के लिए डायट्रिच के कोड / समाधान का उपयोग किया। 10 से अधिकतम दूरी के लिए, प्रति सेकंड प्रश्नों में गति हैं:

Dist     BK Tree     VP Tree         Bitset   Linear

   1   10,133.83   15,773.69   1,905,202.76   4.73
   2      677.78    1,006.95     218,624.08   4.70
   3      113.14      173.15      27,022.32   4.76
   4       34.06       54.13       4,239.28   4.75
   5       15.21       23.81         932.18   4.79
   6        8.96       13.23         236.09   4.78
   7        6.52        8.37          69.18   4.77
   8        5.11        6.15          23.76   4.68
   9        4.39        4.83           9.01   4.47
  10        3.69        3.94           2.82   4.13

Prepare     4.1s       21.0s          1.52s  0.13s
times (for building the data structure before the queries)

छोटी दूरी के लिए, बिटसेट समाधान चार में से सबसे तेज़ है। प्रश्न लेखक एरिक ने नीचे टिप्पणी की है कि ब्याज की सबसे बड़ी दूरी शायद 4-5 होगी। स्वाभाविक रूप से, मेरा बिटसेट समाधान बड़ी दूरी के लिए धीमा हो जाता है, यहां तक ​​कि रैखिक खोज की तुलना में धीमा (दूरी 32 के लिए, यह 2 32 संख्याओं के माध्यम से जाएगा )। लेकिन दूरी 9 के लिए यह अभी भी आसानी से जाता है।

मैंने डायट्रिच के परीक्षण को भी संशोधित किया। उपर्युक्त परिणामों में से प्रत्येक एल्गोरिदम को कम से कम तीन प्रश्नों को हल करने के लिए है और यह लगभग 15 सेकंड में कर सकते हैं (मैं 1, 2, 4, 8, 16, आदि प्रश्नों के साथ कम से कम 10 सेकंड तक राउंड करता हूं) कुल मिलाकर पारित)। यह काफी स्थिर है, मुझे भी सिर्फ 1 सेकंड के लिए समान संख्याएं मिलती हैं।

मेरा CPU एक i7-6700 है। मेरा कोड (डायट्रिच के आधार पर) यहाँ है (अभी तक कम से कम इस दस्तावेज़ को अनदेखा करें, निश्चित नहीं है कि इसके बारे में क्या करना है, लेकिन tree.cइसमें सभी कोड और मेरे test.batशो शामिल हैं कि मैंने कैसे संकलित किया और भाग गया (मैंने डिट्रिच से झंडे का इस्तेमाल किया Makefile)) ।मेरे समाधान के लिए शॉर्टकट

एक चेतावनी: मेरे क्वेरी परिणामों में केवल एक बार संख्याएँ होती हैं, इसलिए यदि इनपुट सूची में डुप्लिकेट संख्याएँ होती हैं, तो वे वांछित नहीं भी हो सकती हैं। प्रश्न लेखक एरिक के मामले में, कोई डुप्लिकेट नहीं था (नीचे टिप्पणी देखें)। किसी भी स्थिति में, यह समाधान उन लोगों के लिए अच्छा हो सकता है जिनके या तो इनपुट में कोई डुप्लिकेट नहीं है या क्वेरी परिणामों में डुप्लिकेट की आवश्यकता नहीं है या नहीं (मुझे लगता है कि यह संभावना है कि शुद्ध क्वेरी परिणाम केवल एक अंत के लिए साधन हैं और फिर कुछ अन्य कोड संख्याओं को किसी और चीज़ में बदल देते हैं, उदाहरण के लिए एक मैप जो किसी संख्या को उन फ़ाइलों की सूची में मैप कर रहा है जिनकी हैश वह संख्या है)।


ब्याज की सबसे बड़ी दूरी शायद 4-5 होगी, इसलिए यह समाधान बहुत दिलचस्प है। वास्तविक डोमेन में कोई डुप्लिकेट नहीं है जो प्रश्न को प्रेरित करता है।
एरिक जे।

3

एक सामान्य दृष्टिकोण (कम से कम मेरे लिए) पूर्व-चरण चरण के रूप में सटीक मिलान के लिए इन चंक्सों पर अपनी बिट स्ट्रिंग को कई टुकड़ों में विभाजित करना और क्वेरी करना है। यदि आप फ़ाइलों के साथ काम करते हैं, तो आप उतने ही फाइल बनाते हैं, जितने कि आपके पास हैं (जैसे 4 यहाँ) सामने वाले प्रत्येक चंक के साथ और फिर फ़ाइलों को क्रमबद्ध करें। आप एक बाइनरी खोज का उपयोग कर सकते हैं और आप बोनस के लिए मिलान मिलान के ऊपर और नीचे खोज का विस्तार भी कर सकते हैं।

आप फिर लौटे परिणामों पर एक बिटवाइज़ हैमिंग दूरी गणना कर सकते हैं जो आपके संपूर्ण डेटासेट का केवल एक छोटा उपसमूह होना चाहिए। यह डेटा फ़ाइलों या SQL तालिकाओं का उपयोग करके किया जा सकता है।

इसलिए पुनरावृत्ति करने के लिए: कहो कि आपके पास DB या फ़ाइलों में 32 बिट्स स्ट्रिंग्स का एक गुच्छा है और आप हर उस हैश को ढूंढना चाहते हैं जो 3 बिट्स की दूरी या आपके "क्वेरी" बिट स्ट्रिंग से कम है:

  1. चार स्तंभों के साथ एक तालिका बनाएं: प्रत्येक में 8 बिट्स होंगे (एक स्ट्रिंग या इंट के रूप में) 32 बिट्स हैश का स्लाइस, 1 से 4 तक। या यदि आप फ़ाइलों का उपयोग करते हैं, तो चार फाइलें बनाएं, प्रत्येक में स्लाइस का क्रमिक होना प्रत्येक "पंक्ति" के सामने एक "इस्लाम"

  2. qslice 1 से 4 में उसी तरह से अपनी क्वेरी बिट स्ट्रिंग को स्लाइस करें।

  3. इस तालिका को किसी भी तरह से क्वेरी करें qslice1=islice1 or qslice2=islice2 or qslice3=islice3 or qslice4=islice4। यह आपको प्रत्येक स्ट्रिंग देता 8 - 1है जो क्वेरी स्ट्रिंग के 7 बिट्स ( ) के भीतर है । यदि फ़ाइल का उपयोग कर रहे हैं, तो एक ही परिणाम के लिए चार अनुमत फ़ाइलों में से प्रत्येक में एक द्विआधारी खोज करें।

  4. प्रत्येक लौटी हुई बिट स्ट्रिंग के लिए, सटीक हैमिंग डिस्टेंस पेयर-वाइज को अपने साथ क्वेरी बिट स्ट्रिंग (चार-स्लाइस में से इंडेक्स-साइड बिट स्ट्रिंग्स का पुनर्निर्माण या तो डीबी से या एक अनुमति प्राप्त फ़ाइल से गणना करें)

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

अब निश्चित रूप से आपके मामले में, आप एक प्रकार के स्व-जुड़ाव की तलाश में हैं, यह सभी मूल्य हैं जो एक-दूसरे से कुछ दूरी पर हैं। एक ही दृष्टिकोण अभी भी IMHO काम करता है, हालांकि आपको क्रमपरिवर्तन (फ़ाइलों या सूचियों का उपयोग करके) के लिए एक प्रारंभिक बिंदु से ऊपर और नीचे का विस्तार करना होगा जो शुरुआती हिस्सा साझा करते हैं और परिणामस्वरूप क्लस्टर के लिए हैमिंग दूरी की गणना करते हैं।

यदि फ़ाइलों के बजाय मेमोरी में चल रहा है, तो आपके 100M 32 बिट्स स्ट्रिंग्स डेटा सेट 4 जीबी की सीमा में होंगे। इसलिए चार अनुमत सूचियों में लगभग 16GB + RAM की आवश्यकता हो सकती है। हालाँकि मुझे इसके बजाय मेमोरी मैप्ड फ़ाइलों के साथ उत्कृष्ट परिणाम मिलते हैं और समान आकार के डेटासेट के लिए कम RAM होना चाहिए।

खुला स्रोत कार्यान्वयन उपलब्ध हैं। अंतरिक्ष में सबसे अच्छा IMHO है जो मोज़ाह , सी ++ द्वारा सिम्हाश के लिए किया गया था , लेकिन 64 बिट्स स्ट्रिंग्स और 32 बिट्स के लिए डिज़ाइन नहीं किया गया था।

इस खुशहाल दूरी के दृष्टिकोण को सबसे पहले AFAIK ने मूसा चारीकर द्वारा "सिम्हाश" सेमिनल पेपर और संबंधित Google पेटेंट में वर्णित किया था :

  1. अपीयरिंग न्यूमैरेस्ट नाइटबार्च हार्मिंग स्पेस में

[...]

प्रत्येक बिट्स में d बिट्स से युक्त वैक्टर होते हैं, हम N = O (n 1 / (1+)) बिट्स का यादृच्छिक क्रमांकन चुनते हैं। प्रत्येक यादृच्छिक क्रमांकन ed के लिए, हम बिट वैक्टर के क्रमबद्ध क्रम O a को बनाए रखते हैं, बिट्स के लेक्सिकोग्राफ़िक क्रम में order द्वारा अनुमत। एक क्वेरी बिट वेक्टर q को देखते हुए, हम निम्नलिखित करके निकटतम निकटतम पड़ोसी का पता लगाते हैं:

प्रत्येक क्रमचय σ के लिए, हम O (perm द्वारा अनुमत बिट्स द्वारा प्राप्त लेक्सिकोग्राफ़िक क्रम में) निकटतम दो बिट वैक्टर का पता लगाने के लिए O locate पर एक द्विआधारी खोज करते हैं। अब हम प्रत्येक क्रमबद्ध क्रम में खोज करते हैं O ining ऊपर और नीचे की स्थिति के तत्वों की जाँच बाइनरी खोज द्वारा की गई सबसे लंबी उपसर्ग की लंबाई के क्रम में होती है जो q से मेल खाती है।

मोनिका हेन्जिगर ने अपने पेपर में "निकट-डुप्लिकेट वेब पृष्ठों को खोजना: एल्गोरिदम का एक बड़े पैमाने पर मूल्यांकन" का विस्तार किया :

3.3 एल्गोरिथ्म सी के लिए परिणाम

हमने प्रत्येक पृष्ठ की बिट स्ट्रिंग को 12 गैर-अतिव्यापी 4-बाइट टुकड़ों में विभाजित किया, जिससे 20B टुकड़े बने और सभी पृष्ठों की सी-समानता की गणना की, जिसमें कम से कम एक टुकड़ा था। इस दृष्टिकोण की गारंटी दी गई है कि 11 तक के अंतर वाले सभी जोड़ों को खोजने के लिए, यानी, सी-समानता 373, लेकिन बड़े अंतर के लिए कुछ छूट सकती है।

गुरमीत सिंह मनकू, अरविंद जैन, और अनीश दास सरमा द्वारा वेब क्रॉलिंग के पास-डुप्लिकेट का पता लगाने वाले पेपर में भी यह बताया गया है :

  1. स्मरण शक्ति समस्या

परिभाषा: f -bit उंगलियों के निशान और एक क्वेरी फिंगरप्रिंट F के संग्रह को देखते हुए, पहचानें कि क्या मौजूदा फिंगरप्रिंट F से सबसे k बिट में भिन्न है। (उपरोक्त समस्या के बैच-मोड संस्करण में, हमारे पास एक एकल क्वेरी फ़िंगरप्रिंट के बजाय क्वेरी फ़िंगरप्रिंट का एक सेट है)

[...]

अंतर्ज्ञान: 2 df की सॉर्ट की गई तालिका पर विचार करें-सही मायने में यादृच्छिक उंगलियों के निशान। तालिका में केवल सबसे महत्वपूर्ण डी बिट्स पर ध्यान दें। इन डी-बिट संख्याओं की एक सूची इस अर्थ में "लगभग एक काउंटर" है कि (ए) काफी कुछ 2 डी-बिट संयोजन मौजूद हैं, और (बी) बहुत कम डी-बिट संयोजन डुप्लिकेट हैं। दूसरी ओर, कम से कम महत्वपूर्ण f - d बिट "लगभग यादृच्छिक" हैं।

अब d ऐसा चुनें | d - d | एक छोटा पूर्णांक है। चूंकि तालिका छांटी गई है, इसलिए एक एकल जांच उन सभी उंगलियों के निशान की पहचान करती है जो घ में सबसे महत्वपूर्ण बिट-पदों से मेल खाते हैं। चूंकि | d - d | छोटा है, ऐसे मैचों की संख्या भी छोटी होने की उम्मीद है। प्रत्येक मिलान फिंगरप्रिंट के लिए, हम आसानी से यह पता लगा सकते हैं कि यह F से सबसे k बिट-पोज़िशन में भिन्न है या नहीं (ये अंतर स्वाभाविक रूप से f - d-महत्वपूर्ण बिट-पोज़िशन तक सीमित होगा)।

ऊपर वर्णित प्रक्रिया हमें एक मौजूदा फ़िंगरप्रिंट का पता लगाने में मदद करती है जो कि के-पोज़िशन्स में एफ से अलग है, जिनमें से सभी एफ-डी बिट्स के कम से कम महत्वपूर्ण एफ के बीच सीमित हैं। यह उचित संख्या में मामलों की देखभाल करता है। सभी मामलों को कवर करने के लिए, यह अगले खंड में औपचारिक रूप से उल्लिखित अतिरिक्त सॉर्ट किए गए तालिकाओं की एक छोटी संख्या का निर्माण करने के लिए पर्याप्त है।

नोट: मैंने संबंधित डीबी-केवल प्रश्न के समान उत्तर पोस्ट किया है


2

आप निर्दिष्ट हैमिंग दूरी के भीतर अपनी मूल सूची के हर संभव बदलाव की पूर्व-गणना कर सकते हैं, और इसे एक ब्लूम फ़िल्टर में संग्रहीत कर सकते हैं। यह आपको एक तेज़ "NO" देता है लेकिन जरूरी नहीं कि "YES" के बारे में स्पष्ट उत्तर हो।

हाँ के लिए, ब्लूम फ़िल्टर में प्रत्येक स्थिति से जुड़े सभी मूल मूल्यों की एक सूची संग्रहीत करें, और एक बार में उनके माध्यम से जाएं। गति / मेमोरी ट्रेड-ऑफ़ के लिए अपने ब्लूम फ़िल्टर का आकार चुनें।

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


कोई बहुत संभावना नहीं है? 2 प्रतिशत प्रविष्टियाँ मौजूद हैं।
नील जी

1

कैसे सूची को क्रमबद्ध करने के बारे में और फिर आपके द्वारा हेमिंगिंग दूरी के भीतर विभिन्न संभावित मूल्यों पर उस क्रमबद्ध सूची में एक द्विआधारी खोज कर रहा है?


2
1 की हैमिंग दूरी के लिए, यह उचित है क्योंकि मूल इनपुट के 32 क्रमांकन हैं (मूल इनपुट में प्रत्येक बिट को एक बार फ्लिप करें)। 2 की दूरी के लिए, कई और अधिक अनुमत इनपुट मान हैं जिनकी खोज करनी होगी।
एरिक जे।

2
1024 + 32 + 1 खोज बहुत बड़ी संख्या में बाइनरी खोज नहीं है। यहां तक ​​कि 32 ^ 3 खोजों कि कई नहीं है।

@ एरिक जे - हालांकि, 100 मीटर डेटा हैं। यह अभी भी उचित है - यह कहते हुए कि पोस्टर में "डेटा संरचना के निर्माण की लागत माध्यमिक है" - एक उचित बाधा दूरी के लिए।
19

देखें बिट स्ट्रिंग-पास-पड़ोसी-खोज है, जो विभिन्न प्रकार है, तो द्विआधारी खोज का उपयोग करता है।
डेनिस

1

इस समस्या को हल करने के लिए एक संभव दृष्टिकोण एक डिस्जॉइंट-सेट डेटा संरचना का उपयोग कर रहा है । यह विचार एक ही सेट में हामिंग दूरी <= k के साथ सूची सदस्यों को मर्ज करने का है। यहाँ एल्गोरिथ्म की रूपरेखा है:

  • प्रत्येक सूची सदस्य के लिए हैमिंग दूरी के साथ हर संभव मूल्य की गणना करें <= k। K = 1 के लिए, 32 मान हैं (32-बिट मान के लिए)। K = 2, 32 + 32 * 31/2 मान के लिए।

    • प्रत्येक गणना मूल्य के लिए , परीक्षण करें कि यह मूल इनपुट में है या नहीं। आप इस चेक को करने के लिए साइज़ 2 ^ 32 या हैश मैप के साथ एक सरणी का उपयोग कर सकते हैं।

    • यदि मूल्य मूल इनपुट में है, तो सूची सदस्य के साथ "यूनियन" ऑपरेशन करें

    • एक चर में निष्पादित यूनियन संचालन की संख्या रखें।

आप एल्गोरिथ्म को एन डिसऑइंट सेट (जहां एन इनपुट में तत्वों की संख्या है) के साथ शुरू करते हैं। हर बार जब आप एक यूनियन ऑपरेशन को अंजाम देते हैं, तो आप डिसऑइंटमेंट सेट की संख्या 1 से घटा देते हैं। जब एल्गोरिथ्म समाप्त हो जाता है, तो असंतुष्ट-सेट डेटा संरचना में हेमिंगिंग दूरी के साथ सभी मूल्य होंगे इस असंतुष्ट-सेट डेटा संरचना की गणना लगभग रैखिक समय में की जा सकती है ।


मुझे समझ नहीं आ रहा है। यदि आपका इनपुट सेट {11000000, 0110000, 00110000, 00011000, 00001100, 00000110, 00000011} और k = 2 है, तो मुझे लगता है कि आपका एल्गोरिथ्म प्रत्येक तत्व को उसके अगले पड़ोसी (वे हैमिंग दूरी 2) के साथ एकजुट करेगा, इस प्रकार उन सभी को एकजुट करेगा। । लेकिन 11000000 और 00000011 में हैमिंग की दूरी 2 नहीं है; उनकी हैमिंग की दूरी 4. है। असंतुष्ट सेट वनों (संघ-खोज) का उपयोग करने के साथ मूलभूत समस्या यह है कि महंगाई एक समतुल्य संबंध नहीं है।
जोनास कोल्कर

अच्छी बात! लेकिन आपको यह विचार करना होगा कि प्रत्येक तत्व को क्रमिक रूप से संसाधित किया जाता है और एक बार मैच देखने के बाद, मिलान किया गया तत्व सूची से हटा दिया जाता है। इसलिए, आपके उदाहरण में, 11000000 और 01100000 के बीच संघ संचालन के बाद, बाद वाला 00110000 के साथ संघ के लिए उपलब्ध नहीं होगा। आप 5 सेटों के साथ समाप्त होंगे और आप प्रत्येक सेट के एक प्रतिनिधि तत्व के साथ इनपुट की तुलना करेंगे।
मर्सियो फोंसेका

मुझे आपका सुझाव समझ नहीं आया। शायद आप इसे कोड कर सकते हैं (एन के कुछ छोटे मूल्य के लिए)? यहाँ परीक्षण करने के लिए एक चीज़ है: यदि आपके पास चार सूची के सदस्य हैं x, y, z, w, जिनमें से प्रत्येक में हामिंग दूरी 3 से अगली है, और आपकी क्वेरी हैमिंग दूरी 5 है, तो x और y एक ही समतुल्य वर्ग से संबंधित होंगे (यानी संघ-खोज वृक्ष)? Y और Z होगा? Z और w होगा? आप आउटपुट कक्षाओं का उपयोग कैसे करते हैं यह तय करने के लिए कि आउटपुट क्या है? जहाँ तक मैं बता सकता हूँ, अगर आप किसी भी चीज़ के लिए यूनियन-खोज का उपयोग कर रहे हैं, तो आप अपने आउटपुट को डी-डुप्लिकेट करने के लिए उपयोग कर रहे हैं, जो मुझे लगता है कि हैश-सेट सिर्फ एक अच्छा काम कर सकता है। लेकिन मुझे यकीन नहीं है कि मैं समझ गया हूं?
जोनास कोल्कर

1

यहां एक सरल विचार है: 100 मीटर इनपुट पूर्णांकों के बाइट-वार रेडिक्स प्रकार, सबसे महत्वपूर्ण बाइट पहले, कुछ बाहरी संरचना में पहले तीन स्तरों पर बाल्टी सीमाओं का ट्रैक रखना।

क्वेरी करने के लिए, dऔर अपने इनपुट शब्द की दूरी के बजट के साथ शुरू करें w। बाइट मान के साथ शीर्ष स्तर में प्रत्येक बाल्टी के लिए b, और के उच्च बाइट के d_0बीच हैमिंग दूरी की गणना करें । उस बकेट को एक बार फिर से खोज लें : प्रत्येक बाइट मान के लिए , के बीच और दूसरी बाइट के बीच हैमिंग दूरी हो । तीसरी बार में , और इसी तरह के बजट के साथ खोज करें ।bwd - d_0b'd_1b'wd - d_0 - d_1

ध्यान दें कि बाल्टी एक पेड़ बनाते हैं। जब भी आपका बजट नकारात्मक हो जाए, तो उस सबट्री को खोजना बंद कर दें। यदि आप अपने दूरी के बजट को उड़ाने के बिना पुन: एक पत्ती में उतरते हैं, तो उस पत्ते का मूल्य आउटपुट का हिस्सा होना चाहिए।

बाहरी बकेट सीमा संरचना का प्रतिनिधित्व करने का एक तरीका यहां है: लंबाई की एक सरणी है 16_777_216 ( = (2**8)**3 = 2**24), जहां सूचकांक में तत्वi बाल्टी का प्रारंभिक सूचकांक है जिसमें रेंज [256 * i, 256 * i + 255] है। सूचकांक को उस बाल्टी के अंत से परे खोजने के लिए, सूचकांक i + 1 को देखें (या i + 1 = 2 ** 24 के लिए सरणी के अंत का उपयोग करें)।

मेमोरी बजट 100 मीटर * 4 बाइट्स प्रति शब्द = 400 एमबी इनपुट्स के लिए है, और 2 ** 24 * 4 बाइट्स प्रति पता = इंडेक्सिंग संरचना के लिए 64 मिब, या कुल में आधा गिग शर्मीला है। कच्चे डेटा पर इंडेक्सिंग संरचना 6.25% ओवरहेड है। बेशक, एक बार जब आप अनुक्रमण संरचना का निर्माण कर लेते हैं, तो आपको केवल प्रत्येक इनपुट शब्द के निम्नतम बाइट को स्टोर करने की आवश्यकता होती है, क्योंकि अन्य तीनों को अनुक्रमणिका संरचना में सूचकांक में निहित किया जाता है, कुल ~ (64 + 50) एमबी के लिए।

यदि आपके इनपुट को समान रूप से वितरित नहीं किया गया है, तो आप अपने इनपुट शब्दों के बिट्स को एक (एकल, सार्वभौमिक रूप से साझा) क्रमचय के साथ अनुमति दे सकते हैं जो पेड़ के शीर्ष की ओर सभी एन्ट्रापी डालता है। इस तरह, प्रूनिंग का पहला स्तर सर्च स्पेस के बड़े हिस्से को खत्म कर देगा।

मैंने कुछ प्रयोग करने की कोशिश की, और यह लीनियर खोज के बारे में भी, कभी-कभी और भी बुरा होता है। इस फैंसी विचार के लिए बहुत कुछ। ओह ठीक है, कम से कम यह स्मृति कुशल है।


इस विकल्प को साझा करने के लिए धन्यवाद। मेरे वातावरण में "मेमोरी सस्ती है", लेकिन एक मेमोरी-कुशल समाधान किसी और को लाभान्वित कर सकता है।
एरिक जे
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.