【问题标题】:Optimization with positive integer parameters使用正整数参数进行优化
【发布时间】:2014-03-07 02:19:01
【问题描述】:

我需要解决一个需要比较具有相同列数的两个矩阵的问题。操纵其中之一,直到获得最佳匹配。我对两个矩阵之间的差异进行评分的方式非常复杂,我仍然需要最终确定它。我目前真正感兴趣的是找到一种仅适用于正整数的搜索/优化算法。我创建了一个简单的示例,其中包含一个简单的函数来最大化。假设我有一个数据集 D。

 D <- data.frame(rbind(c(1,1,1),
                       c(1,1,0),c(1,1,0),c(1,1,0),c(1,0,0),
                       c(0,0,0),c(1,0,0),c(1,0,0),c(1,1,0),
                       c(1,0,0),c(1,1,1),c(1,1,0),c(1,0,0),
                       c(1,0,0),c(1,0,1)))

我想找出 Dx 的哪个重新排列给我的绝对差值最小。

Dx<-data.frame(rbind(c(1,1,0),c(1,0,0),c(0,0,0),c(1,1,0)))

所以我可以使用下面的函数遍历所有可能的排列

    library(combinat)
    SPACE <- t(as.data.frame(list(permn(1:3))))
    f <- function(x){
      if(anyDuplicated(x)>0){return(0)}
      Dist<-NA
      for (i in 1:nrow(D)){
        Dist[i]<-sum(abs(Dx[,x]-t(D[i,])))} 
    return(sum(Dist))}
apply(SPACE,1,f)

并获得正确的结果。但是这对我实际使用的数据有两个缺点:

  1. 我必须指定空格 - 所有可能的列顺序和
  2. apply 遍历每个可能的排列并计算我的错误分数。

随着矩阵中列数的增加,A 和 B 都变得计算困难。我认为在大多数计算机上,即使在一个 R 会话中保留数字 1 到 14 的所有可能排列也是不可能的。

我发现的一种优化算法是网格搜索。这开始解决 A。这意味着我不必指定 SPACE(即所有可能的排列),因此这是朝着正确方向迈出的一步,因为我想查看更大的数据集。

library(NMOF)
gridSearch(f, rep(list(seq(1,ncol(D))),ncol(D)))

但显然这并没有解决 B,因为它经历了每个可能的迭代。如果我的数据集非常大,比如说 15 列甚至更多列怎么办?

请记住,我的参数只能是正整数(即它们是列号),是否有一种 R 算法可以让我在合理数量的范围内找到最佳列顺序(或至少是一个很好的近似值)时间(例如 1-2 天),当我处理更大的数据集时?这可能看起来像一个愚蠢的例子,但它很好地模拟了我试图解决的问题。我试过optim()method="SANN",但没有成功。不幸的是,我的经验很少,所以如果您认为这是一个不可行的问题,请告诉我。只是从一个更简单的数据集(几行但很多列)问题开始,您是否认为可以通过使用某种巧妙的优化来找到如上所示的 D2 的最佳列顺序?

   #D2
D<-cbind(D,D,D,D,D)
ncol(D)
Dx<-cbind(Dx,Dx,Dx,Dx,Dx)
#examples 
f(c(1,2,3,4,5,6,7,8,9,10,11,12,13,14,15))
f(c(13,2,4,3,5,6,7,8,9,10,11,12,1,14,15))

编辑: 我的主要兴趣是了解如何使用在搜索过程中使用一系列独特的正积分(基本上是排名)的优化算法,而不是解决这个特定问题。在这种情况下,我使用了一个简单的示例,以便于复制,但是我比较的两个数据集通常在行数和其他方面有所不同,我在这里没有详细说明......距离函数 I' m building 可以很好地处理这个问题,因此了解如何使用 D2 将优化算法(例如下面建议的遗传算法)应用于上述函数 f 因此是我目前的主要问题。

