
一、算例说明选用教材《水利水电工程优化调度》唐德善 唐彦 黄显峰 史记毅超 等编著中国水利水电出版社上对应P43页-P47页的例题3-3进行代码验证。①具体例题资料②思路说明我们需要关注的信息是1水库的防洪限制水位起调水位对应库容60500(m³/s)·h、防洪高水位对应库容109370(m³/s)·h2百年一遇设计洪水的来水过程3安全泄量为q安2000m³/s4要求以最大削峰为准则针对上述重点信息对例题资料做如下处理1动态规划一般逆时序从后往前推所以将109370作为起点将60500作为终点2根据图3-6的示意图可以看出要将相应时刻来水流量转化为时段平均来水流量3安全泄量是每个阶段下泄流量的要求要保证下泄流量数值在2000附近4最大削峰准则的目标函数为下泄流量的平方和最小对应公式3-36结合各种约束条件以及不计区间来水的假定建立逆时序递推方程对应公式3-37二、代码内容注以下所有代码均按顺序在同一个py文件里方便解释才将其拆开将动态规划阶段按照图3-6分为1阶段4个阶段(t4-t3、t3-t2、t2-t1、t1-t02状态t0、t1、t2、t3、t4时刻对应的库容3决策追求最小累积泄量①将已知数据列出各时段平均来水量以及防洪限制水位起调水位对应库容、防洪高水位对应库容# 各时段来水量come_water_15403come_water_28125come_water_36575come_water_44188# 已知防洪限制水位对应库容/t0对应库容capacity_160500# 已知防洪高水位对应库容/t4对应库容capacity_5109370②t4-t3阶段此阶段为初始阶段起点已知是109370所以只需要一个for循环。for循环表示将t3时刻库容从109370开始遍历至60500步长为-10即逐渐减小。if条件语句是筛选出下泄流量q4与安全泄量2000m³/s的绝对差值在10以内的库容以及对应的累计泄量平方值。# t4-t3-------------------------------------------------# 存储t3时刻库容lst_capacity_4[]# 存储t3-t4累积泄量平方值lst_min_4[]# t3对应库容forcapacity_4inrange(109370,60499,-10):# 平均泄量q4(capacity_4-capacity_5come_water_4*3)/3# 泄量平方值q4_squareq4**2# 余留时期最小泄量平方值初始为0fVi_4_start0# 累计泄量平方值fVi_4_0q4_squarefVi_4_startifabs(q4-2000)10:lst_capacity_4.append(capacity_4)lst_min_4.append(fVi_4_0)③t3-t2阶段这个阶段相对复杂一些因为t4和t3时刻的库容都是变动的所以我们需要进行for循环的嵌套。此外还要对本阶段符合if条件的下泄流量q3、累积下泄流量、t4时刻上一时刻的库容创建3个空列表进行存储方便后续相互利用索引查找。最后还要将符合if条件的t3时刻的库容进行存储并保证其不重复从大到小排列以便于下一阶段的for循环进行遍历。#t3-t2-------------------------------------------------# 存储t2时刻库容lst_capacity_3[]# 存储t2-t3累积泄量平方值lst_min_3[]# 后续会提到以下3个列表的索引值是相同的用于后续相互的查找lstq3[]lst_fVi_3_y[]lst_capacity_4_y[]# t2对应库容forcapacity_3inrange(109370,60499,-10):lst_fVi_3[]forcapacity_4inlst_capacity_4:q3(capacity_3-capacity_4come_water_3*3)/3# 平均泄量q3_squareq3**2# 余留时期最小泄量平方值索引得到相应t3时刻库容capacity_4对应的累计泄量平方值fVi_3_1lst_min_4[lst_capacity_4.index(capacity_4)]# 累计泄量平方值fVi_3_0q3_squarefVi_3_1ifabs(q3-2000)10:# 在临时的泄量储存表里添加与2000相近的平均泄量lstq3.append(q3)# 下面3个列表的索引值是相同的用于后续相互的查找lst_fVi_3.append(fVi_3_0)lst_fVi_3_y.append(fVi_3_0)lst_capacity_4_y.append(capacity_4)#只要lst_fVi_3列表中至少包含一个元素这个条件就为真。# 说明t2时刻库容capacity_3的这个值是有效的。iflen(lst_fVi_3)1:lst_capacity_3.append(capacity_3)# 最小累积泄量平方值# 1、lst_fVi_3# 这是一个列表如果它不为空即至少包含一个元素那么这个条件就为真。# 2、lst_capacity_4.index(capacity_4) len(lst_capacity_4) - 1# 这个条件检查当前遍历的capacity_4是否是lst_capacity_4列表中的最后一个元素。# 如果是那么这个条件就为真。iflst_fVi_3andlst_capacity_4.index(capacity_4)len(lst_capacity_4)-1:lst_min_3.append(min(lst_fVi_3))# 保证不重复# 首先set(lst_capacity_3)会将lst_capacity_3列表转换为一个集合。# 在Python中集合是一个无序的、不包含重复元素的数据结构。# 因此转换为集合的过程会自动去除列表中的重复元素。# 然后list(set(lst_capacity_3))会将这个集合再转换回列表。# 这样得到的lst_capacity_3列表就不包含任何重复的元素了。lst_capacity_3list(set(lst_capacity_3))# 回到原来的降序排序lst_capacity_3.sort(reverseTrue)④t2-t1阶段此阶段和上阶段基本一样参考上阶段的解释以及代码注释即可。# t2-t1-------------------------------------------------# 存储t1时刻库容lst_capacity_2[]# 存储t1-t2累积泄量平方值lst_min_2[]# 后续会提到以下3个列表的索引值是相同的用于后续相互的查找lstq2[]lst_fVi_2_y[]lst_capacity_3_y[]# t1对应库容forcapacity_2inrange(109370,60499,-10):lst_fVi_2[]forcapacity_3inlst_capacity_3:q2(capacity_2-capacity_3come_water_2*3)/3q2_squareq2**2# 余留时期最小泄量平方值fVi_2_1lst_min_3[lst_capacity_3.index(capacity_3)]# 累计泄量平方值fVi_2_0q2_squarefVi_2_1ifabs(q2-2000)10:# 在临时的泄量储存表里添加与2000相近的平均泄量lst_fVi_2.append(fVi_2_0)# 以下3个列表的索引值是相同的用于后续相互的查找lstq2.append(q2)lst_fVi_2_y.append(fVi_2_0)lst_capacity_3_y.append(capacity_3)iflen(lst_fVi_2)1:lst_capacity_2.append(capacity_2)# 最小累积泄量平方值iflst_fVi_2andlst_capacity_3.index(capacity_3)len(lst_capacity_3)-1:lst_min_2.append(min(lst_fVi_2))# 保证不重复lst_capacity_2list(set(lst_capacity_2))# 回到原来的降序排序lst_capacity_2.sort(reverseTrue)⑤t1-t0阶段这是最后一个阶段了相比于前两个阶段该阶段的终点是60500所以代码的处理也相对简单一些。# t1-t0-------------------------------------------------lst_capacity_1[]lst_fVi_1[]lstq1[]# t0对应库容capacity_160500forcapacity_2inlst_capacity_2:q1(capacity_1-capacity_2come_water_1*3)/3# 最大削峰# 平均泄量q1_squareq1**2# 余留时期最小泄量平方值fVi_1_1lst_min_2[lst_capacity_2.index(capacity_2)]# 累计泄量平方值fVi_1_0q1_squarefVi_1_1 lstq1.append(q1)lst_fVi_1.append(fVi_1_0)# 最小累积泄量平方值min_fVi_1_0min(lst_fVi_1)最后输出的便是最小的累积泄量平方值。⑥对变量整合、输出最优下泄方案这一部分比较难以相同的是如何获取最优调度方案对应的各时刻库容、各阶段下泄流量、各阶段累积泄量这就需要利用先前创建的列表进行索引来相互寻找来获取# t0时库容capacity_160500# t1时库容capacity_2lst_capacity_2[lst_fVi_1.index(min_fVi_1_0)]# t0-t1平均泄量q_1lstq1[lst_capacity_2.index(capacity_2)]# t2时库容min_fvi2lst_min_2[lst_capacity_2.index(capacity_2)]capacity_3lst_capacity_3_y[lst_fVi_2_y.index(min_fvi2)]# t1-t2平均泄量q_2lstq2[lst_fVi_2_y.index(min_fvi2)]# t3时库容min_fvi3lst_min_3[lst_capacity_3.index(capacity_3)]capacity_4lst_capacity_4_y[lst_fVi_3_y.index(min_fvi3)]# t2-t3平均泄量q_3lstq3[lst_fVi_3_y.index(min_fvi3)]# t4时库容min_fvi4lst_min_4[lst_capacity_4.index(capacity_4)]capacity_5109370# t3-t4平均泄量q_4(capacity_4-109370come_water_4*3)/3print(t0时库容,capacity_1)print(t0-t1时段平均泄量,q_1)print(t1时库容,capacity_2)print(t0-t1最小累积泄量平方值:,min_fVi_1_0)print(t1-t2时段平均泄量,q_2)print(t2时库容,capacity_3)print(t1-t2累计最小泄量平方值,min_fvi2)print(t2-t3时段平均泄量,q_3)print(t3时库容,capacity_4)print(t2-t3累计最小泄量平方值,min_fvi3)print(t3-t4时段平均泄量,q_4)print(t4时库容,capacity_5)print(t3-t4累计最小泄量平方值,min_fvi4)print(最小累积泄量平方值:,min_fVi_1_0)输出结果如下三、与案例进行结果对比教材给出的过程及结果如下通过对比发现Python代码结果对应最小累积泄量为16004007教材案例所给结果为16000018且各阶段的下泄流量方案也有略微的差别。这是因为教材为了便于读者理解和练习将下泄流量q进行了四舍五入的简化这样导致了细微的差别演算到最后也会有略微的差别。本篇博客旨在帮助大家理解练习动态规划在水库调度中的应用在实际的水库调度案例中将会有更为复杂的状况实际的调度常是水库群的联合调度且在考虑防洪的前提下还要尽可能的兴利。以上是全部内容欢迎大家评论区留言批评指正。