কেউ হাস্কেলের স্মৃতিচারণের পেছনের ধারণাটি ব্যাখ্যা করতে পারে?


12

(নোট আমি প্রশ্নটি এখানে রাখছি কারণ এটি কোডিং সমস্যার পরিবর্তে এটির ধারণাগত মেকানিক্স সম্পর্কে)

আমি একটি ছোট প্রোগ্রামে কাজ করছিলাম, এটি তার সমীকরণে ফিবোনাচি সংখ্যাগুলির ক্রম ব্যবহার করছিলাম, তবে আমি লক্ষ্য করেছি যে আমি যদি একটি নির্দিষ্ট সংখ্যার উপরে পৌঁছে যাই তবে এটি বেদনাদায়কভাবে ধীর হয়ে উঠেছে, কিছুটা প্রায় গুগল করে আমি হাস্কেল নামে পরিচিত একটি প্রযুক্তিতে হোঁচট খেয়েছি Memoization, তারা কোডগুলি এভাবে কাজ করে দেখিয়েছিল:

-- Traditional implementation of fibonacci, hangs after about 30
slow_fib :: Int -> Integer
slow_fib 0 = 0
slow_fib 1 = 1
slow_fib n = slow_fib (n-2) + slow_fib (n-1)

-- Memorized variant is near instant even after 10000
memoized_fib :: Int -> Integer
memoized_fib = (map fib [0 ..] !!)
   where fib 0 = 0
         fib 1 = 1
         fib n = memoized_fib (n-2) + memoized_fib (n-1)

সুতরাং আপনাদের কাছে আমার প্রশ্নটি হল, কিভাবে বা বরং কেন এই কাজ করে?

এটি কি কারণ এটি কোনওভাবে হিসাব শুরুর আগে বেশিরভাগ তালিকার মধ্যে দিয়ে চালানো পরিচালনা করে? তবে হ্যাশেল যদি অলস হয় তবে সত্যিই এমন কোনও গণনা নেই যা ধরতে হবে ... সুতরাং এটি কীভাবে কাজ করবে?


1
আপনি নির্মল পারে আপনি দ্বারা কি বোঝাতে চেয়েছেন the calculation catches up। : BTW, memoization না নির্দিষ্ট Haskell হয় en.wikipedia.org/wiki/Memoization
সাইমন Bergot

কিলান এর উত্তরে আমার ব্যাখ্যা দেখুন
ইলেকট্রিক কফি

2
আপনার প্রশ্ন ভালবাসেন; কেবলমাত্র একটি দ্রষ্টব্য নোট: কৌশলটিকে মেমো আই জ্যাশন বলা হয় , মেমো রি জেশন নয়।
রাশেত

উত্তর:


11

কেবল প্রকৃত স্মৃতিচারণের পিছনে যান্ত্রিকগুলি ব্যাখ্যা করতে,

memo_fib = (map fib [1..] !!)

"থঙ্কস", অব্যক্ত গণনাগুলির একটি তালিকা তৈরি করে। এগুলি অনির্বাচিত উপহারগুলির মতো চিন্তা করুন, যতক্ষণ না আমরা তাদের স্পর্শ না করি, সেগুলি চলবে না।

এখন একবার আমরা কোনও কাণ্ডকে মূল্যায়ন করি, আমরা কখনই তা আর মূল্যায়ন করব না। এটি আসলে "স্বাভাবিক" হাস্কেলের পরিবর্তনের একমাত্র রূপ, কংক্রিটের মানগুলি হয়ে ওঠার জন্য থঙ্কস মিউটেট একবার মূল্যায়ন করে।

সুতরাং আপনার কোডে ফিরে আসুন, আপনি বংশের একটি তালিকা পেয়েছেন এবং আপনি এখনও এই গাছটি পুনরাবৃত্তি করেন, তবে আপনি তালিকাটি ব্যবহার করে পুনরাবৃত্তি করেন এবং তালিকার কোনও উপাদানটি একবার মূল্যায়ন করা গেলে এটি আর কখনও গণনা হয় না। সুতরাং, আমরা নিষ্পাপ ফাইব ফাংশনে গাছের পুনরাবৃত্তি এড়াতে চাই।

