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