इस समस्या से निपटने के कई तरीके हैं। डेटा का रेखापुंज प्रारूप एक रेखापुंज-आधारित दृष्टिकोण का सुझाव देता है; उन दृष्टिकोणों की समीक्षा करने में, द्विआधारी पूर्णांक रैखिक कार्यक्रम के रूप में समस्या का एक रूप आशाजनक दिखता है, क्योंकि यह कई जीआईएस साइट-चयन विश्लेषण की भावना में बहुत है और आसानी से उनके लिए अनुकूलित किया जा सकता है।
इस फॉर्मूलेशन में, हम भरने वाले बहुभुज (ओं) के सभी संभावित पदों और झुकावों की गणना करते हैं, जिन्हें मैं "टाइल" के रूप में संदर्भित करूंगा। " प्रत्येक टाइल के साथ संबद्ध इसकी "अच्छाई" का एक उपाय है। उद्देश्य गैर-अतिव्यापी टाइलों का एक संग्रह ढूंढना है, जिनकी कुल अच्छाई यथासंभव बड़ी है। यहां, हम प्रत्येक टाइल की अच्छाई को उस क्षेत्र के रूप में ले सकते हैं जो इसे कवर करता है। (अधिक डेटा-समृद्ध और परिष्कृत निर्णय वातावरण में, हम प्रत्येक टाइल के भीतर शामिल कोशिकाओं के गुणों के संयोजन के रूप में अच्छाई की गणना कर सकते हैं, गुण शायद दृश्यता से संबंधित हैं, अन्य चीजों से निकटता, और इसी तरह।)
इस समस्या पर अड़चन केवल यह है कि समाधान के भीतर कोई दो टाइलें ओवरलैप नहीं हो सकती हैं।
यह और अधिक संक्षेप में एक छोटे से फंसाया जा सकता है, एक तरह से कुशल गणना के लिए अनुकूल में बहुभुज में कोशिकाओं की गणना द्वारा भरा जाना है ( "क्षेत्र") 1, 2, ..., एम । किसी भी टाइल के प्लेसमेंट को शून्य और लोगों के एक संकेतक वेक्टर के साथ एन्कोड किया जा सकता है, जिससे लोगों को टाइल और ज़ीरोस द्वारा कवर कोशिकाओं के अनुरूप हो सकता है। इस एन्कोडिंग में, सभी टाइल का एक संग्रह के बारे में आवश्यक जानकारी से पाया जा सकता है संक्षेप (हमेशा की तरह, घटक द्वारा घटक) उनके सूचक वैक्टर: योग अशून्य वास्तव में हो जाएगा जहां कम से कम एक टाइल कवर एक सेल और राशि अधिक हो जाएगा एक से अधिक दो या दो से अधिक टाइल ओवरलैप। (योग प्रभावी रूप से ओवरलैप की मात्रा को गिनता है।)
एक और थोड़ा अमूर्त: संभव टाइल प्लेसमेंट के सेट को खुद ही कहा जा सकता है, 1, 2, ..., एन । टाइल प्लेसमेंट के किसी भी सेट का चयन स्वयं एक संकेतक वेक्टर से मेल खाता है जहां लोग टाइल को रखने के लिए नामित करते हैं।
यहां विचारों को ठीक करने के लिए एक छोटा चित्रण किया गया है । यह गणना करने के लिए उपयोग किए जाने वाले मैथेमेटिका कोड के साथ है , ताकि प्रोग्रामिंग कठिनाई (या इसके अभाव) स्पष्ट हो सके।
सबसे पहले, हम एक क्षेत्र को टाइल किए जाने का चित्रण करते हैं:
region = {{0, 0, 1, 1}, {1, 1, 1, 1}, {1, 1, 1, 1}, {1, 1, 1, 1}};
यदि हम इसकी कोशिकाओं को बाएं से दाएं, शीर्ष पर शुरू करते हैं, तो क्षेत्र के लिए संकेतक वेक्टर में 16 प्रविष्टियां हैं:
Flatten[region]
{, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}
चलो 90 डिग्री के गुणकों द्वारा सभी घुमावों के साथ, निम्नलिखित टाइल का उपयोग करें:
tileSet = {{{1, 1}, {1, 0}}};
रोटेशन उत्पन्न करने के लिए कोड (और प्रतिबिंब):
apply[s_List, alpha] := Reverse /@ s;
apply[s_List, beta] := Transpose[s];
apply[s_List, g_List] := Fold[apply, s, g];
group = FoldList[Append, {}, Riffle[ConstantArray[alpha, 4], beta]];
tiles = Union[Flatten[Outer[apply[#1, #2] &, tileSet, group, 1], 1]];
(यह कुछ हद तक अपारदर्शी गणना /math//a/159159 पर एक उत्तर में समझाया गया है , जो यह दर्शाता है कि यह बस एक टाइल के सभी संभव घुमाव और प्रतिबिंब पैदा करता है और फिर किसी भी डुप्लिकेट परिणामों को निकालता है।)
मान लीजिए कि हम यहाँ दिखाए गए अनुसार टाइल लगा रहे हैं:
कक्ष 3, 6 और 7 इस प्लेसमेंट में शामिल हैं। यह संकेतक वेक्टर द्वारा निर्दिष्ट है
{, 0, 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0}
यदि हम इस टाइल को एक कॉलम को दाईं ओर शिफ्ट करते हैं, तो वह संकेतक वेक्टर इसके बजाय होगा
{, 0, 0, 1, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0}
इन दोनों पदों पर एक साथ टाइल लगाने की कोशिश का संयोजन इन संकेतकों के योग से निर्धारित होता है,
{, 0, 1, 1, 1, 0, 1, 2, 1, 0, 0, 0, 0, 0, 0, 0}, 0}
सातवें स्थान पर 2 इन ओवरलैप को एक सेल (दूसरी पंक्ति नीचे, बाएं से तीसरा स्तंभ) में दिखाता है। क्योंकि हम ओवरलैप नहीं चाहते हैं, हमें आवश्यकता होगी कि किसी भी वैध समाधान में वैक्टर का योग 1 से अधिक कोई प्रविष्टि न हो।
यह पता चला है कि इस समस्या के लिए, टाइल्स के लिए अभिविन्यास और स्थिति के 29 संयोजन संभव हैं। (यह एक संपूर्ण खोज से जुड़े कोडिंग का एक सरल सा के साथ मिला था।) हम के रूप में उनके संकेतक बनाकर सभी 29 संभावनाओं को दर्शाती कर सकते हैं स्तंभ वैक्टर। (पंक्तियों के बजाय स्तंभों का उपयोग करना पारंपरिक है।) यहां परिणामस्वरूप सरणी की एक तस्वीर है, जिसमें 16 पंक्तियाँ होंगी (आयत में प्रत्येक संभावित सेल के लिए एक) और 29 कॉलम:
makeAllTiles[tile_, {n_Integer, m_Integer}] :=
With[{ m0 = Length[tile], n0 = Length[First[tile]]},
Flatten[
Table[ArrayPad[tile, {{i, m - m0 - i}, {j, n - n0 - j}}], {i, 0, m - m0}, {j, 0, n - n0}], 1]];
allTiles = Flatten[ParallelMap[makeAllTiles[#, ImageDimensions[regionImage]] & , tiles], 1];
allTiles = Parallelize[
Select[allTiles, (regionVector . Flatten[#]) >= (Plus @@ (Flatten[#])) &]];
options = Transpose[Flatten /@ allTiles];
(पिछले दो संकेतक वैक्टर बाईं ओर पहले दो कॉलम के रूप में दिखाई देते हैं।) तेज-तर्रार पाठक ने समानांतर प्रसंस्करण के कई अवसरों पर ध्यान दिया हो सकता है: ये गणना कुछ सेकंड ले सकती हैं।
सभी पूर्वगामी मैट्रिक्स संकेतन का उपयोग करके कॉम्पैक्ट रूप से बहाल किया जा सकता है:
F , M पंक्तियों और N कॉलमों के साथ विकल्पों की यह सरणी है ।
X , लंबाई N के टाइल प्लेसमेंट का एक संकेतक है ।
b एक N -vector है।
आर क्षेत्र के लिए संकेतक है; यह एक एम- ट्रेक्टर है।
किसी भी संभावित समाधान एक्स से जुड़ी कुल "अच्छाई" आरएफएक्स के बराबर होती है , क्योंकि एफएक्स एक्स द्वारा कवर की गई कोशिकाओं का संकेतक है और आर इन मूल्यों के साथ उत्पाद । ( यदि हम इस क्षेत्र में कुछ क्षेत्रों के पक्ष में या बचने के लिए समाधान चाहते हैं, तो हम आर का वजन कर सकते हैं ।) यह अधिकतम होना है। क्योंकि हम इसे ( RF ) के रूप में लिख सकते हैं । एक्स , यह एक है रैखिक के समारोह एक्स : यह महत्वपूर्ण है। (नीचे दिए गए कोड में, चर c
में RF शामिल है ।)
अड़चनें हैं कि
एक्स के सभी तत्व गैर-नकारात्मक होने चाहिए;
एक्स के सभी तत्व 1 से कम होना चाहिए (जो कि बी में संबंधित प्रविष्टि है );
X के सभी तत्व अभिन्न होने चाहिए।
बाधाओं (1) और (2) इसे एक रैखिक कार्यक्रम बनाते हैं , जबकि तीसरी आवश्यकता इसे पूर्णांक रैखिक कार्यक्रम में बदल देती है ।
वास्तव में इस रूप में व्यक्त पूर्णांक रैखिक कार्यक्रमों को हल करने के लिए कई पैकेज मौजूद हैं । वे एम और एन के मूल्यों को दसियों या सैकड़ों सैकड़ों में संभालने में सक्षम हैं । यह शायद कुछ वास्तविक दुनिया के अनुप्रयोगों के लिए पर्याप्त है।
हमारे पहले चित्रण के रूप में, मैंने गणितज्ञ 8 के LinearProgramming
आदेश का उपयोग करके पूर्ववर्ती उदाहरण के लिए एक समाधान की गणना की । (यह एक रेखीय उद्देश्य फ़ंक्शन को कम कर देगा । उद्देश्य फ़ंक्शन की उपेक्षा करके न्यूनतमकरण को आसानी से अधिकतम करने के लिए बदल दिया जाता है।) इसने 0.011 सेकंड में एक समाधान (टाइल्स और उनके पदों की सूची के रूप में) लौटाया:
b = ConstantArray[-1, Length[options]];
c = -Flatten[region].options;
lu = ConstantArray[{0, 1}, Length[First[options]]];
x = LinearProgramming[c, -options, b, lu, Integers, Tolerance -> 0.05];
If[! ListQ[x] || Max[options.x] > 1, x = {}];
solution = allTiles[[Select[x Range[Length[x]], # > 0 &]]];
ग्रे कोशिकाएं इस क्षेत्र में बिल्कुल नहीं हैं; इस समाधान द्वारा सफेद कोशिकाओं को कवर नहीं किया गया था।
आप बाहर (हाथ से) कई अन्य झुकावों को काम कर सकते हैं जो इस एक के रूप में अच्छे हैं - लेकिन आप कोई भी बेहतर नहीं ढूंढ सकते हैं। इस दृष्टिकोण की एक संभावित सीमा है: यह आपको एक सबसे अच्छा समाधान देता है , भले ही एक से अधिक हो। (कुछ वर्कअराउंड हैं: यदि हम एक्स के कॉलम को फिर से व्यवस्थित करते हैं , तो समस्या अपरिवर्तित रहती है, लेकिन सॉफ्टवेयर अक्सर परिणामस्वरूप एक अलग समाधान चुनता है। हालांकि, यह व्यवहार अप्रत्याशित है।)
दूसरे दृष्टांत के रूप में , अधिक यथार्थवादी होने के लिए, आइए प्रश्न में क्षेत्र पर विचार करें। छवि को आयात करने और इसे फिर से शुरू करने से, मैंने इसे 69 द्वारा 81 ग्रिड के साथ प्रतिनिधित्व किया:
इस क्षेत्र में इस ग्रिड की 2156 कोशिकाएँ शामिल हैं।
चीजों को दिलचस्प बनाने के लिए, और रैखिक प्रोग्रामिंग सेटअप की व्यापकता को स्पष्ट करने के लिए, आइए इस क्षेत्र को यथासंभव दो प्रकार के आयतों के साथ कवर करने का प्रयास करें :
एक 17 से 9 (153 सेल) और दूसरा 15 बाई 11 (165 सेल) है। हम दूसरे का उपयोग करना पसंद कर सकते हैं, क्योंकि यह बड़ा है, लेकिन पहला स्किनियर है और तंग जगहों पर फिट हो सकता है। चलो देखते हैं!
कार्यक्रम में अब एन = 5589 संभव टाइल प्लेसमेंट शामिल हैं। यह काफी बड़ा है! गणना के 6.3 सेकंड के बाद, गणितज्ञ इस दस-टाइल समाधान के साथ आया:
कुछ सुस्त ( .eg) के कारण, हम नीचे की बाईं टाइल को इसके कॉलम में चार कॉलम तक स्थानांतरित कर सकते हैं), जाहिर है कुछ अन्य समाधान इस से थोड़ा अलग हैं।