2010-09-02 15 views
7

यह एक समस्या है जो मुझे लगता है कि पहले से ही एक एल्गोरिदम है - लेकिन मुझे लगता है कि Google के साथ उपयोग करने के लिए सही शब्द नहीं हैं :)।इष्टतम फ़ाइल आकार संयोजन

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

इस बटन को निर्देशिका में सभी फाइलों की तुलना करनी चाहिए और परिणामस्वरूप फाइलों की एक सूची प्रदान की जानी चाहिए जो एक साथ रखे जाने पर सीमा के बिना अधिकतम कुल फ़ाइल आकार के करीब आते हैं।

इस तरह से आप सीडी या डीवीडी को जलाने के दौरान कौन सी फाइलों को गठबंधन कर सकते हैं, ताकि आप डिस्क के जितना संभव हो सके उपयोग कर सकें।

मैं इस खुद के लिए एल्गोरिथ्म साथ आने के लिए कोशिश की है - लेकिन असफल :(

किसी को भी ऐसा करने के लिए कुछ अच्छा कलन विधि के बारे में पता

अग्रिम :)

+3

यह मुझे http://xkcd.com/287/ – ruslik

+0

की याद दिलाता है मुझे लगता है कि सही समस्या परिभाषा होगी "इन फ़ाइलों को न्यूनतम संख्या में डिब्बे कैसे विभाजित करें, ताकि प्रत्येक बिन की फ़ाइलें अधिक न हों आकार सीमा। ", और यह नासैकैक की एक और मुश्किल समस्या है। – ruslik

उत्तर

2

धन्यवाद।? लगता है कि आपके पास hard समस्या है। यह समस्या अच्छी तरह से जानी जाती है, लेकिन कोई कुशल समाधान (कर सकते हैं?) मौजूद नहीं है।

+0

कुशल * अनुमानित * समाधान मौजूद हैं। –

+2

उचित कुशल सटीक समाधान मौजूद हैं। गतिशील प्रोग्रामिंग समाधान छद्म-बहुपद है। और सौभाग्य से, एक डीवीडी का आकार स्थिर है, कम से कम जब तक आप ब्लू-रे-डब्ल्यू ड्राइव प्राप्त नहीं करते हैं। इसलिए मैं कम से कम डीपी समाधान को जाने दूंगा। यह बड़ी निर्देशिकाओं के लिए असफल हो सकता है, सच है, लेकिन मुझे वास्तव में पता नहीं है कि "बड़ी" 10000 फाइलें कहें, उससे कम या कम है। युक्ति: सभी फाइल आकारों को डीवीडी फाइल सिस्टम ब्लॉक आकार में पहले करें: यह डीपी समाधान को काफी तेज़ी से बढ़ाएगा और * अधिक * सटीक परिणाम देगा। –

+0

(1 घंटा बाद में) अब मुझे पता है कि "बड़ी" 10000 से कम फाइलें हैं, जिससे डीपी समाधान चल रहा है। लेकिन यह एक कठोर कठोर समस्या नहीं है, यह उस कष्टप्रद-के-क्रम-परिमाण में है-जब तक-मैं-सोच-कुछ-चालाक क्षेत्र नहीं कर सकता। –

0

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

0

आपके उत्तरों के लिए धन्यवाद।

मैंने दिए गए उत्तरों के मार्गदर्शन के साथ अब इस समस्या को और अधिक देखा। अन्य चीजों के अलावा मुझे यह वेबपृष्ठ मिला, http://www.mathmaniacs.org/lessons/C-subsetsum/index.html। यह सबसेट योग समस्या के बारे में बताता है, जो मुझे विश्वास है कि मैंने यहां वर्णित समस्या है।

वेबपेज से एक वाक्य यह है:

-

आप का कहना कर सकते हैं कि 2300 की तरह एक नंबर इतनी बड़ी है कि यहां तक ​​कि एक लाख या अरब से अधिक की रफ्तार से एक कंप्यूटर गिनती प्रत्येक सेकेंड, हमारे सूर्य जलाए जाने के लंबे समय तक 2300 तक नहीं पहुंच पाएगा।

-

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

एमपी 3 के साथ एक सीडी आसानी से 100 एमपी 3 और डीवीडी बहुत अधिक हो सकती है, जिससे मेरा उत्तर देने से पहले सूर्य जल रहा है :)।

