public static OptimalRoutesCollection FindOptimalRoutes(GeoCoords nowPos, GeoCoords needPos, DateTime time, Dictionary <Priority, double> priorities, IEnumerable <RouteType> types = null, double speed = 5, double dopTimeMinutes = 2, double percentTotalTime = 1, double percentTotalGoingTime = 1, double percentTotalTransportChangingCount = 1)
        {
            int n1 = 1, n2 = 1;

            if (priorities == null || priorities.Count == 0)
            {
                throw new Exception("Не заданы приоритеты.");
            }

            OptimalRoutesCollection findedOptimalRoutes = new OptimalRoutesCollection();

            //DateTime ttt1 = DateTime.Now;
            findedOptimalRoutes.Add(new OptimalRoute(nowPos, needPos, time, types, speed, dopTimeMinutes));
            //MessageBox.Show((DateTime.Now - ttt1).TotalMilliseconds.ToString());

            //return findedOptimalRoutes;//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!1

            List <Route> ignoringRoutes   = new List <Route>();


            Stack <Priority> myPriorities = new Stack <Priority>(priorities.Keys);
            //for (Priority currentPriority = myPriorities.Pop(); myPriorities.Count != 0; currentPriority = myPriorities.Pop())
            //{
            Priority currentPriority      = myPriorities.Pop();
            //double ddd = priorities[currentPriority];
            double ddd = 0.25;// 0.95;// 0.85; // Порог эффективности маршрута по выбранному критерию.

            if (ddd > 1 || ddd < 0.25)
            {
                throw new Exception("Priority must been from [0.25; 1]");
            }
            //List<IgnoringFragment> globalIgnoringFragments = new List<IgnoringFragment>();
            IgnoringFragments ignoringFragments = new IgnoringFragments();//!!!!!!!!!!!!!!

            //List<IgnoringFragment> currentIgnoringFragments;

            //Point myStartPoint = findedOptimalRoutes[0].startPoint;

            for (OptimalRoute selectedOptimalRoute = findedOptimalRoutes[0]; selectedOptimalRoute != null; selectedOptimalRoute.Visited(), selectedOptimalRoute = SelectOptimalRouteWithMinimalMark(findedOptimalRoutes, Priority.MinimalTime))
            {
                ignoringRoutes = new List <Route>();//!!!!!!!!!!!1111111111
                // Проходим по всем ребрам выбранного пути и строим новые маршруты при удалении ребер:
                for (Points.Point tmpP = selectedOptimalRoute.myPoints.finalPoint; tmpP.Previous != null; tmpP = tmpP.Previous)
                {
                    if (tmpP.Route != null && !ignoringRoutes.Contains(tmpP.Route))
                    {
                        ignoringRoutes.Add(tmpP.Route);
                    }


                    ////// Игнорируемое "ребро":
                    ////IgnoringFragment tmpIgnFragm = new IgnoringFragment(tmpP.StationCode, tmpP.RouteCode, tmpP.PreviousStationCode);

                    //////!!!!!!!!!!!!!!!!!//
                    ////ignoringFragments = new IgnoringFragments(selectedOptimalRoute.myIgnoringFragments);//!!!!

                    ////if (ignoringFragments.Contains(tmpIgnFragm)) continue;
                    ////ignoringFragments.Add(tmpIgnFragm);

                    ////Points myPoints = null;
                    //////Point myFinishPoint = null;
                    ////OptimalRoute tmpOptimalRoute = null;

                    //////myPoints = selectedOptimalRoute.MyPoints.Downgrade(ignoringFragments);
                    //////myFinishPoint = selectedOptimalRoute.finalPoint.Downgrade(ignoringFragments);

                    //////myPoints = tmpP.Previous.CurrentGraph;

                    ////// Строим новый маршрут, избегая указанные ребра:
                    ////tmpOptimalRoute = new OptimalRoute(nowPos, needPos, time, types, speed, dopTimeMinutes, ignoringList: ignoringFragments/*,/*myStartPoint,*/ /*myPoints*//*, myFinishPoint*/);


                    ////n2++;
                    ////if (tmpOptimalRoute.TotalTime.TotalSeconds <= findedOptimalRoutes[0].TotalTime.TotalSeconds / ddd)
                    ////{
                    ////    string tmpJSON = JsonConvert.SerializeObject(tmpOptimalRoute.points);
                    ////    bool ok = false;
                    ////    foreach (OptimalRoute opt in findedOptimalRoutes)
                    ////    {
                    ////        if (JsonConvert.SerializeObject(opt.points) == tmpJSON)
                    ////        {
                    ////            ok = true;
                    ////            break;
                    ////        }
                    ////    }
                    ////    if (ok) continue;
                    ////    findedOptimalRoutes.Add(tmpOptimalRoute);
                    ////    n1++;
                    ////}
                }
                foreach (Route r in ignoringRoutes)
                {
                    if (selectedOptimalRoute.ignoringRoutes.Contains(r))
                    {
                        continue;
                    }
                    List <Route> ignoringRoutesAdd = new List <Route>(selectedOptimalRoute.ignoringRoutes);
                    ignoringRoutesAdd.Add(r);
                    OptimalRoute tmpOptimalRoute = new OptimalRoute(nowPos, needPos, time, types, speed, dopTimeMinutes, ignoringRoutesAdd: ignoringRoutesAdd);

                    n2++;
                    if (tmpOptimalRoute.TotalTime.TotalSeconds <= findedOptimalRoutes[0].TotalTime.TotalSeconds / ddd)
                    {
                        string tmpJSON = JsonConvert.SerializeObject(tmpOptimalRoute.points);
                        bool   ok      = false;
                        foreach (OptimalRoute opt in findedOptimalRoutes)
                        {
                            if (JsonConvert.SerializeObject(opt.points) == tmpJSON)
                            {
                                ok = true;
                                break;
                            }
                        }
                        if (ok)
                        {
                            continue;
                        }
                        findedOptimalRoutes.Add(tmpOptimalRoute);
                        n1++;
                    }
                }
            }
            //MessageBox.Show(n1 + " from " + n2);
            return(findedOptimalRoutes);
        }
