ডায়নামিক প্রোগ্রামিং কী? [বন্ধ]


276

ডায়নামিক প্রোগ্রামিং কী ?

এটি পুনরাবৃত্তি, স্মৃতিচারণ ইত্যাদি থেকে কীভাবে আলাদা?

আমি এটিতে উইকিপিডিয়া নিবন্ধটি পড়েছি , তবে আমি এখনও এটি সত্যি বুঝতে পারি না।


1
এখানে মাইকেল এ ট্রিকের সিএমইউর একটি টিউটোরিয়াল যা আমি বিশেষভাবে সহায়ক বলে মনে করেছি: mat.gsia.cmu.edu/classes/dynamic/dynamic.html অন্যরা যে সমস্ত সংস্থান দ্বারা প্রস্তাবিত হয়েছে তা ছাড়াও এটি অবশ্যই রয়েছে (অন্যান্য সমস্ত সংস্থান, বিশেষত সিএলআর এবং ক্লেইনবার্গ, টার্ডোস খুব ভাল!)। আমার এই টিউটোরিয়ালটি কেন পছন্দ করার কারণ এটি মোটামুটি ধীরে ধীরে উন্নত ধারণাগুলি প্রবর্তন করে। এটি কিছুটা পুরাতন উপাদান তবে এটি এখানে উপস্থাপিত তালিকার একটি ভাল সংযোজন। : এছাড়াও স্টিভেন Skiena পৃষ্ঠা এবং ডায়নামিক প্রোগ্রামিং এর উপর লেকচার খুঁজে বার করো cs.sunysb.edu/~algorith/video-lectures করুন: http
Edmon

11
আমি সর্বদা "ডায়নামিক প্রোগ্রামিং" কে একটি বিভ্রান্তিকর শব্দ পেয়েছি - "ডায়নামিক" স্থির নয়, তবে "স্ট্যাটিক প্রোগ্রামিং" কী? এবং "... প্রোগ্রামিং" মনে রাখে "অবজেক্ট ওরিয়েন্টেড প্রোগ্রামিং" এবং "ফাংশনাল প্রোগ্রামিং", এটি সুপারিশ করে যে ডিপি একটি প্রোগ্রামিং দৃষ্টান্ত। আমার আর ভাল নাম নেই (সম্ভবত "ডায়নামিক অ্যালগোরিদম"?) তবে এটি খুব খারাপ যে আমরা এইটির সাথে আটকে আছি stuck
dimo414

3
@ ডিমো 414 এখানে "প্রোগ্রামিং" আরও বেশি সম্পর্কিত "লিনিয়ার প্রোগ্রামিং" এর সাথে সম্পর্কিত যা গাণিতিক অপ্টিমাইজেশন পদ্ধতিগুলির একটি শ্রেণির অধীনে আসে। অন্যান্য গাণিতিক প্রোগ্রামিং পদ্ধতির তালিকার জন্য নিবন্ধ গাণিতিক অপ্টিমাইজেশন দেখুন ।
সাইকেট

1
@ dimo414 এই প্রসঙ্গে "প্রোগ্রামিং" কম্পিউটারের কোড লেখার জন্য নয়, একটি সারণী পদ্ধতিকে বোঝায়। - কোরিম্যান
ব্যবহারকারী 2618142

Cs.stackexchange.com/questions/59797/… এ বর্ণিত বাসের টিকিটের মূল্য হ্রাসকরণ সমস্যাটি ডায়নামিক প্রোগ্রামিংয়ে সবচেয়ে ভাল সমাধান করা হয়েছে।
ট্রুথহোল্ডার

উত্তর:


210

ডায়নামিক প্রোগ্রামিং হ'ল আপনি যখন ভবিষ্যতের সমস্যা সমাধান করা সহজ করার জন্য অতীত জ্ঞান ব্যবহার করেন।

একটি ভাল উদাহরণ হ'ল ফিবোনাচি সিকোয়েন্সটি n = 1000,002 এর জন্য।

এটি খুব দীর্ঘ প্রক্রিয়া হবে তবে আমি যদি আপনাকে n = 1,000,000 এবং n = 1,000,001 এর ফলাফল দিই? হঠাৎ সমস্যাটি আরও পরিচালনাযোগ্য হয়ে উঠল।

ডায়নামিক প্রোগ্রামিং স্ট্রিং এডিট সমস্যা যেমন স্ট্রিং সমস্যাগুলিতে প্রচুর ব্যবহৃত হয়। আপনি সমস্যার একটি উপসেট (গুলি) সমাধান করুন এবং তারপরে আরও জটিল মূল সমস্যাটি সমাধান করতে সেই তথ্যটি ব্যবহার করুন।

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

করম্যান অ্যালগরিদম বইটিতে ডায়নামিক প্রোগ্রামিং সম্পর্কে একটি দুর্দান্ত অধ্যায় রয়েছে। এবং এটি গুগল বুকে বিনামূল্যে! এটি এখানে দেখুন।


