मैं इसी तरह की समस्या पर शोध करते हुए इस सवाल पर भागा: स्तरीकरण को कम करने के लिए तरल पदार्थों का इष्टतम जोड़। ऐसा लगता है कि मेरा समाधान आपकी स्थिति पर भी लागू होगा।
यदि आप 30,20,10 के अनुपात में तरल पदार्थ A, B, और C को मिलाना चाहते हैं (अर्थात A की 30 इकाइयाँ, B की 20 इकाइयाँ और C की 10 इकाइयाँ), तो आप स्तरीकरण के साथ समाप्त हो जाते हैं यदि आप सभी को जोड़ते हैं ए, फिर सभी बी, और फिर सभी सी। आप छोटी इकाइयों को मिलाकर बेहतर हैं। उदाहरण के लिए, [A, B, A, C, B, A] अनुक्रम में एकल-इकाई जोड़ करें। यह स्तरीकरण को पूरी तरह से रोक देगा।
जिस तरह से मैंने ऐसा किया है वह एक प्राथमिकता मर्ज का उपयोग करके इसे एक प्रकार का मर्ज के रूप में माना जाता है। यदि मैं परिवर्धन का वर्णन करने के लिए एक संरचना बनाता हूं:
MergeItem
Item, Count, Frequency, Priority
फ़्रिक्वेंसी को "हर एन" के रूप में व्यक्त किया जाता है। तो A, जिसे छह में से तीन बार जोड़ा गया है, की आवृत्ति 2 (6/3) है।
और एक ढेर को शुरू करें जिसमें शुरू में शामिल हो:
(A, 3, 2, 2)
(B, 2, 3, 3)
(C, 1, 6, 6)
अब, मैं पहले आइटम को ढेर से हटाता हूं और इसे आउटपुट करता हूं। फिर इसकी गिनती 1 से कम करें और फ़्रीक्वेंसी द्वारा प्राथमिकता बढ़ाएं और इसे वापस ढेर में जोड़ें। परिणामी हीप है:
(B, 2, 3, 0)
(A, 2, 2, 4)
(C, 1, 6, 6)
अगला, बी को ढेर से हटा दें, आउटपुट करें और इसे अपडेट करें, फिर वापस हीप में जोड़ें:
(A, 2, 2, 4)
(C, 1, 6, 6)
(B, 1, 3, 6)
यदि मैं उस फैशन में जारी रहता हूं, तो मुझे वांछित मिश्रण मिलता है। मैं यह सुनिश्चित करने के लिए एक कस्टम तुलनित्र का उपयोग करता हूं कि जब समान प्राथमिकता वाले आइटम को ढेर में डाला जाता है, तो सबसे अधिक आवृत्ति वाले मान (यानी कम से कम लगातार) का आदेश दिया जाता है।
मैंने अपने ब्लॉग पर समस्या और उसके समाधान का अधिक पूर्ण विवरण लिखा, और कुछ कार्यशील C # कोड प्रस्तुत किए जो इसे दिखाता है। समान रूप से सूची में आइटम वितरित करना देखें ।
टिप्पणियों के बाद अपडेट करें
मुझे लगता है कि मेरी समस्या ओपी की समस्या के समान है, और इसलिए मेरा समाधान संभावित रूप से उपयोगी है। मैं ओपी के प्रश्न के संदर्भ में अपने उत्तर को अधिक नहीं बताने के लिए माफी चाहता हूं।
पहली आपत्ति, कि मेरा समाधान 0, 1, और 2 के बजाय A, B, और C का उपयोग कर रहा है, आसानी से छूट जाता है। यह केवल नामकरण की बात है। मुझे यह सोचने में आसान और कम भ्रमित लगता है और "दो 1" के बजाय "दो ए" कहा जाता है। लेकिन इस चर्चा के प्रयोजनों के लिए मैंने ओपी के नामकरण का उपयोग करने के लिए अपने आउटपुट को नीचे संशोधित किया है।
बेशक मेरी समस्या दूरी की अवधारणा से संबंधित है। यदि आप "चीजों को समान रूप से फैलाना चाहते हैं," दूरी निहित है। लेकिन, फिर से, यह पर्याप्त रूप से यह दिखाने में विफल रहा कि मेरी समस्या ओपी की समस्या के समान कैसे है।
मैंने ओपी द्वारा प्रदान किए गए दो उदाहरणों के साथ कुछ परीक्षण किए। अर्थात्:
[1,1,2,2,3,3] // which I converted to [0,0,1,1,2,2]
[0,0,0,0,1,1,1,2,2,3]
मेरे नामकरण में वे क्रमशः [२,२,२] और [४,३,२,१] के रूप में व्यक्त किए जाते हैं। अर्थात्, अंतिम उदाहरण में, "टाइप 0 के 4 आइटम, टाइप 1 के 3 आइटम, टाइप 2 के 2 आइटम, और टाइप 3 के 1 आइटम।"
मैंने अपना परीक्षण कार्यक्रम चलाया (जैसा कि तुरंत नीचे वर्णित है), और अपने परिणाम पोस्ट किए हैं। ओपी से अनुपस्थित इनपुट, मैं यह नहीं कह सकता कि अगर मेरे परिणाम समान हैं, तो इससे भी बदतर, या उससे बेहतर हैं। न ही मैं अपने परिणामों की तुलना किसी और के परिणामों से कर सकता हूं क्योंकि किसी और ने कोई पोस्ट नहीं किया है।
मैं कह सकता हूं, हालांकि, एल्गोरिथ्म तरल पदार्थ को मिलाते समय स्तरीकरण को खत्म करने की मेरी समस्या का एक अच्छा समाधान प्रदान करता है । और ऐसा लगता है कि यह ओपी की समस्या का उचित समाधान प्रदान करता है।
नीचे दिखाए गए परिणामों के लिए, मैंने अपने ब्लॉग प्रविष्टि में विस्तृत एल्गोरिथ्म का उपयोग किया, जिसमें प्रारंभिक प्राथमिकता निर्धारित की गई थी Frequency/2
, और ढेर तुलनाकर्ता को अधिक लगातार आइटम का पक्ष लेने के लिए संशोधित किया गया था। संशोधित कोड यहां दिखाया गया है, जिसमें संशोधित लाइनों पर टिप्पणी की गई है।
private class HeapItem : IComparable<HeapItem>
{
public int ItemIndex { get; private set; }
public int Count { get; set; }
public double Frequency { get; private set; }
public double Priority { get; set; }
public HeapItem(int itemIndex, int count, int totalItems)
{
ItemIndex = itemIndex;
Count = count;
Frequency = (double)totalItems / Count;
// ** Modified the initial priority setting.
Priority = Frequency/2;
}
public int CompareTo(HeapItem other)
{
if (other == null) return 1;
var rslt = Priority.CompareTo(other.Priority);
if (rslt == 0)
{
// ** Modified to favor the more frequent item.
rslt = Frequency.CompareTo(other.Frequency);
}
return rslt;
}
}
ओपी के पहले उदाहरण के साथ अपने परीक्षण कार्यक्रम को चला रहा हूं, मुझे मिलता है:
Counts: 2,2,2
Sequence: 1,0,2,1,0,2
Distances for item type 0: 3,3
Stddev = 0
Distances for item type 1: 3,3
Stddev = 0
Distances for item type 2: 3,3
Stddev = 0
इसलिए मेरा एल्गोरिथ्म सभी काउंट्स की तुच्छ समस्या के लिए समान रूप से काम करता है।
दूसरी समस्या के लिए जो ओपी ने पोस्ट किया, मुझे मिला:
Counts: 4,3,2,1
Sequence: 0,1,2,0,1,3,0,2,1,0
Distances for item type 0: 3,3,3,1
Stddev = 0.866025403784439
Distances for item type 1: 3,4,3
Stddev = 0.471404520791032
Distances for item type 2: 5,5
Stddev = 0
Distances for item type 3: 10
Stddev = 0
Standard dev: 0.866025403784439,0.471404520791032,0,0
मुझे उस पर सुधार करने का कोई स्पष्ट तरीका नहीं दिख रहा है। इसे आइटम 0 [2,3,2,3] या 2 और 3 की कुछ अन्य व्यवस्था के लिए दूरी बनाने के लिए फिर से व्यवस्थित किया जा सकता है, लेकिन यह आइटम 1 और / या 2 के लिए विचलन को बदल देगा। मुझे वास्तव में नहीं पता कि क्या "इष्टतम" इस स्थिति में है। क्या अधिक बार या कम लगातार वस्तुओं पर एक बड़ा विचलन होना बेहतर है?
ओपी से अन्य समस्याओं को कम करते हुए, मैंने अपने स्वयं के कुछ बनाने के लिए उनके विवरण का उपयोग किया। उन्होंने अपने पोस्ट में कहा:
एक विशिष्ट सूची में ~ 15 अलग-अलग मात्राओं में 15 अलग-अलग मूल्यों के साथ 50 आइटम हैं।
तो मेरे दो परीक्षण थे:
[8,7,6,5,5,4,3,3,2,2,2,1,1,1,1] // 51 items, 15 types
[12,6,5,4,4,3,3,3,2,2,2,1,1] // 48 items, 13 types
और मेरे परिणाम:
Counts: 8,7,6,5,5,4,3,3,2,2,2,1,1,1,1
Sequence: 0,1,2,3,4,5,7,6,0,1,2,8,9,10,4,3,0,1,5,2,0,1,3,4,6,7,14,11,13,12,0,2,5,1,0,3,4,2,8,10,9,1,0,7,6,5,3,4,2,1,0
Distances for item type 0: 8,8,4,10,4,8,8,1
Stddev = 2.82566363886433
Distances for item type 1: 8,8,4,12,8,8,3
Stddev = 2.76272565797339
Distances for item type 2: 8,9,12,6,11,5
Stddev = 2.5
Distances for item type 3: 12,7,13,11,8
Stddev = 2.31516738055804
Distances for item type 4: 10,9,13,11,8
Stddev = 1.72046505340853
Distances for item type 5: 13,14,13,11
Stddev = 1.08972473588517
Distances for item type 6: 17,20,14
Stddev = 2.44948974278318
Distances for item type 7: 19,18,14
Stddev = 2.16024689946929
Distances for item type 8: 27,24
Stddev = 1.5
Distances for item type 9: 28,23
Stddev = 2.5
Distances for item type 10: 26,25
Stddev = 0.5
Distances for item type 11: 51
Stddev = 0
Distances for item type 12: 51
Stddev = 0
Distances for item type 13: 51
Stddev = 0
Distances for item type 14: 51
Stddev = 0
और दूसरे उदाहरण के लिए:
Counts: 12,6,5,4,4,3,3,3,2,2,2,1,1
Sequence: 0,1,2,0,3,4,7,5,6,0,1,8,9,10,0,2,0,3,4,1,0,2,6,7,5,12,11,0,1,0,3,4,2,0,1,10,8,9,0,7,5,6,0,
4,3,2,1,0
Distances for item type 0: 3,6,5,2,4,7,2,4,5,4,5,1
Stddev = 1.68325082306035
Distances for item type 1: 9,9,9,6,12,3
Stddev = 2.82842712474619
Distances for item type 2: 13,6,11,13,5
Stddev = 3.44093010681705
Distances for item type 3: 13,13,14,8
Stddev = 2.34520787991171
Distances for item type 4: 13,13,12,10
Stddev = 1.22474487139159
Distances for item type 5: 17,16,15
Stddev = 0.816496580927726
Distances for item type 6: 14,19,15
Stddev = 2.16024689946929
Distances for item type 7: 17,16,15
Stddev = 0.816496580927726
Distances for item type 8: 25,23
Stddev = 1
Distances for item type 9: 25,23
Stddev = 1
Distances for item type 10: 22,26
Stddev = 2
Distances for item type 11: 48
Stddev = 0
Distances for item type 12: 48
Stddev = 0