您可以使用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