एक बंधी हुई छोटी समस्या को 0/1 चापाकल समस्या में बदलना


12

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

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

उदाहरण के लिए, दिए गए केबल:
1 x 10ft,
1 x 7ft,
1 x 6ft,
5 x 3ft,
6 x 2ft,
7 x 1ft

यदि लक्ष्य अवधि 13ft है, तो DP एल्गोरिथ्म दूरी तय करने के लिए 7 + 6 उठाता है। एक लालची एल्गोरिथ्म ने 10 + 3 उठाया होगा, लेकिन यह न्यूनतम संख्या में केबलों के लिए एक टाई है। समस्या तब पैदा होती है, जब 15 फीट तक फैलने की कोशिश की जाती है। डीपी एल्गोरिथ्म ने 4 केबल प्राप्त करने के लिए 6 + 3 + 3 + 3 को चुनना समाप्त कर दिया, जबकि लालची एल्गोरिथम केवल 3 केबलों के लिए 10 + 3 + 2 को सही ढंग से चुनता है।

वैसे भी, परिवर्तित करने की कुछ हल्की स्कैनिंग 0/1 तक सीमित है, यह कई वस्तुओं को {p, 2p, 4p ...} में बदलने के लिए प्रसिद्ध दृष्टिकोण की तरह लगता है। मेरा प्रश्न यह है कि यह रूपांतरण कैसे काम करता है यदि p + 2p + 4p कई मदों की संख्या में नहीं जोड़ता है। उदाहरण के लिए: मेरे पास 5 3ft केबल हैं। मैं बहुत अच्छी तरह से {3, 2x3, 4x3} नहीं जोड़ सकता क्योंकि 3 + 2x3 + 4x3> 5x3। क्या मुझे इसके बजाय {3, 4x3} जोड़ना चाहिए?

[मैं वर्तमान में "ओरेगन ट्रेल नैकपैक प्रॉब्लम" पेपर को टटोलने की कोशिश कर रहा हूं, लेकिन वर्तमान में ऐसा लगता है कि वहां इस्तेमाल किया गया दृष्टिकोण गतिशील प्रोग्रामिंग नहीं है।]


1
मुझे लगता है कि होगा यह करने के लिए अधिक उपयुक्त है math.stackexchange.com या यहाँ तक कि mathoverflow.net
Oded

3
मैं जेनेरिक स्टैकओवरफ़्लो के बीच फटा हुआ था, और यहाँ। दोनों साइटों पर अक्सर पूछे जाने वाले प्रश्न, यह साइट पहले डेटा संरचनाओं और एल्गोरिदम को सूचीबद्ध करती है। गणित साइट के लिए अक्सर पूछे जाने वाले प्रश्न को पढ़ना, ऐसा लगता है कि इसके बजाय cstheory साइट पर सुझाव देना चाहिए।
चींटियों

जवाबों:


1

यह आपके कोड में कुछ गलती हो सकती है। मैंने डीपी कार्यक्रम लिखा है जैसा कि नारिशकिन ने उल्लेख किया है। लक्ष्य 13 की अवधि के लिए, यह 6 + 7 रिपोर्ट करता है, और 15 के लिए, यह 2 + 6 + 7 रिपोर्ट करता है।

# weight: cable length
# total weight: target span
# value: 1 for each cable
# want minimum number of cables, i.e. minimum total value

def knapsack_01_exact_min(weights, values, W):
    # 0-1 knapsack, exact total weight W, minimizing total value
    n = len(weights)
    values = [0] + values
    weights = [0] + weights
    K = [[0 for i in range(W+1)] for j in range(n+1)]
    choice = [[0 for i in range(W+1)] for j in range(n+1)]
    for i in range(1, n+1):
        for w in range(1, W+1):
            K[i][w] = K[i-1][w]
            choice[i][w] = '|'
            if w >= weights[i]:
                t = K[i-1][w-weights[i]]
                if (w==weights[i] or t) and (K[i][w]==0 or t+values[i] < K[i][w]):
                    choice[i][w] = '\\'
                    K[i][w] = t+values[i]
    return K[n][W], choice

def print_choice(choice, weights):
    i = len(choice)-1
    j = len(choice[0])-1
    weights = [0] + weights
    while i > 0 and j > 0:
        if choice[i][j]=='\\':
            print weights[i],
            j -= weights[i]
        i -= 1
    print

