namespace IStation.Algorithm
|
{
|
|
#region ViewModel
|
|
/// <summary>
|
///
|
/// </summary>
|
public class FreCombine
|
{
|
public FreCombine() { }
|
public List<int> Flags { get; set; }
|
public int RunCount { get; set; }
|
public double Flow { get; set; }
|
public double Head { get; set; }
|
public double Power { get; set; }
|
public double Efficiency { get; set; }
|
public double Frequency { get; set; }
|
public double Speed { get; set; }
|
public List<FrePump> FrePumps { get; set; }
|
|
public void Round()
|
{
|
this.Flow = Math.Round(this.Flow, 1);
|
this.Head = Math.Round(this.Head, 3);
|
this.Power = Math.Round(this.Power, 1);
|
this.Efficiency = Math.Round(this.Efficiency, 1);
|
this.Frequency = Math.Round(this.Frequency, 1);
|
this.Speed = Math.Round(this.Speed, 1);
|
}
|
|
}
|
|
|
/// <summary>
|
///
|
/// </summary>
|
public class FrePump
|
{
|
public FrePump() { }
|
public int Flag { get; set; }
|
public double Flow { get; set; }
|
public double Head { get; set; }
|
public double Power { get; set; }
|
public double Efficiency { get; set; }
|
public double Frequency { get; set; }
|
public double Speed { get; set; }
|
|
public void Round()
|
{
|
this.Flow = Math.Round(this.Flow, 1);
|
this.Head = Math.Round(this.Head, 3);
|
this.Power = Math.Round(this.Power, 1);
|
this.Efficiency = Math.Round(this.Efficiency, 1);
|
this.Frequency = Math.Round(this.Frequency, 1);
|
this.Speed = Math.Round(this.Speed, 1);
|
}
|
|
}
|
|
|
|
/// <summary>
|
/// 分析泵项
|
/// </summary>
|
public class OptimalCombine
|
{
|
public OptimalCombine() { }
|
public double Flow { get; set; }
|
public double Head { get; set; }
|
public double Power { get; set; }
|
public double Efficiency { get; set; }
|
public double WP { get; set; }
|
public double UWP { 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; }
|
|
public void Round()
|
{
|
this.Flow = Math.Round(this.Flow, 1);
|
this.Head = Math.Round(this.Head, 3);
|
this.Power = Math.Round(this.Power, 1);
|
this.Efficiency = Math.Round(this.Efficiency, 1);
|
this.WP = Math.Round(this.WP, 2);
|
this.UWP = Math.Round(this.UWP, 2);
|
|
if (this.Combines != null && this.Combines.Any())
|
{
|
foreach (var combine in Combines)
|
{
|
combine.Round();
|
if (combine.FrePumps != null && combine.FrePumps.Any())
|
{
|
foreach (var pump in combine.FrePumps)
|
{
|
pump.Round();
|
}
|
}
|
}
|
}
|
}
|
}
|
|
#endregion
|
|
/// <summary>
|
/// 调度分析辅助类
|
/// </summary>
|
public class SchedulingHelper
|
{
|
decimal _frequency_min = 25;
|
decimal _frequency_max = 50;
|
decimal _frequency_space = 0.1m;//频率间隔
|
|
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";
|
string _falgFixPumpTag = "G";
|
string _falgSpaceMark = "_";
|
|
|
string GetRunFlag(int[] flags)
|
{
|
var runFlag = string.Empty;
|
var index = 0;
|
var count = flags.Length;
|
foreach (var flag in flags)
|
{
|
runFlag += GetGFlag(flag);
|
index++;
|
if (index != count)
|
{
|
runFlag += _falgSpaceMark;
|
}
|
}
|
return runFlag;
|
}
|
|
string GetRunFlag(List<int> flags)
|
{
|
var runFlag = string.Empty;
|
var index = 0;
|
var count = flags.Count;
|
foreach (var flag in flags)
|
{
|
runFlag += GetGFlag(flag);
|
index++;
|
if (index != count)
|
{
|
runFlag += _falgSpaceMark;
|
}
|
}
|
return runFlag;
|
}
|
|
string GetGFlag(int flag)
|
{
|
return _falgFrePumpTag + flag;
|
}
|
|
#endregion
|
|
DAL.ScheduleCombine _dal = new DAL.ScheduleCombine();
|
DAL.ScheduleConclusion _dalScheduleConclusion = new DAL.ScheduleConclusion();
|
DAL.ScheduleAnaLog _dalAnaLog = new DAL.ScheduleAnaLog();
|
|
|
public OptimalCombine AnaOptimalCombine(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)
|
{
|
if (pumps == null || !pumps.Any())
|
{
|
return default;
|
}
|
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_nr_dict = pumps.ToDictionary(x => x.ID, x => x.Nr);
|
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++)
|
{
|
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 (flags_part1.Contains(pump))
|
{
|
combine_flag_list_part1.Add(pump);
|
}
|
else
|
{
|
combine_flag_list_part2.Add(pump);
|
}
|
}
|
|
//区分同型号泵
|
List<FreCombine> fre_combine_list_part1 = new List<FreCombine>();
|
List<FreCombine> fre_combine_list_part2 = new List<FreCombine>();
|
|
if (combine_flag_list_part1.Count > 0)
|
{
|
var conclusion_list_dic = new Dictionary<int, List<Entity.ScheduleConclusion>>();
|
foreach (var flag in combine_flag_list_part1)
|
{
|
var runFlag = GetGFlag(flag);
|
if (conclusion_list_dic.ContainsKey(flag))
|
continue;
|
var conclusionList = _dalScheduleConclusion.GetList(runFlag, target_head);
|
conclusion_list_dic[flag] = conclusionList;
|
}
|
|
if (conclusion_list_dic.Count < 1)
|
{
|
continue;
|
}
|
|
for (decimal fre = _frequency_max; fre >= _frequency_min; fre -= _frequency_space)
|
{
|
var freCombine = new FreCombine();
|
freCombine.Frequency = (double)fre;
|
freCombine.Flags = new List<int>();
|
freCombine.FrePumps = new List<FrePump>();
|
foreach (var item in conclusion_list_dic)
|
{
|
var conclusion = item.Value.Find(x => x.Pump1 == (double)fre);
|
if (conclusion != null)
|
{
|
freCombine.Flags.Add(item.Key);
|
freCombine.Flow += conclusion.Flow;
|
freCombine.Power += conclusion.Power;
|
freCombine.RunCount++;
|
|
var fre_pump = new FrePump();
|
fre_pump.Flag = item.Key;
|
fre_pump.Flow = conclusion.Flow;
|
fre_pump.Head = target_head;
|
fre_pump.Power = conclusion.Power;
|
fre_pump.Efficiency = CurveCalcuHelper.CalculateE(fre_pump.Flow, fre_pump.Head, fre_pump.Power);
|
fre_pump.Frequency = freCombine.Frequency;
|
fre_pump.Speed = (double)fre / 50 * pump_nr_dict[item.Key];
|
freCombine.FrePumps.Add(fre_pump);
|
}
|
}
|
if (freCombine.Flags.Count < 1)
|
continue;
|
fre_combine_list_part1.Add(freCombine);
|
}
|
}
|
if (combine_flag_list_part2.Count > 0)
|
{
|
var conclusion_list_dic = new Dictionary<int, List<Entity.ScheduleConclusion>>();
|
foreach (var flag in combine_flag_list_part2)
|
{
|
var runFlag = GetGFlag(flag);
|
if (conclusion_list_dic.ContainsKey(flag))
|
continue;
|
var conclusionList = _dalScheduleConclusion.GetList(runFlag, target_head);
|
conclusion_list_dic[flag] = conclusionList;
|
}
|
|
if (conclusion_list_dic.Count < 1)
|
{
|
continue;
|
}
|
|
for (decimal fre = _frequency_max; fre >= _frequency_min; fre -= _frequency_space)
|
{
|
var freCombine = new FreCombine();
|
freCombine.Frequency = (double)fre;
|
freCombine.Flags = new List<int>();
|
freCombine.FrePumps = new List<FrePump>();
|
foreach (var item in conclusion_list_dic)
|
{
|
var conclusion = item.Value.Find(x => x.Pump1 == (double)fre);
|
if (conclusion != null)
|
{
|
freCombine.Flags.Add(item.Key);
|
freCombine.Flow += conclusion.Flow;
|
freCombine.Power += conclusion.Power;
|
freCombine.RunCount++;
|
|
var fre_pump = new FrePump();
|
fre_pump.Flag = item.Key;
|
fre_pump.Flow = conclusion.Flow;
|
fre_pump.Head = target_head;
|
fre_pump.Power = conclusion.Power;
|
fre_pump.Efficiency = CurveCalcuHelper.CalculateE(fre_pump.Flow, fre_pump.Head, fre_pump.Power);
|
fre_pump.Frequency = freCombine.Frequency;
|
fre_pump.Speed = (double)fre / 50 * pump_nr_dict[item.Key];
|
freCombine.FrePumps.Add(fre_pump);
|
}
|
}
|
if (freCombine.Flags.Count < 1)
|
continue;
|
fre_combine_list_part2.Add(freCombine);
|
}
|
}
|
|
if (fre_combine_list_part1.Count == 0 && fre_combine_list_part2.Count == 0)
|
continue;
|
|
double total_flow_deviation = target_flow;//总流量偏差
|
double total_power = double.MaxValue;//总功率
|
double total_flow = double.MaxValue;//总流量
|
|
FreCombine optimal_combine_part1 = null;
|
FreCombine optimal_combine_part2 = null;
|
if (fre_combine_list_part1.Count < 1 || fre_combine_list_part2.Count < 1)
|
{
|
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 (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)
|
{
|
combine_merit_ratio -= total_flow_deviation_ratio;
|
}
|
|
|
var efficiency = CurveCalcuHelper.CalculateE(total_flow, target_head, total_power);
|
var wp = CurveCalcuHelper.CalculateWP(total_power, total_flow);
|
var uwp = CurveCalcuHelper.CalculateUWP(total_power, total_flow, target_head);
|
|
#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.Head = target_head;
|
optimal_combine.Power = total_power;
|
optimal_combine.Efficiency = efficiency;
|
optimal_combine.WP = wp;
|
optimal_combine.UWP = uwp;
|
|
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_list.Add(optimal_combine);
|
|
#endregion
|
}
|
}
|
|
if (optimal_combine_list.Count < 1)
|
return default;
|
|
optimal_combine_list = optimal_combine_list.OrderByDescending(x => x.MeritRatio).ToList();
|
var opt = optimal_combine_list.First();
|
opt.Round();
|
return opt;
|
}
|
|
|
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)
|
{
|
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++)
|
{
|
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 (flags_part1.Contains(pump))
|
{
|
combine_flag_list_part1.Add(pump);
|
}
|
else
|
{
|
combine_flag_list_part2.Add(pump);
|
}
|
}
|
|
//区分同型号泵
|
List<FreCombine> fre_combine_list_part1 = new List<FreCombine>();
|
List<FreCombine> fre_combine_list_part2 = new List<FreCombine>();
|
|
if (combine_flag_list_part1.Count > 0)
|
{
|
var conclusion_list_dic = new Dictionary<int, List<Entity.ScheduleConclusion>>();
|
foreach (var flag in combine_flag_list_part1)
|
{
|
var runFlag = GetGFlag(flag);
|
if (conclusion_list_dic.ContainsKey(flag))
|
continue;
|
var conclusionList = _dalScheduleConclusion.GetList(runFlag, target_head);
|
conclusion_list_dic[flag] = conclusionList;
|
}
|
|
if (conclusion_list_dic.Count < 1)
|
{
|
continue;
|
}
|
|
for (decimal fre = _frequency_max; fre >= _frequency_min; fre -= _frequency_space)
|
{
|
var freCombine = new FreCombine();
|
freCombine.Frequency = (double)fre;
|
freCombine.Flags = new List<int>();
|
foreach (var item in conclusion_list_dic)
|
{
|
var conclusion = item.Value.Find(x => x.Pump1 == (double)fre);
|
if (conclusion != null)
|
{
|
freCombine.Flags.Add(item.Key);
|
freCombine.Flow += conclusion.Flow;
|
freCombine.Power += conclusion.Power;
|
freCombine.RunCount++;
|
}
|
}
|
if (freCombine.Flags.Count < 1)
|
continue;
|
fre_combine_list_part1.Add(freCombine);
|
}
|
}
|
if (combine_flag_list_part2.Count > 0)
|
{
|
var conclusion_list_dic = new Dictionary<int, List<Entity.ScheduleConclusion>>();
|
foreach (var flag in combine_flag_list_part2)
|
{
|
var runFlag = GetGFlag(flag);
|
if (conclusion_list_dic.ContainsKey(flag))
|
continue;
|
var conclusionList = _dalScheduleConclusion.GetList(runFlag, target_head);
|
conclusion_list_dic[flag] = conclusionList;
|
}
|
|
if (conclusion_list_dic.Count < 1)
|
{
|
continue;
|
}
|
|
for (decimal fre = _frequency_max; fre >= _frequency_min; fre -= _frequency_space)
|
{
|
var freCombine = new FreCombine();
|
freCombine.Frequency = (double)fre;
|
freCombine.Flags = new List<int>();
|
foreach (var item in conclusion_list_dic)
|
{
|
var conclusion = item.Value.Find(x => x.Pump1 == (double)fre);
|
if (conclusion != null)
|
{
|
freCombine.Flags.Add(item.Key);
|
freCombine.Flow += conclusion.Flow;
|
freCombine.Power += conclusion.Power;
|
freCombine.RunCount++;
|
}
|
}
|
if (freCombine.Flags.Count < 1)
|
continue;
|
fre_combine_list_part2.Add(freCombine);
|
}
|
}
|
|
if (fre_combine_list_part1.Count == 0 && fre_combine_list_part2.Count == 0)
|
continue;
|
|
double total_flow_deviation = target_flow;//总流量偏差
|
double total_power = double.MaxValue;//总功率
|
double total_flow = double.MaxValue;//总流量
|
|
FreCombine optimal_combine_part1 = null;
|
FreCombine optimal_combine_part2 = null;
|
if (fre_combine_list_part1.Count < 1 || fre_combine_list_part2.Count < 1)
|
{
|
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 (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)
|
{
|
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_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)
|
{
|
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")}");
|
}
|
return sb.ToString();
|
|
}
|
|
|
/// <summary>
|
/// 插入分析日志
|
/// </summary>
|
private void InsertAnaLog(string info)
|
{
|
var entity = new Entity.ScheduleAnaLog(info);
|
_dalAnaLog.Insert(entity);
|
}
|
|
|
/// <summary>
|
/// 判断表是否存在
|
/// </summary>
|
public bool ExistTable(string runFlag)
|
{
|
return _dal.ExistTable(runFlag);
|
}
|
|
}
|
}
|