3

質問

文字列の MiniZinc 配列が与えられた場合:

int: numStats;
set of int: Stats = 1..numStats;
array[Stats] of string: statNames;

... MiniZinc データ ファイルから読み込まれたデータ:

numStats = 3;
statNames = ["HEALTH", "ARMOR", "MANA"];

配列内の特定の文字列のインデックスを調べるにはどうすればよいですか? たとえば、その ARMOR は位置 2 にあります。

コンテキスト

ステータスに関するいくつかの制約に関して、アイテムの最適な選択を見つける必要があります。この情報は、次のように宣言された 2D 配列に格納されます。

int: numItems;
set of int: Items = 1..numItems;
array[Items, Stats] of float: itemStats;

したがって、たとえば、選択したアイテムから得られる ARMOR の最小量に関する制約を記述するには、ARMOR が内部配列にインデックス 2 を持っていることを知る必要があります。

データ ファイルは外部プログラムによって生成され、統計の数と順序は動的であるため、制約でインデックスをハードコードすることはできません。

1つの解決策(私の場合は機能しません)

MiniZincチュートリアルでは、興味深いトリックを使用して同様のことを実現しています。

set of int: Colors = 1..3;
int: red = 1;
int: yellow = 2;
int: blue = 3;
array[Colors] of string: name = ["red", "yellow", "blue"];

var Colors: x;
constraint x != red;
output [ name[fix(x)] ];

残念ながら、MiniZinc データ ファイルでは変数宣言が許可されていないため、このトリックは私の場合には機能しません。

4

4 に答える 4

5

独自のカスタム関数を記述して、文字列配列内の文字列のインデックスを取得できます。

function int: getIndexOfString(string: str, 
                               array[int] of string: string_array) = 
   sum(  [ if str = string_array[i] 
              then i
           else 0 endif  
          | i in index_set(string_array) ]
   );

この関数では、位置の整数がifiのインデックスと等しいか、 そうでない場合の整数の配列を作成します。たとえば、サンプルの文字列配列と strの場合、結果の int 配列は になります。strstring_array[i]=str0["HEALTH", "ARMOR", "MANA"]ARMOR[0,2,0]

これが、単純に int 配列を合計して文字列のインデックスを取得できる理由です。文字列が発生しない場合、戻り値は です0。これは、MiniZinc のインデックスがデフォルトで 1 から始まるため問題ありません。

最初の例で上記の関数を呼び出す方法は次のとおりです。

int: numStats;
set of int: Stats = 1..numStats;
array[Stats] of string: statNames;

numStats = 3;
statNames = ["HEALTH", "ARMOR", "MANA"];

var int: indexOfArmor;

constraint 
   indexOfArmor = getIndexOfString("ARMOR",statNames);  

solve satisfy;  

ただし、上記の機能には制限があり、いくつかの欠陥があることに注意してください。まず、配列内に文字列が複数回出現する場合、無効なインデックス (str発生したすべてのインデックスの合計) を受け取ります。また、文字列配列 (たとえば(2..6)) に独自のインデックス セットがある場合は、関数を調整する必要があります。

于 2017-06-30T12:53:58.337 に答える
1

Stackoverflow に関するこの他の投稿によると、MiniZinc で文字列を整数に変換する方法はなく、その逆のみです。最初に他の言語でデータを前処理し、整数に変換する必要があります。ただし、MiniZinc で完了したら、これらの整数を文字列に変換できます。

ただし、必要に応じて、データ ファイルの代わりに MiniZinc ファイルをロードできます。include 構文を使用して、任意の .mzn ファイルを含めます。

于 2016-03-02T23:58:11.680 に答える