using IStation.CalcModel;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
namespace IStation.Calc
{
internal partial class ErQuCalcHelper_2_递归_定水位_任意时间 : ErQuCalcHelper_2_递归_定水量
{
///
///
///
///
protected override AnaPrj CalcOptPrjsCore()
{
_minTimeCountOpenPump = this.MinOpenPumpMinute / this.CalcSpaceMinute;
_minTimeCountSwitch = this.MinSwitchPumpMinute / this.CalcSpaceMinute;
//this._maxPumpSwitchCount = 5;
var result定水量 = CalcOptPrjsBlockItems定水量();
if (result定水量 == null)
return null;
foreach (var item in result定水量.Items)
{
if (item.ReservoirStartHeight >= _maxReservoirHeight || item.ReservoirEndHeight >= _maxReservoirHeight)
{
return ToAnaPrj(result定水量);
}
}
var result = CalcOptPrjsBlockItems_定水位_任意时间();
if (result == null)
return null;
return ToAnaPrj(result);
}
///
///
///
///
private BlockItemList CalcOptPrjsBlockItems_定水位_任意时间()
{
var result = RecursionFind初始_定水位_任意时间();
if (result == null || result.Items == null)
return null;
if (result.Items.First().StartIndx > 0)
{
var empty_0 = new RunBlock();
empty_0.PumpCount = 0;
empty_0.StartIndx = 0;
empty_0.EndIndx = result.Items.First().StartIndx;
empty_0.ReservoirStartHeight = this._start_level水库水位;
empty_0.ReservoirEndHeight = CalcReservoirHeight(//下次开始时的水位
empty_0.StartIndx,
empty_0.EndIndx,
0, this._start_level水库水位);
result.Items.Insert(0, empty_0);
}
double lastLevelHeight = this._start_level水库水位;
foreach (var s in from x in result.Items orderby x.StartIndx select x)
{
if (s.PumpCount == 0)
{
var end = CalcReservoirHeight(//下次开始时的水位
s.StartIndx,
s.EndIndx,
0, lastLevelHeight);
s.ReservoirStartHeight = lastLevelHeight;
s.ReservoirEndHeight = end;
lastLevelHeight = end;
}
else
{
var td = GetTimeDataBundle(s.PumpCount);
double sumFlow = 0;
for (int i = s.StartIndx; i < s.EndIndx; i++)
{
sumFlow += td.TimeDatas[i].SumFlow;
}
var end = CalcReservoirHeight(//下次开始时的水位
s.StartIndx,
s.EndIndx,
sumFlow, lastLevelHeight);
s.ReservoirStartHeight = lastLevelHeight;
s.ReservoirEndHeight = end;
lastLevelHeight = end;
}
}
if (result.Items.Last().EndIndx < this._timeDataListCount - 3)
{
var empty_l = new RunBlock();
empty_l.PumpCount = 0;
empty_l.StartIndx = result.Items.Last().EndIndx;
empty_l.EndIndx = this._timeDataListCount - 1;
empty_l.ReservoirStartHeight = result.Items.Last().ReservoirEndHeight;
empty_l.ReservoirEndHeight = CalcReservoirHeight(//下次开始时的水位
empty_l.StartIndx,
empty_l.EndIndx,
0, result.Items.Last().ReservoirEndHeight);
result.Items.Add(empty_l);
}
return result;
}
///
///
///
///
public void SetMaxReservoirHeight(double level水库水位)
{
_maxReservoirHeight = level水库水位 - 0.02; //放点余量
}
protected double _maxReservoirHeight = 0;
private bool CheckMaxLevel(double start_level, double end_level)
{
if (start_level >= this._maxReservoirHeight || end_level >= this._maxReservoirHeight)
return true;
else
return false;
}
private bool CheckMaxLevel(double start_level, List Items)
{
if (start_level >= this._maxReservoirHeight)
return true;
if (Items != null)
{
foreach (var item in Items)
{
if (item.ReservoirStartHeight >= this._maxReservoirHeight || item.ReservoirEndHeight >= this._maxReservoirHeight)
return true;
}
}
return false;
}
private bool CheckMaxLevel(double start_level, double middle_level, double end_level)
{
if (start_level >= this._maxReservoirHeight || middle_level >= this._maxReservoirHeight || end_level >= this._maxReservoirHeight)
return true;
else
return false;
}
///
///
///
///
private BlockItemList RecursionFind初始_定水位_任意时间()
{
int startSwitchTimeIndx = _minTimeCountSwitch;//保证不是一开始就进行泵切换
BlockItemList current_best_solution = new BlockItemList();
current_best_solution.TotalCompare = double.MaxValue;
current_best_solution.Items = null;
#region 判断: 全部都一样(不切换泵), 是否可以
for (int pumpNum_left = 1; pumpNum_left <= _maxOpenPumpCount; pumpNum_left++)
{
if (this._startOpenPumpCount >= 0)
{
if (this._startOpenPumpCount != pumpNum_left)
continue;
}
_totalCalcCount++;
//
double sumCompareWhole = 0;
double sumFlowWhole = 0;
var td = GetTimeDataBundle(pumpNum_left);
td.GetRangeDataStart1(0, out sumFlowWhole, out sumCompareWhole);
if (sumFlowWhole >= this._stationTotalFlow)
{
if (sumCompareWhole < current_best_solution.TotalCompare)
{
// 结束时的水位
var end_level = CalcReservoirHeight(
0,
_timeDataListCount - 1,
sumFlowWhole, this._start_level水库水位);
if (!CheckMaxLevel(_start_level水库水位, end_level))
{//检查水位
continue;
}
current_best_solution.TotalCompare = sumCompareWhole;
current_best_solution.TotalFlow = sumFlowWhole;
current_best_solution.Items = new List()
{
new RunBlock()
{
PumpCount = pumpNum_left ,
StartIndx = 0,
EndIndx = _timeDataListCount-1,
TotalCompare = sumCompareWhole,
TotalFlow = sumFlowWhole,
ReservoirStartHeight = _start_level水库水位,
ReservoirEndHeight = end_level
}
};
}
}
}
#endregion
#region 开始 不开机 情况
if (this._startOpenPumpCount == 0 || this._startOpenPumpCount == -1)
{
for (int splitIndx = startSwitchTimeIndx; splitIndx < _timeDataListCount - _minTimeCountSwitch; splitIndx++)
{//_timeList[i].IsLimitSwitch
if (!_timeList[splitIndx].IsSwitchPumpAble) continue;
//右侧继续迭代
var end_level = CalcReservoirHeight(// 结束时的水位
0,
splitIndx,
0, this._start_level水库水位);
BlockItemList right_solutions = RecursionFindRight_定水位_任意时间(
0, end_level, this._start_level水库水位, 1, 0, splitIndx);
if (right_solutions == null)
{//没有找到合适的
continue;
}
if (current_best_solution.TotalCompare > right_solutions.TotalCompare)
{
if (!CheckMaxLevel(_start_level水库水位, right_solutions.Items))
{//检查水位
continue;
}
current_best_solution.TotalCompare = right_solutions.TotalCompare;
current_best_solution.TotalFlow = right_solutions.TotalFlow;
current_best_solution.Items = new List(right_solutions.Items);
}
}
}
#endregion
#region 开机
for (int pumpNum_left = 1; pumpNum_left <= _maxOpenPumpCount; pumpNum_left++)
{
if (this._startOpenPumpCount >= 0)
{
if (this._startOpenPumpCount != pumpNum_left)
continue;
}
for (int splitIndx = startSwitchTimeIndx; splitIndx < _timeDataListCount - _minTimeCountSwitch; splitIndx++)
{ //没有 splitIndx = endTimeIndx的情况,前面已考虑
if (!_timeList[splitIndx].IsSwitchPumpAble) continue;
_totalCalcCount++;
double sumCompareLeft = 0;
double sumFlowLeft = 0; // 获取从开始时间,到结束时间,开pumpNum台泵的流量
//获取从开始时间,到结束时间,开pumpNum台泵的费用
var td = GetTimeDataBundle(pumpNum_left);
td.GetRangeData1(0, splitIndx, out sumFlowLeft, out sumCompareLeft);
if (sumFlowLeft >= this._stationTotalFlow)
{
#region 左侧已经能达到要求了,右边的全关机
if (current_best_solution.TotalCompare > sumCompareLeft)
{
//左侧结束时的水位
var left_end_level = CalcReservoirHeight(
0,
splitIndx,
sumFlowLeft, this._start_level水库水位);
if (!CheckMaxLevel(_start_level水库水位, left_end_level))
{//检查水位
continue;
}
current_best_solution.TotalCompare = sumCompareLeft;
current_best_solution.TotalFlow = sumFlowLeft;
current_best_solution.Items = new List() {//只有一个时间块
new RunBlock(){
PumpCount = pumpNum_left ,
StartIndx = 0,
EndIndx = splitIndx,
TotalCompare = sumCompareLeft,
TotalFlow = sumFlowLeft,
ReservoirStartHeight = _start_level水库水位,
ReservoirEndHeight = left_end_level
} };
}
#endregion
break;//不用再继续了,再继续 功率只会越来越大
}
else
{
//左侧结束时的水位
var left_end_level = CalcReservoirHeight(
0,
splitIndx,
sumFlowLeft, this._start_level水库水位);
//右侧继续迭代
var left_max_level = Math.Max(_start_level水库水位, left_end_level);
BlockItemList right_solutions = RecursionFindRight_定水位_任意时间(
sumFlowLeft, left_end_level, left_max_level, 1, pumpNum_left, splitIndx);
if (right_solutions == null)
{//没有找到合适的
continue;
}
double cur_sumPower = sumCompareLeft + right_solutions.TotalCompare;
if (current_best_solution.TotalCompare > cur_sumPower)
{
if (!CheckMaxLevel(left_max_level, right_solutions.Items))
{//检查水位
continue;
}
current_best_solution.TotalCompare = cur_sumPower;
current_best_solution.TotalFlow = sumFlowLeft + right_solutions.TotalFlow;
current_best_solution.Items = new List(right_solutions.Items);
current_best_solution.Items.Insert(0,//在前面插入左侧时间块
new RunBlock()
{
PumpCount = pumpNum_left,
StartIndx = 0,
EndIndx = splitIndx,
TotalCompare = sumCompareLeft,
TotalFlow = sumFlowLeft,
ReservoirStartHeight = _start_level水库水位,
ReservoirEndHeight = left_end_level
});
}
}
}
}
#endregion
if (current_best_solution.TotalCompare == double.MaxValue)
return null;
return current_best_solution;
}
///
/// 递归
///
/// 当前的流量(左侧时间块流量)
/// 当前的水库水位(左侧时间块)
/// 当前切换次数
/// 开始时间段角标
///
BlockItemList RecursionFindRight_定水位_任意时间(
double lastTotalFlow,
double lastReservoirHeight,//结束时的水位,本次迭代开始时水位
double lastMaxReservoirHeight,//以前的最高水位
int lastSwitchCount,
int lastOpenPumpCount,
int startTimeIndx)
{
if (lastSwitchCount > this.MaxPumpSwitchCount)
{//不能再切换泵了:基本上不会出现,进入前已判断
return null;
}
if (lastTotalFlow > this._stationTotalFlow)
{//已达到流量:基本上不会出现,进入前已判断
return null;
}
if (!_timeList[startTimeIndx].IsSwitchPumpAble) return null;
//
int flowKey = 0;
if (lastTotalFlow > 0)
{
flowKey = (int)(lastTotalFlow / 2000);
}
if (lastMaxReservoirHeight > this._maxReservoirHeight)
{
if (_dictCalcCache定水量[startTimeIndx][lastSwitchCount].ContainsKey(flowKey))
{
_totalCacheCount++;
var cache_model = _dictCalcCache定水量[startTimeIndx][lastSwitchCount][flowKey];
if (cache_model == null)
return null;
if (cache_model.Items.First().PumpCount == lastOpenPumpCount)
return null;
if (cache_model.TotalFlow + lastTotalFlow >= this._stationTotalFlow)
{
BlockItemList cache_model_copy = new BlockItemList();
cache_model_copy.TotalCompare = cache_model.TotalCompare;
cache_model_copy.TotalFlow = cache_model.TotalFlow;
cache_model_copy.Items = new List(cache_model.Items);
return cache_model_copy;
}
}
}
//else
//{
// if (_dictCalcCache定水量[startTimeIndx][lastSwitchCount].ContainsKey(flowKey))
// {
// _totalCacheCount++;
// var cache_model = _dictCalcCache定水量[startTimeIndx][lastSwitchCount][flowKey];
// if (cache_model == null)
// return null;
// if (cache_model.Items.First().PumpCount == lastOpenPumpCount)
// return null;
// if (cache_model.TotalFlow + lastTotalFlow >= this._stationTotalFlow && cache_model.Items)
// {
// BlockItemList cache_model_copy = new BlockItemList();
// cache_model_copy.TotalCompare = cache_model.TotalCompare;
// cache_model_copy.TotalFlow = cache_model.TotalFlow;
// cache_model_copy.Items = new List(cache_model.Items);
// return cache_model_copy;
// }
// }
//}
BlockItemList current_best_solution = new BlockItemList();
current_best_solution.TotalCompare = double.MaxValue;
current_best_solution.TotalFlow = 0;
current_best_solution.Items = null;
#region 判断: 全部都一样(不切换泵), 是否可以
for (int pumpNum_left = 1; pumpNum_left <= _maxOpenPumpCount; pumpNum_left++)
{
if (pumpNum_left == lastOpenPumpCount)
continue;
_totalCalcCount++;
double sumCompareWhole = 0;
double sumFlowWhole = 0; // 获取从开始时间,到结束时间,开pumpNum台泵的流量
//获取从开始时间,到结束时间,开pumpNum台泵的费用
var td = GetTimeDataBundle(pumpNum_left);
td.GetRangeDataStart1(startTimeIndx, out sumFlowWhole, out sumCompareWhole);
if (sumCompareWhole == double.MaxValue)
continue;
if (sumFlowWhole + lastTotalFlow >= this._stationTotalFlow &&
sumCompareWhole < current_best_solution.TotalCompare)
{
//左侧结束时的水位
var left_end_level = CalcReservoirHeight(
startTimeIndx,
_timeDataListCount - 1,
sumFlowWhole, lastReservoirHeight);
if (!this.CheckMaxLevel(lastMaxReservoirHeight, left_end_level))
{
continue;
}
current_best_solution.TotalCompare = sumCompareWhole;
current_best_solution.TotalFlow = sumFlowWhole;
current_best_solution.Items = new List()
{
new RunBlock()
{
PumpCount = pumpNum_left,
StartIndx = startTimeIndx,
EndIndx = _timeDataListCount - 1,
TotalCompare = sumCompareWhole,
TotalFlow = sumFlowWhole,
ReservoirStartHeight = lastReservoirHeight,
ReservoirEndHeight = left_end_level
}
};
}
}
#endregion
if (startTimeIndx < this._timeDataListCount - _minTimeCountSwitch)
{
#region 左侧 不开机
if (0 != lastOpenPumpCount)
{
for (int splitIndx = startTimeIndx + _minTimeCountSwitch;
splitIndx < _timeDataListCount - _minTimeCountSwitch; splitIndx++)
{
if (!_timeList[splitIndx].IsSwitchPumpAble) continue;
_totalCalcCount++;
//左侧结束时的水位(右侧开始时)
var left_end_level = CalcReservoirHeight(
startTimeIndx,
splitIndx,
0, lastReservoirHeight);
//右侧继续迭代
BlockItemList right_solutions = RecursionFindRight_定水位_任意时间(
lastTotalFlow, left_end_level, lastMaxReservoirHeight, lastSwitchCount + 1, 0, splitIndx);
if (right_solutions == null || right_solutions.TotalCompare == double.MaxValue)
{//没有找到合适的
continue;
}
if (current_best_solution.TotalCompare > right_solutions.TotalCompare)
{
if (!this.CheckMaxLevel(lastMaxReservoirHeight, right_solutions.Items))
{
continue;
}
current_best_solution.TotalCompare = right_solutions.TotalCompare;
current_best_solution.TotalFlow = right_solutions.TotalFlow;
current_best_solution.Items = new List(right_solutions.Items.Count + 1);
current_best_solution.Items.Add(new RunBlock()
{
PumpCount = 0,
StartIndx = startTimeIndx,
EndIndx = splitIndx,
ReservoirStartHeight = lastReservoirHeight,
ReservoirEndHeight = left_end_level
});
current_best_solution.Items.AddRange(right_solutions.Items);
}
}
}
#endregion
#region 左侧 开机
{
for (int pumpNum_left = 1; pumpNum_left <= _maxOpenPumpCount; pumpNum_left++)
{
if (pumpNum_left == lastOpenPumpCount)
continue;
for (int splitIndx = startTimeIndx + _minTimeCountSwitch;
splitIndx < _timeDataListCount - _minTimeCountSwitch; splitIndx++)
{ //没有 splitIndx = endTimeIndx的情况,前面已考虑
if (!_timeList[splitIndx].IsSwitchPumpAble) continue;
_totalCalcCount++;
double left_sumCompareLeft = 0;
double left_sumFlowLeft = 0; // 获取从开始时间,到结束时间,开pumpNum台泵的流量
//获取从开始时间,到结束时间,开pumpNum台泵的费用
var td = GetTimeDataBundle(pumpNum_left);
td.GetRangeData1(startTimeIndx, splitIndx,
out left_sumFlowLeft, out left_sumCompareLeft);
if (left_sumCompareLeft == double.MaxValue)
continue;
var total_current_flow = left_sumFlowLeft + lastTotalFlow;
if (total_current_flow >= this._stationTotalFlow)
{//左侧已经能达到要求了
if (current_best_solution.TotalCompare > left_sumCompareLeft)
{
//左侧结束时的水位(右侧开始时)
var left_end_level = CalcReservoirHeight(
startTimeIndx,
splitIndx,
left_sumFlowLeft, lastReservoirHeight);
if (!this.CheckMaxLevel(lastMaxReservoirHeight, left_end_level))
{
continue;
}
current_best_solution.TotalCompare = left_sumCompareLeft;
current_best_solution.TotalFlow = left_sumFlowLeft;
current_best_solution.Items = new List() {
new RunBlock(){
PumpCount = pumpNum_left ,
StartIndx = startTimeIndx,
EndIndx = splitIndx ,
TotalCompare = left_sumCompareLeft,
TotalFlow = left_sumFlowLeft,
ReservoirStartHeight = lastReservoirHeight,
ReservoirEndHeight = left_end_level
} };
}
//break;//不用再继续了,再继续 功率只会越来越大
}
else
{
//左侧结束时的水位
var left_end_level = CalcReservoirHeight(
startTimeIndx,
splitIndx,
left_sumFlowLeft, lastReservoirHeight);
var mmm = Math.Max(left_end_level, lastMaxReservoirHeight);
//右侧继续迭代
BlockItemList right_solutions = RecursionFindRight_定水位_任意时间(
total_current_flow, left_end_level, mmm, lastSwitchCount + 1, pumpNum_left, splitIndx);
if (right_solutions == null || right_solutions.TotalCompare == double.MaxValue)
{//没有找到合适的
continue;
}
double cur_sumPower = left_sumCompareLeft + right_solutions.TotalCompare;
if (current_best_solution.TotalCompare > cur_sumPower)
{
if (!this.CheckMaxLevel(mmm, current_best_solution.Items))
{
continue;
}
current_best_solution.TotalCompare = cur_sumPower;
current_best_solution.TotalFlow = left_sumFlowLeft + right_solutions.TotalFlow;
current_best_solution.Items = new List(right_solutions.Items);
current_best_solution.Items.Insert(0,//在前面插入左侧时间块
new RunBlock()
{
PumpCount = pumpNum_left,
StartIndx = startTimeIndx,
EndIndx = splitIndx,
TotalCompare = left_sumCompareLeft,
TotalFlow = left_sumFlowLeft,
ReservoirStartHeight = lastReservoirHeight,
ReservoirEndHeight = left_end_level
});
}
}
}
}
}
#endregion
}
else
{
}
if (current_best_solution.TotalCompare == double.MaxValue)
{
//if (isNeedInsertCache)
//{
// _dictCalcCache[startTimeIndx][lastSwitchCount][flowKey] = null;
//}
return null;
}
else
{
//if (isNeedInsertCache)
//{
// _dictCalcCache[startTimeIndx][lastSwitchCount][flowKey] = current_best_solution;
//}
return current_best_solution;
}
}
}
}