एल्गोरिथ्म के लिए पैटर्न जो जरूरत पड़ने पर समाधान के बारे में एक विवरण प्रस्तुत करता है


14

निम्नलिखित परिदृश्य मेरे साथ कई बार हुआ।

मैंने एक एल्गोरिथ्म प्रोग्राम किया जो एक निश्चित समस्या को हल करता है। यह ठीक काम करता है और सही समाधान ढूंढता है। अब, मैं एल्गोरिथ्म को बताने के लिए एक विकल्प रखना चाहता हूं "आपको समाधान कैसे मिला, इसकी पूरी व्याख्या लिखें"। मेरा लक्ष्य ऑनलाइन प्रदर्शनों, ट्यूटोरियल कक्षाओं आदि में एल्गोरिथ्म का उपयोग करने में सक्षम होना है, मैं अभी भी स्पष्टीकरण के बिना एल्गोरिथ्म को वास्तविक समय में चलाने का विकल्प रखना चाहता हूं। उपयोग करने के लिए एक अच्छा डिजाइन पैटर्न क्या है?

उदाहरण: मान लीजिए कि मैं इस विधि को सबसे बड़े सामान्य भाजक को खोजने के लिए लागू करता हूं । वर्तमान कार्यान्वित विधि सही उत्तर देती है, लेकिन कोई स्पष्टीकरण नहीं है। मैं अपने कार्यों को समझाने की विधि के लिए एक विकल्प रखना चाहता हूं, जैसे:

Initially, a=6 and b=4. The number of 2-factors, d, is initialized to 0.
a and b are both even, so we divide them by 2 and increment d by 1.
Now, a=3 and b=2.
a is odd but b is even, so we divide b by 2.
Now, a=3 and b=1.
a and b are both odd, so we replace a by (a-b)/2 = 1.
Now, a=1 and b=1.
a=b, so the GCD is a*2^d = 2.

आउटपुट को ऐसे लौटाया जाना चाहिए कि इसे कंसोल और वेब-आधारित अनुप्रयोगों में आसानी से प्रदर्शित किया जा सके।

आवश्यकता पड़ने पर एल्गोरिदम के वास्तविक समय के प्रदर्शन को नुकसान न पहुंचाते हुए स्पष्टीकरण प्रदान करने के लिए एक अच्छा पैटर्न क्या है?

जवाबों:


50

जिस "पैटर्न" की आप तलाश कर रहे हैं उसे "लॉगिंग" कहा जाता है, बस लॉगिंग स्टेटमेंट को क्रिया के रूप में बनाएं जैसे आपको उनकी आवश्यकता है। एक सभ्य लॉगिंग फ़्रेमवर्क का उपयोग करके आप इसे रन टाइम पर चालू और बंद करने में सक्षम होना चाहिए, विभिन्न क्रियात्मक स्तर प्रदान करते हैं, या अलग-अलग उद्देश्यों (जैसे वेब बनाम कंसोल) के लिए आउटपुट को दर्जी करते हैं।

यदि इसका एक उल्लेखनीय प्रदर्शन प्रभाव पड़ता है (भले ही लॉगिंग स्विच हो जाए), तो संभवतः भाषा, रूपरेखा और लॉगिंग स्टेटमेंट की संख्या पर निर्भर करता है जो आपको विशिष्ट मामले में चाहिए। संकलित भाषाओं में, यदि यह वास्तव में एक समस्या बन जाती है, तो आप अपने कोड के "लॉगिंग वेरिएंट" और "नॉन-लॉगिंग वेरिएंट" बनाने के लिए एक कंपाइलर स्विच प्रदान कर सकते हैं। हालाँकि, मैं पहले से माप किए बिना "बस के मामले में" को अनुकूलित करने के खिलाफ बहुत अधिक सलाह देता हूं।


2
जब वे कुछ ऐसा नहीं करते हैं जिसे आप लॉगिंग की तरह चालू और बंद करते हैं, तो ऐसा लगता है कि टिप्पणियों और स्वयं दस्तावेज कोड को कम से कम एक "एल्गोरिथ्म जो खुद को समझाता है" के बारे में एक प्रश्न में एक सम्मानजनक उल्लेख प्राप्त करना चाहिए।
कैंडिड_ओरेंज

9
@CandiedOrange प्रश्न को विशेष रूप से "स्पष्टीकरण" के लिए पूछता है जिसमें वास्तविक रन-टाइम मान शामिल हैं। टिप्पणियाँ उस मामले में बहुत मदद नहीं करेगा।
16'16

@metacubed ओह चलो। मैंने यह नहीं कहा कि यह लॉगिंग का एक विकल्प था। प्रश्न शीर्षक देखें और यहां से आने वाले ट्रैफ़िक के बारे में सोचें।
candied_orange

