R优化最大买/卖取决于库存水平 [英] R optimisation max buy/sell dependent on stock level

查看:82
本文介绍了R优化最大买/卖取决于库存水平的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想找到优化问题的解决方案.目的是通过低价购买和更高价格出售来最大化利润.存在一些限制,例如最大库存水平和最大购买/出售单位数量.此外,买卖限制取决于库存水平.我问过一个类似的问题,尽管这里没有最后一个条件 R优化买入卖出.

I would like to find a solution to an optimisation problem. The aim is to maximise profit by buying for low price and selling for a higher one. There are constraints such as maximum stock level, and max buy/sell number of units. Moreover, sell and buy limits depend on the inventory levels. I have asked a similar question albeit without the last condition here R optimisation buy sell.

这里是一个例子:

price = c(12, 11, 12, 13, 16, 17, 18, 17, 18, 16, 17, 13)
capacity = 25
max_units_buy_30 = 4 # when inventory level is lower then 30% it is possible to buy 0 to 4 units
max_units_buy_65 = 3 # when inventory level is between 30% and 65% it is possible to buy 0 to 3 units
max_units_buy_100 = 2 # when inventory level is between 65% and 100% it is possible to buy 0 to 2 units
max_units_sell_30 = 4 # when inventory level is lower then 30% it is possible to sell 0 to 4 units
max_units_sell_70 = 6 # when inventory level is between 30% and 70% it is possible to sell 0 to 6 units
max_units_sell_100 = 8 # when inventory level is between 70% and 100% it is possible to sell 0 to 8 units

推荐答案

这里发生了很多事情.

  1. 说明

说明中似乎存在问题. "最高卖出/价格取决于库存水平."这似乎是错误的.从数据来看,价格似乎是恒定的,但买卖限制取决于库存水平.

There seems to be a problem in the description. "The max sell/price is dependent on the stock level." This seems to be wrong. From the data, it looks like the price is constant, but rather sell and buy limits depend on the inventory levels.

  1. 时间

正确安排时间很重要.通常,我们将buysell视为在 t 时期内发生的事情(我们将其称为流变量). inv库存变量,在周期 t 结束时进行测量.说sell[t]buy[t]依赖于inv[t]有点奇怪(我们在时间上倒退了).当然,我们可以对其建模并求解(我们以联立方程求解,因此我们可以做这些事情).但是,这在现实世界中可能没有意义.可能我们应该看一下inv[t-1]才能更改buy[t]sell[t].

It is important to get the timing right. Usually, we look at buy and sell as things that happen during period t (we call them flow variables). inv is a stock variable, and is measured at the end of period t. To say that sell[t] and buy[t] depend on inv[t] is a bit strange (we are going backward in time). Of course, we can model it and solve it (we solve as simultaneous equations, so we can do these things). But, it may not make sense in the real world. Probably we should look at inv[t-1] in order to change buy[t] and sell[t].

  1. 细分库存水平.

我们需要将广告资源级别划分为多个细分.我们分为以下几个部分:

We need to split inventory levels into segments. We have the following segments:

0%-30%
30%-65%
65%-70%
70%-100%

我们将二进制变量与每个细分相关联:

we associate a binary variable with each segment:

inventory in [0%-30%]  <=> δ[1,t] = 1, all other zero
             [30%-65%]     δ[2,t] = 1 
             [65%-70%]     δ[3,t] = 1 
             [70%-100%]    δ[4,t] = 1 

因为我们需要在所有时间段内都这样做,所以我们拍了一个额外的索引t.警告:我们将在时间段t的开始将δ[k,t]与广告资源相关联,即inv[t-1].我们可以根据所处的段来更改上下限,从而将δ[k,t]链接至inv[t-1].

Because we need to do this for all time periods, we slap on an extra index t. Warning: we will associate δ[k,t] with the inventory at the beginning of period t, i.e. inv[t-1]. We can link δ[k,t] to inv[t-1] by changing lower- and upper bounds depending on in which segment we are.

  1. 买卖限制

类似于广告资源的范围,我们在买卖方面具有以下上限:

Similar to bounds on the inventory, we have the following upper bounds on buy and sell:

     segment     buy   sell
     0%-30%       4     4 
     30%-65%      3     6
     65%-70%      2     6
     70%-100%     2     8

第一步是建立数学模型.这里发生了太多事情,我们可以立即进行编码.数学模型是我们的设计".所以我们开始:

