我正在计算一个幻想自行车比赛的最佳队伍。我有一个csv文件,其中包含176名自行车手,他们的球队,他们得分的数额和价格,把他们放在我的团队。我正在努力寻找得分最高的16人车队。在
适用于任何团队组成的规则是:
下面是我的csv文件的简短摘录。在
THOMAS Geraint,Team INEOS,142,13
SAGAN Peter,BORA - hansgrohe,522,11.5
GROENEWEGEN Dylan,Team Jumbo-Visma,205,11
FUGLSANG Jakob,Astana Pro Team,46,10
BERNAL Egan,Team INEOS,110,10
BARDET Romain,AG2R La Mondiale,21,9.5
QUINTANA Nairo,Movistar Team,58,9.5
YATES Adam,Mitchelton-Scott,40,9.5
VIVIANI Elia,Deceuninck - Quick Step,273,9.5
YATES Simon,Mitchelton-Scott,13,9
EWAN Caleb,Lotto Soudal,13,9
解决这个问题的最简单的方法是生成一个所有可能的团队组合的列表,然后应用规则排除不符合上述规则的团队。在这之后,很容易计算出每支球队的总得分,并选出得分最高的一支。理论上,可以通过下面的代码生成可用团队的列表。在
^{pr2}$然而,将176名自行车运动员的所有组合计算成16人一组,这对我的电脑来说只是too many calculations的事情,尽管this问题的答案意味着其他的事情。我做了一些研究,但没有找到任何方法来应用上述条件,而不必迭代每个选项。在
有没有办法找到一个最佳的团队,要么通过使上述方法发挥作用,要么使用另一种方法?在
编辑: 在文本中,可以找到完整的CSV文件here
我为你的问题补充一个答案:
如果你认为我应该编辑我的第一篇文章,请让我知道,我认为这样更清楚,因为我的第一篇文章相当密集,回答了最初的问题。在
我们引入一个新变量:
您需要添加这些约束以链接变量Zik和Xi(如果未选择cyclist i,即Xi=0,则变量Zik不能为1)
^{pr2}$每天选择10名骑车人的限制条件如下:
最后,你的目标可以这样写:
这是思考的部分。这样写的目标不是线性的(注意两个变量X和Z之间的乘法)。幸运的是,这两个二进制文件都有,而且有一个技巧可以将这个公式转换成它的线性形式。在
让我们再次引入新的变量,比如(
Lik = Xi * Zik
)来线性化目标。在目标现在可以这样写,并且是线性的:
现在我们需要添加这些约束,使
Lik
等于Xi * Zik
:好吧。这就是数学的美,你可以用线性方程组来模拟很多事情。我提出了先进的概念,如果你第一眼看不懂是正常的。在
我在这个file上模拟了每天的分数列。在
下面是解决新问题的Python代码:
结果如下:
您的团队:
每天选择骑自行车的人
让我们比较答案1和答案2的结果
print(solver.Objective().Value())
:第一个模型得到
3738.0
,第二个模型得到3129.087388325567
。该值较低,因为每个阶段只选择10个自行车手,而不是16个。在如果保留第一个解并使用新的评分方法,我们得到
3122.9477585307413
我们可以认为第一个模型已经足够好了:我们不必引入新的变量/约束,模型保持简单,我们得到的解决方案几乎和复杂模型一样好。有时不需要100%的精确性,通过一些近似值可以更容易、更快地求解模型。在
这是一个经典的operations research问题。在
有大量的算法可以找到一个最优的(或者仅仅是一个非常好的,取决于算法)解决方案:
下面的代码将使用MIP、或工具库和默认解算器COIN-OR找到最佳解决方案:
印刷品:
^{pr2}$这个代码如何解决这个问题?正如@KyleParsons所说,它看起来像背包问题,可以用整数规划建模。在
让我们定义变量
Xi (0 <= i <= nb_cyclists)
和Yj (0 <= j <= nb_teams)
。在要定义这些变量之间的关系,可以对这些约束进行建模:
若要为每个车队最多选择4名自行车手,请创建以下约束:
要选择16名自行车手,以下是相关的约束:
成本约束:
然后你可以最大化
请注意,我们使用线性目标和线性不等式约束对问题进行建模。如果Xi和Yj是连续变量,这个问题将是polynomial(线性规划),可以使用以下方法解决:
因为这些变量都是整数(整数规划或混合整数规划),这个问题被称为NP_complete类的一部分(除非你是genious),否则无法使用多项式解来解决。像
COIN-OR
这样的解算器使用复杂的Branch & Bound或{a10}方法来有效地求解它们。ortools
为在python中使用COIN提供了一个很好的包装器。这些工具是免费和开源的。在所有这些方法的优点是在不迭代所有可能解的情况下找到一个最优解(并大大减少了组合运算)。在
相关问题 更多 >
编程相关推荐