GraphViz - Bagaimana menghubungkan subgraph?

166

Dalam DOTbahasa untuk GraphViz, saya mencoba mewakili diagram ketergantungan. Saya harus dapat memiliki simpul di dalam wadah dan untuk dapat membuat simpul dan / atau wadah tergantung pada simpul dan / atau wadah lain.

Saya menggunakan subgraphuntuk mewakili wadah saya. Menghubungkan node berfungsi dengan baik, tapi saya tidak tahu bagaimana menghubungkan subgraph.

Dengan adanya program di bawah ini, saya harus dapat terhubung cluster_1dan cluster_2dengan panah, tetapi apa pun yang saya coba buat membuat simpul baru alih-alih menghubungkan kluster:

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";
}

masukkan deskripsi gambar di sini

Winston Smith
sumber
2
Saya mengalami masalah yang sama, namun mereka memiliki contoh alami di mana subgraph bertindak seperti node, graphviz.org/content/fdpclust .
nlucaroni
1
@ nlucaroni saya ingin tahu apakah masalah ini terpecahkan. contoh ini memberi saya grafik yang salah: tepi menghubungkan pusat subgraph. tidak tahukah kamu bagaimana membuatnya bekerja seperti pada contoh?
k102
1
@ k102, saya tahu. Periksa kembali halaman itu; katanya Anda harus menggunakan fdp. Contoh yang ditautkan, dan yang di atas keduanya berfungsi (baris terakhir dalam contoh di sini perlu menggunakan nama subgraph bukan label dan mungkin lebih baik untuk memasukkan panjang garis untuk grafik); ini sedikit ketat seperti).
nlucaroni
1
@nlucaroni Menggunakan fdpv2.28.0 dan menyalin / menempelkan sumber dari contoh, garis-garis terhubung ke tengah subgraph, bukan ke tepi. Jika Anda membuka .dot di OmniGraffle mereka terhubung dengan benar, sementara neatodan dotkeduanya membuat node berlebihan untuk cluster.
Phrogz

Jawaban:

190

Manual pengguna DOT memberikan contoh berikut grafik dengan kluster dengan tepi di antara kluster:

PENTING: compound=truePernyataan awal diperlukan.

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;
}

... dan tepi antara node dan cluster:

masukkan deskripsi gambar di sini

Tanda Kinerja Tinggi
sumber
14
Terima kasih - itu berhasil, tapi rasanya seperti retasan jelek. Saya berharap saya tidak memiliki skenario di mana saya memiliki wadah tanpa node.
Winston Smith
5
Jika ada yang tertarik, ini dapat menyebabkan masalah penentuan posisi jika Anda memiliki tautan berlabel (tepian). Sementara kepala atau ekor tepi mungkin disembunyikan di bawah sebuah cluster, label masih diposisikan di titik tengah, yang berarti beberapa label tepi tampaknya mengambang di atas sebuah cluster alih-alih diposisikan oleh tepi itu sendiri.
Winston Smith
58
@ WinstonSmith: Pertanyaan lama, tapi saya punya masalah yang sama dan menyelesaikannya dengan simpul dummy per cluster, yang dapat dihubungkan dengan bahkan jika cluster kosong sebaliknya. DUMMY_0 [shape=point style=invis]
DevSolar
2
Saya menemukan tepi antar-kluster saya akan diciutkan menjadi hanya kepala panah, ketika menggunakan cluster yang hanya terhubung secara vertikal. Saya memperbaikinya dengan minlen = 1 di tepinya. c -> g [ltail = cluster0, lhead = cluster1, minlen = 1];
Freenerd
3
Inilah tautan ke manual dengan contoh: graphviz.org/Documentation/dotguide.pdf (halaman 30).
Kirill Bulygin
90

Untuk kemudahan referensi solusi yang dijelaskan dalam jawaban HighPerformanceMark, diterapkan langsung ke pertanyaan awal, terlihat seperti ini:

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];
}

The compound=truedalam graphdeklarasi sangat penting. Itu menghasilkan output:

grafik dengan cluster yang terhubung

Perhatikan bahwa saya mengubah tepi ke node referensi di dalam kluster, menambahkan atribut ltail dan lhead ke setiap tepi, menentukan nama cluster, dan menambahkan atribut tingkat-grafik 'compound = true'.

Mengenai kekhawatiran bahwa seseorang mungkin ingin menghubungkan sebuah cluster tanpa node di dalamnya, solusi saya adalah untuk selalu menambahkan node ke setiap cluster, diterjemahkan dengan style = plaintext. Gunakan simpul ini untuk memberi label pada kluster (alih-alih atribut "label" bawaan kluster, yang harus ditetapkan ke string kosong (dengan Python, label='""'). Ini berarti saya tidak lagi menambahkan tepi yang menghubungkan kluster secara langsung, tetapi bekerja dalam situasi khusus saya.

Jonathan Hartley
sumber
24
Catatan: 'graph [fontsize = 10 fontname = "Verdana" compound = true];' sangat penting - jika Anda melewatkan tautan ke ltail / lhead tidak berfungsi.
s.Daniel
1
@ Jonathan Hartley, Sesuai paragraf terakhir Anda, apakah ada cara untuk memusatkan simpul itu tepat di tengah-tengah cluster?
Pacerier
juga nama gugus tidak boleh dimulai dengan huruf kapital
JCLL
7
@ s.Daniel Hanya senyawa = benar; yang diperlukan
Dr. Max Völkel
Alih-alih mengatur ulang lhead dan ltail ketika menautkan "Item 1" -> "Item 3", bagaimana cara menautkan cluster_0 dan cluster_1 dengan kode yang berarti? Saya meam, cluster_0 -> cluster_1hadir sebagai output Anda. Karena mungkin ada banyak item di cluster_0 tautan ke banyak item lain di cluster_1 (banyak ke banyak atau satu ke banyak). Akan bagus untuk hanya menghubungkan dua.
Mithril
11

Pastikan Anda menggunakan fdptata letak untuk file tersebut. Saya tidak berpikir neatomendukung cluster.

mihajlv
sumber
2
Saya juga telah berpengalaman menemukan bahwa neatomesin tidak mendukung cluster .. Saya tidak yakin apakah ini bug atau tidak ..
Ross Rogers