% {8 X2 [) j: E3 L / l6 t4 m7 K5 } B3 y* a
智能优化算法要解决的一般是最优化问题。最优化问题可以分为(1)求解一个函数中,使得函数值最小的自变量取值的函数优化问题和(2)在一个解空间里面,寻找最/ H- z Q8 f2 D
优解,使目标函数值最小的组合优化问题。典型的组合优化问题有:旅行商问题(Traveling 4 U; T( f9 `7 m. S Salesman Problem,TSP),加工调度问题(Scheduling ; @# E* A8 u( \+ v: d1 Y
Problem),0-1背包问题(Knapsack ?; n! u- A* Z- w5 m. Z9 e0 o
Problem),以及装箱问题(Bin Packing Problem)等。 0 r8 { E, L9 ~" \+ D. p/ r 优化算法有很多,经典算法包括:有线性规划,动态规划等;改进型局部搜索算法包括爬山法,最速下降法等,本文介绍的模拟退火、遗传算法以及禁忌搜索称作指导性搜7 b- V; d, c& v5 d9 X- g
索法。而神经网络,混沌搜索则属于系统动态演化方法。 ; m, Q; L% I9 _) _5 \ $ O/ Y+ S* ^1 c9 c& n) k$ T
+ ^: z5 `# J0 u8 E/ |8 m1 ?& r
优化思想里面经常提到邻域函数,它的作用是指出如何由当前解得到一个(组)新解。其具体实现方式要根据具体问题分析来定。 + `' F# z, A! E5 v& P0 i; @ $ G; @; ^' Y% p1 o1 o" {% ` 2 K2 ?" |6 `! A. P- H
一般而言,局部搜索就是基于贪婪思想利用邻域函数进行搜索,若找到一个比现有值更优的解就弃前者而取后者。但是,它一般只可以得到“局部极小解”,就是说,可能. c) M" a! h2 S2 @
这只兔子登“登泰山而小天下”,但是却没有找到珠穆朗玛峰。而模拟退火,遗传算法,禁忌搜索,神经网络等从不同的角度和策略实现了改进,取得较好的“全局最小解 ”。 0 b4 c, k( B0 D" s6 `9 }6 ?3 @ ; f$ _+ B& S+ Z8 V$ [
- T7 I/ C3 u7 {: F' G1 Z 模拟退火算法(Simulated Annealing,SA) : U, ]. I# U" g$ N! X 2 {* B2 I: ^8 z; T
; K9 F- k$ Z" {- e! E* k 模拟退火算法的依据是固体物质退火过程和组合优化问题之间的相似性。物质在加热的时候,粒子间的布朗运动增强,到达一定强度后,固体物质转化为液态,这个时候再1 H' F2 Q% X; H& R
进行退火,粒子热运动减弱,并逐渐趋于有序,最后达到稳定。 % g; d8 H0 l- ^3 Z: z8 P 5 W! z9 Z T- j4 R$ ?$ ~ ) \; Y" h& z k! ~
模拟退火的解不再像局部搜索那样最后的结果依赖初始点。它引入了一个接受概率p。如果新的点(设为pn)的目标函数f(pn)更好,则p=1,表示选取新点;否: l1 {% `" R1 N2 N$ [
则,接受概率p是当前点(设为pc)的目标函数f(pc),新点的目标函数f(pn)以及另一个控制参数“温度”T的函数。也就是说,模拟退火没有像局部搜索那 ' v) P( h+ o* n# M/ Y: J样每次都贪婪地寻找比现在好的点,目标函数差一点的点也有可能接受进来。随着算法的执行,系统温度T逐渐降低,最后终止于某个低温,在该温度下,系统不再接受变! Y, g. ?- A; \4 c* {3 j+ d& ^
化。& u! b! v+ ?! Y) E
' g ~3 ~* T* D% Z5 J2 Z, d
' r, i+ J0 g# P/ g Y
模拟退火的典型特征是除了接受目标函数的改进外,还接受一个衰减极限,当T较大时,接受较大的衰减,当T逐渐变小时,接受较小的衰减,当T为0时,就不再接受衰8 a$ k5 `. A6 G0 i3 f) X( X0 ^
减。这一特征意味着模拟退火与局部搜索相反,它能避开局部极小,并且还保持了局部搜索的通用性和简单性。1 R: _3 h. i8 q
在物理上,先加热,让分子间互相碰撞,变成无序状态,内能加大,然后降温,最后的分子次序反而会更有序,内能比没有加热前更小。就像那只兔子,它喝醉后,对比较; u# z# @/ [, [3 ]2 |+ C% N O. _
近的山峰视而不见,迷迷糊糊地跳一大圈子,反而更有可能找到珠峰。 + \+ l/ j! M6 R' }! n ; t4 v; \% k. W" z4 j 5 E# r# C( p" K9 }7 T i% f6 x, J* J 值得注意的是,当T为0时,模拟退火就成为局部搜索的一个特例。( v8 o) S" ?; A/ O6 ? J/ p4 {
& i/ o2 X4 W% [! l, h+ i: |. @
u% Q, H: [. Z/ d1 {1 Y# ` 模拟退火的伪码表达:7 x) e7 T# `) p3 A U1 K1 E
procedure simulated annealing 1 ]/ D2 N0 x. z6 G
begin & g, J# J/ }3 i1 E: _0 c6 P
t:=0; & q) ~$ S! R4 G% t( v- H$ f9 }7 f/ [ initialize temperature T 6 l) t1 [% {; U0 s
select a current string vc at random; , J7 }( ^, }" J6 u5 x# L/ v evaluate vc; , K' w) F; K4 P- w7 H
repeat ( i# b4 m" _1 P repeat 8 n. U/ i0 a$ r9 I4 K select a new string vn in the neighborhood of vc; (1) % p9 k; {* z& I
if f(vc) then vc:=vn; / t4 ^! ?7 Z* O+ Z1 S
else if random [0,1] then vc:=vn; 4 l: X6 l# P: S' p& b
until (termination-condition) (3) - V; A/ [" ?. S: Z8 G' [0 x- K
T:=g(T,t); (4) 7 `/ O* }+ Q+ M" b. Z l
T:=t+1; / i h( F) P, Y' M* y until (stop-criterion) (5) 9 V2 n6 p- Z' E end; ! Y) x% F9 C9 _+ U% @# U 1 N4 i& G* T' b8 A3 m& ^/ [
5 p' C/ O% |1 K; [7 t
上面的程序中,关键的是(1)新状态产生函数,(2)新状态接受函数,(3)抽样稳定准则,(4)退温函数,(5)退火结束准则! c+ _9 X% ]# T
(简称三函数两准则)是直接影响优化结果的主要环节。虽然实验结果证明初始值对于最后的结果没有影响,但是初温越高,得到高质量解的概率越大。所以,应该尽量选0 M1 p) |& T7 T8 m+ i& }: f
取比较高的初温。" D* W5 a) Y" Y1 s3 ^" ]
6 u: p* c" x" ]. U7 `0 w ! A, q" A) A" K3 d5 D
上面关键环节的选取策略: $ T) |: @, L: y8 g (1)状态产生函数:候选解由当前解的邻域函数决定,可以取互换,插入,逆序等操作产生,然后根据概率分布方式选取新的解,概率可以取均匀分布、正态分布、高斯2 O9 v3 B. p, X
分布、柯西分布等。/ y4 ` {6 Q1 J) ?0 C
2 Z( U$ R' f4 E ) X$ z" N: Y+ m Q' N+ t
(2)状态接受函数:这个环节最关键,但是,实验表明,何种接受函数对于最后结果影响不大。所以,一般选取min 4 H% Q @! Y7 i* O: S [1, exp ((f (vn)-f (vc))/T)]。+ h$ x' [9 u' B( D) U) M- K- P
(3)抽样稳定准则:一般常用的有:检验目标函数的均值是否稳定;连续若干步的目标值变化较小;规定一定的步数;* \$ @% @$ m: W* g# Z) i1 y2 \
' y( E( o, m+ A7 h& @, r ! c! F3 [8 [0 _; `& `
(4)退温函数:如果要求温度必须按照一定的比率下降,SA算法可以采用 . Z( w7 C1 v/ C' e ,但是温度下降很慢;快速SA中,一般采用' F! t# d: |3 D$ R
。目前,经常用的是 , 是一个不断变化的值。 / N" i% ^, H0 J- Z T. c0 F* Q (5)退火结束准则:一般有:设置终止温度;设置迭代次数;搜索到的最优值连续多次保持不变;检验系统熵是否稳定。5 C R4 H! A. X7 q+ T5 r( ]
" ?" e( p, n/ o( @: G3 J , W, C) ]8 y' a; a" \
为了保证有比较优的解,算法往往采取慢降温、多抽样、以及把“终止温度”设的比较低等方式,导致算法运行时间比较长,这也是模拟退火的最大缺点。人喝醉了酒办起; f4 b5 X! L( f) z( h
事来都不利索,何况兔子?8 B( `. K5 |$ t. H# _( G* I x
* i+ A3 L" C; j% M
3 {3 z% C* L9 ~5 ~9 { F 遗传算法(Genetic Algorithm, GA) , p+ r4 d1 E+ \& K 1 Z% G5 k$ l( I7 g 6 u O4 I9 b0 W. W: n! O “物竞天择,适者生存”,是进化论的基本思想。遗传算法就是模拟自然界想做的事。遗传算法可以很好地用于优化问题,若把它看作对自然过程高度理想化的模拟,更能 $ j0 u( t4 D J( l% g: }3 u显出它本身的优雅——虽然生存竞争是残酷的。: S0 u6 A/ \& o
/ |3 b$ Z) N" {( B g) J
+ e2 O0 L8 p0 C, o 9 [; u+ Q; ?* m# p
遗传算法的伪码: 2 X9 {4 S; F# `8 h2 G% z " g: u, f- A% k
% U, @" o$ X( T6 E
procedure genetic algorithm 2 P! V0 z9 m- T: U begin ! s+ [1 |- `$ P! A1 z initialize a group and evaluate the fitness value ; (1) , S7 c3 z* X& ^3 o; Z" x* c while not convergent (2)+ z" O1 `& i3 W1 q2 p
begin : @, ^# N* `* O; ^( |. M
select; (3)9 G4 D! F5 p$ P
if random[0,1] crossover; (4)/ v$ s" v& h2 x( c% ^
if random (0,1) mutation; (5)! i9 t/ k' [( |4 ?1 F) Z5 C6 C: \
end; $ w; b- n9 `# }# ]( \. G1 T1 E
end 3 u+ Q& {& n, |; S 上述程序中有五个重要的环节: ; f4 k ?& ]; B/ j1 r (1)编码和初始群体的生成:GA在进行搜索之前先将解空间的解数据表示成遗传空间的基因型串结构数据,这些串结构数据的不同组合便构成了不同的点。然后随机产 ; `4 k ?! h0 N- H& V& y生N个初始串结构数据,每个串结构数据称为一个个体,5 A8 o; B. B9 T2 Q8 y/ N' k6 i7 n/ p
N个体构成了一个群体。GA以这N个串结构数据作为初始点开始迭代。" l; t6 ]8 h7 V9 [. C* K
: V! x: o6 A+ v( P 5 C; ^4 B+ w1 {: G
比如,旅行商问题中,可以把商人走过的路径进行编码,也可以对整个图矩阵进行编码。编码方式依赖于问题怎样描述比较好解决。初始群体也应该选取适当,如果选取的 # }2 g# c ~- O$ X$ Y5 Y0 q8 b过小则杂交优势不明显,算法性能很差(数量上占了优势的老鼠进化能力比老虎强),群体选取太大则计算量太大。/ X2 s. {! n7 ?" V I
4 ] Y+ |1 O) u/ U3 ?5 N& R O % V* D( I) _8 |% T" a' U# i" g: ^! @
(2)检查算法收敛准则是否满足,控制算法是否结束。可以采用判断与最优解的适配度或者定一个迭代次数来达到。 6 \5 Q4 s% o1 Y g0 r - S3 W4 I! R9 g $ y, P0 N! l. ?4 l
(3)适应性值评估检测和选择:适应性函数表明个体或解的优劣性,在程序的开始也应该评价适应性,以便和以后的做比较。不同的问题,适应性函数的定义方式也不同 7 i# B' }+ F+ u& `: }。根据适应性的好坏,进行选择。选择的目的是为了从当前群体中选出优良的个体,使它们有机会作为父代为下一代繁殖子孙。遗传算法通过选择过程体现这一思想,进行' J) B1 {$ |5 s) l8 l
选择的原则是适应性强的个体为下一代贡献一个或多个后代的概率大。选择实现了达尔文的适者生存原则。 7 S8 R) e( k) i& M$ D$ j# e : i0 P1 e# f3 P4 ?% N - ^: [; g; Q" N Q (4)杂交:按照杂交概率(pc)进行杂交。杂交操作是遗传算法中最主要的遗传操作。通过杂交操作可以得到新一代个体,新个体组合了其父辈个体的特性。杂交体现- a' e! X1 I( E! ~/ q, T
了信息交换的思想。: v9 w( a. q' |$ c- c" y1 e0 t
# h$ D1 q \( q! S ( g& e* l: r2 {0 o# Q
可以选定一个点对染色体串进行互换,插入,逆序等杂交,也可以随机选取几个点杂交。杂交概率如果太大,种群更新快,但是高适应性的个体很容易被淹没,概率小了搜 + P2 ]1 b4 @3 i& x4 m6 U索会停滞。 # I9 F- |8 Q# ^* f/ M $ `3 }1 {# ` l3 @1 c 3 T7 b9 x3 | @) r b; |- d (5)变异:按照变异概率(pm)进行变异。变异首先在群体中随机选择一个个体,对于选中的个体以一定的概率随机地改变串结构数据中某个串的值。同生物界一样, GA中变异发生的概率很低。变异为新个体的产生提供了机会。 " N. y, E6 T: ?3 g4 p1 Q ( V* G- P8 N) @! @ 7 S; g+ i5 g2 ^: `. \, H 变异可以防止有效基因的缺损造成的进化停滞。比较低的变异概率就已经可以让基因不断变更,太大了会陷入随机搜索。想一下,生物界每一代都和上一代差距很大,会是 ! z* A1 f$ M! D; u怎样的可怕情形。+ f% A8 A: O. J7 r
, D7 V8 O7 h- H4 g- C
_ o+ [( Z% M# a2 t 就像自然界的变异适和任何物种一样,对变量进行了编码的遗传算法没有考虑函数本身是否可导,是否连续等性质,所以适用性很强;并且,它开始就对一个种群进行操作 1 \1 ~7 H1 l& L7 F3 d9 i+ o! T# X5 Q,隐含了并行性,也容易找到“全局最优解”。 2 q7 r4 R4 I7 p, y' n6 i , }+ b; D0 X8 u- Z) N- Z! g, x' x 9 u3 Z8 s8 s4 _$ t7 S 禁忌搜索算法(Tabu Search,TS) + a' h6 _; R4 N, R1 F2 p 7 B: `$ \1 U, ]* i2 L7 j & ~. ?+ \0 ?, L! H- N
为了找到“全局最优解”,就不应该执着于某一个特定的区域。局部搜索的缺点就是太贪婪地对某一个局部区域以及其邻域搜索,导致一叶障目,不见泰山。禁忌搜索就是) J3 L0 U% i9 s# \' O& i' h
对于找到的一部分局部最优解,有意识地避开它(但不是完全隔绝),从而获得更多的搜索区间。兔子们找到了泰山,它们之中的一只就会留守在这里,其他的再去别的地% R' b; h, p8 i2 H( L9 k- }1 F8 {
方寻找。就这样,一大圈后,把找到的几个山峰一比较,珠穆朗玛峰脱颖而出。 + D" P$ m" N. D! X7 P* {8 {2 N 8 T, A$ G, p) o z: m* i ) j0 ]8 X+ A! r0 j' N1 @8 _! Y 当兔子们再寻找的时候,一般地会有意识地避开泰山,因为他们知道,这里已经找过,并且有一只兔子在那里看着了。这就是禁忌搜索中“禁忌表(tabu & p% \- O3 t# K3 c9 X9 s! z
list)”的含义。那只留在泰山的兔子一般不会就安家在那里了,它会在一定时间后重新回到找最高峰的大军,因为这个时候已经有了许多新的消息,泰山毕竟也有一 . e# @! b6 N# I1 T$ K4 U: [1 B个不错的高度,需要重新考虑,这个归队时间,在禁忌搜索里面叫做“禁忌长度(tabu 9 E3 D( L% O2 t& ^+ y; P
length)”;如果在搜索的过程中,留守泰山的兔子还没有归队,但是找到的地方全是华北平原等比较低的地方,兔子们就不得不再次考虑选中泰山,也就是说,当 z! P- i! P4 s2 K( m7 }& [一个有兔子留守的地方优越性太突出,超过了“best 3 M& B6 j1 n& l# Z
to ; b+ U: ]* h' A6 ?
far”的状态,就可以不顾及有没有兔子留守,都把这个地方考虑进来,这就叫“特赦准则(aspiration % z- R" O0 T% _. L7 B& O
criterion)”。这三个概念是禁忌搜索和一般搜索准则最不同的地方,算法的优化也关键在这里。% ?$ n+ @' K) C; }; S ~
6 [2 H6 k; Y: |, L5 L
1 T& l1 o( K9 A, q 伪码表达:2 L) l; p- Y g
procedure tabu search; 4 x l5 L) ?4 N9 Q2 c4 y- X' I. r begin / U1 t! B: n! i+ p
initialize a string vc at random,clear up the tabu list; ) J ]- p0 H& t* |- S( t cur:=vc; : L4 x6 ^- R8 j0 s, ` repeat 4 [5 P, j% `8 ?4 I. A' p8 o
select a new string vn in the neighborhood of vc; / L$ J# Z' Q' J; M+ v& L' H if va>best_to_far then {va is a string in the tabu list} + y r: L& H$ P! k3 c$ T begin 8 j3 A# n1 [3 U* X# G2 D cur:=va; - L" F6 @4 @ m$ j5 T1 {
let va take place of the oldest string in the tabu list; % B( A- p7 Z7 F. V; a4 h$ E) e best_to_far:=va; ( T9 n; e; k+ E. X) W+ s end else 0 }! W U& W) A3 X* w& g8 {# a6 z
begin / d/ }& r! s/ ] Q( m+ R% P
cur:=vn; 8 e& [3 E7 C) U let vn take place of the oldest string in the tabu list; $ s0 I3 T0 M) H2 i/ c w, j$ }3 j
end; 3 h! |1 T; ^" {$ J B" F( B until (termination-condition); # V- F# U! B" m/ |# Q. o* l end; ' p1 ?" i8 }6 f& I: b3 @
* C& q; [3 f N " x% Z2 y8 }- O0 ~) {
以上程序中有关键的几点: 5 E) C+ V) m8 C: N7 j% P4 o (1)禁忌对象:可以选取当前的值(cur)作为禁忌对象放进tabu : h+ m5 U2 C# S: Z list,也可以把和当然值在同一“等高线”上的都放进tabu 2 p I4 Q0 I; ]1 N8 R
list。) f, P" V- Y6 V9 C0 |5 W: z2 P
(2)为了降低计算量,禁忌长度和禁忌表的集合不宜太大,但是禁忌长度太小容易循环搜索,禁忌表太小容易陷入“局部极优解”。 4 v$ h/ t) a3 e6 H! l$ U/ I - q4 L2 h( M& `6 V' f! [