यादृच्छिक रूप से इष्टतम राशि खोजने का प्रयास कर आपको बहुत करीब मिल सकता है लेकिन इसे कभी भी इष्टतम उत्तर होने की गारंटी नहीं दी जा सकती है और दुर्भाग्य से भी बहुत दूर हो सकता है। ब्रूट-फोर्स एकमात्र वास्तविक तरीका है जो ऐसा लगता है कि इष्टतम उत्तर प्राप्त होता है और यह बहुत लंबा रास्ता लेगा।

तो मुझे लगता है कि मैं सीडी और डीवीडी पर जलाने के लिए फ़ाइलों का मैन्युअल रूप से एक अच्छा संयोजन अनुमान लगा रहा हूं। :)

सहायता के लिए धन्यवाद। :)

+1

नहीं, आप अनावश्यक निराशावादी हैं। मैंने अभी पाइथन में कुछ कोड तैयार किए हैं, पूरी तरह से अप्रत्याशित। 2kb के ब्लॉक आकार को मानते हुए, यह 100 सेकंड (100k-6k ब्लॉक के बीच यादृच्छिक आकार) और 100 सेकंड में आकार 40000 ब्लॉक (यानी, 80 एमबी) की डिस्क के लिए समस्या के निर्णय संस्करण को हल करेगा। जाहिर है कि यह आपकी समस्या तक अभी तक नहीं है, लेकिन यह कम से कम ballpark में है, और सूर्य अभी तक जलाया नहीं है कि मैंने देखा है ;-)। आपने जो पढ़ा है उसके बावजूद, सटीक समाधान वास्तव में ओ (एन * एम) है, जहां एन फाइलों की संख्या है और एम डीवीडी का आकार है। यह * घाटा * नहीं है। –

5

यह अन्य इंगित करता है, नॅपैकैक समस्या, जो संयोजी अनुकूलन समस्या है। इसका मतलब है कि आप एक सेट के कुछ सबसेट या क्रमपरिवर्तन की तलाश करते हैं जो एक निश्चित लागत को कम करता है (या अधिकतम करता है)। एक और अच्छी तरह से ज्ञात ऐसी समस्या Traveling Salesman Problem है।

ऐसी समस्याएं हल करने के लिए आमतौर पर बहुत कठिन होती हैं। लेकिन यदि आप में लगभग समाधानों में रुचि रखते हैं, तो आप simulated annealing जैसे गैर-निर्धारिती एल्गोरिदम का उपयोग कर सकते हैं। आपको सबसे अधिक संभावना इष्टतम समाधान नहीं मिलेगा, लेकिन लगभग इष्टतम।

This link बताता है कि कैसे नकली एनीलिंग नॅपैकैक समस्या को हल कर सकती है, और इसलिए आपको दिलचस्प होना चाहिए।

+0

सभी सच एक चीज़ को बचाते हैं - आप? कर सकते हैं? इष्टतम समाधान प्राप्त करें, केवल कोई * गारंटी * नहीं है जो आप करेंगे - खोज स्थान के आकार पर निर्भर करता है और आप कितने भाग्यशाली हैं - निश्चित रूप से असंभव है, लेकिन लॉटरी भी है, और लोग जीतते हैं ...... –

+0

@ मार्क: वास्तव में ट्रैवलिंग सेल्समैन समस्या के लिए, गैर-निर्धारक तरीकों से मिले समाधान की इष्टतमता को प्रमाणित किया जा सकता है। YYY की संभावना के साथ एनएनएन चरणों के बाद आपको अनुकूलतम (लागत की अवधि में) के भीतर समाधान प्राप्त करने की गारंटी है, और आपके पास XXX, YYY और NNN से संबंधित एक सूत्र है। यह अभ्यास में बहुत अच्छा है। –

+0

सच - आपको गारंटी है कि समाधान इष्टतम XXX के भीतर होगा - मेरा अवलोकन केवल इतना था कि आप भाग्यशाली हो सकते हैं और इष्टतम समाधान को हिट कर सकते हैं - मैं आपकी मूल पोस्ट को नापसंद कर रहा था जब आपने कहा था कि आपको इष्टतम समाधान नहीं मिलेगा - आप कर सकते हैं, लेकिन मैं निश्चित रूप से इस पर शर्त नहीं लगाऊंगा :-) –

4

