Ejemplo n.º 1
0
        /// <summary>
        /// Tries adding or updating an edge and returns #added and #removed edges.
        /// </summary>
        /// <returns></returns>
        public static void TryAddOrUpdateEdge(this DirectedMetaGraph graph, uint vertex1, uint vertex2, float weight, bool?direction, uint contractedId,
                                              out int added, out int removed)
        {
            var hasExistingEdge = false;
            var hasExistingEdgeOnlySameDirection = true;
            var edgeCount      = 0;
            var edgeEnumerator = graph.GetEdgeEnumerator(vertex1);

            while (edgeEnumerator.MoveNext())
            {
                if (edgeEnumerator.Neighbour == vertex2)
                {
                    edgeCount++;
                    hasExistingEdge = true;
                    if (ContractedEdgeDataSerializer.HasDirection(edgeEnumerator.Data0, direction))
                    {     // has the same direction.
                        if (weight < ContractedEdgeDataSerializer.DeserializeWeight(edgeEnumerator.Data0))
                        { // the weight is better, just update.
                            added   = 1;
                            removed = 1;
                            return;
                        }
                        hasExistingEdgeOnlySameDirection = false;
                    }
                }
            }

            if (!hasExistingEdge)
            { // no edge exists yet.
                added   = 1;
                removed = 0;
                return;
            }
            else if (hasExistingEdgeOnlySameDirection)
            { // there is an edge already but it has a better weight.
                added   = 0;
                removed = 0;
                return;
            }
            else
            { // see what's there and update if needed.
                var forward              = false;
                var forwardWeight        = float.MaxValue;
                var forwardContractedId  = uint.MaxValue;
                var backward             = false;
                var backwardWeight       = float.MaxValue;
                var backwardContractedId = uint.MaxValue;

                if (direction == null || direction.Value)
                {
                    forward             = true;
                    forwardWeight       = weight;
                    forwardContractedId = contractedId;
                }
                if (direction == null || !direction.Value)
                {
                    backward             = true;
                    backwardWeight       = weight;
                    backwardContractedId = contractedId;
                }

                edgeEnumerator = graph.GetEdgeEnumerator(vertex1);
                while (edgeEnumerator.MoveNext())
                {
                    if (edgeEnumerator.Neighbour == vertex2)
                    {
                        float localWeight;
                        bool? localDirection;
                        uint  localContractedId;
                        ContractedEdgeDataSerializer.Deserialize(edgeEnumerator.Data0, edgeEnumerator.MetaData0,
                                                                 out localWeight, out localDirection, out localContractedId);
                        if (localDirection == null || localDirection.Value)
                        {
                            if (localWeight < forwardWeight)
                            {
                                forwardWeight       = localWeight;
                                forward             = true;
                                forwardContractedId = localContractedId;
                            }
                        }
                        if (localDirection == null || !localDirection.Value)
                        {
                            if (localWeight < backwardWeight)
                            {
                                backwardWeight       = localWeight;
                                backward             = true;
                                backwardContractedId = localContractedId;
                            }
                        }
                    }
                }

                removed = edgeCount;
                added   = 0;

                if (forward && backward &&
                    forwardWeight == backwardWeight &&
                    forwardContractedId == backwardContractedId)
                { // add one bidirectional edge.
                    added++;
                }
                else
                {     // add two unidirectional edges if needed.
                    if (forward)
                    { // there is a forward edge.
                        added++;
                    }
                    if (backward)
                    { // there is a backward edge.
                        added++;
                    }
                }
            }
        }
Ejemplo n.º 2
0
        public void TestSerialize()
        {
            var edgeData = new ContractedEdgeData()
            {
                Weight       = 100f,
                Direction    = null,
                ContractedId = Constants.NO_VERTEX
            };

            var data = ContractedEdgeDataSerializer.SerializeMeta(edgeData);

            Assert.IsNotNull(data);
            Assert.AreEqual(2, data.Length);
            Assert.AreEqual(((uint)(100.0f * 4 * ContractedEdgeDataSerializer.PRECISION_FACTOR)), data[0]);
            Assert.AreEqual(Constants.NO_VERTEX, data[1]);

            edgeData = new ContractedEdgeData()
            {
                Weight       = ContractedEdgeDataSerializer.MAX_DISTANCE,
                Direction    = true,
                ContractedId = Constants.NO_VERTEX
            };

            data = ContractedEdgeDataSerializer.SerializeMeta(edgeData);
            Assert.IsNotNull(data);
            Assert.AreEqual(2, data.Length);
            Assert.AreEqual(((uint)1) + (((uint)(ContractedEdgeDataSerializer.MAX_DISTANCE * 4 * ContractedEdgeDataSerializer.PRECISION_FACTOR))), data[0]);
            Assert.AreEqual(Constants.NO_VERTEX, data[1]);

            edgeData = new ContractedEdgeData()
            {
                Weight       = 100.25f,
                Direction    = null,
                ContractedId = Constants.NO_VERTEX
            };

            data = ContractedEdgeDataSerializer.SerializeMeta(edgeData);
            Assert.IsNotNull(data);
            Assert.AreEqual(2, data.Length);
            Assert.AreEqual(((uint)(100.25f * ContractedEdgeDataSerializer.PRECISION_FACTOR) * 4), data[0]);
            Assert.AreEqual(Constants.NO_VERTEX, data[1]);

            edgeData = new ContractedEdgeData()
            {
                Weight       = 100,
                Direction    = false,
                ContractedId = Constants.NO_VERTEX
            };

            data = ContractedEdgeDataSerializer.SerializeMeta(edgeData);
            Assert.IsNotNull(data);
            Assert.AreEqual(2, data.Length);
            Assert.AreEqual(((uint)2) + (((uint)(100.0f * 4 * ContractedEdgeDataSerializer.PRECISION_FACTOR))), data[0]);
            Assert.AreEqual(Constants.NO_VERTEX, data[1]);

            edgeData = new ContractedEdgeData()
            {
                Weight       = 100,
                Direction    = true,
                ContractedId = Constants.NO_VERTEX
            };

            data = ContractedEdgeDataSerializer.SerializeMeta(edgeData);
            Assert.IsNotNull(data);
            Assert.AreEqual(2, data.Length);
            Assert.AreEqual(((uint)1) + (((uint)(100.0f * ContractedEdgeDataSerializer.PRECISION_FACTOR) * 4)), data[0]);
            Assert.AreEqual(Constants.NO_VERTEX, data[1]);

            edgeData = new ContractedEdgeData()
            {
                Weight       = ContractedEdgeDataSerializer.MAX_DISTANCE,
                Direction    = false,
                ContractedId = Constants.NO_VERTEX
            };

            data = ContractedEdgeDataSerializer.SerializeMeta(edgeData);
            Assert.IsNotNull(data);
            Assert.AreEqual(2, data.Length);
            Assert.AreEqual(((uint)2) + (((uint)(ContractedEdgeDataSerializer.MAX_DISTANCE * 4 * ContractedEdgeDataSerializer.PRECISION_FACTOR))), data[0]);
            Assert.AreEqual(Constants.NO_VERTEX, data[1]);

            edgeData = new ContractedEdgeData()
            {
                Weight       = ContractedEdgeDataSerializer.MAX_DISTANCE + 100,
                Direction    = true,
                ContractedId = Constants.NO_VERTEX
            };
            Assert.Catch <ArgumentOutOfRangeException>(() =>
            {
                ContractedEdgeDataSerializer.SerializeMeta(edgeData);
            });
        }
Ejemplo n.º 3
0
 /// <summary>
 /// Add edge.
 /// </summary>
 /// <returns></returns>
 public static void AddEdge(this DirectedMetaGraph graph, uint vertex1, uint vertex2, float weight,
                            bool?direction, uint contractedId, float distance, float time)
 {
     graph.AddEdge(vertex1, vertex2, new uint[] { ContractedEdgeDataSerializer.Serialize(
                                                      weight, direction) }, ContractedEdgeDataSerializer.SerializeMetaAugmented(contractedId, distance, time));
 }
