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; #region 判断定水量是否可以 if (this._flowInTotalFlow > 0) { var result定水量 = CalcOptPrjsBlockItems定水量(); if (result定水量 == null) return null; //if (CheckMaxLevel(result定水量.Items)) //{ // return ToAnaPrj(result定水量); //} var prj定水量 = ToAnaPrj(result定水量); var height = prj定水量.GetWaterLevelHByTime(_maxReservoirTime); if(height >= _maxReservoirHeight) { return prj定水量; } } #endregion for (int i = 0; i < _timeList.Count; i++) { if (_timeList[i].Time >= _maxReservoirTime) { _maxReservoirTimeIndex = i; break; } } // 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水库水位, DateTime time) { _maxReservoirHeight = level水库水位 - 0.02;//放点余量 //_maxReservoirHeightMin = level水库水位 - 0.2; //_maxReservoirHeightMax = level水库水位 + 0.2; _maxReservoirTime = time; } protected double _maxReservoirHeight = 0; protected DateTime _maxReservoirTime; protected int _maxReservoirTimeIndex = -1; //protected double _maxReservoirHeightMin = 0; //protected double _maxReservoirHeightMax = 0; private bool CheckMaxLevel(int start_time_index, double start_level, int end_time_index, double end_level) { if (_maxReservoirTimeIndex < start_level || _maxReservoirTimeIndex > end_time_index) return true; var WaterLevelH = start_level + (start_time_index - _maxReservoirTimeIndex) * (-start_level + end_level) / (start_time_index - end_time_index); if (WaterLevelH >= _maxReservoirHeight) return true; else return false; } private bool CheckMaxLevel(List Items) { if (Items == null) return true; foreach (var item in Items) { if (_maxReservoirTimeIndex < item.StartIndx || _maxReservoirTimeIndex > item.EndIndx) continue; var WaterLevelH = Math.Round( item.ReservoirStartHeight + (item.StartIndx - _maxReservoirTimeIndex) * (-item.ReservoirStartHeight + item.ReservoirEndHeight) / (item.StartIndx - item.EndIndx), 4); if (WaterLevelH >= _maxReservoirHeight ) return true; else return false; } return true; } /// /// /// /// 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._flowInTotalFlow) { if (sumCompareWhole < current_best_solution.TotalCompare) { // 结束时的水位 var end_level = CalcReservoirHeight( 0, _timeDataListCount - 1, sumFlowWhole, this._start_level水库水位); if (!CheckMaxLevel(0, _start_level水库水位, _timeDataListCount - 1, 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水库水位); if (!CheckMaxLevel(0, _start_level水库水位, splitIndx, end_level)) {//检查水位 continue; } BlockItemList right_solutions = RecursionFindRight_定水位_指定时间( 0, end_level, 1, 0, splitIndx); if (right_solutions == null) {//没有找到合适的 continue; } if (current_best_solution.TotalCompare > right_solutions.TotalCompare) { if (!CheckMaxLevel(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._flowInTotalFlow) { #region 左侧已经能达到要求了,右边的全关机 if (current_best_solution.TotalCompare > sumCompareLeft) { //左侧结束时的水位 var left_end_level = CalcReservoirHeight( 0, splitIndx, sumFlowLeft, this._start_level水库水位); //检查水位 if (splitIndx > this._maxReservoirTimeIndex) { if (!CheckMaxLevel(0, _start_level水库水位, splitIndx, left_end_level)) { continue; } } else { //如果还未达到指定时间,还需检查指定时间的水位 var finish_level = CalcReservoirHeight( splitIndx, _timeDataListCount - 1, 0, left_end_level); if (!CheckMaxLevel(splitIndx, left_end_level, _timeDataListCount - 1, finish_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水库水位); if (!CheckMaxLevel(0, _start_level水库水位, splitIndx, left_end_level)) {//检查水位 continue; } //右侧继续迭代 BlockItemList right_solutions = RecursionFindRight_定水位_指定时间( sumFlowLeft, left_end_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(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,//结束时的水位,本次迭代开始时水位 int lastSwitchCount, int lastOpenPumpCount, int startTimeIndx) { if (lastSwitchCount > this.MaxPumpSwitchCount) {//不能再切换泵了:基本上不会出现,进入前已判断 return null; } if (lastTotalFlow > this._flowInTotalFlow) {//已达到流量:基本上不会出现,进入前已判断 return null; } if (!_timeList[startTimeIndx].IsSwitchPumpAble) return null; // //int flowKey = 0; //if (lastTotalFlow > 0) //{ // flowKey = (int)(lastTotalFlow / 2000); //} //if (startTimeIndx > this._maxReservoirTimeIndex) //{ // 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; // } // } //} 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._flowInTotalFlow && sumCompareWhole < current_best_solution.TotalCompare) { //左侧结束时的水位 var left_end_level = CalcReservoirHeight( startTimeIndx, _timeDataListCount - 1, sumFlowWhole, lastReservoirHeight); if (!this.CheckMaxLevel(startTimeIndx, lastReservoirHeight, _timeDataListCount - 1, 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); if (!CheckMaxLevel(startTimeIndx, lastReservoirHeight, splitIndx, left_end_level)) {//检查水位 continue; } //右侧继续迭代 BlockItemList right_solutions = RecursionFindRight_定水位_指定时间( lastTotalFlow, left_end_level, lastSwitchCount + 1, 0, splitIndx); if (right_solutions == null || right_solutions.TotalCompare == double.MaxValue || right_solutions.Items == null) {//没有找到合适的 continue; } if (current_best_solution.TotalCompare > right_solutions.TotalCompare) { if(startTimeIndx < _maxReservoirTimeIndex) {//检查水位 if (right_solutions.Items.Last().EndIndx < this._maxReservoirTimeIndex) {//如果还未达到指定时间,还需检查指定时间的水位 var finish_level = CalcReservoirHeight( right_solutions.Items.Last().EndIndx, _timeDataListCount - 1, 0, right_solutions.Items.Last().ReservoirEndHeight); if (!CheckMaxLevel(right_solutions.Items.Last().EndIndx, right_solutions.Items.Last().ReservoirEndHeight, _timeDataListCount - 1, finish_level)) { continue; } } else { if (!this.CheckMaxLevel(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._flowInTotalFlow) {//左侧已经能达到要求了 if (current_best_solution.TotalCompare > left_sumCompareLeft) { //左侧结束时的水位(右侧开始时) var left_end_level = CalcReservoirHeight( startTimeIndx, splitIndx, left_sumFlowLeft, lastReservoirHeight); if (startTimeIndx < _maxReservoirTimeIndex) {//检查水位 if (splitIndx < this._maxReservoirTimeIndex) {//如果还未达到指定时间,还需检查指定时间的水位 var finish_level = CalcReservoirHeight( splitIndx, _timeDataListCount - 1, 0, lastReservoirHeight); if (!CheckMaxLevel(splitIndx, left_end_level, _timeDataListCount - 1, finish_level)) { continue; } } else { if (!this.CheckMaxLevel(startTimeIndx, lastReservoirHeight, splitIndx, 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); if (!this.CheckMaxLevel(startTimeIndx, lastReservoirHeight, splitIndx, left_end_level)) { continue; } //右侧继续迭代 BlockItemList right_solutions = RecursionFindRight_定水位_指定时间( total_current_flow, left_end_level, lastSwitchCount + 1, pumpNum_left, splitIndx); if (right_solutions == null || right_solutions.TotalCompare == double.MaxValue || right_solutions.Items == null) {//没有找到合适的 continue; } double cur_sumPower = left_sumCompareLeft + right_solutions.TotalCompare; if (current_best_solution.TotalCompare > cur_sumPower) { if (startTimeIndx < _maxReservoirTimeIndex) {//检查水位 if (right_solutions.Items.Last().EndIndx < this._maxReservoirTimeIndex) {//如果还未达到指定时间,还需检查指定时间的水位 var finish_level = CalcReservoirHeight( right_solutions.Items.Last().EndIndx, _timeDataListCount - 1, 0, right_solutions.Items.Last().ReservoirEndHeight); if (!CheckMaxLevel(right_solutions.Items.Last().EndIndx, right_solutions.Items.Last().ReservoirEndHeight, _timeDataListCount - 1, finish_level)) { continue; } } else { if (!this.CheckMaxLevel(right_solutions.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; } } } }