একটি স্পর্শকাতর আকর্ষণীয় নোট হিসাবে, এটি বিশেষত একটি সিরিজের ফাইবোনাসি সংখ্যার চেয়ে দ্রুত গতিযুক্ত যেহেতু সেই তালিকাটি কেবল একবার মূল্যায়ন করা হয় যার অর্থ আপনি যদি memo_fib 10000দুবার গণনা করেন তবে দ্বিতীয়বারটি তাত্ক্ষণিক হওয়া উচিত। এটি হ্যাসেল কেবল একবার ফাংশনে যুক্তির মূল্যায়ন করে এবং আপনি ল্যাম্বদার পরিবর্তে আংশিক অ্যাপ্লিকেশন ব্যবহার করছেন।

টিএলডিআর: একটি তালিকায় গণনা সঞ্চয় করে, তালিকার প্রতিটি উপাদান একবার মূল্যায়ন করা হয়, সুতরাং, প্রতিটি ফাইবোনাকির সংখ্যা পুরো প্রোগ্রাম জুড়ে ঠিক একবার গণনা করা হয়।

ভিজুয়ালাইজেশান:

 [THUNK_1, THUNK_2, THUNK_3, THUNK_4, THUNK_5]
 -- Evaluating THUNK_5
 [THUNK_1, THUNK_2, THUNK_3, THUNK_4, THUNK_3 + THUNK_4]
 [THUNK_1, THUNK_2, THUNK_1 + THUNK_2, THUNK_4, THUNK_3 + THUNK_4]
 [1, 1, 1 + 1, THUNK_4, THUNK_3 + THUNK_4]
 [1, 1, 2, THUNK_4, 2 + THUNK4]
 [1, 1, 2, 1 + 2, 2 + THUNK_4]
 [1, 1, 2, 3, 2 + 3]
 [1, 1, 2, 3, 5]

সুতরাং আপনি দেখতে পাচ্ছেন যে মূল্যায়নের জন্য কীভাবে THUNK_4তাড়াতাড়ি করা হয়েছে কারণ এটি ইতিমধ্যে মূল্যায়ন করা হয়েছে be


তালিকার মানগুলি সংক্ষিপ্ত ক্রমের জন্য কীভাবে আচরণ করে তার একটি উদাহরণ আপনি সরবরাহ করতে পারেন? আমি মনে করি এটি কীভাবে কাজ করার কথা বলে এর ভিজ্যুয়ালাইজেশনে যুক্ত হতে পারে ... এবং এটি সত্য যে আমি যদি memo_fibএকই মান দিয়ে দু'বার কল করি তবে দ্বিতীয়বার তাত্ক্ষণিকভাবে আসে, তবে আমি যদি এটির সাথে 1 টি উচ্চতর মান দিয়ে কল করি তবে এটি এখনও মূল্যায়ন করতে চিরকাল লাগে (যেমন 30 থেকে 31 তে যান)
বৈদ্যুতিন কফি

@ ইলেক্ট্রিক কফি যুক্ত হয়েছে
ড্যানিয়েল

@ ইলেক্ট্রিক কফি না, সেহেতু এটি ইতিমধ্যে হবে না memo_fib 29এবং memo_fib 30এরই মধ্যে মূল্যায়ন করা হয়েছে, এই দুটি সংখ্যা যুক্ত করতে এটি যতক্ষণ সময় নেবে ঠিক তেমন সময় লাগবে :) একবার যখন কোনও কিছু ইভাল-এড হয়ে যায়, তখন তা স্পষ্ট থাকে।
ড্যানিয়েল গ্রেটজার

1
@ ইলেক্ট্রিক কফি আপনার পুনরাবৃত্তি তালিকার মধ্য দিয়ে যেতে হবে, অন্যথায় আপনি কোনও কার্যকারিতা অর্জন করতে পারবেন না
ড্যানিয়েল গ্রেটজার

2
@ ইলেক্ট্রিককফি তবে তালিকার ৩১ তম উপাদানটি গত গণনাগুলি ব্যবহার করছে না, আপনি হ্যাঁ স্মরণ করিয়ে দিচ্ছেন, তবে একটি সুন্দর অকেজো উপায়ে .. যে গণনাগুলি পুনরাবৃত্তি হয়েছে তা দুবার গণনা করা হয় না, তবে আপনার কাছে এখনও প্রতিটি নতুন মানের জন্য বৃক্ষ পুনরাবৃত্তি রয়েছে যা খুব, খুব ধীর
ড্যানিয়েল গ্রেটজার

1