50
আপনি কি স্মৃতিচারণের বর্ণনা দিচ্ছেন না?
ড্রেডওয়েল

31
আমি বলব মেমোইজেশন হ'ল ডায়নামিক প্রোগ্রামিংয়ের একটি রূপ, যখন মেমোয়েজড ফাংশন / পদ্ধতিটি পুনরাবৃত্তি হয়।
ড্যানিয়েল হাকস্টেপ

6
উত্তম উত্তর, কেবলমাত্র সর্বোত্তম উপ-কাঠামো সম্পর্কে একটি উল্লেখ যুক্ত করবে (উদাহরণস্বরূপ, এ থেকে বি পর্যন্ত সংক্ষিপ্ততম পথের যে কোনও পথের প্রতিটি উপসেট নিজেই একটি দূরত্বের মেট্রিক ধরে ত্রিভুজের বৈষম্যকে ধরে রাখে এমন দুটি প্রান্তের মধ্যে সংক্ষিপ্ততম পথ)।
শেয়া

5
আমি "সহজ" বলব না, তবে দ্রুত। একটি সাধারণ ভুল বোঝাবুঝি হ'ল ডিপি এমন সমস্যা সমাধান করে যা নিষ্কলুষ অ্যালগরিদমগুলি পারে না এবং এটি তেমন নয়। কার্যকারিতা নয়, পারফরম্যান্সের বিষয়।
andandandand

6
মেমোইজেশন ব্যবহার করে ডায়নামিক প্রোগ্রামিং সমস্যাগুলি টপ ডাউন পদ্ধতিতে সমাধান করা যায়। অর্থাত্ চূড়ান্ত মান গণনা করার জন্য ফাংশনটি কল করা এবং সেই ফাংশনটি এটিকে নিমজ্জনিতভাবে সাব-প্রবলেমগুলি সমাধান করার জন্য কল করে। এগুলি ব্যতীত, গতিশীল প্রোগ্রামিংয়ের সমস্যাগুলি কেবল নীচের অংশে সমাধান করা যায়।
প্রণব

175

ডায়নামিক প্রোগ্রামিং হ'ল একটি কৌশল যা পুনরাবৃত্ত আলগোরিদিমে একই সাবপ্রব্লেম একাধিকবার গণনা এড়াতে ব্যবহৃত হয়।

আসুন ফিবোনাচি সংখ্যাগুলির সহজ উদাহরণটি গ্রহণ করি: সংজ্ঞায়িত n তম ফিবোনাচি সংখ্যাটি সন্ধান করুন

এফ এন = এফ এন -1 + এফ এন -2 এবং এফ 0 = 0, এফ 1 = 1

recursion

এটি করার সুস্পষ্ট উপায়টি পুনরাবৃত্তিযোগ্য:

def fibonacci(n):
    if n == 0:
        return 0
    if n == 1:
        return 1

    return fibonacci(n - 1) + fibonacci(n - 2)

ডায়নামিক প্রোগ্রামিং

  • শীর্ষ ডাউন - স্মৃতিচারণ

পুনরাবৃত্তি অনেক অপ্রয়োজনীয় গণনা করে কারণ প্রদত্ত ফিবোনাচি নম্বরটি একাধিকবার গণনা করা হবে। এর উন্নতি করার একটি সহজ উপায় হল ফলাফলগুলি ক্যাশে করা:

cache = {}

def fibonacci(n):
    if n == 0:
        return 0
    if n == 1:
        return 1
    if n in cache:
        return cache[n]

    cache[n] = fibonacci(n - 1) + fibonacci(n - 2)

    return cache[n]
  • বটম-আপ

এটি করার একটি আরও ভাল উপায় হ'ল সঠিক ক্রমে ফলাফলগুলি মূল্যায়ন করে পুনরাবৃত্তিটি সর্বত্র একত্রিত করা:

cache = {}

def fibonacci(n):
    cache[0] = 0
    cache[1] = 1

    for i in range(2, n + 1):
        cache[i] = cache[i - 1] +  cache[i - 2]

    return cache[n]

আমরা এমনকি ধ্রুবক স্থান ব্যবহার করতে পারি এবং কেবল প্রয়োজনীয় আংশিক ফলাফলগুলি পথে সংরক্ষণ করতে পারি:

def fibonacci(n):
  fi_minus_2 = 0
  fi_minus_1 = 1

  for i in range(2, n + 1):
      fi = fi_minus_1 + fi_minus_2
      fi_minus_1, fi_minus_2 = fi, fi_minus_1

  return fi
  • ডায়নামিক প্রোগ্রামিং কীভাবে প্রয়োগ করবেন?

    1. সমস্যার পুনরাবৃত্তি সন্ধান করুন।
    2. টপ-ডাউন: প্রতিটি সাব-প্রবলেমের জন্য উত্তরটি একটি টেবিলের মধ্যে সংরক্ষণ করুন যাতে সেগুলি পুনরায় সংশোধন না করে।
    3. নীচে আপ: ফলাফলগুলি মূল্যায়নের জন্য সঠিক ক্রমটি সন্ধান করুন যাতে প্রয়োজনে আংশিক ফলাফল পাওয়া যায়।

