एक बूट ट्री संरचना बूटस्ट्रैपिंग


16

2-3 अंगुल वृक्षों के साथ काम करने के बाद मैं बहुत से ऑपरेशनों में उनकी गति से प्रभावित हुआ। हालाँकि, मैंने जो एक मुद्दा चलाया है वह एक बड़े उंगली के पेड़ के प्रारंभिक निर्माण से जुड़ा हुआ एक बड़ा ओवरहेड है। क्योंकि निर्माण को आपस में जुड़ने वाले संचालन के अनुक्रम के रूप में परिभाषित किया जाता है, जिसे आप बड़ी संख्या में उंगली के पेड़ की संरचनाओं का निर्माण करते हैं जो कि अनावश्यक हैं।

2-3 अंगुल वृक्षों की जटिल प्रकृति के कारण मुझे बूटस्ट्रैपिंग के लिए कोई सहज विधि नहीं दिखाई देती है, और मेरी सभी खोजें खाली हो गई हैं। तो सवाल यह है कि आप न्यूनतम ओवरहेड के साथ 2-3 उंगली के पेड़ को बूटस्ट्रैप करने के बारे में कैसे जा सकते हैं?

स्पष्ट होना करने के लिए: एक दृश्य दिया जाना जाता लंबाई के की उंगली पेड़ प्रतिनिधित्व उत्पन्न न्यूनतम संचालन के साथ।SnS

पूरा करने का भोला तरीका सामान्य ऑपरेशन (साहित्य में ' ' ऑपरेटर) के लिए लगातार कॉल है । बहरहाल, यह पैदा करेगा के सभी स्लाइस का प्रतिनिधित्व अलग उंगली वृक्ष संरचना के लिए ।एन एस [ १ .. मैं ]nS[1..i]


1
क्या उंगली के पेड़: हिंज़ और पैटरसन द्वारा एक सामान्य सामान्य प्रयोजन डेटा संरचना उत्तर प्रदान करती है?
डेव क्लार्क

@ क्या मैंने वास्तव में उनके पेपर को लागू किया है, और वे कुशल निर्माण को संबोधित नहीं करते हैं।
jbondeson

मुझे इतना ज्यादा लगा।
डेव क्लार्क

क्या आप इस मामले में "बिल्ड" के अर्थ से थोड़ा अधिक विशिष्ट हो सकते हैं? क्या यह एक अनकही बात है?
जप्पल

@jbapple - मैंने एक अधिक स्पष्ट होने के लिए संपादित किया, भ्रम के लिए खेद है।
१:07:०५ पर जॉन्डेसन

जवाबों:


16

GHC के Data.Sequenceके replicateसमारोह में एक fingertree बनाता समय और स्थान है, लेकिन इस तत्वों कि get-जाने से उंगली ट्री के दाईं ओर रीढ़ की हड्डी पर जाना जानने से सक्षम है। यह लाइब्रेरी 2-3 उंगली के पेड़ों पर मूल पेपर के लेखकों द्वारा लिखी गई थी।हे(एलजीn)

यदि आप बार-बार संघनन द्वारा एक उंगली के पेड़ का निर्माण करना चाहते हैं, तो आप रीढ़ के प्रतिनिधित्व को बदलकर निर्माण करते समय क्षणिक स्थान के उपयोग को कम करने में सक्षम हो सकते हैं। 2-3 उंगली के पेड़ों पर रीढ़ को बड़ी चतुराई से सिंक्रनाइज़-लिंक्ड सूची के रूप में संग्रहीत किया जाता है। यदि, इसके बजाय, आप रीढ़ को देवताओं के रूप में संग्रहीत करते हैं, तो पेड़ों को समतल करते समय अंतरिक्ष को बचाने के लिए संभव हो सकता है। विचार यह है कि पेड़ों की रीढ़ का पुन: उपयोग करके एक ही ऊंचाई के दो पेड़ों को समेटकर स्थान लिया जाता है। जब मूल रूप से वर्णित के रूप में 2-3 उंगली के पेड़ों को समतल करते हैं, तो नए पेड़ के लिए आंतरिक रूप से उपयोग किए जाने वाले स्पाइन का उपयोग अब नहीं किया जा सकता है।हे(1)

