public List<Path> Calculate( int sourceVertexId, int destinationVertexId, Int32 maxDepth = 1, Double maxPathWeight = Double.MaxValue, Int32 maxResults = 1, PathDelegates.EdgePropertyFilter edgePropertyFilter = null, PathDelegates.VertexFilter vertexFilter = null, PathDelegates.EdgeFilter edgeFilter = null, PathDelegates.EdgeCost edgeCost = null, PathDelegates.VertexCost vertexCost = null) { #region initial checks VertexModel sourceVertex; VertexModel targetVertex; if (!(_fallen8.TryGetVertex(out sourceVertex, sourceVertexId) && _fallen8.TryGetVertex(out targetVertex, destinationVertexId))) { return null; } if (maxDepth == 0 || maxResults == 0 || maxResults <= 0) { return null; } if (ReferenceEquals(sourceVertex, targetVertex)) { return null; } #endregion #region data var sourceVisitedVertices = new BigBitArray(); sourceVisitedVertices.SetValue(sourceVertex.Id, true); var targetVisitedVertices = new BigBitArray(); targetVisitedVertices.SetValue(targetVertex.Id, true); #endregion #region maxdepth = 1 if (maxDepth == 1) { var depthOneFrontier = GetGlobalFrontier(new List<VertexModel> { sourceVertex }, sourceVisitedVertices, edgePropertyFilter, edgeFilter, vertexFilter); } #endregion #region maxdepth > 1 //find the middle element s-->m-->t Int32 sourceLevel = 0; Int32 targetLevel = 0; var sourceFrontiers = new List<Dictionary<VertexModel, VertexPredecessor>>(); var targetFrontiers = new List<Dictionary<VertexModel, VertexPredecessor>>(); Dictionary<VertexModel, VertexPredecessor> currentSourceFrontier = null; Dictionary<VertexModel, VertexPredecessor> currentTargetFrontier = null; IEnumerable<VertexModel> currentSourceVertices = new List<VertexModel> { sourceVertex }; IEnumerable<VertexModel> currentTargetVertices = new List<VertexModel> { targetVertex }; List<VertexModel> middleVertices = null; do { #region calculate frontier #region source --> target currentSourceFrontier = GetGlobalFrontier(currentSourceVertices, sourceVisitedVertices, edgePropertyFilter, edgeFilter, vertexFilter); sourceFrontiers.Add(currentSourceFrontier); currentSourceVertices = sourceFrontiers[sourceLevel].Keys; sourceLevel++; if (currentSourceFrontier.ContainsKey(targetVertex)) { if (middleVertices == null) { middleVertices = new List<VertexModel>{targetVertex}; } else { middleVertices.Add(targetVertex); } break; } if (FindMiddleVertices(out middleVertices, currentSourceFrontier, currentTargetFrontier)) break; if ((sourceLevel + targetLevel) == maxDepth) break; #endregion #region target --> source currentTargetFrontier = GetGlobalFrontier(currentTargetVertices, targetVisitedVertices, edgePropertyFilter, edgeFilter, vertexFilter); targetFrontiers.Add(currentTargetFrontier); currentTargetVertices = targetFrontiers[targetLevel].Keys; targetLevel++; if (currentTargetFrontier.ContainsKey(sourceVertex)) { if (middleVertices == null) { middleVertices = new List<VertexModel> { sourceVertex }; } else { middleVertices.Add(sourceVertex); } break; } if (FindMiddleVertices(out middleVertices, currentSourceFrontier, currentTargetFrontier)) break; if ((sourceLevel + targetLevel) == maxDepth) break; #endregion #endregion } while (true); return middleVertices != null ? CreatePaths(middleVertices, sourceFrontiers, targetFrontiers, maxResults, sourceLevel, targetLevel) : null; #endregion }
/// <summary> /// Calculates the weight of this path element /// </summary> /// <param name="vertexCost"> The vertex cost delegate. </param> /// <param name="edgeCost"> The edge cost delegate </param> public virtual void CalculateWeight(PathDelegates.VertexCost vertexCost, PathDelegates.EdgeCost edgeCost) { Weight = 0; if (vertexCost != null) { Weight = vertexCost(TargetVertex); } if (edgeCost != null) { Weight += edgeCost(Edge); } }
/// <summary> /// Gets the frontier elements on an outgoing edge /// </summary> /// <param name="vertex">The vertex behind the frontier</param> /// <param name="edgepropertyFilter">The edge property filter</param> /// <param name="edgeFilter">The edge filter</param> /// <param name="vertexFilter">The vertex filter</param> /// <param name="alreadyVisited">The vertices that have been visited already</param> /// <returns>A number of frontier elements</returns> private static IEnumerable<FrontierElement> GetValidOutgoingEdges( VertexModel vertex, PathDelegates.EdgePropertyFilter edgepropertyFilter, PathDelegates.EdgeFilter edgeFilter, PathDelegates.VertexFilter vertexFilter, BigBitArray alreadyVisited) { var edgeProperties = vertex.GetOutgoingEdges(); var result = new List<FrontierElement>(); if (edgeProperties != null) { foreach (var edgeContainer in edgeProperties) { if (edgepropertyFilter != null && !edgepropertyFilter(edgeContainer.EdgePropertyId, Direction.OutgoingEdge)) { continue; } if (edgeFilter != null) { for (var i = 0; i < edgeContainer.Edges.Count; i++) { var aEdge = edgeContainer.Edges[i]; if (edgeFilter(aEdge, Direction.OutgoingEdge)) { if (alreadyVisited.SetValue(aEdge.TargetVertex.Id, true)) { if (vertexFilter != null) { if (vertexFilter(aEdge.TargetVertex)) { result.Add(new FrontierElement { EdgeDirection = Direction.OutgoingEdge, EdgeLocation = new EdgeLocation { Edge = aEdge, EdgePropertyId = edgeContainer.EdgePropertyId }, FrontierVertex = aEdge.TargetVertex }); } } else { result.Add(new FrontierElement { EdgeDirection = Direction.OutgoingEdge, EdgeLocation = new EdgeLocation { Edge = aEdge, EdgePropertyId = edgeContainer.EdgePropertyId }, FrontierVertex = aEdge.TargetVertex }); } } } } } else { if (vertexFilter != null) { for (var i = 0; i < edgeContainer.Edges.Count; i++) { var aEdge = edgeContainer.Edges[i]; if (alreadyVisited.SetValue(aEdge.TargetVertex.Id, true)) { if (vertexFilter(aEdge.TargetVertex)) { result.Add(new FrontierElement { EdgeDirection = Direction.OutgoingEdge, EdgeLocation = new EdgeLocation { Edge = aEdge, EdgePropertyId = edgeContainer.EdgePropertyId }, FrontierVertex = aEdge.TargetVertex }); } } } } else { for (var i = 0; i < edgeContainer.Edges.Count; i++) { var aEdge = edgeContainer.Edges[i]; if (alreadyVisited.SetValue(aEdge.TargetVertex.Id, true)) { result.Add(new FrontierElement { EdgeDirection = Direction.OutgoingEdge, EdgeLocation = new EdgeLocation { Edge = aEdge, EdgePropertyId = edgeContainer.EdgePropertyId }, FrontierVertex = aEdge.TargetVertex }); } } } } } } return result; }
/// <summary> /// Gets the local frontier corresponding to a vertex /// </summary> /// <param name="vertex">The vertex behind the local frontier</param> /// <param name="alreadyVisitedVertices">The vertices that have been visited already</param> /// <param name="edgepropertyFilter">The edge property filter</param> /// <param name="edgeFilter">The edge filter</param> /// <param name="vertexFilter">The vertex filter</param> /// <returns>The local frontier</returns> private static IEnumerable<FrontierElement> GetLocalFrontier(VertexModel vertex, BigBitArray alreadyVisitedVertices, PathDelegates.EdgePropertyFilter edgepropertyFilter, PathDelegates.EdgeFilter edgeFilter, PathDelegates.VertexFilter vertexFilter) { var result = new List<FrontierElement>(); result.AddRange(GetValidIncomingEdges(vertex, edgepropertyFilter, edgeFilter, vertexFilter, alreadyVisitedVertices)); result.AddRange(GetValidOutgoingEdges(vertex, edgepropertyFilter, edgeFilter, vertexFilter, alreadyVisitedVertices)); return result; }
/// <summary> /// Gets the global frontier corresponding to a certain level /// </summary> /// <param name="startingVertices">The starting vertices behind the frontier</param> /// <param name="visitedVertices">The visited vertices corresponding to the frontier</param> /// <param name="edgepropertyFilter">The edge property filter</param> /// <param name="edgeFilter">The edge filter</param> /// <param name="vertexFilter">The vertex filter</param> /// <returns>The frontier vertices and their predecessors</returns> private static Dictionary<VertexModel, VertexPredecessor> GetGlobalFrontier(IEnumerable<VertexModel> startingVertices, BigBitArray visitedVertices, PathDelegates.EdgePropertyFilter edgepropertyFilter, PathDelegates.EdgeFilter edgeFilter, PathDelegates.VertexFilter vertexFilter) { var frontier = new Dictionary<VertexModel, VertexPredecessor>(); foreach (var aKv in startingVertices) { foreach (var aFrontierElement in GetLocalFrontier(aKv, visitedVertices, edgepropertyFilter, edgeFilter, vertexFilter)) { VertexPredecessor pred; if (frontier.TryGetValue(aFrontierElement.FrontierVertex, out pred)) { switch (aFrontierElement.EdgeDirection) { case Direction.IncomingEdge: pred.Incoming.Add(aFrontierElement.EdgeLocation); break; case Direction.OutgoingEdge: pred.Outgoing.Add(aFrontierElement.EdgeLocation); break; default: throw new ArgumentOutOfRangeException(); } } else { pred = new VertexPredecessor(); switch (aFrontierElement.EdgeDirection) { case Direction.IncomingEdge: pred.Incoming.Add(aFrontierElement.EdgeLocation); break; case Direction.OutgoingEdge: pred.Outgoing.Add(aFrontierElement.EdgeLocation); break; default: throw new ArgumentOutOfRangeException(); } frontier.Add(aFrontierElement.FrontierVertex, pred); } } } return frontier; }
/// <summary> /// Get the valid edges of a vertex /// </summary> /// <param name="vertex">The vertex.</param> /// <param name="direction">The direction.</param> /// <param name="edgepropertyFilter">The edge property filter.</param> /// <param name="edgeFilter">The edge filter.</param> /// <param name="vertexFilter">The target vertex filter.</param> /// <returns>Valid edges</returns> public static List<Tuple<UInt16, IEnumerable<EdgeModel>>> GetValidEdges( VertexModel vertex, Direction direction, PathDelegates.EdgePropertyFilter edgepropertyFilter, PathDelegates.EdgeFilter edgeFilter, PathDelegates.VertexFilter vertexFilter) { var edgeProperties = direction == Direction.IncomingEdge ? vertex.GetIncomingEdges() : vertex.GetOutgoingEdges(); var result = new List<Tuple<ushort, IEnumerable<EdgeModel>>>(); if (edgeProperties != null) { foreach (var edgeContainer in edgeProperties) { if (edgepropertyFilter != null && !edgepropertyFilter(edgeContainer.EdgePropertyId, direction)) { continue; } if (edgeFilter != null) { var validEdges = new List<EdgeModel>(); for (var i = 0; i < edgeContainer.Edges.Count; i++) { var aEdge = edgeContainer.Edges[i]; if (edgeFilter(aEdge, direction)) { if (vertexFilter != null) { if ( vertexFilter(direction == Direction.IncomingEdge ? aEdge.SourceVertex : aEdge.TargetVertex)) { validEdges.Add(aEdge); } } else { validEdges.Add(aEdge); } } } result.Add(new Tuple<ushort, IEnumerable<EdgeModel>>(edgeContainer.EdgePropertyId, validEdges)); } else { if (vertexFilter != null) { var validEdges = new List<EdgeModel>(); for (var i = 0; i < edgeContainer.Edges.Count; i++) { var aEdge = edgeContainer.Edges[i]; if ( vertexFilter(direction == Direction.IncomingEdge ? aEdge.SourceVertex : aEdge.TargetVertex)) { validEdges.Add(aEdge); } } result.Add(new Tuple<ushort, IEnumerable<EdgeModel>>(edgeContainer.EdgePropertyId, validEdges)); } else { result.Add(new Tuple<ushort, IEnumerable<EdgeModel>>(edgeContainer.EdgePropertyId, edgeContainer.Edges)); } } } } return result; }
public bool CalculateShortestPath( out List<Path> result, string algorithmname, Int32 sourceVertexId, Int32 destinationVertexId, Int32 maxDepth = 1, Double maxPathWeight = Double.MaxValue, Int32 maxResults = 1, PathDelegates.EdgePropertyFilter edgePropertyFilter = null, PathDelegates.VertexFilter vertexFilter = null, PathDelegates.EdgeFilter edgeFilter = null, PathDelegates.EdgeCost edgeCost = null, PathDelegates.VertexCost vertexCost = null) { IShortestPathAlgorithm algo; if (PluginFactory.TryFindPlugin(out algo, algorithmname)) { algo.Initialize(this, null); if (ReadResource()) { result = algo.Calculate(sourceVertexId, destinationVertexId, maxDepth, maxPathWeight, maxResults, edgePropertyFilter, vertexFilter, edgeFilter, edgeCost, vertexCost); FinishReadResource(); return result != null && result.Count > 0; } throw new CollisionException(); } result = null; return false; }