একটি আঙুল গাছ কাঠামো বুটস্ট্র্যাপিং


16

বেশ খানিকটা ২-৩ আঙুল গাছ নিয়ে কাজ করার পরে বেশিরভাগ অপারেশনে আমি তাদের গতি দেখে মুগ্ধ হয়েছি। যাইহোক, আমি যে ইস্যুটি চালিয়েছি তা হ'ল বড় আঙুলের গাছের প্রাথমিক তৈরির সাথে যুক্ত বড় ওভারহেড। যেহেতু বিল্ডিংকে সংক্ষিপ্তকরণের ক্রিয়াকলাপ হিসাবে সংজ্ঞায়িত করা হয় আপনি প্রচুর পরিমাণে আঙুলের গাছের কাঠামো তৈরি করে শেষ করেন যা অবিবাহিত।

২-৩ টি আঙুল গাছের জটিল প্রকৃতির কারণে আমি এগুলি বুটস্ট্র্যাপ করার জন্য কোনও স্বজ্ঞাত পদ্ধতি দেখছি না, এবং আমার সমস্ত অনুসন্ধান খালি উঠে এসেছে। সুতরাং প্রশ্নটি হল, আপনি কীভাবে নূন্যতম ওভারহেড দিয়ে একটি 2-3 আঙুল গাছ বুটস্ট্র্যাপিং সম্পর্কে যেতে পারেন?

স্পষ্ট হবে: একটি ক্রম দেওয়া পরিচিত দৈর্ঘ্যের এন আঙ্গুল গাছ উপস্থাপনা উৎপন্ন এস ন্যূনতম অপারেশন সঙ্গে।SnS

সম্পন্ন করার সহজ উপায় হ'ল কনস অপারেশনের ধারাবাহিক কল (সাহিত্যে ' ' অপারেটর)। যাইহোক, এই তৈরি করবে এন সব টুকরা প্রতিনিধিত্বমূলক স্বতন্ত্র আঙুল গাছ কাঠামো এস জন্য [ 1 .. আমি ]nS[1..i]



@ ডেভ আমি প্রকৃতপক্ষে তাদের কাগজপত্র কার্যকর করেছি, এবং তারা দক্ষ সৃষ্টিকে সম্বোধন করে না।
jbondeson

আমি যতটা মূর্ত.
ডেভ ক্লার্ক

এই ক্ষেত্রে "বিল্ড" বলতে কী বোঝাতে চেয়েছেন আপনি কি আরও কিছুটা নির্দিষ্ট হতে পারেন? এটি কি একটি অনাবৃত?
jbapple

@jbapple - আমি বিভ্রান্তির জন্য আরও স্পষ্ট, দুঃখিত বলে সম্পাদনা করেছি।
jbondeson

উত্তর:


16

GHC এর Data.Sequence'র replicateফাংশন একটি fingertree তৈরী করে সময় এবং স্থান, কিন্তু এই উপাদান আছে যা পেতে দ্য-গো থেকে আঙুল গাছের অধিকার মেরুদণ্ড যেতে বুদ্ধিমান দ্বারা সক্রিয় করা হয়। এই গ্রন্থাগারটি মূল কাগজের লেখকরা লিখেছিলেন 2-3 আঙুলের গাছে onহে(এলজিএন)

