コード例 #1
0
ファイル: SrlgGraphSearch.cs プロジェクト: domn1995/Onos.Net
        /// <inheritdoc/>
        protected override IResult <V, E> InternalSearch(IGraph <V, E> graph, V src, V dst, IEdgeWeigher <V, E> weigher, int maxPaths = -1)
        {
            if (maxPaths == AllPaths)
            {
                maxPaths = popSize;
            }
            if (useSuurballe)
            {
                return(new SuurballeGraphSearch <V, E>().Search(graph, src, dst, weigher, AllPaths));
            }
            orig         = graph;
            this.src     = src;
            this.dst     = dst;
            this.weigher = weigher;
            IList <Subset> best = new GaPopulation <Subset>().RunGa(iterations, popSize, maxPaths, new Subset(this, new bool[numGroups]));
            var            dpps = new HashSet <DisjointPathPair <V, E> >();

            foreach (Subset s in best)
            {
                dpps.UnionWith(s.BuildPaths());
            }
            IResult <V, E> firstDijkstra = new DijkstraGraphSearch <V, E>().Search(orig, src, dst, weigher, 1);
            var            result        = new InternalResult(this, firstDijkstra, dpps);

            return(result);
        }
コード例 #2
0
ファイル: SrlgGraphSearch.cs プロジェクト: domn1995/Onos.Net
        /// <summary>
        /// Finds the shortest path in the graph given a subset of edge types to use.
        /// </summary>
        /// <param name="subset"></param>
        /// <returns></returns>
        private IResult <V, E> FindShortestPathFromSubset(bool[] subset)
        {
            IGraph <V, E>       graph    = orig;
            IEdgeWeigher <V, E> modified = new InternalWeigher(weigher, riskGrouping, subset);
            IResult <V, E>      res      = new DijkstraGraphSearch <V, E>().Search(graph, src, dst, modified, 1);

            return(res);
        }
コード例 #3
0
        /// <inheritdoc/>
        protected override IResult <V, E> InternalSearch(IGraph <V, E> graph, V src, V dst, IEdgeWeigher <V, E> weigher, int maxPaths = -1)
        {
            // TODO: This method needs to be refactored as it is difficult to follow and debug.
            // TODO: There is a defect here triggered by 3+ edges between the same vertices which
            // makes an attempt to produce looping paths. Protection against this was added to
            // AbstractGraphPathSearch, but the root issue remains here.
            // TODO: There is a defect here where not all paths are truly disjoint.
            // This class needs to filter its own results to make sure that the paths
            // are indeed disjoint. Temporary fix for this is provided, but the issue still
            // needs to be addressed through refactoring.
            weightF        = weigher;
            firstDijkstraS = (DefaultResult)base.InternalSearch(graph, src, dst, weigher, AllPaths);
            firstDijkstra  = (DefaultResult)base.InternalSearch(graph, src, null, weigher, AllPaths);

            // Choose an arbitrary shortest path to run Suurballe on.
            IPath <V, E> shortPath = null;

            if (firstDijkstraS.Paths.Count == 0)
            {
                return(firstDijkstraS);
            }

            DisjointPathResult result = new DisjointPathResult(firstDijkstra, src, dst, maxPaths);

            foreach (IPath <V, E> p in firstDijkstraS.Paths)
            {
                shortPath = p;
                // Transforms the graph so tree edges have 0 weight.
                var modified = new ModifiedWeigher(this);
                // Create a residual graph g' by removing all source vertices and reversing 0 length path edges.
                IMutableGraph <V, E> gt = MutableCopy(graph);
                foreach (E edge in graph.GetEdgesTo(src))
                {
                    gt.RemoveEdge(edge);
                }
                foreach (E edge in shortPath.Edges)
                {
                    gt.RemoveEdge(edge);
                    E reverse = (E)Activator.CreateInstance(typeof(E), edge.Dst, edge.Src);
                    revToEdge.AddOrSet(reverse, edge);
                    gt.AddEdge(reverse);
                }
                // Rerun dijkstra on the temporary graph to get a second path.
                IResult <V, E> secondDijkstra    = new DijkstraGraphSearch <V, E>().Search(gt, src, dst, modified);
                IPath <V, E>   residualShortPath = null;

                if (secondDijkstra.Paths.Count == 0)
                {
                    result.Dpps.Add(new DisjointPathPair <V, E>(shortPath, null));
                    continue;
                }

                foreach (IPath <V, E> p2 in secondDijkstra.Paths)
                {
                    residualShortPath = p2;
                    IMutableGraph <V, E> roundTrip = MutableCopy(graph);
                    List <E>             tmp       = roundTrip.Edges.ToList();
                    tmp.ForEach(roundTrip.RemoveEdge);
                    foreach (E edge in shortPath.Edges)
                    {
                        roundTrip.AddEdge(edge);
                    }

                    if (residualShortPath != null)
                    {
                        foreach (E edge in residualShortPath.Edges)
                        {
                            if (revToEdge.ContainsKey(edge))
                            {
                                E edgeToRemove = revToEdge[edge];
                                if (roundTrip.Edges.Contains(edgeToRemove))
                                {
                                    roundTrip.RemoveEdge(edgeToRemove);
                                }
                            }
                            else
                            {
                                roundTrip.AddEdge(edge);
                            }
                        }
                    }

                    // Actually build the final result.
                    DefaultResult lastSearch = (DefaultResult)base.InternalSearch(roundTrip, src, dst, weigher, AllPaths);
                    IPath <V, E>  primary    = lastSearch.Paths.First();

                    foreach (E edge in primary.Edges)
                    {
                        roundTrip.RemoveEdge(edge);
                    }

                    ISet <IPath <V, E> > backups = base.InternalSearch(roundTrip, src, dst, weigher, AllPaths).Paths;

                    // Find first backup path that does not share any nodes with the primary.
                    foreach (IPath <V, E> backup in backups)
                    {
                        if (IsDisjoint(primary, backup))
                        {
                            result.Dpps.Add(new DisjointPathPair <V, E>(primary, backup));
                            break;
                        }
                    }
                }
            }

            for (int i = result.Dpps.Count - 1; i > 0; --i)
            {
                if (result.Dpps[i].Size <= 1)
                {
                    result.Dpps.RemoveAt(i);
                }
            }

            result.BuildPaths();
            return(result);
        }
