2.15 設備計画問題
設備計画問題として以下の例題では,電力を購入して生産を行っている工場が,自家発電用の発電機を導入する問題を考えます.
例題
電力を購入して生産を行っているある工場が,自家発電用の発電機の導入を計画しています.ただしその際,購入したスポット電力と自家発電の電力の和が,想定されるすべての時刻で電力需要を上回らなければなりません.なお,購入を想定するスポット電力商品は次の3つとします.スポット電力ですので,時刻毎に購入する商品を変更することが可能です.ただし,各時刻において必ず1つの商品を選択して購入しなければなりません.
商品 | 1 | 2 | 3 |
---|---|---|---|
出力電力(kWh) | 5 | 10 | 20 |
単位時間あたりのコスト | 10 | 20 | 30 |
また,新たに導入する候補となる発電機は,以下の6種類とします.発電機を導入しますと,以下のような定常的な出力が得られるものとします.
発電機 | 1 | 2 | 3 | 4 | 5 | 6 |
---|---|---|---|---|---|---|
出力電力(kWh) | 5 | 6 | 8 | 10 | 15 | 20 |
導入コスト | 100 | 120 | 150 | 160 | 280 | 300 |
時刻t = 1,...,24について電力需要予想は以下のように与えられているものとします.スポット電力購入コストと発電機導入コストの和を最小化するような,発電機の導入方法およびスポット電力の購入方法を求めてください.
t | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 |
---|---|---|---|---|---|---|---|---|---|---|---|---|
10 | 10 | 12 | 12 | 15 | 20 | 30 | 30 | 35 | 40 | 50 | 56 |
t | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 |
---|---|---|---|---|---|---|---|---|---|---|---|---|
52 | 47 | 40 | 35 | 42 | 50 | 48 | 40 | 30 | 20 | 15 | 12 |
この問題の定式化は,以下のようになります.
集合 | |
商品集合 | |
発電機集合 | |
時刻集合 | |
定数 | |
各商品に対する単位時間あたりのコスト | |
各発電機に対する導入コスト | |
各商品の単位時間あたりの出力電力 | |
各発電機の単位時間あたりの出力電力 | |
時刻ごとの電力需要 | |
0-1整数変数 | |
各時刻ごとに各商品について,利用するならば1,利用しないならば0 | |
各発電機に関して,導入するならば1,しないならば0 | |
目的関数(最小化) | |
総コスト(スポット電力購入コストと発電機導入コストの和)の最小化 | |
制約条件 | |
各時刻における商品の使用は1つのみ | |
すべての時刻において,購入したスポット電力と自家発電の出力電力の和が電力需要を上回らないといけない |
定式化のポイントとしましては,すべての時刻における電力の総和と電力需要に関する制約式を,時刻ごとに設けるのでなく,時刻に関するmax関数を用いて表現する点にあります.そのため制約充足問題ソルバwcspを用いて解くべく,SIMPLEでは以下のように記述します.なお,max関数に関しましては,Numerical Optimizer/SIMPLEマニュアルの記述もあわせてご覧ください.
// 商品集合 Set Product; Element i(set=Product); // 時刻集合 Set Time; Element t(set=Time); // 発電機集合 Set Dynamo; Element j(set=Dynamo); // コスト // 各商品に対する単位時間あたりのコスト Parameter costS(name="costS", index=i); // 各発電機に対する導入コスト Parameter costP(name="costP", index=j); // 出力電力 // 各商品の単位時間あたりの出力電力 Parameter p(name="p", index=i); // 各発電機の単位時間あたりの出力電力 Parameter q(name="q", index=j); // 時刻ごとの電力需要 Parameter D(name="D", index=t); // 変数 // 各時間ごとに,どの商品を利用するか IntegerVariable u(name="商品", index=(i,t), type=binary); // どの発電機を導入するか IntegerVariable x(name="発電機", index=j, type=binary); // 目的関数(総コストの最小化) Objective cost(name="総コスト", type=minimize); cost = sum(costS[i]*u[i,t], (i,t)) + sum(costP[j]*x[j], j); // 制約式 // 各時間における商品の使用は 1 つのみ selection(u[i,t], i); // すべての時刻において,購入したスポット電力と自家発電の出力電力の和が // 電力需要を上回らないといけない max(D[t] - sum(p[i]*u[i,t], i), t) <= sum(q[j]*x[j], j); // 最大求解時間の設定 options.maxtim = 5; // 求解 solve(); // 結果の出力 cost.val.print(); x.val.print(); u.val.print();
データファイル(dat形式)は以下のようになります.
costS = [1] 10 [2] 20 [3] 30; costP = [1] 100 [2] 120 [3] 150 [4] 160 [5] 280 [6] 300; p = [1] 5 [2] 10 [3] 20; q = [1] 5 [2] 6 [3] 8 [4] 10 [5] 15 [6] 20; D = [1] 10 [2] 10 [3] 12 [4] 12 [5] 15 [6] 20 [7] 30 [8] 30 [9] 35 [10] 40 [11] 50 [12] 56 [13] 52 [14] 47 [15] 40 [16] 35 [17] 42 [18] 50 [19] 48 [20] 40 [21] 30 [22] 20 [23] 15 [24] 12;
このモデルを実行すると,以下のような解が得られ,発電機の導入方法および電力の購入方法が求まりました.
総コスト=950 発電機[1]=0 発電機[2]=0 発電機[3]=1 発電機[4]=1 発電機[5]=0 発電機[6]=1 ,[*] = [j]
商品[1,1]=1 商品[1,2]=1 商品[1,3]=1 商品[1,4]=1 商品[1,5]=1 商品[1,6]=1 商品[1,7]=1 商品[1,8]=1 商品[1,9]=1 商品[1,10]=1 商品[1,11]=0 商品[1,12]=0 商品[1,13]=0 商品[1,14]=0 商品[1,15]=1 商品[1,16]=1 商品[1,17]=1 商品[1,18]=0 商品[1,19]=0 商品[1,20]=1 商品[1,21]=1 商品[1,22]=1 商品[1,23]=1 商品[1,24]=1
商品[2,1]=0 商品[2,2]=0 商品[2,3]=0 商品[2,4]=0 商品[2,5]=0 商品[2,6]=0 商品[2,7]=0 商品[2,8]=0 商品[2,9]=0 商品[2,10]=0 商品[2,11]=0 商品[2,12]=0 商品[2,13]=0 商品[2,14]=1 商品[2,15]=0 商品[2,16]=0 商品[2,17]=0 商品[2,18]=0 商品[2,19]=1 商品[2,20]=0 商品[2,21]=0 商品[2,22]=0 商品[2,23]=0 商品[2,24]=0
商品[3,1]=0 商品[3,2]=0 商品[3,3]=0 商品[3,4]=0 商品[3,5]=0 商品[3,6]=0 商品[3,7]=0 商品[3,8]=0 商品[3,9]=0 商品[3,10]=0 商品[3,11]=1 商品[3,12]=1 商品[3,13]=1 商品[3,14]=0 商品[3,15]=0 商品[3,16]=0 商品[3,17]=0 商品[3,18]=1 商品[3,19]=0 商品[3,20]=0 商品[3,21]=0 商品[3,22]=0 商品[3,23]=0 商品[3,24]=0 ,[*,*]= [i,t]
上に戻る