मैं एक दोहरे पुनरावर्ती कार्य के क्रम को कैसे निर्धारित करूं?


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_one

11
ठीक है समझ आ गया। वोटिंग करने वालों के लिए यह स्टैक ओवरफ्लो में माइग्रेट करना: यह यहां ऑन टॉपिक है, और स्टैक ओवरफ्लो पर ऑफ-टॉपिक। Programmers.SE वैचारिक, व्हाइटबोर्ड-वाई प्रश्नों के लिए है; स्टैक ओवरफ्लो कार्यान्वयन के लिए है, समस्या-समय-मैं-कोडिंग प्रश्न।

3
धन्यवाद, यही कारण है कि मैंने इसे पहले स्थान पर किया। इसके अलावा यह जानना बेहतर है कि मछली कैसे प्राप्त करें।
if_zero_equals_one

1
इस विशेष मामले में यह अभी भी आम तौर पर एक अनंत पुनरावृत्ति है क्योंकि b (a (0)) असीम रूप से कई अन्य b (a (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... और कहा कि क्या के रूप में जाना जाता है अनंत प्रत्यावर्तन


यहाँ विशेष कार्यों की तलाश नहीं है। मैं एक दूसरे को कॉल करने वाले पुनरावर्ती कार्यों के रन समय का पता लगाने के लिए एक सामान्य तरीके की तलाश कर रहा हूं।
if_zero_equals_one

1
मुझे यकीन नहीं है कि सामान्य मामले में कोई समाधान है। बिग-ओ को समझ में आने के लिए, आपको यह जानना होगा कि क्या एल्गोरिथ्म कभी रुक जाएगा। कुछ पुनरावर्ती एल्गोरिदम हैं जहां आपको गणना करने से पहले यह जानना होगा कि इसमें कितना समय लगेगा (जैसे यह निर्धारित करना कि कोई बिंदु मैंडलब्रॉट सेट का है या नहीं)।
jimreed

हमेशा नहीं, aकेवल तभी कॉल किया जाता है bजब नंबर पास हुआ है = = 0. लेकिन हाँ, एक अनंत लूप है।
btilly

1
मेरे जवाब पोस्ट करने के बाद @btilly का उदाहरण बदल दिया गया।
जिम्मीड करें

1
@ जिम: और इसे फिर से बदल दिया गया है। अगर मैं कर सकता था तो मैं अपनी टिप्पणी हटा दूंगा।
btilly

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.wikipedia.org/wiki/Hofstadter_fterence#Hofstadter_Femont_and_M___ इस कारण से इनका उत्तर देना मुश्किल है। यह इन पारस्परिक-पुनरावर्ती कार्यों के कारण है "कठिन रूप"।

किसी भी तरह, आइए इस आसान उदाहरण को देखें:

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 से प्रेरित होकर , जो स्वयं एक अच्छा पढ़ा हुआ है, आइए देखें: "" फाइबोनैचि संख्याओं की व्याख्या पारस्परिक पुनरावृत्ति के माध्यम से की जा सकती है: F (0) = 1 और G (0) ) = 1, F (n + 1) = F (n) + G (n) और G (n + 1) = F (n) के साथ। "" "

तो, F का रनटाइम क्या है? हम दूसरे रास्ते से जाएंगे।
खैर, आर (एफ (0)) = 1 = एफ (0); R (G (0)) = 1 = G (0)
अब R (F (1)) = R (F (0)) + R (G (0)) = F (0) + G (0) = F (1)
...
यह देखना मुश्किल नहीं है कि R (F (m)) = F (m) - उदाहरण के लिए, फंक्शन की संख्या की आवश्यकता सूचकांक में एक फाइबोनैचि संख्या की गणना करने के लिए 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

बिग-ओ में रनटाइम?

यह आसान है: ओ (एन) - यह मानते हुए कि समाप्ति की स्थिति है।

रिकर्सन सिर्फ लूपिंग है, और एक साधारण लूप है ओ (एन) कोई फर्क नहीं पड़ता कि आप उस लूप में कितनी चीजें करते हैं (और दूसरी विधि को कॉल करना लूप में सिर्फ एक और कदम है)।

जहां यह दिलचस्प होगा यदि आपके पास एक या अधिक पुनरावर्ती तरीकों के भीतर एक लूप है। उस स्थिति में आप किसी प्रकार के घातांक प्रदर्शन ( विधि द्वारा प्रत्येक पास पर O (N) से गुणा करना ) के साथ समाप्त हो जाएंगे ।


2
आप किसी भी विधि का उच्चतम क्रम लेकर और कॉलिंग विधि के क्रम से गुणा करके बिग-ओ प्रदर्शन का निर्धारण करते हैं। हालांकि, एक बार जब आप घातीय और तथ्यात्मक प्रदर्शन के बारे में बात करना शुरू करते हैं, तो आप बहुपद प्रदर्शन को अनदेखा कर सकते हैं। मेरा मानना ​​है कि घातांक और तथ्यात्मक की तुलना करते समय वही धारण करता है: भाज्य जीतता है। मुझे कभी भी ऐसी प्रणाली का विश्लेषण नहीं करना पड़ा है जो घातीय और वास्तविक दोनों थी ।
एनॉन

5
यह गलत है। Nth फाइबोनैचि संख्या और क्विकसॉर्ट की गणना के पुनरावर्ती रूप क्रमशः O(2^n)और O(n*log(n))हैं।
20-40

1
कुछ फैंसी प्रूफ किए बिना मैं आपको amazon.com/Introduction-Algorithms-Second-Thomas-Cormen/dp/… पर निर्देशित करना चाहूंगा और इस SE साइट cstheory.startexchange.com पर एक नज़र डालने की कोशिश करूंगा
ब्रायन हैरिंगटन

4
लोगों ने इस गलत जवाब को क्यों वोट दिया? किसी विधि को कॉल करने में समय उस पद्धति के लिए आनुपातिक लगता है। इस मामले में विधि aकॉल bऔर bकॉल करती है, aइसलिए आप केवल यह नहीं मान सकते हैं कि या तो विधि में समय लगता है O(1)
btilly

2
@ तोप - पोस्टर मनमाने ढंग से दोहरे पुनरावर्ती कार्य के लिए कह रहा था, न कि केवल ऊपर दिखाया गया। मैंने सरल पुनरावृत्ति के दो उदाहरण दिए जो आपके स्पष्टीकरण में फिट नहीं हैं। यह पुराने मानकों को "दोहरे-पुनरावर्ती" रूप में परिवर्तित करने वाला है, जो कि घातीय (आपके कैविएट को फिट करना) है और जो नहीं है (कवर नहीं)।
अपराह्न
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.