/// <summary> /// Calculates the priority of this vertex. /// </summary> public static float Priority <T>(this VertexInfo <T> vertexInfo, DirectedMetaGraph graph, WeightHandler <T> weightHandler, float differenceFactor, float contractedFactor, float depthFactor, float weightDiffFactor = 1) where T : struct { var vertex = vertexInfo.Vertex; var removed = vertexInfo.Count; var added = 0; //var removedWeight = 0f; //var addedWeight = 0f; foreach (var shortcut in vertexInfo.Shortcuts) { var shortcutForward = weightHandler.GetMetric(shortcut.Value.Forward); var shortcutBackward = weightHandler.GetMetric(shortcut.Value.Backward); int localAdded, localRemoved; if (shortcutForward > 0 && shortcutForward < float.MaxValue && shortcutBackward > 0 && shortcutBackward < float.MaxValue && System.Math.Abs(shortcutForward - shortcutBackward) < FastHierarchyBuilder <float> .E) { // add two bidirectional edges. graph.TryAddOrUpdateEdge(shortcut.Key.Vertex1, shortcut.Key.Vertex2, shortcutForward, null, vertex, out localAdded, out localRemoved); added += localAdded; removed += localRemoved; graph.TryAddOrUpdateEdge(shortcut.Key.Vertex2, shortcut.Key.Vertex1, shortcutForward, null, vertex, out localAdded, out localRemoved); added += localAdded; removed += localRemoved; //added += 2; //addedWeight += shortcutForward; //addedWeight += shortcutBackward; } else { if (shortcutForward > 0 && shortcutForward < float.MaxValue) { graph.TryAddOrUpdateEdge(shortcut.Key.Vertex1, shortcut.Key.Vertex2, shortcutForward, true, vertex, out localAdded, out localRemoved); added += localAdded; removed += localRemoved; graph.TryAddOrUpdateEdge(shortcut.Key.Vertex2, shortcut.Key.Vertex1, shortcutForward, false, vertex, out localAdded, out localRemoved); added += localAdded; removed += localRemoved; //added += 2; //addedWeight += shortcutForward; //addedWeight += shortcutForward; } if (shortcutBackward > 0 && shortcutBackward < float.MaxValue) { graph.TryAddOrUpdateEdge(shortcut.Key.Vertex1, shortcut.Key.Vertex2, shortcutBackward, false, vertex, out localAdded, out localRemoved); added += localAdded; removed += localRemoved; graph.TryAddOrUpdateEdge(shortcut.Key.Vertex2, shortcut.Key.Vertex1, shortcutBackward, true, vertex, out localAdded, out localRemoved); added += localAdded; removed += localRemoved; //added += 2; //addedWeight += shortcutBackward; //addedWeight += shortcutBackward; } } } //for (var e = 0; e < vertexInfo.Count; e++) //{ // var w = weightHandler.GetEdgeWeight(vertexInfo[e]); // var wMetric = weightHandler.GetMetric(w.Weight); // if (w.Direction.F) // { // removedWeight += wMetric; // } // if (w.Direction.B) // { // removedWeight += wMetric; // } //} var weigthDiff = 1f; //if (removedWeight != 0) //{ // weigthDiff = removedWeight; //} return((differenceFactor * (added - removed) + (depthFactor * vertexInfo.Depth) + (contractedFactor * vertexInfo.ContractedNeighbours)) * (weigthDiff * weightDiffFactor)); //return ((differenceFactor * (2 * added - 4 * removed)) / 2 + (depthFactor * vertexInfo.Depth) + // (contractedFactor * vertexInfo.ContractedNeighbours));// * (weigthDiff * weightDiffFactor); }
/// <summary> /// Calculates the priority of the given vertex. /// </summary> public float Calculate(BitArray32 contractedFlags, uint vertex) { var removed = 0; var added = 0; // get and keep edges. var edges = new List <Edge>(_graph.Graph.GetEdgeEnumerator(vertex)); // remove 'downward' edge to vertex. var i = 0; while (i < edges.Count) { var edgeEnumerator = _graph.GetEdgeEnumerator(edges[i].Neighbour); edgeEnumerator.Reset(); while (edgeEnumerator.MoveNext()) { if (edgeEnumerator.Neighbour == vertex) { removed++; } } if (contractedFlags[edges[i].Neighbour]) { // neighbour was already contracted, remove 'downward' edge and exclude it. edgeEnumerator.MoveTo(vertex); edgeEnumerator.Reset(); while (edgeEnumerator.MoveNext()) { if (edgeEnumerator.Neighbour == edges[i].Neighbour) { removed++; } } edges.RemoveAt(i); } else { // move to next edge. i++; } } // loop over all edge-pairs once. for (var j = 1; j < edges.Count; j++) { var edge1 = edges[j]; float edge1Weight; bool? edge1Direction; Data.Contracted.Edges.ContractedEdgeDataSerializer.Deserialize(edge1.Data[0], out edge1Weight, out edge1Direction); var edge1CanMoveForward = edge1Direction == null || edge1Direction.Value; var edge1CanMoveBackward = edge1Direction == null || !edge1Direction.Value; // figure out what witness paths to calculate. var forwardWitnesses = new bool[j]; var backwardWitnesses = new bool[j]; var targets = new List <uint>(j); var targetWeights = new List <float>(j); for (var k = 0; k < j; k++) { var edge2 = edges[k]; float edge2Weight; bool? edge2Direction; Data.Contracted.Edges.ContractedEdgeDataSerializer.Deserialize(edge2.Data[0], out edge2Weight, out edge2Direction); var edge2CanMoveForward = edge2Direction == null || edge2Direction.Value; var edge2CanMoveBackward = edge2Direction == null || !edge2Direction.Value; forwardWitnesses[k] = !(edge1CanMoveBackward && edge2CanMoveForward); backwardWitnesses[k] = !(edge1CanMoveForward && edge2CanMoveBackward); targets.Add(edge2.Neighbour); targetWeights.Add(edge1Weight + edge2Weight); } // calculate all witness paths. _witnessCalculator.Calculate(_graph.Graph, edge1.Neighbour, targets, targetWeights, ref forwardWitnesses, ref backwardWitnesses, vertex); // add contracted edges if needed. for (var k = 0; k < j; k++) { var edge2 = edges[k]; var removedLocal = 0; var addedLocal = 0; if (!forwardWitnesses[k] && !backwardWitnesses[k]) { // add bidirectional edge. _graph.TryAddOrUpdateEdge(edge1.Neighbour, edge2.Neighbour, targetWeights[k], null, vertex, out addedLocal, out removedLocal); added += addedLocal; removed += removedLocal; _graph.TryAddOrUpdateEdge(edge2.Neighbour, edge1.Neighbour, targetWeights[k], null, vertex, out addedLocal, out removedLocal); added += addedLocal; removed += removedLocal; } else if (!forwardWitnesses[k]) { // add forward edge. _graph.TryAddOrUpdateEdge(edge1.Neighbour, edge2.Neighbour, targetWeights[k], true, vertex, out addedLocal, out removedLocal); added += addedLocal; removed += removedLocal; _graph.TryAddOrUpdateEdge(edge2.Neighbour, edge1.Neighbour, targetWeights[k], false, vertex, out addedLocal, out removedLocal); added += addedLocal; removed += removedLocal; } else if (!backwardWitnesses[k]) { // add forward edge. _graph.TryAddOrUpdateEdge(edge1.Neighbour, edge2.Neighbour, targetWeights[k], false, vertex, out addedLocal, out removedLocal); added += addedLocal; removed += removedLocal; _graph.TryAddOrUpdateEdge(edge2.Neighbour, edge1.Neighbour, targetWeights[k], true, vertex, out addedLocal, out removedLocal); added += addedLocal; removed += removedLocal; } } } var contracted = 0; _contractionCount.TryGetValue(vertex, out contracted); var depth = 0; _depth.TryGetValue(vertex, out depth); return(this.DifferenceFactor * (added - removed) + (this.DepthFactor * depth) + (this.ContractedFactor * contracted)); }