ডায়নামিক প্রোগ্রামিং সাধারণত সেই সমস্যাগুলির জন্য কাজ করে যাগুলির অন্তর্নিহিত বাম থেকে ডান ক্রম যেমন স্ট্রিং, ট্রি বা পূর্ণসংখ্যার ক্রম। যদি নিষ্কলুষ পুনরাবৃত্তির অ্যালগরিদম একই সাব-প্রব্লেমটিকে একাধিকবার গণনা না করে তবে ডায়নামিক প্রোগ্রামিং সাহায্য করবে না।

যুক্তিটি বুঝতে সহায়তা করার জন্য আমি সমস্যার একটি সংগ্রহ করেছি: https://github.com/tristanguigue/dynamic- প্রোগ্রামিং


3
এটি দুর্দান্ত উত্তর এবং গিথুবের সমস্যা সংগ্রহও খুব দরকারী। ধন্যবাদ!
p4sh4

বিষয়গুলি পরিষ্কার করার জন্য কৌতূহলের বাইরে - আপনার মতে, একটি পুনরাবৃত্তির সম্পর্ক এবং স্মৃতি ব্যবহার করে একটি পুনরাবৃত্তি বাস্তবায়ন গতিশীল প্রোগ্রামিং?
কোডার

ব্যাখ্যার জন্য ধন্যবাদ. নীচের অংশ থেকে নিচে থেকে কোনও শর্ত অনুপস্থিত রয়েছে: if n in cacheউপরের নিচের উদাহরণের মতো বা আমিও কিছু মিস করছি।
ডেভিডসি

আমি কি সঠিকভাবে বুঝতে পারি যে প্রতিটি পুনরাবৃত্তিতে গণনা করা মানগুলি পরবর্তী পুনরাবৃত্তিতে ব্যবহৃত হয় এমন কোনও লুপটি গতিশীল প্রোগ্রামিংয়ের উদাহরণ?
আলেক্সি

টপ-ডাউন এবং ডাউন-আপ বিশেষ কেসগুলি সহ আপনি যে ব্যাখ্যাটি দিয়েছেন তার জন্য আপনি কোনও রেফারেন্স দিতে পারেন?
অ্যালেক্সি

37

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

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

ডায়নামিক প্রোগ্রামিং হ'ল উপ-সমস্যাগুলি সমাধান করার সহজ সমাধান এবং সেখান থেকে উত্তর তৈরি করার প্রক্রিয়া। বেশিরভাগ ডিপি অ্যালগরিদমগুলি লোভী অ্যালগরিদম (যদি বিদ্যমান থাকে) এবং একটি ক্ষতিকারক (সমস্ত সম্ভাবনার গণনা করুন এবং সেরাটি সন্ধান করুন) অ্যালগরিদমের মধ্যে চলমান সময়ে হবে।

  • ডিপি অ্যালগরিদমগুলি পুনরাবৃত্তি সহ প্রয়োগ করা যেতে পারে, তবে সেগুলি হওয়ার দরকার নেই।
  • মেমোয়াইজেশন দ্বারা ডিপি অ্যালগরিদমগুলি গতি বাড়ানো যায় না, কারণ প্রতিটি উপ-সমস্যা কেবল একবার সমাধান করা হয় (বা "সমাধান" ফাংশন বলে) একবার।

খুব স্পষ্টভাবে বলা। আমি আশা করি অ্যালগরিদম প্রশিক্ষকরা এটি ভালভাবে ব্যাখ্যা করতে পারে।
কেলি এস ফরাসী

21

এটি আপনার অ্যালগরিদমের একটি অপ্টিমাইজেশন যা চলমান সময়কে হ্রাস করে।

যদিও লোভী অ্যালগরিদমকে সাধারণত নিখুঁত বলা হয় , কারণ এটি একই সেট ডেটার একাধিকবার চলতে পারে, ডায়নামিক প্রোগ্রামিং চূড়ান্ত সমাধান গঠনে সহায়তা করতে আংশিক ফলাফলগুলির গভীর বোঝার মাধ্যমে এই ক্ষতিটিকে এড়িয়ে চলে।

একটি সহজ উদাহরণ হ'ল নোডগুলির মাধ্যমে গাছ বা একটি গ্রাফকে অনুসরণ করা যা সমাধানে অবদান রাখবে বা আপনি এতক্ষণে যে সমাধানগুলি পেয়েছেন সেগুলি একটি টেবিলের মধ্যে রেখে দিচ্ছেন যাতে আপনি একই নোডগুলি বার বার অতিক্রম করতে পারবেন।

ইউভিএ'র অনলাইন বিচারক থেকে ডায়নামিক প্রোগ্রামিংয়ের জন্য উপযুক্ত এমন সমস্যার উদাহরণ এখানে রয়েছে: পদক্ষেপ মই সম্পাদনা করুন।

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

এই সমস্যাটিকে ভাল করে দেখুন, আমরা যদি দুটি স্ট্রিংয়ের পরিমাণ কতটুকু প্রযোজ্য তা ব্যয় করে আমাদের একটি ব্যয় নির্ধারণ করে, আমাদের দুটি প্রাকৃতিক ধরণের পরিবর্তন বিবেচনা করে থাকে:

প্রতিস্থাপন - "শ" থেকে "স্পট" এ পরিবর্তনের মতো পাঠ্য "টি" এর একটি ভিন্ন চরিত্রে প্যাটার্ন "এস" থেকে একটি একক অক্ষর পরিবর্তন করুন।

সন্নিবেশ - পাঠ্য "টি" এর সাথে মেলে "ago" এর সাথে প্যাটার্ন "s" তে একটি অক্ষর সন্নিবেশ করান, যেমন "পূর্বে" "অ্যাগ্রোগ" এ পরিবর্তন করা।

মুছে ফেলা - "টি" এর সাথে টেক্সট মেলাতে সহায়তা করতে প্যাটার্ন "s" থেকে একটি অক্ষর মুছুন, যেমন "ঘন্টা" পরিবর্তন করে "আমাদের" করুন to

যখন আমরা এই পদক্ষেপের প্রতিটি সেট করে এক ধাপ ব্যয় করি তখন আমরা দুটি স্ট্রিংয়ের মধ্যে সম্পাদনার দূরত্বটি নির্ধারণ করি। তাহলে আমরা কীভাবে এটি গণনা করব?

আমরা পর্যবেক্ষণটি ব্যবহার করে একটি পুনরাবৃত্তির অ্যালগরিদম সংজ্ঞায়িত করতে পারি যে স্ট্রিংয়ের শেষ অক্ষরটি অবশ্যই ম্যাচ, প্রতিস্থাপন, sertedোকানো বা মুছে ফেলা উচিত। শেষ সম্পাদনা ক্রিয়াকলাপে অক্ষরগুলি কেটে ফেলার ফলে একটি জুড়ি অপারেশন এক জোড়া ছোট ছোট স্ট্রিং ফেলে। I এবং j যথাক্রমে এবং t এর প্রাসঙ্গিক উপসর্গের সর্বশেষ চরিত্র হয়ে উঠি। শেষ অপারেশনের পরে তিন জোড়া সংক্ষিপ্ত স্ট্রিং রয়েছে, ম্যাচ / প্রতিস্থাপন, সন্নিবেশ বা মোছার পরে স্ট্রিংয়ের সাথে সম্পর্কিত। আমরা যদি তিনটি ছোট স্ট্রিংগুলির সম্পাদনার ব্যয়টি জানতাম, তবে আমরা সিদ্ধান্ত নিতে পারি যে কোন বিকল্পটি সবচেয়ে ভাল সমাধানের দিকে নিয়ে যায় এবং সেই বিকল্পটি সেই অনুযায়ী চয়ন করতে পারি। পুনরাবৃত্তি হওয়া দুর্দান্ত জিনিসটির মাধ্যমে আমরা এই ব্যয়টি শিখতে পারি:

#define MATCH 0 /* enumerated type symbol for match */
#define INSERT 1 /* enumerated type symbol for insert */
#define DELETE 2 /* enumerated type symbol for delete */


int string_compare(char *s, char *t, int i, int j)

{

    int k; /* counter */
    int opt[3]; /* cost of the three options */
    int lowest_cost; /* lowest cost */
    if (i == 0) return(j * indel(’ ’));
    if (j == 0) return(i * indel(’ ’));
    opt[MATCH] = string_compare(s,t,i-1,j-1) +
      match(s[i],t[j]);
    opt[INSERT] = string_compare(s,t,i,j-1) +
      indel(t[j]);
    opt[DELETE] = string_compare(s,t,i-1,j) +
      indel(s[i]);
    lowest_cost = opt[MATCH];
    for (k=INSERT; k<=DELETE; k++)
    if (opt[k] < lowest_cost) lowest_cost = opt[k];
    return( lowest_cost );

}

এই অ্যালগরিদম সঠিক, তবে অসম্ভব ধীর।

আমাদের কম্পিউটারে চলমান, দুটি 11-বর্ণের দুটি স্ট্রিং তুলনা করতে বেশ কয়েক সেকেন্ড সময় লাগে, এবং গণনাটি আর কখনও কখনও কখনও কখনও না ঘটে into

