Иерархический граф с параллельными ребрами

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

Что нужно:

http://i.imgur.com/hzQHD07.png

Обязательные требования:

  1. Иерархическое размещение узлов
  2. Упорядоченное размещение узлов, т. е. «A» должно быть слева от «B».
  3. Параллельные ребра между узлами
  4. Минимальная длина ребра (чтобы метка не заходила за узел, как в D-E)
  5. Программное решение, практически не требующее редактирования файла точек для достижения желаемого результата.
  6. Масштабирование до нескольких тысяч узлов

Очень важные требования:

  1. Прямые линии (или орто)
  2. Этикетки на голове и хвосте
  3. Возможность отображения стрелок

Граф может быть неориентированным или направленным, но должен удовлетворять вышеуказанным требованиям.

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')

Не могу опубликовать ссылку на изображение для последней визуализации из-за недостаточной репутации.


person TraderMoe    schedule 24.01.2016    source источник
comment
Вам будет легче помочь, если вы разместите свой текущий код и сообщите нам, где он не работает. SO - это не служба кодирования, а просто сайт вопросов/ответов.   -  person Imanol Luengo    schedule 24.01.2016
comment
Добавлен код с полученными графиками.   -  person TraderMoe    schedule 24.01.2016
comment
Graphviz довольно самоуверен и имеет всего несколько ручек для настройки внешнего вида графиков. Можете ли вы дать ссылку на существующую демонстрацию, которая дает вам уверенность в том, что Graphviz способен производить то, что вы ищете?   -  person bignose    schedule 24.01.2016
comment
Большое спасибо за ответ. Поверьте мне, я бы не создал аккаунт на SO, если бы смог найти в Интернете один пример, который соответствует ВСЕМ моим требованиям. Сказав это, я просто не могу принять (пока), что это невозможно сделать с помощью Graphviz или подобных инструментов, потому что то, чего я пытаюсь достичь, не кажется (по крайней мере мне) очень сложным.   -  person TraderMoe    schedule 24.01.2016