问题
I have the following data frames:
Required <- data.table( Country=c("AT", "BE", "BG", "CY"),Mat1=c(0,5,0,5),Mat2=c(0,3,2,0),Mat3=c(10,2,0,12))
Supplied <- data.table( Country=c("AT", "BE", "BG", "CY"),Mat1=c(0,4,0,10),Mat2=c(20,20,20,0),Mat3=c(8,10,0,10))
> Required
Country Mat1 Mat2 Mat3
1: AT 0 0 10
2: BE 5 3 2
3: BG 0 2 0
4: CY 5 0 2
> Supplied
Country Mat1 Mat2 Mat3
1: AT 0 20 8
2: BE 4 20 10
3: BG 5 20 0
4: CY 10 0 10
"Required" shows the requirement of three types of materials to different countries, while "Supplied" shows the supply capacity of these countries. I seek to apply an optimization algorithm by which the "Required" data frame is modified according to the supply capacity. For instance, 5 units of "Mat1" are required to the country "BE", while it can only supply 4 units. The algorithm should look for the less constrained country to supply this material, in this case countries "BG" and "CY" both have 5 units "available". The less constrained country is thus the one that has the most units of material available in absolute terms.
The resulting requirement table "RequiredNew" should thus be:
> Required
Country Mat1 Mat2 Mat3
1: AT 0 0 8
2: BE 4 3 3
3: BG 0.5 2 0
4: CY 5.5 0 3
Any ideas on how to proceed? This is an example and the actual table is quite bigger, so I seek a programatical approach.
Many thanks in advance.
回答1:
This is a little bit convoluted, but it should work:
library(data.table)
Required <- data.table( Country=c("AT", "BE", "BG", "CY"),Mat1=c(0,5,0,5),Mat2=c(0,3,2,0),Mat3=c(10,2,0,2))
Supplied <- data.table( Country=c("AT", "BE", "BG", "CY"),Mat1=c(0,4,5,10),Mat2=c(20,20,20,0),Mat3=c(8,10,0,10))
# I prefer to work with matrices, so here I turn Required and Supplied into matrices
req <- as.matrix(Required[,-1,with=FALSE])
row.names(req) <- Required$Country
sup <- as.matrix(Supplied[,-1,with=FALSE])
row.names(sup) <- Supplied$Country
# create a copy of Required data.table to contain the result (we'll overwrite the values)
RequiredNew <- copy(Required)
# for each material...
for(col in 1:(ncol(req))){
# for each country we compute the remaining stock and requirement after satisfying itself
netreq <- req[,col] - sup[,col]
netreq[netreq < 0] <- 0
netstk <- sup[,col] - req[,col]
netstk[netstk < 0] <- 0
# we loop until we satisfy all the requirements or we finish the stock
finalreq <- req[,col] - netreq
while(sum(netreq) > 0 && sum(netstk) > 0){
maxavailidxs <- which(netstk == max(netstk))
requiredqty <- min(sum(netreq),sum(netstk[maxavailidxs]))
deltareq <- (requiredqty * netreq) / sum(netreq)
deltastk <- rep(0,length(netstk))
deltastk[maxavailidxs] <- requiredqty / length(netstk[maxavailidxs])
netreq <- netreq - deltareq
netstk <- netstk - deltastk
finalreq <- finalreq + deltastk
}
# we set the current material final requirement column into the result data.table
set(RequiredNew,NULL,col+1L, finalreq)
}
RequiredNew
> RequiredNew
Country Mat1 Mat2 Mat3
1: AT 0.0 0 8
2: BE 4.0 3 3
3: BG 0.5 2 0
4: CY 5.5 0 3
来源:https://stackoverflow.com/questions/31923107/mathematical-optimization-in-r