using System;
|
using System.Collections;
|
using System.Collections.Generic;
|
using System.Linq;
|
using System.Text;
|
using System.Threading.Tasks;
|
using AForge;
|
using System.Drawing;
|
using System.Text.RegularExpressions;
|
using AForge.Genetic;
|
//using NPOI.SS.Formula.Eval;
|
using System.Runtime.Serialization;
|
using Newtonsoft.Json;
|
using System.Collections.Concurrent;
|
using Dapper;
|
|
namespace CommonBase
|
{
|
public class GeneticParams
|
{
|
static int Count = 0;
|
public GeneticParams(int Level)
|
{
|
this.Level = Level;
|
this.ID = Count;
|
Count++;
|
}
|
|
public GeneticParams(string ConfigPath, GeneticParams gParam)
|
{
|
if (gParam == null) gParam = new GeneticParams(0);
|
this.Level = gParam.Level;
|
this.ID = gParam.ID;
|
if (gParam.Db == null) gParam.Db = new Db();
|
if (!string.IsNullOrEmpty(ConfigPath)) gParam.Db.Init(ConfigPath);
|
this.Db = gParam.Db;
|
if (gParam.Quene!=null) gParam.Quene.Dispose();
|
gParam.Quene = new Quene();
|
this.Quene= gParam.Quene;
|
//获取全局默认设置
|
var globalConfig = gParam.Db.Connection.QueryFirstOrDefault<string>("SELECT FValue FROM MyConfig WHERE FKey='GlobalConfig'");
|
gParam.GlobalConfig = JsonConvert.DeserializeObject<GlobalConfig>(globalConfig) ?? new GlobalConfig();
|
this.GlobalConfig = gParam.GlobalConfig;
|
//return gParam;
|
}
|
public void Dispose()
|
{
|
onReportProgress = null;
|
Db.Close();
|
Db = null;
|
|
}
|
|
public List<double> list_BestEnerge;
|
public List<double> list_AvgHz;
|
public List<DRange> ranges;
|
public List<int> DLengths;
|
public List<double?> accuracys;
|
public double[] list_AtemtpArr;
|
|
public string SolutionSaveName;
|
public int populationSize;
|
public int iterations;
|
public int populationSize_full;
|
public int iterations_full;
|
|
|
public int selectionMethod;
|
public int optimizationMode;
|
public bool 强制重计算;
|
|
public int iterations_min;
|
public double accuracyNum;
|
//public int MultiTimes=0;
|
|
public int MaxRobot;
|
public int RuningRobot;
|
|
public int num;
|
public double BestOptValue;
|
public MyDoubleRange tolerance;
|
public FinishEvent onFinished;
|
public FinishEvent onError;
|
public FinishEvent onReportProgress;
|
public SetEvent setVars;
|
|
public Db Db;
|
public dynamic SolutionDBHelper = null;
|
public GlobalConfig GlobalConfig;
|
public Quene Quene;
|
public int Level;
|
public int ID;
|
|
public bool isNeedOutput = true;
|
|
public double CurrentTotalDemand = -1;
|
|
|
}
|
|
[Serializable]
|
public class DRange
|
{
|
private double min;
|
|
private double max;
|
|
public double Min
|
{
|
get
|
{
|
return min;
|
}
|
set
|
{
|
min = value;
|
}
|
}
|
|
public double Max
|
{
|
get
|
{
|
return max;
|
}
|
set
|
{
|
max = value;
|
}
|
}
|
|
public double Length => max - min;
|
|
public DRange(double min, double max)
|
{
|
this.min = min;
|
this.max = max;
|
}
|
|
|
}
|
|
public class Result
|
{
|
public double[] arrayTryValue = null;
|
public float Demand;
|
public double ObjFunctionValue;
|
public int it_Times = 0;
|
}
|
public class Quene
|
{
|
|
public System.Collections.Generic.Queue<WdnmoParam> RequestQueues;
|
public HashSet<Guid> RequestFinished;
|
public Dictionary<ulong, double> ResultHash;
|
public int Level;
|
public Dictionary<Guid, double?> ResultDictionary;
|
public Dictionary<Guid, ChromosomeBase> ResultChrome;
|
public int MissionQueneCount;
|
public List<calcParam> MissionQuene;
|
public DateTime ScadaTime;
|
public List<TimePoint> TimePoints;
|
public double BestResult=double.MaxValue;
|
public void Dispose()
|
{
|
if (RequestQueues != null)
|
{
|
RequestQueues.Clear();
|
RequestQueues = null;
|
}
|
if (RequestFinished != null)
|
{
|
RequestFinished.Clear();
|
RequestFinished = null;
|
}
|
|
if (ResultHash != null)
|
{
|
ResultHash.Clear();
|
ResultHash = null;
|
}
|
if (ResultDictionary != null)
|
{
|
ResultDictionary.Clear();
|
ResultDictionary = null;
|
}
|
if (ResultChrome != null)
|
{
|
ResultChrome.Clear();
|
ResultChrome = null;
|
}
|
if (MissionQuene != null)
|
{
|
MissionQuene.Clear();
|
MissionQuene = null;
|
}
|
if (TimePoints != null)
|
{
|
TimePoints.Clear();
|
TimePoints = null;
|
}
|
|
}
|
}
|
[Serializable]
|
|
public class WdnmoParam
|
{
|
|
public List<PointF> results;
|
public double DistriDemand;
|
|
|
public Guid ID;
|
public List<TimePoint> ScadaPoints { get; set; } = new List<TimePoint>();
|
|
public ConcurrentDictionary<string, TimePoint> dict_Scada_key = null;
|
public List<TimePoint> ConfigPoints { get; set; } = new List<TimePoint>();
|
public List<TimePoint> ResultPoints { get; set; } = new List<TimePoint>();
|
public double Fitness = -1;
|
public DateTime time { get; set; } = default(DateTime);
|
public int RunTimes = 0;
|
public int Period { get; set; } = 0;
|
public string ErrorMessage { get; set; } = null;
|
|
public bool fullSearchMode = false;
|
public FinishEvent onFinish;
|
public bool isNeedOutPut = false;
|
public Dictionary<string, double[]> ToSearchDict()
|
{
|
Dictionary<string, double[]> dict = new Dictionary<string, double[]>();
|
foreach (var point in ScadaPoints)
|
{
|
if (!dict.ContainsKey(point.Key))
|
dict.Add(point.Key, new double[] { point.Value - point.SearchRange / 2, point.Value + point.SearchRange / 2 });
|
else
|
dict[point.Key] = new double[] { point.Value - point.SearchRange / 2, point.Value + point.SearchRange / 2 };
|
}
|
if (!dict.ContainsKey("period"))
|
dict.Add("period", new double[] { Period - 8, Period + 8 });
|
else
|
dict["period"] = new double[] { Period - 8, Period + 8 };
|
return dict;
|
}
|
//public ulong Toulong(string childSaveName)
|
//{
|
|
//}
|
public string ToSearchSring()
|
{
|
Dictionary<string, double> dict = new Dictionary<string, double>();
|
|
foreach (var point in ScadaPoints)
|
{
|
if (!dict.ContainsKey(point.Key))
|
dict.Add(point.Key, point.Value);
|
else
|
dict[point.Key] = point.Value;
|
}
|
if (!dict.ContainsKey("period"))
|
dict.Add("period", Period);
|
StringBuilder sb = new StringBuilder();
|
foreach (var point in dict)
|
{
|
sb.AppendLine(point.Key + "\t" + point.Value);
|
}
|
|
|
|
// List<string> ListTemp = new List<string>();
|
// var di = this.ToSearchDict();
|
// foreach (var kp in di)
|
// {
|
// ListTemp.Add(
|
//$@"{{ {kp.Key}: {{ ""$gte"": {kp.Value[0]},""$lte"": {kp.Value[1]} }}}}");
|
// }
|
|
// sb.AppendLine("--------------搜索表达式-------------");
|
// sb.AppendLine(
|
//$@"
|
//{{
|
// ""$and"":
|
// [
|
// {string.Join(",", ListTemp)}
|
// ]
|
//}}
|
//");
|
return sb.ToString();
|
|
}
|
public Dictionary<string, double> ToResultDict()
|
{
|
Dictionary<string, double> dict = new Dictionary<string, double>();
|
foreach (var point in ScadaPoints)
|
{
|
if (!dict.ContainsKey(point.Key))
|
dict.Add(point.Key, point.Value);
|
else
|
dict[point.Key] = point.Value;
|
}
|
if (!dict.ContainsKey("period"))
|
dict.Add("period", Period);
|
else
|
dict["period"] = Period;
|
foreach (var point in ResultPoints)
|
{
|
if (!point.isNeedtoSave) continue;
|
if (!CheckExpandoVariableName(point.SaveKey)) continue;
|
if (!dict.ContainsKey(point.SaveKey))
|
{
|
dict.Add(point.SaveKey, point.Value);
|
}
|
else
|
dict[point.SaveKey] = point.Value;
|
}
|
return dict;
|
// 重载 == 运算符
|
|
}
|
private bool CheckExpandoVariableName(string name)
|
{
|
if (name == null) return false;
|
// 正则表达式:以字母或下划线开头,后面跟着任意个字母、数字或下划线
|
string pattern = @"^[a-zA-Z_]\w*$";
|
return Regex.IsMatch(name, pattern);
|
}
|
|
public void Dispose()
|
{
|
results?.Clear();
|
ScadaPoints?.Clear();
|
ConfigPoints?.Clear();
|
ResultPoints?.Clear();
|
onFinish = null;
|
}
|
}
|
|
public class calcParam
|
{
|
|
public double[] vars;
|
|
public Guid ID;
|
|
public IChromosome chromosome;
|
|
public List<SetVar> setVars = new List<SetVar>();
|
|
|
}
|
public class SetVar
|
{
|
public string ID;
|
public bool isNode = true;
|
public int type;
|
public float value;
|
public SetVar(string ID,bool isNode,int type,float value)
|
{
|
this.ID= ID;
|
this.isNode = isNode;
|
this.type = type;
|
this.value = value;
|
}
|
}
|
|
[Serializable]
|
|
public class TimePoint
|
{
|
public TimePoint()
|
{
|
|
}
|
public TimePoint(string key, double value)
|
{
|
Key = key;
|
Value = value;
|
}
|
|
public string Name;
|
public DateTime ValueTime { get; set; }
|
public string Key { get; set; }
|
public double Value { get; set; }
|
public double[] Pattern { get; set; } = null;
|
public string ModelObjectID { get; set; }
|
public SettingCalcType CType { get; set; } = SettingCalcType.Add;
|
|
public double SearchRange = 0;
|
|
public bool isNeedtoSave = false;
|
|
public string SaveKey = null;
|
|
public override string ToString()
|
{
|
return $"{Name}\t[{Key}]\t{Value}";
|
}
|
}
|
|
|
[Serializable]
|
public delegate void FinishEvent(dynamic txt);
|
public delegate void SetEvent(string name, WdnmoParam param);
|
//public event FinishEvent ss;
|
|
|
[Serializable]
|
|
public enum SettingCalcType
|
{
|
Add = 0,
|
Const = 1
|
}
|
|
|
|
[Serializable]
|
public class LogicModelParams
|
{
|
|
|
public Guid ID = new Guid();
|
public List<variable> 集合 = new List<variable>();
|
public List<variable> 初始条件 = new List<variable>();
|
public List<variable> 下阶段条件 = new List<variable>();
|
public List<variable> 约束变量 = new List<variable>();
|
public List<variable> 试算变量 = new List<variable>();
|
public List<variable> 水量分配变量 = new List<variable>();
|
public List<variable> 变量 = new List<variable>();
|
public List<variable> 表达式 = new List<variable>();
|
public List<variable> 预处理插件 = new List<variable>();
|
public List<variable> 接口变量
|
{
|
get
|
{
|
List<variable> all = new List<variable>();
|
all.AddRange(变量);
|
all.AddRange(初始条件);
|
all.AddRange(下阶段条件);
|
all.AddRange(表达式);
|
return all;
|
}
|
}
|
|
public List<variable> 设定变量
|
{
|
get
|
{
|
List<variable> all = new List<variable>();
|
all.AddRange(初始条件);
|
all.AddRange(下阶段条件);
|
return all;
|
}
|
}
|
|
public List<variable> 变量全集
|
{
|
get
|
{
|
List<variable> all = new List<variable>();
|
all.AddRange(初始条件);
|
all.AddRange(下阶段条件);
|
all.AddRange(变量);
|
all.AddRange(试算变量);
|
all.AddRange(集合);
|
all.AddRange(表达式);
|
all.AddRange(约束变量);
|
if (OFunction?.variable!=null) all.Add(OFunction.variable);
|
|
return all;
|
}
|
|
|
}
|
[NonSerialized]
|
public Dictionary<string, variable> dict_Name;
|
public Dictionary<int, variable> dict_ID;
|
|
//public string inputFileString;
|
|
public void buildDict()
|
{
|
dict_Name = new Dictionary<string, variable>();
|
dict_ID=new Dictionary<int, variable>();
|
变量全集.ForEach(vv => { if (!string.IsNullOrEmpty(vv.Name) && !dict_Name.ContainsKey(vv.Name)) dict_Name.Add(vv.Name, vv); });
|
变量全集.ForEach(vv => { if (!dict_ID.ContainsKey(vv.ID)) dict_ID.Add(vv.ID, vv); });
|
|
}
|
|
[NonSerialized]
|
public Dictionary<string, childSolutionParam> ChildParam = new Dictionary<string, childSolutionParam>();
|
|
public OBJFunction OFunction;
|
public EN_Times 时间刻度;
|
public List<PointF> results = new List<PointF>();
|
public int times;
|
|
public LogicModelParams CloneResult()
|
{
|
var param_new = new LogicModelParams();
|
初始条件.ForEach(v => param_new.初始条件.Add(new variable {ID=v.ID,CalcValue=v.CalcValue,LogicValue=v.LogicValue,objListString=v.objListString })) ;
|
下阶段条件.ForEach(v => param_new.下阶段条件.Add(new variable { ID = v.ID, CalcValue = v.CalcValue, LogicValue = v.LogicValue, objListString = v.objListString }));
|
约束变量.ForEach(v => param_new.约束变量.Add(new variable { ID = v.ID, CalcValue = v.CalcValue, LogicValue = v.LogicValue, objListString = v.objListString }));
|
试算变量.ForEach(v => param_new.试算变量.Add(new variable { ID = v.ID, CalcValue = v.CalcValue, LogicValue = v.LogicValue, objListString = v.objListString }));
|
水量分配变量.ForEach(v => param_new.水量分配变量.Add(new variable { ID = v.ID, CalcValue = v.CalcValue, LogicValue = v.LogicValue, objListString = v.objListString }));
|
变量.ForEach(v => param_new.变量.Add(new variable { ID = v.ID, CalcValue = v.CalcValue, LogicValue = v.LogicValue, objListString = v.objListString }));
|
集合.ForEach(v => param_new.集合.Add(new variable { ID = v.ID, CalcValue = v.CalcValue, LogicValue = v.LogicValue, objListString = v.objListString }));
|
表达式.ForEach(v => param_new.表达式.Add(new variable { ID = v.ID, CalcValue = v.CalcValue, LogicValue = v.LogicValue, objListString = v.objListString }));
|
param_new.OFunction = new OBJFunction();
|
param_new.OFunction.value = OFunction.value;
|
param_new.buildDict();
|
return param_new;
|
}
|
|
}
|
/// <summary>
|
/// 子方案参数集
|
/// </summary>
|
public class childSolutionParam
|
{
|
/// <summary>
|
///计算参数
|
/// </summary>
|
public WdnmoParam wParam;
|
public List<variable> childVars_In;
|
public List<variable> childVars_Out;
|
public string childSaveName;
|
public variable childFitness_Out;
|
//public SaveSettings saveSettings;
|
//public string savePath;
|
}
|
public class EN_Times
|
{
|
public int duration;
|
public int step;
|
public int Ntimes;
|
}
|
|
|
[Serializable]
|
public class variable
|
{
|
public static List<string> listUsedInitValue = new List<string>() { "初始计算值", "变化值", "绝对变化值" };
|
public static List<string> list_输入值 = new List<string>() { "基准值(界面)", "定义值", "基准值(接口)", "定义值" };
|
public static List<string> listUsedScadaValue = new List<string> { "定义值", "基准值(接口)" };
|
|
public static List<string> list_接口输出值 = new List<string>() { "表达式计算", "计算值", "变化值", "初始计算值", "子方案值" };
|
public static List<string> list_接口输入值 = new List<string>() { "基准值(接口)", "模式系数(接口)" };
|
|
public static List<string> list_NoNeedModelIndex = new List<string>() { "基准值(界面)", "定义值", "基准值(接口)", "模式系数(界面)", "模式系数(接口)" };
|
public int ID;
|
public string modelObjectID;
|
public string Name;
|
public int modelIndex;
|
public int maxTimes = 1;
|
|
//CF修订 2023年7月10日 处理序列化失败的问题
|
[NonSerialized]
|
public List<variable> Vars = null;
|
// public int ParentID;
|
|
public bool isNode;
|
//public bool? isOutput;
|
|
public dynamic Type;
|
public dynamic resultType;
|
public DRange doubleRange;
|
|
public double? accuracy = null;
|
public string expressString;
|
public string expressType;
|
//public string expressType
|
//{
|
// get { return _expressType; }
|
// set
|
// {
|
|
// if (expressString == "tagfenghuang_shuiwei" && value=="0.01")
|
// {
|
// var a = 0;
|
// }
|
// _expressType = value;
|
// }
|
//}
|
public string defineType;
|
public string IndicatorType;
|
public int ObjType;
|
public string logicType;
|
/// <summary>
|
/// 设定值
|
/// </summary>
|
public double? LogicValue = null;
|
/// <summary>
|
/// 设定模式
|
/// </summary>
|
public double[] LogicPattern = null;
|
|
|
|
/// <summary>
|
/// 初始状态计算值
|
/// </summary>
|
public double CalcValue_Init;
|
///// <summary>
|
///// 目标状态计算值
|
///// </summary>
|
//public double? CalcValue_Calc = null;
|
|
|
public double CalcValue_Set
|
{
|
set
|
{
|
lock(this)
|
{
|
this.CalcValue = value;
|
}
|
|
}
|
}
|
/// <summary>
|
/// 数学模型目标值
|
/// </summary>
|
public double? CalcValue { get; set; }=null;
|
|
/// <summary>
|
/// 数学模型目标值多时刻
|
/// </summary>
|
public double[] CalcValue_Arr = null;
|
|
/// <summary>
|
/// 显示的小数位数
|
/// </summary>
|
public int 小数位数 = 3;
|
|
/// <summary>
|
/// 标高
|
/// </summary>
|
public double elevation = -9099;
|
|
public int sort = 0;
|
|
public string childSolution = "";
|
|
public string childTag = "";
|
|
public string childType = "传入";
|
|
public double SearchRange = -1;
|
|
public bool isNeedToSave = false;
|
|
public string SaveKey = null;
|
|
|
|
/// <summary>
|
/// 是否是虚拟变量(由集合产生)
|
/// </summary>
|
public bool virturl = false;
|
|
|
[NonSerialized]
|
public dynamic Eval = null;
|
|
/// <summary>
|
/// 对象清单
|
/// </summary>
|
public string objListString;
|
|
/// <summary>
|
/// 对象编号(最优)
|
/// </summary>
|
public string obj_Best;
|
|
public double ErrNum = -9999999;
|
|
private int _level = 0;
|
|
[JsonIgnore]
|
public int Level
|
{
|
get
|
{
|
if (_level!=0) return _level;
|
int tempLevel = 1;
|
if (Vars!=null)
|
foreach (var v in Vars)
|
{
|
if (tempLevel < v.Level + 1) tempLevel = v.Level + 1;
|
}
|
_level= tempLevel;
|
return _level;
|
}
|
|
}
|
|
public override string ToString()
|
{
|
string value = CalcValue == null ? LogicValue.ToString() : CalcValue.ToString();
|
return $"[{Name}]{value}";
|
}
|
|
public double GetValue(Func<variable, double> GetCalcValue = null, int? period = 0, bool is清除缓存 = false)
|
{
|
double Value;
|
var v = this;
|
// is double dd
|
if (v.expressType == "子方案值" || v.expressType=="目标函数")
|
{
|
lock(v)
|
{
|
if (!v.CalcValue.HasValue)
|
throw (new Exception("异常"));
|
else
|
Value = (double)v.CalcValue;//v.GetCalcValue(GetCalcValue, period, false);
|
}
|
|
|
|
}
|
else if (variable.list_输入值.IndexOf(v.expressType) < 0)
|
{
|
Value = v.GetCalcValue(GetCalcValue, period, is清除缓存);
|
}
|
else
|
{
|
double? d;
|
if ((d = v.GetLogicValue()) == null)
|
{
|
//result = $"变量[{v.Name}]配置错误,编号[{v.modelObjectID}]取值失败";
|
Value = (ErrNum);
|
}
|
else
|
{
|
Value = (double)(v.GetLogicValue() ?? (ErrNum));
|
}
|
}
|
return Value;
|
}
|
public double GetCalcValue(Func<variable, double> GetCalcValue = null, int? period = 0, bool is清除缓存 = false)
|
{
|
//if (CalcValue != null) return (double)CalcValue;
|
//double CalcValue_Calc;
|
|
if (is清除缓存)
|
{
|
CalcValue = null;
|
}
|
else
|
{
|
if (CalcValue!=null) return (double)CalcValue;
|
}
|
|
|
|
double CalcValue_Calc;
|
double result;
|
if (expressType == listUsedInitValue[0])//初始计算值
|
{
|
result = CalcValue_Init;
|
}
|
else if (expressType == listUsedInitValue[1])//变化值
|
{
|
CalcValue_Calc = GetCalcValue(this);
|
result = CalcValue_Calc - CalcValue_Init;
|
}
|
else if (expressType == listUsedInitValue[2])//绝对变化值
|
{
|
CalcValue_Calc = GetCalcValue(this);
|
result = CalcValue_Calc - CalcValue_Init;
|
if (result < 0) result *= -1;
|
}
|
else
|
{
|
CalcValue_Calc = GetCalcValue(this);
|
result = CalcValue_Calc;
|
}//计算值
|
|
CalcValue = result;
|
return result;
|
}
|
public double? GetLogicValue()
|
{
|
if (LogicValue != null) return (double)LogicValue;
|
return null;
|
}
|
|
public double[] GetShowValue_Arr()
|
{
|
|
if (list_输入值.IndexOf(expressType) >= 0)
|
//return LogicPattern;
|
return CalcValue_Arr;
|
else
|
return CalcValue_Arr;
|
}
|
|
/// <summary>
|
/// 获取页面显示的结果值及样式
|
/// </summary>
|
/// <returns></returns>
|
public string GetShowValue(bool showString = false)
|
{
|
//,Color.Red,Color.Blue,Color.Orange
|
|
double? result;
|
string Result;
|
if (list_输入值.IndexOf(expressType) >= 0)
|
result = LogicValue;
|
else
|
result = CalcValue;
|
|
|
Result = result == null ? "-" : Math.Round(Double.Parse(result.ToString()), 小数位数).ToString();
|
if (showString)
|
{
|
if (!string.IsNullOrEmpty(obj_Best))
|
{
|
Result += $" [{obj_Best}]";
|
}
|
}
|
else
|
if (Type.ToString().ToLower()== "initstatus")// is EPAModelNameSpace.EPAModelOutput.eType.INITSTATUS || Type is EPAModelNameSpace.EPAModelInput.eType.initStatus)
|
{
|
if (result == 0)
|
Result = "关|Yellow";
|
else
|
Result = "开|DarkGreen";
|
}
|
else
|
{
|
if (list_输入值.IndexOf(expressType) >= 0)
|
Result += "|Blue";
|
else
|
Result += "|White";// Color.DarkGreen
|
}
|
|
return Result;
|
}
|
}
|
|
[Serializable]
|
public class OBJFunction
|
{
|
public string Text_origin;
|
public string Text_change;
|
public string Text;
|
public string ExpressType;
|
public string Name;
|
|
public double value;
|
public MyDoubleRange tolerance;
|
public variable variable;
|
public List<variable> paramVariables;
|
public List<double> paramValues;
|
[NonSerialized]
|
public dynamic eval;
|
public bool isUseOriginValue = false;
|
/// <summary>
|
/// true:使用表达式模式,false:使用编号模式
|
/// </summary>
|
public bool? isUseExpression = true;
|
public bool isUseScadaValue = false;
|
|
}
|
|
|
|
|
}
|