国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

遺傳算法求解旅行商問(wèn)題(含python源代碼)

這篇具有很好參考價(jià)值的文章主要介紹了遺傳算法求解旅行商問(wèn)題(含python源代碼)。希望對(duì)大家有所幫助。如果存在錯(cuò)誤或未考慮完全的地方,請(qǐng)大家不吝賜教,您也可以點(diǎn)擊"舉報(bào)違法"按鈕提交疑問(wèn)。

目錄

前言

編碼初始化種群

計(jì)算適應(yīng)度

選擇

交叉

變異

完整代碼

總結(jié)


前言

這次的算法有一點(diǎn)不能確定是否正確,希望有大佬能夠批評(píng)指正。

遺傳算法的一般步驟

實(shí)現(xiàn)基于遺傳算法的34個(gè)城市的旅行商問(wèn)題,python,開發(fā)語(yǔ)言

編碼初始化種群

種群(population)指同一時(shí)間生活在一定自然區(qū)域內(nèi),同種生物的所有個(gè)體。

所以種群是由個(gè)體組成的,所以先需要得到個(gè)體,然后再隨機(jī)產(chǎn)生一定數(shù)目的個(gè)體。

在本算法中個(gè)體采用的是實(shí)數(shù)編碼(表示城市的編號(hào),對(duì)應(yīng)列表的下標(biāo),按照順序就是在城市之間的移動(dòng)路線)。

先對(duì)城市的位置進(jìn)行初始化,采用的是用列表來(lái)表示城市的坐標(biāo),可以單個(gè)定義,也可以隨機(jī)生成。

先生成一串有序的數(shù)字用來(lái)表示城市的編號(hào),再每次隨機(jī)進(jìn)行打亂后儲(chǔ)存到pop列表中,pop表示種群,里面裝著的是列表用來(lái)表示個(gè)體。(個(gè)體表示城市的編號(hào),種群表示編號(hào)打亂后所有個(gè)體的集合

群體規(guī)模太小,不能提供足夠的采樣點(diǎn),以致算法性能很差,易陷入局部最優(yōu)解。

群體規(guī)模太大,盡管可以增加優(yōu)化信息,阻止早熟收斂的發(fā)生,但無(wú)疑會(huì)增加計(jì)算量,造成收斂時(shí)間太長(zhǎng),表現(xiàn)為收斂速度緩慢。

City_Map = 100 * np.random.rand(20, 2)  # 隨機(jī)產(chǎn)生20個(gè)城市(20行2列,數(shù)值乘以100)
DNA_SIZE = len(City_Map)  # 編碼長(zhǎng)度(返回行的個(gè)數(shù))
POP_SIZE = 100  # 種群大小
# 生成初代種群pop
pop = []
list = list(range(DNA_SIZE))  # 生成[0,DNA_SIZE)的列表
for i in range(POP_SIZE):  # POP_SIZE是指種群大小,在程序中是一個(gè)固定的值(打亂POP_SIZE次之后把結(jié)果儲(chǔ)存到pop列表中
    random.shuffle(list)  # 隨機(jī)打亂list,進(jìn)行初始化操作
    l = list.copy()  # 把list中的數(shù)據(jù)拷貝到l中
    pop.append(l)  # 將l添加到pop列表中

計(jì)算適應(yīng)度

適應(yīng)度函數(shù)值只能是正值,越大越好。

DNA表示個(gè)體,根據(jù)個(gè)體的值(表示城市的編號(hào))來(lái)計(jì)算距離。

旅行商問(wèn)題要求距離越短越好,所以距離越大越不滿足要求,故而可以通過(guò)對(duì)距離求倒數(shù)來(lái)表示適應(yīng)度。

在最后減去適應(yīng)度最小的值,可以保證適應(yīng)度都為正值。(如果有負(fù)數(shù),減去一個(gè)更小的負(fù)數(shù),會(huì)變成正值)

適應(yīng)度表示的是個(gè)體對(duì)種群的適應(yīng)程度,distance函數(shù)返回的是按照pop[i]路線計(jì)算出來(lái)的路徑距離大小,故而getfitness函數(shù)返回的列表表示的是每一個(gè)個(gè)體pop[i]通過(guò)distance函數(shù)計(jì)算出來(lái)距離的倒數(shù)歸一化(減去最小的距離的倒數(shù))之后的結(jié)果。

distance求出來(lái)的距離不是兩個(gè)城市之間的距離,而是某條路線經(jīng)過(guò)城市的距離之和(是所有的距離)。

def distance(DNA):  # 根據(jù)DNA的路線計(jì)算距離
    dis = 0
    temp = City_Map[DNA[0]]
    for i in DNA[1:]:
        # sqrt(pow(x-x0,2)+pow(y-y0,2))
        dis = dis + ((City_Map[i][0] - temp[0]) ** 2 + (City_Map[i][1] - temp[1]) ** 2) ** 0.5
        temp = City_Map[i]
    return dis + ((temp[0] - City_Map[DNA[0]][0]) ** 2 + (temp[1] - City_Map[DNA[0]][1]) ** 2) ** 0.5


def getfitness(pop):  # 計(jì)算種群適應(yīng)度,這里適應(yīng)度用距離的倒數(shù)表示
    temp = []
    for i in range(len(pop)):
        temp.append(1 / (distance(pop[i])))
    # 減去最小值是為了防止適應(yīng)度出現(xiàn)負(fù)值
    return temp - np.min(temp)

選擇

選擇操作也稱為復(fù)制( reproduction) 操作:從當(dāng)前群體中按照一定概率選出優(yōu)良的個(gè)體, 使它們有機(jī)會(huì)作為父代繁殖下一代子孫。
判斷個(gè)體優(yōu)良與否的準(zhǔn)則是各個(gè)個(gè)體的適應(yīng)度值:個(gè)體適應(yīng)度越高, 其被選擇的機(jī)會(huì)就越多。

在程序中個(gè)體的選擇方法采用的是輪盤賭的方法:

按個(gè)體的選擇概率產(chǎn)生一個(gè)輪盤,輪盤每個(gè)區(qū)的角度與個(gè)體的選擇概率成比例。
產(chǎn)生一個(gè)隨機(jī)數(shù), 它落入轉(zhuǎn)盤的哪個(gè)區(qū)域就選擇相應(yīng)的個(gè)體交叉。
適應(yīng)度的小的個(gè)體也有可能被選中。

def select(pop, fitness):  # 根據(jù)適應(yīng)度選擇,以賭輪盤的形式,適應(yīng)度越大的個(gè)體被選中的概率越大
    # print(fitness)
    s = fitness.sum()
    # np.random.choice(a,size,replace,p=None)隨機(jī)抽取樣本a,表示范圍,replace=True被抽中后仍有機(jī)會(huì)被再次抽中,p沒(méi)抽中的概率
    temp = np.random.choice(np.arange(len(pop)), size=POP_SIZE, replace=True, p=(fitness / s))
    p = []
    for i in temp:
        p.append(pop[i])

    return p

交叉

程序中交叉采用部分匹配交叉,如果直接采用兩點(diǎn)交叉會(huì)導(dǎo)致一個(gè)個(gè)體中出現(xiàn)兩個(gè)重復(fù)的城市,顯然是和題目要求是不符合的。

部分匹配交叉保證了每個(gè)染色體中的基因僅出現(xiàn)一次,通過(guò)該交叉策略在一個(gè)染色體中不會(huì)出現(xiàn)重復(fù)的基因,所以部分匹配交叉經(jīng)常用于旅行商(TSP)或其他排序問(wèn)題編碼。部分匹配交叉類似于兩點(diǎn)交叉,通過(guò)隨機(jī)選擇兩個(gè)交叉點(diǎn)確定交叉區(qū)域。執(zhí)行交叉后一般會(huì)得到兩個(gè)無(wú)效的染色體,個(gè)別基因會(huì)出現(xiàn)重復(fù)的情況,為了修復(fù)染色體,可以在交叉區(qū)域內(nèi)建立每個(gè)染色體的匹配關(guān)系,然后在交叉區(qū)域外對(duì)重復(fù)基因應(yīng)用此匹配關(guān)系就可以消除沖突。

交叉概率太大時(shí),種群中個(gè)體更新很快,會(huì)造成高適應(yīng)度值的個(gè)體很快被破壞掉;

概率太小時(shí),交叉操作很少進(jìn)行,從而會(huì)使搜索停滯不前,造成算法的不收斂。

def crossmuta(pop, CROSS_RATE):  # 交叉變異
    new_pop = []
    for i in range(len(pop)):  # 遍歷種群中的每一個(gè)個(gè)體,將該個(gè)體作為父代
        n = np.random.rand()
        if n >= CROSS_RATE:  # 大于交叉概率時(shí)不發(fā)生變異,該子代直接進(jìn)入下一代
            temp = pop[i].copy()
            new_pop.append(temp)  # 直接進(jìn)行拷貝

        if n < CROSS_RATE:  # 小于交叉概率時(shí)發(fā)生變異
            list1 = pop[i].copy()
            list2 = pop[np.random.randint(POP_SIZE)].copy()  # 選取種群中另一個(gè)個(gè)體進(jìn)行交叉(隨機(jī)選擇)
            status = True
            while status:  # 產(chǎn)生2個(gè)不相等的節(jié)點(diǎn),中間部分作為交叉段,采用部分匹配交叉(直到k1<k2的時(shí)候才會(huì)跳出循環(huán))
                k1 = random.randint(0, len(list1) - 1)
                k2 = random.randint(0, len(list2) - 1)
                if k1 < k2:
                    status = False

            k11 = k1  # 保存切片起始的下標(biāo)

            # 先對(duì)部分片段進(jìn)行切片,把切片出來(lái)的內(nèi)容進(jìn)行交換(完全交換)
            fragment1 = list1[k1: k2]
            fragment2 = list2[k1: k2]

            list1[k1: k2] = fragment2
            list2[k1: k2] = fragment1

            del list1[k1: k2]  # 刪除list1中[k1,k2)的內(nèi)容
            left1 = list1

            # 進(jìn)行部分匹配的交叉
            offspring1 = []#后代
            #對(duì)left1中的每一個(gè)位置pos遍歷
            for pos in left1:
                #檢查它是否存在于frag2中
                if pos in fragment2:
                    #從fragment1中找到對(duì)應(yīng)的基因
                    pos = fragment1[fragment2.index(pos)]
                    #直到基因不再fragment2中為止(遍歷fragment2,確保每一個(gè)基因都和pos不同)
                    while pos in fragment2:
                        pos = fragment1[fragment2.index(pos)]
                    offspring1.append(pos)
                    continue
                #如何pos不存在fragment2中,那么就直接將其添加到新的后代中
                offspring1.append(pos)
            # 插入新片段
            for i in range(0, len(fragment2)):
                offspring1.insert(k11, fragment2[i])
                k11 += 1
            temp = offspring1.copy()

            mutation(temp, MUTA_RATE)  # 進(jìn)行變異

            new_pop.append(temp)  # 把部分匹配交叉后形成的合法個(gè)體加入到下一代種群

    return new_pop

變異

互換變異:隨機(jī)選取染色體的兩個(gè)基因進(jìn)行簡(jiǎn)單互換。
采用隨機(jī)的形式,在[0,DNA_SIZE)的范圍內(nèi)生成兩個(gè)下標(biāo)(確保兩個(gè)位置不一致),在將兩個(gè)位置上面的值進(jìn)行交換。

變異概率太小則很難產(chǎn)生新模式,變異概率太大則會(huì)使遺傳算法成為隨機(jī)搜索算法。

def mutation(DNA, MUTA_RATE):  # 進(jìn)行變異
    # 兩點(diǎn)變異
    if np.random.rand() < MUTA_RATE:  # 以MUTA_RATE的概率進(jìn)行變異
        mutate_point1 = np.random.randint(0, DNA_SIZE)  # 隨機(jī)產(chǎn)生一個(gè)實(shí)數(shù),代表要變異基因的位置
        mutate_point2 = np.random.randint(0, DNA_SIZE)  # 隨機(jī)產(chǎn)生一個(gè)實(shí)數(shù),代表要變異基因的位置
        while (mutate_point1 == mutate_point2):  # 保證2個(gè)所選位置不相等
            mutate_point2 = np.random.randint(0, DNA_SIZE)  #如果相等將mutate_point2重新進(jìn)行隨機(jī)生成位置
        DNA[mutate_point1], DNA[mutate_point2] = DNA[mutate_point2], DNA[mutate_point1]  # 2個(gè)所選位置進(jìn)行互換

逆轉(zhuǎn)變異:在個(gè)體碼串中隨機(jī)選擇兩點(diǎn)( 逆轉(zhuǎn)點(diǎn)) ,然后將兩點(diǎn)之間的基因值以逆向排序插入到原位置中。

隨機(jī)生成兩個(gè)下標(biāo),如x1,x2(確保x1<x2),對(duì)列表進(jìn)行[x1,x2)的切片,在原始的列表中刪除切片的部分,將切片的部分翻轉(zhuǎn)之后添加到原始的位置。

def mutation(DNA, MUTA_RATE):  # 進(jìn)行變異
    # 逆轉(zhuǎn)變異
    if np.random.rand() < MUTA_RATE:  # 以MUTA_RATE的概率進(jìn)行變異
        status = True
        while status:  # 產(chǎn)生2個(gè)不相等的節(jié)點(diǎn),中間部分作為交叉段,采用部分匹配交叉(直到mutate_point1<mutate_point2的時(shí)候才會(huì)跳出循環(huán))
            mutate_point1 = np.random.randint(0, DNA_SIZE)  # 隨機(jī)產(chǎn)生一個(gè)實(shí)數(shù),代表要變異基因片段的起始的位置
            mutate_point2 = np.random.randint(0, DNA_SIZE)  # 隨機(jī)產(chǎn)生一個(gè)實(shí)數(shù),代表要變異基因片段的結(jié)束的位置
            if mutate_point1 < mutate_point2:
                status = False

        k1 = mutate_point1  # 保存切片起始的下標(biāo)
        temp = DNA[mutate_point1:mutate_point2]  # 把需要逆轉(zhuǎn)的片段先提取出來(lái)
        del DNA[mutate_point1:mutate_point2]  # 先暫時(shí)刪除這段片段
        temp.reverse()  # 反轉(zhuǎn)基因序列
        # 插入翻轉(zhuǎn)后的新片段
        for i in range(0, len(temp)):
            DNA.insert(k1, temp[i])
            k1 += 1

插入變異:在個(gè)體碼串中隨機(jī)選擇一個(gè)碼, 然后將此碼插入隨機(jī)選擇的插入點(diǎn)中間。

隨機(jī)生成兩個(gè)實(shí)數(shù),這次不是交換,是插入的方式,也就是插入點(diǎn)之后的元素的位置都會(huì)發(fā)生改變。

def mutation(DNA, MUTA_RATE):  # 進(jìn)行變異
    #插入變異
    if np.random.rand() < MUTA_RATE:  # 以MUTA_RATE的概率進(jìn)行變異
        mutate_point1 = np.random.randint(0, DNA_SIZE)  # 隨機(jī)產(chǎn)生一個(gè)實(shí)數(shù),代表要變異基因的位置(選中一個(gè)基因)
        mutate_point2 = np.random.randint(0, DNA_SIZE)  # 隨機(jī)產(chǎn)生一個(gè)實(shí)數(shù),代表要變異基因的位置(插入點(diǎn))
        while (mutate_point1 == mutate_point2):  # 保證2個(gè)所選位置不相等
            mutate_point2 = np.random.randint(0, DNA_SIZE)

        temp=DNA[mutate_point1]#先保存mutate_point1對(duì)應(yīng)的值
        del DNA[mutate_point1]#刪除mutate_point1對(duì)應(yīng)的值
        DNA.insert(mutate_point2,temp)#重新插入到列表中

完整代碼

import time
import numpy as np
import random
import matplotlib.pyplot as plt

# 各個(gè)城市的坐標(biāo)
City_Map = 100 * np.random.rand(10, 2)  # 隨機(jī)產(chǎn)生10個(gè)城市(10行2列,數(shù)值乘以100)

DNA_SIZE = len(City_Map)  # 編碼長(zhǎng)度(返回行的個(gè)數(shù))
POP_SIZE = 100  # 種群大小
CROSS_RATE = 0.85  # 交叉率
MUTA_RATE = 0.15  # 變異率
Iterations = 500  # 迭代次數(shù)


def distance(DNA):  # 根據(jù)DNA的路線計(jì)算距離
    dis = 0
    temp = City_Map[DNA[0]]
    for i in DNA[1:]:
        # sqrt(pow(x-x0,2)+pow(y-y0,2))
        dis = dis + ((City_Map[i][0] - temp[0]) ** 2 + (City_Map[i][1] - temp[1]) ** 2) ** 0.5
        temp = City_Map[i]
    return dis + ((temp[0] - City_Map[DNA[0]][0]) ** 2 + (temp[1] - City_Map[DNA[0]][1]) ** 2) ** 0.5


def getfitness(pop):  # 計(jì)算種群適應(yīng)度,這里適應(yīng)度用距離的倒數(shù)表示
    temp = []
    for i in range(len(pop)):
        temp.append(1 / (distance(pop[i])))
    # 減去最小值是為了防止適應(yīng)度出現(xiàn)負(fù)值
    return temp - np.min(temp)


def select(pop, fitness):  # 根據(jù)適應(yīng)度選擇,以賭輪盤的形式,適應(yīng)度越大的個(gè)體被選中的概率越大
    # print(fitness)
    s = fitness.sum()
    # np.random.choice(a,size,replace,p=None)隨機(jī)抽取樣本a,表示范圍,replace=True被抽中后仍有機(jī)會(huì)被再次抽中,p沒(méi)抽中的概率
    temp = np.random.choice(np.arange(len(pop)), size=POP_SIZE, replace=True, p=(fitness / s))
    p = []
    for i in temp:
        p.append(pop[i])

    return p


def mutation(DNA, MUTA_RATE):  # 進(jìn)行變異
    # 兩點(diǎn)變異
    if np.random.rand() < MUTA_RATE:  # 以MUTA_RATE的概率進(jìn)行變異
        mutate_point1 = np.random.randint(0, DNA_SIZE)  # 隨機(jī)產(chǎn)生一個(gè)實(shí)數(shù),代表要變異基因的位置
        mutate_point2 = np.random.randint(0, DNA_SIZE)  # 隨機(jī)產(chǎn)生一個(gè)實(shí)數(shù),代表要變異基因的位置
        while (mutate_point1 == mutate_point2):  # 保證2個(gè)所選位置不相等
            mutate_point2 = np.random.randint(0, DNA_SIZE)  #如果相等將mutate_point2重新進(jìn)行隨機(jī)生成位置
        DNA[mutate_point1], DNA[mutate_point2] = DNA[mutate_point2], DNA[mutate_point1]  # 2個(gè)所選位置進(jìn)行互換
    

def crossmuta(pop, CROSS_RATE):  # 交叉變異
    new_pop = []
    for i in range(len(pop)):  # 遍歷種群中的每一個(gè)個(gè)體,將該個(gè)體作為父代
        n = np.random.rand()
        if n >= CROSS_RATE:  # 大于交叉概率時(shí)不發(fā)生變異,該子代直接進(jìn)入下一代
            temp = pop[i].copy()
            new_pop.append(temp)  # 直接進(jìn)行拷貝

        if n < CROSS_RATE:  # 小于交叉概率時(shí)發(fā)生變異
            list1 = pop[i].copy()
            list2 = pop[np.random.randint(POP_SIZE)].copy()  # 選取種群中另一個(gè)個(gè)體進(jìn)行交叉(隨機(jī)選擇)
            status = True
            while status:  # 產(chǎn)生2個(gè)不相等的節(jié)點(diǎn),中間部分作為交叉段,采用部分匹配交叉(直到k1<k2的時(shí)候才會(huì)跳出循環(huán))
                k1 = random.randint(0, len(list1) - 1)
                k2 = random.randint(0, len(list2) - 1)
                if k1 < k2:
                    status = False

            k11 = k1  # 保存切片起始的下標(biāo)

            # 先對(duì)部分片段進(jìn)行切片,把切片出來(lái)的內(nèi)容進(jìn)行交換(完全交換)
            fragment1 = list1[k1: k2]
            fragment2 = list2[k1: k2]

            list1[k1: k2] = fragment2
            list2[k1: k2] = fragment1

            del list1[k1: k2]  # 刪除list1中[k1,k2)的內(nèi)容
            left1 = list1

            # 進(jìn)行部分匹配的交叉
            offspring1 = []#后代
            #對(duì)left1中的每一個(gè)位置pos遍歷
            for pos in left1:
                #檢查它是否存在于frag2中
                if pos in fragment2:
                    #從fragment1中找到對(duì)應(yīng)的基因
                    pos = fragment1[fragment2.index(pos)]
                    #直到基因不再fragment2中為止(遍歷fragment2,確保每一個(gè)基因都和pos不同)
                    while pos in fragment2:
                        pos = fragment1[fragment2.index(pos)]
                    offspring1.append(pos)
                    continue
                #如何pos不存在fragment2中,那么就直接將其添加到新的后代中
                offspring1.append(pos)
            # 插入新片段
            for i in range(0, len(fragment2)):
                offspring1.insert(k11, fragment2[i])
                k11 += 1
            temp = offspring1.copy()

            mutation(temp, MUTA_RATE)  # 進(jìn)行變異

            new_pop.append(temp)  # 把部分匹配交叉后形成的合法個(gè)體加入到下一代種群

    return new_pop


def print_info(pop):  # 用于輸出結(jié)果
    fitness = getfitness(pop)
    maxfitness = np.argmax(fitness)  # 得到種群中最大適應(yīng)度個(gè)體的索引
    # 打印結(jié)果
    print("最優(yōu)的基因型:", pop[maxfitness])
    print("最短距離:", distance(pop[maxfitness]))
    # 按最優(yōu)結(jié)果順序把地圖上的點(diǎn)加入到best_map列表中
    best_map = []
    for i in pop[maxfitness]:
        best_map.append(City_Map[i])
    best_map.append(City_Map[pop[maxfitness][0]])
    X = np.array((best_map))[:, 0]
    Y = np.array((best_map))[:, 1]
    # 繪制地圖以及路線
    plt.figure()
    plt.rcParams['font.sans-serif'] = ['SimHei']
    plt.scatter(X, Y)
    for dot in range(len(X) - 1):
        plt.annotate(pop[maxfitness][dot], xy=(X[dot], Y[dot]), xytext=(X[dot], Y[dot]))
    plt.annotate('start', xy=(X[0], Y[0]), xytext=(X[0] + 1, Y[0]))
    plt.plot(X, Y)


if __name__ == "__main__":  # 主循環(huán)
    # 生成初代種群pop
    pop = []
    list = list(range(DNA_SIZE))  # 生成[0,DNA_SIZE)的列表
    for i in range(POP_SIZE):  # POP_SIZE是指種群大小,在程序中是一個(gè)固定的值(打亂POP_SIZE次之后把結(jié)果儲(chǔ)存到pop列表中
        random.shuffle(list)  # 隨機(jī)打亂list,進(jìn)行初始化操作
        l = list.copy()  # 把list中的數(shù)據(jù)拷貝到l中
        pop.append(l)  # 將l添加到pop列表中
    best_dis = []
    # 最好適應(yīng)度
    #goodFitness = 0
    # 最差適應(yīng)度(如果進(jìn)行歸一化處理之后,適應(yīng)度都減去最小值,那么他的最差適應(yīng)度不都就是0了)
    #chaFitness = 0
    # 總體適應(yīng)度
    #sumFitness = 0
    # 所有數(shù)量
    #sumCount = 0
    # 平均適應(yīng)度
    #averageFitness = 0

    # 獲取當(dāng)前時(shí)間(算法開始時(shí)間)
    start_time = time.time()

    # 進(jìn)行選擇,交叉,變異,并把每代的最優(yōu)個(gè)體保存在best_dis中
    for i in range(Iterations):  # 迭代N代
        pop = crossmuta(pop, CROSS_RATE)  # CROSS_RATE交叉率
        fitness = getfitness(pop)  # 得到適應(yīng)度種群的適應(yīng)度
        # 更新最差適應(yīng)度
        # print(np.min(fitness))
        tmpfitness = np.max(fitness)

        # 更新最好適應(yīng)度
        #if tmpfitness > goodFitness:
        #    goodFitness = tmpfitness
        # print(goodFitness)

        # 記錄所有適應(yīng)度的值
        #sumFitness = np.sum(fitness) + sumFitness
        # 記錄所有適應(yīng)度的個(gè)數(shù)
        #sumCount = sumCount + np.size(fitness)

        maxfitness = np.argmax(fitness)  # 返回?cái)?shù)值最大的索引
        best_dis.append(distance(pop[maxfitness]))
        pop = select(pop, fitness)  # 選擇生成新的種群(適應(yīng)度最大的)
        print("iteration", i)

    #averageFitness = sumFitness / sumCount
    # 獲取當(dāng)前時(shí)間(算法結(jié)束時(shí)間)
    end_time = time.time()

    print_info(pop)  # 打印信息

    print('逐代的最小距離:', best_dis)
    #print(f'最好適應(yīng)度:{goodFitness:.4f}')
    #print(f'最差適應(yīng)度:{chaFitness:.4f}')
    #print(f'平均適應(yīng)度:{averageFitness:.4f}')
    print(f'程序運(yùn)行時(shí)間:{(end_time - start_time):.4f}秒')
    #print(pop)


# 畫圖
plt.figure()
plt.plot(range(Iterations), best_dis)
plt.show()
plt.close()

參考信息

遺傳算法入門詳解 - 知乎 (zhihu.com)https://zhuanlan.zhihu.com/p/100337680遺傳算法python進(jìn)階理解+論文復(fù)現(xiàn)(純干貨,附前人總結(jié)引路)_python神經(jīng)網(wǎng)絡(luò)遺傳算法_不想禿頭的夜貓子的博客-CSDN博客https://blog.csdn.net/golden_knife/article/details/128510731通俗易懂地解釋遺傳算法 - 知乎 (zhihu.com)https://zhuanlan.zhihu.com/p/136393730遺傳算法解決旅行商問(wèn)題(詳細(xì)解釋+代碼分享) - 知乎 (zhihu.com)https://zhuanlan.zhihu.com/p/344588977用遺傳算法求解旅行商問(wèn)題_中國(guó)旅行商問(wèn)題,34個(gè)省會(huì)-CSDN博客https://blog.csdn.net/breeze_blows/article/details/102992997遺傳算法(三)——適應(yīng)度與選擇_遺傳算法適應(yīng)度函數(shù)-CSDN博客https://blog.csdn.net/weixin_30239361/article/details/101540896

總結(jié)

這個(gè)最好適應(yīng)度,最差適應(yīng)度以及平均適應(yīng)度的概念沒(méi)完全掌握,不知道是不是這一個(gè)意思,所以在程序中注釋了,大家可以根據(jù)自己的理解來(lái)添加。

我理解到的:

最好適應(yīng)度就是每一次的迭代都會(huì)有一個(gè)適應(yīng)度最高的個(gè)體,把每一代適應(yīng)度最高的個(gè)體進(jìn)行比較選出最大的那個(gè),得到的就是整體適應(yīng)度最好的。

最差適應(yīng)度就是0,因?yàn)槊恳淮味歼M(jìn)行了歸一化操作。

