最適化セミナーのご案内

4.1.1 モデル兼ドライバの記述(VC++)

 このプロジェクトではnoClass.cppというソースファイルにモデルとモデルを利用する手続きが両方書き込まれています.noClass.cppではknapsackSolveという名前の手続きを定義しています.この手続きは入力として,ナップサック問題のモデルの

Parameter a(index=i);
Parameter b;
Parameter c(index=i);

に相当するデータ(aargbargcarg)を与えると

Variable x(index=i);

に相当する変数値(xarg)と目的関数(farg)を返します.

#include "simple.h"
//
//   ナップサック問題(モデルの記述と実行を分離しない)
//
int knapsackSolve(int narg,double* aarg,double barg,double* carg
       ,double* xarg,double* farg)
{
  //
  // システムの初期化.
  //
  SimpleInitialize();
  {
    Set S;
    Element i(set=S);

    IntegerVariable x(name="決定ベクトル",index=i,type=binary); // 整数変数
    Parameter c(name="価値",index=i);
    Parameter a(name="重量",index=i);
    Parameter b(name="許容重量");
    Objective obj(name="総価値",type=maximize);

    // 引数からデータを設定
    a.readD(narg,aarg);
    b = barg;
    c.readD(narg,carg);

    sum(a[i]*x[i],i) <= b;     // 制約条件
    obj = sum(c[i]*x[i],i);    // 目的関数

    // Numerical Optimizerからの最適化結果ファイル.solの
    // 名前の設定
    //    options.outfilename = "nuoptout";
    // .solのファイル出力を抑制する場合には次のように書く
    options.outfilename = "_NULL_";
    // 出力を抑制する
    options.outputMode = "silent";

    // 最適化の実行
    solve();

    // xの内容をC++の配列にダンプ

    int lenx;
    int* indx;
    double* valx;
    x[i].val.dump(lenx,indx,valx);

    if ( lenx != narg) {
      return 99; // x[i]の実際の長さがnargと異なる(データに矛盾あり)
    }

    // 引数に設定
    int it;
    for ( it = 0 ; it < lenx ; ++it ) {
      xarg[indx[it]-1] = valx[it];
      // indx[it]は1,2, ... nargなので,1を引く
    }

    // 目的関数値の設定
    *farg = result.optValue;

    // indx,valxはdump内部で独自にallocateされるのでfreeしておく.
    delete [] indx;
    delete [] valx;
  }
  // Numerical Optimizerのエラーコードを返す.
  return result.errorCode;
}

 このインタフェースを用いる場合,モデルはプログラム全体で1つだけ定義することが可能です.変数,制約式は定義した場所によらずにそのモデルに追加されてゆくことになります.SimpleInitialize()のコールより後と,SimpleClearBuffer()のコールより前は中括弧{ }でくくる必要があります.SIMPLEのオブジェクト(SetElement)の宣言は,この中括弧{ }の中で行います.SimpleInitialize()をコールせずにSIMPLEのオブジェクトを宣言して利用する,或いはこの中括弧{}の外でSIMPLEのオブジェクトを宣言すると実行時エラーとなります.


 

 

上に戻る