最適化セミナーのご案内

2.1 目的関数・変数・制約

 次のような生産計画問題を考えます.

 2つの油田X, Yが存在し,それぞれ一日あたり重油・ガスを次の量だけ生産する.

生産量/日
  重油 ガス
X 6t 4t
Y 1t 6t

 

 また,重油・ガスの週あたりの生産ノルマが,次のように定められている.

  ノルマ/週
重油 12t
ガス 24t

 

 油田X, Yの日あたりの運転コストは,次のとおりである.

  運転コスト/日
X 180
Y 160

 

 油田X, Yともに,最大で週5日まで運転可能である.ノルマを満たしながら運転コストを最小化するためには,それぞれの油田を週あたり何日運転すれば良いだろうか?

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

変数
$x$ 油田Xの運転日数/週
$y$ 油田Yの運転日数/週
 
目的関数(最小化)
$180x+160y$ 運転コスト/週
 
制約条件
$6x + y \geq 12$ 重油ノルマ/週
$4x + 6y \geq 24$ ガスノルマ/週
$0 \leq x \leq 5$ 油田Xの週あたりの運転日数制約
$0 \leq y \leq 5$ 油田Yの週あたりの運転日数制約

 それでは,この問題をSIMPLEで記述した例を見てみましょう.

// 油田X,Yの運転日数/週(変数)
Variable x(name="油田Xの運転日数");
Variable y(name="油田Yの運転日数");

// 運転コスト(目的関数)
Objective cost(name="全運転コスト", type=minimize);
cost = 180*x + 160*y;

// 製品ノルマ
6*x + y >= 12;     // 重油ノルマ/週
4*x + 6*y >= 24;   // ガスノルマ/週

// 各油田の日数制約
0 <= x <= 5;       // 油田Xの週あたりの運転日数制約
0 <= y <= 5;       // 油田Yの週あたりの運転日数制約

// 求解
solve();

// 結果出力
x.val.print();
y.val.print();
cost.val.print();

 このSIMPLEによる記述を上から順に見ていきましょう.

// 油田X,Yの運転日数/週(変数)
Variable x(name="油田Xの運転日数");
Variable y(name="油田Yの運転日数");

 この部分は変数(油田の運転日数)の宣言です.モデル中で使用する変数は,使用する前に宣言する必要があります.name="..."の部分には変数の名前を指定します.name="..."は省略可能ですが,出力などで使用されますので,なるべく記述した方が良いでしょう.

 "//"から行の終わりまではコメントです.

// 運転コスト(目的関数)
Objective cost(name="全運転コスト", type=minimize);

 この部分は目的関数(運転コスト)の宣言です.目的関数の内容を定義する前に,宣言する必要があります.name="..."の部分には目的関数の名前を指定します.変数の宣言同様,name="..."は省略可能ですが,出力などに利用されますので,なるべく記述した方が良いでしょう.type=minimizeで目的関数が最小化されるべきことを指示します.type=maximizeとすれば,目的関数を最大化します.

cost = 180*x + 160*y;

 この部分は目的関数(運転コスト)の内容定義です.=の左辺に目的関数を,右辺に目的関数の内容を記述します.*は積,+は和を表す演算子です.SIMPLEでは四則演算や初等関数(exp(), sin()...)などを式の記述に用いることができます.

// 製品ノルマ
6*x + y >= 12;     // 重油ノルマ/週
4*x + 6*y >= 24;   // ガスノルマ/週

 この部分では制約式(生産ノルマ)を定義しています.関係演算子>=の左辺,右辺には,任意の式を記述できます.目的関数の内容定義の際と同様に,任意の式の中に演算子や初等関数を記述できます.左辺と右辺の関係を表す関係演算子には,以下のものを指定できます.

SIMPLEの関係演算子 定式化時の記述
>= $\geq$
<= $\leq$
== $=$

 

// 各油田の日数制約
0 <= x <= 5;       // 油田Xの週あたりの運転日数制約
0 <= y <= 5;       // 油田Yの週あたりの運転日数制約

 この部分は制約式(運転日数の上下限)を定義しています.ここでは変数の上下限を指定していますが,SIMPLEでは一般の制約式と変数の上下限制約を区別しませんので,x, yの部分に任意の式を書くことが可能です.

 

 以上で,問題の定義の記述は完了です.

 次に,これまでに定義した問題の最適解を求め,結果を出力する部分を記述します.

// 求解
solve();

 solve()は,定義したモデルについて最適解の計算を行う関数です.solve()は,必ずモデル記述の後に記述する必要があります.

// 結果出力
x.val.print();
y.val.print();
cost.val.print();

 この部分は,最適化計算結果の出力を指定しています.最適化計算後の値を出力するためには,最適化計算solve()の後に記述する必要があります.

 

 以上でこのモデルについてのSIMPLEの記述は終了です.

 次にこのモデルを実行してみます(実行方法については「3数理計画問題を解く」を参照してください).すると,数理計画モデルを解く経過が,以下のように出力されます.

[Expand Constraints and Objectives]
sample.smp:7:info: 展開中 目的関数 (1/5) name="全運転コスト"
sample.smp:10:info: 展開中 制約式   (2/5) name=""
sample.smp:11:info: 展開中 制約式   (3/5) name=""
sample.smp:14:info: 展開中 制約式   (4/5) name=""
sample.smp:15:info: 展開中 制約式   (5/5) name=""

[About Numerical Optimizer]
MSI Numerical Optimizer xx.x.x (NLP/LP/IP/SDP module)
         <with META-HEURISTICS engine "wcsp"/"rcpsp">
         <with GLOBAL-OPTIMIZATION add-on "global">
         <with DERIVATIVE-FREE-OPTIMIZATION add-on "DFO">
        , Copyright (C) 1991 NTT DATA Mathematical Systems Inc.

[Problem and Algorithm]
PROBLEM_NAME                                           sample
NUMBER_OF_VARIABLES                                         2
NUMBER_OF_FUNCTIONS                                         3
PROBLEM_TYPE                                     MINIMIZATION
METHOD                                           HIGHER_ORDER

[Progress]
<preprocess begin>.........<preprocess end>
<iteration begin>
    res=4.0e+001 .... 2.8e-005  1.4e-007 
<iteration end>

[Result]
STATUS                                                OPTIMAL
VALUE_OF_OBJECTIVE                                750.0000021
ITERATION_COUNT                                             6
FUNC_EVAL_COUNT                                             9
FACTORIZATION_COUNT                                         7
RESIDUAL                                     1.402395924e-007
ELAPSED_TIME(sec.)                                       0.20
SOLUTION_FILE                                      sample.sol

 最後に結果出力に対応する結果が以下のように出力されます.

油田Xの運転日数=1.5
油田Yの運転日数=3
全運転コスト=750

 =の左辺は指定した変数と目的関数の名前で,name="..."に記述したものが出力されます.右辺には変数と目的関数の値が出力されています.


 

 

上に戻る