4
@CandiedOrange: मुझे लगता है कि प्रश्न शीर्षक भ्रामक है, आप सही हैं कि इस तरह से व्याख्या की जा सकती है, लेकिन यह वह नहीं है जो ओपी पूछ रहा है। लेकिन मैंने मुझे सही करने दिया, मैं शीर्षक संपादित करूंगा।
डॉक ब्राउन

1
ध्यान दें कि treelog की तरह कुछ विशेष रूप से आउटपुट का निर्माण करने के लिए डिज़ाइन किया गया है जो फ़ंक्शन कॉल का एक पूरा रिकॉर्ड तैयार करके जटिल संगणना को बताता है।
बोरिस द स्पाइडर

7

एक अच्छा पैटर्न ऑब्जर्वर है। https://en.wikipedia.org/wiki/Observer_pattern

अपने एल्गोरिथ्म में, प्रत्येक बिंदु पर जहां आप कुछ आउटपुट करना चाहते हैं, आप कुछ पर्यवेक्षक को सूचित करते हैं। वे फिर तय करते हैं कि क्या करना है, यह आपके टेक्स्ट को कंसोल पर आउटपुट करना है, या इसे HTML इंजन / अपाचे आदि पर भेजना है।

आपकी प्रोग्रामिंग भाषा के आधार पर इसे तेज़ बनाने के अलग-अलग तरीके हो सकते हैं। उदाहरण के लिए, जावा में (इसे छद्म के रूप में देखें, संक्षिप्तता के लिए; इसे "सही" बनाने के लिए, गेटर्स, सेटर के साथ, पाठक पर छोड़ दिया जाता है):

interface AlgoLogObserver {
   public void observe(String message);
}

class AlgorithmXyz {   
   AlgoLogObserver observer = null;
   void runCalculation() {   
       if (observer!=null) { oberserver.observe("Hello"); }
       ...
   }   
}

...
algo = new AlgorithmXyz();
algo.observer = new ConsoleLoggingObserver();  // yes, yes make a 
                                               // setter instead, or use Ruby :-)
algo.runCalculation();

यह थोड़ा वर्बोज़ है, लेकिन इसके लिए चेक ==nullउतना तेज़ होना चाहिए जितना इसे मिल सके।

(ध्यान दें कि सामान्य मामले में, observerसंभवतः एक Vector observersसे अधिक पर्यवेक्षक के लिए अनुमति देने के लिए होगा; यह निश्चित रूप से संभव है और अधिक ओवरहेड की ओर नहीं ले जाएगा; आप अभी भी उस अनुकूलन में रख सकते हैं जो आप सेट observers=nullकरने के बजाय सेट करते हैं खाली है Vector।)

बेशक, आप विभिन्न प्रकार के पर्यवेक्षकों को लागू करना चाहते हैं जो आप प्राप्त करना चाहते हैं उसके आधार पर। आप वहां टाइमिंग के आंकड़े आदि भी डाल सकते हैं, या अन्य फैंसी चीजें कर सकते हैं।


5

सीधे लॉगिंग में मामूली सुधार के रूप में, कुछ प्रकार की वस्तु बनाएं जो एल्गोरिथ्म के एक निष्पादन को मॉडल करता है। जब भी आपका कोड कुछ दिलचस्प करता है, तो इस कंटेनर ऑब्जेक्ट में "चरण" जोड़ें। एल्गोरिथ्म के अंत में, कंटेनर से संचित चरणों को लॉग करें।

इसके कुछ फायदे हैं:

  1. आप पूर्ण निष्पादन को एक लॉग प्रविष्टि के रूप में लॉग कर सकते हैं , अक्सर उपयोगी होता है जब आपके एलो स्टेप्स के बीच अन्य थ्रेड्स लॉगिंग सामान की संभावना होती है।
  2. इस वर्ग के मेरे जावा संस्करण में (जिसे केवल "डीबग" कहा जाता है), मैं स्ट्रिंग्स को लॉग प्रविष्टियों के रूप में नहीं जोड़ता , लेकिन लैम्बडा जो स्ट्रिंग्स का उत्पादन करता है। इन लंबों का केवल मूल्यांकन किया जाता है कि क्या वास्तविक लॉगिंग होगी, अर्थात यदि डीबग ऑब्जेक्ट पाता है कि इसका लॉग स्तर वर्तमान में सक्रिय है। इस तरह, अनावश्यक रूप से लॉग स्ट्रिंग्स के निर्माण का कोई प्रदर्शन ओवरहेड नहीं है।

