Лекция 1.6. Графвиз — различия между версиями

Материал из Wiki
Перейти к:навигация, поиск
Строка 1: Строка 1:
 +
'''Graphviz''' — это разработанный специалистами лаборатории AT&T пакет утилит по автоматической визуализации графов, заданных в виде текстового описания. Пакет распространяется с открытыми исходными файлами и работает на всех операционных системах, включая Windows, Linux/Unix, Mac OS. Самой интересной программой пакета является «dot», автоматический визуализатор направленных графов, который принимает на вход текстовый файл со структурой графа, а на выходе формирует граф в виде графического, векторного или текстового файла.
 +
 +
= Быстрый старт =
 +
 +
Входной файл для программы «DOT» является обычным текстовым файлом на специальном языке разметки графа. Структура файла очень простая, например,
 +
 +
digraph G{
 +
  Рождение->Юность->Зрелость->Старость->Смерть;
 +
  Юность->Смерть;
 +
  Зрелость->Смерть;
 +
}
 +
 +
на выходе будет
 +
 +
<graph>
 +
digraph G{
 +
      Рождение->Юность->Зрелость->Старость->Смерть;
 +
      Юность->Смерть;
 +
      Зрелость->Смерть;
 +
  }
 +
</graph>
 +
 +
Программа «Dot» сама распознает все связи графа и упорядочит его таким образом, чтобы было наименьшее количество пересечений.
 +
 +
Чтобы использовать «dot»-графы в [[{{SITENAME}}]], используйте следующий синтаксис:
 +
 +
<nowiki><graph>
 +
digraph G{
 +
  Рождение->Юность->Зрелость->Старость->Смерть;
 +
  Юность->Смерть;
 +
  Зрелость->Смерть;
 +
}
 +
</graph></nowiki>
 +
 +
Если у вас узлы поименованы словосочетаниями, заключите их в кавычки, т. е.
 +
 +
<nowiki><graph>
 +
digraph G{
 +
  "Полет фантазии"->"Расход горючего";
 +
}
 +
</graph></nowiki>
 +
 +
Поздравляем! Теперь вы способны рисовать графы в [[{{SITENAME}}]]. Остальной текст будет посвящен некоторым тонкостям использования [[Graphviz]].
 +
 +
= Внешний вид графа =
 +
«Dot» позволяет изменять внешний вид графа. Например, можно изменять форму фигур (прямоугольники, овалы, круги, параллелограммы, многоугольники), цвет и шрифт текста, цвет фона фигур, стиль стрелок и рамок фигур, подписи стрелок и т. д.
 +
Итак, основные объектами являются узлы («node») и ребра («edge»). Для того, чтобы настроить свойства всех узлов или ребер нужно вначале использовать команды
 +
node[свойство1="значение1",свойство2="значение2",...]
 +
edge[свойство1="значение1",свойство2="значение2",...]
 +
Также (в квадратных скобках после описания объекта) можно изменять настройки конкретного узла или ребра. Параметры графа, просто задаются в виде <tt>параметр=значение</tt>.
 +
Полезно запомнить параметр «rankdir», он может быть «TB» (top->bottom, параметр по умолчанию), или «LR» (left->right), и определяет, сверху-вниз, или справа-налево, нужно располагать узлы графа. Вот пестрый пример:
 +
 +
digraph G{
 +
  rankdir=LR;
 +
  node[color="red",fontsize=14];
 +
  edge[color="darkgreen",fontcolor="blue",fontsize=12];
 +
  OPEN[shape="rectangle",style="filled",fillcolor="lightgrey"];
 +
  CLOSED[shape="octagon",label="Финиш"];
 +
  VERIFIED[shape="rectangle",style="rounded"];
 +
  OPEN->RESOLVED->VERIFIED->CLOSED;
 +
  OPEN->CLOSED[style="bold"];
 +
  VERIFIED->OPEN[label="обнаружены ошибки",style="dashed",arrowhead="dot"];
 +
}
 +
 +
на выходе будет
 +
 +
<graph>
 +
digraph G{
 +
  rankdir=LR;
 +
  node[color="red",fontsize=14];
 +
  edge[color="darkgreen",fontcolor="blue",fontsize=12];
 +
  OPEN[shape="rectangle",style="filled",fillcolor="lightgrey"];
 +
  CLOSED[shape="octagon",label="Финиш"];
 +
  VERIFIED[shape="rectangle",style="rounded"];
 +
  OPEN->RESOLVED->VERIFIED->CLOSED;
 +
  OPEN->CLOSED[style="bold"];
 +
  VERIFIED->OPEN[label="обнаружены ошибки",style="dashed",arrowhead="dot"];
 +
}
 +
</graph>
 +
 +
Если предполагается, что граф будут не только просматривать через IE, но и печатать, то необходимо установить ширину картинки, иначе при печати картинка будет обрезана. Для этого следует задать внутри описания
 +
size="6.7,15";
 +
Существенна только первая цифра. Число 6.7 подобрано эмпирически, оно обеспечивает печать полной картинки при настройках IE по умолчанию.
 +
 +
= Уровни в графах =
 +
 +
В «Dot» присутствует возможность связать узлы графа не только стрелками, но и уровнями отображения, что позволяет создавать шкалу и располагать узлы графа соответственно данной шкале. Для связывания используется следующая конструкция:
 +
  { rank = same; "элемент уровня"; "элемент для привязки 1"; "элемент для привязки 2"; ..}
 +
 +
 +
Например, при использовании следующей конструкции:
 +
<nowiki><graph>
 +
digraph G{
 +
  node[fontsize=9];
 +
  { /* шкала месяцев*/
 +
    node[shape=plaintext]; /* что бы не было видно рамок */
 +
    edge[color=white] /* что бы не было видно стрелок */
 +
    "март" ->  "июнь" -> "сентябрь" -> "декабрь";
 +
  }
 +
  { rank = same; "март"; "весна"; "a"; }
 +
  { rank = same; "июнь"; "лето";}
 +
  { rank = same; "сентябрь"; "осень"; "d"; }
 +
  { rank = same; "декабрь"; "зима"; "e"}
 +
  "весна" -> "лето" -> "осень" -> "зима" -> "весна"
 +
  "a" -> "b" -> "c" -> "d" -> "e" ;
 +
}
 +
</graph></nowiki>
 +
 +
на выходе получается:
 +
<graph>
 +
