10.3 simple_printf関数
simple_printf
関数は,以下のような特徴を持っています.
simple_printf
関数は,SIMPLEオブジェクトの情報をユーザ指定のフォーマットで出力することができます.- フォーマットの形式はプログラミング言語C/C++の標準関数
printf
に従います. - 条件式を記述して,出力する添字範囲を指定することができます.
- 対象となるSIMPLEオブジェクトは以下です.
- 変数
Variable
- 目的関数
Objective
- 制約式
Constraint
- 定数
Parameter
- 整数変数
IntegerVariable
- 式
Expression
- 対称行列
SymmetricMatrix
- 変数
- 集合
Set
や順序集合OrderedSet
に関する情報を取得することはできません. - 引数の数は34個までです.
simple_printf
関数の書式は以下のように定められています.
simple_printf(出力指定書式, 出力対象1, 出力対象2, ..);
条件式を引数の最後に記述することが可能です.
simple_printf(出力指定書式, 出力対象1, 出力対象2, .., 条件式);
条件式を複数記述することも可能です.
simple_printf(出力指定書式, 出力対象1, 出力対象2, .., 条件式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);
出力
xの値 = 3.000000
以下は指数形式で出力する例です.指数形式で出力するには%eを用います.
simple_printf("xの値 = %e\n", x);
出力
xの値 = 3.000000e+000
表示させる桁数を指定することもできます.以下の例では,小数点以下二桁のみが出力されるよう記述しています.
simple_printf("xの値 = %.2f\n", x); simple_printf("xの値 = %.2e\n", x);
出力
xの値 = 3.00 xの値 = 3.00e+000
出力の幅を指定することもできます.以下の例では,半角15文字に出力が収まるように記述しています.
simple_printf("xの値 = %15f\n", x); simple_printf("xの値 = %15e\n", x);
出力
xの値 = 3.000000 xの値 = 3.000000e+000
桁数と出力幅の両方をまとめて記述することもできます.
simple_printf("xの値 = %15.2f\n", x); simple_printf("xの値 = %15.2e\n", x);
出力
xの値 = 3.00 xの値 = 3.00e+000
求解関数solve
の前にSIMPLEオブジェクトを出力すると,求解前の初期状態の情報が記述されます.求解関数solve
は,明示的に記述されない場合,モデルの最後尾にあるものと認識されます.例えば,次のモデルに対する出力は以下のようになります.
モデルファイル
Variable x; Objective f(type = minimize); f = 2 * x; x >= 5; //制約 x = 10; //初期値設定 simple_printf("xの値 = %f\n", x);
出力
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);
出力
xの値 = 5.000000
添字を持つ対象も出力させる事ができます.次の例では,添字を持つ変数の現在値を整数形式で出力させています.
Set S = "1 2 3"; Element i(set = S); Variable x(index = i); x[i] = 3; simple_printf("%d\n", x);
これに対する出力は以下のようになります.
3 3 3
次のように記述すると,以下のように出力されます.
simple_printf("x[%d]の値 = %d\n", i, x[i]);
出力
x[1]の値 = 3 x[2]の値 = 3 x[3]の値 = 3
引数の最後に条件式を指定することで,添字の範囲を制限させる事ができます.次の例では,x[1]
, x[2]
の値のみを表示させています.
simple_printf("x[%d]の値 = %d\n", i, x[i], i < 3);
出力
x[1]の値 = 3 x[2]の値 = 3
同じ添字の対象であれば,同時に複数出力することができます.次の例では,変数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
多次元集合の添字について,複雑な条件を課して出力を行いたい場合,複雑な条件を記述する集合を事前に作成しておくことが推奨されます.以下は具体例です.二次元集合IJ
などを定義します.
Set I; Element i(set=I); I = "1 .. 7"; Set J; Element j(set=J); J = "1 .. 4"; Set IJ(dim=2); IJ = "1,1, 2,2 3,1"; Parameter b(index=(i,j)); b[i,j] = i+j, (i,j) < IJ;
上記の集合について,定数b
が 4 となる変数の組を出力する例を示します.以下のように二次元集合B
を定義します.
Set B(dim=2); Element ij(set=B); B = setOf( (i,j), b[i,j] == 4);
上記集合B
を用いると,意図通りの記述ができます.
/* 以下が出力されます 2,2 3,1 */ simple_printf("%d,%d\n", ij, b[ij] == 4);
次の例では3つの対称行列(SymmetricMatrix
),
,
の値を表示させています.
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, i, j, X[n, i, j]);
出力
X1[1, 1] = 111.000000 X1[1, 2] = 112.000000 X1[2, 1] = 112.000000 X1[2, 2] = 122.000000 X2[1, 1] = 211.000000 X2[1, 2] = 212.000000 X2[2, 1] = 212.000000 X2[2, 2] = 222.000000 X3[1, 1] = 311.000000 X3[1, 2] = 312.000000 X3[2, 1] = 312.000000 X3[2, 2] = 322.000000
simple_printf
関数は,最適化計算結果resultの情報も出力させる事ができます.以下は最適化計算結果を出力するモデルファイルの記述例です.
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
上に戻る