Beispiel #2
0
            /*
             * /// <summary>
             * /// Откатывает вершины до момента, когда они еще не содержали блокируемые фрагменты пути.
             * /// </summary>
             * /// <param name="ignoringFragments">Блокируемые фрагменты пути.</param>
             * /// <returns>Возвращает ближайшую версию, не содержащую блокируемые фрагменты пути.</returns>
             * public Points Downgrade(IgnoringFragments ignoringFragments)
             * {
             *  Points newP = new Points(startPoint, finalPoint);
             *  foreach (Point p in this) newP.Add(p.Downgrade(ignoringFragments));
             *  return newP;
             * }*/
            /// <summary>
            /// Находит кратчайший путь.
            /// </summary>
            /// <param name="myStartPoint"></param>
            /// <param name="myFinishPoint"></param>
            /// <param name="myIgnoringFragments"></param>
            /// <param name="time"></param>
            /// <param name="types"></param>
            /// <param name="speed"></param>
            /// <param name="reservedTime"></param>
            /// <param name="databaseMysqlConnection"></param>
            public void CountShortWay(/*Point myStartPoint, Point myFinishPoint,*/ List <Route> ignoringRoutes, IgnoringFragments myIgnoringFragments, DateTime time, IEnumerable <RouteType> types, double speed, TimeSpan reservedTime, MySql.Data.MySqlClient.MySqlConnection databaseMysqlConnection)
            {
                //TimeSpan overLimitResedvedTime = TimeSpan.FromMinutes(20);

                DEBUG_timeToCreateNext = new TimeSpan();
                DateTime t0 = DateTime.Now, t1;
                TimeSpan /*t_total = new TimeSpan(),*/          t_giversin = new TimeSpan(), t_finding_time = new TimeSpan() /*, t_upd_in_stations = new TimeSpan()*/;
                TimeSpan /*t_updating_total = new TimeSpan(),*/ t_going_check_total = new TimeSpan(), t_stations = new TimeSpan(), t_without_finding_marks = new TimeSpan();

                for (Point selectedPoint = Next(); selectedPoint != null; selectedPoint = Next())
                {
                    //!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
                    if (selectedPoint.TotalTime > finalPoint.TotalTime /* + overLimitResedvedTime*/) //... Пропускаем и удаляем, если значение метки превышает минимальное время до пункта назначения.
                    {
                        //points.Remove(selectedPoint);//
                        break;
                        //continue;//
                    }
                    DateTime t4 = DateTime.Now;
                    DateTime t3 = DateTime.Now;
                    Station  selectedPointStation = selectedPoint.Station;
                    if (selectedPointStation != null)
                    {
                        // Момент, когда мы прибудем на остановку:
                        DateTime momentWhenComingToStation = time + selectedPoint.TotalTime;

                        //t1 = DateTime.Now;
                        // Загружаем маршруты, проходящие через остановку:
                        List <Route> routesOnStation;// = routesOnStation = Database.GetRoutesOnStation(selectedPointStation.hashcode, canReadDataFromLocalCopy: true);
                        if (selectedPointStation.routes != null)
                        {
                            routesOnStation = selectedPointStation.routes;
                        }
                        else
                        {
                            continue;
                        }

                        //t_total += DateTime.Now - t1;
                        foreach (Route selectedRoute in routesOnStation)
                        {
                            if (ignoringRoutes != null && ignoringRoutes.Contains(selectedRoute))
                            {
                                continue;
                            }
                            if (types.Contains(RouteTypeConverter.FromString(selectedRoute.type)))
                            {
                                //t1 = DateTime.Now;
                                // Следующая остановка у данного транспорта:
                                Station nextStation = selectedRoute.getNextStation(selectedPointStation);

                                /*// Код остановки, на которую попадем на данном транспорте:
                                 * string nextCode = selectedRoute.getNextStationCodeAfter(selectedPointStation.hashcode, canReadDataFromLocalCopy: true);*/
                                //t_total += DateTime.Now - t1;
                                if (nextStation /*nextCode*/ != null) // Если остановка не является конечной, то:
                                {
                                    //t1 = DateTime.Now;
                                    // Загружаем расписание:
                                    Timetable table = selectedRoute.GetTimetable(selectedPointStation);//Database.GetTimetable(selectedPointStation.hashcode, selectedRoute.hashcode, databaseMysqlConnection, canReadDataFromLocalCopy: true);
                                    //t_total += DateTime.Now - t1;
                                    // Блокируем попытку попасть указанным транспортом на указанную остановку:
                                    if (myIgnoringFragments.Contains(nextStation.hashcode /*nextCode*/, selectedRoute.hashcode, selectedPointStation.hashcode))
                                    {
                                        continue;
                                    }

                                    if (table.type == TableType.table) // Если это точное расписание, то:
                                    {
                                        // Минимальный начальный момент, с который можно начинать ожидать посадку:
                                        DateTime momentWhenAskingForGoing = momentWhenComingToStation;

                                        // Резервируем дополнительное время, если будем пересаживаться на другой маршрут:
                                        //if (selectedPoint.RouteCode == null || selectedPoint.RouteCode != selectedRoute.hashcode) momentWhenAskingForGoing += reservedTime;
                                        if (selectedPoint.Route != null && selectedPoint.Route != selectedRoute)
                                        {
                                            momentWhenAskingForGoing += reservedTime;
                                        }

                                        t1 = DateTime.Now;
                                        // Подсчитываем, сколько будем ожидать этот транспорт на остановке:
                                        TimeSpan waitingTime = table.FindTimeAfter(momentWhenAskingForGoing);
                                        t_finding_time += DateTime.Now - t1;

                                        // Момент, когда мы сядем в транспорт:
                                        DateTime momentWhenSitInTransport = momentWhenAskingForGoing + waitingTime;
                                        //t1 = DateTime.Now;

                                        /*// Следующая остановка у данного транспорта:
                                         * Station nextStation = Database.GetStationByHashcode(nextCode, databaseMysqlConnection, canReadDataFromLocalCopy: true);*/

                                        // И соответствующее расписание на этой остановке:
                                        Timetable tbl = selectedRoute.GetTimetable(nextStation);//Database.GetTimetable(nextStation.hashcode, selectedRoute.hashcode, databaseMysqlConnection, canReadDataFromLocalCopy: true);
                                        //t_total += DateTime.Now - t1;
                                        t1 = DateTime.Now;
                                        // (сколько будем ехать до следующей остановки):
                                        TimeSpan goingOnTransportTime = tbl.FindTimeAfter(momentWhenSitInTransport);
                                        t_finding_time += DateTime.Now - t1;

                                        // Метка времени:
                                        TimeSpan onNextPointTotalTime = momentWhenSitInTransport - momentWhenComingToStation + goingOnTransportTime + selectedPoint.TotalTime;
                                        //t1 = DateTime.Now;
                                        if (Find(nextStation).tryUpdate(onNextPointTotalTime, selectedPoint, selectedPointStation, selectedRoute))
                                        {
                                        }
                                        //t_updating_total += DateTime.Now - t1;
                                    }
                                    else if (table.type == TableType.periodic)
                                    {
                                        throw new NotImplementedException();
                                    }
                                }
                            }
                        }
                    }
                    //t_upd_in_stations = TimeSpan.FromMilliseconds(t_updating_total.TotalMilliseconds);
                    t_stations += DateTime.Now - t3;
                    GeoCoords selectedPointCoords = selectedPoint.Coords;
                    t_without_finding_marks += DateTime.Now - t4;
                    // Нет смысла идти пешком "транзитом" через остановку:
                    /*//11111111111111111111111111!!!!!!!!!!!!!!!!!*/
                    if (selectedPoint.Route == null)
                    {
                        continue;
                    }
                    t4 = DateTime.Now;
                    DateTime t2 = DateTime.Now;
                    // Попробуем пройти пешком до других "вершин":
                    foreach (Point p in this /*!!!!!!!!!!!!points*/)
                    {
                        if (!p.IsVisited && p != selectedPoint)
                        {
                            // Блокируем попытку дойти пешком до указанной остановки:
                            if (myIgnoringFragments.Contains(p.StationCode, null, selectedPointStation.hashcode))
                            {
                                continue;
                            }

                            t1 = DateTime.Now;
                            int distanceToSelectedPoint = GeoCoords.Distance(selectedPointCoords, p.Coords);
                            t_giversin += DateTime.Now - t1;

                            TimeSpan goingTime = GetTimeForGoingTo(distanceToSelectedPoint, speed /*, true, sp*/);

                            TimeSpan newTime = selectedPoint.TotalTime + goingTime + reservedTime;
                            /*if (p != myFinishPoint)*/ // newTime += reservedTime;
                            //t1 = DateTime.Now;
                            if (p.tryUpdate(newTime, selectedPoint, selectedPointStation))
                            {
                            }
                            //t_updating_total += DateTime.Now - t1;
                        }
                    }
                    t_going_check_total += DateTime.Now - t2;

                    t_without_finding_marks += DateTime.Now - t4;
                    if (myIgnoringFragments.Contains(null, null, selectedPointStation.hashcode))
                    {
                        continue;
                    }
                    //t1 = DateTime.Now;
                    if (finalPoint.tryUpdate(selectedPoint.TotalTime + GetTimeForGoingTo(selectedPointCoords, finalPoint.Coords, speed), selectedPoint, selectedPointStation))
                    {
                    }
                    //t_updating_total += DateTime.Now - t1;
                }

                t1 = DateTime.Now;
                // Сокращаем время ходьбы пешком до минимума и избавляемся от "бессмысленных" пересадок, сохраняя общее время неизменным:
                Point currentPoint = finalPoint.Previous;

                while (currentPoint != startPoint)
                {
                    Route r = currentPoint.Route;
                    if (r != null)
                    {
                        Point previousPoint = currentPoint.Previous;
                        if (previousPoint != startPoint && previousPoint.Route != r) // Если на предыдущую остановку мы добрались другим транспортом, то:
                        {
                            Station previousRouteStation = r.getPreviousStation(previousPoint.Station);
                            if (previousRouteStation != null)
                            {
                                Point point = previousRouteStation.Point;
                                if (point != null && point.IsVisited)
                                {
                                    Timetable ttt = r.GetTimetable(previousRouteStation);
                                    if (ttt != null)
                                    {
                                        DateTime ddd      = time + previousPoint.TotalTime;
                                        TimeSpan moment   = r.GetTimetable(currentPoint.Station).FindTimeAfter(ddd);
                                        TimeSpan tmp_time = ttt.FindTimeBefore(ddd + moment);

                                        TimeSpan momentArriveOnCurrent   = previousPoint.TotalTime + moment;
                                        TimeSpan momentSittingOnPrevious = momentArriveOnCurrent + tmp_time;

                                        /*bool bbb = point.Route != null && point.Route.GetTimetable(point.Station) != null && point.Route.GetTimetable(point.Station).FindTimeAfter(time + point.TotalTime) <= previousPoint.TotalTime + moment + tmp_time;
                                         * if (bbb)
                                         * {
                                         *  previousPoint.Route = r;
                                         *  previousPoint.Previous = point;////!bbb && point.TotalTime <= momentSittingOnPrevious &&
                                         * }
                                         * else */
                                        if (/*point.TotalGoingTime>=previousPoint.TotalGoingTime || */ point.TotalTime <= previousPoint.TotalTime /* && point.TotalGoingTime <= previousPoint.TotalGoingTime*/)
                                        {
                                            previousPoint.Route    = r;
                                            previousPoint.Previous = point;
                                        }
                                    }
                                }
                            }
                        }
                    }
                    currentPoint = currentPoint.Previous;
                }

                //MessageBox.Show("Total: " + (DateTime.Now - t0).TotalMilliseconds
                ///**///+ "\n\tWithout finding minimal marks: " + t_without_finding_marks.TotalMilliseconds
                //+ "\n\tFinding minimal marks: " + DEBUG_timeToCreateNext.TotalMilliseconds
                //+ "\n\tStations: " + t_stations.TotalMilliseconds
                //+ "\n\t\tFinding time: " + t_finding_time.TotalMilliseconds
                //+ "\n\tWalking checks: " + t_going_check_total.TotalMilliseconds
                //+ "\n\t\tGaversin: " + t_giversin.TotalMilliseconds/**/
                //+ "\n\tRecount: " + (DateTime.Now - t1).TotalMilliseconds
                //);
            }
        /// <summary>
        ///
        /// </summary>
        /// <param name="nowPos"></param>
        /// <param name="needPos"></param>
        /// <param name="time">Начальный момент времени.</param>
        /// <param name="types">Допустимые типы транспорта.</param>
        /// <param name="goingSpeed">Скорость движения пешком.</param>
        /// <param name="dopTimeMinutes">Резерв времени для ожидания транспорта.</param>
        public OptimalRoute(GeoCoords nowPos, GeoCoords needPos, DateTime time, IEnumerable <RouteType> types = null, double goingSpeed = 5, double dopTimeMinutes = 2, List <Route> ignoringRoutesAdd = null, IEnumerable <IgnoringFragment> ignoringList = null, /*Point myStartPoint = null,*/ Points myPoints = null /*, Point myFinishPoint = null*/)
        {
            if (ignoringRoutesAdd != null)
            {
                this.ignoringRoutes = ignoringRoutesAdd;
            }
            else
            {
                this.ignoringRoutes = new List <Route>();
            }
            Database.TryInitialize();
            MySql.Data.MySqlClient.MySqlConnection databaseMysqlConnection = Database.conn;

            this.needPos    = needPos;
            this.nowPos     = nowPos;
            this.goingSpeed = goingSpeed;
            this.time       = time;
            TimeSpan reservedTime = TimeSpan.FromMinutes(dopTimeMinutes);

            if (types == null)
            {
                types = new RouteType[] { RouteType.bus, RouteType.trolleybus, /*RouteType.tram, RouteType.metro, RouteType.express_bus, RouteType.marsh*/ }
            }
            ;
            this.types = types;//{ RouteType.bus };//

            if (ignoringList != null)
            {
                myIgnoringFragments = new IgnoringFragments(ignoringList);
            }
            else
            {
                myIgnoringFragments = new IgnoringFragments();
            }

            //if (myPoints == null)
            //{
            Points.Point myStartPoint  = new Points.Point(TimeSpan.FromSeconds(0), nowPos);
            Points.Point myFinishPoint = new Points.Point(TimeSpan.FromDays(25000), needPos);
            myFinishPoint.tryUpdate(GetTimeForGoingTo(nowPos, needPos, goingSpeed) + TimeSpan.FromMinutes(20), myStartPoint);//!!!!!!!!!!!!!!!!!
            //myFinishPoint.tryUpdate(GetTimeForGoingTo(GoogleApi.GetWalkingDistance(nowPos, needPos), goingSpeed), myStartPoint);
            myPoints = new Points(myStartPoint, myFinishPoint);
            // Получим "начальный" список станций:
            List <Station> stationsList = Database.GetStationsAround(myPoints.startPoint.Coords, GeoCoords.Distance(myPoints.startPoint.Coords, myPoints.finalPoint.Coords), canReadDataFromLocalCopy: true);

            myPoints.Fill(stationsList, goingSpeed, reservedTime, myIgnoringFragments);

            //}

            //else
            //{
            //    if (myFinishPoint == null || myStartPoint == null)
            //        throw new Exception();

            //}

            //DateTime ttt1 = DateTime.Now;
            // Находим кратчайшие пути до всех вершин:
            myPoints.CountShortWay(/*myStartPoint, myFinishPoint,*/ ignoringRoutes, myIgnoringFragments, time, types, goingSpeed, reservedTime, databaseMysqlConnection);

            //myFinishPoint.tryUpdate(GetTimeForGoingTo(nowPos, needPos, goingSpeed), myStartPoint);//!!!!!!!!!!!!!!!!!

            //MessageBox.Show((DateTime.Now - ttt1).TotalMilliseconds.ToString());

            Points.Point tmpP = myPoints.finalPoint;
            this.points.Add(tmpP.ToString());////
            while (tmpP.Previous != null)
            {
                tmpP = tmpP.Previous;//
                this.points.Add(tmpP.ToString());
                if (tmpP.Previous == null && tmpP.Coords != myPoints.startPoint.Coords)
                {
                    throw new Exception("Где-то удалилась часть маршрута...");
                }
            }

            this.totalTime      = myPoints.finalPoint.TotalTime;
            this.totalGoingTime = myPoints.finalPoint.TotalGoingTime;
            this.totalTransportChangingCount = myPoints.finalPoint.TotalTransportChangingCount;

            /*this.finalPoint = myFinishPoint;
             * this.startPoint = myStartPoint;*/
            this.myPoints = myPoints;
        }
Beispiel #4
0
            public void Fill(IEnumerable <Station> stationsList, double goingSpeed, TimeSpan reservedTime, IgnoringFragments myIgnoringFragments = null)
            {
                foreach (Station st in stationsList)
                {
                    if (myIgnoringFragments != null && myIgnoringFragments.Contains(st.hashcode, null, null))
                    {
                        continue;
                    }

                    Point add = new Point(TimeSpan.FromDays(25000), st);
                    add.tryUpdate(GetTimeForGoingTo(this.startPoint.Coords, st.Coords, goingSpeed) + reservedTime, this.startPoint);
                    this.Add(add);
                }
            }