Exemple #1
0
        public static bool CanEscapeTyphoonByFrontCancel(List <Airline> AirlineList)
        {
            int StartIndex, EndIndex;
            var range = GetTyphoonRange(AirlineList);

            StartIndex = range.StartIndex;
            EndIndex   = range.EndIndex;
            //StartIndex 是受   台风影响的航班
            //EndIndex   是不受 台风影响的航班!
            if (EndIndex == -1 || StartIndex == -1 || EndIndex == AirlineList.Count)
            {
                return(false);
            }
            string StartAirPort = AirlineList[EndIndex].StartAirPort;

            if (CheckCondition.TyphoonAirport.Contains(StartAirPort))
            {
                return(false);
            }
            for (int i = EndIndex - 1; i > Math.Max(1, StartIndex - 5); i--)
            {
                //如果存在开始为StartPort的航班
                if (AirlineList[i].StartAirPort.Equals(StartAirPort))
                {
                    for (int j = i; j < EndIndex; j++)
                    {
                        AirlineList[j].FixMethod = enmFixMethod.Cancel;
                    }
                    return(CoreAlgorithm.AdjustAirLineList(AirlineList));
                }
            }
            return(false);
        }
Exemple #2
0
        //关于台风的极端处理
        //1.调机开始点:如果一个航班将要飞往一个台风机场如果无法降落,则视为是开始点,
        //  虽然台风允许提早,则也不一定可以起飞
        //2.第一个没有台风影响的航班作为调机终止点
        //如果没有航班,则选择下一个
        //考虑抢先做调机工作
        public static bool FixByEmptyFly(List <Airline> AirlineList, bool IsTry)
        {
            int StartIndex, EndIndex;
            var range = GetTyphoonRange(AirlineList);

            StartIndex = range.StartIndex;
            EndIndex   = range.EndIndex;
            //StartIndex 是受   台风影响的航班
            //EndIndex   是不受 台风影响的航班!
            if (EndIndex == -1 || StartIndex == -1)
            {
                return(false);
            }
            //空飞航班起点在 StartIndex,终点在 EndIndex

            bool CanEmptyFly = IsCanEmptyFly(AirlineList, ref StartIndex, ref EndIndex);

            if (!CanEmptyFly)
            {
                return(false);
            }
            //新增航班
            Airline EmptyFly = GetEmptyFly(AirlineList, StartIndex, EndIndex);

            if (!IsTry)
            {
                EmptyFlyList.Add(EmptyFly);
            }
            for (int i = StartIndex; i < EndIndex; i++)
            {
                AirlineList[i].FixMethod = enmFixMethod.Cancel;
            }
            return(CoreAlgorithm.AdjustAirLineList(AirlineList));
        }
Exemple #3
0
        public static (int StartCancelIndex, int EndCancelIndex) GetCancelSomeSectionIndex(List <Airline> AirlineList)
        {
            int StartIndex, EndIndex;
            var range = GetTyphoonRange(AirlineList);

            StartIndex = range.StartIndex;
            EndIndex   = range.EndIndex;
            //StartIndex 是受   台风影响的航班
            //EndIndex   是不受 台风影响的航班!
            if (EndIndex == -1 || StartIndex == -1)
            {
                return(-1, -1);
            }
            var MinScore         = double.MaxValue;
            var MinStartEndIndex = (-1, -1);

            //台风外的3个,台风内的5个,进行双循环匹配
            for (int StIdx = Math.Max(1, StartIndex - 5); StIdx < StartIndex; StIdx++)
            {
                for (int EdIdx = StartIndex + 1; EdIdx < Math.Min(AirlineList.Count, StartIndex + 8); EdIdx++)
                {
                    if (AirlineList[StIdx].FixMethod == enmFixMethod.Cancel ||
                        AirlineList[EdIdx].FixMethod == enmFixMethod.Cancel)
                    {
                        continue;
                    }
                    if (AirlineList[StIdx].EndAirPort.Equals(AirlineList[EdIdx].StartAirPort))
                    {
                        if (!CheckCondition.TyphoonAirport.Contains(AirlineList[StIdx].EndAirPort))
                        {
                            var AirlineListClone = Utility.DeepCopy(AirlineList);
                            for (int CancelIdx = StIdx + 1; CancelIdx < EdIdx; CancelIdx++)
                            {
                                AirlineListClone[CancelIdx].FixMethod = enmFixMethod.Cancel;
                            }
                            if (CoreAlgorithm.AdjustAirLineList(AirlineListClone))
                            {
                                var CurrentResult = Statistics.WriteResult(AirlineListClone);
                                if (MinScore > CurrentResult)
                                {
                                    MinScore         = CurrentResult;
                                    MinStartEndIndex = (StIdx, EdIdx);
                                }
                            }
                        }
                    }
                }
            }
            return(MinStartEndIndex);
        }
Exemple #4
0
        public static int GetFixByEmptyFlyAdvanced(List <Airline> AirlineList)
        {
            int StartIndex, EndIndex;
            var range = GetTyphoonRange(AirlineList);

            StartIndex = range.StartIndex;
            EndIndex   = range.EndIndex;
            //StartIndex 是受   台风影响的航班
            //EndIndex   是不受 台风影响的航班!
            if (EndIndex == -1 || StartIndex == -1)
            {
                return(-1);
            }
            var MinScore    = double.MaxValue;
            var MinEndIndex = -1;

            //空飞航班起点在 StartIndex,终点在 EndIndex之前是否也可以?
            for (int NewEndIndex = StartIndex + 1; NewEndIndex < EndIndex; NewEndIndex++)
            {
                var StartIndexClone = StartIndex;
                var EndIndexClone   = NewEndIndex;
                if (IsCanEmptyFly(AirlineList, ref StartIndexClone, ref EndIndexClone))
                {
                    if (StartIndex != StartIndexClone || NewEndIndex != EndIndexClone)
                    {
                        continue;
                    }
                    //可以直飞
                    //Console.WriteLine("Try EmptyFly" + AirlineList[StartIndex].ID + "," + AirlineList[NewEndIndex].ID);
                    //尝试状态
                    var AirlineListClone = Utility.DeepCopy(AirlineList);
                    var EmptyFly         = GetEmptyFly(AirlineListClone, StartIndex, NewEndIndex);
                    for (int i = StartIndex; i < NewEndIndex; i++)
                    {
                        AirlineListClone[i].FixMethod = enmFixMethod.Cancel;
                    }
                    if (CoreAlgorithm.AdjustAirLineList(AirlineListClone))
                    {
                        var CurrentResult = Statistics.WriteResult(AirlineListClone) + Statistics.EmptyFlyParm;
                        if (MinScore > CurrentResult)
                        {
                            MinScore    = CurrentResult;
                            MinEndIndex = NewEndIndex;
                        }
                    }
                }
            }
            return(MinEndIndex);
        }
