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というキーワード付きで宣言したオブジェクトが出現順に並びます).
上に戻る
