//Make a new edge that has this vertex as source and another vertex //as target. public Edge insertEdge(Vertex target) { if (adjList == null) adjList = new List<Edge>(size); Edge e = new Edge(this, target); adjList.Add(e); return e; }
//Reverse the edge. Used in the Max Bipartite Matching algorithm. public void reverseEdge() { if (source.removeEdge(this)) { target.insertEdge(this); Vertex tmp = source; source = target; target = tmp; } }
public Edge(Vertex source, Vertex target, int cost) { this.source = source; this.target = target; this.cost = cost; }
public Edge(Vertex source, Vertex target) { this.source = source; this.target = target; }
public int topDownUnorderedMaxCommonSubtreeIso(Node r1, Node r2) { //Cannot find a isomophism when the labels differ if (r1.getId() != r2.getId()) { return 0; } //The isomorphism has size 0 or 1 if one of the nodes are leaf nodes if (r1.isLeaf() || r2.isLeaf()) { return (r1.getId() == r2.getId()) ? 1 : 0; } int result; Node rp1 = r1.Parent; Node rp2 = r2.Parent; //Use LCS if r1 and r2 are root nodes in subtrees that represents method bodies. if ((rp1 != null && r1.getId() == SyntaxKind.Block && rp1.getId() == SyntaxKind.MethodDeclaration) && (rp2 != null && r2.getId() == SyntaxKind.Block && rp2.getId() == SyntaxKind.MethodDeclaration)) { int res = lcs(r1, r2); result = res; } else { int p = r1.Size; int q = r2.Size; //Each child of r1 has a corresponding vertex in the bipartite graph. A map from node to vertex. Dictionary<Node, Vertex> T1G = new Dictionary<Node, Vertex>(p); //Each child of r2 has a corresponding vertex in the bipartite graph. A map from node to vertex. Dictionary<Node, Vertex> T2G = new Dictionary<Node, Vertex>(q); //A map from vertex to node. Dictionary<Vertex, Node> GT = new Dictionary<Vertex, Node>(p + q); //There is maximum p*q edges in the bipartite graph. List<Edge> edges = new List<Edge>(p * q); //The vertices that represents the children of r1. List<Vertex> U = new List<Vertex>(p); foreach (Node v1 in r1.Children) { //q is the number of neighbors that v can have in the bipartite graph. Vertex v = new Vertex(q); U.Add(v); GT.Add(v, v1); T1G.Add(v1, v); } //The vertices that represents the children of r2. List<Vertex> W = new List<Vertex>(q); foreach (Node v2 in r2.Children) { //p is the number of neighbors that w can have in the bipartite graph. Vertex w = new Vertex(p); W.Add(w); GT.Add(w, v2); T2G.Add(v2, w); } //List of matched edges List<Edge> list = null; foreach (Node v1 in r1.Children) { foreach (Node v2 in r2.Children) { //Find max common subtree between v1 and v2 int res = topDownUnorderedMaxCommonSubtreeIso(v1, v2); //If max common subtree if (res != 0) { Vertex v = T1G[v1]; //Insert edge between v1 and v2 Edge e = v.insertEdge(T2G[v2]); //Set cost of edge to res (size of max common subtree) e.setCost(res); edges.Add(e); } } } //Find the children of r1 and r2 that are part of r1's and r2's max common subtree BipartiteMatching bm = new BipartiteMatching(); list = bm.maxWeightBipartiteMatching(U, W, edges, p, q); //Can map r1 to r2 int ress = 1; //Go through the mached edges in the bipartite graph foreach (Edge e in list) { List<Node> nodeList; //All edges goes from the children of r1 to the children of r2 Node v = GT[e.getSource()]; Node w = GT[e.getTarget()]; //v is already in B if (bMap.ContainsKey(v)) { nodeList = bMap[v]; } //First time we insert v. Create a list for the nodes that can be mapped to v. else { nodeList = new List<Node>(100); } //Insert w into the list nodeList.Add(w); bMap[v] = nodeList; //Add the size of the max common subtree between v and w to res. ress += e.getCost(); } result = ress; } return result; }
private void augment(Vertex a, Dictionary<Vertex, Boolean> free, Dictionary<Vertex, Edge> pred, Dictionary<Vertex, Int32> dist, Dictionary<Vertex, Int32> pot, FibHeap PQ) { //init //dist from a is zero dist[a] = 0; //a is the best vertex in A Vertex bestVertexInA = a; //potential of a int minA = pot[a]; int delta; //make a stack for nodes in A that are visited during the shortest path comp. Stack<Vertex> RA = new Stack<Vertex>(); RA.Push(a); //make a strack for the nodes in B that are visited during the shortest path comp. Stack<Vertex> RB = new Stack<Vertex>(); Vertex a1 = a; //relax all edges out of a1 List<Edge> adjEdges = a1.getAdjList(); if(adjEdges == null) return; foreach(Edge e in adjEdges){ Vertex b = e.getTarget(); //set the distance from a1 to all its neighbors. int db = dist[a1] + (pot[a1] + pot[b] - e.getCost()); dist[b] = db; pred[b] = e; //predecessor for b is e RB.Push(b); //push to stack PQ.insert(b, db); //insert in priority queue } //select from PQ the vertex b with min distance db while(true){ Vertex b; int db = 0; if(PQ.empty()){ b = null; } else { b = (Vertex) PQ.extractMin(); db = dist[b]; } //distinguish three cases if(b == null || db >= minA){ //We have a node v in A with potential zero. augment a path from a to v. delta = minA; //augmentation by path to best vertex in A augmentPathTo(bestVertexInA, pred); free[a] = false; free[bestVertexInA] = true; break; } else { //b is a free node, can be matched if(free[b]){ delta = db; //augmentation by path to b augmentPathTo(b, pred); free[a] = false; free[b] = false; break; } //Neither of the above. b is matched else { //continue shortest-path computation Edge e = b.getFirstAdjEdge(); a1 = e.getTarget(); //target of b pred[a1] = e; RA.Push(a1); dist[a1] = db; //if better than minA if((db + pot[a1]) < minA){ bestVertexInA = a1; minA = db + pot[a1]; } //relax all edges out of a1 adjEdges = a1.getAdjList(); foreach(Edge e1 in adjEdges){ b = e1.getTarget(); db = dist[a1] + (pot[a1] + pot[b] - e1.getCost()); if(pred[b] == null){ dist[b] = db; pred[b] = e1; RB.Push(b); PQ.insert(b, db); } //b is already in the priority queue else { if(db < dist[b]){ dist[b] = db; pred[b] = e1; PQ.decreaseKey(b, db); } } } } } } //augment: potential update and reinit //Update the potential and remove the nodes from the stack while(RA.Count > 0){ Vertex tmp = RA.Pop(); pred[tmp] = null; int potChange = delta - dist[tmp]; if(potChange <= 0){ continue; } pot[tmp] = (pot[tmp] - potChange); } //Update the potential and remove the nodes from the stack. while(RB.Count > 0){ Vertex tmp = RB.Pop(); pred[tmp] = (Edge) null; //if b is in the heap if(PQ.member(tmp)){ PQ.delete(tmp); } int potChange = delta - dist[tmp]; if(potChange <= 0){ continue; } pot[tmp] = (pot[tmp] + potChange); } }
//We reverse all the edges on the path when we augment from a node v private void augmentPathTo(Vertex v, Dictionary<Vertex, Edge> pred) { Edge e = pred[v]; while (e != null) { e.reverseEdge(); e = pred[e.getTarget()];//NOT SOURCE } }