这个例子展示了如何安排两个燃气发电机的最佳,意思是获得最大的收入减去成本。虽然这个例子并不完全现实,但它确实说明了如何考虑依赖于决策时机的成本。
关于这个问题的基于求解器的方法,请参见基于求解器的发电机优化调度.
电力市场在一天中的不同时段有不同的价格。如果你有发电机供应电力,你可以通过安排发电机在价格高的时候运行来利用这种可变定价。假设你控制了两个发电机。每台发电机有三个功率等级(关、低、高)。每台发电机在每个功率级别上都有指定的燃料消耗和功率生产速率。发电机关闭时燃油消耗量为0。
你可以为一天中每半小时的时间间隔(24小时,也就是48个间隔)分配一个功率级别给每个发电机。根据历史记录,假设您知道在每个时间间隔中获得的每兆瓦时(MWh)收益。本例的数据来自澳大利亚能源市场运营商https://www.nemweb.com.au/REPORTS/CURRENT/
在2013年年中,并且在他们的条款下使用https: /
/
www。
aemo。
com。
非盟/
privacy-and-legal-notices /
copyright-permissions
.
负载dispatchPrice;% Get poolPrice,这是每MWh的收入栏(poolPrice。5)xlim([5, 48.5])包含(“每个时期每兆瓦时的价格”)
发电机关闭后再启动是要花钱的。此外,一天的最大燃料使用量也有限制。这个限制的存在是因为你提前一天购买燃料,所以你只能使用你刚买的燃料。
你可以将调度问题表述为二进制整数规划问题。定义索引我
,j
,k
,一个二进制调度向量y
,如下所示:
nPeriods
=时间段的数量,在本例中为48。
我
= a time period, 1 <=我
< = 48。
j
=生成器索引,1 <=j
本例中<= 2。
y (i, j, k) = 1
当时间我
、发电机j
是否在功率水平运行k
.让低权力存在k = 1
和高的力量是k = 2
.当发电机关闭时Sum_k y(i,j,k) = 0
.
确定发电机在关闭后何时启动。为此,定义辅助二进制变量z (i, j)
指示是否为开启发电机充电j
在期我
.
z (i, j) = 1
当发电机j
在某段时间关闭我
,但在期间是开着的我+ 1
.z (i, j) = 0
否则。换句话说,z (i, j) = 1
当Sum_k y(i,j,k) = 0
和Sum_k y(i+1,j,k) = 1
.
你需要一种设置方法z
自动根据的设置y
.下面的线性约束处理这个设置。
您还需要成本、每个发电机的发电水平、发电机的消耗水平和可用燃料的问题参数。
poolPrice(我)
—以美元/兆瓦时为单位的收入我
创(j, k)
——发电机产生的兆瓦j
在功率k
燃料(j, k)
——发电机使用的燃料j
在功率k
totalFuel
——一天可用的燃料
startCost
——发电机关闭后启动的美元成本
fuelPrice
——单位燃料的成本
你有poolPrice
当你执行加载dispatchPrice;
.其他参数如下所示。
fuelPrice = 3;totalFuel = 3.95 e4;nPeriods =长度(poolPrice);% 48期ngen = 2;%两个发电机创= (61152;50150);%发电机1低= 61 MW,高= 152 MW燃料= (427806;325765);%发电机2的燃料消耗低= 325,高= 765startCost = 1 e4;%发电机关闭后启动的成本
检查两台发电机在两个工作点的效率。
效率= /燃料将军;计算单位燃料耗电量rr =效率”;%的策划h =酒吧(rr);h(1)。FaceColor =‘g’;h(2)。FaceColor =“c”;传奇(h,发电机1的,《发电机2》,“位置”,“NorthEastOutside”) ax = gca;斧子。XTick = [1, 2];斧子。XTickLabel = {“低”,“高”};ylim ([1, 2]) ylabel (“效率”)
注意,发电机2在其相应的运行点(低和高)比发电机1更有效率,但发电机1在高运行点比发电机2在低运行点更有效率。
为了设置问题,您需要将所有问题数据和约束以问题形式编码。的变量y (i, j, k)
表示问题的解,以及辅助变量z (i, j)
指示是否为开启发电机充电。y
是一个nPeriods-by-nGens-by-2
数组,并z
是一个nPeriods-by-nGens
数组中。所有变量都是二进制的。
y = optimvar (“y”nPeriods ngen, {“低”,“高”},“类型”,“整数”,下界的,0,...“UpperBound”1);z = optimvar (“z”nPeriods ngen,“类型”,“整数”,下界的,0,...“UpperBound”1);
为保证功率级不超过一个分量等于1,设置线性不等式约束。
powercons = y (:,:“低”) + y (:,:“高”) < = 1;
每个时期的运行成本是该时期的燃料成本。为发电机j
操作的级别k
,成本是fuelPrice *燃料(j, k)
.
创建一个表达式fuelUsed
这就是所有燃料的消耗。
yFuel = 0 (nPeriods ngen 2);yFuel(:, - 1, - 1) =燃料(1,1);%发电机1在低设定时的燃料消耗量yFuel(:, 1, 2) =燃料(1、2);%发电机1在高设定时的燃料消耗量yFuel(: 2 1) =燃料(2,1);%发电机2在低设定时的燃料消耗量yFuel(: 2 2) =燃料(2,2);%发电机2在高设定时的燃料消耗量fuelUsed =总和(总和(sum (y。* yFuel)));
限制条件是所使用的燃料不能超过可用的燃料。
fuelcons = fuelUsed <= totalFuel;
如何让解算器设置z
变量自动匹配的活动/关闭周期y
变量?回想一下,要满足的条件是z (i, j) = 1
什么时候Sum_k y(i,j,k) = 0
和Sum_k y(i+1,j,k) = 1
.
请注意,Sum_k (- y(i,j,k) + y(i+1,j,k)) > 0
正好在你想要的时候z (i, j) = 1
.
因此,在问题的表述中包含这些线性不等式约束。
Sum_k (- y(i,j,k) + y(i+1,j,k)) - z(i,j) < = 0
.
此外,包括z
变量中的目标函数是成本。与z
目标函数中的变量,解算器试图降低它们的值,这意味着它试图将它们都设为0。但是对于这些时间间隔,当发电机启动时,线性不等式起作用z (i, j)
等于1。
创建一个辅助变量w
代表y (i + 1 j k) - y (i, j, k)
.表示发电机启动不平等w
.
w = optimexpr (nPeriods ngen);%分配widx = 1:(nPeriods-1);w (idx:) = y (idx + 1:“低”) - y (idx:,“低”) + y (idx + 1:“高”) - y (idx:,“高”);w (nPeriods:) = y (1:“低”) - y (nPeriods:,“低”) + y (1:“高”) - y (nPeriods:,“高”);Switchcons = w - z <= 0;
目标函数包括运行发电机的燃料成本,运行发电机的收入,以及启动发电机的成本。
generatorlevel = 0(大小(yFuel));generatorlevel(:, - 1, - 1) =创(1,1);%填写等级generatorlevel(:, 1, 2) =创(1、2);generatorlevel(: 2 1) =创(2,1);generatorlevel(: 2 2) =创(2,2);
收入= y* generatorlevel。* poolPrice
.
收入= optimexpr(大小(y));为2 = 1: nPeriods收入(ii):,:) = poolPrice (ii) * y (ii):,:)。* generatorlevel (ii):,:);结束
总燃料成本=fuelUsed * fuelPrice
.
fuelCost = fuelUsed * fuelPrice;
发电机启动费用=z * startCost
.
startingCost z = * startCost;
利润=收入-
燃料总成本-
启动成本。
利润= sum(sum(sum(revenue)) - fuelCost - sum(sum(startingCost));
创建一个优化问题,包括目标和约束条件。
调度= optimproblem (“ObjectiveSense”,“最大化”);调度。目标=利润;dispatch.Constraints.switchcons = switchcons;dispatch.Constraints.fuelcons = fuelcons;dispatch.Constraints.powercons = powercons;
为了节省空间,禁止重复显示。
选择= optimoptions (“intlinprog”,“显示”,“最后一次”);
解决这个问题。
[dispatchsol, fval exitflag、输出]=解决(调度,“选项”、选择);
使用intlinprog解决问题。找到最优解。Intlinprog停止是因为客观值在最优值选项的间隙公差范围内。AbsoluteGapTolerance = 0(默认值)。intcon变量是在公差选项内的整数。IntegerTolerance = 1e-05(默认值)。
画出解作为时间的函数。
次要情节(1,1)栏(dispatchsol.y(:, 1, 1) *创(1,1)+ dispatchsol.y(:, 1, 2) *创(1、2),5,‘g’) xlim ([5, 48.5]) ylabel (“MWh”)标题(“发电机1最佳调度”,“FontWeight”,“大胆”次要情节(3、1、2)酒吧(dispatchsol.y(:, 2, 1) *创(1,1)+ dispatchsol.y(:, 2, 2) *创(1、2),5,“c”)标题(“发电机2最佳调度”,“FontWeight”,“大胆”) xlim ([5, 48.5]) ylabel (“MWh”) subplot(3,1,3) bar(poolPrice,.5) xlim([.5,48.5]) title(能源价格的,“FontWeight”,“大胆”)包含(“时间”) ylabel (“美元/千瓦时”)
生成器2比生成器1运行的时间更长,这是您所期望的,因为它更高效。发电机2运行在它的高功率水平时,它是开着的。发电机1主要运行在它的高功率水平,但下降到低功率的一个时间单位。每个发电机每天运行一组连续的周期,因此,每天只产生一次启动成本。
检查z
变量为1表示生成器启动时的周期。
Starttimes = find(round(dispatchsol.z) == 1);%对于非整数结果使用round(年度变化平均数低于thegenerator] = ind2sub(大小(dispatchsol.z),开始时间)
年度变化平均数低于=2×123日16
thegenerator =2×11 2
生成器开始时的句号与情节相匹配。
如果指定较低的值startCost
,该解决方案涉及多个生成周期。
startCost = 500;选择一个较低的惩罚启动发电机startingCost z = * startCost;利润= sum(sum(sum(revenue)) - fuelCost - sum(sum(startingCost));调度。目标=利润;[dispatchsolnew, fvalnew exitflagnew outputnew] =解决(调度,“选项”、选择);
使用intlinprog解决问题。找到最优解。Intlinprog停止是因为客观值在最优值选项的间隙公差范围内。AbsoluteGapTolerance = 0(默认值)。intcon变量是在公差选项内的整数。IntegerTolerance = 1e-05(默认值)。
次要情节(1,1)栏(dispatchsolnew.y(:, 1, 1) *创(1,1)+ dispatchsolnew.y(:, 1, 2) *创(1、2),5,‘g’) xlim ([5, 48.5]) ylabel (“MWh”)标题(“发电机1最佳调度”,“FontWeight”,“大胆”次要情节(3、1、2)酒吧(dispatchsolnew.y(:, 2, 1) *创(1,1)+ dispatchsolnew.y(:, 2, 2) *创(1、2),5,“c”)标题(“发电机2最佳调度”,“FontWeight”,“大胆”) xlim ([5, 48.5]) ylabel (“MWh”) subplot(3,1,3) bar(poolPrice,.5) xlim([.5,48.5]) title(能源价格的,“FontWeight”,“大胆”)包含(“时间”) ylabel (“美元/千瓦时”)
Starttimes = find(round(dispatchsolnew.z) == 1);%对于非整数结果使用round(年度变化平均数低于thegenerator] = ind2sub(大小(dispatchsolnew.z),开始时间)
年度变化平均数低于=3×122日16 45
thegenerator =3×11 2 2