lens = [10, 7, 6] + 5*[3] + 6*[2] + 7*[1]
values = (3+5+6+7)*[1]
span = 13
v, choice = knapsack_01_exact_min(lens, values, span)
print "need %d cables to span %d:" % (v,span),
print_choice(choice, lens)

span = 15
v, choice = knapsack_01_exact_min(lens, values, span)
print "need %d cables to span %d:" % (v,span),
print_choice(choice, lens)

यदि आप इनपुट लंबाई के क्रम को समायोजित करते हैं, तो यह अन्य इष्टतम समाधान दे सकता है। उदाहरण के लिए, lens = 5*[3] + 6*[2] + 7*[1] + [10, 7, 6]15 = 10 + 2 + 3 देंगे।


आपको यह कथन कहां से मिला: 'अगर (w-weights [i] == 0 या t) और (K [i] [w] == 0 या t + मान [i] <K [i] [w] ): '? अगर अब मेरे डीपी एल्गोरिथ्म के स्रोत को भूल जाते हैं, लेकिन मेरे पास कोई शून्य चेक नहीं था, तो केवल '(t + मूल्य [i] <K [i] [w])' के लिए जाँच करें
चींटियों

1
आप सटीक कुल वजन के लिए हल कर रहे हैं , जिसका अर्थ है कि जब भी कोई आइटम उठाया जाता है, तो हमें यह सुनिश्चित करने की आवश्यकता होती है कि सटीक वजन (वर्तमान चरण का) पूरा हो। इसलिए, जब हम किसी आइटम को लेने का निर्णय लेते हैं, तो दूसरा क्लॉज "t + मान [i] <K [i] [w]" सुनिश्चित करता है कि हमारे पास एक छोटा कुल मूल्य होगा; लेकिन इससे पहले, हमें आवश्यक वजन को भी पूरा करने की आवश्यकता है, अर्थात पहला i-1 आइटम वजन को पूरा करने में सक्षम होना चाहिए (w-weights [i]), इसलिए पहला खंड "यदि K [i-1] [w -हम [i]] "(मैं उस के लिए एक अस्थायी चर टी का उपयोग कर रहा हूं)।
jsz

दो अतिरिक्त चेक "w == वेट [i]" और "K [i] [w] == 0" हैं; वे आवश्यक हैं और इस कारण से कि तालिकाओं को कैसे प्रारंभ किया जाता है; मुझे लगता है कि आप इसे बनाने में सक्षम होंगे इसलिए मैं विवरण में नहीं जाऊंगा। (मैंने डब्ल्यू-वेट [i] == 0 से w == वेट [i] बदल दिया; यह अधिक स्पष्ट होना चाहिए)।
jsz

1

जिस तरह से मैंने एक बाउंडेड नैकपैक समस्या को 0/1 में बदलने के लिए इस्तेमाल किया है वह सिर्फ कई समान वस्तुओं के लिए है। कहो अगर आपके पास निम्नलिखित वस्तुएं हैं (वजन, उपयोगिता के रूप में):

  • २ एक्स १, २
  • ३ एक्स २, ३

आप इसे 0/1 समस्या के साथ आइटम का उपयोग करके बदल देंगे

  • 1, 2
  • 1, 2
  • २, ३
  • २, ३
  • २, ३

और इसे हल करने के लिए 0/1 एल्गोरिथ्म का उपयोग करें। आपके पास समान शुद्धता के कई समाधान होने की संभावना है ताकि आप एक मनमाना चुनें।


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


हाँ, यह वही है जो मैं वजन और मूल्य को भरने के लिए कर रहा हूं। मैं मिनट के बजाय अधिकतम मूल्य के लिए कंप्यूटिंग कर रहा था। जैसा कि आपने सुझाव दिया था, मैंने अभी कोड को बदल दिया है, और MAXINT होने के लिए DP तालिका की प्रारंभिक पंक्ति 0 शुरू की है। अभी भी एक ही परिणाम है, नैकस्पैक समस्याओं के लिए गतिशील प्रोग्रामिंग समाधान अभी भी 10 + 3 + 2 या 7 + 6 + 2 के बजाय 6 + 3 + 3 + 3 उठाता है।
चींटियां
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.