2013-05-10 3 views
3

У меня есть коллекция орграфов, закодированных на языке DOT. Я хочу построить граф-граф, так что каждый узел в суперграфе является одним из этих орграфов. Есть ли способ сделать это в рамках GraphViz?График графов в Graphviz

Я знаю, что gvpack позволит мне собрать несколько графиков в один .dot файл. Но я не знаю, разрешит ли я объявить ребра между этими графами.

ответ

5

Короткий ответ заключается в том, что gvpack не объявляет ребра между субграфами. Действительно, когда между подграфами есть общие имена узлов, gvpack переименовывает их, чтобы избежать столкновений. Однако это можно устранить.

Например, если три .dot файлы 1.dot:

digraph { 
    A -> B 
    A -> C 
    } 

2.dot:

digraph { 
    D -> E 
    E -> F 
    } 

... и 3.dot:

digraph { 
    D -> G 
    G -> A 
    } 

... работает gvpack -u 1.dot 2.dot 3.dot | dot -Tjpg -ogvp1.jpg дает следующее график gvp1.jpg:

enter image description here

Как вы можете видеть, gvpack имеет этикетки для дублированных имен узлов. Тем не менее, мы можем легко обратить повторную маркировку с использованием gvpack -u 1.dot 2.dot 3.dot | sed 's/_gv[0-9]\+//g' | dot -Tjpg -ogvsub.jpg, который производит следующий график gvsub.jpg:

enter image description here

Этот подход основан на подграфах, имеющие имена узлов общих, так что может быть необходимо, чтобы вставить дополнительные узлы в подграфе .dot файлов для этого.

(EDIT: Раствор выше показал граф с узлами объединены, но не с подграфов в кластерах Следующее решение показывает суб-графики в кластерах..)

Указанные .dot файлы 1.dot (это так же, как файлы выше, за исключением того, что я дал каждому Digraph имя):

digraph g1 { 
    A -> B 
    A -> C 
    } 

2.dot:

digraph g2 { 
    D -> E 
    E -> F 
    } 

... и 3.dot:

digraph g3 { 
    D -> G 
    G -> A 
    } 

... вместе с hdr.dot:

digraph GMaster { 
    compound = true; 
    g1 [style=invisible, height = 0, width = 0, label=""]; 
    g2 [style=invisible, height = 0, width = 0, label=""]; 
    g3 [style=invisible, height = 0, width = 0, label=""]; 
    g1 -> g2 [lhead=clusterg2, ltail=clusterg1]; 
    g1 -> g3 [lhead=clusterg3, ltail=clusterg1] 

... и tail.dot:

} 

...мы можем запустить cat 1.dot 2.dot 3.dot | sed 's/digraph \(\w*\) *{/subgraph cluster\1 { \1/' | cat hdr.dot - tail.dot | dot -Tjpg -oclust1.jpg дать файл clust1.jpg:

enter image description here

Таким образом, в файле заголовка, я добавил Invisble узел для каждого подграфа, с тем же именем, что и подграфа, используется compound=true для разрешить края между кластерами. Я указал края для рисования между кластерами, и я установил lhead и ltail для каждого из краев между невидимыми узлами, чтобы гарантировать, что правый кластер используется как голова и хвост каждого из этих ребер. Я также добавил соответствующий невидимый узел для каждого подграфа в процессе преобразования каждого подграфа в кластер с использованием sed.

Ребра между узлами D, G и A показаны, поскольку эти узлы являются общими для кластеров. Кроме того, каждый из них отображается только в одном кластере. Если узлы были уникальны для кластеров, единственными ребрами, которые были бы показаны между кластерами, были бы ребра между невидимыми узлами. Это можно увидеть на следующем графике, где я переименовал узлы в 3.dot:

enter image description here

Существует один оставшийся недостаток, который я не совсем был в состоянии исправить. Невидимые узлы по-прежнему занимают немного места, поэтому ящики кластера выглядят однобокими, потому что невидимые узлы располагаются рядом с видимыми узлами. Это также означает, что головки краев между кластерами указывают на одну сторону блока кластера, а не на середину. В настоящее время я не вижу, что можно сделать по этому поводу, если мы не готовы смотреть на каждый подграф и находим узел, который уже находится в этом подграфе/кластере, чтобы служить репрезентативным узлом для этого подграфа/кластера (т. Е. один или на который мы рисуем края для этого кластера). Это можно сделать достаточно легко вручную для нескольких подграфов, но было бы утомительно, если бы было много подграфов.

Напротив, подход, который я использовал выше, требует только того, чтобы мы знали имя кластера и можем вставить его в файл hdr.dot.

Я построил hdr.dot файл вручную для этого случая, но содержимое файла hdr.dot может быть извлечен из других .dot файлов с sed, awk, perl или python, если есть необходимость. Сценарий также может вставлять края для связывания кластеров в hdr.dot, если информация о том, какие кластеры должны быть подключены, была доступна где-то.

+0

Спасибо за тщательный ответ Саймон. В моем случае, хотя я хочу рассматривать каждый из подграфов как узлы суперграфа, а не компоненты. Я хочу указать, что ребро существует между 1-> 2 и 1-> 3 и имеют явно выраженные подграфы, связанные с узлами, с соответствующими ребрами между компонентами. – MRocklin

+0

А, я вижу. Я думаю, что присоединение к подграфам может быть достигнуто с помощью аналогичного метода подхода, который я принял в своем ответе. Я подумаю. – Simon

+0

Я отредактировал свой ответ, чтобы показать, как кластеры могут быть связаны по краям. – Simon

Смежные вопросы