कपलान और टारजन की "प्योरली फंक्शनल रिप्रजेंटेशन ऑफ कैटेनएबल सॉर्टेड लिस्ट" में एक अधिक जटिल उंगली के पेड़ की संरचना का वर्णन किया गया है। यह पत्र (खंड 4 में) भी एक निर्माण के बारे में चर्चा करता है जो कि मेरे द्वारा किए गए छल के सुझाव के समान है। मेरा मानना ​​है कि वे जिस संरचना का वर्णन करते हैं, वह समय और स्थान में समान ऊंचाई के दो पेड़ों को समतल कर सकती है। उंगली के पेड़ों के निर्माण के लिए, क्या यह आपके लिए पर्याप्त जगह की बचत है?हे(1)

NB: शब्द "बूटस्ट्रैपिंग" के उनके उपयोग का मतलब है कि आपके उपयोग के ऊपर कुछ अलग है। वे एक ही संरचना का एक सरल संस्करण का उपयोग कर एक डेटा संरचना का हिस्सा भंडारण का मतलब है।


एक बहुत ही दिलचस्प विचार। मुझे इस पर गौर करना होगा और देखना होगा कि समग्र डेटा संरचना के लिए व्यापार-नापसंद क्या होगा।
jbondeson

मेरा मतलब था कि इस उत्तर में दो विचार होंगे: (1) लगभग समान रूप से आकार के पेड़ों के लिए प्रतिकृति विचार (2) तेज़। मुझे लगता है कि यदि इनपुट एक सरणी है, तो प्रतिकृति विचार बहुत कम अतिरिक्त स्थान पर उंगली के पेड़ का निर्माण कर सकता है।
jbapple

हां, मैंने दोनों को देखा। क्षमा करें, मैंने उन दोनों पर टिप्पणी नहीं की। मैं पहले प्रतिकृति कोड में देख रहा हूं - हालांकि मैं निश्चित रूप से अपने हास्केल ज्ञान को बढ़ा रहा हूं जहां तक ​​यह जाएगा। पहले ब्लश पर यह दिखता है कि यह उन अधिकांश मुद्दों को हल कर सकता है जो मैं कर रहा हूं, बशर्ते आपके पास तेजी से रैंडम एक्सेस हो। रैंडम एसेस न होने की स्थिति में फास्ट कॉनैट थोड़ा अधिक सामान्य समाधान हो सकता है।
jbondeson

10

के बारे में jbapple के शानदार जवाब पर रिफ़िंग replicate, लेकिन इसके बजाय replicateA(जो replicateपर बनाया गया है) का उपयोग करके , मैं निम्नलिखित के साथ आया:

--Unlike fromList, one needs the length explicitly. 
myFromList :: Int -> [b] -> Seq b
myFromList l xs = flip evalState xs $ Seq.replicateA l go
    where go = do
           (y:ys) <- get
            put ys
            return y

myFromList(थोड़े अधिक कुशल संस्करण में) पहले से परिभाषित है और आंतरिक रूप से Data.Sequenceउंगली के पेड़ों के निर्माण के लिए उपयोग किया जाता है जो कि प्रकार के परिणाम हैं।

सामान्य तौर पर, अंतर्ज्ञान replicateAसरल है। एप्लिकेशनट्रीट्री फ़ंक्शन के replicateAशीर्ष पर बनाया गया है। एक आकार के पेड़ का एक टुकड़ा लेता है , और इस की प्रतियां युक्त एक अच्छी तरह से संतुलित पेड़ का उत्पादन करता है । के लिए मामलों 8 अप करने के लिए (एक उंगली) हार्ड कोडित रहे हैं। इसके ऊपर कुछ भी, और यह खुद को पुनरावर्ती रूप से आमंत्रित करता है। "आवेदक" तत्व बस यह है कि यह पेड़ के निर्माण को उन प्रभावों से फैलाता है, जैसे कि उपरोक्त कोड, स्थिति।applicativeTreemnnDeep

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

कुछ और ठोस नोट

main = print (length (show (Seq.fromList [1..10000000::Int])))

