繁体   English   中英

如何让Gurobi(使用R)显示所有解决方案

[英]How can I make Gurobi (Using R) show all solutions

正如问题所述:我知道有几种解决方案(参见GA的输出并检查值和约束是否正确),但我无法将它们从Gurobi中取出。

在@ Paleo13回答之后编辑 :正如他所说,他的回答是一个很好的工作。 但是,如果有更有效的选择,我也很乐意看到。 因此,我加了赏金。 在这里这里看到我所知道的。

可重复的例子:

my_fun <- function(x) {
  f <- sum(model$obj * x)
  penalty <- sum(abs(model$A %*% x - model$rhs))
  return_value <- -f - 1e8 * penalty # sum(model$obj^2) * // 1e7 * 
  return(return_value)
}

model <- structure(
  list(modelsense = "min", 
           obj = c(0, 40, 20, 40, 0, 20, 20, 20, 0), 
           A = structure(c(0, 0, 0, 0, 0, 0, 0, 0, 0, 1, -1, 0, 1, 0, 0, 1, 
                           1, 0, -1, 0, 0, 0, 0, -1, 1, 0, 0, 1, 0, 0, 0, 0, 
                           0, 0, 0, 0, 1, 0, 1, -1, 0, 0, 1, 0, -1, 0, 1, 0, 
                           0, 1, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0), 
                         .Dim = c(7L, 9L), 
                         .Dimnames = list(
                           c("constraint1", "constraint2", "", "", "", "", ""), 
                           NULL)),
           rhs = c(1, 1, 0, 0, 0, 1, 1), 
           sense = c("=", "=", "=", "=", "=", "=", "="), 
           vtype = "B"), 
      .Names = c("modelsense", "obj", "A", "rhs", "sense", "vtype"))

# Gurobi:
params <- list(OutputFlag = 1, Presolve = 2,  LogToConsole = 1, PoolSearchMode = 2, PoolSolutions = 10)
ilp_result <- gurobi::gurobi(model, params)
print(ilp_result$x)

# GA for cross-check
GA <- GA::ga(type = "binary", fitness = my_fun, nBits = length(model$obj),
             maxiter = 3000, run = 2000, popSize = 10, seed = 12)

# Crosscheck:
summary(GA)

my_fun(ilp_result$x)
my_fun(GA@solution[1, ])
my_fun(GA@solution[2, ])

sum(abs(model$A %*% ilp_result$x - model$rhs))
sum(abs(model$A %*% GA@solution[1, ] - model$rhs))
sum(abs(model$A %*% GA@solution[2, ] - model$rhs))

您所描述的内容可以通过解决方案池完成 Gurobi在8.0版中为解决方案池添加了R API。 您可以设置参数来控制解决方案池; 名为componentsSolution Pool中返回多个解决方案 这在poolsearch.R示例中进行了说明,该示例也可以在examples \\ R子目录中找到。

免责声明:我管理Gurobi的技术支持。

Gurobi确实可以存储在寻找最佳解决方案时遇到的可行解决方案(或者更确切地说是符合指定的opitmality间隙的解决方案)。 这些解决方案存储在“解决方案池”中。 遗憾的是, gurobi R软件包没有访问解决方案池中的解决方案的功能,因此如果我们正在寻找仅使用R的解决方案,那么我们就无法使用解决方案池。 此外,值得注意的是,解决方案池可能不一定包含所有可行的解决方案,它只包含Gurobi在此过程中发现的解决方案,因此如果我们需要所有可行的解决方案,那么我们不能仅仅依赖于单个解决方案池古罗比的奔跑

因此,关于您的问题,一种策略是使用称为“Bender's cut”的方法。 这基本上涉及解决问题,添加约束以禁止我们刚刚获得的解决方案,然后再次解决问题,并重复此过程直到没有任何更可行的解决方案。 我编写了一个使用下面的gurobi R包实现此方法的函数,并将其应用于您的示例。 这种方法可能无法很好地扩展到大量可行解决方案的问题,因为理想情况下我们会访问解决方案池以减少Gurobi运行的总数,但这是我所知道的最佳方法(但我很乐意听到)如果有人有任何更好的想法)。

# define functions
find_all_feasible_solutions <- function(model, params) {
  # initialize variables
  counter <- 0
  solutions <- list()
  objs <- numeric(0)
  # search for feasible solutions until no more exist
  while (TRUE) {
    # increment counter
    counter <- counter + 1
    # solve problem
    s <- gurobi::gurobi(model, params)
    # break if status indicates that no feasible solution found
    if (s$status %in% c("INFEASIBLE")) break()
    # store set of solutions
    solutions[[counter]] <- s$x
    objs[[counter]] <- s$objval
    # add constraint to forbid solution this solution
    model$rhs <- c(model$rhs, sum(s$x) - 1)
    model$sense <- c(model$sense, "<=")
    model$A <- rbind(model$A, (s$x * 2) - 1)
  }
  # throw error if no feasible sets of solutions found
  if (length(solutions) == 0) {
    stop("no feasible solutions found.")
  }
  # return solutions as matrix
  list(x = do.call(rbind, solutions), obj = objs)
}

# create initial model
model <- list(
  modelsense = "min",
   obj = c(0, 40, 20, 40, 0, 20, 20, 20, 0),
   A = structure(c(0, 0, 0, 0, 0, 0, 0, 0, 0, 1, -1, 0, 1, 0, 0, 1,
     1, 0, -1, 0, 0, 0, 0, -1, 1, 0, 0, 1, 0, 0, 0, 0,
     0, 0, 0, 0, 1, 0, 1, -1, 0, 0, 1, 0, -1, 0, 1, 0,
     0, 1, 0, 0, -1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0),
    .Dim = c(7L, 9L),
    .Dimnames = list(c("constraint1", "constraint2", "", "", "", "", ""),
                     NULL)),
  rhs = c(1, 1, 0, 0, 0, 1, 1),
  sense = c("=", "=", "=", "=", "=", "=", "="),
  vtype = "B")

# create parameters
params <- list(OutputFlag = 1, Presolve = 2,  LogToConsole = 1)

# find all feasible solutions
output <- find_all_feasible_solutions(model, params)

# print number of feasible solutions
print(length(output$obj))

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM