0

I am implementing an improved cuckoo search algorithm for research (link below). This algorithm should work very very well, however my implementation is approximately 1.5 times of the optimal on the test TSPLIB 'eil51.txt' while it should be close or optimal. If any of you guys has some feedback or improvements i would love to hear them.

import math
from random import randint
from random import uniform
import numpy as np
import pandas as pd


def levyFlight(u):
    return u/math.pow(1-u, 1.6)

def randF():
    return uniform(0.0001, 0.9999)

def calculateDistance(route, distanceMatrix):
    distance = 0
    for i in range(len(route)-1):
        j = i + 1
        distance += inputMatrix[route[i]][route[j]]
    distance+=inputMatrix[route[j]][route[1]]
    return distance

def swap(sequence, i, j):
    temp = sequence[i]
    sequence[i] = sequence[j]
    sequence[j] = temp
    return sequence

#returns the best direction of a given path
def bestDirection(path, distanceMatrix):
    temp = path.copy()
    temp.reverse()
    if(calculateDistance(path,distanceMatrix)>calculateDistance(temp,distanceMatrix)):
        return temp
    else:
        return path

#single two opt move
def simpleMove(nest, distanceMatrix):
    nest = nest[0][:]
    n = len(distanceMatrix)
    a, b = randint(0, n - 1), randint(0, n - 1)
    while a == b:
        a, b = randint(0, n - 1), randint(0, n - 1)
    temp = swap(nest, a, b)
    temp = bestDirection(temp, distanceMatrix)

    if calculateDistance(nest, distanceMatrix) > calculateDistance(temp, distanceMatrix):
        return (temp, calculateDistance(temp, distanceMatrix))
    else:
        return (nest, calculateDistance(nest, distanceMatrix))

#double bridge move
def doubleMove(nest, distanceMatrix):
    nest = nest[0][:]
    n = len(distanceMatrix)
    a, b, c, d = randint(0, n - 1), randint(0, n - 1), randint(0, n - 1), randint(0, n - 1)
    while (a == b) or (a == c) or (a == d) or (b == c) or b == d or (c == d):
        a, b, c, d = randint(0, n - 1), randint(0, n - 1), randint(0, n - 1), randint(0, n - 1)
    route = swap(nest, a, b)
    route = swap(route, c, d)
    route=bestDirection(route, distanceMatrix)
    if calculateDistance(nest, distanceMatrix) > calculateDistance(route, distanceMatrix):
        return (route, calculateDistance(route, distanceMatrix))
    else:
        return (nest, calculateDistance(nest, distanceMatrix))

#main
def cuckoo_search(distanceMatrix):
    numNests = 20
    pa = int(0.2 * numNests)
    pc = int(0.6 * numNests)

    maxGen = 750
    n = len(distanceMatrix)

    nests = []
    initPath = list(range(0, len(distanceMatrix)))
    print('distance initpath', calculateDistance(initPath, distanceMatrix))
    index = 0
    for i in range(numNests):
        if i != 0:
            if index == n - 1:
                index = 0
            initPath = swap(initPath, index, index + 1)
        index += 1
        nests.append((initPath[:], calculateDistance(initPath, distanceMatrix)))
    print(nests[0])
    nests.sort(key=lambda tup: tup[1])
    for t in range(maxGen):
        for k in range(numNests):
            levyRange = 0.2
            levy = levyFlight(randF())
            if ( levy <= levyRange):
                cuckooNest = doubleMove(nests[k], distanceMatrix)
            elif (levy <=levyRange*2):
                cuckooNest = doubleMove(nests[k], distanceMatrix)
                cuckooNest = doubleMove(cuckooNest, distanceMatrix)
            elif (levy <=levyRange*3):
                cuckooNest = doubleMove(nests[k], distanceMatrix)
                cuckooNest = doubleMove(cuckooNest, distanceMatrix)
                cuckooNest = doubleMove(cuckooNest, distanceMatrix)
            elif (levy <=levyRange*4):
                cuckooNest = doubleMove(nests[k], distanceMatrix)
                cuckooNest = doubleMove(cuckooNest, distanceMatrix)
                cuckooNest = doubleMove(cuckooNest, distanceMatrix)
                cuckooNest = doubleMove(cuckooNest, distanceMatrix)
            else:
                cuckooNest = simpleMove(nests[k], distanceMatrix)

            randomNestIndex = randint(0, numNests - 1)
            if (nests[randomNestIndex][1] > cuckooNest[1]):
                nests[randomNestIndex] = cuckooNest
            for i in range(numNests - pa, numNests):
                nests[i] = simpleMove(nests[i], distanceMatrix)
            nests.sort(key=lambda tup: tup[1])
    return nests[0][0], nests[0][1]

#only for eil51
def create_disMatrix(data):
    matrix = np.zeros((len(data), len(data)))
    for i in range(len(data)):
        a = data[i]
        for j in range(len(data)):
            b = data[j]
            dist = np.linalg.norm(a-b)
            matrix[i][j] = dist
    return matrix

if __name__ == '__main__':
    data = pd.read_csv('C:/.../eil51.txt', sep=" ", header=None)    
    data = data.drop(0, axis=1)
    data = data.to_numpy()
    inputMatrix = create_disMatrix(data)
    distanceMatrix = inputMatrix.copy()

    route, distance = cuckoo_search(distanceMatrix)
    distance = calculateDistance(route, inputMatrix)
    print(route, distance)

Paper Improved Cuckoo Search: https://link.springer.com/article/10.1007/s11042-022-12409-x

kGame
  • 21
  • 3

0 Answers0