主要内容

基于问题的发电机优化调度

这个例子展示了如何优化调度两台燃气发电机,这意味着获得最大的收入减去成本。虽然这个例子并不完全现实,但它展示了如何考虑取决于决策时间的成本。

有关此问题的基于解算器的方法,请参见基于求解器的发电机优化调度

问题定义

电力市场在一天中的不同时间有不同的价格。如果您有发电机供电,您可以通过安排发电机在价格较高时运行来利用此可变价格。假设您控制两台发电机。每台发电机有三个功率级别(关、低和高).每台发电机在每个功率水平下都有指定的燃油消耗率和功率产生率。当发电机关闭时,燃油消耗率为0。

您可以为每台发电机在一天中的每半小时时间间隔(24小时,所以48个时间间隔)分配一个功率级别。根据历史记录,假设您知道您在每个时间间隔收到的每兆瓦时(MWh)收入。本例中的数据来自澳大利亚能源市场运营商https://www.nemweb.com.au/REPORTS/CURRENT/在2013年年中,并且在他们的条款下使用https://www。aemo。com。非盟/隐私和法律公告/版权许可

负载调度价格;% Get poolPrice,这是每MWh的收入栏(poolPrice。5)xlim([5, 48.5])包含(“每个时期每兆瓦时的价格”)

图中包含一个axes对象。axes对象包含一个bar类型的对象。

在发电机关闭后启动发电机是有成本的。此外,对一天的最大燃料使用量也有限制。这种限制的存在是因为你提前一天购买了燃料,所以你只能使用刚刚购买的燃料。

问题符号和参数

您可以将调度问题表述为二进制整数规划问题。定义索引,J,K,以及二进制调度向量Y,详情如下:

  • n周期=时间段的数量,在本例中为48。

  • = a time period, 1 <=<= 48.

  • J=生成器索引,1<=J本例中<= 2。

  • y(i,j,k)=1当时间、发电机J正在以功率级别运行K.让低功耗成为可能k = 1,以及高功率bek = 2.发电机在以下情况下关闭:Sum_k y(i,j,k) = 0

确定发电机关闭后何时启动。为此,请定义辅助二进制变量z(i,j)指示是否充电以打开发电机J在时期

  • z (i, j) = 1当发电机J他在周末休息,但在期间是开着的i+1z (i, j) = 0否则,换句话说,,z (i, j) = 1什么时候Sum_k y(i,j,k) = 0求和y(i+1,j,k)=1

你需要一种设置方法Z自动根据的设置Y.下面的线性约束处理这个设置。

您还需要问题的参数,包括成本、每个发电机的发电水平、发电机的消耗水平和可用燃料。

  • poolPrice(我)—以美元/兆瓦时为单位的收入

  • 总务(j,k)--发电机产生的兆瓦J在功率级K

  • 燃料(j,k)--发电机使用的燃料J在功率级K

  • totalFuel--一天内可用的燃料

  • startCost——发电机关闭后启动的美元成本

  • fuelPrice--单位燃料的成本

你有普尔普莱斯当你执行死刑的时候负荷调度价格;.其他参数如下所示。

fuelPrice = 3;totalFuel = 3.95 e4;nPeriods =长度(poolPrice);% 48期nGens=2;%两个发电机创= (61152;50150);%1号发电机低=61 MW,高=152 MW燃料= (427806;325765);%发电机2的燃油消耗量低=325,高=765startCost=1e4;%发电机关闭后启动的成本

发电机效率

检查两台发电机在两个工作点的效率。

效率= /燃料将军;计算单位燃料耗电量rr=效率';%的策划h =酒吧(rr);h(1)。FaceColor =“g”;h(2)。脸颜色=“c”;图例(h,发电机1的,《发电机2》,“位置”,“东北外”) ax = gca;斧子。XTick = [1, 2];斧子。XTickLabel = {“低”,“高”}; ylim([1,.2])ylabel(“效率”)

图中包含一个Axis对象。Axis对象包含2个bar类型的对象。这些对象表示Generator 1和Generator 2。

请注意,发电机2在其相应工作点(低和高)的效率略高于发电机1,但发电机1在其高工作点的效率高于发电机2在其低工作点的效率。

求解变量

要设置问题,需要以问题形式对所有问题数据和约束进行编码。变量y(i,j,k)表示问题的解决方案和辅助变量z(i,j)指示是否为打开发电机充电。Y是一个nPeriods-by-nGens-by-2数组,并Z是一个nPeriods by Ngenes数组中。所有变量都是二进制的。

y=最优值(“是的”,n周期,n周期{“低”,“高”},“类型”,“整数”,下界的,0,...“上限”1);z = optimvar (“z”,n周期,n周期,“类型”,“整数”,下界的,0,...“上限”1);

线性约束

若要确保功率级别不超过一个等于1的分量,请设置线性不等式约束。

