我想一群人分成更小的子组,洗牌组多次为历届会议之后,让所有的人满足对方在至少一次。分组的人多次,所有的成员达到同组彼此至少一次
- 在每个会话中,人们被划分为固定数量的小组。每个人都必须加入一个小组。
- 组的大小应该是最接近于(人数)/(组数)。不应该有一群人太少或太多人。
- 会议持续进行,直到每对人至少遇见一次。
- 优选地,同一对彼此相遇的次数应该被最小化。
以下是11人(编号0-10)和3组(3列)的此问题的答案。它需要5个会话。
Session 1: 3,6,8,10 0,1,7,9 2,4,5
Session 2: 3,5,7,8 0,1,2,10 4,6,9
Session 3: 0,1,6,8 2,3,4,9 5,7,10
Session 4: 0,3,5,9 1,4,8,10 2,6,7
Session 5: 1,3,5,6 2,8,9,10 0,4,7
Members of two groups of different size must meet each other (1v1, once)
上面的问题是相似的,但我想宁可让人们见面只是在一个组一个更大的群体,而不是1对1的。
,以下是我的做法是使用合金。这适用于少数人(〜15)和组(〜2),但当尺寸增加时,它很快会导致计算时间爆炸。我需要为〜25个人和〜5个团队计算它。
module Teaming
sig Person { groups: some Group }
sig Group { people: some Person }
sig Session { groups: some Group }
one sig Sessions { sessions: some Session }
sig GroupPerSession {}
-- Tree structures
fact {
all s: Session | s in Sessions.sessions
all g: Group | g in Session.groups
all s: Session | all p:Person | p in s.groups.people
people =~ groups
}
-- The total number of people
fact {
all s: Session | #s.groups.people = #Person
}
-- The number of groups per session
fact {
all s: Session | #s.groups = #GroupPerSession
}
-- The number of people in a group
fact {
all g: Group | (#g.people) >= div[#(Person), #(GroupPerSession)] and (#g.people) <= add[div[#Person,#GroupPerSession],1]
}
-- Mutually exclusive grouping in a session
fact separate {
all s: Session | all disj a,b: s.groups | no p: Person | p in a.people and p in b.people
}
-- Every pair of people meets somewhere
pred sameGroup {
all disj a,b: Person | some g: Group | a in g.people and b in g.people
}
-- The same people should not meet too many times
fact sameGroupNotTooMuch {
all disj a,b: Person | #{a.groups & b.groups} <= 3
}
run sameGroup for 6 Int, 5 Session, 15 Group, exactly 3 GroupPerSession, exactly 16 Person
run sameGroup for 6 Int, 6 Session, 24 Group, exactly 4 GroupPerSession, exactly 18 Person
run sameGroup for 6 Int, 7 Session, 35 Group, exactly 5 GroupPerSession, exactly 18 Person
我想动态编程应该可以工作,但我找不到任何具体的东西。 Alloy代码或其他算法的改进指针会很棒。