অ্যালগরিদম এত ধীর কেন? এটি ক্ষতিকারক সময় নেয় কারণ এটি বারবার মানগুলি পুনরায় সংশোধন করে। স্ট্রিংয়ের প্রতিটি অবস্থানে, পুনরাবৃত্তিটি তিনটি উপায়ে শাখা করে, এর অর্থ এটি কমপক্ষে 3 ^ n হারে বৃদ্ধি পায় - প্রকৃতপক্ষে, আরও দ্রুত কলগুলি দুটি সূচকগুলির মধ্যে একটি হ্রাস করে, উভয়ই নয়।

তাহলে আমরা কীভাবে অ্যালগরিদমকে ব্যবহারিক করে তুলতে পারি? গুরুত্বপূর্ণ পর্যবেক্ষণটি হ'ল এই পুনরাবৃত্তির কলগুলির মধ্যে বেশিরভাগই এমন জিনিসগুলি কম্পিউটিং করা হয় যা ইতিমধ্যে গণনা করা হয়েছিল। আমরা কিভাবে জানব? ঠিক আছে, কেবলমাত্র | গুলি | · | টি | সম্ভাব্য অনন্য পুনরাবৃত্ত কলগুলি, যেহেতু পুনরাবৃত্ত কলগুলির পরামিতি হিসাবে পরিবেশন করতে কেবলমাত্র অনেকগুলি পৃথক (i, j) জোড়া রয়েছে।

একটি টেবিলের মধ্যে এইগুলির (আই, জে) জোড়াগুলির জন্য মানগুলি সঞ্চয় করে আমরা সেগুলি পুনর্নির্মাণ এড়াতে পারি এবং প্রয়োজন অনুযায়ী সেগুলি সন্ধান করতে পারি।

টেবিলটি একটি দ্বি-মাত্রিক ম্যাট্রিক্স মি যেখানে প্রতিটি | s | · | t | প্রতি কোষগুলিতে এই সাবপ্রব্লেমটির সর্বোত্তম সমাধানের ব্যয় পাশাপাশি আমরা কীভাবে এই অবস্থানে পৌঁছেছি তা বোঝাতে একটি পিতামাতার পয়েন্টার রয়েছে:

typedef struct {
int cost; /* cost of reaching this cell */
int parent; /* parent cell */
} cell;

cell m[MAXLEN+1][MAXLEN+1]; /* dynamic programming table */

গতিশীল প্রোগ্রামিং সংস্করণটির পুনরাবৃত্ত সংস্করণ থেকে তিনটি পার্থক্য রয়েছে।

প্রথমত, এটি পুনরাবৃত্তির কলগুলির পরিবর্তে টেবিল প্রদর্শন ব্যবহার করে এর মধ্যবর্তী মানগুলি লাভ করে।

** দ্বিতীয়, ** এটি প্রতিটি ঘরের মূল ক্ষেত্র আপডেট করে, যা পরবর্তী সময়ে সম্পাদনা ক্রমটি পুনর্গঠন করতে সক্ষম করবে।

** তৃতীয়, ** তৃতীয়, এটি cell()কেবল এম [| এস |] [| টি |]। কোস্ট ফিরে আসার পরিবর্তে আরও সাধারণ লক্ষ্য ফাংশন ব্যবহার করে চালিত হয়। এটি আমাদের সমস্যার বিস্তৃত শ্রেণিতে এই রুটিনটি প্রয়োগ করতে সক্ষম করবে।

এখানে, সর্বাধিক অনুকূল আংশিক ফলাফল সংগ্রহ করতে যা লাগে তার একটি বিশেষ বিশ্লেষণ, যা সমাধানটিকে "গতিশীল" করে তোলে।

এখানে একই সমস্যার একটি বিকল্প, সম্পূর্ণ সমাধান রয়েছে। এটি কার্যকর করার পরেও এটি কার্যকর একটি "গতিশীল"। আমি আপনাকে পরামর্শ দিচ্ছি যে ইউভিএর অনলাইন বিচারকের কাছে জমা দিয়ে সমাধানটি কতটা কার্যকর by আমি এত বিস্ময়কর সমস্যাটি এত দক্ষতার সাথে কীভাবে মোকাবেলা করেছি তা আশ্চর্যজনক বলে মনে করি।


সত্যিই কি স্টোরেজটির গতিশীল প্রোগ্রামিং হওয়া দরকার? কাজের পরিমাণ এড়িয়ে যাওয়া কোনও অ্যালগরিদমকে গতিশীল হিসাবে যোগ্যতা অর্জন করবে না?
Nthalk

আপনি আছে অনুকূল জড়ো করা ধাপে ধাপে ফলাফল একটি আলগোরিদিম "গতিশীল" করা। ডায়নামিক প্রোগ্রামিং OR এ বেলম্যানের কাজ থেকে শুরু করে, যদি আপনি বলেন যে "যে কোনও পরিমাণ শব্দ বাদ দেওয়া ডায়নামিক প্রোগ্রামিং" আপনি এই শব্দটিকে অবমূল্যায়ন করছেন, কারণ কোনও অনুসন্ধানের heuristic হবে গতিশীল প্রোগ্রামিং। en.wikipedia.org/wiki/Dynamic_programming
andandandand