powercons=y(:,:,“低”)+y(:,:,“高”) < = 1;

每个时期的运行成本是该时期的燃料成本。为发电机J水平运行K,成本是燃料价格*燃料(j,k)

创建表达式fuelUsed这是所有燃料消耗的原因。

yFuel=0(n周期,nGens,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(sum(sum(y.*yFuel));

限制条件是使用的燃油不超过可用燃油。

fuelcons=已用燃料<=总燃料;

设置发电机启动指示器变量

如何让解算器设置Z自动设置变量,以匹配系统的激活/关闭周期Y变量?回想一下,要满足的条件是z (i, j) = 1确切时间Sum_k y(i,j,k) = 0求和y(i+1,j,k)=1

请注意,求和k(-y(i,j,k)+y(i+1,j,k))>0正好在你想要的时候z (i, j) = 1

因此,在问题公式中包含这些线性不等式约束。

求和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=最优表达式(n周期,n个周期);%分配widx=1:(n周期-1);w(idx,:)=y(idx+1,:,“低”)-y(idx,:,“低”)+y(idx+1,:,“高”)-y(idx,:,“高”); w(n周期,:)=y(1,:,“低”)-y(n周期,:,“低”)+y(1,:,“高”)-y(n周期,:,“高”);Switchcons = w - z <= 0;

定义目标

目标函数包括运行发电机的燃料成本,运行发电机的收入,以及启动发电机的成本。

发电机电平=零(大小(yFuel));发电机级(:,1,1)=发电机(1,1);%填表发电机级(:,1,2)=发电机(1,2);发电机级(:,2,1)=发电机(2,1);发电机级(:,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;

利润=收入-燃料总成本-启动成本。

利润=总和(总和(总和(收入)))-燃料成本-总和(总和(启动成本));

解决问题

创建一个优化问题,包括目标和约束。

调度= optimproblem (“ObjectiveSense”,“最大化”); 目标=利润;dispatch.Constraints.switchcons=开关cons;dispatch.Constraints.fuelcons=fuelcons;dispatch.Constraints.powercons=powercons;

要节省空间,请抑制迭代显示。

选项=最佳选项(“intlinprog”,“显示”,“决赛”);

解决问题。

[dispatchsol, fval exitflag、输出]=解决(调度,“选项”,选项);
使用intlinprog解决问题。找到最优解。Intlinprog停止是因为客观值在最优值选项的间隙公差范围内。AbsoluteGapTolerance = 0(默认值)。intcon变量是在公差选项内的整数。IntegerTolerance = 1e-05(默认值)。

检查解决方案

将解决方案绘制为时间的函数。

子地块(3,1,1)bar(发货单y(:,1,1)*gen(1,1)+发货单y(:,1,2)*gen(1,2),.5,“g”) xlim ([5, 48.5]) ylabel (“MWh”)头衔(“发电机1最佳计划”,“FontWeight”,“大胆”)子地块(3,1,2)bar(签派Sol.y(:,2,1)*gen(1,1)+签派Sol.y(:,2,2)*gen(1,2),.5,“c”)头衔(“发电机2最佳调度”,“FontWeight”,“大胆”) xlim ([5, 48.5]) ylabel (“MWh”)子地块(3,1,3)bar(poolPrice,.5)xlim([5,48.5])标题(“能源价格”,“FontWeight”,“大胆”)包含(“时间”) ylabel (“$/MWh”)

图中包含3个轴对象。标题为Generator 1 Optimal Schedule的axis对象1包含一个bar类型的对象。标题为Generator 2 Optimal Schedule的axis对象2包含一个bar类型的对象。标题为Energy Price的axis对象3包含一个bar类型的对象。

生成器2比生成器1运行的时间更长,这是您所期望的,因为它更高效。发电机2运行在它的高功率水平时,它是开着的。发电机1主要运行在它的高功率水平,但下降到低功率的一个时间单位。每个发电机每天运行一组连续的周期,因此,每天只产生一次启动成本。

检查Z变量为1表示生成器启动时的周期。

Starttimes = find(round(dispatchsol.z) == 1);%对非整数结果使用舍入[theperiod,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”)子地块(3,1,3)bar(poolPrice,.5)xlim([5,48.5])标题(“能源价格”,“FontWeight”,“大胆”)包含(“时间”) ylabel (“$/MWh”)

图中包含3个轴对象。标题为Generator 1 Optimal Schedule的axis对象1包含一个bar类型的对象。标题为Generator 2 Optimal Schedule的axis对象2包含一个bar类型的对象。标题为Energy Price的axis对象3包含一个bar类型的对象。

Starttimes = find(round(dispatchsolnew.z) == 1);%对非整数结果使用舍入[theperiod,thegenerator]=ind2sub(大小(dispatchsolnew.z),起始时间)
时期=3×122 16 45
thegenerator =3×11 2 2

相关的话题