ট্রিভিডথ গণনা করুন


14

Treewidth একটি undirected গ্রাফ গ্রাফ তত্ত্ব একটি অত্যন্ত গুরুত্বপূর্ণ ধারণা। টন গ্রাফ অ্যালগরিদমগুলি উদ্ভাবিত হয়েছে যা আপনার যদি ছোট গাছের প্রস্থের সাথে গ্রাফের ক্ষয় হয় তবে দ্রুত চলে।

গাছের পাতাগুলি প্রায়শই গাছের পচে যাওয়ার ক্ষেত্রে সংজ্ঞায়িত হয়। উইকিপিডিয়ায় সৌজন্যে এই গ্রাফটির একটি গ্রাফ এবং গাছের পঁচন এখানে রয়েছে:

এখানে চিত্র বর্ণনা লিখুন

একটি গাছের পচন হ'ল এমন একটি গাছ যেখানে প্রতিটি শীর্ষবিন্দু নীচের বৈশিষ্ট্য সহ মূল গ্রাফের শীর্ষে একটি উপসেটের সাথে যুক্ত থাকে:

  • মূল গ্রাফের প্রতিটি ভার্টেক্স কমপক্ষে একটি উপসর্গের মধ্যে থাকে।
  • মূল গ্রাফের প্রতিটি প্রান্তের কমপক্ষে একটিতে উপসর্গের উভয়টিই এর উল্লম্ব রয়েছে।
  • পচনগুলির সমস্ত শিখাগুলি যার উপসাগরগুলিতে প্রদত্ত আসল প্রান্তটি সংযুক্ত থাকে।

উপরের পচনটি এই নিয়মগুলি অনুসরণ করে আপনি তা পরীক্ষা করতে পারেন। গাছের পচনের প্রস্থ হ'ল এর বৃহত্তম উপসেট, মাইনাস একের আকার। সুতরাং, এটি উপরের পচনের জন্য দুটি। গ্রাফের গাছের প্রস্থটি সেই গ্রাফের যে কোনও গাছের ক্ষয়ের ক্ষুদ্রতম প্রস্থ।


এই চ্যালেঞ্জে আপনাকে একটি সংযুক্ত, পুনর্নির্দেশিত গ্রাফ দেওয়া হবে এবং আপনাকে অবশ্যই এটির গাছের দৈর্ঘ্যের সন্ধান করতে হবে।

গাছের পচে যাওয়াগুলি খুঁজে পাওয়া শক্ত, তবে গাছের প্রস্থকে গণনা করার অন্যান্য উপায় রয়েছে। উইকিপিডিয়া পৃষ্ঠায় আরও তথ্য রয়েছে তবে গাছের প্রস্থ গণনা করার একটি পদ্ধতি সেখানে উল্লেখ করা হয়নি যা প্রায়শই গাছের প্রস্থ গণনা করতে অ্যালগরিদমে ব্যবহৃত হয় ন্যূনতম বিলোপকরণ অর্ডার প্রস্থ। এই সত্যটি ব্যবহার করে একটি কাগজের জন্য এখানে দেখুন ।

অ্যালিমিনেশন অর্ডারে, একটি একবারে গ্রাফের সমস্ত শীর্ষে দূর করে। যখন প্রতিটি ভার্টেক্স মুছে ফেলা হয়, তখন প্রান্তগুলি সেই ভার্টেক্সের সমস্ত প্রতিবেশীকে একে অপরের সাথে সংযুক্ত করে যুক্ত করা হয়। সমস্ত উল্লম্বটি শেষ না হওয়া পর্যন্ত এটি পুনরাবৃত্তি হয়। এই প্রক্রিয়া চলাকালীন নির্মূলের অর্ডার প্রস্থ হ'ল প্রতিবেশীদের সর্বাধিক সংখ্যা। নির্মূল আদেশের প্রস্থের সমস্ত ক্রমগুলির চেয়ে গাছের প্রস্থ নূন্যতমের সমান। গাছের প্রস্থকে গণনা করার জন্য এই বাস্তবতাকে ব্যবহার করে একটি উদাহরণ প্রোগ্রাম এখানে দেওয়া হয়েছে:

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)এটি একটি বৈধ ইনপুট হবে?
ბიმო

নিখুঁত
isaacg

উত্তর:


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এটি দরকার নেই তবে এটি টিওতে যুক্ত করা উচিত।

এটি অনলাইন চেষ্টা করুন!

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

@ আইসএইচজি কোন সমস্যা নেই আমার হাতে অন্য জিনিস আছে :)
rahnema1

@ আইসএইচজি এই উত্তরটি কোনও মানক লুফোলটি লঙ্ঘন করে না?
পাইরুলেজ

rahnema1, আমার সম্পাদনা দেখুন। বিল্টিনগুলি নিষিদ্ধ, সুতরাং এই উত্তর অনুমোদিত নয়। দয়া করে এটি মুছুন বা
নন

@ আইস্যাচ ধন্যবাদ, আমি এটিকে নন-কার্পেটিং হিসাবে চিহ্নিত করেছি।
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

এটি অনলাইন চেষ্টা করুন!

অবরুদ্ধ সংস্করণ:

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))
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.