【问题标题】:R - Combinations of a dataframe with constraintsR - 数据框与约束的组合
【发布时间】:2015-12-27 21:34:08
【问题描述】:

我正在尝试为梦幻足球(正确的英国足球,而不是手蛋 :-))制作一个 R 脚本,我可以在其中输入 csv 中的球员列表,它会输出每 11 名球员的组合,其中满足各种约束。

这是我的示例数据框:

df <- read.csv("Filename.csv",
               header = TRUE)
    > print(df)
                       Name Positon Team   Salary
    1             Eric Dier       D  TOT  9300000
    2          Erik Pieters       D  STO  9200000
    3       Christian Fuchs       D  LEI  9100000
    4       Héctor Bellerín       D  ARS  9000000
    5       Charlie Daniels       D  BOU  9000000
    6            Ben Davies       D  TOT  8900000
    7    Federico Fernández       D  SWA  8800000
    8       Per Mertesacker       D  ARS  8800000
    9        Alberto Moreno       D  LIV  8700000
    10       Chris Smalling       D  MUN  8700000
    11       Seamus Coleman       D  EVE  8700000
    12       Jan Vertonghen       D  TOT  8700000
    13        Romelu Lukaku       F  EVE 12700000
    14           Harry Kane       F  TOT 12500000
    15           Max Gradel       F  BOU 11900000
    16       Alexis Sánchez       F  ARS 11300000
    17          Jamie Vardy       F  LEI 11200000
    18         Theo Walcott       F  ARS 10700000
    19       Olivier Giroud       F  ARS 10700000
    20        Wilfried Bony       F  MCI 10000000
    21 Kristoffer Nordfeldt       G  SWA  7000000
    22             Joe Hart       G  MCI  6800000
    23            Jack Rose       G  WBA  6600000
    24        Asmir Begovic       G  CHE  6600000
    25           Mesut Özil       M  ARS 15600000
    26         Riyad Mahrez       M  LEI 15200000
    27         Ross Barkley       M  EVE 13300000
    28        Dimitri Payet       M  WHM 12800000
    29              Willian       M  CHE 12500000
    30      Bertrand Traore       M  CHE 12500000
    31      Kevin De Bruyne       M  MCI 12400000

并且约束如下:

1) 每个11人阵容的总工资不能超过100,000,000

2) 一支球队最多只能有四名球员。例如。来自“CHE”(切尔西)的四名球员。

3) 每个 11 人阵容中每个位置的球员人数都有限制。可以有:

1 G(守门员),3 到 4 D(后卫),3 到 5 M(中场),1 到 3 F(前锋)

我希望退回符合上述限制的每 11 个玩家组合。顺序并不重要(例如,1,2,3 被认为与 2,1,3 相同,不应重复),一名球员可以出现在多个阵容中。

我已经进行了相当多的研究并玩过,但似乎对此一无所知。我是 R 的新手。我不希望有人为我解决这个问题,但如果有人可以为像我这样的新手指出正确的方向,我将不胜感激。

谢谢。

【问题讨论】:

  • 您为每个约束尝试了什么?代码在哪里?
  • 我不知道您的 csv 文件中有多少玩家,但希望您意识到从 31 件事情中选择 所有可能 11 件套,不管顺序,让你84,672,315 个组合进行测试。这里没有简单的出路。您必须根据您的规范构建构建团队的算法,我认为任何库在这里都没有特别的帮助。
  • @kliron:作者描述的问题是一个经典的约束满足问题。这些问题在人工智能中很常见。您答案的第一部分假设问题是使用对接技术解决的。第二部分指向正确的方向。事实上,这些都可以使用任何 CSP 求解器来解决,它们会进行某种巧妙的解决方案构建。幸运的是,有很多算法和库。第一:基于搜索的算法,我不会在 R 中实现/期望。第二算法将问题转化为优化问题,基本上是一组线性方程。
  • 在下面查看我的评论。感谢 LPSolve 的提示,我不知道那个库。

标签: r


【解决方案1】:

这可以使用库 LPSolve 作为线性整数程序求解。 这类问题可以很好地解决——与之前写过的相反——因为典型的解决方案的数量远小于域的大小。

您可以为每个玩家添加一个零一变量,无论该玩家是否在团队中。

可以使用安装包

 install.packages("lpSolve")
 install.packages("lpSolveAPI")

文档位于:https://cran.r-project.org/web/packages/lpSolve/lpSolve.pdf

玩家的第一个约束总和 11

工资基本上是所有球员变量的总和乘以工资列等等......