আপনি যদি বারবার কনটেন্টেশন দিয়ে আঙুলের গাছ বানাতে চান তবে আপনি মেরুদণ্ডের উপস্থাপনা পরিবর্তন করে বিল্ডিংয়ের সময় ক্ষণস্থায়ী স্থানের ব্যবহার হ্রাস করতে সক্ষম হতে পারেন। 2-3 আঙুলের গাছে থাকা স্পাইনগুলি চতুরতার সাথে সিঙ্ক্রোনাইজড একক-লিঙ্কযুক্ত তালিকাগুলি হিসাবে সংরক্ষণ করা হয়। পরিবর্তে, আপনি যদি মেরুদণ্ডগুলি ডেক হিসাবে সংরক্ষণ করেন তবে গাছগুলি সংমিশ্রনের সময় স্থান সংরক্ষণ করা সম্ভব হতে পারে। ধারণাটি হ'ল একই উচ্চতার দুটি গাছ গাছের মেরুদণ্ড পুনরায় ব্যবহার করে স্থান নেয় । মূলত বর্ণিত হিসাবে 2-3 আঙ্গুলের গাছগুলি সংশ্লেষ করার সময়, নতুন গাছে অভ্যন্তরীণ মেরুদণ্ডগুলি আর যেমন হয় তেমন ব্যবহার করা যাবে না।হে(1)

ক্যাপলান এবং টার্জনের "কেটনেবল সাজানো তালিকার বিশুদ্ধ কার্যকরী প্রতিনিধিত্বগুলি" আরও জটিল আঙুলের গাছের কাঠামো বর্ণনা করে। এই কাগজটিতে (বিভাগে 4) আমি উপরে তৈরি ডিক পরামর্শের অনুরূপ একটি নির্মাণ সম্পর্কেও আলোচনা করেছি। আমি বিশ্বাস করি যে তারা যে কাঠামোটির বর্ণনা করেছেন তা সময় এবং স্থানের সমান উচ্চতার দুটি গাছকে সংযুক্ত করতে পারে । আঙুলের গাছ তৈরির জন্য, আপনার জন্য কি এই পর্যাপ্ত জায়গাটি সাশ্রয় হচ্ছে?হে(1)

এনবি: "বুটস্ট্র্যাপিং" শব্দটির তাদের ব্যবহারের অর্থ উপরের আপনার ব্যবহারের চেয়ে কিছুটা আলাদা। এর অর্থ একই কাঠামোর একটি সহজ সংস্করণ ব্যবহার করে কোনও ডেটা স্ট্রাকচারের কিছু অংশ সঞ্চয় করা।


একটি খুব আকর্ষণীয় ধারণা। আমাকে এটি খতিয়ে দেখতে হবে এবং সামগ্রিক ডেটা স্ট্রাকচারে ট্রেড-অফগুলি কী হবে তা দেখতে হবে।
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])))

কিছু সাধারণ পরীক্ষায়, এটি একটি আকর্ষণীয় পারফরম্যান্স ট্রেড অফ করেছে। উপরের মূল ফাংশনটি MyFromList এর চেয়ে প্রায় 1/3 কম দৌড়েছিল fromList। অন্যদিকে, myFromList2MB এর ধ্রুবক স্তূপ ব্যবহৃত হয়, যখন মানটি fromList926MB অবধি ব্যবহৃত হয়। 926MB একবারে পুরো তালিকা মেমরির মধ্যে রাখা প্রয়োজন থেকে উদ্ভূত। এদিকে, সমাধানটি myFromListঅলস স্ট্রিমিং ফ্যাশনে কাঠামোটি গ্রাস করতে সক্ষম। গতির ফলাফল এই বিষয়টি থেকে যেটি myFromListপ্রায় বরাদ্দ দ্বিগুণ করতে হবে (রাজ্য মনডের জুড়ি নির্মাণ / ধ্বংসের ফলস্বরূপ) হিসাবেfromList। আমরা সিপিএস-রুপান্তরিত রাষ্ট্র মোনাডে গিয়ে এই বরাদ্দগুলি অপসারণ করতে পারি, তবে ফলস্বরূপ যে কোনও সময়ে আরও বেশি স্মৃতি ধরে রাখা যায়, কারণ অলসতার ক্ষতিতে তালিকাটি স্ট্রিমিং পদ্ধতিতে অনুসরণ করা প্রয়োজন vers

