Zer*_*ro3 3 constraints minizinc
给定一个 MiniZinc 字符串数组:
int: numStats;
set of int: Stats = 1..numStats;
array[Stats] of string: statNames;
Run Code Online (Sandbox Code Playgroud)
...从 MiniZinc 数据文件加载数据:
numStats = 3;
statNames = ["HEALTH", "ARMOR", "MANA"];
Run Code Online (Sandbox Code Playgroud)
如何在数组中查找特定字符串的索引?例如,ARMOR 位于位置 2。
我需要根据统计数据的一些限制找到最佳的项目选择。此信息存储在一个二维数组中,声明如下:
int: numItems;
set of int: Items = 1..numItems;
array[Items, Stats] of float: itemStats;
Run Code Online (Sandbox Code Playgroud)
因此,为了对通过所选项目获得的最小 ARMOR 数量编写约束,我需要知道 ARMOR 在内部数组中的索引为 2。
由于数据文件是由外部程序生成的,并且统计信息的数量和顺序是动态的,因此我无法对约束中的索引进行硬编码。
该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)] ];
Run Code Online (Sandbox Code Playgroud)
不幸的是,由于 MiniZinc 数据文件中不允许变量声明,这个技巧在我的情况下不起作用。
您可以编写自己的自定义函数来获取字符串数组中字符串的索引:
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) ]
);
Run Code Online (Sandbox Code Playgroud)
在这个函数中创建一个整数数组,其中在位置的整数i或者等于索引str如果string_array[i]=str和 0其它。例如,对于您的示例字符串数组["HEALTH", "ARMOR", "MANA"]和 str ARMOR,生成的 int 数组将为[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;
Run Code Online (Sandbox Code Playgroud)
但是请注意,上述功能是有限的并且存在一些缺陷。首先,如果您在数组中多次出现该字符串,那么您将收到一个无效索引(出现的所有索引的总和str)。此外,如果您为字符串数组设置了自己的索引(比如(2..6)),那么您将需要调整该函数。