书店买书之0-1规划(蒙特卡罗模拟)
蒙特卡罗方法又称随机抽样或统计试验方法,通常蒙特卡罗模拟通过构造符合一定规则的随机数来解决数学上的各种问题。对于那些由于计算过于复杂而难以得到解析解或者根本没有解析解的问题,蒙特卡罗模拟是一种有效的求出数值解的方法。
蒙特卡罗算法表示采样越多,越近似最优解。举个例子,假如筐里有100个苹果,让我每次闭眼拿1个,挑出最大的。于是我随机拿1个,再随机拿1个跟它比,留下大的,再随机拿1个……我每拿一次,留下的苹果都至少不比上次的小。拿的次数越多,挑出的苹果就越大,但我除非拿100次,否则无法肯定挑出了最大的。这个挑苹果的算法,就属于蒙特卡罗算法。告诉我们样本容量足够大,则最接近所要求解的概率。
问题如下:
我们解决这种问题的根本思想是利用matlab的rand函数来模拟出每一种可能,并计算其结果,只要列出其全部结果或者列出其大部分情况,我就能无限接近最优答案。
解:设 i=1,2, … , 6 表示 A.B····E、F 六 家商城 , j=1,2···,5表示五本书。
记表示第j本书在第i家店的售价, 表示第i家店的运费。
当=0时,则没有在该店买书;当=1时,则在该店买书。
约束有: ,j=1,2,···,5 (每本书只买一本)
花费求和有两个方面:
1.书价=
2.运费 求解可参考如下代码
result = randi([1, 6],1,5); % 在1-6这些整数中随机抽取一个1*5的向量,表示这五本书分别在哪家书店购买
index = unique(result); % 在哪些商店购买了商品,因为我们等下要计算运费
money = sum(freight(index)); % 计算买书花费的运费
先通过unique函数确定在哪几家店买过书,然后通过其下标求和。(freight是一个记录每家店运费数组)
蒙特卡罗模拟和遗传算法的异同点:
同:都不同程度存在“随机性”
异:蒙特卡罗方法相当于一个人走迷宫,而遗传算法和粒子群可以找一群人来走迷宫。蒙特卡罗有一种究极暴力求解的感觉,而遗传算法则是看“运气”。
min_money = +Inf; % 初始化最小的花费为无穷大,后续只要找到比它小的就更新
min_result = randi([1, 6],1,5); % 初始化五本书都在哪一家书店购买,后续我们不断对其更新
%若min_result = [5 3 6 2 3],则解释为:第1本书在第5家店买,第2本书在第3家店买,第3本书在第6家店买,第4本书在第2家店买,第5本书在第3家店买
n = 100000; % 蒙特卡罗模拟的次数
M = [18 39 29 48 59
24 45 23 54 44
22 45 23 53 53
28 47 17 57 47
24 42 24 47 59
27 48 20 55 53]; % m_ij 第j本书在第i家店的售价
freight = [10 15 15 10 10 15]; % 第i家店的运费
for k = 1:n % 开始循环
result = randi([1, 6],1,5); % 在1-6这些整数中随机抽取一个1*5的向量,表示这五本书分别在哪家书店购买
index = unique(result); % 在哪些商店购买了商品,因为我们等下要计算运费
money = sum(freight(index)); % 计算买书花费的运费
% 计算总花费:刚刚计算出来的运费 + 五本书的售价
for i = 1:5
money = money + M(result(i),i);
end
if money < min_money % 判断刚刚随机生成的这组数据的花费是否小于最小花费,如果小于的话
min_money = money % 我们更新最小的花费
min_result = result % 用这组数据更新最小花费的结果
end
end