GraphViz - Comment connecter des sous-graphes?

166

Dans le DOTlangage pour GraphViz, j'essaye de représenter un diagramme de dépendance. J'ai besoin de pouvoir avoir des nœuds à l'intérieur d'un conteneur et de pouvoir rendre les nœuds et / ou conteneurs dépendants d'autres nœuds et / ou conteneurs.

J'utilise subgraphpour représenter mes conteneurs. La liaison de nœuds fonctionne très bien, mais je ne peux pas comprendre comment connecter des sous-graphiques.

Compte tenu du programme ci-dessous, je dois être capable de me connecter cluster_1et cluster_2avec une flèche, mais tout ce que j'ai essayé crée de nouveaux nœuds au lieu de connecter les clusters:

digraph G {

    graph [fontsize=10 fontname="Verdana"];
    node [shape=record fontsize=10 fontname="Verdana"];

    subgraph cluster_0 {
        node [style=filled];
        "Item 1" "Item 2";
        label = "Container A";
        color=blue;
    }

    subgraph cluster_1 {
        node [style=filled];
        "Item 3" "Item 4";
        label = "Container B";
        color=blue;
    }

    subgraph cluster_2 {
        node [style=filled];
        "Item 5" "Item 6";
        label = "Container C";
        color=blue;
    }

    // Renders fine
    "Item 1" -> "Item 2";
    "Item 2" -> "Item 3";

    // Both of these create new nodes
    cluster_1 -> cluster_2;
    "Container A" -> "Container C";
}

entrez la description de l'image ici

Winston Smith
la source
2
J'ai le même problème, mais ils ont un exemple naturel où les sous-graphes agissent comme des nœuds, graphviz.org/content/fdpclust .
nlucaroni
1
@nlucaroni je me demande si ce problème est résolu. cet exemple me donne un mauvais graphe: les arêtes relient les centres du sous-graphe. ne savez-vous pas comment le faire fonctionner comme dans l'exemple?
k102
1
@ k102, je sais. Consultez à nouveau cette page; il dit que vous devez utiliser fdp. L'exemple lié et celui ci-dessus fonctionnent tous les deux (la dernière ligne de l'exemple ici doit utiliser les noms de sous-graphe et non l'étiquette et il peut être intéressant d'inclure des longueurs de ligne pour le graphe); c'est un peu serré tel quel).
nlucaroni
1
@nlucaroni En utilisant fdpv2.28.0 et en copiant / collant la source de l'exemple, les lignes se connectent au centre du sous-graphe, pas aux bords. Si vous ouvrez le .dot dans OmniGraffle, ils sont correctement connectés, tandis neatoque les dotdeux créent des nœuds superflus pour le cluster.
Phrogz

Réponses:

190

Le manuel de l'utilisateur du DOT donne l'exemple suivant d'un graphe avec des clusters avec des arêtes entre les clusters:

IMPORTANT: la compound=truedéclaration initiale est requise.

digraph G {
  compound=true;
  subgraph cluster0 {
    a -> b;
    a -> c;
    b -> d;
    c -> d;
  }
  subgraph cluster1 {
    e -> g;
    e -> f;
  }
  b -> f [lhead=cluster1];
  d -> e;
  c -> g [ltail=cluster0,lhead=cluster1];
  c -> e [ltail=cluster0];
  d -> h;
}

... et les arêtes entre les nœuds et les clusters:

entrez la description de l'image ici