digraph G{
 +
  node[fontsize=9];
 +
  { /* шкала месяцев*/
 +
    node[shape=plaintext]; /* что бы не было видно рамок */
 +
    edge[color=white] /* что бы не было видно стрелок */
 +
    "март" ->  "июнь" -> "сентябрь" -> "декабрь";
 +
  }
 +
  { rank = same; "март"; "весна"; "a"; }
 +
  { rank = same; "июнь"; "лето";}
 +
  { rank = same; "сентябрь"; "осень"; "d"; }
 +
  { rank = same; "декабрь"; "зима"; "e"}
 +
  "весна" -> "лето" -> "осень" -> "зима" -> "весна"
 +
  "a" -> "b" -> "c" -> "d" -> "e" ;
 +
}
 +
</graph>
 +
 +
= Многосекционный узлы =
 +
 +
Dot позволяет создавать многосекционные узлы при это каждая секция может быть поименована, и тогда ребра можно продоводить между секциями и узлами.
 +
 +
Для включения режима многосекционности устанавливается атрибут узла shape.
 +
shape=record;
 +
 +
Секции описываются в атрибуте label узла,  с помощью разделителя «|». Для именования секции ее имя указывается в <>. При описание ребра, исходящего или входящего в секцию, секция именуется следующим образом:
 +
 +
элемент:<имя_секции>
 +
 +
Например, из такого описания:
 +
 +
digraph structs {
 +
  rankdir=HR;
 +
  first [shape=record,label="  x1\n all | { x21 | <f0> x22| x23} | x3" ];
 +
  second [shape=record,label=" x22_1 | x22_2 | x22_3"];
 +
  first:<f0> -> second;
 +
}
 +
 +
Получается следующее:
 +
 +
<graph>
 +
digraph structs {
 +
  rankdir=HR;
 +
  first [shape=record,label="  x1\n all | { x21 | <f0> x22| x23} | x3" ];
 +
  second [shape=record,label=" x22_1 | x22_2 | x22_3"];
 +
  first:<f0> -> second;
 +
}
 +
</graph>
 +
 +
= Гиперссылки на графах =
 +
 +
Можно использовать атрибут «URL», задавая относительные или абсолютные гиперссылки для узлов и ребер. Например
 +
 +
<nowiki><graph>
 +
digraph G {
 +
    rankdir=LR;
 +
            SGML [URL="SGML"];
 +
            HTML [URL="HTML"];
 +
            XML [URL="XML"];
 +
            XHTML [URL="http://www.w3schools.com/xhtml/"];
 +
    SGML->HTML;
 +
    SGML->XML;
 +
    HTML->XHTML;
 +
    XML->XHTML;
 +
    SGML->XHTML[color="red",fontcolor="blue",label="ссылка на Google",URL="http://www.google.com"];
 +
}
 +
</graph></nowiki>
 +
 +
 +
<graph>
 +
digraph G {
 +
    rankdir=LR;
 +
            SGML [URL="SGML"];
 +
            HTML [URL="HTML"];
 +
            XML [URL="XML"];
 +
            XHTML [URL="http://www.w3schools.com/xhtml/"];
 +
    SGML->HTML;
 +
    SGML->XML;
 +
    HTML->XHTML;
 +
    XML->XHTML;
 +
    SGML->XHTML[color="red",fontcolor="blue",label="ссылка на Google",URL="http://www.google.com"];
 +
}
 +
</graph>
 +
 +
= Кластеры в графах =
 +
 +
Программа «Dot» позволяет объединять узлы графов в кластеры для подчеркивания общности.
 +
 +
Кластер описывается следующим синтаксисом:
 +
subgraph имя{
 +
свойство1 = "значение1",свойство2="значение2",...
 +
узел1;
 +
узел2;
 +
...
 +
}
 +
При этом ''имя'' подграфа должно начинаться с префикса '''cluster''', иначе подграф не позволяет себя отобразить на экран(раскраска, контур, подпись, .. ).
 +
 +
Например:
 +
 +
  digraph G {
 +
  rankdir=LR;
 +
  subgraph cluster0 {
 +
        node [style=filled,color=white];
 +
        style=filled;
 +
        color=lightgrey;
 +
        a0;
 +
        a1
 +
        label = "process #1";
 +
  }
 +
  subgraph cluster1 {
 +
        node [style=filled];
 +
        b0;
 +
        label = "process #2";
 +
        color=blue
 +
  }
 +
  start -> a0;
 +
  start -> b0;
 +
  a0 -> a1 -> end;
 +
  b0 -> end;
 +
  }
 +
 +
<graph>
 +
digraph G {
 +
  rankdir=LR;
 +
  subgraph cluster0 {
 +
        node [style=filled,color=white];
 +
        style=filled;
 +
        color=lightgrey;
 +
        a0;
 +
        a1
 +
        label = "process #1";
 +
  }
 +
  subgraph cluster1 {
 +
        node [style=filled];
 +
        b0;
 +
        label = "process #2";
 +
        color=blue
 +
  }
 +
  start -> a0;
 +
  start -> b0;
 +
  a0 -> a1 -> end;
 +
  b0 -> end;
 +
  }
 +
</graph>
 +
 +
= Цвета и черно-белая печать=
 +
Graphviz позволяет использовать широкую цветовую палитру, однако, стоит не забывать, что контрастно выглядящие на цветном мониторе цвета, могут быть совершенно неразличимы после черно-белой печати. После проделанных экспериментов ({{Bug|11015}}), можно рекомендовать следующие палитры цветов (иллюстрированы на цвете ребер графа):
 +
 +
<graph-print>
 +
digraph G{ rankdir=TB; size="7,6";
 +
 +
Палитра1->goldenrod1 [color=goldenrod1]
 +
Палитра1->green [color=green]
 +
Палитра1->sienna4 [color=sienna4]
 +
Палитра1->red1 [color=red1]
 +
Палитра1->blue2 [color=blue2]
 +
 +
Палитра2->lightcyan2 [color=lightcyan2]
 +
Палитра2->pink2 [color=pink2]
 +
Палитра2->green [color=green]
 +
Палитра2->sienna4 [color=sienna4]
 +
Палитра2->red2 [color=red2]
 +
Палитра2->black1 [color=black1]
 +
}
 +
</graph-print>
 +
 +
= Формы вершин =
 +
 +
Перечислим палитру возможных форм вершин (узлов).
 +
 +
<neato>
 +
