一、Xprog
1.工具箱简介
Xprog是由新加坡国立大学的Peng Xiong于2016年发布的一款matlab工具箱,可以用于求解确定性优化、随机优化、鲁棒优化和分布式鲁棒优化问题。目前文献中很常见的多阶段鲁棒优化问题,同样可以利用Xprog工具箱进行求解。
对于鲁棒优化的的求解方法,一般都是通过求对偶将鲁棒优化的目标函数进行转换,再采用常规方法进行求解,但求对偶问题的过程还是比较麻烦,很容易出问题。利用工具箱Xprog的话,就是帮你把求对偶,求解模型的过程封装起来,只需要给定决策变量,不确定集以及约束条件,就可以快速求出结果,省去繁琐的中间不走。另外,工具箱默认求解器是cplex,如果你用的是cplex教育版,可问题的规模是有限制的,使用xprog求解大规模问题时很有可能会报错。
2.工具箱的下载安装
Xprog工具箱的下载方式,可以参考这篇文章:
【学界】XPROG: 简单实用的鲁棒优化(RO, DRO)编程语言
安装步骤如下:
step1.下载完成之后,可以先将解压之后的文件放在matlab的toolbox文件夹下:
step2.点击设置路径,将Xprog添加到matlab搜索路径中:
step3.在matlab命令行中输入configure并回车,如果使用的是cplex12.6.1-3之间的版本,直接输入对应的数字就可以安装:
如果使用的是其他版本的cplex,则需要事先安装一个兼容的C/C++编译器,然后在命令行输入mex-setup命令激活matlab和C++的混合编译,然后再运行configure,这样也可以顺利安装Xprog工具箱。
混合编译的步骤可以参考这篇博客:
提示“Xprog configuration completed!”就代表工具箱配置成功了。
step4.如果使用了其他版本的matlab,最后还需要把cplex根目录(cplex/bin)中的cplexxxx.dll文件复制到Xprog工具箱的functions文件夹中,就完成了Xprog的安装。
3.工具箱测试
以下算例都来自Xprog用户手册:
3.1 算例1:简单线性规划
matlab代码:
model=xprog('Simple LP'); % 新建一个名为"Simple LP"的Xprog模型 x=model.decision; % 给模型新增一个变量x y=model.decision; % 给模型新增一个变量y model.max(3*x+4*y); % 目标函数,求max model.add(2.5*x+y<=20); % 增加第1个约束条件 model.add(3*x+3*y<=30); % 增加第2个约束条件 model.add(x+2*y<=16); % 增加第3个约束条件 model.add(x>=0); % x的范围 model.add(y>=0); % y的范围 model.solve; % 求解模型 Obj=model.get % 求解目标函数值 X =x.get % 求x的取值 Y =y.get % 求y的取值
运行结果:
3.2 算例2:随机规划问题
一家家具公司生产的书桌(desks)、餐桌(tables)和椅子(chairs),售价分别为60美元、40美元和10美元。每种产品的制造都需要木材(lumber)和两种工人:安装工(finishing)和木工(Carpentry)。下表列出了每种资源的成本和制造每种类型的家具所需的数量:
在这个问题中,每个产品的需求都是不确定的。不确定的需求有三种情况:“需求低(low)”、“需求还行(most likely)”和“需求多(high)”。各情景和相关概率的结果如下表:
表示是场景s中家具i的需求,是场景s的概率。设x为表示所购买资源数量的第一阶段决策,决策变量y表示在第s个场景中生产的书桌、餐桌和椅子的数量。目标函数为利润最大化,可用随机规划问题表示为:
matlab代码:
model=xprog('SP Example'); % 新建一个名为"SP Example"的xprog模型 x=model.decision(3); % 第一阶段的决策变量x y=cell(1,3); % 新建三维元胞变量y,分别表示三个场景 for s=1:3 y{s}=model.decision(3); % 为场景s定义第二阶段决策变量y(s) end P= [0.3 0.4 0.3]; % 三个场景的概率 c=-[2 4 5.2]; % 第一阶段目标函数的系数 q= [60 40 10]; % 第二阶段目标函数的系数 Exp=0; for s=1:3 Exp=Exp+P(s)*q*y{s}; % 第二阶段目标函数的期望 end model.max(c*x+Exp); W=[8 6 1; % 定义约束矩阵 4 2 1.5; 2 1.5 0.5]; D=[50 150 250; % 定义随机的需求矩阵 20 110 250; 200 225 500]; for s=1:3 model.add(W*y{s}-x<=0); % 添加约束条件add 1st~3rd constraints model.add(y{s}>=0); % y(s)的范围 model.add(y{s}<=D(:,s)); % 需满足需求的约束 end model.add(x>=0) % x的范围 model.solve; % 求解问题 Obj=model.get % 目标函数取值 X =x.get % 变量x的取值
运行结果:
3.3算例3:鲁棒优化问题
假设一共有150种股票可供选择,股票i的不确定收益用表示,其取值满足约束条件:,其中,表示股票i的期望收益,表示股票i的偏差,不确定集可以用一范数和无穷范数表示为:
该投资组合问题的鲁棒优化模型可以表示为:
在本例中,假设Γ=5,参数pi和σi满足如下公式:
这两个方程表明,期望收益较高的股票也具有较高的不确定性水平。
matlab代码表示为:
n = 150; % 股票的数量 p = 1.15+ 0.05/150*(1:n)'; % 期望的收益 sigma = 0.05/450*sqrt(2*n*(n+1)*(1:n)'); % 收益的偏差 Gamma = 5; model=xprog('portfolio'); % 新建一个xprog模型 x=model.decision(n); % 决策变量x % 随机变量和不确定集 z=model.random(n); % 与期望收益之间的不确定偏差z u=model.random(n); % z的绝对值 model.uncertain(abs(z)<=1); % z的无穷范数小于1 model.uncertain(abs(z)<=u); % 用u表示z的绝对值 model.uncertain(sum(u)<=Gamma); % z的1范数小于Γ r = p + sigma.*z; % 股票的不确定性收益 model.max(r'*x) % 目标函数 %model.add(a<=r'*x); % a是目标的下界 model.add(sum(x)==1); % x的约束条件 model.add(x>=0); % x的范围 model.solve; % 求解鲁棒优化问题 Obj=model.get % 目标函数取值 plot(x.get) % 图形表示购买股票的比例
运行结果
可以看到,对于简单的确定性优化问题、随机规划问题与鲁棒优化,Xprog都可以快速求解,功能还是比较强大的。
二、RSOME
1.工具箱简介
还有一个针对鲁棒随机优化设计的matlab工具箱——RSOME(Robust Stochastic Optimization Made Easy),也可以用来解决一般的线性规划、随机规划、鲁棒优化和数据驱动的分布式鲁棒优化问题。Xprog的作者是Dr. Peng Xiong,他也是RSOME的三位作者之一,两个工具箱的编程思路和数据格式都是比较类似的。
Xprog求解优化时调用的是cplex求解器;RSOME的默认求解器是cplex,但是同样支持gurobi或mosek求解器。
2.工具箱的下载安装
直接去官网下载就可以:
Robust Stochastic Optimization Made Easy
安装步骤比较简单:
安装步骤如下:
step1.下载完成之后,可以先将解压之后的文件放在matlab的toolbox文件夹下:
step2.点击设置路径,将RSOME添加到matlab搜索路径中即可:
3.工具箱测试
以下算例都来自于RSOME工具箱用户手册:
3.1简单线性规划
matlab代码:
model = rsome('LP Exmaple'); % 新建一个名为"LP Example"的模型 x = model.decision; % 决策变量x y = model.decision; % 决策变量y model.max(3*x + 4*y); % 目标函数 model.append(2.5*x + y <= 20); % 约束条件1 model.append(x + 2*y <= 16); % 约束条件2 model.append(abs(y) <= 4); % 约束条件3 model.solve; % 求解问题 Obj = model.get; % 目标函数取值 X = x.get; % 变量x取值 Y = y.get; % 变量y取值
运行结果:
3.2 鲁棒优化问题
对于上文中提到的股票投资组合问题,是一个典型的鲁棒优化问题:
同样可以采用RSOME进行数学建模,matlab代码如下:
n = 150; % 股票数量 p = 1.15+ 0.05/150*(1:n)'; % 期望收益 sigma = 0.05/450*sqrt(2*(1:n)'*n*(n+1)); % 偏差 Gamma = 3; model=rsome('portfolio'); % 新建一个名为"portfolio"的rsome模型 x=model.decision(n); % 决策变量x z=model.random(n); % 与期望收益之间的不确定性偏差 P = model.ambiguity; % 模型的模糊集集 P.suppset(norm(z, Inf) <= 1, ... norm(z, 1) <= Gamma); % z的不确定集合表示 model.with(P); % 将P表示为模型的模糊集 r = p + sigma.*z; % 股票的不确定收益 model.max(r'*x) % 目标函数 model.append(sum(x)==1); % 约束条件 model.append(x>=0); % x的范围 model.solve; % 求解问题 plot(x.get) % 画图表示 Obj=model.get; % 目标函数取值
运行结果:
3.3 分布式鲁棒优化问题
考虑一个单产品的报童问题,报童问题是一个典型的存贮问题,也可以用分布式鲁棒优化模型来表示。假设p为一份报纸的售价,c为一份报纸的成本,w为决策变量,表示报童订购的报纸数,为用户的不确定性需求,。是一个随机变量,服从于概率分布,即,概率分布包含于模糊集,也就是。用Wasserstein模糊集表示为:
式中,S是样本数量,是Wasserstein球半径,为场景s下需求的估计值,表示两者之间的Wasserstein距离,通过引入一个中间变量,可以把模糊集改写为如下形式:
则该问题的分布式鲁棒优化模型可以表示为:
取p=1.5,c=1,=100,S=500,=0.01,则该鲁棒优化问题可以用matlab代码表示为:
%% 参数 Ubar = 100; % 不确定需求的上限 S = 500; % 样本数 Uhat = Ubar * rand(1, S); % 需求的经验分布 p = 1.5; % 一份报纸的售价 c = 1.0; % 一份报纸的成本 theta = Ubar*0.01; % Wasserstein球半径 %% Create a RSOME model model = rsome('newsvendor'); % 创建一个名为"newsvendor"的rsome模型 %% Random variables and a type-1 Wasserstein ambiguity set u = model.random; % 不确定的需求变量u v = model.random; % 中间变量v P = model.ambiguity(S); % 创建具有S个场景的模糊集 for n = 1:S P(n).suppset(0 <= u, u <= Ubar, ... norm(u-Uhat(n)) <= v );% 定义每个场景的支持集 end P.exptset(expect(v) <= theta); prob = P.prob; % 所有场景的概率分布函数 P.probset(prob == 1/S); % 每个场景的概率 model.with(P); % 将P定义为模型的模糊集 %% 决策变量 w = model.decision; % 决策变量w %% 目标函数 loss = maxfun({p*(w-u), 0}); % 未售出部分造成的损失 model.max((p-c)*w - expect(loss)); % 分布式鲁棒优化的目标函数 %% 约束条件 model.append(w >= 0); % w的取值范围 %% 求解问题 model.solve; % 求解模型 %% 结果 obj=model.get; % 目标函数取值 W=w.get; % 决策变量取值 disp(['目标函数取值:',num2str(obj),',决策变量取值:',num2str(W)])
运行结果: