【问题标题】:How do we create GV files with non-overlapping subgraphs from a GV file?我们如何从 GV 文件创建具有非重叠子图的 GV 文件?
【发布时间】:2023-01-20 04:23:45
【问题描述】:

图形

我有一个包含 3 个子图的 GV 文件:

  1. cluster_1
  2. cluster_2
  3. cluster_3

    Final_Graph.gv的来源:

    digraph Final_Graph {
        graph [center=true rankdir=LR ratio=compress size="15,10"]
        a
        b
        c
        d
        a -> b [label = 1]
        a -> c [label = 2]
        a -> d [label = 3]
        b -> d [label = 4]
        c -> d [label = 5]
    
        subgraph cluster_1{
            color=lightgrey style=filled
            label="A"
            a
            b
        }
        
        subgraph cluster_2{
            color=lightgrey style=filled
            label="B"
            a
            b
        }
        
        subgraph cluster_3{
            color=lightgrey style=filled
            label="C"
            c
            d
        }
    }
    

    渲染:

    通缉

    我希望创建子图不重叠的其他 GV 文件(即没有相似节点的子图,因此对于这种情况,第一个文件可以有簇 1 和 3,第二个文件可以有簇 2 和 3)。

    代码

    我在 Python 中使用这个函数来完成这个任务:

    import networkx as nx
    import itertools
    def draw_graph_combinations():
    
    # Load the original graph
      G = nx.drawing.nx_agraph.read_dot("Final_Graph.gv")
    
    # Create an empty dictionary to store the subgraphs
      subgraphs = {}
      
    
    # Iterate over the edges of the graph
      for u, v, data in G.edges(data=True):
        label = data.get("label")
        if label not in subgraphs:
            subgraphs[label] = nx.DiGraph()
       
    
      for node in G.nodes:
        # Add the node to each subgraph
        for label, subgraph in subgraphs.items():
            subgraph.add_node(node)
            
      for label, subgraph in subgraphs.items():
        for edge in G.edges:
            subgraph.add_edge(edge[0], edge[1])
    
     # Get all combinations of subgraphs
      combinations = itertools.combinations(subgraphs.items(), len(subgraphs))
    
    # Iterate over the combinations
      for i, subgraph_items in enumerate(combinations):
        combined_subgraph = nx.DiGraph()
        for label, subgraph in subgraph_items:
            combined_subgraph = nx.compose(combined_subgraph, subgraph)
        nx.drawing.nx_agraph.write_dot(combined_subgraph, f"combined_subgraph_{i}.gv")
    

    问题

    但是,当我在 Python 中运行此函数时,打印出的文件仅包含原始文件的节点和边缘,而没有显示子图。

    问题

    Python 中有没有什么方法可以将这个 GV 文件分成子图不重叠的其他文件?

【问题讨论】:

  • 请注意,虽然您的文件是合法语法,但点、neato 或 fdp 不允许您的意图。集群不能共享节点。然而,解析器构建的底层数据结构确实如此!所以,你的目标可能可以用 Python 完成,但不能由我完成(不要做 Python)。我大概可以写进去gvpr(graphviz.org/pdf/gvpr.1.pdf),如果有帮助的话。

标签: python graphviz


【解决方案1】:

您可以使用包 PyGraphviz 来读取、修改、写入和渲染 Graphviz 图形。

PyGraphviz

先决条件:必须在您的系统上安装 graphviz 二进制文件。 使用 pip 安装 Python 包:

pip install pygraphviz

Install — PyGraphviz 1.10 documentation

去除子图

注意:除了从源字符串加载之外,您还可以将文件句柄或文件名作为参数传递给构造函数AGraph(filename='Final_Graph.gv')AGraph(Final_Graph.gv)

import pygraphviz as pgv

s = '''digraph Final_Graph {
    graph [center=true rankdir=LR ratio=compress size="15,10"]
    a
    b
    c
    d
    a -> b [label = 1]
    a -> c [label = 2]
    a -> d [label = 3]
    b -> d [label = 4]
    c -> d [label = 5]
    subgraph cluster_1{
        color=lightgrey style=filled
        label="A"
        a
        b
    }
    
    subgraph cluster_2{
        color=lightgrey style=filled
        label="B"
        a
        b
    }
    
    subgraph cluster_3{
        color=lightgrey style=filled
        label="C"
        c
        d
    }
}'''

G = pgv.AGraph(string=s)  # loading a graph from source string
# print some information of the parsed graph 
print(f"Graph '{G.get_name()}' has:")
print(f"* {len(G.nodes())} nodes")
print(f"* {len(G.edges())} edges")
print(f"* {len(G.subgraphs())} subgraphs")

# the first file could have clusters 1 and 3
G_copy1 = G.copy()  # Return a copy of the graph.
G_copy1.remove_subgraph('cluster_2')  # Remove subgraph with given name: cluster 2
print("## Copy 1: without cluster 2
", G_copy1.string())  # Return a string (unicode) representation of graph in dot format.
G_copy1.write('without_cluster_2.dot')  # Write graph in dot format to file on path.

# the second file could have clusters 2 and 3
G_copy2 = G.copy()  # Return a copy of the graph.
G_copy2.remove_subgraph('cluster_1')  # Remove subgraph with given name: cluster 1
print("## Copy 2: without cluster 1
", G_copy1.string())  # Return a string (unicode) representation of graph in dot format.
G_copy2.write('without_cluster_1.dot')  # Write graph in dot format to file on path.

输出:2 个文件,每个文件有 28 行(384 字节)

  • without_cluster_1.dot
  • without_cluster_2.dot

并在控制台上进行以下操作:

Graph 'Final_Graph' has:
* 4 nodes
* 5 edges
* 3 subgraphs
## Copy 1: without cluster 2
 digraph Final_Graph {
    graph [center=true,
        rankdir=LR,
        ratio=compress,
        size="15,10"
    ];
    subgraph cluster_1 {
        graph [color=lightgrey,
            label=A,
            style=filled
        ];
        a;
        b;
    }
    subgraph cluster_3 {
        graph [color=lightgrey,
            label=C,
            style=filled
        ];
        c;
        d;
    }
    a -> b   [label=1];
    a -> c   [label=2];
    a -> d   [label=3];
    b -> d   [label=4];
    c -> d   [label=5];
}

## Copy 2: without cluster 1
 digraph Final_Graph {
    graph [center=true,
        rankdir=LR,
        ratio=compress,
        size="15,10"
    ];
    subgraph cluster_1 {
        graph [color=lightgrey,
            label=A,
            style=filled
        ];
        a;
        b;
    }
    subgraph cluster_3 {
        graph [color=lightgrey,
            label=C,
            style=filled
        ];
        c;
        d;
    }
    a -> b   [label=1];
    a -> c   [label=2];
    a -> d   [label=3];
    b -> d   [label=4];
    c -> d   [label=5];
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-09-24
    • 2012-05-30
    • 1970-01-01
    • 2012-01-29
    • 1970-01-01
    • 2022-01-24
    • 1970-01-01
    • 2019-05-21
    相关资源
    最近更新 更多