স্মৃতিচারণের বিন্দু কখনও একই ফাংশন দু'বার গণনা করা যায় না - এটি নিখুঁতভাবে কার্যকরী গণনাগুলি গতি বাড়ানোর পক্ষে অত্যন্ত কার্যকর, অর্থাত্ পার্শ্ব প্রতিক্রিয়া ছাড়াই, কারণ তাদের ক্ষেত্রে প্রক্রিয়াটি নির্ভুলতার প্রভাব ছাড়াই সম্পূর্ণ স্বয়ংক্রিয়ভাবে পরিচালিত হতে পারে। এটি বিশেষ করে যেমন ফাংশনগুলির fiboজন্য গাছের পুনরাবৃত্তি , অর্থাত্ প্রচেষ্টা, যখন নিখরচায় প্রয়োগ করা হয় তার জন্য এটি বিশেষভাবে প্রয়োজনীয় । (ফিবোনাচি সংখ্যাগুলি আসলে পাঠদানের পুনরাবৃত্তির জন্য খুব খারাপ উদাহরণ - এটি টিউটোরিয়াল বা বইগুলিতে আপনি যে সমস্ত ডেমো বাস্তবায়ন পান সেগুলি বড় ইনপুট মানগুলির জন্য অকার্যকর one

আপনি সঞ্চালনের প্রবাহ ট্রেস থাকে, তাহলে আপনি দ্বিতীয় ক্ষেত্রে দেখতে হবে, মান fib xযখন সবসময় উপলব্ধ হবে fib x+1মৃত্যুদন্ড কার্যকর করা হয়, এবং রানটাইম সিস্টেম, কেবল স্মৃতি থেকে বদলে অন্য recursive কল মাধ্যমে এটি পড়তে সক্ষম হতে হবে যখন ছোট সমাধানের জন্য ফলাফলগুলি উপলব্ধ হওয়ার আগে প্রথম সমাধান বৃহত্তর সমাধানটি গণনা করার চেষ্টা করে। এটি শেষ পর্যন্ত কারণ पुनरावृत्तीকারীটি [0..n]বাম থেকে ডানে মূল্যায়ন করা হয় এবং তাই এটি দিয়ে শুরু হবে 0, যখন প্রথম উদাহরণে পুনরাবৃত্তিটি শুরু হয় nএবং কেবল তখনই জিজ্ঞাসা করে n-1। এটি হ'ল বহু, বহু অপ্রয়োজনীয় সদৃশ ফাংশন কল।


ওহ, আমি এর বিন্দুটি বুঝতে পেরেছি, আমি কোডটিতে যা দেখতে পাচ্ছি তার থেকে এটি কীভাবে কাজ করে তা কেবল বুঝতে পারি না যে আপনি memorized_fib 20উদাহরণস্বরূপ লেখেন map fib [0..] !! 20, আপনি আসলে ঠিক লিখছেন , তখনও এটি গণনা করা দরকার 20 অবধি সম্পূর্ণ পরিসীমা, বা আমি এখানে কিছু মিস করছি?
বৈদ্যুতিন কফি

1
হ্যাঁ, তবে প্রতিটি সংখ্যার জন্য কেবল একবার। নিষ্পাপ বাস্তবায়ন fib 2প্রায়শই গণনা করে এটি আপনার মাথা ঘূর্ণায়মান করে তুলবে - এগিয়ে যান, কল ট্রি ফুরের মতো লিখুন যেমন একটি ছোট মান n==5। এটি আপনাকে কী সংরক্ষণ করে তা একবার দেখলে আপনি আর স্মৃতি ভুলতে পারবেন না।
কিলিয়ান ফুট

@ ইলেক্ট্রিক কফি: হ্যাঁ, এটি 1 থেকে 20 এর ফাইব গণনা করবে that কল থেকে আপনি কিছু অর্জন করতে পারেন না। এখন fib 21 গণনা করার চেষ্টা করুন, এবং আপনি দেখতে পাবেন যে 1-21 গণনা করার পরিবর্তে আপনি কেবল 21 টি গণনা করতে পারেন কারণ আপনার ইতিমধ্যে 1-20 গণনা করা হয়েছে এবং এটি আবার করার দরকার নেই।
ফোশি

আমি কল ট্রিটি লেখার চেষ্টা করছি n = 5, এবং আমি বর্তমানে এমন পর্যায়ে পৌঁছেছি যেখানে n == 3এতদূর ভাল, তবে সম্ভবত এটি কেবল আমার অপরিহার্য মন এটি ভেবেছে, তবে এর অর্থ এই নয় যে n == 3আপনি কেবল পান map fib [0..]!!3? যা তখন fib nপ্রোগ্রামের শাখায় যায় ... আমি প্রাক-গণিত ডেটার সুবিধাটি কোথা থেকে পাই?
বৈদ্যুতিন কফি

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