R

时间:2015-10-14 10:07:51

标签: r optimization constraints discrete-mathematics

我有一个简单的(实际上是经济学标准)非线性约束的离散最大化问题要在R中解决并且遇到麻烦。我找到了问题的部分的解决方案(非线性最大化;离散最大化),但没有找到所有问题的并集。

这是问题所在。消费者想要购买三种产品(凤梨,香蕉,饼干),知道价格并且预算为20欧元。他喜欢多样性(即,如果可能的话,他希望拥有所有三种产品)并且他的满意度在消耗量上减少(他喜欢他的第一个cookie方式超过他的第100个)。

他希望最大化的功能是

function to maximize

当然,由于每个人都有一个价格,并且他的预算有限,他在这个约束下最大化这个功能

enter image description here

我想要做的是找到满足约束条件的最佳购买清单(N ananas,M香蕉,K饼干)。

如果问题是线性的,我会简单地使用linprog :: solveLP()。但目标函数是非线性的。 如果问题具有连续性,那么它将是一个简单的分析解决方案。

问题是离散和非线性,我不知道如何继续。

以下是一些玩具数据。

df <- data.frame(rbind(c("ananas",2.17),c("banana",0.75),c("cookie",1.34)))
names(df) <- c("product","price")

我希望有一个优化例程,为我提供(N,M,K)的最佳购买清单。

任何提示?

4 个答案:

答案 0 :(得分:2)

如果您不介意使用“手动”解决方案:

uf=function(x)prod(x)^.5
bf=function(x,pr){
  if(!is.null(dim(x)))apply(x,1,bf,pr) else x%*%pr
}
budget=20
df <- data.frame(product=c("ananas","banana","cookie"),
                 price=c(2.17,0.75,1.34),stringsAsFactors = F)
an=0:(budget/df$price[1]) #include 0 for all possibilities
bn=0:(budget/df$price[2])
co=0:(budget/df$price[3])
X=expand.grid(an,bn,co)
colnames(X)=df$product
EX=apply(X,1,bf,pr=df$price)
psX=X[which(EX<=budget),] #1st restrict
psX=psX[apply(psX,1,function(z)sum(z==0))==0,] #2nd restrict
Ux=apply(psX,1,uf)
cbind(psX,Ux)
(sol=psX[which.max(Ux),])
uf(sol) # utility
bf(sol,df$price)  #budget
> (sol=psX[which.max(Ux),])
     ananas banana cookie
1444      3      9      5
> uf(sol) # utility
[1] 11.61895
> bf(sol,df$price)  #budget
 1444 
19.96

答案 1 :(得分:2)

1)没有包这可以通过暴力来完成。使用问题中的df作为输入,确保price为数字(它是问题的df中的一个因素)并计算每个mx的最大数量g变量。然后创建可变计数的网格total并计算每个objective的价格以及相关的gg给出gg。{现在按目标的降序对head进行排序,并使这些解决方案满足约束条件。 price <- as.numeric(as.character(df$price)) mx <- ceiling(20/price) g <- expand.grid(ana = 0:mx[1], ban = 0:mx[2], cook = 0:mx[3]) gg <- transform(g, total = as.matrix(g) %*% price, objective = sqrt(ana * ban * cook)) best <- subset(gg[order(-gg$objective), ], total <= 20) 将显示前几个解决方案。

> head(best) # 1st row is best soln, 2nd row is next best, etc.
     ana ban cook total objective
1643   3   9    5 19.96  11.61895
1929   3   7    6 19.80  11.22497
1346   3  10    4 19.37  10.95445
1611   4   6    5 19.88  10.95445
1632   3   8    5 19.21  10.95445
1961   2  10    6 19.88  10.95445

,并提供:

g

2)dplyr 这也可以使用dplyr包很好地表达。使用上面的pricelibrary(dplyr) g %>% mutate(total = c(as.matrix(g) %*% price), objective = sqrt(ana * ban * cook)) %>% filter(total <= 20) %>% arrange(desc(objective)) %>% top_n(6)

Selecting by objective
  ana ban cook total objective
1   3   9    5 19.96  11.61895
2   3   7    6 19.80  11.22497
3   3  10    4 19.37  10.95445
4   4   6    5 19.88  10.95445
5   3   8    5 19.21  10.95445
6   2  10    6 19.88  10.95445

,并提供:

{{1}}

答案 2 :(得分:1)

我认为这个问题在性质上与这个问题非常相似(Solve indeterminate equation system in R)。 Richie Cotton的答案是这种可能解决方案的基础:

df <- data.frame(product=c("ananas","banana","cookie"),
                 price=c(2.17,0.75,1.34),stringsAsFactors = F)

FUN <- function(w, price=df$price){
  total <- sum(price * w) 
  errs <- c((total-20)^2, -(sqrt(w[1]) * sqrt(w[2]) * sqrt(w[3])))
  sum(errs)
}

init_w <- rep(10,3)
res <- optim(init_w, FUN, lower=rep(0,3), method="L-BFGS-B")
res
res$par # 3.140093 9.085182 5.085095
sum(res$par*df$price) # 20.44192

请注意,解决方案的总成本(即价格)为20.44美元。为了解决这个问题,我们可以对误差项进行加权,以便更加重视第一项,这与总成本有关:

### weighting of error terms
FUN2 <- function(w, price=df$price){
  total <- sum(price * w) 
  errs <- c(100*(total-20)^2, -(sqrt(w[1]) * sqrt(w[2]) * sqrt(w[3]))) # 1st term weighted by 100
  sum(errs)
}

init_w <- rep(10,3)
res <- optim(init_w, FUN2, lower=rep(0,3), method="L-BFGS-B")
res
res$par # 3.072868 8.890832 4.976212
sum(res$par*df$price) # 20.00437

答案 3 :(得分:0)

正如LyzandeR所说,R中没有非线性整数规划求解器。相反,您可以使用R包 rneos 将数据发送到NEOS求解器之一并将结果返回到R过程

NEOS Solvers页面上选择“混合整数非线性约束优化”的解算器之一,例如Bonmin或Couenne。对于上面的示例,请将AMPL建模语言中的以下文件发送给以下解算器之一:

[请注意,最大化产品x1 * x2 * x3与最大化产品sqrt(x1) * sort(x2) * sqrt(x3)相同。]

模型文件:

param p{i in 1..3};
var x{i in 1..3} integer >= 1;
maximize profit: x[1] * x[2] * x[3];
subject to restr: sum{i in 1..3} p[i] * x[i] <= 20;

数据文件:

param p:= 1 2.17  2 0.75  3 1.34 ;

命令文件:

solve;
display x;

您将收到以下解决方案:

x [*] :=
1  3
2  9
3  5
;

这种方法适用于更多扩展示例,“手动”解决方案不合理,并且舍入optim解决方案不正确。

为了看一个更苛刻的例子,让我提出以下问题:

求整数向量x =(x_i),i = 1,...,10,最大化x1 * ... * x10,使得p1 * x1 + ... + p10 * x10 <= 10 ,其中p =(p_i),i = 1,...,10,是以下价格向量

p <- c(0.85, 0.22, 0.65, 0.73, 0.91, 0.11, 0.31, 0.47, 0.93, 0.71)

对于线性不等式约束的非线性优化问题使用constrOptim,我得到了900不同起点的解,但从来没有960的最优解!