Marque haute performance
la source
14
Merci - cela fonctionne, mais cela ressemble vraiment à un horrible hack. J'espère que je n'ai pas un scénario où j'ai un conteneur sans nœuds.
Winston Smith le
5
Au cas où quelqu'un serait intéressé, cela peut causer des problèmes de positionnement si vous avez des liens étiquetés (bords). Bien que la tête ou la queue du bord puisse être cachée sous un cluster, l'étiquette est toujours positionnée au milieu, ce qui signifie que certaines étiquettes de bord semblent flotter sur un cluster au lieu d'être positionnées par le bord lui-même.
Winston Smith
58
@WinstonSmith: Ancienne question, mais j'ai eu un problème similaire et je l'ai résolu avec un nœud factice invisible par cluster, qui peut être lié même si le cluster est vide sinon. DUMMY_0 [shape=point style=invis]
DevSolar
2
J'ai trouvé que mes bords inter-cluster étaient réduits à juste des têtes de flèches, lors de l'utilisation de clusters qui ne sont connectés que verticalement. J'ai corrigé cela avec minlen = 1 sur les bords. c -> g [ltail = cluster0, lhead = cluster1, minlen = 1];
Freenerd
3
Voici le lien vers le manuel avec l'exemple: graphviz.org/Documentation/dotguide.pdf (page 30).
Kirill Bulygin
90

Pour faciliter la référence, la solution décrite dans la réponse de HighPerformanceMark, appliquée directement à la question d'origine, ressemble à ceci:

digraph G {

    graph [fontsize=10 fontname="Verdana" compound=true];
    node [shape=record fontsize=10 fontname="Verdana"];

    subgraph cluster_0 {
        node [style=filled];
        "Item 1" "Item 2";
        label = "Container A";
        color=blue;
    }

    subgraph cluster_1 {
        node [style=filled];
        "Item 3" "Item 4";
        label = "Container B";
        color=blue;
    }

    subgraph cluster_2 {
        node [style=filled];
        "Item 5" "Item 6";
        label = "Container C";
        color=blue;
    }

    // Edges between nodes render fine
    "Item 1" -> "Item 2";
    "Item 2" -> "Item 3";

    // Edges that directly connect one cluster to another
    "Item 1" -> "Item 3" [ltail=cluster_0 lhead=cluster_1];
    "Item 1" -> "Item 5" [ltail=cluster_0 lhead=cluster_2];
}

Le contenu de compound=truela graphdéclaration est vital. Cela produit une sortie:

graphe avec clusters connectés

Notez que j'ai changé les arêtes en nœuds de référence dans le cluster, ajouté les attributs ltail et lhead à chaque arête, en spécifiant le nom du cluster, et ajouté l'attribut de niveau graphique «composé = vrai».

En ce qui concerne le souci que l'on puisse vouloir connecter un cluster sans nœuds à l'intérieur, ma solution a été de toujours ajouter un nœud à chaque cluster, rendu avec style = texte en clair. Utilisez ce nœud pour étiqueter le cluster (au lieu de l'attribut intégré "label" du cluster, qui doit être défini sur la chaîne vide (en Python, label='""'). Cela signifie que je n'ajoute plus d'arêtes qui connectent directement les clusters, mais cela fonctionne dans ma situation particulière.

Jonathan Hartley
la source
24
Remarque: 'graph [fontsize = 10 fontname = "Verdana" compound = true];' est essentiel - si vous manquez cette liaison à ltail / lhead ne fonctionne pas.
s.Daniel
1
@JonathanHartley, Selon votre dernier paragraphe, y a-t-il un moyen de centrer ce nœud en plein milieu du cluster?
Pacerier
aussi le nom du cluster ne doit pas commencer par une majuscule
JCLL
7
@ s.Daniel C'est juste le composé = vrai; qui est obligatoire
Dr.Max Völkel
Au lieu de réinitialiser lhead et ltail lors du lien «Item 1» -> «Item 3», comment lier cluster_0 et cluster_1 avec un code signifiant? Je meam, faites-le cluster_0 -> cluster_1présent au fur et à mesure de votre sortie. Parce qu'il peut y avoir de nombreux éléments dans cluster_0 lien vers d'autres éléments dans cluster_1 (plusieurs à plusieurs ou un à plusieurs). Ce serait bien d'en lier deux.
Mithril
11

Assurez-vous que vous utilisez la fdpmise en page pour le fichier. Je ne pense pas qu'il neatoprenne en charge les clusters.

mihajlv
la source
2
J'ai moi aussi constaté par expérience que le neatomoteur ne prend pas en charge les clusters .. Je ne sais pas si c'est un bogue ou pas ..
Ross Rogers