digraph G{ 
 +
edge [arrowtail="none"]
 +
node [style=filled,  colorscheme="brbg9"];
 +
 +
"box"      [shape="box"      fillcolor="1"];
 +
"polygon"  [shape="polygon"      fillcolor="2"];
 +
"ellipse"  [shape="ellipse"      fillcolor="3"];
 +
"circle"  [shape="circle"      fillcolor="4"];
 +
"point"  [shape="point"      fillcolor="black"];
 +
"egg"  [shape="egg"      fillcolor="6"];
 +
"triangle"  [shape="triangle"      fillcolor="7"];
 +
"plaintext"  [shape="plaintext"      fillcolor="8"];
 +
"diamond"  [shape="diamond"      fillcolor="9"];
 +
"trapezium"  [shape="trapezium"      fillcolor="1"];
 +
"parallelogram"  [shape="parallelogram"      fillcolor="2"];
 +
"house"  [shape="house"      fillcolor="3"];
 +
  "pentagon"  [shape="pentagon"      fillcolor="4"];
 +
"hexagon"  [shape="hexagon"      fillcolor="5"];
 +
"septagon"  [shape="septagon"      fillcolor="6"];
 +
"octagon"  [shape="octagon"      fillcolor="7"];
 +
"doublecircle"  [shape="doublecircle"      fillcolor="8"];
 +
"doubleoctagon"  [shape="doubleoctagon"      fillcolor="9"];
 +
"tripleoctagon"  [shape="tripleoctagon"      fillcolor="1"];
 +
"invtriangle"  [shape="invtriangle"      fillcolor="1"];
 +
"invtrapezium"  [shape="invtrapezium"      fillcolor="2"];
 +
"invhouse"  [shape="invhouse"      fillcolor="3"];
 +
"Mdiamond"  [shape="Mdiamond"      fillcolor="4"];
 +
"Msquare"  [shape="Msquare"      fillcolor="5"];
 +
"Mcircle"  [shape="Mcircle"      fillcolor="6"];
 +
"rect/rectangle"  [shape="rect"      fillcolor="7"];
 +
"none"  [shape="none"      fillcolor="8"];
 +
"note"  [shape="note"      fillcolor="9"];
 +
"tab"  [shape="tab"      fillcolor="1"];
 +
"folder"  [shape="folder"      fillcolor="2"];
 +
"box3d"  [shape="box3d"      fillcolor="3"];
 +
"component"  [shape="component"      fillcolor="4"];
 +
}
 +
</neato>
 +
 +
= Окончания ребер =
 +
Можно задавать стиль офомления начала («arrowtail») и конца («arrowhead») дуг (ребер):
 +
 +
<circo>
 +
digraph G{ 
 +
 +
edge [arrowtail="none"]
 +
A [label="Arrowhead" style=filled fillcolor="yellow"];
 +
 +
  A->"normal" [arrowhead="normal"];
 +
  A->"dot" [arrowhead="dot"];
 +
  A->"odot" [arrowhead="odot"];
 +
  A->"none" [arrowhead="none"];
 +
  A->"empty" [arrowhead="empty"];
 +
  A->"diamond" [arrowhead="diamond"];
 +
  A->"ediamond" [arrowhead="ediamond"];
 +
  A->"box" [arrowhead="box"];
 +
  A->"open" [arrowhead="open"];
 +
  A->"vee" [arrowhead="vee"];
 +
  A->"inv" [arrowhead="inv"];
 +
  A->"invdot" [arrowhead="invdot"];
 +
  A->"invodot" [arrowhead="invodot"];
 +
  A->"tee" [arrowhead="tee"];
 +
  A->"invempty" [arrowhead="invempty"];
 +
  A->"odiamond" [arrowhead="odiamond"];
 +
  A->"crow" [arrowhead="crow"];
 +
  A->"obox" [arrowhead="obox"];
 +
  A->"halfopen" [arrowhead="halfopen"];
 +
}
 +
</circo>
 +
 +
= Неориентированные графы =
 +
Наряду с рисованием ориентированных графов, есть несколько методов для автоматического рисования неориентированных графов (будем рассматривать их на примере несложной ER-диаграммы).
 +
 +
В отличие от автоматического рисования направленных («directed») графов, основанных на ранговой модели, есть несколько подходов к раскладке ненаправленных графов.
 +
 +
== Graph ==
 +
Ненаправленный граф можно нарисовать с помощью рангового подхода (несмотря на ненаправленность ребер) — будет использоваться программа «dot». Как это будет выглядеть для простой ER-диаграммы, можно увидеть ниже.
 +
<graph>
 +
graph ER
 +
{
 +
  node [fontsize=12];
 +
  node [shape=box]; course; institute; student;
 +
  node [shape=ellipse];
 +
  {node [label="name"] name0; name1; name2;}
 +
  code; grade; number;
 +
node [shape=diamond,style=filled,color=lightgrey];
 +
  "C-I"; "S-C"; "S-I";
 +
name0 -- course;
 +
code -- course;
 +
course -- "C-I" [label="n",len=1.00];
 +
"C-I" -- institute [label="1",len=1.00];
 +
institute -- name1;
 +
institute -- "S-I" [label="1",len=1.00];
 +
"S-I" -- student [label="n",len=1.00];
 +
student -- grade;
 +
student -- name2;
 +
student -- number;
 +
student -- "S-C" [label="m",len=1.00];
 +
"S-C" -- course [label="n",len=1.00];
 +
  label = "\n\nEntity Relation Diagram\ndrawn by DOT";
 +
}
 +
</graph>
 +
 +
Очевидна неоптимальность такого подхода для неориентированных графов.
 +
 +
== Neato ==
 +
 +
Метод «neato» использует «энергетическую» (''spring'') модель, по сути, близкую к методу искуственного отжига — начиная с некоторого состояния вершины перемещаются, чтобы минимизировать некую потенциальную энергию. Рекомендуем для ненаправленных графов общего вида.
 +
 +
<neato>
 +
graph ER
 +
{
 +
node [fontsize=12];
 +
node [shape=box]; course; institute; student;
 +
  node [shape=ellipse];
 +
  {node [label="name"] name0; name1; name2;}
 +
  code; grade; number;
 +
node [shape=diamond,style=filled,color=lightgrey];
 +
  "C-I"; "S-C"; "S-I";
 +
name0 -- course;
 +
code -- course;
 +
course -- "C-I" [label="n",len=1.00];
 +
"C-I" -- institute [label="1",len=1.00];
 +
  institute -- name1;
 +
  institute -- "S-I" [label="1",len=1.00];
 +
"S-I" -- student [label="n",len=1.00];
 +
student -- grade;
 +
student -- name2;
 +
student -- number;
 +
student -- "S-C" [label="m",len=1.00];
 +
"S-C" -- course [label="n",len=1.00];
 +
label = "\n\nEntity Relation Diagram\ndrawn by NEATO";
 +
}
 +
