如何根据以下限制将 children 分配给房间
How do I allocate children to rooms based on the following constraints
我需要有关我正在编写的房间分配解决方案的约束规范方面的帮助。所以,限制是同一房间只允许 children 同性别,children 残疾人只能被安置在他们可以进入的房间和 children如果可能的话,在一个房间里的所有人都应该是同龄人(这是一个软约束)。输出应该是将在每个房间的 children 的列表。
我将把我目前拥有的 mzn 代码放在下面。我将不胜感激。
所以,我通过定义child是什么,房间是什么来写模型,从而说明什么是宿舍(一组房间)。我想输出一个二维数组,它说明房间和分配给它的 children 但我在实际编写约束以及如何实际编写代码以分配 children 时遇到问题他们的房间。
-编辑,我不知道为什么第一次没有代码,但它在下面。
enum CHILDREN; %variable name will be the child's name
array[CHILDREN] of string:gender; %input is M or F
array[CHILDREN] of int:age;
array[CHILDREN] of string:disability; %input is Y or N
enum ROOMS;
array[ROOMS] of string:access; %if accessible to those with a disability, input is Y or N
array[ROOMS] of int:size;
array[ROOMS] of CHILDREN: occupy; %rooms have children, trying to solve for this
array[ROOMS] of string:label; %gender label for room, idea is to distinguish rooms
var set of ROOMS:dorm; %defining what a dormitory is i.e. a set of rooms
constraint forall(r in ROOMS)(length(occupy) == (size-1)); %number of children in the room equal to its size-1
solve satisfy
这是 dzn/data 文件中的一些数据。
ROOMS={1,2,3,4,5,6,7};
access=[Y,Y,Y,Y,N,N,N];
size=[5,6,5,6,4,7,4];
occupy=[];
label=['','','','','','',''];
CHILDREN={A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T};
gender=[M,M,F,F,F,F,M,M,M,M,M,M,F,F,F,F,F,F,F,F];
age=[3,5,6,7,8,10,3,5,6,7,7,8,9,9,10,10,10,11,11,13];
disability=[Y,Y,Y,Y,Y,Y,N,N,N,N,N,N,N,N,N,N,N,N,N,N];
看来您刚刚开始使用 MiniZinc。所以我想欢迎你加入社区。您似乎掌握了用该语言声明数据的窍门,但您可能想看看不同的数据类型。例如,性别理想情况下不是字符串,而是枚举,或者,如果您只使用两种类型,则可以使用布尔类型。同样disability和access也可以改成boolean类型。
模型中最重要的决定是选择哪些变量。在我提供的模型中,我选择使用设置变量,其中每个房间都由一组占据它的 children 表示。您可以从数据文件中设置房间的性别标签,但由于未提供数据,我也将其转换为变量,让求解器决定应将哪种性别分配给哪个房间。
添加约束时,您应该始终尝试使用全局约束,因此为了强制所有 children 只在一个房间内,我们使用 all_disjoint
。我们也可以使用array_union
函数来确保所有children都分配到一个房间。其他限制可能不言而喻。
最终的(软)约束可以看作是模型的 objective。我们希望尽量减少房间内的年龄差异。这意味着我们首先必须计算这个差异,然后将其设置为 objective 函数 (solve minimize
)。请注意,添加这些计算和 objective 确实会增加模型的复杂性。
要输出赋值,我们可以使用输出语句。您可能会以任何您喜欢的方式获得输出,但我更喜欢同时显示所做的分配和我们正在计算的 objective 函数。
型号
include "globals.mzn";
enum CHILDREN; %variable name will be the child's name
enum GENDER = { M, F }; % NOTE: Enums are better fit for this purpose than strings
array[CHILDREN] of GENDER: gender; %input is M or F
array[CHILDREN] of int: age;
array[CHILDREN] of bool: disability; %input is true or false
enum ROOMS;
array[ROOMS] of bool: access; %if accessible to those with a disability, input is true or false
array[ROOMS] of int: size;
array[ROOMS] of var set of CHILDREN: occupy; %rooms have children, trying to solve for this
array[ROOMS] of var GENDER: label; %gender label for room, idea is to distinguish rooms
constraint all_disjoint(occupy); % Children can only be assigned one room
constraint array_union(occupy) == CHILDREN; % All children must be assigned a room
constraint forall(r in ROOMS)(card(occupy[r]) <= size[r]); %number of children in the room smaller or equal to its size
constraint forall(r in ROOMS)(forall(o in occupy[r]) (label[r] == gender[o])); % All children in the room must have the gender assigned to the room
constraint forall(r in ROOMS) (forall(o in occupy[r] where disability[o]) (access[r] = true)); % Children with a disability can only be placed in accessible rooms
array[ROOMS] of var int: age_difference;
constraint forall(r in ROOMS) ( age_difference[r] = sum(c1,c2 in occupy[r] where c1 < c2) (abs(age[c1] - age[c2])));
solve minimize sum(age_difference);
output ["ROOM \(r) (\(label[r])): \(occupy[r])\n Age difference: \(age_difference[r])\n" | r in ROOMS] ++ ["Objective: \(sum(age_difference))\n"];
数据
ROOMS={r1,r2,r3,r4,r5,r6,r7};
access=[true,true,true,true,false,false,false];
size=[5,6,5,6,4,7,4];
CHILDREN={cA,cB,cC,cD,cE,cF,cG,cH,cI,cJ,cK,cL,cM,cN,cO,cP,cQ,cR,cS,cT};
gender=[M,M,F,F,F,F,M,M,M,M,M,M,F,F,F,F,F,F,F,F];
age=[3,5,6,7,8,10,3,5,6,7,7,8,9,9,10,10,10,11,11,13];
disability=[true,true,true,true,true,true,false,false,false,false,false,false,false,false,false,false,false,false,false,false];
此模型中有很多可以更改的地方:您可以看看是否可以优化使用的约束,将输出更改为您喜欢的方式,选择不同的 objective函数(例如,为了公平起见,有时优化最小值而不是求和更好),甚至更改变量的选择并重写约束。
此版本的模型使用 chuffed 求解器进行了测试,似乎表现相当不错。记得在IDE中设置-a
标志,或者"show all solutions",当运行一个优化问题。
我需要有关我正在编写的房间分配解决方案的约束规范方面的帮助。所以,限制是同一房间只允许 children 同性别,children 残疾人只能被安置在他们可以进入的房间和 children如果可能的话,在一个房间里的所有人都应该是同龄人(这是一个软约束)。输出应该是将在每个房间的 children 的列表。 我将把我目前拥有的 mzn 代码放在下面。我将不胜感激。
所以,我通过定义child是什么,房间是什么来写模型,从而说明什么是宿舍(一组房间)。我想输出一个二维数组,它说明房间和分配给它的 children 但我在实际编写约束以及如何实际编写代码以分配 children 时遇到问题他们的房间。
-编辑,我不知道为什么第一次没有代码,但它在下面。
enum CHILDREN; %variable name will be the child's name
array[CHILDREN] of string:gender; %input is M or F
array[CHILDREN] of int:age;
array[CHILDREN] of string:disability; %input is Y or N
enum ROOMS;
array[ROOMS] of string:access; %if accessible to those with a disability, input is Y or N
array[ROOMS] of int:size;
array[ROOMS] of CHILDREN: occupy; %rooms have children, trying to solve for this
array[ROOMS] of string:label; %gender label for room, idea is to distinguish rooms
var set of ROOMS:dorm; %defining what a dormitory is i.e. a set of rooms
constraint forall(r in ROOMS)(length(occupy) == (size-1)); %number of children in the room equal to its size-1
solve satisfy
这是 dzn/data 文件中的一些数据。
ROOMS={1,2,3,4,5,6,7};
access=[Y,Y,Y,Y,N,N,N];
size=[5,6,5,6,4,7,4];
occupy=[];
label=['','','','','','',''];
CHILDREN={A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T};
gender=[M,M,F,F,F,F,M,M,M,M,M,M,F,F,F,F,F,F,F,F];
age=[3,5,6,7,8,10,3,5,6,7,7,8,9,9,10,10,10,11,11,13];
disability=[Y,Y,Y,Y,Y,Y,N,N,N,N,N,N,N,N,N,N,N,N,N,N];
看来您刚刚开始使用 MiniZinc。所以我想欢迎你加入社区。您似乎掌握了用该语言声明数据的窍门,但您可能想看看不同的数据类型。例如,性别理想情况下不是字符串,而是枚举,或者,如果您只使用两种类型,则可以使用布尔类型。同样disability和access也可以改成boolean类型。
模型中最重要的决定是选择哪些变量。在我提供的模型中,我选择使用设置变量,其中每个房间都由一组占据它的 children 表示。您可以从数据文件中设置房间的性别标签,但由于未提供数据,我也将其转换为变量,让求解器决定应将哪种性别分配给哪个房间。
添加约束时,您应该始终尝试使用全局约束,因此为了强制所有 children 只在一个房间内,我们使用 all_disjoint
。我们也可以使用array_union
函数来确保所有children都分配到一个房间。其他限制可能不言而喻。
最终的(软)约束可以看作是模型的 objective。我们希望尽量减少房间内的年龄差异。这意味着我们首先必须计算这个差异,然后将其设置为 objective 函数 (solve minimize
)。请注意,添加这些计算和 objective 确实会增加模型的复杂性。
要输出赋值,我们可以使用输出语句。您可能会以任何您喜欢的方式获得输出,但我更喜欢同时显示所做的分配和我们正在计算的 objective 函数。
型号
include "globals.mzn";
enum CHILDREN; %variable name will be the child's name
enum GENDER = { M, F }; % NOTE: Enums are better fit for this purpose than strings
array[CHILDREN] of GENDER: gender; %input is M or F
array[CHILDREN] of int: age;
array[CHILDREN] of bool: disability; %input is true or false
enum ROOMS;
array[ROOMS] of bool: access; %if accessible to those with a disability, input is true or false
array[ROOMS] of int: size;
array[ROOMS] of var set of CHILDREN: occupy; %rooms have children, trying to solve for this
array[ROOMS] of var GENDER: label; %gender label for room, idea is to distinguish rooms
constraint all_disjoint(occupy); % Children can only be assigned one room
constraint array_union(occupy) == CHILDREN; % All children must be assigned a room
constraint forall(r in ROOMS)(card(occupy[r]) <= size[r]); %number of children in the room smaller or equal to its size
constraint forall(r in ROOMS)(forall(o in occupy[r]) (label[r] == gender[o])); % All children in the room must have the gender assigned to the room
constraint forall(r in ROOMS) (forall(o in occupy[r] where disability[o]) (access[r] = true)); % Children with a disability can only be placed in accessible rooms
array[ROOMS] of var int: age_difference;
constraint forall(r in ROOMS) ( age_difference[r] = sum(c1,c2 in occupy[r] where c1 < c2) (abs(age[c1] - age[c2])));
solve minimize sum(age_difference);
output ["ROOM \(r) (\(label[r])): \(occupy[r])\n Age difference: \(age_difference[r])\n" | r in ROOMS] ++ ["Objective: \(sum(age_difference))\n"];
数据
ROOMS={r1,r2,r3,r4,r5,r6,r7};
access=[true,true,true,true,false,false,false];
size=[5,6,5,6,4,7,4];
CHILDREN={cA,cB,cC,cD,cE,cF,cG,cH,cI,cJ,cK,cL,cM,cN,cO,cP,cQ,cR,cS,cT};
gender=[M,M,F,F,F,F,M,M,M,M,M,M,F,F,F,F,F,F,F,F];
age=[3,5,6,7,8,10,3,5,6,7,7,8,9,9,10,10,10,11,11,13];
disability=[true,true,true,true,true,true,false,false,false,false,false,false,false,false,false,false,false,false,false,false];
此模型中有很多可以更改的地方:您可以看看是否可以优化使用的约束,将输出更改为您喜欢的方式,选择不同的 objective函数(例如,为了公平起见,有时优化最小值而不是求和更好),甚至更改变量的选择并重写约束。
此版本的模型使用 chuffed 求解器进行了测试,似乎表现相当不错。记得在IDE中设置-a
标志,或者"show all solutions",当运行一个优化问题。