2011-12-07 13 views
7

एक सरणी [x1, x2, x3, ..., xk] को देखते हुए जहां xi बॉक्स I, में आइटमों की संख्या है, मैं आइटम को फिर से वितरित कैसे कर सकता हूं ताकि कोई बॉक्स एन आइटम से अधिक नहीं है। एन योग (xi)/k के करीब है - यानी, एन प्रत्येक बॉक्स के करीब है जिसमें आइटमों की संख्या समान है। इंटरमीडिएट बक्से का उपयोग वस्तुओं को ले जाने के लिए नहीं किया जाना चाहिए - यदि x1 में अधिशेष है और x2 और x3 में घाटे हैं, तो x1 को कुछ आइटम x2 और x3 पर भेजना चाहिए, लेकिन अपने सभी आइटम x2 पर नहीं भेजना चाहिए और फिर x2 को अधिशेष को हल करने दें ।भार संतुलन/पुन: वितरण से संबंधित एल्गोरिदम का नाम

वास्तविक समस्या यह है कि: प्रत्येक कंप्यूटिंग नोड में नमूने का एक सेट होता है, और एक resampling कदम के बाद कुछ कंप्यूटर नोड्स में अधिशेष हो सकता है जबकि दूसरों के पास घाटा होता है, इसलिए मैं संचार को कम करते समय नमूनों को फिर से वितरित करना चाहता हूं ।

मुझे लगता है कि इस तरह की समस्या का नाम है।

+1

