From 8f6d2b48f22b695574bd4a6c4ac91b1ac9f780b1 Mon Sep 17 00:00:00 2001 From: ningshuxia <ningshuxia0927@outlook.com> Date: 星期一, 06 五月 2024 17:28:35 +0800 Subject: [PATCH] 调度算法 大致完成 --- Schedule/IStation.Algorithm/Schedule/SchedulingHelper.cs | 268 ++++++++++++++++++++++++++++++++++++++++------------- 1 files changed, 200 insertions(+), 68 deletions(-) diff --git a/Schedule/IStation.Algorithm/Schedule/SchedulingHelper.cs b/Schedule/IStation.Algorithm/Schedule/SchedulingHelper.cs index 0e9e97c..c3af6bc 100644 --- a/Schedule/IStation.Algorithm/Schedule/SchedulingHelper.cs +++ b/Schedule/IStation.Algorithm/Schedule/SchedulingHelper.cs @@ -24,11 +24,14 @@ public class OptimalCombine { public OptimalCombine() { } - public List<int> Flags { get; set; } public double Flow { get; set; } public double Head { get; set; } public double Power { get; set; } public List<FreCombine> Combines { get; set; } + public List<int> Flags { get; set; } + public int FlagCount { get; set; } + public string Remark { get; set; } + public double MeritRatio { get; set; } } #endregion @@ -38,12 +41,15 @@ /// </summary> public class SchedulingHelper { - double _frequency_def = 50; decimal _frequency_min = 25; decimal _frequency_max = 50; decimal _frequency_space = 0.1m;//棰戠巼闂撮殧 - double _head_space = 0.1;//鎵▼闂撮殧 + double _start_stop_loss_coefficient = 0.95;//娉靛惎鍋滄崯澶辩郴鏁� + + double _sel_opt_flow_deviation_ratio = 0.05;//鍙�夋柟妗堢殑娴侀噺鍋忓樊姣� + double _sel_opt_reasonable_flow_deviation_ratio = 0.005;//鍚堢悊鐨勬柟妗堢殑娴侀噺鍋忓樊姣� + #region RunFlag string _falgFrePumpTag = "B"; @@ -97,24 +103,92 @@ DAL.ScheduleAnaLog _dalAnaLog = new DAL.ScheduleAnaLog(); - private List<int> _combineFlags1 = new List<int>() { 11, 12, 13, 14, 16, 17, 18 }; - private List<int> _combineFlags2 = new List<int>() { 15 }; + /* private List<int> _combineFlags1 = new List<int>() { 11, 12, 13, 14, 16, 17, 18 }; + private List<int> _combineFlags2 = new List<int>() { 15 };*/ - public void Ana(List<Pump> pumps, double taget_flow, double tagetHead) + public string Ana(List<Pump> pumps, List<int> flags_part1, List<int> flags_part2, double target_flow, double target_head, List<int> current_open_pump_flags, List<int> must_open_pump_flags, List<int> must_not_open_pump_flags) { - tagetHead = Math.Round(tagetHead); + if (pumps == null || !pumps.Any()) + { + return "鏃犳柟妗�:pumps is null"; + } + target_flow = Math.Round(target_flow, 1); + target_head = Math.Round(target_head, 1); + + #region 瀛樺湪-褰撳墠寮�娉靛垪琛� + + var exist_current_open_pump_flags = current_open_pump_flags != null && current_open_pump_flags.Count > 0; + + #endregion + + #region 瀛樺湪-蹇呭紑娉靛垪琛� + + var must_open_pump_flags_remark = string.Empty; + var exist_must_open_pump_flags = must_open_pump_flags != null && must_open_pump_flags.Count > 0; + if (exist_must_open_pump_flags) + { + must_open_pump_flags = must_open_pump_flags.OrderBy(x => x).ToList(); + must_open_pump_flags_remark = IntListHelper.ToString(must_open_pump_flags); + } + + #endregion + + #region 瀛樺湪-蹇呬笉鑳藉紑娉靛垪琛� + + var exist_must_not_open_pump_flags = must_not_open_pump_flags != null && must_not_open_pump_flags.Count > 0; + + #endregion + var pump_flag_list = pumps.Select(x => x.ID).ToList(); + var optimal_combine_list = new List<OptimalCombine>(); for (int pumpCount = 1; pumpCount <= pumps.Count; pumpCount++) { - var combine_list = PermutationAndCombination<int>.GetCombination(pump_flag_list.ToArray(), pumpCount); + if (pumpCount == 1) + { + var max_total_flow = pumps.Max(x => x.Qr); + if (max_total_flow < target_flow) + continue; + } + var combine_list = PermutationAndCombination<int>.GetCombination(pump_flag_list.ToArray(), pumpCount);//鎺掑垪缁勫悎 foreach (var combine in combine_list) { + double combine_merit_ratio = 1;//缁勫悎鎷╀紭鐜� + if (exist_must_open_pump_flags) + { + var combine_remark = IntListHelper.ToString(combine.OrderBy(x => x)); + if (!combine_remark.Contains(must_open_pump_flags_remark)) + continue; + } + if (exist_must_not_open_pump_flags) + { + var exist_intersected = combine.Intersect(must_not_open_pump_flags).Count() > 0; + if (exist_intersected) + continue; + } + + int start_stop_count = 0;//鍚仠鏁伴噺 + if (exist_current_open_pump_flags) + { + var start_pump_count = combine.Except(current_open_pump_flags).Count(); + var close_pump_count = current_open_pump_flags.Except(combine).Count(); + start_stop_count = start_pump_count + close_pump_count;//鍚仠鏁伴噺 + } + else + { + start_stop_count = combine.Count(); + if (exist_must_open_pump_flags) + { + start_stop_count = combine.Except(must_open_pump_flags).Count(); + } + } + var total_loss_ratio = Math.Pow(_start_stop_loss_coefficient, start_stop_count);//鍚仠涓�娆℃崯澶变簺鑳借�� + combine_merit_ratio *= total_loss_ratio; + List<int> combine_flag_list_part1 = new List<int>(); List<int> combine_flag_list_part2 = new List<int>(); - foreach (var pump in combine) { - if (_combineFlags1.Contains(pump)) + if (flags_part1.Contains(pump)) { combine_flag_list_part1.Add(pump); } @@ -124,7 +198,7 @@ } } - + //鍖哄垎鍚屽瀷鍙锋车 List<FreCombine> fre_combine_list_part1 = new List<FreCombine>(); List<FreCombine> fre_combine_list_part2 = new List<FreCombine>(); @@ -136,7 +210,7 @@ var runFlag = GetGFlag(flag); if (conclusion_list_dic.ContainsKey(flag)) continue; - var conclusionList = _dalScheduleConclusion.GetList(runFlag, tagetHead); + var conclusionList = _dalScheduleConclusion.GetList(runFlag, target_head); conclusion_list_dic[flag] = conclusionList; } @@ -165,12 +239,7 @@ continue; fre_combine_list_part1.Add(freCombine); } - - - - } - if (combine_flag_list_part2.Count > 0) { var conclusion_list_dic = new Dictionary<int, List<Entity.ScheduleConclusion>>(); @@ -179,7 +248,7 @@ var runFlag = GetGFlag(flag); if (conclusion_list_dic.ContainsKey(flag)) continue; - var conclusionList = _dalScheduleConclusion.GetList(runFlag, tagetHead); + var conclusionList = _dalScheduleConclusion.GetList(runFlag, target_head); conclusion_list_dic[flag] = conclusionList; } @@ -210,68 +279,131 @@ } } + if (fre_combine_list_part1.Count == 0 && fre_combine_list_part2.Count == 0) + continue; - var optimalCombine = AnaOptimalCombine(fre_combine_list_part1, fre_combine_list_part2, taget_flow); - } + double total_flow_deviation = target_flow;//鎬绘祦閲忓亸宸� + double total_power = double.MaxValue;//鎬诲姛鐜� + double total_flow = double.MaxValue;//鎬绘祦閲� - } - - } - - - private OptimalCombine AnaOptimalCombine(List<FreCombine> fre_combine_list_part1, List<FreCombine> fre_combine_list_part2, double target_flow) - { - double flow_deviation = target_flow; - double total_power = double.MaxValue; - double total_flow = double.MaxValue; - - FreCombine optimal_combine_part1 = null; - FreCombine optimal_combine_part2 = null; - for (int Index_part1 = 0; Index_part1 < fre_combine_list_part1.Count; Index_part1++) - { - for (int Index_part2 = 0; Index_part2 < fre_combine_list_part2.Count; Index_part2++) - { - var fre_combine1 = fre_combine_list_part1[Index_part1]; - var fre_combine2 = fre_combine_list_part2[Index_part2]; - - var current_flow = fre_combine1.Flow + fre_combine2.Flow; - var current_power = fre_combine1.Power + fre_combine2.Power; - - var diff_flow = Math.Abs(current_flow - target_flow); - if (diff_flow < flow_deviation) + FreCombine optimal_combine_part1 = null; + FreCombine optimal_combine_part2 = null; + if (fre_combine_list_part1.Count < 1 || fre_combine_list_part2.Count < 1) { - optimal_combine_part1 = fre_combine1; - optimal_combine_part2 = fre_combine2; - total_power = fre_combine1.Power + fre_combine2.Power; - total_flow = current_flow; - flow_deviation = diff_flow; + if (fre_combine_list_part1.Count < 1) + { + fre_combine_list_part1 = fre_combine_list_part2; + } + for (int Index_part1 = 0; Index_part1 < fre_combine_list_part1.Count; Index_part1++) + { + var fre_combine1 = fre_combine_list_part1[Index_part1]; + var current_flow = fre_combine1.Flow; + var current_power = fre_combine1.Power; + + var diff_flow = Math.Abs(current_flow - target_flow); + if (diff_flow < total_flow_deviation) + { + optimal_combine_part1 = fre_combine1; + total_power = fre_combine1.Power; + total_flow = current_flow; + total_flow_deviation = diff_flow; + } + + if (diff_flow < target_flow * 0.01 && current_power < total_power) + { + optimal_combine_part1 = fre_combine1; + total_power = fre_combine1.Power; + total_flow = current_flow; + } + } + } + else + { + for (int Index_part1 = 0; Index_part1 < fre_combine_list_part1.Count; Index_part1++) + { + for (int Index_part2 = 0; Index_part2 < fre_combine_list_part2.Count; Index_part2++) + { + var fre_combine1 = fre_combine_list_part1[Index_part1]; + var fre_combine2 = fre_combine_list_part2[Index_part2]; + + var current_flow = fre_combine1.Flow + fre_combine2.Flow; + var current_power = fre_combine1.Power + fre_combine2.Power; + + var diff_flow = Math.Abs(current_flow - target_flow); + if (diff_flow < total_flow_deviation) + { + optimal_combine_part1 = fre_combine1; + optimal_combine_part2 = fre_combine2; + total_power = fre_combine1.Power + fre_combine2.Power; + total_flow = current_flow; + total_flow_deviation = diff_flow; + } + + if (diff_flow < target_flow * 0.01 && current_power < total_power) + { + optimal_combine_part1 = fre_combine1; + optimal_combine_part2 = fre_combine2; + total_power = fre_combine1.Power + fre_combine2.Power; + total_flow = current_flow; + } + + } + } } - if (diff_flow < target_flow * 0.01 && current_power < total_power) + if (optimal_combine_part1 == null && optimal_combine_part2 == null) + continue; + + var total_flow_deviation_ratio = Math.Abs((1 - Math.Abs((total_flow / target_flow)))); + if (total_flow_deviation_ratio > _sel_opt_flow_deviation_ratio) + continue; + if (total_flow_deviation_ratio > _sel_opt_reasonable_flow_deviation_ratio) { - optimal_combine_part1 = fre_combine1; - optimal_combine_part2 = fre_combine2; - total_power = fre_combine1.Power + fre_combine2.Power; - total_flow = current_flow; + combine_merit_ratio -= total_flow_deviation_ratio; } + + #region 鍒嗘瀽鏈�浼樼粍鍚堟柟妗� + + var optimal_combine = new OptimalCombine(); + optimal_combine.Combines = new List<FreCombine>(); + optimal_combine.Flags = new List<int>(); + if (optimal_combine_part1 != null) + { + optimal_combine.Combines.Add(optimal_combine_part1); + optimal_combine.Flags.AddRange(optimal_combine_part1.Flags); + } + if (optimal_combine_part2 != null) + { + optimal_combine.Combines.Add(optimal_combine_part2); + optimal_combine.Flags.AddRange(optimal_combine_part2.Flags); + } + optimal_combine.Flow = total_flow; + optimal_combine.Power = total_power; + optimal_combine.Flags = optimal_combine.Flags.OrderBy(x => x).ToList(); + optimal_combine.FlagCount = optimal_combine.Flags.Count; + optimal_combine.Remark = IntListHelper.ToString(optimal_combine.Flags); + + optimal_combine.MeritRatio = combine_merit_ratio; + optimal_combine.Head = target_head; + optimal_combine_list.Add(optimal_combine); + + #endregion } } - if (optimal_combine_part1 == null && optimal_combine_part2 == null) - return default; - var optimal_combine = new OptimalCombine(); - optimal_combine.Combines = new List<FreCombine>(); - if (optimal_combine_part1 != null) + + if (optimal_combine_list.Count < 1) + return "鏃犳柟妗�"; + + var sb = new StringBuilder(); + optimal_combine_list = optimal_combine_list.OrderByDescending(x => x.MeritRatio).ToList(); + foreach (var opt in optimal_combine_list) { - optimal_combine.Combines.Add(optimal_combine_part1); + sb.AppendLine($"MeritRatio:{opt.MeritRatio.ToString("N5")},Flow:{opt.Flow.ToString("N1")},Power:{opt.Power.ToString("N1")}," + + $"Flags:{opt.Remark};FlowDeviation:{(opt.Flow - target_flow).ToString("N1")}"); } - if (optimal_combine_part2 != null) - { - optimal_combine.Combines.Add(optimal_combine_part2); - } - optimal_combine.Flow = total_flow; - optimal_combine.Power = total_power; - return optimal_combine; + return sb.ToString(); + } /// <summary> -- Gitblit v1.9.3