Reputation: 153
I would like to find an efficient way to check if a given "Walk" through a graph is valid.
Such a function should accept a Graph (nodes, edges) and a string of node names, and should output True if nodes can be visited in the given sequence according to the graph and false if not.
Preferably, I would use the NetworkX library, since I already use it to store and represent the graph.
Something resembling this:
""" G:
Q1 -> Q1
Q1 -> Q2
Q2 -> Q2
"""
accepts(G, ["Q1", "Q1", "Q2"])
>> True
accepts(G, ["Q2", "Q2", "Q2"])
>> True
accepts(G, ["Q2", "Q2", "Q1"])
>> False
accepts(G, ["Q1", "Q2", "Q1"])
>> False
accepts(G, ["Q1", "Q1", "Q2", "Q1"])
>> False
This would be used for a automata class. To basically check for membership of a string given a language represented by the graph.
Upvotes: 0
Views: 1534
Reputation: 6632
While @newbie's sentiment that "You only need to check if all the edges of the path are valid" is correct, the implementation he gives is far from efficient; graph.edges()
rebuilds a list of all the graph's edges from scratch for every edge in the path. Instead of (u, v) in g.edges()
you should always use g.has_edge(u, v)
, which is a constant-time operation. Although it seems you're working with DiGraph
at the moment, the latter method also has the added benefit of working for both Graph
and DiGraph
, while the earlier method only works for DiGraph
. (This is because a Graph
's edges()
method only returns the edges in one (random) direction, so checking for the edge in one direction only does not suffice; g.has_edge()
does the right thing here for both Graph
and DiGraph
)
Long story short, use:
def accepts(g, path):
return all([g.has_edge(path[i], path[i+1]) for i in range(len(path)-1)])
Or, a bit more concisely:
def accepts(g, path):
return all(map(g.has_edge, path, path[1:]))
Upvotes: 1
Reputation: 11929
You only need to check if all the edges of the path are valid.
def accepts(g, path):
return all([(path[i],path[i+1]) in g.edges() for i in range(len(path)-1)])
Example:
g=nx.DiGraph()
g.add_edge("Q1","Q1")
g.add_edge("Q1","Q2")
g.add_edge("Q2","Q2")
print(accepts(g, ["Q1", "Q1", "Q2"]))
print(accepts(g, ["Q2", "Q2", "Q2"]))
print(accepts(g, ["Q2", "Q2", "Q1"]))
print(accepts(g, ["Q1", "Q2", "Q1"]))
print(accepts(g, ["Q1", "Q1", "Q2", "Q1"]))
Upvotes: 2