Иерархический граф с параллельными ребрами
Мне нужно создать график из набора данных. Я перебрал бесчисленные вопросы SO, но не смог найти решение, которое отвечало бы всем необходимым требованиям.
Что нужно:
http://i.imgur.com/hzQHD07.png
Обязательные требования:
- Иерархическое размещение узлов
- Упорядоченное размещение узлов, то есть "A" должно быть слева от "B"
- Параллельные ребра между узлами
- Минимальная длина ребра (чтобы избежать вторжения метки в узел, как в D -E)
- Программное решение, практически не требующее редактирования файла точек для достижения желаемого результата
- Масштаб до нескольких тысяч узлов
Очень важные требования:
- Прямые (орто)
- Метки головы и хвоста
- Возможность отображения стрелок
График может быть ненаправленным или направленным, но он должен соответствовать вышеуказанным требованиям.
import networkx as nx
g = nx.Graph()
g.add_edge(node1,node3,headlabel='label 2', taillabel='label 1',fontsize='10')
g.add_edge(node1,node4,headlabel='label 4', taillabel='label 3',fontsize='10')
g.add_edge(node2,node5,headlabel='label 6', taillabel='label 5',fontsize='10')
g.add_edge(node2,node6,headlabel='label 8', taillabel='label 7',fontsize='10')
g.add_edge(node4,node5,headlabel='really long label', taillabel='really long label',fontsize='10')
g.add_edge(node4,node5)
g.add_edge(node3,node7)
g.add_edge(node7,node8)
g.add_edge(node7,node8)
g.add_edge(node4,node8)
g.add_edge(node5,node8)
g.add_edge(node5,node9,headlabel='label 12', taillabel='label 11',fontsize='10')
g.add_edge(node6,node9,headlabel='label 10', taillabel='label 9',fontsize='10')
A = nx.to_agraph(g)
A.add_subgraph([node1,node2],rank='same')
A.add_subgraph([node3,node4,node5,node6],rank='same')
A.add_subgraph([node7,node8,node9],rank='same')
A.draw('example2.png', prog='dot')
Вышеуказанное производит: http://i.imgur.com/1e9YTnQ.png
Конечно, параллельные ребра не показаны с помощью вышеуказанного метода. Я попытался использовать MultiDiGraph, который поддерживает параллельные ребра, но не может заставить его работать из-за следующей ошибки, несмотря на определение уникальных ключей для параллельных ребер (не показано в коде).
Traceback (most recent call last):
File "example3.py", line 31, in <module>
A = nx.to_agraph(g)
File "C:\python27\lib\site-packages\networkx-1.11rc1-py2.7.egg\networkx\drawing\nx_agraph.py", line 152, in to_agraph
A.add_edge(u,v,key=str(key),**str_edgedata)
File "C:\python27\lib\site-packages\pygraphviz\agraph.py", line 481, in add_edge
eh = gv.agedge(self.handle, uh, vh, key, _Action.find)
KeyError: 'agedge: no key'
Использование graphviz без networkx, как показано ниже, дает мне параллельные ребра, но иерархия и упорядочение узлов исчезли. Я знаю, что иерархию можно исправить, добавив rank=same в файл точек, но я бы предпочел сделать это программно.
import graphviz as gv
g = gv.Graph(format='png')
g.edge(node1,node3,headlabel='label 2', taillabel='label 1',fontsize='10')
g.edge(node1,node4,headlabel='label 4', taillabel='label 3',fontsize='10')
g.edge(node2,node5,headlabel='label 6', taillabel='label 5',fontsize='10')
g.edge(node2,node6,headlabel='label 8', taillabel='label 7',fontsize='10')
g.edge(node4,node5,headlabel='really long label', taillabel='really long label',fontsize='10')
g.edge(node4,node5)
g.edge(node3,node7)
g.edge(node7,node8)
g.edge(node7,node8)
g.edge(node4,node8)
g.edge(node5,node8)
g.edge(node5,node9,headlabel='label 12', taillabel='label 11',fontsize='10')
g.edge(node6,node9,headlabel='label 10', taillabel='label 9',fontsize='10')
g.render('example')
Невозможно опубликовать ссылку на изображение для последнего рендеринга из-за недостаточной репутации.