2.4 集約・複数の添字
コスト定義式
cost = costX[0] * x[0] + costX[1] * x[1];
は,すべての油田について運転コストの和をとるという意味なので,これを一般的に記述すると,以下のようになります.
対応するC++SIMPLEの記述は,以下のようになります.
cost = sum(costX[i] * x[i], i);
sum()
はに対応する関数で,
sum(和をとる式, 添字)
の書式を持ちます.
次にノルマ制約についても,sum()
を適用したいと考えますが,旧記述では,
6 * x[0] + x[1] >= norma["重油"]; 4 * x[0] + 6 * x[1] >= norma["ガス"];
と各油田の生産量が直接数値で記述されているので,一般化できません.そこで,定式化において定数を導入し,制約式を次のように記述します.
制約条件 | |
製品jのノルマ/週の制約式 | |
定数 | |
油田iの製品j生産量/日 | |
製品jのノルマ/週 |
対応するC++SIMPLEの記述は,以下のようになります.
Parameter prodX(name = "油田の生産量", index=(i, j)); sum(prodX[i, j] * x[i], i) >= norma[j];
複数の添字に依存する定数を宣言する際には,index = (i, j, ..)
と指定します.上記sum()
は指定した添字iのみの和をとります.i, jについて和をとる場合は,sum(任意の式, (i, j))
,と記述します.
次に油田の生産量の値を追加した以下のデータファイルを作成します.
"油田運転コスト" = [0] 180 [1] 160; "製品ノルマ" = ["重油"] 12 ["ガス"] 24; "油田の生産量" = [0, "重油"] 6 [1, "重油"] 1 [0, "ガス"] 4 [1, "ガス"] 6 ;
データファイル中の””に囲まれていない,スペース,タブ,改行は無視されます.従って,上記の“油田の生産量”のように,値を複数の行にわたって記述することができます.以上で,変更可能性のある全ての数値データをデータファイルから入力することができました.実行結果は以前と同様になります.
ここまでの変更をまとめて,集合,変数,定数,制約条件,目的関数を分類し整理すると,定式化とC++SIMPLEの記述は次のようになります.
集合 | |
油田集合 | |
製品集合 | |
定数 | |
油田iの運転コスト/日 | |
製品jのノルマ/週 | |
油田iの製品j生産量/日 | |
変数 | |
油田iの運転日数/週 | |
目的関数(最小化) | |
運転コスト/週 | |
制約条件 | |
製品jのノルマ/週の制約式 | |
油田iの週あたりの運転日数制約 |
// 油田集合 Set OilField(name = "油田集合"); Element i(set = OilField); // 製品集合 Set Product(name = "製品集合"); Element j(set = Product); // 油田 i の運転コスト/日 Parameter costX(name = "油田運転コスト", index = i); // 製品 j のノルマ/週 Parameter norma(name = "製品ノルマ", index = j); // 油田 i の製品 j 生産量/日 Parameter prodX(name = "油田の生産量", index = (i, j)); // 油田 i の運転日数/週(変数) Variable x(name="油田の運転日数", index = i); // 運転コスト/週(目的関数) Objective cost(name = "全運転コスト", type = minimize); cost = sum(costX[i] * x[i], i); // 製品 j のノルマ/週の制約式 sum(prodX[i, j] * x[i], i) >= norma[j]; // 油田 i の週当りの運転日数制約 0 <= x[i] <= 5; // 求解 solve(); // 結果出力 x[i].val.print(); cost.val.print();
上に戻る