使用正整数参数进行优化

时间:2014-02-25 18:15:13

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

我需要解决一个问题,即需要比较具有相同列数的两个矩阵。其中一个被操纵,直到获得最佳匹配。我对两个矩阵之间的差异进行评分的方式非常复杂,我仍然需要最终确定它。我现在真正感兴趣的是找到一个仅使用正整数的搜索/优化算法。我创建了一个简单的示例,其中包含一个最大化的简单函数。假设我有一个数据集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. 我必须指定SPACE-所有可能的列顺序和
  2. apply会检查每个可能的排列并计算我的错误分数。
  3. 随着矩阵中列数的增加,A和B都变得难以计算。我认为即使在一个R会话中保留数字1到14的所有可能排列在大多数计算机上也是不可能的。

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

    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是我目前的主要问题。

2 个答案:

答案 0 :(得分:3)

如果您的目标函数f必须真正被视为黑盒子,那么我们需要采用近似方法,例如遗传算法。以下是使用gaoptim包的解决方案,该解决方案在f(p)列的所有排列p中最大化Dx

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,但通常不保证遗传算法将返回的解决方案的质量。

答案 1 :(得分:2)

据我了解,您正在搜索从一组候选列到一组目标列的最佳分配,并且将候选列与目标列匹配会产生一些成本。您正在搜索最小化总体成本的一对一匹配。

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

您可以使用lp.assign包中的lpSolve函数在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作为最有希望的。