随机规划案例:The value of the stochastic solution

作者: 刘兴禄,清华大学,清华-伯克利深圳学院博士在读

前几天收到一个读者来信,大致是说阅读了我之前写的推文:《初识随机规划》,有了一些基本的了解之后,在继续深入学习的过程中,遇到了一些困惑。我心血来潮,写了一个代码为他详细解答了他的几个问题。

这里,我将之前回答的内容,整理成一篇关于随机规划的入门推文,共初学者学习和参考。

本文采用的案例,来自John R. Birge大佬的教材《Introduction to Stochastic Programming》中pp4-pp10的一个例子。书的封面和信息如下。

首先来膜拜一下Birge大佬的google scholar吧。
在这里插入图片描述

@book{birge2011introduction,
title={Introduction to stochastic programming},
author={Birge, John R and Louveaux, Francois},
year={2011},
publisher={Springer Science & Business Media}
}

在这里插入图片描述
这位来信的师弟看的slides是Fabian Bastin的教学课件,课件是根据Birge的教材制作的。文中相关的截图也均是出自该slides。

Slides:
Stochastic optimization
by Fabian Bastin
contact:fabian.bastin@umontreal.ca
Institute: Universit{`e} de Montr{`e}al` – CIRRELT – IVADO – Fin-ML
在这里插入图片描述

接下来,我们来详细解释一下这个例子,并给出相关解释。

The farmer problem

一个农民拥有500亩地用以种植小麦(wheat),玉(corn)和甜菜(sugar beets), (注:甜菜在我们那儿叫糖萝卜).
这个农民至少需要200吨小麦和240吨玉米来喂养它的牲畜。剩余的部分则可以用来出售。单如果产量不足,则需要向外界购买相应的粮食予以补充。
农民种植的甜菜可以全部出售,但是前6000吨售价为36美元,超出6000吨的部分则每吨只能卖10美元(这是由于配额导致)。
3种农作物的产量、种植成本、售价、购买价格等参数如下表所示。
在这里插入图片描述
问:该农民应该如何分配种植小麦、玉米和甜菜的面积,来最大化总收益。

Deterministic Model及Gurobi求解

首先,我们来考虑确定性的模型。即,假设小麦、玉米和甜菜的亩产量不受天气等因素的影响,为定值。或者说,我们用平均亩产量代替真实的亩产量。

我们引入下面的决策变量。
在这里插入图片描述
建立如下的线性规划模型。
在这里插入图片描述
其中,目标函数是最小化成本。但是实际上也相当于最大化总收益。

注意:这样处理后,最终的目标函数的相反数就是最终的净利润 。

我们用Python调用Gurobi来求解上述模型,具体代码如下。

from gurobipy import * 
model = Model('deterministic version')
x = {} 
y = {}
w = {} 
for i in range(1, 4):
    x[i] = model.addVar(lb = 0, vtype=GRB.CONTINUOUS, name = 'x_%d'%i) 
for i in range(1, 3): 
    y[i] = model.addVar(lb = 0, vtype=GRB.CONTINUOUS, name = 'y_%d'%i)  
for i in range(1, 5): 
    w[i] = model.addVar(lb = 0, vtype=GRB.CONTINUOUS, name = 'w_%d'%i)   

# set the objective function 
model.setObjective(150 * x[1] + 230 * x[2] + 260 * x[3]   # plantation cost 
                   + 238 * y[1] + 210 * y[2]              # buying cost 
                   - 170 * w[1] - 150 * w[2] - 36 * w[3] - 10 * w[4]  # selling income 
                   , GRB.MINIMIZE
                   )

# set the constraints 
model.addConstr(x[1] + x[2] + x[3] <= 500) 
model.addConstr(2.5 * x[1] + y[1] - w[1] >= 200) 
model.addConstr(3 * x[2] + y[2] - w[2] >= 240) 
model.addConstr(w[3] + w[4] <= 20 * x[3]) 
model.addConstr(w[3] <= 6000)  

# solve the model 
model.optimize() 

# print the solution 
print('Obj \t\t = {}'.format(model.ObjVal)) 
for key in x.keys():
    if(x[key].x > 0):
        print('{} \t\t = {}'.format(x[key].varName, x[key].x)) 
for key in y.keys():
    if(y[key].x > 0):
        print('{} \t\t = {}'.format(y[key].varName, y[key].x)) 
for key in w.keys():
    if(w[key].x > 0):
        print('{} \t\t = {}'.format(w[key].varName, w[key].x))  

运行结果为

Iteration    Objective       Primal Inf.    Dual Inf.      Time
       0   -5.1200000e+33   2.000000e+30   5.120000e+03      0s
       4   -1.1860000e+05   0.000000e+00   0.000000e+00      0s

Solved in 4 iterations and 0.02 seconds
Optimal objective -1.186000000e+05
Obj 		 = -118600.0
x_1 		 = 120.0
x_2 		 = 80.0
x_3 		 = 300.0
w_1 		 = 100.0
w_3 		 = 6000.0

因此,我们得知,最优解为

  • 种植小麦120亩( x 1 = 120 x_1=120 x1=120)
  • 玉米80亩( x 2 = 80 x_2=80 x2=80)
  • 甜菜300亩( x 3 = 300 x_3=300 x3=300)
  • 不用向外界购买( y 1 = y 2 = 0 y_1=y_2 = 0 y1=y2=0)
  • 且可以向外销售小麦100吨( w 1 = 100 w_1=100 w1=100)
  • 以36美元销售甜菜6000吨( w 3 = 6000 w_3=6000 w3=6000)
  • 对应的最大利润为 118600 118600 118600
    在这里插入图片描述

随机因素

但是在实际中,农作物的亩产量会随着天气、土壤、经营等因素发生变化。假设不同的环境,会使得农作物的亩产量增加或者减少20%-25%

本例中,我们仅考虑3种非常简单场景:

  1. 丰收年:每一种农作物的亩产量会增产20%
  2. 平均年:亩产等于平均值
  3. 灾害年:每一种农作物的产量减产20%

我们假设其余的参数,例如售价等,均不变。

我们在丰收年灾害年下,分别改变参数,再次求解上述模型,得到的解如下。

丰收年

# set the objective function 
model.setObjective(150 * x[1] + 230 * x[2] + 260 * x[3]   # plantation cost 
                   + 238 * y[1] + 210 * y[2]              # buying cost 
                   - 170 * w[1] - 150 * w[2] - 36 * w[3] - 10 * w[4]  # selling income 
                   , GRB.MINIMIZE
                   )

# set the constraints 
model.addConstr(x[1] + x[2] + x[3] <= 500) 
model.addConstr(3 * x[1] + y[1] - w[1] >= 200)  
model.addConstr(3.6 * x[2] + y[2] - w[2] >= 240) 
model.addConstr(w[3] + w[4] <= 24 * x[3])  
model.addConstr(w[3] <= 6000)  

# solve the model 
model.optimize() 

运行结果为

Iteration    Objective       Primal Inf.    Dual Inf.      Time
       0   -5.1200000e+33   2.000000e+30   5.120000e+03      0s
       4   -1.6766667e+05   0.000000e+00   0.000000e+00      0s

Solved in 4 iterations and 0.01 seconds
Optimal objective -1.676666667e+05
Obj 		 = -167666.6666666667
x_1 		 = 183.33333333333331
x_2 		 = 66.66666666666667
x_3 		 = 250.0
w_1 		 = 350.0
w_3 		 = 6000.0

在这里插入图片描述

灾害年

# set the objective function 
model.setObjective(150 * x[1] + 230 * x[2] + 260 * x[3]   # plantation cost 
                   + 238 * y[1] + 210 * y[2]              # buying cost 
                   - 170 * w[1] - 150 * w[2] - 36 * w[3] - 10 * w[4]  # selling income 
                   , GRB.MINIMIZE
                   )

# set the constraints 
model.addConstr(x[1] + x[2] + x[3] <= 500) 
model.addConstr(2 * x[1] + y[1] - w[1] >= 200)  
model.addConstr(2.4 * x[2] + y[2] - w[2] >= 240) 
model.addConstr(w[3] + w[4] <= 16 * x[3])  
model.addConstr(w[3] <= 6000)  

# solve the model 
model.optimize() 

运行结果为

Iteration    Objective       Primal Inf.    Dual Inf.      Time
       0   -3.7600000e+33   2.000000e+30   3.760000e+03      0s
       5   -5.9950000e+04   0.000000e+00   0.000000e+00      0s

Solved in 5 iterations and 0.01 seconds
Optimal objective -5.995000000e+04
Obj 		 = -59950.0
x_1 		 = 100.0
x_2 		 = 25.0
x_3 		 = 375.0
y_2 		 = 180.0
w_3 		 = 6000.0

在这里插入图片描述

我们会发现,在丰收年灾害年的设定下,最优解发生了变化。

且3种情形下的目标函数的平均值为

167666.67 + 118600 + 59950 3 ≈ 115406 \frac{167666.67 + 118600 + 59950}{3} \approx 115406 3167666.67+118600+59950115406

如此,农民犯难了。

在一年之初,并不知道今年的完整信息的情况下,该如何决策种植多少亩小麦,多少亩玉米和多少亩甜菜,才能使得最终的收益最大化呢?

这时候就可以请出我们的随机规划了。

wait-and-see approach

这里需要插一句,我们来介绍一个专业术语,wait-and-see approach。由于一些因素是不确定的,所以我们在又不确定因素存在的情形下做决策,是可以采用一种较为简单的办法:wait-and-see approach

在Deterministic Model中,我们相当于是假设我们已经得知了所有未来的信息(perfect information),我们基于这个信息来做决策。这种情况,也就是为我们最常见的,使用随机变量的平均值或者其他值来作为参数。例如本例中,小麦的亩产量,其实是一个随机变量,我们在Deterministic Model中使用了他的平均值作为参数。

另一种,就是等待所有的事情已经发生了,我们看到了这些随机变量的实现(wait to observe the realization of the random variables),比如,我们等到这一年秋天结束,观察到了最终的亩产,确实就是小麦亩产2.5吨等。然后我们基于这个观察到的实现值去做事后诸葛亮一样的决策,这就是wait-and-see approach

Stochastic Programming Model

但是在现实中,事后诸葛亮往往是不可取的,我们都要做事先的决策。因此就需要在一开始做决策的时候,将这些随机变量考虑进去。

以本文提及的例子为例,就是我们考虑3种场景。丰收年平均年灾害年

我们将需要做的决策认为的划分为2个阶段,即

  • 战术层决策(Tactical level decisons): 决策应该种植小麦、玉米、甜菜各多少亩
  • 作业层决策(Operational level decisons): 决策应该外购、向外销售的小麦、玉米和甜菜的量。

确实,在现实中,应该先做出种植小麦、玉米、甜菜各多少亩的决策,等到真正产出以后,才会做出应该外购、向外销售的小麦、玉米和甜菜的量的决策,以及种植小麦、玉米、甜菜各多少亩的决策会极大地影响应该外购、向外销售的小麦、玉米和甜菜的量的决策。

所以,前者是战术层决策(Tactical level decisons),后者是作业层决策(Operational level decisons),是比较合理的。

接下来,我们引入下面的决策变量,来建立Scenario-based随机规划模型。

在这里插入图片描述
随机规划模型如下:

在这里插入图片描述
注意:
该模型的重点在于做出战术层决策(Tactical level decisons),当然,也会针对每一个Scenario产生一套解。

我们调用Gurobi来求解上述模型。

from gurobipy import * 
model = Model('stochastic version') 
x = {} 
y = {}
w = {} 
for i in range(1, 4):
    x[i] = model.addVar(lb = 0, vtype=GRB.CONTINUOUS, name = 'x_%d'%i) 
for i in range(1, 3): 
    for s in range(1, 4):
        y[i, s] = model.addVar(lb = 0, vtype=GRB.CONTINUOUS, name = 'y_%d_%d'%(i, s))   
for i in range(1, 5): 
    for s in range(1, 4): 
        w[i, s] = model.addVar(lb = 0, vtype=GRB.CONTINUOUS, name = 'w_%d_%d'%(i, s))     

# set the objective function 
model.setObjective(150 * x[1] + 230 * x[2] + 260 * x[3]   # plantation cost 
                   + 238/3 * y[1, 1] + 238/3 * y[1, 2] + 238/3 * y[1, 3] 
                   + 210/3 * y[2, 1] + 210/3 * y[2, 2] + 210/3 * y[2, 3]              # buying cost 
                   - 170/3 * w[1, 1] - 170/3 * w[1, 2] - 170/3 * w[1, 3] 
                   - 150/3 * w[2, 1] - 150/3 * w[2, 2] - 150/3 * w[2, 3]  
                   - 36/3 * w[3, 1] - 36/3 * w[3, 2] - 36/3 * w[3, 3]  
                   - 10/3 * w[4, 1] - 10/3 * w[4, 2] - 10/3 * w[4, 3]                 # selling income 
                   , GRB.MINIMIZE
                   )

# set the constraints 
model.addConstr(x[1] + x[2] + x[3] <= 500) 

model.addConstr(3 * x[1] + y[1, 1] - w[1, 1] >= 200)   
model.addConstr(2.5 * x[1] + y[1, 2] - w[1, 2] >= 200)   
model.addConstr(2 * x[1] + y[1, 3] - w[1, 3] >= 200)  

model.addConstr(3.6 * x[2] + y[2, 1] - w[2, 1] >= 240) 
model.addConstr(3 * x[2] + y[2, 2] - w[2, 2] >= 240) 
model.addConstr(2.4 * x[2] + y[2, 3] - w[2, 3] >= 240) 

model.addConstr(w[3, 1] + w[4, 1] <= 24 * x[3]) 
model.addConstr(w[3, 2] + w[4, 2] <= 20 * x[3]) 
model.addConstr(w[3, 3] + w[4, 3] <= 16 * x[3]) 

model.addConstr(w[3, 1] <= 6000)  
model.addConstr(w[3, 2] <= 6000) 
model.addConstr(w[3, 3] <= 6000) 

# solve the model 
model.optimize() 

# print the solution 
print('Obj \t\t = {}'.format(model.ObjVal)) 
for key in x.keys():
    if(x[key].x > 0):
        print('{} \t\t = {}'.format(x[key].varName, x[key].x)) 
for key in y.keys():
    if(y[key].x > 0):
        print('{} \t\t = {}'.format(y[key].varName, y[key].x)) 
for key in w.keys():
    if(w[key].x > 0):
        print('{} \t\t = {}'.format(w[key].varName, w[key].x))  

运行结果如下:

Iteration    Objective       Primal Inf.    Dual Inf.      Time
       0   -2.5600000e+33   6.000000e+30   2.560000e+03      0s
      12   -1.0839000e+05   0.000000e+00   0.000000e+00      0s

Solved in 12 iterations and 0.01 seconds
Optimal objective -1.083900000e+05
Obj 		 = -108389.99999999999
x_1 		 = 170.0
x_2 		 = 80.0
x_3 		 = 250.0
y_2_3 		 = 48.00000000000003
w_1_1 		 = 310.0
w_1_2 		 = 225.0
w_1_3 		 = 140.0
w_2_1 		 = 48.0
w_3_1 		 = 6000.0
w_3_2 		 = 5000.0
w_3_3 		 = 4000.0


在这里插入图片描述
可以看到,在每一个Scenario下,都会对应一个解,但是,第一阶段战术层决策(Tactical level decisons)的解,是通用、的。

在这种情形下,期望的最大收益为108390

关于随机规划的解如何执行的问题

这里,由于随机规划生成了3套解,分别对应3个Scenario。那么在实际中,我们应该如何执行,才能真正达到108390的收益呢?

实际上,在实际中,我们首先会执行第一阶段战术层决策(Tactical level decisons)的决策。

等到按照战术层决策(Tactical level decisons)的决策种植好了小麦、玉米和甜菜后,等到小麦,玉米和甜菜都长成了,到了秋天丰收之后,我们根据实际的产出情况,观察实际情况与哪一个提前考虑的Scenario接近。比如2021年春天农民播种完以后,到了2021年秋天收割完了农作物,清点产出,发现今年的产出与丰收年相近,那他就可以执行丰收年的决策,也就是执行 s = 1 s=1 s=1的那一套决策。或者,也可以根据实际的产出,做再一次的优化。

但是如何能精确的达到108390的收益呢?

答案是,不能保证一定达到。

因为随机规划的目标函数值108390,只是一个事先给出的评估,也就是期望可以达到这么多收益,但是实际能不能达到,那是未知的。只能说,随机规划提供的方案,可以让你平均获得108390的收益。虽然说比起丰收年假设下的167666.67要低了 59276.67 59276.67 59276.67,低了35%,但是比却比灾害年高了80%。

我们发现,在3种确定的场景下的解的平均值为
167666.67 + 118600 + 59950 3 ≈ 115406 \begin{aligned} \frac{167666.67 + 118600 + 59950}{3} \approx 115406 \end{aligned} 3167666.67+118600+59950115406
但是,随机规划的解为108390,随机规划比3种情形下的最优解的平均值低了 115406 − 108390 = 7016 115406 - 108390 = 7016 115406108390=7016,也就是说,不完全的信息,导致的损失为7016,这叫做expected value of perfect information (EVPI), 也就是profit loss due to uncertainty。确实,不确定行势必会带来一定的利润损失。

有些小伙伴也许就会问了,随机规划的解,究竟有什么意义呢?根据上面说的,分别在3种场景下求解模型,得到的解的平均值,要比随机规划的解要好,那随机规划的意义何在?

这里我们就需要来介绍Birge大佬的书中给出的The value of the stochastic solution.

The value of the stochastic solution

接下来我们来探索,随机规划的解,究竟意义何在。

上面产出了,分别在3种场景下求解模型,得到的解的平均值,要比随机规划的解要好,但是我们事前并不知道真实情况更接近于哪一种场景,所以,完整信息下的解,只能是理想情况,不太可能被真正达到。

因此,我们有一个简单的想法,既然模型中的随机变量(也就是本例中的亩产量)不确定,我们可否取其平均值来计算呢?

我们来验证一下。

If use average information

根据丰收年平均年灾害年的亩产量,我们计算出亩产量的平均值

  • 小麦: 3 + 2.5 + 2 3 = 2.5 \frac{3 + 2.5 + 2}{3} = 2.5 33+2.5+2=2.5
  • 玉米: 3.6 + 3 + 2.4 3 = 3 \frac{3.6 + 3 + 2.4}{3} = 3 33.6+3+2.4=3
  • 甜菜: 24 + 20 + 16 3 = 20 \frac{24 + 20 + 16}{3} = 20 324+20+16=20

我们以这个参数,重新求解确定性的模型,得到3者最优的种植亩数。

from gurobipy import * 
model = Model('deterministic version')
x = {} 
y = {}
w = {} 
for i in range(1, 4):
    x[i] = model.addVar(lb = 0, vtype=GRB.CONTINUOUS, name = 'x_%d'%i) 
for i in range(1, 3): 
    y[i] = model.addVar(lb = 0, vtype=GRB.CONTINUOUS, name = 'y_%d'%i)  
for i in range(1, 5): 
    w[i] = model.addVar(lb = 0, vtype=GRB.CONTINUOUS, name = 'w_%d'%i)   

# set the objective function 
model.setObjective(150 * x[1] + 230 * x[2] + 260 * x[3]   # plantation cost 
                   + 238 * y[1] + 210 * y[2]              # buying cost 
                   - 170 * w[1] - 150 * w[2] - 36 * w[3] - 10 * w[4]  # selling income 
                   , GRB.MINIMIZE
                   )

# set the constraints 
model.addConstr(x[1] + x[2] + x[3] <= 500) 
model.addConstr(2.5 * x[1] + y[1] - w[1] >= 200)   # change the coefficient 
model.addConstr(3 * x[2] + y[2] - w[2] >= 240)   # change the coefficient  
model.addConstr(w[3] + w[4] <= 20 * x[3])          # change the coefficient   
model.addConstr(w[3] <= 6000)  

# solve the model 
model.optimize() 

# print the solution 
print('Obj \t\t = {}'.format(model.ObjVal)) 
for key in x.keys():
    if(x[key].x > 0):
        print('{} \t\t = {}'.format(x[key].varName, x[key].x)) 
for key in y.keys():
    if(y[key].x > 0):
        print('{} \t\t = {}'.format(y[key].varName, y[key].x)) 
for key in w.keys():
    if(w[key].x > 0):
        print('{} \t\t = {}'.format(w[key].varName, w[key].x))  

运行结果如下:

Solved in 4 iterations and 0.01 seconds
Optimal objective -1.186000000e+05
Obj 		 = -118600.0
x_1 		 = 120.0
x_2 		 = 80.0
x_3 		 = 300.0
w_1 		 = 100.0
w_3 		 = 6000.0

可知,在这种情形下

  • 种植小麦120亩( x 1 = 120 x_1=120 x1=120)
  • 玉米80亩( x 2 = 80 x_2=80 x2=80)
  • 甜菜300亩( x 3 = 300 x_3=300 x3=300)

农民拿到了这个解,就真的在年初种了120亩小麦、80亩玉米、300亩甜菜。但是到了这一年的秋天,就可能遇到3中情况。

丰收年

在丰收年,我们将参数改为丰收年的参数,并且将下面的变量的值固定: x 1 = 120 x_1=120 x1=120 x 2 = 80 x_2=80 x2=80 x 3 = 300 x_3=300 x3=300

并且,在丰收年,小麦、玉米和甜菜的亩产量分别为3、3.6、24.

# set the objective function 
model.setObjective(150 * x[1] + 230 * x[2] + 260 * x[3]   # plantation cost 
                   + 238 * y[1] + 210 * y[2]              # buying cost 
                   - 170 * w[1] - 150 * w[2] - 36 * w[3] - 10 * w[4]  # selling income 
                   , GRB.MINIMIZE
                   )
# set the constraints 
model.addConstr(x[1] + x[2] + x[3] <= 500) 
model.addConstr(3 * x[1] + y[1] - w[1] >= 200)   # change the coefficient 
model.addConstr(3.6 * x[2] + y[2] - w[2] >= 240)     # change the coefficient  
model.addConstr(w[3] + w[4] <= 24 * x[3])          # change the coefficient   
model.addConstr(w[3] <= 6000)                   
 
model.addConstr(x[1] == 120) 
model.addConstr(x[2] == 80)
model.addConstr(x[3] == 300)

求解结果为

Solved in 0 iterations and 0.01 seconds
Optimal objective -1.480000000e+05
Obj 		 = -148000.0
x_1 		 = 120.0
x_2 		 = 80.0
x_3 		 = 300.0
w_1 		 = 160.0
w_2 		 = 48.0
w_3 		 = 6000.0
w_4 		 = 1200.0

最优解为148000

平均年

在平均年,我们将参数改为平均年的参数,并且将下面的变量的值固定: x 1 = 120 x_1=120 x1=120 x 2 = 80 x_2=80 x2=80 x 3 = 300 x_3=300 x3=300

并且,在平均年,小麦、玉米和甜菜的亩产量分别为2.5、3、20.

# set the objective function 
model.setObjective(150 * x[1] + 230 * x[2] + 260 * x[3]   # plantation cost 
                   + 238 * y[1] + 210 * y[2]              # buying cost 
                   - 170 * w[1] - 150 * w[2] - 36 * w[3] - 10 * w[4]  # selling income 
                   , GRB.MINIMIZE
                   )

# set the constraints 
model.addConstr(x[1] + x[2] + x[3] <= 500) 
model.addConstr(2.5 * x[1] + y[1] - w[1] >= 200)   # change the coefficient 
model.addConstr(3 * x[2] + y[2] - w[2] >= 240)     # change the coefficient  
model.addConstr(w[3] + w[4] <= 20 * x[3])          # change the coefficient   
model.addConstr(w[3] <= 6000)                    
  
model.addConstr(x[1] == 120) 
model.addConstr(x[2] == 80)
model.addConstr(x[3] == 300)  

求解结果为

Optimal objective -1.186000000e+05
Obj 		 = -118600.0
x_1 		 = 120.0
x_2 		 = 80.0
x_3 		 = 300.0
w_1 		 = 100.0
w_3 		 = 6000.0

最优解为118600

灾害年

在灾害年,我们将参数改为灾害年的参数,并且将下面的变量的值固定: x 1 = 120 x_1=120 x1=120 x 2 = 80 x_2=80 x2=80 x 3 = 300 x_3=300 x3=300

并且,在灾害年,小麦、玉米和甜菜的亩产量分别为2、2.4、16.

# set the objective function 
model.setObjective(150 * x[1] + 230 * x[2] + 260 * x[3]   # plantation cost 
                   + 238 * y[1] + 210 * y[2]              # buying cost 
                   - 170 * w[1] - 150 * w[2] - 36 * w[3] - 10 * w[4]  # selling income 
                   , GRB.MINIMIZE
                   )

# set the constraints 
model.addConstr(x[1] + x[2] + x[3] <= 500) 
model.addConstr(2 * x[1] + y[1] - w[1] >= 200)   # change the coefficient 
model.addConstr(2.4 * x[2] + y[2] - w[2] >= 240)     # change the coefficient  
model.addConstr(w[3] + w[4] <= 16 * x[3])          # change the coefficient   
model.addConstr(w[3] <= 6000)                   
  
model.addConstr(x[1] == 120) 
model.addConstr(x[2] == 80)
model.addConstr(x[3] == 300)   

求解结果为

Obj 		 = -55120.0
x_1 		 = 120.0
x_2 		 = 80.0
x_3 		 = 300.0
y_2 		 = 48.0
w_1 		 = 40.0
w_3 		 = 4800.0

最优解为55120

平均值

也就是说 ,在用平均值做为参数求得的第一阶段的解( x 1 = 120 x_1=120 x1=120 x 2 = 80 x_2=80 x2=80 x 3 = 300 x_3=300 x3=300),在3种场景下的最优解分别为14800011860055120,他们的平均值为
148000 + 118600 + 55120 3 = 107240.0 \begin{aligned} \frac{148000 + 118600 + 55120 }{3} = 107240.0 \end{aligned} 3148000+118600+55120=107240.0

这与随机规划的解 108390 108390 108390是有差距的。随机规划的解比上述利用平均信息获得的平均目标函数多 108390 − 107240 = 1150 108390-107240=1150 108390107240=1150

也就是说,我们考虑了3种场景的随机因素,得到的解,要比只考虑参数平均值的情形要优越。

他们之间的差距(也就是1150),就是The value of the stochastic solution

说明,仅仅用参数的平均值做出的决策时比较差的。利用随机规划,考虑不确定的信息,得到的解更加优越。

后记

感谢来信的这位师弟。他有趣的问题促使我完成了这篇推文。

这次邮件讨论非常愉快。希望今后有更多这样深入的讨论。

参考文献

[1] Birge J R, Louveaux F. Introduction to stochastic programming[M]. Springer Science & Business Media, 2011.

  • 12
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值