Lihuen
RSSRSS AtomAtom

Introducción a la sintaxis dot (graphviz)

Este documento introduce a la sintaxis de los archivos .dot para dibujar grafos con la herramienta graphviz

Instalación

Para instalar graphviz en Lihuen, basta con poner como root en un terminal

#apt-get install graphviz graphviz-dev graphviz-doc

y aceptar.

Esto instala entre otras cosas, la aplicación dot que nos permitirá convertir un archivo .dot a un archivo .ps (PostScript) o .png (Portable Network Graphic) con el dibujo del grafo y las páginas del manual con el detalle de la sintaxis para dot.

Primeros pasos

Los archivos .dot tienen la siguiente sintaxis.

/*Esto es un comentario*/
graph nombre_del_grafo {
    "idNodo1";
    "idNodo2"; /*estos son identificadores de nodos*/
    "idNodo3";
    "idNodo1" -- "idNodo2";
    "idNodo1" -- "idNodo3"; /*estas son relaciones entre nodos*/
    "idNodo3" -- "idNodo1";
}

Para compilar el siguiente código escribimos en la terminal

$dot ejemplo1.dot -o ejemplo1.png -Tpng -Gcharset=utf8

Donde ejemplo.dot es el archivo que contiene el código, ejemplo1.png es el archivo con el grafico generado y -Tpng para que el tipo del archivo de salida sea png (Cambiar por -Tps para ps o -Tjpg para jpg, etc.). Así, se genera el siguiente gráfico:

GrafoEjemplo1.png

Con esto generamos un grafo no dirigido con 3 nodos. Es posible mostrar una etiqueta para un nodo en lugar de su id. Por ejemplo:

graph nombre_del_grafo {
   "idNodo1" [label="Nodo"];
   "idNodo2" [label="Nodo"];
   "idNodo3" [label="Nodo"];
   "idNodo1" -- "idNodo2";
   "idNodo1" -- "idNodo3";
   "idNodo3" -- "idNodo1";
}

Compilando de vuelta con dot

$ dot ejemplo2.dot -o ejemplo2.png -Tpng -Gcharset=utf8

obtenemos el siguiente gráfico

GrafoEjemplo2.png

Modificando las propiedades de los nodos

Además de modificar el nombre que va a mostrar el nodo, podemos modificar algunas otras de sus propiedades como su forma, color, fuente, tamaño, etc. Por ejemplo el siguiente código:

graph nombre_del_grafo {
       "idNodo1" [label="Nodo", fillcolor="lightblue", style="filled", shape="triangle"];
       "idNodo2" [label="Nodo", fillcolor="darkolivegreen4", style="filled", fontname="Courier"];
       "idNodo3" [label="Nodo", fillcolor="mistyrose2", style="filled", shape="parallelogram"];
       "idNodo1" -- "idNodo2";
       "idNodo1" -- "idNodo3";
       "idNodo3" -- "idNodo1";
}

Genera el gráfico

GrafoEjemplo3.png

En este caso sólo se modifican las propiedades para cada nodo, para que todos los nodos tengan una determinada propiedad por ejemplo label="Nodo", se usa la instrucción node [atribs]. Estas propiedades son específicas para todos los nodos, pero pueden ser redefinidas para un nodo en particular

graph nombre_del_grafo {
       node [label="Nodo", style="filled"] /*Propiedades globales para todos los nodos*/
       "idNodo1" [fillcolor="lightblue", shape="triangle"];
       "idNodo2" [fillcolor="darkolivegreen4", fontname="Courier"];
       "idNodo3" [label="Nodo Importante", fillcolor="mistyrose2", shape="parallelogram"]; /*Acá se redefine la etiqueta label*/
       "idNodo1" -- "idNodo2";
       "idNodo1" -- "idNodo3";
       "idNodo3" -- "idNodo1";
}

Note la etiqueta del nodo que redefine la propiedad label...

GrafoEjemplo4.png

Modificando las propiedades de las aristas

Las aristas pueden tener diferentes trazos y colores y al igual que las propiedades de los nodos pueden modificar local o globalmente usando la instrucción edge [atribs].

graph nombre_del_grafo {
       edge [label="Arista", style="dashed", color="blue"]; /*propiedades globales*/
       "idNodo1" [label="Nodo", fillcolor="lightblue", style="filled", shape="triangle"];
       "idNodo2" [label="Nodo", fillcolor="darkolivegreen4", style="filled", fontname="Courier"];
       "idNodo3" [label="Nodo", fillcolor="mistyrose2", style="filled", shape="parallelogram"];
       "idNodo1" -- "idNodo2" [label="Arista Importante"];
       "idNodo1" -- "idNodo3" [style="solid", color="red" ];/*propiedades sobreescritas*/
       "idNodo3" -- "idNodo1";
}

Note las propiedades sobreescritas

GrafoEjemplo5.png


La definición formal del lenguaje dot en EBNF

<graph> ::= [ 'strict' ] ('graph' | 'digraph') [ ID ] '{' <stmt_list> '}'
<stmt_list> ::= [ <stmt> [ ';' ] [ <stmt_list> ] ]
<stmt>  ::=  <node_stmt> | <edge_stmt> | <attr_stmt> | ID '=' ID |  <subgraph>
<attr_stmt>  ::=  ('graph' | 'node' | 'edge') <attr_list>
<attr_list>  ::=  '[' [ <a_list> ] ']' [ <attr_list> ]
<a_list> ::= ID [ '=' ID ] [ ',' ] [ <a_list> ]
<edge_stmt> ::= ('node_id' | 'subgraph') <edgeRHS> [ <attr_list> ]
<edgeRHS> ::= <edgeop> (<node_id> | <subgraph>) [ <edgeRHS> ]
<node_stmt> ::= <node_id> [ <attr_list> ]
<node_id> ::= ID [ <port> ]
<port> ::= ':' ID [ ':' <compass_pt> ] |  ':' <compass_pt>
<subgraph> ::= [ <subgraph> [ ID ] ] '{' <stmt_list> '}'
<compass_pt> ::= ('n' | 'ne' | 'e' | 'se' | 's' | 'sw' | 'w' | 'nw')