数理最適化セミナーのご案内

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について電力需要予想$D_{t}$は以下のように与えられているものとします.スポット電力購入コストと発電機導入コストの和を最小化するような,発電機の導入方法およびスポット電力の購入方法を求めてください.

t 1 2 3 4 5 6 7 8 9 10 11 12
$D_{t}$ 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
$D_{t}$ 52 47 40 35 42 50 48 40 30 20 15 12

 この問題の定式化は,以下のようになります.

集合
$Product$ 商品集合
$Dynamo$ 発電機集合
$Time$ 時刻集合
 
定数
$costS_{i}, i \in Product$ 各商品に対する単位時間あたりのコスト
$costP_{j}, j \in Dynamo$ 各発電機に対する導入コスト
$p_{i}, i \in Product$ 各商品の単位時間あたりの出力電力
$q_{j}, j \in Dynamo$ 各発電機の単位時間あたりの出力電力
$D_{t}, t \in Time$ 時刻ごとの電力需要
 
0-1整数変数
$u_{i}^{t}, i \in Product, t \in Time$ 各時刻ごとに各商品について,利用するならば1,利用しないならば0
$x_{j}, j \in Dynamo$ 各発電機に関して,導入するならば1,しないならば0
 
目的関数(最小化)
$\displaystyle \sum_{i, t} costS_i \times u_i^t  + \sum_j costP_j \times x_j$ 総コスト(スポット電力購入コストと発電機導入コストの和)の最小化
 
制約条件
$\displaystyle \sum_i u_i^t  = 1, \forall t \in Time$ 各時刻における商品の使用は1つのみ
$\displaystyle D_t - \sum_i p_i \times u_i^t \le \sum_j q_j \times x_j, \forall t \in Time$ すべての時刻において,購入したスポット電力と自家発電の出力電力の和が電力需要を上回らないといけない

 定式化の結果をC++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);

// すべての時刻において,購入したスポット電力と自家発電の出力電力の和が電力需要を上回らないといけない
D[t] - sum(p[i] * u[i, t], i) <= 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
商品[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

 

 

上に戻る