অন্যদিকে, যদি শোয়ের সাথে পুরো ক্রমটি চাপিয়ে দেওয়ার পরিবর্তে, আমি কেবল মাথা বা শেষ উপাদানটি বের করতে চলে যাই, myFromListতাত্ক্ষণিকভাবে একটি বড় জয় উপস্থাপন করি - মাথা উপাদানটি বের করা প্রায় তাত্ক্ষণিক, এবং শেষ উপাদানটি বের করা 0.8s হয় । এদিকে, স্ট্যান্ডার্ড সহ fromList, মাথা বা শেষ উপাদানটি উত্তোলনের জন্য খরচ হয় ~ 2.3 সেকেন্ড।

এটি সমস্ত বিবরণ, এবং এটি বিশুদ্ধতা এবং অলসতার পরিণতি। পরিব্যক্তি এবং এলোমেলো অ্যাক্সেসের মতো পরিস্থিতিতে আমি কল্পনা করব replicateসমাধানটি আরও ভাল।

যাইহোক, এটি এমন প্রশ্নটি উত্থাপন করে applicativeTreeযে myFromListএ জাতীয় পুনর্লিখনের কোনও উপায় রয়েছে যা আরও কঠোরভাবে দক্ষ। বিষয়টি হ'ল আমি মনে করি, গাছ প্রাকৃতিকভাবে বিচ্যুত হওয়ার চেয়ে প্রয়োগযোগ্য ক্রিয়াকলাপগুলি একটি ভিন্ন ক্রমে সম্পাদিত হয় তবে আমি কীভাবে এটি কাজ করে তা সম্পূর্ণরূপে কাজ করতে পারি নি, বা যদি সমাধান করার কোনও উপায় থাকে তবে।


4
(1) আকর্ষণীয়। ভালো দেখায় এই কাজের করার সঠিক উপায় হল। শুনে আমি অবাক হয়েছি যে পুরো ক্রমটি যখন বাধ্য করা হয় তার চেয়ে ধীর । (২) হতে পারে এই উত্তরটি খুব কোড-ভারী এবং cstheory.stackexchange.com এর জন্য ভাষা-নির্ভর। ভাষা-স্বতন্ত্র পদ্ধতিতে কীভাবে কাজ করে তা আপনি যদি একটি ব্যাখ্যা যুক্ত করতে পারেন তবে এটি দুর্দান্ত । fromListreplicateA
সোসোশি ইটো

9

আপনি মধ্যবর্তী আঙুলের বৃহত সংখ্যক কাঠামো দিয়ে সজ্জিত করার সময়, তারা তাদের কাঠামোর বিশাল অংশ একে অপরের সাথে ভাগ করে নেয়। শেষ পর্যন্ত আপনি আদর্শের ক্ষেত্রে দ্বিগুণ মেমরি বরাদ্দ করেন এবং বাকীটি প্রথম সংগ্রহের সাথে মুক্ত হয়। এগুলির অ্যাসিম্পটোটিকগুলি যেমন তারা পেতে পারে ঠিক তেমনি আপনাকে শেষ পর্যন্ত এন মান দিয়ে ভরাট একটি আঙুলের গাছ দরকার।

আপনি Data.FingerTree.replicateব্যবহার FingerTree.fmapWithPosকরতে তাদের ব্যবহার করে এবং সেগুলি আপনার সীমাবদ্ধ ক্রমের ভূমিকা পালন করতে পারে এমন একটি অ্যারেতে আপনার মানগুলি সন্ধান traverseWithPosকরার জন্য বা একটি তালিকা বা অন্য পরিচিত আকারের ধারক থেকে তাদের ছাঁটাই করে ব্যবহার করে ফিঙ্গারট্রি তৈরি করতে পারেন ।

হে(লগএন)হে(এন)হে(লগএন)

হে(লগএন)replicateAmapAccumL

টিএল; ডিআর যদি আমার এটি করতে হয় তবে আমি সম্ভবত ব্যবহার করতাম:

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

এবং একটি নির্দিষ্ট আকারের অ্যারেতে সূচি দেওয়ার জন্য আমি কেবল উপরের (arr !)জন্য সরবরাহ করব f

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.