Exemple #5
0
        public static double FixByEmptyFlyAdvanced(List <Airline> AirlineList, int BestEndIndex, bool IsTry)
        {
            int StartIndex, NewEndIndex;
            var range = GetTyphoonRange(AirlineList);

            StartIndex  = range.StartIndex;
            NewEndIndex = BestEndIndex;
            var EmptyFly = GetEmptyFly(AirlineList, StartIndex, NewEndIndex);

            for (int i = StartIndex; i < NewEndIndex; i++)
            {
                AirlineList[i].FixMethod = enmFixMethod.Cancel;
            }
            CoreAlgorithm.AdjustAirLineList(AirlineList);
            if (!IsTry)
            {
                EmptyFlyList.Add(EmptyFly);
            }
            return(Statistics.WriteResult(AirlineList) + (IsTry ? Statistics.EmptyFlyParm : 0));
        }
Exemple #6
0
        public static bool CanEscapeTyphoonByCancelAdvanced(List <Airline> AirlineList)
        {
            int StartIndex, EndIndex;
            var range = GetTyphoonRange(AirlineList);

            StartIndex = range.StartIndex;
            EndIndex   = range.EndIndex;
            //StartIndex 是受   台风影响的航班
            //EndIndex   是不受 台风影响的航班!
            if (EndIndex == -1 || StartIndex == -1 || EndIndex == AirlineList.Count)
            {
                return(false);
            }
            string StartAirPort = AirlineList[StartIndex].StartAirPort;

            if (CheckCondition.TyphoonAirport.Contains(StartAirPort))
            {
                return(false);
            }
            for (int i = StartIndex; i < EndIndex; i++)
            {
                //如果存在开始为StartPort的航班
                if (AirlineList[i].StartAirPort.Equals(StartAirPort))
                {
                    //是否能够通过延迟的方式,使得航班降落
                    var CloneAirlineList = Utility.DeepCopy(AirlineList);
                    CloneAirlineList[i].Problem = GetProblem(CloneAirlineList[i]);
                    if (FixAirportProblemByChangeTakeOffTime(CloneAirlineList, i, CloneAirlineList[i]))
                    {
                        for (int j = StartIndex; j < i; j++)
                        {
                            AirlineList[j].FixMethod = enmFixMethod.Cancel;
                        }
                        return(CoreAlgorithm.AdjustAirLineList(AirlineList));
                    }
                }
            }
            return(false);
        }
        public static (bool IsOK, double Score) FixAirline(List <Airline> PlaneAirlineList, bool IsTry = false)
        {
            //停机库的备份
            var CloneTyphoonAirportRemain = Utility.DeepCopy(CheckCondition.TyphoonAirportRemain);

            //多线程,防止出现异常循环体内外写不同的变量
            foreach (var airport in CloneTyphoonAirportRemain.Keys)
            {
                CheckCondition.TyphoonAirportRemain[airport] = 999;
            }
            //复杂调整
            var PlaneAirlineListCloneComplexAdjust = Utility.DeepCopy(PlaneAirlineList);
            var ScoreComplexAdjust = double.MaxValue;

            if (CoreAlgorithm.FixByComplexAdjust(PlaneAirlineListCloneComplexAdjust))
            {
                ScoreComplexAdjust = Statistics.WriteResult(PlaneAirlineListCloneComplexAdjust);
            }

            //单纯调机
            var PlaneAirlineListCloneWithEmptyFly = Utility.DeepCopy(PlaneAirlineList);
            var ScoreWithEmptyFly = double.MaxValue;

            //调机的结果
            if (CoreAlgorithm.FixByEmptyFly(PlaneAirlineListCloneWithEmptyFly, true))
            {
                //计算空飞分数正式输出的时候,是最后一起算的,所以,这里必须要补上空飞的惩罚
                ScoreWithEmptyFly = Statistics.WriteResult(PlaneAirlineListCloneWithEmptyFly) + Statistics.EmptyFlyParm;
            }

            //取消一些航班
            var PlaneAirlineListCloneCancel = Utility.DeepCopy(PlaneAirlineList);
            var ScoreCancel = double.MaxValue;

            if (CoreAlgorithm.CanEscapeTyphoonByCancel(PlaneAirlineListCloneCancel))
            {
                ScoreCancel = Statistics.WriteResult(PlaneAirlineListCloneCancel);
            }

            //取消一些航班-高级
            var PlaneAirlineListCloneCancelAdvanced = Utility.DeepCopy(PlaneAirlineList);
            var ScoreCancelAdvanced = double.MaxValue;

            if (CoreAlgorithm.CanEscapeTyphoonByCancelAdvanced(PlaneAirlineListCloneCancelAdvanced))
            {
                ScoreCancelAdvanced = Statistics.WriteResult(PlaneAirlineListCloneCancelAdvanced);
            }

            //普通调整
            var ScoreNormal = double.MaxValue;
            var PlaneAirlineListCloneNormal = Utility.DeepCopy(PlaneAirlineList);

            if (CoreAlgorithm.AdjustAirLineList(PlaneAirlineListCloneNormal))
            {
                ScoreNormal = Statistics.WriteResult(PlaneAirlineListCloneNormal);
            }

            var PlaneAirlineListCloneFrontCancel = Utility.DeepCopy(PlaneAirlineList);
            var ScoreFrontCancel = double.MaxValue;

            if (CoreAlgorithm.CanEscapeTyphoonByFrontCancel(PlaneAirlineListCloneFrontCancel))
            {
                ScoreFrontCancel = Statistics.WriteResult(PlaneAirlineListCloneFrontCancel);
            }

            var PlaneAirlineListCloneConvertToEmpty = Utility.DeepCopy(PlaneAirlineList);
            var ScoreConvertToEmpty = double.MaxValue;

            if (CoreAlgorithm.FixByConvertToEmptyFly(PlaneAirlineListCloneConvertToEmpty, true))
            {
                //计算空飞分数正式输出的时候,是最后一起算的,所以,这里必须要补上空飞的惩罚
                ScoreConvertToEmpty = Statistics.WriteResult(PlaneAirlineListCloneConvertToEmpty) + Statistics.EmptyFlyParm;
            }

            var PlaneAirlineListCloneEmptyAdvanced = Utility.DeepCopy(PlaneAirlineList);
            var ScoreEmptyAdvanced = double.MaxValue;
            int BestEndIndex       = CoreAlgorithm.GetFixByEmptyFlyAdvanced(PlaneAirlineListCloneEmptyAdvanced);

            if (BestEndIndex != -1)
            {
                ScoreEmptyAdvanced = CoreAlgorithm.FixByEmptyFlyAdvanced(PlaneAirlineListCloneEmptyAdvanced, BestEndIndex, true);
            }

            var PlaneAirlineListCloneCancelSomeSection = Utility.DeepCopy(PlaneAirlineList);
            var ScoreCancelSomeSection = double.MaxValue;
            var BestStartEndIndex      = CoreAlgorithm.GetCancelSomeSectionIndex(PlaneAirlineListCloneCancelSomeSection);

            if (BestStartEndIndex.StartCancelIndex != -1)
            {
                ScoreCancelSomeSection = CoreAlgorithm.FixByCancelSomeSection(PlaneAirlineListCloneCancelSomeSection, BestStartEndIndex);
            }


            //寻找最小的一种方式
            double MinScore = Math.Min(ScoreComplexAdjust, ScoreWithEmptyFly);

            MinScore = Math.Min(ScoreCancel, MinScore);
            MinScore = Math.Min(ScoreCancelAdvanced, MinScore);
            MinScore = Math.Min(ScoreNormal, MinScore);
            MinScore = Math.Min(ScoreFrontCancel, MinScore);
            MinScore = Math.Min(ScoreConvertToEmpty, MinScore);
            MinScore = Math.Min(ScoreEmptyAdvanced, MinScore);
            MinScore = Math.Min(ScoreCancelSomeSection, MinScore);
            if (IsTry)
            {
                return(MinScore != double.MaxValue, MinScore);
            }
            CheckCondition.TyphoonAirportRemain = CloneTyphoonAirportRemain;
            if (Math.Round(MinScore, 0) == Math.Round(ScoreComplexAdjust, 0))
            {
                Utility.Log("FixByComplexAdjust:" + PlaneAirlineList[0].ModifiedPlaneID);
                return(CoreAlgorithm.FixByComplexAdjust(PlaneAirlineList), MinScore);
            }

            if (Math.Round(MinScore, 0) == Math.Round(ScoreWithEmptyFly, 0))
            {
                Utility.Log("FixByEmptyFly:" + PlaneAirlineList[0].ModifiedPlaneID);
                return(CoreAlgorithm.FixByEmptyFly(PlaneAirlineList, false), MinScore);
            }
            if (Math.Round(MinScore, 0) == Math.Round(ScoreCancel, 0))
            {
                Utility.Log("CanEscapeTyphoonByCancel:" + PlaneAirlineList[0].ModifiedPlaneID);
                return(CoreAlgorithm.CanEscapeTyphoonByCancel(PlaneAirlineList), MinScore);
            }
            if (Math.Round(MinScore, 0) == Math.Round(ScoreCancelAdvanced, 0))
            {
                Utility.Log("CanEscapeTyphoonByCancelAdvanced:" + PlaneAirlineList[0].ModifiedPlaneID);
                return(CoreAlgorithm.CanEscapeTyphoonByCancelAdvanced(PlaneAirlineList), MinScore);
            }
            if (Math.Round(MinScore, 0) == Math.Round(ScoreNormal, 0))
            {
                //普通调整
                Utility.Log("AdjustAirLineList:" + PlaneAirlineList[0].ModifiedPlaneID);
                return(CoreAlgorithm.AdjustAirLineList(PlaneAirlineList), MinScore);
            }
            if (Math.Round(MinScore, 0) == Math.Round(ScoreFrontCancel, 0))
            {
                Utility.Log("CanEscapeTyphoonByFrontCancel:" + PlaneAirlineList[0].ModifiedPlaneID);
                return(CoreAlgorithm.CanEscapeTyphoonByFrontCancel(PlaneAirlineList), MinScore);
            }
            if (Math.Round(MinScore, 0) == Math.Round(ScoreConvertToEmpty, 0))
            {
                Utility.Log("FixByConvertToEmptyFly:" + PlaneAirlineList[0].ModifiedPlaneID);
                return(CoreAlgorithm.FixByConvertToEmptyFly(PlaneAirlineList, false), MinScore);
            }
            if (Math.Round(MinScore, 0) == Math.Round(ScoreEmptyAdvanced, 0))
            {
                Utility.Log("FixByEmptyFlyAdvanced:" + PlaneAirlineList[0].ModifiedPlaneID);
                CoreAlgorithm.FixByEmptyFlyAdvanced(PlaneAirlineList, BestEndIndex, false);
                return(true, MinScore);
            }
            if (Math.Round(MinScore, 0) == Math.Round(ScoreCancelSomeSection, 0))
            {
                Utility.Log("ScoreCancelSomeSection:" + PlaneAirlineList[0].ModifiedPlaneID);
                CoreAlgorithm.FixByCancelSomeSection(PlaneAirlineList, BestStartEndIndex);
                return(true, MinScore);
            }
            return(false, double.MaxValue);
        }
        public static bool CanChangePlane(List <Airline> AirlineList)
        {
            int StartIndex, EndIndex;
            var range = CoreAlgorithm.GetTyphoonRange(AirlineList);

            StartIndex = range.StartIndex;
            EndIndex   = range.EndIndex;
            if (StartIndex <= 0 || EndIndex == -1)
            {
                return(false);
            }

            /*StartIndex 是受   台风影响的航班
             * EndIndex   是不受 台风影响的航班!
             * 空飞航班起点在 StartIndex,终点在 EndIndex
             * 第一:机型相同(不同机型惩罚太大)
             * 第二:被取代的航班的飞机,其被取代航班的前期航班,能有一个目的地为当前调整航班台风后的机场的机会
             * 第三:代价不能太大*/

            var CurrentAirline  = AirlineList[StartIndex - 1];
            var MinTakeOffTime  = CurrentAirline.ModifiedEndTime.AddMinutes(Utility.StayAtAirPortMinutes);
            var Airport         = CurrentAirline.EndAirPort;
            var orgPlaneType    = CurrentAirline.PlaneType;
            int MinScore        = int.MaxValue;
            var OrgAirlineList  = new List <Airline>();
            var RepAirlineList  = new List <Airline>();
            var BaseAirlineList = new List <Airline>();
            var OrgAirlineIdx   = new List <int>();
            var RepAirlineIdx   = new List <int>();
            var BaseIdx         = new List <int>();

            foreach (var info in AirportIdAirlineDic[Airport])
            {
                //机型相同(不同机型惩罚太大)
                if (info.IsTakeOff && info.EventTime >= MinTakeOffTime && info.EventAirline.PlaneType == orgPlaneType)
                {
                    //已经有调机或者取消的情况,则跳过
                    if (CoreAlgorithm.EmptyFlyList.Count((x => { return(x.ModifiedPlaneID == info.EventAirline.ModifiedPlaneID); })) == 1)
                    {
                        continue;
                    }
                    if (Solution.PlaneIdAirlineDic[info.EventAirline.ModifiedPlaneID].Count((x => { return(x.FixMethod == enmFixMethod.Cancel); })) > 0)
                    {
                        continue;
                    }
                    var ReplaceAirline = Solution.PlaneIdAirlineDic[info.EventAirline.ModifiedPlaneID];
                    //被取代的航班的飞机,其被取代航班的前期航班,能有一个目的地为当前调整航班台风后的机场的机会
                    for (int org = EndIndex; org < AirlineList.Count; org++)
                    {
                        //遍历原来航班的台风后的航班(包括台风后的第一个航班)
                        //当前被替代航班为止(倒序,越接近越好)
                        var replbase = 0; //被取代航班索引号
                        for (int i = 0; i < ReplaceAirline.Count; i++)
                        {
                            if (ReplaceAirline[i].ID == info.EventAirline.ID)
                            {
                                replbase = i;
                            }
                        }

                        for (int rep = replbase - 1; rep > 0; rep--)
                        {
                            if (ReplaceAirline[rep].EndAirPort.Equals(AirlineList[org].EndAirPort))
                            {
                                var Score = replbase - rep + org - EndIndex;

                                /*
                                 * Console.Write("被取代航班在原飞行计划中的索引:" + RepIdx);
                                 * Console.WriteLine("  前导航班索引:" + rep + "  间隔航班数:" + (RepIdx - rep));
                                 * Console.WriteLine("被前导航班:" + ReplaceAirline[rep].ToString());
                                 * Console.Write("台风后续首航班索引:" + EndIndex);
                                 * Console.WriteLine("台风后续目标航班索引:" + org + "  间隔航班数:" + (org - EndIndex));
                                 * Console.WriteLine("总体偏差:" + Score);
                                 */
                                if (Score < MinScore)
                                {
                                    OrgAirlineList.Clear();
                                    RepAirlineList.Clear();
                                    BaseAirlineList.Clear();
                                    OrgAirlineIdx.Clear();
                                    RepAirlineIdx.Clear();
                                    BaseIdx.Clear();
                                    MinScore = Score;
                                    OrgAirlineList.Add(AirlineList[org]);
                                    RepAirlineList.Add(ReplaceAirline[rep]);
                                    BaseAirlineList.Add(info.EventAirline);
                                    OrgAirlineIdx.Add(org);
                                    RepAirlineIdx.Add(rep);
                                    BaseIdx.Add(replbase);
                                }
                                else
                                {
                                    if (Score == MinScore)
                                    {
                                        OrgAirlineList.Add(AirlineList[org]);
                                        RepAirlineList.Add(ReplaceAirline[rep]);
                                        BaseAirlineList.Add(info.EventAirline);
                                        OrgAirlineIdx.Add(org);
                                        RepAirlineIdx.Add(rep);
                                        BaseIdx.Add(replbase);
                                    }
                                }
                                break;
                            }
                        }
                    }
                }
            }
            if (OrgAirlineList.Count != 0)
            {
                //选择基准时间最早的航班,理由如下
                //在衔接的时候,越是早交换,则越可以避免过站时间不足的问题
                var SetIdx             = 0;
                var OrgPlandId         = AirlineList[0].ModifiedPlaneID;
                var RelPlaneId         = BaseAirlineList[SetIdx].ModifiedPlaneID;
                var ReplaceAirlineList = Solution.PlaneIdAirlineDic[RelPlaneId];
                //取消的时候牵涉到台风场景
                if (CheckCondition.TyphoonAirport.Contains(ReplaceAirlineList[RepAirlineIdx[SetIdx]].EndAirPort))
                {
                    return(false);
                }
                if (CheckCondition.TyphoonAirport.Contains(AirlineList[OrgAirlineIdx[SetIdx]].EndAirPort))
                {
                    return(false);
                }
                //飞机航线的测试
                for (int i = BaseIdx[SetIdx]; i < ReplaceAirlineList.Count; i++)
                {
                    if (!CheckCondition.IsAirlinePlaneAvalible(ReplaceAirlineList[i].StartAirPort, ReplaceAirlineList[i].EndAirPort, OrgPlandId))
                    {
                        return(false);
                    }
                }
                for (int i = OrgAirlineIdx[SetIdx] + 1; i < AirlineList.Count; i++)
                {
                    if (!CheckCondition.IsAirlinePlaneAvalible(AirlineList[i].StartAirPort, AirlineList[i].EndAirPort, RelPlaneId))
                    {
                        return(false);
                    }
                }
                var AirlineListClone        = Utility.DeepCopy(AirlineList);
                var ReplaceAirlineListClone = Utility.DeepCopy(ReplaceAirlineList);
                //1.从StartIndex开始,到ORG为止的航班取消掉
                for (int i = StartIndex; i < OrgAirlineIdx[SetIdx] + 1; i++)
                {
                    AirlineListClone[i].FixMethod = enmFixMethod.Cancel;
                }
                //2.被取代的部分取消
                for (int i = RepAirlineIdx[SetIdx] + 1; i < BaseIdx[SetIdx]; i++)
                {
                    ReplaceAirlineListClone[i].FixMethod = enmFixMethod.Cancel;
                }
                //3.取代操作(取代者)
                for (int i = BaseIdx[SetIdx]; i < ReplaceAirlineList.Count; i++)
                {
                    ReplaceAirlineListClone[i].ModifiedPlaneID = OrgPlandId;
                }
                //4.取代操作(被取代者)
                for (int i = OrgAirlineIdx[SetIdx] + 1; i < AirlineList.Count; i++)
                {
                    AirlineListClone[i].ModifiedPlaneID = RelPlaneId;
                }

                var NewOrgPlaneList = new List <Airline>();
                var NewRelPlaneList = new List <Airline>();
                for (int i = 0; i < AirlineListClone.Count; i++)
                {
                    if (AirlineListClone[i].ModifiedPlaneID == OrgPlandId)
                    {
                        NewOrgPlaneList.Add(AirlineListClone[i]);
                    }
                    if (AirlineListClone[i].ModifiedPlaneID == RelPlaneId)
                    {
                        NewRelPlaneList.Add(AirlineListClone[i]);
                    }
                }
                for (int i = 0; i < ReplaceAirlineListClone.Count; i++)
                {
                    if (ReplaceAirlineListClone[i].ModifiedPlaneID == OrgPlandId)
                    {
                        NewOrgPlaneList.Add(ReplaceAirlineListClone[i]);
                    }
                    if (ReplaceAirlineListClone[i].ModifiedPlaneID == RelPlaneId)
                    {
                        NewRelPlaneList.Add(ReplaceAirlineListClone[i]);
                    }
                }
                NewOrgPlaneList.Sort((x, y) => { return(x.ModifiedEndTime.CompareTo(y.ModifiedStartTime)); });
                NewRelPlaneList.Sort((x, y) => { return(x.ModifiedEndTime.CompareTo(y.ModifiedStartTime)); });

                //检查时间间隔
                for (int i = 0; i < NewOrgPlaneList.Count; i++)
                {
                    if (i != 0)
                    {
                        if (NewOrgPlaneList[i].PlaneID != NewOrgPlaneList[i].ModifiedPlaneID)
                        {
                            if (NewOrgPlaneList[i].ModifiedStartTime.Subtract(NewOrgPlaneList[i - 1].ModifiedEndTime).TotalMinutes < Utility.StayAtAirPortMinutes)
                            {
                                return(false);
                            }
                        }
                    }
                }

                for (int i = 0; i < NewRelPlaneList.Count; i++)
                {
                    if (i != 0)
                    {
                        if (NewRelPlaneList[i].PlaneID != NewRelPlaneList[i].ModifiedPlaneID)
                        {
                            if (NewRelPlaneList[i].ModifiedStartTime.Subtract(NewRelPlaneList[i - 1].ModifiedEndTime).TotalMinutes < Utility.StayAtAirPortMinutes)
                            {
                                return(false);
                            }
                        }
                    }
                }
                //1.从StartIndex开始,到ORG为止的航班取消掉
                for (int i = StartIndex; i < OrgAirlineIdx[SetIdx] + 1; i++)
                {
                    AirlineList[i].FixMethod = enmFixMethod.Cancel;
                }
                //2.被取代的部分取消
                for (int i = RepAirlineIdx[SetIdx] + 1; i < BaseIdx[SetIdx]; i++)
                {
                    ReplaceAirlineList[i].FixMethod = enmFixMethod.Cancel;
                }
                //3.取代操作(取代者)
                for (int i = BaseIdx[SetIdx]; i < ReplaceAirlineList.Count; i++)
                {
                    ReplaceAirlineList[i].ModifiedPlaneID = OrgPlandId;
                    ReplaceAirlineList[i].FixMethod       = enmFixMethod.ChangePlane;
                }
                //4.取代操作(被取代者)
                for (int i = OrgAirlineIdx[SetIdx] + 1; i < AirlineList.Count; i++)
                {
                    AirlineList[i].ModifiedPlaneID = RelPlaneId;
                    AirlineList[i].FixMethod       = enmFixMethod.ChangePlane;
                }
                //5.Solution的飞机表更新
                Solution.PlaneIdAirlineDic[OrgPlandId].Clear();
                Solution.PlaneIdAirlineDic[RelPlaneId].Clear();
                foreach (var airline in AirlineList)
                {
                    Solution.PlaneIdAirlineDic[airline.ModifiedPlaneID].Add(airline);
                }
                foreach (var airline in ReplaceAirlineList)
                {
                    Solution.PlaneIdAirlineDic[airline.ModifiedPlaneID].Add(airline);
                }

                Console.WriteLine(OrgPlandId + "->" + RelPlaneId);

                return(true);
            }
            return(false);
        }