</neato>
 +
 +
== FDP ==
 +
Метод «fdp» по сути, близок к методу «neato», и использует другую разновидность «энергетического» («spring») подхода. Также рекомендуется для ненаправленных графов общего типа.
 +
 +
<fdp>
 +
graph ER
 +
{
 +
node [fontsize=12];
 +
node [shape=box]; course; institute; student;
 +
  node [shape=ellipse];
 +
  {node [label="name"] name0; name1; name2;}
 +
  code; grade; number;
 +
node [shape=diamond,style=filled,color=lightgrey];
 +
  "C-I"; "S-C"; "S-I";
 +
name0 -- course;
 +
code -- course;
 +
course -- "C-I" [label="n",len=1.00];
 +
"C-I" -- institute [label="1",len=1.00];
 +
  institute -- name1;
 +
institute -- "S-I" [label="1",len=1.00];
 +
"S-I" -- student [label="n",len=1.00];
 +
student -- grade;
 +
student -- name2;
 +
student -- number;
 +
student -- "S-C" [label="m",len=1.00];
 +
"S-C" -- course [label="n",len=1.00];
 +
label = "\n\nEntity Relation Diagram\ndrawn by FDP";
 +
}
 +
</fdp>
 +
 +
 +
 +
 +
== Twopi ==
 +
 +
Метод «twopi» рисует графы с радиальной раскладкой. По сути одна вершина выбирается центральной, и помещается в центр, а остальные размещаются на последовательности концентрических орбит, вокруг этой вершины. Т.е. все вершины на расстоянии в «одно ребро» от центра, лежат на первой орбите, «в два ребра» — на второй и т. д.
 +
 +
<twopi>
 +
graph ER
 +
{
 +
 +
node [fontsize=12];
 +
  node [shape=box]; course; institute; student;
 +
  node [shape=ellipse];
 +
  {node [label="name"] name0; name1; name2;}
 +
  code; grade; number;
 +
node [shape=diamond,style=filled,color=lightgrey];
 +
  "C-I"; "S-C"; "S-I";
 +
name0 -- course;
 +
code -- course;
 +
course -- "C-I" [label="n",len=1.00];
 +
"C-I" -- institute [label="1",len=1.00];
 +
  institute -- name1;
 +
institute -- "S-I" [label="1",len=1.00];
 +
"S-I" -- student [label="n",len=1.00];
 +
student -- grade;
 +
student -- name2;
 +
student -- number;
 +
student -- "S-C" [label="m",len=1.00];
 +
"S-C" -- course [label="n",len=1.00];
 +
label = "\n\nEntity Relation Diagram\ndrawn by TWOPI";
 +
}
 +
</twopi>
 +
 +
== CIRCO ==
 +
 +
Метод «circo» использует «circular layout». Выделяются двусвязные компоненты (каждая вершина имеет по крайней мере два ребра) и вершины этих компонент рисуются на некотором круге. «Дополнительные» ребра рисуются радиально и далее процесс повторяется. Пересечение ребер внутри круга минимизируется максимально возможным выносом ребер с круга за его периметр.
 +
 +
<circo>
 +
graph ER
 +
{
 +
node [fontsize=12];
 +
node [shape=box]; course; institute; student;
 +
  node [shape=ellipse];
 +
  {node [label="name"] name0; name1; name2;}
 +
  code; grade; number;
 +
node [shape=diamond,style=filled,color=lightgrey];
 +
  "C-I"; "S-C"; "S-I";
 +
name0 -- course;
 +
code -- course;
 +
course -- "C-I" [label="n",len=1.00];
 +
"C-I" -- institute [label="1",len=1.00];
 +
  institute -- name1;
 +
institute -- "S-I" [label="1",len=1.00];
 +
"S-I" -- student [label="n",len=1.00];
 +
student -- grade;
 +
student -- name2;
 +
student -- number;
 +
student -- "S-C" [label="m",len=1.00];
 +
"S-C" -- course [label="n",len=1.00];
 +
label = "\n\nEntity Relation Diagram\ndrawn by CIRCO";
 +
}
 +
</circo>
 +
 +
= Версии для печати =
 +
Как известно, трудно добиться хорошего результата одновременно на экране и на принтере, в силу разных разрешений. Картинка экранного разрешения будет плохо (с «зазубринами») выглядеть на принтере, а картинка печатного разрешения, будет очень плохо выглядеть на экране (к сожалению, современные броузеры выполняют очень примитивный ресайзинг картинок при показе), и будет достаточно много «весить». Все соображения о печатных картинках также относятся к случаю, когда вы переносите (например, копируя вебстраницу из броузера через клипборд) содержимое MediaWiki-статьи в MS Word или другой текстовый редактор.
 +
Для такого, «печатного» случая (т. е. если у вас не примитивные графы, и вы собираетесь их печатать или переносить в другую систему верстки), мы сделали «печатную версию» всех перечисленных графов, с разрешением около 200 DPI. Для этого надо использовать те же самые тэги с постфиксом «-print», например «graph-print»,«neato-print», и т.п.:
 +
 +
<graph-print>
 +
digraph G{
 +
  rankdir=LR;
 +
  node[color="red",fontsize=14];
 +
  edge[color="darkgreen",fontcolor="blue",fontsize=12];
 +
  OPEN[shape="rectangle",style="filled",fillcolor="lightgrey"];
 +
  CLOSED[shape="octagon",label="Финиш"];
 +
  VERIFIED[shape="rectangle",style="rounded"];
 +
  OPEN->RESOLVED->VERIFIED->CLOSED;
 +
  OPEN->CLOSED[style="bold"];
 +
  VERIFIED->OPEN[label="обнаружены ошибки",style="dashed",arrowhead="dot"];
 +
}
 +
</graph-print>
 +
 +
Полученные картинки являются компромиссом, между весом, читаемостью на экране и читаемостью на бумаге.
 +
Желательно не использовать для совершенно тривиальных графов, или графов, которых вы не собираетесь печатать.
 +
 +
 
<graphviz>digraph G{Рождение->Юность->Зрелость->Старость->Смерть;Юность->Смерть;Зрелость->Смерть;}
 
<graphviz>digraph G{Рождение->Юность->Зрелость->Старость->Смерть;Юность->Смерть;Зрелость->Смерть;}
 
</graphviz>  
 
</graphviz>  

Версия 10:14, 28 апреля 2009