要获得正确的解决方案,您需要在

中指定
lp.solve(all.bin=TRUE

这样所有涉及玩家的变量要么为零,要么为一。

(我知道您正在努力学习,这就是为什么我不给出完整的解决方案)

编辑 因为我可能因为没有给出完整的解决方案而被否决。正如原作者明确写的那样,他并不期待一个完整的解决方案,有点可悲

library(lpSolve)

df <- read.csv("/tmp/football.csv",header = TRUE,sep=";")

f.obj <- rep(1,nrow(df))

f.con <- 
  matrix(c(f.obj <- rep(1,nrow(df)),
    as.vector(df$Salary),
    (df$Positon=="G") *1.0,
    (df$Positon=="D") *1.0,
    (df$Positon=="D") *1.0,
    (df$Positon=="M") *1.0,
    (df$Positon=="M") *1.0,
    (df$Positon=="F") *1.0,
    (df$Positon=="F") *1.0),nrow=9,byrow= TRUE)

f.dir <- c("==", "<=","==",">=","<=",">=","<=",">=","<=")

f.rhs<- c(11, #number players
       100000000, #salary
       1 , #Goalkeeper
       3 , # def min
       4 , # def max
       3 , # mdef min
       5,  # mdef max
       1,  # for, min
       3  # wor, max
       )



solutions <-   lp ("max", f.obj, f.con, f.dir, f.rhs,all.bin=TRUE)

我没有添加团队约束,因为它不会在这里提供任何额外的见解......

** EDIT2 ** 如果您更改数据集,这可能会派上用场 R lpsolve binary find all possible solutions

【讨论】:

  • 就目前的答案而言,与其说是答案,不如说是评论。
  • @Jaap:问题作者明确写道:我不希望任何人为我解决这个问题,因此我只给出了指示。
  • 现在好多了! (+1)
  • 感谢好友的回复。我使用 LPSolve 的经验为零,因此可能需要阅读。
【解决方案2】:

解决这个问题的蛮力方法(它也可以很好地并行化并保证您所有可能的组合)是计算所有 11 位玩家的排列,然后过滤掉不适合的组合逐步符合您的限制。

要使这样的程序适合您的计算机内存,请给每个玩家一个唯一的整数 ID,并创建 ID 向量作为团队集。然后,当您实现过滤器时,您的函数可以通过该 ID 在单个数据框中引用播放器信息。

假设df 是您包含所有玩家数据的数据框。

df$id <- 1:nrow(df)

获取所有id组合:

# This will take a long time or run out of memory!
# In my 2.8Gz laptop took 466 seconds just for your 31 players
teams <- combn(df$id, 11) 

当然,如果您的数据框很大(如数百名玩家),则此实现可能需要很长时间才能完成。您最好只从您的球员组中抽取 11 组而不进行替换,并以“按需”方式构建团队。

一种更聪明的方法是根据球员位置将数据集划分为 - 一个用于守门员,一个用于防守等。然后使用上述方法从每个位置创建不同球员的排列并组合最终结果。这将花费更少的时间,它仍然可以并行化和详尽(给你所有可能的组合)。

【讨论】:

  • 作者描述的问题是一个经典的约束满足问题。在单一类别的问题中,通常存在相变,将一个类别的实例分为三组。那些很容易找到解决方案的,那些没有解决方案的和那些 NP 难以解决的(相变中的那些)。您的解决方案很可能只会在解决实例的琐碎中找到解决方案。有专门用于 CSP 的基于采样的算法。但我建议使用 R 作为任何这些算法的实现语言。
  • 感谢您的回复。我喜欢这种方法;主要是因为像我这样的编程新手可以准确地理解代码在做什么。我想下一步是使用 for 循环通过约束过滤原始组合。
  • @CAFEBABE 如果您指的是组合搜索方法,我已经说明了局限性并暗示了启发式方法可以将无法解决的问题变为可解决的问题。我的目的不是给出一个正式的、通用的解决方案,而是指出 OP 解决这个问题的有趣方向。
  • 问题不在于组合探索本身。组合爆炸有很多问题,很容易解决。你的想法是在许多任务都是解决方案的假设下起作用的。但是,当您尝试解决 OP 问题时,采样问题就很明显了。分区的问题是您只能沿一个变量进行分区。然而,有 2 个复杂的约束条件(团队+价格)需要更精细的技术。一点理论基础:很可能找到一个单人任务已经是 NP。因此,问题类别是#P... ;)
猜你喜欢
  • 1970-01-01
  • 2019-09-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-07-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多