The first step is to develop a mathematical model. There is too much going on here that we can immediately code things up. The mathematical model is our "design". So here we go:

以此,我们可以开发一些R代码.在这里,我们使用CVXR作为建模工具,并使用GLPK作为MIP求解器.

With this, we can develop some R code. Here we use CVXR as a modeling tool and GLPK as an MIP solver.

> library(CVXR)
> 
> # data
> price = c(12, 11, 12, 13, 16, 17, 18, 17, 18, 16, 17, 13)
> capacity = 25
> max_units_buy = 4
> max_units_sell = 8
> 
> # capacity segments
> s <- c(0,0.3,0.65,0.7,1)
> 
> # corresponding lower and upper bounds
> invlb <- s[1:(length(s)-1)] * capacity
> invlb
[1]  0.00  7.50 16.25 17.50
> invub <- s[2:length(s)] * capacity
> invub
[1]  7.50 16.25 17.50 25.00
> 
> buyub <- c(4,3,2,2)
> sellub <- c(4,6,6,8)
> 
> # number of time periods
> NT <- length(price)
> NT
[1] 12
> 
> # number of capacity segments
> NS <- length(s)-1
> NS
[1] 4
> 
> # Decision variables
> inv = Variable(NT,integer=T)
> buy = Variable(NT,integer=T)
> sell = Variable(NT,integer=T)
> delta = Variable(NS,NT,boolean=T)
> 
> # Lag operator
> L = cbind(rbind(0,diag(NT-1)),0)
> 
> # optimization model
> problem <- Problem(Maximize(sum(price*(sell-buy))),
+                    list(inv == L %*% inv + buy - sell,
+                         sum_entries(delta,axis=2)==1, 
+                         L %*% inv >= t(delta) %*% invlb,
+                         L %*% inv <= t(delta) %*% invub,
+                         buy <= t(delta) %*% buyub,
+                         sell <= t(delta) %*% sellub,
+                         inv >= 0, inv <= capacity,
+                         buy >= 0, sell >= 0))
> result <- solve(problem,verbose=T)
GLPK Simplex Optimizer, v4.47
120 rows, 84 columns, 369 non-zeros
      0: obj =  0.000000000e+000  infeas = 1.200e+001 (24)
*    23: obj =  0.000000000e+000  infeas = 0.000e+000 (24)
*    85: obj = -9.875986758e+001  infeas = 0.000e+000 (2)
OPTIMAL SOLUTION FOUND
GLPK Integer Optimizer, v4.47
120 rows, 84 columns, 369 non-zeros
84 integer variables, 48 of which are binary
Integer optimization begins...
+    85: mip =     not found yet >=              -inf        (1; 0)
+   123: >>>>> -8.800000000e+001 >= -9.100000000e+001   3.4% (17; 0)
+   126: >>>>> -9.000000000e+001 >= -9.100000000e+001   1.1% (9; 11)
+   142: mip = -9.000000000e+001 >=     tree is empty   0.0% (0; 35)
INTEGER OPTIMAL SOLUTION FOUND
> cat("status:",result$status)
status: optimal
> cat("objective:",result$value)
objective: 90
> print(result$getValue(buy))
      [,1]
 [1,]    3
 [2,]    4
 [3,]    4
 [4,]    3
 [5,]    3
 [6,]    1
 [7,]    0
 [8,]    0
 [9,]    0
[10,]    4
[11,]    0
[12,]    0
> print(result$getValue(sell))
      [,1]
 [1,]    0
 [2,]    0
 [3,]    0
 [4,]    0
 [5,]    0
 [6,]    0
 [7,]    8
 [8,]    6
 [9,]    4
[10,]    0
[11,]    4
[12,]    0
> print(result$getValue(inv))
      [,1]
 [1,]    3
 [2,]    7
 [3,]   11
 [4,]   14
 [5,]   17
 [6,]   18
 [7,]   10
 [8,]    4
 [9,]    0
[10,]    4
[11,]    0
[12,]    0
> print(result$getValue(delta))
     [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10] [,11] [,12]
[1,]    1    1    1    0    0    0    0    0    1     1     1     1
[2,]    0    0    0    1    1    0    0    1    0     0     0     0
[3,]    0    0    0    0    0    1    0    0    0     0     0     0
[4,]    0    0    0    0    0    0    1    0    0     0     0     0
> 

所以,我认为有人为此欠了一瓶白兰地.

So, I think someone owes me a good bottle of cognac for this.

这篇关于R优化最大买/卖取决于库存水平的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