来自另一个数组的Minizinc约束

时间:2016-10-24 16:32:39

标签: minizinc

我尝试使用minizinc进行第一次约束编程。我尝试使用n个广告位和n个人创建一个时间表,并为每个广告位分配一个不同的人。我使用array of var int为日程安排建模,使用alldifferent()确保每个广告位中有不同的人。 单独的array大小nnames包含其名称,如下所示:

% Pseudo enum
set of int: NameIndex = 1..2;
int: Forename = 1;
int: Surname = 2;

int: n = 4; % Number of slots and people
set of int: slots = 1..n;

array[slots, NameIndex] of string: names = [| "John", "Doe" 
                                            | "Ann", "Jones" 
                                            | "Fred", "Doe"
                                            | "Barry", "Doe" |];                  
% The schedule
array[slots] of var slots: schedule;

% Every person is scheduled:
include "alldifferent.mzn";
constraint alldifferent(schedule);

% How to constrain by a value from names, say alphabetic order by forename.
% Want to compare each value in schedule to the next one.
%constraint forall (i in 1..n-1) (names[schedule[i],Forename] < names[schedule[i+1],Forename]);

solve satisfy;

output [show(i) ++ ": " ++ show(names[schedule[i], Forename]) ++ " " ++ show(names[schedule[i], Surname])  ++ "\n"
    | i in slots]
% should be:
%  | i in schedule]

如何通过名称中的值约束schdule?在我上面的(破碎)示例中,当forall约束被取消注释时,我得到(使用Minizinc IDE):

in call 'forall'
in array comprehension expression
  with i = 1
in binary '<' operator expression
in array access
cannot find matching declaration

我遵循错误,直到不了解找不到哪个声明。当我从schdule值索引到数组时,输出块show()的值非常高兴。

我错过了什么?是否有更好的方法来模拟名称?我希望将名称扩展到其他属性&#39;人和创造额外的约束。我确定模型和我的forall约束都很天真!

1 个答案:

答案 0 :(得分:0)

问题在于MiniZinc对字符串的支持不多;并且特定于您的示例:不支持比较字符串(“&lt;”)。

也就是说,有一些计划支持var字符串(即使用字符串作为决策变量),但我不知道它何时被释放的确切状态。

这是一个非常简单的修复,但它需要一些预处理:

1)创建一个新数组,其中包含每个名称的(排序)索引:

  array[slots] of int: names_ix = [4, % John Doe
                                   1, % Ann Jones
                                   3, % Fred Doe
                                   2, % Barry Doe
                                   ];                  

2)更改排序约束以使用此新数组

constraint 
   forall (i in 1..n-1) (
      names_ix[schedule[i]] <= names_ix[schedule[i+1]]
   );

[有一个更复杂的变体,需要将名称中的每个字符转换为整数(在“var int”的矩阵中),然后要求将单词 - 作为整数集合 - 排序。请注意,这往往非常混乱,例如处理不同长度的字符串等。]