Ejemplo n.º 4
0
        /// <summary>
        /// Add or update edge.
        /// </summary>
        /// <returns></returns>
        public static void AddOrUpdateEdge(this DirectedMetaGraph graph, uint vertex1, uint vertex2, float weight,
                                           bool?direction, uint contractedId, float distance, float time)
        {
            var current         = ContractedEdgeDataSerializer.Serialize(weight, direction);
            var hasExistingEdge = false;
            var hasExistingEdgeOnlySameDirection = true;

            if (graph.UpdateEdge(vertex1, vertex2, (data) =>
            {
                hasExistingEdge = true;
                if (ContractedEdgeDataSerializer.HasDirection(data[0], direction))
                {     // has the same direction.
                    if (weight < ContractedEdgeDataSerializer.DeserializeWeight(data[0]))
                    { // the weight is better, just update.
                        return(true);
                    }
                    return(false);
                }
                hasExistingEdgeOnlySameDirection = false;
                return(false);
            }, new uint[] { current }, ContractedEdgeDataSerializer.SerializeMetaAugmented(contractedId, distance, time)) != Constants.NO_EDGE)
            { // updating the edge succeeded.
                return;
            }
            if (!hasExistingEdge)
            { // no edge exists yet.
                graph.AddEdge(vertex1, vertex2, new uint[] { current }, ContractedEdgeDataSerializer.SerializeMetaAugmented(
                                  contractedId, distance, time));
                return;
            }
            else if (hasExistingEdgeOnlySameDirection)
            { // there is an edge already but it has a better weight.
                return;
            }
            else
            { // see what's there and update if needed.
                var forward              = false;
                var forwardWeight        = float.MaxValue;
                var forwardContractedId  = uint.MaxValue;
                var forwardTime          = float.MaxValue;
                var forwardDistance      = float.MaxValue;
                var backward             = false;
                var backwardWeight       = float.MaxValue;
                var backwardContractedId = uint.MaxValue;
                var backwardTime         = float.MaxValue;
                var backwardDistance     = float.MaxValue;

                if (direction == null || direction.Value)
                {
                    forward             = true;
                    forwardWeight       = weight;
                    forwardContractedId = contractedId;
                    forwardTime         = time;
                    forwardDistance     = distance;
                }
                if (direction == null || !direction.Value)
                {
                    backward             = true;
                    backwardWeight       = weight;
                    backwardContractedId = contractedId;
                    backwardTime         = time;
                    backwardDistance     = distance;
                }

                var edgeEnumerator = graph.GetEdgeEnumerator(vertex1);
                while (edgeEnumerator.MoveNext())
                {
                    if (edgeEnumerator.Neighbour == vertex2)
                    {
                        float localWeight;
                        bool? localDirection;
                        ContractedEdgeDataSerializer.Deserialize(edgeEnumerator.Data0,
                                                                 out localWeight, out localDirection);
                        uint  localContractedId;
                        float localTime;
                        float localDistance;
                        ContractedEdgeDataSerializer.DeserializeMetaAgumented(edgeEnumerator.MetaData, out localContractedId, out localDistance, out localTime);
                        if (localDirection == null || localDirection.Value)
                        {
                            if (localWeight < forwardWeight)
                            {
                                forwardWeight       = localWeight;
                                forward             = true;
                                forwardContractedId = localContractedId;
                                forwardTime         = localTime;
                                forwardDistance     = localDistance;
                            }
                        }
                        if (localDirection == null || !localDirection.Value)
                        {
                            if (localWeight < backwardWeight)
                            {
                                backwardWeight       = localWeight;
                                backward             = true;
                                backwardContractedId = localContractedId;
                                backwardDistance     = localDistance;
                                backwardTime         = localTime;
                            }
                        }
                    }
                }

                graph.RemoveEdge(vertex1, vertex2);

                if (forward && backward &&
                    forwardWeight == backwardWeight &&
                    forwardContractedId == backwardContractedId)
                { // add one bidirectional edge.
                    graph.AddEdge(vertex1, vertex2, forwardWeight, null, forwardContractedId, forwardDistance, forwardTime);
                    //graph.AddEdge(vertex1, vertex2,
                    //    ContractedEdgeDataSerializer.Serialize(forwardWeight, null), forwardContractedId);
                }
                else
                {     // add two unidirectional edges if needed.
                    if (forward)
                    { // there is a forward edge.
                        graph.AddEdge(vertex1, vertex2, forwardWeight, true, forwardContractedId, forwardDistance, forwardTime);
                        //graph.AddEdge(vertex1, vertex2,
                        //    ContractedEdgeDataSerializer.Serialize(forwardWeight, true), forwardContractedId);
                    }
                    if (backward)
                    { // there is a backward edge.
                        graph.AddEdge(vertex1, vertex2, backwardWeight, false, backwardContractedId, backwardDistance, backwardTime);
                    }
                }
            }
        }
Ejemplo n.º 5
0
        private void Contract(uint vertex)
        {
            List <MetaEdge> metaEdgeList = new List <MetaEdge>((IEnumerable <MetaEdge>) this._graph.GetEdgeEnumerator(vertex));
            int             index1       = 0;

            while (index1 < metaEdgeList.Count)
            {
                this._graph.RemoveEdge(metaEdgeList[index1].Neighbour, vertex);
                if (this._contractedFlags.Contains((long)metaEdgeList[index1].Neighbour))
                {
                    this._graph.RemoveEdge(vertex, metaEdgeList[index1].Neighbour);
                    metaEdgeList.RemoveAt(index1);
                }
                else
                {
                    ++index1;
                }
            }
            for (int capacity = 1; capacity < metaEdgeList.Count; ++capacity)
            {
                MetaEdge metaEdge1 = metaEdgeList[capacity];
                float    weight1;
                bool?    direction1;
                ContractedEdgeDataSerializer.Deserialize(metaEdge1.Data[0], out weight1, out direction1);
                bool         flag1           = !direction1.HasValue || direction1.Value;
                bool         flag2           = !direction1.HasValue || !direction1.Value;
                bool[]       forwardWitness  = new bool[capacity];
                bool[]       backwardWitness = new bool[capacity];
                List <uint>  targets         = new List <uint>(capacity);
                List <float> weights         = new List <float>(capacity);
                for (int index2 = 0; index2 < capacity; ++index2)
                {
                    MetaEdge metaEdge2 = metaEdgeList[index2];
                    float    weight2;
                    bool?    direction2;
                    ContractedEdgeDataSerializer.Deserialize(metaEdge2.Data[0], out weight2, out direction2);
                    bool flag3 = !direction2.HasValue || direction2.Value;
                    bool flag4 = !direction2.HasValue || !direction2.Value;
                    forwardWitness[index2]  = !(flag2 & flag3);
                    backwardWitness[index2] = !(flag1 & flag4);
                    targets.Add(metaEdge2.Neighbour);
                    weights.Add(weight1 + weight2);
                }
                this._witnessCalculator.Calculate(this._graph.Graph, metaEdge1.Neighbour, targets, weights, ref forwardWitness, ref backwardWitness, vertex);
                for (int index2 = 0; index2 < capacity; ++index2)
                {
                    MetaEdge metaEdge2 = metaEdgeList[index2];
                    if ((int)metaEdge1.Neighbour != (int)metaEdge2.Neighbour)
                    {
                        if (!forwardWitness[index2] && !backwardWitness[index2])
                        {
                            this._graph.AddOrUpdateEdge(metaEdge1.Neighbour, metaEdge2.Neighbour, weights[index2], new bool?(), vertex);
                            this._graph.AddOrUpdateEdge(metaEdge2.Neighbour, metaEdge1.Neighbour, weights[index2], new bool?(), vertex);
                        }
                        else if (!forwardWitness[index2])
                        {
                            this._graph.AddOrUpdateEdge(metaEdge1.Neighbour, metaEdge2.Neighbour, weights[index2], new bool?(true), vertex);
                            this._graph.AddOrUpdateEdge(metaEdge2.Neighbour, metaEdge1.Neighbour, weights[index2], new bool?(false), vertex);
                        }
                        else if (!backwardWitness[index2])
                        {
                            this._graph.AddOrUpdateEdge(metaEdge1.Neighbour, metaEdge2.Neighbour, weights[index2], new bool?(false), vertex);
                            this._graph.AddOrUpdateEdge(metaEdge2.Neighbour, metaEdge1.Neighbour, weights[index2], new bool?(true), vertex);
                        }
                    }
                }
            }
            this._contractedFlags.Add((long)vertex);
            this._priorityCalculator.NotifyContracted(vertex);
        }
Ejemplo n.º 6
0
 /// <summary>
 /// Add edge.
 /// </summary>
 /// <returns></returns>
 public static void AddEdge(this DirectedMetaGraph graph, uint vertex1, uint vertex2, float weight,
                            bool?direction, uint contractedId)
 {
     graph.AddEdge(vertex1, vertex2, ContractedEdgeDataSerializer.Serialize(
                       weight, direction), contractedId);
 }
Ejemplo n.º 7
0
        public void TestTwoOnewayEdgeInfiniteHops()
        {
            // build graph.
            var graph = new DirectedGraph(ContractedEdgeDataSerializer.Size);

            graph.AddEdge(0, 1, ContractedEdgeDataSerializer.SerializeMeta(new ContractedEdgeData()
            {
                ContractedId = Constants.NO_VERTEX,
                Direction    = true,
                Weight       = 100
            }));
            graph.AddEdge(1, 2, ContractedEdgeDataSerializer.SerializeMeta(new ContractedEdgeData()
            {
                ContractedId = Constants.NO_VERTEX,
                Direction    = true,
                Weight       = 100
            }));
            graph.AddEdge(0, 2, ContractedEdgeDataSerializer.SerializeMeta(new ContractedEdgeData()
            {
                ContractedId = Constants.NO_VERTEX,
                Direction    = true,
                Weight       = 300
            }));

            var witnessCalculator = new DykstraWitnessCalculator(int.MaxValue);

            // calculate witness for weight of 200.
            var forwardWitnesses  = new bool[1];
            var backwardWitnesses = new bool[1];

            witnessCalculator.Calculate(graph, 0, new List <uint>(new uint[] { 2 }), new List <float>(new float[] { 1000 }),
                                        ref forwardWitnesses, ref backwardWitnesses, uint.MaxValue);
            Assert.AreEqual(true, forwardWitnesses[0]);
            Assert.AreEqual(false, backwardWitnesses[0]);

            // calculate witness for weight of 50.
            forwardWitnesses  = new bool[1];
            backwardWitnesses = new bool[1];
            witnessCalculator.Calculate(graph, 0, new List <uint>(new uint[] { 2 }), new List <float>(new float[] { 50 }),
                                        ref forwardWitnesses, ref backwardWitnesses, uint.MaxValue);

            Assert.AreEqual(false, forwardWitnesses[0]);
            Assert.AreEqual(false, backwardWitnesses[0]);

            // build graph.
            graph = new DirectedGraph(ContractedEdgeDataSerializer.Size);
            graph.AddEdge(1, 0, ContractedEdgeDataSerializer.SerializeMeta(new ContractedEdgeData()
            {
                ContractedId = Constants.NO_VERTEX,
                Direction    = true,
                Weight       = 100
            }));
            graph.AddEdge(2, 1, ContractedEdgeDataSerializer.SerializeMeta(new ContractedEdgeData()
            {
                ContractedId = Constants.NO_VERTEX,
                Direction    = true,
                Weight       = 100
            }));
            graph.AddEdge(2, 0, ContractedEdgeDataSerializer.SerializeMeta(new ContractedEdgeData()
            {
                ContractedId = Constants.NO_VERTEX,
                Direction    = true,
                Weight       = 300
            }));


            // calculate witness for weight of 200.
            forwardWitnesses  = new bool[1];
            backwardWitnesses = new bool[1];
            witnessCalculator.Calculate(graph, 2, new List <uint>(new uint[] { 0 }), new List <float>(new float[] { 1000 }),
                                        ref forwardWitnesses, ref backwardWitnesses, uint.MaxValue);
            Assert.AreEqual(true, forwardWitnesses[0]);
            Assert.AreEqual(false, backwardWitnesses[0]);

            // calculate witness for weight of 50.
            forwardWitnesses  = new bool[1];
            backwardWitnesses = new bool[1];
            witnessCalculator.Calculate(graph, 2, new List <uint>(new uint[] { 0 }), new List <float>(new float[] { 50 }),
                                        ref forwardWitnesses, ref backwardWitnesses, uint.MaxValue);

            Assert.AreEqual(false, forwardWitnesses[0]);
            Assert.AreEqual(false, backwardWitnesses[0]);
        }
Ejemplo n.º 8
0
        public void TestDoubleContractionOneway()
        {
            // build graph.
            var graph = new DirectedMetaGraph(ContractedEdgeDataSerializer.Size,
                                              ContractedEdgeDataSerializer.MetaSize);

            graph.AddEdge(0, 2, 100, true, Constants.NO_VERTEX);
            graph.AddEdge(2, 0, 100, false, Constants.NO_VERTEX);
            graph.AddEdge(0, 3, 10, false, Constants.NO_VERTEX);
            graph.AddEdge(3, 0, 10, true, Constants.NO_VERTEX);
            graph.AddEdge(1, 2, 1000, false, Constants.NO_VERTEX);
            graph.AddEdge(2, 1, 1000, true, Constants.NO_VERTEX);
            graph.AddEdge(1, 3, 10000, true, Constants.NO_VERTEX);
            graph.AddEdge(3, 1, 10000, false, Constants.NO_VERTEX);
            graph.Compress();

            // contract graph.
            var priorityCalculator = new EdgeDifferencePriorityCalculator(graph, new DykstraWitnessCalculator(int.MaxValue));

            priorityCalculator.ContractedFactor = 0;
            priorityCalculator.DepthFactor      = 0;
            var hierarchyBuilder = new HierarchyBuilder(graph, priorityCalculator,
                                                        new DykstraWitnessCalculator(int.MaxValue));

            hierarchyBuilder.Run();

            // check edges.
            var edge = graph.GetEdgeEnumerator(0).FirstOrDefault(x => x.Neighbour == 2);

            Assert.IsNotNull(edge);
            var edgeData = ContractedEdgeDataSerializer.Deserialize(edge.Data[0], edge.MetaData[0]);

            Assert.AreEqual(100, edgeData.Weight);
            Assert.AreEqual(true, edgeData.Direction);
            Assert.AreEqual(Constants.NO_VERTEX, edgeData.ContractedId);
            edge = graph.GetEdgeEnumerator(2).FirstOrDefault(x => x.Neighbour == 0);
            Assert.IsNull(edge);

            edge = graph.GetEdgeEnumerator(0).FirstOrDefault(x => x.Neighbour == 3);
            Assert.IsNotNull(edge);
            edgeData = ContractedEdgeDataSerializer.Deserialize(edge.Data[0], edge.MetaData[0]);
            Assert.AreEqual(10, edgeData.Weight);
            Assert.AreEqual(false, edgeData.Direction);
            Assert.AreEqual(Constants.NO_VERTEX, edgeData.ContractedId);
            edge = graph.GetEdgeEnumerator(3).FirstOrDefault(x => x.Neighbour == 0);
            Assert.IsNull(edge);

            edge = graph.GetEdgeEnumerator(2).FirstOrDefault(x => x.Neighbour == 3);
            Assert.IsNotNull(edge);
            edgeData = ContractedEdgeDataSerializer.Deserialize(edge.Data[0], edge.MetaData[0]);
            Assert.AreEqual(110, edgeData.Weight);
            Assert.AreEqual(false, edgeData.Direction);
            Assert.AreEqual(0, edgeData.ContractedId);
            edge = graph.GetEdgeEnumerator(3).FirstOrDefault(x => x.Neighbour == 2);
            Assert.IsNull(edge);

            edge = graph.GetEdgeEnumerator(2).FirstOrDefault(x => x.Neighbour == 1);
            Assert.IsNotNull(edge);
            edgeData = ContractedEdgeDataSerializer.Deserialize(edge.Data[0], edge.MetaData[0]);
            Assert.AreEqual(1000, edgeData.Weight);
            Assert.AreEqual(true, edgeData.Direction);
            Assert.AreEqual(Constants.NO_VERTEX, edgeData.ContractedId);
            edge = graph.GetEdgeEnumerator(1).FirstOrDefault(x => x.Neighbour == 2);
            Assert.IsNull(edge);

            edge = graph.GetEdgeEnumerator(3).FirstOrDefault(x => x.Neighbour == 1 &&
                                                             ContractedEdgeDataSerializer.Deserialize(x.Data[0], x.MetaData[0]).Direction == true);
            Assert.IsNotNull(edge);
            edgeData = ContractedEdgeDataSerializer.Deserialize(edge.Data[0], edge.MetaData[0]);
            Assert.AreEqual(1110, edgeData.Weight);
            Assert.AreEqual(2, edgeData.ContractedId);
            edge = graph.GetEdgeEnumerator(3).FirstOrDefault(x => x.Neighbour == 1 &&
                                                             ContractedEdgeDataSerializer.Deserialize(x.Data[0], x.MetaData[0]).Direction == false);
            Assert.IsNotNull(edge);
            edgeData = ContractedEdgeDataSerializer.Deserialize(edge.Data[0], edge.MetaData[0]);
            Assert.AreEqual(10000, edgeData.Weight);
            Assert.AreEqual(Constants.NO_VERTEX, edgeData.ContractedId);
            edge = graph.GetEdgeEnumerator(1).FirstOrDefault(x => x.Neighbour == 3);
            Assert.IsNull(edge);
        }
Ejemplo n.º 9
0
 public void Calculate(DirectedGraph graph, uint source, List <uint> targets, List <float> weights, ref bool[] forwardWitness, ref bool[] backwardWitness, uint vertexToSkip)
 {
     if (this._hopLimit == 1)
     {
         this.ExistsOneHop(graph, source, targets, weights, ref forwardWitness, ref backwardWitness);
     }
     else
     {
         HashSet <uint> uintSet1 = new HashSet <uint>();
         HashSet <uint> uintSet2 = new HashSet <uint>();
         HashSet <uint> uintSet3 = new HashSet <uint>();
         HashSet <uint> uintSet4 = new HashSet <uint>();
         float          num1     = 0.0f;
         float          num2     = 0.0f;
         for (int index = 0; index < weights.Count; ++index)
         {
             if (!forwardWitness[index])
             {
                 uintSet4.Add(targets[index]);
                 if ((double)num1 < (double)weights[index])
                 {
                     num1 = weights[index];
                 }
             }
             if (!backwardWitness[index])
             {
                 uintSet3.Add(targets[index]);
                 if ((double)num2 < (double)weights[index])
                 {
                     num2 = weights[index];
                 }
             }
         }
         if ((double)num1 == 0.0 && (double)num2 == 0.0)
         {
             return;
         }
         Dictionary <uint, float> dictionary1 = new Dictionary <uint, float>();
         Dictionary <uint, float> dictionary2 = new Dictionary <uint, float>();
         this._heap.Clear();
         this._heap.Push(new DykstraWitnessCalculator.SettledVertex(source, 0.0f, 0U, (double)num1 > 0.0, (double)num2 > 0.0), 0.0f);
         DirectedGraph.EdgeEnumerator edgeEnumerator = graph.GetEdgeEnumerator();
         while (this._heap.Count > 0)
         {
             DykstraWitnessCalculator.SettledVertex settledVertex1 = this._heap.Pop();
             if ((long)(settledVertex1.Hops + 1U) < (long)this._hopLimit && (int)settledVertex1.VertexId != (int)vertexToSkip)
             {
                 bool flag1 = uintSet2.Contains(settledVertex1.VertexId);
                 bool flag2 = uintSet1.Contains(settledVertex1.VertexId);
                 if (!(flag1 & flag2))
                 {
                     if (settledVertex1.Forward)
                     {
                         uintSet2.Add(settledVertex1.VertexId);
                         dictionary1.Remove(settledVertex1.VertexId);
                         if (uintSet4.Contains(settledVertex1.VertexId))
                         {
                             for (int index = 0; index < targets.Count; ++index)
                             {
                                 if ((int)targets[index] == (int)settledVertex1.VertexId)
                                 {
                                     forwardWitness[index] = (double)settledVertex1.Weight < (double)weights[index];
                                     uintSet4.Remove(settledVertex1.VertexId);
                                 }
                             }
                         }
                     }
                     if (settledVertex1.Backward)
                     {
                         uintSet1.Add(settledVertex1.VertexId);
                         dictionary2.Remove(settledVertex1.VertexId);
                         if (uintSet3.Contains(settledVertex1.VertexId))
                         {
                             for (int index = 0; index < targets.Count; ++index)
                             {
                                 if ((int)targets[index] == (int)settledVertex1.VertexId)
                                 {
                                     backwardWitness[index] = (double)settledVertex1.Weight < (double)weights[index];
                                     uintSet3.Remove(settledVertex1.VertexId);
                                 }
                             }
                         }
                     }
                     if (uintSet4.Count == 0 && uintSet3.Count == 0 || uintSet2.Count >= this._maxSettles && uintSet1.Count >= this._maxSettles)
                     {
                         break;
                     }
                     bool flag3 = settledVertex1.Forward && uintSet4.Count > 0 && !flag1;
                     bool flag4 = settledVertex1.Backward && uintSet3.Count > 0 && !flag2;
                     if (flag3 | flag4)
                     {
                         edgeEnumerator.MoveTo(settledVertex1.VertexId);
                         while (edgeEnumerator.MoveNext())
                         {
                             uint  neighbour = edgeEnumerator.Neighbour;
                             float weight1;
                             bool? direction;
                             ContractedEdgeDataSerializer.Deserialize(edgeEnumerator.Data0, out weight1, out direction);
                             bool  flag5    = !direction.HasValue || direction.Value;
                             bool  flag6    = !direction.HasValue || !direction.Value;
                             float weight2  = settledVertex1.Weight + weight1;
                             bool  forward  = flag3 & flag5 && (double)weight2 < (double)num1 && !uintSet2.Contains(neighbour);
                             bool  backward = flag4 & flag6 && (double)weight2 < (double)num2 && !uintSet1.Contains(neighbour);
                             if (backward | forward)
                             {
                                 float num3;
                                 if (forward)
                                 {
                                     if (dictionary1.TryGetValue(neighbour, out num3))
                                     {
                                         if ((double)num3 <= (double)weight2)
                                         {
                                             forward = false;
                                         }
                                         else
                                         {
                                             dictionary1[neighbour] = weight2;
                                         }
                                     }
                                     else
                                     {
                                         dictionary1[neighbour] = weight2;
                                     }
                                 }
                                 if (backward)
                                 {
                                     if (dictionary2.TryGetValue(neighbour, out num3))
                                     {
                                         if ((double)num3 <= (double)weight2)
                                         {
                                             backward = false;
                                         }
                                         else
                                         {
                                             dictionary2[neighbour] = weight2;
                                         }
                                     }
                                     else
                                     {
                                         dictionary2[neighbour] = weight2;
                                     }
                                 }
                                 if (backward | forward)
                                 {
                                     DykstraWitnessCalculator.SettledVertex settledVertex2 = new DykstraWitnessCalculator.SettledVertex(neighbour, weight2, settledVertex1.Hops + 1U, forward, backward);
                                     this._heap.Push(settledVertex2, settledVertex2.Weight);
                                 }
                             }
                         }
                     }
                 }
             }
         }
     }
 }
