Treewidth bir yönsüz grafik Grafik Teorisi çok önemli bir kavramdır. Grafiğin küçük trewidth ile ayrışması varsa hızlı çalışan tonlarca grafik algoritması icat edilmiştir.
Ağaç genişliği genellikle ağaç ayrışması olarak tanımlanır. İşte Wikipedia'nın izniyle bir grafik ve bu grafiğin ağaç ayrışması:
Bir ağaç ayrışması, her bir tepe noktasının, orijinal grafiğin köşe noktalarının bir alt kümesiyle, aşağıdaki özelliklere sahip olduğu bir ağaçtır:
- Orijinal grafikteki her köşe, alt kümelerden en az birinde bulunur.
- Orijinal grafikteki her kenar, alt kümelerden en az birinde her iki köşesine sahiptir.
- Alt kümeleri belirli bir orijinal tepe noktası içeren ayrışmadaki tüm köşeler bağlanır.
Yukarıdaki ayrışmanın bu kurallara uygun olup olmadığını kontrol edebilirsiniz. Bir ağaç ayrışmasının genişliği, eksi bir olan en büyük alt kümesinin boyutudur. Bu nedenle, yukarıdaki ayrışma için iki tanedir. Bir grafiğin üçlü genişliği, o grafiğin herhangi bir ağaç ayrışmasının en küçük genişliğidir.
Bu meydan okumada, size bağlı, yönlendirilmemiş bir grafik verilecek ve bunun trewidth'ini bulmalısınız.
Ağaç ayrışmalarını bulmak zor olsa da, trewidth'i hesaplamanın başka yolları da vardır. Vikipedi sayfasında daha fazla bilgi var, ancak trewidth'i hesaplamak için algoritmalarda sıklıkla kullanılan treewthth'i hesaplamak için bir yöntem minimum eleme sipariş genişliği. Bu gerçeği kullanan bir makale için buraya bakınız .
Eliminasyon düzeninde, bir grafiğin tüm köşeleri teker teker ortadan kaldırılır. Her tepe noktası elimine edildiğinde, bu tepe noktasının tüm komşularını birbirine bağlayan kenarlar eklenir. Bu, tüm köşeler kaybolana kadar tekrarlanır. Eliminasyon sırası genişliği, ortadan kaldırılan herhangi bir tepe noktasının bu işlem sırasında sahip olduğu en fazla komşu sayısıdır. Ağaç genişliği, eleme sırası genişliğinin tüm siparişleri üzerindeki minimum değere eşittir. İşte treewthth hesaplamak için bu gerçeği kullanan bir örnek program:
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))
Örnekler:
[(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
Grafiği girdi olarak alırsınız ve trewidth'i çıktı olarak döndürmeniz gerekir. Giriş formatı esnektir. Girdi olarak kenarların bir listesini, bir bitişiklik haritasını veya bir bitişiklik matrisini alabilirsiniz. Başka bir giriş biçimi kullanmak isterseniz yorumlarda sorun. Girdinin bağlı olduğunu varsayabilir ve bu varsayımı girdi biçiminize, örneğin bir kenar listesi kullanarak oluşturabilirsiniz.
DÜZENLEME: Ağaç genişliğini hesaplayan yerleşik işlemlere izin verilmez. Bunu önceden belirtmediğim için özür dilerim.
En kısa kod kazanır.
(V,E)
bu geçerli bir girdi olur mu?