数模入门——关于NP问题的智能算法求解

1、写在前面

  • 中国大学生数学建模大赛(CUMCM)是全国高校规模最大的基础学科竞赛,也是世界规模最大的数学建模竞赛。由于其巨大的影响力,数模比赛奖项的含金量也是极高的。那么如何准备该项赛事呢?笔者自己是从经典题目入手,先根据自己想法初步拟定算法思路,再查询相关文献优化解法。在这篇博客中,笔者会分享自己对一道问题的解决思路,希望能起到抛砖引玉的效果。

2、问题阐述

  某同学要从15 家商城中 选购20本书籍, 给出该同学最省钱的选购方案。小条件:如果在同一个书店的消费额不低于88元,那么这个书店包邮,即在这个书店买书不用出运费了。

PS:数据库

3、问题分析

  这是一个经典的优化问题——书店买书。初看该题目,似乎是一个比较简单的规划问题。思路是很直接的,通过0-1规划,通过购买矩阵和价格矩阵相乘,加上邮费矩阵,最后通过规划求最小值。然而0-1规划问题的解决难度是比较大的,一般思路通过松弛变量法为转化为连续性规划问题解决。但由于邮费阵的加入,这样的思路精确求解该题的难度较大。

  经分析不难发现,该题的主要难点在于运算的规模呈指数型增大,是一个典型的NP问题。若通过枚举的方式求取最优解,那么运算将达到15^20的恐怖规模,显然是无法求解的。那么如果无法求得一个准确的最优解,是否可以通过求得一个尽可能逼近最优的次优解以解决问题呢?

4、算法设计

  那么我们思考的重点应转换为如何建立费用函数关系,确定解空间的范围,建立一种新解的产生方式。当然最重要的是解决解的接受以及将解空间不断缩小的问题。

  在此思路下,一个常见的想法是运用蒙特卡洛模拟,即随机生成很多组解,然后验证这些解是否满足题目的约束条件。若满足则将其保存到一个“可行集"中,然后计算这个可行集内每个解对应的目标函数值,在里面找到最值即可。该思路乍看一定程度上解决了解空间过于巨大的问题,再通过迭代,似乎最终能逼近最优解。

  这样的算法固然可能得到答案,但无法保证得到解的最优性。因为蒙特卡洛模拟的弊端在于,难以处理局部最优解问题。这样的盲目搜索算法每次都会选择当前的最优解。那么当步长很小时,局部最优解的左右都不会被选择,导致其一直在局部最优解附近波动。

解会在陡峭的极大值附近波动

  要解决这个问题,我们自然希望能在算法在小峰上徘徊不前时,给予它一些提示,让它能继续前进。为了实现这样带启发的搜索,我们考虑采用智能算法求解。有多种智能算法都可能适应该题的求解,包括模拟退火算法、免疫算法以及遗传算法

5、智能算法

  在这里我们通过经典的“袋鼠蹦跳”问题来理解智能算法的大致思路。

我们把函数曲线理解成一个一个山峰和山谷组成的山脉。那么我们可以设想所得到的每一个解就是一只袋鼠,我们希望它们不断的向着更高处跳去,直到跳到最高的山峰。所以求最大值的过程就转化成一个“袋鼠跳”的过程。

  那么我们可以有以下几种“袋鼠跳”的方式:

  1. 爬山算法:一只袋鼠朝着比现在高的地方跳去。它找到了不远处的最高的山峰。但是这座山不一定是最高峰。这就是爬山算法,它不能保证局部最优值就是全局最优值。
  2. 模拟退火:袋鼠喝醉了。它随机地跳了很长时间。这期间,它可能走向高处,也可能踏入平地。但是,它渐渐清醒了并朝最高峰跳去。这就是模拟退火算法。
  3. 遗传算法:有很多袋鼠,它们降落到喜玛拉雅山脉的任意地方。这些袋鼠并不知道它们的任务是寻找珠穆朗玛峰。但每过几年,就在一些海拔高度较低的地方射杀一些袋鼠。于是,不断有袋鼠死于海拔较低的地方,而越是在海拔高的袋鼠越是能活得更久,也越有机会生儿育女。就这样经过许多年,这些袋鼠们竟然都不自觉地聚拢到了一个个的山峰上,可是在所有的袋鼠中,只有聚拢到珠穆朗玛峰的袋鼠被带回了美丽的澳洲。

6、遗传算法

  针对此题,我们考虑通过遗传算法来求解。其算法设计思路如下:

  1. 随机产生种群。
  2. 根据策略判断个体的适应度,是否符合优化准则,若符合,输出最佳个体及其最优解,结束。否则,进行下一步。
  3. 依据适应度选择父母,适应度高的个体被选中的概率高,适应度低的个体被淘汰。
  4. 用父母的染色体按照一定的方法进行交叉,生成子代。
  5. 对子代染色体进行变异。
  6. 由交叉和变异产生新一代种群,返回步骤2,直到最优解产生。
遗传算法过程图解

  由此得出该题初步算法实现:

算法实现流程

  在这道题中,我们将20本书组成的向量视作染色体,同一本书在不同商家购买的价格视作等位基因,由此可以建立初始种群矩阵。该算法的核心在于设计评价函数即选择函数。由于我们要求的是费用最低,那么自然将总费用视作评价指标,因此我们可以设置评价函数=书本费向量+邮费矩阵。然后将函数值归一化即得到该个体的适合度(fitvalue)。为了选择出更适宜环境的个体,我们构造轮盘,使得适合度更大的个体产生的子代数量更多,MATLAB实现代码如下(其中pop为二进制化后的种群):

function [newpop] = selection(pop,fitvalue)
%构造轮盘
[px,py] = size(pop);
totalfit = sum(fitvalue);
p_fitvalue = fitvalue/totalfit;
p_fitvalue = cumsum(p_fitvalue);%概率求和排序
ms = sort(rand(px,1));%从小到大排列
fitin = 1;
newin = 1;
while newin<=px
    if(ms(newin))<p_fitvalue(fitin)
        newpop(newin,:)=pop(fitin,:);
        newin = newin+1;
    else
        fitin=fitin+1;
    end
end

  最后通过编程实现该算法。这里笔者通过MATLAB软件实现,由于篇幅原因略去具体代码。

7、总结

  遗传算法(Genetic Algorithm, GA)是模拟达尔文生物进化论的自然选择和遗传学机理的生物进化过程的计算模型,是一种通过模拟自然进化过程搜索最优解的方法。其主要特点是直接对结构对象进行操作,不存在求导和函数连续性的限定;具有内在的隐并行性和更好的全局寻优能力;采用概率化的寻优方法,不需要确定的规则就能自动获取和指导优化的搜索空间,自适应地调整搜索方向。

  在算法的具体实现中,主要的难点在于编码方式的选择、适应度评估函数的建立以及变异函数的选用,应结合具体问题分析求解。

8、参考文献

[1]李振,胡庆东,张国英,马湘.基于小生境遗传算法的人工拣货路径优化研究[J].物流科技,2011,34(06):85-88.

[2]冯如玉. 综合货损和搬运成本的拣货路径优化模型研究[D].深圳大学,2019.

posted @ 2021-03-25 22:36  WHU-TD  阅读(1279)  评论(0编辑  收藏  举报