我有一个包含135种食物的数据集,我用它们来解决饮食问题:最小化成本和最大化营养价值。我想创建一个包含多种食物的模型,而不是告诉我每周只吃80份土豆和50份菠菜。我想:
1)设定食物份数的上限(即每种食物最多10份),不改变其他变量(如食物组)的上限和下限
2)能够指定我在模型中想要的食物(/变量)的最小数量
现在,我正在写出模型中的所有变量,除了指定纤维、卡路里、水果盎司、蔬菜盎司等的最小值和最大值之外:
minCost <- lp("min", SNAP$costPerServ,
rbind(SNAP$protPerServ, SNAP$protPerServ, SNAP$fatPerServ,
SNAP$fatPerServ, SNAP$costPerServ, SNAP$costPerServ, SNAP$sodiumPerServ,
SNAP$sodiumPerServ, SNAP$fiberPerServ, SNAP$fiberPerServ, SNAP$sugarPerServ,
SNAP$sugarPerServ, SNAP$calsPerServ, SNAP$calsPerServ, SNAP$fruit, SNAP$vegs,
SNAP$grains, SNAP$grains, SNAP$meatProtein, SNAP$dairy, SNAP$X1, SNAP$X2,
SNAP$X3, SNAP$X4, SNAP$X5, SNAP$X6, SNAP$X7, SNAP$X8, SNAP$X9, ... [more foods
here] ..., SNAP$X135),
c(">=", "<=", ">=", "<=", ">=", "<=", ">=", "<=", ">=", "<=", ">=",
"<=", ">=", "<=", ">=", ">=", ">=", "<=", ">=", ">=",
"<=", "<=", "<=", "<=", "<=", "<=", "<=", "<=", "<=",
"<=", ...[more "<="s here]..., "<="),
c(input$prot[1]*7, input$prot[2]*7, input$fat[1]*7, input$fat[2]*7,
input$budget[1], input$budget[2], input$sodium[1]*7, input$sodium[2]*7,
input$fiber[1]*7, input$fiber[2]*7, input$sugar[1]*7, input$sugar[2]*7,
input$cals[1]*7, input$cals[2]*7, 16, 28, 9, 25, 6.4, 24, input$serv,
input$serv, input$serv, input$serv, input$serv, input$serv, input$serv,
input$serv, input$serv, input$serv, ...[more input$servs here]...,
input$serv))
我使用了闪亮的包,所以这就是为什么它是"input$serv"而不是一个具体的数字。用户可以使用滑块小部件选择最大份数,默认为10。
模型所依据的食物营养信息在一个单独的csv文件中。
一瞥(临时)观察:135
变量:
$ food (fctr)可口可乐,萨克拉门托番茄汁,纯果乐Trop50橙汁,V8蔬菜…
$ foodGroup (fctr)饮料,饮料,饮料,饮料,乳制品,乳制品,乳制品,乳制品,乳制品…
美元calsPerServ(双)140.0,35.0,50.0,50.0,90.0,90.0,102.4,150.0,90.0,90.0,113.0,50.0…
$ ozPerServ (dbl) 1,000000, 6,000000, 8,000000, 2,500000, 4,070000, 8,000000, 8.0…
美元fatPerServ(双)0.00,0.00,0.00,0.00,5.00,1.00,0.24,8.00,0.00,0.00,9.00,3.00,7…
美元protPerServ(双)0.0,1.0,1.0,2.0,8.0,16.0,7.2,8.0,6.0,3.0,7.0,4.0,2.0,2.0,6.0…
$ sodiumPerServ (dbl) 45.00, 560.00, 10.00, 590.00, 80.00, 360.00, 120.80, 120.00, 100.00, 60.00…
美元fiberPerServ(双)0.0,1.0,0.0,2.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,1.0,…
美元sugarPerServ(双)39.00,4.90,10.00,8.00,0.00,3.00,11.20,11.00,12.00,14.00,0.00,1…
$ costPerServ (dbl) 0.4800000, 0.2400000, 0.5600000, 0.4737500, 0.1750000, 0.4884000, 0.240000…
谷物(双)美元0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,…
oilsFats美元(双)0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,…
$ fruit (dbl) 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0.00000, 0....
美元的糖 ( 双)0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,…
meatProtein美元(双)0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,…
数十亿美元 ( int) 12 6 8 8 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0…
美元的蔬菜 ( 双)0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,…
$ dairy (dbl) 0.000000, 0.000000, 0.000000, 0.000000, 2.500000, 4.070000, 8.000000, 8.00…
X1美元 ( int) 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,…
X2美元 ( int) 0 1 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,…
X3美元 ( int) 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,…
好吧,没有SNAP数据的源文件,我想出了我自己的食物/营养矩阵。应该很容易看出如何适应你的问题。这是一个非常基本的单纯形线性优化问题。我们根据成本、人均最小和最大份量以及营养成分(目前仅限于维生素A和卡路里)来定义每种食物。有2种营养成分,有5列。有42种营养成分,就有45列。
第二个矩阵,最小和最大推荐每日摄取量(RDA),每个最小/最大RDA有一行。
这是四种食物的R代码,玉米,牛奶,面包和大豆:
library(lpSolveAPI)
# Diet options (index, cost, min servings, max servings, vitA, calories)
food.corn <- c(0.18, 0, 10, 107, 72)
food.milk <- c(0.23, 0, 10, 500, 121)
food.bread <- c(0.05, 0, 10, 0, 65)
food.soylent <- c(0.50, 0, 10, 625, 250)
foods <- matrix(c(food.corn, food.milk, food.bread, food.soylent), 4, 5, byrow=TRUE)
# Recommended Daily Allowance (min, max)
rda.vitA <- c(5000, 50000)
rda.cal <- c(2000, 2250)
rdas <- matrix(c(rda.vitA, rda.cal), 2, 2, byrow=TRUE)
nr <- length(foods[,1])
varcount <- nr
const.count <- 0
lp <- make.lp (0, varcount, verbose="normal")
lp.control (lp, sense="min")
set.objfn (lp, foods[,1])
for (i in length(rdas[,1])) {
add.constraint (lp, foods[,(3+i)], ">=", as.double(rdas[i,1]))
add.constraint (lp, foods[,(3+i)], "<=", as.double(rdas[i,2]))
const.count <- const.count + 1
}
for (i in nr) {
add.constraint (lp, c(rep(0,i-1), 1, rep(0,nr-i)), ">=", as.double(foods[i,2]))
add.constraint (lp, c(rep(0,i-1), 1, rep(0,nr-i)), "<=", as.double(foods[i,3]))
const.count <- const.count + 1
}
set.bounds (lp, lower=foods[,2], upper=foods[,3])
set.type (lp, 1:varcount, type="integer")
resize.lp (lp, const.count, varcount)
if (solve (lp) == 0) {
lps.out <- list(solution=get.variables(lp), objective=get.objective(lp))
} else {
print ("No feasible solution")
lps.out <- NA
}
按口味调味