// 创建一个 Stopwatch 实例
|
using System.Collections.Concurrent;
|
using System.Diagnostics;
|
using System.Text;
|
|
|
Console.WriteLine("开始模拟...");
|
Stopwatch stopwatch = new Stopwatch();
|
stopwatch.Start();
|
|
var file_path = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "1897563622226399232.inp");
|
|
var pressure = 0d;
|
var minDemand = 50.0; // 最小总需水量(m³/h)
|
var maxDemand = 500.0; // 最大总需水量(m³/h)
|
var calcCount = 20000; // 计算次数
|
|
|
var list = new List<SimulationResult>(calcCount);
|
using (var helper = new Yw.Epanet.InteropXHelper())
|
{
|
var err = helper.Open(file_path, "", "");
|
err = helper.GetCount(Yw.Epanet.eCountType.Node, out int nodeCount);
|
err = helper.OpenH();
|
|
var allDemands = GenerateDemandMatrix(minDemand, maxDemand, nodeCount, calcCount);
|
for (int i = 0; i < calcCount; i++)
|
{
|
helper.InitH(false);
|
var demands = allDemands[i];
|
for (int nodeIdx = 1; nodeIdx <= nodeCount; nodeIdx++)
|
{
|
double demand = demands[nodeIdx - 1];
|
err = helper.SetNodeValue(nodeIdx, Yw.Epanet.eNodeProperty.BaseDemand, demand);
|
}
|
|
helper.RunH(out long t);
|
|
var result = new SimulationResult();
|
for (int nodeIdx = 1; nodeIdx <= nodeCount; nodeIdx++)
|
{
|
pressure = 0;
|
helper.GetNodeValue(nodeIdx, Yw.Epanet.eNodeProperty.Pressure, out pressure);
|
result.UpdateMaxPressure(nodeIdx, pressure);
|
}
|
helper.NextH(out long tstep);
|
list.Add(result);
|
}
|
|
|
helper.Close();
|
|
}
|
|
|
|
stopwatch.Stop();
|
|
Console.WriteLine("所有模拟已完成。");
|
Console.WriteLine($"总时间:{stopwatch.Elapsed.TotalSeconds}");
|
|
var strBuild = new StringBuilder();
|
foreach (var item in list)
|
{
|
var pressureList = item.MaxPressures.Values.ToList();
|
strBuild.AppendLine($"{pressureList.Min()},{pressureList.Max()}");
|
}
|
|
Console.WriteLine(strBuild.ToString());
|
Console.ReadLine();
|
Console.ReadKey();
|
|
|
|
/// <summary>
|
/// 生成需水量矩阵(基于遗传算法的随机分配策略[2](@ref))
|
/// </summary>
|
double[][] GenerateDemandMatrix(double minDemand, double maxDemand, int nodeCount, int totalSteps)
|
{
|
var demandMatrix = new double[totalSteps][];
|
double stepSize = (maxDemand - minDemand) / (totalSteps - 1);
|
var rand = new Random();
|
for (int step = 0; step < totalSteps; step++)
|
{
|
double totalDemand = minDemand + step * stepSize;
|
demandMatrix[step] = GenerateRandomDemands(rand, nodeCount, totalDemand);
|
}
|
return demandMatrix;
|
}
|
|
/// <summary>
|
/// 随机分配总需水量到各节点(符合案例中的用水量分配逻辑[1](@ref))
|
/// </summary>
|
double[] GenerateRandomDemands(Random rand, int nodeCount, double totalDemand)
|
{
|
double[] demands = new double[nodeCount];
|
double remaining = totalDemand;
|
|
// 加权随机分配算法
|
for (int i = 0; i < nodeCount - 1; i++)
|
{
|
double maxPossible = remaining / (nodeCount - i);
|
demands[i] = rand.NextDouble() * maxPossible;
|
remaining -= demands[i];
|
}
|
demands[nodeCount - 1] = remaining; // 确保总和准确
|
return demands;
|
}
|
|
double[,] GenerateAllDemands(int nodeCount, int totalIterations, double[] weValues)
|
{
|
|
double[,] demands = new double[totalIterations, nodeCount];
|
Parallel.For(0, totalIterations, iter =>
|
{
|
var rand = new Random();
|
for (int node = 0; node < nodeCount; node++)
|
{
|
// 遗传算法式选择
|
int idx = rand.Next(weValues.Length);
|
|
// 20%概率变异
|
if (rand.NextDouble() < 0.2)
|
idx = (idx + 1) % weValues.Length;
|
demands[iter, node] = weValues[idx];
|
}
|
});
|
return demands;
|
}
|
|
public class SimulationResult
|
{
|
public ConcurrentDictionary<int, double> MaxPressures { get; } = new();
|
|
public void UpdateMaxPressure(int nodeId, double pressure)
|
{
|
MaxPressures.AddOrUpdate(nodeId, pressure,
|
(id, old) => Math.Max(old, pressure));
|
}
|
}
|