আমি কীভাবে একটি দ্বৈত পুনরাবৃত্ত ফাংশনের রানটাইম নির্ধারণ করব?


15

যেকোন যথেচ্ছভাবে দ্বি-পুনরাবৃত্ত ক্রিয়াকলাপ দেওয়া, কেউ কীভাবে তার রান সময় গণনা করবে?

উদাহরণস্বরূপ (সিউডোকোডে):

int a(int x){
  if (x < = 0)
    return 1010;
  else
    return b(x-1) + a(x-1);
}
int b(int y){
  if (y <= -5)
    return -2;
  else
    return b(a(y-1));
}

বা এই লাইন বরাবর কিছু।

এই জাতীয় কিছু নির্ধারণের জন্য কোন পদ্ধতিগুলি ব্যবহার করতে পারে বা হওয়া উচিত?


2
এই হোমওয়ার্ক হয়?
বার্নার্ড

5
না এখন গ্রীষ্মের সময় এবং আমি শিখতে পছন্দ করি। আমার মস্তিষ্ককে কুঁচকে যাওয়ার পরিবর্তে আমি এগিয়ে যেতে চাই।
if_zero_equals_ এক

11
আচ্ছা আমি বুঝে গেছি. যারা স্ট্যাক ওভারফ্লোতে এই স্থানান্তরিত করতে ভোট দিচ্ছেন তাদের কাছে: এটি এখানে বিষয়বহুল এবং স্ট্যাক ওভারফ্লোতে অফ-টপিক। প্রোগ্রামার্স.এসই ধারণামূলক, হোয়াইটবোর্ড-ওয়াই প্রশ্নের জন্য; স্ট্যাক ওভারফ্লো বাস্তবায়নের জন্য, যখন আমি-কোডিং প্রশ্ন করি।

3
ধন্যবাদ যে কারণেই আমি এখানে এটি প্রথম স্থানে করেছি। পাশাপাশি মাছ গ্রহণের চেয়ে মাছ কীভাবে জানবেন তা আরও ভাল।
if_zero_equals_ এক

1
এই নির্দিষ্ট ক্ষেত্রে এটি এখনও সাধারণত একটি অসীম পুনরাবৃত্তি কারণ খ (ক (0)) অসীম অনেক অন্যান্য খ (ক (0)) পদগুলিকে আহ্বান করে। যদি এটি একটি গণিতের সূত্র হত তবে এটি অন্যরকম হত। আপনার সেটআপটি অন্যরকম হলে এটি অন্যরকমভাবে কাজ করতে পারত। গণিতে যেমন, সিএস-তে কিছু সমস্যার সমাধান থাকে, কিছু থাকে না, কারও কারও কাছে সহজ সমাধান থাকে, কিছু থাকে না। অনেকগুলি পারস্পরিক-পুনরাবৃত্তি হওয়া মামলা রয়েছে যেখানে সমাধানটি বিদ্যমান। কখনও কখনও, কোনও স্ট্যাক ফুঁকতে না দেওয়ার জন্য ট্রামপোলিন প্যাটার্ন ব্যবহার করতে হয়।
চাকরী

উত্তর:


11

আপনি আপনার ফাংশন পরিবর্তন করতে থাকুন। তবে এগুলি বাছাই করুন যা কোনও রূপান্তর ছাড়াই চিরকাল চলবে ..

পুনরাবৃত্তি জটিল, দ্রুত হয়ে যায়। প্রস্তাবিত দ্বিগুণ পুনরাবৃত্তি ফাংশন বিশ্লেষণের প্রথম পদক্ষেপটি হ'ল কিছু নমুনা মানগুলি এটির মাধ্যমে আবিষ্কার করার চেষ্টা করা হয়, এটি কী করে তা দেখে। যদি আপনার গণনা অসীম লুপে যায় তবে ফাংশনটি ভালভাবে সংজ্ঞায়িত হয় না। যদি আপনার গণনা একটি সর্পিল হয়ে যায় যা বড় সংখ্যা পেতে থাকে (যা খুব সহজে ঘটে) তবে এটি সম্ভবত সঠিকভাবে সংজ্ঞায়িত হয়নি।

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

