5.3 ドライバ
ではこのモデルを解く汎用のC++プログラムを準備しましょう.それはプロジェクトに追加されている
driver.cpp
というファイルで,knapsackSolve
という名前の手続きです.このルーチンのインタフェースは入力として,ナップサック問題のモデルの
Parameter a(index = i); Parameter b; Parameter c(index = i);
に相当するデータ(aarg
,barg
,carg
)を与えると
Variable x(index = i);
に相当する変数値(xarg
)と目的関数(farg
)を返すというものです.ドライバのこのインタフェースは問題に特化して調整できるので,より柔軟なコード作成が可能になります.
#include "knapsack.h" // インクルード宣言 // // ナップサック問題の求解 // // int knapsackSolve(int narg // 問題のサイズ ,double* aarg // 係数a ,double barg // 係数b ,double* carg // 係数c ,double* xarg // 解ベクトル( x ) ,double* farg // 目的関数 ) { // 初期化 SimpleInitialize(); { // SimpleInitialize()のコールの後は{を付ける // 値転送用のオブジェクト Set S; Element i(set = S); Parameter b; Parameter c(index = i), a(index = i); // C配列を初期化用のデータに与える. b = barg; // スカラはそのまま代入 c.readD(narg, carg); // 配列からSIMPLEのオブジェクトへの設定 a.readD(narg, aarg); // 配列からSIMPLEのオブジェクトへの設定 // // knapsack問題の求解 // System_knapsack knap(c, a, b); int len; int* ind; double* knapx; knap.x.val.dump(len, ind, knapx); // knapsack問題のxをCの配列であるknapxに設定 // 解を戻り配列に設定 int it; for (it = 0; it < len; ++it) { xarg[it] = knapx[it]; } *farg = result.optValue; // 目的関数値を取る簡単な方法(asDouble()でも可能) // 不要な領域の破壊 delete [] ind; delete [] knapx; } // SimpleClearBuffer()のコールの前を}で閉じる. // 終了処理 SimpleClearBuffer(); return result.errorCode; // エラーコードを返す. }
SimpleInitialize()
とSimpleClearBuffer()
はC++SIMPLEを利用した処理の最初と最後に必ず必要なコールです.実装上の理由により,SimpleInitialize
のコールより後と,SimpleClearBuffer()
のコールより前は{ }
でくくる必要があります.SIMPLEのオブジェクト(Set
やElement
)の宣言は,この{ }
の中で行います.SimpleInitialize
をコールせずにSIMPLEのオブジェクトを宣言して利用した場合,あるいはこの{}
の外でSIMPLEのオブジェクトを宣言すると実行時エラーとなります.
手続きの中ほどでSystem_knapsack
というクラスのオブジェクトknap
を宣言していますが,これがknapsack.smp
というモデル記述に対応するクラスのオブジェクトの宣言です.このプログラムの先頭の
#include "knapsack.h"
がこのモデル定義を含むファイルで,モデルknapsack
に対応するクラスを利用する場合には必ずインクルードする必要があります.
一般にNAME.smp
なるモデルにはSystem_NAME
というクラスが対応します.クラスの定義ファイルNAME.h
にはSystem_NAME
の定義が書かれています.そのため,System_NAME
を使用する際には必ずNAME.h
のインクルードが必要になります.
クラス宣言の中でSIMPLEオブジェクトをrequired
というキーワード付きで
// knapsack.smpの中 Parameter c(index = i, required); Parameter a(index = i, required); Parameter b(required);
のように宣言しているので,呼び出し側の手続きで同様に宣言した受け渡し用のオブジェクト
// driver.cppの中 Set S; Element i(set = S); Parameter b; Parameter c(index = i), a(index = i);
に
b = barg; // スカラはそのまま代入 c.readD(narg, cary); // 配列はreadDを用いる. a.readD(narg, aary); // 配列はreadDを用いる.
として値を設定,システムオブジェクトknap
の宣言の際に
System_knapsack knap(c, a, b); // knapsack問題の求解
のように渡しています(この引数にはモデル中,required
というキーワード付きで宣言したオブジェクトが出現順に並びます).
上に戻る