Graphviz — это разработанный специалистами лаборатории AT&T пакет утилит по автоматической визуализации графов, заданных в виде текстового описания. Пакет распространяется с открытыми исходными файлами и работает на всех операционных системах, включая Windows, Linux/Unix, Mac OS. Самой интересной программой пакета является «dot», автоматический визуализатор направленных графов, который принимает на вход текстовый файл со структурой графа, а на выходе формирует граф в виде графического, векторного или текстового файла.

Быстрый старт

Входной файл для программы «DOT» является обычным текстовым файлом на специальном языке разметки графа. Структура файла очень простая, например,

digraph G{ 
 Рождение->Юность->Зрелость->Старость->Смерть;
 Юность->Смерть;
 Зрелость->Смерть;
}

на выходе будет

<graph>

digraph G{
     Рождение->Юность->Зрелость->Старость->Смерть;
     Юность->Смерть;
     Зрелость->Смерть;
 }

</graph>

Программа «Dot» сама распознает все связи графа и упорядочит его таким образом, чтобы было наименьшее количество пересечений.

Чтобы использовать «dot»-графы в Wiki, используйте следующий синтаксис:

<graph>
digraph G{ 
  Рождение->Юность->Зрелость->Старость->Смерть;
  Юность->Смерть;
  Зрелость->Смерть;
 }
 </graph>

Если у вас узлы поименованы словосочетаниями, заключите их в кавычки, т. е.

<graph>
digraph G{
  "Полет фантазии"->"Расход горючего";
 }
 </graph>

Поздравляем! Теперь вы способны рисовать графы в Wiki. Остальной текст будет посвящен некоторым тонкостям использования Graphviz.

Внешний вид графа

«Dot» позволяет изменять внешний вид графа. Например, можно изменять форму фигур (прямоугольники, овалы, круги, параллелограммы, многоугольники), цвет и шрифт текста, цвет фона фигур, стиль стрелок и рамок фигур, подписи стрелок и т. д. Итак, основные объектами являются узлы («node») и ребра («edge»). Для того, чтобы настроить свойства всех узлов или ребер нужно вначале использовать команды

node[свойство1="значение1",свойство2="значение2",...]
edge[свойство1="значение1",свойство2="значение2",...]

Также (в квадратных скобках после описания объекта) можно изменять настройки конкретного узла или ребра. Параметры графа, просто задаются в виде параметр=значение. Полезно запомнить параметр «rankdir», он может быть «TB» (top->bottom, параметр по умолчанию), или «LR» (left->right), и определяет, сверху-вниз, или справа-налево, нужно располагать узлы графа. Вот пестрый пример:

digraph G{
 rankdir=LR;
 node[color="red",fontsize=14];
 edge[color="darkgreen",fontcolor="blue",fontsize=12];
 OPEN[shape="rectangle",style="filled",fillcolor="lightgrey"];
 CLOSED[shape="octagon",label="Финиш"];
 VERIFIED[shape="rectangle",style="rounded"];
 OPEN->RESOLVED->VERIFIED->CLOSED;
 OPEN->CLOSED[style="bold"];
 VERIFIED->OPEN[label="обнаружены ошибки",style="dashed",arrowhead="dot"];
}

на выходе будет

<graph> digraph G{

  rankdir=LR;
 node[color="red",fontsize=14];
 edge[color="darkgreen",fontcolor="blue",fontsize=12];
 OPEN[shape="rectangle",style="filled",fillcolor="lightgrey"];
 CLOSED[shape="octagon",label="Финиш"];
 VERIFIED[shape="rectangle",style="rounded"];
 OPEN->RESOLVED->VERIFIED->CLOSED;
 OPEN->CLOSED[style="bold"];
 VERIFIED->OPEN[label="обнаружены ошибки",style="dashed",arrowhead="dot"];
}

</graph>

Если предполагается, что граф будут не только просматривать через IE, но и печатать, то необходимо установить ширину картинки, иначе при печати картинка будет обрезана. Для этого следует задать внутри описания

size="6.7,15";

Существенна только первая цифра. Число 6.7 подобрано эмпирически, оно обеспечивает печать полной картинки при настройках IE по умолчанию.

Уровни в графах

В «Dot» присутствует возможность связать узлы графа не только стрелками, но и уровнями отображения, что позволяет создавать шкалу и располагать узлы графа соответственно данной шкале. Для связывания используется следующая конструкция:

  { rank = same; "элемент уровня"; "элемент для привязки 1"; "элемент для привязки 2"; ..}

Например, при использовании следующей конструкции:

<graph>
 digraph G{
   node[fontsize=9];
   { /* шкала месяцев*/
     node[shape=plaintext]; /* что бы не было видно рамок */
     edge[color=white] /* что бы не было видно стрелок */
     "март" ->  "июнь" -> "сентябрь" -> "декабрь"; 
   }
   { rank = same; "март"; "весна"; "a"; }
   { rank = same; "июнь"; "лето";}
   { rank = same; "сентябрь"; "осень"; "d"; }
   { rank = same; "декабрь"; "зима"; "e"}
   "весна" -> "лето" -> "осень" -> "зима" -> "весна"
   "a" -> "b" -> "c" -> "d" -> "e" ;
 }
 </graph>

на выходе получается: <graph> digraph G{

  node[fontsize=9];
  { /* шкала месяцев*/
    node[shape=plaintext]; /* что бы не было видно рамок */
    edge[color=white] /* что бы не было видно стрелок */
    "март" ->  "июнь" -> "сентябрь" -> "декабрь"; 
  }
  { rank = same; "март"; "весна"; "a"; }
  { rank = same; "июнь"; "лето";}
  { rank = same; "сентябрь"; "осень"; "d"; }
  { rank = same; "декабрь"; "зима"; "e"}
  "весна" -> "лето" -> "осень" -> "зима" -> "весна"
  "a" -> "b" -> "c" -> "d" -> "e" ;
}

</graph>

Многосекционный узлы

Dot позволяет создавать многосекционные узлы при это каждая секция может быть поименована, и тогда ребра можно продоводить между секциями и узлами.

Для включения режима многосекционности устанавливается атрибут узла shape.

shape=record;

Секции описываются в атрибуте label узла, с помощью разделителя «|». Для именования секции ее имя указывается в <>. При описание ребра, исходящего или входящего в секцию, секция именуется следующим образом:

элемент:<имя_секции>

Например, из такого описания:

digraph structs {
  rankdir=HR;
  first [shape=record,label="  x1\n all | { x21 | <f0> x22| x23} | x3" ];
  second [shape=record,label=" x22_1 | x22_2 | x22_3"];
  first:<f0> -> second;
}