平均適應(yīng)度就是保存每一代的適應(yīng)度以及個(gè)體的數(shù)量,最后進(jìn)行求平均值。

運(yùn)行時(shí)間就是在算法運(yùn)行前記錄當(dāng)前系統(tǒng)的時(shí)間,算法運(yùn)行后記錄當(dāng)前系統(tǒng)的時(shí)間,所形成的差值(運(yùn)行后-運(yùn)行前)就是程序運(yùn)行的時(shí)間。

適應(yīng)度因?yàn)椴捎玫氖蔷嚯x的倒數(shù),加上還進(jìn)行了歸一化的處理,隨機(jī)生成城市的的坐標(biāo)*100,導(dǎo)致兩點(diǎn)之間的距離較大,如果想得到較大一點(diǎn)的適應(yīng)度,可以縮小城市之間的距離。

City_Map = 100 * np.random.rand(20, 2)

City_Map =? np.random.rand(20, 2)

遺傳算法的思路是“適者生存,優(yōu)勝劣汰”,模擬生物的進(jìn)化,以一個(gè)初始生物群體為起點(diǎn),經(jīng)過(guò)競(jìng)爭(zhēng)后,一部分個(gè)體被淘汰而無(wú)法再進(jìn)入這個(gè)循環(huán)圈,而另一部分則勝出成為種群。對(duì)于算法的選擇的個(gè)體,適應(yīng)度高的并不一定進(jìn)入種群,只是進(jìn)入種群的可能性比較大;而適應(yīng)度低的個(gè)體并不一定被淘汰,只是進(jìn)入種群的可能性比較小,模擬生物進(jìn)化的過(guò)程。文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-817720.html

