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); }
//关于台风的极端处理 //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)); }
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); }
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); }
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)); }
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); }
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); }
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()); }