12

ডায়নামিক প্রোগ্রামিংয়ের মূল বিটগুলি হ'ল "ওভারল্যাপিং সাব-সমস্যাগুলি" এবং "সর্বোত্তম কাঠামো"। সমস্যার এই বৈশিষ্ট্যগুলির অর্থ একটি অনুকূল সমাধান তার উপ-সমস্যার সর্বোত্তম সমাধানগুলির সমন্বয়ে গঠিত। উদাহরণস্বরূপ, সবচেয়ে সংক্ষিপ্ত পথের সমস্যাগুলি সর্বোত্তম কাঠামোগত প্রদর্শন করে। এ থেকে সি পর্যন্ত সংক্ষিপ্ততম পথ হ'ল এ থেকে কিছু নোড বি এর সংক্ষিপ্ততম পথ এবং তারপরে সেই নোড বি থেকে সি পর্যন্ত সবচেয়ে ছোট পথ by

আরও বিশদে বিশদভাবে, একটি সংক্ষিপ্ততম পথের সমস্যাটি সমাধান করার জন্য আপনি:

  • শুরু নোড থেকে স্পর্শকারী প্রতিটি নোডের দূরত্বগুলি সন্ধান করুন (এ থেকে বি এবং সি পর্যন্ত বলুন)
  • সেই নোডগুলি থেকে তাদের স্পর্শকারী নোডের দূরত্বগুলি সন্ধান করুন (বি থেকে ডি এবং ই এবং সি এবং ই এবং এফ পর্যন্ত)
  • আমরা এখন A থেকে E পর্যন্ত সংক্ষিপ্ততম পথটি জানি: আমরা যে কয়েকটি নোড এক্স দেখেছি তার জন্য এটি এক্স এবং এক্স এর সংক্ষিপ্ত যোগফল (বি বা সি হয়)
  • চূড়ান্ত গন্তব্য নোড না পৌঁছানো পর্যন্ত এই প্রক্রিয়াটি পুনরাবৃত্তি করুন

যেহেতু আমরা নীচে কাজ করছি, আমাদের কাছে ইতিমধ্যে সাব-সমস্যাগুলির সমাধান করার সময় আসে যখন সেগুলি স্মরণে করে ব্যবহার করার সময় আসে।

মনে রাখবেন, ডায়নামিক প্রোগ্রামিং সমস্যার ক্ষেত্রে ওভারল্যাপিং উপ-সমস্যা এবং সর্বোত্তম কাঠামো উভয়ই থাকতে পারে। ফিবোনাচি সিক্যুয়েন্স তৈরি করা গতিশীল প্রোগ্রামিং সমস্যা নয়; এটি মেমোয়েজেশনকে কাজে লাগায় কারণ এতে ওভারল্যাপিং উপ-সমস্যা রয়েছে তবে এটিতে সর্বোত্তম কাঠামো নেই (কারণ এতে কোনও অপ্টিমাইজেশানের সমস্যা নেই)।


1
আইএমএইচও, ডায়নামিক প্রোগ্রামিংয়ের ক্ষেত্রে এটিই একমাত্র উত্তর sense আমি কৌতুহলী তখন থেকেই লোকেরা ফিবোনাচি নম্বর ব্যবহার করে ডিপি ব্যাখ্যা করতে শুরু করে (খুব কমই প্রাসঙ্গিক)।
টেরি লি

@ টেরিলি, এটি সম্ভবত "জ্ঞান" তৈরি করছে, তবে এটি বোঝা সহজ নয়। ফিবোনাচি নম্বর সমস্যাটি জানা এবং বোঝা সহজ।
অজয়

5

ডায়নামিক প্রোগ্রামিং

সংজ্ঞা

ডায়নামিক প্রোগ্রামিং (ডিপি) ওভারল্যাপিং উপ-সমস্যাগুলি নিয়ে সমস্যাগুলি সমাধান করার জন্য একটি সাধারণ অ্যালগরিদম ডিজাইন কৌশল। এই কৌশলটি আমেরিকান গণিতবিদ "রিচার্ড বেলম্যান" 1950 সালে আবিষ্কার করেছিলেন।

কী আইডিয়া

মূল ধারণাটি পুনরায় পুনর্নির্মাণ এড়াতে আরও ছোট ছোট সমস্যাগুলিকে ওভারল্যাপ করার উত্তরগুলি সংরক্ষণ করা।