到了這里,關(guān)于遺傳算法求解旅行商問(wèn)題(含python源代碼)的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來(lái)自互聯(lián)網(wǎng)用戶投稿,該文觀點(diǎn)僅代表作者本人,不代表本站立場(chǎng)。本站僅提供信息存儲(chǔ)空間服務(wù),不擁有所有權(quán),不承擔(dān)相關(guān)法律責(zé)任。如若轉(zhuǎn)載,請(qǐng)注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實(shí)不符,請(qǐng)點(diǎn)擊違法舉報(bào)進(jìn)行投訴反饋,一經(jīng)查實(shí),立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費(fèi)用

相關(guān)文章

  • 【路徑規(guī)劃】基于遺傳算法求解機(jī)器人柵格地圖路徑規(guī)劃問(wèn)題matlab代碼

    【路徑規(guī)劃】基于遺傳算法求解機(jī)器人柵格地圖路徑規(guī)劃問(wèn)題matlab代碼

    ??作者簡(jiǎn)介:熱愛(ài)科研的Matlab仿真開發(fā)者,修心和技術(shù)同步精進(jìn), 代碼獲取、論文復(fù)現(xiàn)及科研仿真合作可私信。 ??個(gè)人主頁(yè):Matlab科研工作室 ??個(gè)人信條:格物致知。 更多Matlab完整代碼及仿真定制內(nèi)容點(diǎn)擊?? 智能優(yōu)化算法?? ? ??神經(jīng)網(wǎng)絡(luò)預(yù)測(cè)?? ? ??雷達(dá)通信?? ?

    2024年01月24日
    瀏覽(25)
  • 強(qiáng)化學(xué)習(xí)求解TSP:Qlearning求解旅行商問(wèn)題(Traveling salesman problem, TSP)提供Python代碼

    強(qiáng)化學(xué)習(xí)求解TSP:Qlearning求解旅行商問(wèn)題(Traveling salesman problem, TSP)提供Python代碼

    Q-learning是一種強(qiáng)化學(xué)習(xí)算法,用于解決基于獎(jiǎng)勵(lì)的決策問(wèn)題。它是一種無(wú)模型的學(xué)習(xí)方法,通過(guò)與環(huán)境的交互來(lái)學(xué)習(xí)最優(yōu)策略。Q-learning的核心思想是通過(guò)學(xué)習(xí)一個(gè)Q值函數(shù)來(lái)指導(dǎo)決策,該函數(shù)表示在給定狀態(tài)下采取某個(gè)動(dòng)作所獲得的累積獎(jiǎng)勵(lì)。 Q-learning的訓(xùn)練過(guò)程如下: 1. 初

    2024年02月03日
    瀏覽(19)
  • 遺傳算法解決旅行商問(wèn)題

    遺傳算法解決旅行商問(wèn)題

    一、問(wèn)題描述 旅行商問(wèn)題(Travelling Salesman Problem, 簡(jiǎn)記TSP,亦稱貨郎擔(dān)問(wèn)題):設(shè)有n個(gè)城市和距離矩陣D=[dij],其中dij表示城市i到城市j的距離,i,j=1,2 … n,則問(wèn)題是要找出遍訪每個(gè)城市恰好一次的一條回路并使其路徑長(zhǎng)度為最短。 初始問(wèn)題圖像如下: 近似理想結(jié)果圖像如

    2024年02月07日
    瀏覽(19)
  • 通用的改進(jìn)遺傳算法求解帶約束的優(yōu)化問(wèn)題(MATLAB代碼精講、實(shí)際工程經(jīng)驗(yàn)分享)

    通用的改進(jìn)遺傳算法求解帶約束的優(yōu)化問(wèn)題(MATLAB代碼精講、實(shí)際工程經(jīng)驗(yàn)分享)

    在對(duì)多約束、非線性問(wèn)題的求解上,傳統(tǒng)線性規(guī)劃等方法往往無(wú)法有效求解(求解時(shí)間過(guò)長(zhǎng)、無(wú)法處理非線性約束等。 進(jìn)化算法是一類強(qiáng)有力的工具,已經(jīng)在多個(gè)領(lǐng)域有了較為成功的應(yīng)用。然而,在利用遺傳算法、粒子群等等進(jìn)化算法求解實(shí)際的優(yōu)化問(wèn)題時(shí),還存在許多困難

    2023年04月19日
    瀏覽(94)
  • Python實(shí)現(xiàn)支持向量機(jī)(SVM)算法及源代碼

    Python實(shí)現(xiàn)支持向量機(jī)(SVM)算法及源代碼 支持向量機(jī)(SVM)是一種經(jīng)典的分類算法,它在解決二分類問(wèn)題的性能優(yōu)秀。本文將介紹如何使用Python實(shí)現(xiàn)SVM算法,并提供完整的源代碼。 通過(guò)安裝必要的Python庫(kù),我們可以開始編寫SVM代碼。首先,導(dǎo)入必要的庫(kù): 然后,使用make_blobs函數(shù)

    2024年02月10日
    瀏覽(38)
  • Python實(shí)現(xiàn)BP神經(jīng)網(wǎng)絡(luò)算法詳解與源代碼

    Python實(shí)現(xiàn)BP神經(jīng)網(wǎng)絡(luò)算法詳解與源代碼 BP神經(jīng)網(wǎng)絡(luò)是一種常用的人工神經(jīng)網(wǎng)絡(luò)。它通過(guò)誤差逆向傳播來(lái)訓(xùn)練模型。本文將介 紹BP神經(jīng)網(wǎng)絡(luò)的基本原理及其Python實(shí)現(xiàn)。 一. BP神經(jīng)網(wǎng)絡(luò)的基本原理 BP神經(jīng)網(wǎng)絡(luò)由輸入層、隱藏層和輸出層組成。其中,輸入層接受原始數(shù)據(jù),隱藏層進(jìn)行

    2024年02月16日
    瀏覽(21)
  • 歐拉法與梯形法求解微分方程【含matlab源代碼】

    歐拉法與梯形法求解微分方程【含matlab源代碼】

    本文介紹兩種入門級(jí)求解微分方程的方法 —— 梯形法與歐拉法。 將上述方程組改寫成matlab語(yǔ)言: 一、歐拉法 1.1?向前歐拉公式 1.2?向后歐拉公式 ? ? 歐拉法求解源代碼? ? ?? 歐拉法結(jié)果圖?? 二、梯形法 ? ?梯形法求解源代碼??? ???梯形法結(jié)果圖? ? 感謝 Miracle 向公眾

    2024年02月15日
    瀏覽(20)
  • 關(guān)于旅行商問(wèn)題的多種算法求解

    關(guān)于旅行商問(wèn)題的多種算法求解

    一、問(wèn)題描述 旅行商問(wèn)題是指旅行家要旅行n個(gè)城市,要求每個(gè)城市經(jīng)歷一次且僅經(jīng)歷一次然后回到出發(fā)城市,并要求所走路程最短。 首先通過(guò)所給出的一個(gè)無(wú)向圖,即n個(gè)頂點(diǎn),m個(gè)無(wú)向邊,每條邊有一個(gè)權(quán)值代表兩個(gè)點(diǎn)之間的距離,要求把每一個(gè)點(diǎn)都走一遍并回到原點(diǎn),求

    2024年02月04日
    瀏覽(20)
  • Matlab蟻群算法求解旅行商問(wèn)題

    Matlab蟻群算法求解旅行商問(wèn)題

    目錄 問(wèn)題展現(xiàn) 解決代碼 代碼1 輸出結(jié)果 代碼2 輸出結(jié)果 代碼3 輸出結(jié)果 假設(shè)有一個(gè)旅行商人要拜訪全國(guó) 31 個(gè)省會(huì)城市,他需要選擇所要走的路徑,路徑的限制是每個(gè)城市只能拜訪一次,而且最后要回到原來(lái)出發(fā)的城市。路徑的選擇要求是:所選路徑的路程為所有路徑之中的

    2023年04月15日
    瀏覽(24)
  • 整數(shù)規(guī)劃——分支界定算法(旅行商問(wèn)題,規(guī)約矩陣求解)

    整數(shù)規(guī)劃——分支界定算法(旅行商問(wèn)題,規(guī)約矩陣求解)

    一、普通優(yōu)化問(wèn)題分枝定界求解 題目的原問(wèn)題為 ? 在計(jì)算過(guò)程中,利用MATLAB中的linprog()函數(shù)進(jìn)行求解最優(yōu)解,具體的計(jì)算步驟如下: A為約束系數(shù)矩陣,B為等式右邊向量,C為目標(biāo)函數(shù)的系數(shù)向量。 ? 進(jìn)行第一次最優(yōu)求解以A=[2 9;11 -8],B=[40;82],C=[-3,-13]利用linprog函數(shù)求解。解

    2024年02月16日
    瀏覽(26)

覺(jué)得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請(qǐng)作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包