数理最適化セミナーのご案内

5.10 集合クラスSet

 集合はSetというクラスで表現されます.以下の例では,自然数1, 2, 3を要素とする集合Sを定義しています.

Set S;
S = "1 2 3";

 集合の要素間は,半角スペースで区切る必要があります.また,集合自体の定義と,構成要素の定義を同時に行う事ができます.以下の記述は上の記述と同じ意味です.

Set S = "1 2 3";

 添字クラスElementと併用することで,変数Variableを集合の要素ごとに設定できます(制約式Constraint,定数Parameter,整数変数IntegerVariable,式Expressionについても同様です).以下の例では3個の変数y[1], y[2], y[3], 3個の定数b[1], b[2], b[3]を定義しています.

Set S;
S = "1 2 3";
Element i(set = S);
Variable y(index = i);
Parameter b(index = i);

 集合の要素には自然数だけでなく,文字列も使用することができます.以下の例では2個の整数変数z[p], z[q],2個の式g[p], g[q]を定義しています.

Set T;
T = "p q";
Element j(set = T);
IntegerVariable z(index = j);
Expression g(index = j);
g[j] = 2 * x[j] + 3 * y[j];

 要素の文字列は必ずしも一文字である必要はありません.

Set T = "before after";

 要素の文字列には半角英数字,半角記号_-と全角文字を使用できます.

Set T = "前_before 後_after";

 集合の要素に文字列を使用した場合は,対象を個別に記述する際に,添字部分にダブルクォート"を用いる必要があります.

-1 <= z["p"] <= 2;

 一括して記述する場合にはダブルクォートで囲んではいけません.

-1 <= z[j] <= 2;

 集合の要素に自然数を用いる場合は,..を用いる事で途中の要素を自動的に補間することが可能です.以下の二つの例はいずれも自然数1から10で構成される集合Sを定義しています.

Set S = "1 .. 10";
Set S = "1 2 3 4 5 6 7 8 9 10";

 要素に文字列を用いる場合は,上記の自動補間機能を用いることはできません.次の記述は誤りです.

Set T = "a .. k";

 集合の要素は,モデルファイル内で定義する以外に,データファイルから与える方法もあります.以下は自然数1, 2, 3を要素とする集合Sの定義を,データファイルfoo.datから与える例です.

 モデルファイル内

Set S;

 foo.dat

S = "1 2 3";

 集合クラスの構成要素は,明示的に定義しなくとも,モデルファイルやデータファイルの情報から自動的に定義されます.これをSIMPLEの自動代入機能と呼びます.以下の例では,自動代入機能により,集合Sの要素は1, 2, 3であると判断されます.

Set S;
Element i(set = S);
Parameter a(index = i);
a[1] = -1;
a[2] = -1;
a[3] = 1;

 以下のように,データファイル(foo.dat)内でaの値を定めた場合も同様です.

 モデルファイル内

Set S;
Element i(set = S);
Parameter a(index = i);

 foo.dat

a = [1] -1 [2] -1 [3] 1

 部分集合を定義したい場合は,引数superSetを用います.以下の例では集合Tが集合Sの部分集合であることを記述しています.

Set S;
Set T(superSet = S)

 ある集合に対して定義された添字は,その部分集合に対しても自動的に定義されます.

 添字を部分集合のみ(あるいは部分集合以外)で走らせたい場合は,集合と添字の包含関係を表す演算子<, >を利用します.以下の例では,定数a[1], a[2]-1を,a[3]1を設定しています.

Set S;
S = "1 2 3";
Set T(superSet = S);
T = "1 2";
Element i(set = S);
Parameter a(index = i);
a[i] = -1, i < T; // iがTに含まれる場合
a[i] = 1, i > T; // iがTに含まれない場合

 多次元集合(要素の組の集合)を定義する場合には,引数dimで次元を指定します.以下の例では,Iの要素とJの要素の組を要素とする集合IJを定義し,二次元の添字をもつ変数xを定義しています.Iの要素とJの要素のすべての組み合わせについて変数を定義したいわけではない場合などに,多次元集合を使用します.

Set I;
Element i(set = I);
Set J;
Element j(set = J);
Set IJ(dim = 2, superSet = (I, J));
Element ij(set = IJ);
IJ = "a 1 b 2";                 // 集合の要素を"a, 1"と"b, 2"とする
Variable x(index = ij);         // x["a, 1"]とx["b, 2"]が定義される
x[i, j] >= 0, (i, j) < IJ;      // x["a, 1"]とx["b, 2"]に下限を設定する

 条件式から部分集合を取得するには,関数setOfを使用します.setOf関数の第一引数は添字,第二引数は条件式である必要があります.関数の返り値は集合です.なお,得られた集合について,通常の集合と異なり自動代入機能を利用することは出来ません.以下の例では,集合Sの中で条件a[i] > 0を満たす要素のみから,集合Tを取得しています.

Set S = "1 2 3";
Set T;
Element i(set = S);
Parameter a(index = i);
a[1] = -1;
a[2] = -1;
a[3] = 1;
T = setOf(i, a[i] > 0); // 要素3のみからなる集合Tが作成される.

 集合の要素数を取得するには,card関数を使用します.card関数の返り値はint型です.以下の例では,整数nに集合Sの要素数を格納しています.

int n = S.card();

 集合には他にも様々な演算がありますが,使用頻度の低い用法は本マニュアルでは除外しています.詳細はお問い合わせください.


 

 

上に戻る