ट्रेविदथ की गणना करें


14

Treewidth एक अनिर्दिष्ट ग्राफ का ग्राफ़ थ्योरी में एक बहुत महत्वपूर्ण अवधारणा है। टनों ग्राफ एल्गोरिदम का आविष्कार किया गया है जो कि तेजी से चलते हैं यदि आपके पास छोटे ट्रेविद के साथ ग्राफ का अपघटन होता है।

ट्रीविद को अक्सर पेड़ के विघटन के रूप में परिभाषित किया जाता है। यहाँ एक ग्राफ और उस ग्राफ के एक पेड़ के अपघटन, विकिपीडिया के सौजन्य से:

यहाँ छवि विवरण दर्ज करें

एक पेड़ का अपघटन एक पेड़ है जहां प्रत्येक शीर्ष मूल ग्राफ के कोने के सबसेट के साथ जुड़ा हुआ है, निम्नलिखित प्रश्न हैं:

  • मूल ग्राफ में प्रत्येक शीर्ष कम से कम एक उपसमुच्चय में है।
  • मूल ग्राफ़ में प्रत्येक किनारे में कम से कम एक सबसेट में इसके दोनों कोने हैं।
  • विघटन में सभी कोने जिनके उपसेट में एक दिया गया मूल शीर्ष जुड़ा हुआ है।

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


इस चुनौती में, आपको एक जुड़ा हुआ, अप्रत्यक्ष ग्राफ दिया जाएगा, और आपको इसका संक्षिप्त विवरण खोजना होगा।

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

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

import itertools
def elimination_width(graph):
    max_neighbors = 0
    for i in sorted(set(itertools.chain.from_iterable(graph))):
        neighbors = set([a for (a, b) in graph if b == i] + [b for (a, b) in graph if a == i])
        max_neighbors = max(len(neighbors), max_neighbors)
        graph = [edge for edge in graph if i not in edge] + [(a, b) for a in neighbors for b in neighbors if a < b]
    return max_neighbors

def treewidth(graph):
    vertices = list(set(itertools.chain.from_iterable(graph)))
    min_width = len(vertices)
    for permutation in itertools.permutations(vertices):
        new_graph = [(permutation[vertices.index(a)], permutation[vertices.index(b)]) for (a, b) in graph]
        min_width = min(elimination_width(new_graph), min_width)
    return min_width

if __name__ == '__main__':
    graph = [('a', 'b'), ('a', 'c'), ('b', 'c'), ('b', 'e'), ('b', 'f'), ('b', 'g'),
            ('c', 'd'), ('c', 'e'), ('d', 'e'), ('e', 'g'), ('e', 'h'), ('f', 'g'), ('g', 'h')]
    print(treewidth(graph))

उदाहरण:

[(0, 1), (0, 2), (0, 3), (2, 4), (3, 5)]
1

[(0, 1), (0, 2), (1, 2), (1, 4), (1, 5), (1, 6), (2, 3), (2, 4), (3, 4), (4, 6), (4, 7), (5, 6), (6, 7)]
2

[(0, 1), (0, 3), (1, 2), (1, 4), (2, 5), (3, 4), (3, 6), (4, 5), (4, 7), (5, 8), (6, 7), (7, 8)]
3

[(0, 1), (0, 2), (0, 3), (0, 4), (1, 2), (1, 3), (1, 4), (2, 3), (2, 4), (3, 4)]
4

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

संपादित करें: अंतर्निहित कार्य जो ट्रेविद की गणना करते हैं, उन्हें अनुमति नहीं है। मैं इस बात को स्पष्ट नहीं करने के लिए माफी चाहता हूं।

सबसे छोटा कोड जीतता है।


चूंकि एक ग्राफ औपचारिक रूप से एक नल है, (V,E)क्या यह एक वैध इनपुट होगा?
ბიმო

@ ब्रूस_फोर्ट बिल्कुल।
ईसैक

जवाबों:


7

ऑक्टेव, 195 बाइट्स