Exemple #9
0
        public static bool FixByComplexAdjust(List <Airline> airlineList)
        {
            //将所有的航班分组(假设没有从台风飞到台风的航班,如果有的话,暂时不处理)
            //分组的规则为,第一个是起飞是台风关联航班,最后一个结尾是台风关联航班
            var            airlinegrpList = new List <List <Airline> >();
            var            IsGroupStarted = false;
            List <Airline> CurrentGroup   = null;

            for (int i = 0; i < airlineList.Count; i++)
            {
                if (CheckCondition.TyphoonAirport.Contains(airlineList[i].StartAirPort))
                {
                    //起飞是台风航班
                    CurrentGroup = new List <Airline>();
                    airlinegrpList.Add(CurrentGroup);
                    CurrentGroup.Add(airlineList[i]);
                    IsGroupStarted = true;
                }
                else
                {
                    if (CheckCondition.TyphoonAirport.Contains(airlineList[i].EndAirPort))
                    {
                        //降落是台风航班
                        if (IsGroupStarted)
                        {
                            //分组开始状态
                            CurrentGroup.Add(airlineList[i]);
                            IsGroupStarted = false;
                        }
                        else
                        {
                            //分组未开始状态(第一个航班降落在台风机场的情况)
                            CurrentGroup = new List <Airline>();
                            airlinegrpList.Add(CurrentGroup);
                            CurrentGroup.Add(airlineList[i]);
                        }
                    }
                    else
                    {
                        //起飞降落都是台风航班
                        if (IsGroupStarted)
                        {
                            //分组开始状态
                            CurrentGroup.Add(airlineList[i]);
                        }
                        else
                        {
                            //普通航班
                            CurrentGroup = new List <Airline>();
                            airlinegrpList.Add(CurrentGroup);
                            CurrentGroup.Add(airlineList[i]);
                        }
                    }
                }
            }
            var firstTyphoonGroupId = -1;

            for (int i = 0; i < airlinegrpList.Count; i++)
            {
                foreach (var airline in airlinegrpList[i])
                {
                    //判断被台风影响的航班
                    var Problem = CheckCondition.IsExistTyphoon(airline);
                    if (Problem.DetailType == ProblemType.TyphoonLand)
                    {
                        firstTyphoonGroupId = i;
                        break;
                    }
                }
                if (firstTyphoonGroupId != -1)
                {
                    break;
                }
            }
            //索引检查
            if (firstTyphoonGroupId >= airlinegrpList.Count - 1)
            {
                return(false);
            }
            if (firstTyphoonGroupId <= 0)
            {
                return(false);
            }
            // Console.WriteLine("台风开始组号:[" + firstTyphoonGroupId + "]");
            var firstAirline = airlinegrpList[firstTyphoonGroupId + 1].First();
            var lastAirline  = airlinegrpList[firstTyphoonGroupId - 1].Last();

            //台风上一组的结束和台风下一组的开始能否衔接?
            if (lastAirline.EndAirPort != firstAirline.StartAirPort)
            {
                return(false);
            }
            //下一组的第一个航班是否可以通过提早飞行而成功?
            firstAirline.Problem = GetProblem(firstAirline);
            //检查之前,需要正确设置上一个航班的信息!
            firstAirline.PreviousAirline = lastAirline;
            if (firstAirline.Problem.DetailType == ProblemType.None || firstAirline.Problem.DetailType == ProblemType.TyphoonStay)
            {
                return(false);
            }
            if (!FixTyphoonTakeOffByChangeTakeOffTime(firstAirline))
            {
                return(false);
            }
            //尝试将第一组台风影响航班取消
            foreach (var item in airlinegrpList[firstTyphoonGroupId])
            {
                item.FixMethod = enmFixMethod.Cancel;
            }
            return(CoreAlgorithm.AdjustAirLineList(airlineList));
        }
        public static void Run()
        {
            InitAirportIdAirlineDic();

            //单位时间容量限制
            UnitCapLimit();
            return;

            //修改执飞航班
            TryChangePlane();

            CancelPairList.Clear();

            GetCancelPair();
            //按照机场和重要度进行排序
            CancelPairList.Sort((x, y) =>
            {
                if (x.StartAirPort == y.StartAirPort)
                {
                    return(y.ImportFac.CompareTo(x.ImportFac));
                }
                else
                {
                    return(x.StartAirPort.CompareTo(y.StartAirPort));
                }
            });

            GapList.Clear();
            foreach (var airportId in AirportIdAirlineDic.Keys)
            {
                PutCancelToBigGap(airportId);
            }
            //按照机场和时间进行排序
            GapList.Sort(
                (x, y) =>
            {
                if (x.AirportID == y.AirportID)
                {
                    return(x.LandTime.CompareTo(y.LandTime));
                }
                else
                {
                    return(x.AirportID.CompareTo(y.AirportID));
                }
            }
                );


            //进行匹配
            for (int i = 0; i < CancelPairList.Count; i++)
            {
                double MaxScore   = 0;
                int    MaxIndex   = -1;
                var    CancelItem = CancelPairList[i];
                for (int j = 0; j < GapList.Count; j++)
                {
                    var GapItem = GapList[j];
                    if (GapItem.IsFilled)
                    {
                        continue;
                    }

                    //Gap的机场和取消组的机场一致
                    if (CancelItem.StartAirPort != GapItem.AirportID)
                    {
                        continue;
                    }
                    //不是同一架飞机,机型相同
                    if (CancelItem.PlaneID == GapItem.PlaneID || CancelItem.PlaneType != GapItem.PlaneType)
                    {
                        continue;
                    }
                    //中间是台风,暂时不考虑
                    var ArrivalTime = GapItem.LandTime.AddMinutes(Utility.StayAtAirPortMinutes) + CancelItem.First.FlightSpan;
                    if (CheckCondition.TyphoonAirport.Contains(CancelItem.MidAirport))
                    {
                        DateTime TyphoonTime = DateTime.MinValue;
                        foreach (var item in CheckCondition.TyphoonList)
                        {
                            if (item.AirPort == CancelItem.MidAirport && item.TroubleType == "停机")
                            {
                                TyphoonTime = item.EndTime;
                                break;
                            }
                        }
                        if (ArrivalTime < TyphoonTime)
                        {
                            continue;
                        }
                    }
                    //联航不能分割
                    if (CancelItem.First.ComboAirline != null && !CancelItem.First.IsFirstCombinedVoyage)
                    {
                        continue;
                    }
                    if (CancelItem.Second.ComboAirline != null && CancelItem.Second.IsFirstCombinedVoyage)
                    {
                        continue;
                    }
                    var TakeOffEarlyTime = GapItem.LandTime.AddMinutes(Utility.StayAtAirPortMinutes);
                    if (TakeOffEarlyTime <= CancelItem.First.StartTime)
                    {
                        //取消组的开始时间暂时要求在50分钟之内
                        if (CancelItem.Second.EndTime.AddMinutes(Utility.StayAtAirPortMinutes) < GapItem.TakeOffTime)
                        {
                            //结束飞行后有充分的过站时间
                            Console.WriteLine("Cancel: " + CancelItem.PlaneID + " StartAirPort:" + CancelItem.StartAirPort + " MidAirPort:" + CancelItem.MidAirport + " " +
                                              CancelItem.First.StartTime + " " + CancelItem.Second.EndTime);
                            Console.WriteLine("Gap: " + GapItem.PlaneID + " StartAirPort:" + GapItem.AirportID + " " + GapItem.LandTime + " " + GapItem.TakeOffTime);
                        }
                    }
                    else
                    {
                        //允许延期
                        var CloneAirline = Utility.DeepCopy(Solution.PlaneIdAirlineDic[GapItem.PlaneID]);
                        //取消恢复后的可以挽回的分数:
                        var FixScore = CancelItem.ImportFac * Statistics.CancelAirlineParm;
                        //修改前分数
                        var GapBefore = Statistics.WriteResult(CloneAirline);
                        //添加取消项目到原列表中
                        var C1       = Utility.DeepCopy(CancelItem.First);
                        var C2       = Utility.DeepCopy(CancelItem.Second);
                        var TimeDiff = TakeOffEarlyTime.Subtract(CancelItem.First.StartTime);
                        C1.ModifiedStartTime = TakeOffEarlyTime;
                        C2.ModifiedStartTime = C1.ModifiedEndTime.AddMinutes(Utility.StayAtAirPortMinutes);
                        C1.FixMethod         = enmFixMethod.UnFixed;
                        C2.FixMethod         = enmFixMethod.UnFixed;
                        C1.ModifiedPlaneID   = GapItem.PlaneID;
                        C2.ModifiedPlaneID   = GapItem.PlaneID;
                        if (C2.ModifiedEndTime.AddMinutes(Utility.StayAtAirPortMinutes) > GapItem.TakeOffTime)
                        {
                            continue;
                        }
                        CloneAirline.Add(C1);
                        CloneAirline.Add(C2);
                        CloneAirline.Sort((x, y) => { return(x.ModifiedStartTime.CompareTo(y.ModifiedStartTime)); });
                        if (!CoreAlgorithm.AdjustAirLineList(CloneAirline))
                        {
                            continue;
                        }
                        var GapAfter = Statistics.WriteResult(CloneAirline);
                        var Decream  = FixScore - (GapAfter - GapBefore);
                        if (Decream > MaxScore)
                        {
                            MaxScore = Decream;
                            MaxIndex = j;
                        }
                    }
                }

                if (MaxIndex != -1)
                {
                    var GapItem = GapList[MaxIndex];
                    Console.WriteLine("Gap PlaneID:" + GapItem.PlaneID + " Max Score:" + MaxScore);
                    Console.WriteLine("Gap Land:" + GapItem.LandAirline.ToString());
                    Console.WriteLine("Gap Takeoff:" + GapItem.TakeoffAirLine.ToString());
                    var TakeOffEarlyTime = GapItem.LandTime.AddMinutes(Utility.StayAtAirPortMinutes);
                    CancelItem.First.ModifiedStartTime  = TakeOffEarlyTime;
                    CancelItem.Second.ModifiedStartTime = CancelItem.First.ModifiedEndTime.AddMinutes(Utility.StayAtAirPortMinutes);
                    CancelItem.First.ModifiedPlaneID    = GapItem.PlaneID;
                    CancelItem.Second.ModifiedPlaneID   = GapItem.PlaneID;
                    CancelItem.First.FixMethod          = enmFixMethod.UnFixed;
                    CancelItem.Second.FixMethod         = enmFixMethod.UnFixed;
                    Solution.PlaneIdAirlineDic[GapItem.PlaneID].Add(CancelItem.First);
                    Solution.PlaneIdAirlineDic[GapItem.PlaneID].Add(CancelItem.Second);
                    Solution.PlaneIdAirlineDic[GapItem.PlaneID].Sort((x, y) => { return(x.ModifiedStartTime.CompareTo(y.ModifiedStartTime)); });
                    CoreAlgorithm.AdjustAirLineList(Solution.PlaneIdAirlineDic[GapItem.PlaneID]);
                    Solution.GetAirlineDicByPlaneId();
                    GapItem.IsFilled = true;
                }
            }
        }
        static ExchangeRecord ExchangeEvaluateAdvance(string firstPlaneId, string secondPlandId)
        {
            ExchangeRecord Rtn = new ExchangeRecord();

            Rtn.DiffScore = 0;

            List <Airline> first  = Solution.PlaneIdAirlineDic[firstPlaneId];
            List <Airline> second = Solution.PlaneIdAirlineDic[secondPlandId];
            //测试一下当前分数:
            double FirstScore         = scoreDic[firstPlaneId];
            double SecondScore        = scoreDic[secondPlandId];
            var    TotalScore         = FirstScore + SecondScore;
            var    FirstTyphoonRange  = CoreAlgorithm.GetTyphoonRange(first);
            var    SecondTyphonnRange = CoreAlgorithm.GetTyphoonRange(second);

            for (int firstIdx = Math.Max(FirstTyphoonRange.StartIndex - 2, 2); firstIdx < FirstTyphoonRange.EndIndex; firstIdx++)
            {
                //首航班不调整
                if (firstIdx == 0)
                {
                    continue;
                }
                //是否存在无法降落的航班
                var firstAirline = first[firstIdx];

                //相同起飞机场的检查
                var FocusAirport = firstAirline.StartAirPort;
                for (int secondIdx = Math.Max(SecondTyphonnRange.StartIndex - 2, 2); secondIdx < SecondTyphonnRange.EndIndex; secondIdx++)
                {
                    //首航班不调整
                    if (secondIdx == 0)
                    {
                        continue;
                    }
                    var secondAirline = second[secondIdx];
                    if (secondAirline.StartAirPort != FocusAirport)
                    {
                        continue;
                    }
                    //联程不能换飞机(但是可以同时换两个)
                    if ((first[firstIdx].ComboAirline != null && !first[firstIdx].IsFirstCombinedVoyage) ||
                        second[secondIdx].ComboAirline != null && !second[secondIdx].IsFirstCombinedVoyage)
                    {
                        continue;
                    }

                    var FirstAirlineListClone  = Utility.DeepCopy(first);
                    var SecondAirlineListClone = Utility.DeepCopy(second);
                    //时间测试(起飞关系不能乱,等于也不可以,防止前后航班关系错乱)
                    var TakeoffAfterThisTime = SecondAirlineListClone[secondIdx - 1].ModifiedEndTime.AddMinutes(Utility.StayAtAirPortMinutes);
                    var AddTime = TakeoffAfterThisTime.Subtract(FirstAirlineListClone[firstIdx].ModifiedStartTime);
                    if (AddTime.TotalMinutes > 0)
                    {
                        //尝试是否能够将first整体后移
                        for (int i = firstIdx; i < first.Count; i++)
                        {
                            FirstAirlineListClone[i].ModifiedStartTime += AddTime;
                        }
                    }

                    TakeoffAfterThisTime = FirstAirlineListClone[firstIdx - 1].ModifiedEndTime.AddMinutes(Utility.StayAtAirPortMinutes);
                    AddTime = TakeoffAfterThisTime.Subtract(SecondAirlineListClone[secondIdx].ModifiedStartTime);
                    if (AddTime.TotalMinutes > 0)
                    {
                        //尝试是否能够将first整体后移
                        for (int i = secondIdx; i < second.Count; i++)
                        {
                            SecondAirlineListClone[i].ModifiedStartTime += AddTime;
                        }
                    }
                    if (!Exchange(FirstAirlineListClone, firstIdx, SecondAirlineListClone, secondIdx))
                    {
                        continue;
                    }
                    var FirstForTest  = new List <Airline>();
                    var SecondForTest = new List <Airline>();
                    foreach (var air in FirstAirlineListClone)
                    {
                        if (air.ModifiedPlaneID == firstPlaneId)
                        {
                            FirstForTest.Add(air);
                        }
                        else
                        {
                            SecondForTest.Add(air);
                        }
                    }
                    foreach (var air in SecondAirlineListClone)
                    {
                        if (air.ModifiedPlaneID == firstPlaneId)
                        {
                            FirstForTest.Add(air);
                        }
                        else
                        {
                            SecondForTest.Add(air);
                        }
                    }
                    //测试一下交换后分数
                    FirstForTest.Sort((x, y) => { return(x.ModifiedStartTime.CompareTo(y.ModifiedStartTime)); });
                    SecondForTest.Sort((x, y) => { return(x.ModifiedStartTime.CompareTo(y.ModifiedStartTime)); });
                    var FirstScoreAfter = Solution.FixAirline(FirstForTest, true).Score;
                    if (FirstScoreAfter == double.MaxValue)
                    {
                        continue;
                    }
                    var SecondScoreAfter = Solution.FixAirline(SecondForTest, true).Score;
                    if (SecondScoreAfter == double.MaxValue)
                    {
                        continue;
                    }
                    var TotalScoreAfter = FirstScoreAfter + SecondScoreAfter;
                    var Minius          = Math.Round(TotalScoreAfter, 0) - Math.Round(TotalScore, 0);
                    Rtn = new ExchangeRecord()
                    {
                        firstIndex    = firstIdx,
                        secondIndex   = secondIdx,
                        firstPlaneId  = firstPlaneId,
                        secondPlaneId = secondPlandId,
                        firstScore    = FirstScoreAfter,
                        secondScore   = SecondScoreAfter,
                        DiffScore     = Minius,
                    };
                    return(Rtn);
                }
            }
            return(Rtn);
        }
