此示例显示如何最佳地安排两个燃气发电机,这意味着获得最多的收入减去费用。虽然该示例并不完全逼真,但它确实展示了如何考虑到依赖决策时间的成本。
对于基于求解器的方法,请参阅电力发电机最佳调度:基于求解器.
电力市场在一天中的不同时段有不同的价格。如果你有发电机供应电力,你可以通过安排发电机在价格高的时候运行来利用这种可变定价。假设你控制了两个发电机。每台发电机有三个功率等级(关、低、高)。每台发电机在每个功率级别上都有指定的燃料消耗和功率生产速率。发电机关闭时燃油消耗量为0。
您可以在一天内为每个半小时时间间隔分配给每个发电机的功率电平(24小时,所以48间隔)。根据历史记录,假设您知道每次间隔中收到的每兆瓦的收入(MWH)。此示例的数据来自澳大利亚能源市场运营商https://www.nemweb.com.au/reports/current/
在2013年中期,并在其条款下使用https: /
/
万维网。
AEMO。
com。
au /
privacy-and-legal-notices /
copyright-permissions
.
加载调解;%get poolprice,这是每兆瓦的收入Bar(PoolPrice,.5)XLIM([。5,48.5])Xlabel('每个时期每兆瓦的价格')
在关闭之后开始发电机的成本是成本。此外,存在对当天的最大燃料使用量的约束。这种约束存在,因为您提前每天购买燃料,所以您只能使用您刚刚购买的内容。
您可以将调度问题作为二进制整数编程问题。定义索引一世
那j
, 和K.
,以及二进制调度向量y
, 如下:
nPeriods
在这种情况下,48的时间段数。
一世
=时间段,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
在某段时间关闭一世
,但在时期I + 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(i)
- 间隔每兆瓦的收入一世
Gen(j,k)
——发电机产生的兆瓦j
在权力水平K.
燃料(j, k)
——发电机使用的燃料j
在权力水平K.
完全税
- 一天内提供燃料
startcost.
- 在它已关闭之后开启发电机的美元成本
花费
- 燃料单位的成本
你有poolPrice
当你执行时LOAD DISPACTPRICE;
.设置如下其他参数。
forprice = 3;totalfuel = 3.95e4;nperiods =长度(poolprice);%48个时期ngens = 2;%两个发电机Gen = [61,152; 50,150];%发电机1低= 61 MW,高= 152 MW燃料= [427,806; 325,765];发电机2的%燃料消耗低= 325,高= 765startcost = 1E4;在它已关闭后启动发电机的%成本
检查两台发电机在两个工作点的效率。
效率= gen./fuel;%计算每单位燃料使用电力rr =效率';策划的百分比h =酒吧(rr);h(1)。FaceColor =‘g’;H(2).facecolor ='C';传奇(h,'发电机1'那'发电机2'那'地点'那“东北朝”斧头= GCA;ax.xtick = [1,2];ax.xticklabel = {'低的'那'高的'};ylim ([1, 2]) ylabel (“效率”)
请注意,发电机2在其相应的操作点(低和高)处比发生器1更有效,但在其高工作点处的发生器1比在其低操作点处更有效。
要设置问题,您需要在问题表单中编码所有问题数据和约束。变量y (i, j, k)
表示问题的解,以及辅助变量z (i, j)
表示是否充电以打开发电机。y
是一个nperiods-by-ngens-by-2
阵列和Z.
是一个nPeriods-by-nGens
大批。所有变量都是二进制的。
y = optimvar ('是'nPeriods ngen, {'低的'那'高的'},“类型”那“整数”那'indowbound'0,......'上行',1);z = Optimvar('z'nPeriods ngen,“类型”那“整数”那'indowbound'0,......'上行',1);
为保证功率级不超过一个分量等于1,设置线性不等式约束。
powercons = y(:,:,'低的')+ y(:,:,'高的')<= 1;
每个时期的运行成本是该期间的燃料成本。对于发电机j
在级别运营K.
,成本是Forclice *燃料(J,K)
.
创建一个表达式燃料
占据所有燃料的账户。
yfuel = zeros(nperiods,ngens,2);yfuel(:,1,1)=燃料(1,1);%燃料在低设置中使用发电机1yFuel(:, 1, 2) =燃料(1、2);%发电机1在高设定时的燃料消耗量yFuel(: 2 1) =燃料(2,1);%燃料在低设置中使用发电机2yfuel(:,2,2)=燃料(2,2);%发电机2在高设定时的燃料消耗量燃料=总和(总和(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,ngens);%分配W.Idx = 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 =零(尺寸(yfuel));generatorlevel(:,1,1)= gen(1,1);%填写水平GeneratorLevel(:,1,2)= Gen(1,2);GeneratorLevel(:,2,1)= Gen(2,1);GeneratorLevel(:,2,2)= Gen(2,2);
收入= y* generatorlevel。* poolPrice
.
收入= Optimexpr(大小(y));为了II = 1:nperiods收入(ii,:,:) = poolprice(ii)* y(ii,:,:)。* generatorlevel(ii,:,:);结尾
总燃料成本=燃料*燃料
.
Fuelcost =燃料*燃料;
发电机启动成本=z * startcost.
.
hivechcost = z * startcost;
利润=来收入-
总燃料成本-
启动成本。
利润=总和(总和(收入))) - 燃料 - 总和(总和(起跑));
创建一个优化问题,包括目标和约束条件。
dispatch = OptimProblem('ObjectiveSense'那“最大化”);dispatch.objective =利润;dispatch.Constraints.switchcons = switchcons;dispatch.Constraints.fuelcons = fuelcons;dispatch.Constraints.powercons = powercons;
为了节省空间,禁止重复显示。
选择= optimoptions ('intlinprog'那“显示”那“最后一次”);
解决这个问题。
[Dispatchsol,Fval,ExitFlag,输出] =求解(调度,“选项”、选择);
使用intlinprog解决问题。找到最佳解决方案。intlinprog由于客观值在最佳值的差距容忍范围内,Options.AbsolutegAppolerance = 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')子图(3,1,3)栏(PoolPrice,.5)XLIM([5,48.5])标题(能源价格的那'fontweight'那'胆大')Xlabel('时期')ylabel('$ / mwh')
生成器2比生成器1长时间运行,您可以期待,因为它更有效。生成器2在其上时在其高功率级别运行。发电机1主要以其高功率电平运行,但为一个时间单位倾斜至低功耗。每个生成器每天运行一个连续的周期,因此,每天只引发一个启动成本。
检查这一点Z.
变量为1表示生成器启动时的周期。
starttimes = find(round(dispatchsol.z)== 1);%对非整数结果使用圆形结果[Period,TheGeNerator] = Ind2Sub(大小(Dispatchsol.z),starttifs)
年度变化平均数低于=2×123 16.
thegenerator =2×11 2
发电机开始匹配绘图时的时期。
如果指定较低的值startcost.
,该解决方案涉及多个生成期。
startcost = 500;%选择用于启动发电机的较低罚款hivechcost = z * startcost;利润=总和(总和(收入))) - 燃料 - 总和(总和(起跑));dispatch.objective =利润;[Dispatchsolnew,Fvalnew,ExitFlagnew,OutputNew] =解决(调度,“选项”、选择);
使用intlinprog解决问题。找到最佳解决方案。intlinprog由于客观值在最佳值的差距容忍范围内,Options.AbsolutegAppolerance = 0(默认值)。INTCON变量在容差,选项中是整数.inteGertolerance = 1E-05(默认值)。
子图(3,1,1)栏(Dispatchsolnew.y(:,1,1)* Gen(1,1)+ DispatchsolNew.y(:,1,2)* Gen(1,2),5,‘g’)XLIM([5,48.5])Ylabel('MWH')标题('发电机1最佳时间表'那'fontweight'那'胆大')子图(3,1,2)栏(Dispatchsolnew.y(:,2,1)* Gen(1,1)+ Dispatchsolnew.y(:,2,2)* Gen(1,2),.5,'C')标题('发电机2最佳时间表'那'fontweight'那'胆大')XLIM([5,48.5])Ylabel('MWH')子图(3,1,3)栏(PoolPrice,.5)XLIM([5,48.5])标题(能源价格的那'fontweight'那'胆大')Xlabel('时期')ylabel('$ / mwh')
starttimes = find(round(dispatchsolnew.z)== 1);%对非整数结果使用圆形结果(年度变化平均数低于thegenerator] = ind2sub(大小(dispatchsolnew.z),开始时间)
年度变化平均数低于=3×122 16 45.
thegenerator =3×11 2 2