def create_scenario(): ''' Create something as: v4 v0 \ / | \ v1 | \ / | v5 / \ / v2 | v3 ''' E = [] data_to_vertex = {} vertices = [] for i in range(6): data = 'v%s' % (i, ) v = Vertex(data) data_to_vertex[data] = v v.view = VertexViewer(100, 50) vertices.append(v) edge = Edge(vertices[0], vertices[1]) edge.view = EdgeViewer() E.append(edge) edge = Edge(vertices[0], vertices[2]) edge.view = EdgeViewer() E.append(edge) edge = Edge(vertices[1], vertices[5]) edge.view = EdgeViewer() E.append(edge) edge = Edge(vertices[2], vertices[3]) edge.view = EdgeViewer() E.append(edge) edge = Edge(vertices[4], vertices[5]) edge.view = EdgeViewer() E.append(edge) edge = Edge(vertices[5], vertices[2]) edge.view = EdgeViewer() E.append(edge) G = Graph(vertices, E) assert len(G.C) == 1 gr = G.C[0] # not needed anymore... #r = filter(lambda x: len(x.e_in()) == 0, gr.sV) #if len(r) == 0: # r = [gr.sV[0]] return gr, data_to_vertex
def initView(self): cfg = self.func.cfg vertexs = {} done = set() for block in cfg.blocks: if block in done: continue done.add(block) startLockey = block.loc_key endLockey = block.loc_key blocks = [block] while (block.lines[-1].name == 'CALL') and (len(cfg.predecessors(block.get_next())) == 1): nextLockey = block.get_next() if block.loc_key in cfg.successors(nextLockey): break block = cfg.loc_key_to_block(nextLockey) blocks.append(block) endLockey = block.loc_key done.add(block) vertex = Vertex(startLockey) vertexs[startLockey] = vertex vertex.view = AsmBlockView(startLockey, endLockey, blocks, self.func) edges = [] for src in vertexs.values(): successLocKeys = cfg.successors(src.view.endLockey) for key in successLocKeys: vSrc = vertexs[src.view.lockey] vDst = vertexs[key] edge = Edge(vSrc, vDst) edge.view = BasicEdge(vDst) edges.append(edge) vSrc.view.outBlocks.append(vDst.view) vDst.view.inBlocks.append(vSrc.view) self.graph = Graph(vertexs.values(), edges) sugLayout = SugiyamaLayout(self.graph.C[0]) sugLayout.route_edge = route_with_lines sugLayout.init_all() sugLayout.draw() for v in vertexs.values(): self.addBlock(v.view, v.view.xy[0] - (v.view.w / 2), v.view.xy[1] - (v.view.h / 2)) v.view.gotoAddress.connect(self.selectAddress) for e in edges: srcView = e.v[0].view srcBlock = e.v[0].data dstBlock = e.v[1].data if len(srcView.outBlocks) == 1: color = Qt.darkBlue elif dstBlock == cfg.successors(srcBlock)[0]: color = Qt.darkRed else: color = Qt.darkGreen edge_view = e.view edge_view.color = color self.scene.addItem(edge_view)
def initView(self): vertexs = {} for lockey, block in self.ircfg.blocks.items(): vertexs[lockey] = Vertex(block) vertexs[lockey].view = IRBlockView(lockey, block, False) edges = [] for src in vertexs: successLocKeys = self.ircfg.successors(src) for key in successLocKeys: if key in vertexs: vSrc = vertexs[src] vDst = vertexs[key] edge = Edge(vSrc, vDst) edge.view = BasicEdge(vDst) edges.append(edge) vSrc.view.outBlocks.append(vDst.view) vDst.view.inBlocks.append(vSrc.view) self.graph = Graph(vertexs.values(), edges) sugLayout = SugiyamaLayout(self.graph.C[0]) sugLayout.route_edge = route_with_lines sugLayout.init_all() sugLayout.draw() for v in vertexs.values(): self.addBlock(v.view, v.view.xy[0] - (v.view.w / 2), v.view.xy[1] - (v.view.h / 2)) for e in edges: srcView = e.v[0].view srcBlock = e.v[0].data dstBlock = e.v[1].data if len(srcView.outBlocks) == 1: color = Qt.darkBlue elif dstBlock.loc_key == self.ircfg.successors(srcBlock.loc_key)[0]: color = Qt.darkRed else: color = Qt.darkGreen edge_view = e.view edge_view.color = color self.scene.addItem(edge_view)
def _layout_graph_sugiyama(graph): """ Arrange the graph automatically using grandalf package """ from grandalf.graphs import Graph, Vertex, Edge from grandalf.layouts import SugiyamaLayout # Build the viez class for grandalf vertices class View(object): def __init__(self, w, h): self.w = w self.h = h self.xy = (0, 0) # Build the grandalf graph ggraph = Graph() # Vertices vertices_by_id = {} all_nodes_by_id = {n.id: n for n in graph.all_nodes()} # Get average width for distance between nodes avg_width = 0 avg_height = 0 for n in all_nodes_by_id.values(): v = Vertex(n.id) if NODE_LAYOUT_DIRECTION == NODE_LAYOUT_HORIZONTAL: view = View(n.view.height, n.view.width) else: view = View(n.view.width, n.view.height) avg_width += n.view.width avg_height += n.view.height v.view = view vertices_by_id[n.id] = v avg_width /= len(all_nodes_by_id) avg_height /= len(all_nodes_by_id) for v in vertices_by_id.values(): ggraph.add_vertex(v) # Edges inverted_edges = [] looked_up_nodes = set([]) for n in all_nodes_by_id.values(): for cns in n.connected_output_nodes().values(): for cn in cns: e = Edge(vertices_by_id[n.id], vertices_by_id[cn.id]) if cn.id in looked_up_nodes: inverted_edges.append(e) else: looked_up_nodes.add(cn.id) ggraph.add_edge(e) # Build the layout sug = SugiyamaLayout(ggraph.C[0]) sug.yspace = avg_width if NODE_LAYOUT_DIRECTION == NODE_LAYOUT_HORIZONTAL else avg_height sug.xspace = avg_height if NODE_LAYOUT_DIRECTION == NODE_LAYOUT_HORIZONTAL else avg_width print(inverted_edges) # sug.init_all(inverted_edges=inverted_edges or None) sug.init_all() sug.draw(10) for v in ggraph.C[0].sV: node = all_nodes_by_id[v.data] if NODE_LAYOUT_DIRECTION == NODE_LAYOUT_HORIZONTAL: node.set_pos(*reversed(v.view.xy)) else: node.set_pos(*v.view.xy)
def dotnode(seq): _start = Vertex(seq) _start.view = Node(_start) return _start
def updateLayeredLayoutWithComp(self): class Vtx(object): def __init__(self, name, idx, radius = 1, height = 1): self.inNodes = set() self.outNodes = set() self.name = name self.idx = idx self.comp = None self.compIdx = None self.pos = None self.radius = radius self.fontHeight = height self.height = max(radius, height) self.firstKey = 0.0 self.secondKey = 0.0 self.thirdKey = 0.0 def getLayoutHeight(self): return self.height + self.radius def setLayoutPos(self,x,y): self.pos = (x, y-0.5*(self.height - self.radius)) def getMinX(self): return self.pos[0] - self.radius def getMaxX(self): return self.pos[0] + self.radius def getMinY(self): return self.pos[1] - self.radius def getMaxY(self): return self.pos[1] + self.height def getPos(self): return self.pos if len(self.scene.itemDict) == 0: return vtxName2Id = {} vtxList = [] edgeList = [] for name, item in self.scene.itemDict.items(): ithVtx = len(vtxList) v = Vtx(name, ithVtx, item.getRadius(), item.getHeight()) v.dispName = item.name vtxList.append(v) vtxName2Id[name] = ithVtx for edgeKey, edge in self.scene.edgeDict.items(): v1 = vtxName2Id[edgeKey[0]] v2 = vtxName2Id[edgeKey[1]] vtxList[v1].outNodes.add(v2) vtxList[v2].inNodes.add(v1) edgeList.append((v1,v2)) # 构造连通分量 remainSet = set([i for i in range(len(vtxList))]) compList = [] # [[idx1,idx2,...],[...]] while len(remainSet) > 0: # 找出剩余一个顶点并加入队列 ids = [list(remainSet)[0]] ithComp = len(compList) vtxList[ids[0]].comp = ithComp compMap = [] # 遍历一个连通分量 while len(ids) > 0: newIds = [] for id in ids: # 把一个顶点加入连通分量 vtx = vtxList[id] vtx.compIdx = len(compMap) compMap.append(id) # 把周围未遍历顶点加入队列 for inId in vtx.inNodes: inVtx = vtxList[inId] if inVtx.comp is None: inVtx.comp = ithComp newIds.append(inId) for outId in vtx.outNodes: outVtx = vtxList[outId] if outVtx.comp is None: outVtx.comp = ithComp newIds.append(outId) remainSet.discard(id) ids = newIds # 增加一个连通分量 compList.append(compMap) from grandalf.graphs import Vertex, Edge, Graph class VtxView(object): def __init__(self, w, h): self.w = w self.h = h # 构造每个连通分量的图结构 offset = (0,0) bboxMin = [1e6,1e6] bboxMax = [-1e6,-1e6] self.scene.boxTest = [] for ithComp, compMap in enumerate(compList): minPnt = [1e6,1e6] maxPnt = [-1e6,-1e6] # 构造图数据并布局 V = [] for oldId in compMap: w = vtxList[oldId].getLayoutHeight() vtx = Vertex(oldId) height = 200 vtx.view = VtxView(w, height) V.append(vtx) E = [] for edgeKey in edgeList: if vtxList[edgeKey[0]].comp == ithComp: E.append(Edge(V[vtxList[edgeKey[0]].compIdx], V[vtxList[edgeKey[1]].compIdx])) g = Graph(V,E) from grandalf.layouts import SugiyamaLayout packSpace = 4 sug = SugiyamaLayout(g.C[0]) sug.xspace = packSpace sug.yspace = packSpace #sug.order_iter = 32 sug.dirvh = 3 sug.init_all() sug.draw(10) # 统计包围盒 for v in g.C[0].sV: oldV = vtxList[v.data] x= v.view.xy[1] y= v.view.xy[0] oldV.setLayoutPos(x,y) minPnt[0] = min(minPnt[0],oldV.getMinX()) minPnt[1] = min(minPnt[1],oldV.getMinY()) maxPnt[0] = max(maxPnt[0],oldV.getMaxX()) maxPnt[1] = max(maxPnt[1],oldV.getMaxY()) for v in g.C[0].sV: oldV = vtxList[v.data] posInComp = oldV.getPos() newPos = (posInComp[0], posInComp[1]-minPnt[1]+offset[1]) self.scene.itemDict[oldV.name].setTargetPos(QtCore.QPointF(newPos[0], newPos[1])) bboxMin[0] = min(bboxMin[0], newPos[0]) bboxMin[1] = min(bboxMin[1], newPos[1]) bboxMax[0] = max(bboxMax[0], newPos[0]) bboxMax[1] = max(bboxMax[1], newPos[1]) offset = (offset[0], offset[1]+maxPnt[1]-minPnt[1]+packSpace) # 设置四个角的item cornerList = self.scene.cornerItem mar = 2000 cornerList[0].setPos(bboxMin[0]-mar, bboxMin[1]-mar) cornerList[1].setPos(bboxMin[0]-mar, bboxMax[1]+mar) cornerList[2].setPos(bboxMax[0]+mar, bboxMin[1]-mar) cornerList[3].setPos(bboxMax[0]+mar, bboxMax[1]+mar) # 更新标志数据 self.itemSet = set(self.scene.itemDict.keys()) self.edgeNum = len(self.scene.edgeDict)