সতর্কতা অবলম্বন করুন যে একক পুনরাবৃত্তি হওয়া সত্ত্বেও, এমন ফাংশনগুলি নিয়ে আসা সহজ যাঁর রানটাইম আমরা কীভাবে গণনা করতে জানি না। উদাহরণস্বরূপ নিম্নলিখিত বিবেচনা করুন:

def recursive (n):
    if 0 == n%2:
        return 1 + recursive(n/2)
    elif 1 == n:
        return 0
    else:
        return recursive(3*n + 1)

এটি বর্তমানে অজানা যে এই ফাংশনটি সর্বদা সুনির্দিষ্টভাবে সংজ্ঞায়িত করা হয়, এর রানটাইমটি কী তা একা ছেড়ে দিন।


5

সেই বিশেষ জুটির ফাংশনগুলির রানটাইম অসীম কারণ অন্যটিকে ডেকে না নিয়েই ফিরে আসে না। ফেরত মান aহয় সবসময় একটি কলে ফেরত মান উপর নির্ভরশীল bযা সবসময় কল a... এবং যে কি একে বলা হয় অসীম recursion


এখানে নির্দিষ্ট ক্রিয়াকলাপ অনুসন্ধান না করে। একে অপরকে কল করে এমন পুনরাবৃত্ত ক্রিয়াকলাপগুলির চালনার সময়টি সন্ধান করার জন্য আমি একটি সাধারণ উপায় সন্ধান করছি।
if_zero_equals_ এক

1
আমি নিশ্চিত না যে সাধারণ ক্ষেত্রে কোনও সমাধান আছে। বিগ-ওটি বোঝার জন্য, আপনাকে জানতে হবে যে অ্যালগরিদমটি কখনও থামবে কিনা। কিছু পুনরাবৃত্তির অ্যালগরিদম রয়েছে যেখানে আপনি কতক্ষণ সময় নেবেন তা জানার আগে আপনাকে গণনা চালাতে হবে (উদাহরণস্বরূপ নির্ধারণ করুন যে কোনও পয়েন্ট ম্যান্ডলেব্রোট সেটের সাথে সম্পর্কিত কিনা তা নির্ধারণ করে)।
jimreed

সর্বদা নয়, aকেবল bপাস করা নম্বরটি = = 0 হলে কল করুন তবে হ্যাঁ, অসীম লুপ রয়েছে।
btilly

1
@ তবে আমার উত্তর পোস্ট করার পরে উদাহরণটি পরিবর্তন করা হয়েছিল।
jimreed

1
@ জিম্রিড: এবং এটি আবার পরিবর্তন করা হয়েছে। আমি পারলে আমার মন্তব্য মুছে ফেলব।
btilly 21

4

সুস্পষ্ট পদ্ধতিটি হ'ল ফাংশনটি চালানো এবং এটি কতক্ষণ সময় নেয় তা পরিমাপ করে। এটি কেবল আপনাকে জানায় যে কোনও নির্দিষ্ট ইনপুটটিতে এটি কতক্ষণ সময় নেয়। এবং যদি আপনি আগেই জানেন না যে ফাংশনটি সমাপ্ত হয়, শক্ত: ফাংশনটি সমাপ্ত হয় কিনা তা বের করার কোনও যান্ত্রিক উপায় নেই - এটি হ'ল সমস্যা , এবং এটি অনস্বীকার্য।

রাইসের উপপাদ্য দ্বারা কোনও ফাংশনের রান সময় সন্ধান করা একইভাবে অনস্বীকার্য । আসলে, রাইসের উপপাদ্যটি দেখায় যে এমনকি কোনও ফাংশন O(f(n))সময়মতো চালিত হয় কিনা তা সিদ্ধান্ত নেওয়াও অনস্বীকার্য।

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

T_a(x) = if x ≤ 0 then 1 else T_b(x-1) + T_a(x-1)
T_b(x) = if x ≤ -5 then 1 else T_b(T_a(x-1))

এরপর কী? আপনার এখন একটি গণিত সমস্যা: আপনার এই কার্যকরী সমীকরণগুলি সমাধান করা দরকার। একটি পন্থা যে কাজ করে ফাংশন ব্যাখ্যা, বিশ্লেষণ ফাংশন এবং ব্যবহারের ক্যালকুলাস উপর সমীকরণ মধ্যে পূর্ণসংখ্যা ফাংশন উপর এই সমীকরণ ঘুরে এই বিশ্লিষ্ট করা হল T_aএবং T_bযেমন ফাংশন উৎপাদিত

