using IStation.CalcModel;
|
using System;
|
using System.Collections.Generic;
|
using System.ComponentModel;
|
using System.Linq;
|
|
namespace IStation.Calc
|
{
|
internal partial class ErQuCalcHelper_2_递归 : ErQuCalcBaseHelper
|
{
|
BlockItemList _globalOptSolution = null;
|
/// <summary>
|
/// 递归
|
/// </summary>
|
/// <param name="dd_minute"></param>
|
/// <returns></returns>
|
private BlockItemList CalcOptPrjsCore控制水位()
|
{
|
//_dictCalcCache = new List<List<Dictionary<int, BlockItemList>>>(_timeDataListCount + 1);
|
//for (int i = 0; i < _timeDataListCount + 1; i++)
|
//{
|
// var ak = new List<Dictionary<int, BlockItemList>>(_timeDataListCount + 1);
|
// for (int j = 0; j < this.MaxPumpSwitchCount + 2; j++)
|
// {
|
// ak.Add(new Dictionary<int, BlockItemList>());
|
// }
|
// _dictCalcCache.Add(ak);
|
//}
|
_globalOptSolution = new BlockItemList();
|
_globalOptSolution.TotalCompare = double.MaxValue;
|
|
CalcAna只有一个时间块();
|
CalcAna只有两个时间块();
|
CalcAna至少三个时间块();
|
if (_globalOptSolution.TotalCompare == double.MaxValue)
|
return null;
|
return _globalOptSolution ;
|
}
|
|
|
#region 一个时间块
|
private bool CalcAna只有一个时间块()
|
{
|
bool isHave = false;
|
for (int pumpNum_left = 1; pumpNum_left <= 4; pumpNum_left++)
|
{
|
if (this._startOpenCount >= 0)
|
{
|
if (this._startOpenCount != pumpNum_left)
|
continue;
|
}
|
|
_totalCalcCount++;
|
int startIndx = 0;
|
//
|
double sumCompareWhole = 0;
|
double sumFlowWhole = 0;
|
var td = GetTimeDataBundle(pumpNum_left);
|
td.GetRangeDataStart1(0, out sumFlowWhole, out sumCompareWhole);
|
if (sumFlowWhole < this._stationTotalFlow)
|
continue;
|
if (_globalOptSolution.TotalCompare < sumCompareWhole)
|
continue;
|
|
// 水库水位
|
var end_reservoir_height = CalcReservoirHeight(
|
startIndx,
|
_timeDataListCount - 1,
|
sumFlowWhole, this._start_level水库水位);
|
if (!CheckReservoirHeight(_start_level水库水位, end_reservoir_height))
|
continue;
|
{
|
isHave = true;
|
_globalOptSolution.TotalFlow = sumFlowWhole;
|
_globalOptSolution.TotalCompare = sumCompareWhole;
|
_globalOptSolution.Items = new List<RunBlock>()
|
{
|
new RunBlock()
|
{
|
PumpCount = pumpNum_left ,
|
StartIndx = startIndx,
|
EndIndx = _timeDataListCount-1,
|
TotalCompare = sumCompareWhole,
|
TotalFlow = sumFlowWhole,
|
ReservoirStartHeight = _start_level水库水位,
|
ReservoirEndHeight = end_reservoir_height
|
}
|
};
|
}
|
}
|
|
return isHave;
|
}
|
#endregion
|
|
|
#region 两个时间块
|
class two
|
{
|
public two(int n1,int n2)
|
{
|
this.open_num1 = n1;
|
this.open_num2 = n2;
|
}
|
public int open_num1 = 0;
|
public int open_num2 = 0;
|
public two Tran()
|
{
|
return new two(this.open_num2,this.open_num1);
|
}
|
}
|
|
/// <summary>
|
/// 两个时间块
|
/// </summary>
|
/// <returns></returns>
|
private bool CalcAna只有两个时间块()
|
{
|
bool isHave = false;
|
List<two> tuples1 = new List<two>();
|
tuples1.Add(new two(0, 1));
|
tuples1.Add(new two(0, 2));
|
tuples1.Add(new two(0, 3));
|
tuples1.Add(new two(0, 4));
|
|
tuples1.Add(new two(1, 2));
|
tuples1.Add(new two(1, 3));
|
tuples1.Add(new two(1, 4));
|
|
tuples1.Add(new two(2, 3));
|
tuples1.Add(new two(2, 4));
|
|
tuples1.Add(new two(3, 4));
|
List<two> tuples = new List<two>();
|
tuples.AddRange(tuples1);
|
foreach (var tuple in tuples1)
|
{
|
tuples.Add (tuple.Tran());
|
}
|
|
for (int splitIndx = _minTimeCountSwitch; splitIndx < _timeDataListCount - this._minTimeCountSwitch; splitIndx++)
|
{//_timeList[i].IsLimitSwitch
|
if (!_timeList[splitIndx].IsSwitchPumpAble) continue;
|
|
foreach(var t in tuples)
|
{
|
double sumCompareLeft = 0;
|
double sumFlowLeft = 0;
|
|
if (t.open_num1 > 0)
|
{
|
var td1 = GetTimeDataBundle(t.open_num1);
|
td1.GetRangeData1(0, splitIndx, out sumFlowLeft, out sumCompareLeft);
|
}
|
double sumCompareRight = 0;
|
double sumFlowRight = 0;
|
if (t.open_num2 > 0)
|
{
|
var td2 = GetTimeDataBundle(t.open_num2);
|
td2.GetRangeData1(splitIndx, _timeDataListCount-1, out sumFlowRight, out sumCompareRight);
|
}
|
if (sumFlowRight + sumFlowLeft < this._stationTotalFlow)
|
{
|
continue;
|
}
|
|
if (this._globalOptSolution.TotalCompare < sumCompareLeft + sumCompareRight)
|
{
|
continue;
|
}
|
|
|
|
|
var middle_rev_height = CalcReservoirHeight(//下次开始时的水位
|
0,
|
splitIndx,
|
sumFlowLeft, _start_level水库水位);
|
|
|
var end_rev_height1 = CalcReservoirHeight(//下次开始时的水位
|
splitIndx,
|
_timeDataListCount - 1,
|
sumFlowRight, middle_rev_height);
|
if (!CheckReservoirHeight(_start_level水库水位, middle_rev_height, end_rev_height1))
|
continue;
|
|
|
BlockItemList current_opt_solution = new BlockItemList();
|
current_opt_solution.TotalFlow = sumFlowRight + sumFlowLeft;
|
current_opt_solution.TotalCompare = sumCompareLeft + sumCompareRight;
|
current_opt_solution.Items = new List<RunBlock>()
|
{
|
new RunBlock()
|
{
|
PumpCount = t.open_num1,
|
StartIndx = 0,
|
EndIndx = splitIndx,
|
TotalCompare = sumCompareLeft,
|
TotalFlow = sumFlowLeft,
|
ReservoirStartHeight = this._start_level水库水位,
|
ReservoirEndHeight = middle_rev_height
|
},
|
new RunBlock()
|
{
|
PumpCount = t.open_num2,
|
StartIndx = splitIndx,
|
EndIndx = _timeDataListCount - 1,
|
TotalCompare = sumCompareRight,
|
TotalFlow = sumFlowRight,
|
ReservoirStartHeight = middle_rev_height,
|
ReservoirEndHeight = end_rev_height1
|
}
|
};
|
|
|
_globalOptSolution = current_opt_solution;
|
|
|
isHave = true;
|
}
|
|
}
|
|
return isHave;
|
}
|
|
#endregion
|
|
|
#region 多个时间块
|
/// <summary>
|
///
|
/// </summary>
|
/// <returns></returns>
|
private bool CalcAna至少三个时间块()
|
{
|
//int startSwitchTimeIndx = 4;//保证不是一开始就进行泵切换
|
|
|
|
bool isHave = false;
|
|
int max_dex =
|
_timeDataListCount - 2 * this._minTimeCountSwitch - 2 * this._minTimeCountOpenPump;
|
|
|
#region 不开机
|
if (this._startOpenCount == 0 || this._startOpenCount == -1)
|
{
|
for (int splitIndx = 0; splitIndx < max_dex; splitIndx++)
|
{
|
if (!_timeList[splitIndx].IsSwitchPumpAble) continue;
|
//右侧继续迭代
|
var end_rev_height = CalcReservoirHeight(//下次开始时的水位
|
0,
|
splitIndx,
|
0, this._start_level水库水位);
|
BlockItemList right_solutions = RecursionFindRight(
|
0, 0, end_rev_height, 1, splitIndx,
|
0, end_rev_height, _start_level水库水位);
|
if (right_solutions == null || right_solutions.TotalFlow < this._stationTotalFlow)
|
{//没有找到合适的
|
continue;
|
}
|
if (_globalOptSolution.TotalCompare < right_solutions.TotalCompare)
|
continue;
|
BlockItemList current_opt_solution = new BlockItemList();
|
current_opt_solution.TotalFlow = right_solutions.TotalFlow;
|
current_opt_solution.TotalCompare = right_solutions.TotalCompare;
|
current_opt_solution.Items = new List<RunBlock>()
|
{
|
new RunBlock()
|
{
|
PumpCount = 0,
|
StartIndx = 0,
|
EndIndx = splitIndx,
|
TotalCompare = 0,
|
TotalFlow = 0,
|
ReservoirStartHeight = this._start_level水库水位,
|
ReservoirEndHeight = end_rev_height
|
}
|
};
|
current_opt_solution.Items.AddRange(right_solutions.Items);
|
_globalOptSolution = current_opt_solution;
|
isHave = true;
|
}
|
}
|
#endregion
|
|
|
#region 开机
|
for (int openPumpNum = 1; openPumpNum <= 4; openPumpNum++)
|
{
|
if (this._startOpenCount >= 0)
|
{
|
if (this._startOpenCount != openPumpNum)
|
continue;
|
}
|
|
for (int splitIndx = 0; splitIndx < max_dex; splitIndx++)
|
{ //没有 splitIndx = endTimeIndx的情况,前面已考虑
|
if (!_timeList[splitIndx].IsSwitchPumpAble) continue;
|
|
_totalCalcCount++;
|
double sumCompareLeft = 0;
|
double sumFlowLeft = 0; // 获取从开始时间,到结束时间,开pumpNum台泵的流量
|
|
//获取从开始时间,到结束时间,开pumpNum台泵的费用
|
var td = GetTimeDataBundle(openPumpNum);
|
td.GetRangeData1(0, splitIndx, out sumFlowLeft, out sumCompareLeft);
|
if (this._globalOptSolution.TotalCompare < sumCompareLeft)
|
break;//左侧功率已经超过最优,就不要再向右移动了, 再继续 功率只会越来越大
|
|
|
|
var end_rev_height = CalcReservoirHeight(//下次开始时的水位
|
0,
|
splitIndx,
|
sumFlowLeft, _start_level水库水位);
|
double min_height = Math.Min(_start_level水库水位, end_rev_height);
|
double max_height = Math.Max(_start_level水库水位, end_rev_height);
|
|
//右侧继续迭代
|
BlockItemList right_solutions = RecursionFindRight(
|
sumFlowLeft, sumCompareLeft, end_rev_height, 1, splitIndx,
|
openPumpNum, min_height, max_height);
|
if (right_solutions == null ||
|
right_solutions.TotalCompare == double.MaxValue)
|
{//没有找到合适的
|
continue;
|
}
|
|
double cur_sum_flow = right_solutions.TotalFlow + sumFlowLeft;
|
if (cur_sum_flow < this._stationTotalFlow)
|
continue;
|
double cur_sum_compare = sumCompareLeft + right_solutions.TotalCompare;
|
if (_globalOptSolution.TotalCompare < cur_sum_compare)
|
continue;
|
|
BlockItemList current_opt_solution = new BlockItemList();
|
current_opt_solution.TotalFlow = cur_sum_flow;
|
current_opt_solution.TotalCompare = cur_sum_compare;
|
current_opt_solution.Items = new List<RunBlock>()
|
{
|
new RunBlock()
|
{
|
PumpCount = openPumpNum,
|
StartIndx = 0,
|
EndIndx = splitIndx,
|
TotalCompare = sumCompareLeft,
|
TotalFlow = sumFlowLeft,
|
ReservoirStartHeight = this._start_level水库水位,
|
ReservoirEndHeight = end_rev_height
|
}
|
};
|
current_opt_solution.Items.AddRange(right_solutions.Items);
|
|
_globalOptSolution = current_opt_solution;
|
isHave = true;
|
}
|
}
|
|
|
#endregion
|
|
|
|
|
return isHave;
|
}
|
|
|
|
/// <summary>
|
/// 递归
|
/// </summary>
|
/// <param name="lastTotalFlow">上次结束,这次开始时,总流量</param>
|
/// <param name="lastTotalCompare">上次结束,这次开始时,总比较</param>
|
/// <param name="lastEndReservoirHeight">上次结束,这次开始时水位</param>
|
/// <param name="lastSwitchCount">切换次数</param>
|
/// <param name="startTimeIndx">这次开始时间点</param>
|
/// <param name="lastMinReservoirHeight">上次最小</param>
|
/// <param name="lastMaxReservoirHeight">上次最大</param>
|
/// <returns></returns>
|
BlockItemList RecursionFindRight(
|
double lastTotalFlow,
|
double lastTotalCompare,
|
double lastEndReservoirHeight,
|
int lastSwitchCount,
|
int startTimeIndx,
|
int lastOpenPump,
|
double lastMinReservoirHeight,
|
double lastMaxReservoirHeight)
|
{
|
if (lastSwitchCount > this.MaxPumpSwitchCount)
|
{//不能再切换泵了:基本上不会出现,进入前已判断
|
return null;
|
}
|
if (startTimeIndx >= this._timeDataListCount - 1)
|
{
|
return null;
|
}
|
if (lastTotalCompare > this._globalOptSolution.TotalCompare)
|
return null;
|
|
if (!_timeList[startTimeIndx].IsSwitchPumpAble) return null;
|
|
BlockItemList current_opt_solution = new BlockItemList();
|
current_opt_solution.TotalCompare = double.MaxValue;
|
current_opt_solution.Items = null;
|
|
if(lastSwitchCount > 2)
|
{
|
#region 检查不开机是否符合要求
|
//以前的水位已经可以满足要求的话,就不要开机了
|
if (this.CheckReservoirHeight(lastMaxReservoirHeight, lastMaxReservoirHeight)
|
&& lastTotalFlow > this._stationTotalFlow)
|
{
|
_totalCalcCount++;
|
|
// 水库水位
|
var end_reservoir_height = CalcReservoirHeight(
|
startTimeIndx,
|
_timeDataListCount - 1,
|
0, lastEndReservoirHeight);
|
|
current_opt_solution.TotalFlow = 0;
|
current_opt_solution.TotalCompare = 0;
|
current_opt_solution.Items = new List<RunBlock>(){
|
new RunBlock()
|
{
|
PumpCount = 0,
|
StartIndx = startTimeIndx,
|
EndIndx = _timeDataListCount - 1,
|
TotalCompare = 0,
|
TotalFlow = 0,
|
ReservoirStartHeight = lastEndReservoirHeight,
|
ReservoirEndHeight = end_reservoir_height
|
} };
|
}
|
|
#endregion
|
|
#region 判断: 剩余的全部都一样(不切换泵), 是否可以
|
for (int openPumpNum = 1; openPumpNum <= 4; openPumpNum++)
|
{
|
if (lastOpenPump == openPumpNum)
|
{
|
continue;
|
}
|
_totalCalcCount++;
|
|
//获取从开始时间,到结束时间,开pumpNum台泵的费用
|
double sumCompareWhole = 0;
|
double sumFlowWhole = 0; // 获取从开始时间,到结束时间,开pumpNum台泵的流量
|
//if (openPumpNum > 0)
|
{
|
var td = GetTimeDataBundle(openPumpNum);
|
td.GetRangeDataStart1(startTimeIndx, out sumFlowWhole, out sumCompareWhole);
|
}
|
|
if (sumFlowWhole + lastTotalFlow < this._stationTotalFlow)
|
continue;
|
if (this._globalOptSolution.TotalCompare < sumCompareWhole + lastTotalCompare)
|
break;//不要再继续了,再继续,功率只会越高
|
|
// 水库水位
|
var end_reservoir_height = CalcReservoirHeight(
|
startTimeIndx,
|
_timeDataListCount - 1,
|
sumFlowWhole, lastEndReservoirHeight);
|
double min_height = Math.Min(lastMinReservoirHeight, end_reservoir_height);
|
double max_height = Math.Max(lastMaxReservoirHeight, end_reservoir_height);
|
if (!CheckReservoirHeight(min_height, max_height))
|
continue;
|
current_opt_solution.TotalFlow = sumFlowWhole;
|
current_opt_solution.TotalCompare = sumCompareWhole;
|
current_opt_solution.Items = new List<RunBlock>(){
|
new RunBlock()
|
{
|
PumpCount = openPumpNum,
|
StartIndx = startTimeIndx,
|
EndIndx = _timeDataListCount - 1,
|
TotalCompare = sumCompareWhole,
|
TotalFlow = sumFlowWhole,
|
ReservoirStartHeight = lastEndReservoirHeight,
|
ReservoirEndHeight = end_reservoir_height
|
} };
|
}
|
|
#endregion
|
}
|
|
|
|
|
//int flowKey = 0;
|
//if (lastTotalFlow > 0)
|
//{
|
// flowKey = (int)(lastTotalFlow / 1500);
|
//}
|
//int key = flowKey;
|
//if (_dictCalcCache[startTimeIndx][lastSwitchCount].ContainsKey(key))
|
//{
|
// _totalCacheCount++;
|
// var cache_model = _dictCalcCache[startTimeIndx][lastSwitchCount][key];
|
// if (cache_model == null)
|
// return null;
|
// BlockItemList cache_model2 = new BlockItemList();
|
// cache_model2.BestTotalCompare = cache_model.BestTotalCompare;
|
// cache_model2.Items = new List<RunBlock>(cache_model.Items);
|
// return cache_model2;
|
//}
|
|
|
|
|
|
|
|
if (lastSwitchCount < this.MaxPumpSwitchCount &&
|
startTimeIndx < _timeDataListCount - this._minTimeCountSwitch)
|
{
|
#region 不开机
|
if (lastOpenPump != 0)
|
{
|
for (int splitIndx = startTimeIndx + _minTimeCountSwitch;
|
splitIndx < _timeDataListCount - this._minTimeCountSwitch; splitIndx++)
|
{
|
if (!_timeList[splitIndx].IsSwitchPumpAble) continue;
|
|
_totalCalcCount++;
|
|
var end_rev_height = CalcReservoirHeight(//下次开始时的水位
|
startTimeIndx,
|
splitIndx,
|
0, lastEndReservoirHeight);
|
double min_height = Math.Min(end_rev_height, lastMinReservoirHeight);
|
//右侧继续迭代
|
BlockItemList right_solutions = RecursionFindRight(
|
lastTotalFlow, lastTotalCompare, end_rev_height,
|
lastSwitchCount + 1, splitIndx, 0,
|
min_height, lastMaxReservoirHeight);
|
|
if (right_solutions == null ||
|
right_solutions.TotalCompare == double.MaxValue)
|
{//没有找到合适的
|
continue;
|
}
|
if (this._globalOptSolution.TotalCompare < lastTotalCompare + right_solutions.TotalCompare)
|
{
|
continue;
|
}
|
|
current_opt_solution.TotalFlow = right_solutions.TotalFlow;
|
current_opt_solution.TotalCompare = right_solutions.TotalCompare;
|
current_opt_solution.Items = current_opt_solution.Items = new List<RunBlock>(){
|
new RunBlock()
|
{
|
PumpCount = 0,//当前关机
|
StartIndx = startTimeIndx,
|
EndIndx = splitIndx,
|
TotalCompare = 0,
|
TotalFlow = 0,
|
ReservoirStartHeight = lastEndReservoirHeight,
|
ReservoirEndHeight = end_rev_height
|
} };
|
|
|
current_opt_solution.Items.AddRange(right_solutions.Items);
|
}
|
}
|
#endregion
|
|
#region 开机
|
{
|
for (int openPumpNum = 1; openPumpNum <= 4; openPumpNum++)
|
{
|
if (lastOpenPump == openPumpNum)
|
continue;
|
|
for (int splitIndx = startTimeIndx + _minTimeCountSwitch;
|
splitIndx < _timeDataListCount - _minTimeCountSwitch;
|
splitIndx++)
|
{ //没有 splitIndx = endTimeIndx的情况,前面已考虑
|
//if (!_timeIsLimitList[splitIndx]) continue;
|
if (!_timeList[splitIndx].IsSwitchPumpAble) continue;
|
|
_totalCalcCount++;
|
|
double sumCompareLeft = 0;
|
double sumFlowLeft = 0; // 获取从开始时间,到结束时间,开pumpNum台泵的流量
|
|
//获取从开始时间,到结束时间,开pumpNum台泵的费用
|
var td = GetTimeDataBundle(openPumpNum);
|
td.GetRangeData1(startTimeIndx, splitIndx,
|
out sumFlowLeft, out sumCompareLeft);
|
|
if (this._globalOptSolution.TotalCompare < sumCompareLeft + lastTotalCompare)
|
{//不用继续了
|
break;
|
}
|
|
|
var end_rev_height = CalcReservoirHeight(//下次开始时的水位
|
startTimeIndx,
|
splitIndx,
|
sumFlowLeft, lastEndReservoirHeight);
|
|
|
double min_height = Math.Min(lastMinReservoirHeight, end_rev_height);
|
double max_height = Math.Max(lastMaxReservoirHeight, end_rev_height);
|
|
//右侧继续迭代
|
BlockItemList right_solutions = RecursionFindRight(
|
lastTotalFlow + sumFlowLeft, lastTotalCompare + sumCompareLeft,
|
end_rev_height,
|
lastSwitchCount + 1, splitIndx,
|
openPumpNum, min_height, max_height);
|
if (right_solutions == null ||
|
right_solutions.TotalCompare == double.MaxValue)
|
{//没有找到合适的
|
continue;
|
}
|
|
if (this._globalOptSolution.TotalCompare < lastTotalCompare + sumCompareLeft + current_opt_solution.TotalCompare)
|
continue;
|
current_opt_solution.TotalFlow = sumFlowLeft + right_solutions.TotalFlow;
|
current_opt_solution.TotalCompare = sumCompareLeft + right_solutions.TotalCompare;
|
current_opt_solution.Items = new List<RunBlock>()
|
{
|
new RunBlock()
|
{
|
PumpCount = openPumpNum,
|
StartIndx = startTimeIndx,
|
EndIndx = splitIndx,
|
TotalCompare = sumCompareLeft,
|
TotalFlow = sumFlowLeft,
|
ReservoirStartHeight = lastEndReservoirHeight,
|
ReservoirEndHeight = end_rev_height
|
}
|
};
|
current_opt_solution.Items.AddRange(right_solutions.Items);
|
|
}
|
}
|
}
|
|
#endregion
|
}
|
|
if (current_opt_solution.TotalCompare == double.MaxValue)
|
{
|
//_dictCalcCache[startTimeIndx][lastSwitchCount][key] = null;
|
return null;
|
}
|
else
|
{
|
//_dictCalcCache[startTimeIndx][lastSwitchCount][key] = current_opt_solution;
|
return current_opt_solution;
|
}
|
}
|
|
|
|
#endregion
|
|
|
|
}
|
}
|