संपादित करें: जैसा कि दूसरों द्वारा टिप्पणी की गई है, लैम्बदास ने ओवरहेड किया है, इसलिए आपको यह सुनिश्चित करने के लिए बेंचमार्क करना होगा कि लॉग स्ट्रिंग के निर्माण के लिए आवश्यक कोड के अनावश्यक मूल्यांकन से कम है (लॉग प्रविष्टियां अक्सर सरल शाब्दिक नहीं होती हैं, लेकिन इसमें प्रासंगिक जानकारी शामिल होती है। भाग लेने वाली वस्तुएं)।


2
निश्चित रूप से नहीं है, बनाने की भूमि के ऊपर lambdas ...
सर्जियो Tulentsev

1
सर्जियो प्रकाश बनाता है, लेकिन अपने तर्क की मूर्खता को पूरी तरह से स्पष्ट नहीं करता है। लॉग स्ट्रिंग्स के निर्माण का प्रदर्शन ओवरहेड, लैम्ब्डा के निर्माण के प्रदर्शन ओवरहेड की तुलना में कम परिमाण का एक आदेश है । आपने यहां बहुत खराब
ट्रेडऑफ

2
@ टायर: क्या आपके पास एक विश्वसनीय बेंचमार्क है जो साबित कर रहा है? (आपके द्वारा लिंक किया गया बेंचमार्क गहराई से त्रुटिपूर्ण है, cf stackoverflow.com/questions/504103/… )
मेरिटॉन

1
@ यह सब विशिष्ट स्थिति पर निर्भर करता है। मैं आपको एक, यकीनन, अधिक प्रासंगिक प्रतिसाद भी दे सकता हूं । आप देख सकते हैं कि स्ट्रिंग संस्करण रननेबल से अधिक परिमाण का एक क्रम है। यह मामला अधिक यथार्थवादी है, क्योंकि इस प्रश्न के संदर्भ में आप हमेशा अपने तार का निर्माण गतिशील रूप से करना चाहेंगे। यह हमेशा स्ट्रिंगबिल्डर वस्तुओं के निर्माण की आवश्यकता होती है, जबकि लैम्ब्डा के साथ वे केवल तभी बनाए जाएंगे जब जरूरत (यानी जब लॉगिंग होती है)।
ज्योत

1
लंबोदर ने ओवरहेड किया, सहमति व्यक्त की। हालाँकि, पोस्टमार्क इस संदर्भ में पूरी तरह अप्रासंगिक है। एल्गोरिदम के लॉगिंग में अक्सर अन्य कोड का मूल्यांकन शामिल होता है जिनका मूल्यांकन नहीं किया गया होता है लॉगिंग को छोड़ दिया गया है (भाग लेने वाली वस्तुओं, आदि से प्रासंगिक जानकारी प्राप्त करना)। यह मूल्यांकन है कि लंबोदर बचते हैं। लेकिन आप सही कह रहे हैं, ऊपर दिए गए मेरे जवाब से यह अनुमान लगाया जा सकता है कि लैम्ब्डा ओवरहेड इस ओवरहेड से कम है , जिसे मैंने लगातार परीक्षण नहीं किया है।
कॉर्नेल मेसन

0

मैं आमतौर पर ब्रांचिंग के लिए देखता हूं, जिसका अर्थ है कि अगर मैं स्टेटमेंट देखता हूं। क्योंकि ये इंगित करते हैं कि मैं एक मूल्य का मूल्यांकन करता हूं, जो कि एल्गोरिथ्म के प्रवाह को नियंत्रित करेगा। इस तरह के प्रत्येक भयावहता (प्रत्येक स्थिति) में मैं फिर चुने हुए मार्ग को लॉग कर सकता हूं, और इसे क्यों चुना गया।

इसलिए मूल रूप से मैं प्रवेश मूल्यों (प्रारंभिक स्थिति), चुने गए प्रत्येक शाखा (सशर्त) और मूल्यों को चुना शाखा (मंदिर राज्य) में प्रवेश करते समय प्रवेश करूंगा।


1
यह पूछे जाने वाले प्रश्न के एल्गोरिथ्म के वास्तविक समय के प्रदर्शन को नुकसान न पहुंचाने के बारे में पूछे जाने पर भी नहीं करता है, जब स्पष्टीकरण की आवश्यकता नहीं होती है
gnat

मैंने उससे अधिक सामान्य प्रश्न लिया और मैंने इसका उत्तर एक डिज़ाइन स्तर पर दिया। लेकिन अगर यह एक चिंता का विषय है, तो सशर्त एक ध्वज को जोड़ने के लिए सेट करें यदि आप लॉग इन करना चाहते हैं या नहीं। लॉन्च करते समय इस ध्वज को एक पैरामीटर के रूप में सेट करें।
रिचर्ड टायर्रेम
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.