Exemple #1
0
        /// <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));
        }