অন্যান্য বিভিন্ন বিচ্ছিন্ন গণিতের বিষয় তৈরির ক্ষেত্রে, আমি রোনাল্ড গ্রাহাম, ডোনাল্ড নুথ এবং ওরেন পাতাসনিকের কংক্রিট গণিত বইয়ের প্রস্তাব দিই ।


1

অন্যরা যেমন উল্লেখ করেছে, পুনরাবৃত্তি বিশ্লেষণ করা খুব দ্রুত খুব দ্রুত পেতে পারে। এই জাতীয় জিনিসটির আরও একটি উদাহরণ এখানে দেওয়া হয়েছে: http://rosettacode.org/wiki/Mutual_recursion http://en.wikedia.org/wiki/Hofstadter_sequence#Hofstadter_Female_and_Male_sequferences এগুলির জন্য একটি উত্তর এবং চলমান সময় গণনা করা শক্ত। এটি "কঠিন ফর্ম" থাকার এই পারস্পরিক পুনরাবৃত্ত ক্রিয়াকলাপগুলির কারণে।

যাইহোক, আসুন এই সহজ উদাহরণটি দেখুন:

http://pramode.net/clojure/2010/05/08/clojure-trampoline/

(declare funa funb)
(defn funa [n]
  (if (= n 0)
    0
    (funb (dec n))))
(defn funb [n]
  (if (= n 0)
    0
    (funa (dec n))))

আসুন গণনা করার চেষ্টা করে শুরু করুন funa(m), m > 0:

funa(m) = funb(m - 1) = funa(m - 2) = ... funa(0) or funb(0) = 0 either way.

রান-টাইমটি হ'ল:

R(funa(m)) = 1 + R(funb(m - 1)) = 2 + R(funa(m - 2)) = ... m + R(funa(0)) or m + R(funb(0)) = m + 1 steps either way

এবার আরও একটি জটিল উদাহরণ বেছে নেওয়া যাক:

Http://planetmath.org/encyclopedia/MutualRecursion.html দ্বারা অনুপ্রাণিত , যা নিজে নিজেই পড়া ভাল, আসুন দেখে নেওয়া যাক: "" "ফিবোনাকির সংখ্যাগুলি পারস্পরিক পুনরাবৃত্তির মাধ্যমে ব্যাখ্যা করা যেতে পারে: এফ (0) = 1 এবং জি (0) ) = 1, এফ (এন + 1) = এফ (এন) + জি (এন) এবং জি (এন + 1) = এফ (এন) দিয়ে। "" "

তো, এফের রানটাইম কত? আমরা অন্য পথে যেতে হবে।
ভাল, আর (এফ (0)) = 1 = এফ (0); আর (জি (0)) = 1 = জি (0)
এখন আর (এফ (1)) = আর (এফ (0)) + আর (জি (0)) = এফ (0) + জি (0) = এফ (1)
...
আর (এফ (এম)) = এফ (এম) দেখতে অসুবিধা হয় না - উদাহরণস্বরূপ আমি সূচীতে একটি ফিবোনাকি নম্বর গণনা করতে প্রয়োজনীয় ফাংশন কলগুলির সংখ্যা একটি ফিবোনাকির সংখ্যার মানের সমান? সূচীতে i। এটি ধরে নিয়েছে যে দুটি সংখ্যা একসাথে যুক্ত করা একটি ফাংশন কলের চেয়ে অনেক দ্রুত। যদি এটি না হয়, তবে এটি সত্য হবে: আর (এফ (1)) = আর (এফ (0)) + 1 + আর (জি (0)), এবং এর বিশ্লেষণ আরও জটিল হত, সম্ভবত একটি সহজ বদ্ধ ফর্ম সমাধান ছাড়াই।

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


0

করণীয় হ'ল প্রথমটি হ'ল এটি যা আপনার সংজ্ঞায়িত ফাংশনগুলি সমাপ্ত হয় এবং যার জন্য হুবহু মান। উদাহরণ হিসাবে আপনি সংজ্ঞায়িত করেছেন

int a(int x){
  if (x < = 0)
    return 1010;
  else
    return b(x-1) + a(x-1);
}
int b(int y){
  if (y <= -5)
    return -2;
  else
    return b(a(y-1));
}