গতিশীল প্রোগ্রামিংয়ের বৈশিষ্ট্য

  • ছোট উদাহরণগুলির জন্য সমাধানগুলি ব্যবহার করে একটি উদাহরণ সমাধান করা হয়।
  • একটি ছোট উদাহরণের জন্য সমাধানগুলি একাধিক বার প্রয়োজন হতে পারে, সুতরাং তাদের ফলাফলগুলি একটি টেবিলের মধ্যে সঞ্চয় করুন।
  • সুতরাং প্রতিটি ছোট উদাহরণ কেবল একবার সমাধান করা হয়।
  • সময় বাঁচাতে অতিরিক্ত স্থান ব্যবহার করা হয়।

4

আমি ডায়নামিক প্রোগ্রামিংয়েও খুব নতুন (বিশেষ ধরণের সমস্যার জন্য একটি শক্তিশালী অ্যালগরিদম)

সর্বাধিক সহজ কথায়, গতিশীল প্রোগ্রামিংটিকে পূর্ববর্তী জ্ঞানটি ব্যবহার করে পুনরাবৃত্তির পদ্ধতি হিসাবে ভাবেন

পূর্ববর্তী জ্ঞান হ'ল এখানে সর্বাধিক গুরুত্বপূর্ণ, আপনার ইতিমধ্যে যে উপ-সমস্যা রয়েছে তার সমাধানের খোঁজ রাখুন।

এটি বিবেচনা করুন, উইকিপিডিয়া থেকে ডিপি-র জন্য সবচেয়ে প্রাথমিক উদাহরণ

ফিবোনাচি ক্রম সন্ধান করা হচ্ছে

function fib(n)   // naive implementation
    if n <=1 return n
    return fib(n − 1) + fib(n − 2)

এন = 5 দিয়ে ফাংশন কলটি ভেঙে ফেলা যাক

fib(5)
fib(4) + fib(3)
(fib(3) + fib(2)) + (fib(2) + fib(1))
((fib(2) + fib(1)) + (fib(1) + fib(0))) + ((fib(1) + fib(0)) + fib(1))
(((fib(1) + fib(0)) + fib(1)) + (fib(1) + fib(0))) + ((fib(1) + fib(0)) + fib(1))

বিশেষত, ফাইব (2) স্ক্র্যাচ থেকে তিনবার গণনা করা হয়েছিল। বৃহত্তর উদাহরণগুলিতে, ফাইব বা উপ-সমস্যাগুলির আরও অনেক মানগুলি পুনরায় গণনা করা হয়, যা ঘনঘন সময় আলগরিদমের দিকে পরিচালিত করে।

এখন, মানচিত্রটি একটি ডেটা-কাঠামোর মধ্যে আমরা ইতিমধ্যে খুঁজে পেয়েছি যে মানটি সংরক্ষণ করে এটি ব্যবহার করে দেখি

var m := map(0 → 0, 1 → 1)
function fib(n)
    if key n is not in map m 
        m[n] := fib(n − 1) + fib(n − 2)
    return m[n]

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

শেষ পর্যন্ত, কোনও সমস্যার জন্য, প্রথমে রাজ্যগুলি অনুসন্ধান করার চেষ্টা করুন (সম্ভাব্য উপ-সমস্যাগুলি এবং আরও ভাল পুনরাবৃত্তি পদ্ধতির কথা চিন্তা করার চেষ্টা করুন যাতে আপনি পূর্ববর্তী সাব-সমস্যার সমাধানটি আরও একটি ক্ষেত্রে ব্যবহার করতে পারেন)।


সোজা উইকিপিডিয়া থেকে রিপ-অফ। Downvoted !!
solidak

3

ডায়নামিক প্রোগ্রামিং ওভারল্যাপিং সাব সমস্যাগুলির সাথে সমস্যাগুলি সমাধান করার একটি কৌশল। একটি গতিশীল প্রোগ্রামিং অ্যালগরিদম প্রতিটি উপ সমস্যা ঠিক একবার সমাধান করে এবং তারপরে একটি উত্তর সারণিতে (অ্যারে) সংরক্ষণ করে। প্রতিবার সাব সমস্যায় পড়লে উত্তরটি পুনরায় কম্পিউটিংয়ের কাজ এড়ানো। ডায়নামিক প্রোগ্রামিংয়ের অন্তর্নিহিত ধারণাটি হ'ল: একই উপায়ে দু'বার গণনা করা থেকে বিরত থাকুন, সাধারণত উপ সমস্যার পরিচিত ফলাফলগুলির একটি সারণী রেখে।

