'Finding list of edges in graphviz in Python
Is there any way to get list of edges in graphviz in python. In my program I wanted to check whether edge already exist between nodes before adding edge in the directed graph. I couldn't find any function like get_edge() or has_connected() function in grahviz in python. Is there any other way of doing the above mentioned task? Any help would be appreciated.
Solution 1:[1]
if your goal is to avoid duplicates edges, use Digraph(strict=True) or Graph(strict=True)
Solution 2:[2]
I just ran into this problem. I don't see anything in the source code that would indicate a convenient way of checking if an edge is in a graph.
If you're dealing with a very simple graph then maybe this will help.
def has_edge(graph, v1, v2):
tail_name = graph._quote_edge(v1)
head_name = graph._quote_edge(v2)
return (graph._edge % (tail_name, head_name, '')) in graph.body
I adapted this from the 'edge()' method in graphviz/dot.py. It doesn't handle any attributes.
From what I can see, the graph.body is a list of strings representing nodes and edges.
Solution 3:[3]
Here's get_edges to get a list of edges for a given graphviz digraph (or graph).
The graph can be expressed as a BaseGraph or Source object, or simply the source string. But default it will return pairs of node ids (strings), but you can tell get_edges to give you anything (including the pydot.Edge object itself, containing all its properties.
from typing import Tuple, List, Iterable
from pydot import Dot, graph_from_dot_data, Edge
from graphviz.graphs import BaseGraph
from graphviz import Source
def edge_to_node_ids(edge: Edge) -> Tuple[str, str]:
"""Returns the node id pair for the edge object"""
return (edge.get_source(), edge.get_destination())
def get_graph_dot_obj(graph_spec) -> List[Dot]:
"""Get a dot (graphs) object list from a variety of possible sources (postelizing inputs here)"""
_original_graph_spec = graph_spec
if isinstance(graph_spec, (BaseGraph, Source)):
# get the source (str) from a graph object
graph_spec = graph_spec.source
if isinstance(graph_spec, str):
# get a dot-graph from dot string data
graph_spec = graph_from_dot_data(graph_spec)
# make sure we have a list of Dot objects now
assert isinstance(graph_spec, list) and all(
isinstance(x, Dot) for x in graph_spec
), (
f"Couldn't get a proper dot object list from: {_original_graph_spec}. "
f"At this point, we should have a list of Dot objects, but was: {graph_spec}"
)
return graph_spec
def get_edges(graph_spec, postprocess_edges=edge_to_node_ids):
"""Get a list of edges for a given graph (or list of lists thereof).
If ``postprocess_edges`` is ``None`` the function will return ``pydot.Edge`` objects from
which you can extract any information you want.
By default though, it is set to extract the node pairs for the edges, and you can
replace with any function that takes ``pydot.Edge`` as an input.
"""
graphs = get_graph_dot_obj(graph_spec)
n_graphs = len(graphs)
if n_graphs > 1:
return [get_edges(graph, postprocess_edges) for graph in graphs]
elif n_graphs == 0:
raise ValueError(f"Your input had no graphs")
else:
graph = graphs[0]
edges = graph.get_edges()
if callable(postprocess_edges):
edges = list(map(postprocess_edges, edges))
return edges
Test:
digraph_dot_source = """
DIGRAPH{
rain -> traffic
rain -> wet
traffic, wet -> moody
}
"""
assert (
get_edges(digraph_dot_source)
== get_edges(Source(digraph_dot_source))
== [('rain', 'traffic'), ('rain', 'wet'), ('wet', 'moody')]
)
graph_dot_source = """
GRAPH{
rain -- traffic
rain -- wet
traffic, wet -- moody
}
"""
assert (
get_edges(graph_dot_source)
== get_edges(Source(graph_dot_source))
== [('rain', 'traffic'), ('rain', 'wet'), ('wet', 'moody')]
)
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | Alexander Ponomarenko |
| Solution 2 | alex |
| Solution 3 | thorwhalen |
