背景的
我有一群学生,他们想要的项目和各个项目的主管。我正在运行一系列模拟,以查看学生最终完成的项目,这将使我能够获得反馈所需的一些有用的统计数据。所以,这实际上是一个Monte-Carlo
模拟,我将学生列表随机化,然后遍历它,分配项目直到我到达列表的末尾。然后再次重复该过程。
请注意,在单个会话中,每次成功分配项目后,都会发生以下情况:
+项目设置为allocated
,不能提供给其他学生
+主管有一个固定的quota
他可以监督的学生。这减少1
+一旦quota
命中0,该主管的所有项目都变为blocked
,这与项目allocated
代码
def resetData():
for student in students.itervalues():
student.allocated_project = None
for supervisor in supervisors.itervalues():
supervisor.quota = 0
for project in projects.itervalues():
project.allocated = False
project.blocked = False
resetData()
的作用是“重置”某些数据位。例如,成功分配项目后,该项目的project.allocated
将翻转为True
。虽然这对于单次运行很有用,但对于下一次运行,我需要取消分配。
上面我正在通过三个词典进行迭代 - 每个词典用于学生,项目和主管 - 存储信息。
下一位是分配算法的“蒙特卡罗”模拟。
sesh_id = 1
for trial in range(50):
for id in randomiseStudents(1):
stud_id = id
student = students[id]
if not student.preferences:
# Ignoring the students who've not entered any preferences
for rank in ranks:
temp_proj = random.choice(list(student.preferences[rank]))
if not (temp_proj.allocated or temp_proj.blocked):
alloc_proj = student.allocated_proj_ref = temp_proj.proj_id
alloc_proj_rank = student.allocated_rank = rank
successActions(temp_proj)
temp_alloc = Allocated(sesh_id, stud_id, alloc_proj, alloc_proj_rank)
print temp_alloc # Explained
break
sesh_id += 1
resetData() # Refer to def resetData() above
所有randomiseStudents(1)
确实按照学生的顺序随机化。
Allocated
是一个定义如下的类:
class Allocated(object):
def __init__(self, sesh_id, stud_id, alloc_proj, alloc_proj_rank):
self.sesh_id = sesh_id
self.stud_id = stud_id
self.alloc_proj = alloc_proj
self.alloc_proj_rank = alloc_proj_rank
def __repr__(self):
return str(self)
def __str__(self):
return "%s - Student: %s (Project: %s - Rank: %s)" %(self.sesh_id, self.stud_id, self.alloc_proj, self.alloc_proj_rank)
Output and problem
现在如果我运行这个,我得到一个像这样的截断(截断):
1 - Student: 7720 (Project: 1100241 - Rank: 1)
1 - Student: 7832 (Project: 1100339 - Rank: 1)
1 - Student: 7743 (Project: 1100359 - Rank: 1)
1 - Student: 7820 (Project: 1100261 - Rank: 2)
1 - Student: 7829 (Project: 1100270 - Rank: 1)
.
.
.
1 - Student: 7822 (Project: 1100280 - Rank: 1)
1 - Student: 7792 (Project: 1100141 - Rank: 7)
2 - Student: 7739 (Project: 1100267 - Rank: 1)
3 - Student: 7806 (Project: 1100272 - Rank: 1)
.
.
.
45 - Student: 7806 (Project: 1100272 - Rank: 1)
46 - Student: 7714 (Project: 1100317 - Rank: 1)
47 - Student: 7930 (Project: 1100343 - Rank: 1)
48 - Student: 7757 (Project: 1100358 - Rank: 1)
49 - Student: 7759 (Project: 1100269 - Rank: 1)
50 - Student: 7778 (Project: 1100301 - Rank: 1)
基本上,它适用于第一次运行,但是在导致 n 运行的后续运行中,在这种情况下为50,只返回一个学生项目分配对。
因此,我遇到的主要问题是找出导致这种异常行为的原因,特别是因为第一次运行顺利进行。
提前致谢,
AZ
答案 0 :(得分:0)
你真的打算在resetData()
中将主管的配额设置为0吗?这是不是意味着他们的所有项目现在都被阻止了?
乌鸦:
主管有他可以监督的固定学生名额。这将减少1.一旦配额达到0,该主管的所有项目都将被阻止,这与正在分配的项目具有相同的效果。
如果不是这样,您应该检查randomiseStudents()
的输出,以确保它返回完整列表。毕竟,它是该内循环的控制项目。
根据评论进行更新:
问题 似乎是您将主管的配额设置为0,从而导致所有项目被阻止。
这对我来说是纯粹的猜测,但你可能在每次迭代中都有一个学生,因为所有主管的检查都是在分配后发生的。在这种情况下,刚刚分配的配额为-1,所有其他配额为0,有效地停止之后的所有分配。
理想情况下,您需要将主管的配额设置回resetData()
中的原始值。如果它是一个固定的配额(每个主管都相同),你可以简单地使用:
for supervisor in supervisors.itervalues():
supervisor.quota = 7 # for example
如果每个主管都有不同的配额,您需要将其与其他信息一起存储(在初始化期间但不重置),例如supervisor.start_quota
。然后你可以使用:
for supervisor in supervisors.itervalues():
supervisor.quota = supervisor.start_quota