बस मस्ती के लिए मैंने सटीक गतिशील प्रोग्रामिंग समाधान की कोशिश की। पाइथन में लिखा गया है कि मेरे सर्वोच्च विश्वास के कारण आपको इसे अनुकूलित नहीं करना चाहिए ;-)

यह या तो एक शुरुआत प्रदान कर सकता है, या फिर अनुमान लगा सकता है कि आप अनुमान लगाने से पहले कितना करीब प्राप्त कर सकते हैं।

कोड http://en.wikipedia.org/wiki/Knapsack_problem#0-1_knapsack_problem पर आधारित है, इसलिए कम-से-जानकारीपूर्ण चर नाम m, W, w, v

#!/usr/bin/python 

import sys 

solcount = 0 

class Solution(object): 
    def __init__(self, items): 
     object.__init__(self) 
     #self.items = items 
     self.value = sum(items) 
     global solcount 
     solcount += 1 
    def __str__(self): 
     #return str(self.items) + ' = ' + str(self.value) 
     return ' = ' + str(self.value) 

m = {} 

def compute(v, w): 
    coord = (len(v),w) 
    if coord in m: 
     return m[coord] 
    if len(v) == 0 or w == 0: 
     m[coord] = Solution([]) 
     return m[coord] 
    newvalue = v[0] 
    newarray = v[1:] 
    notused = compute(newarray, w) 
    if newvalue > w: 
     m[coord] = notused 
     return notused 
    # used = Solution(compute(newarray, w - newvalue).items + [newvalue]) 
    used = Solution([compute(newarray, w - newvalue).value] + [newvalue]) 
    best = notused if notused.value >= used.value else used 
    m[coord] = best 
    return best 

def main(): 
    v = [int(l) for l in open('filesizes.txt')] 
    W = int(sys.argv[1]) 
    print len(v), "items, limit is", W 
    print compute(v, W) 
    print solcount, "solutions computed" 

if __name__ == '__main__': 
    main() 

सरलता के लिए मैं सिर्फ फ़ाइल आकार पर विचार कर रहा हूँ: एक बार आप आकार है कि आप उपयोग करना चाहते हैं की सूची है, तो आप एक सूची के माध्यम से खोज से उन आकारों के साथ कुछ फ़ाइल नाम मिल सकता है, इसलिए वहाँ कोई मतलब नहीं tangling है कोर में फ़ाइल नाम, कार्यक्रम के धीमे भाग। मैं ब्लॉक आकार के गुणकों में सबकुछ भी व्यक्त कर रहा हूं।

जैसा कि आप देख सकते हैं, मैंने उस कोड को टिप्पणी की है जो वास्तविक समाधान (समाधान के मूल्य के विपरीत) देता है। यह स्मृति को सहेजना था - उपयोग की गई फ़ाइलों की सूची को स्टोर करने का उचित तरीका प्रत्येक समाधान में एक सूची नहीं है, यह प्रत्येक समाधान को हल किए गए समाधान पर वापस इंगित करना है। फिर आप प्रत्येक चरण में मानों के बीच अंतर को आउटपुट करते हुए श्रृंखला के माध्यम से वापस जाकर अंत में फाइलों की सूची की गणना कर सकते हैं।

2000-6000 की सीमा में 100 यादृच्छिक रूप से जेनरेट की गई फ़ाइल आकारों की एक सूची के साथ (मैं 2k ब्लॉक मान रहा हूं, इसलिए आकार 4-12 एमबी की फाइलें हैं), यह मेरे लैपटॉप पर 100 सेकंड में डब्ल्यू = 40 के लिए हल करता है । ऐसा करने में यह एक संभावित 4 एम समाधान के 2.6 एम की गणना करता है।

जटिलता ओ (डब्ल्यू * एन) है, जहां एन फाइलों की संख्या है। यह इस तथ्य का खंडन नहीं करता है कि समस्या एनपी-पूर्ण है। तो मैं कम से कम एक समाधान के पास आ रहा हूं, और यह सिर्फ अनियंत्रित पायथन में है।