Ejemplo n.º 10
0
        public void TestOneEdgeAugmented()
        {
            // build graph.
            var graph = new Itinero.Graphs.Graph(EdgeDataSerializer.Size);

            graph.AddVertex(0);
            graph.AddVertex(1);
            graph.AddEdge(0, 1, EdgeDataSerializer.Serialize(new EdgeData()
            {
                Distance = 100,
                Profile  = 1
            }));

            // build speed profile function.
            var speed = 100f / 3.6f;
            Func <ushort, FactorAndSpeed> getFactor = (x) =>
            {
                return(new FactorAndSpeed()
                {
                    Direction = 0,
                    SpeedFactor = 1.0f / speed,
                    Value = 1.0f / speed
                });
            };

            // convert graph.
            var directedGraph = new DirectedMetaGraph(ContractedEdgeDataSerializer.Size,
                                                      ContractedEdgeDataSerializer.MetaAugmentedSize);
            var algorithm = new DirectedGraphBuilder <Weight>(graph, directedGraph, new WeightHandler(getFactor));

            algorithm.Run();

            // check result.
            Assert.IsTrue(algorithm.HasRun);
            Assert.IsTrue(algorithm.HasSucceeded);

            directedGraph.Compress();
            Assert.AreEqual(2, directedGraph.VertexCount);
            Assert.AreEqual(2, directedGraph.EdgeCount);

            // verify all edges.
            var edges = directedGraph.GetEdgeEnumerator(0);

            Assert.AreEqual(1, edges.Count);
            var data     = ContractedEdgeDataSerializer.Serialize(100 * getFactor(1).Value, null);
            var metaData = ContractedEdgeDataSerializer.SerializeMetaAugmented(Constants.NO_VERTEX, 100, 100 * getFactor(1).Value);

            Assert.AreEqual(data, edges.First().Data[0]);
            Assert.AreEqual(metaData[0], edges.First().MetaData[0]);
            Assert.AreEqual(metaData[1], edges.First().MetaData[1]);
            Assert.AreEqual(metaData[2], edges.First().MetaData[2]);
            Assert.AreEqual(1, edges.First().Neighbour);

            edges = directedGraph.GetEdgeEnumerator(1);
            Assert.AreEqual(1, edges.Count);
            data     = ContractedEdgeDataSerializer.Serialize(100 * getFactor(1).Value, null);
            metaData = ContractedEdgeDataSerializer.SerializeMetaAugmented(Constants.NO_VERTEX, 100, 100 * getFactor(1).Value);
            Assert.AreEqual(data, edges.First().Data[0]);
            Assert.AreEqual(metaData[0], edges.First().MetaData[0]);
            Assert.AreEqual(metaData[1], edges.First().MetaData[1]);
            Assert.AreEqual(metaData[2], edges.First().MetaData[2]);
            Assert.AreEqual(0, edges.First().Neighbour);
        }
        public float Calculate(ILongIndex contractedFlags, uint vertex)
        {
            int         num1     = 0;
            int         num2     = 0;
            List <Edge> edgeList = new List <Edge>((IEnumerable <Edge>) this._graph.Graph.GetEdgeEnumerator(vertex));
            int         index1   = 0;

            while (index1 < edgeList.Count)
            {
                DirectedMetaGraph.EdgeEnumerator edgeEnumerator = this._graph.GetEdgeEnumerator(edgeList[index1].Neighbour);
                edgeEnumerator.Reset();
                while (edgeEnumerator.MoveNext())
                {
                    if ((int)edgeEnumerator.Neighbour == (int)vertex)
                    {
                        ++num1;
                    }
                }
                if (contractedFlags.Contains((long)edgeList[index1].Neighbour))
                {
                    edgeEnumerator.MoveTo(vertex);
                    edgeEnumerator.Reset();
                    while (edgeEnumerator.MoveNext())
                    {
                        if ((int)edgeEnumerator.Neighbour == (int)edgeList[index1].Neighbour)
                        {
                            ++num1;
                        }
                    }
                    edgeList.RemoveAt(index1);
                }
                else
                {
                    ++index1;
                }
            }
            for (int capacity = 1; capacity < edgeList.Count; ++capacity)
            {
                Edge  edge1 = edgeList[capacity];
                float weight1;
                bool? direction1;
                ContractedEdgeDataSerializer.Deserialize(edge1.Data[0], out weight1, out direction1);
                bool         flag1           = !direction1.HasValue || direction1.Value;
                bool         flag2           = !direction1.HasValue || !direction1.Value;
                bool[]       forwardWitness  = new bool[capacity];
                bool[]       backwardWitness = new bool[capacity];
                List <uint>  targets         = new List <uint>(capacity);
                List <float> weights         = new List <float>(capacity);
                for (int index2 = 0; index2 < capacity; ++index2)
                {
                    Edge  edge2 = edgeList[index2];
                    float weight2;
                    bool? direction2;
                    ContractedEdgeDataSerializer.Deserialize(edge2.Data[0], out weight2, out direction2);
                    bool flag3 = !direction2.HasValue || direction2.Value;
                    bool flag4 = !direction2.HasValue || !direction2.Value;
                    forwardWitness[index2]  = !(flag2 & flag3);
                    backwardWitness[index2] = !(flag1 & flag4);
                    targets.Add(edge2.Neighbour);
                    weights.Add(weight1 + weight2);
                }
                this._witnessCalculator.Calculate(this._graph.Graph, edge1.Neighbour, targets, weights, ref forwardWitness, ref backwardWitness, vertex);
                for (int index2 = 0; index2 < capacity; ++index2)
                {
                    Edge edge2   = edgeList[index2];
                    int  removed = 0;
                    int  added   = 0;
                    if (!forwardWitness[index2] && !backwardWitness[index2])
                    {
                        this._graph.TryAddOrUpdateEdge(edge1.Neighbour, edge2.Neighbour, weights[index2], new bool?(), vertex, out added, out removed);
                        int num3 = num2 + added;
                        int num4 = num1 + removed;
                        this._graph.TryAddOrUpdateEdge(edge2.Neighbour, edge1.Neighbour, weights[index2], new bool?(), vertex, out added, out removed);
                        num2 = num3 + added;
                        num1 = num4 + removed;
                    }
                    else if (!forwardWitness[index2])
                    {
                        this._graph.TryAddOrUpdateEdge(edge1.Neighbour, edge2.Neighbour, weights[index2], new bool?(true), vertex, out added, out removed);
                        int num3 = num2 + added;
                        int num4 = num1 + removed;
                        this._graph.TryAddOrUpdateEdge(edge2.Neighbour, edge1.Neighbour, weights[index2], new bool?(false), vertex, out added, out removed);
                        num2 = num3 + added;
                        num1 = num4 + removed;
                    }
                    else if (!backwardWitness[index2])
                    {
                        this._graph.TryAddOrUpdateEdge(edge1.Neighbour, edge2.Neighbour, weights[index2], new bool?(false), vertex, out added, out removed);
                        int num3 = num2 + added;
                        int num4 = num1 + removed;
                        this._graph.TryAddOrUpdateEdge(edge2.Neighbour, edge1.Neighbour, weights[index2], new bool?(true), vertex, out added, out removed);
                        num2 = num3 + added;
                        num1 = num4 + removed;
                    }
                }
            }
            int num5 = 0;

            this._contractionCount.TryGetValue(vertex, out num5);
            int num6 = 0;

            this._depth.TryGetValue((long)vertex, out num6);
            return((float)(this.DifferenceFactor * (num2 - num1) + this.DepthFactor * num6 + this.ContractedFactor * num5));
        }
