/// <summary> /// Contracts the given vertex. /// </summary> private void Contract() { var vertex = _vertexInfo.Vertex; var enumerator = _graph.GetEdgeEnumerator(); // remove 'downward' edge to vertex. var i = 0; while (i < _vertexInfo.Count) { var edge = _vertexInfo[i]; _graph.RemoveEdge(edge.Neighbour, vertex); i++; } // add shortcuts. foreach (var s in _vertexInfo.Shortcuts) { var shortcut = s.Value; var edge = s.Key; var forwardMetric = _weightHandler.GetMetric(shortcut.Forward); var backwardMetric = _weightHandler.GetMetric(shortcut.Backward); if (forwardMetric > 0 && forwardMetric < float.MaxValue && backwardMetric > 0 && backwardMetric < float.MaxValue && System.Math.Abs(backwardMetric - forwardMetric) < HierarchyBuilder <float> .E) { // forward and backward and identical weights. _weightHandler.AddOrUpdateEdge(_graph, edge.Vertex1, edge.Vertex2, vertex, null, shortcut.Forward); _weightHandler.AddOrUpdateEdge(_graph, edge.Vertex2, edge.Vertex1, vertex, null, shortcut.Backward); } else { if (forwardMetric > 0 && forwardMetric < float.MaxValue) { _weightHandler.AddOrUpdateEdge(_graph, edge.Vertex1, edge.Vertex2, vertex, true, shortcut.Forward); _weightHandler.AddOrUpdateEdge(_graph, edge.Vertex2, edge.Vertex1, vertex, false, shortcut.Forward); } if (backwardMetric > 0 && backwardMetric < float.MaxValue) { _weightHandler.AddOrUpdateEdge(_graph, edge.Vertex1, edge.Vertex2, vertex, false, shortcut.Backward); _weightHandler.AddOrUpdateEdge(_graph, edge.Vertex2, edge.Vertex1, vertex, true, shortcut.Backward); } } } _contractedFlags[vertex] = true; this.NotifyContracted(vertex); }
public void TestRemoveEdge() { var graph = new DirectedMetaGraph(1, 1, 10); // add and remove edge. graph.AddEdge(0, 1, 10, 100); Assert.AreEqual(0, graph.RemoveEdge(1, 0)); Assert.AreEqual(1, graph.RemoveEdge(0, 1)); graph = new DirectedMetaGraph(1, 1, 10); // add and remove edge. graph.AddEdge(0, 1, 10, 100); graph.AddEdge(0, 1, 20, 200); Assert.AreEqual(2, graph.GetEdgeEnumerator(0).Count); Assert.AreEqual(0, graph.RemoveEdge(1, 0)); Assert.AreEqual(2, graph.RemoveEdge(0, 1)); Assert.AreEqual(0, graph.GetEdgeEnumerator(0).Count); graph = new DirectedMetaGraph(1, 1, 10); // add and remove edge. graph.AddEdge(0, 1, 10, 100); graph.AddEdge(0, 1, 20, 200); Assert.AreEqual(2, graph.GetEdgeEnumerator(0).Count); Assert.AreEqual(0, graph.RemoveEdge(1, 0)); Assert.AreEqual(2, graph.RemoveEdge(0, 1)); Assert.AreEqual(0, graph.GetEdgeEnumerator(0).Count); graph = new DirectedMetaGraph(1, 1, 10); // add and remove edge. graph.AddEdge(0, 1, 10, 100); graph.AddEdge(0, 2, 20, 200); graph.RemoveEdge(0, 1); var edges = graph.GetEdgeEnumerator(0); Assert.IsNotNull(edges); Assert.AreEqual(2, edges.First().Neighbour); }
public void TestEdgeCount() { var graph = new DirectedMetaGraph(1, 1, 10); // add edge. graph.AddEdge(0, 1, 1, 100); Assert.AreEqual(1, graph.EdgeCount); graph = new DirectedMetaGraph(1, 1, 10); // add edge. graph.AddEdge(0, 1, 1, 100); graph.AddEdge(0, 11001, 1, 100); Assert.AreEqual(2, graph.EdgeCount); graph.AddEdge(0, 11001, 2, 200); Assert.AreEqual(3, graph.EdgeCount); graph.RemoveEdge(0, 11001); Assert.AreEqual(1, graph.EdgeCount); graph.RemoveEdge(0, 1); Assert.AreEqual(0, graph.EdgeCount); }
public void TestSerialize() { var graph = new DirectedMetaGraph(1, 1, 10); // add and compress. graph.AddEdge(0, 1, 1, 100); graph.Compress(); var expectedSize = 1 + 1 + 8 + 8 + 4 + 4 + // the header: two longs representing vertex and edge count and one int for edge size and one for vertex size. graph.VertexCount * 2 * 4 + // the bytes for the vertex-index: 2 uint's. graph.EdgeCount * 2 * 4 + // the bytes for the edges: one edge 1 uint. 4 + 4 + // the header for the meta-data: 2 uint for sizes. graph.EdgeCount * 4; // the bytes for the edges: one edge 1 uint. using (var stream = new System.IO.MemoryStream()) { Assert.AreEqual(expectedSize, graph.Serialize(stream)); Assert.AreEqual(expectedSize, stream.Position); } // verify all edges. var edges = graph.GetEdgeEnumerator(0); Assert.AreEqual(1, edges.Count()); Assert.AreEqual(1, edges.First().Data[0]); Assert.AreEqual(1, edges.First().Neighbour); graph = new DirectedMetaGraph(1, 1, 10); // add and compress. graph.AddEdge(0, 1, 10, 100); graph.AddEdge(1, 2, 20, 200); graph.AddEdge(2, 3, 30, 300); graph.AddEdge(3, 4, 40, 400); graph.RemoveEdge(1, 2); graph.Compress(); expectedSize = 1 + 1 + 8 + 8 + 4 + 4 + // the header: two longs representing vertex and edge count and one int for edge size and one for vertex size. graph.VertexCount * 2 * 4 + // the bytes for the vertex-index: 2 uint's. graph.EdgeCount * 2 * 4 + // the bytes for the edges: one edge 1 uint. 4 + 4 + // the header for the meta-data: 2 uint for sizes. graph.EdgeCount * 4; // the bytes for the edges: one edge 1 uint. using (var stream = new System.IO.MemoryStream()) { Assert.AreEqual(expectedSize, graph.Serialize(stream)); Assert.AreEqual(expectedSize, stream.Position); } }
public static void AddOrUpdateEdge(this DirectedMetaGraph graph, uint vertex1, uint vertex2, float weight, bool?direction, uint contractedId) { uint data1 = ContractedEdgeDataSerializer.Serialize(weight, direction); bool hasExistingEdge = false; bool hasExistingEdgeOnlySameDirection = true; if ((int)graph.UpdateEdge(vertex1, vertex2, (Func <uint[], bool>)(data => { hasExistingEdge = true; if (ContractedEdgeDataSerializer.HasDirection(data[0], direction)) { return((double)weight < (double)ContractedEdgeDataSerializer.DeserializeWeight(data[0])); } hasExistingEdgeOnlySameDirection = false; return(false); }), new uint[1] { data1 }, contractedId) != -1) { return; } if (!hasExistingEdge) { int num1 = (int)graph.AddEdge(vertex1, vertex2, data1, contractedId); } else { if (hasExistingEdgeOnlySameDirection) { return; } bool flag1 = false; float weight1 = float.MaxValue; uint metaData1 = uint.MaxValue; bool flag2 = false; float weight2 = float.MaxValue; uint metaData2 = uint.MaxValue; if (!direction.HasValue || direction.Value) { flag1 = true; weight1 = weight; metaData1 = contractedId; } if (!direction.HasValue || !direction.Value) { flag2 = true; weight2 = weight; metaData2 = contractedId; } DirectedMetaGraph.EdgeEnumerator edgeEnumerator = graph.GetEdgeEnumerator(vertex1); while (edgeEnumerator.MoveNext()) { if ((int)edgeEnumerator.Neighbour == (int)vertex2) { float weight3; bool? direction1; uint contractedId1; ContractedEdgeDataSerializer.Deserialize(edgeEnumerator.Data0, edgeEnumerator.MetaData0, out weight3, out direction1, out contractedId1); if ((!direction1.HasValue || direction1.Value) && (double)weight3 < (double)weight1) { weight1 = weight3; flag1 = true; metaData1 = contractedId1; } if ((!direction1.HasValue || !direction1.Value) && (double)weight3 < (double)weight2) { weight2 = weight3; flag2 = true; metaData2 = contractedId1; } } } graph.RemoveEdge(vertex1, vertex2); if (flag1 & flag2 && (double)weight1 == (double)weight2 && (int)metaData1 == (int)metaData2) { int num2 = (int)graph.AddEdge(vertex1, vertex2, ContractedEdgeDataSerializer.Serialize(weight1, new bool?()), metaData1); } else { if (flag1) { int num3 = (int)graph.AddEdge(vertex1, vertex2, ContractedEdgeDataSerializer.Serialize(weight1, new bool?(true)), metaData1); } if (!flag2) { return; } int num4 = (int)graph.AddEdge(vertex1, vertex2, ContractedEdgeDataSerializer.Serialize(weight2, new bool?(false)), metaData2); } } }
public void TestCompress() { var graph = new DirectedMetaGraph(1, 1, 10); // add and compress. graph.AddEdge(0, 1, 1, 100); graph.Compress(); // verify all edges. var edges = graph.GetEdgeEnumerator(0); Assert.AreEqual(1, edges.Count()); Assert.AreEqual(1, edges.First().Data[0]); Assert.AreEqual(1, edges.First().Neighbour); graph = new DirectedMetaGraph(1, 1, 10); // add and compress. graph.AddEdge(0, 1, 10, 100); graph.AddEdge(1, 2, 20, 200); graph.AddEdge(2, 3, 30, 300); graph.AddEdge(3, 4, 40, 400); graph.RemoveEdge(1, 2); // verify all edges. edges = graph.GetEdgeEnumerator(0); Assert.AreEqual(1, edges.Count()); Assert.AreEqual(10, edges.First().Data[0]); Assert.AreEqual(100, edges.First().MetaData[0]); Assert.AreEqual(1, edges.First().Neighbour); edges = graph.GetEdgeEnumerator(1); Assert.AreEqual(0, edges.Count()); edges = graph.GetEdgeEnumerator(2); Assert.AreEqual(1, edges.Count()); Assert.AreEqual(30, edges.First().Data[0]); Assert.AreEqual(300, edges.First().MetaData[0]); Assert.AreEqual(3, edges.First().Neighbour); edges = graph.GetEdgeEnumerator(3); Assert.AreEqual(1, edges.Count()); Assert.AreEqual(40, edges.First().Data[0]); Assert.AreEqual(400, edges.First().MetaData[0]); Assert.AreEqual(4, edges.First().Neighbour); // compress. graph.Compress(); // verify all edges. edges = graph.GetEdgeEnumerator(0); Assert.AreEqual(1, edges.Count()); Assert.AreEqual(10, edges.First().Data[0]); Assert.AreEqual(100, edges.First().MetaData[0]); Assert.AreEqual(1, edges.First().Neighbour); edges = graph.GetEdgeEnumerator(1); Assert.AreEqual(0, edges.Count()); edges = graph.GetEdgeEnumerator(2); Assert.AreEqual(1, edges.Count()); Assert.AreEqual(30, edges.First().Data[0]); Assert.AreEqual(300, edges.First().MetaData[0]); Assert.AreEqual(3, edges.First().Neighbour); edges = graph.GetEdgeEnumerator(3); Assert.AreEqual(1, edges.Count()); Assert.AreEqual(40, edges.First().Data[0]); Assert.AreEqual(400, edges.First().MetaData[0]); Assert.AreEqual(4, edges.First().Neighbour); }
/// <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); } } } }
/// <summary> /// Contracts the given vertex. /// </summary> protected virtual void Contract() { var vertex = _vertexInfo.Vertex; // remove 'downward' edge to vertex. var i = 0; while (i < _vertexInfo.Count) { var edge = _vertexInfo[i]; _graph.RemoveEdge(edge.Neighbour, vertex); i++; // TOOD: what to do when stuff is only removed, is nothing ok? //_witnessQueue.Add(edge.Neighbour); } // add shortcuts. foreach (var s in _vertexInfo.Shortcuts) { var shortcut = s.Value; var edge = s.Key; if (edge.Vertex1 == edge.Vertex2) { // TODO: figure out how this is possible, it shouldn't! continue; } var forwardMetric = _weightHandler.GetMetric(shortcut.Forward); var backwardMetric = _weightHandler.GetMetric(shortcut.Backward); if (forwardMetric > 0 && forwardMetric < float.MaxValue && backwardMetric > 0 && backwardMetric < float.MaxValue && System.Math.Abs(backwardMetric - forwardMetric) < FastHierarchyBuilder <float> .E) { // forward and backward and identical weights. _weightHandler.AddOrUpdateEdge(_graph, edge.Vertex1, edge.Vertex2, vertex, null, shortcut.Forward); _weightHandler.AddOrUpdateEdge(_graph, edge.Vertex2, edge.Vertex1, vertex, null, shortcut.Backward); _witnessQueue.Add(edge.Vertex1); _witnessQueue.Add(edge.Vertex2); } else { if (forwardMetric > 0 && forwardMetric < float.MaxValue) { _weightHandler.AddOrUpdateEdge(_graph, edge.Vertex1, edge.Vertex2, vertex, true, shortcut.Forward); _weightHandler.AddOrUpdateEdge(_graph, edge.Vertex2, edge.Vertex1, vertex, false, shortcut.Forward); _witnessQueue.Add(edge.Vertex1); _witnessQueue.Add(edge.Vertex2); } if (backwardMetric > 0 && backwardMetric < float.MaxValue) { _weightHandler.AddOrUpdateEdge(_graph, edge.Vertex1, edge.Vertex2, vertex, false, shortcut.Backward); _weightHandler.AddOrUpdateEdge(_graph, edge.Vertex2, edge.Vertex1, vertex, true, shortcut.Backward); _witnessQueue.Add(edge.Vertex1); _witnessQueue.Add(edge.Vertex2); } } } _contractedFlags[vertex] = true; this.NotifyContracted(vertex); }
/// <summary> /// Remove all witnessed edges. /// </summary> private void RemoveWitnessedEdges() { _logger.Log(TraceEventType.Information, "Removing witnessed edges..."); var witnessEdgeEnumerator = _witnessGraph.GetEdgeEnumerator(); var edgeEnumerator = _graph.GetEdgeEnumerator(); var edges = new List <MetaEdge>(); for (uint vertex = 0; vertex < _graph.VertexCount; vertex++) { // collect all relevant edges. edges.Clear(); if (witnessEdgeEnumerator.MoveTo(vertex) && edgeEnumerator.MoveTo(vertex)) { while (edgeEnumerator.MoveNext()) { if (vertex < edgeEnumerator.Neighbour) { // only check in on directions, all edges are added twice initially. edges.Add(edgeEnumerator.Current); } } } // check witness paths. for (var i = 0; i < edges.Count; i++) { var edge = edges[0]; while (witnessEdgeEnumerator.MoveNext()) { if (witnessEdgeEnumerator.Neighbour == edge.Neighbour) { // this edge is witnessed, figure out how. var forwardWitnessWeight = DirectedGraphExtensions.FromData(witnessEdgeEnumerator.Data0); var backwardWitnessWeight = DirectedGraphExtensions.FromData(witnessEdgeEnumerator.Data1); var weightAndDir = _weightHandler.GetEdgeWeight(edge); var weight = _weightHandler.GetMetric(weightAndDir.Weight); var witnessed = false; if (weightAndDir.Direction.F && weight > forwardWitnessWeight) { // witnessed in forward direction. weightAndDir.Direction = new Dir(false, weightAndDir.Direction.B); witnessed = true; } if (weightAndDir.Direction.B && weight > backwardWitnessWeight) { // witnessed in backward direction. weightAndDir.Direction = new Dir(weightAndDir.Direction.F, false); witnessed = true; } if (witnessed) { // edge was witnessed, do something. // remove the edge (in both directions) _graph.RemoveEdge(vertex, edge.Neighbour); _graph.RemoveEdge(edge.Neighbour, vertex); if (weightAndDir.Direction.B || weightAndDir.Direction.F) { // add it again if there is something relevant still left. _weightHandler.AddEdge(_graph, vertex, edge.Neighbour, Constants.NO_VERTEX, weightAndDir.Direction.AsNullableBool(), weightAndDir.Weight); weightAndDir.Direction.Reverse(); _weightHandler.AddEdge(_graph, edge.Neighbour, vertex, Constants.NO_VERTEX, weightAndDir.Direction.AsNullableBool(), weightAndDir.Weight); } } } } } } }
/// <summary> /// Remove all witnessed edges. /// </summary> private void RemoveWitnessedEdges() { _logger.Log(TraceEventType.Information, "Removing witnessed edges..."); var edges = new List <MetaEdge>(); var weights = new List <T>(); var metrics = new List <float>(); var targets = new List <uint>(); for (uint vertex = 0; vertex < _graph.VertexCount; vertex++) { edges.Clear(); weights.Clear(); metrics.Clear(); targets.Clear(); edges.AddRange(_graph.GetEdgeEnumerator(vertex)); var forwardWitnesses = new bool[edges.Count]; var backwardWitnesses = new bool[edges.Count]; for (var i = 0; i < edges.Count; i++) { var edge = edges[i]; bool?edgeDirection; var edgeWeight = _weightHandler.GetEdgeWeight(edge, out edgeDirection); var edgeCanMoveForward = edgeDirection == null || edgeDirection.Value; var edgeCanMoveBackward = edgeDirection == null || !edgeDirection.Value; forwardWitnesses[i] = !edgeCanMoveForward; backwardWitnesses[i] = !edgeCanMoveBackward; weights.Add(edgeWeight); metrics.Add(_weightHandler.GetMetric(edgeWeight)); targets.Add(edge.Neighbour); } // calculate all witness paths. _witnessCalculator.Calculate(_graph.Graph, vertex, targets, metrics, ref forwardWitnesses, ref backwardWitnesses, uint.MaxValue); // check witness paths. for (var i = 0; i < edges.Count; i++) { if (forwardWitnesses[i] && backwardWitnesses[i]) { // in both directions the edge does not represent the shortest path. _graph.RemoveEdge(vertex, targets[i]); } else if (forwardWitnesses[i]) { // only in forward direction is this edge useless. _graph.RemoveEdge(vertex, targets[i]); _weightHandler.AddEdge(_graph, vertex, targets[i], Constants.NO_VERTEX, false, weights[i]); //_graph.AddEdge(vertex, targets[i], weights[i], false, Constants.NO_VERTEX); } else if (backwardWitnesses[i]) { // only in backward direction is this edge useless. _graph.RemoveEdge(vertex, targets[i]); _weightHandler.AddEdge(_graph, vertex, targets[i], Constants.NO_VERTEX, true, weights[i]); } } } }