我有一个简单的(实际上是经济学标准)非线性约束的离散最大化问题要在R中解决并且遇到麻烦。我找到了问题的部分的解决方案(非线性最大化;离散最大化),但没有找到所有问题的并集。
这是问题所在。消费者想要购买三种产品(凤梨,香蕉,饼干),知道价格并且预算为20欧元。他喜欢多样性(即,如果可能的话,他希望拥有所有三种产品)并且他的满意度在消耗量上减少(他喜欢他的第一个cookie方式超过他的第100个)。
他希望最大化的功能是
当然,由于每个人都有一个价格,并且他的预算有限,他在这个约束下最大化这个功能
我想要做的是找到满足约束条件的最佳购买清单(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)的最佳购买清单。
任何提示?
答案 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包很好地表达。使用上面的price
和library(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的最优解!