0.说明
- 本文是鸡年新年计划的内容之一:每周学习一个数学模型,写一篇总结,记录自己学到的东西和遇到的问题。
- 这些文章并不是相关模型的全面介绍,也不是从最基础的开始,所以不一定适合数学模型的beginner,但都是些很实际的技术,希望能帮到你。
- 本文的重点是使用Monte Carlo方法求解非线性规划。
1.向大家求助的问题
关于下面的这些问题,我迫切的需要你的帮助,哪怕是一些网址和信息,所以,感谢你给我发邮件[email protected]或直接加我QQ好友:117829132(请一定注明“帮助你”)或直接在评论中留言。
1.Monte Carlo方法求解非线性规划,取多少个点是至关重要的,欢迎你告诉我更多实用的、确定点数的方法。
2.一个线性规划模型记为M,限制其中某些(或全部)决策变量只能取整数后得到一个整数线性规划,记为M’。即使M有最优解,M’也有可能甚至没有可行解,为什么?
2. 用Monte Carlo 方法求解如下非线性整数规划
使用MATLAB编写程序求解,需要编写两个程序:
计算给定点的目标函数值和约束条件值的程序如下:
function [ f, g ] = ex2_6( x )
f = [1 1 3 4 2] * (x.^2)' - [8 2 3 1 2] * x';
g = [ sum(x) - 400
[1 2 2 1 6] * x' - 800
[2 1 6 0 0] * x' - 200
[0 0 1 1 5] * x' - 200];
随机选取点进行验证和统计的程序如下:
fix(clock) %显示当前时刻,也就是程序开始运行的时刻
x00=[];p00=[];t=[];%初始化三个变量,用于存放最优解(x00)、最优值(p00)和每个单次(取10^6个点)进行计算的时间,用于后续的分析
for k=1:3000 %为了测试性能和保证准确性,进行3000个单次的循环
rand( 'state', sum(clock)); %初始化随机数的种子
tic; %开始计时
p0 = 0; x0 = 0; %初始化这个单次的最优值和最优解
for i = 1:10^6 %共选取10^6个点
x = randi(99, 1, 5); %随时生成一个1行5列的x,每个元素是1至99之间的整数
[f, g] = ex2_6(x); %计算目标函数和约束条件的值
if all(g <= 0) %如果约束条件全部满足
if f>p0
p0 = f; x0 = x; %如果该值处的目标函数值比当前的最优值还大,那么更新最优值和最优解
end
end
end
%x0, p0
x00(k, :) = x0; %记录每个单次的最优解
p00(k, :) = p0; %记录每个单次的最优值
t(k)=toc; %记录每个单次的运行时间
end
x00
p00
fix(clock) %显示全部程序结束的时刻
t
上述程序共运行3000个单次,每个单次选择10^6个点进行验证。3000个单次共耗时36815秒、合计613.5793分钟、10.2263小时,比事前预估的时间少30几分钟。
用Monte Carlo方法找到的最优解是[41 99 3 99 17],最优值是,50623
该问题也可以用Lingo精确求解,准确的最优解是:[50 99 0 99 20],最优值是51568。
二者之间的差约为1.83%,对于很多问题而言,精度已经足够了。
2.关于randi函数和randint函数的异同
第一版的程序中,我使用的是randint函数来生成随机数,每个单次运行时间大约1400多秒,合计24分钟左右。每个单次选取10^6个点进行验证。
随后,按照MATLAB的提示,我换成randi函数,则每个单次的运行时间剧减为13至14秒之间。
开始我以为是对于程序的其他修改导致的,于是,我做了两个版本的程序,这两个版本之间只有该函数不同。尝试运行后randi版本的时间仍然是14秒左右。
为了保险起见,我还在重启电脑前后测试了randi版本的运行时间,结果是没有变化,也就是说,可以排除之前运行的程序可能残留的初值导致的运行时间的减少。
所以,我的结论是,使用randi函数生成随机整数,运行时间是使用较早版本MATLAB中的randint的时间1.1%,可以大幅度的提高仿真效率!!
3. 如何确定选取多少点
用Monte Carlo方法求解非线性规划时,一个非常重要的任务就是要确定选取多少点,点数过多则计算时间过长;点数太少则结果的准确性就会较差,如何取点是非常重要的。上述问题是纯整数规划,每个x可以取0至99共100个点,所以,全部验证所有可能性需要(100)^5=10^10个点,需要耗费大量的时间。
本文给出的,是验证10^6个点,下面粗略的说明,为什么验证10^6个点就足够了?(不失一般性,可以建设最优值点不是孤立的奇点)
假设每个点处的函数值落在高值区的可能性为0.01和0.00001,则当验证10^6个点后,至少有一个点落在高值区的概率为
可见,我们验证10^6个点就可以在高值区找到一个点的可能性还是非常高的。
需要注意的是,上述叙述中使用的是“高值区”,而不是最优点,这二者是不同的,请仔细区分。
未完待续