蒙特卡洛法是基于大量事件的统计结果来实现一些确定性问题的计算。而在规划问题中,蒙特卡洛法可以通俗理解为枚举法,通过产生很多随机数,对每一个随机数都进行判断是否符合约束条件,进而再计算目标函数的值,最后汇总比较得出其中最大(最小)的值,便是其解。
理论上,蒙特卡洛法可以解决所有规划问题,但由于其只能求解近似解,而对于线性规划、特殊的非线性规划和特殊的整数规划,可以用对应的函数求出精确解,所以蒙特卡洛法适用于无法求出精确解的大部分非线性规划和整数规划。
m a x z = x 1 2 + x 2 2 + 3 x 3 2 + 4 x 4 2 + 2 x 5 2 − 8 x 1 − 2 x 2 − 3 x 3 − x 4 − 2 x 5 , max \quad z=x_1^2+x_2^2+3x_3^2+4x_4^2+2x_5^2-8x_1-2x_2-3x_3-x_4-2x_5, maxz=x12+x22+3x32+4x42+2x52−8x1−2x2−3x3−x4−2x5,
s . t . { 0 ≤ x i ≤ 99 , i = 1 , ⋯ , 5 , x 1 + x 2 + x 3 + x 4 + x 5 ≤ 400 , x 1 + 2 x 2 + 2 x 3 + x 4 + 6 x 5 ≤ 800 , 2 x 1 + x 2 + 6 x 3 ≤ 200 , x 3 + x 4 + 5 x 5 ≤ 200 s.t. \begin{cases} 0\le x_i\le 99,\quad i=1,\cdots,5, \\ x_1+x_2+x_3+x_4+x_5\le 400,\\ x_1+2x_2+2x_3+x_4+6x_5\le 800,\\ 2x_1+x_2+6x_3\le 200,\\ x_3+x_4+5x_5\le 200\\ \end{cases} s.t.⎩⎪⎪⎪⎪⎪⎪⎨⎪⎪⎪⎪⎪⎪⎧0≤xi≤99,i=1,⋯,5,x1+x2+x3+x4+x5≤400,x1+2x2+2x3+x4+6x5≤800,2x1+x2+6x3≤200,x3+x4+5x5≤200
用于定义目标函数f和约束向量函数g,matlab程序如下:
function [f,g] = mengte(x)
% mengte()蒙特卡洛函数 输入对应解的向量,返回目标函数值f 以及 约束函数值g
% 目标函数
f=x(1)^2 + x(2)^2 + 3*x(3)^2 + 4*x(4)^2 + 2*x(5)^2 - 8*x(1) - 2*x(2) - 3*x(3) - x(4) - 2*x(5);
% 约束函数
g=[sum(x)-400 % sum()函数用于对向量求和,或对矩阵的列求和,即x(1) + x(2) + x(3) + x(4) + x(5)
x(1) + 2*x(2) + 2*x(3) + x(4) + 6*x(5) - 800
2*x(1) + x(2) + 6*x(3) - 200
x(3) + x(4) + 5*x(5) - 200];
end
% 蒙特卡洛法
% 用matlab来进行 蒙特卡洛法 ,可以得到一个满意的解,理论上也是非常接近精确解
% 但它并不是精确解,所以它每一次的解都会不一样
rand('state', sum(clock)); % 初始化随机数发生器
% 用rand('state',X)来设置随机数流的状态,使随机数随X来改变
% 与C++中的seed相似
p0=0;
tic % 计时开始 呼应上文的clock
for i = 1:10^6
x=randi([0,99], 1, 5); % 产生一行五列的在区间[0, 99]上的随机整数
% randi()函数,用于产生一个随机整数矩阵
[f, g] = mengte(x); % 调用mengte()函数
if all(g<=0) % 使用约束函数进行限制
% all()函数 对向量/矩阵所有项进行相同的逻辑比较,并返回bool值
if p0 < f % 用p0储存上一个的f值,并通过比较来得到最大的f
x0 = x; % 记录目前达到最大值的x值
p0 = f; % 记录目前的最大值
end
end
end
x0,p0 % 输出x0和p0的值
参考资料:
[1] 司守奎, 孙兆亮. 数学建模算法与应用[M].北京:国防工业出版社,2020:2.