Ejemplo n.º 12
0
        /// <summary>
        /// Calculates witness paths.
        /// </summary>
        public void Calculate(DirectedGraph graph, uint source, List <uint> targets, List <float> weights,
                              ref bool[] forwardWitness, ref bool[] backwardWitness, uint vertexToSkip)
        {
            if (_hopLimit == 1)
            {
                this.ExistsOneHop(graph, source, targets, weights, ref forwardWitness, ref backwardWitness);
                return;
            }

            // creates the settled list.
            var   backwardSettled = new HashSet <uint>();
            var   forwardSettled = new HashSet <uint>();
            var   backwardTargets = new HashSet <uint>();
            var   forwardTargets = new HashSet <uint>();
            float forwardMaxWeight = 0, backwardMaxWeight = 0;

            for (int idx = 0; idx < weights.Count; idx++)
            {
                if (!forwardWitness[idx])
                {
                    forwardTargets.Add(targets[idx]);
                    if (forwardMaxWeight < weights[idx])
                    {
                        forwardMaxWeight = weights[idx];
                    }
                }
                if (!backwardWitness[idx])
                {
                    backwardTargets.Add(targets[idx]);
                    if (backwardMaxWeight < weights[idx])
                    {
                        backwardMaxWeight = weights[idx];
                    }
                }
            }
            if (forwardMaxWeight == 0 && backwardMaxWeight == 0)
            { // no need to search!
                return;
            }

            // creates the priorty queue.
            var forwardMinWeight  = new Dictionary <uint, float>();
            var backwardMinWeight = new Dictionary <uint, float>();

            _heap.Clear();
            _heap.Push(new SettledVertex(source, 0, 0, forwardMaxWeight > 0, backwardMaxWeight > 0), 0);

            // keep looping until the queue is empty or the target is found!
            var edgeEnumerator = graph.GetEdgeEnumerator();

            while (_heap.Count > 0)
            { // pop the first customer.
                var current = _heap.Pop();
                if (current.Hops + 1 < _hopLimit)
                {
                    if (current.VertexId == vertexToSkip)
                    { // this is the vertex being contracted.
                        continue;
                    }
                    var forwardWasSettled  = forwardSettled.Contains(current.VertexId);
                    var backwardWasSettled = backwardSettled.Contains(current.VertexId);
                    if (forwardWasSettled && backwardWasSettled)
                    { // both are already settled.
                        continue;
                    }

                    if (current.Forward)
                    { // this is a forward settle.
                        forwardSettled.Add(current.VertexId);
                        forwardMinWeight.Remove(current.VertexId);
                        if (forwardTargets.Contains(current.VertexId))
                        {
                            for (var i = 0; i < targets.Count; i++)
                            {
                                if (targets[i] == current.VertexId)
                                {
                                    forwardWitness[i] = current.Weight < weights[i];
                                    forwardTargets.Remove(current.VertexId);
                                }
                            }
                        }
                    }
                    if (current.Backward)
                    { // this is a backward settle.
                        backwardSettled.Add(current.VertexId);
                        backwardMinWeight.Remove(current.VertexId);
                        if (backwardTargets.Contains(current.VertexId))
                        {
                            for (var i = 0; i < targets.Count; i++)
                            {
                                if (targets[i] == current.VertexId)
                                {
                                    backwardWitness[i] = current.Weight < weights[i];
                                    backwardTargets.Remove(current.VertexId);
                                }
                            }
                        }
                    }

                    if (forwardTargets.Count == 0 &&
                        backwardTargets.Count == 0)
                    { // there is nothing left to check.
                        break;
                    }

                    if (forwardSettled.Count >= _maxSettles &&
                        backwardSettled.Count >= _maxSettles)
                    { // do not continue searching.
                        break;
                    }

                    var doForward  = current.Forward && forwardTargets.Count > 0 && !forwardWasSettled;
                    var doBackward = current.Backward && backwardTargets.Count > 0 && !backwardWasSettled;
                    if (doForward || doBackward)
                    { // get the neighbours.
                        edgeEnumerator.MoveTo(current.VertexId);
                        while (edgeEnumerator.MoveNext())
                        { // move next.
                            var neighbour = edgeEnumerator.Neighbour;

                            float neighbourWeight;
                            bool? neighbourDirection;
                            ContractedEdgeDataSerializer.Deserialize(edgeEnumerator.Data0,
                                                                     out neighbourWeight, out neighbourDirection);
                            var neighbourCanMoveForward  = neighbourDirection == null || neighbourDirection.Value;
                            var neighbourCanMoveBackward = neighbourDirection == null || !neighbourDirection.Value;

                            var totalNeighbourWeight = current.Weight + neighbourWeight;
                            var doNeighbourForward   = doForward && neighbourCanMoveForward && totalNeighbourWeight < forwardMaxWeight &&
                                                       !forwardSettled.Contains(neighbour);
                            var doNeighbourBackward = doBackward && neighbourCanMoveBackward && totalNeighbourWeight < backwardMaxWeight &&
                                                      !backwardSettled.Contains(neighbour);
                            if (doNeighbourBackward || doNeighbourForward)
                            {
                                float existingWeight;
                                if (doNeighbourForward)
                                {
                                    if (forwardMinWeight.TryGetValue(neighbour, out existingWeight))
                                    {
                                        if (existingWeight <= totalNeighbourWeight)
                                        {
                                            doNeighbourForward = false;
                                        }
                                        else
                                        {
                                            forwardMinWeight[neighbour] = totalNeighbourWeight;
                                        }
                                    }
                                    else
                                    {
                                        forwardMinWeight[neighbour] = totalNeighbourWeight;
                                    }
                                }
                                if (doNeighbourBackward)
                                {
                                    if (backwardMinWeight.TryGetValue(neighbour, out existingWeight))
                                    {
                                        if (existingWeight <= totalNeighbourWeight)
                                        {
                                            doNeighbourBackward = false;
                                        }
                                        else
                                        {
                                            backwardMinWeight[neighbour] = totalNeighbourWeight;
                                        }
                                    }
                                    else
                                    {
                                        backwardMinWeight[neighbour] = totalNeighbourWeight;
                                    }
                                }

                                if (doNeighbourBackward || doNeighbourForward)
                                { // add to heap.
                                    var newSettle = new SettledVertex(neighbour,
                                                                      totalNeighbourWeight, current.Hops + 1, doNeighbourForward, doNeighbourBackward);
                                    _heap.Push(newSettle, newSettle.Weight);
                                }
                            }
                        }
                    }
                }
            }
        }