कुछ सरल परीक्षणों पर, इसने एक दिलचस्प प्रदर्शन ट्रेडऑफ़ प्राप्त किया। ऊपर मुख्य समारोह लगभग 1/3 से कम चला गया myFromList के साथ की तुलना में fromList। दूसरी ओर, myFromList2MB के एक निरंतर ढेर का fromListउपयोग किया , जबकि मानक 926MB तक का उपयोग किया। वह 926MB एक बार में पूरी सूची को मेमोरी में रखने की आवश्यकता से उत्पन्न होती है। इस बीच, समाधान myFromListएक आलसी स्ट्रीमिंग फैशन में संरचना का उपभोग करने में सक्षम है। इस तथ्य से गति के परिणाम के myFromListरूप में कई आवंटन (राज्य निर्माण के विनाश के रूप में जोड़ी निर्माण / विनाश के परिणामस्वरूप) के रूप में लगभग दो बार प्रदर्शन करना चाहिएfromList। हम उन आवंटन को एक सीपीएस-रूपांतरित राज्य मोनड में स्थानांतरित करके समाप्त कर सकते हैं, लेकिन इसके परिणामस्वरूप किसी भी समय अधिक स्मृति को धारण किया जा सकता है, क्योंकि आलस्य के नुकसान को गैर-स्ट्रीमिंग तरीके से सूची का पता लगाने की आवश्यकता होती है।

दूसरी ओर, अगर एक शो के साथ पूरे अनुक्रम को मजबूर करने के बजाय, मैं सिर्फ सिर या आखिरी तत्व को निकालने के लिए आगे बढ़ता हूं, तो myFromListतुरंत एक बड़ी जीत प्रस्तुत करता है - सिर के तत्व को निकालना लगभग तुरंत है, और अंतिम तत्व को निकालना 0.8 है । इस बीच, मानक के साथ fromList, सिर या अंतिम तत्व को निकालने में ~ 2.3 सेकंड का खर्च आता है।

यह सब विवरण है, और पवित्रता और आलस्य का परिणाम है। म्यूटेशन और रैंडम एक्सेस वाली स्थिति में, मुझे लगता है कि replicateसमाधान सख्ती से बेहतर होगा।

हालांकि, यह सवाल उठाता है कि क्या इस तरह के फिर से लिखने का एक तरीका है applicativeTreeजो myFromListसख्ती से अधिक कुशल है। मुद्दा यह है, मुझे लगता है, कि पेड़ से स्वाभाविक रूप से अलग-अलग क्रम में लागू किया जाता है, लेकिन मैंने पूरी तरह से काम नहीं किया है कि यह कैसे काम करता है, या अगर इसे हल करने का कोई तरीका है।


4
(१) दिलचस्प। यह इस कार्य को करने का सही तरीका लगता है । मैं यह सुनकर आश्चर्यचकित हूं कि यह धीमी गति से है fromListजब पूरे अनुक्रम को मजबूर किया जाता है। (२) शायद यह उत्तर बहुत भारी है और cstheory.stackexchange.com के लिए भाषा-निर्भर है। यह बहुत अच्छा होगा यदि आप एक स्पष्टीकरण जोड़ सकते हैं कि replicateAभाषा-स्वतंत्र तरीके से कैसे काम करता है।
त्सुयोशी इतो

9

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

आप उपयोग करके उंगलियों का निर्माण कर सकते हैं Data.FingerTree.replicateऔर उन्हें FingerTree.fmapWithPosअपने मूल्यों को एक सरणी में देखने के लिए उपयोग कर सकते हैं जो आपके परिमित अनुक्रम की भूमिका निभाता है, या traverseWithPosउन्हें सूची या अन्य ज्ञात आकार के कंटेनर से छीलने के लिए उपयोग करता है।

हे(लॉगn)हे(n)हे(लॉगn)

हे(लॉगn)replicateAmapAccumL

TL, डॉ। अगर मुझे ऐसा करना पड़ा, तो मैं शायद उपयोग करूंगा:

rep :: (Int -> a) -> Int -> Seq a 
rep f n = mapWithIndex (const . f) $ replicate n () 

और एक निश्चित आकार के सरणी में अनुक्रमण करने के लिए मैं सिर्फ ऊपर के (arr !)लिए आपूर्ति करूंगा f

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