स्पष्ट रूप से कुछ अनुकूलन की आवश्यकता है, क्योंकि वास्तव में इसे डब्ल्यू = 4 एम (8 जीबी डीवीडी) के लिए हल करने की आवश्यकता है और हालांकि आपके पास कई फाइलें हैं (कुछ हज़ार कहें)। यह मानते हुए कि कार्यक्रम को 15 मिनट (डीवीडी लिखने के लिए आवश्यक समय के बराबर) लेने की अनुमति है, इसका मतलब है कि प्रदर्शन वर्तमान में लगभग 10^3 के कारक से छोटा है। इसलिए हमें एक समस्या है जो एक पीसी पर जल्दी और सटीक हल करने में काफी मुश्किल है, लेकिन प्रौद्योगिकी की सीमाओं से परे नहीं है।

स्मृति उपयोग मुख्य चिंता है, क्योंकि एक बार जब हम स्वैप मारना शुरू कर देते हैं तो हम धीमे हो जाएंगे, और यदि हम वर्चुअल एड्रेस स्पेस से बाहर निकलते हैं तो हम वास्तविक परेशानी में हैं क्योंकि हमें डिस्क पर समाधानों का अपना संग्रहण लागू करना है । मेरा परीक्षण 600 एमबी पर चोटी चलाता है। यदि आपने 32-बिट मशीन पर सी में कोड लिखा है, तो प्रत्येक "समाधान" में 8 बाइट्स का निश्चित आकार होता है। इसलिए आप लूप में कोई स्मृति आवंटन किए बिना उनमें से एक विशाल 2-डी सरणी उत्पन्न कर सकते हैं, लेकिन 2 जीबी रैम में आप केवल W = 4M और n = 67 को संभाल सकते हैं। ओह - डीवीडी बाहर हैं। यह लगभग 2-के अवरोधक सीडी के लिए लगभग हल हो सकता है, हालांकि: डब्ल्यू = 350k एन = 766 देता है।

संपादित करें: एमएके के सुझाव को क्रमशः नीचे-नीचे की तुलना में नीचे की ओर गणना करने के लिए, स्मृति की आवश्यकता को बड़े पैमाने पर कम करना चाहिए। सबसे पहले 0 < = डब्ल्यू < = डब्ल्यू के लिए एम (1, डब्ल्यू) की गणना करें। इस सरणी से, आप सभी= डब्ल्यू < = डब्ल्यू के लिए एम (2, डब्ल्यू) की गणना कर सकते हैं। फिर आप सभी एम को फेंक सकते हैं (1, डब्ल्यू) मूल्य: आपको एम (3, डब्ल्यू) आदि की गणना करने की आवश्यकता नहीं होगी

वैसे, मुझे संदेह है कि वास्तव में जिस समस्या को आप हल करना चाहते हैं वह bin packing problem हो सकता है, केवल प्रश्न के बजाय एक डीवीडी भरने के लिए निकटतम संभव कैसे प्राप्त करें। ऐसा लगता है कि यदि आपके पास फाइलों का एक गुच्छा है, तो आप उन्हें डीवीडी पर लिखना चाहते हैं, जितना संभव हो उतने डीवीडी का उपयोग कर। ऐसी स्थितियां हैं जहां बिन पैकिंग समस्या को हल करना बहुत आसान है, लेकिन इस समस्या को हल करना मुश्किल है। उदाहरण के लिए, मान लीजिए कि आपके पास 8 जीबी डिस्क हैं, और 15 जीबी छोटी फाइलें हैं। यह 8 जीबी के निकटतम संभावित मैच को खोजने के लिए कुछ खोज करने जा रहा है, लेकिन बिन-पैकिंग समस्या को केवल प्रत्येक डिस्क पर लगभग आधे फाइलों को डालकर हल किया जाएगा - इससे कोई फ़र्क नहीं पड़ता कि आप उन्हें कैसे विभाजित करते हैं क्योंकि आप हैं जो भी आप करते हैं 1 जीबी स्पेस बर्बाद करने जा रहे हैं।

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

+0

+1। संभावित अनुकूलन (ओपी के लिए): रिकर्सन के बजाय नीचे एक डीपी का उपयोग करें, या कम से कम 'dict' को' 2 डी सरणी या 'सूची' की 'सूची' के साथ बदलें। – MAK

+0

और दूसरा अनुकूलन - एक नई सूची 'newarray' नहीं बनाएं, उसी सूची का उपयोग करें, लेकिन आसपास एक इंडेक्स पास करें। 'एम' के लिए 2-डी सरणी के साथ, और सी जैसी भाषा में स्विच मानते हुए, जो' गणना 'से अंतिम स्मृति आवंटन को समाप्त करता है। –