Ejemplo n.º 13
0
        public void Run(DirectedGraph graph, DirectedGraph witnessGraph, uint vertex, HashSet <uint> dirty)
        {
            try
            {
                forwardSettled.Clear();
                backwardSettled.Clear();
                pathTree.Clear();
                pointerHeap.Clear();
                witnesses.Clear();

                var p = pathTree.AddSettledVertex(vertex, new WeightAndDir <float>()
                {
                    Direction = new Dir(true, true),
                    Weight    = 0
                }, 0, Constants.NO_VERTEX);
                pointerHeap.Push(p, 0);

                // dequeue vertices until stopping conditions are reached.
                var enumerator = graph.GetEdgeEnumerator();

                // calculate max forward/backward weight.
                var forwardMax  = 0f;
                var backwardMax = 0f;
                enumerator.MoveTo(vertex);
                var nextEnumerator = graph.GetEdgeEnumerator();
                while (enumerator.MoveNext())
                {
                    var nVertex1 = enumerator.Neighbour;

                    if (dirty != null &&
                        !dirty.Contains(nVertex1))
                    { // this is not a hop-2 to consider.
                        continue;
                    }

                    ContractedEdgeDataSerializer.Deserialize(enumerator.Data0,
                                                             out Dir dir1, out float weight1);
                    var p1 = pathTree.AddSettledVertex(nVertex1, weight1, dir1, 1, vertex);
                    pointerHeap.Push(p1, weight1);

                    nextEnumerator.MoveTo(enumerator.Neighbour);
                    while (nextEnumerator.MoveNext())
                    {
                        var nVertex2 = nextEnumerator.Neighbour;
                        if (nVertex2 == vertex)
                        { // no u-turns.
                            continue;
                        }

                        ContractedEdgeDataSerializer.Deserialize(nextEnumerator.Data0,
                                                                 out Dir dir2, out float weight2);

                        dir2._val = (byte)(dir1._val & dir2._val);
                        if (dir2._val == 0)
                        {
                            continue;
                        }

                        var weight2Hops = weight1 + weight2;
                        var p2          = pathTree.AddSettledVertex(nVertex2, weight2Hops, dir2, 2, nVertex1);
                        pointerHeap.Push(p2, weight2Hops);

                        if (dir2.F && weight2Hops > forwardMax)
                        {
                            forwardMax = weight2Hops;
                        }
                        if (dir2.B && weight2Hops > backwardMax)
                        {
                            backwardMax = weight2Hops;
                        }
                    }
                }

                if (forwardMax == 0 &&
                    backwardMax == 0)
                {
                    return;
                }

                while (pointerHeap.Count > 0)
                {
                    var cPointer = pointerHeap.Pop();
                    pathTree.GetSettledVertex(cPointer, out uint cVertex, out WeightAndDir <float> cWeight,
                                              out uint cHops, out uint pVertex);

                    if (cHops == 2)
                    { // check if the search can stop or not.
                        var witness = new Shortcut <float>();
                        witness.Forward  = float.MaxValue;
                        witness.Backward = float.MaxValue;
                        if (cWeight.Direction.F &&
                            forwardSettled.TryGetValue(cVertex, out float best) &&
                            best < cWeight.Weight)
                        { // this is a 2-hop and vertex was settled before, we have a witness!
                            witness.Forward = best;
                        }
                        if (cWeight.Direction.B &&
                            backwardSettled.TryGetValue(cVertex, out best) &&
                            best < cWeight.Weight)
                        { // this is a 2-hop and vertex was settled before, we have a witness!
                            witness.Backward = best;
                        }
                        if (witness.Backward != float.MaxValue ||
                            witness.Forward != float.MaxValue)
                        {     // report witness here.
                            if (vertex != cVertex)
                            { // TODO: check this, how can they ever be the same?
                                witnesses.Add(new Witness()
                                {
                                    Vertex1  = vertex,
                                    Vertex2  = cVertex,
                                    Forward  = witness.Forward,
                                    Backward = witness.Backward
                                });
                            }
                        }
                    }

                    if (forwardSettled.Count > _maxSettles ||
                        backwardSettled.Count > _maxSettles)
                    { // over settled count.
                        break;
                    }

                    if (cWeight.Weight > backwardMax &&
                        cWeight.Weight > forwardMax)
                    { // over max weights.
                        break;
                    }

                    if (forwardSettled.ContainsKey(cVertex) ||
                        cWeight.Weight > forwardMax)
                    {
                        cWeight.Direction = new Dir(false, cWeight.Direction.B);
                    }
                    if (backwardSettled.ContainsKey(cVertex) ||
                        cWeight.Weight > backwardMax)
                    {
                        cWeight.Direction = new Dir(cWeight.Direction.F, false);
                    }

                    var isRelevant = false;
                    if (cWeight.Direction.F)
                    {
                        forwardSettled.Add(cVertex, cWeight.Weight);
                        isRelevant = true;
                    }
                    if (cWeight.Direction.B)
                    {
                        backwardSettled.Add(cVertex, cWeight.Weight);
                        isRelevant = true;
                    }

                    if (!isRelevant)
                    { // not forward, not backwards.
                        continue;
                    }

                    cHops++;
                    if (cHops >= _hopLimit)
                    { // over hop limit, don't queue.
                        continue;
                    }

                    if (cHops == 1)
                    {
                        if (dirty == null)
                        { // all hops 1 are already queued.
                            continue;
                        }
                    }
                    else if (cHops == 2)
                    {
                        if (dirty == null ||
                            dirty.Contains(cVertex))
                        { // all these hops 2 are already queue.
                            continue;
                        }
                    }

                    enumerator.MoveTo(cVertex);
                    while (enumerator.MoveNext())
                    {
                        var nVertex = enumerator.Neighbour;

                        if (nVertex == pVertex)
                        { // no going back.
                            continue;
                        }

                        if (cHops == 1)
                        {     // check if the neighbour is dirty.
                            if (dirty.Contains(nVertex))
                            { // skip dirty vertices, they are already in the queue.
                                continue;
                            }
                        }

                        Dir   nDir;
                        float nWeight;
                        ContractedEdgeDataSerializer.Deserialize(enumerator.Data0,
                                                                 out nDir, out nWeight);

                        nDir._val = (byte)(cWeight.Direction._val & nDir._val);
                        if (nDir._val == 0)
                        {
                            continue;
                        }

                        nWeight = nWeight + cWeight.Weight;

                        if (nDir.F && nWeight > forwardMax)
                        {
                            nDir = new Dir(false, nDir.B);
                            if (nDir._val == 0)
                            {
                                continue;
                            }
                        }
                        if (nDir.B && nWeight > backwardMax)
                        {
                            nDir = new Dir(nDir.F, false);
                            if (nDir._val == 0)
                            {
                                continue;
                            }
                        }

                        var nPoiner = pathTree.AddSettledVertex(nVertex, nWeight, nDir, cHops, cVertex);
                        pointerHeap.Push(nPoiner, nWeight);
                    }
                }

                if (witnesses.Count > 0)
                {
                    lock (witnessGraph)
                    {
                        foreach (var witness in witnesses)
                        {
                            //witnessGraph.AddOrUpdateEdge(witness.Item1, witness.Item2, witness.Item3.Forward,
                            //        witness.Item3.Backward);
                            witnessGraph.AddOrUpdateEdge(witness.Vertex1, witness.Vertex2,
                                                         witness.Forward, witness.Backward);
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }
Ejemplo n.º 14
0
        public void TestRestrictedNetwork2()
        {
            // build graph.
            var graph = new DirectedDynamicGraph(ContractedEdgeDataSerializer.DynamicFixedSize);

            graph.AddEdge(0, 1, 100, null);
            graph.AddEdge(1, 0, 100, null);
            graph.AddEdge(1, 2, 100, null);
            graph.AddEdge(2, 1, 100, null);
            graph.AddEdge(1, 3, 100, null);
            graph.AddEdge(3, 1, 100, null);
            graph.AddEdge(1, 4, 100, null);
            graph.AddEdge(4, 1, 100, null);
            graph.AddEdge(2, 3, 100, null);
            graph.AddEdge(3, 2, 100, null);
            graph.Compress();

            // contract graph.
            var priorities = new Dictionary <uint, float>();

            priorities.Add(1, 0);
            priorities.Add(0, 1);
            priorities.Add(2, 2);
            priorities.Add(3, 3);
            priorities.Add(4, 4);
            var hierarchyBuilder = new HierarchyBuilder(graph,
                                                        new MockPriorityCalculator(priorities),
                                                        new DykstraWitnessCalculator(int.MaxValue), (i) =>
            {
                if (i == 0 || i == 1 || i == 4)
                {
                    return(new uint[][]
                    {
                        new uint[] { 0, 1, 4 }
                    });
                }
                return(null);
            });

            hierarchyBuilder.Run();

            // check all edges.
            ContractedEdgeData edgeData;
            var edge = graph.GetEdgeEnumerator(0).FirstOrDefault(x =>
            {
                if (x.Neighbour == 4)
                {
                    edgeData = ContractedEdgeDataSerializer.Deserialize(x.Data[0], Constants.NO_VERTEX);
                    return(edgeData.Direction == true);
                }
                return(false);
            });

            Assert.IsNotNull(edge);
            edgeData = ContractedEdgeDataSerializer.Deserialize(edge.Data[0], Constants.NO_VERTEX);
            Assert.AreEqual(500, edgeData.Weight);
            Assert.AreEqual(true, edgeData.Direction);
            Assert.AreEqual(1, edge.GetContracted());
            edge = graph.GetEdgeEnumerator(0).FirstOrDefault(x =>
            {
                if (x.Neighbour == 4)
                {
                    edgeData = ContractedEdgeDataSerializer.Deserialize(x.Data[0], Constants.NO_VERTEX);
                    return(edgeData.Direction == false);
                }
                return(false);
            });
            Assert.IsNotNull(edge);
            edgeData = ContractedEdgeDataSerializer.Deserialize(edge.Data[0], Constants.NO_VERTEX);
            Assert.AreEqual(200, edgeData.Weight);
            Assert.AreEqual(false, edgeData.Direction);
            Assert.AreEqual(1, edge.GetContracted());
            edge = graph.GetEdgeEnumerator(0).FirstOrDefault(x => x.Neighbour == 2);
            Assert.IsNotNull(edge);
            edgeData = ContractedEdgeDataSerializer.Deserialize(edge.Data[0], Constants.NO_VERTEX);
            Assert.AreEqual(200, edgeData.Weight);
            Assert.AreEqual(null, edgeData.Direction);
            Assert.AreEqual(1, edge.GetContracted());
            edge = graph.GetEdgeEnumerator(0).FirstOrDefault(x => x.Neighbour == 3);
            Assert.IsNotNull(edge);
            edgeData = ContractedEdgeDataSerializer.Deserialize(edge.Data[0], Constants.NO_VERTEX);
            Assert.AreEqual(200, edgeData.Weight);
            Assert.AreEqual(null, edgeData.Direction);
            Assert.AreEqual(1, edge.GetContracted());

            edge = graph.GetEdgeEnumerator(1).FirstOrDefault(x => x.Neighbour == 0);
            Assert.IsNotNull(edge);
            edgeData = ContractedEdgeDataSerializer.Deserialize(edge.Data[0], Constants.NO_VERTEX);
            Assert.AreEqual(100, edgeData.Weight);
            Assert.AreEqual(null, edgeData.Direction);
            Assert.AreEqual(null, edge.GetContracted());
            edge = graph.GetEdgeEnumerator(1).FirstOrDefault(x => x.Neighbour == 2);
            Assert.IsNotNull(edge);
            edgeData = ContractedEdgeDataSerializer.Deserialize(edge.Data[0], Constants.NO_VERTEX);
            Assert.AreEqual(100, edgeData.Weight);
            Assert.AreEqual(null, edgeData.Direction);
            Assert.AreEqual(null, edge.GetContracted());
            edge = graph.GetEdgeEnumerator(1).FirstOrDefault(x => x.Neighbour == 3);
            Assert.IsNotNull(edge);
            edgeData = ContractedEdgeDataSerializer.Deserialize(edge.Data[0], Constants.NO_VERTEX);
            Assert.AreEqual(100, edgeData.Weight);
            Assert.AreEqual(null, edgeData.Direction);
            Assert.AreEqual(null, edge.GetContracted());
            edge = graph.GetEdgeEnumerator(1).FirstOrDefault(x => x.Neighbour == 4);
            Assert.IsNotNull(edge);
            edgeData = ContractedEdgeDataSerializer.Deserialize(edge.Data[0], Constants.NO_VERTEX);
            Assert.AreEqual(100, edgeData.Weight);
            Assert.AreEqual(null, edgeData.Direction);
            Assert.AreEqual(null, edge.GetContracted());

            edge = graph.GetEdgeEnumerator(2).FirstOrDefault(x => x.Neighbour == 3);
            Assert.IsNotNull(edge);
            edgeData = ContractedEdgeDataSerializer.Deserialize(edge.Data[0], Constants.NO_VERTEX);
            Assert.AreEqual(100, edgeData.Weight);
            Assert.AreEqual(null, edgeData.Direction);
            Assert.AreEqual(null, edge.GetContracted());
            edge = graph.GetEdgeEnumerator(2).FirstOrDefault(x => x.Neighbour == 4);
            Assert.IsNotNull(edge);
            edgeData = ContractedEdgeDataSerializer.Deserialize(edge.Data[0], Constants.NO_VERTEX);
            Assert.AreEqual(200, edgeData.Weight);
            Assert.AreEqual(null, edgeData.Direction);
            Assert.AreEqual(1, edge.GetContracted());

            edge = graph.GetEdgeEnumerator(3).FirstOrDefault(x => x.Neighbour == 4);
            Assert.IsNotNull(edge);
            edgeData = ContractedEdgeDataSerializer.Deserialize(edge.Data[0], Constants.NO_VERTEX);
            Assert.AreEqual(200, edgeData.Weight);
            Assert.AreEqual(null, edgeData.Direction);
            Assert.AreEqual(1, edge.GetContracted());
        }
Ejemplo n.º 15
0
        public void TestQuadrilateralOneWay()
        {
            // build graph.
            var graph = new DirectedGraph(ContractedEdgeDataSerializer.Size);

            graph.AddEdge(0, 2, ContractedEdgeDataSerializer.SerializeMeta(new ContractedEdgeData()
            {
                ContractedId = Constants.NO_VERTEX,
                Direction    = true,
                Weight       = 100
            }));
            graph.AddEdge(2, 0, ContractedEdgeDataSerializer.SerializeMeta(new ContractedEdgeData()
            {
                ContractedId = Constants.NO_VERTEX,
                Direction    = false,
                Weight       = 100
            }));
            graph.AddEdge(0, 3, ContractedEdgeDataSerializer.SerializeMeta(new ContractedEdgeData()
            {
                ContractedId = Constants.NO_VERTEX,
                Direction    = false,
                Weight       = 10
            }));
            graph.AddEdge(3, 0, ContractedEdgeDataSerializer.SerializeMeta(new ContractedEdgeData()
            {
                ContractedId = Constants.NO_VERTEX,
                Direction    = true,
                Weight       = 10
            }));
            graph.AddEdge(1, 2, ContractedEdgeDataSerializer.SerializeMeta(new ContractedEdgeData()
            {
                ContractedId = Constants.NO_VERTEX,
                Direction    = false,
                Weight       = 1000
            }));
            graph.AddEdge(2, 1, ContractedEdgeDataSerializer.SerializeMeta(new ContractedEdgeData()
            {
                ContractedId = Constants.NO_VERTEX,
                Direction    = true,
                Weight       = 1000
            }));
            graph.AddEdge(1, 3, ContractedEdgeDataSerializer.SerializeMeta(new ContractedEdgeData()
            {
                ContractedId = Constants.NO_VERTEX,
                Direction    = true,
                Weight       = 10000
            }));
            graph.AddEdge(3, 1, ContractedEdgeDataSerializer.SerializeMeta(new ContractedEdgeData()
            {
                ContractedId = Constants.NO_VERTEX,
                Direction    = false,
                Weight       = 10000
            }));
            graph.Compress(false);

            var witnessCalculator = new DykstraWitnessCalculator(int.MaxValue);

            // calculate witnesses for 0.
            var forwardWitnesses  = new bool[1];
            var backwardWitnesses = new bool[1];

            witnessCalculator.Calculate(graph, 2, new List <uint>(new uint[] { 3 }), new List <float>(new float[] { 110 }),
                                        ref forwardWitnesses, ref backwardWitnesses, 0);
            Assert.AreEqual(false, forwardWitnesses[0]);
            Assert.AreEqual(false, backwardWitnesses[0]);

            // calculate witnesses for 0.
            forwardWitnesses  = new bool[1];
            backwardWitnesses = new bool[1];
            witnessCalculator.Calculate(graph, 3, new List <uint>(new uint[] { 2 }), new List <float>(new float[] { 110 }),
                                        ref forwardWitnesses, ref backwardWitnesses, 0);
            Assert.AreEqual(false, forwardWitnesses[0]);
            Assert.AreEqual(false, backwardWitnesses[0]);

            // calculate witnesses for 2.
            forwardWitnesses  = new bool[1];
            backwardWitnesses = new bool[1];
            witnessCalculator.Calculate(graph, 0, new List <uint>(new uint[] { 1 }), new List <float>(new float[] { 1100 }),
                                        ref forwardWitnesses, ref backwardWitnesses, 2);
            Assert.AreEqual(false, forwardWitnesses[0]);
            Assert.AreEqual(false, backwardWitnesses[0]);

            // calculate witnesses for 2.
            forwardWitnesses  = new bool[1];
            backwardWitnesses = new bool[1];
            witnessCalculator.Calculate(graph, 1, new List <uint>(new uint[] { 0 }), new List <float>(new float[] { 1100 }),
                                        ref forwardWitnesses, ref backwardWitnesses, 2);
            Assert.AreEqual(false, forwardWitnesses[0]);
            Assert.AreEqual(false, backwardWitnesses[0]);

            // calculate witnesses for 1.
            forwardWitnesses  = new bool[1];
            backwardWitnesses = new bool[1];
            witnessCalculator.Calculate(graph, 3, new List <uint>(new uint[] { 2 }), new List <float>(new float[] { 11000 }),
                                        ref forwardWitnesses, ref backwardWitnesses, 1);
            Assert.AreEqual(true, forwardWitnesses[0]);
            Assert.AreEqual(false, backwardWitnesses[0]);

            // calculate witnesses for 1.
            forwardWitnesses  = new bool[1];
            backwardWitnesses = new bool[1];
            witnessCalculator.Calculate(graph, 2, new List <uint>(new uint[] { 3 }), new List <float>(new float[] { 11000 }),
                                        ref forwardWitnesses, ref backwardWitnesses, 1);
            Assert.AreEqual(false, forwardWitnesses[0]);
            Assert.AreEqual(true, backwardWitnesses[0]);

            // calculate witnesses for 3.
            forwardWitnesses  = new bool[1];
            backwardWitnesses = new bool[1];
            witnessCalculator.Calculate(graph, 0, new List <uint>(new uint[] { 1 }), new List <float>(new float[] { 10010 }),
                                        ref forwardWitnesses, ref backwardWitnesses, 3);
            Assert.AreEqual(true, forwardWitnesses[0]);
            Assert.AreEqual(false, backwardWitnesses[0]);

            // calculate witnesses for 3.
            forwardWitnesses  = new bool[1];
            backwardWitnesses = new bool[1];
            witnessCalculator.Calculate(graph, 1, new List <uint>(new uint[] { 0 }), new List <float>(new float[] { 10010 }),
                                        ref forwardWitnesses, ref backwardWitnesses, 3);
            Assert.AreEqual(false, forwardWitnesses[0]);
            Assert.AreEqual(true, backwardWitnesses[0]);
        }
Ejemplo n.º 16
0
        public void TestAddOrUpdateEdge()
        {
            // build graph.
            var graph = new DirectedMetaGraph(ContractedEdgeDataSerializer.Size,
                                              ContractedEdgeDataSerializer.MetaSize);

            graph.AddEdge(0, 1, 100, null, Constants.NO_VERTEX);

            // update.
            graph.AddOrUpdateEdge(0, 1, 99, null, Constants.NO_VERTEX);

            // check result.
            var edges = new List <MetaEdge>(graph.GetEdgeEnumerator(0).Where(x => x.Neighbour == 1));

            Assert.AreEqual(1, edges.Count);
            Assert.AreEqual(1, edges[0].Neighbour);
            var edgeData = ContractedEdgeDataSerializer.Deserialize(edges[0].Data[0], edges[0].MetaData[0]);

            Assert.AreEqual(null, edgeData.Direction);
            Assert.AreEqual(Constants.NO_VERTEX, edgeData.ContractedId);
            Assert.AreEqual(99, edgeData.Weight);

            // build graph.
            graph = new DirectedMetaGraph(ContractedEdgeDataSerializer.Size,
                                          ContractedEdgeDataSerializer.MetaSize);
            graph.AddEdge(0, 1, 100, null, Constants.NO_VERTEX);

            // update.
            graph.AddOrUpdateEdge(0, 1, 101, null, Constants.NO_VERTEX);

            // check result.
            edges = new List <MetaEdge>(graph.GetEdgeEnumerator(0).Where(x => x.Neighbour == 1));
            Assert.AreEqual(1, edges.Count);
            Assert.AreEqual(1, edges[0].Neighbour);
            edgeData = ContractedEdgeDataSerializer.Deserialize(edges[0].Data[0], edges[0].MetaData[0]);
            Assert.AreEqual(null, edgeData.Direction);
            Assert.AreEqual(Constants.NO_VERTEX, edgeData.ContractedId);
            Assert.AreEqual(100, edgeData.Weight);

            // build graph.
            graph = new DirectedMetaGraph(ContractedEdgeDataSerializer.Size,
                                          ContractedEdgeDataSerializer.MetaSize);
            graph.AddEdge(0, 1, 100, true, Constants.NO_VERTEX);

            // update.
            graph.AddOrUpdateEdge(0, 1, 99, true, Constants.NO_VERTEX);

            // check result.
            edges = new List <MetaEdge>(graph.GetEdgeEnumerator(0).Where(x => x.Neighbour == 1));
            Assert.AreEqual(1, edges.Count);
            Assert.AreEqual(1, edges[0].Neighbour);
            edgeData = ContractedEdgeDataSerializer.Deserialize(edges[0].Data[0], edges[0].MetaData[0]);
            Assert.AreEqual(true, edgeData.Direction);
            Assert.AreEqual(Constants.NO_VERTEX, edgeData.ContractedId);
            Assert.AreEqual(99, edgeData.Weight);

            // build graph.
            graph = new DirectedMetaGraph(ContractedEdgeDataSerializer.Size,
                                          ContractedEdgeDataSerializer.MetaSize);
            graph.AddEdge(0, 1, 100, null, Constants.NO_VERTEX);

            // update.
            graph.AddOrUpdateEdge(0, 1, 99, true, Constants.NO_VERTEX);

            // check result.
            var edge = graph.GetEdgeEnumerator(0).First(x => x.Neighbour == 1 &&
                                                        ContractedEdgeDataSerializer.Deserialize(x.Data[0], x.MetaData[0]).Direction == false);

            Assert.IsNotNull(edge);
            edgeData = ContractedEdgeDataSerializer.Deserialize(edge.Data[0], edge.MetaData[0]);
            Assert.AreEqual(Constants.NO_VERTEX, edgeData.ContractedId);
            Assert.AreEqual(100, edgeData.Weight);

            edge = graph.GetEdgeEnumerator(0).First(x => x.Neighbour == 1 &&
                                                    ContractedEdgeDataSerializer.Deserialize(x.Data[0], x.MetaData[0]).Direction == true);
            Assert.IsNotNull(edge);
            edgeData = ContractedEdgeDataSerializer.Deserialize(edge.Data[0], edge.MetaData[0]);
            Assert.AreEqual(Constants.NO_VERTEX, edgeData.ContractedId);
            Assert.AreEqual(99, edgeData.Weight);

            // build graph.
            graph = new DirectedMetaGraph(ContractedEdgeDataSerializer.Size,
                                          ContractedEdgeDataSerializer.MetaSize);
            graph.AddEdge(0, 1, 100, false, Constants.NO_VERTEX);

            // update.
            graph.AddOrUpdateEdge(0, 1, 99, true, Constants.NO_VERTEX);

            // check result.
            edge = graph.GetEdgeEnumerator(0).First(x => x.Neighbour == 1 &&
                                                    ContractedEdgeDataSerializer.Deserialize(x.Data[0], x.MetaData[0]).Direction == false);
            Assert.IsNotNull(edge);
            edgeData = ContractedEdgeDataSerializer.Deserialize(edge.Data[0], edge.MetaData[0]);
            Assert.AreEqual(Constants.NO_VERTEX, edgeData.ContractedId);
            Assert.AreEqual(100, edgeData.Weight);

            edge = graph.GetEdgeEnumerator(0).First(x => x.Neighbour == 1 &&
                                                    ContractedEdgeDataSerializer.Deserialize(x.Data[0], x.MetaData[0]).Direction == true);
            Assert.IsNotNull(edge);
            edgeData = ContractedEdgeDataSerializer.Deserialize(edge.Data[0], edge.MetaData[0]);
            Assert.AreEqual(Constants.NO_VERTEX, edgeData.ContractedId);
            Assert.AreEqual(99, edgeData.Weight);

            // build graph.
            graph = new DirectedMetaGraph(ContractedEdgeDataSerializer.Size,
                                          ContractedEdgeDataSerializer.MetaSize);
            graph.AddEdge(0, 1, 100, false, Constants.NO_VERTEX);
            graph.AddEdge(0, 1, 99, true, Constants.NO_VERTEX);

            // update.
            graph.AddOrUpdateEdge(0, 1, 98, null, Constants.NO_VERTEX);

            // check result.
            edge = graph.GetEdgeEnumerator(0).First(x => x.Neighbour == 1 &&
                                                    ContractedEdgeDataSerializer.Deserialize(x.Data[0], x.MetaData[0]).Direction == null);
            Assert.IsNotNull(edge);
            edgeData = ContractedEdgeDataSerializer.Deserialize(edge.Data[0], edge.MetaData[0]);
            Assert.AreEqual(Constants.NO_VERTEX, edgeData.ContractedId);
            Assert.AreEqual(98, edgeData.Weight);

            // build graph.
            graph = new DirectedMetaGraph(ContractedEdgeDataSerializer.Size,
                                          ContractedEdgeDataSerializer.MetaSize);
            graph.AddEdge(0, 1, 100, false, Constants.NO_VERTEX);
            graph.AddEdge(0, 1, 98, true, Constants.NO_VERTEX);

            // update.
            graph.AddOrUpdateEdge(0, 1, 99, null, Constants.NO_VERTEX);

            // check result.
            edge = graph.GetEdgeEnumerator(0).First(x => x.Neighbour == 1 &&
                                                    ContractedEdgeDataSerializer.Deserialize(x.Data[0], x.MetaData[0]).Direction == false);
            Assert.IsNotNull(edge);
            edgeData = ContractedEdgeDataSerializer.Deserialize(edge.Data[0], edge.MetaData[0]);
            Assert.AreEqual(Constants.NO_VERTEX, edgeData.ContractedId);
            Assert.AreEqual(99, edgeData.Weight);

            edge = graph.GetEdgeEnumerator(0).First(x => x.Neighbour == 1 &&
                                                    ContractedEdgeDataSerializer.Deserialize(x.Data[0], x.MetaData[0]).Direction == true);
            Assert.IsNotNull(edge);
            edgeData = ContractedEdgeDataSerializer.Deserialize(edge.Data[0], edge.MetaData[0]);
            Assert.AreEqual(Constants.NO_VERTEX, edgeData.ContractedId);
            Assert.AreEqual(98, edgeData.Weight);

            // build graph.
            graph = new DirectedMetaGraph(ContractedEdgeDataSerializer.Size,
                                          ContractedEdgeDataSerializer.MetaSize);
            graph.AddEdge(0, 1, 100, null, Constants.NO_VERTEX);

            // update.
            graph.AddOrUpdateEdge(0, 2, 99, null, Constants.NO_VERTEX);

            // check result.
            edge = graph.GetEdgeEnumerator(0).First(x => x.Neighbour == 2 &&
                                                    ContractedEdgeDataSerializer.Deserialize(x.Data[0], x.MetaData[0]).Direction == null);
            Assert.IsNotNull(edge);
            edgeData = ContractedEdgeDataSerializer.Deserialize(edge.Data[0], edge.MetaData[0]);
            Assert.AreEqual(Constants.NO_VERTEX, edgeData.ContractedId);
            Assert.AreEqual(99, edgeData.Weight);
        }
Ejemplo n.º 17
0
        /// <summary>
        /// Calculates witness paths.
        /// </summary>
        public virtual void Calculate(DirectedGraph graph, WeightHandler <T> weightHandler, uint vertex,
                                      uint source, Dictionary <uint, Shortcut <T> > targets, int maxSettles, int hopLimit)
        {
            pathTree.Clear();
            pointerHeap.Clear();

            var forwardSettled  = new HashSet <uint>();
            var backwardSettled = new HashSet <uint>();

            var forwardTargets  = new HashSet <uint>();
            var backwardTargets = new HashSet <uint>();

            var maxWeight = 0f;

            foreach (var targetPair in targets)
            {
                var target   = targetPair.Key;
                var shortcut = targetPair.Value;
                var e        = new OriginalEdge(source, target);

                var shortcutForward = weightHandler.GetMetric(shortcut.Forward);
                if (shortcutForward > 0 && shortcutForward < float.MaxValue)
                {
                    forwardTargets.Add(e.Vertex2);
                    if (shortcutForward > maxWeight)
                    {
                        maxWeight = shortcutForward;
                    }
                }
                var shortcutBackward = weightHandler.GetMetric(shortcut.Backward);
                if (shortcutBackward > 0 && shortcutBackward < float.MaxValue)
                {
                    backwardTargets.Add(e.Vertex2);
                    if (shortcutBackward > maxWeight)
                    {
                        maxWeight = shortcutBackward;
                    }
                }
            }

            // queue the source.
            pathTree.Clear();
            pointerHeap.Clear();
            var p = pathTree.AddSettledVertex(source, new WeightAndDir <float>()
            {
                Direction = new Dir(true, true),
                Weight    = 0
            }, 0);

            pointerHeap.Push(p, 0);

            // dequeue vertices until stopping conditions are reached.
            var cVertex = Constants.NO_VERTEX;
            WeightAndDir <float> cWeight;
            var cHops      = uint.MaxValue;
            var enumerator = graph.GetEdgeEnumerator();

            while (pointerHeap.Count > 0)
            {
                var cPointer = pointerHeap.Pop();
                pathTree.GetSettledVertex(cPointer, out cVertex, out cWeight, out cHops);

                if (cVertex == vertex)
                {
                    continue;
                }

                if (cWeight.Weight >= maxWeight)
                {
                    break;
                }

                if (forwardSettled.Contains(cVertex) ||
                    forwardTargets.Count == 0 ||
                    forwardSettled.Count > maxSettles)
                {
                    cWeight.Direction = new Dir(false, cWeight.Direction.B);
                }
                if (backwardSettled.Contains(cVertex) ||
                    backwardTargets.Count == 0 ||
                    backwardSettled.Count > maxSettles)
                {
                    cWeight.Direction = new Dir(cWeight.Direction.F, false);
                }

                if (cWeight.Direction.F)
                {
                    forwardSettled.Add(cVertex);
                    if (forwardTargets.Contains(cVertex))
                    { // target reached, evaluate it as a shortcut.
                        Shortcut <T> shortcut;
                        if (targets.TryGetValue(cVertex, out shortcut))
                        {
                            var shortcutForward = weightHandler.GetMetric(shortcut.Forward);
                            if (shortcutForward > cWeight.Weight)
                            { // a witness path was found, don't add a shortcut.
                                shortcut.Forward = weightHandler.Zero;
                                targets[cVertex] = shortcut;
                            }
                        }
                        forwardTargets.Remove(cVertex);
                        if (forwardTargets.Count == 0)
                        {
                            if (backwardTargets.Count == 0)
                            {
                                break;
                            }
                            cWeight.Direction = new Dir(false, cWeight.Direction.B);
                            if (!cWeight.Direction.F && !cWeight.Direction.B)
                            {
                                continue;
                            }
                        }
                    }
                }
                if (cWeight.Direction.B)
                {
                    backwardSettled.Add(cVertex);
                    if (backwardTargets.Contains(cVertex))
                    { // target reached, evaluate it as a shortcut.
                        Shortcut <T> shortcut;
                        if (targets.TryGetValue(cVertex, out shortcut))
                        {
                            var shortcutBackward = weightHandler.GetMetric(shortcut.Backward);
                            if (shortcutBackward > cWeight.Weight)
                            { // a witness path was found, don't add a shortcut.
                                shortcut.Backward = weightHandler.Zero;
                                targets[cVertex]  = shortcut;
                            }
                        }
                        backwardTargets.Remove(cVertex);
                        if (backwardTargets.Count == 0)
                        {
                            if (forwardTargets.Count == 0)
                            {
                                break;
                            }
                            cWeight.Direction = new Dir(cWeight.Direction.F, false);
                            if (!cWeight.Direction.F && !cWeight.Direction.B)
                            {
                                continue;
                            }
                        }
                    }
                }

                if (cHops + 1 >= hopLimit)
                {
                    continue;
                }

                if (forwardSettled.Count > maxSettles &&
                    backwardSettled.Count > maxSettles)
                {
                    continue;
                }

                enumerator.MoveTo(cVertex);
                while (enumerator.MoveNext())
                {
                    var nVertex = enumerator.Neighbour;
                    var nWeight = ContractedEdgeDataSerializer.Deserialize(enumerator.Data0);

                    nWeight = new WeightAndDir <float>()
                    {
                        Direction = Dir.Combine(cWeight.Direction, nWeight.Direction),
                        Weight    = cWeight.Weight + nWeight.Weight
                    };

                    if (nWeight.Direction.F &&
                        forwardSettled.Contains(nVertex))
                    {
                        nWeight.Direction = new Dir(false, nWeight.Direction.B);
                    }
                    if (nWeight.Direction.B &&
                        backwardSettled.Contains(nVertex))
                    {
                        nWeight.Direction = new Dir(nWeight.Direction.F, false);
                    }
                    if (!nWeight.Direction.F && !nWeight.Direction.B)
                    {
                        continue;
                    }

                    var nPoiner = pathTree.AddSettledVertex(nVertex, nWeight, cHops + 1);
                    pointerHeap.Push(nPoiner, nWeight.Weight);
                }
            }
        }