问题
As a personal easter project I'm trying to implement some model-based testing at work. I've got a graph implemented in python and I need to traverse all edges / do all transitions of the graph, at least once. Traversing an edge twice or more does not matter, but I need to start and end in the same node and get a sequence of edges/transitions back.
Simpler algorithm > shortest sequence.
I've looked around and found a lot of algorithms, but I couldn't find one / a combination that works for me. It would be great if someone could point me in the right direction or give me some tips on how to do this.
My graph implementation looks like this:
graph = {
A : {'IDLE': 't8', 'B': 't2', 'C': 't4'},
B : {'A': 't3', 'C': 't4', 'IDLE': 't6'},
C : {'A': 't5', 'IDLE': 't7', 'B': 't2'},
IDLE : {'A': 't1'}
}
回答1:
Approach 1
You can change your graph G into a new graph G' where each edge in G becomes a node in G'. Make an edge from t1 to t2 in G' if "A -> t1 -> B -> t2 -> C" is possible in G for some A,B and C.
Then you need to find a path cover in G'.
Approach 2
- Your position P initially is some node P0 (e.g. idle).
- For each edge T (from A to B), find any route from P to A, then use T to go to B. Update P to be B.
- Finally find any route from P back to P0.
回答2:
This problem is not the same as the Traveling Salesman Problem. Instead it's called a Chinese Postman Problem. The biggest difference is that the TSP wants to visit all nodes (cities) where the CPP wants to visit all edges (streets).
A perfect tutorial for exactly this can be found here: https://www.datacamp.com/community/tutorials/networkx-python-graph-tutorial
回答3:
I am not sure if you want an algorithm or you want to know how to get your job done. If its the later, you can use networkx.
Once you downloaded and installed networkx you can try the following
>>> import networkx as nx
>>> DG=nx.DiGraph()
>>> def CycleFrom(G,node):
return sorted((c for c in nx.simple_cycles(DG) if node in c), key=len)[0]
>>> for (stnode, edges) in graph.items():
for (ennode,edge) in edges.items():
DG.add_edge(stnode,ennode,name=edge)
>>> for node in DG.nodes():
print "Cycles from {0} is {1}".format(node,CycleFrom(DG,node))
Cycles from A is ['A', 'IDLE', 'A']
Cycles from IDLE is ['A', 'IDLE', 'A']
Cycles from B is ['A', 'B', 'A']
Cycles from C is ['A', 'C', 'A']
>>>
回答4:
for each P1, P2 points in your graph find all the R roads, where R looks like this:
R = (P1, Pf1, ..., Pfn, P2)
for each R1, R2 roads from P1 to P2, if Intersection(R1, R2) has more than 0 points (except P1 and P2, of course) determine which is shorter. If the length of R1 is smaller than the length of R2 then forget R2, otherwise forget R1.
In an iteration you will find the shortest totally separate roads from P1 to P2. If you want to traverse a road, where you have the points (P1, ..., Pk) If we choose Pi, where 1<= i <= k, we know that the first point will be Pi and the last point will also be Pi.
Suppose that the order doesn't matter. Whenever you traverse a point, mark it as traversed. If a point is marked as traversed, you won't want to go again to the given point, but you won't mind traversing the point again if necessary. So, the planned road will be: Pf1, ..., Pfk, Pf1.
for each Pfj, Pfm:
We are in Pfj in this moment. If Pfm is traversed then we don't want to go to Pfm again, so we go to the next iteration
If Pfm is not traversed, we have R1, ..., Rq roads from Pfj to Pfm. Choose the road with the maximum number of untraversed points and minimum number of already traversed roads. You need to weight the importance of an untraversed Point in the road and a traversed Point by a clever idea (hopefully your weight will minimize the total length of your road from Pf1 to Pf1).
Note that Pf1 should not be marked as traversed, because you want to arrive there at the end of your algorithm.
来源:https://stackoverflow.com/questions/10043060/algorithm-to-traverse-all-edges-in-a-graph