+0

@MAK: मैं * भी * रिकर्सन के बारे में चिंतित नहीं हूं, क्योंकि यह केवल 'n' गहरा हो जाता है। N> = 1000 के लिए, इसका अर्थ है पायथन में 'sys.setrecursionlimit' को कॉल करना। –

0

यदि आप एक उचित ह्युरिस्टिक खोज रहे हैं, और उद्देश्य आवश्यक डिस्क की संख्या को कम करना है, तो यहां एक साधारण व्यक्ति है जिसे आप विचार कर सकते हैं। यह हाल ही में एक नौकरी की दुकान की समस्या के लिए इस्तेमाल किया गया है। मैं इसे ज्ञात ऑप्टिमा से तुलना करने में सक्षम था, और पाया कि यह आवंटन प्रदान करता है जो इष्टतम या इष्टतम होने के बेहद करीब थे।

मान लीजिए बी सभी फाइलों का आकार संयुक्त है और सी प्रत्येक डिस्क की क्षमता है। फिर आपको कम से कम एन = राउंडअप (बी/सी) डिस्क की आवश्यकता होगी। एन डिस्क पर सभी फाइलों को फिट करने का प्रयास करें। यदि आप ऐसा करने में सक्षम हैं, तो आप समाप्त हो गए हैं, और एक इष्टतम समाधान है। अन्यथा, एन + 1 डिस्क पर सभी फाइलों को फिट करने का प्रयास करें। यदि आप ऐसा करने में सक्षम हैं, तो आपके पास एक उदारवादी समाधान है; अन्यथा एन + 2 डिस्क पर फ़ाइलों को फिट करने का प्रयास करें, और इसी तरह, जब तक आप ऐसा करने में सक्षम न हों।

नीचे डिस्क पर फ़ाइलों के किसी दिए गए आवंटन के लिए (जो कुछ डिस्क क्षमताओं से अधिक हो सकता है), सी डिस्क को आवंटित फ़ाइलों का संयुक्त आकार होना चाहिए, और टी = अधिकतम si। हम समाप्त हो जाते हैं जब टी < = सी।

सबसे पहले, ऑर्डर (और इंडेक्स) फ़ाइलों को सबसे छोटे से सबसे छोटे।

मीटर> = n डिस्क के लिए,

  1. एक वापस-इन-आगे रास्ते में डिस्क के लिए फ़ाइलों का आवंटन: 1-> 1, 2> 2, ... m-> मीटर , एम + 1> एम -1, एम + 2-> एम -2, ... 2 एम-> 1, 2 एम + 1-> 2, 2 एम + 2-> 3 ... 3 एम-> एम, 3 एम + 1 -> एम -1, और तब तक जब तक सभी फ़ाइलों को आवंटित नहीं किया जाता है, डिस्क क्षमता के संबंध में। यदि टी < = सी हम समाप्त हो गए हैं (और एम = एन) आवंटन इष्टतम है; अन्य # 2 पर जाएं।

  2. टी से एक फ़ाइल को स्थानांतरित करके टी को कम करने का प्रयास करें, मैं si = t से दूसरी डिस्क तक, टी को बढ़ाए बिना। टी < = सी तक ऐसा करना जारी रखें, जिस स्थिति में हम समाप्त हो जाते हैं (और आवंटन इष्टतम है अगर m = n), या टी को और कम नहीं किया जा सकता है, इस मामले में # 3 पर जाएं।

  3. डिस्क के बीच जोड़ी के एक्सचेंजों को निष्पादित करके टी को कम करने का प्रयास करें। टी < = सी तक ऐसा करना जारी रखें, इस मामले में हम समाप्त हो गए हैं (और आवंटन इष्टतम है अगर एम = एन), या टी को जोड़ीदार एक्सचेंजों के साथ आगे नहीं बढ़ाया जा सकता है। बाद के मामले में, # 2 दोहराएं, जब तक कि कोई सुधार नहीं किया गया था पिछली बार # 2 दोहराया गया था, जिस स्थिति में एक करके वृद्धि हुई है और # 1 दोहराएं।

# 2 और # 3 में संभावित पुनर्वितरण और जोड़ीदार एक्सचेंजों को ऑर्डर करने के लिए बिल्कुल अलग तरीके हैं।

संबंधित मुद्दे