/// <summary> /// Implements a very simple dykstra version. /// </summary> /// <param name="from"></param> /// <param name="to"></param> /// <param name="via"></param> /// <param name="max_weight"></param> /// <param name="max_settles"></param> /// <returns></returns> private float CalculateWeight(uint from, uint to, uint via, float max_weight, int max_settles) { int max_hops = 5; float weight = float.MaxValue; // creates the settled list. HashSet<uint> settled = new HashSet<uint>(); settled.Add(via); // creates the priorty queue. BinairyHeap<SettledVertex> heap = new BinairyHeap<SettledVertex>(); heap.Push(new SettledVertex(from, 0, 0), 0); // keep looping until the queue is empty or the target is found! while (heap.Count > 0) { // pop the first customer. SettledVertex current = heap.Pop(); if (!settled.Contains(current.VertexId)) { // the current vertex has net been settled. settled.Add(current.VertexId); // settled the vertex. // test stop conditions. if (current.VertexId == to) { // target is found! return current.Weight; } // test the hop count. if (current.Hops < max_hops) { // the neighbours will only increase hops! if (settled.Count >= max_settles) { // do not continue searching. return float.MaxValue; } // get the neighbours. KeyValuePair<uint, CHEdgeData>[] neighbours = _data.GetArcs(current.VertexId); for (int idx = 0; idx < neighbours.Length; idx++) { if (neighbours[idx].Value.Forward && (neighbours[idx].Key == to || !settled.Contains(neighbours[idx].Key))) { SettledVertex neighbour = new SettledVertex(neighbours[idx].Key, neighbours[idx].Value.Weight + current.Weight, current.Hops + 1); if (neighbour.Weight < max_weight) { if (neighbours[idx].Key == to) { return neighbour.Weight; } heap.Push(neighbour, neighbour.Weight); } } } } } } return weight; }
/// <summary> /// Calculates witnesses from on source to multiple targets at once. /// </summary> /// <param name="graph"></param> /// <param name="from"></param> /// <param name="tos"></param> /// <param name="tosWeights"></param> /// <param name="maxSettles"></param> /// <param name="forwardExists"></param> /// <param name="backwardExists"></param> /// <param name="toSkip"></param> public void Exists(GraphBase<CHEdgeData> graph, uint from, List<uint> tos, List<float> tosWeights, int maxSettles, ref bool[] forwardExists, ref bool[] backwardExists, uint toSkip) { int maxHops = _hopLimit; if (maxHops == 1) { this.ExistsOneHop(graph, from, tos, tosWeights, maxSettles, ref forwardExists, ref backwardExists); return; } // creates the settled list. var backwardSettled = new HashSet<uint>(); var forwardSettled = new HashSet<uint>(); var backwardToSet = new HashSet<uint>(); var forwardToSet = new HashSet<uint>(); float forwardMaxWeight = 0, backwardMaxWeight = 0; for (int idx = 0; idx < tosWeights.Count; idx++) { if (!forwardExists[idx]) { forwardToSet.Add(tos[idx]); if (forwardMaxWeight < tosWeights[idx]) { forwardMaxWeight = tosWeights[idx]; } } if (!backwardExists[idx]) { backwardToSet.Add(tos[idx]); if (backwardMaxWeight < tosWeights[idx]) { backwardMaxWeight = tosWeights[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>(); var heap = _reusableHeap; heap.Clear(); heap.Push(new SettledVertex(from, 0, 0, forwardMaxWeight > 0, backwardMaxWeight > 0), 0); // keep looping until the queue is empty or the target is found! while (heap.Count > 0) { // pop the first customer. var current = heap.Pop(); if (current.Hops + 1 < maxHops) { // the current vertex has net been settled. if(current.VertexId == toSkip) { continue; } bool forwardWasSettled = forwardSettled.Contains(current.VertexId); bool backwardWasSettled = backwardSettled.Contains(current.VertexId); if (forwardWasSettled && backwardWasSettled) { continue; } if (current.Forward) { // this is a forward settle. forwardSettled.Add(current.VertexId); forwardMinWeight.Remove(current.VertexId); if (forwardToSet.Contains(current.VertexId)) { int index = tos.IndexOf(current.VertexId); forwardExists[index] = current.Weight <= tosWeights[index]; //if (forwardExists[index]) //{ forwardToSet.Remove(current.VertexId); //} } } if (current.Backward) { // this is a backward settle. backwardSettled.Add(current.VertexId); backwardMinWeight.Remove(current.VertexId); if (backwardToSet.Contains(current.VertexId)) { int index = tos.IndexOf(current.VertexId); backwardExists[index] = current.Weight <= tosWeights[index]; //if (backwardExists[index]) //{ backwardToSet.Remove(current.VertexId); //} } } if (forwardToSet.Count == 0 && backwardToSet.Count == 0) { // there is nothing left to check. break; } if (forwardSettled.Count >= maxSettles && backwardSettled.Count >= maxSettles) { // do not continue searching. break; } bool doForward = current.Forward && forwardToSet.Count > 0 && !forwardWasSettled; bool doBackward = current.Backward && backwardToSet.Count > 0 && !backwardWasSettled; if (doForward || doBackward) { // get the neighbours. var neighbours = graph.GetEdges(current.VertexId); while (neighbours.MoveNext()) { // move next. var edgeData = neighbours.EdgeData; var neighbourWeight = current.Weight + edgeData.Weight; var doNeighbourForward = doForward && edgeData.CanMoveForward && neighbourWeight <= forwardMaxWeight && !forwardSettled.Contains(neighbours.Neighbour); var doNeighbourBackward = doBackward && edgeData.CanMoveBackward && neighbourWeight <= backwardMaxWeight && !backwardSettled.Contains(neighbours.Neighbour); if (doNeighbourBackward || doNeighbourForward) { float existingWeight; if (doNeighbourForward) { if (forwardMinWeight.TryGetValue(neighbours.Neighbour, out existingWeight)) { if(existingWeight <= neighbourWeight) { doNeighbourForward = false; } else { forwardMinWeight[neighbours.Neighbour] = neighbourWeight; } } else { forwardMinWeight[neighbours.Neighbour] = neighbourWeight; } } if (doNeighbourBackward) { if (backwardMinWeight.TryGetValue(neighbours.Neighbour, out existingWeight)) { if (existingWeight <= neighbourWeight) { doNeighbourBackward = false; } else { backwardMinWeight[neighbours.Neighbour] = neighbourWeight; } } else { backwardMinWeight[neighbours.Neighbour] = neighbourWeight; } } if (doNeighbourBackward || doNeighbourForward) { var neighbour = new SettledVertex(neighbours.Neighbour, neighbourWeight, current.Hops + 1, doNeighbourForward, doNeighbourBackward); heap.Push(neighbour, neighbour.Weight); } } } } } } }
/// <summary> /// Implements a very simple dykstra version. /// </summary> /// <param name="graph"></param> /// <param name="from"></param> /// <param name="to"></param> /// <param name="via"></param> /// <param name="max_weight"></param> /// <param name="max_settles"></param> /// <returns></returns> private float CalculateWeight(IBasicRouterDataSource <CHEdgeData> graph, uint from, uint to, uint via, float max_weight, int max_settles) { int max_hops = _hopLimit; float weight = float.MaxValue; // creates the settled list. HashSet <uint> settled = new HashSet <uint>(); settled.Add(via); // creates the priorty queue. BinairyHeap <SettledVertex> heap = new BinairyHeap <SettledVertex>(); heap.Push(new SettledVertex(from, 0, 0), 0); // keep looping until the queue is empty or the target is found! while (heap.Count > 0) { // pop the first customer. SettledVertex current = heap.Pop(); if (!settled.Contains(current.VertexId)) { // the current vertex has net been settled. settled.Add(current.VertexId); // settled the vertex. // test stop conditions. if (current.VertexId == to) { // target is found! return(current.Weight); } // test the hop count. if (current.Hops < max_hops) { // the neighbours will only increase hops! if (settled.Count >= max_settles) { // do not continue searching. return(float.MaxValue); } // get the neighbours. KeyValuePair <uint, CHEdgeData>[] neighbours = graph.GetEdges(current.VertexId); for (int idx = 0; idx < neighbours.Length; idx++) { var neighbourPair = neighbours[idx]; if (neighbourPair.Value.Forward && (neighbourPair.Key == to || !settled.Contains(neighbourPair.Key))) { var neighbour = new SettledVertex(neighbours[idx].Key, neighbours[idx].Value.Weight + current.Weight, current.Hops + 1); if (neighbour.Weight < max_weight) { if (neighbours[idx].Key == to) { return(neighbour.Weight); } heap.Push(neighbour, neighbour.Weight); } } } } } } return(weight); }
/// <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); } } } } } } }
/// <summary> /// Calculates witnesses from on source to multiple targets at once. /// </summary> /// <param name="graph"></param> /// <param name="from"></param> /// <param name="tos"></param> /// <param name="tosWeights"></param> /// <param name="maxSettles"></param> /// <param name="forwardExists"></param> /// <param name="backwardExists"></param> /// <param name="toSkip"></param> public void Exists(GraphBase <CHEdgeData> graph, uint from, List <uint> tos, List <float> tosWeights, int maxSettles, ref bool[] forwardExists, ref bool[] backwardExists, uint toSkip) { int maxHops = _hopLimit; if (maxHops == 1) { this.ExistsOneHop(graph, from, tos, tosWeights, maxSettles, ref forwardExists, ref backwardExists); return; } // creates the settled list. var backwardSettled = new HashSet <uint>(); var forwardSettled = new HashSet <uint>(); var backwardToSet = new HashSet <uint>(); var forwardToSet = new HashSet <uint>(); float forwardMaxWeight = 0, backwardMaxWeight = 0; for (int idx = 0; idx < tosWeights.Count; idx++) { if (!forwardExists[idx]) { forwardToSet.Add(tos[idx]); if (forwardMaxWeight < tosWeights[idx]) { forwardMaxWeight = tosWeights[idx]; } } if (!backwardExists[idx]) { backwardToSet.Add(tos[idx]); if (backwardMaxWeight < tosWeights[idx]) { backwardMaxWeight = tosWeights[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>(); var heap = _reusableHeap; heap.Clear(); heap.Push(new SettledVertex(from, 0, 0, forwardMaxWeight > 0, backwardMaxWeight > 0), 0); // keep looping until the queue is empty or the target is found! while (heap.Count > 0) { // pop the first customer. var current = heap.Pop(); if (current.Hops + 1 < maxHops) { // the current vertex has net been settled. if (current.VertexId == toSkip) { continue; } bool forwardWasSettled = forwardSettled.Contains(current.VertexId); bool backwardWasSettled = backwardSettled.Contains(current.VertexId); if (forwardWasSettled && backwardWasSettled) { continue; } if (current.Forward) { // this is a forward settle. forwardSettled.Add(current.VertexId); forwardMinWeight.Remove(current.VertexId); if (forwardToSet.Contains(current.VertexId)) { int index = tos.IndexOf(current.VertexId); forwardExists[index] = current.Weight <= tosWeights[index]; //if (forwardExists[index]) //{ forwardToSet.Remove(current.VertexId); //} } } if (current.Backward) { // this is a backward settle. backwardSettled.Add(current.VertexId); backwardMinWeight.Remove(current.VertexId); if (backwardToSet.Contains(current.VertexId)) { int index = tos.IndexOf(current.VertexId); backwardExists[index] = current.Weight <= tosWeights[index]; //if (backwardExists[index]) //{ backwardToSet.Remove(current.VertexId); //} } } if (forwardToSet.Count == 0 && backwardToSet.Count == 0) { // there is nothing left to check. break; } if (forwardSettled.Count >= maxSettles && backwardSettled.Count >= maxSettles) { // do not continue searching. break; } bool doForward = current.Forward && forwardToSet.Count > 0 && !forwardWasSettled; bool doBackward = current.Backward && backwardToSet.Count > 0 && !backwardWasSettled; if (doForward || doBackward) { // get the neighbours. var neighbours = graph.GetEdges(current.VertexId); while (neighbours.MoveNext()) { // move next. var edgeData = neighbours.EdgeData; var neighbourWeight = current.Weight + edgeData.Weight; var doNeighbourForward = doForward && edgeData.CanMoveForward && neighbourWeight <= forwardMaxWeight && !forwardSettled.Contains(neighbours.Neighbour); var doNeighbourBackward = doBackward && edgeData.CanMoveBackward && neighbourWeight <= backwardMaxWeight && !backwardSettled.Contains(neighbours.Neighbour); if (doNeighbourBackward || doNeighbourForward) { float existingWeight; if (doNeighbourForward) { if (forwardMinWeight.TryGetValue(neighbours.Neighbour, out existingWeight)) { if (existingWeight <= neighbourWeight) { doNeighbourForward = false; } else { forwardMinWeight[neighbours.Neighbour] = neighbourWeight; } } else { forwardMinWeight[neighbours.Neighbour] = neighbourWeight; } } if (doNeighbourBackward) { if (backwardMinWeight.TryGetValue(neighbours.Neighbour, out existingWeight)) { if (existingWeight <= neighbourWeight) { doNeighbourBackward = false; } else { backwardMinWeight[neighbours.Neighbour] = neighbourWeight; } } else { backwardMinWeight[neighbours.Neighbour] = neighbourWeight; } } if (doNeighbourBackward || doNeighbourForward) { var neighbour = new SettledVertex(neighbours.Neighbour, neighbourWeight, current.Hops + 1, doNeighbourForward, doNeighbourBackward); heap.Push(neighbour, neighbour.Weight); } } } } } } }
/// <summary> /// Calculates witnesses from on source to multiple targets at once. /// </summary> /// <param name="graph"></param> /// <param name="from"></param> /// <param name="tos"></param> /// <param name="tosWeights"></param> /// <param name="maxSettles"></param> /// <param name="exists"></param> public void Exists(IBasicRouterDataSource<CHEdgeData> graph, uint from, List<uint> tos, List<float> tosWeights, int maxSettles, ref bool[] exists) { int maxHops = _hopLimit; if (maxHops == 1) { this.ExistsOneHop(graph, from, tos, tosWeights, maxSettles, ref exists); return; } // creates the settled list. var settled = new HashSet<uint>(); var toSet = new HashSet<uint>(); float maxWeight = 0; for(int idx = 0; idx < tos.Count; idx++) { if(!exists[idx]) { toSet.Add(tos[idx]); if(maxWeight < tosWeights[idx]) { maxWeight = tosWeights[idx]; } } } // creates the priorty queue. var heap = _reusableHeap; heap.Clear(); heap.Push(new SettledVertex(from, 0, 0), 0); // keep looping until the queue is empty or the target is found! while (heap.Count > 0) { // pop the first customer. var current = heap.Pop(); if (!settled.Contains(current.VertexId)) { // the current vertex has net been settled. settled.Add(current.VertexId); // settled the vertex. // check if this is a to. if(toSet.Contains(current.VertexId)) { int index = tos.IndexOf(current.VertexId); exists[index] = current.Weight < tosWeights[index]; toSet.Remove(current.VertexId); if(toSet.Count == 0) { break; } } if (settled.Count >= maxSettles) { // do not continue searching. break; } // get the neighbours. var neighbours = graph.GetEdges(current.VertexId); while (neighbours.MoveNext()) { if (!settled.Contains(neighbours.Neighbour)) { if (neighbours.isInverted) { var invertedEdgeData = neighbours.InvertedEdgeData; if (invertedEdgeData.Backward && !invertedEdgeData.ToHigher && !invertedEdgeData.ToLower) { var neighbour = new SettledVertex(neighbours.Neighbour, invertedEdgeData.BackwardWeight + current.Weight, current.Hops + 1); if (neighbour.Weight < maxWeight && neighbour.Hops < maxHops) { heap.Push(neighbour, neighbour.Weight); //if (toSet.Contains(neighbours.Neighbour)) // check early for witnesses. //{ // this neighbour has been found and it already represents a witness even if not shortest. // int index = tos.IndexOf(neighbours.Neighbour); // if (neighbour.Weight < tosWeights[index] || // heap.Peek().VertexId == neighbours.Neighbour) // { // ok, witness already found. // exists[index] = current.Weight < tosWeights[index]; // toSet.Remove(neighbours.Neighbour); // if (toSet.Count == 0) // { // break; // } // } //} } } } else { var edgeData = neighbours.EdgeData; if (edgeData.Forward && !edgeData.ToHigher && !edgeData.ToLower) { var neighbour = new SettledVertex(neighbours.Neighbour, edgeData.ForwardWeight + current.Weight, current.Hops + 1); if (neighbour.Weight < maxWeight && neighbour.Hops < maxHops) { heap.Push(neighbour, neighbour.Weight); //if (toSet.Contains(neighbours.Neighbour)) // check early for witnesses. //{ // this neighbour has been found and it already represents a witness even if not shortest. // int index = tos.IndexOf(neighbours.Neighbour); // if (neighbour.Weight < tosWeights[index] || // heap.Peek().VertexId == neighbours.Neighbour) // { // ok, witness already found. // exists[index] = current.Weight < tosWeights[index]; // toSet.Remove(neighbours.Neighbour); // if (toSet.Count == 0) // { // break; // } // } //} } } } } } } } }