编写优化函数
我正在尝试写一个网球预约系统,但遇到了一些问题。假设你有一些球员,他们对场地编号、日期和时间都有自己的偏好。而且每个球员都有排名,所以如果某个日期/时间段有多个球员想预约,优先级最高的那个球员应该被选中。
我在考虑使用一些优化算法来解决这个问题,但我不太确定该用什么样的成本函数或者算法。有没有什么建议?
还有一件事,我更倾向于使用Python,但如果有不依赖于语言的建议也非常欢迎。谢谢!
编辑:
一些澄清:
优先级高的球员会赢,优先级低的球员会被安排到最近的时间段。时间段的安排比较灵活。是的,我希望能最大化让更多人预约到他们最想要的时间。
7 个回答
这是一个NP完全问题,我觉得,所以对于任何大数据集来说,想要有一个非常快的算法几乎是不可能的。
还有一个问题是,你可能会遇到一个根本无法安排的时间表。假设这种情况不存在,那么像下面这样的伪代码可能是你最好的选择:
sort players by priority, highest to lowest
start with empty schedule
for player in players:
for timeslot in player.preferences():
if timeslot is free:
schedule.fillslot(timeslot, player)
break
else:
#if we get here, it means this player couldn't be accomodated at all.
#you'll have to go through the slots that were filled and move another (higher-priority) player's time slot
你在描述一个匹配问题。可以参考一下斯托尼布鲁克算法库和Kleinberg和Tardos的《算法设计》。如果参与者的数量和场地的数量相等,就可以找到一个稳定的匹配,这个问题被称为稳定婚姻问题。其他的匹配方式就会变得更复杂。
基本算法
我会先把玩家按等级排序,因为高等级的玩家总是会把低等级的玩家推开。然后从等级最高的玩家开始,满足他所请求的内容(如果他真的是最高等级的玩家,他总是会赢,所以你可以给他任何他想要的东西)。接着我会处理第二高等级的玩家。如果他请求的东西已经被最高等级的玩家占用了,就试着找一个附近的空位给他。然后是第三高等级的玩家。如果他请求的东西也被最高等级的玩家占用了,就把他移动到附近的一个空位。如果这个空位已经被第二高等级的玩家占用,就把他移动到更远的一个空位。依此类推,处理其他所有玩家。
一些需要考虑的调整:
如果多个玩家的等级相同,你可能需要实现一些“公平性”。所有等级相同的玩家在排序时会随机排列,比如用快速排序。你可以通过不逐个玩家处理,而是按等级处理来增加公平性。你从最高等级开始,处理这个等级的第一个玩家的第一个请求。然而,在处理他的第二个请求之前,先处理下一个最高等级玩家的第一个请求,然后是第三个最高等级玩家的第一个请求。算法和上面一样,但假设你有10个玩家,玩家1-4是最高等级,玩家5-7是低等级,玩家8-10是非常低等级,每个玩家都有3个请求,你可以这样处理:
Player 1 - Request 1
Player 2 - Request 1
Player 3 - Request 1
Player 4 - Request 1
Player 1 - Request 2
Player 2 - Request 2
:
这样你就有了一些公平性。你也可以在每个等级内随机选择,这样也能提供一些公平性。
你甚至可以在不同等级之间实现公平。例如,如果你有4个等级,你可以说:
Rank 1 - 50%
Rank 2 - 25%
Rank 3 - 12,5%
Rank 4 - 6,25%
(这只是示例值,你可以使用不同的方式,而不是总是乘以0.5,比如乘以0.8,这样数字下降得会更慢)
现在你可以说,从等级1开始处理请求,但一旦满足了50%的等级1请求,就转到等级2,确保满足25%的请求,依此类推。这样,即使是等级4的用户也有机会战胜等级1的用户,虽然这有点违背最初的算法,但你提供了一些公平性。即使是等级4的玩家,有时也能得到他的请求,他不会“干涸”。否则,如果等级1的玩家在同一时间安排所有请求,而等级4的玩家没有机会得到任何请求,这样就会让等级4的玩家完全没有机会。这样至少他有一点机会能得到一个请求。
在确保每个人的最低请求比例被处理后(等级越高,比例越多),你再回到最高等级,从等级1开始处理他们剩下的请求,然后是等级2的请求,依此类推。
最后但同样重要:你可能想定义一个最大空位偏移。如果一个空位被占用,程序应该寻找离得最近的空位。但是,如果这个最近的空位很远呢?比如我在周一下午4点请求一个空位,而程序找到的下一个空位是在周三上午9点,这对我来说并没有什么帮助,对吧?我可能周三根本没有时间。所以你可以限制空位搜索在同一天,并规定空位最多偏移3小时。如果在这个范围内找不到空位,就取消请求。在这种情况下,你需要告诉玩家:“我们很抱歉,但我们无法为您找到附近的空位;请在其他日期/时间请求空位,我们会看看能否为您找到合适的空位。”