आपका प्रश्न underspecified है: इसके अलावा, मुझे लगता है कि आदेश पुनर्वितरण में संरक्षित है सुनिश्चित करने के लिए (हालांकि वह पर्याप्त है, तो क्रम महत्वपूर्ण है ऐसा करना आसान है) किसी भी प्रयास नहीं किए हैं। उदाहरण के लिए, क्या एक दर्जन दूर नोड्स एक साथ लागत के समय अपने पड़ोसियों से बात कर सकते हैं? यदि 100 नोड्स में एक्स के लिए संदेश हैं, तो क्या वे उन्हें एक ही समय में, लागत 1 पर भेज सकते हैं, या क्या उन्हें लागत 100 पर क्रमबद्ध किया जाना चाहिए? अलग-अलग एल्गोरिदम अलग-अलग [गणना के मॉडल] के लिए लागू होंगे (http://en.wikipedia.org/wiki/Models_of_computation)। विशेष रूप से, एक [नेटवर्क टोपोलॉजी] (http://en.wikipedia.org/wiki/Network_topology) और/या वितरित स्मृति मॉडल बताएं। –

+0

यह वास्तव में अनिर्धारित है, लेकिन नीचे दिए गए कुछ उत्तरों से पहले ही बहुत मदद मिली है। – Gus

उत्तर

3

इस समस्या को minimum-cost flow के उदाहरण के रूप में मॉडलिंग किया जा सकता है।

Let जी, कोने रों, टी के साथ एक निर्देशित ग्राफ होना एक , ..., एक कश्मीर, ख , ..., ख कश्मीर और आर्क्स रों → एक मैं की क्षमता एक्स मैं और लागत 0, आर्क्स अनंत क्षमता की एक मैं → ख जे और अगर मैं = j 0 लागत और 1 लागत अगर मैं j ≠, और आर्क्स ख जे → टी क्षमता एन की और लागत 0। हम न्यूनतम लागत चाहते हैं प्रवाह जो Σ i x i इकाइयों को एस से टी तक ले जाता है। विचार यह है कि यदि वाई इकाइयां i → बी जे, तो वाई आइटम बॉक्स I से बॉक्स जे में स्थानांतरित हो जाते हैं (यदि मैं ≠ j; अगर i = j, तो कोई चाल नहीं होती है)।

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

  • नोड्स मैं की एक जोड़ी, जे सीधे जुड़ा नहीं है, तो एक मैं → ख जे चाप को हटा दें।

  • हम केवल "ए" पक्ष या "बी" पक्ष पर उन्हें ऊर्ध्वाधर देकर नोड्स को शुरू और बंद कर सकते हैं।

  • हम वर्दी से लागत समायोजित करके संचार गति में मतभेदों को मॉडल कर सकते हैं।

  • हम अपने चाप की क्षमता को सीमित करके दो नोड्स एक्सचेंज आइटमों की संख्या सीमित कर सकते हैं।

  • हम अधिक आंतरिक संकेतों को पेश कर सकते हैं और नेटवर्क विवाद के प्रभावों का मॉडल करने के लिए कनेक्शन के पूर्ण द्विपक्षीय टोपोलॉजी को बदल सकते हैं।

1

ऐसा लगता है कि आप लगातार हैशिंग

http://en.wikipedia.org/wiki/Consistent_hashing

मूल रूप से एक अच्छा यादृच्छिक हैश फ़ंक्शन का प्रयोग उपयोग करने के लिए आप अपने नमूनों कि एक और भी वितरण देना के लिए अद्वितीय आईडी प्राप्त करने की अनुमति देगा चाहते हैं। नोड्स के एक सेट में नमूनों को लगातार वितरित करना आसान होता है।

अधिक जानकारी के लिए

http://www.lexemetech.com/2007/11/consistent-hashing.html http://www.tomkleinpeter.com/2008/03/17/programmers-toolbox-part-3-consistent-hashing/

देखें।

+0

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

+0

अच्छी तरह से लगातार हैशिंग एक वितरित हैश तालिका का एक विशेष रूप है। तकनीकी रूप से यदि आप नोड्स को कभी भी जोड़ते या हटाते हैं तो आप कुछ आसान कर सकते हैं।अक्सर लोगों को डेटा की आईडी हैश करने के बाद नोड्स की संख्या से मॉड्यूल निर्धारित करता है कि डेटा किस नोड पर है। – nickmbailey

+0

मैं संचार को कम करना चाहता हूं। यदि एक नोड में अतिरिक्त वस्तुएं होती हैं और एक नोड में पर्याप्त रिक्ति होती है, तो मैं सभी अतिरिक्त वस्तुओं को एक नोड से दूसरे में ले जाना चाहता हूं। मुझे यह जानने की आवश्यकता नहीं है कि किस नोड में कुछ आइटम शामिल हैं जब तक कि कुछ नोड _does_। – Gus

0

मूल रूप से आप मुझे लगता है कि यह करने के लिए सबसे अच्छा तरीका है मंजिल (राशि (सरणी)/लेन (सरणी)) की गणना करने के लिए है

[9, 6, 1, 6, 2] 

से

[5, 5, 4, 5, 5] 

में जाना चाहते हैं, और फिर इस स्थिति को पाने के लिए आवश्यक अंतर का आकलन करें। इस मामले में, मंजिल ((9 + 6 + 1 + 6 + 2)/5) = 4, इसलिए हम [-5, -2, +3, -2, +2] के प्रारंभिक अंतर को देख रहे हैं। इसके बाद आप आसपास के जोड़ों में लालच से मूल्यों को स्वैप कर सकते हैं जहां संकेत भिन्न होते हैं (जैसे सरणी से 2 [2] -> arr [1] और 2 सरणी [4] -> सरणी [3] से स्थानांतरित करना)। तब आप [-5,0,1,0,0] के साथ छोड़े गए हैं और यहां से आप लालच को शेष बिट्स असाइन कर सकते हैं।

+0

मैं वास्तव में एक नाम की तलाश में हूँ। आपके द्वारा प्रस्तुत एल्गोरिदम अंतर्ज्ञानी है, लेकिन मुझे ऐसा कुछ चाहिए जो स्वैप को कम करने के करीब या कम हो। – Gus

0

मुझे लगता है कि यह पुनर्वितरण समस्या कंप्यूटिंग में लोड संतुलन से थोड़ा अलग है।

लोड संतुलन एल्गोरिदम शब्द का अर्थ आमतौर पर भविष्य के भार (और वर्तमान नहीं) के वितरण को सुनिश्चित करने के लिए नीतियों/हेरिस्टिक्स का संग्रह होता है।

इस मामले में, लोड बैलेंसर मौजूदा सर्वर/सिस्टम से लोड को फिर से वितरित नहीं करेगा, लेकिन आने वाला कोई भी नया अनुरोध, यह कुछ नीति (यानि कम से कम लोड, राउंडरोबिन इत्यादि) का उपयोग करके असाइन करने का प्रयास करेगा, जो करेगा सर्वर को अपेक्षाकृत समान रूप से लंबे समय तक लोड किया जाता है।

http://en.wikipedia.org/wiki/Load_balancing_(computing)

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

+0

मुझे लोड संतुलन को भी कॉल करने में संकोच नहीं है, लेकिन मुझे लगता है कि अवधारणा संबंधित है, या कम से कम यह मेरे मन में एकमात्र प्रश्न शब्द है। आपने "भविष्य" लोड बनाम "वर्तमान" लोड के बारे में भेद बनाया है। Resampling के बाद, एक सर्वर दूसरे के रूप में दो बार कण हो सकता है। इन कणों पर किए गए गणना को "भविष्य" लोड के रूप में माना जा सकता है, जिसे आप नमूने के * वर्तमान * सेट को वितरित करके संतुलित कर सकते हैं। – Gus

3

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

मास्टर फिर से (O(C)) गणना कर सकते हैं N, इस बाध्यता का उल्लंघन नोड्स की पहचान करें, और कितना। ध्यान दें कि बाध्यता पर अधिकता का योग वास्तव में न्यूनतम संचार की आवश्यकता है। N (यानी असंतुलन स्वीकार करके) की गणना करते समय एक स्लैक पैरामीटर डालने से, आप इस मात्रा को नियंत्रित कर सकते हैं।

एक प्रकार का उपयोग करके, नमूना गणना द्वारा नोड्स का क्रम O(C log C) में किया जा सकता है। दो कर्सर चलो, एक तरफ से एक तरफ, बीच की तरफ। प्रत्येक चरण में, बड़े नोड से छोटे नोड तक स्थानांतरण को शेड्यूल करें, शेष में शेष शेष शेष, या छोटे में शेष ढेर पर आकार दिया जाए। अगली वाक्य में जो भी नोड की सक्रिय बाधा थी, उसके सूचक को अग्रिम करें और तब तक दोहराएं जब तक कि नए बड़े पास कोई अतिरिक्त न हो। (मुझे विश्वास है कि यह लालची एल्गोरिदम @ नॉक्सविले हो रहा था।)

मानते हैं कि N प्रति नोड के नमूने की औसत गणना से अधिक है, यह देखने के लिए छोटा है कि यह आदर्श w.r.t. है। न्यूनतम संचार

मशीनों के अपने नेटवर्क किसी भी बाधाओं, या तो के रूप में अनुपस्थित लिंक या अधिकतम प्रवाह या एक किनारे के पार परिवर्तनीय लागत है, तो आप ग्राफ प्रवाह सामान बाहर तोड़ की जरूरत है। हालांकि आपने इस तरह के कुछ भी उल्लेख नहीं किया है, और उसी डेटा सेंटर के भीतर कंप्यूटर क्लस्टर आमतौर पर कोई नहीं है।

1

मुझे लगता है कि सवाल इस तरह से स्पष्ट किया जाना चाहिए:

M अधिशेष नोड्स और K घाटा नोड्स के साथ हम 0 अधिशेष नोड्स और (संभवतः) कुछ घाटा नोड्स के साथ राज्य के लिए नोड्स के बीच नमूने पुनर्वितरित चाहिए। नमूने को पैक में आदान-प्रदान किया जाना चाहिए और इन पैकों की संख्या को कम किया जाना चाहिए।

या, गणितीय, हम M*K मैट्रिक्स है, यह की प्रत्येक कोशिका नमूनों की संख्या का प्रतिनिधित्व K नोड के लिए, प्रत्येक पंक्ति में तत्वों की दी राशि और प्रत्येक स्तंभ में तत्व की राशि का दिया अधिकतम के साथ नोड M से पारित करने के लिए। लक्ष्य nonzero कोशिकाओं की संख्या को कम करने के लिए है।

यह "Constraint satisfaction problems" का एक प्रकार है। यह एनपी पूर्ण है। मुझे दो शास्त्रीय समस्याएं मिलीं जो इस प्रश्न के समान हैं: "पैकिंग सेट करें" और "सामान्यीकृत सटीक कवर"।

समस्या को "Set packing" पर कम करने के लिए, हमें N+1 नमूने के साथ कई अधिशेष नोड्स जोड़ने की आवश्यकता है, ताकि पुनर्वितरण के बाद कोई घाटा नोड छोड़ा जा सके। फिर प्रत्येक नोड के लिए हमें अधिशेष तत्वों और "घाटे" तत्वों के लिए सभी संभावित विभाजन उत्पन्न करने की आवश्यकता होती है। फिर अधिशेष और घाटे के विभाजन के Cartesian product पर "ऑप्टिमाइज़ेशन" संस्करण में "सेट पैकिंग" लागू होता है, जिसमें कम से कम सबसेट मिलते हैं।

समस्या को कम करने के लिए "Generalized exact cover", प्रत्येक नोड के लिए हमें अधिशेष तत्वों और "घाटे" तत्वों के लिए सभी संभावित विभाजन उत्पन्न करने की आवश्यकता है। फिर हमें M, M+1 जोड़ना चाहिए, ... कवर में सबसेट की संख्या को कम करने के लिए अनुकूलन नोड्स। फिर अधिशेष और घाटे के विभाजन और ऑप्टिमाइज़ेशन नोड्स के कार्टेशियन उत्पाद को "सामान्यीकृत सटीक कवर" लागू होता है। ऑप्टिमाइज़ेशन नोड्स की छोटी संख्या के लिए, यह एल्गोरिदम विफल हो जाएगा, कुछ बड़ी संख्या के लिए इसे न्यूनतम संख्या में सबसेट मिलेगा।

"सामान्यीकृत सटीक कवर" "Knuth's Algorithm X" द्वारा हल किया जा सकता है। मुझे "पैकिंग सेट" के लिए कोई एल्गोरिदम नहीं पता है।

ये सभी समाधान सटीक उत्तर देते हैं, लेकिन उनके पास जबरदस्त कम्प्यूटेशनल जटिलता है, यह बहुत ही असंभव है कि कोई वास्तविक शेड्यूलर में उनका उपयोग करता है। प्रैक्टिकल दृष्टिकोण कुछ ह्युरिस्टिक्स और लालची एल्गोरिदम का उपयोग करना है। बस अधिशेष नोड्स और घाटे नोड्स दोनों को सॉर्ट करें और "सर्वश्रेष्ठ फिट" रणनीति लागू करें।

1

मुझे आमतौर पर यह डेटा पुनर्वितरण कहा जाता है, यह समझने के साथ कि यदि आप इसे फिर से वितरित कर रहे हैं तो आप कुछ मीट्रिक के तहत वितरण को इष्टतम होना चाहते हैं, जैसे कार्यों के बीच समानता।

यह कम्प्यूटेशनल लोड संतुलन करने की कोशिश कर रहे समय में वैज्ञानिक/तकनीकी कंप्यूटिंग में आता है। यहां तक ​​कि यदि आप कई आयामों में गणना कर रहे हैं, यदि आप स्पेस भरने वाले वक्र द्वारा प्रोसेसर को असाइन करने वाले स्थानिक डेटा को फिर से वितरित कर रहे हैं, तो यह सटीक समस्या आती है, और वहां आप अक्सर डेटा को समान रूप से विभाजित करना चाहते हैं।

प्रक्रिया बहुत सरल है; आप x i का एक विशेष prefix sum लेना शुरू करते हैं ताकि आप जान सकें कि आपके "बाएं" कितने आइटम हैं। उदाहरण के लिए, ऊपर Noxville के उदाहरण के लिए, यदि आप डेटा था

[9, 6, 1, 6, 2] 

उपसर्ग रकम

[0, 9, 15, 16, 22] 

हो सकता है और आप (पिछले प्रोसेसर की राशि से अधिक कितने है) पाते हैं देखते हैं कि कुल में 24 आइटम।

फिर आप यह पता लगाते हैं कि आपके आदर्श विभाजन कितने बड़े होंगे - कहें, ceil (totitems/nprocs)। आप ऐसा कर सकते हैं हालांकि आप जब तक प्रत्येक प्रोसेसर इस बात पर सहमत होंगे कि सभी विभाजन आकार क्या होंगे।

अब, आपके पास आगे बढ़ने के कुछ तरीके हैं। यदि डेटा आइटम कुछ अर्थों में बड़े होते हैं और आपके पास स्मृति में दो प्रतियां नहीं हो सकती हैं, तो आप डेटा को अपने निकटतम पड़ोसियों में स्थानांतरित करना शुरू कर सकते हैं। आप अपने बाईं ओर वस्तुओं की संख्या और उस दिशा में "अतिरिक्त" या "घाटा" जानते हैं; और आप यह भी जानते हैं कि आपके पास कितने हैं (और अतिरिक्त या घाटे को ठीक करने के लिए आपने अपना हिस्सा पूरा करने के बाद किया होगा)। तो आप अपने बाएं और दाएं पड़ोसी को डेटा भेजना शुरू करते हैं, और अपने बाएं और दाएं पड़ोसी से डेटा प्राप्त करते हैं, जब तक प्रोसेसर को सामूहिक रूप से सही मात्रा में आइटम नहीं मिलते हैं और आप भी करते हैं।

लेकिन यदि आप डेटा की दो प्रतियां प्राप्त कर सकते हैं, तो आप एक और दृष्टिकोण ले सकते हैं जो भेजे गए संदेशों की संख्या को कम करता है। आप अपने स्थानीय डेटा की शुरुआती इंडेक्स के रूप में "ग्लोबल" सरणी में अपने बाएं सेल्स की संख्या के बारे में सोच सकते हैं। चूंकि आप जानते हैं कि प्रत्येक प्रोसेसर के साथ कितने आइटम समाप्त होंगे, आप सीधे पता लगा सकते हैं कि उन वस्तुओं को किस प्रक्रिया में समाप्त किया जाएगा, और उन्हें सीधे भेज सकते हैं। (उदाहरण के लिए, ऊपर दिए गए उदाहरण में, प्रोसेसर 0 - जिसमें आइटम 0..8 है - जानता है कि यदि प्रत्येक प्रोसेसर लेकिन आखिरी बार 5 डेटा आइटम्स के साथ समाप्त हो रहा है, तो 5-8 मान प्रोसेसर 1 को भेजा जा सकता है।) एक बार भेजे जाने के बाद, आप तब तक प्राप्त करते हैं जब तक आपके पास अपेक्षित डेटा की मात्रा न हो; और आपने कल लिया।

नीचे सी और एमपीआई में ऐसा करने का एक सरल उदाहरण है, लेकिन मूल दृष्टिकोण कहीं भी कहीं भी काम करना चाहिए। एमपीआई के उपसर्ग स्कैन आपरेशन समावेशी रकम उत्पन्न करता है, तो हम मान की अपनी संख्या बंद घटाना करने के लिए विशेष राशि प्राप्त करने के लिए:

#include <stdio.h> 
#include <stdlib.h> 
#include <mpi.h> 
#include <time.h> 

void initdata(const int rank, const int maxvals, char **data, int *nvals) { 
    time_t t; 
    unsigned seed; 

    t = time(NULL); 
    seed = (unsigned)(t * (rank + 1)); 

    srand(seed); 
    *nvals = (rand() % (maxvals-1)) + 1; 
    *data = malloc((*nvals+1) * sizeof(char)); 

    for (int i=0; i<*nvals; i++) { 
     (*data)[i] = 'A' + (rank % 26); 
    } 
    (*data)[*nvals] = '\0'; 
} 

int assignrank(const int globalid, const int totvals, const int size) { 
    int nvalsperrank = (totvals + size - 1)/size; 
    return (globalid/nvalsperrank); 
} 

void redistribute(char **data, const int totvals, const int curvals, const int globalstart, 
        const int rank, const int size, int *newnvals) { 

    const int stag = 1; 
    int nvalsperrank = (totvals + size - 1)/size; 

    *newnvals = nvalsperrank; 
    if (rank == size-1) *newnvals = totvals - (size-1)*nvalsperrank; 

    char *newdata = malloc((*newnvals+1) * sizeof(char)); 
    newdata[(*newnvals)] = '\0'; 

    MPI_Request requests[curvals]; 

    int nmsgs=0; 

    /* figure out whose data we have, redistribute it */ 
    int start=0; 
    int newrank = assignrank(globalstart, totvals, size); 
    for (int val=1; val<curvals; val++) { 
     int nextrank = assignrank(globalstart+val, totvals, size); 
     if (nextrank != newrank) { 
      MPI_Isend(&((*data)[start]), (val-1)-start+1, MPI_CHAR, newrank, stag, MPI_COMM_WORLD, &(requests[nmsgs])); 
      nmsgs++; 
      start = val; 
      newrank = nextrank; 
     } 
    } 
    MPI_Isend(&((*data)[start]), curvals-start, MPI_CHAR, newrank, stag, MPI_COMM_WORLD, &(requests[nmsgs])); 
    nmsgs++; 

    /* now receive all of our data */ 
    int newvalssofar= 0; 
    int count; 
    MPI_Status status; 
    while (newvalssofar != *newnvals) { 
     MPI_Recv(&(newdata[newvalssofar]), *newnvals - newvalssofar, MPI_CHAR, MPI_ANY_SOURCE, stag, MPI_COMM_WORLD, &status); 
     MPI_Get_count(&status, MPI_CHAR, &count); 
     newvalssofar += count; 
    } 

    /* wait until all of our sends have been received */ 
    MPI_Status statuses[curvals]; 
    MPI_Waitall(nmsgs, requests, statuses); 

    /* now we can get rid of data and relace it with newdata */ 
    free(*data); 
    *data = newdata; 
} 

int main(int argc, char **argv) { 
    const int maxvals=30; 
    int size, rank; 
    char *data; 
    int mycurnvals, mylvals, myfinalnvals; 
    int totvals; 

    MPI_Init(&argc, &argv); 
    MPI_Comm_size(MPI_COMM_WORLD, &size); 
    MPI_Comm_rank(MPI_COMM_WORLD, &rank); 

    initdata(rank, maxvals, &data, &mycurnvals); 

    MPI_Scan(&mycurnvals, &mylvals, 1, MPI_INT, MPI_SUM, MPI_COMM_WORLD); 
    if (rank == size-1) totvals = mylvals; 
    mylvals -= mycurnvals; 

    MPI_Bcast(&totvals, 1, MPI_INT, size-1, MPI_COMM_WORLD); 

    printf("%3d  : %s %d\n", rank, data, mylvals); 

    redistribute(&data, totvals, mycurnvals, mylvals, rank, size, &myfinalnvals); 


    printf("%3d after: %s\n", rank, data); 

    free(data); 
    MPI_Finalize(); 
    return 0; 
} 

चल रहा है यह आपके अपेक्षित व्यवहार मिलता है, ध्यान दें कि जिस तरह से मैंने "वांछित" विभाजन निर्धारित किया है (छत (totvals/nprocesses) का उपयोग करके) अंतिम प्रोसेसर आम तौर पर लोड हो जाएगा।

$ mpirun -np 13 ./distribute 
    0  : AAAAAAAAAAA 0 
    1  : BBBBBBBBBBBB 11 
    2  : CCCCCCCCCCCCCCCCCCCCCCCCCC 23 
    3  : DDDDDDD 49 
    4  : EEEEEEEEE 56 
    5  : FFFFFFFFFFFFFFFFFF 65 
    6  : G 83 
    7  : HHHHHHH 84 
    8  : IIIIIIIIIIIIIIIIIIIII 91 
    9  : JJJJJJJJJJJJJJJJJJ 112 
10  : KKKKKKKKKKKKKKKKKKKK 130 
11  : LLLLLLLLLLLLLLLLLLLLLLLLLLLL 150 
12  : MMMMMMMMMMMMMMMMMM 178 

    0 after: AAAAAAAAAAABBBBB 
    1 after: BBBBBBBCCCCCCCCC 
    2 after: CCCCCCCCCCCCCCCC 
    3 after: DDDDDDDCEEEEEEEE 
    4 after: EFFFFFFFFFFFFFFF 
    5 after: FFFHHHHHHHIIIIIG 
    6 after: IIIIIIIIIIIIIIII 
    7 after: JJJJJJJJJJJJJJJJ 
    8 after: JJKKKKKKKKKKKKKK 
    9 after: LLLLLLLLLLKKKKKK 
10 after: LLLLLLLLLLLLLLLL 
11 after: LLMMMMMMMMMMMMMM 
12 after: MMMM 
संबंधित मुद्दे