/// <summary> /// Creates the join tree (or forest) of this hypergraph. /// If the graph is not acylic, it returns null. /// </summary> public DynamicForest GetJoinTree() { if (!IsAcyclic) { return(null); } DynamicForest forest = new DynamicForest(edgeList.Length); for (int eId = 0; eId < edgeList.Length; eId++) { forest.AddVertex(); } for (int eId = 0; eId < edgeList.Length; eId++) { int gamma = ai.gamma[eId]; if (gamma < 0) { continue; } int parId = ai.R[gamma]; forest.SetParent(eId, parId); } return(forest); }
public RootedDrawing(DynamicForest forest) { if (forest == null) { throw new ArgumentNullException(); } if (forest.Size == 0) { throw new ArgumentException(); } this.forest = forest.Clone(); PrepareTree(); }
/// <summary> /// Creates a copy of this forest. /// </summary> public DynamicForest Clone() { DynamicForest clone = new DynamicForest(Size); for (int i = 0; i < Size; i++) { clone.parentIds.Add(this.parentIds[i]); clone.vertexData.Add(this.vertexData[i]); clone.vertexList.Add(new List <int>(this.vertexList[i])); } foreach (int rId in this.rootIds) { clone.rootIds.Add(rId); } return(clone); }
private void Preprocess() { hypertree.TransformToDual(); // Generate and "draw" underlying tree. joinForest = hypertree.GetJoinTree(); drawer = new RootedDrawing(joinForest); data = drawer.DrawRadial(); // Computes colouring and max colour. colouring = hypertree.GetVertexColouring(); hypertree.TransformToDual(); maxCol = 0; for (int i = 0; i < colouring.Length; i++) { maxCol = Math.Max(colouring[i], maxCol); } // Counting sort to sort edges by their colour. edgeByColour = new int[colouring.Length]; int[] colCounter = new int[maxCol + 1]; for (int i = 0; i < colouring.Length; i++) { colCounter[colouring[i]]++; } for (int i = 1; i < colCounter.Length; i++) { colCounter[i] += colCounter[i - 1]; } for (int i = colouring.Length - 1; i >= 0; i--) { int col = colouring[i]; colCounter[col]--; int ind = colCounter[col]; edgeByColour[ind] = i; } // End of counting sort. Array.Reverse(edgeByColour); edges = new List <int> [hypertree.NoOfEdges]; for (int i = 0; i < edges.Length; i++) { edges[i] = new List <int>(Math.Max(hypertree.GetCardinality(i) * 2 - 2, 0)); } // Use a DFS to determine the tree-edges of each hyperedge. // The search starts at the root. // Each time the search reaces a vertex v, it checks for all edges e containing v, if e is already activated. // If e is already activated, the tree-edge from v to its parent is part of the edge. bool[] activeEdges = new bool[hypertree.NoOfEdges]; Stack <int> verStack = new Stack <int>(); Stack <int> parStack = new Stack <int>(); int[] rootIds = joinForest.GetRoots(); foreach (int rId in rootIds) { verStack.Push(rId); parStack.Push(-1); while (verStack.Count > 0) { int vId = verStack.Pop(); int pId = parStack.Pop(); int[] edgeIds = hypertree.GetEdges(vId); foreach (int eId in edgeIds) { if (activeEdges[eId]) { edges[eId].Add(pId); edges[eId].Add(vId); } activeEdges[eId] = true; } int[] neighs = joinForest[vId]; foreach (int nId in neighs) { if (nId == pId) { continue; } verStack.Push(nId); parStack.Push(vId); } } } // Now, data contains the radial coordinates of each vertex, // edges contains the list of tree-edges of each hyperedge, // colouring contains the colours of each hyperedge, // and edgeByColur has the edges ordered by their colour. }