private void SecondWalk(TVertex v, TVertex r, double x, double y, float l, float t) { Point pos = new Point(x, y); VertexPositions[v] = pos; visitedVertices.Add(v); BalloonData data = datas[v]; float dd = l * data.d; float p = (float)(t + Math.PI); int degree = VisitedGraph.OutDegree(v); float fs = (degree == 0 ? 0 : data.f / degree); float pr = 0; foreach (var edge in VisitedGraph.OutEdges(v)) { var otherVertex = edge.Target; if (visitedVertices.Contains(otherVertex)) { continue; } var otherData = datas[otherVertex]; float aa = data.c * otherData.a; float rr = (float)(data.d * Math.Tan(aa) / (1 - Math.Tan(aa))); p += pr + aa + fs; float xx = (float)((l * rr + dd) * Math.Cos(p)); float yy = (float)((l * rr + dd) * Math.Sign(p)); pr = aa;; SecondWalk(otherVertex, v, x + xx, y + yy, l * data.c, p); } }
//======================================================================= // The main purpose of this routine is to set distance[v] // to the smallest value allowed by the valid labeling constraints, // which are: // distance[t] = 0 // distance[u] <= distance[v] + 1 for every residual edge (u,v) // private int RelabelDistance(IVertex u) { int minEdges = 0; workSinceLastUpdate += beta; int minDistance = VisitedGraph.VerticesCount; distances[u] = minDistance; // Examine the residual out-edges of vertex i, choosing the // edge whose target vertex has the minimal distance. for (int ai = 0; ai < VisitedGraph.OutDegree(u); ai++) { ++workSinceLastUpdate; IEdge a = VisitedGraph.OutEdges(u)[ai]; IVertex v = a.Target; if (IsResidualEdge(a) && distances[v] < minDistance) { minDistance = distances[v]; minEdges = ai; } } ++minDistance; if (minDistance < n) { distances[u] = minDistance; // this is the main action current[u] = minEdges; maxDistance = Math.Max(minDistance, maxDistance); } return(minDistance); }
private void SecondWalk([NotNull] TVertex vertex, double x, double y, float l, float t) { Debug.Assert(vertex != null); var position = new Point(x, y); VerticesPositions[vertex] = position; _visitedVertices.Add(vertex); BalloonData data = _data[vertex]; float dd = l * data.D; float p = (float)(t + Math.PI); int degree = VisitedGraph.OutDegree(vertex); float fs = degree == 0 ? 0 : data.F / degree; float pr = 0; foreach (TEdge edge in VisitedGraph.OutEdges(vertex)) { TVertex otherVertex = edge.Target; if (_visitedVertices.Contains(otherVertex)) { continue; } BalloonData otherData = _data[otherVertex]; float aa = data.C * otherData.A; float rr = (float)(data.D * Math.Tan(aa) / (1 - Math.Tan(aa))); p += pr + aa + fs; float xx = (float)((l * rr + dd) * Math.Cos(p)); float yy = (l * rr + dd) * Math.Sign(p); pr = aa; SecondWalk(otherVertex, x + xx, y + yy, l * data.C, p); } }
public override void Compute(CancellationToken cancellationToken) { Sizes = new Dictionary <TVertex, Size>(VertexSizes); if (Parameters.Direction == LayoutDirection.LeftToRight || Parameters.Direction == LayoutDirection.RightToLeft) { //change the sizes foreach (var sizePair in Sizes.ToArray()) { Sizes[sizePair.Key] = new Size(sizePair.Value.Height, sizePair.Value.Width); } } if (Parameters.Direction == LayoutDirection.RightToLeft || Parameters.Direction == LayoutDirection.BottomToTop) { _direction = -1; } else { _direction = 1; } GenerateSpanningTree(cancellationToken); //DoWidthAndHeightOptimization(); var graph = new UndirectedBidirectionalGraph <TVertex, TEdge>(VisitedGraph); var scca = new QuickGraph.Algorithms.ConnectedComponents.ConnectedComponentsAlgorithm <TVertex, TEdge>(graph); scca.Compute(); // Order connected components by their vertices count // Group vertices by connected component (they should be placed together) // Order vertices inside each conected component by in degree first, then out dregee // (roots should be placed in the first layer and leafs in the last layer) var components = from e in scca.Components group e.Key by e.Value into c orderby c.Count() descending select c; foreach (var c in components) { var firstOfComponent = true; var vertices = from v in c orderby VisitedGraph.InDegree(v), VisitedGraph.OutDegree(v) descending select v; foreach (var source in vertices) { CalculatePosition(source, null, 0, firstOfComponent); if (firstOfComponent) { firstOfComponent = false; } } } AssignPositions(cancellationToken); }
//======================================================================= // This function is called "push" in Goldberg's h_prf implementation, // but it is called "discharge" in the paper and in hi_pr.c. private void Discharge(IVertex u) { while (true) { int ai; for (ai = current[u]; ai < VisitedGraph.OutDegree(u); ai++) { IEdge a = VisitedGraph.OutEdges(u)[ai]; if (IsResidualEdge(a)) { IVertex v = a.Target; if (IsAdmissible(u, v)) { if (v != sink && excessFlow[v] == 0) { RemoveFromInactiveList(v); AddToActiveList(v, layers[distances[v]]); } PushFlow(a); if (excessFlow[u] == 0) { break; } } } } PreflowLayer layer = layers[distances[u]]; int du = distances[u]; if (ai == VisitedGraph.OutDegree(u)) // i must be relabeled { RelabelDistance(u); if (layer.ActiveVertices.Count == 0 && layer.InactiveVertices.Count == 0) { Gap(du); } if (distances[u] == n) { break; } } else { // i is no longer active current[u] = ai; AddToInactiveList(u, layer); break; } } }
//======================================================================= // remove excess flow, the "second phase" // This does a DFS on the reverse flow graph of nodes with excess flow. // If a cycle is found, cancel it. Unfortunately it seems that we can't // easily take advantage of DepthFirstSearchAlgorithm // Return the nodes with excess flow in topological order. // // Unlike the prefl_to_flow() implementation, we use // "color" instead of "distance" for the DFS labels // "parent" instead of nl_prev for the DFS tree // "topo_next" instead of nl_next for the topological ordering private void ConvertPreflowToFlow() { IVertex r, restart, u; IVertex bos = null, tos = null; VertexVertexDictionary parents = new VertexVertexDictionary(); VertexVertexDictionary topoNext = new VertexVertexDictionary(); foreach (IVertex v in VisitedGraph.Vertices) { //Handle self-loops foreach (IEdge a in VisitedGraph.OutEdges(v)) { if (a.Target == v) { ResidualCapacities[a] = Capacities[a]; } } //Initialize Colors[v] = GraphColor.White; parents[v] = v; current[v] = 0; } // eliminate flow cycles and topologically order the vertices IVertexEnumerator vertices = VisitedGraph.Vertices.GetEnumerator(); while (vertices.MoveNext()) { u = vertices.Current; if (Colors[u] == GraphColor.White && excessFlow[u] > 0 && u != src && u != sink) { r = u; Colors[r] = GraphColor.Gray; while (true) { for (; current[u] < VisitedGraph.OutDegree(u); ++current[u]) { IEdge a = VisitedGraph.OutEdges(u)[current[u]]; if (Capacities[a] == 0 && IsResidualEdge(a)) { IVertex v = a.Target; if (Colors[v] == GraphColor.White) { Colors[v] = GraphColor.Gray; parents[v] = u; u = v; break; } else if (Colors[v] == GraphColor.Gray) { //find minimum flow on the cycle double delta = ResidualCapacities[a]; while (true) { IEdge e = VisitedGraph.OutEdges(v)[current[v]]; delta = Math.Min(delta, ResidualCapacities[e]); if (v == u) { break; } else { v = e.Target; } } //remove delta flow units v = u; while (true) { a = VisitedGraph.OutEdges(v)[current[v]]; ResidualCapacities[a] -= delta; ResidualCapacities[ReversedEdges[a]] += delta; v = a.Target; if (v == u) { break; } } // back-out of DFS to the first saturated edge restart = u; for (v = VisitedGraph.OutEdges(u)[current[u]].Target; v != u; v = a.Target) { a = VisitedGraph.OutEdges(v)[current[v]]; if (Colors[v] == GraphColor.White || IsSaturated(a)) { Colors[VisitedGraph.OutEdges(v)[current[v]].Target] = GraphColor.White; if (Colors[v] != GraphColor.White) { restart = v; } } } if (restart != u) { u = restart; ++current[u]; break; } } } } if (current[u] == VisitedGraph.OutDegree(u)) { // scan of i is complete Colors[u] = GraphColor.Black; if (u != src) { if (bos == null) { bos = u; tos = u; } else { topoNext[u] = tos; tos = u; } } if (u != r) { u = parents[u]; ++current[u]; } else { break; } } } } } // return excess flows // note that the sink is not on the stack if (bos != null) { IEdgeEnumerator ai; for (u = tos; u != bos; u = topoNext[u]) { ai = VisitedGraph.OutEdges(u).GetEnumerator(); while (excessFlow[u] > 0 && ai.MoveNext()) { if (Capacities[ai.Current] == 0 && IsResidualEdge(ai.Current)) { PushFlow(ai.Current); } } } // do the bottom u = bos; ai = VisitedGraph.OutEdges(u).GetEnumerator(); while (excessFlow[u] > 0 && ai.MoveNext()) { if (Capacities[ai.Current] == 0 && IsResidualEdge(ai.Current)) { PushFlow(ai.Current); } } } }
private void Initialize() { int m = 0; n = VisitedGraph.VerticesCount; foreach (IVertex u in VisitedGraph.Vertices) { m += VisitedGraph.OutDegree(u); } // Don't count the reverse edges m /= 2; nm = alpha * n + m; excessFlow.Clear(); current.Clear(); distances.Clear(); layers = new PreflowLayer[n]; for (int i = 0; i < n; i++) { layers[i] = new PreflowLayer(); } // Initialize flow to zero which means initializing // the residual capacity to equal the capacity. foreach (IVertex u in VisitedGraph.Vertices) { foreach (IEdge e in VisitedGraph.OutEdges(u)) { this.ResidualCapacities[e] = this.Capacities[e]; } excessFlow[u] = 0; current[u] = 0; } bool overflowDetected = false; double testExcess = 0; foreach (IEdge a in VisitedGraph.OutEdges(src)) { if (a.Target != src) { testExcess += this.ResidualCapacities[a]; } } if (testExcess >= double.MaxValue || double.IsPositiveInfinity(testExcess)) { overflowDetected = true; } if (overflowDetected) { excessFlow[src] = double.MaxValue; } else { excessFlow[src] = 0; foreach (IEdge a in this.VisitedGraph.OutEdges(src)) { if (a.Target != src) { double delta = this.ResidualCapacities[a]; this.ResidualCapacities[a] -= delta; this.ResidualCapacities[this.ReversedEdges[a]] += delta; this.excessFlow[a.Target] += delta; } } } maxDistance = VisitedGraph.VerticesCount - 1; maxActive = 0; minActive = n; foreach (IVertex u in this.VisitedGraph.Vertices) { if (u == sink) { distances[u] = 0; continue; } else if (u == src && !overflowDetected) { distances[u] = n; } else { distances[u] = 1; } if (excessFlow[u] > 0) { this.AddToActiveList(u, layers[1]); } else if (distances[u] < n) { this.AddToInactiveList(u, layers[1]); } } }
private void FlushVisitQueue() { var cancelManager = this.Services.CancelManager; var oee = this.OutEdgeEnumerator; while (this.rootQueue.Count > 0) { if (cancelManager.IsCancelling) { return; } this.vertexQueue.Enqueue(this.rootQueue.Dequeue()); while (this.vertexQueue.Count > 0) { var u = this.vertexQueue.Dequeue(); this.OnExamineVertex(u); var visited = _sorted ? oee(this.VisitedGraph.OutEdges(u)).OrderBy(e => VisitedGraph.OutDegree(e.Target)) : oee(this.VisitedGraph.OutEdges(u)); foreach (var e in visited) { TVertex v = e.Target; this.OnExamineEdge(e); var vColor = this.VertexColors[v]; if (vColor == GraphColor.White) { this.OnTreeEdge(e); this.VertexColors[v] = GraphColor.Gray; this.OnDiscoverVertex(v); this.vertexQueue.Enqueue(v); } else { this.OnNonTreeEdge(e); if (vColor == GraphColor.Gray) { this.OnGrayTarget(e); } else { this.OnBlackTarget(e); } } } this.VertexColors[u] = GraphColor.Black; this.OnFinishVertex(u); } } }