function x=F(a)r=rows(a);P=perms(s=1:r);x=r;for m=s;b=a;n=0;for z=P(m,:);(T=sum(b)(z))&&{b|=(k=accumarray(nchoosek(find(b(z,:)),2),1,[r r]))|k';n=max(T,n);b(z,:)=0;b(:,z)=0}{4};end;x=min(x,n);end

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

  • endfunctionहालाँकि इसे tio में जोड़ने की कोई आवश्यकता नहीं है ।

इसे ऑनलाइन आज़माएं!

Ungolfed:

function min_width = treewidth(graph_adj)
    Nvertices = rows(graph_adj)
    Permutations = perms(1:Nvertices);                                                            % do not try it for large number of vertices
    min_width = Nvertices;
    for v = 1:Nvertices;
        new_graph=graph_adj;
        max_neighbors=0;
        for p = Permutations(v,:)
            Nneighbors=sum(new_graph)(p);
            if(Nneighbors)>0
                connection=accumarray(nchoosek(find(new_graph(p,:)),2),1,[Nvertices Nvertices]);  % connect all neighbors
                new_graph|=connection|connection';                                                % make the adjacency matrix symmetric
                new_graph(p,:)=0;new_graph(:,p)=0;                                                % eliminate the vertex
                max_neighbors=max(Nneighbors,max_neighbors);
            end
        end
        min_width=min(min_width,max_neighbors);
    end
end

5

सेजमैथ, 29 बाइट्स नॉनकमेटिंग *

lambda L:Graph(L).treewidth()

* यह जवाब ओपी के प्रश्न के बदलने से पहले पोस्ट किया गया था कि "बिल्डिंस पर प्रतिबंध लगा दिया गया है", इसलिए मैंने इसे गैर-जटिल बना दिया।

ऑनलाइन डेमो!


1
पिल्ला। वह अनासक्त है। दुर्भाग्य से, मुझे बिल्डिंस पर प्रतिबंध लगाना होगा, इसके बारे में खेद है।
isaacg

@isaacg कोई समस्या नहीं। मैं एक और बात मेरे हाथ में :)
rahnema1

@isaacg यह जवाब एक मानक खामियों का उल्लंघन नहीं करता है?
PyRulez

rahnema1, मेरा संपादन देखें। बिलों पर प्रतिबंध है, इसलिए इस उत्तर की अनुमति नहीं है। कृपया इसे हटा दें या इसे
नॉन

@isaacg धन्यवाद, मैंने इसे नॉन कमेटिंग के रूप में चिह्नित किया।
rahnema1

5

हास्केल (लैंबडॉट), 329 321 245 बाइट्स

यहां मेरा समाधान है, इनपुट के लचीलेपन के लिए धन्यवाद, यह ग्राफ़ पर काम करता है जिसमें किसी भी प्रकार का ग्राफ़ होता है जो इसका एक उदाहरण है Eq

(&)=elem
l=length
t n g s=last$minimum[max(t n g b)$t(n++b)g$s\\b|b<-filterM(\_->[0>1,1>0])s,l b==div(l s)2]:[l[d|d<-fst g,not$d&n,d/=s!!0,(d&)$foldr(\x y->last$y:[x++y|any(&y)x])[s!!0]$join(>>)[e|e<-snd g,all(&(s!!0:d:n))e]]|1==l s]
w=t[]<*>fst

इसे ऑनलाइन आज़माएं!

Ungolfed संस्करण:

type Vertex a = a
type Edge a   = [Vertex a]
type Graph a  = ([Vertex a],[Edge a])

vertices = fst
edges = snd

-- This corresponds to the function w
treeWidth :: (Eq a) => Graph a -> Int
treeWidth g = recTreeWidth g [] (vertices g)

-- This is the base case (length s == 1) of t
recTreeWidth graph left [v] =
    length [ w | w <- vertices graph
               , w `notElem` left
               , w /= v
               , w `elem` reachable (subGraph w)
           ]

  where subGraph w = [ e | e <- edges graph, all (`elem` v:w:left) e ]

        reachable g = foldr accumulateReachable [v] (g>>g)
        accumulateReachable x y = if any (`elem` y) x
                                  then x++y
                                  else y

-- This is the other case of t
recTreeWidth graph left sub =
  minimum [ comp sub' | sub' <- filterM (const [False,True]) sub
                      , length sub' == div (length sub) 2
          ]

  where comp b = max (recTreeWidth graph left b)
                     (recTreeWidth graph (left++b) (sub\\b))
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.