【问题讨论】:

  • 也许遗传算法方法可以帮助您?
  • 费尔南多,非常感谢。你能告诉我如何将这种方法应用于上面的 f 函数吗?
  • 查看gaoptim 包中的GAPerm 函数,它执行排列优化(类似TSP 的问题)。
  • 谢谢。我看过了,我不太明白如何告诉函数我需要正整数...
  • 我会看看我能想出什么,然后我会再次在这里发布。

标签: r permutation mathematical-optimization genetic-algorithm maximize


【解决方案1】:

如果您的目标函数f 必须真正被视为一个黑匣子,那么我们将需要求助于近似方法,例如遗传算法。这是使用gaoptim 包的解决方案,它在Dx 的列的所有排列p 中最大化f(p)

library(gaoptim)
myGA = GAPerm(f, ncol(Dx), popSize=10)
myGA$evolve(10)
myGA
# Results for 10 Generations:
# Mean Fitness:
#    Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
#    95.0   107.4   115.6   112.4   118.3   120.6 
# 
# Best Fitness:
#    Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
#     125     125     125     125     125     125
# 
# Best individual:
# [1] 3 1 2
# 
# Best fitness value:
# [1] 125

在这种情况下,它找到了可能的最佳解决方案,目标值为 125,但通常不能保证遗传算法将返回的解决方案的质量。

【讨论】:

    【解决方案2】:

    据我了解,您正在搜索从一组候选列到一组目标列的最佳分配,并且将候选列与目标列匹配会产生一些成本。您正在寻找能够最大限度降低总成本的一对一匹配。

    这称为赋值问题,是运筹学中的经典问题。您的网格搜索方法将具有指数运行时间(您需要搜索所有可能的分配),但是对于这个问题有更有效的方法,其中许多依赖于线性规划。

    您可以使用 lpSolve 包中的 lp.assign 函数在 R 中解决您的问题,提供矩阵列之间的成对距离:

    # Build cost matrix
    costs <- as.matrix(dist(t(D), method="manhattan"))
    costs
    #    X1 X2 X3
    # X1  0  7 11
    # X2  7  0  6
    # X3 11  6  0
    
    # Solve assignment problem
    library(lpSolve)
    solution <- lp.assign(costs)$solution
    apply(solution > 0.999, 2, which)
    # [1] 1 2 3
    

    这意味着我们选择了排列 1、2、3 作为最有希望的排列。

    【讨论】:

    • 非常感谢您的回答。不幸的是,我的距离算法着眼于不同数据集的行之间的距离,并且非常复杂,因此我无法创建一个简洁的成本矩阵。你认为有一种方法可以在某种优化引擎中使用上面的 f 函数吗?抱歉,如果这听起来有点奇怪,再次感谢您尝试找到更简单的解决方案,但我需要依赖一个距离函数,该函数返回一个给定排列的数字(有点像上面的 f)。
    • 您将使用的工具实际上取决于成本函数本身。通常我会使用线性或整数编程来解决这样的问题,但这是否合适取决于函数。我建议编辑问题以提供更多详细信息,因为您的最小可重现示例似乎“太少了”。
    • 感谢您的 cmets。我试图举一个更好的例子。
    • 我想知道您概述的技术是否可以用于我需要的东西。假设我们选择 Dx 作为参考,然后建立 Dx 与其自身的 200 列重排之间的距离:我们将这些 DxR1 称为 DxR200,其中 DxR200 是与原始 Dx 最不同的 Dx 的重排。然后我们可以在前 200 个解决方案上运行函数 f(可能使用 optim?)- 如果 DxR200 是根据 f 重新排列的“最佳”列,那么我们可能需要重复该过程,但这次以 DxR200 作为参考。然后我们重复这个过程,直到达到最小值....
    • 您需要将其表述为优化问题并使用lpSolve 包中的lp 函数而不是lp.assign 便利函数来求解。您可以将其作为一个新问题发布并从社区获得一些帮助。
    猜你喜欢
    • 1970-01-01
    • 2018-09-01
    • 2018-08-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-01-07
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多