コード例 #1
0
ファイル: SchemeVisitor.cs プロジェクト: pu4kov/MosMetroPath
        /// <summary>
        /// Поиск оптимального маршрута с посещением всех веток метро с помощью метода ветвей и границ
        /// </summary>
        /// <param name="scheme"></param>
        /// <returns></returns>
        public IEnumerable <IRoute> VisitAllLinesByBranchAndBound(Scheme scheme)
        {
            if (scheme == null)
            {
                throw new ArgumentNullException();
            }

            var stations = scheme.GetAllLineRelationStations();    // Все пересадочные станции всех веток


            var lines         = scheme.GetLines().ToArray(); // все ветки метро
            var linesStations = new Station[lines.Length][]; // массив станций переходов для каждой ветки
            var indeces       = new int[lines.Length];       // индекс станции для каждой ветки

            for (var i = 0; i < lines.Length; ++i)
            {
                linesStations[i] = lines[i].GetRelationStations().ToArray();
                indeces[i]       = 0;
            }

            var lastLineInd = indeces.Length - 1;

            var cache   = new RoutesCollection <Station>((r) => new TwoItemsKey <Station>(r.From, r.To));
            var visitor = new AllLinesVisitor();

            int counter = 0;
            int skipped = 0;

            bool next = true;

            do
            {
                // Обработка станций
                var routes = new List <IRoute>();

                for (int fromLineId = 0; fromLineId < indeces.Length - 1; ++fromLineId)
                {
                    var fromStation = linesStations[fromLineId][indeces[fromLineId]];
                    for (int toLineId = fromLineId + 1; toLineId < indeces.Length; ++toLineId)
                    {
                        var    toStation = linesStations[toLineId][indeces[toLineId]];
                        IRoute route;
                        if (!cache.TryGetRoute(fromStation, toStation, out route))
                        {
                            route = FindRoute(fromStation, toStation);
                            cache.Add(route);
                        }

                        routes.Add(route);
                    }
                }
                visitor.Push(routes);
                counter++;

                /*
                 * // ограничение маршрутов для тестирования
                 * if (counter > 10)
                 *  next = false;
                 */
                // Переход к следующей комбинации
                var lineInd = lastLineInd;
                do
                {
                    ++indeces[lineInd];
                    if (indeces[lineInd] >= linesStations[lineInd].Length)
                    {
                        if (lineInd == 0)
                        {   // перебраны все возможные комбинации
                            next = false;
                            break;
                        }
                        else
                        {
                            indeces[lineInd] = 0;
                        }
                    }
                    else
                    {
                        break;
                    }
                    --lineInd;
                }while (lineInd >= 0);
            }while (next);
            visitor.Complete();
            visitor.Completion.Wait();

            return(visitor.GetResults());
        }
コード例 #2
0
ファイル: SchemeVisitor.cs プロジェクト: pu4kov/MosMetroPath
        /// <summary>
        /// Поиск оптимальных маршрутов движения для посещения всех веток метро
        /// </summary>
        /// <param name="scheme">Схема метро</param>
        /// <returns>Наиболее быстрые маршруты</returns>
        public IEnumerable <IRoute> VisitAllLines(Scheme scheme)
        {
            if (scheme == null)
            {
                throw new ArgumentNullException();
            }

            var stations = scheme.GetAllLineRelationStations().ToList();         // Все пересадочные станции всех веток

            LineRoutesCollection    linesRoutes = new LineRoutesCollection();    // Маршруты между линиями
            PartialRoutesCollection routes      = new PartialRoutesCollection(); // Маршруты, которые могут стать решением

            // Построение маршрутов между всеми парами пересадочных станций
            for (int i = 0; i < stations.Count - 1; ++i)
            {
                var s1 = stations[i];
                for (int j = i + 1; j < stations.Count; ++j)
                {
                    var s2 = stations[j];
                    // Поиск маршрута только если станции на разных ветках
                    // и маршрут не был ранее уже найден
                    if (s1.Line != s2.Line &&
                        !linesRoutes.ContainsRoute(s1, s2))
                    {
                        var newRoute = FindRoute(s1, s2);
                        if (linesRoutes.Add(newRoute))
                        {
                            routes.Add(newRoute);
                        }
                    }
                }
            }

            ResultCollection result = new ResultCollection();

            while (routes.TryPop(out var route))
            {
                if (route.Timespan > result.Timespan)
                {
                    continue;
                }

                var targetLines = scheme.GetLinesExclude(route.GetLines()); // Ветки, которые еще осталось посетить
                if (targetLines.FirstOrDefault() == null)
                {
                    result.Add(route);
                }
                else if (route.Timespan < result.Timespan)
                {   // Время текущего маршрута меньше времени уже найденных полных маршрутов
                    foreach (var targetLine in targetLines)
                    {
                        foreach (var additionalRoute in linesRoutes.GetRoutes(route.To, targetLine))
                        {
                            // Дальше обрабатываются только те маршруты, которые короче уже найденных
                            if (result.Timespan >= additionalRoute.Timespan + route.Timespan)
                            {
                                var newRoute = Route.Union(route, additionalRoute);
                                routes.Add(newRoute);
                            }
                        }
                    }
                }
            }

            return(result);
        }