如何在R中使用lpsolve创建许多变量的上界?

时间:2015-06-09 12:51:49

标签: r variables mathematical-optimization lpsolve upperbound

我有一个包含135种食物的数据集,用于解决diet problem:最小化成本和最大化营养价值。我想创建一个包含各种食物的模型,而不是一个例如告诉我每周只吃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))

我使用了闪亮的包,所以这就是为什么它是“输入$ serv”而不是具体的数字。用户可以选择使用滑块小部件的最大服务数,默认值为10.

该模型所依据的食物营养信息位于单独的csv文件中。

  

一瞥(SNAP)
  观察:135
  变量:
  $ food(fctr)可口可乐,萨克拉门托番茄汁,Tropicana Trop50橙汁,V8蔬菜......   $ foodGroup(fctr)饮料,饮料,饮料,饮料,乳制品,乳制品,乳制品,乳制品,乳制品......
  $ calsPerServ(dbl)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)12.000000,6.00000000,8000000,8000000,2.000000,4.0000000,8000000,8.0 ...   $ fatPerServ(dbl)0.00,0.00,0.00,0.00,5.00,1.00,0.24,8.00,0.00,0.00,9.00,3.00,3.00 ......   $ protPerServ(dbl)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(dbl)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(dbl)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 ...
  $ grains(dbl)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,0,0,0,0,0,0 ,0,0,...
  $ oilsFats(dbl)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,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 ....   $ sugar(dbl)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,0 ,0,0,...
  $ meatProtein(dbl)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,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 ,0,0,...
  $ bev(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 ...
  $ vegs(dbl)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 ,0,0,...
  $ dairy(dbl)0.000000,0.000000,0.000000,0.000000,2.5000,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,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,...
  $ 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,...
  $ 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,......

1 个答案:

答案 0 :(得分:0)

好吧,如果没有SNAP数据的源文件,我想出了自己的食物/营养矩阵。应该很容易看出如何适应您的问题。这是一个非常基本的单纯形线性优化问题。我们根据成本,人均最低和最高份量,然后营养成分(目前仅限于维生素A和kCals)来定义每个食品。有2个营养成分,有5列。有42个营养成分,将有45列。

第二个矩阵,最小和最大推荐每日允许量(RDA),每个最小/最大RDA都有一行。

这里有四种食物的R代码,玉米,牛奶,面包和soylent:

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
}

品尝季节......