Получается следующее:

<graph>

digraph structs {
  rankdir=HR;
  first [shape=record,label="  x1\n all | { x21 | <f0> x22| x23} | x3" ];
  second [shape=record,label=" x22_1 | x22_2 | x22_3"];
  first:<f0> -> second;
}

</graph>

Гиперссылки на графах

Можно использовать атрибут «URL», задавая относительные или абсолютные гиперссылки для узлов и ребер. Например

<graph>
 digraph G {
     rankdir=LR;
            SGML [URL="SGML"];
            HTML [URL="HTML"];
            XML [URL="XML"];
            XHTML [URL="http://www.w3schools.com/xhtml/"];
    SGML->HTML;
    SGML->XML;
    HTML->XHTML;
    XML->XHTML;
    SGML->XHTML[color="red",fontcolor="blue",label="ссылка на Google",URL="http://www.google.com"];
 }
 </graph>


<graph>

digraph G {
    rankdir=LR;
           SGML [URL="SGML"];
           HTML [URL="HTML"];
           XML [URL="XML"];
           XHTML [URL="http://www.w3schools.com/xhtml/"];
   SGML->HTML;
   SGML->XML;
   HTML->XHTML;
   XML->XHTML;
   SGML->XHTML[color="red",fontcolor="blue",label="ссылка на Google",URL="http://www.google.com"];

} </graph>

Кластеры в графах

Программа «Dot» позволяет объединять узлы графов в кластеры для подчеркивания общности.

Кластер описывается следующим синтаксисом:

subgraph имя{
свойство1 = "значение1",свойство2="значение2",...
узел1; 
узел2;
...
}

При этом имя подграфа должно начинаться с префикса cluster, иначе подграф не позволяет себя отобразить на экран(раскраска, контур, подпись, .. ).

Например:

 digraph G {
  rankdir=LR;
  subgraph cluster0 {
       node [style=filled,color=white];
       style=filled;
       color=lightgrey;
       a0;
       a1
       label = "process #1";
  }
  subgraph cluster1 {
       node [style=filled];
       b0;
       label = "process #2";
       color=blue
  }
  start -> a0;
  start -> b0;
  a0 -> a1 -> end;
  b0 -> end;
 }

<graph>

digraph G {
  rankdir=LR;
  subgraph cluster0 {
       node [style=filled,color=white];
       style=filled;
       color=lightgrey;
       a0;
       a1
       label = "process #1";
  }
  subgraph cluster1 {
       node [style=filled];
       b0;
       label = "process #2";
       color=blue
  }
  start -> a0;
  start -> b0;
  a0 -> a1 -> end;
  b0 -> end;
 }

</graph>

Цвета и черно-белая печать

Graphviz позволяет использовать широкую цветовую палитру, однако, стоит не забывать, что контрастно выглядящие на цветном мониторе цвета, могут быть совершенно неразличимы после черно-белой печати. После проделанных экспериментов (Шаблон:Bug), можно рекомендовать следующие палитры цветов (иллюстрированы на цвете ребер графа):

<graph-print> digraph G{ rankdir=TB; size="7,6";

Палитра1->goldenrod1 [color=goldenrod1]
Палитра1->green [color=green]
Палитра1->sienna4 [color=sienna4]
Палитра1->red1 [color=red1]
Палитра1->blue2 [color=blue2]
Палитра2->lightcyan2 [color=lightcyan2]
Палитра2->pink2 [color=pink2]
Палитра2->green [color=green]
Палитра2->sienna4 [color=sienna4]
Палитра2->red2 [color=red2]
Палитра2->black1 [color=black1]
}

</graph-print>

Формы вершин

Перечислим палитру возможных форм вершин (узлов).

<neato> digraph G{

edge [arrowtail="none"]
node [style=filled,  colorscheme="brbg9"]; 

"box"      [shape="box"      fillcolor="1"];
"polygon"  [shape="polygon"      fillcolor="2"];
"ellipse"  [shape="ellipse"      fillcolor="3"];
"circle"  [shape="circle"      fillcolor="4"];
"point"  [shape="point"      fillcolor="black"];
"egg"  [shape="egg"      fillcolor="6"];
"triangle"  [shape="triangle"      fillcolor="7"];
"plaintext"  [shape="plaintext"      fillcolor="8"];
"diamond"  [shape="diamond"      fillcolor="9"];
"trapezium"  [shape="trapezium"      fillcolor="1"];
"parallelogram"  [shape="parallelogram"      fillcolor="2"];
"house"  [shape="house"      fillcolor="3"];
 "pentagon"  [shape="pentagon"      fillcolor="4"];
"hexagon"  [shape="hexagon"      fillcolor="5"];
"septagon"  [shape="septagon"      fillcolor="6"];
"octagon"  [shape="octagon"      fillcolor="7"];
"doublecircle"  [shape="doublecircle"      fillcolor="8"];
"doubleoctagon"  [shape="doubleoctagon"      fillcolor="9"];
"tripleoctagon"  [shape="tripleoctagon"      fillcolor="1"];
"invtriangle"  [shape="invtriangle"      fillcolor="1"];
"invtrapezium"  [shape="invtrapezium"      fillcolor="2"];
"invhouse"  [shape="invhouse"      fillcolor="3"];
"Mdiamond"  [shape="Mdiamond"      fillcolor="4"];
"Msquare"  [shape="Msquare"      fillcolor="5"];
"Mcircle"  [shape="Mcircle"      fillcolor="6"];
"rect/rectangle"  [shape="rect"      fillcolor="7"];
"none"  [shape="none"      fillcolor="8"];
"note"  [shape="note"      fillcolor="9"];
"tab"  [shape="tab"      fillcolor="1"];
"folder"  [shape="folder"      fillcolor="2"];
"box3d"  [shape="box3d"      fillcolor="3"];
"component"  [shape="component"      fillcolor="4"];

} </neato>

Окончания ребер

Можно задавать стиль офомления начала («arrowtail») и конца («arrowhead») дуг (ребер):

