blob: 13f110b62b026189cff3f474ad6675f424f56adf [file] [log] [blame]
You Wangdb927a52016-02-26 11:03:28 -08001"""
2Graph algorithm implementations for CHOTestMonkey
3Author: you@onlab.us
4"""
5class GraphHelper:
6 """
7 This class implements graph algorithms for CHOTestMonkey.
8 It reads main.devices and main.links as vertices and edges.
9 Currently it offers functions for finding (non-)cut-edges and vertices,
10 which is realized based on chain-decomposition algorithm
11 """
12 def __init__( self ):
13 # Depth-first index of each node
14 self.DFI = []
15 # Parent vertex and egde of each node in depth-first search tree
16 self.parentDeviceInDFS = []
17 self.parentLinkInDFS = []
18 # Data structures for chain-decomposition algorithm
19 self.backEdges = {}
20 self.chains = []
21 self.currentDFI = 0
22 self.upDevices = []
23 for device in main.devices:
24 if device.isUp():
25 self.upDevices.append( device )
26 for i in range( len( main.devices ) ):
27 self.DFI.append( -1 )
28 self.parentDeviceInDFS.append( None )
29 self.parentLinkInDFS.append( None )
30
31 def genDFIandBackEdge( self, device ):
32 """
33 This function runs a depth-first search and get DFI of each node
34 as well as collect the back edges
35 """
36 self.DFI[ device.index ] = self.currentDFI
37 self.currentDFI += 1
38 for link in device.outgoingLinks:
39 if not link.isUp():
40 continue
41 backwardLink = link.backwardLink
42 neighbor = link.deviceB
43 if neighbor == self.parentDeviceInDFS[ device.index ]:
44 continue
45 elif self.DFI[ neighbor.index ] == -1:
46 self.parentDeviceInDFS[ neighbor.index ] = device
47 self.parentLinkInDFS[ neighbor.index ] = backwardLink
48 self.genDFIandBackEdge( neighbor )
49 else:
50 key = self.DFI[ neighbor.index ]
51 if key in self.backEdges.keys():
52 if not link in self.backEdges[ key ] and\
53 not backwardLink in self.backEdges[ key ]:
54 self.backEdges[ key ].append( backwardLink )
55 else:
56 tempKey = self.DFI[ device.index ]
57 if tempKey in self.backEdges.keys():
58 if not link in self.backEdges[ tempKey ] and\
59 not backwardLink in self.backEdges[ tempKey ]:
60 self.backEdges[ key ] = [ backwardLink ]
61 else:
62 self.backEdges[ key ] = [ backwardLink ]
63
64 def findChains( self ):
65 """
66 This function finds all the 'chains' for chain-decomposition algorithm
67 """
68 keyList = self.backEdges.keys()
69 keyList.sort()
70 deviceIsVisited = []
71 for i in range( len( main.devices ) ):
72 deviceIsVisited.append( 0 )
73 for key in keyList:
74 backEdgeList = self.backEdges[ key ]
75 for link in backEdgeList:
76 chain = []
77 currentLink = link
78 sourceDevice = link.deviceA
79 while True:
80 currentDevice = currentLink.deviceA
81 nextDevice = currentLink.deviceB
82 deviceIsVisited[ currentDevice.index ] = 1
83 chain.append( currentLink )
84 if nextDevice == sourceDevice or deviceIsVisited[ nextDevice.index ] == 1:
85 break
86 currentLink = self.parentLinkInDFS[ nextDevice.index ]
87 self.chains.append( chain )
88
89 def getNonCutEdges( self ):
90 """
91 This function returns all non-cut-edges of a graph
92 """
93 assert len( self.upDevices ) != 0
94 self.genDFIandBackEdge( self.upDevices[ 0 ] )
95 self.findChains()
96 nonCutEdges = []
97 for chain in self.chains:
98 for link in chain:
99 nonCutEdges.append( link )
100 return nonCutEdges
101
102 def getNonCutVertices( self ):
103 """
104 This function returns all non-cut-vertices of a graph
105 """
106 nonCutEdges = self.getNonCutEdges()
107 nonCutVertices = []
108 for device in self.upDevices:
109 deviceIsNonCut = True
110 for link in device.outgoingLinks:
111 if link.isUp() and not ( link in nonCutEdges or link.backwardLink in nonCutEdges ):
112 deviceIsNonCut = False
113 break
114 if deviceIsNonCut:
115 nonCutVertices.append( device )
116 return nonCutVertices
117
118 def printDFI( self ):
119 print self.DFI
120
121 def printParentInDFS( self ):
122 print self.parentInDFS
123
124 def printBackEdges( self ):
125 print self.backEdges
126
127 def printChains( self ):
128 chainIndex = 0
129 for chain in self.chains:
130 print chainIndex
131 for link in chain:
132 print link
133 chainIndex += 1