循环遍历R中的一组项目

问题描述 投票:0回答:2

我正在尝试模拟线性编程问题。该模型具有obj函数和一些约束。在这种情况下,我引入了2个从正态分布中随机抽取的值。

然后我使用for循环模拟10.000次优化模型。我知道使用for循环是不好的R练习,但在这种情况下速度不是我的关注。

#List of 10000 random, normally distributed observations:
Demand = rnorm(10000, mean=5, sd=2.5)
Demand

Performance = rnorm(10000, mean=100, sd=6)
Performance

Optimas = NULL

#combined_list = c(Demand, Performance)

for (i in Performance){
    op <- OP(objective = c(2.5, 4, i),               #Performance value[i]: works fine 
             L_constraint(L = matrix(c(1, 0, 0,      #LHS
                                       0, 1, 0,       
                                       0, 0, 1),      
                                      ncol=3, nrow = 3, 
                                      byrow = TRUE), 
                          dir = c("<=", "<=", "<="), 
                          rhs = c(50, 70, Demand)),  #Demand value[i]: should go here
              maximum = TRUE,
              types = c("B", "I", "I"))  

    Optima <- ROI_solve(op, solver = "glpk") #solve
    print(Optima)
    print(i)
    Optimas = rbind(Optimas, Optima)
}


Optimas <- as.data.frame(Optimas)
Optimas$objval <- as.numeric(Optimas$objval)
hist(Optimas$objval)

如上所示,我的循环仅通过一个变量(性能),其中我希望将需求向量中的行(i)的需求值放入模型中,同时将行(i)的性能值放入在性能向量中。

总体目标是对模型进行10.000次模拟,其中性能值和需求值仅出现一次(因为我已经拥有的那个之外的另一个循环将产生两个列表的笛卡尔积)。

r loops linear-programming solver normal-distribution
2个回答
1
投票

请注意,您的PerformanceDemand向量包含完全相同数量的元素。因此,您可以简单地循环遍历矢量索引并使用相应的索引值来提取相关元素。

我无法运行您的示例代码,因为我不确定您为OP函数使用哪个优化包。作为一个例子,我将定义一个简单的dummyFunction,它将性能和需求值作为输入,如下所示:

dummyFunction <- function(perf, dem){ return (perf+dem)}

在您的特定用例中,dummyFunction将包含优化逻辑。接下来,您可以通过迭代向量索引获得如下所需的解决方案:

Optimas = vector(mode="numeric", length=length(Performance))
for(idx in 1:length(Performance)){
  Optimas[idx] <- dummyFunction(Performance[idx], Demand[idx])
}

或者,您可以通过将优化逻辑放在for循环中来避免函数定义。对于更“R类似的解决方案”,考虑使用sapply / lapply类型函数:

Optimas <- sapply(1:length(Performance), function(idx) dummyFunction(Performance[idx], Demand[idx]))

请注意,在此特定示例中,您还可以执行以下操作:

Optimas <- dummyFunction(Performance, Demand)

最后,如果性能成为问题,请考虑使用foreachdoparallel包同时在多个内核上运行优化:

library(doParallel)
library(foreach)
nrCores <- detectCores()
cl <- makeCluster(nrCores); registerDoParallel(cl)
clusterExport(cl,c("Demand", "Performance", "dummyFunction"), envir=environment())
Optimas <- foreach(idx=1:length(Performance), .combine="rbind") %dopar%{
  dummyFunction(Performance[idx], Demand[idx])
}
stopCluster(cl)

0
投票

考虑一个mapply()方法,apply函数迭代多个列表/向量传递相应的元素。首先在函数中包装所有操作,然后在mapply()中调用它,为向量传递两个参数。最后,使用lapply()转置为与do.call(rbind...)绑定行的数据帧的长列表。

Performance = rnorm(10000, mean=100, sd=6)
Demand = rnorm(10000, mean=5, sd=2.5)

optimizefct <- function(p, d){
  op <- OP(objective = c(2.5, 4, p),               # Performance 
           L_constraint(L = matrix(c(1, 0, 0,      # LHS
                                     0, 1, 0,       
                                     0, 0, 1),      
                                   ncol=3, nrow = 3, 
                                   byrow = TRUE), 
                        dir = c("<=", "<=", "<="), 
                        rhs = c(50, 70, d)),       # Demand
           maximum = TRUE,
           types = c("B", "I", "I"))  

  Optima <- ROI_solve(op, solver = "glpk") #solve
  print(Optima)
  print(i)

  return(Optima)
}

# WIDE FORMAT
dfList <- mapply(optimizefct, Performance, Demand)

# LONG FORMAT
dfList <- lapply(1:10000, function(i) data.frame(dfList[,i]))

# BIND TO FINAL DF
Optimas <- do.call(rbind, dfList)
Optimas$objval <- as.numeric(Optimas$objval)
© www.soinside.com 2019 - 2024. All rights reserved.