Exemple #12
0
        public static void Run(string PlaneID = "")
        {
            Solution.AirlineDic.Clear();
            Solution.PlaneIdAirlineDic.Clear();
            Solution.CombinedVoyageList.Clear();
            Solution.FlyTimeDic.Clear();
            Solution.PlaneTypeSeatCntDic.Clear();
            Solution.TransTimeList.Clear();
            CheckCondition.AirPortProhibitList.Clear();
            CheckCondition.PlaneProhibitList.Clear();
            CheckCondition.TyphoonList.Clear();
            CheckCondition.TyphoonAirport.Clear();
            var timer = new Stopwatch();

            timer.Start();
            Utility.Log("Start Run AIForAirline...");
            //读取、整理数据
            Solution.ReadCSV();
            //分析数据
            if (false)
            {
                Solution.Analyze();
            }
            //恢复航班
            if (string.IsNullOrEmpty(PlaneID))
            {
                if (false)
                {
                    foreach (var planeid in Solution.PlaneIdAirlineDic.Keys)
                    {
                        CoreAlgorithm.scoreDic.Add(planeid, Solution.FixAirline(Solution.PlaneIdAirlineDic[planeid], true).Score);
                    }
                    Console.WriteLine("当前温度:" + CoreAlgorithm._currentTemperature);
                    do
                    {
                        CoreAlgorithm.CheckExchangableAirline();
                        Solution.GetAirlineDicByPlaneId();
                        Console.WriteLine("当前温度:" + CoreAlgorithm._currentTemperature);
                    } while (CoreAlgorithm._currentTemperature > 0);
                }

                //恢复航班
                Utility.IsUseTyphoonStayRoom = false;
                var UnFix = new List <string>();
                Parallel.ForEach(Solution.PlaneIdAirlineDic.Keys, PlaneIdAirlineKey =>
                {
                    var PlaneAirlineList = Solution.PlaneIdAirlineDic[PlaneIdAirlineKey];
                    if (!Solution.FixAirline(PlaneAirlineList).IsOK)
                    {
                        UnFix.Add(PlaneIdAirlineKey);
                        System.Console.WriteLine("无法修复的飞机号码:" + PlaneAirlineList[0].ModifiedPlaneID);
                    }
                });
                System.Console.WriteLine("启用停机库");
                Utility.IsUseTyphoonStayRoom = true;
                foreach (var PlaneIdAirlineKey in UnFix)
                {
                    var PlaneAirlineList = Solution.PlaneIdAirlineDic[PlaneIdAirlineKey];
                    if (!Solution.FixAirline(PlaneAirlineList).IsOK)
                    {
                        System.Console.WriteLine("无法修复的飞机号码:" + PlaneAirlineList[0].ModifiedPlaneID);
                    }
                    else
                    {
                        System.Console.WriteLine("修复飞机号码:" + PlaneAirlineList[0].ModifiedPlaneID);
                    }
                }

                //签转操作无法多线程
                foreach (var PlaneIdAirlineKey in Solution.PlaneIdAirlineDic.Keys)
                {
                    var PlaneAirlineList = Solution.PlaneIdAirlineDic[PlaneIdAirlineKey];
                    Solution.EndorseGuest(PlaneAirlineList);
                }
                Solution.EndorseTransferGuest();
            }
            else
            {
                //针对航班测试用
                Utility.IsEvalute            = false;
                Utility.IsUseTyphoonStayRoom = false;
                var PlaneAirlineList = Solution.PlaneIdAirlineDic[PlaneID];
                if (Solution.FixAirline(PlaneAirlineList).IsOK)
                {
                    Solution.EndorseGuest(PlaneAirlineList);
                    Solution.EndorseTransferGuest();
                }
                else
                {
                    Utility.IsUseTyphoonStayRoom = true;
                    if (!Solution.FixAirline(PlaneAirlineList).IsOK)
                    {
                        System.Console.WriteLine("无法修复的飞机号码:" + PlaneID);
                    }
                }
            }
            ResultOptimize.Run();
            Utility.Log("Finish!!");
            timer.Stop();
            //输出答案
            var score = Statistics.WriteResult(Solution.AirlineDic.Values.ToList(), true, (int)Math.Round(timer.Elapsed.TotalMinutes, 0));

            Utility.Log("Time Escape:" + timer.Elapsed.ToString());
            //输出Debug页面
            Statistics.WriteDebugInfo(Solution.AirlineDic.Values.ToList());
        }