运行分配模拟在第一次运行后反复中断

发布于 2024-09-03 03:57:58 字数 3288 浏览 3 评论 0原文

背景
我有一群学生、他们想要的项目以及各自项目的导师。我正在运行一系列模拟来查看学生最终完成了哪些项目,这将使我能够获得反馈所需的一些有用的统计数据。因此,这本质上是一个蒙特卡罗模拟,我随机排列学生列表,然后迭代它,分配项目,直到到达列表末尾。然后再次重复该过程。

请注意,在单个会话中,每次成功分配项目后都会发生以下情况:
+ 该项目已设置为已分配并且不能分配给其他学生
+ 导师有固定的配额他可以监督的学生。减 1
+ 一旦配额达到0,该主管的所有项目都会被阻止,这与分配的项目具有相同的效果

代码

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.alowned 将翻转为 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) 所做的只是随机化学生的顺序。

Alsigned 是一个定义如下的类:

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)

输出和问题

现在,如果我运行它,我会得到如下输出(已截断):

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),仅返回一个学生-项目分配对。

因此,我遇到的主要问题是找出导致这种异常行为的原因,特别是因为第一次运行运行顺利。

预先感谢,

阿兹

Background
I have a bunch of students, their desired projects and the supervisors for the respective projects. I'm running a battery of simulations to see which projects the students end up with, which will allow me to get some useful statistics required for feedback. So, this is essentially a Monte-Carlo simulation where I'm randomising the list of students and then iterating through it, allocating projects until I hit the end of the list. Then the process is repeated again.

Note that, within a single session, after each successful allocation of a project the following take place:
+ the project is set to allocated and cannot be given to another student
+ the supervisor has a fixed quota of students he can supervise. This is decremented by 1
+ Once the quota hits 0, all the projects from that supervisor become blocked and this has the same effect as a project being allocated

Code

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

The role of resetData() is to "reset" certain bits of the data. For example, when a project is successfully allocated, project.allocated for that project is flipped to True. While that's useful for a single run, for the next run I need to be deallocated.

Above I'm iterating through thee three dictionaries - one each for students, projects and supervisors - where the information is stored.

The next bit is the "Monte-Carlo" simulation for the allocation algorithm.

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

All randomiseStudents(1) does is randomise the order of students.

Allocated is a class defined as such:

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

Now if I run this I get an output such as this (truncated):

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)

Basically, it works perfectly for the first run, but on subsequent runs leading upto the nth run, in this case 50, only a single student-project allocation pair is returned.

Thus, the main issue I'm having trouble with is figuring out what is causing this anomalous behaviour especially since the first run works smoothly.

Thanks in advance,

Az

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

风吹雪碎 2024-09-10 03:57:58

您真的打算在 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

Do you really intend to set the supervisor's quota to 0 in resetData()? Doesn't that mean all their projects are now blocked?

Quoth the raven:

The supervisor has a fixed quota of students he can supervise. This is decremented by 1. Once the quota hits 0, all the projects from that supervisor become blocked and this has the same effect as a project being allocated.

If that's not it, you should check the output of randomiseStudents() to ensure it's returning a full list. It is, after all, the controlling item for that inner loop.


Update based on comments:

It appears the problem was that you were setting the supervisor's quota to 0 thus rendering all their projects blocked.

This is pure guesswork on my part but you probably got one student out in each iteration because the checking of all supervisors happened after an allocation. In that case, the one just allocated would have a quota of -1 and all the other quotas would be 0, effectively stopping all allocations after that one.

Ideally, you'd want to set the supervisor's quota back to their original value in resetData(). If it were a fixed quota (same for each supervisor), you could simply use:

for supervisor in supervisors.itervalues():
    supervisor.quota = 7 # for example

If each supervisor had a different quota, you would need to store that along with the other information (during initialisation but not resetting) as, for, example supervisor.start_quota. Then you could use:

for supervisor in supervisors.itervalues():
    supervisor.quota = supervisor.start_quota
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文