最適化セミナーのご案内

9.3 simple_printf関数

 simple_printf関数は,プログラミング言語C/C++の関数であるprintfをSIMPLE用に拡張したものです.printf関数はint, double, char型の変数を出力しますが,simple_printf関数は替わりにモデルファイルの構成要素の情報を出力します.

 simple_printf関数は,変数Variable,目的関数Objective,制約式Constraint,定数Parameter,整数変数IntegerVariable,式Expression,対称行列SymmetricMatrix,ベクトルVector,行列Matrixに関する情報を,任意のフォーマットで出力させる機能を有しています.集合Setや順序集合OrderedSetに関する情報を取得することはできません.

 simple_printf関数の書式は以下のように定められています.

simple_printf(出力指定書式, 出力対象1, 出力対象2, ..);

 次の例では,変数の現在値を整数形式で出力させています.整数形式で出力させるには%dを用います.

Variable x;
x = 3;
simple_printf("%d\n", x.val);

 これに対する出力は以下のようになります.

3

 次のように記述すると,出力は以下のようになります.

simple_printf("xの値 = %d\n", x.val);

 出力

xの値 = 3

 simple_printf関数の引数では,.valを省略する事ができます.従って,次のように記述しても出力は同じです.

simple_printf("xの値 = %d\n", x);

 simple_printf関数では,整数以外にも小数や,浮動小数点形式で値を出力させる事ができます.以下は小数を出力する例です.小数を出力するには%fを用います.

simple_printf("xの値 = %f\n", x.val);

 出力

xの値 = 3.000000

 以下は浮動小数点形式で出力する例です.浮動小数点形式で出力するには%eを用います.

simple_printf("xの値 = %e\n", x.val);

 出力

xの値 = 3.000000e+000

 表示させる桁数を指定することもできます.以下の例では,小数点以下二桁のみが出力されるよう記述しています.

simple_printf("xの値 = %.2f\n", x.val);
simple_printf("xの値 = %.2e\n", x.val);

 出力

xの値 = 3.00
xの値 = 3.00e+000

 出力の幅を指定することもできます.以下の例では,半角15文字に出力が収まるように記述しています.

simple_printf("xの値 = %15f\n", x.val);
simple_printf("xの値 = %15e\n", x.val);

 出力

xの値 =        3.000000
xの値 =   3.000000e+000

 上記の両方の記述をまとめることもできます.

simple_printf("xの値 = %15.2f\n", x.val);
simple_printf("xの値 = %15.2e\n", x.val);

 出力

xの値 =            3.00
xの値 =       3.00e+000

 求解関数solveの前にprint関数を記述すると,求解前の初期状態の情報が記述されます.求解関数solveは,明示的に記述されない場合,モデルの最後尾にあるものと認識されます.例えば,次のモデルに対する出力は以下のようになります.

 モデルファイル

Variable x;
Objective f(type=minimize);
f = 2*x;
x >= 5; //制約
x = 10; //初期値設定
simple_printf("xの値 = %f\n", x.val);

 出力

xの値 = 10.00000

 solve関数の後にsimple_printf関数を記述すると次のようになります.

 モデルファイル

Variable x;
Objective f(type=minimize);
f = 2*x;
x >= 5; //制約
x = 10; //初期値設定
solve();
simple_printf("xの値 = %f\n", x.val);

 出力

xの値 = 5.000000

 添字を持つ対象も出力させる事ができます.次の例では,添字を持つ変数の現在値を整数形式で出力させています.

Set S = "1 2 3";
Element i(set=S);
Variable x(index=i);
x[i] = 3;
simple_printf("%d\n", x.val);

 これに対する出力は以下のようになります.

3
3
3

 次のように記述すると,以下のように出力されます.

simple_printf("x[%d]の値 = %d\n", i, x[i].val);

 出力

x[1]の値 = 3
x[2]の値 = 3
x[3]の値 = 3

 引数の最後に条件式を指定することで,添字の範囲を制限させる事ができます.次の例では,x[1], x[2]の値のみを表示させています.

simple_printf("x[%d]の値 = %d\n", i, x[i].val, i<3);

 出力

x[1]の値 = 3
x[2]の値 = 3

 simple_printf関数の引数には制限が無いので,同じ添字の対象であれば,同時に複数出力することができます.次の例では,変数x[1], x[2], x[3]定数a[1], a[2], a[3]の値を同時に出力させています(.valは省略しても大丈夫な性質を利用しています).

Set S = "1 2 3";
Element i(set=S);
Variable x(index=i);
Parameter a(index=i);
x[i] = 3;
a[i] = 5;
simple_printf("x[%d] = %f, a[%d] = %f\n", i, x[i], i, a[i]);

 出力

x[1] = 3.000000, a[1] = 5.000000
x[2] = 3.000000, a[2] = 5.000000
x[3] = 3.000000, a[3] = 5.000000

 対称行列SymmetricMatrixの情報を表示させたい場合,対称行列自身の添字と,行列成分の添字を意識して区別する必要はありません.例えば,次の例では3つの対称行列$X_{1}$, $X_{2}$, $X_{3}$の値を表示させています.行列要素を示す添字は自動的に出力されます.

Set S = "1 2";
Element i(set=S), j(set=S);
Set N = "1 2 3";
Element n(set=N);
SymmetricMatrix X(index=n,(i,j));
X[n,i,j] = 100*n + 10*i + j, i <= j; // 上三角部分のみ定義
simple_printf("X%d[%d,%d] = %f\n", n, X[n]);
        // []内の%d,%dに対応する引数並びは自動的に補われる

 出力

X1[1,1] = 111;
X1[1,2] = 112;
X1[2,2] = 122;
X2[1,1] = 211;
X2[1,2] = 212;
X2[2,2] = 222;
X3[1,1] = 311;
X3[1,2] = 312;
X3[2,2] = 322;

 simple_printf関数は,求解結果を表す要素resultの情報も出力させる事ができます.以下は,resultが保有する情報の一覧です.

名称 意味
nvars int 変数の数
nfunc int 関数の数
iters int 内点法の反復回数
fevals int 関数評価回数
optValue double 目的関数値
tolerance double 内点法の収束判定値
residual double 解における最適性条件の残差
elapseTime double 所要計算時間
errorCode int 終了時ステータス
(成功時:0,失敗時:エラー番号)
エラー番号は付録A.2.1のものに従います

 

 次のモデルに対する出力は,以下のようになります.

Variable x,y;
Objective f(type=minimize);
f = 2*x + 3*y;
x + 2*y == 15;
x >= 0;
y >= 0;
solve();

simple_printf("関数の数         %d\n", result.nfunc);
simple_printf("内点法の反復回数 %d\n", result.iters);
simple_printf("関数評価回数     %d\n", result.fevals);
simple_printf("目的関数値       %e\n", result.optValue);
simple_printf("収束判定条件     %e\n", result.tolerance);
simple_printf("最適性条件残差   %e\n", result.residual);
simple_printf("所要計算時間     %d\n", result.elapseTime);
simple_printf("終了時ステータス %d\n", result.errorCode);

 出力

関数の数         2
内点法の反復回数 5
関数評価回数     8
目的関数値       2.250000e+001
収束判定条件     1.000000e-008
最適性条件残差   3.978422e-008
所要計算時間     0
終了時ステータス 0

 

 

上に戻る