前言 爬山算法 以最简单的连续一元函数找最大值为例,大致阐述一下爬山法
在解空间中随机生成一个初始解; 根据初始解的位置,在下一步有两种走法:向左邻域走一步或者向右邻域走一步 (走的步长越小越好,但会加大计算量); 比较不同走法下目标函数的大小,并决定下一步往哪个方向走。 不断重复 3 ,直到找到一个极大值点(或定义域边缘处),结束搜索。
很明显,如果初始解在途中局部最大值附近,那么最后有可能直接在局部最大值处结束。
而从“上帝视角”来看,局部最大值 本非全局最大值!
综上所述,爬山法属于一种 贪心算法 ,很容易陷入局部最优。
蒙特卡洛 待更
原理 模拟退火算法是一种基于蒙特卡洛 思想设计的近似求解最优化问题 的方法。
它是一种适合解大规模组合优化问题 的通用有效近似算法,是局部搜索算法 的扩展。
它通过在搜索过程引入随机因素。使得计算过程中会以一定的概率来接受一个比当前解要差的解 ,因此有可能**会跳出这个局部的最优解,达到全局的最优解。
所以从理论上来说它是一个能求得全局最优化结果的算法,它是一种启发式算法 ,源于对固体退火 的研究。
退火
算法细则 代码模板 Matlab 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 clc;clear all;close all; a=0.95 ; T0 = 100 ; Tf = 0.1 ; T = T0; mar_length=1000 ; sol_new=round (rand (1 ,num)); E_current=inf ; E_best=inf ; while T > Tf for i =1 :mar_length E_new = func(sol_new); if E_new<E_current E_current=E_new; sol_current=sol_new; if E_new<E_best E_best=E_new; sol_best=sol_new; end else if (rand <exp (-(E_new-E_current)./T)) E_current=E_new; sol_current=sol_new; else sol_new=sol_current; end end end T=T*a; end disp ('最优路径如下:' );
Python 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 class MySA : def __init__ (self,alpha,T_max,T_min,length,sol0 ): self.a = alpha self.T0 = T_max self.Tf = T_min self.mar_len = length self.p = 0 self.best_sol = [] self.best_ans = float ('+inf' ) self.new_sol = copy.deepcopy(sol0) self.new_ans = func(self.new_sol) self.current_sol = copy.deepcopy(sol0) self.current_ans = float ('+inf' ) def update_p (self ): self.p = math.exp(-(self.new_ans-self.current_ans)/self.T0) def create_newsol (self ): ''' 如何产生的根据实际问题进行调整,此处略 ''' self.new_ans = func(self.new_sol) def derstart (self ): for i in range (self.mar_len): self.create_newsol() if self.new_ans < self.current_ans: self.current_sol = copy.deepcopy(self.new_sol) self.current_ans = self.new_ans if self.new_ans < self.best_ans: self.best_sol = copy.deepcopy(self.new_sol) self.best_ans = self.new_ans else : t = random.random() self.update_p() if t < self.p: self.current_sol = copy.deepcopy(self.new_sol) self.current_ans = self.new_ans else : self.new_sol = copy.deepcopy(self.current_sol) def get_sol (self ): while self.T0 > self.Tf: self.derstart() self.T0 = self.T0*self.a return self.best_sol,self.best_ans
参考资料 1.模拟退火算法|bilibili专栏
2.数学建模清风第二次直播:模拟退火算法|bilibili
模拟退火算法 | Simulated-Annealing