为分配/指派问题建立线性规划

rue*_*ued 3 optimization r linear-programming operations-research

我在线性程序方面遇到了一些麻烦,我已经解决并使用 Excel,但现在我想在 R/Python 中执行它,因为我已经达到了 Excel 和求解器的限制。因此,我就这个特定主题寻求帮助。

我通过改变 lp.assign 函数尝试使用 lPsovle 包,但我无法想出解决方案。

问题如下:

假设我是商品的交付者。

我有不同的仓库,服务于不同的区域。这些地区必须满足他们的需求。另一方面,我的仓库的处理和交付能力受到限制。一个站点可以服务多个区域,但一个区域只能由一个站点服务。

我有仓库和区域之间连接的距离/成本矩阵以及该区域的需求。

该解决方案的目标应该是以尽可能最小的努力为这些区域提供服务。

假设成本/距离矩阵如下所示:

assign.costs <- matrix (c(2, 7, 7, 2, 7, 7, 3, 2, 7, 2, 8, 10, 1, 9, 8, 2,7,8,9,10), 4, 10)
Run Code Online (Sandbox Code Playgroud)

因此,这创建了我的矩阵,其中第一行/标题中包含客户/区域,第一列/行名称中包含仓库。

现在地区/客户的需求是:

assign.demand <- matrix (c(1,2,3,4,5,6,7,8,9,10), 1, 10)
Run Code Online (Sandbox Code Playgroud)

容量限制,存款可以提供的金额是:

assign.capacity <- matrix (c(15,15,15,15), 4, 1)
Run Code Online (Sandbox Code Playgroud)

所以现在我希望这个问题可以通过 lp 来解决,以生成分配,根据这些限制,哪个区域应该由哪个仓库提供服务。

结果应该是这样的:

assign.solution <- matrix (c(1,0,0,0 ,0,1,0,0, 1,0,0,0, 1,0,0,0 ,0,0,0,1), 4, 10)
Run Code Online (Sandbox Code Playgroud)

至于限制,这意味着每一列最多只能有一个。

我尝试使用 lpSolve 中的 lpsolve 和 lp.assign 函数,但我不知道如何实现我所拥有的确切类型的限制,并且我已经尝试更改 lp.assign 函数,但没有成功。如果有帮助的话,我还可以制定 lp 的方程。

谢谢大家的帮助,我现在真的很困难:D

BR

Erw*_*gen 6

步骤 1. 建立数学模型

数学模型可以如下所示:

在此输入图像描述

蓝色条目表示数据,红色条目表示决策变量。i是仓库,j是客户。Ship指示我们是否从i运送到j(它是一个二进制变量)。第一个约束条件是从仓库i发货的总量不应超过其容量。第二个约束条件是每个客户j必须恰好有一个供应商i

步骤 2. 实施

现在这只是一个精确的问题。我尽可能严格地遵循上一节中的模型。

library(dplyr)
library(tidyr)
library(ROI)
library(ROI.plugin.symphony)
library(ompr)
library(ompr.roi)

num_depots <- 4
num_cust <- 10

cost <- matrix(c(2, 7, 7, 2, 7, 7, 3, 2, 7, 2, 8, 10, 1, 9, 8, 2,7,8,9,10), num_depots, num_cust)
demand <- c(1,2,3,4,5,6,7,8,9,10)
capacity <- c(15,15,15,15)

m <- MIPModel() %>%
  add_variable(ship[i,j], i=1:num_depots, j=1:num_cust, type="binary") %>%
  add_constraint(sum_expr(demand[j]*ship[i,j], j=1:num_cust) <= capacity[i], i=1:num_depots) %>% 
  add_constraint(sum_expr(ship[i,j], i=1:num_depots) == 1, j=1:num_cust) %>% 
  set_objective(sum_expr(cost[i,j]*ship[i,j], i=1:num_depots, j=1:num_cust),"min") %>% 
  solve_model(with_ROI(solver = "symphony", verbosity=1))

cat("Status:",solver_status(m),"\n")
cat("Objective:",objective_value(m),"\n")
get_solution(m,ship[i, j]) %>%
  filter(value > 0) 
Run Code Online (Sandbox Code Playgroud)

我们看到首先写下一个数学模型是多么重要。它比一堆代码更紧凑、更容易推理。直接编写代码通常会导致各种问题。就像盖房子没有蓝图一样。即使对于这个小例子,写下数学模型也是一个有用的练习。

对于实现,我使用 OMPR 而不是 LpSolve 包,因为 OMPR 让我更接近数学模型。LpSolve 有一个矩阵接口,除了非常结构化的模型之外,很难使用。

第三步:解决它

Status: optimal 
Objective: 32 
   variable i  j value
1      ship 1  1     1
2      ship 4  2     1
3      ship 2  3     1
4      ship 1  4     1
5      ship 3  5     1
6      ship 4  6     1
7      ship 4  7     1
8      ship 2  8     1
9      ship 1  9     1
10     ship 3 10     1
Run Code Online (Sandbox Code Playgroud)

我相信这是正确的解决方案。