/// <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++; } } } }
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); }); }
/// <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)); }
/// <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); } } } }
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); }
/// <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); }
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]); }
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); }
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); } } } } } } } } }
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)); }
/// <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); } } } } } } }
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; } }
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()); }
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]); }
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); }
/// <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); } } }