| | |
| | | using IStation.Curve; |
| | | using MathNet.Numerics.Distributions; |
| | | using MathNet.Numerics.LinearAlgebra; |
| | | using MathNet.Numerics.LinearAlgebra.Double; |
| | | using IStation.Model; |
| | | using System.Data; |
| | | using System.Text; |
| | | |
| | | namespace IStation.Test |
| | | { |
| | | internal class Program |
| | | { |
| | | // 过滤无效数据 |
| | | // 1输模型修正 |
| | | // 2输数据修正 |
| | | // 修正组合偏差 |
| | | static void Main(string[] args) |
| | | { |
| | | var bll = new BLL.StationSignalRecordPacket(); |
| | | var projectId = 661070185922629; |
| | | IStation.SettingsD.Project.ID = projectId; |
| | | var monitorDataSourcesId = 606203941007429; |
| | | var dateStart = new DateTime(2024, 1, 1); |
| | | var dateEnd = new DateTime(2025, 1, 1); |
| | | var stationDict = new Dictionary<int, long> |
| | | //Station1Helper.Start(); //1 数据修正 |
| | | //Station2Helper.Start(); //2 模型修正 |
| | | // 3 python修正 |
| | | //Completion(); //4 修正后相似换算修正 |
| | | |
| | | //StationCombineHelper.Start(1);// 5 组合偏差修正 |
| | | //StationCombineHelper.Start(2);// 5 组合偏差修正 |
| | | |
| | | StationCombineHelper.Start(3);// 6 分析泵频谱系数 |
| | | Console.WriteLine(); |
| | | Console.WriteLine("ok"); |
| | | Console.ReadKey(); |
| | | |
| | | } |
| | | |
| | | |
| | | public static void Completion() |
| | | { |
| | | var fullPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "pumpcsv"); |
| | | |
| | | var fileNameList = Directory.GetFiles(fullPath).Select(x => Path.GetFileNameWithoutExtension(x)).ToList(); |
| | | fileNameList = fileNameList.Where(x => x.Contains("update_curve")).ToList(); |
| | | if (fileNameList == null || fileNameList.Count() < 1) |
| | | return; |
| | | var deleteList = fileNameList.Where(x => x.Contains("similar") || x.Contains("def")).ToList(); |
| | | deleteList?.ForEach(x => File.Delete(x)); |
| | | |
| | | var flagCurveDict = GetFlagCurveDict(); |
| | | |
| | | fileNameList.RemoveAll(x => x.Contains("similar") ||x.Contains("def")); |
| | | var group = fileNameList.Where(x => x.Contains("update_curve")).GroupBy(x => x.Substring(0, 2)); |
| | | foreach (var flagItem in group) |
| | | { |
| | | { 1, 462958406303813 }, |
| | | { 2, 462958422204485 } |
| | | }; |
| | | |
| | | |
| | | var ptFilterList = new List<PointViewModel>(); |
| | | foreach (var station in stationDict) |
| | | { |
| | | var stationIndex = station.Key; |
| | | var stationId = station.Value; |
| | | var packets = bll.Get(monitorDataSourcesId, stationId); |
| | | var ptList = new List<PointViewModel>(); |
| | | |
| | | var records = packets.SelectMany(x => x.StationSignalRecords).ToList(); |
| | | foreach (var x in records) |
| | | if (!int.TryParse(flagItem.Key, out int flag)) |
| | | continue; |
| | | |
| | | var files = flagItem.OrderBy(x => x).ToList(); |
| | | var fileInfoList = new List<(int Hz, string FileName)>(); |
| | | foreach (var fileName in files) |
| | | { |
| | | if (x.TotalPressure > 0 && x.TotalFlow > 0) |
| | | var hz = fileName.Substring(3, 2); |
| | | if (!int.TryParse(hz, out int hzInt)) |
| | | continue; |
| | | if (hzInt > 50) |
| | | { |
| | | //if (stationIndex == 2 && Math.Abs(x.DiffFlow) > 0) |
| | | if (stationIndex == 2 && x.DiffFlow > 0) |
| | | continue; |
| | | } |
| | | fileInfoList.Add((hzInt, fileName)); |
| | | } |
| | | if (fileInfoList.Count == 1 && fileInfoList[0].Hz==50) |
| | | { |
| | | continue; |
| | | } |
| | | for (int i = 25; i <= 50; i++) |
| | | { |
| | | var maxHz = fileInfoList.Max(x => x.Hz); |
| | | var curvePointList = new List<CurvePoint>(); |
| | | var fileName = string.Empty; |
| | | var currentHz = i; |
| | | var newFileName = ""; |
| | | if (fileInfoList.Exists(x => x.Hz == i)) |
| | | { |
| | | continue; |
| | | } |
| | | else if (currentHz == 50) |
| | | { |
| | | var curve = flagCurveDict[flag]; |
| | | curvePointList = curve.GetFitPoints(100).ToList(); |
| | | newFileName = $"{flagItem.Key}_{50}_update_curve_def.csv"; |
| | | } |
| | | else if (currentHz > maxHz) |
| | | { |
| | | var curve = flagCurveDict[flag]; |
| | | var similar_qh = Model.CurveCalcuHelper.CalculateSimilarQH(curve, 50, currentHz); |
| | | if (similar_qh == null) |
| | | { |
| | | continue; |
| | | } |
| | | ptList.Add(new PointViewModel(x.Time, x.TotalFlow, x.TotalPressure, x.DiffFlow, stationIndex)); |
| | | } |
| | | } |
| | | |
| | | |
| | | //var newPtList = DynamicThresholdProcessorHelper.Filter(ptList); |
| | | var newPtList = ptList; |
| | | ptFilterList.AddRange(newPtList); |
| | | } |
| | | |
| | | |
| | | var recordList = new List<RecordViewModel>(); |
| | | var timeGroup = ptFilterList.GroupBy(x => x.Time); |
| | | foreach (var group in timeGroup) |
| | | { |
| | | if (group.Count() < 2) |
| | | continue; |
| | | var record = new RecordViewModel |
| | | { |
| | | Time = group.Key |
| | | }; |
| | | foreach (var item in group) |
| | | { |
| | | if (item.Index == 1) |
| | | { |
| | | record.Flow1 = item.X; |
| | | record.Pressure1 = item.Y; |
| | | curvePointList = similar_qh.GetFitPoints(100).ToList(); |
| | | newFileName = $"{flagItem.Key}_{currentHz}_update_curve_similar_def.csv"; |
| | | } |
| | | else |
| | | { |
| | | record.Flow2 = item.X; |
| | | record.Pressure2 = item.Y; |
| | | record.FlowDiff2 = item.Diff; |
| | | var (Hz, FileName) = fileInfoList.FirstOrDefault(x => x.Hz > i); |
| | | if (Hz < 1) |
| | | continue; |
| | | |
| | | var updateCurvePtList = new List<CurvePoint>(); |
| | | var updateCurveFile = Path.Combine(fullPath, $"{flagItem.Key}_{Hz}_update_curve.csv"); |
| | | using (var fs = new FileStream(updateCurveFile, FileMode.Open, FileAccess.Read)) |
| | | using (var sr = new StreamReader(fs, Encoding.UTF8)) |
| | | { |
| | | var strLine = string.Empty; |
| | | sr.ReadLine(); |
| | | while (!string.IsNullOrEmpty(strLine = sr.ReadLine())) |
| | | { |
| | | var strList = strLine.Split(','); |
| | | var x = double.Parse(strList[0]); |
| | | var y = double.Parse(strList[1]); |
| | | updateCurvePtList.Add(new CurvePoint(x, y)); |
| | | } |
| | | } |
| | | |
| | | var similar_qh = Model.CurveCalcuHelper.CalculateSimilarQH(new CurveExpress(updateCurvePtList), Hz, currentHz); |
| | | if (similar_qh == null) |
| | | { |
| | | continue; |
| | | } |
| | | curvePointList = similar_qh.GetFitPoints(100).ToList(); |
| | | newFileName = $"{flagItem.Key}_{currentHz}_update_curve_similar_{Hz}.csv"; |
| | | } |
| | | } |
| | | |
| | | recordList.Add(record); |
| | | } |
| | | |
| | | var fullPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "csv"); |
| | | if (!Directory.Exists(fullPath)) |
| | | { |
| | | Directory.CreateDirectory(fullPath); |
| | | } |
| | | |
| | | |
| | | { |
| | | |
| | | |
| | | |
| | | var r_list = recordList.Select(x => new PointViewModel(x.Time, Math.Round(x.Pressure2, 1), x.FlowDiff2, 0, 2)).ToList(); |
| | | var group = r_list.GroupBy(x => x.X); |
| | | |
| | | string filePath = Path.Combine(fullPath, "atest.csv"); |
| | | using StreamWriter writer = new StreamWriter(filePath, false, System.Text.Encoding.UTF8); |
| | | |
| | | string filePathLow = Path.Combine(fullPath, "alow.csv"); |
| | | using StreamWriter writerLow = new StreamWriter(filePathLow, false, System.Text.Encoding.UTF8); |
| | | writer.WriteLine($"Pressure2,FlowDiffUpper,FlowDiffAverage,FlowDiffLower"); |
| | | writerLow.WriteLine($"Pressure2,FlowDiffLower"); |
| | | foreach (var item in group) |
| | | { |
| | | var fList = DynamicThresholdProcessorHelper.Filter(item.ToList()); |
| | | var x = item.Key; |
| | | var yUpper = item.Max(x => x.Y); |
| | | var yLower = item.Min(x => x.Y); |
| | | var yAverage = item.Average(x => x.Y); |
| | | |
| | | if (fList != null && fList.Any()) |
| | | if (!curvePointList.Any()) |
| | | { |
| | | yUpper = fList.Max(x => x.Y); |
| | | yLower = fList.Min(x => x.Y); |
| | | yAverage = fList.Average(x => x.Y); |
| | | continue; |
| | | } |
| | | writer.WriteLine($"{x},{yUpper},{yAverage},{yLower}"); |
| | | writerLow.WriteLine($"{x},{yLower}"); |
| | | } |
| | | } |
| | | |
| | | |
| | | { |
| | | |
| | | string filePath = Path.Combine(fullPath, "all.csv"); |
| | | using StreamWriter writer = new StreamWriter(filePath, false, System.Text.Encoding.UTF8); |
| | | |
| | | writer.WriteLine($"Time,Flow1,Pressure1,Flow2,Pressure2,FlowDiff2"); |
| | | |
| | | foreach (var record in recordList) |
| | | { |
| | | writer.WriteLine($"{record.Time},{record.Flow1},{record.Pressure1},{record.Flow2},{record.Pressure2},{record.FlowDiff2}"); |
| | | } |
| | | |
| | | } |
| | | |
| | | |
| | | return; |
| | | |
| | | var dataCellList = new List<DataCellViewModel>() { |
| | | new() { Name = "Flow1", ValueList = recordList.Select(x => x.Flow1).ToArray() }, |
| | | new() { Name = "Pressure1", ValueList = recordList.Select(x => x.Pressure1).ToArray() }, |
| | | new() { Name = "Flow2", ValueList = recordList.Select(x => x.Flow2).ToArray() }, |
| | | new() { Name = "Pressure2", ValueList = recordList.Select(x => x.Pressure2).ToArray() }, |
| | | new() { Name = "FlowDiff2", ValueList = recordList.Select(x => x.FlowDiff2).ToArray() } }; |
| | | |
| | | |
| | | var combineList = IStation.Curve.PermutationAndCombination<DataCellViewModel>.GetCombination(dataCellList.ToArray(), 2); |
| | | Console.WriteLine("输出文件"); |
| | | foreach (var combine in combineList) |
| | | { |
| | | var x = combine[0]; |
| | | var y = combine[1]; |
| | | |
| | | string filePath = Path.Combine(fullPath, $"{x.Name}-{y.Name}.csv"); |
| | | using StreamWriter writer = new StreamWriter(filePath, false, System.Text.Encoding.UTF8); |
| | | var count = x.ValueList.Length; |
| | | writer.WriteLine($"{x.Name},{y.Name}"); |
| | | for (int i = 0; i < count; i++) |
| | | { |
| | | var xv = x.ValueList[i]; |
| | | var yv = y.ValueList[i]; |
| | | writer.WriteLine($"{xv},{yv}"); |
| | | var currentCurveFile = Path.Combine(fullPath, newFileName); |
| | | CsvHelper.ExportToCsv(curvePointList, currentCurveFile); |
| | | Console.WriteLine(newFileName); |
| | | } |
| | | } |
| | | |
| | | |
| | | Console.WriteLine("计算皮尔逊积差相关系数"); |
| | | foreach (var combine in combineList) |
| | | { |
| | | var x = combine[0]; |
| | | var y = combine[1]; |
| | | var (r, pValue) = PearsonTest(x.ValueList, y.ValueList); |
| | | Console.WriteLine($"{x.Name}-{y.Name}: r = {r:F3}"); |
| | | |
| | | } |
| | | |
| | | Console.WriteLine("计算斯皮尔曼等级相关系数"); |
| | | foreach (var combine in combineList) |
| | | { |
| | | var x = combine[0]; |
| | | var y = combine[1]; |
| | | |
| | | var (rho, pValue) = SpearmanTest(x.ValueList, y.ValueList); |
| | | Console.WriteLine($"{x.Name}-{y.Name}: ρ = {rho:F3}"); |
| | | } |
| | | |
| | | foreach (var combine in combineList) |
| | | { |
| | | var x = combine[0]; |
| | | var y = combine[1]; |
| | | |
| | | string filePath = Path.Combine(fullPath, $"{x.Name}-{y.Name}.csv"); |
| | | using StreamWriter writer = new StreamWriter(filePath, false, System.Text.Encoding.UTF8); |
| | | var count = x.ValueList.Length; |
| | | writer.WriteLine($"{x.Name},{y.Name}"); |
| | | for (int i = 0; i < count; i++) |
| | | { |
| | | var xv = x.ValueList[i]; |
| | | var yv = y.ValueList[i]; |
| | | writer.WriteLine($"{xv},{yv}"); |
| | | } |
| | | } |
| | | |
| | | //foreach (var combine in combineList) |
| | | //{ |
| | | // var x = combine[0]; |
| | | // var y = combine[1]; |
| | | // var name = $"{x.Name}-{y.Name}"; |
| | | // if (name.Equals("Flow2-Pressure2") || name.Equals("Pressure1-Pressure2") || name.Equals("Flow1-Pressure2")) |
| | | // { |
| | | // NonlinearRegressionExample2.Test(x, y); |
| | | // } |
| | | //} |
| | | |
| | | Console.WriteLine("ok"); |
| | | Console.ReadKey(); |
| | | } |
| | | |
| | | |
| | | |
| | | /// <summary> |
| | | /// 计算皮尔逊相关系数及显著性p值 |
| | | /// </summary> |
| | | public static (double r, double pValue) PearsonTest(double[] x, double[] y) |
| | | { |
| | | // 计算皮尔逊相关系数 |
| | | double r = CorrelationHelper.Pearson(x, y); |
| | | |
| | | // 计算显著性p值(双尾t检验) |
| | | int n = x.Length; |
| | | double t = r * Math.Sqrt((n - 2) / (1 - r * r)); |
| | | var tDist = new StudentT(location: 0, scale: 1, freedom: n - 2); |
| | | double pValue = 2 * (1 - tDist.CumulativeDistribution(Math.Abs(t))); |
| | | |
| | | return (r, pValue); |
| | | } |
| | | |
| | | /// <summary> |
| | | /// 计算斯皮尔曼等级相关系数及显著性p值 |
| | | /// </summary> |
| | | public static (double rho, double pValue) SpearmanTest(double[] x, double[] y) |
| | | { |
| | | // 计算斯皮尔曼相关系数 |
| | | double rho = CorrelationHelper.Spearman(x, y); |
| | | |
| | | // 大样本正态近似法计算p值 |
| | | int n = x.Length; |
| | | double z = rho * Math.Sqrt(n - 1); |
| | | var normalDist = new Normal(); |
| | | double pValue = 2 * (1 - normalDist.CumulativeDistribution(Math.Abs(z))); |
| | | |
| | | return (rho, pValue); |
| | | } |
| | | |
| | | } |
| | | |
| | | #region ViewModel |
| | | |
| | | public class DataCellViewModel |
| | | { |
| | | public string Name { get; set; } |
| | | public double[] ValueList { get; set; } |
| | | |
| | | } |
| | | |
| | | public class PointViewModel |
| | | { |
| | | public PointViewModel() { } |
| | | public PointViewModel(DateTime dt, double x, double y, double diff, int index) |
| | | { |
| | | this.Time = dt; |
| | | this.X = x; |
| | | this.Y = y; |
| | | this.Diff = diff; |
| | | this.Index = index; |
| | | } |
| | | |
| | | public PointViewModel(PointViewModel rhs) |
| | | { |
| | | this.Time = rhs.Time; |
| | | this.X = rhs.X; |
| | | this.Y = rhs.Y; |
| | | this.Index = rhs.Index; |
| | | this.Diff = rhs.Diff; |
| | | } |
| | | |
| | | public DateTime Time { get; set; } |
| | | public int Index { get; set; } |
| | | public double X { get; set; } |
| | | public double Y { get; set; } |
| | | public double Diff { get; set; } |
| | | |
| | | } |
| | | |
| | | public class RecordViewModel |
| | | { |
| | | public RecordViewModel() { } |
| | | |
| | | public DateTime Time { get; set; } |
| | | |
| | | public double Flow1 { get; set; } |
| | | public double Pressure1 { get; set; } |
| | | |
| | | public double Flow2 { get; set; } |
| | | public double Pressure2 { get; set; } |
| | | |
| | | public double FlowDiff2 { get; set; } |
| | | } |
| | | |
| | | #endregion |
| | | |
| | | public class DynamicThresholdProcessorHelper |
| | | { |
| | | |
| | | public static List<PointViewModel> Filter(List<PointViewModel> ptList) |
| | | { |
| | | var pressures = ptList.Select(p => p.Y).ToList(); |
| | | |
| | | // 计算统计量 |
| | | var (mean, stdDev) = CalculateStats(pressures); |
| | | double skewness = CalculateSkewness(pressures); |
| | | // 动态调整σ倍数 |
| | | double sigmaMultiplier = CalculateSigmaMultiplier(skewness); |
| | | sigmaMultiplier = 3;//目前默认 标准差 |
| | | |
| | | |
| | | // 计算边界 |
| | | double lower = mean - sigmaMultiplier * stdDev; |
| | | double upper = mean + sigmaMultiplier * stdDev; |
| | | |
| | | return ptList.Where(p => p.Y >= lower && p.Y <= upper).ToList(); |
| | | } |
| | | |
| | | |
| | | // 核心统计计算 |
| | | private static (double mean, double stdDev) CalculateStats(List<double> values) |
| | | { |
| | | double mean = values.Average(); |
| | | double stdDev = Math.Sqrt(values.Sum(v => Math.Pow(v - mean, 2)) / (values.Count - 1)); |
| | | return (mean, stdDev); |
| | | } |
| | | |
| | | // 偏度计算(Pearson's moment coefficient) |
| | | private static double CalculateSkewness(List<double> values) |
| | | { |
| | | double mean = values.Average(); |
| | | double std = CalculateStats(values).stdDev; |
| | | double sum = values.Sum(v => Math.Pow((v - mean) / std, 3)); |
| | | return (sum * values.Count) / ((values.Count - 1) * (values.Count - 2)); |
| | | } |
| | | |
| | | // 动态σ倍数计算规则 |
| | | private static double CalculateSigmaMultiplier(double skewness) |
| | | { |
| | | |
| | | return skewness switch |
| | | { |
| | | > 1.0 => 2.0, // 强正偏态 |
| | | > 0.5 => 2.5, |
| | | > -0.5 => 3.0, // 近似正态 |
| | | > -1.0 => 3.5, |
| | | _ => 4.0 // 强负偏态 |
| | | }; |
| | | } |
| | | |
| | | } |
| | | |
| | | public static class CorrelationHelper |
| | | { |
| | | /// <summary> |
| | | /// 计算皮尔逊积差相关系数 |
| | | /// </summary> |
| | | /// <param name="dataA">数据样本A</param> |
| | | /// <param name="dataB">数据样本B</param> |
| | | /// <returns>皮尔逊积差相关系数</returns> |
| | | public static double Pearson(IEnumerable<double> dataA, IEnumerable<double> dataB) |
| | | { |
| | | int n = 0; |
| | | double r = 0.0; |
| | | double meanA = 0; |
| | | double meanB = 0; |
| | | double varA = 0; |
| | | double varB = 0; |
| | | |
| | | using (var ieA = dataA.GetEnumerator()) |
| | | using (var ieB = dataB.GetEnumerator()) |
| | | { |
| | | while (ieA.MoveNext()) |
| | | { |
| | | if (!ieB.MoveNext()) |
| | | { |
| | | throw new ArgumentOutOfRangeException("dataB", "数据长度不一致"); |
| | | } |
| | | |
| | | double currentA = ieA.Current; |
| | | double currentB = ieB.Current; |
| | | |
| | | double deltaA = currentA - meanA; |
| | | double scaleDeltaA = deltaA / ++n; |
| | | |
| | | double deltaB = currentB - meanB; |
| | | double scaleDeltaB = deltaB / n; |
| | | |
| | | meanA += scaleDeltaA; |
| | | meanB += scaleDeltaB; |
| | | |
| | | varA += scaleDeltaA * deltaA * (n - 1); |
| | | varB += scaleDeltaB * deltaB * (n - 1); |
| | | r += (deltaA * deltaB * (n - 1)) / n; |
| | | } |
| | | |
| | | if (ieB.MoveNext()) |
| | | { |
| | | throw new ArgumentOutOfRangeException("dataA", "数据长度不一致"); |
| | | } |
| | | } |
| | | |
| | | return r / Math.Sqrt(varA * varB); |
| | | } |
| | | |
| | | /// <summary> |
| | | /// 计算斯皮尔曼等级相关系数 |
| | | /// </summary> |
| | | public static double Spearman(IEnumerable<double> dataA, IEnumerable<double> dataB) |
| | | { |
| | | return Pearson(Rank(dataA), Rank(dataB)); |
| | | } |
| | | |
| | | private static IEnumerable<double> Rank(IEnumerable<double> sequence) |
| | | { |
| | | var sorted = new List<double>(sequence); |
| | | sorted.Sort(); |
| | | |
| | | return (IEnumerable<double>)sequence.Select(x => (double)sorted.IndexOf(x) + 1); |
| | | } |
| | | } |
| | | |
| | | |
| | | |
| | | public class NonlinearRegressionHelper |
| | | { |
| | | //static void Main(string[] args) |
| | | //{ |
| | | // // 示例数据:Flow1 和 Pressure1 |
| | | // double[] flow1 = { 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0 }; |
| | | // double[] pressure1 = { 2.1, 4.5, 6.8, 9.2, 11.5, 13.8, 16.1, 18.4, 20.7, 23.0 }; |
| | | // var splineList = new List<CurvePoint>(); |
| | | // var measuredList = new List<CurvePoint>(); |
| | | |
| | | // // 多项式回归的阶数(例如,二次多项式) |
| | | // int degree = 2; |
| | | // var path = AppDomain.CurrentDomain.BaseDirectory; |
| | | // var lienPaht = path + @"\pumpcsv\23_44_old_curve.csv"; |
| | | // var measuredPath = path + @"\pumpcsv\23_44.csv"; |
| | | |
| | | // // 拟合多项式回归模型 |
| | | // double[] coefficients = FitPolynomial(flow1, pressure1, degree); |
| | | |
| | | // // 输出回归系数 |
| | | // Console.WriteLine("多项式回归系数:"); |
| | | // for (int i = 0; i <= degree; i++) |
| | | // using (var fs = new FileStream(lienPaht, FileMode.Open, FileAccess.Read)) |
| | | // using (var sr = new StreamReader(fs, Encoding.UTF8)) |
| | | // { |
| | | // Console.WriteLine($"系数 {i}: {coefficients[i]}"); |
| | | // var strLine = string.Empty; |
| | | // sr.ReadLine(); |
| | | // while (!string.IsNullOrEmpty(strLine = sr.ReadLine())) |
| | | // { |
| | | // var strList = strLine.Split(','); |
| | | // var x = double.Parse(strList[0]); |
| | | // var y = double.Parse(strList[1]); |
| | | // splineList.Add(new CurvePoint(x, y)); |
| | | // } |
| | | // } |
| | | |
| | | // // 使用模型进行预测 |
| | | // double xNew = 11.0; |
| | | // double yPredicted = PredictPolynomial(xNew, coefficients); |
| | | // Console.WriteLine($"\n当 Flow1 = {xNew} 时,预测的 Pressure1 = {yPredicted}"); |
| | | // using (var fs = new FileStream(measuredPath, FileMode.Open, FileAccess.Read)) |
| | | // using (var sr = new StreamReader(fs, Encoding.UTF8)) |
| | | // { |
| | | // var strLine = string.Empty; |
| | | // sr.ReadLine(); |
| | | // while (!string.IsNullOrEmpty(strLine = sr.ReadLine())) |
| | | // { |
| | | // var strList = strLine.Split(','); |
| | | // var x = double.Parse(strList[4]); |
| | | // var y = double.Parse(strList[5]); |
| | | // measuredList.Add(new CurvePoint(x, y)); |
| | | // } |
| | | // } |
| | | |
| | | // // 计算 R² 和 MSE |
| | | // double rSquared = CalculateRSquared(flow1, pressure1, coefficients); |
| | | // double mse = CalculateMSE(flow1, pressure1, coefficients); |
| | | // Console.WriteLine($"\nR² = {rSquared}"); |
| | | // Console.WriteLine($"MSE = {mse}"); |
| | | |
| | | // // 样条曲线处理 |
| | | // double[] splineX = splineList.Select(x => x.X).ToArray(); |
| | | // double[] splineY = splineList.Select(x => x.Y).ToArray(); |
| | | |
| | | // // 实测数据处理 |
| | | // double[] measuredXAll = measuredList.Select(x => x.X).ToArray(); |
| | | // double[] measuredYAll = measuredList.Select(x => x.Y).ToArray(); |
| | | |
| | | |
| | | |
| | | // var helper = new PumpCurveDataFusionCorrectorHelper(); |
| | | // (double[] mergedX, double[] mergedY, double[] optimizedX, double[] optimizedY) = helper.Corrent(splineX, splineY, measuredXAll, measuredYAll); |
| | | |
| | | // var pt_list = new List<CurvePoint>(); |
| | | // for (int i = 0; i < optimizedX.Length; i++) |
| | | // { |
| | | // var x = optimizedX[i]; |
| | | // var y = optimizedY[i]; |
| | | // pt_list.Add(new CurvePoint(x, y)); |
| | | // } |
| | | // var fullPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "pumpcsv"); |
| | | // CsvHelper.ExportToCsv(pt_list, Path.Combine(fullPath, $"23_44_update_curve.csv")); |
| | | |
| | | // Console.WriteLine("ok"); |
| | | // Console.ReadKey(); |
| | | //} |
| | | |
| | | public static void Test(DataCellViewModel xCell, DataCellViewModel yCell) |
| | | private static Dictionary<int, IStation.Model.CurveExpress> GetFlagCurveDict() |
| | | { |
| | | var x = xCell.ValueList.ToArray(); |
| | | var y = yCell.ValueList.ToArray(); |
| | | |
| | | // 多项式回归的阶数(例如,二次多项式) |
| | | int degree = 4; |
| | | |
| | | // 拟合多项式回归模型 |
| | | double[] coefficients = FitPolynomial(x, y, degree); |
| | | |
| | | // 输出回归系数 |
| | | Console.WriteLine("多项式回归系数:"); |
| | | for (int i = 0; i <= degree; i++) |
| | | var dict = new Dictionary<int, IStation.Model.CurveExpress>(); |
| | | var bll_curve = new IStation.BLL.PumpCurve(); |
| | | var station_list = new IStation.BLL.Station().GetAll(); |
| | | foreach (var station in station_list) |
| | | { |
| | | Console.WriteLine($"系数 {i}: {coefficients[i]}"); |
| | | } |
| | | |
| | | // 使用模型进行预测 |
| | | double xNew = x.Average(); |
| | | double yPredicted = PredictPolynomial(xNew, coefficients); |
| | | Console.WriteLine($"\n当 {xCell.Name} = {xNew} 时,预测的 {yCell.Name} = {yPredicted}"); |
| | | |
| | | // 计算 R² 和 MSE |
| | | double rSquared = CalculateRSquared(x, y, coefficients); |
| | | double mse = CalculateMSE(x, y, coefficients); |
| | | Console.WriteLine($"\nR² = {rSquared}"); |
| | | Console.WriteLine($"MSE = {mse}"); |
| | | |
| | | Console.WriteLine(); |
| | | Console.WriteLine(); |
| | | |
| | | } |
| | | |
| | | // 多项式回归拟合 |
| | | public static double[] FitPolynomial(double[] x, double[] y, int degree) |
| | | { |
| | | // 构建设计矩阵 |
| | | Matrix<double> X = DenseMatrix.OfArray(new double[x.Length, degree + 1]); |
| | | for (int i = 0; i < x.Length; i++) |
| | | { |
| | | for (int j = 0; j <= degree; j++) |
| | | var eq_list = new IStation.BLL.Equipment().GetPumpListByBelongTypeAndBelongID(IStation.ObjectType.Station, station.ID); |
| | | if (eq_list == null || !eq_list.Any()) |
| | | { |
| | | X[i, j] = Math.Pow(x[i], j); |
| | | continue; |
| | | } |
| | | |
| | | foreach (var eq in eq_list) |
| | | { |
| | | IStation.Model.CurveExpress qh = null; |
| | | var curve_info = bll_curve.GetDefaultWorkingByPumpID(eq.ID)?.CurveInfo; |
| | | if (curve_info != null) |
| | | { |
| | | qh = curve_info.CurveQH; |
| | | } |
| | | dict.Add(eq.SortCode, qh); |
| | | } |
| | | } |
| | | |
| | | // 构建目标向量 |
| | | Vector<double> Y = DenseVector.OfArray(y); |
| | | |
| | | // 使用最小二乘法求解 |
| | | var qr = X.QR(); |
| | | Vector<double> coefficients = qr.Solve(Y); |
| | | |
| | | return coefficients.ToArray(); |
| | | } |
| | | |
| | | // 使用多项式模型进行预测 |
| | | public static double PredictPolynomial(double x, double[] coefficients) |
| | | { |
| | | double prediction = 0.0; |
| | | for (int i = 0; i < coefficients.Length; i++) |
| | | { |
| | | prediction += coefficients[i] * Math.Pow(x, i); |
| | | } |
| | | return prediction; |
| | | } |
| | | |
| | | // 计算 R²(决定系数) |
| | | public static double CalculateRSquared(double[] x, double[] y, double[] coefficients) |
| | | { |
| | | double yMean = 0.0; |
| | | double ssTotal = 0.0; |
| | | double ssResidual = 0.0; |
| | | |
| | | for (int i = 0; i < y.Length; i++) |
| | | { |
| | | yMean += y[i]; |
| | | } |
| | | yMean /= y.Length; |
| | | |
| | | for (int i = 0; i < y.Length; i++) |
| | | { |
| | | double yPredicted = PredictPolynomial(x[i], coefficients); |
| | | ssTotal += Math.Pow(y[i] - yMean, 2); |
| | | ssResidual += Math.Pow(y[i] - yPredicted, 2); |
| | | } |
| | | |
| | | return 1.0 - (ssResidual / ssTotal); |
| | | } |
| | | |
| | | // 计算 MSE(均方误差) |
| | | public static double CalculateMSE(double[] x, double[] y, double[] coefficients) |
| | | { |
| | | double mse = 0.0; |
| | | for (int i = 0; i < y.Length; i++) |
| | | { |
| | | double yPredicted = PredictPolynomial(x[i], coefficients); |
| | | mse += Math.Pow(y[i] - yPredicted, 2); |
| | | } |
| | | return mse / y.Length; |
| | | } |
| | | |
| | | |
| | | //static void Main(string[] args) |
| | | //{ |
| | | // // 示例数据:Flow 和 Pressure |
| | | // double[] flow = { 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0 }; |
| | | // double[] pressure = { 2.1, 4.5, 6.8, 9.2, 11.5, 13.8, 16.1, 18.4, 20.7, 23.0 }; |
| | | |
| | | // // 指数回归 |
| | | // double[] exponentialCoefficients = FitExponentialRegression(flow, pressure); |
| | | // Console.WriteLine("指数回归系数:"); |
| | | // Console.WriteLine($"a = {Math.Exp(exponentialCoefficients[0])}"); |
| | | // Console.WriteLine($"b = {exponentialCoefficients[1]}"); |
| | | |
| | | // double flowNew = 11.0; |
| | | // double pressurePredictedExponential = PredictExponential(flowNew, exponentialCoefficients); |
| | | // Console.WriteLine($"\n当 Flow = {flowNew} 时,指数回归预测的 Pressure = {pressurePredictedExponential}"); |
| | | |
| | | // // 对数回归 |
| | | // double[] logarithmicCoefficients = FitLogarithmicRegression(flow, pressure); |
| | | // Console.WriteLine("\n对数回归系数:"); |
| | | // Console.WriteLine($"a = {logarithmicCoefficients[0]}"); |
| | | // Console.WriteLine($"b = {logarithmicCoefficients[1]}"); |
| | | |
| | | // double pressurePredictedLogarithmic = PredictLogarithmic(flowNew, logarithmicCoefficients); |
| | | // Console.WriteLine($"\n当 Flow = {flowNew} 时,对数回归预测的 Pressure = {pressurePredictedLogarithmic}"); |
| | | |
| | | // // 模型评估 |
| | | // double rSquaredExponential = CalculateRSquaredExponential(flow, pressure, exponentialCoefficients); |
| | | // double mseExponential = CalculateMSEExponential(flow, pressure, exponentialCoefficients); |
| | | // Console.WriteLine($"\n指数回归模型评估:"); |
| | | // Console.WriteLine($"R² = {rSquaredExponential}"); |
| | | // Console.WriteLine($"MSE = {mseExponential}"); |
| | | |
| | | // double rSquaredLogarithmic = CalculateRSquaredLogarithmic(flow, pressure, logarithmicCoefficients); |
| | | // double mseLogarithmic = CalculateMSELogarithmic(flow, pressure, logarithmicCoefficients); |
| | | // Console.WriteLine($"\n对数回归模型评估:"); |
| | | // Console.WriteLine($"R² = {rSquaredLogarithmic}"); |
| | | // Console.WriteLine($"MSE = {mseLogarithmic}"); |
| | | //} |
| | | |
| | | //public static void Test(DataCellViewModel xCell, DataCellViewModel yCell) |
| | | //{ |
| | | // // 示例数据:Flow 和 Pressure |
| | | // double[] x = xCell.ValueList.ToArray(); |
| | | // double[] y = yCell.ValueList.ToArray(); |
| | | |
| | | // // 指数回归 |
| | | // double[] exponentialCoefficients = FitExponentialRegression(x, y); |
| | | // Console.WriteLine("指数回归系数:"); |
| | | // Console.WriteLine($"a = {Math.Exp(exponentialCoefficients[0])}"); |
| | | // Console.WriteLine($"b = {exponentialCoefficients[1]}"); |
| | | |
| | | // double flowNew = x.Average(); |
| | | // double pressurePredictedExponential = PredictExponential(flowNew, exponentialCoefficients); |
| | | // Console.WriteLine($"\n当 {xCell.Name} = {flowNew} 时,指数回归预测的 {yCell.Name} = {pressurePredictedExponential}"); |
| | | |
| | | // // 对数回归 |
| | | // double[] logarithmicCoefficients = FitLogarithmicRegression(x, y); |
| | | // Console.WriteLine("\n对数回归系数:"); |
| | | // Console.WriteLine($"a = {logarithmicCoefficients[0]}"); |
| | | // Console.WriteLine($"b = {logarithmicCoefficients[1]}"); |
| | | |
| | | // double pressurePredictedLogarithmic = PredictLogarithmic(flowNew, logarithmicCoefficients); |
| | | // Console.WriteLine($"\n当 {xCell.Name} = {flowNew} 时,对数回归预测的 {yCell.Name} = {pressurePredictedLogarithmic}"); |
| | | |
| | | // // 模型评估 |
| | | // double rSquaredExponential = CalculateRSquaredExponential(x, y, exponentialCoefficients); |
| | | // double mseExponential = CalculateMSEExponential(x, y, exponentialCoefficients); |
| | | // Console.WriteLine($"\n指数回归模型评估:"); |
| | | // Console.WriteLine($"R² = {rSquaredExponential}"); |
| | | // Console.WriteLine($"MSE = {mseExponential}"); |
| | | |
| | | // double rSquaredLogarithmic = CalculateRSquaredLogarithmic(x, y, logarithmicCoefficients); |
| | | // double mseLogarithmic = CalculateMSELogarithmic(x, y, logarithmicCoefficients); |
| | | // Console.WriteLine($"\n对数回归模型评估:"); |
| | | // Console.WriteLine($"R² = {rSquaredLogarithmic}"); |
| | | // Console.WriteLine($"MSE = {mseLogarithmic}"); |
| | | //} |
| | | |
| | | |
| | | |
| | | // 指数回归拟合 |
| | | public static double[] FitExponentialRegression(double[] x, double[] y) |
| | | { |
| | | // 将 y 转换为自然对数 |
| | | double[] logY = new double[y.Length]; |
| | | for (int i = 0; i < y.Length; i++) |
| | | { |
| | | logY[i] = Math.Log(y[i]); |
| | | } |
| | | |
| | | // 构建设计矩阵 |
| | | Matrix<double> X = DenseMatrix.OfArray(new double[x.Length, 2]); |
| | | for (int i = 0; i < x.Length; i++) |
| | | { |
| | | X[i, 0] = 1.0; // 常数项 |
| | | X[i, 1] = x[i]; |
| | | } |
| | | |
| | | // 构建目标向量 |
| | | Vector<double> Y = DenseVector.OfArray(logY); |
| | | |
| | | // 使用最小二乘法求解 |
| | | var qr = X.QR(); |
| | | Vector<double> coefficients = qr.Solve(Y); |
| | | |
| | | return coefficients.ToArray(); |
| | | } |
| | | |
| | | // 指数回归预测 |
| | | public static double PredictExponential(double x, double[] coefficients) |
| | | { |
| | | double a = Math.Exp(coefficients[0]); |
| | | double b = coefficients[1]; |
| | | return a * Math.Exp(b * x); |
| | | } |
| | | |
| | | // 对数回归拟合 |
| | | public static double[] FitLogarithmicRegression(double[] x, double[] y) |
| | | { |
| | | // 将 x 转换为自然对数 |
| | | double[] logX = new double[x.Length]; |
| | | for (int i = 0; i < x.Length; i++) |
| | | { |
| | | logX[i] = Math.Log(x[i]); |
| | | } |
| | | |
| | | // 构建设计矩阵 |
| | | Matrix<double> X = DenseMatrix.OfArray(new double[x.Length, 2]); |
| | | for (int i = 0; i < x.Length; i++) |
| | | { |
| | | X[i, 0] = 1.0; // 常数项 |
| | | X[i, 1] = logX[i]; |
| | | } |
| | | |
| | | // 构建目标向量 |
| | | Vector<double> Y = DenseVector.OfArray(y); |
| | | |
| | | // 使用最小二乘法求解 |
| | | var qr = X.QR(); |
| | | Vector<double> coefficients = qr.Solve(Y); |
| | | |
| | | return coefficients.ToArray(); |
| | | } |
| | | |
| | | // 对数回归预测 |
| | | public static double PredictLogarithmic(double x, double[] coefficients) |
| | | { |
| | | double a = coefficients[0]; |
| | | double b = coefficients[1]; |
| | | return a + b * Math.Log(x); |
| | | } |
| | | |
| | | // 计算指数回归的 R² |
| | | public static double CalculateRSquaredExponential(double[] x, double[] y, double[] coefficients) |
| | | { |
| | | double yMean = 0.0; |
| | | double ssTotal = 0.0; |
| | | double ssResidual = 0.0; |
| | | |
| | | for (int i = 0; i < y.Length; i++) |
| | | { |
| | | yMean += y[i]; |
| | | } |
| | | yMean /= y.Length; |
| | | |
| | | for (int i = 0; i < y.Length; i++) |
| | | { |
| | | double yPredicted = PredictExponential(x[i], coefficients); |
| | | ssTotal += Math.Pow(y[i] - yMean, 2); |
| | | ssResidual += Math.Pow(y[i] - yPredicted, 2); |
| | | } |
| | | |
| | | return 1.0 - (ssResidual / ssTotal); |
| | | } |
| | | |
| | | // 计算指数回归的 MSE |
| | | public static double CalculateMSEExponential(double[] x, double[] y, double[] coefficients) |
| | | { |
| | | double mse = 0.0; |
| | | for (int i = 0; i < y.Length; i++) |
| | | { |
| | | double yPredicted = PredictExponential(x[i], coefficients); |
| | | mse += Math.Pow(y[i] - yPredicted, 2); |
| | | } |
| | | return mse / y.Length; |
| | | } |
| | | |
| | | // 计算对数回归的 R² |
| | | public static double CalculateRSquaredLogarithmic(double[] x, double[] y, double[] coefficients) |
| | | { |
| | | double yMean = 0.0; |
| | | double ssTotal = 0.0; |
| | | double ssResidual = 0.0; |
| | | |
| | | for (int i = 0; i < y.Length; i++) |
| | | { |
| | | yMean += y[i]; |
| | | } |
| | | yMean /= y.Length; |
| | | |
| | | for (int i = 0; i < y.Length; i++) |
| | | { |
| | | double yPredicted = PredictLogarithmic(x[i], coefficients); |
| | | ssTotal += Math.Pow(y[i] - yMean, 2); |
| | | ssResidual += Math.Pow(y[i] - yPredicted, 2); |
| | | } |
| | | |
| | | return 1.0 - (ssResidual / ssTotal); |
| | | } |
| | | |
| | | // 计算对数回归的 MSE |
| | | public static double CalculateMSELogarithmic(double[] x, double[] y, double[] coefficients) |
| | | { |
| | | double mse = 0.0; |
| | | for (int i = 0; i < y.Length; i++) |
| | | { |
| | | double yPredicted = PredictLogarithmic(x[i], coefficients); |
| | | mse += Math.Pow(y[i] - yPredicted, 2); |
| | | } |
| | | return mse / y.Length; |
| | | return dict; |
| | | } |
| | | } |
| | | |
| | | |
| | | |
| | | |
| | | } |