একটি গতিশীল প্রোগ্রামিং অ্যালগরিদমের বিকাশের সাতটি ধাপ নিম্নরূপ:

  1. একটি পুনরাবৃত্ত সম্পত্তি স্থাপন করুন যা সমস্যার উদাহরণটি সমাধান দেয়।
  2. পুনরাবৃত্ত সম্পত্তি হিসাবে একটি পুনরাবৃত্ত আলগোরিদিম বিকাশ
  3. পুনরাবৃত্ত কলগুলিতে সমস্যার একই উদাহরণ আবারও সমাধান হচ্ছে কিনা তা দেখুন
  4. একটি স্মৃতিযুক্ত পুনরাবৃত্তির অ্যালগরিদম বিকাশ করুন
  5. মেমরিতে ডেটা সঞ্চয় করার প্যাটার্নটি দেখুন
  6. স্মৃতিযুক্ত পুনরাবৃত্তির অ্যালগরিদমকে পুনরাবৃত্ত আলগোরিদিমে রূপান্তর করুন
  7. প্রয়োজনীয় হিসাবে স্টোরেজটি ব্যবহার করে পুনরাবৃত্তির অ্যালগরিদম অনুকূল করে নিন (স্টোরেজ অপ্টিমাইজেশন)

কি 6. Convert the memoized recursive algorithm into iterative algorithmএকটি আবশ্যিক পদক্ষেপ? এর অর্থ হ'ল এর চূড়ান্ত রূপটি পুনরাবৃত্তিযোগ্য?
ট্রুথহোল্ডার

এটি বাধ্যতামূলক নয়, এটি
আদনান কুরেশি

উদ্দেশ্য হ'ল মেমোরিতে ডেটা সংরক্ষণের জন্য ব্যবহৃত পুনরাবৃত্তির অ্যালগরিদমকে স্টোর করা মানগুলির উপরে পুনরাবৃত্তির সাথে প্রতিস্থাপন করা কারণ একটি পুনরাবৃত্ত সমাধানটি প্রতিটি পুনরাবৃত্ত কলের জন্য একটি ফাংশন স্ট্যাকের সৃষ্টি সংরক্ষণ করে।
ডেভিড সি র্যাঙ্কিন

1

সংক্ষেপে পুনরাবৃত্তি স্মৃতিচারণ এবং ডায়নামিক প্রোগ্রামিংয়ের মধ্যে পার্থক্য

নাম হিসাবে প্রস্তাবিত গতিশীল প্রোগ্রামিংটি পূর্ববর্তী গণনা করা মানটি ব্যবহার করে পরবর্তী নতুন সমাধানটি গতিশীলভাবে তৈরি করতে হয়

ডায়নামিক প্রোগ্রামিং কোথায় প্রয়োগ করবেন: আপনি যদি সমাধানটি সর্বোত্তম কাঠামো এবং ওভারল্যাপিং উপ সমস্যার ভিত্তিতে তৈরি করেন তবে সেক্ষেত্রে পূর্ববর্তী গণনা করা মানটি কার্যকর হবে সুতরাং আপনাকে এটি পুনরায় সংশোধন করতে হবে না। এটি নীচে আপ পদ্ধতির হয়। ধরুন আপনাকে সেই ক্ষেত্রে ফাইব (এন) গণনা করতে হবে আপনার কেবলমাত্র ফাইব (এন-1) এবং ফাইব (এন -2) এর আগের গণনা করা মান যুক্ত করা দরকার

পুনরাবৃত্তি: সহজেই সহজেই সমাধান করার জন্য আপনাকে সমস্যাটিকে ছোট্ট ভাগে বিভক্ত করা তবে মনে রাখবেন এটি পুনরায় গণনা এড়ায় না যদি আমাদের অন্যান্য পুনরাবৃত্তির কলে একই মান নির্ধারণ করা হয়।

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


-2

এখানে একটি সহজ পাইথন কোড উদাহরণ Recursive, Top-down, Bottom-upফিবানচি সিরিজের জন্য দৃষ্টীকোণ:

পুনরাবৃত্তি: ও (2 এন )

def fib_recursive(n):
    if n == 1 or n == 2:
        return 1
    else:
        return fib_recursive(n-1) + fib_recursive(n-2)


print(fib_recursive(40))

শীর্ষ-ডাউন: ও (এন) বৃহত্তর ইনপুটটির জন্য দক্ষ

def fib_memoize_or_top_down(n, mem):
    if mem[n] is not 0:
        return mem[n]
    else:
        mem[n] = fib_memoize_or_top_down(n-1, mem) + fib_memoize_or_top_down(n-2, mem)
        return mem[n]


n = 40
mem = [0] * (n+1)
mem[1] = 1
mem[2] = 1
print(fib_memoize_or_top_down(n, mem))

নীচে আপ: ও (এন) সরলতা এবং ছোট ইনপুট আকারের জন্য

def fib_bottom_up(n):
    mem = [0] * (n+1)
    mem[1] = 1
    mem[2] = 1
    if n == 1 or n == 2:
        return 1

    for i in range(3, n+1):
        mem[i] = mem[i-1] + mem[i-2]

    return mem[n]


print(fib_bottom_up(40))

প্রথম ক্ষেত্রে এন ^ 2 এর চলমান সময় নেই, এর সময়ের জটিলতা হ'ল (2 ^ n): স্ট্যাকওভারফ্লো
স্যাম

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