您可以使用lpSolve
包解决您的问题。
您将需要一个成本向量和约束条件信息。在以下结构送入功能限制信息:
lhs
:系数的“左手侧”矩阵,每一个决策变量
dir
:a“方向”,即<
,<=
, ==
,>=
,>
rhs
:一个 “右手边” 的数值
要建立您的合作名单nstraints,我觉得可以考虑每个可能作为X的决定(成为lhs
表中的一列),并且您希望将每个约束定义为一个单独的等式(成为lhs
表中的一行,其中有一个分别dir
和rhs
对应的值)
让我们从所有可能的决定:
library(tidyverse)
library(stringr)
# What are the decision variables? ----
# Which action to take
actions <- str_c('A',seq(1:12) %>% formatC(width = 2, flag = '0'))
actions
#[1] "A01" "A02" "A03" "A04" "A05" "A06" "A07" "A08" "A09" "A10" "A11" "A12"
# When to take it
timings <- str_c('T',seq(1:12) %>% formatC(width = 2, flag = '0'))
timings
#[1] "T01" "T02" "T03" "T04" "T05" "T06" "T07" "T08" "T09" "T10" "T11" "T12"
# List of all possible decisions is this:
decisions <- expand.grid(actions, timings)
# Convert it to a vector
decision_variables <- str_c(decisions[,1], '_', decisions[,2])
# You also need a cost vector.
# We'll use a value increasing as a function of timings,
# as this will penalize "late" actions?
cost <- rep(seq(1:length(timings)), length(actions)) %>% sort
的decision_variables
每个元素都是一个可能的动作(即在给定的时间采取行动。现在我们可以通过引入限制来缩小解算器可用的选项范围。
第一种类型的约束:每个选项只应采取一次! (这实际上是你的第三位,但我开始用这个,因为它是最简单的一种) 我们制定的是这样的:
# Create a matrix with one column per possible decision
# and one row per action (for now)
lhs <- matrix(0,
nrow = length(actions),
ncol = length(decision_variables),
dimnames = list(
actions,
decision_variables))
# Each action should only be taken once!
for (i in 1:length(actions)) {
# Which fields does an action occur in?
this_action <- str_detect(colnames(lhs), actions[i])
# Set their coefficients to 1
lhs[i,this_action] <- 1
}
# create corresponding dir and rhs values
dir <- rep('==', length(actions))
rhs <- rep(1, length(actions))
你可以看到,我们将所有X
的系数(决定)其中包含action
至1
。在我们的最终解决方案中,每个X
将采用0
或1
的值。如果X
为零,则系数将不相关。如果X
是1
,则系数将被添加到lhs
的总和中,并使用dir
与rhs
的值进行比较。
这里,我们的约束条件是我们刚刚介绍的每个约束的总和为coefficient * X == 1
。对于包含给定动作的所有可能的决定,系数是1。艾尔戈,一个解决方案只有在任何给定的行动只被采取一次是有效的。
第二个限制:只有两个c('A03', 'A05', 'A06')
应该在某一天同时出现。
再一次,我们为每个约束生成一行。在这种情况下,我认为我们每天需要一个约束。我们,我们将生成值附加到现有lhs
,dir
和rhs
变量:
# only one of A3, A5, A6 at any given time.
# One constraint for each timestep
for (j in timings) {
lhs <- rbind(lhs, ifelse(str_detect(decision_variables, paste0('A0[356]{1}_',j)), 1, 0))
dir <- c(dir, '<=')
rhs <- c(rhs, 2)
}
占位符的第三个约束
转眼间,我们已经制定了我们的问题。现在让lpSolve
紧缩数字! 您可以养活我们的问题转化为算法是这样的:
library(lpSolve)
# Run lpSolve to find best solution
solution <- lp(
# maximise or minimise the objective function?
direction = 'min',
# coefficients of each variable
objective.in = cost,
const.mat = lhs,
const.dir = dir,
const.rhs = rhs)
# Extract the values of X for the best solution:
print(solution$solution)
# Convert it into ta matrix of the format you are familiar with
matrix(solution$solution,
nrow = length(timings),
ncol = length(actions),
dimnames = list(actions, timings))
这是不是你所需要的?
有任何问题吗?
在我看来,就像一个小而直的MIP问题。不明白为什么这会在R. –
中造成问题。回答下面的两个约束。现在我想不出一种优雅的方式去做最后一个(“A2应该发生在A1之后”)。在Excel解决方案中如何以及如何制定? – JanLauGe
@JanLauGe,在excel中,对于这个约束,我将每一行的SUMPRODUCT与时间(我创建了一个序列1,2,...,12)并且差异应该是'> ='1。例如 - SUMPRODUCT(row2,timesequence) - SUMPRODUCT(row1,timesequence)> = 1'。希望,这回答你的问题。谢谢! – honey