<circo> digraph G{

edge [arrowtail="none"]
A [label="Arrowhead" style=filled fillcolor="yellow"];

 A->"normal" [arrowhead="normal"];
 A->"dot" [arrowhead="dot"];
 A->"odot" [arrowhead="odot"];
  A->"none" [arrowhead="none"];
  A->"empty" [arrowhead="empty"];
  A->"diamond" [arrowhead="diamond"];
  A->"ediamond" [arrowhead="ediamond"];
  A->"box" [arrowhead="box"];
  A->"open" [arrowhead="open"];
  A->"vee" [arrowhead="vee"];
  A->"inv" [arrowhead="inv"];
  A->"invdot" [arrowhead="invdot"];
  A->"invodot" [arrowhead="invodot"];
  A->"tee" [arrowhead="tee"];
  A->"invempty" [arrowhead="invempty"];
  A->"odiamond" [arrowhead="odiamond"];
  A->"crow" [arrowhead="crow"];
  A->"obox" [arrowhead="obox"];
  A->"halfopen" [arrowhead="halfopen"];

} </circo>

Неориентированные графы

Наряду с рисованием ориентированных графов, есть несколько методов для автоматического рисования неориентированных графов (будем рассматривать их на примере несложной ER-диаграммы).

В отличие от автоматического рисования направленных («directed») графов, основанных на ранговой модели, есть несколько подходов к раскладке ненаправленных графов.

Graph

Ненаправленный граф можно нарисовать с помощью рангового подхода (несмотря на ненаправленность ребер) — будет использоваться программа «dot». Как это будет выглядеть для простой ER-диаграммы, можно увидеть ниже. <graph> graph ER {

 node [fontsize=12];
 node [shape=box]; course; institute; student;
 node [shape=ellipse];
 {node [label="name"] name0; name1; name2;}
 code; grade; number;
node [shape=diamond,style=filled,color=lightgrey];
 "C-I"; "S-C"; "S-I";
name0 -- course;
code -- course;
course -- "C-I" [label="n",len=1.00];
"C-I" -- institute [label="1",len=1.00];
institute -- name1;
institute -- "S-I" [label="1",len=1.00];
"S-I" -- student [label="n",len=1.00];
student -- grade;
student -- name2;
student -- number;
student -- "S-C" [label="m",len=1.00];
"S-C" -- course [label="n",len=1.00];
 label = "\n\nEntity Relation Diagram\ndrawn by DOT";

} </graph>

Очевидна неоптимальность такого подхода для неориентированных графов.

Neato

Метод «neato» использует «энергетическую» (spring) модель, по сути, близкую к методу искуственного отжига — начиная с некоторого состояния вершины перемещаются, чтобы минимизировать некую потенциальную энергию. Рекомендуем для ненаправленных графов общего вида.

<neato> graph ER {

node [fontsize=12];
node [shape=box]; course; institute; student;
 node [shape=ellipse];
 {node [label="name"] name0; name1; name2;}
 code; grade; number;
node [shape=diamond,style=filled,color=lightgrey];
 "C-I"; "S-C"; "S-I";
name0 -- course;
code -- course;
course -- "C-I" [label="n",len=1.00];
"C-I" -- institute [label="1",len=1.00];
 institute -- name1;
 institute -- "S-I" [label="1",len=1.00];
"S-I" -- student [label="n",len=1.00];
student -- grade;
student -- name2;
student -- number;
student -- "S-C" [label="m",len=1.00];
"S-C" -- course [label="n",len=1.00];
label = "\n\nEntity Relation Diagram\ndrawn by NEATO";

} </neato>

FDP

Метод «fdp» по сути, близок к методу «neato», и использует другую разновидность «энергетического» («spring») подхода. Также рекомендуется для ненаправленных графов общего типа.

<fdp> graph ER {

node [fontsize=12];
node [shape=box]; course; institute; student;
 node [shape=ellipse];
 {node [label="name"] name0; name1; name2;}
 code; grade; number;
node [shape=diamond,style=filled,color=lightgrey];
 "C-I"; "S-C"; "S-I";
name0 -- course;
code -- course;
course -- "C-I" [label="n",len=1.00];
"C-I" -- institute [label="1",len=1.00];
 institute -- name1;
institute -- "S-I" [label="1",len=1.00];
"S-I" -- student [label="n",len=1.00];
student -- grade;
student -- name2;
student -- number;
student -- "S-C" [label="m",len=1.00];
"S-C" -- course [label="n",len=1.00];
label = "\n\nEntity Relation Diagram\ndrawn by FDP";

} </fdp>



Twopi

Метод «twopi» рисует графы с радиальной раскладкой. По сути одна вершина выбирается центральной, и помещается в центр, а остальные размещаются на последовательности концентрических орбит, вокруг этой вершины. Т.е. все вершины на расстоянии в «одно ребро» от центра, лежат на первой орбите, «в два ребра» — на второй и т. д.

<twopi> graph ER {

node [fontsize=12];
 node [shape=box]; course; institute; student;
 node [shape=ellipse];
 {node [label="name"] name0; name1; name2;}
 code; grade; number;
node [shape=diamond,style=filled,color=lightgrey];
 "C-I"; "S-C"; "S-I";
name0 -- course;
code -- course;
course -- "C-I" [label="n",len=1.00];
"C-I" -- institute [label="1",len=1.00];
 institute -- name1;
institute -- "S-I" [label="1",len=1.00];
"S-I" -- student [label="n",len=1.00];
student -- grade;
student -- name2;
student -- number;
student -- "S-C" [label="m",len=1.00];
"S-C" -- course [label="n",len=1.00];
label = "\n\nEntity Relation Diagram\ndrawn by TWOPI";

} </twopi>

CIRCO

Метод «circo» использует «circular layout». Выделяются двусвязные компоненты (каждая вершина имеет по крайней мере два ребра) и вершины этих компонент рисуются на некотором круге. «Дополнительные» ребра рисуются радиально и далее процесс повторяется. Пересечение ребер внутри круга минимизируется максимально возможным выносом ребер с круга за его периметр.

<circo> graph ER {

node [fontsize=12];
node [shape=box]; course; institute; student;
 node [shape=ellipse];
 {node [label="name"] name0; name1; name2;}
 code; grade; number;
node [shape=diamond,style=filled,color=lightgrey];
 "C-I"; "S-C"; "S-I";
name0 -- course;
code -- course;
course -- "C-I" [label="n",len=1.00];
"C-I" -- institute [label="1",len=1.00];
 institute -- name1;
institute -- "S-I" [label="1",len=1.00];
"S-I" -- student [label="n",len=1.00];
student -- grade;
student -- name2;
student -- number;
student -- "S-C" [label="m",len=1.00];
"S-C" -- course [label="n",len=1.00];
label = "\n\nEntity Relation Diagram\ndrawn by CIRCO";

} </circo>

Версии для печати

Как известно, трудно добиться хорошего результата одновременно на экране и на принтере, в силу разных разрешений. Картинка экранного разрешения будет плохо (с «зазубринами») выглядеть на принтере, а картинка печатного разрешения, будет очень плохо выглядеть на экране (к сожалению, современные броузеры выполняют очень примитивный ресайзинг картинок при показе), и будет достаточно много «весить». Все соображения о печатных картинках также относятся к случаю, когда вы переносите (например, копируя вебстраницу из броузера через клипборд) содержимое MediaWiki-статьи в MS Word или другой текстовый редактор. Для такого, «печатного» случая (т. е. если у вас не примитивные графы, и вы собираетесь их печатать или переносить в другую систему верстки), мы сделали «печатную версию» всех перечисленных графов, с разрешением около 200 DPI. Для этого надо использовать те же самые тэги с постфиксом «-print», например «graph-print»,«neato-print», и т.п.:

<graph-print> digraph G{

 rankdir=LR;
 node[color="red",fontsize=14];
 edge[color="darkgreen",fontcolor="blue",fontsize=12];
 OPEN[shape="rectangle",style="filled",fillcolor="lightgrey"];
 CLOSED[shape="octagon",label="Финиш"];
 VERIFIED[shape="rectangle",style="rounded"];
 OPEN->RESOLVED->VERIFIED->CLOSED;
 OPEN->CLOSED[style="bold"];
 VERIFIED->OPEN[label="обнаружены ошибки",style="dashed",arrowhead="dot"];
}

</graph-print>

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


<graphviz>digraph G{Рождение->Юность->Зрелость->Старость->Смерть;Юность->Смерть;Зрелость->Смерть;} </graphviz>


<graphviz> digraph G { graph [bgcolor=Snow2]; rankdir=LR; node[color="Pink",fontsize=8, fontcolor="blue",style=filled, shape="none"]; edge[color="Brown",fontcolor="Green",fontsize=8]; Ярославль -> Кострома -> "Нижний Новгород" -> Казань -> Сызрань [dir=both, label="Волга"]; "Нижний Новгород" -> Дзержинск [style=dotted, label="Ока",arrowhead="dot" ]; Казань -> Елабуга [label="Кама", color="Green:blue:red"]; Ярославль [shape=Mdiamond], Сызрань [shape=Msquare], Кострома [shape=circle], "Нижний Новгород" [shape = doublecircle],Казань[shape=hexagon,color=green]; {rank=same; Елабуга Дзержинск Сызрань }; } </graphviz>


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

Простейший граф

Свойства графа Для того, граф было удобнее просматривать, можно настроить следующие свойства. Например:  Направленность графа:  rankdir=LR - слева-направо  rankdir=TB - сверху вниз  ratio=auto - отношение = авто;  Цвет фона графа - graph [bgcolor=Snow2] - окрашивает фон в цвет - "серый снег"  Свойства (node)узлов - node[color="Pink",fontsize=10, style=filled, fontcolor="blue", shape="none"] (Сочетание двух и более слов записывается в кавычки - "Нижний Новгород")  color="Pink" - цвет = розовый (Таблице цветов)  fontsize=8 - размер шрифта = 8  style=filled - стиль = заполненный (без неё узел прозрачен)  fontcolor="blue" - цвет шрифта = голубой  shape="none" - форма = "без формы"  Формы узла [shape=?] - invtriangle - треугольник вершиной вниз; box - прямоугольник; ellipse - эллипс; invtrapezium - перевёрнутая трапеция; triangle - треугольник; trapezium - трапеция; record -  ; doubleoctagon - двойной восьмиугольник ; octagon - восьмиугольник; tripleoctagon - тройной восьмиугольник (Все формы)  Ярославль [shape=Mdiamond] - узлу Ярославль придаётся форма ромба(алмаз)  Сызрань [shape=Msquare] - узлу Сызрань придаётся форма квадрата  Кострома [shape=circle] - узлу Кострома придаётся форма круга  "Нижний Новгород" [shape=doublecircle] - узлу "Нижний Новгород" придаётся форма двойного круга  Казань [shape=hexagon,color=green] - узлу Казань придаётся форма шестиугольника и зелёный цвет  Управление положением узлов - {rank=same; Елабуга Дзержинск Сызрань ;} - узлам Елабуга, Дзержинск, Сызрань предан разряд = тот же самый; ranksep=3 - расстояние между разрядами;  Свойства(edge)ребер - edge[color="blue",fontcolor="Green",fontsize=12]  color="Brown" - цвет = коричневый  color="Green:blue:red" - трёхцветие (возможно любое количество)  dir=both - направление стрелки в две стороны  fontsize=8 - размер шрифта = 8  fontcolor="blue" - цвет шрифта = зелёный  style=dotted - стиль = пунктирная линия  arrowhead="dot" - голова стрелки = "точка", "none" - нет (Все формы)  Ярлык ребра [label="Волга"] - все связи Ярославль -> ... -> Сызрань будут помечены меткой Волга.

<graphviz>

digraph G{
graph [bgcolor=Snow2];
rankdir=LR ; // направление графа слева направо
node[color="Pink",fontsize=8, fontcolor="blue",style=filled, shape="none"] ;
edge[color="Brown",fontcolor="Green",fontsize=8] ;
Ярославль -> Кострома -> "Нижний Новгород" -> Казань -> Сызрань [dir=both, label="Волга"];
"Нижний Новгород" -> Дзержинск [style=dotted, label="Ока",arrowhead="dot" ] ;
Казань -> Елабуга [label="Кама", color="Green:blue:red"] ;
Ярославль [shape=Mdiamond], Сызрань [shape=Msquare], Кострома [shape=circle];
"Нижний Новгород" [shape = doublecircle],Казань[shape=hexagon,color=green]
{rank=same; Елабуга Дзержинск Сызрань ;}
}
</graphviz>

Гипертекстовые ссылки на страницы Ссылки на внутренние страницы устанавливаются прямым связыванием:  "Нижний Новгород" [URL="Нижний Новгород"]  Гугл [URL="http://www.google.com"] Кроме того, мы можем в начале графа указать, что все элементы поименованные в графе должны ссылаться на страницы с соответстующим названием. node [URL="/index.php/\N"] ; После этого можно просто указывать имена узлов, а гипертекстовые ссылки добавятся к ним автоматически. Для того, чтобы имя заметки на ребре так же становилось ссылкой на страницу, необходимо дополнить метку ссылкой [label="Волга", URL="Волга"]. В графе, который представлен ниже все узлы и метки являются гиперссылками.

________________________________________  Масштабный пример - Карта книги жизни