コード例 #4
0
        /// <inheritdoc/>
        protected override IResult <V, E> InternalSearch(IGraph <V, E> graph, V src, V dst, IEdgeWeigher <V, E> weigher, int maxPaths = 1)
        {
            CheckNotNull(weigher, "The edge weigher cannot be null.");
            CheckArgument(maxPaths != AllPaths, "KShortestPath cannot search all paths.");
            CheckArgument(maxPaths > 0, "The max number of paths must be greater than 0.");

            IGraph <V, E>        originalGraph   = CheckNotNull(graph, "The graph cannot be null.");
            var                  modifiedWeigher = new InnerEdgeWeigher(weigher);
            var                  result          = new InnerOrderedResult(src, dst, maxPaths);
            var                  resultPaths     = new List <IPath <V, E> >(maxPaths);
            var                  potentialPaths  = new List <IPath <V, E> >();
            var                  dijkstraSearch  = new DijkstraGraphSearch <V, E>();
            ISet <IPath <V, E> > dijkstraResults = dijkstraSearch.Search(originalGraph, src, dst, modifiedWeigher, 1).Paths;

            // Checks if the destination was reachable.
            if (dijkstraResults.Count == 0)
            {
                log.Warn("No path was found.");
                return(result);
            }

            // If it was reachable, add the first shortest path to the set of results.
            resultPaths.Add(dijkstraResults.First());

            for (int k = 1; k < maxPaths; ++k)
            {
                for (int i = 0; i < resultPaths[k - 1].Edges.Count; ++i)
                {
                    V        spurNode         = resultPaths[k - 1].Edges[i].Src;
                    List <E> rootPathEdgeList = resultPaths[k - 1].Edges.Take(i).ToList();

                    foreach (IPath <V, E> path in resultPaths)
                    {
                        if (path.Edges.Count >= i && rootPathEdgeList.SequenceEqual(path.Edges.Take(i)))
                        {
                            modifiedWeigher.RemovedEdges.Add(path.Edges[i]);
                        }
                    }

                    // Effectively remove all nodes from the source path.
                    foreach (E edge in rootPathEdgeList)
                    {
                        foreach (E e in originalGraph.GetEdgesFrom(edge.Src))
                        {
                            modifiedWeigher.RemovedEdges.Add(e);
                        }
                        foreach (E e in originalGraph.GetEdgesTo(edge.Src))
                        {
                            modifiedWeigher.RemovedEdges.Add(e);
                        }
                    }

                    dijkstraResults = dijkstraSearch.Search(originalGraph, spurNode, dst, modifiedWeigher, 1).Paths;

                    if (dijkstraResults.Count > 0)
                    {
                        IPath <V, E> spurPath  = dijkstraResults.First();
                        var          totalPath = new List <E>(rootPathEdgeList);
                        foreach (E edge in spurPath.Edges)
                        {
                            totalPath.Add(edge);
                        }
                        // The following line must use the original weigher, not the modified weigher, because the
                        // modifed weigher will count -1 values used for modifying the graph and return an inaccurate cost.
                        potentialPaths.Add(new DefaultPath <V, E>(totalPath, CalculatePathCost(weigher, totalPath)));
                    }

                    // Restore all removed paths and nodes.
                    modifiedWeigher.RemovedEdges.Clear();
                }

                if (potentialPaths.Count == 0)
                {
                    break;
                }

                potentialPaths.Sort(new InnerPathComparer());
                resultPaths.Add(potentialPaths[0]);
                potentialPaths.RemoveAt(0);
            }

            resultPaths.ForEach(p => result.PathSet.Add(p));

            return(result);
        }