bকেবলমাত্র এর জন্য অবসান হয় y <= -5কারণ আপনি যদি অন্য কোনও মান প্লাগ করেন তবে আপনার ফর্মটির একটি মেয়াদ থাকবে b(a(y-1))। আপনি যদি আরও কিছুটা প্রসারিত করেন তবে আপনি দেখতে পাবেন যে ফর্মের একটি শব্দটি b(a(y-1))পরিশেষে এমন পদটির b(1010)দিকে পরিচালিত করে b(a(1009))যা আবার শর্তের দিকে পরিচালিত করে b(1010)। এর অর্থ আপনি aযে মানটিকে সন্তুষ্ট করেন না এমন কোনও প্লাগ ইন করতে পারবেন না x <= -4কারণ আপনি যদি এমন অসীম লুপটি শেষ করেন যেখানে গুণন করতে হবে মানটি গণনা করার মানের উপর নির্ভর করে। সুতরাং মূলত এই উদাহরণটির ধ্রুব রান সময় রয়েছে।

সুতরাং সহজ উত্তরটি হ'ল পুনরাবৃত্ত ফাংশনগুলির রান সময় নির্ধারণের জন্য কোনও সাধারণ পদ্ধতি নেই কারণ এমন কোনও সাধারণ পদ্ধতি নেই যা নির্ধারণ করে যে কোনও পুনরাবৃত্তভাবে সংজ্ঞায়িত ফাংশনটি সমাপ্ত হয় কিনা।


-5

বিগ-ও-র মতো রানটাইম?

এটি সহজ: ও (এন) - ধরে নিচ্ছি যে এখানে একটি সমাপ্তির শর্ত রয়েছে।

পুনরাবৃত্তি কেবল লুপিং, এবং একটি সাধারণ লুপ হ'ল ও (এন) আপনি যে লুপটিতে কত কিছুই করেন না কেন (এবং অন্য পদ্ধতিটিকে কল করা লুপের আরও একটি পদক্ষেপ)।

এটি আকর্ষণীয় হয়ে উঠতে পারে তা হ'ল যদি আপনার এক বা একাধিক পুনরাবৃত্ত পদ্ধতির মধ্যে লুপ থাকে। সেক্ষেত্রে আপনি কিছু ধরণের ক্ষতিকারক কর্মক্ষমতা ( পদ্ধতিটির মাধ্যমে প্রতিটি পাসে ও (এন) দ্বারা গুণমান) দিয়ে শেষ করবেন।


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

5
এটি ভুল। নবম ফিবোনাচি সংখ্যা এবং কুইকোর্টের গণনা করার পুনরাবৃত্তিমূলক রূপগুলি যথাক্রমে O(2^n)এবং O(n*log(n))
অযৌক্তিক

1
কিছু অভিনব প্রমাণ না করে আমি কি তোমাদেরকে চাই amazon.com/Introduction-Algorithms-Second-Thomas-Cormen/dp/... এবং এই দঃপূঃ সাইটে কটাক্ষপাত গ্রহণ চেষ্টা cstheory.stackexchange.com
ব্রায়ান হ্যারিংটন

4
লোকেরা কেন এই ভয়াবহ ভুল উত্তরটি দিয়েছে? কোনও পদ্ধতিতে কল করা পদ্ধতিটি যে সময় লাগে তার সাথে আনুপাতিক সময় নেয়। এই ক্ষেত্রে পদ্ধতি aকল bএবং bকলগুলি aযাতে আপনি সহজেই অনুমান করতে পারবেন না যে কোনও পদ্ধতিতে সময় লাগে O(1)
btilly

2
@ অ্যান - পোস্টারটি কেবল উপরে দেখানো একটি নয়, ইচ্ছামত দ্বৈত-পুনরাবৃত্তি ফাংশন চেয়েছিল। আমি সাধারণ পুনরাবৃত্তির দুটি উদাহরণ দিয়েছি যা আপনার ব্যাখ্যার সাথে খাপ খায় না। এটি তুচ্ছটি পুরানো মানকে "ডাবল-রিকার্সিভ" আকারে রূপান্তরিত করে, এটির মধ্য দিয়ে ক্ষণস্থায়ী (আপনার ক্যাভেটকে ফিটিং করা) এবং এটির (আবৃত নয়) একটি।
অযৌক্তিক
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.