问题描述
在看完教程后,我以为我已经掌握了概念,于是着手创建自己的模型,但立即遇到了问题。最好尽快陷入困境,以意识到您实际上了解的很少,imo。
在这个例子中,我只想得到一个输出,其中班级由想要他们的学生组成,即 true
,由我的数组表示(并非每个学生每天都能参加)。
模型的编写方式可能有各种各样的缺点......
不用说,我收到错误 WARNING: model inconsistency detected
enum Students = { Mark,Bart,Mary,Anne,Sue };
enum Classes = { Mon,Tue,Wed};
array[Students,Classes] of bool: pref =
[| true,true,false,| false,| true,true |];
constraint forall (i in Students,j in Classes)(pref[i,j]=true);
solve satisfy;
output [ " \(pref[Students,Classes]);\n" ]
奖励会限制它,所以每个 Student
只出现一次...
完美的结果应该是列出所有满足学生偏好且他们属于 1 个班级的组合。
[Mark,Anne | Bart | Mary,Sue]
感谢您一路帮助我!
解决方法
您可能不了解的重要部分是 MiniZinc 是一种声明式语言。您不会告诉它如何解决问题,而只是指定问题,然后让语言完成其余的工作。
MiniZinc 模型是根据
- 变量:需要做出的决定/你想知道的事情
- 参数:你已经知道的事情
- 约束:在任何或所有变量和参数之间强制执行的规则。
在您的模型中,您没有指定任何变量,仅指定了参数和约束。据说这是不一致的,因为你给它一个包含 pref
和 true
的数组 false
,但随后你的约束强制数组中的每个元素必须是 true
。
很可能您打算让 pref
成为您的一组变量,并意味着您的约束应该强制每个学生都有一个偏好:
enum Students = { Mark,Bart,Mary,Anne,Sue };
enum Classes = { Mon,Tue,Wed};
array[Students,Classes] of var bool: pref;
constraint forall (i in Students)(
count(j in Classes) (pref[i,j]) = 1
);
solve satisfy;
output [ "pref = ",show2d(pref),";" ];
如果您只希望每个学生至少有一个偏好,您可以改用 exists
:
enum Students = { Mark,Classes] of var bool: pref;
constraint forall (i in Students)(
exists(j in Classes) (pref[i,j])
);
solve satisfy;
output [ "pref = ",";" ];
这行得通,但是如果您知道,就像第一个解决方案中的情况一样,学生只做出一个偏好,那么最好将其作为变量类型的一部分强制执行:
enum Students = { Mark,Wed};
array[Students] of var Classes: pref;
solve satisfy;
output [ "pref = ",show(pref),";" ];
那么就不需要任何约束来确保学生只有一个偏好。