全局優化算法實踐
全局優化算法概述
我們討論的無約束優化方法僅限於凸優化,這些方法的使用很依賴函數的性質和初始迭代點的選取,在很多情況下只能收斂到局部最小點。爲了在更大尺度,更復雜的函數中搜索,我們需要一些不被局部最優侷限的方法。一般來說,隨機優化方法將能夠實現這個目標,但因爲隨機算法的可行種類非常多,這些算法的理論甚至可以單獨拿出來作爲一門課講解。(可以參考《智能優化算法及其MATLAB實例》),我這裏就把它們作爲一種算法概念進行敘述,至於算法的具體實現和應用則按照興趣來。
各類智能算法的核心思想其實是類似的,都是用隨機優化來擺脫局部最優解。
旅行商問題
Python實現
解10城市的旅行商問題,給定城市的初始座標,城市之間的距離是歐拉距離
cood = [(41, 94),(37, 84),(54, 67),(25, 62),(7, 64),
(2, 99),(68, 58),(71, 44),(54, 62),(83, 69)]
graph = [[0 for _ in range(10)]for _ in range(10)]
for i in range(10):
for j in range(10):
graph[i][j] = ((cood[i][0]-cood[j][0])**2+\
(cood[i][1]-cood[j][1])**2)**0.5
#爲了避免字符串旋轉相等,我們固定起點(兼終點)爲0
def distance(code):
res = graph[0][code[0]]
for i in range(len(code)-1):
res+=graph[code[i]][code[i+1]]
res += graph[code[-1]][0]
return res
import random
def getCode(n):
res = [i for i in range(1,n+1)]
random.shuffle(res)
return res
def exchange(code1,code2):
n = len(code1)
s = random.randint(0,n-1)
e = random.randint(0,n-1)
s,e = min(s,e),max(s,e)
segment1 = code1[s:e]
segment2 = code2[s:e]
dic1 = {}
dic2 = {}
for i in range(s,e):
dic1[code2[i]] = code1[i]
dic2[code1[i]] = code2[i]
code1[s:e] = segment2
code2[s:e] = segment1
for i in range(n):
if s<=i<e:
continue
while(code1[i] in dic1):
code1[i] = dic1[code1[i]]
for i in range(n):
if s<=i<e:
continue
while(code2[i] in dic2):
code2[i] = dic2[code2[i]]
return code1,code2
def mutate(code):
#使用隨機交換實現變異
n = len(code)
s = random.randint(0,n-1)
e = random.randint(0,n-1)
code[s],code[e] = code[e],code[s]
return code
from copy import deepcopy
N = 100
#建立一個100數量的種羣
population = [getCode(9) for _ in range(N)]
bests = []
for iteration in range(100):
new_population = []
best_code = None
best_dist = 10000
#找到種羣中表現最好的個體
for code in population:
dist = distance(code)
if dist<best_dist:
best_code = deepcopy(code)
best_dist = dist
#print(best_code)
#print(best_dist)
bests.append((best_dist,best_code))
#自然選擇,錦標賽模式,隨機選出兩個個體競爭
for _ in range(len(population)):
i1,i2 = random.sample([i for i in range(N)],k=2)
code = None;
code1,code2 = population[i1],population[i2]
if distance(code1)<distance(code2):
code = code1
else:
code = code2
c = deepcopy(code)
new_population.append(c)
population = new_population
#交換進化,我們交換其中的6%
for i in range(3):
population[2*i],population[2*i+1] = \
exchange(population[2*i],population[2*i+1])
#變異進化,我們變異其中的2%
mutated_index = random.sample([i for i in range(N)],k=2)
for i in mutated_index:
population[i] = mutate(population[i])
from matplotlib import pyplot as plt
x = [i for i in range(1,101)]
y = [ele[0] for ele in bests]
plt.title("Genetic Algorithm")
plt.xlabel("Iteration times")
plt.ylabel("Cost")
plt.plot(x,y)
plt.show()
print("Solution:",bests[-1][1])
Solution: [5, 4, 3, 7, 6, 9, 8, 2, 1]
總結
其實我們找到的解並不是最優解,最優的路徑長度cost是242左右。但是我們找到的解已經是一個相當接近最優解的方案了,從本實驗我們可以看出隨機優化算法的廣泛應用;不只是書上學到的函數最大最小值求解,而且可以實際地應用到各種情景中。